opencode-swarm 7.138.3 → 7.139.0

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 (78) hide show
  1. package/.opencode/skills/execute/SKILL.md +11 -2
  2. package/.opencode/skills/swarm-implement/SKILL.md +1 -1
  3. package/dist/cli/{config-doctor-2mwgdbsn.js → config-doctor-aszp7z1h.js} +2 -2
  4. package/dist/cli/{core-v6bte964.js → core-3s832mxx.js} +1 -1
  5. package/dist/cli/{curation-policy-5dqexw5j.js → curation-policy-a3hs73f7.js} +6 -6
  6. package/dist/cli/{curator-llm-factory-wkjme59b.js → curator-llm-factory-e8ngwyjm.js} +26 -25
  7. package/dist/cli/{curator-jjtp9hn2.js → curator-zxjqcc8r.js} +26 -25
  8. package/dist/cli/{evidence-summary-service-6cttrkzw.js → evidence-summary-service-qfhjfxdz.js} +7 -7
  9. package/dist/cli/{gate-evidence-ecx4djaw.js → gate-evidence-m2grv70v.js} +4 -4
  10. package/dist/cli/{guardrail-explain-xppwfnxr.js → guardrail-explain-rqpmzxyy.js} +27 -26
  11. package/dist/cli/{guardrail-log-swet7rch.js → guardrail-log-vd4a0ng5.js} +4 -3
  12. package/dist/cli/{hive-promoter-xvq8jzbs.js → hive-promoter-jc5vym27.js} +26 -25
  13. package/dist/cli/{index-tc61fybd.js → index-0tsetsxs.js} +4 -4
  14. package/dist/cli/{index-jhb8kjc5.js → index-3nr2sn32.js} +3 -3
  15. package/dist/cli/{index-y06a43sk.js → index-4ft523nb.js} +323 -80
  16. package/dist/cli/index-556ja8an.js +62 -0
  17. package/dist/cli/{index-31vfewmn.js → index-5bkpyvdf.js} +271 -94
  18. package/dist/cli/{index-wqg74mwj.js → index-67yqywan.js} +2 -2
  19. package/dist/cli/{index-gda7cwqz.js → index-6q240xgm.js} +30 -68
  20. package/dist/cli/{index-adde7nm2.js → index-84s6x604.js} +5 -5
  21. package/dist/cli/{index-j0xx9wpj.js → index-85hstja2.js} +1 -1
  22. package/dist/cli/{index-xybtaph7.js → index-a614s16f.js} +1 -1
  23. package/dist/cli/{index-10mz5js6.js → index-chvqee1j.js} +2 -2
  24. package/dist/cli/{index-rrxcfxrd.js → index-ddmnhv4h.js} +1 -1
  25. package/dist/cli/{index-1v89yst3.js → index-gytyqv1d.js} +2 -2
  26. package/dist/cli/{index-93ky909v.js → index-kv36s0x0.js} +3 -3
  27. package/dist/cli/{index-z7jgvm9b.js → index-nbgw5dxa.js} +1 -1
  28. package/dist/cli/{index-tqshdzaw.js → index-nc544sfw.js} +1 -1
  29. package/dist/cli/{index-js7th5my.js → index-nsnfvckc.js} +1 -1
  30. package/dist/cli/{index-4fmztnrq.js → index-p2dz85tv.js} +2 -2
  31. package/dist/cli/{index-y6dvs5tt.js → index-q3qtgtd0.js} +1 -1
  32. package/dist/cli/{index-99af5gvd.js → index-r3pth9a7.js} +230 -118
  33. package/dist/cli/{index-ab57h0yq.js → index-rtetrxxq.js} +1 -1
  34. package/dist/cli/{index-rjratees.js → index-s428dmy6.js} +2 -2
  35. package/dist/cli/{index-q344kj84.js → index-t26nfmcs.js} +1 -1
  36. package/dist/cli/{index-1djv5684.js → index-t31cc7kv.js} +6 -6
  37. package/dist/cli/{index-39k6y018.js → index-tcdcj1g2.js} +2 -2
  38. package/dist/cli/{index-en4fb04r.js → index-tyh0p5e8.js} +1 -1
  39. package/dist/cli/{index-xgmx9had.js → index-y46anh5e.js} +28 -27
  40. package/dist/cli/index-ymszzvnr.js +1725 -0
  41. package/dist/cli/{index-ngqxzkqm.js → index-z1tkxzq4.js} +2 -2
  42. package/dist/cli/{index-btx8j39p.js → index-zd15ya1w.js} +1 -1
  43. package/dist/cli/index.js +26 -25
  44. package/dist/cli/{knowledge-escalator-7n384ys1.js → knowledge-escalator-6473ey4c.js} +7 -7
  45. package/dist/cli/{knowledge-events-yaj0yjd6.js → knowledge-events-wwzpz8m4.js} +5 -5
  46. package/dist/cli/{knowledge-link-xc6yhxmz.js → knowledge-link-trfydkzm.js} +4 -4
  47. package/dist/cli/{knowledge-store-d99k0z2d.js → knowledge-store-99gd42jy.js} +5 -5
  48. package/dist/cli/{knowledge-validator-e5fqy9h4.js → knowledge-validator-v2eevvdg.js} +8 -8
  49. package/dist/cli/{pending-delegations-7dbc0j2a.js → pending-delegations-p6n83x67.js} +3 -3
  50. package/dist/cli/{pr-subscriptions-m943zn6g.js → pr-subscriptions-xbrfr51c.js} +3 -3
  51. package/dist/cli/{runner-x1hy047y.js → runner-9an52tmz.js} +5 -5
  52. package/dist/cli/{scan-cursor-9y9msabt.js → scan-cursor-39zxpw34.js} +6 -6
  53. package/dist/cli/{schema-xg5f11md.js → schema-xhfwr6b2.js} +1 -1
  54. package/dist/cli/scope-persistence-nsa6ra9s.js +61 -0
  55. package/dist/cli/{skill-generator-arvwfdfh.js → skill-generator-5px81476.js} +9 -9
  56. package/dist/cli/{telemetry-0yqed3jv.js → telemetry-7nt7zhyp.js} +1 -1
  57. package/dist/cli/{worktree-collision-ownership-hjrt5hx2.js → worktree-collision-ownership-9x4s4890.js} +3 -3
  58. package/dist/hooks/guardrails/destructive-command.d.ts +35 -0
  59. package/dist/hooks/guardrails/file-authority.d.ts +71 -26
  60. package/dist/hooks/guardrails/index.d.ts +2 -0
  61. package/dist/hooks/guardrails/tool-before.d.ts +5 -0
  62. package/dist/hooks/scope-guard.d.ts +3 -1
  63. package/dist/index.js +533 -522
  64. package/dist/plan/manager.d.ts +2 -0
  65. package/dist/scope/path-identity.d.ts +27 -0
  66. package/dist/scope/scope-binding.d.ts +90 -2
  67. package/dist/scope/scope-lease-renewal.d.ts +28 -0
  68. package/dist/scope/scope-persistence.d.ts +102 -19
  69. package/dist/scope/scope-resolution-diagnostic.d.ts +7 -0
  70. package/dist/services/run-memory.d.ts +53 -5
  71. package/dist/tools/declare-scope.d.ts +3 -1
  72. package/dist/tools/save-plan.d.ts +2 -0
  73. package/dist/tools/update-task-status.d.ts +2 -0
  74. package/dist/turbo/lean/lane-scope.d.ts +1 -1
  75. package/dist/utils/path-security.d.ts +25 -1
  76. package/package.json +1 -1
  77. package/dist/cli/index-2y4jy0de.js +0 -642
  78. package/dist/cli/scope-persistence-n1bryhzf.js +0 -38
@@ -3,7 +3,7 @@ import {
3
3
  EvaluationRunV1Schema,
4
4
  GateAuditResultV1Schema,
5
5
  getProtectedEvaluationRunIds
6
- } from "./index-ngqxzkqm.js";
6
+ } from "./index-z1tkxzq4.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-39k6y018.js";
15
+ } from "./index-tcdcj1g2.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-4fmztnrq.js";
43
+ } from "./index-p2dz85tv.js";
44
44
  import {
45
45
  PlanSchema
46
46
  } from "./index-1kz6da87.js";
@@ -56,10 +56,10 @@ import {
56
56
  } from "./index-fsrp8wp3.js";
57
57
  import {
58
58
  withEvidenceLock
59
- } from "./index-xybtaph7.js";
59
+ } from "./index-a614s16f.js";
60
60
  import {
61
61
  emit
62
- } from "./index-10mz5js6.js";
62
+ } from "./index-chvqee1j.js";
63
63
  import {
64
64
  ZodError,
65
65
  init_zod
@@ -1586,9 +1586,247 @@ var _internals5 = {
1586
1586
  readLaneEnvFileFromDiskSync
1587
1587
  };
1588
1588
 
1589
+ // src/services/run-memory.ts
1590
+ import * as crypto2 from "crypto";
1591
+ import * as fs2 from "fs/promises";
1592
+
1593
+ // src/hooks/context-sanitizer.ts
1594
+ function sanitizeContextText(text) {
1595
+ return text.split("").filter((char) => {
1596
+ const code = char.charCodeAt(0);
1597
+ return code === 9 || code === 10 || code === 13 || code > 31 && code !== 127;
1598
+ }).join("").replace(/[\u00AD\u200B-\u200F\u2060-\u2064\uFEFF]/g, "").replace(/[\u202A-\u202E\u2066-\u2069]/g, "").replace(/```/g, "` ` `").replace(/^system\s*:/gim, "[BLOCKED]:").replace(/<system\b[^>]*>/gi, "[BLOCKED-TAG]").replace(/<\/system>/gi, "[/BLOCKED-TAG]").replace(/<tool_call\b[^>]*>/gi, "[BLOCKED-TOOL]").replace(/<\/tool_call>/gi, "[/BLOCKED-TOOL]").replace(/<\/\w+>/g, "[/BLOCKED-TAG]");
1599
+ }
1600
+
1601
+ // src/services/run-memory.ts
1602
+ init_logger();
1603
+
1604
+ // src/utils/path-security.ts
1605
+ function containsPathTraversal(str) {
1606
+ if (/\.\.[/\\]/.test(str))
1607
+ return true;
1608
+ if (/(?:^|[/\\])\.\.(?:[/\\]|$)/.test(str))
1609
+ return true;
1610
+ if (/%2e%2e/i.test(str))
1611
+ return true;
1612
+ if (/%2e\./i.test(str))
1613
+ return true;
1614
+ if (/%2e/i.test(str) && /\.\./.test(str))
1615
+ return true;
1616
+ if (/%252e%252e/i.test(str))
1617
+ return true;
1618
+ if (/\uff0e/.test(str))
1619
+ return true;
1620
+ if (/\u3002/.test(str))
1621
+ return true;
1622
+ if (/\uff65/.test(str))
1623
+ return true;
1624
+ if (/%2f/i.test(str))
1625
+ return true;
1626
+ if (/%5c/i.test(str))
1627
+ return true;
1628
+ return false;
1629
+ }
1630
+ function containsControlChars(str) {
1631
+ for (const ch of str) {
1632
+ const code = ch.codePointAt(0);
1633
+ if (code === undefined)
1634
+ continue;
1635
+ if (code <= 31 || code >= 127 && code <= 159)
1636
+ return true;
1637
+ if (code >= 8234 && code <= 8238)
1638
+ return true;
1639
+ if (code >= 8294 && code <= 8297)
1640
+ return true;
1641
+ }
1642
+ return false;
1643
+ }
1644
+ function validateWorkspaceRoot(directory) {
1645
+ if (!directory || directory.trim() === "") {
1646
+ throw new Error("Invalid directory: empty");
1647
+ }
1648
+ if (containsPathTraversal(directory)) {
1649
+ throw new Error("Invalid directory: path traversal detected");
1650
+ }
1651
+ if (containsControlChars(directory)) {
1652
+ throw new Error("Invalid directory: control characters detected");
1653
+ }
1654
+ }
1655
+
1656
+ // src/services/run-memory.ts
1657
+ var RUN_MEMORY_FILENAME = "run-memory.jsonl";
1658
+ var MAX_SUMMARY_TOKENS = 500;
1659
+ function generateTaskFingerprint(taskId, fileTargets) {
1660
+ const sortedFiles = [...fileTargets].sort().join(",");
1661
+ const hash = crypto2.createHash("sha256").update(taskId + sortedFiles).digest("hex");
1662
+ return hash.slice(0, 8);
1663
+ }
1664
+ async function recordOutcome(directory, entry) {
1665
+ validateWorkspaceRoot(directory);
1666
+ const resolvedPath = validateSwarmPath(directory, RUN_MEMORY_FILENAME);
1667
+ const line = `${JSON.stringify(entry)}
1668
+ `;
1669
+ await fs2.appendFile(resolvedPath, line, { encoding: "utf-8" });
1670
+ }
1671
+ async function getTaskHistory(directory, taskId) {
1672
+ validateWorkspaceRoot(directory);
1673
+ const content = await readSwarmFileAsync(directory, RUN_MEMORY_FILENAME);
1674
+ if (!content) {
1675
+ return [];
1676
+ }
1677
+ const entries = [];
1678
+ const lines = content.split(`
1679
+ `);
1680
+ for (const line of lines) {
1681
+ if (!line.trim())
1682
+ continue;
1683
+ try {
1684
+ const entry = JSON.parse(line);
1685
+ if (entry.taskId === taskId) {
1686
+ entries.push(entry);
1687
+ }
1688
+ } catch {}
1689
+ }
1690
+ return entries;
1691
+ }
1692
+ async function recordTaskAttempt(directory, input) {
1693
+ try {
1694
+ let history = [];
1695
+ try {
1696
+ history = await _internals6.getTaskHistory(directory, input.taskId);
1697
+ } catch (err) {
1698
+ warn(`[run-memory] history read for task ${input.taskId} failed; recording with attemptNumber 1: ${err instanceof Error ? err.message : String(err)}`);
1699
+ }
1700
+ const entry = {
1701
+ timestamp: new Date().toISOString(),
1702
+ taskId: input.taskId,
1703
+ taskFingerprint: _internals6.generateTaskFingerprint(input.taskId, input.fileTargets ?? []),
1704
+ agent: input.agent,
1705
+ outcome: input.outcome,
1706
+ attemptNumber: history.length + 1
1707
+ };
1708
+ if (input.failureReason) {
1709
+ entry.failureReason = input.failureReason;
1710
+ }
1711
+ if (input.fileTargets && input.fileTargets.length > 0) {
1712
+ entry.filesModified = input.fileTargets;
1713
+ }
1714
+ if (typeof input.durationMs === "number") {
1715
+ entry.durationMs = input.durationMs;
1716
+ }
1717
+ await _internals6.recordOutcome(directory, entry);
1718
+ } catch (err) {
1719
+ warn(`[run-memory] failed to record ${input.outcome} for task ${input.taskId}: ${err instanceof Error ? err.message : String(err)}`);
1720
+ }
1721
+ }
1722
+ function groupByTaskId(entries) {
1723
+ const groups = new Map;
1724
+ for (const entry of entries) {
1725
+ const existing = groups.get(entry.taskId) || [];
1726
+ existing.push(entry);
1727
+ groups.set(entry.taskId, existing);
1728
+ }
1729
+ return groups;
1730
+ }
1731
+ function summarizeTask(taskId, entries) {
1732
+ let lastFailure;
1733
+ let lastFailureIndex = -1;
1734
+ let lastPassIndex = -1;
1735
+ let lastPass;
1736
+ let failCount = 0;
1737
+ entries.forEach((entry, index) => {
1738
+ if (entry.outcome === "fail" || entry.outcome === "retry") {
1739
+ failCount++;
1740
+ lastFailure = entry;
1741
+ lastFailureIndex = index;
1742
+ } else if (entry.outcome === "pass") {
1743
+ lastPass = entry;
1744
+ lastPassIndex = index;
1745
+ }
1746
+ });
1747
+ if (!lastFailure) {
1748
+ return null;
1749
+ }
1750
+ const passResolvesFailure = lastPassIndex > lastFailureIndex;
1751
+ if (lastPass && passResolvesFailure) {
1752
+ const passAttempt = lastPass.attemptNumber;
1753
+ const failAttempt = lastFailure.attemptNumber;
1754
+ const reason = sanitizeContextText(lastFailure.failureReason || "unknown");
1755
+ return `Task ${taskId}: FAILED attempt ${failAttempt} \u2014 ${reason}. Passed on attempt ${passAttempt}.`;
1756
+ } else {
1757
+ const reason = sanitizeContextText(lastFailure.failureReason || "unknown");
1758
+ return `Task ${taskId}: FAILED ${failCount} times \u2014 last: ${reason}. Still failing.`;
1759
+ }
1760
+ }
1761
+ async function getRunMemorySummary(directory) {
1762
+ validateWorkspaceRoot(directory);
1763
+ const content = await readSwarmFileAsync(directory, RUN_MEMORY_FILENAME);
1764
+ if (!content) {
1765
+ return null;
1766
+ }
1767
+ const entries = [];
1768
+ const lines = content.split(`
1769
+ `);
1770
+ for (const line of lines) {
1771
+ if (!line.trim())
1772
+ continue;
1773
+ try {
1774
+ const entry = JSON.parse(line);
1775
+ entries.push(entry);
1776
+ } catch {}
1777
+ }
1778
+ if (entries.length === 0) {
1779
+ return null;
1780
+ }
1781
+ const groups = _internals6.groupByTaskId(entries);
1782
+ const summaries = [];
1783
+ for (const [taskId, taskEntries] of groups) {
1784
+ const summary = _internals6.summarizeTask(taskId, taskEntries);
1785
+ if (summary) {
1786
+ summaries.push(summary);
1787
+ }
1788
+ }
1789
+ if (summaries.length === 0) {
1790
+ return null;
1791
+ }
1792
+ const prefix = `[FOR: architect, coder]
1793
+ ## RUN MEMORY \u2014 Previous Task Outcomes
1794
+ `;
1795
+ const suffix = `
1796
+ Use this data to avoid repeating known failure patterns.`;
1797
+ let summaryText = summaries.join(`
1798
+ `);
1799
+ const estimateTokens = (text) => {
1800
+ return Math.ceil(text.length * 0.33);
1801
+ };
1802
+ const totalText = prefix + summaryText + suffix;
1803
+ const estimatedTokens = estimateTokens(totalText);
1804
+ if (estimatedTokens > MAX_SUMMARY_TOKENS) {
1805
+ const prefixTokens = estimateTokens(prefix);
1806
+ const suffixTokens = estimateTokens(suffix);
1807
+ const availableContentTokens = MAX_SUMMARY_TOKENS - prefixTokens - suffixTokens;
1808
+ if (availableContentTokens > 0) {
1809
+ const maxContentChars = Math.floor(availableContentTokens / 0.33);
1810
+ summaryText = summaryText.slice(0, maxContentChars);
1811
+ } else {
1812
+ summaryText = "";
1813
+ }
1814
+ }
1815
+ return prefix + summaryText + suffix;
1816
+ }
1817
+ var _internals6 = {
1818
+ generateTaskFingerprint,
1819
+ recordOutcome,
1820
+ recordTaskAttempt,
1821
+ getTaskHistory,
1822
+ getRunMemorySummary,
1823
+ groupByTaskId,
1824
+ summarizeTask
1825
+ };
1826
+
1589
1827
  // src/turbo/epic/state.ts
1590
1828
  init_logger();
1591
- import * as fs2 from "fs";
1829
+ import * as fs3 from "fs";
1592
1830
  import * as path5 from "path";
1593
1831
  var STATE_FILE = "epic-state.json";
1594
1832
  function nowISO() {
@@ -1596,8 +1834,8 @@ function nowISO() {
1596
1834
  }
1597
1835
  function ensureSwarmDir(directory) {
1598
1836
  const swarmDir = path5.resolve(directory, ".swarm");
1599
- if (!fs2.existsSync(swarmDir)) {
1600
- fs2.mkdirSync(swarmDir, { recursive: true });
1837
+ if (!fs3.existsSync(swarmDir)) {
1838
+ fs3.mkdirSync(swarmDir, { recursive: true });
1601
1839
  }
1602
1840
  return swarmDir;
1603
1841
  }
@@ -1618,16 +1856,16 @@ function markStateUnreadable(directory, reason) {
1618
1856
  function readPersisted(directory) {
1619
1857
  try {
1620
1858
  const filePath = path5.join(directory, ".swarm", STATE_FILE);
1621
- if (!fs2.existsSync(filePath)) {
1859
+ if (!fs3.existsSync(filePath)) {
1622
1860
  const seed = emptyPersisted();
1623
1861
  try {
1624
1862
  ensureSwarmDir(directory);
1625
- fs2.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
1863
+ fs3.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
1626
1864
  `, "utf-8");
1627
1865
  } catch {}
1628
1866
  return seed;
1629
1867
  }
1630
- const raw = fs2.readFileSync(filePath, "utf-8");
1868
+ const raw = fs3.readFileSync(filePath, "utf-8");
1631
1869
  const parsed = JSON.parse(raw);
1632
1870
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 1 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
1633
1871
  markStateUnreadable(directory, `malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
@@ -1664,14 +1902,14 @@ function writePersisted(directory, persisted) {
1664
1902
  throw new Error(`Epic state persistence prepare failed: ${msg}`);
1665
1903
  }
1666
1904
  try {
1667
- fs2.writeFileSync(tmpPath, payload, "utf-8");
1668
- fs2.renameSync(tmpPath, filePath);
1905
+ fs3.writeFileSync(tmpPath, payload, "utf-8");
1906
+ fs3.renameSync(tmpPath, filePath);
1669
1907
  } catch (error2) {
1670
1908
  const msg = error2 instanceof Error ? error2.message : String(error2);
1671
1909
  error(`[turbo/epic/state] Failed to persist ${STATE_FILE} atomically: ${msg}`);
1672
1910
  try {
1673
- if (fs2.existsSync(tmpPath))
1674
- fs2.unlinkSync(tmpPath);
1911
+ if (fs3.existsSync(tmpPath))
1912
+ fs3.unlinkSync(tmpPath);
1675
1913
  } catch {}
1676
1914
  throw new Error(`Epic state persistence failed: ${msg}`);
1677
1915
  }
@@ -1702,7 +1940,7 @@ function isEpicModeActive(directory, sessionID) {
1702
1940
  function isEpicModeActiveForProject(directory) {
1703
1941
  if (stateUnreadableMap.get(directory))
1704
1942
  return false;
1705
- if (!fs2.existsSync(path5.join(directory, ".swarm", STATE_FILE))) {
1943
+ if (!fs3.existsSync(path5.join(directory, ".swarm", STATE_FILE))) {
1706
1944
  return false;
1707
1945
  }
1708
1946
  const persisted = readPersisted(directory);
@@ -1753,11 +1991,11 @@ function isLockContentionError(err) {
1753
1991
  return INDEX_LOCK_ERROR_RE.test(msg);
1754
1992
  }
1755
1993
  async function commitTaskCompletion(directory, taskId, description, scopePaths) {
1756
- if (!_internals6.isGitRepo(directory)) {
1994
+ if (!_internals7.isGitRepo(directory)) {
1757
1995
  return { committed: false, reason: "no-git" };
1758
1996
  }
1759
1997
  try {
1760
- if (_internals6.hasExistingTaskCommit(directory, taskId)) {
1998
+ if (_internals7.hasExistingTaskCommit(directory, taskId)) {
1761
1999
  return { committed: true, reason: "idempotent-skip" };
1762
2000
  }
1763
2001
  } catch {}
@@ -1778,15 +2016,15 @@ async function commitTaskCompletion(directory, taskId, description, scopePaths)
1778
2016
  for (let attempt = 0;attempt <= INDEX_LOCK_BACKOFF_MS.length; attempt++) {
1779
2017
  try {
1780
2018
  if (paths.length > 0) {
1781
- _internals6.stageScopedPaths(directory, paths);
2019
+ _internals7.stageScopedPaths(directory, paths);
1782
2020
  }
1783
- _internals6.commitAllowEmpty(directory, message);
1784
- const sha = _internals6.gitHeadSha(directory);
2021
+ _internals7.commitAllowEmpty(directory, message);
2022
+ const sha = _internals7.gitHeadSha(directory);
1785
2023
  return { committed: true, reason: "success", sha };
1786
2024
  } catch (err) {
1787
2025
  lastError = err;
1788
2026
  if (attempt < INDEX_LOCK_BACKOFF_MS.length && isLockContentionError(err)) {
1789
- await _internals6.sleep(INDEX_LOCK_BACKOFF_MS[attempt]);
2027
+ await _internals7.sleep(INDEX_LOCK_BACKOFF_MS[attempt]);
1790
2028
  continue;
1791
2029
  }
1792
2030
  break;
@@ -1796,7 +2034,7 @@ async function commitTaskCompletion(directory, taskId, description, scopePaths)
1796
2034
  criticalWarn(`[epic:task-commit] commit for task ${taskId} failed (non-fatal): ${msg}`);
1797
2035
  return { committed: false, reason: "commit-failed", error: msg };
1798
2036
  }
1799
- var _internals6 = {
2037
+ var _internals7 = {
1800
2038
  isGitRepo: (cwd) => isGitRepo(cwd),
1801
2039
  stageScopedPaths: (cwd, paths) => {
1802
2040
  const CHUNK = 200;
@@ -1828,7 +2066,7 @@ var _internals6 = {
1828
2066
  };
1829
2067
 
1830
2068
  // src/turbo/lean/conflicts.ts
1831
- import * as fs3 from "fs";
2069
+ import * as fs4 from "fs";
1832
2070
  import * as path6 from "path";
1833
2071
 
1834
2072
  // src/utils/path.ts
@@ -1959,10 +2197,10 @@ function isProtectedPath(normalizedPath) {
1959
2197
  function readTaskScopes(directory, taskId) {
1960
2198
  const scopePath = path6.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
1961
2199
  try {
1962
- if (!fs3.existsSync(scopePath)) {
2200
+ if (!fs4.existsSync(scopePath)) {
1963
2201
  return null;
1964
2202
  }
1965
- const raw = fs3.readFileSync(scopePath, "utf-8");
2203
+ const raw = fs4.readFileSync(scopePath, "utf-8");
1966
2204
  const parsed = JSON.parse(raw);
1967
2205
  if (!parsed || !Array.isArray(parsed.files)) {
1968
2206
  return null;
@@ -1974,17 +2212,17 @@ function readTaskScopes(directory, taskId) {
1974
2212
  }
1975
2213
 
1976
2214
  // src/utils/spec-hash.ts
1977
- import { createHash } from "crypto";
2215
+ import { createHash as createHash2 } from "crypto";
1978
2216
  import * as fsSync2 from "fs";
1979
2217
  import { join as join5 } from "path";
1980
2218
  async function computeSpecHash(directory) {
1981
- const spec = _internals7.readEffectiveSpecSync(directory);
2219
+ const spec = _internals8.readEffectiveSpecSync(directory);
1982
2220
  if (!spec)
1983
2221
  return null;
1984
- return createHash("sha256").update(spec.content, "utf-8").digest("hex");
2222
+ return createHash2("sha256").update(spec.content, "utf-8").digest("hex");
1985
2223
  }
1986
2224
  async function isSpecStale(directory, plan) {
1987
- const currentHash = await _internals7.computeSpecHash(directory);
2225
+ const currentHash = await _internals8.computeSpecHash(directory);
1988
2226
  if (!plan.specHash) {
1989
2227
  return { stale: false };
1990
2228
  }
@@ -2013,7 +2251,7 @@ function isObligationPreserving(directory) {
2013
2251
  } catch {
2014
2252
  return false;
2015
2253
  }
2016
- const currentResult = _internals7.readEffectiveSpecSync(directory);
2254
+ const currentResult = _internals8.readEffectiveSpecSync(directory);
2017
2255
  if (!currentResult || !currentResult.content) {
2018
2256
  return false;
2019
2257
  }
@@ -2043,7 +2281,7 @@ function isObligationPreserving(directory) {
2043
2281
  return false;
2044
2282
  }
2045
2283
  }
2046
- var _internals7 = {
2284
+ var _internals8 = {
2047
2285
  computeSpecDiff,
2048
2286
  computeSpecHash,
2049
2287
  isObligationPreserving,
@@ -2063,7 +2301,7 @@ function computeSpecDiff(directory) {
2063
2301
  } catch {
2064
2302
  return null;
2065
2303
  }
2066
- const spec = _internals7.readEffectiveSpecSync(directory);
2304
+ const spec = _internals8.readEffectiveSpecSync(directory);
2067
2305
  if (!spec) {
2068
2306
  return null;
2069
2307
  }
@@ -2157,7 +2395,7 @@ var startupLedgerCheckedWorkspaces = new Set;
2157
2395
  var ledgerStaleWorkspaces = new Set;
2158
2396
  var recoveryMutexes = new Map;
2159
2397
  var PLAN_JSON_CACHE_NAMESPACE = "plan-json:validated:v1";
2160
- var _internals8 = {
2398
+ var _internals9 = {
2161
2399
  loadPlan,
2162
2400
  loadPlanJsonOnly,
2163
2401
  regeneratePlanMarkdown,
@@ -2165,7 +2403,8 @@ var _internals8 = {
2165
2403
  isEpicModeActiveForProject,
2166
2404
  readTaskScopes,
2167
2405
  commitTaskCompletion,
2168
- getWorktreeMergeFailure
2406
+ getWorktreeMergeFailure,
2407
+ recordTaskAttempt
2169
2408
  };
2170
2409
  var CAS_BACKOFF_START_MS = 5;
2171
2410
  var CAS_BACKOFF_CAP_MS = 250;
@@ -2406,7 +2645,7 @@ async function loadPlan(directory, cache) {
2406
2645
  const inSync = await isPlanMdInSync(directory, validated, cache);
2407
2646
  if (!inSync) {
2408
2647
  try {
2409
- await _internals8.regeneratePlanMarkdown(directory, validated);
2648
+ await _internals9.regeneratePlanMarkdown(directory, validated);
2410
2649
  } catch (regenError) {
2411
2650
  warn(`Failed to regenerate plan.md: ${regenError instanceof Error ? regenError.message : String(regenError)}. Proceeding with plan.json only.`);
2412
2651
  }
@@ -2572,7 +2811,7 @@ async function loadPlan(directory, cache) {
2572
2811
  const existingMutex = recoveryMutexes.get(resolvedDir);
2573
2812
  if (existingMutex) {
2574
2813
  await existingMutex;
2575
- const postRecoveryPlan = await _internals8.loadPlanJsonOnly(directory);
2814
+ const postRecoveryPlan = await _internals9.loadPlanJsonOnly(directory);
2576
2815
  if (postRecoveryPlan)
2577
2816
  return postRecoveryPlan;
2578
2817
  }
@@ -2632,7 +2871,7 @@ async function loadPlan(directory, cache) {
2632
2871
  return null;
2633
2872
  }
2634
2873
  async function savePlanWithAutoAcknowledgedRemovals(directory, plan, source, reason, options) {
2635
- const existing = await _internals8.loadPlanJsonOnly(directory);
2874
+ const existing = await _internals9.loadPlanJsonOnly(directory);
2636
2875
  const newIds = new Set;
2637
2876
  for (const phase of plan.phases) {
2638
2877
  for (const task of phase.tasks)
@@ -2660,7 +2899,7 @@ async function savePlan(directory, plan, options) {
2660
2899
  const validated = PlanSchema.parse(plan);
2661
2900
  if (options?.preserveCompletedStatuses !== false) {
2662
2901
  try {
2663
- const currentPlan2 = await _internals8.loadPlanJsonOnly(directory);
2902
+ const currentPlan2 = await _internals9.loadPlanJsonOnly(directory);
2664
2903
  if (currentPlan2) {
2665
2904
  const completedTaskIds = new Set;
2666
2905
  for (const phase of currentPlan2.phases) {
@@ -2682,7 +2921,7 @@ async function savePlan(directory, plan, options) {
2682
2921
  } catch {}
2683
2922
  }
2684
2923
  derivePhaseStatusesInPlace(validated);
2685
- const currentPlan = await _internals8.loadPlanJsonOnly(directory);
2924
+ const currentPlan = await _internals9.loadPlanJsonOnly(directory);
2686
2925
  const planId = derivePlanId(validated);
2687
2926
  const planHashForInit = computePlanHash(validated);
2688
2927
  if (!await ledgerExists(directory)) {
@@ -2827,7 +3066,7 @@ async function savePlan(directory, plan, options) {
2827
3066
  expectedHash: currentHash,
2828
3067
  planHashAfter: hashAfter,
2829
3068
  verifyValid: async () => {
2830
- const onDisk = await _internals8.loadPlanJsonOnly(directory);
3069
+ const onDisk = await _internals9.loadPlanJsonOnly(directory);
2831
3070
  if (!onDisk)
2832
3071
  return true;
2833
3072
  for (const p of onDisk.phases) {
@@ -2865,7 +3104,7 @@ async function savePlan(directory, plan, options) {
2865
3104
  expectedHash: currentHash,
2866
3105
  planHashAfter: hashAfter,
2867
3106
  verifyValid: async () => {
2868
- const onDisk = await _internals8.loadPlanJsonOnly(directory);
3107
+ const onDisk = await _internals9.loadPlanJsonOnly(directory);
2869
3108
  if (!onDisk)
2870
3109
  return true;
2871
3110
  for (const p of onDisk.phases) {
@@ -3151,6 +3390,10 @@ Phase: ${currentPhase} [${phaseStatus}] | Updated: ${now}
3151
3390
  const sortedDepends = [...task.depends].sort();
3152
3391
  suffix += ` (depends: ${sortedDepends.join(", ")})`;
3153
3392
  }
3393
+ if (task.files_touched.length > 0) {
3394
+ const sortedFiles = [...task.files_touched].sort();
3395
+ suffix += ` (files_touched: ${JSON.stringify(sortedFiles)})`;
3396
+ }
3154
3397
  if (phase.id === plan.current_phase && task.status === "in_progress" && !currentTaskMarked) {
3155
3398
  suffix += " \u2190 CURRENT";
3156
3399
  currentTaskMarked = true;
@@ -3387,12 +3630,12 @@ import {
3387
3630
  rmSync,
3388
3631
  statSync as statSync2
3389
3632
  } from "fs";
3390
- import * as fs6 from "fs/promises";
3633
+ import * as fs7 from "fs/promises";
3391
3634
  import * as os4 from "os";
3392
3635
  import * as path9 from "path";
3393
3636
 
3394
3637
  // src/evaluation/retention.ts
3395
- import * as fs4 from "fs/promises";
3638
+ import * as fs5 from "fs/promises";
3396
3639
  import * as path8 from "path";
3397
3640
  function artifactKey(artifact) {
3398
3641
  return `${artifact.namespace}/${artifact.id}`;
@@ -3404,7 +3647,7 @@ async function evaluationRunCandidates(directory) {
3404
3647
  const root = path8.join(directory, ".swarm", "evolution", "runs");
3405
3648
  let entries = [];
3406
3649
  try {
3407
- entries = await fs4.readdir(root, { withFileTypes: true });
3650
+ entries = await fs5.readdir(root, { withFileTypes: true });
3408
3651
  } catch (error2) {
3409
3652
  if (error2.code === "ENOENT") {
3410
3653
  return { candidates: [], corrupt: [] };
@@ -3422,7 +3665,7 @@ async function evaluationRunCandidates(directory) {
3422
3665
  const artifact = { namespace: "evaluation-run", id };
3423
3666
  const target = path8.join(root, entry.name);
3424
3667
  try {
3425
- const run = EvaluationRunV1Schema.parse(JSON.parse(await fs4.readFile(target, "utf8")));
3668
+ const run = EvaluationRunV1Schema.parse(JSON.parse(await fs5.readFile(target, "utf8")));
3426
3669
  if (run.runId !== id)
3427
3670
  throw new Error("run id/path mismatch");
3428
3671
  candidates.push({
@@ -3441,7 +3684,7 @@ async function gateAuditCandidates(directory) {
3441
3684
  const root = path8.join(directory, ".swarm", "evidence", "gate-audit");
3442
3685
  let entries = [];
3443
3686
  try {
3444
- entries = await fs4.readdir(root, { withFileTypes: true });
3687
+ entries = await fs5.readdir(root, { withFileTypes: true });
3445
3688
  } catch (error2) {
3446
3689
  if (error2.code === "ENOENT") {
3447
3690
  return { candidates: [], corrupt: [] };
@@ -3456,7 +3699,7 @@ async function gateAuditCandidates(directory) {
3456
3699
  const artifact = { namespace: "gate-audit", id: entry.name };
3457
3700
  const target = path8.join(root, entry.name);
3458
3701
  try {
3459
- const result = GateAuditResultV1Schema.parse(JSON.parse(await fs4.readFile(path8.join(target, "results.json"), "utf8")));
3702
+ const result = GateAuditResultV1Schema.parse(JSON.parse(await fs5.readFile(path8.join(target, "results.json"), "utf8")));
3460
3703
  if (result.runId !== entry.name)
3461
3704
  throw new Error("run id/path mismatch");
3462
3705
  candidates.push({
@@ -3487,10 +3730,10 @@ async function protectedArtifacts(directory) {
3487
3730
  }
3488
3731
  async function removeCandidate(candidate) {
3489
3732
  if (candidate.kind === "directory") {
3490
- await fs4.rm(candidate.target, { recursive: true, force: true });
3733
+ await fs5.rm(candidate.target, { recursive: true, force: true });
3491
3734
  return;
3492
3735
  }
3493
- await fs4.unlink(candidate.target);
3736
+ await fs5.unlink(candidate.target);
3494
3737
  }
3495
3738
  var _retentionInternals = {
3496
3739
  protectedArtifacts,
@@ -3546,7 +3789,7 @@ async function archiveEvaluationArtifacts(args) {
3546
3789
  }
3547
3790
 
3548
3791
  // src/evidence/documents-retention.ts
3549
- import * as fs5 from "fs";
3792
+ import * as fs6 from "fs";
3550
3793
  import * as fsp from "fs/promises";
3551
3794
  import * as readline from "readline";
3552
3795
  var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
@@ -3554,13 +3797,13 @@ var MAX_READ_BYTES = 100 * 1024 * 1024;
3554
3797
  var RENAME_MAX_ATTEMPTS = 5;
3555
3798
  var RENAME_BACKOFF_MS = 10;
3556
3799
  var RENAME_RETRY_CODES = new Set(["EPERM", "EBUSY", "ENOTEMPTY", "EACCES"]);
3557
- var _internals9 = {
3800
+ var _internals10 = {
3558
3801
  stat: (p) => fsp.stat(p),
3559
- createReadStream: (p, options) => fs5.createReadStream(p, options),
3560
- openSync: (p, flags) => fs5.openSync(p, flags),
3561
- writeSync: (fd, data, position) => fs5.writeSync(fd, data, position),
3562
- fsyncSync: (fd) => fs5.fsyncSync(fd),
3563
- closeSync: (fd) => fs5.closeSync(fd),
3802
+ createReadStream: (p, options) => fs6.createReadStream(p, options),
3803
+ openSync: (p, flags) => fs6.openSync(p, flags),
3804
+ writeSync: (fd, data, position) => fs6.writeSync(fd, data, position),
3805
+ fsyncSync: (fd) => fs6.fsyncSync(fd),
3806
+ closeSync: (fd) => fs6.closeSync(fd),
3564
3807
  renameWithRetry: atomicRenameWithRetry,
3565
3808
  unlink: (p) => fsp.unlink(p)
3566
3809
  };
@@ -3596,9 +3839,9 @@ function emptyResult(dryRun) {
3596
3839
  };
3597
3840
  }
3598
3841
  async function readCacheRows(filePath) {
3599
- const stat2 = await _internals9.stat(filePath);
3842
+ const stat2 = await _internals10.stat(filePath);
3600
3843
  const bytesBefore = stat2.size;
3601
- const stream = _internals9.createReadStream(filePath, {
3844
+ const stream = _internals10.createReadStream(filePath, {
3602
3845
  encoding: "utf8",
3603
3846
  highWaterMark: 64 * 1024
3604
3847
  });
@@ -3674,23 +3917,23 @@ async function rewriteAtomic(filePath, survivors) {
3674
3917
  `)}
3675
3918
  ` : "";
3676
3919
  let succeeded = false;
3677
- const fd = _internals9.openSync(tmpPath, "w");
3920
+ const fd = _internals10.openSync(tmpPath, "w");
3678
3921
  try {
3679
- _internals9.writeSync(fd, payload, 0);
3680
- _internals9.fsyncSync(fd);
3681
- _internals9.closeSync(fd);
3682
- await _internals9.renameWithRetry(tmpPath, filePath);
3922
+ _internals10.writeSync(fd, payload, 0);
3923
+ _internals10.fsyncSync(fd);
3924
+ _internals10.closeSync(fd);
3925
+ await _internals10.renameWithRetry(tmpPath, filePath);
3683
3926
  succeeded = true;
3684
3927
  } catch (err) {
3685
3928
  try {
3686
- _internals9.closeSync(fd);
3929
+ _internals10.closeSync(fd);
3687
3930
  } catch {}
3688
3931
  const msg = err instanceof Error ? err.message : String(err);
3689
3932
  throw new Error(`documents-cache rewrite failed: ${msg}`);
3690
3933
  } finally {
3691
3934
  if (!succeeded) {
3692
3935
  try {
3693
- await _internals9.unlink(tmpPath);
3936
+ await _internals10.unlink(tmpPath);
3694
3937
  } catch {}
3695
3938
  }
3696
3939
  }
@@ -3702,7 +3945,7 @@ async function pruneEvidenceDocuments(args) {
3702
3945
  const filePath = validateSwarmPath(args.directory, EVIDENCE_CACHE_FILE);
3703
3946
  let stat2;
3704
3947
  try {
3705
- stat2 = await _internals9.stat(filePath);
3948
+ stat2 = await _internals10.stat(filePath);
3706
3949
  } catch (err) {
3707
3950
  const code = err?.code;
3708
3951
  if (code === "ENOENT")
@@ -3879,11 +4122,11 @@ function validateProjectRoot(directory) {
3879
4122
  }
3880
4123
  }
3881
4124
  async function saveEvidence(directory, taskId, evidence) {
3882
- _internals10.validateProjectRoot(directory);
4125
+ _internals11.validateProjectRoot(directory);
3883
4126
  const sanitizedTaskId = sanitizeTaskId2(taskId);
3884
4127
  const relativePath = path9.join("evidence", sanitizedTaskId, "evidence.json");
3885
4128
  validateSwarmPath(directory, relativePath);
3886
- _internals10.validateEvidence(evidence);
4129
+ _internals11.validateEvidence(evidence);
3887
4130
  return withEvidenceLock(directory, relativePath, "evidence-manager", sanitizedTaskId, async () => {
3888
4131
  const evidencePath = validateSwarmPath(directory, relativePath);
3889
4132
  const evidenceDir = path9.dirname(evidencePath);
@@ -3932,7 +4175,7 @@ async function saveEvidence(directory, taskId, evidence) {
3932
4175
  const tempPath = path9.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
3933
4176
  try {
3934
4177
  await bunWrite(tempPath, bundleJson);
3935
- await fs6.rename(tempPath, evidencePath);
4178
+ await fs7.rename(tempPath, evidencePath);
3936
4179
  } catch (error2) {
3937
4180
  try {
3938
4181
  rmSync(tempPath, { force: true });
@@ -3989,7 +4232,7 @@ async function loadEvidence(directory, taskId, options) {
3989
4232
  return { status: "invalid_schema", errors: ["Invalid JSON"] };
3990
4233
  }
3991
4234
  if (isFlatRetrospective(parsed)) {
3992
- const wrappedBundle = _internals10.wrapFlatRetrospective(parsed, sanitizedTaskId);
4235
+ const wrappedBundle = _internals11.wrapFlatRetrospective(parsed, sanitizedTaskId);
3993
4236
  try {
3994
4237
  const validated = EvidenceBundleSchema.parse(wrappedBundle);
3995
4238
  if (options?.migrate === false) {
@@ -4002,7 +4245,7 @@ async function loadEvidence(directory, taskId, options) {
4002
4245
  const tempPath = path9.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
4003
4246
  try {
4004
4247
  await bunWrite(tempPath, bundleJson);
4005
- await fs6.rename(tempPath, evidencePath);
4248
+ await fs7.rename(tempPath, evidencePath);
4006
4249
  } catch (writeError) {
4007
4250
  try {
4008
4251
  rmSync(tempPath, { force: true });
@@ -4081,15 +4324,15 @@ async function checkRequirementCoverage(phase, directory) {
4081
4324
  const relativePath = path9.join("evidence", `req-coverage-phase-${phase}.json`);
4082
4325
  const absolutePath = path9.resolve(directory, ".swarm", relativePath);
4083
4326
  try {
4084
- await fs6.access(absolutePath);
4327
+ await fs7.access(absolutePath);
4085
4328
  return { exists: true, path: absolutePath };
4086
4329
  } catch {
4087
4330
  return { exists: false, path: absolutePath };
4088
4331
  }
4089
4332
  }
4090
4333
  async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
4091
- const taskIds = await _internals10.listEvidenceTaskIds(directory);
4092
- const cutoffDate = options?.now ? new Date(options.now) : _internals10.now();
4334
+ const taskIds = await _internals11.listEvidenceTaskIds(directory);
4335
+ const cutoffDate = options?.now ? new Date(options.now) : _internals11.now();
4093
4336
  cutoffDate.setDate(cutoffDate.getDate() - maxAgeDays);
4094
4337
  const cutoffIso = cutoffDate.toISOString();
4095
4338
  const selected = new Set;
@@ -4101,7 +4344,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
4101
4344
  for (const taskId of taskIds) {
4102
4345
  let result;
4103
4346
  try {
4104
- result = await _internals10.loadEvidence(directory, taskId);
4347
+ result = await _internals11.loadEvidence(directory, taskId);
4105
4348
  } catch {
4106
4349
  warn("archive: skipping corrupt or unreadable evidence for task", taskId);
4107
4350
  continue;
@@ -4129,7 +4372,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
4129
4372
  }
4130
4373
  if (!options?.dryRun) {
4131
4374
  for (const taskId of [...selected].sort()) {
4132
- const deleted = await _internals10.deleteEvidence(directory, taskId);
4375
+ const deleted = await _internals11.deleteEvidence(directory, taskId);
4133
4376
  if (deleted)
4134
4377
  archived.push(taskId);
4135
4378
  else
@@ -4155,7 +4398,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
4155
4398
  };
4156
4399
  if (typeof options?.cacheMaxBytes === "number" && options.cacheMaxBytes > 0 || typeof options?.cacheMaxRecords === "number" && options.cacheMaxRecords > 0) {
4157
4400
  try {
4158
- documentsCache = await _internals10.pruneEvidenceDocuments({
4401
+ documentsCache = await _internals11.pruneEvidenceDocuments({
4159
4402
  directory,
4160
4403
  maxBytes: options?.cacheMaxBytes,
4161
4404
  maxRecords: options?.cacheMaxRecords,
@@ -4183,7 +4426,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
4183
4426
  function validateEvidence(evidence) {
4184
4427
  return EvidenceSchema.parse(evidence);
4185
4428
  }
4186
- var _internals10 = {
4429
+ var _internals11 = {
4187
4430
  wrapFlatRetrospective,
4188
4431
  loadEvidence,
4189
4432
  listEvidenceTaskIds,
@@ -4305,4 +4548,4 @@ function mergeDurableGateEntriesFromEvidence(taskId, entries, evidence) {
4305
4548
  return merged;
4306
4549
  }
4307
4550
 
4308
- export { getExecutor, init_executor, MAX_TRANSIENT_RETRIES, isTransientSpawnError, transientBackoff, getGitRepositoryStatus, isGitRepo, getDefaultBaseBranch, resetToRemoteBranch, resetToMainAfterMerge, isStateUnreadable, loadEpicSessionState, isEpicModeActive, enableEpicMode, disableEpicMode, normalizePath, pathsConflict, isGlobalFile, isProtectedPath, readTaskScopes, computeSpecHash, loadPlanJsonOnly, loadPlan, savePlan, closePlanTerminalState, derivePlanMarkdown, isValidEvidenceType, sanitizeTaskId2 as sanitizeTaskId, validateProjectRoot, saveEvidence, loadEvidence, listEvidenceTaskIds, checkRequirementCoverage, archiveEvidence, readDurableGateEvidence, getDurableGateEvidenceStatus, getDurableGateEvidenceStatusForTask, mergeDurableGateEntriesFromEvidence };
4551
+ export { getExecutor, init_executor, MAX_TRANSIENT_RETRIES, isTransientSpawnError, transientBackoff, getGitRepositoryStatus, isGitRepo, getDefaultBaseBranch, resetToRemoteBranch, resetToMainAfterMerge, containsPathTraversal, containsControlChars, isStateUnreadable, loadEpicSessionState, isEpicModeActive, enableEpicMode, disableEpicMode, normalizePath, pathsConflict, isGlobalFile, isProtectedPath, readTaskScopes, computeSpecHash, loadPlanJsonOnly, loadPlan, savePlan, closePlanTerminalState, derivePlanMarkdown, isValidEvidenceType, sanitizeTaskId2 as sanitizeTaskId, validateProjectRoot, saveEvidence, loadEvidence, listEvidenceTaskIds, checkRequirementCoverage, archiveEvidence, readDurableGateEvidence, getDurableGateEvidenceStatus, getDurableGateEvidenceStatusForTask, mergeDurableGateEntriesFromEvidence };