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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.plugin/plugin.json +1 -1
- package/agents/sdd-automaton.md +2 -3
- package/agents/sdd-impl-judge.md +5 -4
- package/agents/sdd-scanner.md +1 -1
- package/package.json +1 -1
- package/skills/check-scenario-overlap/SKILL.md +1 -2
- package/skills/collision-ladder/SKILL.md +1 -1
- package/skills/combat-log-governance/SKILL.md +1 -1
- package/skills/formation-loop/SKILL.md +1 -4
- package/skills/plugin-contract-governance/SKILL.md +5 -12
- package/skills/resolve-governances/scripts/resolve-governances.mts +1 -1
- package/skills/solution-producer-governance/README.md +1 -1
- package/skills/solution-producer-governance/SKILL.md +1 -1
- package/skills/spec-gate/SKILL.md +1 -1
- package/skills/spec-producer-governance/README.md +1 -1
- package/skills/spec-producer-governance/SKILL.md +1 -1
- package/skills/start-mission/README.md +1 -1
- package/skills/start-mission/SKILL.md +5 -5
- package/skills/suite-format-governance/references/rubric.md +1 -1
- package/skills/touch-set-correction/SKILL.md +1 -1
- package/skills/verify-scenarios/SKILL.md +1 -1
package/.plugin/plugin.json
CHANGED
package/agents/sdd-automaton.md
CHANGED
|
@@ -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 (
|
|
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
|
|
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.
|
package/agents/sdd-impl-judge.md
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
package/agents/sdd-scanner.md
CHANGED
|
@@ -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 (
|
|
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
|
@@ -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.
|
|
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
|
|
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?"
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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).
|