cyber-sdd 0.6.0 → 0.7.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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +2 -2
- package/.plugin/plugin.json +1 -1
- package/agents/sdd-automaton.md +2 -3
- package/agents/sdd-impl-judge.md +5 -4
- package/agents/sdd-scanner.md +1 -1
- package/agents/sdd-spec-judge.md +3 -3
- package/agents/sdd-warden.md +8 -0
- package/dist/check-project-specs/scripts/check-project-specs.js +1 -0
- package/package.json +2 -2
- package/skills/align-spec/README.md +3 -3
- package/skills/align-spec/SKILL.md +1 -1
- package/skills/align-spec/scripts/align-spec.bundle.mjs +6753 -0
- package/skills/align-spec/scripts/align-spec.mjs +12 -0
- package/skills/architect-impl-governance/SKILL.md +3 -1
- package/skills/architect-spec-governance/SKILL.md +5 -1
- package/skills/blast-estimate/README.md +1 -1
- package/skills/blast-estimate/SKILL.md +1 -1
- package/skills/blast-estimate/scripts/blast-estimate.bundle.mjs +593 -0
- package/skills/blast-estimate/scripts/blast-estimate.mjs +12 -0
- package/skills/check-field-mandates/SKILL.md +1 -1
- package/skills/check-field-mandates/scripts/check-field-mandates.bundle.mjs +251 -0
- package/skills/check-field-mandates/scripts/check-field-mandates.mjs +12 -0
- package/skills/check-partition-quality/SKILL.md +1 -1
- package/skills/check-partition-quality/scripts/check-partition-quality.bundle.mjs +233 -0
- package/skills/check-partition-quality/scripts/check-partition-quality.mjs +12 -0
- package/skills/check-plan-safety/README.md +3 -3
- package/skills/check-plan-safety/SKILL.md +1 -1
- package/skills/check-plan-safety/scripts/check-plan-safety.bundle.mjs +107 -0
- package/skills/check-plan-safety/scripts/check-plan-safety.mjs +12 -0
- package/skills/check-plugin-manifests/SKILL.md +1 -1
- package/skills/check-plugin-manifests/scripts/check-plugin-manifests.bundle.mjs +248 -0
- package/skills/check-plugin-manifests/scripts/check-plugin-manifests.mjs +12 -0
- package/skills/check-project-specs/README.md +3 -3
- package/skills/check-project-specs/SKILL.md +2 -2
- package/skills/check-project-specs/scripts/check-project-specs.bundle.mjs +584 -0
- package/skills/check-project-specs/scripts/check-project-specs.mjs +12 -0
- package/skills/check-project-specs/scripts/check-project-specs.mts +1 -0
- package/skills/check-retired-terms/README.md +2 -2
- package/skills/check-retired-terms/SKILL.md +2 -2
- package/skills/check-retired-terms/scripts/check-retired-terms.bundle.mjs +184 -0
- package/skills/check-retired-terms/scripts/check-retired-terms.mjs +12 -0
- package/skills/check-scenario-overlap/README.md +2 -2
- package/skills/check-scenario-overlap/SKILL.md +2 -3
- package/skills/check-scenario-overlap/scripts/check-scenario-overlap.bundle.mjs +175 -0
- package/skills/check-scenario-overlap/scripts/check-scenario-overlap.mjs +12 -0
- package/skills/check-spec-references/README.md +1 -1
- package/skills/check-spec-references/SKILL.md +1 -1
- package/skills/check-spec-references/scripts/check-spec-references.bundle.mjs +285 -0
- package/skills/check-spec-references/scripts/check-spec-references.mjs +12 -0
- package/skills/check-spec-structure/README.md +2 -2
- package/skills/check-spec-structure/SKILL.md +1 -1
- package/skills/check-spec-structure/scripts/check-spec-structure.bundle.mjs +241 -0
- package/skills/check-spec-structure/scripts/check-spec-structure.mjs +12 -0
- package/skills/collision-ladder/SKILL.md +3 -3
- package/skills/collision-ladder/scripts/collision-ladder.bundle.mjs +7041 -0
- package/skills/collision-ladder/scripts/collision-ladder.mjs +12 -0
- package/skills/collision-ladder/scripts/collision-ladder.mts +4 -2
- package/skills/combat-log-governance/SKILL.md +1 -1
- package/skills/concept-index/README.md +2 -2
- package/skills/concept-index/SKILL.md +1 -1
- package/skills/concept-index/scripts/concept-index.bundle.mjs +181 -0
- package/skills/concept-index/scripts/concept-index.mjs +12 -0
- package/skills/discover-plans/README.md +2 -2
- package/skills/discover-plans/SKILL.md +1 -1
- package/skills/discover-plans/scripts/discover-plans.bundle.mjs +135 -0
- package/skills/discover-plans/scripts/discover-plans.mjs +12 -0
- package/skills/discover-specs/README.md +1 -1
- package/skills/discover-specs/SKILL.md +1 -1
- package/skills/discover-specs/scripts/discover-specs.bundle.mjs +319 -0
- package/skills/discover-specs/scripts/discover-specs.mjs +12 -0
- package/skills/doctrine-loop/SKILL.md +2 -2
- package/skills/formation-loop/SKILL.md +11 -4
- package/skills/gate-validation-governance/SKILL.md +1 -1
- package/skills/init/README.md +3 -3
- package/skills/init/SKILL.md +3 -3
- package/skills/init/scripts/wire-statusline.bundle.mjs +166 -0
- package/skills/init/scripts/wire-statusline.mjs +12 -0
- package/skills/manage-ignore/README.md +5 -5
- package/skills/manage-ignore/SKILL.md +1 -1
- package/skills/manage-ignore/scripts/manage-ignore.bundle.mjs +244 -0
- package/skills/manage-ignore/scripts/manage-ignore.mjs +12 -0
- package/skills/manage-scenario-bridge/README.md +3 -3
- package/skills/manage-scenario-bridge/SKILL.md +1 -1
- package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.bundle.mjs +237 -0
- package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.mjs +12 -0
- package/skills/manage-spec-anchors/README.md +4 -4
- package/skills/manage-spec-anchors/SKILL.md +1 -1
- package/skills/manage-spec-anchors/scripts/manage-spec-anchors.bundle.mjs +308 -0
- package/skills/manage-spec-anchors/scripts/manage-spec-anchors.mjs +12 -0
- package/skills/mission-graph/SKILL.md +9 -9
- package/skills/mission-graph/scripts/mission-graph.bundle.mjs +1038 -0
- package/skills/mission-graph/scripts/mission-graph.mjs +12 -0
- package/skills/pause-mission/SKILL.md +1 -1
- package/skills/place-node/README.md +1 -1
- package/skills/place-node/SKILL.md +1 -1
- package/skills/place-node/scripts/place-node.bundle.mjs +115 -0
- package/skills/place-node/scripts/place-node.mjs +12 -0
- package/skills/plan-retirement/SKILL.md +1 -1
- package/skills/plan-retirement/scripts/retire-plans.bundle.mjs +121 -0
- package/skills/plan-retirement/scripts/retire-plans.mjs +12 -0
- package/skills/plan-retirement/scripts/retire-plans.mts +6 -0
- package/skills/plugin-contract-governance/SKILL.md +5 -12
- package/skills/resolve-governances/README.md +1 -1
- package/skills/resolve-governances/SKILL.md +1 -1
- package/skills/resolve-governances/scripts/resolve-governances.bundle.mjs +350 -0
- package/skills/resolve-governances/scripts/resolve-governances.mjs +12 -0
- package/skills/resolve-governances/scripts/resolve-governances.mts +1 -1
- package/skills/resolve-tracking/SKILL.md +1 -1
- package/skills/resolve-tracking/scripts/resolve-tracking.bundle.mjs +150 -0
- package/skills/resolve-tracking/scripts/resolve-tracking.mjs +12 -0
- package/skills/scaffold-project-spec/SKILL.md +2 -2
- package/skills/sdd/SKILL.md +1 -1
- package/skills/solution-producer-governance/README.md +1 -1
- package/skills/solution-producer-governance/SKILL.md +1 -1
- package/skills/spec-gate/SKILL.md +5 -5
- package/skills/spec-gate/scripts/check-spec-state.bundle.mjs +420 -0
- package/skills/spec-gate/scripts/check-spec-state.mjs +12 -0
- package/skills/spec-gate/scripts/check-suite.bundle.mjs +6498 -0
- package/skills/spec-gate/scripts/check-suite.mjs +12 -0
- package/skills/spec-gate/scripts/classify-edit-class.bundle.mjs +6577 -0
- package/skills/spec-gate/scripts/classify-edit-class.mjs +12 -0
- package/skills/spec-producer-governance/README.md +1 -1
- package/skills/spec-producer-governance/SKILL.md +3 -3
- package/skills/spec-structure-governance/README.md +4 -2
- package/skills/spec-structure-governance/SKILL.md +42 -7
- package/skills/start-mission/README.md +1 -1
- package/skills/start-mission/SKILL.md +6 -6
- package/skills/suite-format-governance/references/rubric.md +1 -1
- package/skills/touch-set-correction/SKILL.md +2 -2
- package/skills/touch-set-correction/scripts/touch-set-correction.bundle.mjs +6655 -0
- package/skills/touch-set-correction/scripts/touch-set-correction.mjs +12 -0
- package/skills/touch-set-correction/scripts/touch-set-correction.mts +12 -3
- package/skills/verify-scenarios/README.md +3 -3
- package/skills/verify-scenarios/SKILL.md +3 -3
- package/skills/verify-scenarios/scripts/verify-scenarios.bundle.mjs +6537 -0
- package/skills/verify-scenarios/scripts/verify-scenarios.mjs +12 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
//#region skills/manage-spec-anchors/scripts/manage-spec-anchors.mts
|
|
6
|
+
const ANCHORS_CONFIG = ".agents/sdd/spec-anchors.toml";
|
|
7
|
+
const LIFECYCLE_STATUSES = /* @__PURE__ */ new Set([
|
|
8
|
+
"draft",
|
|
9
|
+
"approved",
|
|
10
|
+
"implemented",
|
|
11
|
+
"deprecated"
|
|
12
|
+
]);
|
|
13
|
+
const SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
14
|
+
"node_modules",
|
|
15
|
+
".git",
|
|
16
|
+
"dist",
|
|
17
|
+
".turbo",
|
|
18
|
+
".next",
|
|
19
|
+
"coverage"
|
|
20
|
+
]);
|
|
21
|
+
const FIXED_ANCHORS = [
|
|
22
|
+
{
|
|
23
|
+
pattern: ".agents/spec/",
|
|
24
|
+
kind: "fixed",
|
|
25
|
+
explanation: "the repo-root single-project spec"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
pattern: ".agents/specs/<project>/",
|
|
29
|
+
kind: "fixed",
|
|
30
|
+
explanation: "each repo-root multi-project spec (the folder names the project)"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
pattern: "<project-path>/.agents/spec/",
|
|
34
|
+
kind: "fixed",
|
|
35
|
+
explanation: "a nested project's hoisted spec, at any depth"
|
|
36
|
+
}
|
|
37
|
+
];
|
|
38
|
+
function parseAnchorsToml(text) {
|
|
39
|
+
const m = /(^|\n)\s*anchors\s*=\s*\[([\s\S]*?)\]/.exec(text);
|
|
40
|
+
if (!m) return [];
|
|
41
|
+
const out = [];
|
|
42
|
+
for (const q of m[2].matchAll(/"([^"]*)"|'([^']*)'/g)) out.push((q[1] ?? q[2]).trim());
|
|
43
|
+
return out.filter((s) => s !== "");
|
|
44
|
+
}
|
|
45
|
+
function readCustomAnchors(root) {
|
|
46
|
+
const file = join(root, ANCHORS_CONFIG);
|
|
47
|
+
if (!existsSync(file)) return [];
|
|
48
|
+
try {
|
|
49
|
+
return parseAnchorsToml(readFileSync(file, "utf8"));
|
|
50
|
+
} catch {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function serializeAnchors(patterns) {
|
|
55
|
+
if (patterns.length === 0) return "anchors = []\n";
|
|
56
|
+
return `anchors = [\n${patterns.map((p) => ` "${p}",`).join("\n")}\n]\n`;
|
|
57
|
+
}
|
|
58
|
+
function writeCustomAnchors(root, patterns) {
|
|
59
|
+
const file = join(root, ANCHORS_CONFIG);
|
|
60
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
61
|
+
writeFileSync(file, serializeAnchors(patterns));
|
|
62
|
+
}
|
|
63
|
+
function isValidPattern(pattern) {
|
|
64
|
+
const p = pattern.trim().replace(/\\/g, "/");
|
|
65
|
+
if (p === "" || p.startsWith("/") || /(^|\/)\.\.(\/|$)/.test(p)) return false;
|
|
66
|
+
const segs = p.replace(/^\/+|\/+$/g, "").split("/");
|
|
67
|
+
if (segs.some((s) => s === "")) return false;
|
|
68
|
+
return segs.every((s) => s === "*" || s === "**" || s === "<project>" || !/[<>]/.test(s));
|
|
69
|
+
}
|
|
70
|
+
function isFixedConvention(pattern) {
|
|
71
|
+
const p = pattern.trim().replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
72
|
+
return p === ".agents/spec" || p === ".agents/specs/<project>" || p === ".agents/specs/*" || p.endsWith("/.agents/spec") || p.endsWith("/.agents/specs/<project>");
|
|
73
|
+
}
|
|
74
|
+
function listAnchors(root) {
|
|
75
|
+
const custom = readCustomAnchors(root).map((pattern) => ({
|
|
76
|
+
pattern,
|
|
77
|
+
kind: "custom",
|
|
78
|
+
explanation: "a declared extra anchor"
|
|
79
|
+
}));
|
|
80
|
+
return [...FIXED_ANCHORS, ...custom];
|
|
81
|
+
}
|
|
82
|
+
function addAnchor(root, pattern) {
|
|
83
|
+
const p = pattern.trim();
|
|
84
|
+
if (isFixedConvention(p)) return {
|
|
85
|
+
ok: false,
|
|
86
|
+
reason: "that is a fixed convention — always scanned, never curated"
|
|
87
|
+
};
|
|
88
|
+
if (!isValidPattern(p)) return {
|
|
89
|
+
ok: false,
|
|
90
|
+
reason: "malformed anchor pattern"
|
|
91
|
+
};
|
|
92
|
+
const current = readCustomAnchors(root);
|
|
93
|
+
if (current.includes(p)) return {
|
|
94
|
+
ok: true,
|
|
95
|
+
changed: false,
|
|
96
|
+
anchors: current,
|
|
97
|
+
message: "already present"
|
|
98
|
+
};
|
|
99
|
+
const next = [...current, p];
|
|
100
|
+
writeCustomAnchors(root, next);
|
|
101
|
+
return {
|
|
102
|
+
ok: true,
|
|
103
|
+
changed: true,
|
|
104
|
+
anchors: next,
|
|
105
|
+
message: `added ${p}`
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function removeAnchor(root, pattern) {
|
|
109
|
+
const p = pattern.trim();
|
|
110
|
+
const current = readCustomAnchors(root);
|
|
111
|
+
if (!current.includes(p)) return {
|
|
112
|
+
ok: true,
|
|
113
|
+
changed: false,
|
|
114
|
+
anchors: current,
|
|
115
|
+
message: "nothing was removed"
|
|
116
|
+
};
|
|
117
|
+
const next = current.filter((a) => a !== p);
|
|
118
|
+
writeCustomAnchors(root, next);
|
|
119
|
+
return {
|
|
120
|
+
ok: true,
|
|
121
|
+
changed: true,
|
|
122
|
+
anchors: next,
|
|
123
|
+
message: `removed ${p}`
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function editAnchor(root, oldPattern, newPattern) {
|
|
127
|
+
const oldP = oldPattern.trim();
|
|
128
|
+
const newP = newPattern.trim();
|
|
129
|
+
if (isFixedConvention(oldP)) return {
|
|
130
|
+
ok: false,
|
|
131
|
+
reason: "cannot edit a fixed convention"
|
|
132
|
+
};
|
|
133
|
+
if (!isValidPattern(newP)) return {
|
|
134
|
+
ok: false,
|
|
135
|
+
reason: "malformed replacement pattern"
|
|
136
|
+
};
|
|
137
|
+
if (isFixedConvention(newP)) return {
|
|
138
|
+
ok: false,
|
|
139
|
+
reason: "replacement is a fixed convention"
|
|
140
|
+
};
|
|
141
|
+
const current = readCustomAnchors(root);
|
|
142
|
+
if (!current.includes(oldP)) return {
|
|
143
|
+
ok: false,
|
|
144
|
+
reason: `no such custom anchor: ${oldP}`
|
|
145
|
+
};
|
|
146
|
+
const next = current.map((a) => a === oldP ? newP : a);
|
|
147
|
+
writeCustomAnchors(root, next);
|
|
148
|
+
return {
|
|
149
|
+
ok: true,
|
|
150
|
+
changed: true,
|
|
151
|
+
anchors: next,
|
|
152
|
+
message: `edited ${oldP} -> ${newP}`
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function inducePatterns(root, samplePath) {
|
|
156
|
+
const rel = samplePath.trim().replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
157
|
+
if (rel === "" || /(^|\/)\.\.(\/|$)/.test(rel)) return {
|
|
158
|
+
ok: false,
|
|
159
|
+
reason: "path is not repo-relative"
|
|
160
|
+
};
|
|
161
|
+
let ok = false;
|
|
162
|
+
try {
|
|
163
|
+
ok = statSync(join(root, rel)).isDirectory();
|
|
164
|
+
} catch {
|
|
165
|
+
ok = false;
|
|
166
|
+
}
|
|
167
|
+
if (!ok) return {
|
|
168
|
+
ok: false,
|
|
169
|
+
reason: `sample path does not resolve to a directory under the repo: ${rel}`
|
|
170
|
+
};
|
|
171
|
+
const generalized = [...rel.split("/").slice(0, -1), "<project>"].join("/");
|
|
172
|
+
return {
|
|
173
|
+
ok: true,
|
|
174
|
+
candidates: generalized === rel ? [rel] : [rel, generalized]
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function collectDescendants(root, startDir) {
|
|
178
|
+
const out = [startDir];
|
|
179
|
+
let entries;
|
|
180
|
+
try {
|
|
181
|
+
entries = readdirSync(join(root, startDir), { withFileTypes: true });
|
|
182
|
+
} catch {
|
|
183
|
+
return out;
|
|
184
|
+
}
|
|
185
|
+
for (const e of entries) {
|
|
186
|
+
if (!e.isDirectory() || SKIP_DIRS.has(e.name)) continue;
|
|
187
|
+
out.push(...collectDescendants(root, startDir ? `${startDir}/${e.name}` : e.name));
|
|
188
|
+
}
|
|
189
|
+
return out;
|
|
190
|
+
}
|
|
191
|
+
function previewPattern(root, pattern) {
|
|
192
|
+
const p = pattern.trim();
|
|
193
|
+
if (!isValidPattern(p)) return {
|
|
194
|
+
ok: false,
|
|
195
|
+
reason: "malformed candidate pattern"
|
|
196
|
+
};
|
|
197
|
+
const segs = p.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
|
|
198
|
+
let frontier = [{ dir: "" }];
|
|
199
|
+
for (const seg of segs) {
|
|
200
|
+
const next = [];
|
|
201
|
+
if (seg === "**") {
|
|
202
|
+
for (const node of frontier) for (const dir of collectDescendants(root, node.dir)) next.push({
|
|
203
|
+
dir,
|
|
204
|
+
capturedName: node.capturedName
|
|
205
|
+
});
|
|
206
|
+
frontier = next;
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const isGlob = seg === "*" || seg === "<project>";
|
|
210
|
+
for (const node of frontier) if (isGlob) {
|
|
211
|
+
let entries;
|
|
212
|
+
try {
|
|
213
|
+
entries = readdirSync(join(root, node.dir), { withFileTypes: true });
|
|
214
|
+
} catch {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
for (const e of entries) {
|
|
218
|
+
if (!e.isDirectory() || SKIP_DIRS.has(e.name)) continue;
|
|
219
|
+
next.push({
|
|
220
|
+
dir: node.dir ? `${node.dir}/${e.name}` : e.name,
|
|
221
|
+
capturedName: seg === "<project>" ? e.name : node.capturedName
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
} else next.push({
|
|
225
|
+
dir: node.dir ? `${node.dir}/${seg}` : seg,
|
|
226
|
+
capturedName: node.capturedName
|
|
227
|
+
});
|
|
228
|
+
frontier = next;
|
|
229
|
+
}
|
|
230
|
+
const matches = [];
|
|
231
|
+
for (const node of frontier) {
|
|
232
|
+
const rel = node.dir ? `${node.dir}/spec.md` : "spec.md";
|
|
233
|
+
let status;
|
|
234
|
+
try {
|
|
235
|
+
status = /(^|\n)status:\s*["']?([a-z]+)/.exec(readFileSync(join(root, rel), "utf8"))?.[2];
|
|
236
|
+
} catch {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if (!status || !LIFECYCLE_STATUSES.has(status)) continue;
|
|
240
|
+
matches.push({
|
|
241
|
+
path: node.dir,
|
|
242
|
+
name: node.capturedName ?? node.dir.split("/").pop() ?? node.dir
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
matches.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
246
|
+
return {
|
|
247
|
+
ok: true,
|
|
248
|
+
matches
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function flag(argv, name) {
|
|
252
|
+
const i = argv.indexOf(name);
|
|
253
|
+
return i === -1 ? void 0 : argv[i + 1];
|
|
254
|
+
}
|
|
255
|
+
function main(argv) {
|
|
256
|
+
const root = flag(argv, "--root") ?? ".";
|
|
257
|
+
const w = (s) => process.stdout.write(`${s}\n`);
|
|
258
|
+
if (argv.includes("--list")) {
|
|
259
|
+
w("Spec anchors discovery scans (fixed conventions are always scanned):");
|
|
260
|
+
for (const a of listAnchors(root)) w(` [${a.kind}] ${a.pattern} — ${a.explanation}`);
|
|
261
|
+
return 0;
|
|
262
|
+
}
|
|
263
|
+
if (argv.includes("--add")) {
|
|
264
|
+
const r = addAnchor(root, flag(argv, "--add") ?? "");
|
|
265
|
+
w(r.ok ? r.message : `refused: ${r.reason}`);
|
|
266
|
+
return r.ok ? 0 : 1;
|
|
267
|
+
}
|
|
268
|
+
if (argv.includes("--remove")) {
|
|
269
|
+
const r = removeAnchor(root, flag(argv, "--remove") ?? "");
|
|
270
|
+
w(r.ok ? r.message : `refused: ${r.reason}`);
|
|
271
|
+
return r.ok ? 0 : 1;
|
|
272
|
+
}
|
|
273
|
+
if (argv.includes("--edit")) {
|
|
274
|
+
const i = argv.indexOf("--edit");
|
|
275
|
+
const r = editAnchor(root, argv[i + 1] ?? "", argv[i + 2] ?? "");
|
|
276
|
+
w(r.ok ? r.message : `refused: ${r.reason}`);
|
|
277
|
+
return r.ok ? 0 : 1;
|
|
278
|
+
}
|
|
279
|
+
if (argv.includes("--induce")) {
|
|
280
|
+
const r = inducePatterns(root, flag(argv, "--induce") ?? "");
|
|
281
|
+
if (!r.ok) {
|
|
282
|
+
w(`unusable: ${r.reason}`);
|
|
283
|
+
return 1;
|
|
284
|
+
}
|
|
285
|
+
w("Candidate anchor patterns:");
|
|
286
|
+
for (const c of r.candidates) w(` ${c}`);
|
|
287
|
+
return 0;
|
|
288
|
+
}
|
|
289
|
+
if (argv.includes("--preview")) {
|
|
290
|
+
const r = previewPattern(root, flag(argv, "--preview") ?? "");
|
|
291
|
+
if (!r.ok) {
|
|
292
|
+
w(`invalid: ${r.reason}`);
|
|
293
|
+
return 1;
|
|
294
|
+
}
|
|
295
|
+
if (r.matches.length === 0) {
|
|
296
|
+
w("This pattern matches no project.");
|
|
297
|
+
return 0;
|
|
298
|
+
}
|
|
299
|
+
w("This pattern would discover:");
|
|
300
|
+
for (const m of r.matches) w(` ${m.path} (${m.name})`);
|
|
301
|
+
return 0;
|
|
302
|
+
}
|
|
303
|
+
w("usage: manage-spec-anchors --list | --add <p> | --remove <p> | --edit <old> <new> | --induce <path> | --preview <p>");
|
|
304
|
+
return 0;
|
|
305
|
+
}
|
|
306
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) process.exit(main(process.argv.slice(2)));
|
|
307
|
+
//#endregion
|
|
308
|
+
export { FIXED_ANCHORS, addAnchor, editAnchor, inducePatterns, isFixedConvention, isValidPattern, listAnchors, main, parseAnchorsToml, previewPattern, readCustomAnchors, removeAnchor, serializeAnchors };
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
|
@@ -32,24 +32,24 @@ never touches a derivation.
|
|
|
32
32
|
## Run it
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
node "<skill>/scripts/mission-graph.
|
|
36
|
-
node "<skill>/scripts/mission-graph.
|
|
37
|
-
node "<skill>/scripts/mission-graph.
|
|
35
|
+
node "<skill>/scripts/mission-graph.mjs" ready [--root .] [--format toon|json]
|
|
36
|
+
node "<skill>/scripts/mission-graph.mjs" cycles [--root .] [--format toon|json]
|
|
37
|
+
node "<skill>/scripts/mission-graph.mjs" operation --id <operation-id> [--root .] [--format toon|json]
|
|
38
38
|
|
|
39
39
|
# the write path (append-only; --root defaults to .)
|
|
40
|
-
node "<skill>/scripts/mission-graph.
|
|
40
|
+
node "<skill>/scripts/mission-graph.mjs" append node --id <id> \
|
|
41
41
|
[--kind mission|operation] [--status open|claimed|retired] [--touch-set a,b,c] \
|
|
42
42
|
[--blast <level>] [--hitl|--afk] [--model-tier <tier>] [--brief-pointer <path>] [--capstone <id>]
|
|
43
43
|
|
|
44
|
-
node "<skill>/scripts/mission-graph.
|
|
44
|
+
node "<skill>/scripts/mission-graph.mjs" append edge --kind RAW|parent-child|discovered-from \
|
|
45
45
|
--from <id> --to <id> [--override]
|
|
46
46
|
|
|
47
|
-
node "<skill>/scripts/mission-graph.
|
|
48
|
-
node "<skill>/scripts/mission-graph.
|
|
47
|
+
node "<skill>/scripts/mission-graph.mjs" append tombstone --target node --id <id>
|
|
48
|
+
node "<skill>/scripts/mission-graph.mjs" append tombstone --target edge --kind <kind> --from <id> --to <id>
|
|
49
49
|
|
|
50
50
|
# store home + reach (idempotent; --root defaults to .)
|
|
51
|
-
node "<skill>/scripts/mission-graph.
|
|
52
|
-
node "<skill>/scripts/mission-graph.
|
|
51
|
+
node "<skill>/scripts/mission-graph.mjs" migrate [--root .]
|
|
52
|
+
node "<skill>/scripts/mission-graph.mjs" sync [--root .] [--remote origin]
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
- Default `--root` is the current directory. The store home is resolved at run time — the orphan ref
|