opencode-swarm 7.184.10 → 7.184.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +26 -24
  2. package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
  3. package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
  4. package/dist/background/delegation-lifecycle.d.ts +6 -2
  5. package/dist/background/pending-delegations.d.ts +23 -1
  6. package/dist/cli/auto-checkpoint-7y3x5cv2.js +183 -0
  7. package/dist/cli/checkpoint-j39f718z.js +51 -0
  8. package/dist/cli/{coder-settlement-b47vmcm9.js → coder-settlement-12ytzqvs.js} +13 -11
  9. package/dist/cli/{config-doctor-3j3m2ccc.js → config-doctor-vphp4shw.js} +2 -2
  10. package/dist/cli/{core-td5kj2w8.js → core-5a1awn37.js} +3 -3
  11. package/dist/cli/{curation-policy-xe77n9zj.js → curation-policy-1rzheh1x.js} +6 -5
  12. package/dist/cli/{curator-drift-wxyhgz7y.js → curator-drift-ex0qxt9p.js} +9 -9
  13. package/dist/cli/curator-llm-factory-ktkat73z.js +81 -0
  14. package/dist/cli/{curator-c7we2apv.js → curator-x2hxjdac.js} +48 -42
  15. package/dist/cli/{dispatch-cv89p2y1.js → dispatch-0ejzwb45.js} +2 -1
  16. package/dist/cli/{evidence-summary-service-2t1ttdgj.js → evidence-summary-service-pfksvp16.js} +24 -19
  17. package/dist/cli/{gate-evidence-5w2q1h5w.js → gate-evidence-8n8kb8tb.js} +8 -6
  18. package/dist/cli/guardrail-explain-px94swcz.js +82 -0
  19. package/dist/cli/{guardrail-log-5zwqdhaf.js → guardrail-log-xevw9xht.js} +7 -7
  20. package/dist/cli/{guardrail-reset-qnq1swzf.js → guardrail-reset-18wvqbga.js} +48 -42
  21. package/dist/cli/hive-promoter-5r35f3ap.js +96 -0
  22. package/dist/cli/{index-260174fq.js → index-27wzbb3n.js} +4 -4
  23. package/dist/cli/{index-b6saxkqj.js → index-2cbt4b7t.js} +2 -2
  24. package/dist/cli/{index-tzyppdv7.js → index-2p1an48j.js} +3 -3
  25. package/dist/cli/index-2y9b45jj.js +24 -0
  26. package/dist/cli/index-34ysgky0.js +954 -0
  27. package/dist/cli/{index-1g2bm6ht.js → index-39ng38sp.js} +1 -1
  28. package/dist/cli/{index-hk0eh9qb.js → index-4g4sr4ah.js} +1 -1
  29. package/dist/cli/{index-cjh92zm9.js → index-53fy0aq2.js} +52 -46
  30. package/dist/cli/{index-7849gy4s.js → index-5w404j07.js} +8 -6
  31. package/dist/cli/index-5y1qxw0x.js +963 -0
  32. package/dist/cli/{index-35cdceqf.js → index-6cjpmvpa.js} +2 -20
  33. package/dist/cli/{index-yyvkeev1.js → index-74e43s33.js} +4 -4
  34. package/dist/cli/index-7bxssqaf.js +2676 -0
  35. package/dist/cli/index-7pmbnjvj.js +11 -0
  36. package/dist/cli/{index-j4efx148.js → index-7r3pkgma.js} +5 -5
  37. package/dist/cli/{index-kg2mb1m5.js → index-7rzgdcvc.js} +2 -2
  38. package/dist/cli/{index-hamqvzqn.js → index-9nyqt3kb.js} +10 -2682
  39. package/dist/cli/{index-hs26e3k6.js → index-a53f5t61.js} +2 -2
  40. package/dist/cli/{index-ta2kp4xy.js → index-azyhws0s.js} +9 -9
  41. package/dist/cli/{index-0mj7hc2z.js → index-bntwj2tp.js} +5 -5
  42. package/dist/cli/{index-aae38s4x.js → index-cftva3pa.js} +2 -11
  43. package/dist/cli/{index-8n2dh26k.js → index-cvam011t.js} +1 -1
  44. package/dist/cli/{index-3rfc2v1d.js → index-d42kjvwy.js} +2 -2
  45. package/dist/cli/{index-gnryhmak.js → index-dftztz4y.js} +1 -1
  46. package/dist/cli/{index-45h58v8d.js → index-dze05t9h.js} +7 -7
  47. package/dist/cli/{index-54f1payv.js → index-eqfmabtd.js} +2 -2
  48. package/dist/cli/{index-4szb7qpv.js → index-fbp7dqfe.js} +10 -38
  49. package/dist/cli/{index-0ajyhjht.js → index-fxf3zhtq.js} +1 -1
  50. package/dist/cli/index-g4fs6z4e.js +37 -0
  51. package/dist/cli/{index-bt1k1ek3.js → index-hfs97j0c.js} +1 -1
  52. package/dist/cli/{index-nh5fxxc9.js → index-jtg0zsnx.js} +4 -2
  53. package/dist/cli/{index-9jz73x8x.js → index-kcbkce43.js} +48 -42
  54. package/dist/cli/{index-07fqfseh.js → index-m1pqenq9.js} +2 -2
  55. package/dist/cli/{index-be5h97z8.js → index-mfqge140.js} +1 -1
  56. package/dist/cli/{index-3wgvpxmv.js → index-n572fdtf.js} +2969 -3838
  57. package/dist/cli/{index-5m1b70z3.js → index-pwcbtbhd.js} +4 -4
  58. package/dist/cli/{index-95vytkv6.js → index-rbvndg2d.js} +3 -3
  59. package/dist/cli/{index-thcyqqdq.js → index-ryafwy2b.js} +1 -1
  60. package/dist/cli/{index-0d7e94zg.js → index-s7rap90y.js} +7 -7
  61. package/dist/cli/{index-q7q00ppx.js → index-tyzmjw2s.js} +7 -7
  62. package/dist/cli/{index-bhj3zx43.js → index-vk49btd6.js} +1 -1
  63. package/dist/cli/{index-fn1y9jpv.js → index-w33zgxn6.js} +3 -3
  64. package/dist/cli/{index-x1gyqgze.js → index-w6w6ny06.js} +2 -2
  65. package/dist/cli/{index-f336fv53.js → index-x0jybm74.js} +3 -3
  66. package/dist/cli/{index-pj877ads.js → index-ymhs7hng.js} +5 -5
  67. package/dist/cli/{index-19e61hgv.js → index-yvmvsej2.js} +55 -971
  68. package/dist/cli/{index-x119gdak.js → index-yx5z4200.js} +2 -2
  69. package/dist/cli/{index-dqpq8m9w.js → index-yydv4jfy.js} +2 -2
  70. package/dist/cli/{index-fxtgxe04.js → index-zmtpnyff.js} +8 -8
  71. package/dist/cli/{index-djnxehe7.js → index-zzebc1td.js} +44 -16
  72. package/dist/cli/index.js +49 -43
  73. package/dist/cli/{knowledge-escalator-912nwxb4.js → knowledge-escalator-z5qb6y6s.js} +13 -12
  74. package/dist/cli/{knowledge-events-hvzj872f.js → knowledge-events-gv173j4d.js} +11 -10
  75. package/dist/cli/{knowledge-link-8tetyje0.js → knowledge-link-vvyfhhmr.js} +5 -4
  76. package/dist/cli/{knowledge-store-sqx0axb6.js → knowledge-store-g4sjhep5.js} +6 -5
  77. package/dist/cli/{knowledge-validator-d8m7p2vg.js → knowledge-validator-8whkrsrb.js} +8 -7
  78. package/dist/cli/{mcp-nxxy0dq0.js → mcp-x25b3q1g.js} +1 -1
  79. package/dist/cli/{model-preflight-2mmep72y.js → model-preflight-b21njmda.js} +48 -42
  80. package/dist/cli/{pending-delegations-fat9r7w1.js → pending-delegations-f6rmrqzn.js} +16 -12
  81. package/dist/cli/{pr-subscriptions-8xv7gaeb.js → pr-subscriptions-nmbme4kp.js} +14 -12
  82. package/dist/cli/{pr-workflow-gate-g9exsspv.js → pr-workflow-gate-mtzfsmkg.js} +48 -42
  83. package/dist/cli/{runner-ff0bj9w0.js → runner-cwmgb9rw.js} +6 -5
  84. package/dist/cli/{scan-cursor-h9tza4z6.js → scan-cursor-gmpjsr3a.js} +7 -6
  85. package/dist/cli/{schema-1p9cw863.js → schema-rvxnxp4n.js} +1 -1
  86. package/dist/cli/{scope-persistence-xv6b7daq.js → scope-persistence-fqenprq7.js} +17 -15
  87. package/dist/cli/{server-z5401cje.js → server-ws1my2dz.js} +62 -54
  88. package/dist/cli/{skill-generator-72n07p92.js → skill-generator-pt1epeer.js} +15 -14
  89. package/dist/cli/{snapshot-coordination-init-xjyv8kxx.js → snapshot-coordination-init-9zrktnh5.js} +48 -42
  90. package/dist/cli/{speckit-checkoff-828xrjfd.js → speckit-checkoff-k13zhgh5.js} +4 -4
  91. package/dist/cli/{telemetry-39zmx4fp.js → telemetry-n6y2sjhg.js} +1 -1
  92. package/dist/cli/{workspace-snapshot-nrbvjh1c.js → workspace-snapshot-gnwak61t.js} +3 -3
  93. package/dist/cli/{worktree-collision-ownership-cr6vv3xk.js → worktree-collision-ownership-mw3rkc4v.js} +18 -16
  94. package/dist/cli/{worktree-isolation-6yycqkc6.js → worktree-isolation-0rtrpf0b.js} +48 -42
  95. package/dist/index.js +541 -541
  96. package/dist/plan/auto-checkpoint.d.ts +56 -0
  97. package/dist/plan/manager.d.ts +8 -12
  98. package/package.json +1 -1
  99. package/dist/cli/curator-llm-factory-1260n9ty.js +0 -75
  100. package/dist/cli/guardrail-explain-qeywnmza.js +0 -76
  101. package/dist/cli/hive-promoter-c3c6tz3b.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-8n2dh26k.js";
10
2
  import {
11
3
  validateWorkspaceRoot
12
4
  } from "./index-6b295cas.js";
5
+ import {
6
+ readEffectiveSpecSync
7
+ } from "./index-cvam011t.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
- isValidTaskId,
25
- readCurrentTaskDeclaredFiles,
26
- readTaskEvidence,
27
- readTaskEvidenceRaw,
28
- sanitizeTaskId
29
- } from "./index-4szb7qpv.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-gnryhmak.js";
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-ta2kp4xy.js";
47
+ } from "./index-azyhws0s.js";
65
48
  import {
66
49
  appendCoreEventSync
67
- } from "./index-kg2mb1m5.js";
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-aae38s4x.js";
56
+ } from "./index-cftva3pa.js";
76
57
  import {
77
58
  DURABILITY_CLASSES,
78
59
  getProjectDb,
79
60
  projectDbExists,
80
61
  withDurabilityClass
81
- } from "./index-5m1b70z3.js";
62
+ } from "./index-pwcbtbhd.js";
82
63
  import {
83
- withEvidenceLock
84
- } from "./index-35cdceqf.js";
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-x1gyqgze.js";
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-0mj7hc2z.js";
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-7y3x5cv2.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-828xrjfd.js");
3083
+ const { maybePropagateSpeckitCheckoff } = await import("./speckit-checkoff-k13zhgh5.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-xv6b7daq.js");
3108
+ const { readDeclaredScopeFilesFromBindings } = await import("./scope-persistence-fqenprq7.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
- // src/evidence/manager.ts
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 };