kane-cli maintain closes the assurance loop with two commands:
maintain reconcile: when a requirement document changes, it turns that one changed source into an honest, row-by-row update plan for your suite.maintain evolve: re-designs a use-case whose design has gone stale.
.context/ store. Maintain adds no new kinds of knowledge; it updates the ones you already have.
maintain reconcile: one changed source, one triage
Use reconcile whenever a requirement document changes. It answers one question: what should the suite do about this change?
Reconcile re-ingests the source, re-extracts use-cases from the new version, and first shows you a changeset (what the change did to your knowledge). In a terminal, every proposed change (adds, updated versions, archives) then waits behind a review card, and nothing from the changeset is committed until you give a verdict. Only two things land without a card when the run finalizes: evidence attached to unchanged matches, and the extraction record itself.
Reconcile takes two explicit inputs, so it never has to guess which source a file belongs to:
--from <file|url>: the new version of the document. This is a file path or a remote source URL; see Remote sources below.--source-id <id>: the existing source that this file replaces. Reconcile moves that source’s head (its current version) to the new file. Find ids withkane-cli context list --type source. Required with a file; optional with a URL, because a URL carries its own id.
--apply <path> alone is enough, because the plan remembers its source.
Input checks
Before anything runs, reconcile checks its inputs in this order. These checks ask no questions, write nothing, and behave the same in every mode:- Both
--fromand--source-idare present. - The file exists and is a regular file.
- It is a document type that can be ingested.
- The source id names a known source.
- That source isn’t retired. Restore it first with
kane-cli context revert. - The file doesn’t already back a different live source. This is the fork guard: it stops one document’s history from silently splitting into another source’s, and the error suggests the
--source-idyou probably meant. - No live session is holding review work pinned to this source. This is the held-source guard: if such a session exists, reconcile refuses to move the head and names the session to finish first (
kane-cli context extract --resume <sid>), so the head never moves under evidence that is still being reviewed. If a session file can’t be read, the check fails closed (it refuses rather than assumes) and points you to thecontext sessionslist and clean commands, because an unreadable file can’t prove there is no hold.
2 with a message naming the next command to run. In --mode agent, these failures arrive on the NDJSON stream (error + done), never on stderr alone.
The changeset: what the change did
The changeset is shown first, before any action. The line list below is what--plan and the headless modes print:
14 stale · 2 direct, or — when nothing goes stale). The plan facts appear dimmed below the table.
- MODIFY: the re-extract matched an existing use-case whose content changed. Each MODIFY records why: either the source content changed, or the change caused a structural break.
- ADD: a use-case newly extracted from the changed source.
- ARCHIVE: the item’s evidence has decayed on all three counts. Every quote fails to relocate into the new text, and no other live source supports the item, and this run attached no fresh evidence. If any one of the three is missing, the item isn’t proposed for archiving.
The in-chat review (the default in a terminal)
In a terminal, reconcile runs as an in-chat review:- The extraction runs over the change, and every proposed change is held.
- The check-in offers
review N change(s) from <source>as its first row.laterstays available, every other row keeps working, and the offer comes back at each check-in until you take it. - Selecting it opens the decision briefing, then walks through the held changes one card at a time, highest risk first.
impact: approving marks 14 item(s) stale). A longer diff collapses to a summary plus a view diff row that commits nothing (esc returns to the card).
The verdicts:
- approve commits the change. An ADD creates the draft (and offers
design tests now). A MODIFY creates the new version with a redirect from the old one (and offersevolve the design now). An ARCHIVE applies a non-destructive retire, which you can undo at any time withkane-cli context revert. Offers are rows you choose; they never run on their own, and a child design run asks its questions in this same session. - reject drops the staged proposal and leaves nothing behind. Because nothing is remembered, a later reconcile may propose the same change again. This is deliberate.
- defer parks the decision as one durable gap. It appears in
cover gapswith the reconcile command as its remedy, and it clears when a later verdict lands on the same change. - ✎ / typing is steering: your words go to the agent, the remaining changes are finalized again, and revised cards are shown. Cards you already resolved never come back. ARCHIVE cards cannot be steered.
While a deferred change is on the record, Kane CLI releases older than 0.7.2 cannot pass the store’s integrity checks or commit to it. If several machines share a store, upgrade them to Kane CLI 0.7.2 or later together.
- Every verdict is checked again at commit time. If the target was retired during the review, the source’s head moved again, or an archive target gained new live evidence, the card is shown again with the reason. An approved change never lands differently from what you saw.
- There is no “approve all”. Row 1 carries the recommendation, so pressing Enter through the cards is the fast path, but every change gets its own decision. Esc on a card does nothing on purpose: verdicts are commits, so there is nothing to back out of.
- Your decisions are never lost. Verdicts are saved next to the proposal as you make them. Ctrl+C keeps every decision, and you resume the review with
--apply(below) or by resuming the session. The last verdict releases the source for other work.
--plan: a preview that doesn’t touch the suite
--plan records the source change and stages everything downstream. The proposed rows are kept in a stored plan (plan stored: <path>, under .context/reconcile/plans/), and no tests or designs are touched.
Two things do land, and the output says so:
- The head move, because the fact that the source changed is true whatever you decide.
- Updates to a matched use-case whose source content moved, because they are part of the re-extract itself.
impact: approving marks N item(s) stale), and a skipped arms line names every analysis that reconcile does not run.
To walk the plan later, run --apply <path>, or --apply on its own:
- If a live review is holding changes, bare
--applyresumes it as cards first, without the agent: no model and no network are needed, because your stored verdicts are the saved state. (A headless run that meets a held review refuses instead of guessing verdicts.) - With no held review, it picks the latest stored plan behind an approval prompt. Headless modes accept the prompt silently.
--apply --from <file> --source-id <id>recomputes the plan live instead.
--plan and --apply together is a usage error (exit 2). Running --plan again re-renders the stored plan. If the source hasn’t changed, reconcile says so truthfully (nothing to reconcile).
Remote sources: --from <url>
--from also accepts a remote source URL: a Jira issue or Confluence page, a public web page, or a Linear issue or document. These are the same URLs that context ingest takes.
Remote sources follow the same flow as files. Reconcile fetches the latest content through the provider, and the head moves if anything you would cite has changed. Everything downstream (the cards, --plan and --apply) works the same way.
- The id comes from the URL. It is
proj-123oreng-42for an issue,page-<id>for a Confluence page,doc-<id>for a Linear document, and a slug plus a short hash for a web page. That is why--source-idis optional. If you pass an id that contradicts the URL’s own id, reconcile refuses, because it never adopts a URL under a different id. To maintain a source you ingested under a custom id withcontext ingest --as, re-run that ingest with the same--as. - The kind of source must match, both ways. A URL cannot version a file-backed source that happens to share its id, and a file cannot version a remote source. Each case refuses and names the correct
--from. The same check runs when a stored plan is replayed, so a stale plan can never overwrite a source that is now backed by something else. - Stored plans remember the URL and recompute by fetching it again, the same way a file plan re-reads its file.
If a Jira issue was ingested with a Kane CLI release older than 0.7.2, its first reconcile after you upgrade may report a head move that is not a content edit. This is a one-time re-version of the source, not a change to review.
Running again: reconcile converges
You can safely repeat the same command. It picks up from wherever things stand:
A plan stored by an earlier kane-cli version is refused with a hint to recompute it, so plans never carry silently across format changes.
Headless modes
--mode agent|ci|override uses the same ask-policy table as extract and design. See Automation for the full contract and reconcile’s NDJSON stream. Three things are specific to reconcile:
- Headless runs don’t stage. The re-extract commits as it goes, and rows apply according to the mode.
overrideandciapply ADD and MODIFY rows automatically;cistops when a run needs a person’s judgement;agentstreams typed events and pauses. The in-chat review is available only in a terminal. - Archiving is never automatic. No headless mode archives anything; ARCHIVE decisions wait for an interactive session.
- The
--mode agentstream is pure NDJSON. It opens with a minimalrun_start, and nothing else prints on either output. The re-extract shares the same stream: its extract events appear between thereconcile_*events, each stampedverb: "reconcile". See Automation for the event list.
2 and asks for an explicit --mode, or for --plan to preview.
The rows
maintain evolve: re-design a stale use-case
- It only runs on stale designs. A target that is still fresh refuses.
--because "<reason>"is the supported override: your reason becomes the change context the re-design sees, and it is kept on the record. --from-stalecollects every use-case with stale designed entities. In a terminal it confirms them one at a time; with--mode agentit asks one question per use-case and runs nothing until all are answered.- In a terminal, evolve’s output starts with an aligned diff report, marks its child design runs with progress-dot lines, and ends with the same session summary that every interactive session prints.
- After a clean run, evolve reports the diff between the two design generations: what was superseded, what was created, what was kept unchanged, and which criteria’s verifying tests moved. A re-design doesn’t break what it didn’t change.
- Reconcile’s MODIFY rows lead here automatically. Run evolve directly when a design went stale outside a reconcile (an older change, or a retired source).
kane-cli cover gapslists stale designed entities in its ranked worklist.
Evolve runs a design, so, like extract, design and reconcile, it calls the KaneAI service and consumes credits.
Headless: --mode agent
Requires Kane CLI 0.8.21 or later.
--mode agent uses the same typed stream as design tests and reconcile: one JSON object per line on stdout, verb: "evolve", nothing on stderr, and done last. Agent mode never answers for you. The blast-radius confirmation becomes a question, the run pauses with exit 3, and the answer comes on the next call:
- The resume command keeps
--because. - With
--from-stalethere is one question per use-case, and nothing runs until every one is answered. A partial set of answers pauses again on the rest and keeps the answers you gave. After a partial answer, the suggested commands include the answers already given, so declining the rest still re-designs the use-cases you answered proceed. - A design session that pauses arrives as its own
session_paused, anddonecarries its resume command. Resume it, then run evolve again to get the diff. --modeacceptsinteractiveandagentonly (anything else refuses withMODE_USAGE). An answer to a question the run does not ask refuses withANSWER_USAGE.
Exit codes
Next steps
- Requirement sources: every file type and remote URL reconcile accepts.
- Coverage:
cover gaps --stage designis the standing worklist between reconciles. - Designing tests: what an approved ADD row actually runs.
- Automation: reconcile in CI, and its NDJSON stream.