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.
Files changed (137) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +2 -2
  3. package/.plugin/plugin.json +1 -1
  4. package/agents/sdd-automaton.md +2 -3
  5. package/agents/sdd-impl-judge.md +5 -4
  6. package/agents/sdd-scanner.md +1 -1
  7. package/agents/sdd-spec-judge.md +3 -3
  8. package/agents/sdd-warden.md +8 -0
  9. package/dist/check-project-specs/scripts/check-project-specs.js +1 -0
  10. package/package.json +2 -2
  11. package/skills/align-spec/README.md +3 -3
  12. package/skills/align-spec/SKILL.md +1 -1
  13. package/skills/align-spec/scripts/align-spec.bundle.mjs +6753 -0
  14. package/skills/align-spec/scripts/align-spec.mjs +12 -0
  15. package/skills/architect-impl-governance/SKILL.md +3 -1
  16. package/skills/architect-spec-governance/SKILL.md +5 -1
  17. package/skills/blast-estimate/README.md +1 -1
  18. package/skills/blast-estimate/SKILL.md +1 -1
  19. package/skills/blast-estimate/scripts/blast-estimate.bundle.mjs +593 -0
  20. package/skills/blast-estimate/scripts/blast-estimate.mjs +12 -0
  21. package/skills/check-field-mandates/SKILL.md +1 -1
  22. package/skills/check-field-mandates/scripts/check-field-mandates.bundle.mjs +251 -0
  23. package/skills/check-field-mandates/scripts/check-field-mandates.mjs +12 -0
  24. package/skills/check-partition-quality/SKILL.md +1 -1
  25. package/skills/check-partition-quality/scripts/check-partition-quality.bundle.mjs +233 -0
  26. package/skills/check-partition-quality/scripts/check-partition-quality.mjs +12 -0
  27. package/skills/check-plan-safety/README.md +3 -3
  28. package/skills/check-plan-safety/SKILL.md +1 -1
  29. package/skills/check-plan-safety/scripts/check-plan-safety.bundle.mjs +107 -0
  30. package/skills/check-plan-safety/scripts/check-plan-safety.mjs +12 -0
  31. package/skills/check-plugin-manifests/SKILL.md +1 -1
  32. package/skills/check-plugin-manifests/scripts/check-plugin-manifests.bundle.mjs +248 -0
  33. package/skills/check-plugin-manifests/scripts/check-plugin-manifests.mjs +12 -0
  34. package/skills/check-project-specs/README.md +3 -3
  35. package/skills/check-project-specs/SKILL.md +2 -2
  36. package/skills/check-project-specs/scripts/check-project-specs.bundle.mjs +584 -0
  37. package/skills/check-project-specs/scripts/check-project-specs.mjs +12 -0
  38. package/skills/check-project-specs/scripts/check-project-specs.mts +1 -0
  39. package/skills/check-retired-terms/README.md +2 -2
  40. package/skills/check-retired-terms/SKILL.md +2 -2
  41. package/skills/check-retired-terms/scripts/check-retired-terms.bundle.mjs +184 -0
  42. package/skills/check-retired-terms/scripts/check-retired-terms.mjs +12 -0
  43. package/skills/check-scenario-overlap/README.md +2 -2
  44. package/skills/check-scenario-overlap/SKILL.md +2 -3
  45. package/skills/check-scenario-overlap/scripts/check-scenario-overlap.bundle.mjs +175 -0
  46. package/skills/check-scenario-overlap/scripts/check-scenario-overlap.mjs +12 -0
  47. package/skills/check-spec-references/README.md +1 -1
  48. package/skills/check-spec-references/SKILL.md +1 -1
  49. package/skills/check-spec-references/scripts/check-spec-references.bundle.mjs +285 -0
  50. package/skills/check-spec-references/scripts/check-spec-references.mjs +12 -0
  51. package/skills/check-spec-structure/README.md +2 -2
  52. package/skills/check-spec-structure/SKILL.md +1 -1
  53. package/skills/check-spec-structure/scripts/check-spec-structure.bundle.mjs +241 -0
  54. package/skills/check-spec-structure/scripts/check-spec-structure.mjs +12 -0
  55. package/skills/collision-ladder/SKILL.md +3 -3
  56. package/skills/collision-ladder/scripts/collision-ladder.bundle.mjs +7041 -0
  57. package/skills/collision-ladder/scripts/collision-ladder.mjs +12 -0
  58. package/skills/collision-ladder/scripts/collision-ladder.mts +4 -2
  59. package/skills/combat-log-governance/SKILL.md +1 -1
  60. package/skills/concept-index/README.md +2 -2
  61. package/skills/concept-index/SKILL.md +1 -1
  62. package/skills/concept-index/scripts/concept-index.bundle.mjs +181 -0
  63. package/skills/concept-index/scripts/concept-index.mjs +12 -0
  64. package/skills/discover-plans/README.md +2 -2
  65. package/skills/discover-plans/SKILL.md +1 -1
  66. package/skills/discover-plans/scripts/discover-plans.bundle.mjs +135 -0
  67. package/skills/discover-plans/scripts/discover-plans.mjs +12 -0
  68. package/skills/discover-specs/README.md +1 -1
  69. package/skills/discover-specs/SKILL.md +1 -1
  70. package/skills/discover-specs/scripts/discover-specs.bundle.mjs +319 -0
  71. package/skills/discover-specs/scripts/discover-specs.mjs +12 -0
  72. package/skills/doctrine-loop/SKILL.md +2 -2
  73. package/skills/formation-loop/SKILL.md +11 -4
  74. package/skills/gate-validation-governance/SKILL.md +1 -1
  75. package/skills/init/README.md +3 -3
  76. package/skills/init/SKILL.md +3 -3
  77. package/skills/init/scripts/wire-statusline.bundle.mjs +166 -0
  78. package/skills/init/scripts/wire-statusline.mjs +12 -0
  79. package/skills/manage-ignore/README.md +5 -5
  80. package/skills/manage-ignore/SKILL.md +1 -1
  81. package/skills/manage-ignore/scripts/manage-ignore.bundle.mjs +244 -0
  82. package/skills/manage-ignore/scripts/manage-ignore.mjs +12 -0
  83. package/skills/manage-scenario-bridge/README.md +3 -3
  84. package/skills/manage-scenario-bridge/SKILL.md +1 -1
  85. package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.bundle.mjs +237 -0
  86. package/skills/manage-scenario-bridge/scripts/manage-scenario-bridge.mjs +12 -0
  87. package/skills/manage-spec-anchors/README.md +4 -4
  88. package/skills/manage-spec-anchors/SKILL.md +1 -1
  89. package/skills/manage-spec-anchors/scripts/manage-spec-anchors.bundle.mjs +308 -0
  90. package/skills/manage-spec-anchors/scripts/manage-spec-anchors.mjs +12 -0
  91. package/skills/mission-graph/SKILL.md +9 -9
  92. package/skills/mission-graph/scripts/mission-graph.bundle.mjs +1038 -0
  93. package/skills/mission-graph/scripts/mission-graph.mjs +12 -0
  94. package/skills/pause-mission/SKILL.md +1 -1
  95. package/skills/place-node/README.md +1 -1
  96. package/skills/place-node/SKILL.md +1 -1
  97. package/skills/place-node/scripts/place-node.bundle.mjs +115 -0
  98. package/skills/place-node/scripts/place-node.mjs +12 -0
  99. package/skills/plan-retirement/SKILL.md +1 -1
  100. package/skills/plan-retirement/scripts/retire-plans.bundle.mjs +121 -0
  101. package/skills/plan-retirement/scripts/retire-plans.mjs +12 -0
  102. package/skills/plan-retirement/scripts/retire-plans.mts +6 -0
  103. package/skills/plugin-contract-governance/SKILL.md +5 -12
  104. package/skills/resolve-governances/README.md +1 -1
  105. package/skills/resolve-governances/SKILL.md +1 -1
  106. package/skills/resolve-governances/scripts/resolve-governances.bundle.mjs +350 -0
  107. package/skills/resolve-governances/scripts/resolve-governances.mjs +12 -0
  108. package/skills/resolve-governances/scripts/resolve-governances.mts +1 -1
  109. package/skills/resolve-tracking/SKILL.md +1 -1
  110. package/skills/resolve-tracking/scripts/resolve-tracking.bundle.mjs +150 -0
  111. package/skills/resolve-tracking/scripts/resolve-tracking.mjs +12 -0
  112. package/skills/scaffold-project-spec/SKILL.md +2 -2
  113. package/skills/sdd/SKILL.md +1 -1
  114. package/skills/solution-producer-governance/README.md +1 -1
  115. package/skills/solution-producer-governance/SKILL.md +1 -1
  116. package/skills/spec-gate/SKILL.md +5 -5
  117. package/skills/spec-gate/scripts/check-spec-state.bundle.mjs +420 -0
  118. package/skills/spec-gate/scripts/check-spec-state.mjs +12 -0
  119. package/skills/spec-gate/scripts/check-suite.bundle.mjs +6498 -0
  120. package/skills/spec-gate/scripts/check-suite.mjs +12 -0
  121. package/skills/spec-gate/scripts/classify-edit-class.bundle.mjs +6577 -0
  122. package/skills/spec-gate/scripts/classify-edit-class.mjs +12 -0
  123. package/skills/spec-producer-governance/README.md +1 -1
  124. package/skills/spec-producer-governance/SKILL.md +3 -3
  125. package/skills/spec-structure-governance/README.md +4 -2
  126. package/skills/spec-structure-governance/SKILL.md +42 -7
  127. package/skills/start-mission/README.md +1 -1
  128. package/skills/start-mission/SKILL.md +6 -6
  129. package/skills/suite-format-governance/references/rubric.md +1 -1
  130. package/skills/touch-set-correction/SKILL.md +2 -2
  131. package/skills/touch-set-correction/scripts/touch-set-correction.bundle.mjs +6655 -0
  132. package/skills/touch-set-correction/scripts/touch-set-correction.mjs +12 -0
  133. package/skills/touch-set-correction/scripts/touch-set-correction.mts +12 -3
  134. package/skills/verify-scenarios/README.md +3 -3
  135. package/skills/verify-scenarios/SKILL.md +3 -3
  136. package/skills/verify-scenarios/scripts/verify-scenarios.bundle.mjs +6537 -0
  137. package/skills/verify-scenarios/scripts/verify-scenarios.mjs +12 -0
@@ -0,0 +1,244 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, writeFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ //#region skills/manage-ignore/scripts/manage-ignore.mts
6
+ const IGNORE_FILE = ".agents/sdd/.sddignore";
7
+ const SKIP_DIRS = /* @__PURE__ */ new Set([
8
+ "node_modules",
9
+ ".git",
10
+ "dist",
11
+ ".turbo",
12
+ ".next",
13
+ "coverage"
14
+ ]);
15
+ function splitLines(text) {
16
+ const lines = text.split("\n");
17
+ if (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
18
+ return lines;
19
+ }
20
+ function readIgnoreLines(root) {
21
+ const file = join(root, IGNORE_FILE);
22
+ if (!existsSync(file)) return [];
23
+ try {
24
+ return splitLines(readFileSync(file, "utf8"));
25
+ } catch {
26
+ return [];
27
+ }
28
+ }
29
+ function writeIgnoreLines(root, lines) {
30
+ const file = join(root, IGNORE_FILE);
31
+ mkdirSync(dirname(file), { recursive: true });
32
+ writeFileSync(file, lines.length === 0 ? "" : `${lines.join("\n")}\n`);
33
+ }
34
+ function isRuleLine(line) {
35
+ const t = line.trim();
36
+ return t !== "" && !t.startsWith("#");
37
+ }
38
+ function listRules(root) {
39
+ return readIgnoreLines(root).filter(isRuleLine).map((l) => l.trim());
40
+ }
41
+ function hasUnclosedBracket(s) {
42
+ let i = 0;
43
+ while (i < s.length) {
44
+ if (s[i] === "\\") {
45
+ i += 2;
46
+ continue;
47
+ }
48
+ if (s[i] === "[") {
49
+ const close = s.indexOf("]", i + 1);
50
+ if (close === -1) return true;
51
+ i = close + 1;
52
+ continue;
53
+ }
54
+ i++;
55
+ }
56
+ return false;
57
+ }
58
+ function isValidPattern(pattern) {
59
+ let s = pattern;
60
+ if (s.startsWith("!")) s = s.slice(1);
61
+ s = s.replace(/^\s+|\s+$/g, "");
62
+ if (s === "" || s.startsWith("#")) return false;
63
+ if (hasUnclosedBracket(s)) return false;
64
+ return true;
65
+ }
66
+ function addRule(root, pattern) {
67
+ const p = pattern.trim();
68
+ if (!isValidPattern(p)) return {
69
+ ok: false,
70
+ reason: "malformed gitignore pattern"
71
+ };
72
+ const lines = readIgnoreLines(root);
73
+ if (lines.some((l) => l.trim() === p)) return {
74
+ ok: true,
75
+ changed: false,
76
+ rules: listRules(root),
77
+ message: "already present"
78
+ };
79
+ const next = [...lines, p];
80
+ writeIgnoreLines(root, next);
81
+ return {
82
+ ok: true,
83
+ changed: true,
84
+ rules: next.filter(isRuleLine).map((l) => l.trim()),
85
+ message: `added ${p}`
86
+ };
87
+ }
88
+ function removeRule(root, pattern) {
89
+ const p = pattern.trim();
90
+ const lines = readIgnoreLines(root);
91
+ const next = lines.filter((l) => l.trim() !== p);
92
+ if (next.length === lines.length) return {
93
+ ok: true,
94
+ changed: false,
95
+ rules: listRules(root),
96
+ message: "nothing was removed"
97
+ };
98
+ writeIgnoreLines(root, next);
99
+ return {
100
+ ok: true,
101
+ changed: true,
102
+ rules: next.filter(isRuleLine).map((l) => l.trim()),
103
+ message: `removed ${p}`
104
+ };
105
+ }
106
+ function inducePatterns(_root, samplePath) {
107
+ const normalized = samplePath.trim().replace(/\\/g, "/");
108
+ if (normalized.startsWith("/")) return {
109
+ ok: false,
110
+ reason: "path is not repo-relative (absolute)"
111
+ };
112
+ const rel = normalized.replace(/\/+$/g, "");
113
+ if (rel === "" || /(^|\/)\.\.(\/|$)/.test(rel)) return {
114
+ ok: false,
115
+ reason: "path is not repo-relative"
116
+ };
117
+ const generalized = `**/${rel.split("/").pop() ?? rel}`;
118
+ return {
119
+ ok: true,
120
+ candidates: generalized === rel ? [rel] : [rel, generalized]
121
+ };
122
+ }
123
+ function gitignoreToRegExp(pattern) {
124
+ let pat = pattern;
125
+ if (pat.endsWith("/")) pat = pat.slice(0, -1);
126
+ let anchored = pat.startsWith("/");
127
+ if (anchored) pat = pat.slice(1);
128
+ if (pat.includes("/")) anchored = true;
129
+ let body = "";
130
+ for (let i = 0; i < pat.length; i++) {
131
+ const c = pat[i];
132
+ if (c === "*") {
133
+ if (pat[i + 1] === "*") {
134
+ i++;
135
+ if (pat[i + 1] === "/") {
136
+ i++;
137
+ body += "(?:.*/)?";
138
+ } else body += ".*";
139
+ } else body += "[^/]*";
140
+ } else if (c === "?") body += "[^/]";
141
+ else if (c === "[") {
142
+ let j = i + 1;
143
+ let cls = "[";
144
+ if (pat[j] === "!") {
145
+ cls += "^";
146
+ j++;
147
+ }
148
+ while (j < pat.length && pat[j] !== "]") {
149
+ cls += /[\\^\]]/.test(pat[j]) ? `\\${pat[j]}` : pat[j];
150
+ j++;
151
+ }
152
+ cls += "]";
153
+ body += cls;
154
+ i = j;
155
+ } else body += c.replace(/[.+^${}()|\\]/g, "\\$&");
156
+ }
157
+ return new RegExp(`${anchored ? "^" : "^(?:.*/)?"}${body}(?:/.*)?$`);
158
+ }
159
+ function matchesPattern(pattern, path) {
160
+ return gitignoreToRegExp(pattern.startsWith("!") ? pattern.slice(1) : pattern).test(path);
161
+ }
162
+ function walkTree(root) {
163
+ const out = [];
164
+ const walk = (rel) => {
165
+ let entries;
166
+ try {
167
+ entries = readdirSync(join(root, rel), { withFileTypes: true });
168
+ } catch {
169
+ return;
170
+ }
171
+ for (const e of entries) {
172
+ if (SKIP_DIRS.has(e.name)) continue;
173
+ const child = rel ? `${rel}/${e.name}` : e.name;
174
+ out.push(child);
175
+ if (e.isDirectory()) walk(child);
176
+ }
177
+ };
178
+ walk("");
179
+ return out.sort();
180
+ }
181
+ function previewPattern(root, pattern) {
182
+ const p = pattern.trim();
183
+ if (!isValidPattern(p)) return {
184
+ ok: false,
185
+ reason: "malformed gitignore pattern"
186
+ };
187
+ return {
188
+ ok: true,
189
+ negated: p.startsWith("!"),
190
+ matches: walkTree(root).filter((path) => matchesPattern(p, path))
191
+ };
192
+ }
193
+ function flag(argv, name) {
194
+ const i = argv.indexOf(name);
195
+ return i === -1 ? void 0 : argv[i + 1];
196
+ }
197
+ function main(argv) {
198
+ const root = flag(argv, "--root") ?? ".";
199
+ const w = (s) => process.stdout.write(`${s}\n`);
200
+ if (argv.includes("--list")) {
201
+ for (const rule of listRules(root)) w(rule);
202
+ return 0;
203
+ }
204
+ if (argv.includes("--add")) {
205
+ const r = addRule(root, flag(argv, "--add") ?? "");
206
+ w(r.ok ? r.message : `refused: ${r.reason}`);
207
+ return r.ok ? 0 : 1;
208
+ }
209
+ if (argv.includes("--remove")) {
210
+ const r = removeRule(root, flag(argv, "--remove") ?? "");
211
+ w(r.ok ? r.message : `refused: ${r.reason}`);
212
+ return r.ok ? 0 : 1;
213
+ }
214
+ if (argv.includes("--induce")) {
215
+ const r = inducePatterns(root, flag(argv, "--induce") ?? "");
216
+ if (!r.ok) {
217
+ w(`unusable: ${r.reason}`);
218
+ return 1;
219
+ }
220
+ w("Candidate ignore patterns:");
221
+ for (const c of r.candidates) w(` ${c}`);
222
+ return 0;
223
+ }
224
+ if (argv.includes("--preview")) {
225
+ const r = previewPattern(root, flag(argv, "--preview") ?? "");
226
+ if (!r.ok) {
227
+ w(`invalid: ${r.reason}`);
228
+ return 1;
229
+ }
230
+ const verb = r.negated ? "re-track" : "ignore";
231
+ if (r.matches.length === 0) {
232
+ w(`This pattern would ${verb} no path.`);
233
+ return 0;
234
+ }
235
+ w(`This pattern would ${verb}:`);
236
+ for (const m of r.matches) w(` ${m}`);
237
+ return 0;
238
+ }
239
+ w("usage: manage-ignore --list | --add <p> | --remove <p> | --induce <path> | --preview <p>");
240
+ return 0;
241
+ }
242
+ if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) process.exit(main(process.argv.slice(2)));
243
+ //#endregion
244
+ export { addRule, gitignoreToRegExp, inducePatterns, isRuleLine, isValidPattern, listRules, main, matchesPattern, previewPattern, readIgnoreLines, removeRule, splitLines };
@@ -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
@@ -11,10 +11,10 @@ config.
11
11
  - **Tests:** [`scripts/manage-scenario-bridge.test.mts`](./scripts/manage-scenario-bridge.test.mts) (`node:test`)
12
12
 
13
13
  ```bash
14
- node scripts/manage-scenario-bridge.mts --project-path packages/cyberlegion --list
15
- node scripts/manage-scenario-bridge.mts --project-path packages/cyberlegion --scaffold \
14
+ node scripts/manage-scenario-bridge.mjs --project-path packages/cyberlegion --list
15
+ node scripts/manage-scenario-bridge.mjs --project-path packages/cyberlegion --scaffold \
16
16
  --adapter junit --command "vitest run --reporter=junit --outputFile=.agents/.scenario-report.xml" \
17
17
  --report-path .agents/.scenario-report.xml
18
- node scripts/manage-scenario-bridge.mts --project-path packages/cyberlegion --add \
18
+ node scripts/manage-scenario-bridge.mjs --project-path packages/cyberlegion --add \
19
19
  --adapter junit --report-path .agents/.other-report.xml
20
20
  ```
@@ -35,7 +35,7 @@ reports it covers.
35
35
  ## Run an operation
36
36
 
37
37
  ```bash
38
- node "<skill>/scripts/manage-scenario-bridge.mts" --project-path <dir> <operation>
38
+ node "<skill>/scripts/manage-scenario-bridge.mjs" --project-path <dir> <operation>
39
39
  ```
40
40
 
41
41
  | Operation | Effect |
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ //#region skills/spec-gate/vendor/gherkin-cli.mjs
6
+ var TokenType;
7
+ (function(TokenType) {
8
+ TokenType[TokenType["None"] = 0] = "None";
9
+ TokenType[TokenType["EOF"] = 1] = "EOF";
10
+ TokenType[TokenType["Empty"] = 2] = "Empty";
11
+ TokenType[TokenType["Comment"] = 3] = "Comment";
12
+ TokenType[TokenType["TagLine"] = 4] = "TagLine";
13
+ TokenType[TokenType["FeatureLine"] = 5] = "FeatureLine";
14
+ TokenType[TokenType["RuleLine"] = 6] = "RuleLine";
15
+ TokenType[TokenType["BackgroundLine"] = 7] = "BackgroundLine";
16
+ TokenType[TokenType["ScenarioLine"] = 8] = "ScenarioLine";
17
+ TokenType[TokenType["ExamplesLine"] = 9] = "ExamplesLine";
18
+ TokenType[TokenType["StepLine"] = 10] = "StepLine";
19
+ TokenType[TokenType["DocStringSeparator"] = 11] = "DocStringSeparator";
20
+ TokenType[TokenType["TableRow"] = 12] = "TableRow";
21
+ TokenType[TokenType["Language"] = 13] = "Language";
22
+ TokenType[TokenType["Other"] = 14] = "Other";
23
+ })(TokenType || (TokenType = {}));
24
+ var RuleType;
25
+ (function(RuleType) {
26
+ RuleType[RuleType["None"] = 0] = "None";
27
+ RuleType[RuleType["_EOF"] = 1] = "_EOF";
28
+ RuleType[RuleType["_Empty"] = 2] = "_Empty";
29
+ RuleType[RuleType["_Comment"] = 3] = "_Comment";
30
+ RuleType[RuleType["_TagLine"] = 4] = "_TagLine";
31
+ RuleType[RuleType["_FeatureLine"] = 5] = "_FeatureLine";
32
+ RuleType[RuleType["_RuleLine"] = 6] = "_RuleLine";
33
+ RuleType[RuleType["_BackgroundLine"] = 7] = "_BackgroundLine";
34
+ RuleType[RuleType["_ScenarioLine"] = 8] = "_ScenarioLine";
35
+ RuleType[RuleType["_ExamplesLine"] = 9] = "_ExamplesLine";
36
+ RuleType[RuleType["_StepLine"] = 10] = "_StepLine";
37
+ RuleType[RuleType["_DocStringSeparator"] = 11] = "_DocStringSeparator";
38
+ RuleType[RuleType["_TableRow"] = 12] = "_TableRow";
39
+ RuleType[RuleType["_Language"] = 13] = "_Language";
40
+ RuleType[RuleType["_Other"] = 14] = "_Other";
41
+ RuleType[RuleType["GherkinDocument"] = 15] = "GherkinDocument";
42
+ RuleType[RuleType["Feature"] = 16] = "Feature";
43
+ RuleType[RuleType["FeatureHeader"] = 17] = "FeatureHeader";
44
+ RuleType[RuleType["Rule"] = 18] = "Rule";
45
+ RuleType[RuleType["RuleHeader"] = 19] = "RuleHeader";
46
+ RuleType[RuleType["Background"] = 20] = "Background";
47
+ RuleType[RuleType["ScenarioDefinition"] = 21] = "ScenarioDefinition";
48
+ RuleType[RuleType["Scenario"] = 22] = "Scenario";
49
+ RuleType[RuleType["ExamplesDefinition"] = 23] = "ExamplesDefinition";
50
+ RuleType[RuleType["Examples"] = 24] = "Examples";
51
+ RuleType[RuleType["ExamplesTable"] = 25] = "ExamplesTable";
52
+ RuleType[RuleType["Step"] = 26] = "Step";
53
+ RuleType[RuleType["StepArg"] = 27] = "StepArg";
54
+ RuleType[RuleType["DataTable"] = 28] = "DataTable";
55
+ RuleType[RuleType["DocString"] = 29] = "DocString";
56
+ RuleType[RuleType["Tags"] = 30] = "Tags";
57
+ RuleType[RuleType["DescriptionHelper"] = 31] = "DescriptionHelper";
58
+ RuleType[RuleType["Description"] = 32] = "Description";
59
+ })(RuleType || (RuleType = {}));
60
+ var AttachmentContentEncoding;
61
+ (function(AttachmentContentEncoding) {
62
+ AttachmentContentEncoding["IDENTITY"] = "IDENTITY";
63
+ AttachmentContentEncoding["BASE64"] = "BASE64";
64
+ })(AttachmentContentEncoding || (AttachmentContentEncoding = {}));
65
+ var HookType;
66
+ (function(HookType) {
67
+ HookType["BEFORE_TEST_RUN"] = "BEFORE_TEST_RUN";
68
+ HookType["AFTER_TEST_RUN"] = "AFTER_TEST_RUN";
69
+ HookType["BEFORE_TEST_CASE"] = "BEFORE_TEST_CASE";
70
+ HookType["AFTER_TEST_CASE"] = "AFTER_TEST_CASE";
71
+ HookType["BEFORE_TEST_STEP"] = "BEFORE_TEST_STEP";
72
+ HookType["AFTER_TEST_STEP"] = "AFTER_TEST_STEP";
73
+ })(HookType || (HookType = {}));
74
+ var PickleStepType;
75
+ (function(PickleStepType) {
76
+ PickleStepType["UNKNOWN"] = "Unknown";
77
+ PickleStepType["CONTEXT"] = "Context";
78
+ PickleStepType["ACTION"] = "Action";
79
+ PickleStepType["OUTCOME"] = "Outcome";
80
+ })(PickleStepType || (PickleStepType = {}));
81
+ var SourceMediaType;
82
+ (function(SourceMediaType) {
83
+ SourceMediaType["TEXT_X_CUCUMBER_GHERKIN_PLAIN"] = "text/x.cucumber.gherkin+plain";
84
+ SourceMediaType["TEXT_X_CUCUMBER_GHERKIN_MARKDOWN"] = "text/x.cucumber.gherkin+markdown";
85
+ })(SourceMediaType || (SourceMediaType = {}));
86
+ var StepDefinitionPatternType;
87
+ (function(StepDefinitionPatternType) {
88
+ StepDefinitionPatternType["CUCUMBER_EXPRESSION"] = "CUCUMBER_EXPRESSION";
89
+ StepDefinitionPatternType["REGULAR_EXPRESSION"] = "REGULAR_EXPRESSION";
90
+ })(StepDefinitionPatternType || (StepDefinitionPatternType = {}));
91
+ var StepKeywordType;
92
+ (function(StepKeywordType) {
93
+ StepKeywordType["UNKNOWN"] = "Unknown";
94
+ StepKeywordType["CONTEXT"] = "Context";
95
+ StepKeywordType["ACTION"] = "Action";
96
+ StepKeywordType["OUTCOME"] = "Outcome";
97
+ StepKeywordType["CONJUNCTION"] = "Conjunction";
98
+ })(StepKeywordType || (StepKeywordType = {}));
99
+ var TestStepResultStatus;
100
+ (function(TestStepResultStatus) {
101
+ TestStepResultStatus["UNKNOWN"] = "UNKNOWN";
102
+ TestStepResultStatus["PASSED"] = "PASSED";
103
+ TestStepResultStatus["SKIPPED"] = "SKIPPED";
104
+ TestStepResultStatus["PENDING"] = "PENDING";
105
+ TestStepResultStatus["UNDEFINED"] = "UNDEFINED";
106
+ TestStepResultStatus["AMBIGUOUS"] = "AMBIGUOUS";
107
+ TestStepResultStatus["FAILED"] = "FAILED";
108
+ })(TestStepResultStatus || (TestStepResultStatus = {}));
109
+ var KeywordPrefix;
110
+ (function(KeywordPrefix) {
111
+ KeywordPrefix["BULLET"] = "^(\\s*[*+-]\\s*)";
112
+ KeywordPrefix["HEADER"] = "^(#{1,6}\\s)";
113
+ })(KeywordPrefix || (KeywordPrefix = {}));
114
+ StepKeywordType.UNKNOWN, PickleStepType.UNKNOWN, StepKeywordType.CONTEXT, PickleStepType.CONTEXT, StepKeywordType.ACTION, PickleStepType.ACTION, StepKeywordType.OUTCOME, PickleStepType.OUTCOME, StepKeywordType.CONJUNCTION;
115
+ //#endregion
116
+ //#region skills/verify-scenarios/scripts/verify-scenarios.mts
117
+ function parseSourcesToml(text) {
118
+ const out = [];
119
+ const blocks = text.split(/(?=^\s*\[\[source\]\]\s*$)/m).filter((b) => /^\s*\[\[source\]\]\s*$/m.test(b));
120
+ for (const block of blocks) {
121
+ const body = block.replace(/^\s*\[\[source\]\]\s*$/m, "");
122
+ const fields = {};
123
+ for (const m of body.matchAll(/^\s*([A-Za-z_][\w-]*)\s*=\s*(?:"([^"]*)"|'([^']*)')\s*$/gm)) fields[m[1]] = m[2] ?? m[3] ?? "";
124
+ if (!fields.adapter || !fields.reportPath) continue;
125
+ out.push({
126
+ adapter: fields.adapter,
127
+ command: fields.command,
128
+ reportPath: fields.reportPath
129
+ });
130
+ }
131
+ return out;
132
+ }
133
+ if (process.argv[1] && false);
134
+ //#endregion
135
+ //#region skills/manage-scenario-bridge/scripts/manage-scenario-bridge.mts
136
+ const CONFIG_REL_PATH = ".agents/sdd/scenario-bridge.toml";
137
+ function configPath(projectPath) {
138
+ return join(projectPath, CONFIG_REL_PATH);
139
+ }
140
+ function listSources(projectPath) {
141
+ const file = configPath(projectPath);
142
+ if (!existsSync(file)) return [];
143
+ try {
144
+ return parseSourcesToml(readFileSync(file, "utf8"));
145
+ } catch {
146
+ return [];
147
+ }
148
+ }
149
+ function renderBlock(source) {
150
+ return [
151
+ "[[source]]",
152
+ `adapter = "${source.adapter}"`,
153
+ ...source.command !== void 0 ? [`command = "${source.command}"`] : [],
154
+ `reportPath = "${source.reportPath}"`
155
+ ].join("\n");
156
+ }
157
+ function validateInput(input) {
158
+ if (!input.adapter || !input.reportPath) return {
159
+ ok: false,
160
+ reason: "a source needs both adapter and reportPath"
161
+ };
162
+ return {
163
+ ok: true,
164
+ adapter: input.adapter,
165
+ command: input.command,
166
+ reportPath: input.reportPath
167
+ };
168
+ }
169
+ function scaffoldSource(projectPath, input) {
170
+ const valid = validateInput(input);
171
+ if (!valid.ok) return valid;
172
+ const file = configPath(projectPath);
173
+ if (existsSync(file)) return {
174
+ ok: false,
175
+ reason: "scenario-bridge.toml already exists; use add to append a source"
176
+ };
177
+ mkdirSync(dirname(file), { recursive: true });
178
+ writeFileSync(file, `${renderBlock(valid)}\n`);
179
+ const sources = listSources(projectPath);
180
+ return {
181
+ ok: true,
182
+ message: `scaffolded ${file}`,
183
+ sources
184
+ };
185
+ }
186
+ function addSource(projectPath, input) {
187
+ const valid = validateInput(input);
188
+ if (!valid.ok) return valid;
189
+ const file = configPath(projectPath);
190
+ if (!existsSync(file)) return {
191
+ ok: false,
192
+ reason: "scenario-bridge.toml does not exist yet; use scaffold to create it first"
193
+ };
194
+ const existing = readFileSync(file, "utf8");
195
+ const sep = existing.endsWith("\n") ? "" : "\n";
196
+ writeFileSync(file, `${existing}${sep}\n${renderBlock(valid)}\n`);
197
+ const sources = listSources(projectPath);
198
+ return {
199
+ ok: true,
200
+ message: `added a source to ${file}`,
201
+ sources
202
+ };
203
+ }
204
+ function flag(argv, name) {
205
+ const i = argv.indexOf(name);
206
+ return i === -1 ? void 0 : argv[i + 1];
207
+ }
208
+ function inputFromArgv(argv) {
209
+ return {
210
+ adapter: flag(argv, "--adapter"),
211
+ command: flag(argv, "--command"),
212
+ reportPath: flag(argv, "--report-path")
213
+ };
214
+ }
215
+ function main(argv) {
216
+ const projectPath = flag(argv, "--project-path") ?? ".";
217
+ const w = (s) => process.stdout.write(`${s}\n`);
218
+ if (argv.includes("--list")) {
219
+ for (const s of listSources(projectPath)) w(`${s.adapter}${s.command ? ` (${s.command})` : ""} -> ${s.reportPath}`);
220
+ return 0;
221
+ }
222
+ if (argv.includes("--scaffold")) {
223
+ const r = scaffoldSource(projectPath, inputFromArgv(argv));
224
+ w(r.ok ? r.message : `refused: ${r.reason}`);
225
+ return r.ok ? 0 : 1;
226
+ }
227
+ if (argv.includes("--add")) {
228
+ const r = addSource(projectPath, inputFromArgv(argv));
229
+ w(r.ok ? r.message : `refused: ${r.reason}`);
230
+ return r.ok ? 0 : 1;
231
+ }
232
+ w("usage: manage-scenario-bridge --project-path <dir> --list | --scaffold --adapter <a> [--command <c>] --report-path <p> | --add --adapter <a> [--command <c>] --report-path <p>");
233
+ return 0;
234
+ }
235
+ if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) process.exit(main(process.argv.slice(2)));
236
+ //#endregion
237
+ export { addSource, configPath, listSources, main, scaffoldSource };
@@ -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
@@ -11,8 +11,8 @@ that lists / CRUDs / induces / previews the anchors so users never hand-edit
11
11
  - **Tests:** [`scripts/manage-spec-anchors.test.mts`](./scripts/manage-spec-anchors.test.mts) (`node:test`)
12
12
 
13
13
  ```bash
14
- node scripts/manage-spec-anchors.mts --list
15
- node scripts/manage-spec-anchors.mts --induce curriculum/web/react/s-01
16
- node scripts/manage-spec-anchors.mts --preview 'curriculum/*/*/<project>'
17
- node scripts/manage-spec-anchors.mts --add 'curriculum/*/*/<project>'
14
+ node scripts/manage-spec-anchors.mjs --list
15
+ node scripts/manage-spec-anchors.mjs --induce curriculum/web/react/s-01
16
+ node scripts/manage-spec-anchors.mjs --preview 'curriculum/*/*/<project>'
17
+ node scripts/manage-spec-anchors.mjs --add 'curriculum/*/*/<project>'
18
18
  ```
@@ -26,7 +26,7 @@ never listed here, and never curatable.
26
26
  ## Run an operation
27
27
 
28
28
  ```bash
29
- node "<skill>/scripts/manage-spec-anchors.mts" [--root .] <operation>
29
+ node "<skill>/scripts/manage-spec-anchors.mjs" [--root .] <operation>
30
30
  ```
31
31
 
32
32
  | Operation | Effect |