@c4a/context-cli 0.5.29-alpha.1 → 0.5.29-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/context-cli",
3
- "version": "0.5.29-alpha.1",
3
+ "version": "0.5.29-alpha.2",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "context": "./cli.js"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "context",
3
3
  "description": "Context For AI — local knowledge workspace. Capture docs, extract code structure, compile into an interlinked wiki with source-traced facts. CLI does mechanical work; agent drives compile/drop via skill protocols.",
4
- "version": "0.5.29-alpha.1",
4
+ "version": "0.5.29-alpha.2",
5
5
  "author": {
6
6
  "name": "c4a"
7
7
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context",
3
- "version": "0.5.29-alpha.1",
3
+ "version": "0.5.29-alpha.2",
4
4
  "description": "Context For AI — local knowledge workspace. Capture docs, extract code structure, compile into source-traced local knowledge, query with citations, and govern source updates.",
5
5
  "author": {
6
6
  "name": "c4a"
@@ -7,7 +7,7 @@ allowed-tools: Bash(context:*, brew:*, curl:*, sh:*, scoop:*, choco:*, lark-cli:
7
7
  <!--
8
8
  This command has no companion skill. Its protocol (argument routing +
9
9
  missing-dependency install flow) lives inline here per the slash-command
10
- length exemption in packages/context-cli/CLAUDE.md.
10
+ length exemption for self-contained slash commands.
11
11
  -->
12
12
 
13
13
  ## Your task
@@ -6,16 +6,15 @@ allowed-tools: Read, Bash(context:*)
6
6
 
7
7
  <!--
8
8
  This command is slightly over the 30-line default because it carries
9
- the default-mode vs `--plan`-mode mode comparison inline; per the
10
- multi-mode exemption in packages/context-cli/CLAUDE.md, the mode
11
- contrast belongs here rather than split across skill references.
9
+ the default-mode vs `--plan`-mode comparison inline; the mode contrast
10
+ belongs here rather than split across skill references.
12
11
  The agent protocol itself still delegates to the compile-draft /
13
12
  compile-close skills.
14
13
  -->
15
14
 
16
15
  ## Your task
17
16
 
18
- Synthesise the align plan into the workspace `knowledge/` directory. The agent produces `CompileDraftAgentOutput` per Node; the CLI writes everything. Workspace reads go through `context workspace`; workflow writes go through `context compile` / `context mdrive`, never through direct file tools.
17
+ Synthesise the align plan into the workspace `knowledge/` directory. The agent produces compile draft JSON per Node; the CLI writes everything. Workspace reads go through `context workspace`; workflow writes go through `context compile` / `context mdrive`, never through direct file tools.
19
18
 
20
19
  Modes:
21
20
 
@@ -28,20 +27,30 @@ Preflight:
28
27
 
29
28
  1. Run `context workspace locate --format json` and use `ctxDir` from that JSON as `WORKSPACE_DIR`. In embedded layout it is the `.context/` directory; in root layout it is the current knowledge repo root. Use `WORKSPACE_DIR/output/...` and `WORKSPACE_DIR/knowledge/...` below; do not assume `.context/...`.
30
29
  2. Require `output/align.md` + `output/bind.yaml`; check them with `context workspace list output --format json`. If missing, tell the user to run `/context:align` and stop.
31
- 3. Run `context doctor`; output-align group must be green. Incremental cache group warnings are informational here; only output-align errors block compile. Run `context mdrive workspace stats --format json` and `context source list --format json` and record the before counts.
30
+ 3. Run `context doctor`; output-align group must be green. Incremental cache group warnings are informational here; only output-align errors block compile. Run `context mdrive workspace stats --format json`, `context source list --format json`, and `context status --format json`; record the before counts and `STATUS.semantic.refreshed_source_pending_compile.source_ids[]`.
32
31
  4. Read `output/align.md` with `context workspace read output/align.md --format text`. Record Nodes in the order they appear in `frontmatter.nodes[]` — do NOT re-sort.
33
32
  5. Run `context compile --changes --format json` and parse the JSON as `COMPILE_WORKSET`.
34
- - If `COMPILE_WORKSET.reason` is `no-changed-nodes`, report `no changed nodes`; stop before reading `compile-draft`, running any draft command, or running close.
33
+ - If `COMPILE_WORKSET.reason` is `no-changed-nodes` and there are no refreshed sources pending compile, report `no changed nodes`; stop before reading `compile-draft`, running any draft command, or running close.
35
34
  - If `COMPILE_WORKSET.status` is `unknown-input`, continue conservatively using the Nodes listed in `COMPILE_WORKSET.nodes`; keep the `unknown_inputs[]` reasons in the final report.
36
35
  - Otherwise process only `COMPILE_WORKSET.nodes`, preserving the `frontmatter.nodes[]` order. Per-Node `processing <slug>` echoes must match this order.
37
36
 
37
+ Review stdin rule: `context reconcile review` accepts at most one `-` input. If either the prepared context or the decisions document is passed through stdin, write the other payload to a temporary scratch file outside `WORKSPACE_DIR`, or reuse a durable CLI scratch file. Valid shapes are `context reconcile review --context - --decisions <scratch-file> --format json` or `context reconcile review --context <prepare-file> --decisions - --format json`; never pass `-` to both flags in the same command.
38
+
39
+ Refreshed-source loop:
40
+
41
+ 1. If `STATUS.semantic.refreshed_source_pending_compile.source_ids[]` is non-empty, process each source id before the per-Node draft loop.
42
+ 2. Run `context reconcile prepare --mode refresh --source <source-id> --format json`. Feed that JSON to `${CLAUDE_PLUGIN_ROOT}/skills/semantic-reconcile/SKILL.md`.
43
+ 3. Pass the skill output to `context reconcile review`, following the review stdin rule above: one input may be `-`, the other must be a scratch file. Resolve questions exactly like the per-Node loop.
44
+ 4. Default mode only: run `context reconcile apply --input <confirmed-decisions>`. In `--plan` mode, stop after review and report the not-written refresh decisions.
45
+ 5. After all refreshed sources are applied in default mode, run `context compile --changes --format json --ignore-source <source-id>` with one `--ignore-source` flag for each refresh-applied source. Use that filtered result for the per-Node loop. This does not rebuild section fingerprints early; it only removes Nodes whose remaining changed blocks came entirely from sources already handled by refresh reconciliation. If a Node still has changed blocks from other sources, unknown inputs, or full-context reasons, keep it in the ordinary per-Node loop.
46
+
38
47
  Per-Node loop:
39
48
 
40
- 1. For every workset Node, run `context compile --context <slug> --changed-only --save-output`. Use the JSON stdout as the NodeContext for the draft skill. When the workset requires full context, the CLI returns `incremental.status: "full-context"` with the `unknown_inputs[]` reasons while still using the changed-only entrypoint. The CLI stores the durable context scratch copy under `output/`. Do not expand the context with direct file tools; the NodeContext is the evidence boundary.
49
+ 1. For every workset Node, run `context compile --context <slug> --changed-only --save-output`. If the refreshed-source loop applied any source, append the same `--ignore-source <source-id>` flags used for the filtered workset. Use the JSON stdout as the NodeContext for the draft skill. When the workset requires full context, the CLI returns `incremental.status: "full-context"` with the `unknown_inputs[]` reasons while still using the changed-only entrypoint. The CLI stores the durable context scratch copy under `output/`. Do not expand the context with direct file tools; the NodeContext is the evidence boundary.
41
50
  2. Read `${CLAUDE_PLUGIN_ROOT}/skills/compile-draft/SKILL.md` and follow its procedures; keep the emitted draft JSON/YAML in memory.
42
51
  3. Pass the draft to `context compile --draft <slug> --input - --save-input --plan`. This validates schema, source refs, and mount matrix without touching `knowledge/`. On CLI rejection, read the error verbatim, fix the draft via the skill's self-verify, and retry up to 3 times.
43
52
  4. Run `context reconcile prepare --mode compile --node <slug> --draft WORKSPACE_DIR/output/compile.<slug>.draft.yaml --format json`. Feed that JSON to `${CLAUDE_PLUGIN_ROOT}/skills/semantic-reconcile/SKILL.md`.
44
- 5. Pass the skill output to `context reconcile review --context <prepare-file-or-stdin> --decisions <decisions-file-or-stdin> --format json`. If questions are returned, ask the user in business language and rewrite unresolved `ask_user` items into final actions before applying.
53
+ 5. Pass the skill output to `context reconcile review`, following the review stdin rule above: one input may be `-`, the other must be a scratch file. If questions are returned, ask the user in business language and convert unresolved `ask_user` items into final actions before applying.
45
54
  6. Default mode only: run `context reconcile apply --input <confirmed-decisions>`. This writes active knowledge, verifies, and records `decisions/semantic.yaml`. In `--plan` mode, stop after review and report the not-written decisions.
46
55
  7. Persistent failure → stop and surface the full rejection list; never edit rendered files to bypass.
47
56
 
@@ -60,7 +69,7 @@ Never use Read / Glob / Grep / Write against `WORKSPACE_DIR`; use `context works
60
69
  For large draft payloads, feed stdin directly into the `context compile` command with a heredoc. Do not pipe a heredoc through another command and do not redirect generated content into workspace files:
61
70
 
62
71
  ```bash
63
- context compile --draft billing-api --input - --save-input <<'JSON'
72
+ context compile --draft billing-api --input - --save-input --plan <<'JSON'
64
73
  {
65
74
  "target_node": "billing-api",
66
75
  "actions": [
@@ -75,8 +84,8 @@ Final report contract (default mode):
75
84
  - Report in the user's conversation language.
76
85
  - Keep a stable structure with these semantic sections; translate section headings into the user's conversation language instead of copying these English labels verbatim:
77
86
  1. Completion headline.
78
- 2. Per-Node writes table with one row per Node in align frontmatter order. Columns: Node title or slug, type, and add / update / supersede / deprecate counts. Include skipped count only when non-zero.
79
- 3. Close stage with `context compile --close` result, final node/section totals, verify status, changelog stamp, incremental counts (`recompiled`, `locator_updates`, `rebuilt`), section fingerprint rebuild count, and archive directory for compile scratch files when present.
87
+ 2. Semantic apply table. Include refreshed-source rows first in source-id order when the refreshed-source loop ran, then one row per Node in align frontmatter order. Columns: target (source id or Node title/slug), type (`refresh` or Node type), and the `context reconcile apply --format json` counts: `applied`, `skipped`, `merged`, `superseded`, `kept_separate`, and `questions_resolved`. Include `reanchored`, `removed_unsupported`, and `split_then_reanchored` only when non-zero.
88
+ 3. Close stage with `context compile --close` result, final node/section totals, verify status, changelog stamp, incremental counts (`recompiled`, `locator_updates`, `rebuilt`), section fingerprint rebuild count, and archive directory for compile scratch files when present. Do not use close output as the semantic apply summary; aggregate the per-Node `context reconcile apply` results from Step 6.
80
89
  4. Before/after status diff table with at least total nodes, node counts by type, total sections, and last compile time.
81
90
  5. Knowledge files as clickable markdown links. Use absolute path targets without `file://`, for example `[knowledge/entity/vmok.md](/abs/path/.context/knowledge/entity/vmok.md)`. Include `_index.md`, `changelog.md`, and every Node article returned by `context mdrive node list --format json`. Use the path relative to `WORKSPACE_DIR` as the link label.
82
91
  6. Optional next step only when there is a concrete useful follow-up (for example recapture stale material or run `/context:align` to revise structure).
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Debug helper: run @c4a/extract against a path and print the ExtractionResult (no files written)."
2
+ description: "Debug helper: run extraction against a path and print structured results (no files written)."
3
3
  argument-hint: "<path> [--format json|jsonl|pretty]"
4
4
  allowed-tools: Bash(context:*)
5
5
  ---
@@ -7,7 +7,7 @@ allowed-tools: Bash(context:*)
7
7
  <!--
8
8
  This command has no companion skill. Its protocol (the focus multi-choice
9
9
  UX before `context init` runs) lives inline here per the slash-command
10
- length exemption in packages/context-cli/CLAUDE.md.
10
+ length exemption for self-contained slash commands.
11
11
  -->
12
12
 
13
13
  ## Your task
@@ -10,6 +10,10 @@ Purge the workspace archive. This is destructive: it deletes all restorable
10
10
  artifacts under `archive/` that were created by `context drop --apply-plan`.
11
11
  It does not modify active `raw/` or active `knowledge/`.
12
12
 
13
+ It does not delete `output/archive/`. Compile/align scratch archives are kept
14
+ under the output lifecycle so prior agent inputs remain inspectable; clean them
15
+ manually or via a future output-retention policy, not with `context purge`.
16
+
13
17
  Run `context purge $ARGUMENTS`. If `--yes` is absent, the CLI prints a summary
14
18
  and asks for confirmation. Relay that summary in the user's language and do not
15
19
  try to inspect `archive/` yourself.
@@ -71,6 +71,19 @@ edges:
71
71
  decisions:
72
72
  notes: |
73
73
  <brief rationale + demotions + unresolved questions>
74
+ new_candidates:
75
+ - slug: <accepted-node-slug>
76
+ mentions:
77
+ - file: <raw-file>
78
+ line: <line-number>
79
+ quote: <verbatim raw quote>
80
+ demotions:
81
+ - heading: <candidate or heading that was not promoted>
82
+ outcome: kept as Section | merged into <slug> | ignored as navigation
83
+ mentions:
84
+ - file: <raw-file>
85
+ line: <line-number>
86
+ quote: <verbatim raw quote>
74
87
  ambiguous: [ ... carried from scan + discovered re-routes ... ]
75
88
  orphans: [ ... carried from scan ... ]
76
89
  ```
@@ -84,7 +97,8 @@ user should never need to know the internal Node / Section / Edge model.
84
97
  1. **Same thing or separate topic?** Pre-resolve with the identity tests.
85
98
  Surface only hard cases in `decisions.ambiguous[]`.
86
99
  2. **Standalone lookup or parent detail?** Set the internal parent / demotion
87
- fields yourself. Ask the user only when future retrieval behavior is unclear.
100
+ fields yourself. Ask the user only when future user-visible lookup or
101
+ organization is unclear.
88
102
  3. **Business relationship?** Ask only when raw evidence leaves multiple
89
103
  plausible meanings, such as alternatives vs dependency vs co-location.
90
104
  4. **Validity change?** Ask when old and new source documents conflict about
@@ -115,6 +129,11 @@ For each `new_candidates[]` from `output/align.scan-decisions.json`:
115
129
  3. For `concept`, run the [Concept three-test gate](${CLAUDE_PLUGIN_ROOT}/skills/align-scan/references/data-model.md#concept-three-test-gate). Any ❌ → demote; do not emit.
116
130
  4. Pick `contains_parent` from the scan's `suggested_parent` or a matching existing Domain.
117
131
  5. Fill `planned_sections[]` only where raw clearly justifies kinds that fit the target type per the [Section mount matrix](${CLAUDE_PLUGIN_ROOT}/skills/align-scan/references/data-model.md#section-mount-matrix).
132
+ 6. For every candidate you promote into `nodes[]`, copy its raw `mentions[]`
133
+ into `decisions.new_candidates[]` under the final `slug`. For every
134
+ candidate or heading you do not promote, add `decisions.demotions[]` with
135
+ the raw mention and the outcome. These are review evidence, not new
136
+ summaries.
118
137
 
119
138
  ### Step 4 — Enumerate edges
120
139
 
@@ -133,6 +152,8 @@ Emit the [AlignRenderInput shape](#alignrenderinput-shape) as YAML for the calle
133
152
  - [ ] Every `entity` has ≥1 A/B tag — if not, **Step 3**.
134
153
  - [ ] Every `action` clears the establishment bar OR is demoted — if not, **Step 3**.
135
154
  - [ ] Every `concept` passes the three-test gate — if not, **Step 3**.
155
+ - [ ] Every promoted new candidate has `decisions.new_candidates[].mentions[]` copied from scan evidence — if not, **Step 3**.
156
+ - [ ] Every demoted candidate/heading has `decisions.demotions[]` with raw mentions — if not, **Step 3**.
136
157
  - [ ] No cycles in `contains` + `refines` — if any, **Step 4**.
137
158
  - [ ] No `refers_to_nodes` edges — if any, **Step 4**.
138
159
  - [ ] No `new` slug collides with an existing slug — if any, treat as `modified` in **Step 3**.
@@ -325,7 +325,7 @@ Warnings don't block; errors flip exit to 2.
325
325
  | Code | Level | Meaning | Minimum fix |
326
326
  |---|---|---|---|
327
327
  | `dropped-source-reference` | error | Node `sources[]` lists a dropped source | Run `/context:drop` to complete cleanup; it uses `context mdrive node update` to remove the id |
328
- | `dangling-source-alias` | error | Section `src-N` past end of `sources[]` | Re-run `context compile --draft <slug>` with correct `source_ref` |
328
+ | `dangling-source-alias` | error | Section `src-N` past end of `sources[]` | Re-run `context compile --draft <slug> --plan` with correct `source_ref` |
329
329
  | `sourceless-node` | warning | Node `sources[]` is empty after cleanup | Keep only if intentionally orphaned by `/context:drop`; otherwise re-anchor or add a source via `context mdrive node update` |
330
330
  | `body-ad-hoc-heading` | error | Node body has a heading the parser reads as a nested Node | Re-run `/context:compile` so the draft loop moves that content into Sections |
331
331
  | `invalid-section-mount` | error | Kind × Node type mismatch | Re-run `/context:compile`; or deprecate via `context mdrive section deprecate` |
@@ -45,7 +45,8 @@ edges, slugs, and source references.
45
45
  | Two products / systems / ideas might be alternatives, dependency, or merely co-mentioned | Yes | If unclear and no user answer, keep only the shared parent; no direct relationship |
46
46
  | A stale source conflicts with a newer active source | Yes | Keep both candidates and ask which claim is current |
47
47
  | A source is being dropped and a claim has no replacement evidence | No | Mark the claim as no longer supported |
48
- | A source is being dropped and another source appears to support the same claim, but the match is inferred | Usually no; show it in the impact plan | Move support to the surviving source and mark the confidence as inferred |
48
+ | A source is being dropped and another source explicitly supports the same claim | No | Move support to the surviving source and mark the confidence based on evidence strength |
49
+ | A source is being dropped and another source only appears to support the claim by inference | Yes | Do not silently re-anchor; ask the user or mark the claim as unsupported |
49
50
  | A proposed rename changes the user's vocabulary | Yes | Keep the original title / alias |
50
51
  | A section kind, edge type, source-ref, or file layout choice is required | No | Agent maps from the user's intent to the model |
51
52
 
@@ -53,32 +54,34 @@ edges, slugs, and source references.
53
54
 
54
55
  ### Align: standalone topic or detail
55
56
 
56
- Context: "I found several Vmok subsections such as 'Core capabilities',
57
- 'Scenarios', and 'Integration example'. The decision is whether people will
58
- search these directly later."
57
+ Context: "I found several payment runtime subsections such as 'Isolation
58
+ model', 'Retry policy', and 'Integration example'. The decision is whether
59
+ people will search these directly later."
59
60
 
60
- Question: "How should these Vmok subsections be organized?"
61
+ Question: "How should these payment runtime subsections be organized?"
61
62
 
62
63
  Choices:
63
64
 
64
- - "Keep them as parts of Vmok" — choose this if people normally read them
65
- while looking at Vmok.
65
+ - "Keep them as parts of payment runtime" — choose this if people normally
66
+ read them while looking at payment runtime.
66
67
  - "Make them separate searchable entries" — choose this if people will ask
67
- for "Vmok integration example" or "Vmok scenarios" directly.
68
+ for "payment retry policy" or "payment runtime integration example" directly.
68
69
  - "Keep only the strongest one separate" — choose this when only one
69
70
  subsection deserves direct lookup.
70
71
 
71
72
  ### Align: relationship meaning
72
73
 
73
- Context: "Vmok and Garfish appear near each other in the source documents, but
74
- the text does not clearly say how they relate."
74
+ Context: "Portal Shell and Plugin Runtime appear near each other in the source
75
+ documents, but the text does not clearly say how they relate."
75
76
 
76
- Question: "What is the business relationship between Vmok and Garfish?"
77
+ Question: "What is the business relationship between Portal Shell and Plugin
78
+ Runtime?"
77
79
 
78
80
  Choices:
79
81
 
80
82
  - "Comparable alternatives" — people may compare them or choose one.
81
- - "Vmok is based on Garfish" — Vmok needs Garfish or builds on it.
83
+ - "Portal Shell is based on Plugin Runtime" — Portal Shell needs Plugin
84
+ Runtime or builds on it.
82
85
  - "Same area, no direct relationship" — both belong under the same broader
83
86
  topic, but there is no direct link.
84
87
 
@@ -100,7 +103,8 @@ Choices:
100
103
 
101
104
  - "Only navigation" — use them to understand relationships, not as content.
102
105
  - "Preserve the explanation" — keep the useful prose in the relevant topic.
103
- - "Not sure" — keep a short summary for now.
106
+ - "Not sure" — keep only raw-backed prose in the relevant topic and flag the
107
+ uncertainty in the summary.
104
108
 
105
109
  ### Align: old or conflicting source
106
110
 
@@ -151,5 +155,5 @@ Choices:
151
155
  | "Keep as Section or promote to Concept?" | "Will people search this as its own topic, or only read it inside the parent topic?" |
152
156
  | "Choose related_to / depends_on / no edge." | "Are these alternatives, does one build on the other, or are they only in the same area?" |
153
157
  | "3 raw files all have Relations blocks. Drop or keep as Section?" | "I found repeated related-links sections. They look like navigation, so I will treat them as structure and not copy them as content." |
154
- | "Re-anchor section-3 from src-1 to src-2?" | "Another source still supports this claim, so I will keep it but mark the support as inferred." |
155
- | "Rename slug vmok-core-capability?" | "Should readers see this as 'Vmok core capabilities', or do you prefer another title?" |
158
+ | "Re-anchor section-3 from src-1 to src-2?" | "Another source explicitly supports this claim, so I will keep it; if the support is only inferred, I will ask before changing it." |
159
+ | "Rename slug payment-retry-policy?" | "Should readers see this as 'payment retry policy', or do you prefer another title?" |
@@ -6,8 +6,8 @@ description: >
6
6
  raw snippets from `bind.yaml` + existing Sections if any), classifies
7
7
  every raw fragment into a Section kind via the priority chain, writes
8
8
  content + detail + confidence + `source_ref_text`, and emits a
9
- `CompileDraftAgentOutput` JSON. The CLI applies the actions via
10
- `context compile --draft <slug> --input <file>`. Activates when
9
+ compile draft JSON document. The CLI validates the actions via
10
+ `context compile --draft <slug> --input <file> --plan`. Activates when
11
11
  `/context:compile` iterates across the confirmed align plan.
12
12
  tools:
13
13
  - Read
@@ -22,7 +22,7 @@ deprecate / skip` actions; emit JSON; the CLI performs every write.
22
22
  ## TL;DR — Non-negotiables
23
23
 
24
24
  - One Node per invocation — `target_node` MUST equal `node.slug`; no cross-Node writes.
25
- - Agent emits JSON only; no markdown, no direct workspace file writes. The caller passes the JSON to `context compile --draft <slug> --input -`; the caller adds `--save-input` when a durable scratch copy is needed.
25
+ - Agent emits JSON only; no markdown, no direct workspace file writes. The caller passes the JSON to `context compile --draft <slug> --input - --plan`; the caller adds `--save-input` when a durable scratch copy is needed.
26
26
  - Default compile sends changed-only NodeContext. Treat `raw_snippets[]` as the complete evidence boundary; never use direct workspace file tools to expand it.
27
27
  - If `incremental.status` is `full-context`, draft from the full fallback and preserve the `unknown_inputs[]` reasons in any abort/retry explanation.
28
28
  - The CLI may deterministically skip unchanged output or update locator-only evidence before writing. Do not force rewrites to bypass fingerprint skip.
@@ -35,6 +35,7 @@ deprecate / skip` actions; emit JSON; the CLI performs every write.
35
35
  - For `add` and `supersede.new`, omit optional fields when empty; do not emit `detail: null`. `detail: null` only has "clear existing detail" meaning on `update`.
36
36
  - `refers_to_nodes[]` only carries slugs present in the context's glossary or existing Sections; never invent one.
37
37
  - `supersede` is for semantic replacement; `update` is for typo / wording fixes; `deprecate` needs a `reason`; `skip` is the honest default when raw adds nothing.
38
+ - Domain containers may legitimately compile to no Sections. If their raw snippets only contain navigation (`Parent` / `Children` / `Related` / `Relations`) or placeholder text that explicitly says no detailed content is available, emit `skip`; do not turn the align summary or placeholder into a `description` Section.
38
39
  - FAQ collections attach to the most specific Node (Entity → Concept → Action → Domain fallback); never a standalone "FAQ Concept" container.
39
40
  - Output language: `content` / `detail` match the raw material; user-facing abort/retry explanations match the user's conversation language; kind / confidence / slug identifiers / `source_ref` format stay English.
40
41
 
@@ -85,7 +86,7 @@ they are the evidence floor.
85
86
  `source_id` is the source registry id, such as `local:billing`; `src-N`
86
87
  aliases only appear inside `source_ref` strings.
87
88
 
88
- ## Output — `CompileDraftAgentOutput`
89
+ ## Output — Compile Draft JSON
89
90
 
90
91
  ```jsonc
91
92
  {
@@ -154,13 +155,18 @@ Before emitting `{op: add, kind: description}`, walk three gates:
154
155
 
155
156
  If the resulting Node has >50% `description` Sections, treat it as a quality smell: redraft only when the raw snippets actually support more precise Section kinds. Sparse Nodes may legitimately end with one concise `description` or a `skip`; do not invent thin `spec` Sections just to improve the ratio.
156
157
 
158
+ Domain container exception: if a Domain's evidence is only a child list,
159
+ relation navigation, or placeholder wording, emit `skip`. The Domain page can
160
+ still be useful via `## Contains` and graph edges created from align; a
161
+ navigation-only snippet is not evidence for a new `description` claim.
162
+
157
163
  ## Glossary and `refers_to_nodes`
158
164
 
159
165
  When raw mentions a name that overlaps the workspace glossary, put
160
166
  that name's slug in `refers_to_nodes[]` for the Section that discusses
161
- it — do NOT substitute it into the prose. This is how cross-Node
162
- retrieval works ("which Sections mention React?"). Slugs come from
163
- the context's existing Sections + glossary; never invent one. A
167
+ it — do NOT substitute it into the prose. This preserves explicit
168
+ cross-Node references for query answers and citations without rewriting
169
+ the claim. Slugs come from the context's existing Sections + glossary; never invent one. A
164
170
  Section can reference multiple Nodes (common on `comparison` /
165
171
  `decision`).
166
172
 
@@ -227,7 +233,7 @@ For each change from Steps 2-3:
227
233
 
228
234
  ### Step 5 — Emit the JSON
229
235
 
230
- Emit one `CompileDraftAgentOutput` document for the caller to pass to `context compile --draft <slug> --input -` (or `context compile --draft <slug> --input - --save-input` when a durable scratch copy is needed). No markdown wrapper, no leading prose, no trailing commentary.
236
+ Emit one compile draft JSON document for the caller to pass to `context compile --draft <slug> --input - --plan` (or `context compile --draft <slug> --input - --save-input --plan` when a durable scratch copy is needed). No markdown wrapper, no leading prose, no trailing commentary.
231
237
 
232
238
  ### Step 6 — Self-verify
233
239
 
@@ -47,11 +47,14 @@ The JSON plan has:
47
47
  | `affected_nodes[]` | Topics whose source list contains the dropped source |
48
48
  | `affected_nodes[].sections[]` | Knowledge items that require semantic reconciliation before the source is dropped |
49
49
  | `affected_nodes[].reindex_sections[]` | Knowledge items whose internal source alias will be renumbered after the source is removed |
50
- | `affected_nodes[].will_be_sourceless` | Topic may be archived if it has no remaining active content after cleanup |
51
- | `affected_graph_edges[]` | Explicit graph edges that will be removed because one endpoint leaves active knowledge |
50
+ | `affected_nodes[].will_be_sourceless` | Topic has no remaining source ids after cleanup |
51
+ | `affected_nodes[].will_be_empty` | Topic has no remaining Section/body/children/contains after cleanup and may be archived even if another source id remains |
52
+ | `affected_graph_edges[]` | Explicit graph edges that will be removed if one endpoint is archived by apply |
52
53
  | `unaffected_references[]` | Topic relationships that mention affected topics but are not source evidence |
53
54
  | `summary` | Counts for confirmation and changelog |
54
55
 
56
+ If a non-domain Node would keep an active source id but lose all of its own Sections while still carrying child Nodes, contains links, or body text, do not rely on verify to catch it after mutation. Produce a semantic reanchor/split decision that preserves a supported Section, or expect `drop --apply-plan` to reject before writing.
57
+
55
58
  ## User-facing impact summary shape
56
59
 
57
60
  ```
@@ -88,6 +91,9 @@ appends a `[drop]` line to `knowledge/changelog.md`, records
88
91
  `decisions/semantic.yaml`, and runs verify. It exits
89
92
  non-zero if the source-id is unknown, already dropped, plan shape is invalid,
90
93
  the plan is stale, semantic decisions are unresolved/invalid, or verify reports errors.
94
+ In drop mode, `remove_unsupported` means physical removal from active knowledge
95
+ after the archive captures the before snapshot; compile/refresh apply uses the
96
+ same action name for Section deprecation.
91
97
 
92
98
  </reference>
93
99
 
@@ -108,8 +114,9 @@ source-already-dropped, relay the error and stop.
108
114
  Render the [User-facing impact summary shape](#user-facing-impact-summary-shape)
109
115
  from the plan JSON in the user's language. Make clear that dropping a source
110
116
  removes listed content from active knowledge but keeps it restorable under
111
- `archive/` until `context purge`. Mention graph edge cleanup when
112
- `affected_graph_edges[]` is non-empty. Include the reason that will be stamped; if
117
+ `archive/` until `context purge`. Mention conditional graph edge cleanup when
118
+ `affected_graph_edges[]` is non-empty; these edges are removed only if the
119
+ endpoint leaves active knowledge after reconciliation. Include the reason that will be stamped; if
113
120
  it is still unknown, ask for the reason before continuing. If `--yes`, log
114
121
  "auto-confirmed per --yes" and continue. Otherwise wait for `y`; abort on
115
122
  anything else without writing.
@@ -125,7 +132,7 @@ context reconcile prepare --mode drop --drop-plan <plan-file> --format json
125
132
  Invoke `${CLAUDE_PLUGIN_ROOT}/skills/semantic-reconcile/SKILL.md` with that
126
133
  prepare payload. Save its decision document outside `WORKSPACE_DIR`, then run
127
134
  `context reconcile review --context <context-file> --decisions <decisions-file> --format json`.
128
- If review returns any `questions[]`, ask the user and rewrite those decisions
135
+ If review returns any `questions[]`, ask the user and convert those decisions
129
136
  from `ask_user` into one of `reanchor`, `remove_unsupported`, or
130
137
  `split_then_reanchor` before continuing. Do not let `--yes` bypass this step.
131
138
 
@@ -44,23 +44,46 @@ decisions:
44
44
  source_ref: "src-2#runtime L12-14"
45
45
  source_ref_text: "sandboxing to avoid state pollution"
46
46
  rationale: "The new evidence refines the same claim."
47
- user_confirmation:
48
- required: true
49
- question_type: merge_confirmation
50
47
  ```
51
48
 
52
49
  ## Action Rules
53
50
 
54
- | action | Required fields |
55
- |---|---|
56
- | `duplicate_skip` | `target` |
57
- | `merge_update` | `target`, `proposed.content`, `proposed.source_ref` |
58
- | `supersede` | `target`, `proposed.kind`, `proposed.content`, `proposed.source_ref` |
59
- | `reanchor` | `target`, `proposed.source_ref`, `proposed.confidence` |
60
- | `remove_unsupported` | `target` |
61
- | `keep_separate` | `target`, `proposed.kind`, `proposed.content`, `proposed.source_ref` |
62
- | `split_then_reanchor` | `target`, `proposed.sections[]` |
63
- | `ask_user` | `user_confirmation.required: true` |
51
+ | action | Required fields | Validation |
52
+ |---|---|---|
53
+ | `duplicate_skip` | `target` | Exact duplicate or already-applied no-op only. |
54
+ | `merge_update` | `target`, `proposed.content`, `proposed.source_ref`, `proposed.source_ref_text` when present in prepare | Final content must be supported by one raw line range; `proposed.kind`, when present, must match target kind. |
55
+ | `supersede` | `target`, `proposed.kind`, `proposed.content`, `proposed.source_ref`, `proposed.source_ref_text` when present in prepare | New Section claim must be supported by one raw line range. |
56
+ | `reanchor` | `target`, `proposed.source_ref`, `proposed.confidence` | Use only when target content is still supported by the new source. |
57
+ | `remove_unsupported` | `target` | Use when no active source supports the target claim in this mode. |
58
+ | `keep_separate` | `target`, `proposed.kind`, `proposed.content`, `proposed.source_ref`, `proposed.source_ref_text` when present in prepare | New orthogonal claim must be supported by one raw line range. |
59
+ | `split_then_reanchor` | `target`, `proposed.sections[]` with each Section carrying `kind`, `content`, `source_ref`, and `source_ref_text` when present in prepare | Each split Section must be independently supported by its cited raw line range. |
60
+ | `ask_user` | `user_confirmation.required: true` | Use only when business meaning or support cannot be decided from prepared evidence. |
61
+
62
+ For `merge_update`, `supersede`, `keep_separate`, and
63
+ `split_then_reanchor`, the final Section content must be lexically supported by
64
+ the cited raw line range in `proposed.source_ref`. Preserve
65
+ `proposed.source_ref_text` from the prepared context when it is present; it is
66
+ the human-readable evidence text the CLI used to derive the canonical
67
+ `source_ref`. Content should retain the raw evidence's key domain terms,
68
+ numbers, code literals, and named entities. Do not turn sparse raw evidence
69
+ into a broad summary, and do not cite a title, `Relations`, `Parent`,
70
+ `Children`, or `Related` navigation line as the only support for a substantive
71
+ claim.
72
+
73
+ The support gate exists to prevent orphan claims and false evidence links, not
74
+ to optimize retrieval. Prefer preserving a precise raw-backed claim over
75
+ rewriting content into a smoother summary. If a useful reader summary would
76
+ combine multiple evidence ranges, choose `split_then_reanchor` or `ask_user`
77
+ instead of forcing it into one `source_ref`.
78
+
79
+ Final executable decisions must not carry `user_confirmation.required: true`.
80
+ Use that flag only on `action: ask_user` items that still require user input.
81
+
82
+ `remove_unsupported` has mode-specific write behavior. In compile/refresh
83
+ apply it deprecates the target Section so the unsupported claim remains visible
84
+ as inactive history. In drop apply it physically removes the Section from active
85
+ knowledge after `archive/sources/.../knowledge/before/` captures the pre-drop
86
+ file. Use the same action only when this mode-specific outcome is intended.
64
87
 
65
88
  </reference>
66
89
 
@@ -82,7 +105,7 @@ decision as a prior only and continue judging.
82
105
  Classify each item:
83
106
 
84
107
  - Exact same claim already active -> `exact_duplicate` + `duplicate_skip`.
85
- - Same claim with safer wording and one supporting source -> `strong_equivalent` or `near_duplicate` + `merge_update`.
108
+ - Same claim with a raw-supported correction or refinement from one supporting source -> `strong_equivalent` or `near_duplicate` + `merge_update`.
86
109
  - Additional but separate boundary -> `complement` + `keep_separate`.
87
110
  - New material replaces old rule -> `supersedes` + `supersede`.
88
111
  - Direct contradiction -> `conflicts` + `ask_user`.