ek9_update_requirement
Rewrites one existing requirement node's markdown file (body, title, meta, position, retirement) or deletes it, and answers the editor envelope: status (applied | ready | conflicts), written, edits[] and summary naming the mode applied.
When to use it
'Change requirement X' is one call: {mode:'edit-body-text', requirementId:'REQ:x', text, authorKind, authorName}; modes cover title, meta, reparent, retire and delete.
When not to use it
- Adding a NEW requirement node - use
ek9_create_requirement. - Anchoring or retargeting which @Test proves a requirement - use
ek9_anchor_test(there is no set-status here: 'developed' is derived from anchors). - Reading a requirement or the graph - use
ek9_query_requirement.
Details
Modes: edit-body-text (authored why; a vertical-drift trigger — clears intent confirmation on confirmed descendants, advisory only, nothing becomes undeveloped), edit-title, edit-meta (empty value removes the key; unnamed attrs left alone), retire / un-retire (retire in place, optional supersededBy successor that must already exist), reparent (own parentId + optional rankKey; refused with kind would-create-cycle if it would make the node its own ancestor), confirm-intent (re-stamp confirmed_at), delete (the only gated mode — kind still-referenced while children/anchors remain). Other conflict kinds: target-not-found, target-retired (un-retire first), missing-value, parent-not-found, parent-retired. rename-slug is refused (a partial rename leaves dangling @Test anchors) - create the replacement and retire this node with supersededBy instead; each edit is a whole-file rewrite (no line range).
Arguments
| Argument | Type | Required | What it is |
|---|---|---|---|
authorKind | string: human | persona | yes | Who is making the change - recorded in the changelog, the same attribution ek9_create_requirement records. Required here: an edit is never attributed by inheritance (only a created child inherits its parent's author). |
authorName | string | yes | The changing identity's name; paired with authorKind. |
dryRun | boolean | When true nothing is written; the response shows the would-be edits with status:'ready'. | |
meta | object | For edit-meta: attributes to set. An empty value removes the key. Attributes not named are left alone. | |
mode | string: edit-body-text | edit-title | edit-meta | retire | un-retire | reparent | confirm-intent | delete | yes | What to change. |
parentId | string | For reparent: the new parent's requirement id. Omit to promote the requirement to a root. | |
rankKey | string | For reparent: position among the new siblings. | |
requirementId | string | yes | The requirement to change, e.g. REQ:fraud-screening. |
supersededBy | string | For retire: the successor requirement that replaces this one. It must already exist. | |
terse | boolean | Retained boolean alias for verbosity:'summary'. | |
text | string | The new body (edit-body-text) or the new title (edit-title). | |
verbosity | string: full | summary | none | Response size: full (default) carries each edit's full content; summary drops the edit bodies; none collapses edits[] to a count. |
Recorded calls
Real calls, recorded against small projects and checked on every build - a changed answer fails it. 3 of the 5 recorded are shown.
Update requirement delete refused
Request
{
"authorKind" : "human",
"authorName" : "Steve Limb",
"mode" : "delete",
"requirementId" : "REQ:payments"
}
Response
{
"conflicts" : [ {
"detail" : "1 thing(s) still reference this - reparent or remove them first: REQ:fraud",
"kind" : "still-referenced",
"subject" : "REQ:payments"
} ],
"edits" : [ ],
"meta" : {
"serverMs" : "<timing>"
},
"risk" : {
"crossesModuleBoundary" : false,
"estimatedSeverity" : "trivial",
"fileCount" : 0,
"lineCount" : 0,
"touchesPublicApi" : false,
"touchesTests" : false
},
"status" : "conflicts",
"summary" : "Would change nothing — 1 conflict(s)",
"wouldBeDiagnostics" : [ ],
"written" : false
}
Update requirement cycle refused
Request
{
"authorKind" : "human",
"authorName" : "Steve Limb",
"mode" : "reparent",
"parentId" : "REQ:fraud",
"requirementId" : "REQ:payments"
}
Response
{
"conflicts" : [ {
"detail" : "REQ:fraud sits beneath REQ:payments, so this would make it its own ancestor",
"kind" : "would-create-cycle",
"subject" : "REQ:payments"
} ],
"edits" : [ ],
"meta" : {
"serverMs" : "<timing>"
},
"risk" : {
"crossesModuleBoundary" : false,
"estimatedSeverity" : "trivial",
"fileCount" : 0,
"lineCount" : 0,
"touchesPublicApi" : false,
"touchesTests" : false
},
"status" : "conflicts",
"summary" : "Would change nothing — 1 conflict(s)",
"wouldBeDiagnostics" : [ ],
"written" : false
}
Update requirement dry run
Request
{
"authorKind" : "human",
"authorName" : "Steve Limb",
"dryRun" : true,
"mode" : "edit-title",
"requirementId" : "REQ:fraud",
"text" : "Changed"
}
Response
{
"conflicts" : [ ],
"edits" : [ {
"after" : "---\nreq_id: REQ:fraud\ntitle: Changed\nretired: false\nversion: 0.1.1\nparent_ref: null\nrank_key: V\nsuperseded_by: null\nconfirmed_at: null\ncreated_at: <instant>\nupdated_at: <instant>\nrule_anchors: []\nown_anchors: []\nabout_concepts: []\nmeta: {}\nauthors:\n - {kind: human, name: Steve Limb}\nchangelog:\n - {at: <instant>, by: human::Steve Limb, action: create}\n - {at: <instant>, by: human::Steve Limb, action: edit-title}\n---\n\n# Intent\n\nOriginal prose.\n",
"file" : ".ek9-ai/requirements/REQ-fraud.md",
"type" : "replace"
} ],
"meta" : {
"serverMs" : "<timing>"
},
"risk" : {
"crossesModuleBoundary" : false,
"estimatedSeverity" : "trivial",
"fileCount" : 1,
"lineCount" : 0,
"touchesPublicApi" : false,
"touchesTests" : false
},
"status" : "ready",
"summary" : "Would apply edit-title to REQ:fraud",
"wouldBeDiagnostics" : [ ],
"written" : false
}