cyber-sdd 0.7.0 → 0.7.2

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 (150) hide show
  1. package/.claude-plugin/plugin.json +1 -2
  2. package/.codex-plugin/plugin.json +1 -2
  3. package/CHANGELOG.md +320 -0
  4. package/agents/sdd-scanner.md +1 -1
  5. package/package.json +11 -12
  6. package/plugin.json +55 -0
  7. package/skills/align-spec/SKILL.md +1 -1
  8. package/skills/align-spec/scripts/align-spec.mjs +6755 -12
  9. package/skills/blast-estimate/README.md +3 -3
  10. package/skills/blast-estimate/scripts/blast-estimate.mjs +601 -12
  11. package/skills/check-field-mandates/scripts/check-field-mandates.mjs +253 -12
  12. package/skills/check-partition-quality/scripts/check-partition-quality.mjs +235 -12
  13. package/skills/check-plan-safety/SKILL.md +2 -3
  14. package/skills/check-plan-safety/scripts/check-plan-safety.mjs +109 -12
  15. package/skills/check-plugin-manifests/scripts/check-plugin-manifests.mjs +250 -12
  16. package/skills/check-project-specs/SKILL.md +1 -1
  17. package/skills/check-project-specs/scripts/check-project-specs.mjs +593 -12
  18. package/skills/check-retired-terms/SKILL.md +2 -3
  19. package/skills/check-retired-terms/scripts/check-retired-terms.mjs +186 -12
  20. package/skills/check-scenario-overlap/SKILL.md +1 -2
  21. package/skills/check-scenario-overlap/scripts/check-scenario-overlap.mjs +177 -12
  22. package/skills/check-spec-references/SKILL.md +2 -2
  23. package/skills/check-spec-references/scripts/check-spec-references.mjs +287 -12
  24. package/skills/check-spec-structure/SKILL.md +1 -2
  25. package/skills/check-spec-structure/scripts/check-spec-structure.mjs +243 -12
  26. package/skills/collision-ladder/README.md +2 -2
  27. package/skills/collision-ladder/scripts/collision-ladder.mjs +7047 -12
  28. package/skills/combat-log-governance/SKILL.md +1 -1
  29. package/skills/concept-index/SKILL.md +1 -1
  30. package/skills/concept-index/scripts/concept-index.mjs +183 -12
  31. package/skills/discover-plans/README.md +3 -3
  32. package/skills/discover-plans/SKILL.md +1 -1
  33. package/skills/discover-plans/scripts/discover-plans.mjs +137 -12
  34. package/skills/discover-specs/README.md +3 -3
  35. package/skills/discover-specs/SKILL.md +1 -1
  36. package/skills/discover-specs/scripts/discover-specs.mjs +321 -12
  37. package/skills/doctrine-loop/SKILL.md +1 -1
  38. package/skills/gate-validation-governance/SKILL.md +1 -1
  39. package/skills/init/README.md +2 -2
  40. package/skills/init/scripts/wire-statusline.mjs +168 -12
  41. package/skills/manage-ignore/README.md +3 -3
  42. package/skills/manage-ignore/SKILL.md +1 -2
  43. package/skills/manage-ignore/scripts/manage-ignore.mjs +285 -12
  44. package/skills/manage-scenario-bridge/README.md +3 -3
  45. package/skills/manage-scenario-bridge/SKILL.md +1 -1
  46. package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.mjs +239 -12
  47. package/skills/manage-spec-anchors/README.md +3 -3
  48. package/skills/manage-spec-anchors/SKILL.md +1 -1
  49. package/skills/manage-spec-anchors/scripts/manage-spec-anchors.mjs +310 -12
  50. package/skills/mission-graph/README.md +2 -2
  51. package/skills/mission-graph/SKILL.md +1 -1
  52. package/skills/mission-graph/scripts/mission-graph.mjs +1040 -12
  53. package/skills/pause-mission/SKILL.md +1 -1
  54. package/skills/place-node/SKILL.md +2 -2
  55. package/skills/place-node/scripts/place-node.mjs +117 -12
  56. package/skills/plan-retirement/README.md +2 -2
  57. package/skills/plan-retirement/scripts/retire-plans.mjs +123 -12
  58. package/skills/resolve-governances/README.md +3 -3
  59. package/skills/resolve-governances/SKILL.md +1 -1
  60. package/skills/resolve-governances/scripts/resolve-governances.mjs +352 -12
  61. package/skills/resolve-tracking/SKILL.md +1 -1
  62. package/skills/resolve-tracking/scripts/resolve-tracking.mjs +152 -12
  63. package/skills/scaffold-project-spec/SKILL.md +1 -1
  64. package/skills/spec-gate/README.md +12 -9
  65. package/skills/spec-gate/SKILL.md +2 -2
  66. package/skills/spec-gate/scripts/check-spec-state.mjs +422 -12
  67. package/skills/spec-gate/scripts/check-suite.mjs +6500 -12
  68. package/skills/spec-gate/scripts/classify-edit-class.mjs +6579 -12
  69. package/skills/spec-producer-governance/SKILL.md +2 -2
  70. package/skills/start-mission/SKILL.md +1 -1
  71. package/skills/suite-format-governance/README.md +1 -1
  72. package/skills/suite-format-governance/SKILL.md +1 -1
  73. package/skills/touch-set-correction/README.md +5 -5
  74. package/skills/touch-set-correction/SKILL.md +1 -1
  75. package/skills/touch-set-correction/scripts/touch-set-correction.mjs +6663 -12
  76. package/skills/verify-scenarios/README.md +6 -6
  77. package/skills/verify-scenarios/scripts/verify-scenarios.mjs +6539 -12
  78. package/.plugin/pins.json +0 -3
  79. package/.plugin/plugin.json +0 -19
  80. package/dist/align-spec/scripts/align-spec.js +0 -102
  81. package/dist/check-project-specs/scripts/check-project-specs.js +0 -312
  82. package/dist/check-scenario-overlap/scripts/check-scenario-overlap.js +0 -175
  83. package/dist/check-spec-references/scripts/check-spec-references.js +0 -285
  84. package/dist/check-spec-structure/scripts/check-spec-structure.js +0 -241
  85. package/dist/concept-index/scripts/concept-index.js +0 -181
  86. package/dist/discover-specs/scripts/discover-specs.js +0 -318
  87. package/dist/spec-gate/scripts/check-spec-state.js +0 -420
  88. package/dist/spec-gate/scripts/check-suite.js +0 -317
  89. package/dist/spec-gate/scripts/classify-edit-class.js +0 -263
  90. package/dist/spec-gate/vendor/gherkin-cli.js +0 -6369
  91. package/skills/align-spec/scripts/align-spec.bundle.mjs +0 -6753
  92. package/skills/align-spec/scripts/align-spec.mts +0 -188
  93. package/skills/blast-estimate/scripts/blast-estimate.bundle.mjs +0 -593
  94. package/skills/blast-estimate/scripts/blast-estimate.mts +0 -586
  95. package/skills/check-field-mandates/scripts/check-field-mandates.bundle.mjs +0 -251
  96. package/skills/check-field-mandates/scripts/check-field-mandates.mts +0 -337
  97. package/skills/check-partition-quality/scripts/check-partition-quality.bundle.mjs +0 -233
  98. package/skills/check-partition-quality/scripts/check-partition-quality.mts +0 -338
  99. package/skills/check-plan-safety/scripts/check-plan-safety.bundle.mjs +0 -107
  100. package/skills/check-plan-safety/scripts/check-plan-safety.mts +0 -148
  101. package/skills/check-plugin-manifests/scripts/check-plugin-manifests.bundle.mjs +0 -248
  102. package/skills/check-plugin-manifests/scripts/check-plugin-manifests.mts +0 -303
  103. package/skills/check-project-specs/scripts/check-project-specs.bundle.mjs +0 -584
  104. package/skills/check-project-specs/scripts/check-project-specs.mts +0 -370
  105. package/skills/check-retired-terms/scripts/check-retired-terms.bundle.mjs +0 -184
  106. package/skills/check-retired-terms/scripts/check-retired-terms.mts +0 -293
  107. package/skills/check-scenario-overlap/scripts/check-scenario-overlap.bundle.mjs +0 -175
  108. package/skills/check-scenario-overlap/scripts/check-scenario-overlap.mts +0 -250
  109. package/skills/check-spec-references/scripts/check-spec-references.bundle.mjs +0 -285
  110. package/skills/check-spec-references/scripts/check-spec-references.mts +0 -422
  111. package/skills/check-spec-structure/scripts/check-spec-structure.bundle.mjs +0 -241
  112. package/skills/check-spec-structure/scripts/check-spec-structure.mts +0 -347
  113. package/skills/collision-ladder/scripts/collision-ladder.bundle.mjs +0 -7041
  114. package/skills/collision-ladder/scripts/collision-ladder.mts +0 -662
  115. package/skills/concept-index/scripts/concept-index.bundle.mjs +0 -181
  116. package/skills/concept-index/scripts/concept-index.mts +0 -246
  117. package/skills/discover-plans/scripts/discover-plans.bundle.mjs +0 -135
  118. package/skills/discover-plans/scripts/discover-plans.mts +0 -215
  119. package/skills/discover-specs/scripts/discover-specs.bundle.mjs +0 -319
  120. package/skills/discover-specs/scripts/discover-specs.mts +0 -420
  121. package/skills/init/scripts/wire-statusline.bundle.mjs +0 -166
  122. package/skills/init/scripts/wire-statusline.mts +0 -279
  123. package/skills/manage-ignore/scripts/manage-ignore.bundle.mjs +0 -244
  124. package/skills/manage-ignore/scripts/manage-ignore.mts +0 -297
  125. package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.bundle.mjs +0 -237
  126. package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.mts +0 -159
  127. package/skills/manage-spec-anchors/scripts/manage-spec-anchors.bundle.mjs +0 -308
  128. package/skills/manage-spec-anchors/scripts/manage-spec-anchors.mts +0 -331
  129. package/skills/mission-graph/scripts/mission-graph.bundle.mjs +0 -1038
  130. package/skills/mission-graph/scripts/mission-graph.mts +0 -1333
  131. package/skills/place-node/scripts/place-node.bundle.mjs +0 -115
  132. package/skills/place-node/scripts/place-node.mts +0 -158
  133. package/skills/plan-retirement/scripts/retire-plans.bundle.mjs +0 -121
  134. package/skills/plan-retirement/scripts/retire-plans.mts +0 -205
  135. package/skills/resolve-governances/scripts/resolve-governances.bundle.mjs +0 -350
  136. package/skills/resolve-governances/scripts/resolve-governances.mts +0 -518
  137. package/skills/resolve-tracking/scripts/resolve-tracking.bundle.mjs +0 -150
  138. package/skills/resolve-tracking/scripts/resolve-tracking.mts +0 -214
  139. package/skills/spec-gate/scripts/check-spec-state.bundle.mjs +0 -420
  140. package/skills/spec-gate/scripts/check-spec-state.mts +0 -637
  141. package/skills/spec-gate/scripts/check-suite.bundle.mjs +0 -6498
  142. package/skills/spec-gate/scripts/check-suite.mts +0 -538
  143. package/skills/spec-gate/scripts/classify-edit-class.bundle.mjs +0 -6577
  144. package/skills/spec-gate/scripts/classify-edit-class.mts +0 -414
  145. package/skills/spec-gate/vendor/gherkin-cli.d.mts +0 -2
  146. package/skills/spec-gate/vendor/gherkin-cli.mjs +0 -6545
  147. package/skills/touch-set-correction/scripts/touch-set-correction.bundle.mjs +0 -6655
  148. package/skills/touch-set-correction/scripts/touch-set-correction.mts +0 -429
  149. package/skills/verify-scenarios/scripts/verify-scenarios.bundle.mjs +0 -6537
  150. package/skills/verify-scenarios/scripts/verify-scenarios.mts +0 -470
@@ -1,188 +0,0 @@
1
- #!/usr/bin/env node
2
- // align-spec — project-spec/align-spec's concrete engine. Detects prose↔suite drift across the
3
- // project spec's nodes and, on request, applies the mechanical write primitives a judge-directed
4
- // reconcile step uses (see this skill's README.md / SKILL.md).
5
- //
6
- // The 12 frozen scenarios split two ways (align-spec.feature):
7
- // - Mechanical (this engine ships code + a test for each):
8
- // * a scenario-diff flags a narrowing of the frozen suite → Clearance
9
- // * check mode exits non-zero on drift and writes nothing
10
- // * check mode exits zero when there is no drift
11
- // * detect runs over every node of the project spec (a chosen set)
12
- // * reconcile never writes lifecycle state (writes only prose or scenarios)
13
- // - Judge-orchestrated (SKILL.md documents the procedure; no engine code):
14
- // coverage-gap detection, prose/scenario contradiction detection, the aligned-report-no-
15
- // drift aggregate, and every reconcile *decision* (add a scenario / trim prose / align the
16
- // losing side / escalate a Clearance) — there are no scenario IDs in prose, so prose↔suite
17
- // alignment is judge-only. This engine feeds that judge the mechanical scan (node
18
- // iteration + scenario-diff); it never itself judges coverage or contradiction.
19
- //
20
- // Node iteration and the scenario-diff reuse the existing engines rather than re-implementing
21
- // them: check-spec-structure's scanProjectSpec (node discovery) and spec-gate's classify-edit-
22
- // class (the gherkin-cli-backed structural diff against a frozen baseline).
23
- //
24
- // No dependencies (the repo's node-≥23.6 / no-deps convention). Pure functions are exported for
25
- // node:test; running the file directly drives the CLI.
26
-
27
- import { existsSync, readdirSync, realpathSync } from 'node:fs'
28
- import { isAbsolute, join, relative } from 'node:path'
29
- import { pathToFileURL } from 'node:url'
30
- import { type NodeRecord, scanProjectSpec } from '../../check-spec-structure/scripts/check-spec-structure.mts'
31
- import { classifyFile } from '../../spec-gate/scripts/classify-edit-class.mts'
32
-
33
- export const DEFAULT_BASE = 'HEAD'
34
-
35
- export type DriftKind = 'narrowing'
36
- export type DriftSeverity = 'clearance'
37
-
38
- export interface DriftFinding {
39
- kind: DriftKind
40
- severity: DriftSeverity
41
- /** The node's display path (a folder for a README-rooted node). */
42
- node: string
43
- detail: string
44
- }
45
-
46
- // ── Node selection — the "chosen set" a detect run scopes to ──
47
- // No `--nodes` arg selects every node scanProjectSpec finds; an explicit list scopes the sweep
48
- // to exactly those nodes (matched by display path or the README's relative path).
49
- export function selectNodes(records: NodeRecord[], only?: string[]): NodeRecord[] {
50
- if (!only || only.length === 0) return records
51
- const wanted = new Set(only.map(normalizeNodeRef))
52
- return records.filter((r) => wanted.has(normalizeNodeRef(r.display)) || wanted.has(normalizeNodeRef(r.relPath)))
53
- }
54
-
55
- function normalizeNodeRef(ref: string): string {
56
- return ref
57
- .replace(/\\/g, '/')
58
- .replace(/\/README\.md$/, '')
59
- .replace(/\/+$/, '')
60
- }
61
-
62
- // ── Locate a node's sibling `.feature` file (same convention check-spec-structure scans by) ──
63
- export function findFeaturePath(specDir: string, node: NodeRecord): string | null {
64
- const nodeDir = join(specDir, node.relPath.replace(/README\.md$/, ''))
65
- if (!existsSync(nodeDir)) return null
66
- const entries = readdirSync(nodeDir, { withFileTypes: true })
67
- const feature = entries.find((e) => e.isFile() && e.name.endsWith('.feature'))
68
- return feature ? join(nodeDir, feature.name) : null
69
- }
70
-
71
- // ── Mechanical scenario-diff: a modified/removed baseline scenario is a narrowing → Clearance ──
72
- // Reuses spec-gate's classify-edit-class rather than hand-rolling a line-diff (a line-diff is
73
- // fooled by a step reassigned off a frozen scenario onto a newly-added adjacent one).
74
- export function detectNarrowing(node: NodeRecord, specDir: string, base: string, cwd = '.'): DriftFinding[] {
75
- const featurePath = findFeaturePath(specDir, node)
76
- if (!featurePath) return []
77
- // classifyFile (and the `git show <base>:<path>` it drives) needs a path relative to cwd
78
- // (the git repo root) — resolve it, since specDir/featurePath may already be absolute.
79
- const relFeaturePath = isAbsolute(featurePath) ? relative(cwd, featurePath) : featurePath
80
- const result = classifyFile(relFeaturePath, base, cwd)
81
- if (result.classification !== 'narrowing' && result.classification !== 'mixed') return []
82
- const narrowed = result.scenarios.filter((s) => s.change === 'modified' || s.change === 'removed')
83
- return [
84
- {
85
- kind: 'narrowing',
86
- severity: 'clearance',
87
- node: node.display,
88
- detail: `scenario-diff vs ${base} narrows: ${narrowed.map((s) => s.name).join(', ')} — escalate a Clearance CR, do not silently rewrite`,
89
- },
90
- ]
91
- }
92
-
93
- // Runs the mechanical scan over exactly the chosen node set — reports drift per node.
94
- export function detect(records: NodeRecord[], specDir: string, base: string, cwd = '.'): DriftFinding[] {
95
- return records.flatMap((node) => detectNarrowing(node, specDir, base, cwd))
96
- }
97
-
98
- export function hasDrift(findings: DriftFinding[]): boolean {
99
- return findings.length > 0
100
- }
101
-
102
- // ── The write boundary ──
103
- // Reconcile decisions (add/trim/align/escalate) are judge-orchestrated (SKILL.md), but the
104
- // mechanical write primitives the judge's verdict drives are engine code, and they are built to
105
- // make writing lifecycle state structurally impossible: a README write splits frontmatter from
106
- // body and only ever touches the body; a .feature write only ever appends a whole scenario block.
107
- export interface SplitDocument {
108
- frontmatter: string
109
- body: string
110
- }
111
-
112
- export function splitFrontmatter(text: string): SplitDocument {
113
- const m = /^(---\r?\n[\s\S]*?\r?\n---\s*(?:\r?\n|$))([\s\S]*)$/.exec(text)
114
- if (!m) return { frontmatter: '', body: text }
115
- return { frontmatter: m[1], body: m[2] }
116
- }
117
-
118
- // Trims prose out of a node's README body — the frontmatter (and any status/approval/freeze
119
- // field it carries) passes through byte-for-byte untouched.
120
- export function trimProse(readmeText: string, proseToRemove: string): string {
121
- const { frontmatter, body } = splitFrontmatter(readmeText)
122
- return frontmatter + body.split(proseToRemove).join('')
123
- }
124
-
125
- // Appends a whole scenario block to a `.feature` file. `.feature` files carry no frontmatter /
126
- // lifecycle fields to begin with — this only ever appends, never rewrites an existing scenario
127
- // (a rewrite of an existing frozen scenario is the narrowing path above, which escalates instead).
128
- export function appendScenario(featureText: string, scenarioBlock: string): string {
129
- const trimmed = featureText.replace(/\s+$/, '')
130
- return `${trimmed}\n\n${scenarioBlock.trim()}\n`
131
- }
132
-
133
- // ── Render ──
134
- export function renderFindings(findings: DriftFinding[], specDir: string): string {
135
- const lines: string[] = [`align-spec: spec-dir=${specDir}`, `drift[${findings.length}]:`]
136
- for (const f of findings) lines.push(` ${f.node} — ${f.kind} (${f.severity}): ${f.detail}`)
137
- if (findings.length === 0) lines.push(' (none — mechanical scenario-diff found no narrowing)')
138
- lines.push(
139
- 'note: coverage gaps and prose/scenario contradictions are judge-only (no scenario IDs in prose) — this engine reports only the mechanical scenario-diff',
140
- )
141
- return lines.join('\n')
142
- }
143
-
144
- // ── CLI ──
145
- function parseNodesArg(value: string | undefined): string[] | undefined {
146
- if (!value) return undefined
147
- const parts = value
148
- .split(',')
149
- .map((s) => s.trim())
150
- .filter(Boolean)
151
- return parts.length > 0 ? parts : undefined
152
- }
153
-
154
- export function main(argv: string[]): number {
155
- let specDir = '.'
156
- let base = DEFAULT_BASE
157
- let mode: 'detect' | 'check' = 'detect'
158
- let format: 'toon' | 'json' = 'toon'
159
- let only: string[] | undefined
160
- for (let i = 0; i < argv.length; i++) {
161
- const a = argv[i]
162
- if (a === '--spec-dir') specDir = argv[++i] ?? '.'
163
- else if (a === '--check') mode = 'check'
164
- else if (a === '--base') base = argv[++i] ?? DEFAULT_BASE
165
- else if (a === '--format') format = (argv[++i] as 'toon' | 'json') ?? 'toon'
166
- else if (a === '--nodes') only = parseNodesArg(argv[++i])
167
- }
168
-
169
- const records = selectNodes(scanProjectSpec(specDir), only)
170
- const findings = detect(records, specDir, base)
171
-
172
- if (mode === 'check') {
173
- if (hasDrift(findings)) {
174
- process.stderr.write(`align-spec: ${findings.length} drift finding(s) (mechanical scenario-diff)\n`)
175
- return 1
176
- }
177
- process.stdout.write('align-spec: no mechanical drift\n')
178
- return 0
179
- }
180
-
181
- if (format === 'json') process.stdout.write(`${JSON.stringify(findings)}\n`)
182
- else process.stdout.write(`${renderFindings(findings, specDir)}\n`)
183
- return 0
184
- }
185
-
186
- if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) {
187
- process.exit(main(process.argv.slice(2)))
188
- }