cyber-sdd 0.6.0 → 0.6.1

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.
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "homepage": "https://github.com/cyberuni/cyber-sdd",
9
9
  "repository": "https://github.com/cyberuni/cyber-sdd",
10
- "version": "0.6.0",
10
+ "version": "0.6.1",
11
11
  "skills": "./skills",
12
12
  "agents": [
13
13
  "./agents/sdd-automaton.md",
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "homepage": "https://github.com/cyberuni/cyber-sdd",
9
9
  "repository": "https://github.com/cyberuni/cyber-sdd",
10
- "version": "0.6.0",
10
+ "version": "0.6.1",
11
11
  "skills": "./skills",
12
12
  "agents": [
13
13
  "./agents/sdd-automaton.md",
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "homepage": "https://github.com/cyberuni/cyber-sdd",
9
9
  "repository": "https://github.com/cyberuni/cyber-sdd",
10
- "version": "0.6.0",
10
+ "version": "0.6.1",
11
11
  "skills": "./skills",
12
12
  "agents": [
13
13
  "./agents/sdd-automaton.md",
@@ -96,7 +96,7 @@ session, or fold judging into your context, which **forfeits grader independence
96
96
  as such. Do not design for depth > 2.
97
97
 
98
98
  A cold-judge or builder dispatch **may** instead be realized through a general-purpose dispatch
99
- capability's `subagent | channel` seam (ADR-0023, referenced by intent — never a pinned mechanism);
99
+ capability's `subagent | channel` seam (referenced by intent — never a pinned mechanism);
100
100
  that is an alternative realization of the same spawns above, not a change to the default depth-1/
101
101
  depth-2 behavior described here.
102
102
 
@@ -108,5 +108,4 @@ handoff. Hand SDD's own judges (`sdd-spec-judge`, `sdd-impl-judge`) to the
108
108
  capability **by file path, never by name** — `agents/<name>.md` under the SDD plugin root, the folder
109
109
  your own definition ships in. Locate that root from the SDD skill that spawned you (two levels above
110
110
  its base directory) or the plugin root your brief names; if no file is there, send the capability no
111
- request for that judge and spawn it as a portable cold subagent (`sdd:<name>`) instead. Full model: `start-mission`'s "Dispatch transport" note and the `design/harness-spawning`
112
- node of the SDD project spec (repo-only).
111
+ request for that judge and spawn it as a portable cold subagent (`sdd:<name>`) instead. Full model: `start-mission`'s "Dispatch transport" note.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: sdd-impl-judge
3
- description: "Internal SDD impl-judge (default). Grades the implementation against the frozen .feature at the impl gate — re-derives each scenario's oracle independently (ADR-0016), runs the impl-producer's verification, and emits per-scenario pass/fail plus a structural read. Spawned cold by the conductor; never user-triggered."
3
+ description: "Internal SDD impl-judge (default). Grades the implementation against the frozen .feature at the impl gate — re-derives each scenario's oracle independently, runs the impl-producer's verification, and emits per-scenario pass/fail plus a structural read. Spawned cold by the conductor; never user-triggered."
4
4
  model: sonnet
5
5
  effort: high
6
6
  ---
@@ -18,7 +18,7 @@ the **conductor** (`start-mission`) turns the rollup into the gate
18
18
  verdict and the leash.
19
19
 
20
20
  Its verdict answers **"does the frozen contract hold"**, not "did the producer's tests pass" — the
21
- producer's own green run is a **pre-filter, never the verdict** (ADR-0016). It does **not** judge
21
+ producer's own green run is a **pre-filter, never the verdict**. It does **not** judge
22
22
  domain contract quality — a plugin's own impl-judge does that when the registry resolves one for the
23
23
  artifact-type.
24
24
 
@@ -39,7 +39,8 @@ when you grade against that bar. The **impl-gate lens set is {builder, architect
39
39
  candidates the matcher hands you (floor `sdd:builder-impl-governance` /
40
40
  `sdd:architect-impl-governance`). Compose per the precedence above — never hand-enumerate.
41
41
  - **Fixed-universal:** `sdd:ownership-governance` — the write-ownership matrix; the impl-judge must
42
- not modify `spec.md` or the `.feature`, and a behavior-changing gap is a `BLOCKER`, not an edit.
42
+ not modify `spec.md` or the `.feature`, and a behavior-changing gap is a `BLOCKER`, not an edit —
43
+ and `sdd:gate-validation-governance` — the gate-legality contract (legal-state tuples, derived sync).
43
44
 
44
45
  ## Input
45
46
 
@@ -49,7 +50,7 @@ IMPLEMENTATION_PATHS: impl-layer paths from the ## Artifacts table
49
50
  VERIFICATION_PATHS: the verification the impl-producer authored (or discoverable across IMPLEMENTATION_PATHS)
50
51
  ```
51
52
 
52
- ## The layered verdict (ADR-0016)
53
+ ## The layered verdict
53
54
 
54
55
  Cold context removes the author's *conversational* bias but not a same-model grader's *correlated*
55
56
  blind spots, and re-running the producer's own assertions only confirms internal consistency. So the
@@ -196,7 +196,7 @@ is separate from strategy-drafting above; you draft nothing and write nothing to
196
196
  tracked issue.
197
197
  - There is **no legal terminal value** for a plan brief's `status` field to autofix into — the
198
198
  contract's own answer to "this mission is over" is retirement (a tracked deletion), not a status
199
- flag (`design/provenance-model.md` reserves the plan-level `status` to the two-value dispatch
199
+ flag (the plan-level `status` is reserved to the two-value dispatch
200
200
  flag `active | approved`). You never write a plan brief's `status`.
201
201
 
202
202
  ## Boundaries
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyber-sdd",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Spec-Driven Development. Scaffold, validate, and maintain behavioral specs (spec.md + .feature files) for software features.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,8 +21,7 @@ The scheduler treats two missions touching different `.feature` files as **file-
21
21
  the **same behavior** is specified in **two** files, a change to that behavior must touch both, so
22
22
  what looked disjoint is a **hard collision the scenario rung cannot see** (it diffs changed scenarios
23
23
  per file, never across files). One behavior = **one scenario in one owning node** keeps the scenario
24
- rung honest. Cross-*project* dedup (`dedupe-specs`) was retired when one project became one spec;
25
- cross-*node* overlap **inside** a project had no detector until this one.
24
+ rung honest. This detector covers cross-*node* overlap **inside** a project.
26
25
 
27
26
  ## The two deterministic candidate kinds (and one judgment arm)
28
27
 
@@ -45,7 +45,7 @@ surfaced as an **architectural smell** to consider splitting (surfacing only —
45
45
 
46
46
  It **composes** the sibling [`touch-set-correction`](../touch-set-correction/README.md)'s
47
47
  `collectChangedFiles` (which itself composes `resolve-governances` for artifact-type and the pinned
48
- `gherkin-cli@0.0.2 diff` for changed scenarios — never a reimplemented differ) and adds one finer source,
48
+ `gherkin-cli diff` for changed scenarios — never a reimplemented differ) and adds one finer source,
49
49
  `git diff -U0` line-hunks (the region rung).
50
50
 
51
51
  Pure derivations (`classify`, `classifyFile`, `hunksDisjoint`, `isFeature`, `isCode`, `confidenceRank`,
@@ -92,7 +92,7 @@ field.
92
92
  ### `report` — per-subagent dispatch (combat log)
93
93
 
94
94
  ```jsonl
95
- {"seq": 3, "ts": "2026-06-28T18:30:11Z", "handle": "unional", "kind": "report", "role": "spec-producer", "agent": "sdd:automaton", "outcome": "pass", "summary": "wrote 14 scenarios covering the ledger expansion"}
95
+ {"seq": 3, "ts": "2026-06-28T18:30:11Z", "handle": "unional", "kind": "report", "role": "spec-producer", "agent": "sdd:sdd-automaton", "outcome": "pass", "summary": "wrote 14 scenarios covering the ledger expansion"}
96
96
  ```
97
97
 
98
98
  `role` is the production role dispatched; `agent` is the plugin-qualified agent name; `outcome` is
@@ -91,10 +91,7 @@ shares one boundary.
91
91
  axis is wrong), not a granularity split to carve as-proposed.
92
92
 
93
93
  An oversize can be a symptom of the **wrong axis**, not just wrong granularity: turn "this node is too
94
- big" into "too big **along which axis** — and is that axis real?" (Precedent: a killed
95
- `identity/`→`presence/` split proposed a plausible-but-unreal axis and was superseded by a realignment
96
- that split along the package's actual command boundary; the producer/consumer boundary had even been
97
- validated as sound, yet the *split axis* was never checked against a real command boundary.)
94
+ big" into "too big **along which axis** — and is that axis real?"
98
95
 
99
96
  Alongside its findings a pass surfaces an **advisory layout-quality signal** — the scheduler's
100
97
  **false-conflict rate** doubles as a **partition-quality metric**: a layout that keeps node↔folder
@@ -20,15 +20,15 @@ means the conductor **spawns** it.
20
20
 
21
21
  | Role key | Acts | SDD default |
22
22
  |---|---|---|
23
- | `spec-producer` | writes the `spec.md` body + the `.feature` | conductor loads `spec-producer-governance`, authors inline (`sdd:automaton`) |
24
- | `solution-producer` | writes `<unit>.solution.md` (the durable, ungated design fork) | conductor loads `solution-producer-governance`, authors inline (`sdd:automaton`) |
23
+ | `spec-producer` | writes the `spec.md` body + the `.feature` | conductor loads `spec-producer-governance`, authors inline (`sdd:sdd-automaton`) |
24
+ | `solution-producer` | writes `<unit>.solution.md` (the durable, ungated design fork) | conductor loads `solution-producer-governance`, authors inline (`sdd:sdd-automaton`) |
25
25
  | `spec-judge` | judges `spec.md` + the `.feature` at the spec gate | `sdd-spec-judge` — spawned cold agent |
26
- | `impl-producer` | builds the artifact **and** its verification | conductor loads `impl-producer-governance`, dispatches a generic builder (`sdd:automaton`) |
26
+ | `impl-producer` | builds the artifact **and** its verification | conductor loads `impl-producer-governance`, dispatches a generic builder (`sdd:sdd-automaton`) |
27
27
  | `impl-judge` | runs the verification against the frozen `.feature` | `sdd-impl-judge` — spawned cold agent |
28
28
 
29
29
  **Producers run inline (or via a mechanical builder), judges spawn cold** ("conductor writes, cold
30
30
  judges grade"): an SDD-default spec/solution-producer is a governance the conductor loads and runs in
31
- its own warm main-session context (recorded `produced-by.<role>: sdd:automaton`); the SDD-default
31
+ its own warm main-session context (recorded `produced-by.<role>: sdd:sdd-automaton`); the SDD-default
32
32
  impl-producer is mechanical and spawned via a generic builder; an SDD-default judge is a cold agent
33
33
  the conductor spawns, because a grader must not share the author's context. A plugin delegate — or a
34
34
  model-tuned producer agent named for the slot — is always spawned.
@@ -37,10 +37,6 @@ Any of the spawns above may instead be realized through a general-purpose dispat
37
37
  `subagent | channel` seam (ADR-0023, referenced by intent only) — an alternative realization of the
38
38
  same spawn, not a change to which roles spawn or how they are graded.
39
39
 
40
- > The legacy role key was `plan-producer` (writing `plan.md` + `tasks.md`); it is renamed
41
- > **`solution-producer`** writing `<unit>.solution.md` (`sdd:combat-log-governance`). A live registry
42
- > still carrying `plan-producer` is migrated on encounter.
43
-
44
40
  ## Which governances each role loads
45
41
 
46
42
  Bars are the Model-B `(actor, gate)` governances (matched by the `resolve-governances` skill; the
@@ -49,10 +45,7 @@ self-aligns to exactly the bars its judge grades. The lens sets are spec gate `{
49
45
  architect}`, impl gate `{builder, architect}`, solution `{architect}` (ungated).
50
46
 
51
47
  **Read each row against that sentence.** A producer row that does not carry its whole lens set is a
52
- transcription slip, not a narrowing — this table is a shipped copy of one owned by SDD's own spec
53
- (`design/specialists-and-squads.md`), restated here because a governance loads standalone and cannot
54
- reach the spec tree. It has drifted once: the spec-producer row lost `architect-spec`, and plugin
55
- authors building to it shipped agents that loaded three bars and were graded against four.
48
+ transcription slip, not a narrowing.
56
49
 
57
50
  | Role | Loads |
58
51
  |---|---|
@@ -49,7 +49,7 @@ export const ROLE_LOADOUT: Record<RoleKey, { bars: BarKey[] }> = {
49
49
 
50
50
  // The SDD-default agent per role. A null ref means the conductor runs the role
51
51
  // INLINE in the main session (spec/solution-producer) or via a generic spawned
52
- // builder (impl-producer); both are recorded produced-by sdd:automaton. The two
52
+ // builder (impl-producer); both are recorded produced-by sdd:sdd-automaton. The two
53
53
  // judges are spawned cold by name.
54
54
  export const SDD_DEFAULT_AGENT: Record<RoleKey, string | null> = {
55
55
  'spec-producer': null,
@@ -2,7 +2,7 @@
2
2
 
3
3
  Non-user-invocable SDD skill holding the **default solution-producer procedure**: how to record a unit's `<unit>.solution.md` (the chosen approach + rejected alternatives) for a domain no plugin covers — **only** when the unit carries durable design rationale.
4
4
 
5
- Loaded via the harness (`Skill`) by the **conductor** (the main session) when it runs the solution-producer role from the SDD default — the conductor authors **inline** in its own warm context (recorded `produced-by.solution-producer: sdd:automaton`) rather than spawning a producer agent. Relocates the *functional-spec* half of the former `plan-producer` role to a per-unit, optional, ungated facet; the task-DAG half is now the conductor's transient execution `.plan.md` `todos`, not this role's output.
5
+ Loaded via the harness (`Skill`) by the **conductor** (the main session) when it runs the solution-producer role from the SDD default — the conductor authors **inline** in its own warm context (recorded `produced-by.solution-producer: sdd:sdd-automaton`) rather than spawning a producer agent. Relocates the *functional-spec* half of the former `plan-producer` role to a per-unit, optional, ungated facet; the task-DAG half is now the conductor's transient execution `.plan.md` `todos`, not this role's output.
6
6
 
7
7
  The solution is the unit's **third facet** (spec / suite / solution). It is **optional** (most units have none), **boundary-aligned** (maps to the design decision, not one entry per scenario), and **ungated / unfrozen** — no judge grades it and the spec gate does not see it; the implementation's frozen-scenario result validates it transitively.
8
8
 
@@ -6,7 +6,7 @@ user-invocable: false
6
6
 
7
7
  # Solution-Producer Governance — the default solution-recording procedure
8
8
 
9
- The procedure the **conductor** follows when it runs the **solution-producer** role from the SDD default — no plugin covers the domain and no model-tuned producer agent is named for the slot, so the conductor **loads this governance and authors inline** in its own warm context (recorded `produced-by.solution-producer: sdd:automaton`). This is the relocation of the former `plan-producer` role's *functional-spec* half: the solution is the chosen approach + rejected alternatives, now recorded **per unit** as `<unit>.solution.md` rather than as a `plan.md`. The task DAG that `plan-producer` also wrote is **not** this role's output — it is the conductor's transient execution `.plan.md` `todos`.
9
+ The procedure the **conductor** follows when it runs the **solution-producer** role from the SDD default — no plugin covers the domain and no model-tuned producer agent is named for the slot, so the conductor **loads this governance and authors inline** in its own warm context (recorded `produced-by.solution-producer: sdd:sdd-automaton`). This is the relocation of the former `plan-producer` role's *functional-spec* half: the solution is the chosen approach + rejected alternatives, now recorded **per unit** as `<unit>.solution.md` rather than as a `plan.md`. The task DAG that `plan-producer` also wrote is **not** this role's output — it is the conductor's transient execution `.plan.md` `todos`.
10
10
 
11
11
  The solution is the unit's **third facet** (spec = *what*, suite = *proof*, solution = *why this shape*). It is **optional** and **ungated**: it gets no judge of its own, stays out of the spec-judge's view, and is never frozen. The implementation's frozen-scenario result validates it transitively.
12
12
 
@@ -158,7 +158,7 @@ change is purely additive with no judge round; a **narrowing/rewriting** edit (a
158
158
  scenario) unfreezes its file and fires **Clearance** once the narrowing is confirmed semantically.
159
159
  The edit-class classification itself — additive / no-content-change / narrowing / mixed — comes from
160
160
  `scripts/classify-edit-class.mts` (`--files <paths> [--base <ref>]`): a **structural** per-named-`Scenario`
161
- diff via the pinned `gherkin-cli@0.0.2 diff`, plus git rename detection for a pure `git mv`, **never a raw
161
+ diff via the pinned `gherkin-cli@0.2.1 diff`, plus git rename detection for a pure `git mv`, **never a raw
162
162
  line diff** (a step orphaned off a frozen scenario onto a new adjacent scenario shows no `-` line and
163
163
  would read as additive to a line-diff; the structural diff correctly reports the losing scenario as
164
164
  `modified`). It only classifies — additive / no-content-change self-clear, narrowing / mixed take the
@@ -2,6 +2,6 @@
2
2
 
3
3
  Non-user-invocable SDD skill holding the **default spec-producer procedure**: how to author the `spec.md` body and a boolean Gherkin `.feature` for a domain no plugin covers.
4
4
 
5
- Loaded via the harness (`Skill`) by the **conductor** (the main session) when it runs the spec-producer role from the SDD default — the conductor authors **inline** in its own warm context (recorded `produced-by.spec-producer: sdd:automaton`) rather than spawning a producer agent. The grader stays separate: a cold `sdd-spec-judge` reviews the output.
5
+ Loaded via the harness (`Skill`) by the **conductor** (the main session) when it runs the spec-producer role from the SDD default — the conductor authors **inline** in its own warm context (recorded `produced-by.spec-producer: sdd:sdd-automaton`) rather than spawning a producer agent. The grader stays separate: a cold `sdd-spec-judge` reviews the output.
6
6
 
7
7
  References `sdd:spec-format-governance` (the universal format bar — including the required `## Use Cases` section, its actor-first enumeration, and the rule that scenarios derive from the CFG rather than from the stated use-case prose) plus the resolved oracle + builder + architect actor bars (the spec-gate lens set, forward face) as its self-alignment criteria, and `sdd:ownership-governance` for the write-ownership matrix. Bakes in the grilling discipline (breadth-first, depth one-at-a-time, prose before suite) and the reconcile-toward-the-correct-answer rule for contradictions surfaced during grilling.
@@ -6,7 +6,7 @@ user-invocable: false
6
6
 
7
7
  # Spec-Producer Governance — the default authoring procedure
8
8
 
9
- The procedure the **conductor** follows when it runs the **spec-producer** role from the SDD default — i.e. no plugin covers the domain and no model-tuned producer agent is named for the slot, so the conductor **loads this governance and authors inline** in its own warm context (recorded `produced-by.spec-producer: sdd:automaton`). The grader is separate — a **cold spec-judge** (`sdd:sdd-spec-judge` or the plugin's judge) always reviews the output; this governance never judges its own work.
9
+ The procedure the **conductor** follows when it runs the **spec-producer** role from the SDD default — i.e. no plugin covers the domain and no model-tuned producer agent is named for the slot, so the conductor **loads this governance and authors inline** in its own warm context (recorded `produced-by.spec-producer: sdd:sdd-automaton`). The grader is separate — a **cold spec-judge** (`sdd:sdd-spec-judge` or the plugin's judge) always reviews the output; this governance never judges its own work.
10
10
 
11
11
  Load alongside this governance: `sdd:spec-format-governance` (the required `## Use Cases` section and the `spec.md` enrichment / human-readability rule), `sdd:suite-format-governance` (the `.feature` format bar and scenario-ordering convention), and the resolved **oracle**, **builder**, and **architect** actor bars — **forward** face — to self-align before writing (scope and kill-or-ship, testability/coverage, structural fit). These are exactly the bars the spec-judge grades **backward** at the spec gate, so the producer self-aligns to the same lens set it will be graded against. Load `sdd:ownership-governance` for the write-ownership matrix — which fields the spec-producer may write and which belong to the conductor or the gate skill.
12
12
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  The single user-facing entry for **changing an SDD project** — triggered by a general change request ("add a start-mission skill to sdd", "implement the auth capability", "work on `<github issue url>`"). User-invocable: opens a **change request** against the one durable project spec and runs the **mission loop** (intake → explore → deliver → handoff) over it.
4
4
 
5
- The session that runs this skill **is the conductor** — the in-session realization of the conductor role; the headless realization is the `automaton` agent. A third realization is **in-session plan-mode preview**: when Claude Code plan mode is active, explore runs its reasoning (classify, seed-intent grill, draft the spec + scenario list, cold spec-judge) but writes no repo files — it renders the drafted spec + suite into the plan file and ends at **ExitPlanMode**, dropping the build-to-learn spikes. On approval the next real explore adopts the preview as the settled draft. Plan mode is detected **in-body**, never via the trigger `description`, so it never re-fires per turn. It supersedes the retired spec-as-mission entries (`create-spec` / `revise-spec`): adding, revising, or deduping part of the project spec is now an **explore-phase operation inside a CR**, not a top-level mission.
5
+ The session that runs this skill **is the conductor** — the in-session realization of the conductor role; the headless realization is the `sdd-automaton` agent. A third realization is **in-session plan-mode preview**: when Claude Code plan mode is active, explore runs its reasoning (classify, seed-intent grill, draft the spec + scenario list, cold spec-judge) but writes no repo files — it renders the drafted spec + suite into the plan file and ends at **ExitPlanMode**, dropping the build-to-learn spikes. On approval the next real explore adopts the preview as the settled draft. Plan mode is detected **in-body**, never via the trigger `description`, so it never re-fires per turn. It supersedes the retired spec-as-mission entries (`create-spec` / `revise-spec`): adding, revising, or deduping part of the project spec is now an **explore-phase operation inside a CR**, not a top-level mission.
6
6
 
7
7
  Bakes in: step-1 intake (recover the request or fetch an issue URL; scaffold the `.plan.md`); explore as the live grill (classify spec-type + artifact-types, scaffold the node, actor-first seed-intent Q&A, the inline spec-producer + cold spec-judge loop with build-to-learn spikes, the iteration cap, the **freeze re-open guard**, observation routing); the internal spec gate (freeze + per-CR gate line to the conductor's own `ledger/` shard + `status: approved`); deliver (spawned impl-producer builder + the internal impl gate); handoff; and the baked autonomy bar (initial strategy, per-gate verdicts, the three hard floors). Pairs with `pause-mission` / `resume-mission`.
@@ -77,11 +77,11 @@ Run authoring **in-session** as the conductor. Explore **builds the implementati
77
77
  For each unit the CR touches:
78
78
 
79
79
  - **Locate or place the node — provisionally.** If a `spec.md` / `README.md` already exists at the target → this is a **revise** (no scaffolding). Otherwise **scaffold** a new node and drop it in a *plausible* home **under the layout the project declared** in its root `spec.md` placement map — `capability-first` groups by what the project *does*, `mirror-source` mirrors the source tree. Placement is judged *within* that declaration, never against a preferred one (`sdd:spec-structure-governance`, "strategy is policy, homes are data"); where no strategy is declared, the `capability-first` default applies. A layered / framework-first **top level** stays discouraged under every strategy (it scatters a capability across folders, breaking node↔folder and degrading scheduling). Consult `project-spec/place-node` (`--concept` → candidate homes; `--name` → "belongs near X" duplicate-catch) and the placement-map routing table (root `spec.md`) for contested overlaps, but **do not agonize**: placement is **provisional** and finalized cheaply at **handoff** (step 4), where a scoped Warden pass relocates it to its blessed home *in the same change* (a pure rename — freeze survives, `sdd:lifecycle-governance`). If the user named no capability, propose a capability folder from the CR and confirm.
80
- - **Classify the node** (declared, never inferred): `spec-type: behavioral` (a testable unit → `## Use Cases` + a `<unit>.feature`), `reference` (a shipped non-testable artifact → `## Subject`, no `.feature`), or **descriptive** (an index → no marker). Tag the node's cross-cutting **`concept:`** (the concern it serves — e.g. `lifecycle` / `resolution`; a string or list, orthogonal to `spec-type`; it feeds `project-spec/concept-index`). Also classify each touched file's **artifact-type** (the squad key — resolved per file, **not stored**): **by convention first** (`skill` under `skills/`, `subagent` under `agents/`, …; the extension never decides). On a genuine **ambiguity or a user-flagged path**, consult and record the tiebreaker map `.agents/sdd/artifact-types.toml` and **confirm — never guess** (`sdd:artifact-type` model).
80
+ - **Classify the node** (declared, never inferred): `spec-type: behavioral` (a testable unit → `## Use Cases` + a `<unit>.feature`), `reference` (a shipped non-testable artifact → `## Subject`, no `.feature`), or **descriptive** (an index → no marker). Tag the node's cross-cutting **`concept:`** (the concern it serves — e.g. `lifecycle` / `resolution`; a string or list, orthogonal to `spec-type`; it feeds `project-spec/concept-index`). Also classify each touched file's **artifact-type** (the squad key — resolved per file, **not stored**): **by convention first** (`skill` under `skills/`, `subagent` under `agents/`, …; the extension never decides). On a genuine **ambiguity or a user-flagged path**, consult and record the tiebreaker map `.agents/sdd/artifact-types.toml` and **confirm — never guess**.
81
81
  - **Scaffold the skeleton** per `sdd:spec-format-governance` (sections per type; `.feature` form per `sdd:suite-format-governance`). Write **no** control frontmatter (`status` / `project-path` / `approval` / `produced-by`) — those live on the root `spec.md` and belong to the conductor and the gate.
82
82
  - **Collect seed intent.** For a **new** feature, ask 3–5 targeted questions — **lead with the actors** (who reaches this capability, and who is affected by its outcome without invoking it), then their goals, then the core problem, observable behavior, edge cases / non-goals, and reviewers who must be heard. Ask for the **public interface last, and never first**: an interface offered up front becomes the anchor the use cases get read off, which is the enumeration failure `sdd:spec-format-governance` exists to prevent. For **backfill** (behavior already in code), skip — the producer reads source, tests, history. For a **revise**, collect what changes and why and the parts it touches.
83
83
 
84
- **The grill loop (the user loop).** You are the conductor. Run the spec-producer **inline** (load `sdd:spec-producer-governance`, or persona-load a plugin specialist for the `artifact-types`), **dispatch the cold spec-judge** each round — through the dispatch capability's intent seam when one is available (preferring its **warm** unit, context-cleared fresh via `npx cyberlegion@0.3.1 unit clear <ref>` before each round's judgment), else a portable cold subagent — and for build-to-learn **dispatch the impl-producer builder** the same way (its warm unit **keeps** its context across spikes; no reset) in `explore` mode against the **non-frozen** suite — spikes are thrown away; their learnings feed the live grill to steer the spec + suite. Set an **iteration cap** (default **3**; honor a user-named cap), then loop:
84
+ **The grill loop (the user loop).** You are the conductor. Run the spec-producer **inline** (load `sdd:spec-producer-governance`, or persona-load a plugin specialist for the `artifact-types`), **dispatch the cold spec-judge** each round — through the dispatch capability's intent seam when one is available (preferring its **warm** unit, context-cleared fresh via `npx cyberlegion@<version> unit clear <ref>` before each round's judgment), else a portable cold subagent — and for build-to-learn **dispatch the impl-producer builder** the same way (its warm unit **keeps** its context across spikes; no reset) in `explore` mode against the **non-frozen** suite — spikes are thrown away; their learnings feed the live grill to steer the spec + suite. Set an **iteration cap** (default **3**; honor a user-named cap), then loop:
85
85
 
86
86
  **Governance provenance relay.** When you dispatch the cold spec-judge, forward the inline spec-producer's declared `governances_loaded` (`sdd:spec-producer-governance`) verbatim through the same dispatch channel, keyed **`producer_governances_declared`** — a brief field when the judge is a cold subagent, a mail envelope field when it runs through an agent pool. Forward it **as-is, including an empty set** — you render **no opinion** on which governances were actually required; that check is the spec-judge's own pre-flight (`sdd:sdd-spec-judge`).
87
87
 
@@ -119,7 +119,7 @@ Build-to-keep against the **frozen** suite. The deliver **read-set is scoped** (
119
119
 
120
120
  **Rebase onto the target — the last deliver act, before the gate.** Before running the impl gate, **rebase the CR branch onto the current tip of the declared target** (for a commit-to-main project, the equivalent `pull --rebase` onto the latest `main`), so the impl gate judges the **merged tree that will actually land** — keeping history linear and leaving handoff a pure consumer that never re-verifies. A **textual conflict** is resolved as **deliver code work** against the frozen `.feature` (never a `.feature` edit); the gate then runs on the resolved tree. A conflict you **cannot resolve confidently is never guess-resolved** — the frozen suite covers *this CR's* behavior, not the incoming change's, so a wrong resolution could still pass the gate and land broken; **stop and escalate** (in-session ask the user; headless return `needs-input` up the relay) and record a `halt`, never land a low-confidence resolution. Rebasing an *unmerged* CR branch is git-reversible (reflog), so it raises **no new hard floor** — but a conflict resolution that would **narrow** a frozen scenario still fires the existing **Clearance** floor, a semver class over the ceiling **Compatibility**, and a genuine contradiction **Conflict** (autonomy bar, below). The rebase-then-gate is **optimistic**: if the target **advances again** between the passing gate and the push (another CR merged in the window), **re-rebase onto the new tip and re-run the impl gate — do not push until the gate passes on the re-rebased tree**, looping until the push wins, so what lands is always a tree the gate saw green. **The loop is bounded, not forced** — if the target keeps advancing past a small cap of attempts, **stop and escalate** (record a `halt`) rather than spinning forever (a liveness stop, same as the unconfident-conflict halt).
121
121
 
122
- **The impl gate (Approved → Implemented, internal).** On entering the gate, overwrite the statusline file with `impl gate`. Dispatch the **cold impl-judge** (`sdd:sdd-impl-judge` or the covering plugin's judge) — same seam-when-available wiring, preferring its warm unit context-cleared fresh via `npx cyberlegion@0.3.1 unit clear <ref>` for this judgment, else a portable cold subagent — to run the verification per frozen scenario plus an orthogonal structural/scope read. Advance to **`status: implemented`** **only when every impl-judge passes** (a frozen scenario with no verification blocks the advance — impl-sync is this suite run, not a stored flag). The three actions: **approve** → `implemented`; **change** → fix the **code** (never the frozen `.feature`), under the same evidence-not-a-work-order remediation the spec gate uses (`sdd:remediation-governance`) — including the **provenance** account that stops a regressing loop; **reject** → redo, or a **Oracle-lens revert** (a frozen scenario proved fatal → unfreeze the `.feature`, return to `draft` — the only place a frozen `.feature` reopens).
122
+ **The impl gate (Approved → Implemented, internal).** On entering the gate, overwrite the statusline file with `impl gate`. Dispatch the **cold impl-judge** (`sdd:sdd-impl-judge` or the covering plugin's judge) — same seam-when-available wiring, preferring its warm unit context-cleared fresh via `npx cyberlegion@<version> unit clear <ref>` for this judgment, else a portable cold subagent — to run the verification per frozen scenario plus an orthogonal structural/scope read. Advance to **`status: implemented`** **only when every impl-judge passes** (a frozen scenario with no verification blocks the advance — impl-sync is this suite run, not a stored flag). The three actions: **approve** → `implemented`; **change** → fix the **code** (never the frozen `.feature`), under the same evidence-not-a-work-order remediation the spec gate uses (`sdd:remediation-governance`) — including the **provenance** account that stops a regressing loop; **reject** → redo, or a **Oracle-lens revert** (a frozen scenario proved fatal → unfreeze the `.feature`, return to `draft` — the only place a frozen `.feature` reopens).
123
123
 
124
124
  ## Step 4 — handoff
125
125
 
@@ -137,13 +137,13 @@ Before you close out, run the **correction-line finalize backstop** (autonomy ba
137
137
 
138
138
  Also run the **plan-brief finalize backstop** (autonomy bar, below): reconcile the plan brief's `todos` and its `## NEXT` anchor to the landed state, **in this same change** — so the delivery never ships a landed mission described as in-progress.
139
139
 
140
- Before closing out, **reset the mission's warm units**: `npx cyberlegion@0.3.1 unit clear <ref>` (context-clear, pane stays warm) or tear down every warm unit this mission dispatched — none carries this mission's context into the next.
140
+ Before closing out, **reset the mission's warm units**: `npx cyberlegion@<version> unit clear <ref>` (context-clear, pane stays warm) or tear down every warm unit this mission dispatched — none carries this mission's context into the next.
141
141
 
142
142
  Once landed, **do not spawn** the formation Warden. Surface a **one-line nudge** that a corpus-wide formation pass is due, pointing to `sdd:manage` ("audit the corpus structure" → `formation-loop`). The pass is **on-demand** — run deliberately, not auto-spawned on every landing; `sdd:manage` owns the trigger. Gate nothing on it.
143
143
 
144
144
  ## Autonomy, provenance, and the hard floor (baked in)
145
145
 
146
- - **Dispatch transport.** Every spawn beyond this session states a **dispatch intent** — role, brief, expected verdict schema — never a pinned command. When a harness-agnostic dispatch capability is available (detected at runtime; the concrete case is the Legate's `dispatch-governance` composing `cyberlegion` primitives — `agent resolve` + `unit spawn` + `mail await` — with **no** `dispatch` CLI verb, the seam named in the SDD project spec's `design/harness-spawning` node, repo-only), route through its intent seam and let it pick `subagent | channel | run-inline`, **preferring a warm unit** over a cold one-shot spawn; with no capability present, fall back to the portable cold subagent (depth-1) default — grader independence intact either way. **Warmth is a property of the unit/process; coldness of the context**: a judge's fresh-context guarantee (ADR-0016) is transport-agnostic — satisfied by a newly spawned cold subagent **or** a warm unit **context-cleared** to a fresh context before **each** judgment (re-deriving its oracle, carrying none of a prior round's context). Clear a warm unit with **`npx cyberlegion@0.3.1 unit clear <ref>`** (`<ref>` = unit id / handle / worktree branch or CR ref) — it injects the harness's own fresh-context command (`/clear` on Claude/Codex/Copilot, `/new-chat` on Cursor; fail-loud on a harness with no honest reset) so the **pane stays warm** while the **context goes cold**; it tears nothing down. The **impl-producer builder** instead stays warm and **keeps** its context across the explore spikes and the deliver build (never cleared between those uses). Warm units stay warm for **one mission** — reused within it, then **`unit clear`**'d or torn down at **handoff**, never carrying this mission's context into the next.
146
+ - **Dispatch transport.** Every spawn beyond this session states a **dispatch intent** — role, brief, expected verdict schema — never a pinned command. When a harness-agnostic dispatch capability is available (detected at runtime; the concrete case is the Legate's `dispatch-governance` composing `cyberlegion` primitives — `agent resolve` + `unit spawn` + `mail await` — with **no** `dispatch` CLI verb, the seam named in the SDD project spec's `design/harness-spawning` node, repo-only), route through its intent seam and let it pick `subagent | channel | run-inline`, **preferring a warm unit** over a cold one-shot spawn; with no capability present, fall back to the portable cold subagent (depth-1) default — grader independence intact either way. **Warmth is a property of the unit/process; coldness of the context**: a judge's fresh-context guarantee (ADR-0016) is transport-agnostic — satisfied by a newly spawned cold subagent **or** a warm unit **context-cleared** to a fresh context before **each** judgment (re-deriving its oracle, carrying none of a prior round's context). Clear a warm unit with **`npx cyberlegion@<version> unit clear <ref>`** (`<ref>` = unit id / handle / worktree branch or CR ref) — it injects the harness's own fresh-context command (`/clear` on Claude/Codex/Copilot, `/new-chat` on Cursor; fail-loud on a harness with no honest reset) so the **pane stays warm** while the **context goes cold**; it tears nothing down. The **impl-producer builder** instead stays warm and **keeps** its context across the explore spikes and the deliver build (never cleared between those uses). Warm units stay warm for **one mission** — reused within it, then **`unit clear`**'d or torn down at **handoff**, never carrying this mission's context into the next.
147
147
  - **SDD's own judges go to the seam by file, not by name.** A dispatch capability may resolve a definition by name only in the project's own agent folder (cyberlegion's `agent resolve` does), so it cannot find one SDD ships. When the judge role resolves to SDD's own `sdd-spec-judge` or `sdd-impl-judge`, locate the definition yourself at **`agents/<name>.md` under the SDD plugin root** — two levels above this skill's own base directory (`<skill dir>/../../agents/<name>.md`) — and hand the capability **that path** (cyberlegion: `agent resolve --file <path>`, `unit spawn --agent-file <path>`), never the bare name. If no file is there, send the capability **no request for that judge** (a by-name one would miss) and take the no-capability route: spawn it as a portable cold subagent through the harness's own plugin-agent spawn (`sdd:sdd-spec-judge` / `sdd:sdd-impl-judge`), which knows the plugin. A plugin-delegated judge is outside this rule.
148
148
  - **Initial strategy** (run start): assess blast radius + the other dimensions and emit a run-level `kind: leash` block to **your own ledger shard** (`ledger/<cr-ref>.<hash>.jsonl` — mint `<hash>` as 6 random hex **once per session** and reuse it for every line you append; `sdd:combat-log-governance`) — `leash` (`auto-none | auto-spec | auto-all`), `by: derived | user`, `approach[]`. It may be user-specified. This block is `kind: leash`, **not** `strategy` — `strategy` is the doctrine Scanner's alone. Ledger lines carry **no `ts`**.
149
149
  - **Per-gate verdict.** At each gate, derive the leash against discovered state and either **self-assert within leash** (write `approval.<gate>: { verdict: approve, by: agent, why }`; the spec lands in the async review queue) or **stop** with a verdict packet for the human. **Never advance** when any judge fails, any open marker remains, or (at the impl gate) any frozen scenario's verification does not pass. Human ratification (`by: <name>`, advance `status`) is reserved to the in-session position holding the user channel — by default you, in-session; a headless `automaton` emits the verdict packet and stops, **even when a coordinator relays "the user approved."**
@@ -207,7 +207,7 @@ handle: the natural in-scenario shape is `narrowing`, so a producer checking whe
207
207
  is present in both shapes, never on the class the diff happens to report.
208
208
 
209
209
  **The freeze sees the rubric only because the differ's pin says it does.** A `@rubric` lives wholly
210
- inside a DocString. The structural differ is pinned at `gherkin-cli@0.0.2`, which hashes what a step
210
+ inside a DocString. The structural differ is pinned (see `spec-gate`), which hashes what a step
211
211
  argument **says**; before that pin its scenario identity covered step text alone, and a rubric could
212
212
  be gutted while its scenario still reported `unchanged`. **The pin is load-bearing here** — moved
213
213
  backwards, every correction in this queue self-clears silently and Clearance never fires.
@@ -23,7 +23,7 @@ and lines them up against the guess:
23
23
 
24
24
  It **composes three tools**, never reimplementing any of them: `git diff --name-status` (the
25
25
  changed files), [`resolve-governances`](../resolve-governances/SKILL.md) (each file's artifact-type,
26
- best-effort — `unknown` when it doesn't resolve), and the pinned `gherkin-cli@0.0.2 diff` (a touched
26
+ best-effort — `unknown` when it doesn't resolve), and the pinned `gherkin-cli diff` (a touched
27
27
  `.feature`'s changed scenario names — the same tool `classify-edit-class` uses).
28
28
 
29
29
  Work-area recovery is **capability-first**: a changed file under a declared project root maps to
@@ -110,7 +110,7 @@ node "<skill>/scripts/verify-scenarios.mts" \
110
110
  ## Boundaries
111
111
 
112
112
  Read-only over the `.feature` and test reports; writes nothing. Consumes `gherkin-cli` (via `npx
113
- gherkin-cli@0.0.2 parse <feature> --format json`) for the scenario set — never re-implements a
113
+ gherkin-cli parse <feature> --format json`) for the scenario set — never re-implements a
114
114
  Gherkin parser. Does not reorganize `.feature` files by runner and does not wire itself into the
115
115
  impl-judge (a separate CR grows the default `sdd-impl-judge` to call this for deterministic
116
116
  artifact-types, run through SDD's own spec gate).