@llman-sdd/core 0.3.0 → 0.5.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 (107) hide show
  1. package/package.json +2 -1
  2. package/src/archive/freeze.ts +86 -18
  3. package/src/archive/frozenCard.ts +105 -0
  4. package/src/archive/sevenzip.ts +15 -13
  5. package/src/change/closeOutHarness.ts +29 -0
  6. package/src/change/collect.ts +140 -0
  7. package/src/change/frontmatter.ts +48 -6
  8. package/src/change/id.ts +2 -6
  9. package/src/change/lifecycle.ts +285 -86
  10. package/src/change/nextId.ts +63 -2
  11. package/src/change/resolve.ts +2 -2
  12. package/src/change/tasks.ts +59 -0
  13. package/src/config/changeId.ts +14 -12
  14. package/src/config/load.ts +14 -0
  15. package/src/config/schema.ts +4 -41
  16. package/src/config/surface.ts +6 -36
  17. package/src/context/indexStore.ts +7 -3
  18. package/src/context/retrieve.ts +8 -10
  19. package/src/context/tree.ts +28 -24
  20. package/src/git/spawnGit.ts +90 -2
  21. package/src/index.ts +67 -59
  22. package/src/init/defaultConfig.ts +1 -5
  23. package/src/init/init.ts +19 -4
  24. package/src/ports.ts +1 -7
  25. package/src/project/migrateNotes.ts +104 -0
  26. package/src/render/machine.ts +30 -0
  27. package/src/report/collect.ts +11 -127
  28. package/src/report/graph/analysis.ts +152 -0
  29. package/src/report/graph/deps.ts +30 -0
  30. package/src/report/graph/graphData.ts +53 -0
  31. package/src/report/graph/nodes.ts +130 -0
  32. package/src/report/graph/render.ts +83 -0
  33. package/src/report/graph/types.ts +47 -0
  34. package/src/report/graph.ts +9 -381
  35. package/src/report/show.ts +20 -22
  36. package/src/report/specHelpers.ts +42 -21
  37. package/src/report/specs.ts +23 -25
  38. package/src/review/review.ts +45 -30
  39. package/src/spec/authoring.ts +91 -63
  40. package/src/spec/ir.ts +43 -15
  41. package/src/spec/migrateNative.ts +167 -0
  42. package/src/spec/parser.ts +73 -77
  43. package/src/spec/reqRegistry.ts +8 -9
  44. package/src/templates/embedded.ts +10 -16
  45. package/src/templates/engine.ts +10 -5
  46. package/src/templates/locale.ts +1 -1
  47. package/src/templates/skills.ts +4 -5
  48. package/src/validation/changeCheck.ts +128 -105
  49. package/src/validation/harness.ts +161 -0
  50. package/src/validation/staleness.ts +9 -5
  51. package/src/validation/validate.ts +60 -88
  52. package/templates/en/skills/llman-sdd-apply-cycle.md +20 -28
  53. package/templates/en/skills/llman-sdd-apply.md +58 -76
  54. package/templates/en/skills/llman-sdd-arch-review.md +12 -19
  55. package/templates/en/skills/llman-sdd-archive.md +27 -42
  56. package/templates/en/skills/llman-sdd-continue.md +17 -24
  57. package/templates/en/skills/llman-sdd-draft.md +17 -28
  58. package/templates/en/skills/llman-sdd-explore.md +29 -43
  59. package/templates/en/skills/llman-sdd-ff.md +12 -17
  60. package/templates/en/skills/llman-sdd-graph.md +14 -32
  61. package/templates/en/skills/llman-sdd-propose.md +48 -63
  62. package/templates/en/skills/llman-sdd-quick.md +12 -27
  63. package/templates/en/skills/llman-sdd-research.md +13 -24
  64. package/templates/en/skills/llman-sdd-specs-compact.md +14 -39
  65. package/templates/en/skills/llman-sdd-validate.md +11 -15
  66. package/templates/en/skills/llman-sdd-verify.md +23 -44
  67. package/templates/en/skills/llman-sdd-wayfinder.md +18 -22
  68. package/templates/en/units/skills/cli-footer.md +2 -0
  69. package/templates/en/units/skills/git-native-flow-brief.md +7 -6
  70. package/templates/en/units/skills/git-native-flow.md +21 -11
  71. package/templates/en/units/skills/human-readable-summary.md +2 -3
  72. package/templates/en/units/skills/stage-guard.md +7 -7
  73. package/templates/en/units/skills/structured-protocol.md +5 -8
  74. package/templates/en/units/skills/validation-hints.md +10 -14
  75. package/templates/en/units/spec/feature-contract.md +27 -16
  76. package/templates/en/units/workflow/archive-freeze-guidance.md +6 -3
  77. package/templates/zh-Hans/skills/llman-sdd-apply-cycle.md +23 -31
  78. package/templates/zh-Hans/skills/llman-sdd-apply.md +63 -81
  79. package/templates/zh-Hans/skills/llman-sdd-arch-review.md +21 -28
  80. package/templates/zh-Hans/skills/llman-sdd-archive.md +29 -44
  81. package/templates/zh-Hans/skills/llman-sdd-continue.md +17 -24
  82. package/templates/zh-Hans/skills/llman-sdd-draft.md +18 -29
  83. package/templates/zh-Hans/skills/llman-sdd-explore.md +34 -48
  84. package/templates/zh-Hans/skills/llman-sdd-ff.md +13 -18
  85. package/templates/zh-Hans/skills/llman-sdd-graph.md +16 -34
  86. package/templates/zh-Hans/skills/llman-sdd-propose.md +51 -65
  87. package/templates/zh-Hans/skills/llman-sdd-quick.md +15 -30
  88. package/templates/zh-Hans/skills/llman-sdd-research.md +17 -28
  89. package/templates/zh-Hans/skills/llman-sdd-specs-compact.md +15 -40
  90. package/templates/zh-Hans/skills/llman-sdd-validate.md +11 -15
  91. package/templates/zh-Hans/skills/llman-sdd-verify.md +26 -47
  92. package/templates/zh-Hans/skills/llman-sdd-wayfinder.md +25 -29
  93. package/templates/zh-Hans/units/skills/cli-footer.md +2 -0
  94. package/templates/zh-Hans/units/skills/git-native-flow-brief.md +7 -6
  95. package/templates/zh-Hans/units/skills/git-native-flow.md +22 -12
  96. package/templates/zh-Hans/units/skills/human-readable-summary.md +4 -5
  97. package/templates/zh-Hans/units/skills/stage-guard.md +9 -9
  98. package/templates/zh-Hans/units/skills/structured-protocol.md +5 -8
  99. package/templates/zh-Hans/units/skills/validation-hints.md +10 -14
  100. package/templates/zh-Hans/units/spec/feature-contract.md +25 -16
  101. package/templates/zh-Hans/units/workflow/archive-freeze-guidance.md +6 -2
  102. package/templates/en/skills/llman-sdd-onboard.md +0 -34
  103. package/templates/en/skills/llman-sdd-show.md +0 -24
  104. package/templates/en/units/migrate-prompt.md +0 -28
  105. package/templates/zh-Hans/skills/llman-sdd-onboard.md +0 -34
  106. package/templates/zh-Hans/skills/llman-sdd-show.md +0 -24
  107. package/templates/zh-Hans/units/migrate-prompt.md +0 -28
@@ -1,18 +1,18 @@
1
1
  /**
2
2
  * Validation engine (validation capability): aggregates Phase-2 parse errors
3
- * plus the verdict-equivalent gates (r11/r12, ordered to match v1
3
+ * plus the verdict-equivalent gates (r11/r12, ordered to match predecessor
4
4
  * `spec/validation.rs` observable issue order). Pure — filesystem access is
5
5
  * injected via SpecIo.
6
6
  */
7
7
  import type { CapabilityDoc } from '../spec/ir.ts';
8
- import { MUST_WORD_RE } from '../spec/ir.ts';
8
+ import { specIdOf } from '../spec/ir.ts';
9
9
  import { buildReqRegistry } from '../spec/reqRegistry.ts';
10
10
 
11
11
  export type ValidationLevel = 'ERROR' | 'WARNING' | 'INFO';
12
12
 
13
13
  export interface ValidationItem {
14
14
  level: ValidationLevel;
15
- /** Gate anchor, e.g. `t/rule/ok` or `t/valid_scope` (v1-style `path`). */
15
+ /** Gate anchor, e.g. `t/rule/ok` or `t/valid_scope` (predecessor-style `path`). */
16
16
  id: string;
17
17
  message: string;
18
18
  }
@@ -41,7 +41,6 @@ export interface ValidationReport {
41
41
  }
42
42
 
43
43
  const rulesPath = (cap: string): string => `${cap}/rules`;
44
- const acceptanceReqPath = (cap: string, name: string): string => `${cap}/acceptance/${name}/@req`;
45
44
  const coveragePath = (cap: string): string => `${cap}/coverage`;
46
45
 
47
46
  export function validateCapability(
@@ -51,7 +50,7 @@ export function validateCapability(
51
50
  opts: { strict?: boolean } = {},
52
51
  ): SpecVerdict {
53
52
  const { doc } = entry;
54
- const cap = doc.header.capability ?? entry.fileName;
53
+ const cap = specIdOf(entry);
55
54
  const strict = opts.strict === true;
56
55
  const items: ValidationItem[] = [];
57
56
 
@@ -59,27 +58,23 @@ export function validateCapability(
59
58
  items.push({ level, id, message });
60
59
  };
61
60
 
62
- // Header gates (r12 / v1 spec_meta). v1 treats a missing `# capability:`
61
+ // Header gates (r12 / predecessor spec_meta). predecessor treats a missing `# capability:`
63
62
  // header as a parse-level failure: only `file` + registry-scan issues are
64
63
  // emitted and all single-track gates are skipped.
65
64
  if (doc.header.capability === null) {
66
- const msg = `spec \`${cap}\`: missing \`# capability:\` header comment (spec-format r133)`;
65
+ const msg = `spec \`${cap}\`: missing \`# capability:\` header comment`;
67
66
  push('ERROR', 'file', msg);
68
67
  push('ERROR', 'llmanspec/specs', `Failed to scan req_id index: ${msg}`);
69
68
  return { fileName: entry.fileName, capability: cap, ok: false, items };
70
69
  }
71
70
  if (doc.header.purpose === null || doc.header.purpose.trim() === '') {
72
- push(
73
- 'ERROR',
74
- `${cap}/purpose`,
75
- '`# purpose:` header comment must not be empty (spec-format r133)',
76
- );
71
+ push('ERROR', `${cap}/purpose`, '`# purpose:` header comment must not be empty');
77
72
  }
78
73
  if (doc.header.scope === null) {
79
74
  push(
80
75
  'ERROR',
81
76
  `${cap}/valid_scope`,
82
- 'Spec valid_scope must not be empty (add it inside the .toon document).',
77
+ 'Spec valid_scope must not be empty (declare it in the "# scope:" header comment).',
83
78
  );
84
79
  } else {
85
80
  // r42: missing valid_scope paths are independent failures —
@@ -112,86 +107,50 @@ export function validateCapability(
112
107
  push('ERROR', `${cap}/feature`, 'Feature line must carry a title');
113
108
  }
114
109
 
115
- // Parser-level structural errors (mutual exclusion, removed-tag migration,
116
- // nested rule scenarios). Header gates and the MUST-word gate are owned here
117
- // (mapped below), so the parser's duplicate findings are skipped.
118
- const OWNED_BY_THIS_LAYER = ['missing-header:', 'rule:missing-must-word'];
110
+ // Parser-level structural errors. Header gates are owned here (mapped below);
111
+ // the parser's duplicate header findings are skipped.
112
+ const OWNED_BY_THIS_LAYER = ['missing-header:'];
119
113
  for (const err of doc.errors) {
120
114
  if (OWNED_BY_THIS_LAYER.some((prefix) => err.code.startsWith(prefix))) continue;
121
115
  push('ERROR', err.code.startsWith('file') ? 'file' : `${cap}/${err.code}`, err.message);
122
116
  }
123
117
 
124
- // Single-track gates (v1 validate_single_track order).
125
- const human = doc.scenarios.filter((s) => s.classification === 'human');
126
- const acceptance = doc.scenarios.filter((s) => s.classification === 'executable');
118
+ // Native single-track gates: `规则:` blocks with `@req` handles; nested
119
+ // `场景:` are their executable examples; top-level scenarios are orphans.
120
+ const rules = doc.rules;
127
121
 
128
- if (human.length === 0) {
129
- push('ERROR', rulesPath(cap), 'spec must define at least one @human constraint scenario');
122
+ if (rules.length === 0) {
123
+ push('ERROR', rulesPath(cap), 'spec must define at least one rule');
130
124
  }
131
125
 
132
- for (const scenario of doc.scenarios) {
133
- const anchor = `${cap}/rule/${scenario.name}`;
134
- if (scenario.classification === 'human') {
135
- if (scenario.reqIds.length === 0) {
136
- push('ERROR', anchor, '@human constraint scenario must carry an @req:<req_id> tag');
137
- }
138
- if (!MUST_WORD_RE.test(scenario.statement)) {
139
- push('ERROR', anchor, 'constraint statement must contain MUST/SHALL (or 必须/不得/禁止)');
140
- }
141
- } else if (scenario.classification === 'executable') {
142
- // (pairing handled below, after all rule req ids are known)
143
- } else {
126
+ for (const rule of rules) {
127
+ const anchor = `${cap}/rule/${rule.title}`;
128
+ if (rule.reqId === '') {
129
+ push('ERROR', anchor, 'rule must carry an @req:<req_id> tag on the rule header');
130
+ } else if (duplicatesFor(rule.reqId)) {
144
131
  push(
145
- 'WARNING',
146
- `${cap}/scenario/${scenario.name}`,
147
- `scenario \`${scenario.name}\` carries neither @human nor @executable; tag it or drop it`,
132
+ 'ERROR',
133
+ `${cap}/registry/${rule.reqId}`,
134
+ `global duplicate req_id \`${rule.reqId}\` used by multiple capabilities`,
148
135
  );
149
136
  }
150
- for (const reqId of scenario.reqIds) {
151
- if (duplicatesFor(reqId)) {
152
- push(
153
- 'ERROR',
154
- `${cap}/registry/${reqId}`,
155
- `global duplicate req_id \`${reqId}\` used by multiple capabilities`,
156
- );
157
- }
158
- }
159
137
  }
160
138
 
161
- // Dangling acceptance @req links (v1 order: acceptance/@req then coverage).
162
- const ruleReqIds = new Set(human.flatMap((s) => s.reqIds));
163
- for (const sc of acceptance) {
164
- // r65: orphan acceptance scenario — no @req link at all (v1 r132 WARNING).
165
- if (sc.reqIds.length === 0) {
166
- push(
167
- 'WARNING',
168
- `${cap}/acceptance/${sc.name}`,
169
- `orphan acceptance scenario \`${sc.name}\` has no @req:<req_id> link`,
170
- );
171
- }
172
- for (const rid of sc.reqIds) {
173
- if (!ruleReqIds.has(rid)) {
174
- push(
175
- 'ERROR',
176
- acceptanceReqPath(cap, sc.name),
177
- `@req:${rid} on acceptance scenario \`${sc.name}\` has no matching @human constraint`,
178
- );
179
- }
180
- }
181
- }
139
+ // Top-level `场景:` outside any rule are plain feature-level examples
140
+ // (native Gherkin); they carry no rule handle, so no warning or signal —
141
+ // they simply aren't part of rule accounting.
182
142
 
183
- // Rule coverage INFO (r134 pending rules).
184
- for (const sc of human) {
185
- for (const rid of sc.reqIds) {
186
- const covered = acceptance.some((a) => a.reqIds.includes(rid));
187
- if (!covered) {
188
- push(
189
- 'INFO',
190
- coveragePath(cap),
191
- `rule ${rid} is pending: no @executable acceptance scenario`,
192
- );
193
- }
194
- }
143
+ // Bare-rule aggregate (r134 migrated): rules with no nested executable
144
+ // scenario, aggregated per capability (never one issue per rule), INFO so it
145
+ // never blocks anything. The real accountability lives in the review
146
+ // `pending` signal and the specs-compact workflow.
147
+ const bare = rules.filter((r) => r.scenarios.length === 0).length;
148
+ if (bare > 0) {
149
+ push(
150
+ 'INFO',
151
+ coveragePath(cap),
152
+ `${bare} bare rule(s) without any executable scenario — convert to 场景: or compact`,
153
+ );
195
154
  }
196
155
 
197
156
  return {
@@ -202,13 +161,28 @@ export function validateCapability(
202
161
  };
203
162
  }
204
163
 
205
- export function validateAllSpecs(entries: readonly SpecEntry[], io: SpecIo): ValidationReport {
164
+ /**
165
+ * Shared req_id duplicate gate — single source of truth for the CLI
166
+ * (`validate <spec>` path) and the full sweep. The registry is built from the
167
+ * already-parsed docs, so a duplicate is reported for every involved
168
+ * capability regardless of unrelated parse errors elsewhere (r12 acceptance:
169
+ * 重复 req_id MUST 对每个涉事 capability 判 ERROR — the 前代 "structural error
170
+ * aborts the index scan" guard is intentionally dropped; a parse-failed spec
171
+ * merely omits the scenarios it could not decode, never invents ids).
172
+ */
173
+ export function buildDuplicatesFor(entries: readonly SpecEntry[]): (reqId: string) => boolean {
206
174
  const registry = buildReqRegistry(entries);
207
175
  const duplicateIds = new Set(registry.duplicates.flatMap((d) => d.reqId));
208
- // v1 parity: a structural error anywhere aborts the req_id index scan, so
209
- // the duplicate gate only fires when every spec parses cleanly.
210
- const structurallyClean = entries.every((e) => e.doc.errors.length === 0);
211
- const duplicatesFor = (reqId: string): boolean => structurallyClean && duplicateIds.has(reqId);
176
+ return (reqId: string): boolean => duplicateIds.has(reqId);
177
+ }
178
+
179
+ /** `Totals:` report line — single wording source for the engine and the CLI. */
180
+ export function formatTotals(passed: number, failed: number, total: number): string {
181
+ return `Totals: ${passed} passed, ${failed} failed (${total} items)`;
182
+ }
183
+
184
+ export function validateAllSpecs(entries: readonly SpecEntry[], io: SpecIo): ValidationReport {
185
+ const duplicatesFor = buildDuplicatesFor(entries);
212
186
 
213
187
  const verdicts = entries.map((e) => validateCapability(e, duplicatesFor, io));
214
188
  const failed = verdicts.some((v) => !v.ok);
@@ -221,14 +195,12 @@ export function validateAllSpecs(entries: readonly SpecEntry[], io: SpecIo): Val
221
195
  lines.push(` [${item.level}] ${item.id}: ${item.message}`);
222
196
  }
223
197
  }
224
- lines.push(
225
- `Totals: ${passed} passed, ${verdicts.length - passed} failed (${verdicts.length} items)`,
226
- );
198
+ lines.push(formatTotals(passed, verdicts.length - passed, verdicts.length));
227
199
 
228
200
  return { verdicts, lines, failed };
229
201
  }
230
202
 
231
- /** v1 `apply_strict`: WARNING issues escalate to ERROR when --strict. */
203
+ /** predecessor `apply_strict`: WARNING issues escalate to ERROR when --strict. */
232
204
  export function applyStrict<T extends { level: ValidationLevel }>(items: readonly T[]): T[] {
233
205
  return items.map((i) => (i.level === 'WARNING' ? { ...i, level: 'ERROR' as const } : i));
234
206
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: "llman-sdd-apply-cycle"
3
- description: "Single closed-loop for one change: gate→implement→test→validate→verify→archive→commit. Manual trigger only. Agent MUST NOT auto-invoke."
3
+ description: "End-to-end closed loop for one change: implement→test→validate→verify→archive. Manual trigger only; agent must not auto-invoke."
4
4
  metadata:
5
5
  version: "{{ llman_version }}"
6
6
  disable-model-invocation: true
@@ -8,7 +8,7 @@ disable-model-invocation: true
8
8
 
9
9
  # LLMAN SDD Apply Cycle
10
10
 
11
- End-to-end closed loop for one change (manual). Requires Branch binding and `readyToImplement=true`.
11
+ End-to-end closed loop for one change (manual). Requires a bound branch and a green specs-landed gate (`specsLanded ∨ needsSpecsChange=false`); `readyToImplement=true` (the completion signal) closes the cycle.
12
12
 
13
13
  **Manual trigger only**: `/skill:llman-sdd-apply-cycle <change-id>`
14
14
 
@@ -16,60 +16,52 @@ End-to-end closed loop for one change (manual). Requires Branch binding and `rea
16
16
 
17
17
  ### 0) Gate + status
18
18
  ```bash
19
- llman-sdd show <change-id> --json --type change
19
+ llman-sdd show <change-id> --output json --type change
20
20
  ```
21
- > Stage gate: decide from `stage` / `readyToImplement` in `llman-sdd show <id> --json --type change`; full decision table lives in llman-sdd-apply.
21
+ > Stage decisions use the `stage` / `readyToImplement` fields; the full decision table lives in llman-sdd-apply.
22
22
 
23
23
  - Must be on the bound non-default branch.
24
- - If `readyToImplement` is not true → STOP (finish Specs landing or `needs_specs_change: false`); **do not** finalize yet.
25
- - Track progress via `tasks.md` checkboxes (or `llman-sdd list` task counts); still read `tasks.md`, proposal/design, and live `llmanspec/specs/**` on the bound branch (SSOT).
24
+ - specs-landed gate failing → STOP (land specs or `needs_specs_change: false`). Green but `readyToImplement=false` → normal: tasks pending, keep implementing; **finalize only when `readyToImplement=true`**.
25
+ - Track progress via `tasks.md` checkboxes (or `llman-sdd list` task counts); still read `tasks.md`, proposal/design, and `llmanspec/specs/**` on the bound branch (the single source of truth).
26
26
 
27
27
  ### 1) Loop: implement → test
28
28
  For each incomplete task:
29
- 1. Implement per task + live specs (minimal diff)
30
- 2. Run `tasks[].test` if present
29
+ 1. Implement per task + specs (minimal diff)
30
+ 2. Run the task's stated verification command when the task text names one
31
31
  3. On failure, fix and retry (same self-repair budget as `llman-sdd-apply`: cap 8 rounds)
32
32
  4. Check off `tasks.md` as `[x]`
33
33
 
34
34
  ### 2) Validate
35
35
  ```bash
36
- llman-sdd validate <change-id> --strict --no-interactive
36
+ llman-sdd validate <change-id> --strict
37
37
  ```
38
- On failure, fix and retry (same self-repair budget as `llman-sdd-apply`: cap 8 rounds).
38
+ On failure, fix and retry (cap 8 rounds).
39
39
 
40
40
  ### 3) Verify (recommended)
41
- Prefer `llman-sdd-verify` (or equivalent dual-axis self-check). CRITICAL → STOP; do not archive.
41
+ Prefer `llman-sdd-verify` (or an equivalent dual-axis self-check). CRITICAL → STOP; do not archive.
42
42
 
43
- ### 4) Archive
43
+ ### 4) Archive + commit
44
44
  ```bash
45
45
  llman-sdd change finalize <change-id>
46
46
  ```
47
- (dirty tree OK; auto merge (squash default) + docs rename + **auto commit** `archive(sdd): <change-id>` in one process. `--no-commit` skips the auto commit for manual/CI histories — then commit with `git add -A && git commit -m "archive(sdd): <change-id>"`.)
47
+ Dirty tree OK; auto merge (squash default) + rename + **auto commit** `archive(sdd): <change-id>` in one process. `--no-commit` skips the auto commit (manual/CI histories) — then commit with `git add -A && git commit -m "archive(sdd): <change-id>"`. Plain `change archive` stays as a fallback.
48
48
 
49
- `change checkpoint` is removed; the plain `change archive` command stays as a fallback (no checkpointed field required).
50
-
51
- ### 5) Commit (see step 4)
52
- Finalize already auto-committed unless `--no-commit` was passed.
53
-
54
- ### 6) Optional cleanup
49
+ ### 5) Optional cleanup
55
50
  ```bash
56
51
  git branch -D <feature-branch> # after squash the branch is no longer an ancestor of main; -d gets refused
57
52
  ```
58
- push / hosting PR only when the user explicitly asks.
53
+ Push / PR only when the user explicitly asks.
59
54
 
60
55
  ## Hard constraints
61
56
  - **Never ask** "should I continue" unless blocked.
62
57
  - **Never switch** changes until this one is archived and committed.
63
- - **Retry cap**: self-repair follows `llman-sdd-apply`'s 8-round budget (including the diagnose escalation path).
64
- - **Do not** author `changes/<id>/specs/` or use `change delta`.
65
- - **No default push/PR**.
58
+ - **Do not** author `changes/<id>/specs/`; **no default push/PR**.
66
59
 
67
60
  ## Ethics Governance
68
61
  - `ethics.risk_level`: medium
69
- - `ethics.prohibited_actions`: implement/archive without `readyToImplement`, switching changes early, writing `changes/<id>/specs/`, commit without validation, default push/PR
62
+ - `ethics.prohibited_actions`: implementing without a bound branch / a green specs-landed gate, archiving without `readyToImplement=true`, switching changes early, writing `changes/<id>/specs/`, committing without validation, default push/PR
70
63
  - `ethics.required_evidence`: `readyToImplement=true`, validate --strict pass, all tasks checked, finalize/archive success
71
- - `ethics.refusal_contract`: after 3 gate/validation failures, report blocker; do not force-archive
72
- - `ethics.escalation_policy`: if changing SDD workflow specs/templates, pause for user confirm before archive
64
+ - `ethics.refusal_contract`: after 8 self-repair rounds still failing, report a blocker; never force-archive
65
+ - `ethics.escalation_policy`: if changing SDD workflow specs/templates, pause for user confirmation before archive
73
66
 
74
- > For command details run `llman-sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
75
- > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman-sdd list --specs` or `llman-sdd show <capability>`.
67
+ {{ unit("skills/cli-footer") }}
@@ -1,125 +1,107 @@
1
1
  ---
2
2
  name: "llman-sdd-apply"
3
- description: "Implement tasks from an llman SDD change in a closed loop — write code, run tests, self-heal on failures until all gates pass. Use when a change is proposed and ready to implement. Updates tasks.md checkboxes and runs validation."
3
+ description: "Implement a proposed change's tasks in a closed loop: code → test → self-heal → all gates green. Enter after propose, once specs are landed."
4
4
  metadata:
5
5
  version: "{{ llman_version }}"
6
6
  ---
7
7
 
8
8
  # LLMAN SDD Apply
9
9
 
10
- Implement all tasks in `llmanspec/changes/<id>/tasks.md` **in one closed loop**:
11
- Implement code → Add tests/acceptance → Run gates → Self-heal on failures → Report results when all pass.
12
- Unless there is a clear blocker, **DO NOT stop halfway to ask "should I continue?"**
10
+ Implement all tasks in `llmanspec/changes/<id>/tasks.md` **in one closed loop**: implement → add tests/acceptance → run gates → self-heal and re-run on failure → report when all pass. Unless there is a clear blocker, **do not stop halfway to ask "should I continue?"**
13
11
 
14
12
  ## Pipeline Position
15
13
 
16
14
  {{ unit("skills/git-native-flow-brief") }}
17
15
 
18
- ### Skill navigation (not the lifecycle; shows current skill only)
19
-
20
16
  ```mermaid
21
17
  flowchart LR
22
- propose["llman-sdd-propose<br/>Propose"] --> apply
23
- apply["★ llman-sdd-apply ★<br/>Implement (readyToImplement)"]
24
- apply --> verify["llman-sdd-verify<br/>Verify"]
25
- verify --> archive["llman-sdd-archive<br/>Archive"]
18
+ propose["llman-sdd-propose"] --> apply["★ llman-sdd-apply"]
19
+ apply --> verify["llman-sdd-verify"]
20
+ verify --> archive["llman-sdd-archive"]
26
21
 
27
22
  style apply fill:#fff3cd,stroke:#ffc107,stroke-width:3px
28
23
  ```
29
24
 
30
- > 📍 You are at Git-native **H (apply)** in the full lifecycle diagram: Specs-landed (or `needs_specs_change: false`) and `readyToImplement=true` required first → next: `llman-sdd-verify`
25
+ > 📍 Entry requires the specs-landed gate green (or `needs_specs_change: false`); `readyToImplement=true` (all gates green) is the completion signal that closes this loop → next `llman-sdd-verify`.
31
26
 
32
27
  ## Hard Constraints
33
28
 
34
- - **SSOT-driven**: `proposal.md` / `design.md` / `tasks.md` and live `llmanspec/specs/**` on the feature branch are the single source of truth; every MUST/SHALL in specs must be fulfilled.
35
- - **Scope-locked**: Only implement what's in the current change; don't fix "unrelated issues" on the side.
36
- - **Minimal changes**: Keep changes minimal and strictly scoped to current tasks.
37
- - **No guessing**: If requirements are unclear, or specs contradict reality, STOP and report — don't assume behavior.
38
- - **No legacy compatibility layers**: If a change requires new behavior, upgrade all call sites directly, unless tasks/proposal explicitly require compatibility.
39
- - **Don't ask "should I continue?"**: Execute to loop closure unless you hit an unresolvable blocker.
40
- - **Close-out**: this skill's closed loop ends by suggesting `llman-sdd-verify`; finalize/archive is handled by `llman-sdd-archive` (do not finalize inside the self-healing loop).
29
+ - **Single-source-of-truth driven**: `proposal.md` / `design.md` / `tasks.md` and `llmanspec/specs/**` on the branch; every MUST/SHALL in specs must be fulfilled.
30
+ - **Scope-locked**: only implement the current change's scope; never fix "unrelated issues" on the side; keep changes minimal.
31
+ - **No guessing**: unclear requirements or specs contradicting reality → STOP and report; don't assume.
32
+ - **No legacy compatibility layers**: if the change requires new behavior, upgrade all call sites directly, unless tasks/proposal explicitly require compatibility.
33
+ - **Close-out**: this loop ends by suggesting `llman-sdd-verify`; finalize/archive belongs to `llman-sdd-archive` (do not finalize inside the self-healing loop).
41
34
 
42
35
  ## Commit Policy
43
36
 
44
- - **Commits on the change branch are free** (no mid-flight archive point; `change finalize` needs no clean tree): segment by task or milestone when it helps review, or keep the working tree dirty and let finalize make ONE close commit — both are first-class. `change checkpoint` no longer exists (calling it exits non-zero and points to finalize), so there is no mid-flight "archive point" to maintain; `change finalize` handles both shapes (it does NOT require a clean tree).
45
- - **Default close-out**: after all tasks pass gates and verify is green, `llman-sdd change finalize <id>` auto-commits `archive(sdd): <change-id>` (uncommitted impl diff + frontmatter + archive rename in one commit). Do not run finalize inside the apply loop. `--no-commit` skips the auto commit (manual/CI histories; pre-commit-hook conflicts).
46
- - **Blocker interrupt**: when you must STOP on a blocker, make ONE work-in-progress commit (e.g. `wip(sdd): <change-id> <summary>`) to preserve the state, then report.
37
+ - **Commits on the change branch are free** (`change finalize` needs no clean tree): segment by task/milestone, or keep the tree dirty and let finalize make one close commit — both are first-class.
38
+ - **Default close-out**: after all tasks pass gates and verify is green, `llman-sdd change finalize <id>` auto-commits `archive(sdd): <change-id>` (uncommitted diff + frontmatter + rename in one commit). Do not run finalize inside the apply loop. `--no-commit` skips the auto commit (manual/CI histories; pre-commit-hook conflicts).
39
+ - **Blocker interrupt**: when you must STOP on a blocker, make ONE WIP commit (e.g. `wip(sdd): <change-id> <summary>`) to preserve the state, then report.
47
40
 
48
41
  ## Steps
49
42
 
50
43
  ### 0) Preflight (required)
51
- - Read and obey: `llmanspec/config.yaml`, `AGENTS.md` (if present).
52
- - `git status --porcelain`:
53
- - If working tree is dirty and changes don't belong to the current change: `git stash push -u -m "llman-sdd-apply autopilot backup"`.
54
- - Run `llman-sdd validate --all --strict --no-interactive`:
55
- - If it fails for reasons unrelated to the current change, stop and report (inconsistent artifacts prevent SSOT-driven implementation).
56
- - **Check spec valid_scope integrity**: use `llman-sdd list --specs --json` to list all specs, then for each spec verify every path in its `valid_scope` exists on disk. If any scope file/directory is missing, stop and suggest updating the spec (remove the deleted path from `valid_scope`).
57
-
58
- ### 1) Select change id and check prerequisites
59
- - If a change id is provided, use it directly.
60
- - Otherwise infer from context; if ambiguous, run `llman-sdd list --json` and let user pick.
61
- - Always announce: "Using change: <id>" and how to override.
62
- - Confirm you are on the non-default feature branch bound via `llman-sdd change start <id>` or `change attach <id>` (`--force` only to rebind). Specs/features on the branch are SSOT — do not author under `changes/<id>/specs/`.
44
+ - Read and obey `llmanspec/config.yaml`, `AGENTS.md` (if present).
45
+ - `git status --porcelain`: if the tree is dirty with changes not belonging to this change → `git stash push -u -m "llman-sdd-apply autopilot backup"` first.
46
+ - `llman-sdd validate --all --strict`: if it fails for reasons unrelated to this change → stop and report (inconsistent artifacts prevent source-of-truth-driven implementation).
47
+ - **Check spec valid_scope integrity**: `llman-sdd list --specs --json` lists all specs; for each, verify every `valid_scope` path exists on disk. On missing paths → stop and suggest updating the spec (remove the deleted path).
48
+
49
+ ### 1) Select the change id and check prerequisites
50
+ - If provided, use it; otherwise infer from context, and if ambiguous run `llman-sdd list --json` and let the user pick. Always announce "Using change: <id>" and how to override.
51
+ - Confirm you are on the non-default branch bound via `llman-sdd change start <id>` or `change attach <id>` (`--force` only to rebind). Specs on the branch are the single source of truth — do not author under `changes/<id>/specs/`.
63
52
  {{ unit("skills/stage-guard") }}
64
53
  - Use `llman-sdd context --task "<goal from proposal>" --paths "<scope from specs>"` to get relevant specs.
65
- - If context is unavailable, run `llman-sdd index rebuild` and retry.
54
+ - Context unavailable → run `llman-sdd index check` first: stale/missing → `llman-sdd index rebuild` and retry; still unavailable on a fresh index (`LLMAN_SDD_INDEX_CHAT_MODEL` unset) → fall back to `llman-sdd list --specs` + reading `.feature` files directly — do not loop on rebuild.
66
55
 
67
- ### 2) Read SSOT artifacts
68
- You must read through:
69
- - `llmanspec/changes/<id>/proposal.md`
70
- - `llmanspec/changes/<id>/design.md` (if present)
71
- - `llmanspec/changes/<id>/tasks.md`
72
- - Live specs on the feature branch: `llmanspec/specs/**` (`<capability>.feature`) — this is SSOT
56
+ ### 2) Read the source-of-truth artifacts
57
+ - `llmanspec/changes/<id>/proposal.md`, `design.md` (if present), `tasks.md`
58
+ - `llmanspec/specs/**` (`<capability>.feature`) on the branch
73
59
 
74
- Extract hard constraints from proposal.md and design.md decisions. Convert tasks.md into a minimal executable step sequence (preserving original order).
60
+ Distill proposal/design decisions into a list of inviolable hard constraints; convert tasks.md into a minimal executable step sequence (preserving original order).
75
61
 
76
62
  ### 3) Show status
77
- - Progress: "N/M tasks complete"
78
- - Next 1–3 unchecked tasks (brief overview)
63
+ - Progress "N/M tasks complete" + a brief look at the next 1–3 unchecked tasks.
79
64
 
80
- ### 4) Implement tasks one by one (closed-loop execution)
65
+ ### 4) Implement tasks one by one (closed loop)
81
66
  For each unchecked task:
82
- 1. **Implement**: strictly per task description + specs requirements, keep changes minimal.
83
- 2. **Update checkbox immediately** after completion: `- [ ]` → `- [x]`.
84
- 3. If task is unclear, you hit a blocker, or specs/design don't match reality → STOP and report the blocker, don't assume.
85
-
86
- > 💡 Previous phase `llman-sdd-propose` (generated tasks); after this phase → `llman-sdd-verify` (verify)
87
-
88
- ### 5) Verification and self-healing loop (run after each task or batch)
89
- Run project gate commands (adapt to the actual project):
90
- - Relevant test suite: `just test` or `cargo test --all`
91
- - Format/lint: `just check` or `just lint` + `just fmt`
92
- - Git-native: stay on the bound feature branch; edit live `llmanspec/specs/<capability>.feature` (flat, or directory `llmanspec/specs/<capability>/` main file; rules `@human`, acceptance `@executable`) as needed; run `llman-sdd validate --specs` after spec edits; commit on the branch freely (segmented or leave dirty for finalize). Do not use `change delta` / solidify / feature_delta; `change checkpoint` is removed.
93
- - SDD validation: `llman-sdd validate <id> --strict --no-interactive`
94
-
95
- **On failure → enter self-healing loop (don't ask "should I continue?"):**
96
- 1. Parse failure cause (test failure / lint / format / validation error).
97
- 2. **Decide if it's a hard-to-locate bug** (cause unclear / intermittent flake / regression not obvious at a glance):
98
- - **Not hard-to-locate** (clear lint/format/compile/validation error): apply a minimum fix (don't expand scope); re-run the "minimum failure repro command" first, then re-run all gates.
99
- - **Hard-to-locate bug → escalate to the diagnose sub-flow**:
67
+ 1. **Implement**: strictly per task description + specs, minimal changes.
68
+ 2. **Check the box immediately** after completion: `- [ ]` → `- [x]`. **Close-out is not a task**: `change finalize` / `change archive` are pipeline steps and MUST NOT appear in tasks.md — if one is listed (e.g. "close-out — finalize"), remove it (the close-out task gate requires every task checked).
69
+ 3. **Edit, then verify — serially**: verification MUST run after edits land on disk; MUST NOT put edits and tests/validation in the same parallel tool-call batch (the check may read stale files and report a false failure or a false pass).
70
+ 4. Task unclear, blocker hit, or specs/design contradict reality → STOP and report; don't assume.
71
+
72
+ ### 5) Verification and self-healing loop (after each task or batch)
73
+ Run the project gates as appropriate:
74
+ - Test suite: `just test` or `cargo test --all`; format/lint: `just check` or `just lint` + `just fmt`
75
+ - Edit `llmanspec/specs/<capability>.feature` on the branch as needed (flat or directory main file; canonical native layout: `@req:<id>` on the `规则:` block header, nested `场景:` as executable examples); run `llman-sdd validate --specs` after spec edits; commit on the branch freely.
76
+ - SDD validation: `llman-sdd validate <id> --strict`
77
+
78
+ **Gate evidence**:
79
+ - Close-out runs the configured `bdd.run_command`, so do not run that command again just before close-out; the skip line printed by `--no-check` is not a pass.
80
+ - Gate verdicts MUST come from the real harness: MUST NOT obtain a "pass" via `--no-check`; on harness failure, find the root cause first (leaked env vars, nested-invocation guards, wrong cwd …) — MUST NOT label it an "inherent/self-referential property" and bypass it.
81
+ - Before/after criteria (counts, baselines) MUST be measured on the change branch (against the freshly computed merge-base); a value measured on the default branch is usually trivially the baseline and proves nothing.
82
+ - Refactors and bulk replacements: MUST compare the test count before and after; all-green gates with fewer tests is a failure.
83
+
84
+ **On failure → self-heal (don't ask "should I continue?"):**
85
+ 1. Parse the failure cause (test / lint / format / validation).
86
+ 2. Decide if it's a hard-to-locate bug (cause unclear / intermittent flake / regression not obvious at a glance):
87
+ - **Not hard-to-locate** (clear lint/format/compile/validation error): apply a minimal fix (don't expand scope); re-run the minimum failure-repro command first, then all gates.
88
+ - **Hard-to-locate → escalate to the diagnose sub-flow**:
100
89
  1. **First build a command that reproduces the failure** (fast, deterministic, agent-runnable, and goes red on *this* bug) — one that drives the real bug path and asserts the user's exact symptom. **MUST NOT start hypothesizing before such a command exists** (staring at code and guessing is the failure this prevents).
101
90
  2. Run it, confirm red → minimize the repro (cut inputs/calls/config/data one at a time, keep only what's load-bearing).
102
91
  3. Generate **3–5 ranked hypotheses**, each falsifiable ("if X is the cause, changing Y makes the bug disappear").
103
92
  4. Verify one variable at a time; fix once the root cause is found.
104
- 5. If there's no correct seam for a regression test, note the architectural gap (hand off to `llman-sdd-arch-review`; when that skill is not enabled via `extra_skills`, write the gap into this change's `proposal.md` Further Notes section or `design.md`, and MUST NOT break the loop over it).
105
- 3. Re-run the "minimum failure repro command" first, then re-run all gates.
106
- 4. Log as one self-healing round: `Round N: failure → fix → re-run → pass/fail`.
107
-
108
- **Self-healing cap: 8 rounds**; exceeding this is a blocker: stop and output a blocker report (last failing command + output summary + what you tried).
93
+ 5. If there's no correct seam for a regression test, note the architectural gap (hand off to `llman-sdd-arch-review`; when not enabled, write the gap into this change's `proposal.md` Further Notes section or `design.md`, and MUST NOT break the loop over it).
94
+ 3. Re-run the minimum failure-repro command first, then all gates.
95
+ 4. Log one self-healing round: `Round N: failure → fix → re-run → pass/fail`.
109
96
 
110
- **Human review checkpoint (after each task batch passes the gates)**: once a batch is green, before starting the next batch or producing the completion report, run `llman-sdd review`:
97
+ **Self-healing cap: 8 rounds**; exceeding it is a blocker: stop and output a blocker report (last failing command + output summary + what you tried).
111
98
 
112
- - Exit code zero → continue.
113
- - Non-zero exit = CRITICAL findings: STOP, fix, re-run review; MUST NOT enter the next batch or emit the completion report with CRITICAL findings open.
99
+ **Human review gate (after each task batch passes the gates)**: before starting the next batch or emitting the completion report, run `llman-sdd review`: exit code zero → continue; non-zero = CRITICAL findings → STOP, fix, re-run review; MUST NOT enter the next batch or emit the completion report with CRITICAL findings open.
114
100
 
115
101
  ### 6) Completion report
116
- After all tasks complete + all gates green, output a structured report (see Output Contract below).
117
- Then suggest running `llman-sdd-verify` for the verification phase.
118
-
119
- > 💡 Implementation done → next: `llman-sdd-verify` (verify)
102
+ After all tasks complete + all gates green, output a structured report (see Output Contract), then suggest `llman-sdd-verify`.
120
103
 
121
- > For command details run `llman-sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
122
- > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman-sdd list --specs` or `llman-sdd show <capability>`.
104
+ {{ unit("skills/cli-footer") }}
123
105
 
124
106
  {{ unit("skills/validation-hints") }}
125
107
 
@@ -1,27 +1,21 @@
1
1
  ---
2
2
  name: "llman-sdd-arch-review"
3
- description: "Scan codebase for shallow modules (interface nearly equals implementation) and surface deepening candidates. Use when the user wants an architecture review, seeks module deepening opportunities, or wants to improve testability and AI-navigability."
3
+ description: "Architecture review: scan for shallow modules (interface ≈ implementation) and surface deepening candidates to improve testability and AI-navigability."
4
4
  metadata:
5
5
  version: "{{ llman_version }}"
6
6
  ---
7
7
 
8
8
  # LLMAN SDD Architecture Review
9
9
 
10
- Scan the codebase for architectural friction and surface **deepening opportunities** — refactors that turn shallow modules (interface nearly equals implementation) into deep ones (lots of behaviour behind a small interface). The aim is testability and AI-navigability.
11
-
12
- ## Pipeline position
13
-
14
- Auxiliary tool, not part of the main pipeline (explore→propose→apply→verify→archive). Usable at any stage; commonly triggered during explore to surface improvement candidates.
15
-
16
- > 📍 Standalone optional skill; does not replace any pipeline stage.
10
+ Scan the codebase for architectural friction and surface **deepening opportunities** — turning shallow modules (interface ≈ implementation) into deep ones (lots of behavior behind a small interface). The aim is testability and AI-navigability. Auxiliary tool, not part of the main pipeline; usable at any stage, commonly triggered during explore.
17
11
 
18
12
  ## Design vocabulary
19
13
 
20
- A set of words about module shape, used to articulate "where it's worth changing". MUST NOT substitute "component" / "service" / "API" / "boundary" (they are broader, less precise):
14
+ Words about module shape; MUST NOT substitute "component" / "service" / "API" / "boundary" (broader, less precise):
21
15
 
22
16
  - **Module** — anything with an interface and an implementation (function/class/package/cross-layer slice).
23
17
  - **Interface** — everything a caller must know to use it correctly: type signature, plus invariants, ordering constraints, error modes, performance characteristics.
24
- - **Depth** — the amount of behaviour behind the interface. **Deep** = lots of behaviour behind a small interface; **shallow** = interface nearly as complex as the implementation (the caller saves nothing).
18
+ - **Depth** — the amount of behavior behind the interface. **Deep** = lots of behavior behind a small interface; **shallow** = interface nearly as complex as the implementation (the caller saves nothing). This skill turns shallow into deep.
25
19
  - **Seam** — a place where you can swap the implementation without editing call sites (where the interface lives). In llman, seam = the public boundary driven by `*.feature` GWT steps.
26
20
  - **Leverage** — what callers get from depth: more capability per unit of interface learned.
27
21
  - **Locality** — what maintainers get from depth: changes/bugs/knowledge/verification concentrate in one place.
@@ -31,10 +25,10 @@ A set of words about module shape, used to articulate "where it's worth changing
31
25
  ### 1. Explore (scope first, YAGNI)
32
26
  - If the user named a direction (module/subsystem/pain point), accept it; skip inference.
33
27
  - Otherwise walk `git log --oneline` for hot spots (files/areas that keep coming up).
34
- - Prefer reading live `<capability>.feature` (single-track SSOT) and `design.md` (existing ADRs); MUST NOT create a `CONTEXT.md`.
28
+ - Prefer reading `<capability>.feature` (the single source of truth) and `design.md` (existing ADRs); MUST NOT create a `CONTEXT.md`.
35
29
  - Use the Agent tool (`subagent_type=Explore`) to walk the codebase, noting friction:
36
30
  - Does understanding one concept require bouncing between many small modules?
37
- - Where are modules **shallow** (interface nearly as complex as the implementation)?
31
+ - Where are modules **shallow** (interface ≈ implementation complexity, callers save nothing)?
38
32
  - Where are pure functions extracted only for testability, but real bugs hide in how they're called (no locality)?
39
33
  - Which parts are untested or hard to test through their current interface?
40
34
 
@@ -46,20 +40,19 @@ For each candidate:
46
40
  - **Benefits** — locality and leverage improvements; how tests get better.
47
41
  - **Recommendation strength** — `Strong` / `Worth exploring` / `Speculative`.
48
42
 
49
- **Deletion test**: for any suspected-shallow module, imagine deleting it — does complexity vanish (it's just a pass-through, no value) or reappear across N call sites (it's actually earning its keep)? "Reappears" is the signal you want.
43
+ **Deletion test**: for any suspected-shallow module, imagine deleting it — does complexity vanish (it's just a pass-through) or reappear across N call sites (it's actually earning its keep)? "Reappears" is the signal you want.
50
44
 
51
45
  **ADR conflicts**: if a candidate contradicts an existing `design.md` decision, surface it only when the friction is real enough to warrant reopening, and mark it in the candidate.
52
46
 
53
- ### 3. Grilling (after the user picks a candidate)
54
- Run `llman-sdd-explore`'s **grilling branch** (trigger "deep-dig") to walk the decision tree — constraints, dependencies, the deepened module's shape, what sits behind the seam, which tests survive.
47
+ ### 3. Deep-dive Q&A (after the user picks a candidate)
48
+ Run `llman-sdd-explore`'s **deep-dive Q&A branch** (trigger "deep-dig") to walk the decision tree — constraints, dependencies, the deepened module's shape, what sits behind the seam, which tests survive.
55
49
 
56
- - A deepened module uses a concept not in the capability `.feature`? → update live `.feature` **only** if the change already has Branch binding and you are on the bound branch (Specs landing); otherwise STOP and route to `llman-sdd-propose` / `change start` — **never** edit live specs on the default branch.
50
+ - The deepened module uses a concept not in the `.feature`? → update the `.feature` **only** if the change is branch-bound and you are on the bound branch; otherwise STOP and route to `llman-sdd-propose` / `change start` — **never** edit specs on the default branch.
57
51
  - User rejects the candidate with a load-bearing reason? → offer an ADR only when "hard to reverse + surprising without context + real trade-off" all hold; record in `design.md`.
58
52
 
59
53
  ## Output
60
- Candidate list (text; optional HTML report written to OS temp dir, not the repo) + the grilling decision record after the user picks one (write back to proposal; contract edits only via Specs landing into live `.feature`).
54
+ Candidate list (text; optional HTML report written to the OS temp dir, not the repo) + the deep-dive decision record after the user picks one (write back to the proposal; contract edits only after landing on the bound branch into the `.feature`).
61
55
 
62
- > For command details run `llman-sdd <cmd> --help`; the CLI is the command reference — skills embed no command tables.
63
- > "Spec" here = a `.feature` file under this project's `llmanspec/specs/`; run `llman-sdd list --specs` or `llman-sdd show <capability>`.
56
+ {{ unit("skills/cli-footer") }}
64
57
 
65
58
  {{ unit("skills/structured-protocol") }}