opencode-swarm 7.139.0 → 7.139.2

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 (90) hide show
  1. package/.opencode/skills/swarm-pr-review/SKILL.md +15 -0
  2. package/README.md +7 -6
  3. package/dist/cli/{config-doctor-aszp7z1h.js → config-doctor-hrb61yqe.js} +2 -2
  4. package/dist/cli/{core-3s832mxx.js → core-g2dfh9fq.js} +1 -1
  5. package/dist/cli/{curation-policy-a3hs73f7.js → curation-policy-4tp0mbcb.js} +7 -7
  6. package/dist/cli/{curator-drift-jpap6hv4.js → curator-drift-vfh07mqy.js} +5 -2
  7. package/dist/cli/{curator-llm-factory-e8ngwyjm.js → curator-llm-factory-hvw13hmr.js} +28 -28
  8. package/dist/cli/{curator-zxjqcc8r.js → curator-vpcs1p1v.js} +28 -28
  9. package/dist/cli/{evidence-summary-service-qfhjfxdz.js → evidence-summary-service-kzxr71yd.js} +9 -9
  10. package/dist/cli/{gate-evidence-m2grv70v.js → gate-evidence-z2b1ymnw.js} +5 -5
  11. package/dist/cli/{guardrail-explain-rqpmzxyy.js → guardrail-explain-k62h3c92.js} +29 -29
  12. package/dist/cli/{guardrail-log-vd4a0ng5.js → guardrail-log-2ftew0p3.js} +3 -3
  13. package/dist/cli/{hive-promoter-jc5vym27.js → hive-promoter-mpf0cfkk.js} +28 -28
  14. package/dist/cli/{index-4ft523nb.js → index-0wp67gqj.js} +143 -89
  15. package/dist/cli/{index-ymszzvnr.js → index-3eddtgxt.js} +1 -1
  16. package/dist/cli/{index-67yqywan.js → index-3radty3f.js} +2 -2
  17. package/dist/cli/{index-p2dz85tv.js → index-4xbyy6aw.js} +2 -2
  18. package/dist/cli/{index-a614s16f.js → index-5j6chvj8.js} +1 -1
  19. package/dist/cli/{index-tcdcj1g2.js → index-5w7ekpy3.js} +2 -2
  20. package/dist/cli/{index-nbgw5dxa.js → index-5zyk8qgv.js} +2 -2
  21. package/dist/cli/{index-tyh0p5e8.js → index-668dpw5e.js} +1 -1
  22. package/dist/cli/{index-6q240xgm.js → index-6c5f309q.js} +2 -2
  23. package/dist/cli/{index-s428dmy6.js → index-6w1re1qn.js} +2 -2
  24. package/dist/cli/{index-nsnfvckc.js → index-8gftfvpp.js} +1 -1
  25. package/dist/cli/{index-rtetrxxq.js → index-8p9pasnp.js} +8 -3
  26. package/dist/cli/{index-85hstja2.js → index-a12906mj.js} +1 -1
  27. package/dist/cli/{index-chvqee1j.js → index-a5eba0t8.js} +2 -2
  28. package/dist/cli/{index-r3pth9a7.js → index-a7nh382r.js} +508 -441
  29. package/dist/cli/{index-t31cc7kv.js → index-cyw81ngh.js} +7 -7
  30. package/dist/cli/{index-kv36s0x0.js → index-e9tx99ds.js} +6 -3
  31. package/dist/cli/{index-fsrp8wp3.js → index-ed5ykebp.js} +25 -2
  32. package/dist/cli/{index-0tsetsxs.js → index-ffpmqx30.js} +4 -4
  33. package/dist/cli/{index-nc544sfw.js → index-gvhvz176.js} +2 -2
  34. package/dist/cli/{index-3nr2sn32.js → index-ktagrqxw.js} +3 -3
  35. package/dist/cli/{index-t26nfmcs.js → index-prmb5qfp.js} +2 -2
  36. package/dist/cli/{index-q3qtgtd0.js → index-q11t5erh.js} +1 -1
  37. package/dist/cli/{index-x20cgr2q.js → index-q7ezzgwq.js} +16 -2
  38. package/dist/cli/{index-z1tkxzq4.js → index-s608d3hw.js} +2 -2
  39. package/dist/cli/{index-y46anh5e.js → index-se8xc78k.js} +30 -30
  40. package/dist/cli/{index-84s6x604.js → index-w71cq27a.js} +5 -5
  41. package/dist/cli/{index-ddmnhv4h.js → index-wrt6m5ze.js} +1 -1
  42. package/dist/cli/{index-4qzeef9h.js → index-x9q4bbhd.js} +1 -1
  43. package/dist/cli/{index-zd15ya1w.js → index-y47dwge1.js} +1 -1
  44. package/dist/cli/{index-5bkpyvdf.js → index-y64jv2pe.js} +1 -1
  45. package/dist/cli/{index-gytyqv1d.js → index-yr6x707c.js} +2 -2
  46. package/dist/cli/index.js +28 -28
  47. package/dist/cli/{knowledge-escalator-6473ey4c.js → knowledge-escalator-n9pmx4qr.js} +8 -8
  48. package/dist/cli/{knowledge-events-wwzpz8m4.js → knowledge-events-raevm18w.js} +6 -6
  49. package/dist/cli/{knowledge-link-trfydkzm.js → knowledge-link-3tq8w6gs.js} +5 -5
  50. package/dist/cli/{knowledge-store-99gd42jy.js → knowledge-store-bcfqz8fr.js} +6 -6
  51. package/dist/cli/{knowledge-validator-v2eevvdg.js → knowledge-validator-jxqj96cx.js} +9 -9
  52. package/dist/cli/{pending-delegations-p6n83x67.js → pending-delegations-tmyf18p4.js} +5 -5
  53. package/dist/cli/{pr-subscriptions-xbrfr51c.js → pr-subscriptions-hhx6yk24.js} +5 -5
  54. package/dist/cli/{runner-9an52tmz.js → runner-w30gazew.js} +6 -6
  55. package/dist/cli/{scan-cursor-39zxpw34.js → scan-cursor-ah5swtyh.js} +7 -7
  56. package/dist/cli/{schema-xhfwr6b2.js → schema-f7jgrtxj.js} +3 -1
  57. package/dist/cli/{scope-persistence-nsa6ra9s.js → scope-persistence-3f0d4fwv.js} +4 -4
  58. package/dist/cli/{skill-generator-5px81476.js → skill-generator-hp7as46c.js} +10 -10
  59. package/dist/cli/{telemetry-7nt7zhyp.js → telemetry-4tgrfhaz.js} +1 -1
  60. package/dist/cli/{worktree-collision-ownership-9x4s4890.js → worktree-collision-ownership-vexb0b6r.js} +38 -8
  61. package/dist/config/context-window.d.ts +210 -0
  62. package/dist/config/schema.d.ts +18 -0
  63. package/dist/evaluation/ephemeral-agent-dispatcher.d.ts +18 -0
  64. package/dist/evaluation/model-dispatcher.d.ts +1 -0
  65. package/dist/hooks/delegate-ack-collector.d.ts +1 -1
  66. package/dist/hooks/delegation-gate/worktree-collision-ownership.d.ts +7 -0
  67. package/dist/hooks/delegation-gate/worktree-isolation.d.ts +2 -1
  68. package/dist/hooks/delegation-gate/worktree-provisioning-owner.d.ts +6 -0
  69. package/dist/hooks/index.d.ts +2 -2
  70. package/dist/hooks/init-orphan-recovery.d.ts +4 -1
  71. package/dist/hooks/knowledge-application-gate.d.ts +2 -1
  72. package/dist/hooks/knowledge-application.d.ts +5 -4
  73. package/dist/hooks/knowledge-injector.d.ts +16 -0
  74. package/dist/hooks/knowledge-types.d.ts +1 -1
  75. package/dist/hooks/messages-transform.d.ts +18 -0
  76. package/dist/hooks/model-limits.d.ts +88 -30
  77. package/dist/hooks/pr-workflow-gate.d.ts +8 -1
  78. package/dist/index.js +455 -452
  79. package/dist/memory/injector.d.ts +2 -0
  80. package/dist/services/context-budget-service.d.ts +6 -1
  81. package/dist/services/status-service.d.ts +14 -0
  82. package/dist/state.d.ts +37 -0
  83. package/dist/tools/context-status.d.ts +3 -1
  84. package/dist/turbo/lean/runner.d.ts +10 -0
  85. package/dist/utils/ephemeral-session-teardown.d.ts +98 -0
  86. package/dist/utils/path-security.d.ts +75 -5
  87. package/dist/utils/swarm-artifact-cache.d.ts +13 -0
  88. package/dist/worktree/index.d.ts +1 -1
  89. package/dist/worktree/merge.d.ts +36 -3
  90. package/package.json +1 -1
@@ -3,7 +3,7 @@ import {
3
3
  EvaluationRunV1Schema,
4
4
  GateAuditResultV1Schema,
5
5
  getProtectedEvaluationRunIds
6
- } from "./index-z1tkxzq4.js";
6
+ } from "./index-s608d3hw.js";
7
7
  import {
8
8
  readEffectiveSpecSync
9
9
  } from "./index-9ss2m4rs.js";
@@ -12,7 +12,7 @@ import {
12
12
  readTaskEvidence,
13
13
  readTaskEvidenceRaw,
14
14
  sanitizeTaskId
15
- } from "./index-tcdcj1g2.js";
15
+ } from "./index-5w7ekpy3.js";
16
16
  import {
17
17
  EVIDENCE_MAX_JSON_BYTES,
18
18
  EvidenceBundleSchema,
@@ -40,7 +40,7 @@ import {
40
40
  replayFromLedgerWithStatus,
41
41
  takeSnapshotEvent,
42
42
  takeSnapshotWithRetry
43
- } from "./index-p2dz85tv.js";
43
+ } from "./index-4xbyy6aw.js";
44
44
  import {
45
45
  PlanSchema
46
46
  } from "./index-1kz6da87.js";
@@ -50,16 +50,17 @@ import {
50
50
  import {
51
51
  readSwarmFileAsync,
52
52
  validateSwarmPath
53
- } from "./index-4qzeef9h.js";
53
+ } from "./index-x9q4bbhd.js";
54
54
  import {
55
+ invalidateCachedArtifact,
55
56
  readCachedParsedFile
56
- } from "./index-fsrp8wp3.js";
57
+ } from "./index-ed5ykebp.js";
57
58
  import {
58
59
  withEvidenceLock
59
- } from "./index-a614s16f.js";
60
+ } from "./index-5j6chvj8.js";
60
61
  import {
61
62
  emit
62
- } from "./index-chvqee1j.js";
63
+ } from "./index-a5eba0t8.js";
63
64
  import {
64
65
  ZodError,
65
66
  init_zod
@@ -980,7 +981,7 @@ import {
980
981
  writeFileSync as writeFileSync4
981
982
  } from "fs";
982
983
  import * as fsPromises from "fs/promises";
983
- import * as path7 from "path";
984
+ import * as path8 from "path";
984
985
 
985
986
  // src/git/branch.ts
986
987
  init_executor();
@@ -1602,6 +1603,7 @@ function sanitizeContextText(text) {
1602
1603
  init_logger();
1603
1604
 
1604
1605
  // src/utils/path-security.ts
1606
+ import * as path5 from "path";
1605
1607
  function containsPathTraversal(str) {
1606
1608
  if (/\.\.[/\\]/.test(str))
1607
1609
  return true;
@@ -1642,14 +1644,56 @@ function containsControlChars(str) {
1642
1644
  return false;
1643
1645
  }
1644
1646
  function validateWorkspaceRoot(directory) {
1647
+ validateProjectDirectory(directory);
1648
+ }
1649
+ function validateProjectDirectory(directory) {
1645
1650
  if (!directory || directory.trim() === "") {
1646
- throw new Error("Invalid directory: empty");
1651
+ throw new Error("Invalid project directory: empty");
1647
1652
  }
1648
1653
  if (containsPathTraversal(directory)) {
1649
- throw new Error("Invalid directory: path traversal detected");
1654
+ throw new Error("Invalid project directory: path traversal detected");
1650
1655
  }
1651
1656
  if (containsControlChars(directory)) {
1652
- throw new Error("Invalid directory: control characters detected");
1657
+ throw new Error("Invalid project directory: control characters detected");
1658
+ }
1659
+ if (!path5.isAbsolute(directory) && !/^[A-Za-z]:[/\\]/.test(directory)) {
1660
+ throw new Error("Invalid project directory: must be an absolute path");
1661
+ }
1662
+ assertNotSystemLocation(directory);
1663
+ }
1664
+ var DENIED_ROOT_SUBTREES = new Set([
1665
+ "etc",
1666
+ "usr",
1667
+ "bin",
1668
+ "sbin",
1669
+ "lib",
1670
+ "lib64",
1671
+ "boot",
1672
+ "dev",
1673
+ "proc",
1674
+ "sys",
1675
+ "windows",
1676
+ "winnt",
1677
+ "program files",
1678
+ "program files (x86)",
1679
+ "programdata",
1680
+ "system volume information"
1681
+ ]);
1682
+ var DENIED_EXACT_ROOT_CHILDREN = new Set(["users", "home", "root"]);
1683
+ function assertNotSystemLocation(directory) {
1684
+ for (const parser of [path5.win32, path5.posix]) {
1685
+ if (!parser.isAbsolute(directory))
1686
+ continue;
1687
+ const normalized = parser.normalize(directory);
1688
+ const { root } = parser.parse(normalized);
1689
+ const segments = normalized.slice(root.length).split(/[/\\]/).filter((segment) => segment.length > 0);
1690
+ if (segments.length === 0) {
1691
+ throw new Error(`Invalid project directory: filesystem root is not a project root (${directory})`);
1692
+ }
1693
+ const first = (segments[0] ?? "").toLowerCase();
1694
+ if (DENIED_ROOT_SUBTREES.has(first) || segments.length === 1 && DENIED_EXACT_ROOT_CHILDREN.has(first)) {
1695
+ throw new Error(`Invalid project directory: system location is not a project root (${directory})`);
1696
+ }
1653
1697
  }
1654
1698
  }
1655
1699
 
@@ -1827,13 +1871,13 @@ var _internals6 = {
1827
1871
  // src/turbo/epic/state.ts
1828
1872
  init_logger();
1829
1873
  import * as fs3 from "fs";
1830
- import * as path5 from "path";
1874
+ import * as path6 from "path";
1831
1875
  var STATE_FILE = "epic-state.json";
1832
1876
  function nowISO() {
1833
1877
  return new Date().toISOString();
1834
1878
  }
1835
1879
  function ensureSwarmDir(directory) {
1836
- const swarmDir = path5.resolve(directory, ".swarm");
1880
+ const swarmDir = path6.resolve(directory, ".swarm");
1837
1881
  if (!fs3.existsSync(swarmDir)) {
1838
1882
  fs3.mkdirSync(swarmDir, { recursive: true });
1839
1883
  }
@@ -1855,7 +1899,7 @@ function markStateUnreadable(directory, reason) {
1855
1899
  }
1856
1900
  function readPersisted(directory) {
1857
1901
  try {
1858
- const filePath = path5.join(directory, ".swarm", STATE_FILE);
1902
+ const filePath = path6.join(directory, ".swarm", STATE_FILE);
1859
1903
  if (!fs3.existsSync(filePath)) {
1860
1904
  const seed = emptyPersisted();
1861
1905
  try {
@@ -1891,7 +1935,7 @@ function writePersisted(directory, persisted) {
1891
1935
  let payload;
1892
1936
  try {
1893
1937
  ensureSwarmDir(directory);
1894
- filePath = path5.join(directory, ".swarm", STATE_FILE);
1938
+ filePath = path6.join(directory, ".swarm", STATE_FILE);
1895
1939
  tmpPath = `${filePath}.tmp.${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
1896
1940
  persisted.updatedAt = nowISO();
1897
1941
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -1940,7 +1984,7 @@ function isEpicModeActive(directory, sessionID) {
1940
1984
  function isEpicModeActiveForProject(directory) {
1941
1985
  if (stateUnreadableMap.get(directory))
1942
1986
  return false;
1943
- if (!fs3.existsSync(path5.join(directory, ".swarm", STATE_FILE))) {
1987
+ if (!fs3.existsSync(path6.join(directory, ".swarm", STATE_FILE))) {
1944
1988
  return false;
1945
1989
  }
1946
1990
  const persisted = readPersisted(directory);
@@ -2049,7 +2093,7 @@ var _internals7 = {
2049
2093
  gitHeadSha: (cwd) => {
2050
2094
  return _internals5.gitExec(["rev-parse", "HEAD"], cwd).trim();
2051
2095
  },
2052
- sleep: (ms) => new Promise((resolve2) => setTimeout(resolve2, ms)),
2096
+ sleep: (ms) => new Promise((resolve3) => setTimeout(resolve3, ms)),
2053
2097
  hasExistingTaskCommit: (cwd, taskId) => {
2054
2098
  const safeId = scrubTaskIdForGitSubject(taskId);
2055
2099
  const escaped = safeId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -2067,7 +2111,7 @@ var _internals7 = {
2067
2111
 
2068
2112
  // src/turbo/lean/conflicts.ts
2069
2113
  import * as fs4 from "fs";
2070
- import * as path6 from "path";
2114
+ import * as path7 from "path";
2071
2115
 
2072
2116
  // src/utils/path.ts
2073
2117
  function normalizePath(p) {
@@ -2195,7 +2239,7 @@ function isProtectedPath(normalizedPath) {
2195
2239
  return false;
2196
2240
  }
2197
2241
  function readTaskScopes(directory, taskId) {
2198
- const scopePath = path6.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
2242
+ const scopePath = path7.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
2199
2243
  try {
2200
2244
  if (!fs4.existsSync(scopePath)) {
2201
2245
  return null;
@@ -2214,7 +2258,7 @@ function readTaskScopes(directory, taskId) {
2214
2258
  // src/utils/spec-hash.ts
2215
2259
  import { createHash as createHash2 } from "crypto";
2216
2260
  import * as fsSync2 from "fs";
2217
- import { join as join5 } from "path";
2261
+ import { join as join6 } from "path";
2218
2262
  async function computeSpecHash(directory) {
2219
2263
  const spec = _internals8.readEffectiveSpecSync(directory);
2220
2264
  if (!spec)
@@ -2243,7 +2287,7 @@ async function isSpecStale(directory, plan) {
2243
2287
  return { stale: false };
2244
2288
  }
2245
2289
  function isObligationPreserving(directory) {
2246
- const snapshotPath = join5(directory, ".swarm", "spec-snapshot.md");
2290
+ const snapshotPath = join6(directory, ".swarm", "spec-snapshot.md");
2247
2291
  try {
2248
2292
  let recordedContent;
2249
2293
  try {
@@ -2256,10 +2300,10 @@ function isObligationPreserving(directory) {
2256
2300
  return false;
2257
2301
  }
2258
2302
  const currentContent = currentResult.content;
2259
- const normalize = (text) => text.replace(/\r\n/g, `
2303
+ const normalize2 = (text) => text.replace(/\r\n/g, `
2260
2304
  `);
2261
- const recordedNorm = normalize(recordedContent);
2262
- const currentNorm = normalize(currentContent);
2305
+ const recordedNorm = normalize2(recordedContent);
2306
+ const currentNorm = normalize2(currentContent);
2263
2307
  const splitParagraphs = (text) => text.split(/\n\s*\n/).map((p) => p.trim()).filter((p) => p.length > 0);
2264
2308
  const recordedParagraphs = splitParagraphs(recordedNorm);
2265
2309
  const currentParagraphs = splitParagraphs(currentNorm);
@@ -2289,7 +2333,7 @@ var _internals8 = {
2289
2333
  readEffectiveSpecSync
2290
2334
  };
2291
2335
  function computeSpecDiff(directory) {
2292
- const snapshotPath = join5(directory, ".swarm", "spec-snapshot.md");
2336
+ const snapshotPath = join6(directory, ".swarm", "spec-snapshot.md");
2293
2337
  let recordedContent;
2294
2338
  try {
2295
2339
  const snapshotSize = fsSync2.statSync(snapshotPath).size;
@@ -2306,11 +2350,11 @@ function computeSpecDiff(directory) {
2306
2350
  return null;
2307
2351
  }
2308
2352
  const currentContent = spec.content;
2309
- const normalize = (text) => text.replace(/\r\n/g, `
2353
+ const normalize2 = (text) => text.replace(/\r\n/g, `
2310
2354
  `);
2311
- const recordedLines = normalize(recordedContent).split(`
2355
+ const recordedLines = normalize2(recordedContent).split(`
2312
2356
  `);
2313
- const currentLines = normalize(currentContent).split(`
2357
+ const currentLines = normalize2(currentContent).split(`
2314
2358
  `);
2315
2359
  const diffLines = computeLcsDiff(recordedLines, currentLines);
2316
2360
  const MAX_DIFF_LINES = 300;
@@ -2493,7 +2537,7 @@ async function retryCasWithBackoff(directory, eventInput, options) {
2493
2537
  expectedHashPrefix: currentExpected.slice(0, 8),
2494
2538
  delayMs
2495
2539
  });
2496
- await new Promise((resolve3) => setTimeout(resolve3, delayMs));
2540
+ await new Promise((resolve4) => setTimeout(resolve4, delayMs));
2497
2541
  if (options.verifyValid) {
2498
2542
  const stillValid = await options.verifyValid();
2499
2543
  if (!stillValid)
@@ -2536,7 +2580,7 @@ async function getLatestLedgerHash(directory) {
2536
2580
  }
2537
2581
  }
2538
2582
  async function surfaceLedgerStaleIfPersisted(directory, plan) {
2539
- const resolvedWorkspace = path7.resolve(directory);
2583
+ const resolvedWorkspace = path8.resolve(directory);
2540
2584
  if (!ledgerStaleWorkspaces.has(resolvedWorkspace)) {
2541
2585
  return plan;
2542
2586
  }
@@ -2555,7 +2599,7 @@ async function surfaceLedgerStaleIfPersisted(directory, plan) {
2555
2599
  return plan;
2556
2600
  }
2557
2601
  async function parsePlanJsonCached(directory) {
2558
- const planJsonPath = path7.resolve(directory, ".swarm", "plan.json");
2602
+ const planJsonPath = path8.resolve(directory, ".swarm", "plan.json");
2559
2603
  return readCachedParsedFile(planJsonPath, PLAN_JSON_CACHE_NAMESPACE, () => readSwarmFileAsync(directory, "plan.json"), (planJsonContent) => {
2560
2604
  if (planJsonContent.includes("\x00") || planJsonContent.includes("\uFFFD")) {
2561
2605
  throw new Error("Plan rejected: .swarm/plan.json contains null bytes or invalid encoding");
@@ -2615,13 +2659,13 @@ async function isPlanMdInSync(directory, plan, cache) {
2615
2659
  return false;
2616
2660
  }
2617
2661
  async function regeneratePlanMarkdown(directory, plan) {
2618
- const swarmDir = path7.resolve(directory, ".swarm");
2662
+ const swarmDir = path8.resolve(directory, ".swarm");
2619
2663
  const contentHash = computePlanContentHash(plan);
2620
2664
  const markdown = derivePlanMarkdown(plan);
2621
2665
  const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
2622
2666
  ${markdown}`;
2623
- const mdPath = path7.join(swarmDir, "plan.md");
2624
- const mdTempPath = path7.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
2667
+ const mdPath = path8.join(swarmDir, "plan.md");
2668
+ const mdTempPath = path8.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
2625
2669
  try {
2626
2670
  await bunWrite(mdTempPath, markdownWithHash);
2627
2671
  renameSync2(mdTempPath, mdPath);
@@ -2630,6 +2674,7 @@ ${markdown}`;
2630
2674
  unlinkSync2(mdTempPath);
2631
2675
  } catch {}
2632
2676
  }
2677
+ invalidateCachedArtifact(mdPath);
2633
2678
  }
2634
2679
  async function loadPlan(directory, cache) {
2635
2680
  const planJsonContent = await readSwarmFileAsync(directory, "plan.json", cache);
@@ -2653,7 +2698,7 @@ async function loadPlan(directory, cache) {
2653
2698
  if (await ledgerExists(directory)) {
2654
2699
  const planHash = computePlanHash(validated);
2655
2700
  const ledgerHash = await getLatestLedgerHash(directory);
2656
- const resolvedWorkspace = path7.resolve(directory);
2701
+ const resolvedWorkspace = path8.resolve(directory);
2657
2702
  if (!startupLedgerCheckedWorkspaces.has(resolvedWorkspace)) {
2658
2703
  startupLedgerCheckedWorkspaces.add(resolvedWorkspace);
2659
2704
  if (ledgerHash !== "" && planHash !== ledgerHash) {
@@ -2727,7 +2772,7 @@ async function loadPlan(directory, cache) {
2727
2772
  if (!preserving) {
2728
2773
  try {
2729
2774
  const diffInfo = computeSpecDiff(directory);
2730
- const specStalenessPath = path7.join(directory, ".swarm", "spec-staleness.json");
2775
+ const specStalenessPath = path8.join(directory, ".swarm", "spec-staleness.json");
2731
2776
  await fsPromises.writeFile(specStalenessPath, JSON.stringify({
2732
2777
  type: "spec_stale_detected",
2733
2778
  timestamp: new Date().toISOString(),
@@ -2739,9 +2784,10 @@ async function loadPlan(directory, cache) {
2739
2784
  diff: diffInfo?.diff ?? null,
2740
2785
  changedSections: diffInfo?.changedSections ?? []
2741
2786
  }, null, 2), "utf-8");
2787
+ invalidateCachedArtifact(specStalenessPath);
2742
2788
  } catch {}
2743
2789
  try {
2744
- const eventsPath = path7.join(directory, ".swarm", "events.jsonl");
2790
+ const eventsPath = path8.join(directory, ".swarm", "events.jsonl");
2745
2791
  const event = {
2746
2792
  type: "spec_stale_detected",
2747
2793
  timestamp: new Date().toISOString(),
@@ -2807,7 +2853,7 @@ async function loadPlan(directory, cache) {
2807
2853
  return migrated;
2808
2854
  }
2809
2855
  if (await ledgerExists(directory)) {
2810
- const resolvedDir = path7.resolve(directory);
2856
+ const resolvedDir = path8.resolve(directory);
2811
2857
  const existingMutex = recoveryMutexes.get(resolvedDir);
2812
2858
  if (existingMutex) {
2813
2859
  await existingMutex;
@@ -2936,9 +2982,9 @@ async function savePlan(directory, plan, options) {
2936
2982
  } else {
2937
2983
  const existingEvents = await readLedgerEvents(directory);
2938
2984
  if (existingEvents.length > 0 && existingEvents[0].plan_id !== planId) {
2939
- const swarmDir2 = path7.resolve(directory, ".swarm");
2940
- const oldLedgerPath = path7.join(swarmDir2, "plan-ledger.jsonl");
2941
- const oldLedgerBackupPath = path7.join(swarmDir2, `plan-ledger.backup-${Date.now()}-${Math.floor(Math.random() * 1e9)}.jsonl`);
2985
+ const swarmDir2 = path8.resolve(directory, ".swarm");
2986
+ const oldLedgerPath = path8.join(swarmDir2, "plan-ledger.jsonl");
2987
+ const oldLedgerBackupPath = path8.join(swarmDir2, `plan-ledger.backup-${Date.now()}-${Math.floor(Math.random() * 1e9)}.jsonl`);
2942
2988
  let backupExists = false;
2943
2989
  if (existsSync3(oldLedgerPath)) {
2944
2990
  try {
@@ -2976,7 +3022,7 @@ async function savePlan(directory, plan, options) {
2976
3022
  }
2977
3023
  }
2978
3024
  if (initSucceeded && backupExists) {
2979
- const archivePath = path7.join(swarmDir2, `plan-ledger.archived-${Date.now()}-${Math.floor(Math.random() * 1e9)}.jsonl`);
3025
+ const archivePath = path8.join(swarmDir2, `plan-ledger.archived-${Date.now()}-${Math.floor(Math.random() * 1e9)}.jsonl`);
2980
3026
  try {
2981
3027
  renameSync2(oldLedgerBackupPath, archivePath);
2982
3028
  warn(`[savePlan] Ledger identity mismatch (was "${existingEvents[0].plan_id}", now "${planId}") \u2014 archived old ledger to ${archivePath} and reinitializing.`);
@@ -3001,7 +3047,7 @@ async function savePlan(directory, plan, options) {
3001
3047
  const toRemove = archivedSiblings.slice(0, archivedSiblings.length - MAX_ARCHIVED_SIBLINGS);
3002
3048
  for (const file of toRemove) {
3003
3049
  try {
3004
- unlinkSync2(path7.join(swarmDir2, file));
3050
+ unlinkSync2(path8.join(swarmDir2, file));
3005
3051
  } catch {}
3006
3052
  }
3007
3053
  }
@@ -3144,9 +3190,9 @@ async function savePlan(directory, plan, options) {
3144
3190
  source: "savePlan_manager"
3145
3191
  });
3146
3192
  }
3147
- const swarmDir = path7.resolve(directory, ".swarm");
3148
- const planPath = path7.join(swarmDir, "plan.json");
3149
- const tempPath = path7.join(swarmDir, `plan.json.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3193
+ const swarmDir = path8.resolve(directory, ".swarm");
3194
+ const planPath = path8.join(swarmDir, "plan.json");
3195
+ const tempPath = path8.join(swarmDir, `plan.json.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3150
3196
  try {
3151
3197
  await bunWrite(tempPath, JSON.stringify(projectedPlan, null, 2));
3152
3198
  renameSync2(tempPath, planPath);
@@ -3155,8 +3201,9 @@ async function savePlan(directory, plan, options) {
3155
3201
  unlinkSync2(tempPath);
3156
3202
  } catch {}
3157
3203
  }
3204
+ invalidateCachedArtifact(planPath);
3158
3205
  try {
3159
- const markerPath = path7.join(swarmDir, ".plan-write-marker");
3206
+ const markerPath = path8.join(swarmDir, ".plan-write-marker");
3160
3207
  const inProgressMarker = JSON.stringify({
3161
3208
  source: "plan_manager",
3162
3209
  timestamp: new Date().toISOString(),
@@ -3171,8 +3218,8 @@ async function savePlan(directory, plan, options) {
3171
3218
  const markdown = derivePlanMarkdown(projectedPlan);
3172
3219
  const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
3173
3220
  ${markdown}`;
3174
- const mdPath = path7.join(swarmDir, "plan.md");
3175
- const mdTempPath = path7.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3221
+ const mdPath = path8.join(swarmDir, "plan.md");
3222
+ const mdTempPath = path8.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3176
3223
  try {
3177
3224
  await bunWrite(mdTempPath, markdownWithHash);
3178
3225
  renameSync2(mdTempPath, mdPath);
@@ -3181,6 +3228,7 @@ ${markdown}`;
3181
3228
  unlinkSync2(mdTempPath);
3182
3229
  } catch {}
3183
3230
  }
3231
+ invalidateCachedArtifact(mdPath);
3184
3232
  } catch (mdError) {
3185
3233
  const message = mdError instanceof Error ? mdError.message : String(mdError);
3186
3234
  warn(`[savePlan] plan.md write failed (non-fatal, plan.json is authoritative): ${message}`);
@@ -3193,7 +3241,7 @@ ${markdown}`;
3193
3241
  } catch {}
3194
3242
  }
3195
3243
  try {
3196
- const markerPath = path7.join(swarmDir, ".plan-write-marker");
3244
+ const markerPath = path8.join(swarmDir, ".plan-write-marker");
3197
3245
  const tasksCount = projectedPlan.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
3198
3246
  const marker = JSON.stringify({
3199
3247
  source: "plan_manager",
@@ -3209,11 +3257,11 @@ async function rebuildPlan(directory, plan, options) {
3209
3257
  const targetPlan = plan ?? await replayFromLedger(directory);
3210
3258
  if (!targetPlan)
3211
3259
  return null;
3212
- const swarmDir = path7.join(directory, ".swarm");
3213
- const planPath = path7.join(swarmDir, "plan.json");
3214
- const mdPath = path7.join(swarmDir, "plan.md");
3260
+ const swarmDir = path8.join(directory, ".swarm");
3261
+ const planPath = path8.join(swarmDir, "plan.json");
3262
+ const mdPath = path8.join(swarmDir, "plan.md");
3215
3263
  mkdirSync3(swarmDir, { recursive: true });
3216
- const tempPlanPath = path7.join(swarmDir, `plan.json.rebuild.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3264
+ const tempPlanPath = path8.join(swarmDir, `plan.json.rebuild.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3217
3265
  {
3218
3266
  const fd = openSync(tempPlanPath, "w");
3219
3267
  try {
@@ -3224,8 +3272,9 @@ async function rebuildPlan(directory, plan, options) {
3224
3272
  }
3225
3273
  }
3226
3274
  renameSync2(tempPlanPath, planPath);
3275
+ invalidateCachedArtifact(planPath);
3227
3276
  try {
3228
- const markerPath = path7.join(swarmDir, ".plan-write-marker");
3277
+ const markerPath = path8.join(swarmDir, ".plan-write-marker");
3229
3278
  const inProgressMarker = JSON.stringify({
3230
3279
  source: "plan_manager",
3231
3280
  timestamp: new Date().toISOString(),
@@ -3240,12 +3289,13 @@ async function rebuildPlan(directory, plan, options) {
3240
3289
  const markdown = derivePlanMarkdown(targetPlan);
3241
3290
  const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
3242
3291
  ${markdown}`;
3243
- const tempMdPath = path7.join(swarmDir, `plan.md.rebuild.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3292
+ const tempMdPath = path8.join(swarmDir, `plan.md.rebuild.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3244
3293
  await bunWrite(tempMdPath, markdownWithHash);
3245
3294
  renameSync2(tempMdPath, mdPath);
3295
+ invalidateCachedArtifact(mdPath);
3246
3296
  } finally {
3247
3297
  try {
3248
- const markerPath = path7.join(swarmDir, ".plan-write-marker");
3298
+ const markerPath = path8.join(swarmDir, ".plan-write-marker");
3249
3299
  const tasksCount = targetPlan.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
3250
3300
  const marker = JSON.stringify({
3251
3301
  source: "plan_manager",
@@ -3308,13 +3358,14 @@ async function closePlanTerminalState(directory, plan, options) {
3308
3358
  planHashAfter: hashAfter,
3309
3359
  source: "close_terminal"
3310
3360
  });
3311
- const swarmDir = path7.join(directory, ".swarm");
3312
- const planPath = path7.join(swarmDir, "plan.json");
3313
- const tempPlanPath = path7.join(swarmDir, `plan.json.close.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3361
+ const swarmDir = path8.join(directory, ".swarm");
3362
+ const planPath = path8.join(swarmDir, "plan.json");
3363
+ const tempPlanPath = path8.join(swarmDir, `plan.json.close.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3314
3364
  await bunWrite(tempPlanPath, JSON.stringify(validated, null, 2));
3315
3365
  renameSync2(tempPlanPath, planPath);
3366
+ invalidateCachedArtifact(planPath);
3316
3367
  try {
3317
- const markerPath = path7.join(swarmDir, ".plan-write-marker");
3368
+ const markerPath = path8.join(swarmDir, ".plan-write-marker");
3318
3369
  const inProgressMarker = JSON.stringify({
3319
3370
  source: "plan_manager_close",
3320
3371
  timestamp: new Date().toISOString(),
@@ -3325,17 +3376,18 @@ async function closePlanTerminalState(directory, plan, options) {
3325
3376
  await bunWrite(markerPath, inProgressMarker);
3326
3377
  } catch {}
3327
3378
  try {
3328
- const mdPath = path7.join(swarmDir, "plan.md");
3379
+ const mdPath = path8.join(swarmDir, "plan.md");
3329
3380
  const contentHash = computePlanContentHash(validated);
3330
3381
  const markdown = derivePlanMarkdown(validated);
3331
3382
  const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
3332
3383
  ${markdown}`;
3333
- const mdTempPath = path7.join(swarmDir, `plan.md.close.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3384
+ const mdTempPath = path8.join(swarmDir, `plan.md.close.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3334
3385
  await bunWrite(mdTempPath, markdownWithHash);
3335
3386
  renameSync2(mdTempPath, mdPath);
3387
+ invalidateCachedArtifact(mdPath);
3336
3388
  } finally {
3337
3389
  try {
3338
- const markerPath = path7.join(swarmDir, ".plan-write-marker");
3390
+ const markerPath = path8.join(swarmDir, ".plan-write-marker");
3339
3391
  const tasksCount = validated.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
3340
3392
  const marker = JSON.stringify({
3341
3393
  source: "plan_manager_close",
@@ -3632,11 +3684,11 @@ import {
3632
3684
  } from "fs";
3633
3685
  import * as fs7 from "fs/promises";
3634
3686
  import * as os4 from "os";
3635
- import * as path9 from "path";
3687
+ import * as path10 from "path";
3636
3688
 
3637
3689
  // src/evaluation/retention.ts
3638
3690
  import * as fs5 from "fs/promises";
3639
- import * as path8 from "path";
3691
+ import * as path9 from "path";
3640
3692
  function artifactKey(artifact) {
3641
3693
  return `${artifact.namespace}/${artifact.id}`;
3642
3694
  }
@@ -3644,7 +3696,7 @@ function validId(value) {
3644
3696
  return /^[A-Za-z0-9][A-Za-z0-9._-]{0,159}$/.test(value);
3645
3697
  }
3646
3698
  async function evaluationRunCandidates(directory) {
3647
- const root = path8.join(directory, ".swarm", "evolution", "runs");
3699
+ const root = path9.join(directory, ".swarm", "evolution", "runs");
3648
3700
  let entries = [];
3649
3701
  try {
3650
3702
  entries = await fs5.readdir(root, { withFileTypes: true });
@@ -3663,7 +3715,7 @@ async function evaluationRunCandidates(directory) {
3663
3715
  if (!validId(id))
3664
3716
  continue;
3665
3717
  const artifact = { namespace: "evaluation-run", id };
3666
- const target = path8.join(root, entry.name);
3718
+ const target = path9.join(root, entry.name);
3667
3719
  try {
3668
3720
  const run = EvaluationRunV1Schema.parse(JSON.parse(await fs5.readFile(target, "utf8")));
3669
3721
  if (run.runId !== id)
@@ -3681,7 +3733,7 @@ async function evaluationRunCandidates(directory) {
3681
3733
  return { candidates, corrupt };
3682
3734
  }
3683
3735
  async function gateAuditCandidates(directory) {
3684
- const root = path8.join(directory, ".swarm", "evidence", "gate-audit");
3736
+ const root = path9.join(directory, ".swarm", "evidence", "gate-audit");
3685
3737
  let entries = [];
3686
3738
  try {
3687
3739
  entries = await fs5.readdir(root, { withFileTypes: true });
@@ -3697,9 +3749,9 @@ async function gateAuditCandidates(directory) {
3697
3749
  if (!entry.isDirectory() || !validId(entry.name))
3698
3750
  continue;
3699
3751
  const artifact = { namespace: "gate-audit", id: entry.name };
3700
- const target = path8.join(root, entry.name);
3752
+ const target = path9.join(root, entry.name);
3701
3753
  try {
3702
- const result = GateAuditResultV1Schema.parse(JSON.parse(await fs5.readFile(path8.join(target, "results.json"), "utf8")));
3754
+ const result = GateAuditResultV1Schema.parse(JSON.parse(await fs5.readFile(path9.join(target, "results.json"), "utf8")));
3703
3755
  if (result.runId !== entry.name)
3704
3756
  throw new Error("run id/path mismatch");
3705
3757
  candidates.push({
@@ -3740,7 +3792,7 @@ var _retentionInternals = {
3740
3792
  removeCandidate
3741
3793
  };
3742
3794
  async function archiveEvaluationArtifacts(args) {
3743
- return withEvidenceLock(args.directory, path8.join("evolution", "retention-index"), "evaluation-retention", "archive", async () => {
3795
+ return withEvidenceLock(args.directory, path9.join("evolution", "retention-index"), "evaluation-retention", "archive", async () => {
3744
3796
  const inventory = await retentionCandidates(args.directory);
3745
3797
  let protectedKeys = await _retentionInternals.protectedArtifacts(args.directory);
3746
3798
  const protectedRefs = inventory.candidates.filter((candidate) => protectedKeys.has(artifactKey(candidate.artifact))).map((candidate) => candidate.artifact);
@@ -3820,7 +3872,7 @@ async function atomicRenameWithRetry(src, dst, renameFn = fsp.rename) {
3820
3872
  throw err;
3821
3873
  }
3822
3874
  if (attempt < RENAME_MAX_ATTEMPTS - 1) {
3823
- await new Promise((resolve3) => setTimeout(resolve3, RENAME_BACKOFF_MS));
3875
+ await new Promise((resolve4) => setTimeout(resolve4, RENAME_BACKOFF_MS));
3824
3876
  }
3825
3877
  }
3826
3878
  }
@@ -4063,8 +4115,8 @@ function isWeakConfigContainerRoot(directory) {
4063
4115
  const resolved = realpathSync(directory);
4064
4116
  return resolved === realpathSync(os4.tmpdir()) || resolved === realpathSync(os4.homedir());
4065
4117
  } catch {
4066
- const resolved = path9.resolve(directory);
4067
- return resolved === path9.resolve(os4.tmpdir()) || resolved === path9.resolve(os4.homedir());
4118
+ const resolved = path10.resolve(directory);
4119
+ return resolved === path10.resolve(os4.tmpdir()) || resolved === path10.resolve(os4.homedir());
4068
4120
  }
4069
4121
  }
4070
4122
  function hasAccessibleProjectIndicator(directory, options = {}) {
@@ -4074,7 +4126,7 @@ function hasAccessibleProjectIndicator(directory, options = {}) {
4074
4126
  continue;
4075
4127
  }
4076
4128
  try {
4077
- const indicatorStat = statSync2(path9.join(directory, indicator));
4129
+ const indicatorStat = statSync2(path10.join(directory, indicator));
4078
4130
  if (indicatorStat.isFile() || indicatorStat.isDirectory()) {
4079
4131
  return true;
4080
4132
  }
@@ -4096,14 +4148,14 @@ function validateProjectRoot(directory) {
4096
4148
  if (depth >= MAX_DEPTH)
4097
4149
  break;
4098
4150
  depth++;
4099
- const parent = path9.dirname(current);
4151
+ const parent = path10.dirname(current);
4100
4152
  if (parent === current)
4101
4153
  break;
4102
- if (path9.dirname(parent) === parent) {
4154
+ if (path10.dirname(parent) === parent) {
4103
4155
  current = parent;
4104
4156
  continue;
4105
4157
  }
4106
- const parentSwarm = path9.join(parent, ".swarm");
4158
+ const parentSwarm = path10.join(parent, ".swarm");
4107
4159
  try {
4108
4160
  if (statSync2(parentSwarm).isDirectory()) {
4109
4161
  if (hasAccessibleProjectIndicator(parent, {
@@ -4124,12 +4176,12 @@ function validateProjectRoot(directory) {
4124
4176
  async function saveEvidence(directory, taskId, evidence) {
4125
4177
  _internals11.validateProjectRoot(directory);
4126
4178
  const sanitizedTaskId = sanitizeTaskId2(taskId);
4127
- const relativePath = path9.join("evidence", sanitizedTaskId, "evidence.json");
4179
+ const relativePath = path10.join("evidence", sanitizedTaskId, "evidence.json");
4128
4180
  validateSwarmPath(directory, relativePath);
4129
4181
  _internals11.validateEvidence(evidence);
4130
4182
  return withEvidenceLock(directory, relativePath, "evidence-manager", sanitizedTaskId, async () => {
4131
4183
  const evidencePath = validateSwarmPath(directory, relativePath);
4132
- const evidenceDir = path9.dirname(evidencePath);
4184
+ const evidenceDir = path10.dirname(evidencePath);
4133
4185
  let bundle;
4134
4186
  const existingContent = await readSwarmFileAsync(directory, relativePath);
4135
4187
  if (existingContent !== null) {
@@ -4172,7 +4224,7 @@ async function saveEvidence(directory, taskId, evidence) {
4172
4224
  throw new Error(`Evidence bundle size (${bundleJson.length} bytes) exceeds maximum (${EVIDENCE_MAX_JSON_BYTES} bytes)`);
4173
4225
  }
4174
4226
  mkdirSync4(evidenceDir, { recursive: true });
4175
- const tempPath = path9.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
4227
+ const tempPath = path10.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
4176
4228
  try {
4177
4229
  await bunWrite(tempPath, bundleJson);
4178
4230
  await fs7.rename(tempPath, evidencePath);
@@ -4182,6 +4234,7 @@ async function saveEvidence(directory, taskId, evidence) {
4182
4234
  } catch {}
4183
4235
  throw error2;
4184
4236
  }
4237
+ invalidateCachedArtifact(evidencePath);
4185
4238
  return updatedBundle;
4186
4239
  });
4187
4240
  }
@@ -4216,7 +4269,7 @@ function wrapFlatRetrospective(flatEntry, taskId) {
4216
4269
  }
4217
4270
  async function loadEvidence(directory, taskId, options) {
4218
4271
  const sanitizedTaskId = sanitizeTaskId2(taskId);
4219
- const relativePath = path9.join("evidence", sanitizedTaskId, "evidence.json");
4272
+ const relativePath = path10.join("evidence", sanitizedTaskId, "evidence.json");
4220
4273
  if (relativePath.length > 4096) {
4221
4274
  return { status: "not_found" };
4222
4275
  }
@@ -4240,12 +4293,13 @@ async function loadEvidence(directory, taskId, options) {
4240
4293
  }
4241
4294
  try {
4242
4295
  await withEvidenceLock(directory, relativePath, "evidence-loader", sanitizedTaskId, async () => {
4243
- const evidenceDir = path9.dirname(evidencePath);
4296
+ const evidenceDir = path10.dirname(evidencePath);
4244
4297
  const bundleJson = JSON.stringify(validated);
4245
- const tempPath = path9.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
4298
+ const tempPath = path10.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
4246
4299
  try {
4247
4300
  await bunWrite(tempPath, bundleJson);
4248
4301
  await fs7.rename(tempPath, evidencePath);
4302
+ invalidateCachedArtifact(evidencePath);
4249
4303
  } catch (writeError) {
4250
4304
  try {
4251
4305
  rmSync(tempPath, { force: true });
@@ -4287,7 +4341,7 @@ async function listEvidenceTaskIds(directory) {
4287
4341
  }
4288
4342
  const taskIds = [];
4289
4343
  for (const entry of entries) {
4290
- const entryPath = path9.join(evidenceBasePath, entry);
4344
+ const entryPath = path10.join(evidenceBasePath, entry);
4291
4345
  try {
4292
4346
  const stats = statSync2(entryPath);
4293
4347
  if (!stats.isDirectory()) {
@@ -4305,7 +4359,7 @@ async function listEvidenceTaskIds(directory) {
4305
4359
  }
4306
4360
  async function deleteEvidence(directory, taskId) {
4307
4361
  const sanitizedTaskId = sanitizeTaskId2(taskId);
4308
- const relativePath = path9.join("evidence", sanitizedTaskId);
4362
+ const relativePath = path10.join("evidence", sanitizedTaskId);
4309
4363
  const evidenceDir = validateSwarmPath(directory, relativePath);
4310
4364
  try {
4311
4365
  statSync2(evidenceDir);
@@ -4321,8 +4375,8 @@ async function deleteEvidence(directory, taskId) {
4321
4375
  }
4322
4376
  }
4323
4377
  async function checkRequirementCoverage(phase, directory) {
4324
- const relativePath = path9.join("evidence", `req-coverage-phase-${phase}.json`);
4325
- const absolutePath = path9.resolve(directory, ".swarm", relativePath);
4378
+ const relativePath = path10.join("evidence", `req-coverage-phase-${phase}.json`);
4379
+ const absolutePath = path10.resolve(directory, ".swarm", relativePath);
4326
4380
  try {
4327
4381
  await fs7.access(absolutePath);
4328
4382
  return { exists: true, path: absolutePath };