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,75 @@
|
|
|
1
|
+
# suite-format-governance
|
|
2
|
+
|
|
3
|
+
This is an internal SDD governance about the acceptance behavior suite.
|
|
4
|
+
|
|
5
|
+
It describes how a capability's `.feature` suite — the executable scenarios that sit beside its
|
|
6
|
+
`spec.md` — is written and judged.
|
|
7
|
+
|
|
8
|
+
Every behavioral spec carries such a suite, and every scenario in it collapses to one pass/fail at
|
|
9
|
+
the point of verification — never a score. The core idea: the suite **is** the capability's
|
|
10
|
+
**control-flow graph (CFG)**. Each scenario pins one branch the capability takes; the suite as a
|
|
11
|
+
whole covers every branch, and nothing that is not a branch.
|
|
12
|
+
|
|
13
|
+
## What it requires
|
|
14
|
+
|
|
15
|
+
| Rule | What it means |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Acceptance only, strict** | A scenario tests a **decision** — a branch you can name. A statement with no nameable branch ("output is valid JSON", "idempotent") is an invariant: not specified here, covered by the implementation's own tests. Properties another capability co-owns are out of scope too. |
|
|
18
|
+
| **One scenario per (path class, edge)** | The `Given` is the path taken to a decision, the `When` is the decision under test, the `Then` is the branch taken. Paths that reconverge with the same outcome collapse into one scenario — that is what keeps the suite finite. An over-specific `Given` is a defect: it manufactures a false permutation. |
|
|
19
|
+
| **Every guard gets a positive companion** | A reject/kill/guard scenario is paired with a scenario driving the same path in its firing direction. A lone negative is inert — a do-nothing subject passes it. |
|
|
20
|
+
| **Scenario map, 1:1** | The spec's `## Scenario map` table and the suite bind one-to-one: every scenario has a row, every row names a real scenario, each row names both the edge and the path class. An unmapped scenario is an orphan; an unmapped edge is a coverage hole. |
|
|
21
|
+
| **Boolean Gherkin by default** | Every `Then` is an observable, deterministic boolean. The test is the **trace, not the verb**: name the artifact a verifier would read to settle it — an output, an exit code, a written file, a returned field. Asserting an *act* is fine when the act leaves a trace; if nothing records it, either add the record or do not assert it. Never assert how the artifact was authored, nor internal state. |
|
|
22
|
+
| **`@rubric` for graded judgment** | When a branch's correctness is a gradient no single boolean captures: named dimensions, a threshold, and a collapsing `Then` — still one boolean per scenario at the verification point. |
|
|
23
|
+
| **A `Given` is a test vector** | The implementation owes conformance to the `Then` only. A `Given`'s domain and framing are apparatus (the swap test tells them apart from the binding precondition), and neither side may absorb the other's examples. |
|
|
24
|
+
| **A `Given` is a scaffoldable state** | Declarative, observable, present-tense, one condition per step. The build test: could two people, given only this line, construct the same fixture? |
|
|
25
|
+
| **Pairwise consistency** | No two scenarios demand opposite verdicts on one constructible state. A narrower `Given` that carves an exception is specialization, not contradiction. |
|
|
26
|
+
| **Dead edges measure nothing** | The miss test: name a plausible wrong subject and check it takes the wrong branch. If none can, the edge is inert. |
|
|
27
|
+
|
|
28
|
+
Scenarios are grouped under section comments mirroring the spec's use-case groups, in the same
|
|
29
|
+
order, stepping down from the happy path to its branches and errors.
|
|
30
|
+
|
|
31
|
+
## Two special markers
|
|
32
|
+
|
|
33
|
+
- **`@pinned`** — a **user-owned** seed scenario. Only the user applies it; the agent may propose a
|
|
34
|
+
change or removal but never executes one without in-session user authorization. A pin marks a
|
|
35
|
+
behavior the CFG did not reach, and the agent grows the CFG around it. It is the one
|
|
36
|
+
override to strict.
|
|
37
|
+
- **`@frozen`** — freeze is per `.feature` file. Adding a scenario folds in and self-clears; a pure
|
|
38
|
+
move preserves the freeze; a narrowing or rewrite unfreezes and fires Clearance at the gate.
|
|
39
|
+
|
|
40
|
+
## The executable check — `check-suite`
|
|
41
|
+
|
|
42
|
+
The mechanical rules — Gherkin validity, boolean `Then`s, section comments, Outline coverage, and
|
|
43
|
+
the scenario-map binding — are linted by `check-suite` (`spec-gate/scripts/check-suite.mts`). The
|
|
44
|
+
spec-producer self-runs it before returning, and the spec gate runs it fail-closed before the cold
|
|
45
|
+
judge. It checks **form only**: whether the map's rows actually cover the drawn CFG — coverage,
|
|
46
|
+
discrimination, consistency — is judged, never linted, so a green check clears no coverage
|
|
47
|
+
question.
|
|
48
|
+
|
|
49
|
+
## Usage
|
|
50
|
+
|
|
51
|
+
- **spec-producer:** self-aligns to this bar before writing the suite, and self-runs `check-suite`
|
|
52
|
+
before returning.
|
|
53
|
+
- **spec-judge** and the actor bars (**oracle** / **architect** / **builder**): judge their slices
|
|
54
|
+
of it backward at the **spec-gate**.
|
|
55
|
+
- **spec-gate:** runs `check-suite` fail-closed before spawning the cold judge.
|
|
56
|
+
|
|
57
|
+
## Related governances
|
|
58
|
+
|
|
59
|
+
This bar owns how the **`.feature` suite** is written. Its neighbors own everything around that:
|
|
60
|
+
|
|
61
|
+
- **`spec-format-governance`** — how the `spec.md` is written: the use-case groups, the drawn
|
|
62
|
+
CFG, and the `## Scenario map` table this suite binds to. Spec-format owns the `spec.md`;
|
|
63
|
+
suite-format owns the `.feature` that mirrors it.
|
|
64
|
+
- **`lifecycle-governance`** — the freeze/unfreeze *model* and its risk trigger; this bar carries
|
|
65
|
+
only the `@frozen` marker's mechanics.
|
|
66
|
+
- **`ownership-governance`** — who may write a frozen `.feature` (no one), and the user's ownership
|
|
67
|
+
of `@pinned` scenarios.
|
|
68
|
+
- **The impl actor bars** (`builder-impl-governance`, `architect-impl-governance`) — the
|
|
69
|
+
**verification level**. This bar is deliberately **silent** on it, and that silence is the point:
|
|
70
|
+
what a suite specifies (acceptance) and how high a test runs to verify it (e2e down to unit) are
|
|
71
|
+
two independent axes. A suite that names a level has leaked the second axis into the first —
|
|
72
|
+
"boundary" is a level, not a category of scenario. The level is chosen per scenario by whoever
|
|
73
|
+
implements the test.
|
|
74
|
+
|
|
75
|
+
Internal SDD governance (`user-invocable: false`). Not triggered by users directly.
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: suite-format-governance
|
|
3
|
+
description: "Partial Skill: invoke by name only"
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Suite-Format Governance — the acceptance behavior-suite bar
|
|
8
|
+
|
|
9
|
+
Form authority for a behavior suite: how it is written and judged. Fixed-universal SDD
|
|
10
|
+
governance — the spec-producer self-aligns to it, and each actor bar (`oracle` / `architect` /
|
|
11
|
+
`builder`) judges its slice of it backward at the gates. Governs the suite of a **behavioral**
|
|
12
|
+
spec only; descriptive and reference nodes carry no suite. Every scenario collapses to **one
|
|
13
|
+
pass/fail** at the verification point — never a score.
|
|
14
|
+
|
|
15
|
+
## The suite specifies acceptance only — strict
|
|
16
|
+
|
|
17
|
+
A suite specifies **acceptance** — the observable **decisions** the node owns — and nothing else.
|
|
18
|
+
|
|
19
|
+
- **Decisions only — and the map is the test.** A scenario tests a **decision** — a branch the
|
|
20
|
+
capability takes. The mechanical filter is **can you name the edge it sits on?** A scenario with no
|
|
21
|
+
nameable edge is a non-branch **invariant** ("output is valid JSON", "idempotent"): not acceptance,
|
|
22
|
+
not specified here, covered by the implementation's own tests.
|
|
23
|
+
Do **not** cut a scenario merely because it reads like a property. A constraint that holds across
|
|
24
|
+
every path *still sits on an edge* — "the envelope is the same for every strategy" is the
|
|
25
|
+
**convergence** shape at that edge (below), asserting the outcome does not vary, which is a design
|
|
26
|
+
decision. Unmappable is the cut; property-sounding is not.
|
|
27
|
+
- **The node's own decisions.** A property **co-owned** across a seam — activation/routing (does this
|
|
28
|
+
config fire?), a sibling's behavior, harness wiring — is not this node's to freeze; it is **out of
|
|
29
|
+
scope** (Oracle relocates or kills it).
|
|
30
|
+
- The only escape from strict is a user **pin** (below).
|
|
31
|
+
|
|
32
|
+
## The suite is the capability's control-flow graph
|
|
33
|
+
|
|
34
|
+
The suite **is** the node's **control-flow graph (CFG)** at acceptance level. Author it as one:
|
|
35
|
+
|
|
36
|
+
- **One scenario = one (path class, edge) pair.** The `Given` is the **path** — the decisions already
|
|
37
|
+
made on the way here; the `When` is the **edge under test**; the `Then` is the **branch taken**. The
|
|
38
|
+
unit is not the edge alone: one edge needs several scenarios when its outcome differs by the path
|
|
39
|
+
reaching it.
|
|
40
|
+
- **State the least specific `Given` that determines the outcome.** Paths that **reconverge** and leave
|
|
41
|
+
no distinguishing state **collapse into one scenario** — `a→b→d` and `a→c→d` are the same scenario
|
|
42
|
+
when the outcome at `d` does not depend on whether `b` or `c` was taken. Name the reconvergence
|
|
43
|
+
point, never the route. This is what keeps the suite finite: without it, every upstream branch
|
|
44
|
+
multiplies every downstream one.
|
|
45
|
+
- **Add a permutation only when the outcome differs.** Same outcome under two prefixes ⇒ one scenario.
|
|
46
|
+
- **An over-specific `Given` is a defect.** Naming state the outcome does *not* depend on
|
|
47
|
+
**manufactures a false permutation** — it implies a sibling scenario for the other value and invites
|
|
48
|
+
exactly the explosion the collapse rule prevents.
|
|
49
|
+
- **Cover every branch.** A decision whose only covered edges are its "no" branches is incomplete: a
|
|
50
|
+
**kill / reject / guard edge is paired with a positive companion** driving the same path in its
|
|
51
|
+
firing direction. A lone negative is passed by a do-nothing subject (the sorted list that "stays
|
|
52
|
+
sorted" under `sort = identity`).
|
|
53
|
+
- **Each edge isolates a specific condition** — the `Given` sets up the exact state forcing *this*
|
|
54
|
+
branch and not its sibling, and hands over **no** part of the verdict. A scenario asserting a finding
|
|
55
|
+
asserts its **binding consequence** (withholds the pass, blocks the gate), never just its emission.
|
|
56
|
+
|
|
57
|
+
A **dead edge** — one no plausible wrong subject takes the wrong way — measures nothing: a missing
|
|
58
|
+
guard, an orphaned negative, or a `Given` that states its own answer. The **miss test** settles it:
|
|
59
|
+
*name a plausible wrong subject and check it takes the wrong branch; if none can, the edge is
|
|
60
|
+
inert.* Plausible, not strawman — a memorizer, a copier, a single-brancher, never an empty artifact.
|
|
61
|
+
Discrimination is **judged, not linted**; a **measured ceiling is a tell an edge cannot be lost**,
|
|
62
|
+
not evidence it works. Rubric-dimension discrimination detail: `references/rubric.md`.
|
|
63
|
+
|
|
64
|
+
**Backfilling from existing code — derive, don't patch.** When the implementation already exists,
|
|
65
|
+
draw the CFG from the code (`sdd:spec-format-governance` owns the `## Control Flow` + `## Scenario
|
|
66
|
+
map` sections) and **re-derive the whole scenario set from its edges** — one scenario per `(path
|
|
67
|
+
class, edge)` pair, every guard paired with a positive companion. Any pre-existing `.feature` or
|
|
68
|
+
legacy corpus (a retired golden set) is **reference only**: each entry is a **claim to verify against
|
|
69
|
+
the current code**, never the baseline to patch. Reading the standing suite and filling only the gaps
|
|
70
|
+
a diff notices is not this procedure — it leaves stale scenarios in place and misses edges the CFG
|
|
71
|
+
mandates (ADR-0029).
|
|
72
|
+
|
|
73
|
+
## Sections mirror the spec's use-case groups; every scenario binds to a map edge
|
|
74
|
+
|
|
75
|
+
`spec.md` sections the node by **use-case group**, each carrying a drawn **CFG** and an
|
|
76
|
+
explicit **scenario-map** table (`sdd:spec-format-governance`). The suite **mirrors** it:
|
|
77
|
+
|
|
78
|
+
- Group scenarios under `# ── <use-case group> ──` comments — same groups, same order — screaming
|
|
79
|
+
the intents; never sectioned by layer, output format, or "misc rules".
|
|
80
|
+
- **The map is 1:1 scenario↔row**, and each row names **both** the edge and the path class
|
|
81
|
+
(`| Edge | Path (Given) | Scenario |`). A scenario off the map is an orphan; an edge with **no** row
|
|
82
|
+
is a coverage hole. An edge with **several** rows is **not** a duplicate — it is permutation
|
|
83
|
+
coverage, and legitimate exactly when each row's path class yields a different outcome. Two rows
|
|
84
|
+
with the same edge *and* the same path class **is** a duplicate. `check-suite` lints orphans,
|
|
85
|
+
uncovered edges, and same-edge-same-path duplicates.
|
|
86
|
+
|
|
87
|
+
**Three shapes sit on the map**, all of them acceptance:
|
|
88
|
+
|
|
89
|
+
- **branch** — the `Given` pins one path class; the `Then` names the branch taken.
|
|
90
|
+
- **convergence** — the `Given` deliberately **spans** classes ("for every strategy"); the `Then`
|
|
91
|
+
asserts the outcome **does not vary**. One scenario legitimately covers many permutations, and that
|
|
92
|
+
non-variance is a design decision, not an invariant.
|
|
93
|
+
- **barred** — the `Then` asserts an edge that must **not** exist (an option never offered).
|
|
94
|
+
|
|
95
|
+
## The tag set — every tag a `.feature` may carry
|
|
96
|
+
|
|
97
|
+
This bar defines the tag **vocabulary** — what each tag *means*. It does **not** define how a judge
|
|
98
|
+
measures the tagged scenario: run counts, thresholds, corpora and pass bars are the resolved
|
|
99
|
+
plugin's (ACED, for agent-config domains). Tag = interface, plugin = implementation. A governance
|
|
100
|
+
that mentions a tag is a consumer. The rules live in the sections named below; this table is the index.
|
|
101
|
+
|
|
102
|
+
| Tag | Names | Scope | Applied by | Means |
|
|
103
|
+
| --- | --- | --- | --- | --- |
|
|
104
|
+
| `@trigger` | the engage decision | scenario | producer | Does the subject **engage** when it should, and stay out when it should not? |
|
|
105
|
+
| `@behavior` | conduct once engaged | scenario | producer | Having engaged, does it take the right steps and honor its rules? |
|
|
106
|
+
| `@quality` | the result | scenario | producer | Is what it produced good? |
|
|
107
|
+
| `@rubric` | the assertion form | scenario | producer | Graded against an inline rubric (named dimensions + threshold) rather than a boolean `Then` — see *Form 2*. Independent of the tags above; a scenario may carry both. |
|
|
108
|
+
| `@pinned` | ownership | scenario | **user only** | A user-owned seed scenario the agent may propose against but never change unilaterally — see *`@pinned`*. |
|
|
109
|
+
| `@frozen` | lifecycle state | **file** | the gate | The suite is the agreed contract; narrowing it needs Clearance — see *The `@frozen` marker*. |
|
|
110
|
+
|
|
111
|
+
**`@trigger` vs `@behavior` is a per-node question, judged — never linted.** `@trigger` is legal
|
|
112
|
+
only *where the node genuinely owns the routing decision*, and two different deciders qualify:
|
|
113
|
+
|
|
114
|
+
- the **harness** — a model matching this config's `description` against a user query. Here the
|
|
115
|
+
decision is **co-owned** (description prose × harness × sibling set) and the node holds one of the
|
|
116
|
+
three, so freezing it on the node is the seam issue #304 raises.
|
|
117
|
+
- **an agent applying the node's own doctrine** — e.g. a coordinator reading this doctrine to decide
|
|
118
|
+
whether it governs the situation at hand. No harness is in the loop and the deciding input is the
|
|
119
|
+
node's own content, so **the node owns it outright**.
|
|
120
|
+
|
|
121
|
+
The two look alike in shape and differ only in who decides, so **step form does not classify them**
|
|
122
|
+
and no mechanical check should try (see `.agents/specs/sdd/ssa-lowering/ssa-lowering.feature`, where
|
|
123
|
+
a deletion that read the second case as the first was blocked at the gate and reverted). A
|
|
124
|
+
deterministic, fully-owned decision table that selects *what an already-invoked subject does* is
|
|
125
|
+
conduct, not engagement — it wants `@behavior`.
|
|
126
|
+
|
|
127
|
+
**`@frozen` is the only file-level tag** — it sits on the `Feature`, not a scenario.
|
|
128
|
+
|
|
129
|
+
`check-suite` ignores tags it does not recognize, so an unknown tag fails silently rather than
|
|
130
|
+
loudly — spell them exactly as written above.
|
|
131
|
+
|
|
132
|
+
## `@pinned` — user-owned seed scenarios
|
|
133
|
+
|
|
134
|
+
A **user** may mark a scenario `@pinned`. It is **user-owned** (`sdd:ownership-governance`) — the one
|
|
135
|
+
scenario class the agent does not own:
|
|
136
|
+
|
|
137
|
+
- **Agent proposes, user disposes.** The agent may propose changing or removing a `@pinned` scenario;
|
|
138
|
+
it may **not execute** the change without in-session user authorization — the authority of a human
|
|
139
|
+
ratification (positional, not relayable, not self-assertable within leash). Ownership is
|
|
140
|
+
lifecycle-independent: the pin holds in `draft` and survives a re-open; freeze does not enter.
|
|
141
|
+
- **Only the user pins.** The agent never applies `@pinned`.
|
|
142
|
+
- **A pin is a seed.** It marks a behavior the CFG did not reach; the agent **grows the
|
|
143
|
+
CFG around it** — proposing the sibling branches, guards, and companions the pinned behavior
|
|
144
|
+
implies (agent-owned; only the seed stays pinned).
|
|
145
|
+
- It is the **override to strict** — kept whatever strict would prune.
|
|
146
|
+
|
|
147
|
+
## One behavior per scenario — SRP and dedup
|
|
148
|
+
|
|
149
|
+
One (path class, edge) per scenario; one canonical scenario per pair. A scenario with several unrelated `Then`s
|
|
150
|
+
churns and its name lies — split it. Two scenarios sharing a `When`+`Then` core are a duplicate —
|
|
151
|
+
dedup to the canonical (never dedup away a `@pinned` scenario without consent).
|
|
152
|
+
|
|
153
|
+
## Form 1 — pure-boolean Gherkin (default)
|
|
154
|
+
|
|
155
|
+
`Given / When / Then` whose every `Then` is an **observable, deterministic boolean**. Use whenever the
|
|
156
|
+
branch is directly checkable.
|
|
157
|
+
|
|
158
|
+
**The test is the trace, not the verb.** A `Then` is legal when you can name the artifact a verifier
|
|
159
|
+
reads to settle it — an output, an exit code, a written file, an emitted event, a returned field.
|
|
160
|
+
Asserting an *act* is not the defect; asserting an act that records nothing is. Follow these:
|
|
161
|
+
|
|
162
|
+
- **Name the artifact before writing the `Then`. If nothing records it, do not assert it.**
|
|
163
|
+
- **Assert an act only when the act leaves a trace.** `Then it reads the role-to-agent map from the
|
|
164
|
+
registry` is legal — the resolved squad is checkable against the registry. `Then it sweeps the
|
|
165
|
+
corpus` is not: no artifact records a sweep.
|
|
166
|
+
- **When an act matters but records nothing, add the record — do not delete the act.** Give the role
|
|
167
|
+
an `Output` field, a written report, or a ledger line, then assert *that*.
|
|
168
|
+
- **Never assert how the artifact came to be authored** — "co-developed", "written test-first",
|
|
169
|
+
"authored in this order". Nothing in the artifact or a run reveals authoring sequence. Assert the
|
|
170
|
+
end state instead, and keep production discipline in governance prose.
|
|
171
|
+
- **Never assert internal state or a function name.** Neither is readable at the verification point.
|
|
172
|
+
|
|
173
|
+
## Form 2 — rubric Gherkin (`@rubric`, judged by hand)
|
|
174
|
+
|
|
175
|
+
For a branch whose correctness is a **gradient judgment** across dimensions no single boolean
|
|
176
|
+
captures. Structure: a rubric block with named dimensions, per-dimension `max`, exactly one
|
|
177
|
+
`threshold`, a collapsing `Then`, **no double-barreled dimension**. Selection (is a dimension
|
|
178
|
+
substitutable), threshold policy, and cSEM: load `references/rubric.md` before authoring or judging
|
|
179
|
+
one. Collapses to one boolean per scenario at the verification point, like every other scenario.
|
|
180
|
+
|
|
181
|
+
## A `Given` is a test vector, not specification
|
|
182
|
+
|
|
183
|
+
The implementation owes conformance to the `Then`, nothing to the `Given`'s apparatus. A `Given`
|
|
184
|
+
carries a **precondition** (the state the `Then` is asserted under — contract, the impl handles it)
|
|
185
|
+
and **apparatus** (domain, names, framing — a test vector, binds nothing). **Swap test:** substitute
|
|
186
|
+
the domain for an unrelated one; if the `Then` still holds, what was swapped is apparatus. **No
|
|
187
|
+
absorption** — no producer lifts a `Given`'s apparatus into the artifact as a worked example, and no
|
|
188
|
+
artifact illustration is lifted into a `Given`; each draws from a domain the other does not probe.
|
|
189
|
+
Judged semantically, not lexically.
|
|
190
|
+
|
|
191
|
+
### A `Given` must be a **scaffoldable state**
|
|
192
|
+
|
|
193
|
+
The `Given` is what the impl-producer **builds** and the impl-judge **checks it built**. If the two
|
|
194
|
+
can read it and picture different fixtures, the gate churns — the producer writes a defensive step
|
|
195
|
+
carrying flags and branches, and the judge disagrees about what was even set up. A step definition
|
|
196
|
+
that needs conditionals is the tell that the step is wrong **upstream**, not that the automation is
|
|
197
|
+
hard.
|
|
198
|
+
|
|
199
|
+
- **A state, not a procedure.** Declarative: *what holds*, never the keystrokes that got there.
|
|
200
|
+
- **Observable, not evaluative.** Bar judgment words — *discernible, valid, appropriate, clear,
|
|
201
|
+
proper, reasonable*. They read as precision and carry none: each reader supplies their own
|
|
202
|
+
threshold. Name the fact instead.
|
|
203
|
+
- **Present, not absent.** A state defined by what is *missing* ("no X and no Y") is unbuildable —
|
|
204
|
+
absence has infinitely many fixtures. Name the concrete shape that *has* the property.
|
|
205
|
+
- **One condition per step.** Split a conjunction into `Given` + `And`. Each step then stands alone
|
|
206
|
+
and is reusable across scenarios, which is what makes a step library accumulate instead of
|
|
207
|
+
fragment.
|
|
208
|
+
- **The build test:** *could two people, given only this line, construct the same fixture?* If no, it
|
|
209
|
+
is not yet a `Given`.
|
|
210
|
+
|
|
211
|
+
**Worked correction.** `Given a project with no discernible capability decomposition and no
|
|
212
|
+
feature-first source layout` fails three ways at once — *discernible* is evaluative, the state is
|
|
213
|
+
doubly absent, and it is a conjunction. It becomes:
|
|
214
|
+
|
|
215
|
+
```gherkin
|
|
216
|
+
Given a project in detection mode
|
|
217
|
+
And its src/ is organized by layer rather than by feature
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Two buildable steps, no judgment words, and the path class is named outright.
|
|
221
|
+
|
|
222
|
+
## Pairwise consistency — no two scenarios contradict on one snapshot
|
|
223
|
+
|
|
224
|
+
Within one suite, no two scenarios may demand **opposite verdicts** on a single constructible state.
|
|
225
|
+
A contradiction needs a shared `When` **and** an overlapping `Given`; different `When`s over one
|
|
226
|
+
state do not contradict. **Specialization is not contradiction** — a specific scenario whose narrower
|
|
227
|
+
`Given` carves an exception wins on it; read a pair as generic/specific before reading it as a
|
|
228
|
+
conflict. The remedy is a `Given` narrowing. Judged, not linted; the `Conflict` hard floor is the
|
|
229
|
+
post-freeze backstop.
|
|
230
|
+
|
|
231
|
+
## Optional conventions — scenario tagging and enumerated cases
|
|
232
|
+
|
|
233
|
+
Additive and plugin-facing (e.g. ACED); untagged plain suites are unaffected and the structural
|
|
234
|
+
check ignores unrecognized tags.
|
|
235
|
+
|
|
236
|
+
- **`@trigger`, `@behavior` and `@quality`** are defined in *The tag set* above. There is no
|
|
237
|
+
collective noun for them and none is wanted: they are three separate tags, not a stack or a
|
|
238
|
+
pipeline, and naming them as a group invites generalizations that do not hold. Apply `@trigger`
|
|
239
|
+
only where the node genuinely owns the routing decision, and read that section's two-deciders test
|
|
240
|
+
before choosing between `@trigger` and `@behavior` — the classification is judged per node, never
|
|
241
|
+
linted.
|
|
242
|
+
- **`Scenario Outline` is a rare exception, not a default** (DAMP over DRY) — legitimate only for a
|
|
243
|
+
genuinely uniform enumerated set (one varying token, every row the same `Then` shape). Two rows
|
|
244
|
+
wanting different `Then`s are two scenarios, not one Outline. Requires a non-empty `Examples:` table
|
|
245
|
+
covering every `<placeholder>`.
|
|
246
|
+
|
|
247
|
+
## The `@frozen` marker
|
|
248
|
+
|
|
249
|
+
Freeze is **per `.feature` file** (a feature-level `@frozen` tag; metadata, excluded from the
|
|
250
|
+
protected content). An **additive** scenario folds in and **self-clears**; a **pure move/rename**
|
|
251
|
+
(`git mv`, zero content delta) **preserves** the freeze; a **narrowing or rewrite** unfreezes and
|
|
252
|
+
fires **Clearance** at the gate. Vocabulary is **freeze / unfreeze**. The model and its risk trigger
|
|
253
|
+
are `sdd:lifecycle-governance`; the write constraint is `sdd:ownership-governance`.
|
|
254
|
+
|
|
255
|
+
## Scenario ordering (step-down)
|
|
256
|
+
|
|
257
|
+
Trace the workflow top-to-bottom: each use-case group in sequence; within a group, the happy path
|
|
258
|
+
first, then its branches and errors; a `@rubric` scenario sorts into its group like any other.
|
|
259
|
+
|
|
260
|
+
## The executable form — `check-suite`
|
|
261
|
+
|
|
262
|
+
The mechanical rules — Gherkin validity, every untagged `Then` a boolean, no leaked rubric lingo,
|
|
263
|
+
`Scenario Outline` Examples coverage, `# ── ── ` section comments, and **scenario-map binding** —
|
|
264
|
+
every scenario carries a map row, every row names a real scenario, and no two rows share an edge
|
|
265
|
+
*and* a path class. Whether the rows **cover the CFG** is judged, not linted: that needs the drawn
|
|
266
|
+
CFG's semantics, so a green check clears no coverage question. A spec with no `## Scenario map`
|
|
267
|
+
section is skipped, not failed — run as `check-suite`
|
|
268
|
+
(`spec-gate/scripts/check-suite.mts`): the spec-producer self-runs it before returning, and the spec
|
|
269
|
+
gate runs it fail-closed before the cold judge.
|
|
270
|
+
|
|
271
|
+
**Form only** — coverage adequacy, discrimination,
|
|
272
|
+
selection, pairwise consistency, and apparatus independence are **judged**, never linted, and a green
|
|
273
|
+
`check-suite` clears none of them.
|
|
274
|
+
|
|
275
|
+
## Key points (read-check)
|
|
276
|
+
|
|
277
|
+
The load-bearing directives below are the ones whose misreading is expensive — read them as the
|
|
278
|
+
compressed form of this bar, not as a summary that replaces it:
|
|
279
|
+
|
|
280
|
+
1. **Acceptance only, strict** — a suite specifies the decisions the node owns; invariants and
|
|
281
|
+
co-owned seams are out of scope.
|
|
282
|
+
2. **The suite is the CFG** — one scenario per **(path class, edge)** pair, cover every
|
|
283
|
+
branch, collapse reconverged paths whose outcome does not differ, and pair every guard/negative
|
|
284
|
+
edge with a positive companion on the same path (a lone negative is inert).
|
|
285
|
+
3. **Each edge isolates a specific condition** — the `Given` hands over no part of the verdict, and a
|
|
286
|
+
scenario asserting a finding asserts its binding consequence, not just its emission.
|
|
287
|
+
4. **A dead edge measures nothing** — run the miss test (a plausible wrong subject takes the wrong
|
|
288
|
+
branch); a measured ceiling is a tell it cannot be lost, not evidence.
|
|
289
|
+
5. **The scenario map is 1:1 scenario<->row**, each row naming both the **edge** and the **path
|
|
290
|
+
class**; an edge may carry several rows (permutation coverage) — a duplicate is same edge *and*
|
|
291
|
+
same path. Sections mirror the spec's use-case groups.
|
|
292
|
+
6. **`@pinned` is user-owned** — the agent proposes but never executes a change or removal without
|
|
293
|
+
user authorization; only the user pins; a pin seeds CFG growth.
|
|
294
|
+
7. **A `Given` is a test vector** — the precondition binds, the apparatus binds nothing (swap test);
|
|
295
|
+
no absorption.
|
|
296
|
+
8. **A `Then` is legal when you can name the artifact that settles it** — the test is the **trace,
|
|
297
|
+
not the verb**. Asserting an *act* is fine when the act leaves a trace; where it records nothing,
|
|
298
|
+
**add the record and assert that**, rather than dropping the act. Never assert how the artifact
|
|
299
|
+
was authored, nor internal state.
|