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
@@ -71,7 +71,7 @@ procedure above, plus one gate before declaring the plan retirement-ready:
71
71
  escape hatch — no suite-relevant behavior, no CR opened, no gate invoked) needs none; mark it
72
72
  complete on its own merits.
73
73
  - **Run the gate floor.** Run `checkGateFloor` (`plugins/sdd/skills/spec-gate/scripts/
74
- check-spec-state.mts`, wired into `pnpm verify:specs`) before marking the plan
74
+ check-spec-state.mjs`, wired into `pnpm verify:specs`) before marking the plan
75
75
  retirement-ready. A clean floor → mark it. A violation (the status is approved/implemented but
76
76
  the ledger has no matching gate approve line) → do **not** mark the plan retirement-ready on
77
77
  git evidence alone; record the violation explicitly in `## NEXT` so a human resolves it (either
@@ -11,8 +11,8 @@ metadata:
11
11
  The concrete engine for the **place-node** step. Given a new
12
12
  node's `concept` (and optional name), it suggests a **provisional** capability home and catches possible
13
13
  duplicates, so explore places a node without holding the whole tree in its head (it scans the project-spec's
14
- `concept:` frontmatter and ranks the capability folders those facets already sit in). Self-contained `.mts`
15
- (the repo's node-≥23.6 / no-deps convention).
14
+ `concept:` frontmatter and ranks the capability folders those facets already sit in). Self-contained `.mjs`
15
+ (compiled from `src/`; no runtime deps, Node ≥22.11).
16
16
 
17
17
  ## Run it
18
18
 
@@ -1,12 +1,117 @@
1
- // Launcher for the engine of the same name. Run it as `node <skill>/scripts/<engine>.mjs`.
2
- // A checkout runs the .mts source. An npm install keeps the skill under node_modules, where Node
3
- // will not strip types, so it runs the self-contained bundle built for the package.
4
- import { spawnSync } from 'node:child_process'
5
- import { fileURLToPath } from 'node:url'
6
-
7
- const self = fileURLToPath(import.meta.url)
8
- const installed = /[\\/]node_modules[\\/]/.test(self)
9
- const target = self.replace(/\.mjs$/, installed ? '.bundle.mjs' : '.mts')
10
- const run = spawnSync(process.execPath, [...process.execArgv, target, ...process.argv.slice(2)], { stdio: 'inherit' })
11
- if (run.error) throw run.error
12
- process.exitCode = run.status ?? 1
1
+ #!/usr/bin/env node
2
+ // Compiled by `universal-plugin plugin build` from src/place-node/place-node.mts. Edit the source, not this file.
3
+ globalThis.__SKILL_SCRIPT__ = {"package":null,"bin":null,"version":"0.7.2","entry":"skills/place-node/scripts/place-node.mjs","commands":{}};
4
+ import { readFileSync, readdirSync, realpathSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { pathToFileURL } from "node:url";
7
+ //#region src/place-node/place-node.mts
8
+ const SKIP_DIRS = /* @__PURE__ */ new Set([
9
+ "node_modules",
10
+ ".git",
11
+ "dist",
12
+ ".turbo",
13
+ ".next",
14
+ "coverage"
15
+ ]);
16
+ function parseConcepts(text) {
17
+ const m = /^---\r?\n([\s\S]*?)\r?\n---\s*(?:\r?\n|$)/.exec(text);
18
+ if (!m) return [];
19
+ const lines = m[1].split("\n").map((l) => l.replace(/\r$/, ""));
20
+ for (let i = 0; i < lines.length; i++) {
21
+ const line = lines[i];
22
+ if (line.length - line.trimStart().length !== 0) continue;
23
+ const [key, ...rest] = line.trim().split(":");
24
+ if (key !== "concept") continue;
25
+ const value = rest.join(":").trim();
26
+ if (value.startsWith("[") && value.endsWith("]")) return value.slice(1, -1).split(",").map((s) => unquote(s.trim())).filter((s) => s.length > 0);
27
+ if (value !== "") return [unquote(value)];
28
+ const out = [];
29
+ for (let j = i + 1; j < lines.length; j++) {
30
+ const item = lines[j];
31
+ if (item.trim() === "") continue;
32
+ if (item.length - item.trimStart().length === 0) break;
33
+ const dash = /^\s*-\s+(.*)$/.exec(item);
34
+ if (dash) out.push(unquote(dash[1].trim()));
35
+ }
36
+ return out;
37
+ }
38
+ return [];
39
+ }
40
+ function unquote(v) {
41
+ return v.replace(/^["']|["']$/g, "");
42
+ }
43
+ function displayPath(relPath) {
44
+ const p = relPath.replace(/\\/g, "/");
45
+ return p.endsWith("/README.md") ? p.slice(0, -9) : p;
46
+ }
47
+ function scanProjectSpec(specDir) {
48
+ const records = [];
49
+ walk(specDir, specDir, records);
50
+ return records;
51
+ }
52
+ function walk(dir, specDir, out) {
53
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
54
+ if (entry.name.startsWith(".") || SKIP_DIRS.has(entry.name)) continue;
55
+ const full = join(dir, entry.name);
56
+ if (entry.isDirectory()) walk(full, specDir, out);
57
+ else if (entry.name.endsWith(".md")) {
58
+ const concepts = parseConcepts(readFileSync(full, "utf8"));
59
+ if (concepts.length === 0) continue;
60
+ const relPath = full.slice(specDir.length + 1).replace(/\\/g, "/");
61
+ out.push({
62
+ relPath,
63
+ capability: relPath.split("/")[0],
64
+ display: displayPath(relPath),
65
+ concepts
66
+ });
67
+ }
68
+ }
69
+ }
70
+ function suggestHomes(records, concept) {
71
+ const counts = /* @__PURE__ */ new Map();
72
+ for (const rec of records) {
73
+ if (!rec.concepts.includes(concept)) continue;
74
+ counts.set(rec.capability, (counts.get(rec.capability) ?? 0) + 1);
75
+ }
76
+ return [...counts.entries()].map(([capability, count]) => ({
77
+ capability,
78
+ count
79
+ })).sort((a, b) => b.count - a.count || a.capability.localeCompare(b.capability));
80
+ }
81
+ function findNear(records, name) {
82
+ const needle = name.trim().toLowerCase();
83
+ if (needle === "") return [];
84
+ return records.filter((rec) => rec.relPath.toLowerCase().includes(needle)).sort((a, b) => a.display.localeCompare(b.display));
85
+ }
86
+ function render(homes, near, concept, name) {
87
+ const lines = [`place-node: concept=${concept || "(none)"} name=${name || "(none)"}`];
88
+ if (homes.length > 0) {
89
+ lines.push(`homes[${homes.length}]{capability,facets}:`);
90
+ for (const h of homes) lines.push(` ${h.capability},${h.count}`);
91
+ } else lines.push("homes[0]: (new concept — pick any plausible capability; finalized at handoff)");
92
+ if (near.length > 0) {
93
+ lines.push(`near[${near.length}]:`);
94
+ for (const n of near) lines.push(` ${n.display}`);
95
+ } else lines.push("near[0]: (no name overlap)");
96
+ lines.push("note: placement is provisional — finalized at handoff");
97
+ return lines.join("\n");
98
+ }
99
+ function main(argv) {
100
+ let specDir = ".";
101
+ let concept = "";
102
+ let name = "";
103
+ for (let i = 0; i < argv.length; i++) {
104
+ const a = argv[i];
105
+ if (a === "--spec-dir") specDir = argv[++i] ?? ".";
106
+ else if (a === "--concept") concept = argv[++i] ?? "";
107
+ else if (a === "--name") name = argv[++i] ?? "";
108
+ }
109
+ const records = scanProjectSpec(specDir);
110
+ const homes = concept ? suggestHomes(records, concept) : [];
111
+ const near = name ? findNear(records, name) : [];
112
+ process.stdout.write(`${render(homes, near, concept, name)}\n`);
113
+ return 0;
114
+ }
115
+ if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) process.exit(main(process.argv.slice(2)));
116
+ //#endregion
117
+ export { findNear, main, parseConcepts, scanProjectSpec, suggestHomes };
@@ -2,7 +2,7 @@
2
2
 
3
3
  Internal, non-user-invocable SDD skill carrying the Doctrine loop's **last retro step** — the
4
4
  gated, idempotent **tracked deletion** of a retired mission plan. It holds a self-contained
5
- `scripts/retire-plans.mts` (node ≥23.6, no deps; an agent fallback when `node` is absent).
5
+ `scripts/retire-plans.mjs` (node ≥22.11, no deps; an agent fallback when `node` is absent).
6
6
 
7
7
  **Distill and delete are decoupled.** The Scanner distills the combat log into ledger `strategy`
8
8
  early (at `→ implemented`); this sweep deletes the plan **later**, gated on source = `done`/merged
@@ -32,4 +32,4 @@ combat log's presence only — a brief owes no distillation, so a cr-ref with br
32
32
  alone does — a brief without a `plan.md` is untouched). Each brief is deleted only if present; an
33
33
  absent one is a no-op, same as the missing log half.
34
34
 
35
- Tests (`scripts/retire-plans.test.mts`) run under `pnpm verify:specs`.
35
+ Tests (`src/plan-retirement/retire-plans.test.mts`) run under `pnpm verify:specs`.
@@ -1,12 +1,123 @@
1
- // Launcher for the engine of the same name. Run it as `node <skill>/scripts/<engine>.mjs`.
2
- // A checkout runs the .mts source. An npm install keeps the skill under node_modules, where Node
3
- // will not strip types, so it runs the self-contained bundle built for the package.
4
- import { spawnSync } from 'node:child_process'
5
- import { fileURLToPath } from 'node:url'
6
-
7
- const self = fileURLToPath(import.meta.url)
8
- const installed = /[\\/]node_modules[\\/]/.test(self)
9
- const target = self.replace(/\.mjs$/, installed ? '.bundle.mjs' : '.mts')
10
- const run = spawnSync(process.execPath, [...process.execArgv, target, ...process.argv.slice(2)], { stdio: 'inherit' })
11
- if (run.error) throw run.error
12
- process.exitCode = run.status ?? 1
1
+ #!/usr/bin/env node
2
+ // Compiled by `universal-plugin plugin build` from src/plan-retirement/retire-plans.mts. Edit the source, not this file.
3
+ globalThis.__SKILL_SCRIPT__ = {"package":null,"bin":null,"version":"0.7.2","entry":"skills/plan-retirement/scripts/retire-plans.mjs","commands":{}};
4
+ import { existsSync, readFileSync, readdirSync, realpathSync, unlinkSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { pathToFileURL } from "node:url";
7
+ //#region src/plan-retirement/retire-plans.mts
8
+ const PLAN_SUFFIX = ".plan.md";
9
+ const LOG_SUFFIX = ".log.jsonl";
10
+ const DESIGN_SUFFIX = ".design.md";
11
+ const OPERATIONS_SUFFIX = ".operations.md";
12
+ const EVIDENCE_SUFFIX = ".evidence.md";
13
+ function transientArtifactFiles(crRef) {
14
+ return [
15
+ `${crRef}${PLAN_SUFFIX}`,
16
+ `${crRef}${LOG_SUFFIX}`,
17
+ `${crRef}${DESIGN_SUFFIX}`,
18
+ `${crRef}${OPERATIONS_SUFFIX}`,
19
+ `${crRef}${EVIDENCE_SUFFIX}`
20
+ ];
21
+ }
22
+ function parseCleared(value) {
23
+ if (!value) return [];
24
+ const seen = /* @__PURE__ */ new Set();
25
+ for (const raw of value.split(",")) {
26
+ const ref = raw.trim();
27
+ if (ref) seen.add(ref);
28
+ }
29
+ return [...seen];
30
+ }
31
+ function discoverPlans(root) {
32
+ let entries;
33
+ try {
34
+ entries = readdirSync(root);
35
+ } catch {
36
+ return [];
37
+ }
38
+ return entries.filter((f) => f.endsWith(PLAN_SUFFIX)).map((f) => f.slice(0, -8));
39
+ }
40
+ function discoverLogs(root) {
41
+ let entries;
42
+ try {
43
+ entries = readdirSync(root);
44
+ } catch {
45
+ return [];
46
+ }
47
+ return entries.filter((f) => f.endsWith(LOG_SUFFIX)).map((f) => f.slice(0, -10));
48
+ }
49
+ function distilledCrRefs(ledgerDir) {
50
+ const distilled = /* @__PURE__ */ new Set();
51
+ let entries;
52
+ try {
53
+ entries = readdirSync(ledgerDir);
54
+ } catch {
55
+ return distilled;
56
+ }
57
+ for (const entry of entries) {
58
+ if (!entry.endsWith(".jsonl")) continue;
59
+ let text;
60
+ try {
61
+ text = readFileSync(join(ledgerDir, entry), "utf8");
62
+ } catch {
63
+ continue;
64
+ }
65
+ for (const line of text.split("\n")) {
66
+ const trimmed = line.trim();
67
+ if (!trimmed) continue;
68
+ let record;
69
+ try {
70
+ record = JSON.parse(trimmed);
71
+ } catch {
72
+ continue;
73
+ }
74
+ if (record === null || typeof record !== "object") continue;
75
+ const { kind, distills } = record;
76
+ if (kind === "strategy" && typeof distills === "string" && distills.length > 0) distilled.add(distills);
77
+ }
78
+ }
79
+ return distilled;
80
+ }
81
+ function decideRetirements(cleared, existing, distilled, logPresent) {
82
+ const present = new Set(existing);
83
+ const seen = /* @__PURE__ */ new Set();
84
+ const out = [];
85
+ for (const ref of cleared) if (present.has(ref) && (distilled.has(ref) || !logPresent.has(ref)) && !seen.has(ref)) {
86
+ seen.add(ref);
87
+ out.push(ref);
88
+ }
89
+ return out;
90
+ }
91
+ function main(argv) {
92
+ const root = argv.includes("--root") ? argv[argv.indexOf("--root") + 1] : ".agents/plans";
93
+ const ledgerArg = argv.includes("--ledger") ? argv[argv.indexOf("--ledger") + 1] : void 0;
94
+ const cleared = parseCleared(argv.includes("--retire") ? argv[argv.indexOf("--retire") + 1] : void 0);
95
+ const dryRun = argv.includes("--dry-run");
96
+ if (argv.includes("--distilled")) {
97
+ for (const ref of distilledCrRefs(argv[argv.indexOf("--distilled") + 1] ?? "")) process.stdout.write(`${ref}\n`);
98
+ return 0;
99
+ }
100
+ let retiring;
101
+ if (!ledgerArg || !existsSync(ledgerArg)) {
102
+ process.stdout.write(`no verifiable ledger (${ledgerArg ? `--ledger ${ledgerArg} unreadable` : "--ledger not given"}): distillation cannot be checked, so retirement is skipped for all cr-refs\n`);
103
+ retiring = [];
104
+ } else {
105
+ const distilled = distilledCrRefs(ledgerArg);
106
+ const logPresent = new Set(discoverLogs(root));
107
+ retiring = decideRetirements(cleared, discoverPlans(root), distilled, logPresent);
108
+ }
109
+ const deleted = [];
110
+ for (const ref of retiring) for (const file of transientArtifactFiles(ref)) {
111
+ const path = join(root, file);
112
+ if (!existsSync(path)) continue;
113
+ if (!dryRun) unlinkSync(path);
114
+ deleted.push(path);
115
+ }
116
+ const verb = dryRun ? "would delete" : "deleted";
117
+ for (const path of deleted) process.stdout.write(`${verb} ${path}\n`);
118
+ process.stdout.write(`${dryRun ? "dry-run: " : ""}retired ${retiring.length} plan(s), ${deleted.length} file(s)\n`);
119
+ return 0;
120
+ }
121
+ if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) process.exit(main(process.argv.slice(2)));
122
+ //#endregion
123
+ export { decideRetirements, discoverLogs, discoverPlans, distilledCrRefs, main, parseCleared, transientArtifactFiles };
@@ -1,14 +1,14 @@
1
1
  # resolve-governances
2
2
 
3
3
  The concrete engine for **SDD governance resolution**.
4
- A non-user-invocable skill carrying a self-contained `.mts` script that, for a touched file's
4
+ A non-user-invocable skill carrying a self-contained `.mjs` script that, for a touched file's
5
5
  artifact-type, resolves each production-chain role to its agent plus the resolved-actor bars it loads
6
6
  — matching candidates across the project's `.agents/governances/` anchors, the matched plugin squad,
7
7
  and the sdd defaults.
8
8
 
9
9
  - **Skill contract:** [`SKILL.md`](./SKILL.md)
10
- - **Script:** [`scripts/resolve-governances.mts`](./scripts/resolve-governances.mts)
11
- - **Tests:** [`scripts/resolve-governances.test.mts`](./scripts/resolve-governances.test.mts) (`node:test`)
10
+ - **Script:** [`scripts/resolve-governances.mjs`](./scripts/resolve-governances.mjs)
11
+ - **Tests:** [`src/resolve-governances/resolve-governances.test.mts`](../../src/resolve-governances/resolve-governances.test.mts) (`node:test`)
12
12
 
13
13
  ```bash
14
14
  node scripts/resolve-governances.mjs --root . --artifact-type skill
@@ -15,7 +15,7 @@ project anchors, the matched plugin squad (from the project registry
15
15
  `.agents/universal-plugin.json`), and the sdd defaults. It is a **dumb matcher**: it returns each
16
16
  bar's candidates **bucketed by tier** and does **not** order by precedence or apply `compose` — the
17
17
  consuming agent composes. The conductor and the cold judges run it so they **never hand-enumerate**
18
- the bars. It carries a self-contained `.mts` script (the repo's node-≥23.6 / no-deps convention).
18
+ the bars. It carries a self-contained `.mjs` script (compiled from `src/`; no runtime deps, Node ≥22.11).
19
19
 
20
20
  ## Run the resolution
21
21