opencode-swarm 7.184.11 → 7.184.13
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/.opencode/skills/swarm-ci-monitor/SKILL.md +1 -0
- package/.opencode/skills/swarm-pr-feedback/SKILL.md +1 -0
- package/.opencode/skills/swarm-pr-review/SKILL.md +21 -21
- package/.opencode/skills/swarm-pr-review/references/lane-output-recoverability.md +11 -0
- package/.opencode/skills/swarm-pr-review/references/parallel-work-example.md +20 -0
- package/.opencode/skills/swarm-pr-subscribe/SKILL.md +1 -0
- package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
- package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
- package/dist/background/delegation-lifecycle.d.ts +6 -2
- package/dist/background/pending-delegations.d.ts +23 -1
- package/dist/cli/auto-checkpoint-a2zbyh20.js +183 -0
- package/dist/cli/checkpoint-s444mhx5.js +51 -0
- package/dist/cli/{coder-settlement-6mhw6b36.js → coder-settlement-hnwwt3f0.js} +13 -11
- package/dist/cli/{config-doctor-tbaswv40.js → config-doctor-2qhay8ft.js} +2 -2
- package/dist/cli/{core-4389fcpc.js → core-567f7gbz.js} +3 -3
- package/dist/cli/{curation-policy-xe77n9zj.js → curation-policy-1rzheh1x.js} +6 -5
- package/dist/cli/{curator-asqb0cm7.js → curator-antxp3dg.js} +48 -42
- package/dist/cli/{curator-drift-nnge4dkk.js → curator-drift-ja4d9gq2.js} +9 -9
- package/dist/cli/curator-llm-factory-0a3svbcn.js +81 -0
- package/dist/cli/{dispatch-cv89p2y1.js → dispatch-0ejzwb45.js} +2 -1
- package/dist/cli/{evidence-summary-service-cdrwfdyp.js → evidence-summary-service-6ch3b0t5.js} +24 -19
- package/dist/cli/{gate-evidence-xbn83jeh.js → gate-evidence-zh4fpbnv.js} +8 -6
- package/dist/cli/guardrail-explain-pqyp8mx5.js +82 -0
- package/dist/cli/{guardrail-log-b6ef00v7.js → guardrail-log-99zsmp0p.js} +7 -7
- package/dist/cli/{guardrail-reset-77r7jfn2.js → guardrail-reset-mzs00j16.js} +48 -42
- package/dist/cli/hive-promoter-f3enyhkn.js +96 -0
- package/dist/cli/index-09wnx2ke.js +954 -0
- package/dist/cli/{index-kaay5kmx.js → index-0p0qwdyy.js} +2 -2
- package/dist/cli/{index-zz5rryxj.js → index-258a0p26.js} +7 -7
- package/dist/cli/{index-908zxswj.js → index-2n1ms79t.js} +44 -16
- package/dist/cli/{index-ejpxkrp6.js → index-2p3nzm9b.js} +1 -1
- package/dist/cli/index-2y9b45jj.js +24 -0
- package/dist/cli/{index-hk0eh9qb.js → index-4g4sr4ah.js} +1 -1
- package/dist/cli/{index-35cdceqf.js → index-6cjpmvpa.js} +2 -20
- package/dist/cli/{index-5cawm255.js → index-79y6dxa9.js} +8 -6
- package/dist/cli/index-7bxssqaf.js +2676 -0
- package/dist/cli/index-7pmbnjvj.js +11 -0
- package/dist/cli/{index-j4efx148.js → index-7r3pkgma.js} +5 -5
- package/dist/cli/{index-kg2mb1m5.js → index-7rzgdcvc.js} +2 -2
- package/dist/cli/{index-8gs8qkjs.js → index-7vb5rx5w.js} +1 -1
- package/dist/cli/{index-hamqvzqn.js → index-9nyqt3kb.js} +10 -2682
- package/dist/cli/{index-5njp971j.js → index-9rm7tw6y.js} +8 -8
- package/dist/cli/{index-c0dahh34.js → index-9y5b3nsk.js} +1 -1
- package/dist/cli/{index-xpcvwzdq.js → index-a96rm6zk.js} +3 -3
- package/dist/cli/{index-jhk62dp4.js → index-a9rfvc8j.js} +4 -4
- package/dist/cli/{index-xw8xdcrf.js → index-awkb5370.js} +5 -5
- package/dist/cli/{index-0mj7hc2z.js → index-bntwj2tp.js} +5 -5
- package/dist/cli/{index-aae38s4x.js → index-cftva3pa.js} +2 -11
- package/dist/cli/{index-hwjr3xyg.js → index-ck2hzp5b.js} +10 -38
- package/dist/cli/{index-e0rrj9kk.js → index-d2xdwz22.js} +9 -9
- package/dist/cli/{index-gnryhmak.js → index-dftztz4y.js} +1 -1
- package/dist/cli/{index-7k4ksbqd.js → index-djct2zsr.js} +1 -1
- package/dist/cli/{index-gqj1k2y6.js → index-e593fgq0.js} +2 -2
- package/dist/cli/{index-0ajyhjht.js → index-fxf3zhtq.js} +1 -1
- package/dist/cli/index-g4fs6z4e.js +37 -0
- package/dist/cli/{index-89nqyqxs.js → index-gz771bj7.js} +3 -3
- package/dist/cli/{index-tamg9rve.js → index-gzh04gxh.js} +2 -2
- package/dist/cli/index-hg1hqfy3.js +963 -0
- package/dist/cli/{index-nh5fxxc9.js → index-jtg0zsnx.js} +4 -2
- package/dist/cli/{index-3w96sd7p.js → index-kxm9wm5e.js} +3044 -3842
- package/dist/cli/{index-07fqfseh.js → index-m1pqenq9.js} +2 -2
- package/dist/cli/{index-be5h97z8.js → index-mfqge140.js} +1 -1
- package/dist/cli/{index-6z53ry5f.js → index-nt8g5952.js} +2 -2
- package/dist/cli/{index-cn67bp4y.js → index-pq35rmz5.js} +52 -46
- package/dist/cli/{index-5m1b70z3.js → index-pwcbtbhd.js} +4 -4
- package/dist/cli/{index-w0jbrttk.js → index-ra0z5wza.js} +3 -3
- package/dist/cli/{index-vx0wjfc1.js → index-sa061g64.js} +7 -7
- package/dist/cli/{index-7kmxy1rb.js → index-t7ck2nvk.js} +4 -4
- package/dist/cli/{index-ygdj73xq.js → index-tswsm3sw.js} +3 -3
- package/dist/cli/{index-q7q00ppx.js → index-tyzmjw2s.js} +7 -7
- package/dist/cli/{index-645ckyxy.js → index-v4ra6hz8.js} +55 -971
- package/dist/cli/{index-pbwfwc0v.js → index-vd1sd1m5.js} +48 -42
- package/dist/cli/{index-x1gyqgze.js → index-w6w6ny06.js} +2 -2
- package/dist/cli/{index-9xfxsx8y.js → index-wksedk4d.js} +1 -1
- package/dist/cli/{index-x119gdak.js → index-yx5z4200.js} +2 -2
- package/dist/cli/{index-dqpq8m9w.js → index-yydv4jfy.js} +2 -2
- package/dist/cli/index.js +49 -43
- package/dist/cli/{knowledge-escalator-8cc6jcw0.js → knowledge-escalator-6c813zv8.js} +13 -12
- package/dist/cli/{knowledge-events-b5g6ky4h.js → knowledge-events-9hbwedqb.js} +11 -10
- package/dist/cli/{knowledge-link-8tetyje0.js → knowledge-link-vvyfhhmr.js} +5 -4
- package/dist/cli/{knowledge-store-1w60j5xm.js → knowledge-store-8t9wy3ab.js} +6 -5
- package/dist/cli/{knowledge-validator-sd88rjcy.js → knowledge-validator-g61010aw.js} +8 -7
- package/dist/cli/{mcp-3052r65q.js → mcp-tyzj9cwy.js} +1 -1
- package/dist/cli/{model-preflight-m0nwfsx8.js → model-preflight-q8pnsjay.js} +48 -42
- package/dist/cli/{pending-delegations-5nx22evh.js → pending-delegations-8nah16wj.js} +16 -12
- package/dist/cli/{pr-subscriptions-kas44ty9.js → pr-subscriptions-rd3gnc3r.js} +14 -12
- package/dist/cli/{pr-workflow-gate-pmggnw1j.js → pr-workflow-gate-1y8by6bt.js} +56 -42
- package/dist/cli/{runner-ff0bj9w0.js → runner-cwmgb9rw.js} +6 -5
- package/dist/cli/{scan-cursor-yw12hvtc.js → scan-cursor-4s30je6f.js} +7 -6
- package/dist/cli/{schema-1g1y1d5q.js → schema-r3v5tb9r.js} +1 -1
- package/dist/cli/{scope-persistence-de472fxy.js → scope-persistence-vtz91b5n.js} +17 -15
- package/dist/cli/{server-1n00bga4.js → server-j1ybvgn4.js} +62 -54
- package/dist/cli/{skill-generator-c5wbbjqx.js → skill-generator-h27wtea0.js} +15 -14
- package/dist/cli/{snapshot-coordination-init-gwj594hc.js → snapshot-coordination-init-yntqf46w.js} +48 -42
- package/dist/cli/{speckit-checkoff-hc479v4r.js → speckit-checkoff-qxt03eh3.js} +4 -4
- package/dist/cli/{telemetry-39zmx4fp.js → telemetry-n6y2sjhg.js} +1 -1
- package/dist/cli/{workspace-snapshot-nrbvjh1c.js → workspace-snapshot-gnwak61t.js} +3 -3
- package/dist/cli/{worktree-collision-ownership-jvgxxnf9.js → worktree-collision-ownership-0a7jtwwe.js} +18 -16
- package/dist/cli/{worktree-isolation-r9hr23r8.js → worktree-isolation-4re648a3.js} +48 -42
- package/dist/hooks/pr-workflow-gate.d.ts +59 -1
- package/dist/index.js +543 -543
- package/dist/plan/auto-checkpoint.d.ts +56 -0
- package/dist/plan/manager.d.ts +8 -12
- package/dist/tools/dispatch-lanes.d.ts +7 -0
- package/dist/tools/submit-pr-review-result.d.ts +17 -0
- package/package.json +1 -1
- package/dist/cli/curator-llm-factory-1gjzcafw.js +0 -75
- package/dist/cli/guardrail-explain-xtyxjmyz.js +0 -76
- package/dist/cli/hive-promoter-dsrj2ar2.js +0 -90
|
@@ -1,48 +1,31 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import {
|
|
3
|
-
EvaluationRunV1Schema,
|
|
4
|
-
GateAuditResultV1Schema,
|
|
5
|
-
getProtectedEvaluationRunIds
|
|
6
|
-
} from "./index-nh5fxxc9.js";
|
|
7
|
-
import {
|
|
8
|
-
readEffectiveSpecSync
|
|
9
|
-
} from "./index-c0dahh34.js";
|
|
10
2
|
import {
|
|
11
3
|
validateWorkspaceRoot
|
|
12
4
|
} from "./index-6b295cas.js";
|
|
5
|
+
import {
|
|
6
|
+
readEffectiveSpecSync
|
|
7
|
+
} from "./index-9y5b3nsk.js";
|
|
13
8
|
import {
|
|
14
9
|
getWorktreeMergeFailure
|
|
15
10
|
} from "./index-zsrtt42s.js";
|
|
16
11
|
import {
|
|
17
12
|
GitBinaryMissingError,
|
|
18
13
|
GitSpawnCwdError,
|
|
19
|
-
TASK_WORKFLOW_SCHEMA_MARKER,
|
|
20
|
-
deriveApplicableGateSet,
|
|
21
14
|
isGitBinaryMissing,
|
|
22
15
|
isSpawnCwdMissing,
|
|
23
|
-
isSpawnCwdUnreadable
|
|
24
|
-
|
|
25
|
-
readCurrentTaskDeclaredFiles,
|
|
26
|
-
readTaskEvidence,
|
|
27
|
-
readTaskEvidenceRaw,
|
|
28
|
-
sanitizeTaskId
|
|
29
|
-
} from "./index-hwjr3xyg.js";
|
|
16
|
+
isSpawnCwdUnreadable
|
|
17
|
+
} from "./index-g4fs6z4e.js";
|
|
30
18
|
import {
|
|
31
19
|
estimateCharsForTokens,
|
|
32
20
|
estimateTokens,
|
|
33
21
|
readSwarmFileAsync,
|
|
34
22
|
validateSwarmPath
|
|
35
|
-
} from "./index-
|
|
23
|
+
} from "./index-dftztz4y.js";
|
|
36
24
|
import {
|
|
37
25
|
bunHash,
|
|
38
26
|
bunWrite,
|
|
39
27
|
mergeEnvForChild
|
|
40
28
|
} from "./index-2s7dvzff.js";
|
|
41
|
-
import {
|
|
42
|
-
EVIDENCE_MAX_JSON_BYTES,
|
|
43
|
-
EvidenceBundleSchema,
|
|
44
|
-
EvidenceSchema
|
|
45
|
-
} from "./index-frcemc0b.js";
|
|
46
29
|
import {
|
|
47
30
|
LedgerStaleWriterError,
|
|
48
31
|
appendLedgerEvent,
|
|
@@ -61,33 +44,32 @@ import {
|
|
|
61
44
|
replayFromLedgerWithStatus,
|
|
62
45
|
takeSnapshotEvent,
|
|
63
46
|
takeSnapshotWithRetry
|
|
64
|
-
} from "./index-
|
|
47
|
+
} from "./index-d2xdwz22.js";
|
|
65
48
|
import {
|
|
66
49
|
appendCoreEventSync
|
|
67
|
-
} from "./index-
|
|
50
|
+
} from "./index-7rzgdcvc.js";
|
|
68
51
|
import {
|
|
69
|
-
derivePlanId,
|
|
70
|
-
derivePlanIdentityHash,
|
|
71
52
|
getCoordinationState,
|
|
72
53
|
importCoordinationOnce,
|
|
73
54
|
listCoordinationStates,
|
|
74
55
|
transitionCoordinationState
|
|
75
|
-
} from "./index-
|
|
56
|
+
} from "./index-cftva3pa.js";
|
|
76
57
|
import {
|
|
77
58
|
DURABILITY_CLASSES,
|
|
78
59
|
getProjectDb,
|
|
79
60
|
projectDbExists,
|
|
80
61
|
withDurabilityClass
|
|
81
|
-
} from "./index-
|
|
62
|
+
} from "./index-pwcbtbhd.js";
|
|
82
63
|
import {
|
|
83
|
-
|
|
84
|
-
|
|
64
|
+
derivePlanId,
|
|
65
|
+
derivePlanIdentityHash
|
|
66
|
+
} from "./index-7pmbnjvj.js";
|
|
85
67
|
import {
|
|
86
68
|
assertProjectRoot
|
|
87
69
|
} from "./index-t7hmqgjy.js";
|
|
88
70
|
import {
|
|
89
71
|
emit
|
|
90
|
-
} from "./index-
|
|
72
|
+
} from "./index-w6w6ny06.js";
|
|
91
73
|
import {
|
|
92
74
|
canonicalRootKeyFresh
|
|
93
75
|
} from "./index-mc72pk74.js";
|
|
@@ -98,7 +80,7 @@ import {
|
|
|
98
80
|
atomicWriteSwarmFileSync,
|
|
99
81
|
invalidateCachedArtifact,
|
|
100
82
|
readCachedParsedFile
|
|
101
|
-
} from "./index-
|
|
83
|
+
} from "./index-bntwj2tp.js";
|
|
102
84
|
import {
|
|
103
85
|
PlanSchema,
|
|
104
86
|
normalizeCurrentPhaseInPlace,
|
|
@@ -110,10 +92,6 @@ import {
|
|
|
110
92
|
init_git_executable,
|
|
111
93
|
resolveGitExecutable
|
|
112
94
|
} from "./index-zxdawwc7.js";
|
|
113
|
-
import {
|
|
114
|
-
ZodError,
|
|
115
|
-
init_zod
|
|
116
|
-
} from "./index-gknz3bv1.js";
|
|
117
95
|
import {
|
|
118
96
|
init_executor,
|
|
119
97
|
isUntrustedEnvKey,
|
|
@@ -129,19 +107,6 @@ import {
|
|
|
129
107
|
__require
|
|
130
108
|
} from "./index-a76rekgs.js";
|
|
131
109
|
|
|
132
|
-
// src/plan/manager.ts
|
|
133
|
-
import {
|
|
134
|
-
closeSync,
|
|
135
|
-
fsyncSync,
|
|
136
|
-
mkdirSync as mkdirSync2,
|
|
137
|
-
openSync,
|
|
138
|
-
renameSync as renameSync2,
|
|
139
|
-
unlinkSync,
|
|
140
|
-
writeFileSync
|
|
141
|
-
} from "fs";
|
|
142
|
-
import * as fsPromises from "fs/promises";
|
|
143
|
-
import * as path3 from "path";
|
|
144
|
-
|
|
145
110
|
// src/db/task-checkpoint-receipt.ts
|
|
146
111
|
import { createHash } from "crypto";
|
|
147
112
|
var TASK_COMPLETION_HASH_LENGTH = 16;
|
|
@@ -299,14 +264,6 @@ function updateTaskCheckpointReceipt(directory, descriptor, state, sha) {
|
|
|
299
264
|
return rowAfter;
|
|
300
265
|
}
|
|
301
266
|
|
|
302
|
-
// src/git/branch.ts
|
|
303
|
-
init_executor();
|
|
304
|
-
import * as child_process from "child_process";
|
|
305
|
-
import * as fsSync from "fs";
|
|
306
|
-
import path from "path";
|
|
307
|
-
init_git_executable();
|
|
308
|
-
init_logger();
|
|
309
|
-
|
|
310
267
|
// src/utils/transient-retry.ts
|
|
311
268
|
var MAX_TRANSIENT_RETRIES = 5;
|
|
312
269
|
var RETRY_BASE_DELAY_MS = 200;
|
|
@@ -326,6 +283,27 @@ function transientBackoff(attempt) {
|
|
|
326
283
|
}
|
|
327
284
|
}
|
|
328
285
|
|
|
286
|
+
// src/plan/manager.ts
|
|
287
|
+
import {
|
|
288
|
+
closeSync,
|
|
289
|
+
fsyncSync,
|
|
290
|
+
mkdirSync as mkdirSync2,
|
|
291
|
+
openSync,
|
|
292
|
+
renameSync as renameSync2,
|
|
293
|
+
unlinkSync,
|
|
294
|
+
writeFileSync
|
|
295
|
+
} from "fs";
|
|
296
|
+
import * as fsPromises from "fs/promises";
|
|
297
|
+
import * as path3 from "path";
|
|
298
|
+
|
|
299
|
+
// src/git/branch.ts
|
|
300
|
+
init_executor();
|
|
301
|
+
import * as child_process from "child_process";
|
|
302
|
+
import * as fsSync from "fs";
|
|
303
|
+
import path from "path";
|
|
304
|
+
init_git_executable();
|
|
305
|
+
init_logger();
|
|
306
|
+
|
|
329
307
|
// src/git/safe-ref.ts
|
|
330
308
|
class UnsafeGitRefError extends Error {
|
|
331
309
|
ref;
|
|
@@ -1764,7 +1742,8 @@ var _internals5 = {
|
|
|
1764
1742
|
isEpicModeActiveForProject,
|
|
1765
1743
|
commitTaskCompletion,
|
|
1766
1744
|
getWorktreeMergeFailure,
|
|
1767
|
-
recordTaskAttempt
|
|
1745
|
+
recordTaskAttempt,
|
|
1746
|
+
maybeSaveAutoCheckpoint: defaultMaybeSaveAutoCheckpoint
|
|
1768
1747
|
};
|
|
1769
1748
|
var CAS_BACKOFF_START_MS = 5;
|
|
1770
1749
|
var CAS_BACKOFF_CAP_MS = 250;
|
|
@@ -3024,6 +3003,10 @@ ${markdown}`;
|
|
|
3024
3003
|
} catch {}
|
|
3025
3004
|
}
|
|
3026
3005
|
}
|
|
3006
|
+
async function defaultMaybeSaveAutoCheckpoint(directory, plan) {
|
|
3007
|
+
const { maybeSaveAutoCheckpoint } = await import("./auto-checkpoint-a2zbyh20.js");
|
|
3008
|
+
return maybeSaveAutoCheckpoint(directory, plan);
|
|
3009
|
+
}
|
|
3027
3010
|
async function updateTaskStatus(directory, taskId, status, options) {
|
|
3028
3011
|
assertProjectRoot(directory);
|
|
3029
3012
|
const derivePhaseStatusFromTasks = (tasks) => {
|
|
@@ -3097,7 +3080,7 @@ async function updateTaskStatus(directory, taskId, status, options) {
|
|
|
3097
3080
|
if (status === "completed") {
|
|
3098
3081
|
try {
|
|
3099
3082
|
const completedTask = updatedPlan.phases.flatMap((phase) => phase.tasks).find((candidate) => candidate.id === taskId);
|
|
3100
|
-
const { maybePropagateSpeckitCheckoff } = await import("./speckit-checkoff-
|
|
3083
|
+
const { maybePropagateSpeckitCheckoff } = await import("./speckit-checkoff-qxt03eh3.js");
|
|
3101
3084
|
await maybePropagateSpeckitCheckoff(directory, {
|
|
3102
3085
|
taskId,
|
|
3103
3086
|
frRefs: completedTask?.fr_refs ?? [],
|
|
@@ -3122,7 +3105,7 @@ async function updateTaskStatus(directory, taskId, status, options) {
|
|
|
3122
3105
|
break;
|
|
3123
3106
|
}
|
|
3124
3107
|
}
|
|
3125
|
-
const { readDeclaredScopeFilesFromBindings } = await import("./scope-persistence-
|
|
3108
|
+
const { readDeclaredScopeFilesFromBindings } = await import("./scope-persistence-vtz91b5n.js");
|
|
3126
3109
|
const canonicalScope = readDeclaredScopeFilesFromBindings({
|
|
3127
3110
|
directory,
|
|
3128
3111
|
taskId,
|
|
@@ -3133,6 +3116,16 @@ async function updateTaskStatus(directory, taskId, status, options) {
|
|
|
3133
3116
|
criticalWarn(`[plan/manager] Rule 2 auto-commit for ${taskId} threw (non-fatal): ${commitErr instanceof Error ? commitErr.message : String(commitErr)}`);
|
|
3134
3117
|
}
|
|
3135
3118
|
}
|
|
3119
|
+
if (status === "completed") {
|
|
3120
|
+
try {
|
|
3121
|
+
const outcome = await _internals5.maybeSaveAutoCheckpoint(directory, updatedPlan);
|
|
3122
|
+
if (outcome && outcome.saved === false && outcome.warning) {
|
|
3123
|
+
criticalWarn(`[plan/manager] auto-checkpoint for ${taskId} was not saved (non-fatal): ${outcome.warning}`);
|
|
3124
|
+
}
|
|
3125
|
+
} catch (checkpointErr) {
|
|
3126
|
+
criticalWarn(`[plan/manager] auto-checkpoint cadence trigger for ${taskId} failed (non-fatal): ${checkpointErr instanceof Error ? checkpointErr.message : String(checkpointErr)}`);
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3136
3129
|
return updatedPlan;
|
|
3137
3130
|
} catch (error2) {
|
|
3138
3131
|
if (error2 instanceof PlanConcurrentModificationError && attempt < MAX_OUTER_RETRIES) {
|
|
@@ -3453,913 +3446,4 @@ function migrateLegacyPlan(planContent, swarmId) {
|
|
|
3453
3446
|
return plan;
|
|
3454
3447
|
}
|
|
3455
3448
|
|
|
3456
|
-
|
|
3457
|
-
init_zod();
|
|
3458
|
-
import {
|
|
3459
|
-
mkdirSync as mkdirSync3,
|
|
3460
|
-
readdirSync,
|
|
3461
|
-
realpathSync,
|
|
3462
|
-
renameSync as renameSync3,
|
|
3463
|
-
rmSync,
|
|
3464
|
-
statSync as statSync2
|
|
3465
|
-
} from "fs";
|
|
3466
|
-
import * as fs5 from "fs/promises";
|
|
3467
|
-
import * as path5 from "path";
|
|
3468
|
-
|
|
3469
|
-
// src/evaluation/retention.ts
|
|
3470
|
-
import * as fs3 from "fs/promises";
|
|
3471
|
-
import * as path4 from "path";
|
|
3472
|
-
function artifactKey(artifact) {
|
|
3473
|
-
return `${artifact.namespace}/${artifact.id}`;
|
|
3474
|
-
}
|
|
3475
|
-
function validId(value) {
|
|
3476
|
-
return /^[A-Za-z0-9][A-Za-z0-9._-]{0,159}$/.test(value);
|
|
3477
|
-
}
|
|
3478
|
-
async function evaluationRunCandidates(directory) {
|
|
3479
|
-
const root = path4.join(directory, ".swarm", "evolution", "runs");
|
|
3480
|
-
let entries = [];
|
|
3481
|
-
try {
|
|
3482
|
-
entries = await fs3.readdir(root, { withFileTypes: true });
|
|
3483
|
-
} catch (error2) {
|
|
3484
|
-
if (error2.code === "ENOENT") {
|
|
3485
|
-
return { candidates: [], corrupt: [] };
|
|
3486
|
-
}
|
|
3487
|
-
throw error2;
|
|
3488
|
-
}
|
|
3489
|
-
const candidates = [];
|
|
3490
|
-
const corrupt = [];
|
|
3491
|
-
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
3492
|
-
if (!entry.isFile() || !entry.name.endsWith(".json"))
|
|
3493
|
-
continue;
|
|
3494
|
-
const id = entry.name.slice(0, -".json".length);
|
|
3495
|
-
if (!validId(id))
|
|
3496
|
-
continue;
|
|
3497
|
-
const artifact = { namespace: "evaluation-run", id };
|
|
3498
|
-
const target = path4.join(root, entry.name);
|
|
3499
|
-
try {
|
|
3500
|
-
const run = EvaluationRunV1Schema.parse(JSON.parse(await fs3.readFile(target, "utf8")));
|
|
3501
|
-
if (run.runId !== id)
|
|
3502
|
-
throw new Error("run id/path mismatch");
|
|
3503
|
-
candidates.push({
|
|
3504
|
-
artifact,
|
|
3505
|
-
createdAt: run.createdAt,
|
|
3506
|
-
target,
|
|
3507
|
-
kind: "file"
|
|
3508
|
-
});
|
|
3509
|
-
} catch {
|
|
3510
|
-
corrupt.push(artifact);
|
|
3511
|
-
}
|
|
3512
|
-
}
|
|
3513
|
-
return { candidates, corrupt };
|
|
3514
|
-
}
|
|
3515
|
-
async function gateAuditCandidates(directory) {
|
|
3516
|
-
const root = path4.join(directory, ".swarm", "evidence", "gate-audit");
|
|
3517
|
-
let entries = [];
|
|
3518
|
-
try {
|
|
3519
|
-
entries = await fs3.readdir(root, { withFileTypes: true });
|
|
3520
|
-
} catch (error2) {
|
|
3521
|
-
if (error2.code === "ENOENT") {
|
|
3522
|
-
return { candidates: [], corrupt: [] };
|
|
3523
|
-
}
|
|
3524
|
-
throw error2;
|
|
3525
|
-
}
|
|
3526
|
-
const candidates = [];
|
|
3527
|
-
const corrupt = [];
|
|
3528
|
-
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
3529
|
-
if (!entry.isDirectory() || !validId(entry.name))
|
|
3530
|
-
continue;
|
|
3531
|
-
const artifact = { namespace: "gate-audit", id: entry.name };
|
|
3532
|
-
const target = path4.join(root, entry.name);
|
|
3533
|
-
try {
|
|
3534
|
-
const result = GateAuditResultV1Schema.parse(JSON.parse(await fs3.readFile(path4.join(target, "results.json"), "utf8")));
|
|
3535
|
-
if (result.runId !== entry.name)
|
|
3536
|
-
throw new Error("run id/path mismatch");
|
|
3537
|
-
candidates.push({
|
|
3538
|
-
artifact,
|
|
3539
|
-
createdAt: result.createdAt,
|
|
3540
|
-
target,
|
|
3541
|
-
kind: "directory"
|
|
3542
|
-
});
|
|
3543
|
-
} catch {
|
|
3544
|
-
corrupt.push(artifact);
|
|
3545
|
-
}
|
|
3546
|
-
}
|
|
3547
|
-
return { candidates, corrupt };
|
|
3548
|
-
}
|
|
3549
|
-
async function retentionCandidates(directory) {
|
|
3550
|
-
const [runs, audits] = await Promise.all([
|
|
3551
|
-
evaluationRunCandidates(directory),
|
|
3552
|
-
gateAuditCandidates(directory)
|
|
3553
|
-
]);
|
|
3554
|
-
return {
|
|
3555
|
-
candidates: [...runs.candidates, ...audits.candidates].sort((a, b) => artifactKey(a.artifact).localeCompare(artifactKey(b.artifact))),
|
|
3556
|
-
corrupt: [...runs.corrupt, ...audits.corrupt].sort((a, b) => artifactKey(a).localeCompare(artifactKey(b)))
|
|
3557
|
-
};
|
|
3558
|
-
}
|
|
3559
|
-
async function protectedArtifacts(directory) {
|
|
3560
|
-
const ids = await getProtectedEvaluationRunIds(directory);
|
|
3561
|
-
return new Set([...ids].map((id) => `evaluation-run/${id}`));
|
|
3562
|
-
}
|
|
3563
|
-
async function removeCandidate(candidate) {
|
|
3564
|
-
if (candidate.kind === "directory") {
|
|
3565
|
-
await fs3.rm(candidate.target, { recursive: true, force: true });
|
|
3566
|
-
return;
|
|
3567
|
-
}
|
|
3568
|
-
await fs3.unlink(candidate.target);
|
|
3569
|
-
}
|
|
3570
|
-
var _retentionInternals = {
|
|
3571
|
-
protectedArtifacts,
|
|
3572
|
-
removeCandidate
|
|
3573
|
-
};
|
|
3574
|
-
async function archiveEvaluationArtifacts(args) {
|
|
3575
|
-
assertProjectRoot(args.directory);
|
|
3576
|
-
return withEvidenceLock(args.directory, path4.join("evolution", "retention-index"), "evaluation-retention", "archive", async () => {
|
|
3577
|
-
const inventory = await retentionCandidates(args.directory);
|
|
3578
|
-
let protectedKeys = await _retentionInternals.protectedArtifacts(args.directory);
|
|
3579
|
-
const protectedRefs = inventory.candidates.filter((candidate) => protectedKeys.has(artifactKey(candidate.artifact))).map((candidate) => candidate.artifact);
|
|
3580
|
-
const eligible = inventory.candidates.filter((candidate) => !protectedKeys.has(artifactKey(candidate.artifact)));
|
|
3581
|
-
const now = args.now ?? new Date;
|
|
3582
|
-
const cutoff = new Date(now.getTime() - args.maxAgeDays * 86400000).toISOString();
|
|
3583
|
-
const selectedKeys = new Set(eligible.filter((candidate) => candidate.createdAt < cutoff).map((candidate) => artifactKey(candidate.artifact)));
|
|
3584
|
-
const remaining = eligible.filter((candidate) => !selectedKeys.has(artifactKey(candidate.artifact))).sort((a, b) => a.createdAt === b.createdAt ? artifactKey(a.artifact).localeCompare(artifactKey(b.artifact)) : a.createdAt.localeCompare(b.createdAt));
|
|
3585
|
-
if (args.maxBundles !== undefined && remaining.length > args.maxBundles) {
|
|
3586
|
-
for (const candidate of remaining.slice(0, remaining.length - args.maxBundles)) {
|
|
3587
|
-
selectedKeys.add(artifactKey(candidate.artifact));
|
|
3588
|
-
}
|
|
3589
|
-
}
|
|
3590
|
-
const selectedCandidates = eligible.filter((candidate) => selectedKeys.has(artifactKey(candidate.artifact))).sort((a, b) => artifactKey(a.artifact).localeCompare(artifactKey(b.artifact)));
|
|
3591
|
-
const archived = [];
|
|
3592
|
-
const failed = [];
|
|
3593
|
-
if (!args.dryRun) {
|
|
3594
|
-
for (const candidate of selectedCandidates) {
|
|
3595
|
-
protectedKeys = await _retentionInternals.protectedArtifacts(args.directory);
|
|
3596
|
-
if (protectedKeys.has(artifactKey(candidate.artifact))) {
|
|
3597
|
-
protectedRefs.push(candidate.artifact);
|
|
3598
|
-
continue;
|
|
3599
|
-
}
|
|
3600
|
-
try {
|
|
3601
|
-
await _retentionInternals.removeCandidate(candidate);
|
|
3602
|
-
archived.push(candidate.artifact);
|
|
3603
|
-
} catch (error2) {
|
|
3604
|
-
failed.push({
|
|
3605
|
-
artifact: candidate.artifact,
|
|
3606
|
-
error: error2 instanceof Error ? error2.message : String(error2)
|
|
3607
|
-
});
|
|
3608
|
-
}
|
|
3609
|
-
}
|
|
3610
|
-
}
|
|
3611
|
-
return {
|
|
3612
|
-
inventory: inventory.candidates.map((candidate) => candidate.artifact),
|
|
3613
|
-
selected: selectedCandidates.map((candidate) => candidate.artifact),
|
|
3614
|
-
archived,
|
|
3615
|
-
corrupt: inventory.corrupt,
|
|
3616
|
-
protected: [
|
|
3617
|
-
...new Map(protectedRefs.map((artifact) => [artifactKey(artifact), artifact])).values()
|
|
3618
|
-
].sort((a, b) => artifactKey(a).localeCompare(artifactKey(b))),
|
|
3619
|
-
failed
|
|
3620
|
-
};
|
|
3621
|
-
});
|
|
3622
|
-
}
|
|
3623
|
-
|
|
3624
|
-
// src/evidence/documents-retention.ts
|
|
3625
|
-
import * as fs4 from "fs";
|
|
3626
|
-
import * as fsp from "fs/promises";
|
|
3627
|
-
import * as readline from "readline";
|
|
3628
|
-
var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
|
|
3629
|
-
var MAX_READ_BYTES = 100 * 1024 * 1024;
|
|
3630
|
-
var RENAME_MAX_ATTEMPTS = 5;
|
|
3631
|
-
var RENAME_BACKOFF_MS = 10;
|
|
3632
|
-
var RENAME_RETRY_CODES = new Set(["EPERM", "EBUSY", "ENOTEMPTY", "EACCES"]);
|
|
3633
|
-
var _internals6 = {
|
|
3634
|
-
stat: (p) => fsp.stat(p),
|
|
3635
|
-
createReadStream: (p, options) => fs4.createReadStream(p, options),
|
|
3636
|
-
openSync: (p, flags) => fs4.openSync(p, flags),
|
|
3637
|
-
writeSync: (fd, data, position) => fs4.writeSync(fd, data, position),
|
|
3638
|
-
fsyncSync: (fd) => fs4.fsyncSync(fd),
|
|
3639
|
-
closeSync: (fd) => fs4.closeSync(fd),
|
|
3640
|
-
renameWithRetry: atomicRenameWithRetry,
|
|
3641
|
-
unlink: (p) => fsp.unlink(p)
|
|
3642
|
-
};
|
|
3643
|
-
async function atomicRenameWithRetry(src, dst, renameFn = fsp.rename) {
|
|
3644
|
-
let lastErr;
|
|
3645
|
-
for (let attempt = 0;attempt < RENAME_MAX_ATTEMPTS; attempt++) {
|
|
3646
|
-
try {
|
|
3647
|
-
await renameFn(src, dst);
|
|
3648
|
-
return;
|
|
3649
|
-
} catch (err) {
|
|
3650
|
-
lastErr = err;
|
|
3651
|
-
const code = err?.code;
|
|
3652
|
-
if (!code || !RENAME_RETRY_CODES.has(code)) {
|
|
3653
|
-
throw err;
|
|
3654
|
-
}
|
|
3655
|
-
if (attempt < RENAME_MAX_ATTEMPTS - 1) {
|
|
3656
|
-
await new Promise((resolve3) => setTimeout(resolve3, RENAME_BACKOFF_MS));
|
|
3657
|
-
}
|
|
3658
|
-
}
|
|
3659
|
-
}
|
|
3660
|
-
throw lastErr;
|
|
3661
|
-
}
|
|
3662
|
-
function emptyResult(dryRun) {
|
|
3663
|
-
return {
|
|
3664
|
-
inventory: 0,
|
|
3665
|
-
selected: 0,
|
|
3666
|
-
archived: 0,
|
|
3667
|
-
corrupt: 0,
|
|
3668
|
-
bytesBefore: 0,
|
|
3669
|
-
bytesAfter: 0,
|
|
3670
|
-
dryRun,
|
|
3671
|
-
aborted: false
|
|
3672
|
-
};
|
|
3673
|
-
}
|
|
3674
|
-
async function readCacheRows(filePath) {
|
|
3675
|
-
const stat2 = await _internals6.stat(filePath);
|
|
3676
|
-
const bytesBefore = stat2.size;
|
|
3677
|
-
const stream = _internals6.createReadStream(filePath, {
|
|
3678
|
-
encoding: "utf8",
|
|
3679
|
-
highWaterMark: 64 * 1024
|
|
3680
|
-
});
|
|
3681
|
-
const rl = readline.createInterface({
|
|
3682
|
-
input: stream,
|
|
3683
|
-
crlfDelay: Infinity
|
|
3684
|
-
});
|
|
3685
|
-
const rows = [];
|
|
3686
|
-
let corrupt = 0;
|
|
3687
|
-
let bytesRead = 0;
|
|
3688
|
-
let aborted = false;
|
|
3689
|
-
try {
|
|
3690
|
-
for await (const line of rl) {
|
|
3691
|
-
const lineBytes = Buffer.byteLength(line, "utf8") + 1;
|
|
3692
|
-
bytesRead += lineBytes;
|
|
3693
|
-
if (bytesRead > MAX_READ_BYTES) {
|
|
3694
|
-
aborted = true;
|
|
3695
|
-
break;
|
|
3696
|
-
}
|
|
3697
|
-
if (line.length === 0)
|
|
3698
|
-
continue;
|
|
3699
|
-
let record = null;
|
|
3700
|
-
try {
|
|
3701
|
-
const parsed = JSON.parse(line);
|
|
3702
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
3703
|
-
record = parsed;
|
|
3704
|
-
} else {
|
|
3705
|
-
corrupt++;
|
|
3706
|
-
continue;
|
|
3707
|
-
}
|
|
3708
|
-
} catch {
|
|
3709
|
-
corrupt++;
|
|
3710
|
-
continue;
|
|
3711
|
-
}
|
|
3712
|
-
rows.push({ raw: line, bytes: lineBytes, record });
|
|
3713
|
-
}
|
|
3714
|
-
} finally {
|
|
3715
|
-
rl.close();
|
|
3716
|
-
stream.destroy();
|
|
3717
|
-
}
|
|
3718
|
-
return { rows, corrupt, aborted, bytesBefore };
|
|
3719
|
-
}
|
|
3720
|
-
function oldestFirst(a, b) {
|
|
3721
|
-
const at = typeof a.record?.capturedAt === "string" ? a.record.capturedAt : "";
|
|
3722
|
-
const bt = typeof b.record?.capturedAt === "string" ? b.record.capturedAt : "";
|
|
3723
|
-
if (at === bt)
|
|
3724
|
-
return a.raw.localeCompare(b.raw);
|
|
3725
|
-
return at.localeCompare(bt);
|
|
3726
|
-
}
|
|
3727
|
-
function selectSurvivors(rows, maxRecords, maxBytes) {
|
|
3728
|
-
const ordered = [...rows].sort(oldestFirst);
|
|
3729
|
-
let keepFrom = 0;
|
|
3730
|
-
if (typeof maxRecords === "number" && ordered.length > maxRecords) {
|
|
3731
|
-
keepFrom = ordered.length - maxRecords;
|
|
3732
|
-
}
|
|
3733
|
-
if (typeof maxBytes === "number" && maxBytes > 0) {
|
|
3734
|
-
let total = 0;
|
|
3735
|
-
for (let i = keepFrom;i < ordered.length; i++) {
|
|
3736
|
-
total += ordered[i].bytes;
|
|
3737
|
-
}
|
|
3738
|
-
while (keepFrom < ordered.length && total > maxBytes) {
|
|
3739
|
-
total -= ordered[keepFrom].bytes;
|
|
3740
|
-
keepFrom++;
|
|
3741
|
-
}
|
|
3742
|
-
}
|
|
3743
|
-
const survivors = ordered.slice(keepFrom);
|
|
3744
|
-
const selected = rows.length - survivors.length;
|
|
3745
|
-
return { survivors, selected };
|
|
3746
|
-
}
|
|
3747
|
-
async function rewriteAtomic(filePath, survivors) {
|
|
3748
|
-
const tmpPath = `${filePath}.tmp.${Date.now()}.${process.pid}`;
|
|
3749
|
-
const payload = survivors.length > 0 ? `${survivors.map((row) => row.raw).join(`
|
|
3750
|
-
`)}
|
|
3751
|
-
` : "";
|
|
3752
|
-
let succeeded = false;
|
|
3753
|
-
const fd = _internals6.openSync(tmpPath, "w");
|
|
3754
|
-
try {
|
|
3755
|
-
_internals6.writeSync(fd, payload, 0);
|
|
3756
|
-
_internals6.fsyncSync(fd);
|
|
3757
|
-
_internals6.closeSync(fd);
|
|
3758
|
-
await _internals6.renameWithRetry(tmpPath, filePath);
|
|
3759
|
-
succeeded = true;
|
|
3760
|
-
} catch (err) {
|
|
3761
|
-
try {
|
|
3762
|
-
_internals6.closeSync(fd);
|
|
3763
|
-
} catch {}
|
|
3764
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
3765
|
-
throw new Error(`documents-cache rewrite failed: ${msg}`);
|
|
3766
|
-
} finally {
|
|
3767
|
-
if (!succeeded) {
|
|
3768
|
-
try {
|
|
3769
|
-
await _internals6.unlink(tmpPath);
|
|
3770
|
-
} catch {}
|
|
3771
|
-
}
|
|
3772
|
-
}
|
|
3773
|
-
return Buffer.byteLength(payload, "utf8");
|
|
3774
|
-
}
|
|
3775
|
-
async function pruneEvidenceDocuments(args) {
|
|
3776
|
-
assertProjectRoot(args.directory);
|
|
3777
|
-
const dryRun = args.dryRun === true;
|
|
3778
|
-
const capsUnset = (typeof args.maxBytes !== "number" || args.maxBytes <= 0) && (typeof args.maxRecords !== "number" || args.maxRecords <= 0);
|
|
3779
|
-
const filePath = validateSwarmPath(args.directory, EVIDENCE_CACHE_FILE);
|
|
3780
|
-
let stat2;
|
|
3781
|
-
try {
|
|
3782
|
-
stat2 = await _internals6.stat(filePath);
|
|
3783
|
-
} catch (err) {
|
|
3784
|
-
const code = err?.code;
|
|
3785
|
-
if (code === "ENOENT")
|
|
3786
|
-
return emptyResult(dryRun);
|
|
3787
|
-
throw err;
|
|
3788
|
-
}
|
|
3789
|
-
if (capsUnset) {
|
|
3790
|
-
return {
|
|
3791
|
-
inventory: 0,
|
|
3792
|
-
selected: 0,
|
|
3793
|
-
archived: 0,
|
|
3794
|
-
corrupt: 0,
|
|
3795
|
-
bytesBefore: stat2.size,
|
|
3796
|
-
bytesAfter: stat2.size,
|
|
3797
|
-
dryRun,
|
|
3798
|
-
aborted: false
|
|
3799
|
-
};
|
|
3800
|
-
}
|
|
3801
|
-
let readResult;
|
|
3802
|
-
try {
|
|
3803
|
-
readResult = await readCacheRows(filePath);
|
|
3804
|
-
} catch (err) {
|
|
3805
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
3806
|
-
warn(`documents-cache prune: read failed: ${msg}`);
|
|
3807
|
-
throw err;
|
|
3808
|
-
}
|
|
3809
|
-
if (readResult.aborted) {
|
|
3810
|
-
warn(`documents-cache prune: aborted, file exceeds ${MAX_READ_BYTES} bytes; left untouched`);
|
|
3811
|
-
return {
|
|
3812
|
-
inventory: readResult.rows.length,
|
|
3813
|
-
selected: 0,
|
|
3814
|
-
archived: 0,
|
|
3815
|
-
corrupt: readResult.corrupt,
|
|
3816
|
-
bytesBefore: readResult.bytesBefore,
|
|
3817
|
-
bytesAfter: readResult.bytesBefore,
|
|
3818
|
-
dryRun,
|
|
3819
|
-
aborted: true
|
|
3820
|
-
};
|
|
3821
|
-
}
|
|
3822
|
-
const { survivors, selected } = selectSurvivors(readResult.rows, args.maxRecords, args.maxBytes);
|
|
3823
|
-
if (dryRun) {
|
|
3824
|
-
const bytesAfter2 = survivors.reduce((sum, row) => sum + row.bytes, 0);
|
|
3825
|
-
return {
|
|
3826
|
-
inventory: readResult.rows.length,
|
|
3827
|
-
selected,
|
|
3828
|
-
archived: 0,
|
|
3829
|
-
corrupt: readResult.corrupt,
|
|
3830
|
-
bytesBefore: readResult.bytesBefore,
|
|
3831
|
-
bytesAfter: bytesAfter2,
|
|
3832
|
-
dryRun: true,
|
|
3833
|
-
aborted: false
|
|
3834
|
-
};
|
|
3835
|
-
}
|
|
3836
|
-
if (selected === 0 && readResult.corrupt === 0) {
|
|
3837
|
-
return {
|
|
3838
|
-
inventory: readResult.rows.length,
|
|
3839
|
-
selected: 0,
|
|
3840
|
-
archived: 0,
|
|
3841
|
-
corrupt: 0,
|
|
3842
|
-
bytesBefore: readResult.bytesBefore,
|
|
3843
|
-
bytesAfter: readResult.bytesBefore,
|
|
3844
|
-
dryRun: false,
|
|
3845
|
-
aborted: false
|
|
3846
|
-
};
|
|
3847
|
-
}
|
|
3848
|
-
const bytesAfter = await rewriteAtomic(filePath, survivors);
|
|
3849
|
-
return {
|
|
3850
|
-
inventory: readResult.rows.length,
|
|
3851
|
-
selected,
|
|
3852
|
-
archived: selected,
|
|
3853
|
-
corrupt: readResult.corrupt,
|
|
3854
|
-
bytesBefore: readResult.bytesBefore,
|
|
3855
|
-
bytesAfter,
|
|
3856
|
-
dryRun: false,
|
|
3857
|
-
aborted: false
|
|
3858
|
-
};
|
|
3859
|
-
}
|
|
3860
|
-
|
|
3861
|
-
// src/evidence/manager.ts
|
|
3862
|
-
var VALID_EVIDENCE_TYPES = [
|
|
3863
|
-
"review",
|
|
3864
|
-
"test",
|
|
3865
|
-
"diff",
|
|
3866
|
-
"approval",
|
|
3867
|
-
"note",
|
|
3868
|
-
"retrospective",
|
|
3869
|
-
"syntax",
|
|
3870
|
-
"placeholder",
|
|
3871
|
-
"sast",
|
|
3872
|
-
"sbom",
|
|
3873
|
-
"build",
|
|
3874
|
-
"quality_budget",
|
|
3875
|
-
"secretscan"
|
|
3876
|
-
];
|
|
3877
|
-
function isValidEvidenceType(type) {
|
|
3878
|
-
return VALID_EVIDENCE_TYPES.includes(type);
|
|
3879
|
-
}
|
|
3880
|
-
function isSecretscanEvidence(evidence) {
|
|
3881
|
-
return evidence.type === "secretscan";
|
|
3882
|
-
}
|
|
3883
|
-
var sanitizeTaskId2 = sanitizeTaskId;
|
|
3884
|
-
function validateProjectRoot(directory) {
|
|
3885
|
-
assertProjectRoot(directory, {
|
|
3886
|
-
realpathSync: _internals7.realpathSync,
|
|
3887
|
-
statSync: _internals7.statSync
|
|
3888
|
-
}, "evidence");
|
|
3889
|
-
}
|
|
3890
|
-
async function saveEvidence(directory, taskId, evidence, abortSignal) {
|
|
3891
|
-
abortSignal?.throwIfAborted();
|
|
3892
|
-
_internals7.validateProjectRoot(directory);
|
|
3893
|
-
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
3894
|
-
const relativePath = path5.join("evidence", sanitizedTaskId, "evidence.json");
|
|
3895
|
-
validateSwarmPath(directory, relativePath);
|
|
3896
|
-
_internals7.validateEvidence(evidence);
|
|
3897
|
-
return withEvidenceLock(directory, relativePath, "evidence-manager", sanitizedTaskId, async () => {
|
|
3898
|
-
abortSignal?.throwIfAborted();
|
|
3899
|
-
const evidencePath = validateSwarmPath(directory, relativePath);
|
|
3900
|
-
const evidenceDir = path5.dirname(evidencePath);
|
|
3901
|
-
let bundle;
|
|
3902
|
-
const existingContent = await readSwarmFileAsync(directory, relativePath);
|
|
3903
|
-
abortSignal?.throwIfAborted();
|
|
3904
|
-
if (existingContent !== null) {
|
|
3905
|
-
try {
|
|
3906
|
-
const parsed = JSON.parse(existingContent);
|
|
3907
|
-
bundle = EvidenceBundleSchema.parse(parsed);
|
|
3908
|
-
} catch (error2) {
|
|
3909
|
-
warn(`Existing evidence bundle invalid for task ${sanitizedTaskId}, creating new: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
3910
|
-
const now = new Date().toISOString();
|
|
3911
|
-
bundle = {
|
|
3912
|
-
schema_version: "1.0.0",
|
|
3913
|
-
task_id: sanitizedTaskId,
|
|
3914
|
-
entries: [],
|
|
3915
|
-
created_at: now,
|
|
3916
|
-
updated_at: now
|
|
3917
|
-
};
|
|
3918
|
-
}
|
|
3919
|
-
} else {
|
|
3920
|
-
const now = new Date().toISOString();
|
|
3921
|
-
bundle = {
|
|
3922
|
-
schema_version: "1.0.0",
|
|
3923
|
-
task_id: sanitizedTaskId,
|
|
3924
|
-
entries: [],
|
|
3925
|
-
created_at: now,
|
|
3926
|
-
updated_at: now
|
|
3927
|
-
};
|
|
3928
|
-
}
|
|
3929
|
-
const MAX_BUNDLE_ENTRIES = 100;
|
|
3930
|
-
let entries = [...bundle.entries, evidence];
|
|
3931
|
-
if (entries.length > MAX_BUNDLE_ENTRIES) {
|
|
3932
|
-
entries = entries.slice(entries.length - MAX_BUNDLE_ENTRIES);
|
|
3933
|
-
}
|
|
3934
|
-
const updatedBundle = {
|
|
3935
|
-
...bundle,
|
|
3936
|
-
entries,
|
|
3937
|
-
updated_at: new Date().toISOString()
|
|
3938
|
-
};
|
|
3939
|
-
const bundleJson = JSON.stringify(updatedBundle);
|
|
3940
|
-
if (bundleJson.length > EVIDENCE_MAX_JSON_BYTES) {
|
|
3941
|
-
throw new Error(`Evidence bundle size (${bundleJson.length} bytes) exceeds maximum (${EVIDENCE_MAX_JSON_BYTES} bytes)`);
|
|
3942
|
-
}
|
|
3943
|
-
mkdirSync3(evidenceDir, { recursive: true });
|
|
3944
|
-
const tempPath = path5.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
|
|
3945
|
-
try {
|
|
3946
|
-
await bunWrite(tempPath, bundleJson);
|
|
3947
|
-
abortSignal?.throwIfAborted();
|
|
3948
|
-
renameSync3(tempPath, evidencePath);
|
|
3949
|
-
} catch (error2) {
|
|
3950
|
-
try {
|
|
3951
|
-
rmSync(tempPath, { force: true });
|
|
3952
|
-
} catch {}
|
|
3953
|
-
throw error2;
|
|
3954
|
-
}
|
|
3955
|
-
invalidateCachedArtifact(evidencePath);
|
|
3956
|
-
return updatedBundle;
|
|
3957
|
-
});
|
|
3958
|
-
}
|
|
3959
|
-
function isFlatRetrospective(parsed) {
|
|
3960
|
-
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && parsed.type === "retrospective" && !parsed.schema_version;
|
|
3961
|
-
}
|
|
3962
|
-
var LEGACY_TASK_COMPLEXITY_MAP = {
|
|
3963
|
-
low: "simple",
|
|
3964
|
-
medium: "moderate",
|
|
3965
|
-
high: "complex"
|
|
3966
|
-
};
|
|
3967
|
-
function remapLegacyTaskComplexity(entry) {
|
|
3968
|
-
const taskComplexity = entry.task_complexity;
|
|
3969
|
-
if (typeof taskComplexity === "string" && taskComplexity in LEGACY_TASK_COMPLEXITY_MAP) {
|
|
3970
|
-
return {
|
|
3971
|
-
...entry,
|
|
3972
|
-
task_complexity: LEGACY_TASK_COMPLEXITY_MAP[taskComplexity]
|
|
3973
|
-
};
|
|
3974
|
-
}
|
|
3975
|
-
return entry;
|
|
3976
|
-
}
|
|
3977
|
-
function wrapFlatRetrospective(flatEntry, taskId) {
|
|
3978
|
-
const now = new Date().toISOString();
|
|
3979
|
-
const remappedEntry = remapLegacyTaskComplexity(flatEntry);
|
|
3980
|
-
return {
|
|
3981
|
-
schema_version: "1.0.0",
|
|
3982
|
-
task_id: remappedEntry.task_id ?? taskId,
|
|
3983
|
-
created_at: remappedEntry.timestamp ?? now,
|
|
3984
|
-
updated_at: remappedEntry.timestamp ?? now,
|
|
3985
|
-
entries: [remappedEntry]
|
|
3986
|
-
};
|
|
3987
|
-
}
|
|
3988
|
-
async function loadEvidence(directory, taskId, options) {
|
|
3989
|
-
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
3990
|
-
const relativePath = path5.join("evidence", sanitizedTaskId, "evidence.json");
|
|
3991
|
-
if (relativePath.length > 4096) {
|
|
3992
|
-
return { status: "not_found" };
|
|
3993
|
-
}
|
|
3994
|
-
const evidencePath = validateSwarmPath(directory, relativePath);
|
|
3995
|
-
const content = await readSwarmFileAsync(directory, relativePath);
|
|
3996
|
-
if (content === null) {
|
|
3997
|
-
return { status: "not_found" };
|
|
3998
|
-
}
|
|
3999
|
-
let parsed;
|
|
4000
|
-
try {
|
|
4001
|
-
parsed = JSON.parse(content);
|
|
4002
|
-
} catch {
|
|
4003
|
-
return { status: "invalid_schema", errors: ["Invalid JSON"] };
|
|
4004
|
-
}
|
|
4005
|
-
if (isFlatRetrospective(parsed)) {
|
|
4006
|
-
const wrappedBundle = _internals7.wrapFlatRetrospective(parsed, sanitizedTaskId);
|
|
4007
|
-
try {
|
|
4008
|
-
const validated = EvidenceBundleSchema.parse(wrappedBundle);
|
|
4009
|
-
if (options?.migrate === false) {
|
|
4010
|
-
return { status: "found", bundle: validated };
|
|
4011
|
-
}
|
|
4012
|
-
try {
|
|
4013
|
-
validateProjectRoot(directory);
|
|
4014
|
-
await withEvidenceLock(directory, relativePath, "evidence-loader", sanitizedTaskId, async () => {
|
|
4015
|
-
const evidenceDir = path5.dirname(evidencePath);
|
|
4016
|
-
const bundleJson = JSON.stringify(validated);
|
|
4017
|
-
const tempPath = path5.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
|
|
4018
|
-
try {
|
|
4019
|
-
await bunWrite(tempPath, bundleJson);
|
|
4020
|
-
await fs5.rename(tempPath, evidencePath);
|
|
4021
|
-
invalidateCachedArtifact(evidencePath);
|
|
4022
|
-
} catch (writeError) {
|
|
4023
|
-
try {
|
|
4024
|
-
rmSync(tempPath, { force: true });
|
|
4025
|
-
} catch {}
|
|
4026
|
-
warn(`Failed to persist repaired flat retrospective for task ${sanitizedTaskId}: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
4027
|
-
}
|
|
4028
|
-
});
|
|
4029
|
-
} catch (lockErr) {
|
|
4030
|
-
warn(`Evidence lock failed during flat-retrospective write-back for task ${sanitizedTaskId}: ${lockErr instanceof Error ? lockErr.message : String(lockErr)}`);
|
|
4031
|
-
}
|
|
4032
|
-
return { status: "found", bundle: validated };
|
|
4033
|
-
} catch (error2) {
|
|
4034
|
-
warn(`Wrapped flat retrospective failed validation for task ${sanitizedTaskId}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
4035
|
-
const errors = error2 instanceof ZodError ? error2.issues.map((e) => `${e.path.join(".")}: ${e.message}`) : [error2 instanceof Error ? error2.message : String(error2)];
|
|
4036
|
-
return { status: "invalid_schema", errors };
|
|
4037
|
-
}
|
|
4038
|
-
}
|
|
4039
|
-
try {
|
|
4040
|
-
const validated = EvidenceBundleSchema.parse(parsed);
|
|
4041
|
-
return { status: "found", bundle: validated };
|
|
4042
|
-
} catch (error2) {
|
|
4043
|
-
warn(`Evidence bundle validation failed for task ${sanitizedTaskId}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
4044
|
-
const errors = error2 instanceof ZodError ? error2.issues.map((e) => `${e.path.join(".")}: ${e.message}`) : [error2 instanceof Error ? error2.message : String(error2)];
|
|
4045
|
-
return { status: "invalid_schema", errors };
|
|
4046
|
-
}
|
|
4047
|
-
}
|
|
4048
|
-
async function listEvidenceTaskIds(directory) {
|
|
4049
|
-
const evidenceBasePath = validateSwarmPath(directory, "evidence");
|
|
4050
|
-
try {
|
|
4051
|
-
statSync2(evidenceBasePath);
|
|
4052
|
-
} catch {
|
|
4053
|
-
return [];
|
|
4054
|
-
}
|
|
4055
|
-
let entries;
|
|
4056
|
-
try {
|
|
4057
|
-
entries = readdirSync(evidenceBasePath);
|
|
4058
|
-
} catch {
|
|
4059
|
-
return [];
|
|
4060
|
-
}
|
|
4061
|
-
const taskIds = [];
|
|
4062
|
-
for (const entry of entries) {
|
|
4063
|
-
const entryPath = path5.join(evidenceBasePath, entry);
|
|
4064
|
-
try {
|
|
4065
|
-
const stats = statSync2(entryPath);
|
|
4066
|
-
if (!stats.isDirectory()) {
|
|
4067
|
-
continue;
|
|
4068
|
-
}
|
|
4069
|
-
sanitizeTaskId2(entry);
|
|
4070
|
-
taskIds.push(entry);
|
|
4071
|
-
} catch (error2) {
|
|
4072
|
-
if (error2 instanceof Error && !error2.message.startsWith("Invalid task ID")) {
|
|
4073
|
-
warn(`Error reading evidence entry '${entry}': ${error2.message}`);
|
|
4074
|
-
}
|
|
4075
|
-
}
|
|
4076
|
-
}
|
|
4077
|
-
return taskIds.sort();
|
|
4078
|
-
}
|
|
4079
|
-
async function deleteEvidence(directory, taskId) {
|
|
4080
|
-
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
4081
|
-
try {
|
|
4082
|
-
validateProjectRoot(directory);
|
|
4083
|
-
} catch {
|
|
4084
|
-
return false;
|
|
4085
|
-
}
|
|
4086
|
-
const relativePath = path5.join("evidence", sanitizedTaskId);
|
|
4087
|
-
const evidenceDir = validateSwarmPath(directory, relativePath);
|
|
4088
|
-
try {
|
|
4089
|
-
statSync2(evidenceDir);
|
|
4090
|
-
} catch {
|
|
4091
|
-
return false;
|
|
4092
|
-
}
|
|
4093
|
-
try {
|
|
4094
|
-
rmSync(evidenceDir, { recursive: true, force: true });
|
|
4095
|
-
return true;
|
|
4096
|
-
} catch (error2) {
|
|
4097
|
-
warn(`Failed to delete evidence for task ${sanitizedTaskId}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
4098
|
-
return false;
|
|
4099
|
-
}
|
|
4100
|
-
}
|
|
4101
|
-
async function checkRequirementCoverage(phase, directory) {
|
|
4102
|
-
const relativePath = path5.join("evidence", `req-coverage-phase-${phase}.json`);
|
|
4103
|
-
const absolutePath = path5.resolve(directory, ".swarm", relativePath);
|
|
4104
|
-
try {
|
|
4105
|
-
await fs5.access(absolutePath);
|
|
4106
|
-
return { exists: true, path: absolutePath };
|
|
4107
|
-
} catch {
|
|
4108
|
-
return { exists: false, path: absolutePath };
|
|
4109
|
-
}
|
|
4110
|
-
}
|
|
4111
|
-
async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
|
|
4112
|
-
const taskIds = await _internals7.listEvidenceTaskIds(directory);
|
|
4113
|
-
const cutoffDate = options?.now ? new Date(options.now) : _internals7.now();
|
|
4114
|
-
cutoffDate.setDate(cutoffDate.getDate() - maxAgeDays);
|
|
4115
|
-
const cutoffIso = cutoffDate.toISOString();
|
|
4116
|
-
const selected = new Set;
|
|
4117
|
-
const selectedByAge = new Set;
|
|
4118
|
-
const selectedByCount = new Set;
|
|
4119
|
-
const archived = [];
|
|
4120
|
-
const failed = [];
|
|
4121
|
-
const remainingBundles = [];
|
|
4122
|
-
for (const taskId of taskIds) {
|
|
4123
|
-
let result;
|
|
4124
|
-
try {
|
|
4125
|
-
result = await _internals7.loadEvidence(directory, taskId);
|
|
4126
|
-
} catch {
|
|
4127
|
-
warn("archive: skipping corrupt or unreadable evidence for task", taskId);
|
|
4128
|
-
continue;
|
|
4129
|
-
}
|
|
4130
|
-
if (result.status !== "found") {
|
|
4131
|
-
continue;
|
|
4132
|
-
}
|
|
4133
|
-
if (result.bundle.updated_at < cutoffIso) {
|
|
4134
|
-
selected.add(taskId);
|
|
4135
|
-
selectedByAge.add(taskId);
|
|
4136
|
-
} else {
|
|
4137
|
-
remainingBundles.push({
|
|
4138
|
-
taskId,
|
|
4139
|
-
updatedAt: result.bundle.updated_at
|
|
4140
|
-
});
|
|
4141
|
-
}
|
|
4142
|
-
}
|
|
4143
|
-
if (maxBundles !== undefined && remainingBundles.length > maxBundles) {
|
|
4144
|
-
remainingBundles.sort((a, b) => a.updatedAt.localeCompare(b.updatedAt));
|
|
4145
|
-
const toDelete = remainingBundles.length - maxBundles;
|
|
4146
|
-
for (let i = 0;i < toDelete; i++) {
|
|
4147
|
-
selected.add(remainingBundles[i].taskId);
|
|
4148
|
-
selectedByCount.add(remainingBundles[i].taskId);
|
|
4149
|
-
}
|
|
4150
|
-
}
|
|
4151
|
-
if (!options?.dryRun) {
|
|
4152
|
-
for (const taskId of [...selected].sort()) {
|
|
4153
|
-
const deleted = await _internals7.deleteEvidence(directory, taskId);
|
|
4154
|
-
if (deleted)
|
|
4155
|
-
archived.push(taskId);
|
|
4156
|
-
else
|
|
4157
|
-
failed.push(taskId);
|
|
4158
|
-
}
|
|
4159
|
-
}
|
|
4160
|
-
const evaluation = await archiveEvaluationArtifacts({
|
|
4161
|
-
directory,
|
|
4162
|
-
maxAgeDays,
|
|
4163
|
-
maxBundles,
|
|
4164
|
-
dryRun: options?.dryRun,
|
|
4165
|
-
now: options?.now
|
|
4166
|
-
});
|
|
4167
|
-
let documentsCache = {
|
|
4168
|
-
inventory: 0,
|
|
4169
|
-
selected: 0,
|
|
4170
|
-
archived: 0,
|
|
4171
|
-
corrupt: 0,
|
|
4172
|
-
bytesBefore: 0,
|
|
4173
|
-
bytesAfter: 0,
|
|
4174
|
-
dryRun: options?.dryRun === true,
|
|
4175
|
-
aborted: false
|
|
4176
|
-
};
|
|
4177
|
-
if (typeof options?.cacheMaxBytes === "number" && options.cacheMaxBytes > 0 || typeof options?.cacheMaxRecords === "number" && options.cacheMaxRecords > 0) {
|
|
4178
|
-
try {
|
|
4179
|
-
documentsCache = await _internals7.pruneEvidenceDocuments({
|
|
4180
|
-
directory,
|
|
4181
|
-
maxBytes: options?.cacheMaxBytes,
|
|
4182
|
-
maxRecords: options?.cacheMaxRecords,
|
|
4183
|
-
dryRun: options?.dryRun
|
|
4184
|
-
});
|
|
4185
|
-
} catch (error2) {
|
|
4186
|
-
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
4187
|
-
warn(`archiveEvidence: documents-cache prune failed (fail-open): ${msg}`);
|
|
4188
|
-
}
|
|
4189
|
-
}
|
|
4190
|
-
if (options?.report) {
|
|
4191
|
-
return {
|
|
4192
|
-
inventoryEvidence: [...taskIds].sort(),
|
|
4193
|
-
selectedEvidence: [...selected].sort(),
|
|
4194
|
-
selectedEvidenceByAge: [...selectedByAge].sort(),
|
|
4195
|
-
selectedEvidenceByCount: [...selectedByCount].sort(),
|
|
4196
|
-
archivedEvidence: archived.sort(),
|
|
4197
|
-
failedEvidence: failed.sort(),
|
|
4198
|
-
evaluation,
|
|
4199
|
-
documentsCache
|
|
4200
|
-
};
|
|
4201
|
-
}
|
|
4202
|
-
return archived.sort();
|
|
4203
|
-
}
|
|
4204
|
-
function validateEvidence(evidence) {
|
|
4205
|
-
return EvidenceSchema.parse(evidence);
|
|
4206
|
-
}
|
|
4207
|
-
var _internals7 = {
|
|
4208
|
-
wrapFlatRetrospective,
|
|
4209
|
-
loadEvidence,
|
|
4210
|
-
listEvidenceTaskIds,
|
|
4211
|
-
validateProjectRoot,
|
|
4212
|
-
validateEvidence,
|
|
4213
|
-
saveEvidence,
|
|
4214
|
-
deleteEvidence,
|
|
4215
|
-
pruneEvidenceDocuments,
|
|
4216
|
-
realpathSync,
|
|
4217
|
-
statSync: statSync2,
|
|
4218
|
-
now: () => new Date
|
|
4219
|
-
};
|
|
4220
|
-
|
|
4221
|
-
// src/evidence/gate-bridge.ts
|
|
4222
|
-
var GATE_EVIDENCE_TYPE_BY_GATE = {
|
|
4223
|
-
reviewer: "review",
|
|
4224
|
-
test_engineer: "test"
|
|
4225
|
-
};
|
|
4226
|
-
async function readDurableGateEvidence(directory, taskId) {
|
|
4227
|
-
try {
|
|
4228
|
-
return await readTaskEvidence(directory, taskId);
|
|
4229
|
-
} catch {
|
|
4230
|
-
return null;
|
|
4231
|
-
}
|
|
4232
|
-
}
|
|
4233
|
-
function getDurableGateEvidenceStatus(evidence) {
|
|
4234
|
-
if (!evidence?.gates || typeof evidence.gates !== "object") {
|
|
4235
|
-
return {
|
|
4236
|
-
isComplete: false,
|
|
4237
|
-
missingGates: [],
|
|
4238
|
-
evidenceExists: evidence != null,
|
|
4239
|
-
invalid: false
|
|
4240
|
-
};
|
|
4241
|
-
}
|
|
4242
|
-
if (!Array.isArray(evidence.required_gates)) {
|
|
4243
|
-
return {
|
|
4244
|
-
isComplete: false,
|
|
4245
|
-
missingGates: ["required_gates"],
|
|
4246
|
-
evidenceExists: true,
|
|
4247
|
-
invalid: false
|
|
4248
|
-
};
|
|
4249
|
-
}
|
|
4250
|
-
const derivedGates = deriveApplicableGateSet(evidence);
|
|
4251
|
-
return {
|
|
4252
|
-
isComplete: derivedGates.missingGates.length === 0,
|
|
4253
|
-
missingGates: derivedGates.missingGates,
|
|
4254
|
-
evidenceExists: true,
|
|
4255
|
-
invalid: false
|
|
4256
|
-
};
|
|
4257
|
-
}
|
|
4258
|
-
async function getDurableGateEvidenceStatusForTask(directory, taskId) {
|
|
4259
|
-
if (!isValidTaskId(taskId)) {
|
|
4260
|
-
return {
|
|
4261
|
-
isComplete: false,
|
|
4262
|
-
missingGates: [],
|
|
4263
|
-
evidenceExists: false,
|
|
4264
|
-
invalid: false
|
|
4265
|
-
};
|
|
4266
|
-
}
|
|
4267
|
-
try {
|
|
4268
|
-
return getDurableGateEvidenceStatusWithCurrentScope(readTaskEvidenceRaw(directory, taskId), directory, taskId);
|
|
4269
|
-
} catch {
|
|
4270
|
-
return {
|
|
4271
|
-
isComplete: false,
|
|
4272
|
-
missingGates: ["invalid_gate_evidence"],
|
|
4273
|
-
evidenceExists: true,
|
|
4274
|
-
invalid: true
|
|
4275
|
-
};
|
|
4276
|
-
}
|
|
4277
|
-
}
|
|
4278
|
-
function getDurableGateEvidenceStatusWithCurrentScope(evidence, directory, taskId) {
|
|
4279
|
-
if (!evidence?.gates || typeof evidence.gates !== "object") {
|
|
4280
|
-
return getDurableGateEvidenceStatus(evidence);
|
|
4281
|
-
}
|
|
4282
|
-
if (!Array.isArray(evidence.required_gates)) {
|
|
4283
|
-
return getDurableGateEvidenceStatus(evidence);
|
|
4284
|
-
}
|
|
4285
|
-
if (!evidence.workflow || evidence.workflow.schema !== TASK_WORKFLOW_SCHEMA_MARKER) {
|
|
4286
|
-
if (evidence.required_gates.length === 0) {
|
|
4287
|
-
return {
|
|
4288
|
-
isComplete: false,
|
|
4289
|
-
missingGates: ["required_gates"],
|
|
4290
|
-
evidenceExists: true,
|
|
4291
|
-
invalid: false
|
|
4292
|
-
};
|
|
4293
|
-
}
|
|
4294
|
-
const missingGates = evidence.required_gates.filter((gate) => evidence.gates[gate] == null);
|
|
4295
|
-
return {
|
|
4296
|
-
isComplete: missingGates.length === 0,
|
|
4297
|
-
missingGates,
|
|
4298
|
-
evidenceExists: true,
|
|
4299
|
-
invalid: false
|
|
4300
|
-
};
|
|
4301
|
-
}
|
|
4302
|
-
const derivedGates = deriveApplicableGateSet(evidence, {
|
|
4303
|
-
currentDeclaredFiles: readCurrentTaskDeclaredFiles(directory, taskId)
|
|
4304
|
-
});
|
|
4305
|
-
return {
|
|
4306
|
-
isComplete: derivedGates.missingGates.length === 0,
|
|
4307
|
-
missingGates: derivedGates.missingGates,
|
|
4308
|
-
evidenceExists: true,
|
|
4309
|
-
invalid: false
|
|
4310
|
-
};
|
|
4311
|
-
}
|
|
4312
|
-
function gateEvidenceToEntry(taskId, gate, type, evidence) {
|
|
4313
|
-
const gateRecord = evidence.gates[gate];
|
|
4314
|
-
if (!gateRecord) {
|
|
4315
|
-
return null;
|
|
4316
|
-
}
|
|
4317
|
-
const base = {
|
|
4318
|
-
task_id: taskId,
|
|
4319
|
-
timestamp: gateRecord.timestamp,
|
|
4320
|
-
agent: gateRecord.agent || gate,
|
|
4321
|
-
verdict: "pass",
|
|
4322
|
-
summary: `Gate evidence recorded by ${gate}`,
|
|
4323
|
-
metadata: { source: "durable_gate_evidence", gate }
|
|
4324
|
-
};
|
|
4325
|
-
if (type === "review") {
|
|
4326
|
-
return {
|
|
4327
|
-
...base,
|
|
4328
|
-
type,
|
|
4329
|
-
risk: "low",
|
|
4330
|
-
issues: []
|
|
4331
|
-
};
|
|
4332
|
-
}
|
|
4333
|
-
if (type === "approval") {
|
|
4334
|
-
return {
|
|
4335
|
-
...base,
|
|
4336
|
-
type
|
|
4337
|
-
};
|
|
4338
|
-
}
|
|
4339
|
-
return {
|
|
4340
|
-
...base,
|
|
4341
|
-
type,
|
|
4342
|
-
tests_passed: 0,
|
|
4343
|
-
tests_failed: 0,
|
|
4344
|
-
failures: []
|
|
4345
|
-
};
|
|
4346
|
-
}
|
|
4347
|
-
function mergeDurableGateEntriesFromEvidence(taskId, entries, evidence) {
|
|
4348
|
-
if (!evidence?.gates) {
|
|
4349
|
-
return entries;
|
|
4350
|
-
}
|
|
4351
|
-
const merged = [...entries];
|
|
4352
|
-
for (const gate of Object.keys(evidence.gates).sort()) {
|
|
4353
|
-
const type = GATE_EVIDENCE_TYPE_BY_GATE[gate] ?? "approval";
|
|
4354
|
-
if ((type === "review" || type === "test") && merged.some((entry2) => entry2.type === type)) {
|
|
4355
|
-
continue;
|
|
4356
|
-
}
|
|
4357
|
-
const entry = gateEvidenceToEntry(taskId, gate, type, evidence);
|
|
4358
|
-
if (entry) {
|
|
4359
|
-
merged.push(entry);
|
|
4360
|
-
}
|
|
4361
|
-
}
|
|
4362
|
-
return merged;
|
|
4363
|
-
}
|
|
4364
|
-
|
|
4365
|
-
export { buildTaskCompletionDescriptor, ensureTaskCheckpointReceipt, updateTaskCheckpointReceipt, MAX_TRANSIENT_RETRIES, isTransientSpawnError, transientBackoff, readLaneEnvFileFromDiskSync, getGitRepositoryStatus, isGitRepo, getDefaultBaseBranch, detectDefaultRemoteBranch, resetToRemoteBranch, resetToMainAfterMerge, sanitizeContextText, getRunMemorySummary, isStateUnreadable, loadEpicSessionState, isEpicModeActive, enableEpicMode, disableEpicMode, PlanRecoverySupersededError, loadPlanJsonOnly, loadPlan, withPlanLifecycleLock, savePlan, closePlanTerminalState, updateTaskStatus, derivePlanMarkdown, getCurrentTaskId, isValidEvidenceType, isSecretscanEvidence, sanitizeTaskId2 as sanitizeTaskId, validateProjectRoot, saveEvidence, loadEvidence, listEvidenceTaskIds, checkRequirementCoverage, archiveEvidence, _internals7 as _internals, readDurableGateEvidence, getDurableGateEvidenceStatusForTask, mergeDurableGateEntriesFromEvidence };
|
|
3449
|
+
export { buildTaskCompletionDescriptor, ensureTaskCheckpointReceipt, updateTaskCheckpointReceipt, MAX_TRANSIENT_RETRIES, isTransientSpawnError, transientBackoff, readLaneEnvFileFromDiskSync, getGitRepositoryStatus, isGitRepo, getDefaultBaseBranch, detectDefaultRemoteBranch, resetToRemoteBranch, resetToMainAfterMerge, sanitizeContextText, getRunMemorySummary, isStateUnreadable, loadEpicSessionState, isEpicModeActive, enableEpicMode, disableEpicMode, PlanRecoverySupersededError, loadPlanJsonOnly, loadPlan, withPlanLifecycleLock, savePlan, closePlanTerminalState, updateTaskStatus, derivePlanMarkdown, getCurrentTaskId };
|