@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.
- package/.claude-plugin/marketplace.json +1 -1
- package/config/config.global.yaml +4 -2
- package/config/decisions/maker-liveness.yaml +39 -0
- package/config/plugin-scripts.json +0 -4
- package/config/rules/README.md +1 -0
- package/config/rules/docs/sourced-api-claims.yaml +56 -12
- package/config/rules/strict/runtime-boundaries.yaml +7 -0
- package/config/script-placement-baseline.json +1 -19
- package/config/templates/AGENTS.md +1 -1
- package/config/workflows/feature-lifecycle.yaml +46 -1
- package/config/workflows/feature-verification.yaml +11 -0
- package/config/workflows/wrapup-pipeline.yaml +1 -1
- package/package.json +10 -10
- package/plugins/sp/README.md +23 -18
- package/plugins/sp/agents/super-planner.md +5 -6
- package/plugins/sp/agents/super-reviewer.md +43 -0
- package/plugins/sp/bunfig.toml +8 -5
- package/plugins/sp/commands/dev-review-session.md +2 -1
- package/plugins/sp/commands/dev-runall.md +18 -9
- package/plugins/sp/hooks/careful-guard.ts +1 -1
- package/plugins/sp/hooks/context-post-tool.ts +7 -404
- package/plugins/sp/hooks/context-session-start.ts +6 -192
- package/plugins/sp/hooks/context-session-stop.ts +6 -91
- package/plugins/sp/hooks/pi/guard-extension.ts +26 -12
- package/plugins/sp/hooks/task-write-guard.ts +1 -1
- package/plugins/sp/{hooks → lib}/agent-hint.ts +1 -1
- package/plugins/sp/lib/context-owner.ts +56 -0
- package/plugins/sp/lib/context-post-tool.ts +432 -0
- package/plugins/sp/lib/context-session-start.ts +214 -0
- package/plugins/sp/lib/context-session-stop.ts +196 -0
- package/plugins/sp/lib/dogfood-pipeline.ts +265 -0
- package/plugins/sp/lib/dogfood-report.ts +278 -0
- package/plugins/sp/lib/idea-handoff.generated.mjs +6 -4
- package/plugins/sp/lib/inline-run-app.ts +40 -0
- package/plugins/sp/lib/inline-run.generated.d.mts +3 -3
- package/plugins/sp/lib/inline-run.generated.mjs +1361 -87
- package/plugins/sp/lib/plan-projection.generated.d.mts +169 -0
- package/plugins/sp/lib/plan-projection.generated.mjs +704 -1
- package/plugins/sp/lib/quality-gate.generated.d.mts +0 -12
- package/plugins/sp/lib/quality-gate.generated.mjs +62 -231
- package/plugins/sp/lib/residual-scan.generated.d.mts +7 -1
- package/plugins/sp/lib/residual-scan.generated.mjs +71 -6
- package/plugins/sp/lib/run-summary-core.ts +34 -370
- package/plugins/sp/lib/transcript.ts +37 -200
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/references/roles.md +1 -1
- package/plugins/sp/scripts/batch-plan.mjs +740 -1
- package/plugins/sp/scripts/batch-plan.ts +48 -3
- package/plugins/sp/scripts/batch-preflight.mjs +23 -1
- package/plugins/sp/scripts/batch-preflight.ts +35 -295
- package/plugins/sp/scripts/daily-summary/daily-summary.mjs +108 -87
- package/plugins/sp/scripts/daily-summary/daily-summary.ts +111 -104
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +2 -1
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +7 -265
- package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +3 -0
- package/plugins/sp/scripts/dogfood-testing/validate-report.ts +6 -272
- package/plugins/sp/scripts/feature-verification-steps.mjs +7 -123
- package/plugins/sp/scripts/feature-verification-steps.ts +29 -181
- package/plugins/sp/scripts/inline-run-dispatch.mjs +27 -26
- package/plugins/sp/scripts/inline-run-dispatch.ts +1 -21
- package/plugins/sp/scripts/inline-run-setup.mjs +158 -120
- package/plugins/sp/scripts/inline-run-setup.ts +1 -21
- package/plugins/sp/scripts/pr-reviewing.mjs +19 -5
- package/plugins/sp/scripts/pr-reviewing.ts +34 -9
- package/plugins/sp/scripts/quality-gate.mjs +38 -208
- package/plugins/sp/scripts/residual-scan.mjs +73 -6
- package/plugins/sp/scripts/residual-scan.ts +8 -5
- package/plugins/sp/scripts/run-summary.mjs +160 -95
- package/plugins/sp/scripts/run-summary.ts +7 -5
- package/plugins/sp/scripts/session-timeline.mjs +57 -29
- package/plugins/sp/scripts/session-timeline.ts +4 -18
- package/plugins/sp/scripts/task-diffstat.mjs +43 -30
- package/plugins/sp/scripts/task-diffstat.ts +40 -71
- package/plugins/sp/skills/code-implementation/SKILL.md +7 -1
- package/plugins/sp/skills/code-verification/references/secu-review.md +2 -1
- package/plugins/sp/skills/code-verification/references/verdict-schema.md +4 -0
- package/plugins/sp/skills/dogfood-testing/SKILL.md +2 -2
- package/plugins/sp/skills/indexed-context/SKILL.md +14 -7
- package/plugins/sp/skills/next-feature/SKILL.md +1 -1
- package/plugins/sp/skills/parallel-execution/SKILL.md +2 -2
- package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +2 -2
- package/plugins/sp/skills/parallel-execution/references/fan-out-patterns.md +2 -2
- package/plugins/sp/skills/pr-reviewing/SKILL.md +7 -3
- package/plugins/sp/skills/session-review/SKILL.md +5 -3
- package/plugins/sp/skills/source-driven-development/SKILL.md +7 -4
- package/plugins/sp/skills/spur-cli/references/builder.md +3 -2
- package/plugins/sp/skills/spur-cli/references/decision.md +40 -8
- package/plugins/sp/skills/spur-cli/references/features.md +46 -5
- package/plugins/sp/skills/spur-cli/references/projects.md +7 -5
- package/plugins/sp/skills/spur-dev/SKILL.md +2 -0
- package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +27 -0
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +2 -3
- package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +6 -1
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +56 -7
- package/plugins/sp/skills/spur-dev/references/execution-parallel-isolation.md +4 -1
- package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +22 -0
- package/plugins/sp/skills/spur-dev/references/execution-worktree-setup.md +14 -0
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +13 -11
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +37 -25
- package/spur.js +89792 -76992
- package/web/_astro/{BoardApp.D66k_s_T.js → BoardApp.5IIl2O-z.js} +1 -1
- package/web/_astro/BoardApp.Drnx-KeM.js +324 -0
- package/web/_astro/TaskDetail.Ci4LNn9S.js +1 -0
- package/web/_astro/{arc._BUadrdH.js → arc.j2EVkYVd.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.Dh7xS1Pp.js → architectureDiagram-3BPJPVTR.DZWSFqEG.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.DFDVpfXm.js → blockDiagram-GPEHLZMM.DE6GpXCN.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.V7_3_glh.js → c4Diagram-AAUBKEIU.DoVR1G6B.js} +1 -1
- package/web/_astro/channel.DmdDxGsq.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.De1yx7Jz.js → chunk-2J33WTMH.Do6-Gbyf.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.BDhHFuxx.js → chunk-4BX2VUAB.BYV1HGHx.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.DDLkWnmC.js → chunk-55IACEB6.CvI1zkrc.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.CwfiLnA7.js → chunk-727SXJPM.DNGSCRlX.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.CtGDmUnM.js → chunk-AQP2D5EJ.DXhhgT5z.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.BOLjpw73.js → chunk-FMBD7UC4.dzkRKP2u.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.BDhQls6O.js → chunk-ND2GUHAM.DujGLeEf.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.76qBynDF.js → chunk-QZHKN3VN.BWtIT3ZU.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.N0mpPHT0.js → classDiagram-4FO5ZUOK.DyApg0Nn.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.N0mpPHT0.js → classDiagram-v2-Q7XG4LA2.DyApg0Nn.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.CKknFfjB.js → cose-bilkent-S5V4N54A.DJQB-u_l.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.Cw3ZWBAh.js → cynefin-OW5HDTMX.bi3D_siV.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.D3yIKCRD.js → dagre-BM42HDAG.C-f7TrRg.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.D51dO83Z.js → diagram-2AECGRRQ.DrPfjHQB.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.Bb-FViDj.js → diagram-5GNKFQAL.C9S4WUHO.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.D3mN8S6x.js → diagram-KO2AKTUF.Dzzye8QH.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.dMMyPcbJ.js → diagram-LMA3HP47.DX-LRiof.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.AzbvzY4C.js → diagram-OG6HWLK6.Z-kAKwIz.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.BR5I4OZb.js → erDiagram-TEJ5UH35.D6dyClSv.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.DFqvhGkn.js → flowDiagram-I6XJVG4X.Cx3q2cxD.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.ByJbhH6J.js → ganttDiagram-6RSMTGT7.DU3gH6CT.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.CInHjQR3.js → gitGraphDiagram-PVQCEYII.ISmCnJ87.js} +1 -1
- package/web/_astro/index.Do2lLdgo.css +1 -0
- package/web/_astro/{infoDiagram-5YYISTIA.Cm0dGVjJ.js → infoDiagram-5YYISTIA.DR6_iNOK.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.C3nOP6Sj.js → ishikawaDiagram-YF4QCWOH.D7wY-ZGA.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.4IvLa2MW.js → journeyDiagram-JHISSGLW.DkP9-WK8.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.DS87Cl-k.js → kanban-definition-UN3LZRKU.wtgY98M2.js} +1 -1
- package/web/_astro/{linear.MzmRrNER.js → linear.CI6djNi7.js} +1 -1
- package/web/_astro/{mermaid.core.fK-WNswS.js → mermaid.core.CuQPxS8b.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.BqipOHhY.js → mindmap-definition-RKZ34NQL.5HNIEG7R.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.0nBiPqFG.js → pieDiagram-4H26LBE5.CchhDFjE.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.Szj7Zpx5.js → quadrantDiagram-W4KKPZXB.PYXXJPSJ.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.D4UR6TWo.js → requirementDiagram-4Y6WPE33.cUQuNAKU.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.DAE7BdOs.js → sankeyDiagram-5OEKKPKP.BO7MnRIA.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.BP9ZVq25.js → sequenceDiagram-3UESZ5HK.D9bElyD6.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.BQW7mIxk.js → stateDiagram-AJRCARHV.DhGdRz7I.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.PbK4nDih.js → stateDiagram-v2-BHNVJYJU.5GvLeAoL.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.Ci_GvUpo.js → timeline-definition-PNZ67QCA.LtAT9haM.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.DNw1Y5qx.js → vennDiagram-CIIHVFJN.DRth1yLA.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.CwlkaaNe.js → wardleyDiagram-YWT4CUSO.h9MlZfcr.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.MI6ZuiH_.js → xychartDiagram-2RQKCTM6.DHqy9DYA.js} +1 -1
- package/web/index.html +2 -2
- package/config/proportional-route-table.ts +0 -155
- package/plugins/sp/commands/dev-parallel.md +0 -37
- package/plugins/sp/scripts/daily-summary/logger.ts +0 -28
- package/web/_astro/BoardApp.D6sjAJr_.js +0 -324
- package/web/_astro/TaskDetail.BynLnMNc.js +0 -1
- package/web/_astro/channel.DZVfto-r.js +0 -1
- package/web/_astro/index.COh_kBxN.css +0 -1
- /package/plugins/sp/{hooks → lib}/destructive-policy.ts +0 -0
- /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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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 {
|
|
24384
|
-
import {
|
|
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.
|
|
24930
|
-
var HISTORY_IMPORT_SCHEMA_VERSION = "0.5.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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 = [
|
|
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
|
|
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), `
|
|
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 =
|
|
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
|
|
60
|
+
function reviewBody(taskContent) {
|
|
31
61
|
const section = taskContent.split(/^### Review\b/m)[1];
|
|
32
|
-
|
|
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
|
|
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 =
|
|
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,
|