cyber-sdd 0.0.0
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 +17 -0
- package/.codex-plugin/plugin.json +17 -0
- package/.plugin/plugin.json +17 -0
- package/README.md +159 -0
- package/agents/sdd-automaton.md +97 -0
- package/agents/sdd-impl-judge.md +214 -0
- package/agents/sdd-scanner.md +120 -0
- package/agents/sdd-spec-judge.md +224 -0
- package/agents/sdd-warden.md +101 -0
- package/package.json +24 -0
- package/skills/align-spec/README.md +20 -0
- package/skills/align-spec/SKILL.md +111 -0
- package/skills/align-spec/scripts/align-spec.mts +187 -0
- package/skills/architect-impl-governance/README.md +46 -0
- package/skills/architect-impl-governance/SKILL.md +45 -0
- package/skills/architect-spec-governance/README.md +48 -0
- package/skills/architect-spec-governance/SKILL.md +59 -0
- package/skills/blast-estimate/README.md +47 -0
- package/skills/blast-estimate/SKILL.md +133 -0
- package/skills/blast-estimate/scripts/blast-estimate.mts +583 -0
- package/skills/builder-impl-governance/README.md +47 -0
- package/skills/builder-impl-governance/SKILL.md +47 -0
- package/skills/builder-spec-governance/README.md +49 -0
- package/skills/builder-spec-governance/SKILL.md +36 -0
- package/skills/check-partition-quality/README.md +22 -0
- package/skills/check-partition-quality/SKILL.md +51 -0
- package/skills/check-partition-quality/scripts/check-partition-quality.mts +336 -0
- package/skills/check-plan-safety/README.md +17 -0
- package/skills/check-plan-safety/SKILL.md +60 -0
- package/skills/check-plan-safety/scripts/check-plan-safety.mts +145 -0
- package/skills/check-project-specs/README.md +19 -0
- package/skills/check-project-specs/SKILL.md +69 -0
- package/skills/check-project-specs/scripts/check-project-specs.mts +217 -0
- package/skills/check-scenario-overlap/README.md +19 -0
- package/skills/check-scenario-overlap/SKILL.md +74 -0
- package/skills/check-scenario-overlap/scripts/check-scenario-overlap.mts +249 -0
- package/skills/check-spec-structure/README.md +17 -0
- package/skills/check-spec-structure/SKILL.md +66 -0
- package/skills/check-spec-structure/scripts/check-spec-structure.mts +346 -0
- package/skills/collision-ladder/README.md +18 -0
- package/skills/collision-ladder/SKILL.md +83 -0
- package/skills/collision-ladder/scripts/collision-ladder.mts +657 -0
- package/skills/combat-log-governance/README.md +13 -0
- package/skills/combat-log-governance/SKILL.md +257 -0
- package/skills/concept-index/README.md +13 -0
- package/skills/concept-index/SKILL.md +38 -0
- package/skills/concept-index/scripts/concept-index.mts +245 -0
- package/skills/discover-plans/README.md +16 -0
- package/skills/discover-plans/SKILL.md +74 -0
- package/skills/discover-plans/scripts/discover-plans.mts +212 -0
- package/skills/discover-specs/README.md +15 -0
- package/skills/discover-specs/SKILL.md +76 -0
- package/skills/discover-specs/scripts/discover-specs.mts +396 -0
- package/skills/doctrine-loop/README.md +15 -0
- package/skills/doctrine-loop/SKILL.md +97 -0
- package/skills/formation-loop/README.md +17 -0
- package/skills/formation-loop/SKILL.md +140 -0
- package/skills/gate-validation-governance/README.md +12 -0
- package/skills/gate-validation-governance/SKILL.md +87 -0
- package/skills/impl-producer-governance/README.md +48 -0
- package/skills/impl-producer-governance/SKILL.md +85 -0
- package/skills/init/README.md +27 -0
- package/skills/init/SKILL.md +68 -0
- package/skills/init/scripts/wire-statusline.mts +276 -0
- package/skills/lifecycle-governance/README.md +11 -0
- package/skills/lifecycle-governance/SKILL.md +168 -0
- package/skills/manage/README.md +9 -0
- package/skills/manage/SKILL.md +62 -0
- package/skills/manage-ignore/README.md +19 -0
- package/skills/manage-ignore/SKILL.md +52 -0
- package/skills/manage-ignore/scripts/manage-ignore.mts +294 -0
- package/skills/manage-scenario-bridge/README.md +20 -0
- package/skills/manage-scenario-bridge/SKILL.md +60 -0
- package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.mts +156 -0
- package/skills/manage-spec-anchors/README.md +18 -0
- package/skills/manage-spec-anchors/SKILL.md +56 -0
- package/skills/manage-spec-anchors/scripts/manage-spec-anchors.mts +328 -0
- package/skills/mission-graph/README.md +15 -0
- package/skills/mission-graph/SKILL.md +67 -0
- package/skills/mission-graph/scripts/mission-graph.mts +844 -0
- package/skills/oracle-spec-governance/README.md +45 -0
- package/skills/oracle-spec-governance/SKILL.md +45 -0
- package/skills/ownership-governance/README.md +65 -0
- package/skills/ownership-governance/SKILL.md +104 -0
- package/skills/pause-mission/README.md +18 -0
- package/skills/pause-mission/SKILL.md +112 -0
- package/skills/place-node/README.md +12 -0
- package/skills/place-node/SKILL.md +47 -0
- package/skills/place-node/scripts/place-node.mts +157 -0
- package/skills/plan-retirement/README.md +32 -0
- package/skills/plan-retirement/SKILL.md +90 -0
- package/skills/plan-retirement/scripts/retire-plans.mts +196 -0
- package/skills/plugin-contract-governance/README.md +12 -0
- package/skills/plugin-contract-governance/SKILL.md +112 -0
- package/skills/remediation-governance/README.md +46 -0
- package/skills/remediation-governance/SKILL.md +78 -0
- package/skills/resolve-governances/README.md +18 -0
- package/skills/resolve-governances/SKILL.md +50 -0
- package/skills/resolve-governances/scripts/resolve-governances.mts +515 -0
- package/skills/resolve-tracking/SKILL.md +64 -0
- package/skills/resolve-tracking/scripts/resolve-tracking.mts +213 -0
- package/skills/resume-mission/README.md +12 -0
- package/skills/resume-mission/SKILL.md +53 -0
- package/skills/scaffold-project-spec/README.md +7 -0
- package/skills/scaffold-project-spec/SKILL.md +192 -0
- package/skills/sdd/README.md +7 -0
- package/skills/sdd/SKILL.md +92 -0
- package/skills/solution-producer-governance/README.md +9 -0
- package/skills/solution-producer-governance/SKILL.md +44 -0
- package/skills/spec-format-governance/README.md +73 -0
- package/skills/spec-format-governance/SKILL.md +114 -0
- package/skills/spec-gate/README.md +26 -0
- package/skills/spec-gate/SKILL.md +201 -0
- package/skills/spec-gate/scripts/check-spec-state.mts +601 -0
- package/skills/spec-gate/scripts/check-suite.mts +501 -0
- package/skills/spec-gate/scripts/classify-edit-class.mts +411 -0
- package/skills/spec-producer-governance/README.md +7 -0
- package/skills/spec-producer-governance/SKILL.md +86 -0
- package/skills/spec-structure-governance/README.md +40 -0
- package/skills/spec-structure-governance/SKILL.md +169 -0
- package/skills/ssa-lowering/README.md +26 -0
- package/skills/ssa-lowering/SKILL.md +181 -0
- package/skills/start-mission/README.md +7 -0
- package/skills/start-mission/SKILL.md +115 -0
- package/skills/suite-format-governance/README.md +75 -0
- package/skills/suite-format-governance/SKILL.md +299 -0
- package/skills/suite-format-governance/references/rubric.md +313 -0
- package/skills/touch-set-correction/README.md +16 -0
- package/skills/touch-set-correction/SKILL.md +67 -0
- package/skills/touch-set-correction/scripts/touch-set-correction.mts +418 -0
- package/skills/verify-scenarios/README.md +17 -0
- package/skills/verify-scenarios/SKILL.md +109 -0
- package/skills/verify-scenarios/scripts/verify-scenarios.mts +386 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sdd-spec-judge
|
|
3
|
+
description: "Internal SDD spec-judge (default). Grades a CR's spec.md + .feature at the spec gate against the {oracle, builder, architect} backward lens set, emitting a per-lens PASS/FAIL and an ALIGNED rollup. Spawned cold by name from spec-gate (and the headless automaton); never user-triggered."
|
|
4
|
+
model: sonnet
|
|
5
|
+
effort: high
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sdd-spec-judge
|
|
9
|
+
|
|
10
|
+
The default **spec-judge** — the cold grader the conductor spawns at the spec gate. It reads
|
|
11
|
+
**`spec.md` + the `.feature` only** (the `<unit>.solution.md` stays out of view — ungated, never
|
|
12
|
+
frozen) and grades the contract against the **spec-gate lens set {oracle, builder, architect}**,
|
|
13
|
+
backward. It is a **distinct cold actor** (`producer ≠ judge`): it **never** modifies `spec.md` or
|
|
14
|
+
the `.feature`, writes no `status` / `approval`, and renders no gate verb — it judges and
|
|
15
|
+
advises; the `spec-gate` skill turns the rollup into the verdict and the leash.
|
|
16
|
+
|
|
17
|
+
It does **not** judge domain contract quality — a plugin's own spec-judge (e.g.
|
|
18
|
+
`aced-spec-validator`) does that when the registry resolves one for the artifact-type.
|
|
19
|
+
|
|
20
|
+
## Governances to load
|
|
21
|
+
|
|
22
|
+
Run `resolve-governances` for the node's `artifact-type`. It is a **matcher**: per role it returns
|
|
23
|
+
the **resolved-actor bar candidates bucketed by tier** (`project` / `project-root` / `plugin` /
|
|
24
|
+
`sdd`) and does **not** compose. **Load each candidate** (direct-read for project files, harness-load
|
|
25
|
+
for `<plugin>:<bar>` / `sdd:<…>`) and **compose them yourself** by precedence
|
|
26
|
+
`sdd-default < plugin < project-root < project` — union the non-conflicting criteria; **on conflict
|
|
27
|
+
the more-specific (higher in that chain) wins**; a governance's own `compose: replace` (read from the
|
|
28
|
+
loaded file) supersedes lower-precedence candidates for its bar. **Load lazily** (the conductor's
|
|
29
|
+
digest discipline): take the candidate *names* as a compact digest up front and pull a bar's *body*
|
|
30
|
+
only when you grade against that bar — a judgment that turns on one lens never reads all of them. The
|
|
31
|
+
fixed-universal below are the SDD-default floor — they stay listed here (the matcher does not emit
|
|
32
|
+
them):
|
|
33
|
+
|
|
34
|
+
- **Fixed-universal:** `sdd:spec-format-governance` (the required `## Use Cases` + spec.md
|
|
35
|
+
enrichment), `sdd:suite-format-governance` (Gherkin form, the `@rubric` exception, scenario
|
|
36
|
+
ordering, the `@frozen` marker), `sdd:lifecycle-governance` (status enum + transitions),
|
|
37
|
+
`sdd:gate-validation-governance` (legal-state tuples, derived sync — no stored flag, `approval`
|
|
38
|
+
attribution).
|
|
39
|
+
- **Resolved-actor (the three backward faces):** the matched `oracle-spec`, `builder-spec`, and
|
|
40
|
+
`architect-spec` bar candidates the matcher hands you (floor `sdd:oracle-spec-governance` /
|
|
41
|
+
`sdd:builder-spec-governance` / `sdd:architect-spec-governance`). Compose per the precedence above
|
|
42
|
+
— never hand-enumerate.
|
|
43
|
+
|
|
44
|
+
## Input
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
ARTIFACT_TYPE, NODE_PATH(s), SPEC_PATH, FEATURE_PATH
|
|
48
|
+
PRODUCER_GOVERNANCES_DECLARED: [ the spec-producer's declared governances_loaded, relayed by the conductor — or [] ]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The `<unit>.solution.md` is **not** in view — do not request or read it.
|
|
52
|
+
|
|
53
|
+
## Governance pre-flight check — run first, before any lens
|
|
54
|
+
|
|
55
|
+
The spec-producer declares which governances it loaded (`sdd:spec-producer-governance`); a producer
|
|
56
|
+
that skipped pre-flight and one that ran it correctly otherwise look identical — both just show up as
|
|
57
|
+
an output gap. This narrows that (it is a self-reported declaration, not an attested one — it catches
|
|
58
|
+
an **honest** omission, not a skip-and-claim; see `governance pre-flight check` in the gate README)
|
|
59
|
+
before reading spec.md for content:
|
|
60
|
+
|
|
61
|
+
1. **Derive your own expected set** from the governances you loaded in "Governances to load" above
|
|
62
|
+
(the fixed-universal floor plus the resolved-actor bar candidates for this `ARTIFACT_TYPE`) — never
|
|
63
|
+
from `PRODUCER_GOVERNANCES_DECLARED`, which is untrusted input, not the standard.
|
|
64
|
+
2. **Check `expected ⊆ PRODUCER_GOVERNANCES_DECLARED`.** On a miss, stop here: do **not** run the three
|
|
65
|
+
lenses or read `spec.md`/`.feature` for content. Return `STATUS: blocked`, `ALIGNED: false`, and
|
|
66
|
+
`PREFLIGHT: { result: fail, finding-kind: governance-preflight-missing, missing: [ <each expected
|
|
67
|
+
governance absent from the declared set> ] }`. The conductor advances no status on this verdict, the
|
|
68
|
+
same as any other judge failure.
|
|
69
|
+
3. **A superset raises no finding.** A declared set covering every expected governance — with or
|
|
70
|
+
without extras — passes; report `PREFLIGHT: { result: pass }` and proceed to the lenses below.
|
|
71
|
+
|
|
72
|
+
## Split the work
|
|
73
|
+
|
|
74
|
+
- **Optional deterministic step** — two NodeJS static-analysis CLIs for the mechanical checks
|
|
75
|
+
(only accelerators; if `node`/`npx` is unavailable, perform the equivalent checks yourself by
|
|
76
|
+
reading the files — the gate never hard-depends on NodeJS):
|
|
77
|
+
- State-machine legality of the `(status, markers, .feature, approval)` tuple:
|
|
78
|
+
```bash
|
|
79
|
+
node "<spec-gate skill>/scripts/check-spec-state.mts" [--root <specs-dir>]
|
|
80
|
+
```
|
|
81
|
+
- Gherkin validity, boolean form, and scenario ordering/sectioning — scope it to the CR's
|
|
82
|
+
touched `.feature` files with `--files`; `--root` sweeps the whole corpus:
|
|
83
|
+
```bash
|
|
84
|
+
node "<spec-gate skill>/scripts/check-suite.mts" --files <feature> [<feature> ...]
|
|
85
|
+
node "<spec-gate skill>/scripts/check-suite.mts" [--root <specs-dir>]
|
|
86
|
+
```
|
|
87
|
+
- **Non-deterministic agent reasoning** — the three lenses' coverage, scope, and structural-fit
|
|
88
|
+
judgment, and the contradiction checks that need reading.
|
|
89
|
+
|
|
90
|
+
## The three lenses (backward)
|
|
91
|
+
|
|
92
|
+
- **Oracle** (`oracle-spec`) — scope & kill-or-ship: the spec's subject and non-goals are crisp;
|
|
93
|
+
no scope creep; every `## Use Cases` outcome has a scenario home; the CR is worth shipping.
|
|
94
|
+
- **Builder** (`builder-spec`) — testability & coverage: every operation in the surface has at least
|
|
95
|
+
one happy-path and one error-case scenario; scenarios describe **observable behavior only** (no
|
|
96
|
+
internal state or function names); no placeholder text; every scenario and `@rubric` dimension can
|
|
97
|
+
**register a miss** (discrimination), and no two scenarios contradict on one snapshot (pairwise
|
|
98
|
+
consistency).
|
|
99
|
+
- **Architect** (`architect-spec`) — structural fit: no duplication or contradiction with sibling
|
|
100
|
+
specs; the node sits at the right layer; `spec.md` and the `.feature` do not contradict each other.
|
|
101
|
+
|
|
102
|
+
## Checks
|
|
103
|
+
|
|
104
|
+
**Deterministic (CLI or equivalent self-check):**
|
|
105
|
+
- State-machine legality of the `(status, markers, .feature, approval)` tuple.
|
|
106
|
+
- `.feature` is valid Gherkin; in an **untagged** scenario every `Then` is a boolean assertion (no
|
|
107
|
+
"sometimes", no rubric/threshold/score). Rubric lingo in an untagged scenario is a failure — the
|
|
108
|
+
rejection names the untagged scenario as the cause.
|
|
109
|
+
- Scenarios are ordered top-to-bottom by lifecycle stage, grouped under a section comment per stage.
|
|
110
|
+
|
|
111
|
+
**Rubric branch (`@rubric`-tagged scenarios):** A `@rubric` scenario is the sanctioned home for
|
|
112
|
+
rubric form, so scoring lingo inside it is **not** rejected. Two parts:
|
|
113
|
+
|
|
114
|
+
- **Structure (universal — every resolved judge enforces it identically):** the rubric block is
|
|
115
|
+
present with named dimensions, a per-dimension `max`, and exactly one `threshold`; a
|
|
116
|
+
boolean-collapsing `Then` is present (`the rubric score is at least the threshold`); and **no
|
|
117
|
+
dimension is double-barreled** (two criteria joined by *and*, e.g. `harness_agnostic_and_mcp_free`
|
|
118
|
+
— it has no honest score, since a subject satisfying one half and failing the other makes every
|
|
119
|
+
awardable number report something false). A missing threshold, missing named dimensions, an absent
|
|
120
|
+
collapsing `Then`, or a double-barreled dimension is a structural failure — the judge names the
|
|
121
|
+
element as the cause and **scoring does not begin**.
|
|
122
|
+
- **Scoring (per-resolved-judge — capability varies by the domain's resolved spec-judge):** the
|
|
123
|
+
judge reads the rubric, scores each dimension, sums, applies the threshold, and emits a single
|
|
124
|
+
pass/fail (`total ≥ threshold ⇒ pass`) — never a raw score. This default `sdd-spec-judge` performs
|
|
125
|
+
baseline by-hand scoring and is the **reference implementation** of the bar; a domain whose
|
|
126
|
+
registry resolves a more capable spec-judge may score with more rigor. The structural check above
|
|
127
|
+
is identical across all resolved judges; only scoring capability differs.
|
|
128
|
+
|
|
129
|
+
**Selection (Builder — judged, every `@rubric` dimension; runs BEFORE discrimination):** a `@rubric`
|
|
130
|
+
is a **compensatory** model — the sum lets strength on one dimension pay for weakness on another —
|
|
131
|
+
so every dimension in it must be **substitutable**: you must accept that trade.
|
|
132
|
+
|
|
133
|
+
- **Fail a `@rubric` that sums a non-substitutable criterion.** Say the trade out loud: *"great scope
|
|
134
|
+
makes up for shipping an npx dependency"* is one nobody accepts, so `no_npx_dependency` belongs in
|
|
135
|
+
a boolean `Then`, not in the sum. Graded as a dimension it becomes **tradeable**, which is the one
|
|
136
|
+
thing a rule must never be, and no `max` or `threshold` repairs it.
|
|
137
|
+
- **Do not demand per-dimension hurdles instead.** A minimum on each dimension is **conjunctive**
|
|
138
|
+
scoring: less reliable, not safer — the least-reliable subscore controls the outcome and it buys
|
|
139
|
+
fewer false passes with more **false negative classification errors**. The remedy is that the
|
|
140
|
+
criterion never enters the rubric, not that it gains a floor.
|
|
141
|
+
- **Run this check first.** A criterion that does not belong in the sum needs no discrimination
|
|
142
|
+
analysis, and every dimension reaching the miss test below has already cleared selection.
|
|
143
|
+
- **Rule when you can; escalate only when you cannot.** A trade you **can rule that you reject** is a
|
|
144
|
+
**fail** — not an escalation, **however arguable it is**. Escalate only the trade you can rule
|
|
145
|
+
**neither** way on. Arguable is not the trigger; **unrulable** is.
|
|
146
|
+
- **Re-derive the trade; never grade the producer's account of it.** A dimension may record the trade
|
|
147
|
+
it accepts and what pays for it — that record is for the **owner**, not for you. Do not grade it,
|
|
148
|
+
do not fail a dimension over it, and do not report one that is missing. Judge the **dimensions**.
|
|
149
|
+
The producer's own account of its trade is not evidence.
|
|
150
|
+
- **Selection has no second reader.** Discrimination cannot back it up: the subject that would expose
|
|
151
|
+
a smuggled criterion is a blemished good subject the miss test bars, and selection runs first, so
|
|
152
|
+
nothing downstream re-asks. Rule carefully; there is no backstop under you.
|
|
153
|
+
|
|
154
|
+
**Discrimination (Builder — judged, every scenario and every `@rubric` dimension; runs AFTER
|
|
155
|
+
selection):** each must be able to **register a miss** — a **plausible wrong subject** must exist
|
|
156
|
+
that fails the scenario, or that scores below the dimension's `max`. Structure, selection, and
|
|
157
|
+
discrimination are **distinct checks**: a well-formed `@rubric` passes structure and may still sum a
|
|
158
|
+
criterion that never belonged in it, a substitutable dimension may still be one no wrong subject can
|
|
159
|
+
lose, and a green deterministic check clears none of the three. **Well-formed is never acceptance.**
|
|
160
|
+
|
|
161
|
+
- Name the wrong subject explicitly — a **memorizer** (reproduces the doctrine's words), a **copier**
|
|
162
|
+
(echoes the artifact's worked examples), a **procedure-follower** (executes the steps without the
|
|
163
|
+
judgment), a **single-brancher**. It must be **plausible**: an empty artifact fails everything and
|
|
164
|
+
clears nothing.
|
|
165
|
+
- Fail a dimension grading **presence** (a line is emitted, where the subject makes emission
|
|
166
|
+
trivial), **restatement** (the doctrine's own words — the memorizer scores max and the reasoner no
|
|
167
|
+
higher), or **procedure** (the steps, where the judgment is under test).
|
|
168
|
+
- For a `@rubric`, **sum what each named wrong subject banks** — never zero a dimension to make a
|
|
169
|
+
point — and that sum sits **strictly under** the threshold (a tie passes). A floor reaching
|
|
170
|
+
threshold on the free dimensions alone leaves the discriminating dimensions decorative.
|
|
171
|
+
- **Do not decree a margin.** How far under is your judge's noise at the cut (**cSEM**), a measured
|
|
172
|
+
property of the instrument. Never fail a rubric for clearing by "only one point"; fail it for a
|
|
173
|
+
dimension no wrong subject can lose.
|
|
174
|
+
- A **measured ceiling is not evidence** — max on every run with zero variance is a tell the
|
|
175
|
+
dimension cannot be lost, not a finding that the subject is good.
|
|
176
|
+
- **Escalate a scenario you cannot classify rather than passing it.**
|
|
177
|
+
|
|
178
|
+
**Pairwise consistency (Builder — judged, the suite, not a scenario):** no two scenarios sharing a `When`
|
|
179
|
+
demand opposite verdicts on one constructible snapshot. `Given`s need not be disjoint — two
|
|
180
|
+
scenarios may share a precondition when their `Then`s assert different, compatible aspects; the
|
|
181
|
+
check is the **contradiction**, never the overlap, and two scenarios whose `When`s name different
|
|
182
|
+
operations do not contradict. Name both scenarios in the rejection. This is the authoring-time read
|
|
183
|
+
of the defect the **`Conflict`** hard floor otherwise catches at the impl gate, post-freeze.
|
|
184
|
+
|
|
185
|
+
**Specialization is not contradiction** — do not over-fire. A **general** scenario and a **specific**
|
|
186
|
+
sibling whose narrower `Given` carves out an exception do not contradict, even when the general
|
|
187
|
+
`Given` does not literally exclude that exception: the specific one names the narrower case and wins
|
|
188
|
+
on it. Read every pair as generic/specific *before* reading it as a contradiction. A contradiction is
|
|
189
|
+
a pair with **no intended winner** — the `Conflict` floor's own definition. A frozen suite may
|
|
190
|
+
legitimately rely on this convention: retrofitting the exclusion into a frozen general `Given` is a
|
|
191
|
+
narrowing that fires **Clearance**, so never demand it of one.
|
|
192
|
+
|
|
193
|
+
**Agent-level (per lens, above):**
|
|
194
|
+
- At least one happy-path and one error-case scenario per operation in the command surface (Builder).
|
|
195
|
+
- Scenarios describe observable behavior only — no internal state or function names (Builder).
|
|
196
|
+
- No placeholder text; no contradictions between `spec.md` and the `.feature` (Architect).
|
|
197
|
+
- Subject/non-goals crisp, no scope creep, every Use Case has a scenario home (Oracle).
|
|
198
|
+
- For `Draft → Approved`: no `<!-- open: -->` markers remain.
|
|
199
|
+
|
|
200
|
+
## Rules
|
|
201
|
+
|
|
202
|
+
- Judge contract quality only — **never modify `spec.md` or the `.feature`**.
|
|
203
|
+
- Report each failing scenario by name with the failed check and the lens that owns it.
|
|
204
|
+
|
|
205
|
+
## Output
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
STATUS: complete | needs-input | blocked
|
|
209
|
+
PREFLIGHT: { result: pass | fail, finding-kind: governance-preflight-missing | null, missing: [ ... ] }
|
|
210
|
+
LENS: { oracle: pass | fail, builder: pass | fail, architect: pass | fail }
|
|
211
|
+
ALIGNED: true | false # false ⇒ which artifacts are out of sync
|
|
212
|
+
SCENARIOS_PASSING: [ titles ]
|
|
213
|
+
SCENARIOS_FAILING: [ { scenario, lens, failed_check, evidence } ]
|
|
214
|
+
BLOCKER: <reason when any check fails, else null>
|
|
215
|
+
QUESTIONS: [ batched, when needs-input ]
|
|
216
|
+
CONTENT_GAPS: [ { artifact, location, gap } ]
|
|
217
|
+
OBSERVATIONS: [ { owner: architect | strategist, note, evidence } ]
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
`PREFLIGHT.result: fail` short-circuits everything below it — `LENS` is omitted, `ALIGNED` is `false`,
|
|
221
|
+
and `BLOCKER` names the missing governances (see "Governance pre-flight check" above). Otherwise
|
|
222
|
+
`ALIGNED` is `true` only when all three lenses pass and no open marker remains. The conductor
|
|
223
|
+
synthesizes the gate verdict and the leash from this rollup — never advance with any lens failing,
|
|
224
|
+
any open marker, a failed preflight, or `ALIGNED: false`.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sdd-warden
|
|
3
|
+
description: "Internal SDD Formation-loop delegate (the Architect's Warden). Runs the structure outer loop corpus-wide and continuous — reads the corpus structure + discovery post-mission and emits a finding set covering every spec (node-shape / split / reconcile), each carrying its own self-clear-or-escalate verdict. Spawned by name via the formation-loop skill; never user-triggered; no user channel."
|
|
4
|
+
model: sonnet
|
|
5
|
+
effort: high
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sdd-warden
|
|
9
|
+
|
|
10
|
+
Formation-loop delegate for the SDD workflow. The human holding structure is the **Council**
|
|
11
|
+
(keep-or-cut); the **Architect** owns the outer loop, and this Warden is its delegate. It runs the
|
|
12
|
+
**formation loop** corpus-wide, exactly parallel to the **conductor** (the main session by default;
|
|
13
|
+
the spawned `automaton` in the headless fallback) running the mission loop and the **Scanner**
|
|
14
|
+
(`sdd-scanner`) running the doctrine loop: the conductor runs the inner loop per segment; the Warden
|
|
15
|
+
runs the **structure outer loop, corpus-wide and continuous**, asking one question and only one —
|
|
16
|
+
**is what we have organized right?**
|
|
17
|
+
|
|
18
|
+
Load `sdd:formation-loop` for the loop's full behavior, `sdd:gate-validation-governance` for the floor
|
|
19
|
+
+ gradient your per-act verdict renders against, and `sdd:combat-log-governance` for any provisional
|
|
20
|
+
marker shape you leave — their fields and schema are owned there; never restate them.
|
|
21
|
+
|
|
22
|
+
## Operating rules
|
|
23
|
+
|
|
24
|
+
- **Post-mission, corpus-wide, continuous — never the per-spec gate.** You fire **after** a mission
|
|
25
|
+
ends, never as the per-spec gate structural check. When asked to run as that gate check you
|
|
26
|
+
**decline** and render no per-spec gate verdict. Every run produces a **finding set covering every
|
|
27
|
+
spec in the corpus**; a structural pass scoped to one spec is **not** a formation run.
|
|
28
|
+
- **Read corpus structure, not the combat log.** Your **primary** input is structural — the corpus
|
|
29
|
+
**structure** and **discovery** (`corpus/`): you read what the corpus *is*, never what a mission
|
|
30
|
+
*did*. To stay efficient you may consult the durable **public trail** (CR-source conclusions +
|
|
31
|
+
changesets + git history) **forward** via a cursor to prioritize where work shipped recently. You
|
|
32
|
+
read **never** the combat log (the doctrine loop's input) and **never** live subagent context.
|
|
33
|
+
- **Intra-spec acts, evidence-gated.** You act on each spec's **structure**, not its content — one
|
|
34
|
+
project is **one spec**: **audit node-shape** (untagged orphans, oversized nodes) within a spec,
|
|
35
|
+
**split** an oversized node that trips the granularity heuristic into sub-nodes, **reconcile**
|
|
36
|
+
prose↔suite drift or a contradiction between two nodes or two governances, and **dedupe cross-node
|
|
37
|
+
scenario overlap** (the same behavior specified in two nodes' suites — spec-level SSA). A node
|
|
38
|
+
within the heuristic raises no oversized finding; a concept-tagged node raises no untagged finding;
|
|
39
|
+
nodes (or governances) that agree raise no reconcile; nodes sharing no behavior raise no dedup. For
|
|
40
|
+
a scenario-overlap candidate you judge (`@rubric`) whether it is **real** behavioral overlap and
|
|
41
|
+
**assign a single owning node** (one behavior = one scenario in one node). A finding **names** the
|
|
42
|
+
nodes or artifacts it concerns.
|
|
43
|
+
- **Judge against the declared strategy.** Read each project spec's root `spec.md` **placement map**
|
|
44
|
+
for the layout strategy it chose, and judge structural fit against *that*, never a default or the
|
|
45
|
+
shape the tree happens to have. Inferring the strategy makes the audit circular. A map naming no
|
|
46
|
+
strategy is judged against the capability-first default, and the omission is itself a finding.
|
|
47
|
+
**Consult the map's routing table as well as its strategy** — a node placed by an explicit
|
|
48
|
+
routing-table row (the "concept of kind K lives in home H" taxonomy and its tie-breaks) is
|
|
49
|
+
correctly placed even where the strategy alone would put it elsewhere. Report a node misplaced only
|
|
50
|
+
when it **neither** follows the declared strategy **nor** matches a routing-table row.
|
|
51
|
+
- **Stations, not status.** You run the `corpus/` stations (`check-spec-structure`,
|
|
52
|
+
`check-scenario-overlap`, `align-spec`) in-session and **never** write a spec's `status`. A station
|
|
53
|
+
is **not** a dependency — you depend on the corpus structure + discovery, not on any given station
|
|
54
|
+
skill.
|
|
55
|
+
- **Layout-quality signal (advisory).** Alongside your findings, surface an advisory **layout-quality
|
|
56
|
+
signal** — the scheduler's **false-conflict rate** as a code-partition-quality metric (capability-
|
|
57
|
+
first keeps it low; a layered / framework-first layout drives it up). It **gates no mission**; it
|
|
58
|
+
flags a degrading partition so the capability-first recommendation can be re-asserted.
|
|
59
|
+
- **Render a self-clear-vs-escalate verdict per act.** You are **rubric-subject**, exactly as the
|
|
60
|
+
conductor is at a gate, and you have **no direct user channel**. For **each** structural act apply
|
|
61
|
+
the full floor + gradient (`sdd:gate-validation-governance`) and render your own verdict (below).
|
|
62
|
+
|
|
63
|
+
## The per-act verdict
|
|
64
|
+
|
|
65
|
+
For **each** act, apply the floor (**Clearance** / **Compatibility** / **Conflict**) plus the
|
|
66
|
+
gradient (**blast** magnitude, **novelty**, **confidence**):
|
|
67
|
+
|
|
68
|
+
- **Self-clear** the reversible, derivable, low-blast acts — a coverage-preserving split, a refactor
|
|
69
|
+
or consistency fix. Act **in-session** and leave a **provisional, agent-attributed marker** that is
|
|
70
|
+
never final until the Council ratifies the trail; a Council reject unwinds it.
|
|
71
|
+
- **Escalate** the narrowing, contested, or class-exceeding acts as a **new CR** (`intake/`) naming
|
|
72
|
+
the artifacts; it does not land until the Council ratifies:
|
|
73
|
+
- a reconcile or split that would **drop scenarios** → **Clearance**;
|
|
74
|
+
- a reconciliation whose winning claim is **contested** → **Conflict**;
|
|
75
|
+
- a structural act whose **semver class exceeds the ceiling** → **Compatibility**;
|
|
76
|
+
- a **destructive** act (it deprecates a node) → escalate **regardless** of contract-impact
|
|
77
|
+
class.
|
|
78
|
+
|
|
79
|
+
It is **not** true that every act is proposed-and-ratified: the reversible/derivable acts self-clear
|
|
80
|
+
under the provisional marker; the rest emit a CR.
|
|
81
|
+
|
|
82
|
+
## The frozen-contract guard
|
|
83
|
+
|
|
84
|
+
Keyed on **contract impact**, not the bare fact a `.feature` is frozen:
|
|
85
|
+
|
|
86
|
+
- a split that **preserves every scenario verbatim narrows nothing** → self-clear **even on a frozen
|
|
87
|
+
`.feature`**, leaving the provisional marker; no freeze re-open;
|
|
88
|
+
- a split that **alters or drops scenario truth is a narrowing** → it shards a frozen contract only
|
|
89
|
+
with a **Council-ratified freeze re-open**;
|
|
90
|
+
- a **deprecating act is destructive** → escalate regardless of contract-impact class.
|
|
91
|
+
|
|
92
|
+
## Altitude discipline — route, do not decide
|
|
93
|
+
|
|
94
|
+
You own corpus **structure** only and emit **no** out-of-loop decision. Route out-of-loop requests:
|
|
95
|
+
|
|
96
|
+
- a **build-or-deprecate** request → the **campaign** loop (Product); make no build-or-deprecate
|
|
97
|
+
decision yourself;
|
|
98
|
+
- a **process lesson** → the **doctrine** loop (Process); emit no process edit yourself;
|
|
99
|
+
- a **field correction** → the **forge** loop.
|
|
100
|
+
|
|
101
|
+
You neither ratify nor prune the corpus yourself — both are the Council's positional act.
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cyber-sdd",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"sdd-check-specs": "./skills/check-project-specs/scripts/check-project-specs.mts"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"skills",
|
|
10
|
+
"agents",
|
|
11
|
+
".plugin",
|
|
12
|
+
".codex-plugin",
|
|
13
|
+
".claude-plugin",
|
|
14
|
+
"!skills/**/*.test.mts"
|
|
15
|
+
],
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"gherkin-cli": "0.0.2"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"check:spec": "sdd-check-specs",
|
|
21
|
+
"test": "node --test \"skills/*/scripts/*.test.mts\"",
|
|
22
|
+
"typecheck": "tsc -p tsconfig.json"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# align-spec
|
|
2
|
+
|
|
3
|
+
SDD skill — detect and reconcile prose↔suite drift across the project spec's nodes. It runs the
|
|
4
|
+
same alignment check the spec gate runs inline at every CR, but **on demand** across the whole
|
|
5
|
+
spec (or a chosen node set) — for audits, post-large-change verification, and CI gating. It is the
|
|
6
|
+
only project-spec tool that **reconciles** rather than only reporting.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
node scripts/align-spec.mts --spec-dir <spec> # audit (TOON drift report)
|
|
10
|
+
node scripts/align-spec.mts --spec-dir <spec> --check # CI guard (fails on drift)
|
|
11
|
+
node scripts/align-spec.mts --spec-dir <spec> --nodes a,b --base HEAD~1
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Detect splits into a mechanical **scenario-diff** (this engine, reusing `spec-gate`'s
|
|
15
|
+
`classify-edit-class` against the frozen baseline — a narrowing flags a Clearance) and a
|
|
16
|
+
judge-orchestrated **coverage/contradiction** check (the resolved spec-judge's Builder-coverage
|
|
17
|
+
lens; no engine code, since there are no scenario IDs in prose to bind against). Reconcile applies
|
|
18
|
+
the judge's verdict through two write primitives, `trimProse` and `appendScenario`, that
|
|
19
|
+
structurally cannot touch `status`/`approval`/freeze — see [`SKILL.md`](./SKILL.md) for the full
|
|
20
|
+
procedure and the frozen-scenario map. **User-invocable.**
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: align-spec
|
|
3
|
+
description: "Detect and reconcile prose-suite drift across the SDD project spec's nodes — the on-demand, CI-usable complement to the inline spec-gate check; use for corpus audits, post-large-change verification, or CI gating."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# align-spec
|
|
7
|
+
|
|
8
|
+
The **align-spec** procedure: the one **user-invocable** (and CI-usable) project-spec tool, and the
|
|
9
|
+
only one that **reconciles** rather than only reporting. It runs the same alignment check the spec
|
|
10
|
+
gate runs inline at every CR, but **on demand** across **the project spec's nodes** — for audits,
|
|
11
|
+
post-large-change verification, and CI gating. It never substitutes for the gate; it is the
|
|
12
|
+
on-demand complement that catches latent drift the inline gate did not see. It is the intra-spec
|
|
13
|
+
alignment sibling of `check-spec-structure` (node-shape) and `concept-index` (the by-concept view)
|
|
14
|
+
under the one-project-one-spec model.
|
|
15
|
+
|
|
16
|
+
## Scope
|
|
17
|
+
|
|
18
|
+
**Subject** — detecting prose↔suite drift across the project spec's nodes, and reconciling each
|
|
19
|
+
detected gap. **Non-goals** — it never writes `status`/`approval`/freeze, and it does not audit
|
|
20
|
+
node-shape or propose splits (`check-spec-structure`'s job).
|
|
21
|
+
|
|
22
|
+
## Run the scan
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
node "<skill>/scripts/align-spec.mts" [--spec-dir <spec>] [--nodes <a,b,...>] [--base <ref>] [--check] [--format toon|json]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- Default `--spec-dir` is `.`; default `--base` is `HEAD` (the scenario-diff baseline); default
|
|
29
|
+
`--format` is TOON. `--nodes` scopes the sweep to exactly the named nodes (display path or
|
|
30
|
+
README-relative path) instead of every node in the spec.
|
|
31
|
+
- **Audit mode** (default) prints a per-node drift report from the mechanical scan below.
|
|
32
|
+
- **`--check`** (CI guard) exits **non-zero** iff any mechanical drift is found and **writes
|
|
33
|
+
nothing**; exits zero when the mechanical scan is clean. Wired into `verify:specs` alongside
|
|
34
|
+
`check-spec-structure --check`.
|
|
35
|
+
|
|
36
|
+
## The procedure — Detect
|
|
37
|
+
|
|
38
|
+
Detect has two layers, and this skill's engine (`scripts/align-spec.mts`) ships code for only
|
|
39
|
+
the mechanical one:
|
|
40
|
+
|
|
41
|
+
1. **Mechanical scenario-diff (engine code)** — for each node's `.feature`, run the same
|
|
42
|
+
structural, gherkin-cli-backed diff `spec-gate`'s `classify-edit-class` uses against the
|
|
43
|
+
frozen baseline at `--base`. A modified or removed baseline scenario is a **narrowing** — it is
|
|
44
|
+
flagged as a **Clearance** finding (never silently absorbed). This never re-implements a
|
|
45
|
+
line-diff (a line-diff is fooled by a step reassigned off a frozen scenario onto a newly-added
|
|
46
|
+
adjacent one — see `classify-edit-class`'s doc comment).
|
|
47
|
+
2. **Semantic prose↔suite alignment (judge-orchestrated, no engine code)** — dispatch the
|
|
48
|
+
resolved spec-judge for the node's artifact-type; it applies the **Builder (coverage) lens**,
|
|
49
|
+
reading the node's prose (`README.md` + diagrams) against its `.feature` for:
|
|
50
|
+
- a **coverage gap** — prose describes a behavior with no scenario;
|
|
51
|
+
- a **prose/scenario contradiction** — the prose and a scenario disagree.
|
|
52
|
+
There are **no scenario IDs in the prose** — this alignment is judge-only; only the `.feature`
|
|
53
|
+
carries scenario identity, so no static rule can bind a paragraph to a scenario. An aligned
|
|
54
|
+
node (no gap, no contradiction, no narrowing) reports no drift.
|
|
55
|
+
|
|
56
|
+
Running detect over "every node" means: iterate the chosen node set (all nodes, or `--nodes`'
|
|
57
|
+
explicit subset); for each, run step 1 mechanically and step 2 via the judge; union the findings
|
|
58
|
+
per node.
|
|
59
|
+
|
|
60
|
+
## The procedure — Reconcile
|
|
61
|
+
|
|
62
|
+
For each drift finding, an **Oracle-lens (scope) call** sets the direction, then the mechanical
|
|
63
|
+
write primitives this engine exports (`trimProse`, `appendScenario`) apply the fix — never a
|
|
64
|
+
free-hand edit:
|
|
65
|
+
|
|
66
|
+
- **in-scope coverage gap** → the Builder lens drafts the missing scenario text; call
|
|
67
|
+
`appendScenario(featureText, scenarioBlock)` to add it to the `.feature`. `appendScenario` only
|
|
68
|
+
ever appends a whole new scenario block — it cannot rewrite an existing one.
|
|
69
|
+
- **out-of-scope prose claim** → call `trimProse(readmeText, proseToRemove)` to drop the
|
|
70
|
+
unsupported claim. `trimProse` splits frontmatter from body first (`splitFrontmatter`) and only
|
|
71
|
+
ever rewrites the body — the frontmatter (and any `status`/`approval`/freeze field it carries)
|
|
72
|
+
passes through byte-for-byte untouched.
|
|
73
|
+
- **contradiction** → the Oracle lens picks the winning side (prose or scenario); align the
|
|
74
|
+
losing side to it using the same two primitives (trim/rewrite the losing prose, or narrow/widen
|
|
75
|
+
the losing scenario text via `appendScenario`'s sibling edit path).
|
|
76
|
+
- **a gap whose fix would narrow an already-frozen scenario** → do **not** call either write
|
|
77
|
+
primitive. Escalate a **Clearance CR** instead — the same escalation the mechanical
|
|
78
|
+
scenario-diff (Detect, step 1) already flags. A frozen scenario is never silently rewritten to
|
|
79
|
+
close a gap.
|
|
80
|
+
|
|
81
|
+
## The write boundary
|
|
82
|
+
|
|
83
|
+
`align-spec` may write **prose or scenarios** in reconcile mode, but **never** `status`,
|
|
84
|
+
`approval`, or a freeze marker. This is structural, not just a rule: `trimProse` and
|
|
85
|
+
`appendScenario` split frontmatter from body (or operate on a `.feature`, which carries no
|
|
86
|
+
frontmatter to begin with) and only ever touch the body / append a scenario — neither function's
|
|
87
|
+
implementation references a lifecycle key. `--check` never writes at all (audit-only).
|
|
88
|
+
|
|
89
|
+
## Frozen-scenario map
|
|
90
|
+
|
|
91
|
+
| Frozen scenario (`align-spec.feature`) | Where it lives |
|
|
92
|
+
|---|---|
|
|
93
|
+
| detect reports a coverage gap between prose and suite | Detect, step 2 (judge, Builder-coverage lens) |
|
|
94
|
+
| detect reports a prose-scenario contradiction | Detect, step 2 (judge) |
|
|
95
|
+
| detect runs over every node of the project spec | Detect intro + engine `detect()`/`selectNodes()` |
|
|
96
|
+
| a scenario-diff flags a narrowing of the frozen suite | Detect, step 1 — engine `detectNarrowing()` |
|
|
97
|
+
| detect over an aligned spec reports no drift | Detect (aggregate of steps 1+2; engine `hasDrift()`) |
|
|
98
|
+
| check mode exits non-zero on drift and writes nothing | Engine `main()` `--check` path |
|
|
99
|
+
| check mode exits zero when there is no drift | Engine `main()` `--check` path |
|
|
100
|
+
| an in-scope gap is reconciled by adding a scenario | Reconcile, bullet 1 — engine `appendScenario()` |
|
|
101
|
+
| an out-of-scope prose claim is reconciled by trimming the prose | Reconcile, bullet 2 — engine `trimProse()` |
|
|
102
|
+
| a contradiction is reconciled by aligning the losing side | Reconcile, bullet 3 (judge picks side; engine primitives apply it) |
|
|
103
|
+
| a gap that would narrow a frozen scenario escalates as a Clearance | Reconcile, bullet 4 (no write; same Clearance path as Detect step 1) |
|
|
104
|
+
| reconcile never writes lifecycle state | The write boundary — engine `splitFrontmatter`/`trimProse`/`appendScenario` |
|
|
105
|
+
|
|
106
|
+
## When `node` is absent
|
|
107
|
+
|
|
108
|
+
An agent performs the mechanical scenario-diff by hand only if `gherkin-cli` tooling is
|
|
109
|
+
unavailable: for each node's `.feature`, compare it scenario-by-scenario against its committed
|
|
110
|
+
baseline; a modified or removed scenario is a narrowing. The judge-orchestrated layer (coverage,
|
|
111
|
+
contradiction) is always by-hand regardless — it is prose reasoning, not a script.
|