cyber-sdd 0.6.1 → 0.7.1

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 (136) hide show
  1. package/.claude-plugin/plugin.json +1 -2
  2. package/.codex-plugin/plugin.json +1 -2
  3. package/agents/sdd-scanner.md +1 -1
  4. package/agents/sdd-spec-judge.md +3 -3
  5. package/agents/sdd-warden.md +8 -0
  6. package/package.json +11 -13
  7. package/plugin.json +55 -0
  8. package/skills/align-spec/README.md +3 -3
  9. package/skills/align-spec/SKILL.md +2 -2
  10. package/skills/align-spec/scripts/align-spec.mjs +6755 -0
  11. package/skills/architect-impl-governance/SKILL.md +3 -1
  12. package/skills/architect-spec-governance/SKILL.md +5 -1
  13. package/skills/blast-estimate/README.md +4 -4
  14. package/skills/blast-estimate/SKILL.md +1 -1
  15. package/skills/blast-estimate/scripts/blast-estimate.mjs +601 -0
  16. package/skills/check-field-mandates/SKILL.md +1 -1
  17. package/skills/check-field-mandates/scripts/check-field-mandates.mjs +253 -0
  18. package/skills/check-partition-quality/SKILL.md +1 -1
  19. package/skills/check-partition-quality/scripts/check-partition-quality.mjs +235 -0
  20. package/skills/check-plan-safety/README.md +3 -3
  21. package/skills/check-plan-safety/SKILL.md +3 -4
  22. package/skills/check-plan-safety/scripts/check-plan-safety.mjs +109 -0
  23. package/skills/check-plugin-manifests/SKILL.md +1 -1
  24. package/skills/check-plugin-manifests/scripts/check-plugin-manifests.mjs +250 -0
  25. package/skills/check-project-specs/README.md +3 -3
  26. package/skills/check-project-specs/SKILL.md +3 -3
  27. package/{dist/check-project-specs/scripts/check-project-specs.js → skills/check-project-specs/scripts/check-project-specs.mjs} +300 -18
  28. package/skills/check-retired-terms/README.md +2 -2
  29. package/skills/check-retired-terms/SKILL.md +4 -5
  30. package/skills/check-retired-terms/scripts/check-retired-terms.mjs +186 -0
  31. package/skills/check-scenario-overlap/README.md +2 -2
  32. package/skills/check-scenario-overlap/SKILL.md +2 -3
  33. package/{dist/check-scenario-overlap/scripts/check-scenario-overlap.js → skills/check-scenario-overlap/scripts/check-scenario-overlap.mjs} +3 -1
  34. package/skills/check-spec-references/README.md +1 -1
  35. package/skills/check-spec-references/SKILL.md +3 -3
  36. package/{dist/check-spec-references/scripts/check-spec-references.js → skills/check-spec-references/scripts/check-spec-references.mjs} +3 -1
  37. package/skills/check-spec-structure/README.md +2 -2
  38. package/skills/check-spec-structure/SKILL.md +2 -3
  39. package/{dist/check-spec-structure/scripts/check-spec-structure.js → skills/check-spec-structure/scripts/check-spec-structure.mjs} +3 -1
  40. package/skills/collision-ladder/README.md +2 -2
  41. package/skills/collision-ladder/SKILL.md +2 -2
  42. package/skills/collision-ladder/scripts/collision-ladder.mjs +7047 -0
  43. package/skills/combat-log-governance/SKILL.md +1 -1
  44. package/skills/concept-index/README.md +2 -2
  45. package/skills/concept-index/SKILL.md +2 -2
  46. package/{dist/concept-index/scripts/concept-index.js → skills/concept-index/scripts/concept-index.mjs} +3 -1
  47. package/skills/discover-plans/README.md +5 -5
  48. package/skills/discover-plans/SKILL.md +2 -2
  49. package/skills/discover-plans/scripts/discover-plans.mjs +137 -0
  50. package/skills/discover-specs/README.md +4 -4
  51. package/skills/discover-specs/SKILL.md +2 -2
  52. package/{dist/discover-specs/scripts/discover-specs.js → skills/discover-specs/scripts/discover-specs.mjs} +4 -1
  53. package/skills/doctrine-loop/SKILL.md +2 -2
  54. package/skills/formation-loop/SKILL.md +10 -0
  55. package/skills/gate-validation-governance/SKILL.md +2 -2
  56. package/skills/init/README.md +5 -5
  57. package/skills/init/SKILL.md +3 -3
  58. package/skills/init/scripts/wire-statusline.mjs +168 -0
  59. package/skills/manage-ignore/README.md +8 -8
  60. package/skills/manage-ignore/SKILL.md +2 -3
  61. package/skills/manage-ignore/scripts/manage-ignore.mjs +285 -0
  62. package/skills/manage-scenario-bridge/README.md +6 -6
  63. package/skills/manage-scenario-bridge/SKILL.md +2 -2
  64. package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.mjs +239 -0
  65. package/skills/manage-spec-anchors/README.md +7 -7
  66. package/skills/manage-spec-anchors/SKILL.md +2 -2
  67. package/skills/manage-spec-anchors/scripts/manage-spec-anchors.mjs +310 -0
  68. package/skills/mission-graph/README.md +2 -2
  69. package/skills/mission-graph/SKILL.md +10 -10
  70. package/skills/mission-graph/scripts/mission-graph.mjs +1040 -0
  71. package/skills/pause-mission/SKILL.md +2 -2
  72. package/skills/place-node/README.md +1 -1
  73. package/skills/place-node/SKILL.md +3 -3
  74. package/skills/place-node/scripts/place-node.mjs +117 -0
  75. package/skills/plan-retirement/README.md +2 -2
  76. package/skills/plan-retirement/SKILL.md +1 -1
  77. package/skills/plan-retirement/scripts/retire-plans.mjs +123 -0
  78. package/skills/resolve-governances/README.md +4 -4
  79. package/skills/resolve-governances/SKILL.md +2 -2
  80. package/skills/resolve-governances/scripts/resolve-governances.mjs +352 -0
  81. package/skills/resolve-tracking/SKILL.md +2 -2
  82. package/skills/resolve-tracking/scripts/resolve-tracking.mjs +152 -0
  83. package/skills/scaffold-project-spec/SKILL.md +3 -3
  84. package/skills/sdd/SKILL.md +1 -1
  85. package/skills/spec-gate/README.md +12 -9
  86. package/skills/spec-gate/SKILL.md +6 -6
  87. package/{dist/spec-gate/scripts/check-spec-state.js → skills/spec-gate/scripts/check-spec-state.mjs} +3 -1
  88. package/{dist/spec-gate/vendor/gherkin-cli.js → skills/spec-gate/scripts/check-suite.mjs} +319 -188
  89. package/skills/spec-gate/{vendor/gherkin-cli.mjs → scripts/classify-edit-class.mjs} +243 -209
  90. package/skills/spec-producer-governance/SKILL.md +4 -4
  91. package/skills/spec-structure-governance/README.md +4 -2
  92. package/skills/spec-structure-governance/SKILL.md +42 -7
  93. package/skills/start-mission/SKILL.md +2 -2
  94. package/skills/suite-format-governance/README.md +1 -1
  95. package/skills/suite-format-governance/SKILL.md +1 -1
  96. package/skills/touch-set-correction/README.md +5 -5
  97. package/skills/touch-set-correction/SKILL.md +2 -2
  98. package/skills/touch-set-correction/scripts/touch-set-correction.mjs +6663 -0
  99. package/skills/verify-scenarios/README.md +9 -9
  100. package/skills/verify-scenarios/SKILL.md +2 -2
  101. package/skills/verify-scenarios/scripts/verify-scenarios.mjs +6539 -0
  102. package/.plugin/pins.json +0 -3
  103. package/.plugin/plugin.json +0 -19
  104. package/dist/align-spec/scripts/align-spec.js +0 -102
  105. package/dist/spec-gate/scripts/check-suite.js +0 -317
  106. package/dist/spec-gate/scripts/classify-edit-class.js +0 -263
  107. package/skills/align-spec/scripts/align-spec.mts +0 -188
  108. package/skills/blast-estimate/scripts/blast-estimate.mts +0 -586
  109. package/skills/check-field-mandates/scripts/check-field-mandates.mts +0 -337
  110. package/skills/check-partition-quality/scripts/check-partition-quality.mts +0 -338
  111. package/skills/check-plan-safety/scripts/check-plan-safety.mts +0 -148
  112. package/skills/check-plugin-manifests/scripts/check-plugin-manifests.mts +0 -303
  113. package/skills/check-project-specs/scripts/check-project-specs.mts +0 -369
  114. package/skills/check-retired-terms/scripts/check-retired-terms.mts +0 -293
  115. package/skills/check-scenario-overlap/scripts/check-scenario-overlap.mts +0 -250
  116. package/skills/check-spec-references/scripts/check-spec-references.mts +0 -422
  117. package/skills/check-spec-structure/scripts/check-spec-structure.mts +0 -347
  118. package/skills/collision-ladder/scripts/collision-ladder.mts +0 -660
  119. package/skills/concept-index/scripts/concept-index.mts +0 -246
  120. package/skills/discover-plans/scripts/discover-plans.mts +0 -215
  121. package/skills/discover-specs/scripts/discover-specs.mts +0 -420
  122. package/skills/init/scripts/wire-statusline.mts +0 -279
  123. package/skills/manage-ignore/scripts/manage-ignore.mts +0 -297
  124. package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.mts +0 -159
  125. package/skills/manage-spec-anchors/scripts/manage-spec-anchors.mts +0 -331
  126. package/skills/mission-graph/scripts/mission-graph.mts +0 -1333
  127. package/skills/place-node/scripts/place-node.mts +0 -158
  128. package/skills/plan-retirement/scripts/retire-plans.mts +0 -199
  129. package/skills/resolve-governances/scripts/resolve-governances.mts +0 -518
  130. package/skills/resolve-tracking/scripts/resolve-tracking.mts +0 -214
  131. package/skills/spec-gate/scripts/check-spec-state.mts +0 -637
  132. package/skills/spec-gate/scripts/check-suite.mts +0 -538
  133. package/skills/spec-gate/scripts/classify-edit-class.mts +0 -414
  134. package/skills/spec-gate/vendor/gherkin-cli.d.mts +0 -2
  135. package/skills/touch-set-correction/scripts/touch-set-correction.mts +0 -420
  136. package/skills/verify-scenarios/scripts/verify-scenarios.mts +0 -470
@@ -13,8 +13,7 @@ retires a path, directory, or naming convention, and records it once in
13
13
  `.agents/sdd/retired-terms.toml`. This engine guards that the retirement holds: it scans every
14
14
  git-tracked file in the repo — not only the node someone happened to touch — for a literal,
15
15
  case-sensitive occurrence of a registered term, and reports every survivor as `file:line:term` with
16
- the replacement to use. It carries a self-contained `.mts` script (the repo's node-≥23.6 / no-deps
17
- convention), parsing the registry with the same minimal hand-rolled TOML subset `discover-specs`
16
+ the replacement to use. It carries a self-contained `.mjs` script (compiled from `src/`; no runtime deps, Node ≥22.11), parsing the registry with the same minimal hand-rolled TOML subset `discover-specs`
18
17
  already uses for `spec-anchors.toml`.
19
18
 
20
19
  It is the corpus-wide, declared-data sibling of `check:metaphor-free`
@@ -56,8 +55,8 @@ allow = [ # optional: sanctioned occurrenc
56
55
  ## Run the scan
57
56
 
58
57
  ```bash
59
- node "<skill>/scripts/check-retired-terms.mts" [--root .] # the verify-time sweep
60
- node "<skill>/scripts/check-retired-terms.mts" [--root .] --list # what is registered
58
+ node "<skill>/scripts/check-retired-terms.mjs" [--root .] # the verify-time sweep
59
+ node "<skill>/scripts/check-retired-terms.mjs" [--root .] --list # what is registered
61
60
  ```
62
61
 
63
62
  - Default `--root` is the current directory.
@@ -67,7 +66,7 @@ node "<skill>/scripts/check-retired-terms.mts" [--root .] --list # what is regi
67
66
  non-zero, because the registry *is* the check.
68
67
  - **`--list`** prints each registered term with its `since` and `replacement`, and exits 0. With no
69
68
  registry, it states plainly that nothing is registered — a definitive empty state, not silence.
70
- - Wired into `check:specs` (`node …/check-retired-terms.mts --root .`), so it runs on every
69
+ - Wired into `check:specs` (`node …/check-retired-terms.mjs --root .`), so it runs on every
71
70
  `pnpm verify` and in CI.
72
71
 
73
72
  When `node` is absent, an agent performs the same derivation by hand: read
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env node
2
+ // Compiled by `universal-plugin plugin build` from src/check-retired-terms/check-retired-terms.mts. Edit the source, not this file.
3
+ globalThis.__SKILL_SCRIPT__ = {"package":null,"bin":null,"version":"0.7.1","entry":"skills/check-retired-terms/scripts/check-retired-terms.mjs","commands":{}};
4
+ import { execFileSync } from "node:child_process";
5
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
6
+ import { join } from "node:path";
7
+ import { pathToFileURL } from "node:url";
8
+ //#region src/check-retired-terms/check-retired-terms.mts
9
+ var RegistryParseError = class extends Error {};
10
+ const REGISTRY_PATH = ".agents/sdd/retired-terms.toml";
11
+ function isBlankOrComment(line) {
12
+ const t = line.trim();
13
+ return t === "" || t.startsWith("#");
14
+ }
15
+ function extractString(block, key) {
16
+ const m = new RegExp(`(^|\\n)\\s*${key}\\s*=\\s*"([^"]*)"[^\\n]*`).exec(block);
17
+ if (!m) throw new RegistryParseError(`[[retired]] entry is missing a string "${key}"`);
18
+ return m[2];
19
+ }
20
+ function extractArray(block, key) {
21
+ const openMatch = new RegExp(`(^|\\n)\\s*${key}\\s*=\\s*\\[`).exec(block);
22
+ if (!openMatch) return [];
23
+ const openIdx = openMatch.index + openMatch[0].length - 1;
24
+ const closeIdx = block.indexOf("]", openIdx);
25
+ if (closeIdx === -1) throw new RegistryParseError(`"${key}" array is never closed with "]"`);
26
+ const arrText = block.slice(openIdx, closeIdx);
27
+ const out = [];
28
+ for (const q of arrText.matchAll(/"([^"]*)"/g)) out.push(q[1]);
29
+ return out;
30
+ }
31
+ /** Parses the registry's minimal TOML subset: an array of `[[retired]]` tables carrying string
32
+ * keys (term/since/replacement, all required) and optional string-array keys (scope/allow). Throws
33
+ * `RegistryParseError` on anything that does not fit that shape — an absent registry is handled by
34
+ * the caller (`readRegistry`), not here; an empty/comment-only file parses to `[]`. */
35
+ function parseRegistryToml(text) {
36
+ const marker = "[[retired]]";
37
+ const firstIdx = text.indexOf(marker);
38
+ if (firstIdx === -1) {
39
+ if (text.split("\n").every(isBlankOrComment)) return [];
40
+ throw new RegistryParseError("no [[retired]] table found and the file is not empty/comment-only");
41
+ }
42
+ if (!text.slice(0, firstIdx).split("\n").every(isBlankOrComment)) throw new RegistryParseError("content found before the first [[retired]] table header");
43
+ return text.slice(firstIdx).split(marker).slice(1).map((block) => {
44
+ const term = extractString(block, "term");
45
+ const since = extractString(block, "since");
46
+ const replacement = extractString(block, "replacement");
47
+ const scope = extractArray(block, "scope");
48
+ const allow = extractArray(block, "allow");
49
+ const entry = {
50
+ term,
51
+ since,
52
+ replacement
53
+ };
54
+ if (scope.length) entry.scope = scope;
55
+ if (allow.length) entry.allow = allow;
56
+ return entry;
57
+ });
58
+ }
59
+ /** Reads and parses the registry at `<root>/.agents/sdd/retired-terms.toml`. An absent file yields
60
+ * `[]` (an "an absent registry sweeps clean" registry, not an error). A present-but-malformed file
61
+ * throws `RegistryParseError` — the caller must surface that loudly and exit non-zero. */
62
+ function readRegistry(root) {
63
+ const file = join(root, REGISTRY_PATH);
64
+ if (!existsSync(file)) return [];
65
+ return parseRegistryToml(readFileSync(file, "utf8"));
66
+ }
67
+ const DEFAULT_BUILTIN_EXCLUDED_FILES = [
68
+ REGISTRY_PATH,
69
+ "plugins/sdd/src/check-retired-terms/check-retired-terms.mts",
70
+ "plugins/sdd/src/check-retired-terms/check-retired-terms.test.mts",
71
+ ".agents/specs/sdd/corpus/retired-terms/README.md",
72
+ ".agents/specs/sdd/corpus/retired-terms/retired-terms.feature"
73
+ ];
74
+ const DEFAULT_BUILTIN_EXCLUDED_PREFIXES = [".agents/plans/"];
75
+ function isUnderLedgerDir(relPath) {
76
+ return relPath.split("/").slice(0, -1).includes("ledger");
77
+ }
78
+ function isBuiltinExcluded(relPath, excludedFiles, excludedPrefixes) {
79
+ if (excludedFiles.includes(relPath)) return true;
80
+ if (excludedPrefixes.some((p) => relPath.startsWith(p))) return true;
81
+ if (isUnderLedgerDir(relPath)) return true;
82
+ return false;
83
+ }
84
+ function inScope(relPath, scope) {
85
+ if (!scope || scope.length === 0) return true;
86
+ return scope.some((prefix) => relPath.startsWith(prefix));
87
+ }
88
+ function parseAllowEntry(raw) {
89
+ const idx = raw.indexOf("::");
90
+ if (idx === -1) return { file: raw.trim() };
91
+ return {
92
+ file: raw.slice(0, idx).trim(),
93
+ substring: raw.slice(idx + 2).trim()
94
+ };
95
+ }
96
+ function isAllowed(relPath, lineText, allow) {
97
+ if (!allow) return false;
98
+ for (const raw of allow) {
99
+ const parsed = parseAllowEntry(raw);
100
+ if (parsed.file !== relPath) continue;
101
+ if (parsed.substring === void 0) return true;
102
+ if (lineText.includes(parsed.substring)) return true;
103
+ }
104
+ return false;
105
+ }
106
+ /** The git-tracked file set, repo-relative, one per line. An untracked file is outside the sweep
107
+ * by construction — it is never in this list. */
108
+ function listTrackedFiles(root) {
109
+ return execFileSync("git", ["ls-files"], {
110
+ cwd: root,
111
+ encoding: "utf8"
112
+ }).split("\n").filter((l) => l !== "");
113
+ }
114
+ /** Sweeps `root` for survivors of every entry in `entries`. `options` lets callers (tests)
115
+ * substitute fixture-scoped config — the tracked-file source and the built-in exclusion lists —
116
+ * in place of the real repo and the real defaults, mirroring `findMetaphorViolations`'s
117
+ * `ScanOptions` (packages/cyberlegion/src/metaphor-free.ts). */
118
+ function sweep(root, entries, options = {}) {
119
+ const listFiles = options.listTrackedFiles ?? listTrackedFiles;
120
+ const excludedFiles = options.builtinExcludedFiles ?? DEFAULT_BUILTIN_EXCLUDED_FILES;
121
+ const excludedPrefixes = options.builtinExcludedPrefixes ?? DEFAULT_BUILTIN_EXCLUDED_PREFIXES;
122
+ const violations = [];
123
+ for (const relPath of listFiles(root)) {
124
+ if (isBuiltinExcluded(relPath, excludedFiles, excludedPrefixes)) continue;
125
+ let text;
126
+ try {
127
+ text = readFileSync(join(root, relPath), "utf8");
128
+ } catch {
129
+ continue;
130
+ }
131
+ const lines = text.split("\n");
132
+ for (const entry of entries) {
133
+ if (!inScope(relPath, entry.scope)) continue;
134
+ lines.forEach((lineText, i) => {
135
+ if (!lineText.includes(entry.term)) return;
136
+ if (isAllowed(relPath, lineText, entry.allow)) return;
137
+ violations.push({
138
+ file: relPath,
139
+ line: i + 1,
140
+ term: entry.term,
141
+ replacement: entry.replacement
142
+ });
143
+ });
144
+ }
145
+ }
146
+ return violations.sort((a, b) => a.file !== b.file ? a.file < b.file ? -1 : 1 : a.line - b.line);
147
+ }
148
+ /** Renders `--list` output: one line per registered term with its `since` and `replacement`, or a
149
+ * definitive empty-state line when nothing is registered — never silence. */
150
+ function formatList(entries) {
151
+ if (entries.length === 0) return "check-retired-terms: no term is registered\n";
152
+ return entries.map((e) => `${e.term} (since ${e.since}) -> ${e.replacement}\n`).join("");
153
+ }
154
+ /** Renders the sweep report: `file:line:term` plus the declared replacement, one per survivor
155
+ * (every survivor, not just the first), then a count summary. */
156
+ function formatViolations(violations) {
157
+ const lines = violations.map((v) => `${v.file}:${v.line}:${v.term} — replace with: ${v.replacement}\n`);
158
+ lines.push(`check-retired-terms: ${violations.length} survivor(s) found\n`);
159
+ return lines.join("");
160
+ }
161
+ function main(argv) {
162
+ const root = argv.includes("--root") ? argv[argv.indexOf("--root") + 1] ?? "." : ".";
163
+ const list = argv.includes("--list");
164
+ let entries;
165
+ try {
166
+ entries = readRegistry(root);
167
+ } catch (err) {
168
+ const message = err instanceof Error ? err.message : String(err);
169
+ process.stderr.write(`check-retired-terms: malformed registry — ${message}\n`);
170
+ return 1;
171
+ }
172
+ if (list) {
173
+ process.stdout.write(formatList(entries));
174
+ return 0;
175
+ }
176
+ const violations = sweep(root, entries);
177
+ if (violations.length === 0) {
178
+ process.stdout.write("check-retired-terms: clean — no survivors found\n");
179
+ return 0;
180
+ }
181
+ process.stdout.write(formatViolations(violations));
182
+ return 1;
183
+ }
184
+ if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) process.exit(main(process.argv.slice(2)));
185
+ //#endregion
186
+ export { RegistryParseError, formatList, formatViolations, listTrackedFiles, main, parseRegistryToml, readRegistry, sweep };
@@ -6,8 +6,8 @@ one node's `.feature`**, for the formation Warden: the intra-project **spec-leve
6
6
  collision ladder, and the cross-node sibling of `check-spec-structure` (intra-node node-shape).
7
7
 
8
8
  ```bash
9
- node scripts/check-scenario-overlap.mts --spec-dir <spec> # audit (TOON candidate set)
10
- node scripts/check-scenario-overlap.mts --spec-dir <spec> --check # CI guard (fails on exact-duplicate)
9
+ node scripts/check-scenario-overlap.mjs --spec-dir <spec> # audit (TOON candidate set)
10
+ node scripts/check-scenario-overlap.mjs --spec-dir <spec> --check # CI guard (fails on exact-duplicate)
11
11
  ```
12
12
 
13
13
  Two deterministic candidate kinds — **exact-duplicate** (blocking: two nodes share an identical
@@ -12,8 +12,7 @@ The concrete engine for **cross-node scenario-overlap detection** — the intra-
12
12
  SSA** partner of the code-side collision ladder. It audits **across the nodes** of one project spec
13
13
  and returns the candidates where the **same behavior lives in more than one node's `.feature`**, for
14
14
  the formation **Warden**. It is the **cross-node** sibling of `check-spec-structure` (intra-node
15
- node-shape), whose per-node scope leaves this cross-node axis uncovered. Self-contained `.mts` (the
16
- repo's node-≥23.6 / no-deps convention).
15
+ node-shape), whose per-node scope leaves this cross-node axis uncovered. Self-contained `.mjs` (compiled from `src/`; no runtime deps, Node ≥22.11).
17
16
 
18
17
  ## Why this rung exists
19
18
 
@@ -48,7 +47,7 @@ only**: a scenario duplicated **within one node** raises no candidate, and a sce
48
47
  ## Run the scan
49
48
 
50
49
  ```bash
51
- node "<skill>/scripts/check-scenario-overlap.mts" [--spec-dir <spec>] [--check] [--format toon|json]
50
+ node "<skill>/scripts/check-scenario-overlap.mjs" [--spec-dir <spec>] [--check] [--format toon|json]
52
51
  ```
53
52
 
54
53
  - Default `--spec-dir` is the current directory; default `--format` is **TOON** (the token-efficient
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ // Compiled by `universal-plugin plugin build` from src/check-scenario-overlap/check-scenario-overlap.mts. Edit the source, not this file.
3
+ globalThis.__SKILL_SCRIPT__ = {"package":null,"bin":null,"version":"0.7.1","entry":"skills/check-scenario-overlap/scripts/check-scenario-overlap.mjs","commands":{}};
2
4
  import { readFileSync, readdirSync, realpathSync } from "node:fs";
3
5
  import { join } from "node:path";
4
6
  import { pathToFileURL } from "node:url";
5
- //#region skills/check-scenario-overlap/scripts/check-scenario-overlap.mts
7
+ //#region src/check-scenario-overlap/check-scenario-overlap.mts
6
8
  const SKIP_DIRS = /* @__PURE__ */ new Set([
7
9
  "node_modules",
8
10
  ".git",
@@ -5,7 +5,7 @@ Internal SDD skill — the concrete engine for the **spec-reference resolution c
5
5
  directory, and reports the ones that resolve to nothing.
6
6
 
7
7
  ```bash
8
- node scripts/check-spec-references.mts --spec-dir <specDir>
8
+ node scripts/check-spec-references.mjs --spec-dir <specDir>
9
9
  ```
10
10
 
11
11
  Exits non-zero on any unresolved reference, reporting each as `file:line: <ref> -> <resolved path>` — naming the resolved path is the
@@ -12,8 +12,8 @@ The concrete engine for the **spec-reference resolution check**. It walks every
12
12
  project spec, extracts each **explicitly-relative** reference, resolves it **against the file's own
13
13
  directory**, and fails on every one that resolves to nothing. Read-only, deterministic, and — unlike
14
14
  its `check-spec-structure` sibling — single-severity: a reference that does not resolve is always a
15
- defect, so there is one mode, not a report mode and a gate mode. It carries a self-contained `.mts`
16
- script (the repo's node-≥23.6 / no-deps convention).
15
+ defect, so there is one mode, not a report mode and a gate mode. It carries a self-contained `.mjs`
16
+ script (compiled from `src/`; no runtime deps, Node ≥22.11).
17
17
 
18
18
  It closes a failure **review cannot catch**: a consistent off-by-one reads as entirely plausible —
19
19
  right filename, right-looking depth, wrong level — so re-reading a reference by eye is not a check
@@ -70,7 +70,7 @@ from **outside the code spans**, so a line that merely quotes the marker keeps i
70
70
  ## Run the check
71
71
 
72
72
  ```bash
73
- node "<skill>/scripts/check-spec-references.mts" --spec-dir <specDir>
73
+ node "<skill>/scripts/check-spec-references.mjs" --spec-dir <specDir>
74
74
  ```
75
75
 
76
76
  - Exits **zero** on a spec whose every reference resolves, printing a definitive clean line.
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ // Compiled by `universal-plugin plugin build` from src/check-spec-references/check-spec-references.mts. Edit the source, not this file.
3
+ globalThis.__SKILL_SCRIPT__ = {"package":null,"bin":null,"version":"0.7.1","entry":"skills/check-spec-references/scripts/check-spec-references.mjs","commands":{}};
2
4
  import { existsSync, readFileSync, readdirSync, realpathSync } from "node:fs";
3
5
  import { dirname, join, relative, resolve } from "node:path";
4
6
  import { pathToFileURL } from "node:url";
5
- //#region skills/check-spec-references/scripts/check-spec-references.mts
7
+ //#region src/check-spec-references/check-spec-references.mts
6
8
  /** Suppresses every reference on the line it appears on. Matched as a COMPLETE html comment, not
7
9
  * as a substring: a marker whose name merely starts with this one's (a typo, a future sibling)
8
10
  * must not silently inherit its power to hide a reference. The optional `: reason` is convention,
@@ -5,8 +5,8 @@ internal node-shape and emits a finding set for the formation Warden: the intra-
5
5
  retired cross-spec `dedupe-specs`/`split-spec` tools, now that one project is one spec.
6
6
 
7
7
  ```bash
8
- node scripts/check-spec-structure.mts --spec-dir <spec> # audit (TOON finding set)
9
- node scripts/check-spec-structure.mts --spec-dir <spec> --check # CI guard (fails on blocking)
8
+ node scripts/check-spec-structure.mjs --spec-dir <spec> # audit (TOON finding set)
9
+ node scripts/check-spec-structure.mjs --spec-dir <spec> --check # CI guard (fails on blocking)
10
10
  ```
11
11
 
12
12
  Three deterministic checks — **untagged-node** (blocking: a spec-typed node with no `concept:`),
@@ -11,8 +11,7 @@ metadata:
11
11
  The concrete engine for **spec-structure checking**.
12
12
  It audits the **internal node-shape** of one project spec and returns a finding set for the
13
13
  formation **Warden** — the **intra-spec** successor to the retired cross-spec `dedupe-specs`/`split-spec`
14
- tools, now that one project is **one spec**. It carries a self-contained `.mts` script (the repo's
15
- node-≥23.6 / no-deps convention). It is the **node-shape** sibling of `align-spec` (prose↔suite
14
+ tools, now that one project is **one spec**. It carries a self-contained `.mjs` script (compiled from `src/`; no runtime deps, Node ≥22.11). It is the **node-shape** sibling of `align-spec` (prose↔suite
16
15
  alignment) and `concept-index` (the by-concept view).
17
16
 
18
17
  ## The three deterministic checks (and two judgment arms)
@@ -42,7 +41,7 @@ alignment) and `concept-index` (the by-concept view).
42
41
  ## Run the scan
43
42
 
44
43
  ```bash
45
- node "<skill>/scripts/check-spec-structure.mts" [--spec-dir <spec>] [--check] [--max-scenarios <n>] [--format toon|json]
44
+ node "<skill>/scripts/check-spec-structure.mjs" [--spec-dir <spec>] [--check] [--max-scenarios <n>] [--format toon|json]
46
45
  ```
47
46
 
48
47
  - Default `--spec-dir` is the current directory; default `--format` is **TOON** (the token-efficient
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ // Compiled by `universal-plugin plugin build` from src/check-spec-structure/check-spec-structure.mts. Edit the source, not this file.
3
+ globalThis.__SKILL_SCRIPT__ = {"package":null,"bin":null,"version":"0.7.1","entry":"skills/check-spec-structure/scripts/check-spec-structure.mjs","commands":{}};
2
4
  import { existsSync, readFileSync, readdirSync, realpathSync } from "node:fs";
3
5
  import { join } from "node:path";
4
6
  import { pathToFileURL } from "node:url";
5
- //#region skills/check-spec-structure/scripts/check-spec-structure.mts
7
+ //#region src/check-spec-structure/check-spec-structure.mts
6
8
  const SKIP_DIRS = /* @__PURE__ */ new Set([
7
9
  "node_modules",
8
10
  ".git",
@@ -11,6 +11,6 @@ cyberplace repository, not shipped in this package) carries the authoritative be
11
11
  and the frozen 18-scenario contract.
12
12
 
13
13
  - **Skill contract:** [`SKILL.md`](./SKILL.md)
14
- - **Script:** [`scripts/collision-ladder.mts`](./scripts/collision-ladder.mts)
15
- - **Tests:** [`scripts/collision-ladder.test.mts`](./scripts/collision-ladder.test.mts)
14
+ - **Script:** [`scripts/collision-ladder.mjs`](./scripts/collision-ladder.mjs)
15
+ - **Tests:** [`src/collision-ladder/collision-ladder.test.mts`](../../src/collision-ladder/collision-ladder.test.mts)
16
16
  (`node:test`) — one test per frozen scenario, titled `scenario: <verbatim frozen scenario name>`.
@@ -57,10 +57,10 @@ engine's composition.
57
57
 
58
58
  ```bash
59
59
  # constructed input (a ClassifyInput JSON) — the primary, tested path:
60
- node "<skill>/scripts/collision-ladder.mts" --input <file|-> [--format toon|json]
60
+ node "<skill>/scripts/collision-ladder.mjs" --input <file|-> [--format toon|json]
61
61
 
62
62
  # sourced from two mission git ranges for one colliding node:
63
- node "<skill>/scripts/collision-ladder.mts" --from-git --node <project/capability> \
63
+ node "<skill>/scripts/collision-ladder.mjs" --from-git --node <project/capability> \
64
64
  --x <base..head> --y <base..head> [--root .] \
65
65
  [--layout 'sdd:.agents/specs/sdd,plugins/sdd/skills']... \
66
66
  [--shared-thin-threshold 3] [--format toon|json]