@gobing-ai/spur 0.3.95 → 0.3.97

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 (165) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/plugin-scripts.json +0 -54
  3. package/config/rules/boundary/sp-script-placement.yaml +19 -0
  4. package/config/rules/strict/runtime-boundaries.yaml +6 -0
  5. package/config/rules/structure/test-location.yaml +2 -0
  6. package/config/rules/typescript/no-syscall-emulation-in-boundary-mock.yaml +1 -1
  7. package/config/rules/typescript/output-boundaries.yaml +15 -2
  8. package/config/script-placement-baseline.json +51 -0
  9. package/config/templates/AGENTS.md +3 -3
  10. package/config/workflows/feature-verification.yaml +1 -1
  11. package/config/workflows/history-anatomy.yaml +23 -11
  12. package/config/workflows/idea-pipeline.yaml +80 -85
  13. package/config/workflows/pr-review.yaml +18 -9
  14. package/config/workflows/task-pipeline.yaml +42 -95
  15. package/config/workflows/wrapup-pipeline.yaml +91 -38
  16. package/package.json +2 -2
  17. package/plugins/sp/README.md +14 -10
  18. package/plugins/sp/agents/super-reviewer.md +43 -18
  19. package/plugins/sp/commands/dev-fixgha.md +83 -0
  20. package/plugins/sp/commands/dev-gitmsg.md +8 -6
  21. package/plugins/sp/commands/dev-gtd.md +2 -2
  22. package/plugins/sp/commands/dev-idea.md +22 -12
  23. package/plugins/sp/commands/dev-job-dump.md +29 -0
  24. package/plugins/sp/commands/dev-job-resume.md +29 -0
  25. package/plugins/sp/commands/dev-plan.md +8 -9
  26. package/plugins/sp/commands/dev-review.md +22 -13
  27. package/plugins/sp/commands/dev-verifyall.md +1 -1
  28. package/plugins/sp/commands/spur-init.md +2 -2
  29. package/plugins/sp/lib/history-anatomy.generated.d.mts +112 -0
  30. package/plugins/sp/lib/history-anatomy.generated.mjs +686 -0
  31. package/plugins/sp/lib/idea-handoff.generated.mjs +5 -4
  32. package/plugins/sp/lib/inline-run.generated.d.mts +11 -0
  33. package/plugins/sp/lib/inline-run.generated.mjs +39 -13
  34. package/plugins/sp/lib/quality-gate.generated.d.mts +104 -0
  35. package/plugins/sp/lib/quality-gate.generated.mjs +445 -0
  36. package/plugins/sp/lib/residual-scan.generated.d.mts +63 -0
  37. package/plugins/sp/lib/residual-scan.generated.mjs +226 -0
  38. package/plugins/sp/lib/spur-bin.ts +36 -0
  39. package/plugins/sp/lib/step-profile.generated.d.mts +71 -0
  40. package/plugins/sp/lib/step-profile.generated.mjs +174 -0
  41. package/plugins/sp/plugin.json +1 -1
  42. package/plugins/sp/references/roles.md +3 -3
  43. package/plugins/sp/scripts/feature-verification-steps.mjs +14 -1
  44. package/plugins/sp/scripts/feature-verification-steps.ts +14 -1
  45. package/plugins/sp/scripts/history-anatomy-cache.mjs +20 -19
  46. package/plugins/sp/scripts/history-anatomy-cache.ts +23 -928
  47. package/plugins/sp/scripts/inline-run-setup.mjs +85 -320
  48. package/plugins/sp/scripts/inline-run-setup.ts +104 -667
  49. package/plugins/sp/scripts/quality-gate.mjs +46 -24
  50. package/plugins/sp/scripts/quality-gate.ts +13 -659
  51. package/plugins/sp/scripts/residual-scan.mjs +179 -174
  52. package/plugins/sp/scripts/residual-scan.ts +125 -517
  53. package/plugins/sp/scripts/script-root.mjs +5 -1
  54. package/plugins/sp/scripts/script-root.ts +5 -1
  55. package/plugins/sp/scripts/workflow-step-profile.mjs +25 -17
  56. package/plugins/sp/scripts/workflow-step-profile.ts +21 -315
  57. package/plugins/sp/scripts/wrapup-drift-probe.mjs +8 -2
  58. package/plugins/sp/scripts/wrapup-drift-probe.ts +3 -2
  59. package/plugins/sp/scripts/wrapup-steps.mjs +72 -33
  60. package/plugins/sp/scripts/wrapup-steps.ts +128 -37
  61. package/plugins/sp/skills/code-improvement/SKILL.md +5 -4
  62. package/plugins/sp/skills/code-verification/SKILL.md +34 -9
  63. package/plugins/sp/skills/code-verification/references/verdict-schema.md +3 -3
  64. package/plugins/sp/skills/functional-review/SKILL.md +7 -4
  65. package/plugins/sp/skills/functional-review/references/verdict-schema.md +1 -1
  66. package/plugins/sp/skills/history-anatomy/references/modes.md +2 -1
  67. package/plugins/sp/skills/next-feature/references/handoff-routing.md +1 -1
  68. package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
  69. package/plugins/sp/skills/source-driven-development/SKILL.md +11 -0
  70. package/plugins/sp/skills/spur-cli/SKILL.md +3 -3
  71. package/plugins/sp/skills/spur-cli/references/agent.md +10 -10
  72. package/plugins/sp/skills/spur-cli/references/features.md +17 -6
  73. package/plugins/sp/skills/spur-cli/references/init.md +17 -16
  74. package/plugins/sp/skills/spur-cli/references/self.md +3 -2
  75. package/plugins/sp/skills/spur-cli/references/serve.md +10 -10
  76. package/plugins/sp/skills/spur-cli/references/tasks/section-editing.md +9 -5
  77. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +21 -6
  78. package/plugins/sp/skills/spur-cli/references/tasks.md +14 -8
  79. package/plugins/sp/skills/spur-cli/references/workflows.md +17 -14
  80. package/plugins/sp/skills/spur-dev/SKILL.md +2 -0
  81. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +4 -3
  82. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +14 -10
  83. package/plugins/sp/skills/spur-dev/references/decision-brief.md +1 -1
  84. package/plugins/sp/skills/spur-dev/references/dev-operations.md +165 -75
  85. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +7 -5
  86. package/plugins/sp/skills/spur-dev/references/execution-batch.md +84 -39
  87. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +8 -12
  88. package/plugins/sp/skills/spur-dev/references/feature-link-helper.md +3 -3
  89. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +40 -21
  90. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +19 -19
  91. package/plugins/sp/skills/spur-dev/references/idea-evaluation.md +4 -3
  92. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +72 -15
  93. package/plugins/sp/skills/spur-doctor/SKILL.md +1 -1
  94. package/plugins/sp/skills/sys-architecture/SKILL.md +3 -2
  95. package/spur.js +4461 -2085
  96. package/web/_astro/{BoardApp.Cpxntzad.js → BoardApp.Bmv5WkJ9.js} +1 -1
  97. package/web/_astro/BoardApp.vveLOdDq.js +322 -0
  98. package/web/_astro/{TaskDetail.C5bW4WGV.js → TaskDetail.IKc3uDYV.js} +1 -1
  99. package/web/_astro/{arc.CyjRvNMY.js → arc.C63Ufg35.js} +1 -1
  100. package/web/_astro/{architectureDiagram-3BPJPVTR.B4lWRzJA.js → architectureDiagram-3BPJPVTR.CP8Hyldk.js} +1 -1
  101. package/web/_astro/{blockDiagram-GPEHLZMM.Be38USQ2.js → blockDiagram-GPEHLZMM.Bo_48MRA.js} +1 -1
  102. package/web/_astro/{c4Diagram-AAUBKEIU.DT9Fj5Qx.js → c4Diagram-AAUBKEIU.Ch61sw-O.js} +1 -1
  103. package/web/_astro/channel.BKCmJpWM.js +1 -0
  104. package/web/_astro/{chunk-2J33WTMH.SeSBWLg5.js → chunk-2J33WTMH.CHpzS7xf.js} +1 -1
  105. package/web/_astro/{chunk-4BX2VUAB.DoO4VE14.js → chunk-4BX2VUAB.DzMNNWIw.js} +1 -1
  106. package/web/_astro/{chunk-55IACEB6.DrmTFA53.js → chunk-55IACEB6.BqPrDw_Q.js} +1 -1
  107. package/web/_astro/{chunk-727SXJPM.Bi-TUb_V.js → chunk-727SXJPM.ZzBHhNw-.js} +1 -1
  108. package/web/_astro/{chunk-AQP2D5EJ.B-xp8Uhi.js → chunk-AQP2D5EJ.1_O_LLkx.js} +1 -1
  109. package/web/_astro/{chunk-FMBD7UC4.DGWrDnUU.js → chunk-FMBD7UC4.GS4UHg7_.js} +1 -1
  110. package/web/_astro/{chunk-ND2GUHAM._BagvPDy.js → chunk-ND2GUHAM.BnqotN4g.js} +1 -1
  111. package/web/_astro/{chunk-QZHKN3VN.VOboYWQ0.js → chunk-QZHKN3VN.Ghuh8zoJ.js} +1 -1
  112. package/web/_astro/{classDiagram-4FO5ZUOK.D_apfHS7.js → classDiagram-4FO5ZUOK.BW9vC3zg.js} +1 -1
  113. package/web/_astro/{classDiagram-v2-Q7XG4LA2.D_apfHS7.js → classDiagram-v2-Q7XG4LA2.BW9vC3zg.js} +1 -1
  114. package/web/_astro/{cose-bilkent-S5V4N54A.DNLU_L-x.js → cose-bilkent-S5V4N54A.D6jNC0ti.js} +1 -1
  115. package/web/_astro/{cynefin-OW5HDTMX.D8borhV-.js → cynefin-OW5HDTMX.BOGoCs4L.js} +1 -1
  116. package/web/_astro/{dagre-BM42HDAG.Uc0lvjcV.js → dagre-BM42HDAG.8iU5VcWi.js} +1 -1
  117. package/web/_astro/{diagram-2AECGRRQ.DDIxtDBo.js → diagram-2AECGRRQ.CVt88HwH.js} +1 -1
  118. package/web/_astro/{diagram-5GNKFQAL.DVoDnD3H.js → diagram-5GNKFQAL.C9HxUUMl.js} +1 -1
  119. package/web/_astro/{diagram-KO2AKTUF.CRubTJ-0.js → diagram-KO2AKTUF.4ywkQN3t.js} +1 -1
  120. package/web/_astro/{diagram-LMA3HP47.m9SeYcXQ.js → diagram-LMA3HP47.C48A6gpz.js} +1 -1
  121. package/web/_astro/{diagram-OG6HWLK6.C6s2ZjV5.js → diagram-OG6HWLK6.DxFieQW4.js} +1 -1
  122. package/web/_astro/{erDiagram-TEJ5UH35.nSzr5KTj.js → erDiagram-TEJ5UH35.CtjtQqYs.js} +1 -1
  123. package/web/_astro/{flowDiagram-I6XJVG4X.DrZcys16.js → flowDiagram-I6XJVG4X.C5zAiahU.js} +1 -1
  124. package/web/_astro/{ganttDiagram-6RSMTGT7.Do4M1b-K.js → ganttDiagram-6RSMTGT7.D_L6zsny.js} +1 -1
  125. package/web/_astro/{gitGraphDiagram-PVQCEYII.BWc9oJ4l.js → gitGraphDiagram-PVQCEYII.Ignnrk3V.js} +1 -1
  126. package/web/_astro/index.CbNz17Sx.css +1 -0
  127. package/web/_astro/{infoDiagram-5YYISTIA.BIdOctFk.js → infoDiagram-5YYISTIA.DLv8-P5u.js} +1 -1
  128. package/web/_astro/{ishikawaDiagram-YF4QCWOH.CV5SuG2t.js → ishikawaDiagram-YF4QCWOH.p0OTpwFO.js} +1 -1
  129. package/web/_astro/{journeyDiagram-JHISSGLW.CxE-rEJ-.js → journeyDiagram-JHISSGLW.CIaBt-DD.js} +1 -1
  130. package/web/_astro/{kanban-definition-UN3LZRKU.BPRdKWs_.js → kanban-definition-UN3LZRKU.DGySIntq.js} +1 -1
  131. package/web/_astro/{linear.zRsuuDTE.js → linear.BATV4RXu.js} +1 -1
  132. package/web/_astro/{mermaid.core.jAJTcMKc.js → mermaid.core.DzkwM3VX.js} +4 -4
  133. package/web/_astro/{mindmap-definition-RKZ34NQL.BffJxfCr.js → mindmap-definition-RKZ34NQL.3piBRRzA.js} +1 -1
  134. package/web/_astro/{pieDiagram-4H26LBE5.CacwWaE3.js → pieDiagram-4H26LBE5.DUNueLub.js} +1 -1
  135. package/web/_astro/{quadrantDiagram-W4KKPZXB.hXELD06-.js → quadrantDiagram-W4KKPZXB.9bihVbrt.js} +1 -1
  136. package/web/_astro/{requirementDiagram-4Y6WPE33.DdEbPcqT.js → requirementDiagram-4Y6WPE33.CkjsC-YT.js} +1 -1
  137. package/web/_astro/{sankeyDiagram-5OEKKPKP.DgaDocKv.js → sankeyDiagram-5OEKKPKP.Dbq4vaoQ.js} +1 -1
  138. package/web/_astro/{sequenceDiagram-3UESZ5HK.B0KScnAu.js → sequenceDiagram-3UESZ5HK.BivrH99P.js} +1 -1
  139. package/web/_astro/{stateDiagram-AJRCARHV.CV9M_WNc.js → stateDiagram-AJRCARHV.CqLQ1Vzz.js} +1 -1
  140. package/web/_astro/{stateDiagram-v2-BHNVJYJU.BOAo74Et.js → stateDiagram-v2-BHNVJYJU.DvvoLD3b.js} +1 -1
  141. package/web/_astro/{timeline-definition-PNZ67QCA.CqqepUMe.js → timeline-definition-PNZ67QCA.B-KR78gv.js} +1 -1
  142. package/web/_astro/{vennDiagram-CIIHVFJN.DDqe4dOG.js → vennDiagram-CIIHVFJN.Ck0Eieb5.js} +1 -1
  143. package/web/_astro/{wardleyDiagram-YWT4CUSO.B3R9OPdO.js → wardleyDiagram-YWT4CUSO.CRfdd_do.js} +1 -1
  144. package/web/_astro/{xychartDiagram-2RQKCTM6.B3SvgXpQ.js → xychartDiagram-2RQKCTM6.Ck_Jxk9C.js} +1 -1
  145. package/web/index.html +2 -2
  146. package/plugins/sp/lib/artifact-digest.generated.d.mts +0 -7
  147. package/plugins/sp/lib/artifact-digest.generated.mjs +0 -48
  148. package/plugins/sp/scripts/feature-sync-bounded.mjs +0 -301
  149. package/plugins/sp/scripts/feature-sync-bounded.ts +0 -481
  150. package/plugins/sp/scripts/idea-coverage-check.ts +0 -168
  151. package/plugins/sp/scripts/inline-pipeline-parity-check.ts +0 -298
  152. package/plugins/sp/scripts/record-feature-sync.mjs +0 -63
  153. package/plugins/sp/scripts/record-feature-sync.ts +0 -84
  154. package/plugins/sp/scripts/script-contract-check.ts +0 -506
  155. package/plugins/sp/scripts/stage-registry-adapter.ts +0 -1533
  156. package/plugins/sp/scripts/surface-drift-inventory.ts +0 -989
  157. package/plugins/sp/scripts/task-evidence-precheck.ts +0 -189
  158. package/plugins/sp/scripts/task-size-precheck.ts +0 -212
  159. package/plugins/sp/scripts/transition-shim-check.ts +0 -238
  160. package/plugins/sp/scripts/validate-commands.ts +0 -689
  161. package/plugins/sp/scripts/validate-flag-contracts.ts +0 -890
  162. package/plugins/sp/scripts/verify-answer-lint.ts +0 -549
  163. package/web/_astro/BoardApp.BxJuwD7I.js +0 -191
  164. package/web/_astro/channel.CI6N_tCg.js +0 -1
  165. package/web/_astro/index.CENnIEqT.css +0 -1
@@ -2,7 +2,16 @@
2
2
  // @bun
3
3
 
4
4
  // plugins/sp/scripts/quality-gate.ts
5
- import { spawnSync } from "child_process";
5
+ import { appendFileSync as appendFileSync2 } from "fs";
6
+ import { join as join2 } from "path";
7
+
8
+ // plugins/sp/lib/env.ts
9
+ function getEnvVars() {
10
+ return process.env;
11
+ }
12
+
13
+ // plugins/sp/lib/quality-gate.generated.mjs
14
+ import { spawnSync } from "node:child_process";
6
15
  import {
7
16
  appendFileSync,
8
17
  closeSync,
@@ -14,16 +23,9 @@ import {
14
23
  rmSync,
15
24
  statSync,
16
25
  writeFileSync
17
- } from "fs";
18
- import { tmpdir } from "os";
19
- import { join } from "path";
20
-
21
- // plugins/sp/lib/env.ts
22
- function getEnvVars() {
23
- return process.env;
24
- }
25
-
26
- // plugins/sp/scripts/quality-gate.ts
26
+ } from "node:fs";
27
+ import { tmpdir } from "node:os";
28
+ import { join } from "node:path";
27
29
  var MAX_GATE_ATTEMPTS = 5;
28
30
  var MAX_FINDINGS = 20;
29
31
  var RETRY_DELAY_MS_DEFAULT = 1e4;
@@ -121,6 +123,9 @@ function readReceiptStatus(receiptPath, currentDigest) {
121
123
  }
122
124
  if (receipt.tier !== "full")
123
125
  return { reuse: false, reason: "light-only" };
126
+ if (!Array.isArray(receipt.checks) || receipt.checks.length === 0 || receipt.checks.some((row) => row === null || typeof row !== "object" || row.status !== "PASS" || typeof row.cmd !== "string" || row.cmd.trim().length === 0)) {
127
+ return { reuse: false, reason: "failed" };
128
+ }
124
129
  return { reuse: true, reason: "ok" };
125
130
  }
126
131
  var TEST_FILE_PATTERN = /\.test\.tsx?$/;
@@ -241,7 +246,7 @@ function runLightGate(env, options = {}) {
241
246
  if (priorRow !== undefined) {
242
247
  checks.push(priorRow);
243
248
  skipped++;
244
- const line = `--- light ${plan.id}: check.reused \u2014 skipped (PASS at the same input digest)
249
+ const line = `--- light ${plan.id}: check.reused — skipped (PASS at the same input digest)
245
250
  `;
246
251
  process.stdout.write(line);
247
252
  appendFileSync(abs(logFile), line);
@@ -264,7 +269,7 @@ ${result.output}`);
264
269
  completedAt: new Date().toISOString()
265
270
  });
266
271
  if (preserveFullReceipt) {
267
- appendFileSync(abs(logFile), `--- light receipt: not written \u2014 the full-tier receipt at the same input digest is preserved
272
+ appendFileSync(abs(logFile), `--- light receipt: not written — the full-tier receipt at the same input digest is preserved
268
273
  `);
269
274
  process.stdout.write(`light gate ${receipt.status} (${scope.files.length} changed files; checks: ${checks.length},` + ` skipped: ${skipped}; receipt: ${receiptFile} preserved (full tier); log: ${logFile})
270
275
  `);
@@ -315,17 +320,32 @@ function runQualityGate(mode, env, options = {}) {
315
320
  writeFileSync(abs(attemptFile), `0
316
321
  `);
317
322
  const gateStartedAtMs = Date.now();
318
- let gateRc = 0;
323
+ const commandPresent = (env.qualityGateCmd ?? "").trim().length > 0;
324
+ let gateRc = commandPresent ? 0 : 1;
319
325
  let gateAttempt = 0;
320
- const noProgressSkip = mode === "recheck" && receiptFailsAtDigest(readReceipt(abs(rel("-check-receipt.json"))), env.proofDigest ?? "");
326
+ if (!commandPresent)
327
+ appendFileSync(abs(logFile), `quality-gate: mode ${mode} requires env \`qualityGateCmd\` to be non-empty
328
+ `);
329
+ const reusePass = commandPresent && readReceiptStatus(abs(rel("-check-receipt.json")), env.proofDigest ?? "").reuse;
330
+ if (reusePass) {
331
+ const line = `check.reused — full-tier PASS receipt at input digest ${env.proofDigest ?? ""}; gate skipped
332
+ `;
333
+ process.stdout.write(line);
334
+ appendFileSync(abs(logFile), line);
335
+ writeFileSync(abs(findingsFile), extractFindings(readFileSync(abs(logFile), "utf8")));
336
+ writeFileSync(abs(statusFile), `PASS
337
+ `);
338
+ return { status: "PASS", attempts: 0, logFile, findingsFile, statusFile, attemptFile };
339
+ }
340
+ const noProgressSkip = commandPresent && mode === "recheck" && receiptFailsAtDigest(readReceipt(abs(rel("-check-receipt.json"))), env.proofDigest ?? "");
321
341
  if (noProgressSkip) {
322
- const line = `check.skipped-no-progress \u2014 full-tier FAIL receipt at input digest ${env.proofDigest ?? ""}; recheck skipped
342
+ const line = `check.skipped-no-progress — full-tier FAIL receipt at input digest ${env.proofDigest ?? ""}; recheck skipped
323
343
  `;
324
344
  process.stdout.write(line);
325
345
  appendFileSync(abs(logFile), line);
326
346
  gateRc = 1;
327
347
  }
328
- if (mode === "recheck" && !noProgressSkip && (env.gateProbeCmd ?? "").length > 0) {
348
+ if (mode === "recheck" && gateRc === 0 && (env.gateProbeCmd ?? "").length > 0) {
329
349
  const probe = runShellCommand(env.gateProbeCmd ?? "", cwd);
330
350
  writeFileSync(abs(`${logFile}.probe`), probe.output);
331
351
  gateRc = probe.code;
@@ -371,7 +391,7 @@ function runQualityGate(mode, env, options = {}) {
371
391
  process.stdout.write(`quality gate PASS (attempts: ${attemptsLabel}; log: ${logFile}; bytes: ${bytes})
372
392
  `);
373
393
  } else {
374
- process.stdout.write(`quality gate FAIL \u2014 last 40 lines follow (full log: ${logFile})
394
+ process.stdout.write(`quality gate FAIL — last 40 lines follow (full log: ${logFile})
375
395
  `);
376
396
  process.stdout.write(tailLines(readFileSync(abs(logFile), "utf8"), 40));
377
397
  }
@@ -382,7 +402,7 @@ function runQualityGate(mode, env, options = {}) {
382
402
  appendFileSync(abs(logFile), `proof-digest: ${env.proofDigest ?? ""}
383
403
  `);
384
404
  let receiptFile;
385
- if (!noProgressSkip) {
405
+ if (!noProgressSkip && commandPresent) {
386
406
  if ((env.proofDigest ?? "").length > 0) {
387
407
  receiptFile = join(runDir, `${env.wbs}-check-receipt.json`);
388
408
  const receipt = buildReceipt({
@@ -404,11 +424,13 @@ function runQualityGate(mode, env, options = {}) {
404
424
  writeFileSync(abs(receiptFile), `${JSON.stringify(receipt, null, 2)}
405
425
  `);
406
426
  } else {
407
- appendFileSync(abs(logFile), "check-receipt: not written \u2014 env `proofDigest` is not set\n");
427
+ appendFileSync(abs(logFile), "check-receipt: not written — env `proofDigest` is not set\n");
408
428
  }
409
429
  }
410
430
  return { status, attempts: gateAttempt, logFile, findingsFile, statusFile, attemptFile, receiptFile };
411
431
  }
432
+
433
+ // plugins/sp/scripts/quality-gate.ts
412
434
  var QUALITY_GATE_USAGE = "usage: quality-gate.ts <run|recheck|light|status> (env: wbs, qualityGateCmd, gateProbeCmd, proofDigest, runId)";
413
435
  function main(argv, rawEnv = getEnvVars(), options = {}) {
414
436
  const mode = argv[0];
@@ -426,18 +448,18 @@ function main(argv, rawEnv = getEnvVars(), options = {}) {
426
448
  if (mode === "light") {
427
449
  runLightGate(env);
428
450
  } else if (mode === "status") {
429
- const runDir = join(options.cwd ?? ".", ".spur", "run");
430
- const verdict = readReceiptStatus(join(runDir, `${env.wbs}-check-receipt.json`), env.proofDigest ?? "");
451
+ const runDir = join2(options.cwd ?? ".", ".spur", "run");
452
+ const verdict = readReceiptStatus(join2(runDir, `${env.wbs}-check-receipt.json`), env.proofDigest ?? "");
431
453
  if (verdict.reuse) {
432
454
  const line = `check.reused \u2014 full-tier receipt reused for input digest ${env.proofDigest ?? ""}
433
455
  `;
434
456
  process.stdout.write(line);
435
- appendFileSync(join(runDir, `${env.wbs}-test-gate.log`), line);
457
+ appendFileSync2(join2(runDir, `${env.wbs}-test-gate.log`), line);
436
458
  }
437
459
  process.stdout.write(`${JSON.stringify(verdict)}
438
460
  `);
439
461
  } else {
440
- runQualityGate(mode, env);
462
+ return runQualityGate(mode, env, options).status === "PASS" ? 0 : 1;
441
463
  }
442
464
  return 0;
443
465
  }