cyber-sdd 0.7.0 → 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 (149) 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/package.json +11 -13
  5. package/plugin.json +55 -0
  6. package/skills/align-spec/SKILL.md +1 -1
  7. package/skills/align-spec/scripts/align-spec.mjs +6755 -12
  8. package/skills/blast-estimate/README.md +3 -3
  9. package/skills/blast-estimate/scripts/blast-estimate.mjs +601 -12
  10. package/skills/check-field-mandates/scripts/check-field-mandates.mjs +253 -12
  11. package/skills/check-partition-quality/scripts/check-partition-quality.mjs +235 -12
  12. package/skills/check-plan-safety/SKILL.md +2 -3
  13. package/skills/check-plan-safety/scripts/check-plan-safety.mjs +109 -12
  14. package/skills/check-plugin-manifests/scripts/check-plugin-manifests.mjs +250 -12
  15. package/skills/check-project-specs/SKILL.md +1 -1
  16. package/skills/check-project-specs/scripts/check-project-specs.mjs +593 -12
  17. package/skills/check-retired-terms/SKILL.md +2 -3
  18. package/skills/check-retired-terms/scripts/check-retired-terms.mjs +186 -12
  19. package/skills/check-scenario-overlap/SKILL.md +1 -2
  20. package/skills/check-scenario-overlap/scripts/check-scenario-overlap.mjs +177 -12
  21. package/skills/check-spec-references/SKILL.md +2 -2
  22. package/skills/check-spec-references/scripts/check-spec-references.mjs +287 -12
  23. package/skills/check-spec-structure/SKILL.md +1 -2
  24. package/skills/check-spec-structure/scripts/check-spec-structure.mjs +243 -12
  25. package/skills/collision-ladder/README.md +2 -2
  26. package/skills/collision-ladder/scripts/collision-ladder.mjs +7047 -12
  27. package/skills/combat-log-governance/SKILL.md +1 -1
  28. package/skills/concept-index/SKILL.md +1 -1
  29. package/skills/concept-index/scripts/concept-index.mjs +183 -12
  30. package/skills/discover-plans/README.md +3 -3
  31. package/skills/discover-plans/SKILL.md +1 -1
  32. package/skills/discover-plans/scripts/discover-plans.mjs +137 -12
  33. package/skills/discover-specs/README.md +3 -3
  34. package/skills/discover-specs/SKILL.md +1 -1
  35. package/skills/discover-specs/scripts/discover-specs.mjs +321 -12
  36. package/skills/doctrine-loop/SKILL.md +1 -1
  37. package/skills/gate-validation-governance/SKILL.md +1 -1
  38. package/skills/init/README.md +2 -2
  39. package/skills/init/scripts/wire-statusline.mjs +168 -12
  40. package/skills/manage-ignore/README.md +3 -3
  41. package/skills/manage-ignore/SKILL.md +1 -2
  42. package/skills/manage-ignore/scripts/manage-ignore.mjs +285 -12
  43. package/skills/manage-scenario-bridge/README.md +3 -3
  44. package/skills/manage-scenario-bridge/SKILL.md +1 -1
  45. package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.mjs +239 -12
  46. package/skills/manage-spec-anchors/README.md +3 -3
  47. package/skills/manage-spec-anchors/SKILL.md +1 -1
  48. package/skills/manage-spec-anchors/scripts/manage-spec-anchors.mjs +310 -12
  49. package/skills/mission-graph/README.md +2 -2
  50. package/skills/mission-graph/SKILL.md +1 -1
  51. package/skills/mission-graph/scripts/mission-graph.mjs +1040 -12
  52. package/skills/pause-mission/SKILL.md +1 -1
  53. package/skills/place-node/SKILL.md +2 -2
  54. package/skills/place-node/scripts/place-node.mjs +117 -12
  55. package/skills/plan-retirement/README.md +2 -2
  56. package/skills/plan-retirement/scripts/retire-plans.mjs +123 -12
  57. package/skills/resolve-governances/README.md +3 -3
  58. package/skills/resolve-governances/SKILL.md +1 -1
  59. package/skills/resolve-governances/scripts/resolve-governances.mjs +352 -12
  60. package/skills/resolve-tracking/SKILL.md +1 -1
  61. package/skills/resolve-tracking/scripts/resolve-tracking.mjs +152 -12
  62. package/skills/scaffold-project-spec/SKILL.md +1 -1
  63. package/skills/spec-gate/README.md +12 -9
  64. package/skills/spec-gate/SKILL.md +2 -2
  65. package/skills/spec-gate/scripts/check-spec-state.mjs +422 -12
  66. package/skills/spec-gate/scripts/check-suite.mjs +6500 -12
  67. package/skills/spec-gate/scripts/classify-edit-class.mjs +6579 -12
  68. package/skills/spec-producer-governance/SKILL.md +2 -2
  69. package/skills/start-mission/SKILL.md +1 -1
  70. package/skills/suite-format-governance/README.md +1 -1
  71. package/skills/suite-format-governance/SKILL.md +1 -1
  72. package/skills/touch-set-correction/README.md +5 -5
  73. package/skills/touch-set-correction/SKILL.md +1 -1
  74. package/skills/touch-set-correction/scripts/touch-set-correction.mjs +6663 -12
  75. package/skills/verify-scenarios/README.md +6 -6
  76. package/skills/verify-scenarios/scripts/verify-scenarios.mjs +6539 -12
  77. package/.plugin/pins.json +0 -3
  78. package/.plugin/plugin.json +0 -19
  79. package/dist/align-spec/scripts/align-spec.js +0 -102
  80. package/dist/check-project-specs/scripts/check-project-specs.js +0 -312
  81. package/dist/check-scenario-overlap/scripts/check-scenario-overlap.js +0 -175
  82. package/dist/check-spec-references/scripts/check-spec-references.js +0 -285
  83. package/dist/check-spec-structure/scripts/check-spec-structure.js +0 -241
  84. package/dist/concept-index/scripts/concept-index.js +0 -181
  85. package/dist/discover-specs/scripts/discover-specs.js +0 -318
  86. package/dist/spec-gate/scripts/check-spec-state.js +0 -420
  87. package/dist/spec-gate/scripts/check-suite.js +0 -317
  88. package/dist/spec-gate/scripts/classify-edit-class.js +0 -263
  89. package/dist/spec-gate/vendor/gherkin-cli.js +0 -6369
  90. package/skills/align-spec/scripts/align-spec.bundle.mjs +0 -6753
  91. package/skills/align-spec/scripts/align-spec.mts +0 -188
  92. package/skills/blast-estimate/scripts/blast-estimate.bundle.mjs +0 -593
  93. package/skills/blast-estimate/scripts/blast-estimate.mts +0 -586
  94. package/skills/check-field-mandates/scripts/check-field-mandates.bundle.mjs +0 -251
  95. package/skills/check-field-mandates/scripts/check-field-mandates.mts +0 -337
  96. package/skills/check-partition-quality/scripts/check-partition-quality.bundle.mjs +0 -233
  97. package/skills/check-partition-quality/scripts/check-partition-quality.mts +0 -338
  98. package/skills/check-plan-safety/scripts/check-plan-safety.bundle.mjs +0 -107
  99. package/skills/check-plan-safety/scripts/check-plan-safety.mts +0 -148
  100. package/skills/check-plugin-manifests/scripts/check-plugin-manifests.bundle.mjs +0 -248
  101. package/skills/check-plugin-manifests/scripts/check-plugin-manifests.mts +0 -303
  102. package/skills/check-project-specs/scripts/check-project-specs.bundle.mjs +0 -584
  103. package/skills/check-project-specs/scripts/check-project-specs.mts +0 -370
  104. package/skills/check-retired-terms/scripts/check-retired-terms.bundle.mjs +0 -184
  105. package/skills/check-retired-terms/scripts/check-retired-terms.mts +0 -293
  106. package/skills/check-scenario-overlap/scripts/check-scenario-overlap.bundle.mjs +0 -175
  107. package/skills/check-scenario-overlap/scripts/check-scenario-overlap.mts +0 -250
  108. package/skills/check-spec-references/scripts/check-spec-references.bundle.mjs +0 -285
  109. package/skills/check-spec-references/scripts/check-spec-references.mts +0 -422
  110. package/skills/check-spec-structure/scripts/check-spec-structure.bundle.mjs +0 -241
  111. package/skills/check-spec-structure/scripts/check-spec-structure.mts +0 -347
  112. package/skills/collision-ladder/scripts/collision-ladder.bundle.mjs +0 -7041
  113. package/skills/collision-ladder/scripts/collision-ladder.mts +0 -662
  114. package/skills/concept-index/scripts/concept-index.bundle.mjs +0 -181
  115. package/skills/concept-index/scripts/concept-index.mts +0 -246
  116. package/skills/discover-plans/scripts/discover-plans.bundle.mjs +0 -135
  117. package/skills/discover-plans/scripts/discover-plans.mts +0 -215
  118. package/skills/discover-specs/scripts/discover-specs.bundle.mjs +0 -319
  119. package/skills/discover-specs/scripts/discover-specs.mts +0 -420
  120. package/skills/init/scripts/wire-statusline.bundle.mjs +0 -166
  121. package/skills/init/scripts/wire-statusline.mts +0 -279
  122. package/skills/manage-ignore/scripts/manage-ignore.bundle.mjs +0 -244
  123. package/skills/manage-ignore/scripts/manage-ignore.mts +0 -297
  124. package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.bundle.mjs +0 -237
  125. package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.mts +0 -159
  126. package/skills/manage-spec-anchors/scripts/manage-spec-anchors.bundle.mjs +0 -308
  127. package/skills/manage-spec-anchors/scripts/manage-spec-anchors.mts +0 -331
  128. package/skills/mission-graph/scripts/mission-graph.bundle.mjs +0 -1038
  129. package/skills/mission-graph/scripts/mission-graph.mts +0 -1333
  130. package/skills/place-node/scripts/place-node.bundle.mjs +0 -115
  131. package/skills/place-node/scripts/place-node.mts +0 -158
  132. package/skills/plan-retirement/scripts/retire-plans.bundle.mjs +0 -121
  133. package/skills/plan-retirement/scripts/retire-plans.mts +0 -205
  134. package/skills/resolve-governances/scripts/resolve-governances.bundle.mjs +0 -350
  135. package/skills/resolve-governances/scripts/resolve-governances.mts +0 -518
  136. package/skills/resolve-tracking/scripts/resolve-tracking.bundle.mjs +0 -150
  137. package/skills/resolve-tracking/scripts/resolve-tracking.mts +0 -214
  138. package/skills/spec-gate/scripts/check-spec-state.bundle.mjs +0 -420
  139. package/skills/spec-gate/scripts/check-spec-state.mts +0 -637
  140. package/skills/spec-gate/scripts/check-suite.bundle.mjs +0 -6498
  141. package/skills/spec-gate/scripts/check-suite.mts +0 -538
  142. package/skills/spec-gate/scripts/classify-edit-class.bundle.mjs +0 -6577
  143. package/skills/spec-gate/scripts/classify-edit-class.mts +0 -414
  144. package/skills/spec-gate/vendor/gherkin-cli.d.mts +0 -2
  145. package/skills/spec-gate/vendor/gherkin-cli.mjs +0 -6545
  146. package/skills/touch-set-correction/scripts/touch-set-correction.bundle.mjs +0 -6655
  147. package/skills/touch-set-correction/scripts/touch-set-correction.mts +0 -429
  148. package/skills/verify-scenarios/scripts/verify-scenarios.bundle.mjs +0 -6537
  149. package/skills/verify-scenarios/scripts/verify-scenarios.mts +0 -470
@@ -1,12 +1,250 @@
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/check-plugin-manifests/check-plugin-manifests.mts. Edit the source, not this file.
3
+ globalThis.__SKILL_SCRIPT__ = {"package":null,"bin":null,"version":"0.7.1","entry":"skills/check-plugin-manifests/scripts/check-plugin-manifests.mjs","commands":{}};
4
+ import { existsSync, lstatSync, readFileSync, readdirSync, realpathSync } from "node:fs";
5
+ import { dirname, join, relative, sep } from "node:path";
6
+ import { pathToFileURL } from "node:url";
7
+ //#region src/check-plugin-manifests/check-plugin-manifests.mts
8
+ /**
9
+ * Directories that hold a manifest one level below the plugin root.
10
+ *
11
+ * This is a path-shape list, not a provenance one: `.plugin/` holds the **canonical** manifest and
12
+ * the other two hold its generated vendor copies, but all three sit one level down, so a pointer
13
+ * inside any of them resolves against the parent. Naming it for vendors would contradict the
14
+ * spec's own vocabulary and has already misled one reader.
15
+ */
16
+ const MANIFEST_DIRS = [
17
+ ".plugin",
18
+ ".claude-plugin",
19
+ ".codex-plugin"
20
+ ];
21
+ const MANIFEST_NAME = "plugin.json";
22
+ const SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git"]);
23
+ /**
24
+ * Every manifest at a conventional location under `root`, repo-relative and path-sorted.
25
+ *
26
+ * A manifest is a `plugin.json` either inside a vendor directory, or sitting beside a
27
+ * `package.json` (a package-root manifest). Sorted so a sweep's report order is deterministic.
28
+ * A symlink is included: it resolves to a real manifest, and a broken one must surface as
29
+ * unreadable rather than vanish from the sweep.
30
+ */
31
+ /** Directory entries, or none where the directory cannot be read. */
32
+ function safeReaddir(dir) {
33
+ try {
34
+ return readdirSync(dir, { withFileTypes: true });
35
+ } catch {
36
+ return [];
37
+ }
38
+ }
39
+ function discoverManifests(root) {
40
+ const found = [];
41
+ const walk = (dir) => {
42
+ for (const e of safeReaddir(dir)) {
43
+ const full = join(dir, e.name);
44
+ if (e.isDirectory()) {
45
+ if (!SKIP_DIRS.has(e.name)) walk(full);
46
+ continue;
47
+ }
48
+ if (e.name !== MANIFEST_NAME) continue;
49
+ const parent = dirname(full);
50
+ if (MANIFEST_DIRS.includes(parent.split(sep).pop() ?? "") || existsSync(join(parent, "package.json"))) found.push(full);
51
+ }
52
+ };
53
+ walk(root);
54
+ return found.map((f) => relative(root, f).split(sep).join("/")).sort();
55
+ }
56
+ /**
57
+ * The plugin root a manifest's pointers resolve against — NOT the manifest's own directory.
58
+ *
59
+ * A vendor manifest sits one level down, and its `./skills` still names the plugin's skills
60
+ * directory. A guard resolving relative to the file it just read reports every vendor manifest as
61
+ * entirely broken.
62
+ */
63
+ function pluginRootOf(manifestRelPath) {
64
+ const parts = manifestRelPath.split("/");
65
+ const parentName = parts[parts.length - 2];
66
+ const drop = parentName !== void 0 && MANIFEST_DIRS.includes(parentName) ? 2 : 1;
67
+ return parts.slice(0, parts.length - drop).join("/");
68
+ }
69
+ /** Every `./`-prefixed string value in the manifest, paired with the key it sits under. */
70
+ function extractPointers(manifest) {
71
+ const out = [];
72
+ const visit = (value, key) => {
73
+ if (typeof value === "string") {
74
+ if (value.startsWith("./")) out.push({
75
+ key,
76
+ pointer: value
77
+ });
78
+ return;
79
+ }
80
+ if (Array.isArray(value)) {
81
+ for (const item of value) visit(item, key);
82
+ return;
83
+ }
84
+ if (value !== null && typeof value === "object") for (const [k, v] of Object.entries(value)) visit(v, k);
85
+ };
86
+ visit(manifest, "");
87
+ return out;
88
+ }
89
+ /**
90
+ * The nearest `package.json` at or above the plugin root, and whether it publishes.
91
+ *
92
+ * A package publishes when it is not `private` AND declares a `files` allowlist. A `private`
93
+ * package ships no tarball, so its `files` constrains nothing. A package declaring no `files` at
94
+ * all ships everything, so there is no allowlist to be outside of — npm's own semantic, and
95
+ * inverting it manufactures a finding against every pointer in the package.
96
+ */
97
+ function owningPackage(root, pluginRoot) {
98
+ let dir = pluginRoot;
99
+ for (;;) {
100
+ const candidate = dir === "" ? "package.json" : `${dir}/package.json`;
101
+ const abs = join(root, candidate);
102
+ if (existsSync(abs)) try {
103
+ const pkg = JSON.parse(readFileSync(abs, "utf8"));
104
+ const files = Array.isArray(pkg.files) ? pkg.files.filter((f) => typeof f === "string") : null;
105
+ const packs = pkg.private !== true;
106
+ return {
107
+ path: candidate,
108
+ packs,
109
+ publishes: packs && files !== null,
110
+ files: files ?? []
111
+ };
112
+ } catch {
113
+ return {
114
+ path: candidate,
115
+ packs: false,
116
+ publishes: false,
117
+ files: []
118
+ };
119
+ }
120
+ if (dir === "") return null;
121
+ dir = dir.split("/").slice(0, -1).join("/");
122
+ }
123
+ }
124
+ /**
125
+ * Whether a `files` allowlist covers a pointer, compared on the leading path segment.
126
+ *
127
+ * Both sides are normalized past a leading `./`, because an allowlist may legitimately spell an
128
+ * entry either way and a pointer always carries the prefix — comparing them raw reports a shipped
129
+ * component as unpublished.
130
+ *
131
+ * A `!`-prefixed entry is an exclusion and needs no special case: its leading `!` is part of its
132
+ * first segment, so it can never equal a real segment and is never read as an inclusion.
133
+ */
134
+ function filesCovers(files, pointer) {
135
+ const head = (path) => path.replace(/^\.\//, "").split("/")[0];
136
+ const segment = head(pointer);
137
+ if (segment === void 0 || segment === "") return true;
138
+ return files.some((entry) => {
139
+ const h = head(entry);
140
+ return h === "*" || h === "**" || h === segment;
141
+ });
142
+ }
143
+ /** Whether a package that packs a tarball ships the package-relative path `./<rel>`. */
144
+ function ships(pkg, rel) {
145
+ return pkg?.packs === true && (!pkg.publishes || filesCovers(pkg.files, `./${rel}`));
146
+ }
147
+ /** Every symbolic link at or below `abs` — the path itself included, links never followed. */
148
+ function findSymlinks(abs) {
149
+ let stat;
150
+ try {
151
+ stat = lstatSync(abs);
152
+ } catch {
153
+ return [];
154
+ }
155
+ if (stat.isSymbolicLink()) return [abs];
156
+ if (!stat.isDirectory()) return [];
157
+ return safeReaddir(abs).filter((e) => !SKIP_DIRS.has(e.name)).flatMap((e) => findSymlinks(join(abs, e.name)));
158
+ }
159
+ function sweep(root, manifests) {
160
+ const findings = [];
161
+ const linksSeen = /* @__PURE__ */ new Set();
162
+ const reportLinks = (rel, abs, key, pointer) => {
163
+ for (const link of findSymlinks(abs)) {
164
+ const linkRel = relative(root, link).split(sep).join("/");
165
+ if (linksSeen.has(linkRel)) continue;
166
+ linksSeen.add(linkRel);
167
+ findings.push({
168
+ kind: "symlink",
169
+ manifest: rel,
170
+ ...key === void 0 ? {} : {
171
+ key,
172
+ pointer
173
+ },
174
+ detail: `${linkRel} is a symbolic link — the registry rejects a package that ships one`
175
+ });
176
+ }
177
+ };
178
+ for (const rel of manifests) {
179
+ let parsed;
180
+ try {
181
+ parsed = JSON.parse(readFileSync(join(root, rel), "utf8"));
182
+ } catch {
183
+ findings.push({
184
+ kind: "unreadable",
185
+ manifest: rel,
186
+ detail: "not readable as JSON"
187
+ });
188
+ continue;
189
+ }
190
+ const pluginRoot = pluginRootOf(rel);
191
+ const pkg = owningPackage(root, pluginRoot);
192
+ const pkgDir = pkg ? dirname(pkg.path) : "";
193
+ const fromPkg = (path) => relative(join(root, pkgDir), join(root, path)).split(sep).join("/");
194
+ if (ships(pkg, fromPkg(rel))) reportLinks(rel, join(root, rel));
195
+ for (const { key, pointer } of extractPointers(parsed)) {
196
+ const target = join(root, pluginRoot, pointer);
197
+ if (!existsSync(target)) {
198
+ findings.push({
199
+ kind: "unresolved",
200
+ manifest: rel,
201
+ key,
202
+ pointer,
203
+ detail: "names no path on disk"
204
+ });
205
+ continue;
206
+ }
207
+ if (pkg?.publishes && !filesCovers(pkg.files, pointer)) {
208
+ findings.push({
209
+ kind: "unpublished",
210
+ manifest: rel,
211
+ key,
212
+ pointer,
213
+ detail: `declared but not published — ${pkg.path} files omits it`
214
+ });
215
+ continue;
216
+ }
217
+ if (ships(pkg, fromPkg(join(pluginRoot, pointer)))) reportLinks(rel, target, key, pointer);
218
+ }
219
+ }
220
+ return findings;
221
+ }
222
+ function formatReport(manifests, findings) {
223
+ if (manifests.length === 0) return "check-plugin-manifests: no plugin manifest found\n";
224
+ if (findings.length === 0) return `check-plugin-manifests: ${manifests.length} manifest(s) OK\n`;
225
+ return `${findings.map((f) => ` ${f.kind.padEnd(11)} ${f.manifest}${f.key ? ` [${f.key}] ${f.pointer}` : ""} — ${f.detail}`).join("\n")}\ncheck-plugin-manifests: ${findings.length} finding(s) across ${manifests.length} manifest(s)\n`;
226
+ }
227
+ function main(argv) {
228
+ let root = ".";
229
+ for (let i = 0; i < argv.length; i++) {
230
+ const a = argv[i];
231
+ if (a === "--root") {
232
+ const next = argv[++i];
233
+ if (next === void 0) {
234
+ process.stderr.write("check-plugin-manifests: --root needs a directory\n");
235
+ return 1;
236
+ }
237
+ root = next;
238
+ continue;
239
+ }
240
+ process.stderr.write(`check-plugin-manifests: unrecognized flag ${a}\n`);
241
+ return 1;
242
+ }
243
+ const manifests = discoverManifests(root);
244
+ const findings = sweep(root, manifests);
245
+ process.stdout.write(formatReport(manifests, findings));
246
+ return findings.length === 0 ? 0 : 1;
247
+ }
248
+ if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) process.exit(main(process.argv.slice(2)));
249
+ //#endregion
250
+ export { discoverManifests, extractPointers, filesCovers, findSymlinks, formatReport, main, owningPackage, pluginRootOf, sweep };
@@ -10,7 +10,7 @@ metadata:
10
10
 
11
11
  The **entrypoint** for the project-spec checks — the harness behind `corpus/spec-floor`. It resolves
12
12
  which spec governs which project and runs each project-spec engine against it. It carries a
13
- self-contained `.mts` script (the repo's node-≥23.6 / no-deps convention).
13
+ self-contained `.mjs` script (compiled from `src/`; no runtime deps, Node ≥22.11).
14
14
 
15
15
  Two scopes:
16
16