@gobing-ai/spur 0.3.53 → 0.3.55

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 (96) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/corpus-baseline.json +2783 -2783
  3. package/config/pipeline-budgets.json +42 -0
  4. package/config/plugin-scripts.json +73 -0
  5. package/config/workflow-composition-baseline.json +561 -0
  6. package/config/workflows/docs-pipeline.yaml +29 -13
  7. package/config/workflows/feature-dev.yaml +54 -2
  8. package/config/workflows/idea-pipeline.yaml +15 -0
  9. package/config/workflows/task-pipeline.yaml +77 -65
  10. package/config/workflows/wrapup-pipeline.yaml +40 -45
  11. package/package.json +9 -9
  12. package/plugins/README.md +1 -1
  13. package/plugins/sp/README.md +3 -3
  14. package/plugins/sp/agents/super-planner.md +1 -1
  15. package/plugins/sp/commands/dev-daily.md +1 -1
  16. package/plugins/sp/commands/dev-history-load.md +1 -1
  17. package/plugins/sp/commands/dev-idea.md +10 -2
  18. package/plugins/sp/plugin.json +1 -1
  19. package/plugins/sp/scripts/batch-preflight.mjs +160 -0
  20. package/plugins/sp/scripts/batch-preflight.ts +1 -1
  21. package/plugins/sp/scripts/daily-summary/daily-summary.mjs +479 -0
  22. package/plugins/sp/scripts/daily-summary/daily-summary.ts +75 -37
  23. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +204 -0
  24. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +1 -1
  25. package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +141 -0
  26. package/plugins/sp/scripts/dogfood-testing/validate-report.ts +1 -1
  27. package/plugins/sp/scripts/feature-sync-bounded.mjs +290 -0
  28. package/plugins/sp/scripts/feature-sync-bounded.ts +9 -8
  29. package/plugins/sp/scripts/history-load.mjs +268 -0
  30. package/plugins/sp/scripts/pr-reviewing.mjs +685 -0
  31. package/plugins/sp/scripts/pr-reviewing.ts +1 -1
  32. package/plugins/sp/scripts/script-contract-check.ts +319 -0
  33. package/plugins/sp/skills/daily-summary/SKILL.md +3 -3
  34. package/plugins/sp/skills/dogfood-testing/SKILL.md +5 -5
  35. package/plugins/sp/skills/dogfood-testing/references/report-template.md +1 -1
  36. package/plugins/sp/skills/pr-reviewing/SKILL.md +3 -3
  37. package/plugins/sp/skills/spur-dev/SKILL.md +2 -1
  38. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +3 -4
  39. package/plugins/sp/skills/spur-dev/references/dev-operations.md +1 -1
  40. package/plugins/sp/skills/spur-dev/references/execution-batch.md +3 -3
  41. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +4 -4
  42. package/spur.js +4270 -1323
  43. package/web/_astro/{BoardApp.plVXYkKo.js → BoardApp.DCLSB3Zs.js} +63 -63
  44. package/web/_astro/BoardApp.Dx5gzAhb.js +1 -0
  45. package/web/_astro/{TaskDetail.5DIyVQ_N.js → TaskDetail.DN_RxS-2.js} +1 -1
  46. package/web/_astro/{arc.BnUgL7ho.js → arc.CldTHRg-.js} +1 -1
  47. package/web/_astro/{architectureDiagram-3BPJPVTR.B9YMJau-.js → architectureDiagram-3BPJPVTR.DQ4T9oeU.js} +1 -1
  48. package/web/_astro/{blockDiagram-GPEHLZMM.Dw2qgvWJ.js → blockDiagram-GPEHLZMM.CGDaXH8J.js} +1 -1
  49. package/web/_astro/{c4Diagram-AAUBKEIU.jTbU0-Nk.js → c4Diagram-AAUBKEIU.Cqsc2iub.js} +1 -1
  50. package/web/_astro/channel.CrBJYpxo.js +1 -0
  51. package/web/_astro/{chunk-2J33WTMH.Di46EtkU.js → chunk-2J33WTMH.CQSKsRmq.js} +1 -1
  52. package/web/_astro/{chunk-4BX2VUAB.DweHBwqQ.js → chunk-4BX2VUAB.Pv1HCtp8.js} +1 -1
  53. package/web/_astro/{chunk-55IACEB6.rRjTKaa7.js → chunk-55IACEB6.-9MseOIk.js} +1 -1
  54. package/web/_astro/{chunk-727SXJPM.BkEQIkSV.js → chunk-727SXJPM.M3OI1DF7.js} +1 -1
  55. package/web/_astro/{chunk-AQP2D5EJ.Cfe9IvAd.js → chunk-AQP2D5EJ.NfHka5Ca.js} +1 -1
  56. package/web/_astro/{chunk-FMBD7UC4.fI6tLbeN.js → chunk-FMBD7UC4.B2suYe3s.js} +1 -1
  57. package/web/_astro/{chunk-ND2GUHAM.BIjgpq0O.js → chunk-ND2GUHAM.BfJ7aucP.js} +1 -1
  58. package/web/_astro/{chunk-QZHKN3VN.ZwLnVxyz.js → chunk-QZHKN3VN._582hZVc.js} +1 -1
  59. package/web/_astro/{classDiagram-4FO5ZUOK.BJAGYidE.js → classDiagram-4FO5ZUOK._tttU_jk.js} +1 -1
  60. package/web/_astro/{classDiagram-v2-Q7XG4LA2.BJAGYidE.js → classDiagram-v2-Q7XG4LA2._tttU_jk.js} +1 -1
  61. package/web/_astro/{cose-bilkent-S5V4N54A.B5y3nz26.js → cose-bilkent-S5V4N54A.C4rVATLQ.js} +1 -1
  62. package/web/_astro/{dagre-BM42HDAG.DHmw0ZBC.js → dagre-BM42HDAG.8BLRi7f9.js} +1 -1
  63. package/web/_astro/{diagram-2AECGRRQ.10gapJfY.js → diagram-2AECGRRQ.D6lwUZos.js} +1 -1
  64. package/web/_astro/{diagram-5GNKFQAL.Gh33_drM.js → diagram-5GNKFQAL.Cl_rMiVT.js} +1 -1
  65. package/web/_astro/{diagram-KO2AKTUF.8ROWlfcX.js → diagram-KO2AKTUF.DhMExHLp.js} +1 -1
  66. package/web/_astro/{diagram-LMA3HP47.BsP3tKmg.js → diagram-LMA3HP47.3OAxzH_o.js} +1 -1
  67. package/web/_astro/{diagram-OG6HWLK6.DM2WFDhU.js → diagram-OG6HWLK6.Uh9RLucG.js} +1 -1
  68. package/web/_astro/{erDiagram-TEJ5UH35.royaC_lH.js → erDiagram-TEJ5UH35.izzElG0c.js} +1 -1
  69. package/web/_astro/{flowDiagram-I6XJVG4X.C9GEvIie.js → flowDiagram-I6XJVG4X.BlGwp5qM.js} +1 -1
  70. package/web/_astro/{ganttDiagram-6RSMTGT7.CXO4T2U0.js → ganttDiagram-6RSMTGT7.je7Vf8dN.js} +1 -1
  71. package/web/_astro/{gitGraphDiagram-PVQCEYII.Q02KzYH7.js → gitGraphDiagram-PVQCEYII.DNk0Ycop.js} +1 -1
  72. package/web/_astro/{index.DAxu50UF.css → index.V6Q7nhed.css} +1 -1
  73. package/web/_astro/{infoDiagram-5YYISTIA.DNfSDKJt.js → infoDiagram-5YYISTIA.K2HhGyWH.js} +1 -1
  74. package/web/_astro/{ishikawaDiagram-YF4QCWOH.BFttvtgJ.js → ishikawaDiagram-YF4QCWOH.BbbOW4IN.js} +1 -1
  75. package/web/_astro/{journeyDiagram-JHISSGLW.Cfm-2SbG.js → journeyDiagram-JHISSGLW.B1UaZKqN.js} +1 -1
  76. package/web/_astro/{kanban-definition-UN3LZRKU.BWGNW6fV.js → kanban-definition-UN3LZRKU.9tsw5QFd.js} +1 -1
  77. package/web/_astro/{linear.BprdUk2Y.js → linear.I9dvtu-j.js} +1 -1
  78. package/web/_astro/{mermaid.core.B2zRNxtX.js → mermaid.core.5bKJsMgf.js} +4 -4
  79. package/web/_astro/{mindmap-definition-RKZ34NQL.g9jij8sw.js → mindmap-definition-RKZ34NQL.BC5MqSn6.js} +1 -1
  80. package/web/_astro/{pieDiagram-4H26LBE5.CbzR4n5b.js → pieDiagram-4H26LBE5.B8GIMyxD.js} +1 -1
  81. package/web/_astro/{quadrantDiagram-W4KKPZXB.DxV3viWt.js → quadrantDiagram-W4KKPZXB.K_aZSM_u.js} +1 -1
  82. package/web/_astro/{requirementDiagram-4Y6WPE33.DvAb90JS.js → requirementDiagram-4Y6WPE33.B_V5kzfT.js} +1 -1
  83. package/web/_astro/{sankeyDiagram-5OEKKPKP.CIFz5t4D.js → sankeyDiagram-5OEKKPKP.DyV2quLS.js} +1 -1
  84. package/web/_astro/{sequenceDiagram-3UESZ5HK.DzlEQynd.js → sequenceDiagram-3UESZ5HK.BlKvPnBv.js} +1 -1
  85. package/web/_astro/{stateDiagram-AJRCARHV.Dph2V-ts.js → stateDiagram-AJRCARHV.C1lYUMdS.js} +1 -1
  86. package/web/_astro/{stateDiagram-v2-BHNVJYJU.wJhfrLAy.js → stateDiagram-v2-BHNVJYJU.DJWjr3QV.js} +1 -1
  87. package/web/_astro/{timeline-definition-PNZ67QCA.BrSiyubX.js → timeline-definition-PNZ67QCA.CYYiXVlv.js} +1 -1
  88. package/web/_astro/{vennDiagram-CIIHVFJN.COobPrUX.js → vennDiagram-CIIHVFJN.zYjQKa_S.js} +1 -1
  89. package/web/_astro/{wardley-L42UT6IY.CrjeTx8A.js → wardley-L42UT6IY.BGrWTY3D.js} +1 -1
  90. package/web/_astro/{wardleyDiagram-YWT4CUSO.B8_fTQ8E.js → wardleyDiagram-YWT4CUSO.CkXxtcI1.js} +1 -1
  91. package/web/_astro/{xychartDiagram-2RQKCTM6.BPpokgVv.js → xychartDiagram-2RQKCTM6.BhKH3KG3.js} +1 -1
  92. package/web/index.html +2 -2
  93. package/config/workflows/planning-pipeline.yaml +0 -249
  94. package/config/workflows/task-pipeline2.yaml +0 -778
  95. package/web/_astro/BoardApp.pdtYu-yW.js +0 -1
  96. package/web/_astro/channel.DEqvaz-I.js +0 -1
@@ -0,0 +1,319 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * script-contract-check — two-sided gate over plugins/sp script entrypoint contracts
4
+ * (task 0600, feature I, ADR-065).
5
+ *
6
+ * Enforces superskill's standard plugin script contract across plugins/sp:
7
+ * 1. A 'standard' entry must have a valid .mjs twin not older than its .ts source.
8
+ * 2. A .mjs twin on disk must be registered under a 'standard' entry (never 'repo-only' or unlisted).
9
+ * 3. Every script file under plugins/sp/scripts/ must have a manifest entry (two-sided).
10
+ * 4. No shipped surface (commands/, skills/, agents/, README.md) may reference 'bun plugins/sp/scripts/'.
11
+ *
12
+ * Usage:
13
+ * bun plugins/sp/scripts/script-contract-check.ts
14
+ * [--manifest <path>] default: config/plugin-scripts.json
15
+ * [--scripts-dir <path>] default: plugins/sp/scripts
16
+ * [--plugin-dir <path>] default: plugins/sp
17
+ *
18
+ * Exit code: 0 on success, 1 on any violation.
19
+ */
20
+
21
+ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
22
+ import { join, resolve } from 'node:path';
23
+
24
+ export type ScriptContractType = 'standard' | 'repo-only';
25
+
26
+ export interface ScriptManifestEntry {
27
+ rel: string;
28
+ contract: ScriptContractType;
29
+ twin?: string;
30
+ }
31
+
32
+ export interface ScriptManifest {
33
+ schema_version?: number;
34
+ description?: string;
35
+ entries: ScriptManifestEntry[];
36
+ }
37
+
38
+ export interface Violation {
39
+ kind:
40
+ | 'missing_twin'
41
+ | 'stale_twin'
42
+ | 'unexpected_twin'
43
+ | 'unregistered_script'
44
+ | 'forbidden_invocation'
45
+ | 'incomplete';
46
+ target: string;
47
+ message: string;
48
+ }
49
+
50
+ export function parseArgs(argv: string[]): {
51
+ manifest: string;
52
+ scriptsDir: string;
53
+ pluginDir: string;
54
+ cwd: string;
55
+ } {
56
+ let manifest = 'config/plugin-scripts.json';
57
+ let scriptsDir = 'plugins/sp/scripts';
58
+ let pluginDir = 'plugins/sp';
59
+ for (let i = 0; i < argv.length; i++) {
60
+ if (argv[i] === '--manifest') manifest = argv[++i] ?? manifest;
61
+ else if (argv[i] === '--scripts-dir') scriptsDir = argv[++i] ?? scriptsDir;
62
+ else if (argv[i] === '--plugin-dir') pluginDir = argv[++i] ?? pluginDir;
63
+ }
64
+ return { manifest, scriptsDir, pluginDir, cwd: process.cwd() };
65
+ }
66
+
67
+ export function loadManifest(path: string): { manifest: ScriptManifest | null; error: string | null } {
68
+ if (!existsSync(path)) return { manifest: null, error: `manifest not found at ${path}` };
69
+ try {
70
+ const raw = readFileSync(path, 'utf8');
71
+ const parsed = JSON.parse(raw) as ScriptManifest;
72
+ if (!Array.isArray(parsed.entries)) {
73
+ return { manifest: null, error: `${path}: missing "entries" array` };
74
+ }
75
+ return { manifest: parsed, error: null };
76
+ } catch (err) {
77
+ return { manifest: null, error: `malformed JSON at ${path}: ${String(err)}` };
78
+ }
79
+ }
80
+
81
+ export function listDiskScripts(scriptsDir: string): { tsFiles: string[]; mjsFiles: string[] } {
82
+ const tsFiles: string[] = [];
83
+ const mjsFiles: string[] = [];
84
+
85
+ function walk(dir: string, base: string): void {
86
+ let entries: string[];
87
+ try {
88
+ entries = readdirSync(dir);
89
+ } catch {
90
+ return;
91
+ }
92
+ for (const entry of entries) {
93
+ const fullPath = join(dir, entry);
94
+ let st: ReturnType<typeof statSync>;
95
+ try {
96
+ st = statSync(fullPath);
97
+ } catch {
98
+ continue;
99
+ }
100
+ if (st.isDirectory()) {
101
+ walk(fullPath, base ? `${base}/${entry}` : entry);
102
+ } else if (st.isFile()) {
103
+ const rel = base ? `${base}/${entry}` : entry;
104
+ if (entry.endsWith('.ts')) {
105
+ tsFiles.push(rel);
106
+ } else if (entry.endsWith('.mjs')) {
107
+ mjsFiles.push(rel);
108
+ }
109
+ }
110
+ }
111
+ }
112
+
113
+ walk(scriptsDir, '');
114
+ return { tsFiles: tsFiles.sort(), mjsFiles: mjsFiles.sort() };
115
+ }
116
+
117
+ export function scanShippedSurfaces(pluginDir: string): Array<{ file: string; line: number; content: string }> {
118
+ const matches: Array<{ file: string; line: number; content: string }> = [];
119
+ const forbiddenPattern = 'bun plugins/sp/scripts/';
120
+
121
+ const searchDirs = ['commands', 'skills', 'agents'];
122
+ const singleFiles = ['README.md'];
123
+
124
+ function scanFile(filePath: string): void {
125
+ if (!existsSync(filePath)) return;
126
+ let text: string;
127
+ try {
128
+ text = readFileSync(filePath, 'utf8');
129
+ } catch {
130
+ return;
131
+ }
132
+ const lines = text.split('\n');
133
+ for (let i = 0; i < lines.length; i++) {
134
+ const line = lines[i] ?? '';
135
+ if (line.includes(forbiddenPattern)) {
136
+ matches.push({
137
+ file: filePath,
138
+ line: i + 1,
139
+ content: line.trim(),
140
+ });
141
+ }
142
+ }
143
+ }
144
+
145
+ function walk(dir: string): void {
146
+ let entries: string[];
147
+ try {
148
+ entries = readdirSync(dir);
149
+ } catch {
150
+ return;
151
+ }
152
+ for (const entry of entries) {
153
+ const fullPath = join(dir, entry);
154
+ let st: ReturnType<typeof statSync>;
155
+ try {
156
+ st = statSync(fullPath);
157
+ } catch {
158
+ continue;
159
+ }
160
+ if (st.isDirectory()) {
161
+ walk(fullPath);
162
+ } else if (
163
+ st.isFile() &&
164
+ (entry.endsWith('.md') || entry.endsWith('.json') || entry.endsWith('.yaml') || entry.endsWith('.yml'))
165
+ ) {
166
+ scanFile(fullPath);
167
+ }
168
+ }
169
+ }
170
+
171
+ for (const d of searchDirs) {
172
+ walk(join(pluginDir, d));
173
+ }
174
+ for (const f of singleFiles) {
175
+ scanFile(join(pluginDir, f));
176
+ }
177
+
178
+ return matches;
179
+ }
180
+
181
+ export function validateContract(manifest: ScriptManifest, scriptsDir: string, pluginDir: string): Violation[] {
182
+ const violations: Violation[] = [];
183
+ const { tsFiles, mjsFiles } = listDiskScripts(scriptsDir);
184
+
185
+ const manifestMap = new Map<string, ScriptManifestEntry>();
186
+ for (const entry of manifest.entries) {
187
+ if (!entry.rel || !entry.contract) {
188
+ violations.push({
189
+ kind: 'incomplete',
190
+ target: entry.rel ?? '<missing>',
191
+ message: `manifest entry missing required fields (rel, contract)`,
192
+ });
193
+ continue;
194
+ }
195
+ manifestMap.set(entry.rel, entry);
196
+ }
197
+
198
+ // Rule 1: standard entries must have valid .mjs twins not older than the .ts source.
199
+ // mtime is only meaningful when a build genuinely ran: a `git worktree add` stamps
200
+ // every checked-out file within the same millisecond, and the lexicographic write
201
+ // order (`tool.mjs` < `tool.ts`) makes the twin spuriously "older" by <1ms. Tolerate
202
+ // sub-second deltas so a fresh checkout is never flagged; real build staleness is
203
+ // seconds-to-minutes, far beyond this window (task 0606 R1 eval-worktree blocker).
204
+ const STALE_TWIN_TOLERANCE_MS = 1000;
205
+ for (const entry of manifest.entries) {
206
+ if (entry.rel && entry.contract === 'standard') {
207
+ const expectedTwinRel = entry.twin ?? entry.rel.replace(/\.ts$/, '.mjs');
208
+ const twinPath = join(scriptsDir, expectedTwinRel);
209
+ const tsPath = join(scriptsDir, entry.rel);
210
+
211
+ if (!existsSync(twinPath)) {
212
+ violations.push({
213
+ kind: 'missing_twin',
214
+ target: entry.rel,
215
+ message: `standard script ${entry.rel} is missing its .mjs twin (${expectedTwinRel})`,
216
+ });
217
+ } else if (existsSync(tsPath)) {
218
+ const tsStat = statSync(tsPath);
219
+ const twinStat = statSync(twinPath);
220
+ if (twinStat.mtimeMs < tsStat.mtimeMs - STALE_TWIN_TOLERANCE_MS) {
221
+ violations.push({
222
+ kind: 'stale_twin',
223
+ target: entry.rel,
224
+ message: `standard script .mjs twin ${expectedTwinRel} is older than source ${entry.rel}`,
225
+ });
226
+ }
227
+ }
228
+ }
229
+ }
230
+
231
+ // Rule 2: committed .mjs files must belong to a 'standard' entry
232
+ for (const mjsRel of mjsFiles) {
233
+ const correspondingTsRel = mjsRel.replace(/\.mjs$/, '.ts');
234
+ const entry = manifestMap.get(correspondingTsRel);
235
+ if (!entry) {
236
+ violations.push({
237
+ kind: 'unexpected_twin',
238
+ target: mjsRel,
239
+ message: `.mjs twin ${mjsRel} exists on disk but has no manifest entry for ${correspondingTsRel}`,
240
+ });
241
+ } else if (entry.contract === 'repo-only') {
242
+ violations.push({
243
+ kind: 'unexpected_twin',
244
+ target: mjsRel,
245
+ message: `repo-only script ${correspondingTsRel} must not have a .mjs twin (${mjsRel})`,
246
+ });
247
+ }
248
+ }
249
+
250
+ // Rule 3: all .ts files on disk must have a manifest entry
251
+ const diskTsSet = new Set(tsFiles);
252
+ for (const tsRel of tsFiles) {
253
+ if (!manifestMap.has(tsRel)) {
254
+ violations.push({
255
+ kind: 'unregistered_script',
256
+ target: tsRel,
257
+ message: `script ${tsRel} exists in scripts dir but is not registered in manifest`,
258
+ });
259
+ }
260
+ }
261
+
262
+ // Also verify manifest entries exist on disk
263
+ for (const [rel] of manifestMap) {
264
+ if (!diskTsSet.has(rel)) {
265
+ violations.push({
266
+ kind: 'unregistered_script',
267
+ target: rel,
268
+ message: `manifest entry ${rel} does not exist on disk in ${scriptsDir}`,
269
+ });
270
+ }
271
+ }
272
+
273
+ // Rule 4: scan shipped surfaces for forbidden invocation
274
+ const forbiddenHits = scanShippedSurfaces(pluginDir);
275
+ for (const hit of forbiddenHits) {
276
+ violations.push({
277
+ kind: 'forbidden_invocation',
278
+ target: `${hit.file}:${hit.line}`,
279
+ message: `shipped surface ${hit.file}:${hit.line} contains forbidden invocation 'bun plugins/sp/scripts/': ${hit.content}`,
280
+ });
281
+ }
282
+
283
+ return violations;
284
+ }
285
+
286
+ export function run(argv: string[] = process.argv.slice(2)): number {
287
+ const { manifest, scriptsDir, pluginDir, cwd } = parseArgs(argv);
288
+ const manifestPath = resolve(cwd, manifest);
289
+ const absScriptsDir = resolve(cwd, scriptsDir);
290
+ const absPluginDir = resolve(cwd, pluginDir);
291
+
292
+ const { manifest: parsed, error } = loadManifest(manifestPath);
293
+ if (error || !parsed) {
294
+ console.error(`script-contract-check: FAIL - ${error}`);
295
+ return 1;
296
+ }
297
+
298
+ const violations = validateContract(parsed, absScriptsDir, absPluginDir);
299
+ const ok = violations.length === 0;
300
+
301
+ const standardCount = parsed.entries.filter((e) => e.contract === 'standard').length;
302
+ const repoOnlyCount = parsed.entries.filter((e) => e.contract === 'repo-only').length;
303
+
304
+ console.log(
305
+ `script-contract-check: ${parsed.entries.length} script(s) baselined (${standardCount} standard, ${repoOnlyCount} repo-only), ` +
306
+ `${violations.length} violation(s) — ${ok ? 'PASS' : 'FAIL'}`,
307
+ );
308
+
309
+ if (ok) return 0;
310
+
311
+ for (const v of violations) {
312
+ console.error(`script-contract-check: FAIL (${v.kind}) - ${v.message}`);
313
+ }
314
+ return 1;
315
+ }
316
+
317
+ if (import.meta.main) {
318
+ process.exit(run());
319
+ }
@@ -52,13 +52,13 @@ The daily-summary skill:
52
52
 
53
53
  ```bash
54
54
  # Generate summary for today
55
- bun plugins/sp/scripts/daily-summary/daily-summary.ts
55
+ node "$(superskill script path sp daily-summary/daily-summary.mjs)"
56
56
 
57
57
  # Generate summary for a specific date
58
- bun plugins/sp/scripts/daily-summary/daily-summary.ts --date 2026-04-17
58
+ node "$(superskill script path sp daily-summary/daily-summary.mjs)" --date 2026-04-17
59
59
 
60
60
  # Show summary without writing file
61
- bun plugins/sp/scripts/daily-summary/daily-summary.ts --dry-run
61
+ node "$(superskill script path sp daily-summary/daily-summary.mjs)" --dry-run
62
62
  ```
63
63
 
64
64
  ## Workflows
@@ -96,9 +96,9 @@ The command forwards these via `$ARGUMENTS`:
96
96
  in-agent):
97
97
 
98
98
  ```bash
99
- bun plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts \
99
+ node "$(superskill script path sp dogfood-testing/detect-pipeline-driving.mjs)" \
100
100
  --testee "<raw testee string>" \
101
- [--max-retry-present] # pass this flag only when the dogfood invocation included --max-retry
101
+ [--max-retry-present]
102
102
  ```
103
103
 
104
104
  - Exit **2** → print the stdout refuse line and **stop** (do not plan). The CLI refuses on either
@@ -118,7 +118,7 @@ The command forwards these via `$ARGUMENTS`:
118
118
  re-run the gate with the derived step labels:
119
119
 
120
120
  ```bash
121
- bun plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts \
121
+ node "$(superskill script path sp dogfood-testing/detect-pipeline-driving.mjs)" \
122
122
  --testee "<raw testee string>" \
123
123
  --max-retry-present \
124
124
  --steps "step1 label||step2 label||..."
@@ -226,7 +226,7 @@ contract violation**.
226
226
  **before** claiming `status: complete`:
227
227
 
228
228
  ```bash
229
- bun plugins/sp/scripts/dogfood-testing/validate-report.ts --file <report-path>
229
+ node "$(superskill script path sp dogfood-testing/validate-report.mjs)" --file <report-path>
230
230
  ```
231
231
 
232
232
  Exit **0** → proceed. Exit **2** → set `status: aborted`, list every error code under §5
@@ -328,7 +328,7 @@ Do **not** use this skill for:
328
328
  Pipeline-driving detection is **word-boundary**, not leading-space substring. The live gate is:
329
329
 
330
330
  ```bash
331
- bun plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts --testee "<testee>" [--max-retry-present] [--steps "…"] [--json]
331
+ node "$(superskill script path sp dogfood-testing/detect-pipeline-driving.mjs)" --testee "<testee>" [--max-retry-present] [--steps "…"] [--json]
332
332
  ```
333
333
 
334
334
  | Token shape | Examples | Matches | Rejects |
@@ -278,7 +278,7 @@ Before the skill may stop (success, partial, fail, observe-only end, or abort),
278
278
  and mirror the footer block at the **end of the report file**. A report whose body lacks the
279
279
  footer cannot set `status: complete`.
280
280
  8. **Self-validate (task 0278 R6):** run
281
- `bun plugins/sp/scripts/dogfood-testing/validate-report.ts --file <report-path>` before
281
+ `node "$(superskill script path sp dogfood-testing/validate-report.mjs)" --file <report-path>` before
282
282
  claiming `status: complete`. Exit 2 → `status: aborted` + list error codes under
283
283
  `#### Unresolved` (never force complete on a non-@1.2 shape).
284
284
  9. **Refusal rule (@1.2):** when any check above fails, set `status: aborted` and list every
@@ -129,11 +129,11 @@ staged entrypoint below, supports `--json`, and must be parsed. Stop at the firs
129
129
  report its artifact. The canonical installed invocation is:
130
130
 
131
131
  ```sh
132
- bun "$(superskill script path sp pr-reviewing.ts)" <subcommand> [flags]
132
+ node "$(superskill script path sp pr-reviewing.mjs)" <subcommand> [flags]
133
133
  ```
134
134
 
135
- Installed targets resolve the staged TypeScript source and execute it with Bun, matching the rest
136
- of `plugins/sp/scripts`.
135
+ Installed targets resolve the staged `.mjs` twin and execute it with Node, matching the standard
136
+ superskill script contract.
137
137
 
138
138
  1. **Preflight** — `<script> preflight --base "$base" --json`. Hard-fails on a
139
139
  detached HEAD, missing `gh` auth, no GitHub remote, a dirty tree, or the current branch
@@ -219,7 +219,8 @@ for "what's actually in file Y" or for resources that sit outside the step seque
219
219
  - `plugins/sp/references/roles.md` — the Layer-1 role→tier table (`scribe` / `coder` / `reviewer` /
220
220
  `planner`, one per tier); the role vocabulary this spine's operations route under.
221
221
  - `.spur/workflows/task-pipeline.yaml` — the execution pipeline definition.
222
- - `.spur/workflows/planning-pipeline.yaml` — the front-half state machine.
222
+ - `.spur/workflows/idea-pipeline.yaml` — the front-half state machine (absorbed the retired
223
+ planning-pipeline in D5-K; `/sp:dev-plan` routes here, ADR-072).
223
224
  - `.spur/templates/bdd/gherkin.md` — the BDD scenario template.
224
225
 
225
226
  ## Platform Notes
@@ -538,8 +538,7 @@ invariants that keep the pipeline set coherent as new ones are added.
538
538
 
539
539
  | Pipeline | Lifecycle phase | Entry point | Terminal states |
540
540
  | --- | --- | --- | --- |
541
- | `idea-pipeline.yaml` | Ideation (vague idea → feature + AC + task batch) | `/sp:dev-idea` | `handoff`, `cancelled` |
542
- | `planning-pipeline.yaml` | Design (known slug/task → design handoff) | `/sp:dev-plan` | `handoff`, `cancelled` |
541
+ | `idea-pipeline.yaml` | Ideation + planning (vague idea or known slug → feature + AC + task batch) | `/sp:dev-idea`, `/sp:dev-plan` | `handoff`, `cancelled` |
543
542
  | `task-pipeline.yaml` | Execution (one task → done) | `/sp:dev-run` | `done`, `failed` |
544
543
  | `wrapup-pipeline.yaml` | Wrap-up (completed tasks → learning + metrics + doc-sync) | `/sp:dev-wrap`, `/sp:dev-wrapall` | `done`, `skipped` |
545
544
  | `feature-dev.yaml` | Umbrella (brainstorm → plan → execute → feature-verify) | `/sp:dev-runall --feature <id>` (or `--tasks feature:<id>`) | `done`, `failed` |
@@ -644,8 +643,8 @@ next_action: "run verification"
644
643
  **Write checkpoints after:**
645
644
 
646
645
  - Every HITL gate decision (approved/rejected/deferred).
647
- - Every phase transition in `planning-pipeline`, `task-pipeline`, `feature-dev`, `idea-pipeline`,
648
- and `wrapup-pipeline`.
646
+ - Every phase transition in `task-pipeline`, `feature-dev`, `idea-pipeline`, and
647
+ `wrapup-pipeline`.
649
648
  - Every terminal state (`done`, `failed`, `cancelled`, `skipped`).
650
649
 
651
650
  **Read checkpoints when:**
@@ -82,7 +82,7 @@ each would be scope creep for one-liner procedures.
82
82
  | 13a | parallel | `dev-parallel` | `Skill()` | `sp:parallel-execution` | `--tasks <selector> [--feature <id>] [--mode <fan-out\|review-panel\|investigation>] [--agent <inline\|auto\|name>] [--json]` |
83
83
  | 14 | wrap | `dev-wrap` | `Skill()` | `spur workflow run` (wrapup-pipeline) | `<wbs> [--agent <inline\|auto\|name>] [--auto] [--merge] [--dry-run]` |
84
84
  | 15 | wrapall | `dev-wrapall` | `Skill()` | `spur workflow run` (wrapup-pipeline) | `[--since <iso>] [--feature <id>] [--status <s>] [--agent <inline\|auto\|name>] [--auto] [--merge] [--dry-run]` |
85
- | 16 | idea | `dev-idea` | `Skill()` | `spur workflow run` (idea-pipeline) | `"<idea>" [--auto] [--skip-design] [--approve-taste]` |
85
+ | 16 | idea | `dev-idea` | `Skill()` | `spur workflow run` (idea-pipeline) | `"<idea>" [--auto] [--skip-design] [--approve-taste] [--agent <inline\|auto\|name>]` |
86
86
 
87
87
  ## Skill-backed operations
88
88
 
@@ -179,7 +179,7 @@ The ordered execution plan: a WBS-ascending-topological list of tasks to run, pl
179
179
  helper (preferred) or `sp:next-router` dry-run:
180
180
 
181
181
  ```bash
182
- bun plugins/sp/scripts/batch-preflight.ts \
182
+ node "$(superskill script path sp batch-preflight.mjs)" \
183
183
  --wbs <wbs> --status <status> \
184
184
  --deps <comma-deps> --dep-status <wbs:status,...> --json
185
185
  ```
@@ -278,7 +278,7 @@ After a non-PASS terminal state (or when the task status is stuck at `wip`/`test
278
278
  verdict), consult **one** recovery hop:
279
279
 
280
280
  ```bash
281
- bun plugins/sp/scripts/batch-preflight.ts --wbs <wbs> --status <status> --recovery
281
+ node "$(superskill script path sp batch-preflight.mjs)" --wbs <wbs> --status <status> --recovery
282
282
  # → e.g. /sp:dev-verify 0042 --auto --next
283
283
  ```
284
284
 
@@ -306,7 +306,7 @@ Both `task-pipeline.yaml` (`record` step) and `wrapup-pipeline.yaml` (`feature-t
306
306
  invoke the bounded wrapper instead of raw `feature sync`:
307
307
 
308
308
  ```bash
309
- bun plugins/sp/scripts/feature-sync-bounded.ts <feature-id> --spur-bin "<spurBin>" --json
309
+ node "$(superskill script path sp feature-sync-bounded.mjs)" <feature-id> --spur-bin "<spurBin>" --json
310
310
  ```
311
311
 
312
312
  The wrapper:
@@ -36,8 +36,8 @@ SSOT: `.spur/workflows/task-lifecycle.yaml`.
36
36
 
37
37
  ## feature-check gate
38
38
 
39
- Entered before `spur feature check <id> --strict` (idea-pipeline `feature-check` state;
40
- planning-pipeline AC validation).
39
+ Entered before `spur feature check <id> --strict` (idea-pipeline `feature-check` state — the
40
+ AC-validation gate `/sp:dev-plan` also routes through since D5-K).
41
41
 
42
42
  - [ ] Feature file has a non-placeholder `## Goal` and `## Scope` section.
43
43
  - [ ] Acceptance criteria are R-numbered scenarios in Gherkin `Feature/Scenario` form (see `ac-style-guide.md`).
@@ -48,8 +48,8 @@ planning-pipeline AC validation).
48
48
 
49
49
  ## batch-create gate
50
50
 
51
- Entered before `spur task batch-create --file <json>` (idea-pipeline `batch-create` state;
52
- planning-pipeline decomposition gate).
51
+ Entered before `spur task batch-create --file <json>` (idea-pipeline `batch-create` state — the
52
+ decomposition gate `/sp:dev-plan` also routes through since D5-K).
53
53
 
54
54
  - [ ] The batch JSON is a bare array (not an object with a `tasks` key).
55
55
  - [ ] Each entry validates locally against `apps/cli/schemas/task-batch.schema.json` (`additionalProperties: false` — no unknown keys).