@gobing-ai/spur 0.4.1 → 0.4.3

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 (159) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.global.yaml +4 -2
  3. package/config/decisions/maker-liveness.yaml +39 -0
  4. package/config/plugin-scripts.json +0 -4
  5. package/config/rules/README.md +1 -0
  6. package/config/rules/docs/sourced-api-claims.yaml +56 -12
  7. package/config/rules/strict/runtime-boundaries.yaml +7 -0
  8. package/config/script-placement-baseline.json +1 -19
  9. package/config/templates/AGENTS.md +1 -1
  10. package/config/workflows/feature-lifecycle.yaml +46 -1
  11. package/config/workflows/feature-verification.yaml +11 -0
  12. package/config/workflows/wrapup-pipeline.yaml +1 -1
  13. package/package.json +10 -10
  14. package/plugins/sp/README.md +23 -18
  15. package/plugins/sp/agents/super-planner.md +5 -6
  16. package/plugins/sp/agents/super-reviewer.md +43 -0
  17. package/plugins/sp/bunfig.toml +8 -5
  18. package/plugins/sp/commands/dev-review-session.md +2 -1
  19. package/plugins/sp/commands/dev-runall.md +18 -9
  20. package/plugins/sp/hooks/careful-guard.ts +1 -1
  21. package/plugins/sp/hooks/context-post-tool.ts +7 -404
  22. package/plugins/sp/hooks/context-session-start.ts +6 -192
  23. package/plugins/sp/hooks/context-session-stop.ts +6 -91
  24. package/plugins/sp/hooks/pi/guard-extension.ts +26 -12
  25. package/plugins/sp/hooks/task-write-guard.ts +1 -1
  26. package/plugins/sp/{hooks → lib}/agent-hint.ts +1 -1
  27. package/plugins/sp/lib/context-owner.ts +56 -0
  28. package/plugins/sp/lib/context-post-tool.ts +432 -0
  29. package/plugins/sp/lib/context-session-start.ts +214 -0
  30. package/plugins/sp/lib/context-session-stop.ts +196 -0
  31. package/plugins/sp/lib/dogfood-pipeline.ts +265 -0
  32. package/plugins/sp/lib/dogfood-report.ts +278 -0
  33. package/plugins/sp/lib/idea-handoff.generated.mjs +6 -4
  34. package/plugins/sp/lib/inline-run-app.ts +40 -0
  35. package/plugins/sp/lib/inline-run.generated.d.mts +3 -3
  36. package/plugins/sp/lib/inline-run.generated.mjs +1361 -87
  37. package/plugins/sp/lib/plan-projection.generated.d.mts +169 -0
  38. package/plugins/sp/lib/plan-projection.generated.mjs +704 -1
  39. package/plugins/sp/lib/quality-gate.generated.d.mts +0 -12
  40. package/plugins/sp/lib/quality-gate.generated.mjs +62 -231
  41. package/plugins/sp/lib/residual-scan.generated.d.mts +7 -1
  42. package/plugins/sp/lib/residual-scan.generated.mjs +71 -6
  43. package/plugins/sp/lib/run-summary-core.ts +34 -370
  44. package/plugins/sp/lib/transcript.ts +37 -200
  45. package/plugins/sp/plugin.json +1 -1
  46. package/plugins/sp/references/roles.md +1 -1
  47. package/plugins/sp/scripts/batch-plan.mjs +740 -1
  48. package/plugins/sp/scripts/batch-plan.ts +48 -3
  49. package/plugins/sp/scripts/batch-preflight.mjs +23 -1
  50. package/plugins/sp/scripts/batch-preflight.ts +35 -295
  51. package/plugins/sp/scripts/daily-summary/daily-summary.mjs +108 -87
  52. package/plugins/sp/scripts/daily-summary/daily-summary.ts +111 -104
  53. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +2 -1
  54. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +7 -265
  55. package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +3 -0
  56. package/plugins/sp/scripts/dogfood-testing/validate-report.ts +6 -272
  57. package/plugins/sp/scripts/feature-verification-steps.mjs +7 -123
  58. package/plugins/sp/scripts/feature-verification-steps.ts +29 -181
  59. package/plugins/sp/scripts/inline-run-dispatch.mjs +27 -26
  60. package/plugins/sp/scripts/inline-run-dispatch.ts +1 -21
  61. package/plugins/sp/scripts/inline-run-setup.mjs +158 -120
  62. package/plugins/sp/scripts/inline-run-setup.ts +1 -21
  63. package/plugins/sp/scripts/pr-reviewing.mjs +19 -5
  64. package/plugins/sp/scripts/pr-reviewing.ts +34 -9
  65. package/plugins/sp/scripts/quality-gate.mjs +38 -208
  66. package/plugins/sp/scripts/residual-scan.mjs +73 -6
  67. package/plugins/sp/scripts/residual-scan.ts +8 -5
  68. package/plugins/sp/scripts/run-summary.mjs +160 -95
  69. package/plugins/sp/scripts/run-summary.ts +7 -5
  70. package/plugins/sp/scripts/session-timeline.mjs +57 -29
  71. package/plugins/sp/scripts/session-timeline.ts +4 -18
  72. package/plugins/sp/scripts/task-diffstat.mjs +43 -30
  73. package/plugins/sp/scripts/task-diffstat.ts +40 -71
  74. package/plugins/sp/skills/code-implementation/SKILL.md +7 -1
  75. package/plugins/sp/skills/code-verification/references/secu-review.md +2 -1
  76. package/plugins/sp/skills/code-verification/references/verdict-schema.md +4 -0
  77. package/plugins/sp/skills/dogfood-testing/SKILL.md +2 -2
  78. package/plugins/sp/skills/indexed-context/SKILL.md +14 -7
  79. package/plugins/sp/skills/next-feature/SKILL.md +1 -1
  80. package/plugins/sp/skills/parallel-execution/SKILL.md +2 -2
  81. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +2 -2
  82. package/plugins/sp/skills/parallel-execution/references/fan-out-patterns.md +2 -2
  83. package/plugins/sp/skills/pr-reviewing/SKILL.md +7 -3
  84. package/plugins/sp/skills/session-review/SKILL.md +5 -3
  85. package/plugins/sp/skills/source-driven-development/SKILL.md +7 -4
  86. package/plugins/sp/skills/spur-cli/references/builder.md +3 -2
  87. package/plugins/sp/skills/spur-cli/references/decision.md +40 -8
  88. package/plugins/sp/skills/spur-cli/references/features.md +46 -5
  89. package/plugins/sp/skills/spur-cli/references/projects.md +7 -5
  90. package/plugins/sp/skills/spur-dev/SKILL.md +2 -0
  91. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +27 -0
  92. package/plugins/sp/skills/spur-dev/references/dev-operations.md +2 -3
  93. package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +6 -1
  94. package/plugins/sp/skills/spur-dev/references/execution-batch.md +56 -7
  95. package/plugins/sp/skills/spur-dev/references/execution-parallel-isolation.md +4 -1
  96. package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +22 -0
  97. package/plugins/sp/skills/spur-dev/references/execution-worktree-setup.md +14 -0
  98. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +13 -11
  99. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +37 -25
  100. package/spur.js +89792 -76992
  101. package/web/_astro/{BoardApp.D66k_s_T.js → BoardApp.5IIl2O-z.js} +1 -1
  102. package/web/_astro/BoardApp.Drnx-KeM.js +324 -0
  103. package/web/_astro/TaskDetail.Ci4LNn9S.js +1 -0
  104. package/web/_astro/{arc._BUadrdH.js → arc.j2EVkYVd.js} +1 -1
  105. package/web/_astro/{architectureDiagram-3BPJPVTR.Dh7xS1Pp.js → architectureDiagram-3BPJPVTR.DZWSFqEG.js} +1 -1
  106. package/web/_astro/{blockDiagram-GPEHLZMM.DFDVpfXm.js → blockDiagram-GPEHLZMM.DE6GpXCN.js} +1 -1
  107. package/web/_astro/{c4Diagram-AAUBKEIU.V7_3_glh.js → c4Diagram-AAUBKEIU.DoVR1G6B.js} +1 -1
  108. package/web/_astro/channel.DmdDxGsq.js +1 -0
  109. package/web/_astro/{chunk-2J33WTMH.De1yx7Jz.js → chunk-2J33WTMH.Do6-Gbyf.js} +1 -1
  110. package/web/_astro/{chunk-4BX2VUAB.BDhHFuxx.js → chunk-4BX2VUAB.BYV1HGHx.js} +1 -1
  111. package/web/_astro/{chunk-55IACEB6.DDLkWnmC.js → chunk-55IACEB6.CvI1zkrc.js} +1 -1
  112. package/web/_astro/{chunk-727SXJPM.CwfiLnA7.js → chunk-727SXJPM.DNGSCRlX.js} +1 -1
  113. package/web/_astro/{chunk-AQP2D5EJ.CtGDmUnM.js → chunk-AQP2D5EJ.DXhhgT5z.js} +1 -1
  114. package/web/_astro/{chunk-FMBD7UC4.BOLjpw73.js → chunk-FMBD7UC4.dzkRKP2u.js} +1 -1
  115. package/web/_astro/{chunk-ND2GUHAM.BDhQls6O.js → chunk-ND2GUHAM.DujGLeEf.js} +1 -1
  116. package/web/_astro/{chunk-QZHKN3VN.76qBynDF.js → chunk-QZHKN3VN.BWtIT3ZU.js} +1 -1
  117. package/web/_astro/{classDiagram-4FO5ZUOK.N0mpPHT0.js → classDiagram-4FO5ZUOK.DyApg0Nn.js} +1 -1
  118. package/web/_astro/{classDiagram-v2-Q7XG4LA2.N0mpPHT0.js → classDiagram-v2-Q7XG4LA2.DyApg0Nn.js} +1 -1
  119. package/web/_astro/{cose-bilkent-S5V4N54A.CKknFfjB.js → cose-bilkent-S5V4N54A.DJQB-u_l.js} +1 -1
  120. package/web/_astro/{cynefin-OW5HDTMX.Cw3ZWBAh.js → cynefin-OW5HDTMX.bi3D_siV.js} +1 -1
  121. package/web/_astro/{dagre-BM42HDAG.D3yIKCRD.js → dagre-BM42HDAG.C-f7TrRg.js} +1 -1
  122. package/web/_astro/{diagram-2AECGRRQ.D51dO83Z.js → diagram-2AECGRRQ.DrPfjHQB.js} +1 -1
  123. package/web/_astro/{diagram-5GNKFQAL.Bb-FViDj.js → diagram-5GNKFQAL.C9S4WUHO.js} +1 -1
  124. package/web/_astro/{diagram-KO2AKTUF.D3mN8S6x.js → diagram-KO2AKTUF.Dzzye8QH.js} +1 -1
  125. package/web/_astro/{diagram-LMA3HP47.dMMyPcbJ.js → diagram-LMA3HP47.DX-LRiof.js} +1 -1
  126. package/web/_astro/{diagram-OG6HWLK6.AzbvzY4C.js → diagram-OG6HWLK6.Z-kAKwIz.js} +1 -1
  127. package/web/_astro/{erDiagram-TEJ5UH35.BR5I4OZb.js → erDiagram-TEJ5UH35.D6dyClSv.js} +1 -1
  128. package/web/_astro/{flowDiagram-I6XJVG4X.DFqvhGkn.js → flowDiagram-I6XJVG4X.Cx3q2cxD.js} +1 -1
  129. package/web/_astro/{ganttDiagram-6RSMTGT7.ByJbhH6J.js → ganttDiagram-6RSMTGT7.DU3gH6CT.js} +1 -1
  130. package/web/_astro/{gitGraphDiagram-PVQCEYII.CInHjQR3.js → gitGraphDiagram-PVQCEYII.ISmCnJ87.js} +1 -1
  131. package/web/_astro/index.Do2lLdgo.css +1 -0
  132. package/web/_astro/{infoDiagram-5YYISTIA.Cm0dGVjJ.js → infoDiagram-5YYISTIA.DR6_iNOK.js} +1 -1
  133. package/web/_astro/{ishikawaDiagram-YF4QCWOH.C3nOP6Sj.js → ishikawaDiagram-YF4QCWOH.D7wY-ZGA.js} +1 -1
  134. package/web/_astro/{journeyDiagram-JHISSGLW.4IvLa2MW.js → journeyDiagram-JHISSGLW.DkP9-WK8.js} +1 -1
  135. package/web/_astro/{kanban-definition-UN3LZRKU.DS87Cl-k.js → kanban-definition-UN3LZRKU.wtgY98M2.js} +1 -1
  136. package/web/_astro/{linear.MzmRrNER.js → linear.CI6djNi7.js} +1 -1
  137. package/web/_astro/{mermaid.core.fK-WNswS.js → mermaid.core.CuQPxS8b.js} +4 -4
  138. package/web/_astro/{mindmap-definition-RKZ34NQL.BqipOHhY.js → mindmap-definition-RKZ34NQL.5HNIEG7R.js} +1 -1
  139. package/web/_astro/{pieDiagram-4H26LBE5.0nBiPqFG.js → pieDiagram-4H26LBE5.CchhDFjE.js} +1 -1
  140. package/web/_astro/{quadrantDiagram-W4KKPZXB.Szj7Zpx5.js → quadrantDiagram-W4KKPZXB.PYXXJPSJ.js} +1 -1
  141. package/web/_astro/{requirementDiagram-4Y6WPE33.D4UR6TWo.js → requirementDiagram-4Y6WPE33.cUQuNAKU.js} +1 -1
  142. package/web/_astro/{sankeyDiagram-5OEKKPKP.DAE7BdOs.js → sankeyDiagram-5OEKKPKP.BO7MnRIA.js} +1 -1
  143. package/web/_astro/{sequenceDiagram-3UESZ5HK.BP9ZVq25.js → sequenceDiagram-3UESZ5HK.D9bElyD6.js} +1 -1
  144. package/web/_astro/{stateDiagram-AJRCARHV.BQW7mIxk.js → stateDiagram-AJRCARHV.DhGdRz7I.js} +1 -1
  145. package/web/_astro/{stateDiagram-v2-BHNVJYJU.PbK4nDih.js → stateDiagram-v2-BHNVJYJU.5GvLeAoL.js} +1 -1
  146. package/web/_astro/{timeline-definition-PNZ67QCA.Ci_GvUpo.js → timeline-definition-PNZ67QCA.LtAT9haM.js} +1 -1
  147. package/web/_astro/{vennDiagram-CIIHVFJN.DNw1Y5qx.js → vennDiagram-CIIHVFJN.DRth1yLA.js} +1 -1
  148. package/web/_astro/{wardleyDiagram-YWT4CUSO.CwlkaaNe.js → wardleyDiagram-YWT4CUSO.h9MlZfcr.js} +1 -1
  149. package/web/_astro/{xychartDiagram-2RQKCTM6.MI6ZuiH_.js → xychartDiagram-2RQKCTM6.DHqy9DYA.js} +1 -1
  150. package/web/index.html +2 -2
  151. package/config/proportional-route-table.ts +0 -155
  152. package/plugins/sp/commands/dev-parallel.md +0 -37
  153. package/plugins/sp/scripts/daily-summary/logger.ts +0 -28
  154. package/web/_astro/BoardApp.D6sjAJr_.js +0 -324
  155. package/web/_astro/TaskDetail.BynLnMNc.js +0 -1
  156. package/web/_astro/channel.DZVfto-r.js +0 -1
  157. package/web/_astro/index.COh_kBxN.css +0 -1
  158. /package/plugins/sp/{hooks → lib}/destructive-policy.ts +0 -0
  159. /package/plugins/sp/{hooks → lib}/task-file-policy.ts +0 -0
@@ -10,18 +10,6 @@ export declare const LOCKED_PATTERN: RegExp;
10
10
  export declare const FINDINGS_PATTERN: RegExp;
11
11
  export declare const COVERAGE_ROW_PATTERN: RegExp;
12
12
  export declare const RECEIPT_SCHEMA_VERSION: 'check-receipt/v1';
13
- export declare const GATE_LOCK_DIR_ENV: string;
14
- export declare const GATE_LOCK_POLL_MS_ENV: string;
15
- export declare const GATE_LOCK_OFF_ENV: string;
16
- export declare const GATE_LOCK_TOKEN_ENV: string;
17
- export declare const GATE_LOCK_POLL_MS_DEFAULT: number;
18
- export declare const GATE_LOCK_MKDIR_HOLD_MS_ENV: string;
19
- export declare interface GateLock {
20
- release(): void;
21
- queueWaitMs: number;
22
- token: string;
23
- }
24
- export declare function acquireGateLock(env: QualityGateEnv, logLine?: (line: string) => void): GateLock;
25
13
  export declare interface QualityGateEnv {
26
14
  wbs: string;
27
15
  qualityGateCmd?: string;
@@ -17,7 +17,7 @@ var __export = (target, all) => {
17
17
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
18
18
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
19
 
20
- // node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/errors.js
20
+ // node_modules/.bun/@gobing-ai+ts-utils@0.5.24/node_modules/@gobing-ai/ts-utils/dist/errors.js
21
21
  var ErrorCode;
22
22
  var init_errors = __esm(() => {
23
23
  ErrorCode = {
@@ -28,7 +28,7 @@ var init_errors = __esm(() => {
28
28
  };
29
29
  });
30
30
 
31
- // node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/api-response.js
31
+ // node_modules/.bun/@gobing-ai+ts-utils@0.5.24/node_modules/@gobing-ai/ts-utils/dist/api-response.js
32
32
  var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
33
33
  var init_api_response = __esm(() => {
34
34
  init_errors();
@@ -51,28 +51,18 @@ var init_api_response = __esm(() => {
51
51
  CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
52
52
  });
53
53
 
54
- // node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/cursor.js
54
+ // node_modules/.bun/@gobing-ai+ts-utils@0.5.24/node_modules/@gobing-ai/ts-utils/dist/cursor.js
55
55
  var init_cursor = () => {};
56
56
 
57
- // node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/env.js
58
- function getEnvVar(name, fallback) {
59
- const raw = process.env[name];
60
- return raw === undefined ? fallback : raw;
61
- }
57
+ // node_modules/.bun/@gobing-ai+ts-utils@0.5.24/node_modules/@gobing-ai/ts-utils/dist/env.js
62
58
  function getEnvVars() {
63
59
  return process.env;
64
60
  }
65
- function setEnvVar(name, value) {
66
- if (value === undefined)
67
- delete process.env[name];
68
- else
69
- process.env[name] = value;
70
- }
71
61
 
72
- // node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
62
+ // node_modules/.bun/@gobing-ai+ts-utils@0.5.24/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
73
63
  var init_event_severity = () => {};
74
64
 
75
- // node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/index.js
65
+ // node_modules/.bun/@gobing-ai+ts-utils@0.5.24/node_modules/@gobing-ai/ts-utils/dist/index.js
76
66
  var init_dist = __esm(() => {
77
67
  init_api_response();
78
68
  init_cursor();
@@ -23896,7 +23886,7 @@ var init_dist2 = __esm(() => {
23896
23886
  $visitAsync = visit.visitAsync;
23897
23887
  });
23898
23888
 
23899
- // node_modules/.bun/@gobing-ai+ts-db@0.5.21+3862528db3f84042/node_modules/@gobing-ai/ts-db/dist/schema/common.js
23889
+ // node_modules/.bun/@gobing-ai+ts-db@0.5.24+685def093374c416/node_modules/@gobing-ai/ts-db/dist/schema/common.js
23900
23890
  function nowTimestamp() {
23901
23891
  return Date.now();
23902
23892
  }
@@ -23925,7 +23915,7 @@ var init_common3 = __esm(() => {
23925
23915
  appendOnlyColumns = buildAppendOnlyColumns();
23926
23916
  });
23927
23917
 
23928
- // node_modules/.bun/@gobing-ai+ts-db@0.5.21+3862528db3f84042/node_modules/@gobing-ai/ts-db/dist/schema/drizzle-internals.js
23918
+ // node_modules/.bun/@gobing-ai+ts-db@0.5.24+685def093374c416/node_modules/@gobing-ai/ts-db/dist/schema/drizzle-internals.js
23929
23919
  function sqlExpressionToText(value) {
23930
23920
  if (typeof value !== "object" || value === null || !("queryChunks" in value)) {
23931
23921
  return;
@@ -23948,7 +23938,7 @@ function getDrizzleTableName(table3) {
23948
23938
  return String(table3[nameSym]);
23949
23939
  }
23950
23940
 
23951
- // node_modules/.bun/@gobing-ai+ts-db@0.5.21+3862528db3f84042/node_modules/@gobing-ai/ts-db/dist/schema/ddl.js
23941
+ // node_modules/.bun/@gobing-ai+ts-db@0.5.24+685def093374c416/node_modules/@gobing-ai/ts-db/dist/schema/ddl.js
23952
23942
  function quoteIdent(name) {
23953
23943
  return `"${name.replace(/"/g, '""')}"`;
23954
23944
  }
@@ -24320,7 +24310,7 @@ var init_drizzle_zod = __esm(() => {
24320
24310
  };
24321
24311
  });
24322
24312
 
24323
- // node_modules/.bun/@gobing-ai+ts-db@0.5.21+3862528db3f84042/node_modules/@gobing-ai/ts-db/dist/schema/define-table.js
24313
+ // node_modules/.bun/@gobing-ai+ts-db@0.5.24+685def093374c416/node_modules/@gobing-ai/ts-db/dist/schema/define-table.js
24324
24314
  function defineTable(name, columns2) {
24325
24315
  const table3 = sqliteTable(name, columns2);
24326
24316
  let insert2;
@@ -24354,7 +24344,7 @@ var init_define_table = __esm(() => {
24354
24344
  init_ddl();
24355
24345
  });
24356
24346
 
24357
- // node_modules/.bun/@gobing-ai+ts-db@0.5.21+3862528db3f84042/node_modules/@gobing-ai/ts-db/dist/schema/index.js
24347
+ // node_modules/.bun/@gobing-ai+ts-db@0.5.24+685def093374c416/node_modules/@gobing-ai/ts-db/dist/schema/index.js
24358
24348
  var init_schema = __esm(() => {
24359
24349
  init_sqlite_core();
24360
24350
  init_define_table();
@@ -24372,16 +24362,14 @@ import {
24372
24362
  mkdirSync,
24373
24363
  mkdtempSync,
24374
24364
  openSync,
24375
- readdirSync,
24376
24365
  readFileSync,
24377
- rmdirSync,
24378
24366
  rmSync,
24379
24367
  statSync,
24380
24368
  unlinkSync,
24381
24369
  writeFileSync
24382
24370
  } from "node:fs";
24383
- import { homedir, tmpdir } from "node:os";
24384
- import { dirname, join, resolve } from "node:path";
24371
+ import { tmpdir } from "node:os";
24372
+ import { join, resolve } from "node:path";
24385
24373
 
24386
24374
  // packages/app/src/workflow/composition-baseline.ts
24387
24375
  function canonicalJsonStringify(obj) {
@@ -24450,6 +24438,7 @@ function isRfc3339Timestamp(value) {
24450
24438
  var ALL_FINDING_CODES = [
24451
24439
  "L1.markdown-parse",
24452
24440
  "L1.schema-validation",
24441
+ "L1.wbs-collision",
24453
24442
  "L2.missing-required-section",
24454
24443
  "L2.forbidden-section",
24455
24444
  "L2.disallowed-section",
@@ -24477,6 +24466,7 @@ var ALL_FINDING_CODES = [
24477
24466
  "L4.design-placeholder",
24478
24467
  "L4.feature-not-found",
24479
24468
  "L4.feature-terminal",
24469
+ "L4.feature-deprecated",
24480
24470
  "L4.missing-feature-id",
24481
24471
  "L4.parent-not-found",
24482
24472
  "L4.dependency-not-found",
@@ -24926,8 +24916,8 @@ var POST_WATERMARK_TABLES = [
24926
24916
  "history_daily_stats",
24927
24917
  "history_board_source_daily"
24928
24918
  ];
24929
- // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.21+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/schema-sql.js
24930
- var HISTORY_IMPORT_SCHEMA_VERSION = "0.5.21";
24919
+ // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.24+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/schema-sql.js
24920
+ var HISTORY_IMPORT_SCHEMA_VERSION = "0.5.24";
24931
24921
  var HISTORY_IMPORT_SCHEMA_SQL = `
24932
24922
  CREATE TABLE IF NOT EXISTS history_import_checkpoint (
24933
24923
  source TEXT NOT NULL,
@@ -25054,13 +25044,13 @@ CREATE INDEX IF NOT EXISTS idx_history_skill_call_invocation_kind
25054
25044
  ON history_skill_call(invocation_kind);
25055
25045
  `.trim();
25056
25046
 
25057
- // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.21+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/sources.js
25047
+ // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.24+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/sources.js
25058
25048
  init_zod();
25059
25049
 
25060
- // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.21+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/mappers.js
25050
+ // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.24+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/mappers.js
25061
25051
  init_zod();
25062
25052
 
25063
- // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.21+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/hash.js
25053
+ // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.24+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/hash.js
25064
25054
  import { createHash } from "node:crypto";
25065
25055
  function stableJson(value) {
25066
25056
  if (Array.isArray(value)) {
@@ -25079,7 +25069,7 @@ function sha256Text(text) {
25079
25069
  return createHash("sha256").update(text, "utf8").digest("hex");
25080
25070
  }
25081
25071
 
25082
- // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.21+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/capability.js
25072
+ // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.24+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/capability.js
25083
25073
  function matchCapabilityOrigin(origins, source, canonicalName, observable) {
25084
25074
  let candidates = origins.filter((origin2) => origin2.source === source && origin2.skillName === canonicalName);
25085
25075
  if (candidates.length === 0)
@@ -25344,7 +25334,7 @@ function extractNestedExecCommandLiterals(payloadText) {
25344
25334
  return literals;
25345
25335
  }
25346
25336
 
25347
- // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.21+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/redaction.js
25337
+ // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.24+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/redaction.js
25348
25338
  var DEFAULT_REDACTION_RULES = [
25349
25339
  {
25350
25340
  name: "api-key",
@@ -25386,7 +25376,7 @@ function applyRules(value, rules = DEFAULT_REDACTION_RULES) {
25386
25376
  return rules.reduce((current, rule) => current.replace(rule.pattern, rule.replacement), value);
25387
25377
  }
25388
25378
 
25389
- // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.21+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/mappers.js
25379
+ // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.24+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/mappers.js
25390
25380
  var MESSAGE_MAPPER_KEYS = [
25391
25381
  "_codexUsageCarrier",
25392
25382
  "session_id",
@@ -27492,7 +27482,7 @@ var GROK_SCHEMA = passthroughSchema;
27492
27482
  var GEMINI_SCHEMA = passthroughSchema;
27493
27483
  var DSH_SCHEMA = passthroughSchema;
27494
27484
 
27495
- // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.21+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/sources.js
27485
+ // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.24+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/sources.js
27496
27486
  var sourceRecordSchema = exports_external.object({
27497
27487
  source_record_id: exports_external.string().min(1),
27498
27488
  created_at: exports_external.string().min(1),
@@ -27596,10 +27586,10 @@ var SOURCE_DEFINITIONS = {
27596
27586
  openclaw: sourceDefinition("openclaw", "OpenClaw", [".openclaw"], ["*.jsonl"])
27597
27587
  };
27598
27588
 
27599
- // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.21+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/jsonl-importer-dao.js
27589
+ // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.24+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/jsonl-importer-dao.js
27600
27590
  var TYPED_HISTORY_TABLES = ["history_message", "history_tool_call", "history_skill_call"];
27601
27591
  var TYPED_IGNORED_KEYS = new Set(["_meta", "split_index", "source_record_id", "_capabilityConflict"]);
27602
- // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.21+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/tables.js
27592
+ // node_modules/.bun/@gobing-ai+ts-llm-jsonl-importer@0.5.24+f66f1d7f0d37c145/node_modules/@gobing-ai/ts-llm-jsonl-importer/dist/tables.js
27603
27593
  var BOOKKEEPING_HISTORY_TABLES = ["history_import_checkpoint", "history_import_ledger"];
27604
27594
  var IMPORTER_OWNED_TABLES = [
27605
27595
  ...TYPED_HISTORY_TABLES,
@@ -27676,6 +27666,9 @@ var artifactsTable = defineTable("artifacts", {
27676
27666
  ...standardColumns
27677
27667
  });
27678
27668
  var artifacts = artifactsTable.table;
27669
+ // packages/domain/src/dao/database-inspector.ts
27670
+ var encoder = new TextEncoder;
27671
+ var decoder = new TextDecoder;
27679
27672
  // packages/domain/src/schema/phase-runs.ts
27680
27673
  init_schema();
27681
27674
  var phaseRunsTable = defineTable("phase_runs", {
@@ -27713,7 +27706,7 @@ var workflowStatesTable = defineTable("workflow_states", {
27713
27706
  ...standardColumns
27714
27707
  });
27715
27708
  var workflowStates = workflowStatesTable.table;
27716
- // node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.5.21+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema-sql.js
27709
+ // node_modules/.bun/@gobing-ai+ts-dual-workflow-engine@0.5.24+df32fe902834add3/node_modules/@gobing-ai/ts-dual-workflow-engine/dist/schema-sql.js
27717
27710
  var WORKFLOW_ENGINE_SCHEMA_SQL = `
27718
27711
  CREATE TABLE IF NOT EXISTS runs (
27719
27712
  id TEXT PRIMARY KEY,
@@ -27812,7 +27805,7 @@ ALTER TABLE runs ADD COLUMN owner_pid INTEGER;
27812
27805
  ALTER TABLE runs ADD COLUMN interrupt_reason TEXT;
27813
27806
  ALTER TABLE runs ADD COLUMN terminal_reason TEXT;
27814
27807
  `.trim();
27815
- // node_modules/.bun/@gobing-ai+ts-rule-engine@0.5.21+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/schema.js
27808
+ // node_modules/.bun/@gobing-ai+ts-rule-engine@0.5.24+df32fe902834add3/node_modules/@gobing-ai/ts-rule-engine/dist/persistence/schema.js
27816
27809
  var RULE_ENGINE_SCHEMA_SQL = `
27817
27810
  CREATE TABLE IF NOT EXISTS rule_runs (
27818
27811
  id TEXT PRIMARY KEY,
@@ -27922,6 +27915,9 @@ var INBOX_MESSAGES_REQUEST_KEY_SCHEMA_SQL = `
27922
27915
  ALTER TABLE inbox_messages ADD COLUMN request_key TEXT;
27923
27916
  CREATE UNIQUE INDEX IF NOT EXISTS idx_inbox_messages_request_key ON inbox_messages (request_key) WHERE request_key IS NOT NULL;
27924
27917
  `;
27918
+ var INBOX_MESSAGES_READ_AT_SCHEMA_SQL = `
27919
+ ALTER TABLE inbox_messages ADD COLUMN read_at INTEGER;
27920
+ `;
27925
27921
  var QUEUE_JOBS_SCHEMA_SQL = `
27926
27922
  CREATE TABLE IF NOT EXISTS queue_jobs (
27927
27923
  id TEXT PRIMARY KEY,
@@ -28934,6 +28930,11 @@ var CLI_MIGRATIONS = [
28934
28930
  {
28935
28931
  id: "0052_spur_cli_decision_logs",
28936
28932
  sql: DECISION_LOGS_SCHEMA_SQL
28933
+ },
28934
+ {
28935
+ id: "0053_spur_cli_inbox_messages_read_at",
28936
+ sql: INBOX_MESSAGES_READ_AT_SCHEMA_SQL,
28937
+ addColumnIfMissing: { table: "inbox_messages", column: "read_at" }
28937
28938
  }
28938
28939
  ];
28939
28940
  // packages/domain/src/envelope/schema.ts
@@ -29889,7 +29890,15 @@ function escapeYamlValue(value) {
29889
29890
  // packages/domain/src/planning/schema.ts
29890
29891
  init_zod();
29891
29892
  var TASK_STATUSES = ["backlog", "todo", "wip", "testing", "blocked", "done", "cancelled"];
29892
- var FEATURE_STATUSES = ["backlog", "active", "verifying", "blocked", "done", "cancelled"];
29893
+ var FEATURE_STATUSES = [
29894
+ "backlog",
29895
+ "active",
29896
+ "verifying",
29897
+ "blocked",
29898
+ "done",
29899
+ "cancelled",
29900
+ "deprecated"
29901
+ ];
29893
29902
  var PRIORITIES = ["P0", "P1", "P2", "P3"];
29894
29903
  var PROFILES = [
29895
29904
  "simple",
@@ -30436,159 +30445,6 @@ function runShellCommand(cmd, cwd, extraEnv) {
30436
30445
  rmSync(dir, { recursive: true, force: true });
30437
30446
  }
30438
30447
  }
30439
- var GATE_LOCK_DIR_ENV = "SPUR_GATE_LOCK_DIR";
30440
- var GATE_LOCK_POLL_MS_ENV = "SPUR_GATE_LOCK_POLL_MS";
30441
- var GATE_LOCK_OFF_ENV = "SPUR_GATE_LOCK";
30442
- var GATE_LOCK_TOKEN_ENV = "SPUR_GATE_LOCK_TOKEN";
30443
- var GATE_LOCK_POLL_MS_DEFAULT = 5000;
30444
- var GATE_LOCK_MKDIR_HOLD_MS_ENV = "SPUR_GATE_LOCK_TEST_MKDIR_HOLD_MS";
30445
- var GATE_LOCK_LOST_RACE_SLEEP_MS = 20;
30446
- var GATE_LOCK_LOST_RACE_LOG_AT = 250;
30447
- function gateLockDir() {
30448
- const raw = getEnvVar(GATE_LOCK_DIR_ENV);
30449
- return raw !== undefined && raw.length > 0 ? raw : join(homedir(), ".config", "spur", "run", "full-gate.lock");
30450
- }
30451
- function gateLockPollMs() {
30452
- const raw = Number.parseInt(getEnvVar(GATE_LOCK_POLL_MS_ENV) ?? "", 10);
30453
- return Number.isFinite(raw) && raw > 0 ? raw : GATE_LOCK_POLL_MS_DEFAULT;
30454
- }
30455
- function isProcessAlive(pid) {
30456
- try {
30457
- process.kill(pid, 0);
30458
- return true;
30459
- } catch (error51) {
30460
- return error51.code !== "ESRCH";
30461
- }
30462
- }
30463
- function readGateLockClaim(dir) {
30464
- let markers;
30465
- try {
30466
- markers = readdirSync(dir).sort();
30467
- } catch {
30468
- return null;
30469
- }
30470
- for (const marker of markers) {
30471
- try {
30472
- const claim = JSON.parse(readFileSync(join(dir, marker), "utf8"));
30473
- if (typeof claim.pid === "number")
30474
- return { claim, marker };
30475
- } catch {
30476
- const pid = Number.parseInt(/^(\d+)-/.exec(marker)?.[1] ?? "", 10);
30477
- if (pid > 0) {
30478
- return { claim: { pid, startedAt: Date.now(), wbs: "?", runId: "?", cwd: "?" }, marker };
30479
- }
30480
- }
30481
- }
30482
- return null;
30483
- }
30484
- function acquireGateLock(env2, logLine = () => {}) {
30485
- if ((getEnvVar(GATE_LOCK_OFF_ENV) ?? "") === "off") {
30486
- return { release() {}, queueWaitMs: 0, token: "" };
30487
- }
30488
- const dir = gateLockDir();
30489
- mkdirSync(dirname(dir), { recursive: true });
30490
- const pollMs = gateLockPollMs();
30491
- const claim = {
30492
- pid: process.pid,
30493
- startedAt: Date.now(),
30494
- wbs: env2.wbs,
30495
- runId: receiptRunId(env2),
30496
- cwd: process.cwd()
30497
- };
30498
- const marker = `${process.pid}-${randomUUID()}`;
30499
- const startedWaitingAt = Date.now();
30500
- let holderLogged = false;
30501
- let graceLogged = false;
30502
- let lostRaces = 0;
30503
- let lostRaceLogged = false;
30504
- const mkdirHoldMs = Number.parseInt(getEnvVar(GATE_LOCK_MKDIR_HOLD_MS_ENV) ?? "", 10);
30505
- for (;; ) {
30506
- let dirIno = null;
30507
- try {
30508
- mkdirSync(dir);
30509
- dirIno = statSync(dir).ino;
30510
- if (Number.isFinite(mkdirHoldMs) && mkdirHoldMs > 0)
30511
- gateSleep(mkdirHoldMs);
30512
- writeFileSync(join(dir, marker), JSON.stringify(claim), { flag: "wx" });
30513
- } catch (error51) {
30514
- const code = error51.code;
30515
- if (code === "ENOENT" || code === "EINVAL") {
30516
- lostRaces += 1;
30517
- if (lostRaces === GATE_LOCK_LOST_RACE_LOG_AT && !lostRaceLogged) {
30518
- lostRaceLogged = true;
30519
- logLine(`quality gate lock: still losing the claim race after ${lostRaces} attempts (dir ${dir})
30520
- `);
30521
- }
30522
- gateSleep(GATE_LOCK_LOST_RACE_SLEEP_MS);
30523
- continue;
30524
- }
30525
- if (code !== "EEXIST") {
30526
- throw error51;
30527
- }
30528
- }
30529
- if (dirIno !== null) {
30530
- let currentIno = null;
30531
- let entries = [];
30532
- try {
30533
- currentIno = statSync(dir).ino;
30534
- entries = readdirSync(dir);
30535
- } catch {}
30536
- if (currentIno !== dirIno || entries.length !== 1 || entries[0] !== marker) {
30537
- try {
30538
- unlinkSync(join(dir, marker));
30539
- } catch {}
30540
- lostRaces += 1;
30541
- gateSleep(GATE_LOCK_LOST_RACE_SLEEP_MS);
30542
- continue;
30543
- }
30544
- return {
30545
- release() {
30546
- try {
30547
- rmSync(join(dir, marker), { force: true });
30548
- rmdirSync(dir);
30549
- } catch {}
30550
- },
30551
- queueWaitMs: Date.now() - startedWaitingAt,
30552
- token: marker
30553
- };
30554
- }
30555
- const held = readGateLockClaim(dir);
30556
- if (held !== null && isProcessAlive(held.claim.pid)) {
30557
- if (getEnvVar(GATE_LOCK_TOKEN_ENV) === held.marker) {
30558
- return { release() {}, queueWaitMs: Date.now() - startedWaitingAt, token: held.marker };
30559
- }
30560
- if (!holderLogged) {
30561
- holderLogged = true;
30562
- logLine(`quality gate lock: waiting for holder (wbs ${held.claim.wbs}, run ${held.claim.runId}, pid ${held.claim.pid}, cwd ${held.claim.cwd}, held ${Date.now() - held.claim.startedAt}ms)
30563
- `);
30564
- }
30565
- } else if (held !== null) {
30566
- logLine(`quality gate lock: reclaimed stale claim (pid ${held.claim.pid})
30567
- `);
30568
- try {
30569
- unlinkSync(join(dir, held.marker));
30570
- rmdirSync(dir);
30571
- } catch {}
30572
- } else {
30573
- try {
30574
- rmdirSync(dir);
30575
- graceLogged = false;
30576
- } catch {
30577
- gateSleep(pollMs);
30578
- try {
30579
- rmdirSync(dir);
30580
- graceLogged = false;
30581
- } catch {
30582
- if (!graceLogged) {
30583
- graceLogged = true;
30584
- logLine(`quality gate lock: dir has no readable claim and is not empty — waiting
30585
- `);
30586
- }
30587
- }
30588
- }
30589
- }
30590
- }
30591
- }
30592
30448
  function recomputeGateProofFingerprint(cwd, env2) {
30593
30449
  const taskSpecPath = env2.taskSpecPath ?? env2.taskFile;
30594
30450
  if (!taskSpecPath || taskSpecPath.trim() === "") {
@@ -30712,44 +30568,27 @@ function runQualityGate(mode, env2, options = {}) {
30712
30568
  appendFileSync(abs(logFile), probe.output);
30713
30569
  rmSync(abs(`${logFile}.probe`), { force: true });
30714
30570
  }
30715
- let queueWaitMs = 0;
30716
30571
  let gateRuntimeMs = 0;
30717
30572
  if (gateRc === 0) {
30718
30573
  const delayMs = retryDelayMs(env2);
30719
- const lockLine = (line) => {
30574
+ const gateRuntimeStartMs = Date.now();
30575
+ for (gateAttempt = 1;gateAttempt <= MAX_GATE_ATTEMPTS; gateAttempt++) {
30576
+ const attemptLogPath = `${logFile}.attempt-${gateAttempt}`;
30577
+ const attempt = runShellCommand(env2.qualityGateCmd ?? "", cwd);
30578
+ writeFileSync(abs(attemptLogPath), attempt.output);
30579
+ const locked = isTransientLock(attempt.output);
30580
+ appendFileSync(abs(logFile), attempt.output);
30581
+ rmSync(abs(attemptLogPath), { force: true });
30582
+ gateRc = attempt.code;
30583
+ if (gateRc === 0 || !locked || gateAttempt >= MAX_GATE_ATTEMPTS)
30584
+ break;
30585
+ const line = retryMessage(gateAttempt);
30720
30586
  process.stdout.write(line);
30721
30587
  appendFileSync(abs(logFile), line);
30722
- };
30723
- const lock = acquireGateLock(env2, lockLine);
30724
- queueWaitMs = lock.queueWaitMs;
30725
- lockLine(`quality gate lock: queueWaitMs=${queueWaitMs}
30726
- `);
30727
- const gateRuntimeStartMs = Date.now();
30728
- const previousToken = getEnvVar(GATE_LOCK_TOKEN_ENV);
30729
- if (lock.token.length > 0)
30730
- setEnvVar(GATE_LOCK_TOKEN_ENV, lock.token);
30731
- try {
30732
- for (gateAttempt = 1;gateAttempt <= MAX_GATE_ATTEMPTS; gateAttempt++) {
30733
- const attemptLogPath = `${logFile}.attempt-${gateAttempt}`;
30734
- const attempt = runShellCommand(env2.qualityGateCmd ?? "", cwd, lock.token.length > 0 ? { [GATE_LOCK_TOKEN_ENV]: lock.token } : undefined);
30735
- writeFileSync(abs(attemptLogPath), attempt.output);
30736
- const locked = isTransientLock(attempt.output);
30737
- appendFileSync(abs(logFile), attempt.output);
30738
- rmSync(abs(attemptLogPath), { force: true });
30739
- gateRc = attempt.code;
30740
- if (gateRc === 0 || !locked || gateAttempt >= MAX_GATE_ATTEMPTS)
30741
- break;
30742
- const line = retryMessage(gateAttempt);
30743
- process.stdout.write(line);
30744
- appendFileSync(abs(logFile), line);
30745
- gateSleep(delayMs);
30746
- }
30747
- } finally {
30748
- setEnvVar(GATE_LOCK_TOKEN_ENV, previousToken);
30749
- lock.release();
30588
+ gateSleep(delayMs);
30750
30589
  }
30751
30590
  gateRuntimeMs = Date.now() - gateRuntimeStartMs;
30752
- appendFileSync(abs(logFile), `quality gate lock: queueWaitMs=${queueWaitMs} gateRuntimeMs=${gateRuntimeMs}
30591
+ appendFileSync(abs(logFile), `gate runtime: ${gateRuntimeMs}ms
30753
30592
  `);
30754
30593
  }
30755
30594
  if (gateRc !== 0) {
@@ -30802,7 +30641,6 @@ function runQualityGate(mode, env2, options = {}) {
30802
30641
  }
30803
30642
  ],
30804
30643
  completedAt: new Date().toISOString(),
30805
- queueWaitMs,
30806
30644
  gateRuntimeMs
30807
30645
  });
30808
30646
  writeFileSync(abs(receiptFile), `${JSON.stringify(receipt, null, 2)}
@@ -30834,19 +30672,12 @@ export {
30834
30672
  isTransientLock,
30835
30673
  extractFindings,
30836
30674
  buildReceipt,
30837
- acquireGateLock,
30838
30675
  RETRY_DELAY_MS_ENV,
30839
30676
  RETRY_DELAY_MS_DEFAULT,
30840
30677
  RECEIPT_SCHEMA_VERSION,
30841
30678
  MAX_GATE_ATTEMPTS,
30842
30679
  MAX_FINDINGS,
30843
30680
  LOCKED_PATTERN,
30844
- GATE_LOCK_TOKEN_ENV,
30845
- GATE_LOCK_POLL_MS_ENV,
30846
- GATE_LOCK_POLL_MS_DEFAULT,
30847
- GATE_LOCK_OFF_ENV,
30848
- GATE_LOCK_MKDIR_HOLD_MS_ENV,
30849
- GATE_LOCK_DIR_ENV,
30850
30681
  FINDINGS_PATTERN,
30851
30682
  COVERAGE_ROW_PATTERN
30852
30683
  };
@@ -2,7 +2,12 @@
2
2
  * GENERATED by scripts/commands/bundle-plugin-lib.ts — do not edit.
3
3
  * Source of truth: packages/app/src/services/residual-scan.ts (task 1003 R5).
4
4
  */
5
- export declare type ResidualCategory = 'review-finding' | 'diff-marker' | 'unchecked-box' | 'staging-residue';
5
+ export declare type ResidualCategory =
6
+ | 'review-finding'
7
+ | 'diff-marker'
8
+ | 'unchecked-box'
9
+ | 'staging-residue'
10
+ | 'review-contract';
6
11
  export declare type ResidualClass = 'blocking' | 'deferrable' | 'advisory' | 'housekeeping';
7
12
  export declare interface ResidualItem {
8
13
  id: string;
@@ -62,6 +67,7 @@ export declare function classify(
62
67
  export declare function scanResiduals(inputs: ResidualScanInputs): ResidualArtifact;
63
68
  export declare function parseDeferralEntries(raw: unknown): Deferral[];
64
69
  export declare function blockingReviewFindings(taskContent: string, deferrals: Deferral[]): ResidualItem[];
70
+ export declare function reviewContractViolations(taskContent: string): Array<{ location: string; text: string }>;
65
71
  export declare function buildReviewGateArtifact(
66
72
  wbs: string,
67
73
  taskContent: string,
@@ -1,6 +1,36 @@
1
1
  // packages/app/src/services/residual-scan.ts
2
2
  import { join } from "node:path";
3
3
  import { createHash } from "node:crypto";
4
+
5
+ // packages/app/src/services/verify-answer-lint.ts
6
+ var CLAIM_MARKERS = [
7
+ /@[a-z0-9._-]+\/[a-z0-9._-]+/i,
8
+ /\bnode_modules\//,
9
+ /\b\d+\.\d+\.\d+\b/,
10
+ /`[A-Za-z_$][\w.$]*\s*\([^`]*\)`/
11
+ ];
12
+ var CITATION_FORMS = [
13
+ /`[^`\s]+:\d+(?:-\d+)?`/,
14
+ /`[^`]+`\s+lines?\s+\d+/i,
15
+ /\b[\w./-]+\.[A-Za-z0-9]+:\d+(?:-\d+)?\b/,
16
+ /https?:\/\/\S+/i
17
+ ];
18
+ function hasClaimMarker(evidence) {
19
+ return CLAIM_MARKERS.some((re) => re.test(evidence));
20
+ }
21
+ function hasCitationForm(evidence) {
22
+ return CITATION_FORMS.some((re) => re.test(evidence));
23
+ }
24
+ var CONFIDENCE_LEVELS = ["HIGH", "MEDIUM", "LOW"];
25
+ function extractAnswerConfidence(text) {
26
+ const matches = [...text.matchAll(/^\s*Confidence:\s*(\S+)\s*$/gim)];
27
+ if (matches.length !== 1)
28
+ return;
29
+ const value = (matches[0]?.[1] ?? "").toUpperCase();
30
+ return CONFIDENCE_LEVELS.includes(value) ? value : undefined;
31
+ }
32
+
33
+ // packages/app/src/services/residual-scan.ts
4
34
  var MARKER_PATTERN = /TODO|FIXME|XXX|HACK/;
5
35
  var PRIORITY_PATTERN = /^P[1-4]/;
6
36
  var RANGE_PRIORITY = /^P[1-4]\s*[\u2013\u2014-]\s*P?[1-4]/;
@@ -27,11 +57,15 @@ function locationOf(locationCell, finding) {
27
57
  const backtick = finding.match(/`([^`]+)`/)?.[1];
28
58
  return backtick === undefined ? "" : normalizeAnchor(backtick);
29
59
  }
30
- function parseReviewFindings(taskContent) {
60
+ function reviewBody(taskContent) {
31
61
  const section = taskContent.split(/^### Review\b/m)[1];
32
- if (section === undefined)
62
+ return section === undefined ? null : section.split(/^### /m)[0] ?? "";
63
+ }
64
+ function parseReviewFindings(taskContent) {
65
+ const section = reviewBody(taskContent);
66
+ if (section === null)
33
67
  return [];
34
- const body = section.split(/^### /m)[0] ?? "";
68
+ const body = section;
35
69
  const out = [];
36
70
  const lines = body.split(`
37
71
  `);
@@ -144,7 +178,8 @@ function scanResiduals(inputs) {
144
178
  "review-finding": true,
145
179
  "diff-marker": base !== null,
146
180
  "unchecked-box": true,
147
- "staging-residue": true
181
+ "staging-residue": true,
182
+ "review-contract": false
148
183
  },
149
184
  items,
150
185
  counts
@@ -165,8 +200,36 @@ function blockingReviewFindings(taskContent, deferrals) {
165
200
  }));
166
201
  return classify(items, [...tableDeferrals, ...deferrals]);
167
202
  }
203
+ function reviewContractViolations(taskContent) {
204
+ const violations = [];
205
+ const body = reviewBody(taskContent);
206
+ if (body !== null && extractAnswerConfidence(body.replace(/\*\*/g, "")) === undefined) {
207
+ violations.push({
208
+ location: "task-file:Review",
209
+ text: "Review report carries no single valid `**Confidence:** HIGH | MEDIUM | LOW` line — " + "state the level the report can defend (HIGH: every requirement row MET, every finding " + "dispositioned, evidence cited; MEDIUM/LOW: name the gap)."
210
+ });
211
+ }
212
+ for (const row of parseReviewFindings(taskContent)) {
213
+ if (hasClaimMarker(row.text) && !hasCitationForm(row.text)) {
214
+ violations.push({
215
+ location: row.location.length > 0 ? row.location : "task-file:Review",
216
+ text: `${row.priority} finding asserts an external API/library/version claim without a ` + "same-cell citation (add a repo `path:line`, an external named-origin form, or a URL " + `to the Finding cell): ${row.text.slice(0, 80)}`
217
+ });
218
+ }
219
+ }
220
+ return violations;
221
+ }
168
222
  function buildReviewGateArtifact(wbs, taskContent, deferrals) {
169
- const items = blockingReviewFindings(taskContent, deferrals);
223
+ const items = [
224
+ ...blockingReviewFindings(taskContent, deferrals),
225
+ ...reviewContractViolations(taskContent).map((v) => ({
226
+ id: makeItemId("review-contract", v.location, v.text),
227
+ category: "review-contract",
228
+ class: "blocking",
229
+ location: v.location,
230
+ text: v.text
231
+ }))
232
+ ];
170
233
  const blocking = items.filter((i) => i.class === "blocking");
171
234
  const counts = { blocking: 0, deferrable: 0, advisory: 0, housekeeping: 0 };
172
235
  for (const item of items)
@@ -178,7 +241,8 @@ function buildReviewGateArtifact(wbs, taskContent, deferrals) {
178
241
  "review-finding": true,
179
242
  "diff-marker": false,
180
243
  "unchecked-box": false,
181
- "staging-residue": false
244
+ "staging-residue": false,
245
+ "review-contract": true
182
246
  },
183
247
  items,
184
248
  counts
@@ -313,6 +377,7 @@ function parseScanArgs(argv, cwd, defaultTmpDir) {
313
377
  export {
314
378
  verdictDisagreementNote,
315
379
  scanResiduals,
380
+ reviewContractViolations,
316
381
  renderReport,
317
382
  recordedVerdictPath,
318
383
  parseScanArgs,