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.
Files changed (133) hide show
  1. package/.claude-plugin/plugin.json +17 -0
  2. package/.codex-plugin/plugin.json +17 -0
  3. package/.plugin/plugin.json +17 -0
  4. package/README.md +159 -0
  5. package/agents/sdd-automaton.md +97 -0
  6. package/agents/sdd-impl-judge.md +214 -0
  7. package/agents/sdd-scanner.md +120 -0
  8. package/agents/sdd-spec-judge.md +224 -0
  9. package/agents/sdd-warden.md +101 -0
  10. package/package.json +24 -0
  11. package/skills/align-spec/README.md +20 -0
  12. package/skills/align-spec/SKILL.md +111 -0
  13. package/skills/align-spec/scripts/align-spec.mts +187 -0
  14. package/skills/architect-impl-governance/README.md +46 -0
  15. package/skills/architect-impl-governance/SKILL.md +45 -0
  16. package/skills/architect-spec-governance/README.md +48 -0
  17. package/skills/architect-spec-governance/SKILL.md +59 -0
  18. package/skills/blast-estimate/README.md +47 -0
  19. package/skills/blast-estimate/SKILL.md +133 -0
  20. package/skills/blast-estimate/scripts/blast-estimate.mts +583 -0
  21. package/skills/builder-impl-governance/README.md +47 -0
  22. package/skills/builder-impl-governance/SKILL.md +47 -0
  23. package/skills/builder-spec-governance/README.md +49 -0
  24. package/skills/builder-spec-governance/SKILL.md +36 -0
  25. package/skills/check-partition-quality/README.md +22 -0
  26. package/skills/check-partition-quality/SKILL.md +51 -0
  27. package/skills/check-partition-quality/scripts/check-partition-quality.mts +336 -0
  28. package/skills/check-plan-safety/README.md +17 -0
  29. package/skills/check-plan-safety/SKILL.md +60 -0
  30. package/skills/check-plan-safety/scripts/check-plan-safety.mts +145 -0
  31. package/skills/check-project-specs/README.md +19 -0
  32. package/skills/check-project-specs/SKILL.md +69 -0
  33. package/skills/check-project-specs/scripts/check-project-specs.mts +217 -0
  34. package/skills/check-scenario-overlap/README.md +19 -0
  35. package/skills/check-scenario-overlap/SKILL.md +74 -0
  36. package/skills/check-scenario-overlap/scripts/check-scenario-overlap.mts +249 -0
  37. package/skills/check-spec-structure/README.md +17 -0
  38. package/skills/check-spec-structure/SKILL.md +66 -0
  39. package/skills/check-spec-structure/scripts/check-spec-structure.mts +346 -0
  40. package/skills/collision-ladder/README.md +18 -0
  41. package/skills/collision-ladder/SKILL.md +83 -0
  42. package/skills/collision-ladder/scripts/collision-ladder.mts +657 -0
  43. package/skills/combat-log-governance/README.md +13 -0
  44. package/skills/combat-log-governance/SKILL.md +257 -0
  45. package/skills/concept-index/README.md +13 -0
  46. package/skills/concept-index/SKILL.md +38 -0
  47. package/skills/concept-index/scripts/concept-index.mts +245 -0
  48. package/skills/discover-plans/README.md +16 -0
  49. package/skills/discover-plans/SKILL.md +74 -0
  50. package/skills/discover-plans/scripts/discover-plans.mts +212 -0
  51. package/skills/discover-specs/README.md +15 -0
  52. package/skills/discover-specs/SKILL.md +76 -0
  53. package/skills/discover-specs/scripts/discover-specs.mts +396 -0
  54. package/skills/doctrine-loop/README.md +15 -0
  55. package/skills/doctrine-loop/SKILL.md +97 -0
  56. package/skills/formation-loop/README.md +17 -0
  57. package/skills/formation-loop/SKILL.md +140 -0
  58. package/skills/gate-validation-governance/README.md +12 -0
  59. package/skills/gate-validation-governance/SKILL.md +87 -0
  60. package/skills/impl-producer-governance/README.md +48 -0
  61. package/skills/impl-producer-governance/SKILL.md +85 -0
  62. package/skills/init/README.md +27 -0
  63. package/skills/init/SKILL.md +68 -0
  64. package/skills/init/scripts/wire-statusline.mts +276 -0
  65. package/skills/lifecycle-governance/README.md +11 -0
  66. package/skills/lifecycle-governance/SKILL.md +168 -0
  67. package/skills/manage/README.md +9 -0
  68. package/skills/manage/SKILL.md +62 -0
  69. package/skills/manage-ignore/README.md +19 -0
  70. package/skills/manage-ignore/SKILL.md +52 -0
  71. package/skills/manage-ignore/scripts/manage-ignore.mts +294 -0
  72. package/skills/manage-scenario-bridge/README.md +20 -0
  73. package/skills/manage-scenario-bridge/SKILL.md +60 -0
  74. package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.mts +156 -0
  75. package/skills/manage-spec-anchors/README.md +18 -0
  76. package/skills/manage-spec-anchors/SKILL.md +56 -0
  77. package/skills/manage-spec-anchors/scripts/manage-spec-anchors.mts +328 -0
  78. package/skills/mission-graph/README.md +15 -0
  79. package/skills/mission-graph/SKILL.md +67 -0
  80. package/skills/mission-graph/scripts/mission-graph.mts +844 -0
  81. package/skills/oracle-spec-governance/README.md +45 -0
  82. package/skills/oracle-spec-governance/SKILL.md +45 -0
  83. package/skills/ownership-governance/README.md +65 -0
  84. package/skills/ownership-governance/SKILL.md +104 -0
  85. package/skills/pause-mission/README.md +18 -0
  86. package/skills/pause-mission/SKILL.md +112 -0
  87. package/skills/place-node/README.md +12 -0
  88. package/skills/place-node/SKILL.md +47 -0
  89. package/skills/place-node/scripts/place-node.mts +157 -0
  90. package/skills/plan-retirement/README.md +32 -0
  91. package/skills/plan-retirement/SKILL.md +90 -0
  92. package/skills/plan-retirement/scripts/retire-plans.mts +196 -0
  93. package/skills/plugin-contract-governance/README.md +12 -0
  94. package/skills/plugin-contract-governance/SKILL.md +112 -0
  95. package/skills/remediation-governance/README.md +46 -0
  96. package/skills/remediation-governance/SKILL.md +78 -0
  97. package/skills/resolve-governances/README.md +18 -0
  98. package/skills/resolve-governances/SKILL.md +50 -0
  99. package/skills/resolve-governances/scripts/resolve-governances.mts +515 -0
  100. package/skills/resolve-tracking/SKILL.md +64 -0
  101. package/skills/resolve-tracking/scripts/resolve-tracking.mts +213 -0
  102. package/skills/resume-mission/README.md +12 -0
  103. package/skills/resume-mission/SKILL.md +53 -0
  104. package/skills/scaffold-project-spec/README.md +7 -0
  105. package/skills/scaffold-project-spec/SKILL.md +192 -0
  106. package/skills/sdd/README.md +7 -0
  107. package/skills/sdd/SKILL.md +92 -0
  108. package/skills/solution-producer-governance/README.md +9 -0
  109. package/skills/solution-producer-governance/SKILL.md +44 -0
  110. package/skills/spec-format-governance/README.md +73 -0
  111. package/skills/spec-format-governance/SKILL.md +114 -0
  112. package/skills/spec-gate/README.md +26 -0
  113. package/skills/spec-gate/SKILL.md +201 -0
  114. package/skills/spec-gate/scripts/check-spec-state.mts +601 -0
  115. package/skills/spec-gate/scripts/check-suite.mts +501 -0
  116. package/skills/spec-gate/scripts/classify-edit-class.mts +411 -0
  117. package/skills/spec-producer-governance/README.md +7 -0
  118. package/skills/spec-producer-governance/SKILL.md +86 -0
  119. package/skills/spec-structure-governance/README.md +40 -0
  120. package/skills/spec-structure-governance/SKILL.md +169 -0
  121. package/skills/ssa-lowering/README.md +26 -0
  122. package/skills/ssa-lowering/SKILL.md +181 -0
  123. package/skills/start-mission/README.md +7 -0
  124. package/skills/start-mission/SKILL.md +115 -0
  125. package/skills/suite-format-governance/README.md +75 -0
  126. package/skills/suite-format-governance/SKILL.md +299 -0
  127. package/skills/suite-format-governance/references/rubric.md +313 -0
  128. package/skills/touch-set-correction/README.md +16 -0
  129. package/skills/touch-set-correction/SKILL.md +67 -0
  130. package/skills/touch-set-correction/scripts/touch-set-correction.mts +418 -0
  131. package/skills/verify-scenarios/README.md +17 -0
  132. package/skills/verify-scenarios/SKILL.md +109 -0
  133. package/skills/verify-scenarios/scripts/verify-scenarios.mts +386 -0
@@ -0,0 +1,213 @@
1
+ // resolve-tracking — resolve one artifact's tracking signal (tracked | ignored).
2
+ // Self-contained, no deps (repo's node-≥23.6 convention). Spec:
3
+ // .agents/specs/sdd/intake/resolve-tracking/README.md
4
+
5
+ import { existsSync, readFileSync } from 'node:fs'
6
+ import { join } from 'node:path'
7
+
8
+ export type Tracking = 'tracked' | 'ignored'
9
+
10
+ // ─── .sddignore (.agents/sdd/.sddignore) — the universal override valve ───────────────
11
+ //
12
+ // gitignore syntax. Each non-blank, non-comment line is a pattern. A leading `!` marks the
13
+ // path tracked (re-include); any other pattern marks it ignored. Matching is
14
+ // last-match-wins: the LAST rule whose pattern matches the path decides.
15
+
16
+ export interface IgnoreRule {
17
+ negated: boolean // leading `!` — re-includes (tracked)
18
+ regex: RegExp
19
+ source: string // the original pattern text (for notes)
20
+ }
21
+
22
+ // Compile the pattern body (no ! / trailing slash) to a regex fragment:
23
+ // ** spans path separators, * and ? stay within a segment.
24
+ function globToRegExpBody(glob: string): string {
25
+ return glob
26
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&') // escape regex specials (leave * ?)
27
+ .replace(/\*+/g, (m) => (m.length > 1 ? '.*' : '[^/]*')) // ** spans separators, * does not
28
+ .replace(/\?/g, '[^/]')
29
+ }
30
+
31
+ // Parse one raw line into a rule. Returns:
32
+ // - a rule for a well-formed pattern
33
+ // - 'skip' for a blank line or a comment (nothing loaded)
34
+ // - null for a malformed line (an empty pattern after stripping ! and trailing /)
35
+ export function parseIgnoreLine(raw: string): IgnoreRule | 'skip' | null {
36
+ const line = raw.replace(/\r$/, '')
37
+ const trimmed = line.trim()
38
+ if (!trimmed || trimmed.startsWith('#')) return 'skip'
39
+
40
+ let body = trimmed
41
+ const negated = body.startsWith('!')
42
+ if (negated) body = body.slice(1)
43
+ const dirOnly = body.endsWith('/')
44
+ if (dirOnly) body = body.slice(0, -1)
45
+
46
+ let anchored = false
47
+ if (body.startsWith('/')) {
48
+ anchored = true
49
+ body = body.slice(1)
50
+ } else if (body.includes('/')) {
51
+ anchored = true
52
+ }
53
+
54
+ if (body === '') return null // nothing to match — malformed
55
+
56
+ // A leading `**/` matches at any depth; otherwise anchored patterns pin to root and
57
+ // unanchored patterns (no interior slash) match the name at any level. A trailing
58
+ // component (or dir-only pattern) also matches everything under it, mirroring git's
59
+ // "ignore a directory ⇒ ignore its contents".
60
+ const prefix = anchored ? '^' : '^(?:.*/)?'
61
+ const core = globToRegExpBody(body)
62
+ const suffix = '(?:/.*)?$'
63
+ try {
64
+ return { negated, regex: new RegExp(prefix + core + suffix), source: trimmed }
65
+ } catch {
66
+ return null // uncompilable — malformed
67
+ }
68
+ }
69
+
70
+ export function parseIgnoreFile(text: string): IgnoreRule[] {
71
+ const out: IgnoreRule[] = []
72
+ for (const raw of text.split('\n')) {
73
+ const rule = parseIgnoreLine(raw)
74
+ if (rule && rule !== 'skip') out.push(rule)
75
+ }
76
+ return out
77
+ }
78
+
79
+ // A missing file is legal — most projects need no overrides.
80
+ export function loadIgnoreRules(root: string): IgnoreRule[] {
81
+ const path = join(root, '.agents', 'sdd', '.sddignore')
82
+ if (!existsSync(path)) return []
83
+ return parseIgnoreFile(readFileSync(path, 'utf8'))
84
+ }
85
+
86
+ // Last-match-wins: iterate rules in file order; the LAST rule that matches decides.
87
+ // `!` => tracked, else => ignored. No match => null (fall through).
88
+ export function resolveFromIgnore(rules: IgnoreRule[], path: string): Tracking | null {
89
+ let value: Tracking | null = null
90
+ for (const rule of rules) {
91
+ if (rule.regex.test(path)) value = rule.negated ? 'tracked' : 'ignored'
92
+ }
93
+ return value
94
+ }
95
+
96
+ // ─── kind default — the fixed agent-config location convention ───────────────────────
97
+ //
98
+ // Only skill / subagent / command carry a location-varying convention. Project-private
99
+ // paths (`.agents/{skills,agents,commands}/**`) => ignored; project-public / shipped paths
100
+ // (`skills/**`, `plugins/*/skills/**`, `packages/*/skills/**`, and the agents/commands
101
+ // equivalents) => tracked. agents-section has one AGENTS.md (no location convention); code
102
+ // artifact-types have no universal convention — both fall through with no kind default.
103
+ const KIND_DEFAULT_GLOBS: Record<string, { ignored: string[]; tracked: string[] }> = {
104
+ skill: {
105
+ ignored: ['.agents/skills/**'],
106
+ tracked: ['skills/**', 'plugins/*/skills/**', 'packages/*/skills/**'],
107
+ },
108
+ subagent: {
109
+ ignored: ['.agents/agents/**'],
110
+ tracked: ['plugins/*/agents/**', 'packages/*/agents/**'],
111
+ },
112
+ command: {
113
+ ignored: ['.agents/commands/**'],
114
+ tracked: ['plugins/*/commands/**', 'packages/*/commands/**'],
115
+ },
116
+ }
117
+
118
+ function globMatch(glob: string, path: string): boolean {
119
+ return new RegExp(`^${globToRegExpBody(glob)}$`).test(path)
120
+ }
121
+
122
+ export function resolveKindDefault(artifactType: string | undefined, path: string): Tracking | null {
123
+ if (!artifactType) return null
124
+ const kind = KIND_DEFAULT_GLOBS[artifactType]
125
+ if (!kind) return null
126
+ if (kind.ignored.some((g) => globMatch(g, path))) return 'ignored'
127
+ if (kind.tracked.some((g) => globMatch(g, path))) return 'tracked'
128
+ return null
129
+ }
130
+
131
+ // ─── the four-step resolution ─────────────────────────────────────────────────────────
132
+
133
+ export interface ResolveInput {
134
+ root: string
135
+ path: string
136
+ artifactType?: string
137
+ explicit?: Tracking
138
+ }
139
+
140
+ export interface ResolveResult {
141
+ value: Tracking
142
+ reason: string
143
+ }
144
+
145
+ export function resolveTracking(input: ResolveInput): ResolveResult {
146
+ if (input.explicit) {
147
+ return { value: input.explicit, reason: 'explicit override' }
148
+ }
149
+ const rules = loadIgnoreRules(input.root)
150
+ const ignoreMatch = resolveFromIgnore(rules, input.path)
151
+ if (ignoreMatch) {
152
+ return { value: ignoreMatch, reason: '.sddignore' }
153
+ }
154
+ const kindDefault = resolveKindDefault(input.artifactType, input.path)
155
+ if (kindDefault) {
156
+ return { value: kindDefault, reason: `kind-default (${input.artifactType})` }
157
+ }
158
+ return { value: 'tracked', reason: 'fail-closed (no signal)' }
159
+ }
160
+
161
+ // ─── validate the ignore file (no --path given) ───────────────────────────────────────
162
+
163
+ export function validateIgnoreFile(root: string): { ok: boolean; message: string } {
164
+ const path = join(root, '.agents', 'sdd', '.sddignore')
165
+ if (!existsSync(path)) return { ok: true, message: '.sddignore OK (absent, fine)' }
166
+ const text = readFileSync(path, 'utf8')
167
+ const notes: string[] = []
168
+ const lines = text.split('\n')
169
+ lines.forEach((raw, i) => {
170
+ if (parseIgnoreLine(raw) === null) {
171
+ notes.push(`line ${i + 1}: not a valid gitignore pattern: ${raw.trim()}`)
172
+ }
173
+ })
174
+ if (notes.length > 0) {
175
+ return { ok: false, message: notes.join('\n') }
176
+ }
177
+ const loaded = parseIgnoreFile(text).length
178
+ return { ok: true, message: `.sddignore OK (${loaded} rule(s))` }
179
+ }
180
+
181
+ // ─── CLI ────────────────────────────────────────────────────────────────────────────
182
+
183
+ function parseArgs(argv: string[]) {
184
+ const out: Record<string, string> = {}
185
+ for (let i = 0; i < argv.length; i++) {
186
+ if (argv[i].startsWith('--')) {
187
+ out[argv[i].slice(2)] = argv[i + 1]
188
+ i++
189
+ }
190
+ }
191
+ return out
192
+ }
193
+
194
+ export function main(argv: string[]): void {
195
+ const args = parseArgs(argv)
196
+ const root = args.root ?? '.'
197
+
198
+ if (!args.path) {
199
+ const result = validateIgnoreFile(root)
200
+ process.stdout.write(`${result.message}\n`)
201
+ if (!result.ok) process.exitCode = 1
202
+ return
203
+ }
204
+
205
+ const explicit = args.explicit === 'tracked' || args.explicit === 'ignored' ? args.explicit : undefined
206
+ const result = resolveTracking({ root, path: args.path, artifactType: args['artifact-type'], explicit })
207
+ process.stdout.write(`${result.value}\n`)
208
+ process.stdout.write(`reason: ${result.reason}\n`)
209
+ }
210
+
211
+ if (process.argv[1] && import.meta.url === `file://${process.argv[1]}`) {
212
+ main(process.argv.slice(2))
213
+ }
@@ -0,0 +1,12 @@
1
+ # resume-mission
2
+
3
+ Project-private workflow skill for **resuming an in-progress SDD mission from its plan brief**
4
+ (`.agents/plans/<cr-ref>.plan.md`). Invoke it at the start of a new session ("load the plan",
5
+ "resume the mission", "continue github-NN") to re-establish the working method and spec context,
6
+ find the next todo, and continue without relitigating settled decisions.
7
+
8
+ The plan is the **state** (mission-specific todos, decisions, findings); this skill is one
9
+ convenient **procedure** for picking any plan up — any session that reads the plan can continue
10
+ without it. If no plan exists yet, it scaffolds one from a basic template. `internal: true` —
11
+ contributor tooling for this repo, not a shipped SDD capability. If "mission resume" should become an SDD-delivered
12
+ capability, spec it in `mission/` first and build the impl in the SDD plugin.
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: resume-mission
3
+ description: "Resume an in-progress SDD mission from its plan brief. Use when asked to 'load the plan', 'resume the mission', 'continue github-NN', or otherwise pick up an SDD .plan.md where it left off — re-establish the working method and spec context, find the next todo, and continue without relitigating settled ground."
4
+ ---
5
+
6
+ # Resume an SDD mission from its plan
7
+
8
+ An SDD mission is carried by a single tracked **plan brief** at
9
+ `.agents/plans/<cr-ref>.plan.md` (the portable handoff artifact). The plan is the **state**;
10
+ this skill is one convenient **procedure** for picking it up — any session that reads the plan
11
+ can continue without it. It re-establishes context from the brief and continues the Mission Loop
12
+ where it left off.
13
+
14
+ ## Procedure
15
+
16
+ 1. **Open the plan — create it if missing.** Open `.agents/plans/<cr-ref>.plan.md` and read it in
17
+ full: the frontmatter `todos` (the ordered task list; `status: pending | in_progress |
18
+ completed`) and the body (working method, resolved decisions, findings, `## NEXT`). **If no
19
+ plan exists** (the mission was never intook), scaffold a minimal one from a basic template
20
+ (frontmatter `todos` + a `## NEXT` anchor) and start the mission from there.
21
+
22
+ 2. **Find the next action.** Resume the single `in_progress` todo if one exists; otherwise the
23
+ first `pending` todo whose prerequisites are met. The body's `## NEXT` section names the
24
+ live frontier and any blocking decisions — honor it over guessing.
25
+
26
+ 3. **Reload the working method — do not relearn or relitigate it.** The plan records *how this
27
+ mission is run* (its phase model, per-step rhythm, suite/impl conventions, which plugin or
28
+ spec dirs are baseline vs fresh). Treat resolved decisions (the `## Resolved decisions`
29
+ block) as settled; reopen one only on new evidence, and say so.
30
+
31
+ 4. **Load only the spec context the next todo needs.** For a capability sub-mission, read that
32
+ capability's `README.md` under `.agents/specs/<project>/<cap>/` plus the SDD design rules and
33
+ governances it references — not the whole tree.
34
+
35
+ 5. **Continue, committing per unit.** Work in the plan's stated rhythm; commit each coherent
36
+ unit (Conventional Commits, one concern, tests green). Update the todo `status` and record
37
+ any new finding or decision **back into the plan** as you go, so the next resume is clean.
38
+
39
+ 6. **Surface blocking decisions; never guess past them.** If `## NEXT` names an open decision
40
+ (a scope call, an unresolved `<!-- open: -->` marker), raise it before proceeding past it.
41
+
42
+ ## Guardrails (carried across sessions)
43
+
44
+ - **Reason to the correct answer, not a vote.** On a contradiction, reason from the design's
45
+ *intent*; corroboration, implementation, and recency are evidence to weigh, not ballots to
46
+ tally. Fix the side that is wrong.
47
+ - **Spec the behavior, then build.** A skill or governance is a testable capability — spec it
48
+ (prose + a per-unit `.feature`) before or alongside building its implementation; never
49
+ hand-edit an implementation as a shortcut around its spec.
50
+ - **Respect the baseline.** Build fresh where the plan says fresh; never mutate a directory the
51
+ plan marks as the untouched reference baseline.
52
+ - **Commit boundary.** The unit of work is one co-committable change (clear message, green
53
+ tests) — not the whole CR. A CR's mission lands as many commits.
@@ -0,0 +1,7 @@
1
+ # scaffold-project-spec
2
+
3
+ Non-user-invocable SDD skill holding the **project-level layout bootstrap**: when a project has **no spec yet**, choose how the spec is organized, scaffold that skeleton, and declare the choice. It serves an **existing** project and a **greenfield** one through one entry, branching on **evidence mode**.
4
+
5
+ Loaded via the harness (`Skill`) by the **conductor** (the main session) **once at bootstrap** when `start-mission` explore finds a project lacking a spec. It is **not** a user entry — the single entry is `start-mission`; this is an internal explore-phase step. It runs a seven-step procedure — pick the evidence mode (is there source to read?) → establish the project shape (read the source, or ask what the project will do) → choose the spec location (colocated / hoisted / monorepo-member) → recommend + choose a strategy (capability-first default, mirror-source) → scaffold the shared envelope + the strategy skeleton (each node declaring a legal `spec-type`) → declare the `project-path` frontmatter + the body placement map → hand back to per-unit explore — and leaves the tree at `status: draft`.
6
+
7
+ The skill is self-contained — it bakes in the whole layout model: the node taxonomy (three spec-types, the concept axis, the two-level depth cap, screaming-architecture default), the strategy menu + the shared envelope + the per-strategy SDD-fit, and the spec-location rules (the hoist-out-of-the-distributable rule). It also bakes in the boundary-aligned mirror-depth rule, the spec-type classifier, the reserved by-concept index block (filled by the `concept-index` skill, not by hand), ADR-as-facet (a `design/decisions/` log, never an ADR-organized body), and the output boundary — it authors no node's `## Use Cases`/`.feature`, renders no gate verdict, and writes no control frontmatter (those are `spec-gate`'s and the conductor's). Proposes node placement for the formation Warden to confirm.
@@ -0,0 +1,192 @@
1
+ ---
2
+ name: scaffold-project-spec
3
+ description: "Partial Skill: invoke by name only — lay out an SDD project-spec"
4
+ user-invocable: false
5
+ ---
6
+
7
+ # scaffold-project-spec — lay out a project's spec
8
+
9
+ The procedure the **conductor** follows, **once at bootstrap**, when `start-mission` explore finds a project
10
+ with **no spec yet**. It chooses *how the spec is organized*, scaffolds that skeleton, and
11
+ **declares the choice**, so the per-unit explore that follows (`spec-producer-governance`) slots work into known
12
+ homes. It is **internal** — reached through `start-mission`, never a user entry — and leaves the tree at
13
+ `status: draft`; it authors no node's `## Use Cases`/`.feature`, renders no gate verdict, and freezes nothing.
14
+
15
+ **Load `sdd:spec-structure-governance`** for the layout law it applies: the node taxonomy (three
16
+ spec-types, the concept axis), the two-level depth cap, screaming architecture and the
17
+ non-capability folders, root-files-not-folders, and the colocate-or-hoist test. This skill does not
18
+ restate that law — it **runs** it, and owns only what is genuinely its own: the **strategy menu**,
19
+ the **shared envelope**, and the seven-step procedure below.
20
+
21
+ Run the seven steps in order, surfacing each choice to the user (recommended-first), never assuming
22
+ silently.
23
+
24
+ ## 0 — Pick the evidence mode
25
+
26
+ **Detected, not chosen.** Ask one question of the tree, not of the user: **does this project have source to
27
+ read?** Scope it to the **project**, never the repo — a new package inside an existing monorepo is a
28
+ greenfield *project* in a populated *repo*.
29
+
30
+ - **detection mode** — the project's source exists. Steps 1-3 read it.
31
+ - **intent mode** — the project's source does not exist yet. Steps 1-3 have nothing to read for it, so they
32
+ run off what the user states the project *will* be.
33
+
34
+ **The repo around an intent-mode project is still readable**, and reading it is not a mode switch: an
35
+ existing monorepo's shape, conventions, and sibling packages inform the recommendation even when the
36
+ project itself is empty. Intent mode means *this project* has no source — not that the disk is blank.
37
+
38
+ Steps 4-6 are identical under both modes. Never run detection's signal-reading against an empty project and
39
+ never let intent mode fall through to a silent default.
40
+
41
+ ## 1 — Establish the project shape
42
+
43
+ **Detection mode** — read signals, do not guess: an **agentic plugin** (`.plugin/` + `skills/` + `agents/`);
44
+ a **monorepo** (`apps/`+`packages/`, or multiple package anchors each with their own manifest); whether
45
+ `src/` is **feature-** or **layer-organized**; framework markers; owners (`CODEOWNERS`); size.
46
+
47
+ **Intent mode** — the project has no signals of its own. Establish by asking (reading the surrounding repo
48
+ where it helps) the three things detection would otherwise have read:
49
+
50
+ 1. **What kind of project** — a repo harness, an agent plugin, an npm package, a website, an app
51
+ (`project-unit.md`). This is what the plugin/monorepo/plain classification stood for.
52
+ 2. **Where it will live** — the repo-relative dir its source will occupy. This is the **`project-path`** step
53
+ 5 must write, and in a greenfield project that directory does not exist yet, so it can only be asked.
54
+ Confirm it rather than inventing a path.
55
+ 3. **What it will do** — the intended capabilities, which step 3 recommends a strategy from.
56
+
57
+ (2) gives the `project-path`; (1) decides the **location**, per step 2 — nesting does not.
58
+
59
+ ## 2 — Choose the spec location
60
+
61
+ Recommend, let the user override, never assume:
62
+
63
+ **Colocate by default.** Hoist only when the spec **cannot be kept out of what ships** — nesting alone is
64
+ never the reason.
65
+
66
+ - **`<project>/.agents/spec/`** (colocated).
67
+ An npm package colocates fine: `files` / `.npmignore` excludes `.agents/` from the tarball.
68
+ - **`<repo>/.agents/specs/<name>/`** (hoisted — named by the package). Only when the project dir is
69
+ distributed **wholesale**, with no include/exclude mechanism to leave the spec behind. The one identified
70
+ case is an **agentic plugin**: plugin install distributes the whole plugin directory, so a colocated spec
71
+ would ship to every consumer. If a new packaging format has the same all-or-nothing distribution, it joins
72
+ this case; otherwise colocate.
73
+ - **monorepo** — offer to lay out **every package** (each hoisted to `<repo>/.agents/specs/<name>/`) plus the
74
+ outer project (`<repo>/.agents/spec/`). Run steps 1–6 **per selected project**, producing several draft
75
+ trees (the evidence mode is picked once, in step 0, for the whole run).
76
+
77
+ In **intent mode** apply the same test to the **kind of project** established in step 1: an agentic plugin
78
+ hoists, everything else colocates at the `project-path` given. Confirm with the user; never re-ask location
79
+ as an independent choice, and never hoist merely because the path is nested.
80
+
81
+ ## 3 — Recommend + choose the strategy
82
+
83
+ Present **one recommendation + its rationale + the alternative**; the user chooses. Shipped menu:
84
+
85
+ - **capability-first** *(default)* — top-level folders by what the project *does*. Recommend when a capability
86
+ decomposition is discernible. For a fixed-layout plugin this is a spec-side abstraction over fixed source —
87
+ accepted for legibility; name the spec↔source divergence as a known cost.
88
+ - **mirror-source** — spec nodes track the source tree. Offer whenever the team **navigates by code**;
89
+ a **feature-first** `src/` is the best case, not a precondition. Over a **layered** source, still
90
+ offer it — but name the cost: the folder partition is coarse, so the scheduler sees more collisions
91
+ and the schedule is slower (never wrong — an unresolved collision serializes, `sdd:spec-structure-governance`).
92
+ Say what recovers it (the collision ladder resolves most shared-node pairs at the file or symbol
93
+ rung) and what the exit looks like (concept tags accumulate; hoist a capability when the
94
+ false-conflict rate earns it). Mirror is **boundary-aligned** (step 4). **Detection mode only** —
95
+ there is no source tree to mirror in intent mode.
96
+
97
+ **Offer to measure, rather than argue.** In **detection mode** on a repo with real history, offer to
98
+ run `sdd:check-partition-quality` before the choice is made: it reports, from this project's own
99
+ commits, how much parallel work each candidate layout would permit. Opt-in — it reads `git log`, so
100
+ it is slow on a large repo and says nothing useful on a young one, and it renders no verdict. When it
101
+ runs, present its parallelizable shares alongside the recommendation so the user chooses on their own
102
+ numbers rather than on doctrine. Skip it silently in intent mode: a greenfield project has no history
103
+ to measure.
104
+
105
+ **Do not require a restructuring before the first spec.** An existing project adopting SDD keeps the
106
+ shape it has; capability-first is the destination, reached on evidence, not an entry toll. Recommend
107
+ capability-first, accept mirror-source with its cost stated, and let the data drive the migration.
108
+
109
+ In **intent mode**, recommend from the capabilities the user stated in step 1. If they have not stated any,
110
+ **ask for them** — never apply the capability-first default silently. (Detection mode's no-signal fallback
111
+ *is* the capability-first default; intent mode has no equivalent, because a greenfield project always has an
112
+ intent to state.)
113
+
114
+ Never offer **layering** or **arc42 sections** as the *top* level — they nest *inside* a capability. **ADR is
115
+ not a strategy** — it is the decisions facet (step 4). The deferred strategies (bounded-context, layered,
116
+ doc-envelope) are off the shipped menu; surface them only on an explicit "show more options".
117
+
118
+ ## 4 — Scaffold the envelope + skeleton
119
+
120
+ Write the **shared envelope** every strategy ships:
121
+
122
+ - root **`spec.md`** (the index + the `project-path` frontmatter + the placement map + the reserved by-concept
123
+ index block — step 5);
124
+ - **`design/`** — the rules/model home, **including `design/decisions/`** (the ADR log: append-only,
125
+ descriptive, ungated — the project-scope sibling of a unit's `<unit>.solution.md`; *organize no node as an
126
+ ADR body*);
127
+ - **`workflows/`** — the workflows suite home (cross-capability usage flows);
128
+ - a **tooling/project** home (build, CI, packaging, deps);
129
+ - **`glossary.md`** — a root file beside `spec.md` (never a folder): the project's ubiquitous
130
+ language, every load-bearing term defined once in plain words. Seed it with the terms the scaffold
131
+ already commits to; per-unit explore adds the rest.
132
+
133
+ Then the chosen strategy's **top-level skeleton** of **stub node READMEs**, each declaring a legal
134
+ **`spec-type`** via the classifier:
135
+
136
+ - a **testable surface** → `behavioral` (`## Use Cases`; its `.feature` is authored later, in explore);
137
+ - a **shipped suite-less artifact** (a governance, a config) → `reference` (`## Subject`, no
138
+ `.feature`);
139
+ - an **index / rule / structural grouping** → **descriptive** (no marker).
140
+
141
+ The skeleton obeys the **two-level depth cap** under **every** strategy: a node is
142
+ `<capability>/<unit>` and **never three deep** — a sub-grouping inside a capability is a `concept:` tag
143
+ recovered by the by-concept index, not a third folder level. Under **mirror-source**, mirror **only to the
144
+ unit boundary**: a folder with a testable surface becomes one behavioral leaf that owns its subtree; create
145
+ **no node below a behavioral leaf** (nested `src/` there is impl detail). A capability node README carries
146
+ **only** its `spec-type` marker — never a lifecycle field; its cross-cutting **`concept:`** tag is assigned
147
+ later in per-unit explore (via the `place-node` skill), not at scaffold.
148
+
149
+ ## 5 — Declare the organization (do not leave it to be re-derived)
150
+
151
+ In the same act that writes root `spec.md`, record both so a later edit reads, never re-scans:
152
+
153
+ - **`project-path` frontmatter** — the repo-relative source dir this spec governs (the package for a
154
+ hoisted spec; the project root for a colocated one). It is the router's source→spec map; the spec
155
+ **location mode** (`colocated | hoisted | monorepo-member`) is *derived* from it, not stored. There is
156
+ **no `spec-layout` block** (ADR-0017: frontmatter is the router index — the strategy is not something the
157
+ router needs).
158
+ - **`name` frontmatter (the project name)** — write it when the project's name is **not reliably
159
+ derivable** from the location (`discover-specs` derives `repo` for a repo-root single-project and the
160
+ folder for a `.agents/specs/<project>`, but only **guesses** a nested project's folder basename). For a
161
+ **hoisted / nested** project, **ask the user for the name and store it** (infer a default from the
162
+ invocation when the user named the project — e.g. `backfill <this-project>`); confirm before writing.
163
+ Skip it when the derived name is already right (a plain colocated repo-root project).
164
+ - the **placement map** in the body — the maintained "a concept of kind K lives in home H" taxonomy + the
165
+ nesting rule, **naming the chosen strategy** in its heading/intro, so a newcomer routes a new concept
166
+ without holding the tree in their head and `start-mission` / the Warden read the strategy on demand.
167
+ - the **reserved by-concept index block** beside it (generated by the `concept-index` skill) — the
168
+ cross-cutting `concept → its nodes` view. Reserve the block; **leave it for `concept-index` to
169
+ generate** from `concept:` frontmatter — pure derivation, never hand-maintained.
170
+
171
+ Validate the result with the `spec-gate` skill's `check-spec-state` script (`check-spec-state.mts --root
172
+ <specs-dir>`): the root lifecycle tuple must be legal.
173
+
174
+ ## 6 — Hand back
175
+
176
+ Backfill ends with **stub** behavioral nodes (`## Use Cases` present, no `.feature`), not filled ones —
177
+ filling them is the **per-unit explore grill** (`spec-producer-governance`), the interactive live loop. **Do
178
+ not auto-continue into it.** Present the count of stub nodes and **ask the user**:
179
+
180
+ - **Continue now** — proceed into per-unit explore in this session, node by node, to the spec gate.
181
+ - **Defer to a mission** — stop at `status: draft`; the stubs stay a worklist any later `start-mission` /
182
+ `resume-mission` picks up (the explore grill may want a different model or session).
183
+
184
+ Either way, **propose** the node placement for the formation **Warden** to confirm or relocate, and leave
185
+ `status: draft`.
186
+
187
+ ## Output boundary
188
+
189
+ Write the skeleton, the root envelope (`project-path` frontmatter + placement map + the reserved by-concept
190
+ index block), the `design/decisions/` home, and `glossary.md` — nothing else. Do **not** author any node's `## Use Cases`/`.feature`, render a gate verdict,
191
+ freeze, or write `status` / `approval` / `produced-by` (the conductor's and `spec-gate`'s; see
192
+ `ownership-governance`).
@@ -0,0 +1,7 @@
1
+ # sdd
2
+
3
+ The SDD **gateway** skill — the universal front door to a Spec-Driven-Development project. User-invocable: activates SDD, gathers missing intent, classifies what the user wants to do to the project, and **loads the handling skill in the current session** (`start-mission` for a change, the corpus tools, the outer loops), where the session works the task directly.
4
+
5
+ A **thin classifier**: it holds no production logic, loads **no governance** (the macro-grill ruling), and writes no contract state. It does **not** pin a model — the skill it loads declares the model + effort its work needs. By default it **spawns nothing** — it loads the matched skill in the main session, which **is** the conductor (the user in the driver's seat). It spawns the **automaton** (the headless driver) **only** when there is no user channel (an unattended scheduler or a multi-CR fan-out).
6
+
7
+ Bakes in: explicit activation (`$sdd`), the fast path (change + target → load directly), the two-level intake menu with the hard four-option rule, surface-pending-strategy (count the unratified `strategy` lines globbed from the `ledger/` shards sibling to `spec.md` — never the `*.log.jsonl` combat log; never draft or ratify), the routing-table-as-capability-index (a change → `start-mission`), load-in-session-vs-headless-automaton with write-ownership preserved, and escape / freeze recognition (a non-CR escapes with no record; a frozen `.feature` re-opens through a mission).
@@ -0,0 +1,92 @@
1
+ ---
2
+ name: sdd
3
+ description: Use this skill when the user explicitly invokes SDD or wants to work on a creation artifact with Spec-Driven Development.
4
+ ---
5
+
6
+ # SDD
7
+
8
+ Gateway skill for Spec-Driven Development — the front door to the project. It **activates** SDD, gathers missing intent, classifies what the user wants to do to the project, and **loads the handling skill in the current session**, where the session works the task directly. It is a **thin classifier**: it holds **no production logic**, loads **no governance**, and writes no contract state. It does not edit project files, register hooks, install packages, or require a CLI command.
9
+
10
+ For an attended session the gateway **spawns nothing** — it loads the matched skill (for a change to the project, `start-mission`) in the **main session** and the work proceeds there. The session itself is the **conductor** (the user in the driver's seat). The only thing the gateway spawns is the **automaton** — the headless driver — when there is **no user channel** (an unattended scheduler or a multi-CR fan-out).
11
+
12
+ > **Model is set by the skill you load, not here.** The gateway does not pin a model: classification is light, but the skill it loads declares the model + effort its work needs (`start-mission` advises a capable model for the live grill). The routed skill advises; the user switches manually. (Harness gap: the gateway cannot switch the session model itself.)
13
+
14
+ ## Gateway intake
15
+
16
+ Treat `$sdd`, "use SDD", and "use Spec-Driven Development" as explicit activation. **Most** activating requests are CRs; classification decides which source carried it and which skill handles it. A task with **no suite-relevant behavior**, or one confined to an **ignored** surface, is **not a CR** and escapes (below); recognition is the grill, so ambiguity routes *into* the lifecycle and is decided during explore.
17
+
18
+ ### Surface pending strategy
19
+
20
+ When the Council re-enters, **surface the count of pending (unratified) strategy** — count the `strategy` lines with `"ratified": false` globbed from the project's **root `ledger/` shards** (the durable sibling directory of the root `spec.md`; a legacy `ledger.jsonl` still counts) and state "N pending strategy" alongside the intake; if the Council picks it, route them to review those entries. Count only `kind: strategy` — the conductor's `kind: leash` run-start blocks are **not** strategy and never counted. The gateway only *surfaces* the count — it never **drafts** strategy (the Scanner's job) nor **ratifies** it (the Council's positional act). A zero count is not surfaced. (`strategy` lives in the durable `ledger/` shards, **never** in the per-mission `*.log.jsonl` combat log.)
21
+
22
+ ### Surface in-progress missions
23
+
24
+ On re-entry, **surface the resumable missions** — run the **`discover-plans`** skill (the engine for `intake/plan-discovery`), which scans `.agents/plans/` for `*.plan.md` briefs and returns each one's CR ref, todo tally, and `## NEXT` lead as TOON. A present brief is an **unretired** mission (the doctrine loop's `plan-retirement` deletes a brief once its CR is done/merged and distilled), so each one listed is **resumable**; state them alongside the intake (e.g. "3 in-progress: `github-34` 21/34, …") and, if the user picks one, **load `resume-mission`** on it. The gateway only *surfaces* — it never **resumes** (that's `resume-mission`) nor **retires** (that's `plan-retirement`). An empty set is not surfaced. This is a **read** (the same category as counting strategy lines), so the thin-classifier rule holds.
25
+
26
+ This is the **resumable-mission** sibling of surface-pending-strategy — two distinct concerns, both surfaced: pending strategy is the doctrine loop's unratified ledger lines for the **Council** to keep-or-cut; in-progress missions are **paused work** any user can continue.
27
+
28
+ ### Fast path — skip the menu
29
+
30
+ When the invocation already names **both** a change and a target — "add a start-mission skill to sdd", "implement the auth capability", "work on <issue url>" — skip the menu and load the handling skill directly. A partially-specified request resolves what it can and asks only for the missing piece, within the four-option rule.
31
+
32
+ ### Two-level menu — bare invocation
33
+
34
+ When `$sdd` is invoked with no work item, artifact, or action, do not guess. Conduct intake as a **two-level menu**, never a flat list. **Never ask more than four options** in a single `AskUserQuestion` (the tool rejects more than four). The top-level question presents **exactly four** options:
35
+
36
+ | # | Top-level option | Covers |
37
+ |---|---|---|
38
+ | 1 | **Make a change to the project** | open a CR against the project spec (add a capability, revise behavior, implement, land) → `start-mission` |
39
+ | 2 | **Manage the corpus** | setup & discovery, inspect, audit, or housekeeping (non-mission) → `manage` |
40
+ | 3 | **Review pending strategy** | the doctrine loop's unratified `strategy` lines, when any are pending |
41
+ | 4 | **Help me choose** | scan the spec + statuses, suggest the most-actionable few (≤ 4), let the user pick |
42
+
43
+ When a derived list would exceed four, present only the most-actionable few (≤ 4) or ask the user to name the target directly; never enumerate into an over-four question and never truncate silently.
44
+
45
+ ### Scan statuses with discover-specs
46
+
47
+ For **Help me choose** — and whenever it needs to locate the project spec or rank the most-actionable few — the gateway runs the **`discover-specs`** skill, the frontmatter-only engine for `corpus/discovery`. It returns the TOON list of every project spec at the SDD spec locations — the three fixed conventions plus any opt-in extra anchors a project declared (ADR-0019) — with its `status`, `project-path`, and gate `approvals`; the gateway ranks from that and never opens a spec body. This is a read, not production logic — the same category as counting `ledger/` shard lines for pending strategy — so the thin-classifier rule still holds.
48
+
49
+ **No spec found offers spec anchors.** When `discover-specs` finds no spec for a target project, do not assume it was simply never scaffolded — its spec may sit off the three fixed conventions and need a declared extra anchor. Offer `manage-spec-anchors` (via `manage`) alongside `scaffold-project-spec` as entry points, rather than routing straight to backfill.
50
+
51
+ ## The routing table is the user-skill→capability index
52
+
53
+ Classification routes a request to the **skill** that handles it; the routing table doubles as the index of what a user can invoke (there is no separate `skills.md`).
54
+
55
+ | User intent | Skill (handler) |
56
+ |---|---|
57
+ | Make any change to the project / spec (add, revise, implement, land) | **`start-mission`** — opens a CR against the project spec and runs the mission loop |
58
+ | Manage the corpus — setup & discovery, inspect, audit, or housekeeping (non-mission) | **`manage`** — the manage dispatcher; loads the matching corpus engine in-session |
59
+ | A task with no suite-relevant behavior, or confined to an ignored surface (not a CR) | **escape** — proceeds outside the lifecycle, leaves no SDD record |
60
+ | Product / structure / process retrospective, or field corrections | the **campaign / formation / doctrine / forge** loop — emits a new CR (→ `start-mission`) |
61
+
62
+ One project is one spec — routing classifies *what a user wants to do to the project*, never *which spec in a fleet*. Almost every change is one entry — `start-mission` — which runs the mission loop; whether the CR adds a capability, revises behavior, or reconciles overlap is decided during its **explore** phase, not by a separate entry skill.
63
+
64
+ ## Load the handling skill in-session
65
+
66
+ When the route resolves, **load the matched skill in the current session** and work the task directly — spawn nothing.
67
+
68
+ - **Default (a user session hosts the conductor): load in-session.** For a change to the project, load `start-mission`; it runs the mission loop over the project spec. The session **is** the conductor (the user in the driver's seat); it holds the user channel directly and spawns only the **cold judges** and the **impl-producer builder** at depth 1, where grader independence requires it.
69
+ - **Headless (no user channel — an unattended scheduler or a multi-CR fan-out): spawn the automaton.** The **automaton** is the headless driver (the orchestrator delegate). It runs the same mission loop with no human in the seat: it self-asserts at the autonomy bar and batches `needs-input` rather than asking live, and whatever spawned it relays those questions. The automaton is **not** a separate orchestrator role — it is the driver run headless.
70
+
71
+ ### Dispatch the approved queue — the multi-CR fan-out
72
+
73
+ When the work is a **queue of already-reviewed missions** (each brief cleared with `status: approved`), run the **dispatch loop** — entered by an attended "run the approved missions" request or an unattended trigger (cron):
74
+
75
+ 1. **Select the queue.** Run `discover-plans --status approved` — the approved briefs, in list order. An empty queue is a no-op.
76
+ 2. **Run sequentially, one fresh automaton per mission.** For each brief: if it has no remaining todos, **skip** it (nothing to run); otherwise **spawn a fresh `sdd-automaton` on that brief** — a cold context that reads only its own brief + on-disk artifacts. Collect its verdict packet, then move to the next. **Never run two missions in parallel on the shared working tree.**
77
+ 3. **Relay, never guess.** On a `needs-input` verdict, relay it live (attended) or batch it up the relay (unattended); never auto-accept past it. On a `halt` verdict, **stop that mission** and relay the halt (do not continue it), then move to the next brief.
78
+
79
+ The **fresh spawn per mission is deliberate** — each automaton's context dies with it, so nothing carries from one mission to the next and the dispatch session holds only the queue + small verdict packets (not compaction, which would bleed a prior mission's settled decisions into the next grill). Dispatch **spawns and relays only** — it writes no contract state; each mission's automaton self-asserts and writes its own ledger lines, and the `approved` flag is the human's (set via `pause-mission --approve`), never dispatch's.
80
+
81
+ **Write-ownership.** The gateway writes **no** contract state. The internal spec / impl gates own the `status` write and the human ratification of `approval`; the conductor (the in-session user, or the automaton when headless) owns any provisional self-assertion. The gateway writes neither.
82
+
83
+ ## Recognize the escape and the freeze
84
+
85
+ - **Escape.** A task that is **not a CR** escapes: create no draft, invoke no gate, and **write no record** (a non-CR is not SDD's to track; a spec-prose-only change is already in git). Two independent triggers: **no suite-relevant behavior**, or an **ignored** touched artifact. Escaping does not mean stopping — if the artifact-type has a producer with an escaped-request entry point (e.g. `define-skill` for `skill`), invoke it directly to do the actual work; only state "leaving the lifecycle" and stop when no such producer exists. For tracking, run the `resolve-tracking` skill (`intake/resolve-tracking`'s concrete engine) per touched artifact:
86
+
87
+ ```bash
88
+ node "<resolve-tracking skill>/scripts/resolve-tracking.mts" --root . --path <repo-relative-path> [--artifact-type <type>] [--explicit tracked|ignored]
89
+ ```
90
+
91
+ `--explicit` carries a tracking statement the requester made directly in the prompt/CR, when present. Pass `--artifact-type` when convention already makes it obvious (`skill` under `skills/`, `subagent` under `agents/`, …) — a full `resolve-governances` classification is not needed just to gate the escape check. An `ignored` result escapes the same as no-suite-relevant-behavior; a `tracked` result (including the fail-closed default) proceeds toward CR classification. This is a **read**, the same category as counting strategy lines or scanning specs — the thin-classifier rule still holds. Recognition is the **grill + impact analysis**, not a gateway classifier — the grill may carve a CR out of the tracked parts of a mixed request and escape the ignored ones. Ambiguity defaults *into* the lifecycle and is decided during explore.
92
+ - **Freeze.** SDD freezes the `.feature` at approval. A request to change a frozen scenario is **not** edited in place; it loads **`start-mission`**, which grills the spec back open through the explore phase before scenarios may be revised.
@@ -0,0 +1,9 @@
1
+ # solution-producer-governance
2
+
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
+
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.
6
+
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
+
9
+ References the resolved **architect** actor bar (structural fit) as its self-alignment criterion and `sdd:ownership-governance` for the write-ownership matrix (it never edits `spec.md`, the `.feature`, or control frontmatter). Bakes in the warranted-vs-not test (a real design fork vs a shape that follows from the spec) and the never-restate-the-contract rule.