opencode-swarm 7.189.0 → 7.190.1

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 (177) hide show
  1. package/README.md +42 -6
  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/agents/architect.d.ts +1 -1
  5. package/dist/background/completion-observer.d.ts +6 -0
  6. package/dist/cli/{auto-checkpoint-m7c4x8bk.js → auto-checkpoint-26m3h5f4.js} +9 -9
  7. package/dist/cli/{checkpoint-m7q9886q.js → checkpoint-7a0achpv.js} +18 -20
  8. package/dist/cli/{coder-settlement-hh81z2f7.js → coder-settlement-dsb1t39t.js} +13 -13
  9. package/dist/cli/{config-doctor-0rexy3xt.js → config-doctor-9txawzng.js} +23 -20
  10. package/dist/cli/{core-ays6stz4.js → core-kv7jz9ty.js} +4 -4
  11. package/dist/cli/{curation-policy-65ckmmd5.js → curation-policy-6p6fcfjb.js} +6 -6
  12. package/dist/cli/{curator-dfzkfgs0.js → curator-26yzg8wp.js} +44 -44
  13. package/dist/cli/{curator-drift-nts5atks.js → curator-drift-kxn5sk3z.js} +9 -9
  14. package/dist/cli/curator-llm-factory-hs2y9kmw.js +82 -0
  15. package/dist/cli/{doctor-knowledge-receipt-phase-id-ec40k5hn.js → doctor-knowledge-receipt-phase-id-z8wea03e.js} +9 -9
  16. package/dist/cli/{evidence-summary-service-vgtm72g5.js → evidence-summary-service-bg5zq78s.js} +21 -22
  17. package/dist/cli/{gate-evidence-vmn65kxe.js → gate-evidence-0beg9c7r.js} +8 -8
  18. package/dist/cli/guardrail-explain-n8bm0hpm.js +83 -0
  19. package/dist/cli/{guardrail-log-hc8fjm4x.js → guardrail-log-r2zazmbn.js} +8 -8
  20. package/dist/cli/{guardrail-reset-ct00w300.js → guardrail-reset-0q54t44w.js} +44 -44
  21. package/dist/cli/{hive-promoter-2xax6van.js → hive-promoter-7dr5b9zv.js} +44 -44
  22. package/dist/cli/{index-9gqb5nkj.js → index-0gve0mkj.js} +4 -4
  23. package/dist/cli/{index-34vsyj15.js → index-0yrg10jx.js} +5 -5
  24. package/dist/cli/{index-mfxef20k.js → index-0z8vdkvg.js} +4 -4
  25. package/dist/cli/{index-2nexf5vz.js → index-1f084tqn.js} +22223 -15395
  26. package/dist/cli/{index-qx3g1bbe.js → index-26e2s6r1.js} +1 -1
  27. package/dist/cli/{index-kqegvngt.js → index-2c47efpt.js} +4 -4
  28. package/dist/cli/{index-9tvjwv01.js → index-2fpv2wmc.js} +1 -1
  29. package/dist/cli/{index-8q8783g0.js → index-3zwhxk98.js} +1 -1
  30. package/dist/cli/{index-9j3ybyfs.js → index-4a15347d.js} +7 -7
  31. package/dist/cli/{index-5cfhwd65.js → index-67a6mk20.js} +2 -2
  32. package/dist/cli/{index-d3rjvm9e.js → index-7vnr5cmp.js} +2 -2
  33. package/dist/cli/{index-twb3f4tk.js → index-8bx6vhzk.js} +1 -1
  34. package/dist/cli/{index-0gejy4cx.js → index-ay8ggtgr.js} +2 -2
  35. package/dist/cli/{index-8xabhfwr.js → index-b2j231jy.js} +2 -2
  36. package/dist/cli/{index-cbqkag7q.js → index-bcwmn4d7.js} +3 -3
  37. package/dist/cli/{index-fbgjj7h5.js → index-bfyh3gpe.js} +101 -13
  38. package/dist/cli/{index-skdpgjar.js → index-cewpxcwm.js} +862 -1221
  39. package/dist/cli/{index-bzbxn24k.js → index-dbdkh7pq.js} +5 -5
  40. package/dist/cli/{index-w4zscz6p.js → index-dnp4qtpf.js} +5 -5
  41. package/dist/cli/{index-waxvpwbv.js → index-efztf4yw.js} +127 -13
  42. package/dist/cli/{index-4p3jh14t.js → index-enq166kw.js} +4 -4
  43. package/dist/cli/{index-g03m5jhw.js → index-f46dbyew.js} +3 -3
  44. package/dist/cli/{index-ntda6tje.js → index-feaxsjrt.js} +10 -2
  45. package/dist/cli/{index-89f56ej4.js → index-fthhppnc.js} +46 -46
  46. package/dist/cli/{index-wqa31xnf.js → index-gqb8etv4.js} +7 -7
  47. package/dist/cli/{index-1cwmj1gs.js → index-ha0w0a7t.js} +77 -16
  48. package/dist/cli/{index-nhsafbrh.js → index-hx1fmywk.js} +5 -5
  49. package/dist/cli/{index-kaqdzhj3.js → index-kfevm0n5.js} +2 -2
  50. package/dist/cli/{index-z29hksyw.js → index-m28dzyy8.js} +26 -10
  51. package/dist/cli/{index-x1eh2636.js → index-mcv0v2dp.js} +1 -1
  52. package/dist/cli/{index-9czp2dcg.js → index-mjfpaxw3.js} +7 -7
  53. package/dist/cli/{index-f6exny9m.js → index-n8q43eff.js} +2 -2
  54. package/dist/cli/{index-7hr5m7yp.js → index-nkgzkt7c.js} +1 -1
  55. package/dist/cli/{index-p2tqzwh6.js → index-qs9myayh.js} +5 -10
  56. package/dist/cli/{index-hh7pa3yk.js → index-r9yvpr2m.js} +2 -2
  57. package/dist/cli/{index-cdjxzs2r.js → index-rjzn7hf0.js} +7 -7
  58. package/dist/cli/{index-zfbxfm2m.js → index-s8b67e6h.js} +33 -12
  59. package/dist/cli/{index-bskex45z.js → index-s9cgnd2z.js} +2 -2
  60. package/dist/cli/{index-cj4mp0fm.js → index-sc7t1tev.js} +6 -6
  61. package/dist/cli/{index-3dx0c7ve.js → index-sfjpbnqs.js} +44 -44
  62. package/dist/cli/{index-16m2m4ah.js → index-spgfs5y7.js} +1 -1
  63. package/dist/cli/{index-q9kefh33.js → index-sxj143a4.js} +1 -1
  64. package/dist/cli/{index-zsrtt42s.js → index-v3bmwmqw.js} +25 -1
  65. package/dist/cli/{index-5v09zw1q.js → index-v3j9fk16.js} +18 -8
  66. package/dist/cli/{index-2btybj8w.js → index-xdq6mak1.js} +4 -4
  67. package/dist/cli/{index-k8sarme1.js → index-y9v41185.js} +1 -1
  68. package/dist/cli/{index-4a7j5f60.js → index-yy5yyyst.js} +4 -4
  69. package/dist/cli/{index-1xa8wq76.js → index-z3ahy9c2.js} +2 -2
  70. package/dist/cli/{index-wrdktgpy.js → index-zk6ttjkt.js} +2 -2
  71. package/dist/cli/index.js +45 -45
  72. package/dist/cli/{knowledge-escalator-v3c8w86g.js → knowledge-escalator-hdrqt5pj.js} +15 -15
  73. package/dist/cli/{knowledge-events-kagaccj9.js → knowledge-events-ttebc8gn.js} +13 -13
  74. package/dist/cli/{knowledge-link-h4pdcnya.js → knowledge-link-6hw3z6wn.js} +5 -5
  75. package/dist/cli/{knowledge-store-ywxjk5pb.js → knowledge-store-8cxv6w2n.js} +6 -6
  76. package/dist/cli/{knowledge-validator-210gkpec.js → knowledge-validator-kr5xmqpa.js} +8 -8
  77. package/dist/cli/{mcp-58hgx6av.js → mcp-jtk79ygp.js} +1 -1
  78. package/dist/cli/{model-preflight-e69b48n0.js → model-preflight-d6tt7479.js} +44 -44
  79. package/dist/cli/{pending-delegations-g24d3qa9.js → pending-delegations-ttk09f50.js} +12 -12
  80. package/dist/cli/{pr-subscriptions-qprh2zsm.js → pr-subscriptions-2kbeezsr.js} +12 -12
  81. package/dist/cli/{pr-workflow-gate-pj7dhkv4.js → pr-workflow-gate-3ra6p7k4.js} +44 -44
  82. package/dist/cli/{runner-4hfmp1ag.js → runner-ssnsje35.js} +6 -6
  83. package/dist/cli/{scan-cursor-s5wsxxd1.js → scan-cursor-zzccy117.js} +7 -7
  84. package/dist/cli/{schema-smgngq9m.js → schema-9prswg1x.js} +14 -2
  85. package/dist/cli/{scope-persistence-tbv2ar4w.js → scope-persistence-eqm8vwnx.js} +16 -16
  86. package/dist/cli/{server-7p2ds5w2.js → server-swjre81h.js} +45 -45
  87. package/dist/cli/{skill-generator-r4hsne71.js → skill-generator-d8dk9vps.js} +17 -17
  88. package/dist/cli/{snapshot-coordination-init-ydjwh56d.js → snapshot-coordination-init-f49y0zr0.js} +44 -44
  89. package/dist/cli/{speckit-checkoff-aj75vmjq.js → speckit-checkoff-pnb6q9gd.js} +5 -5
  90. package/dist/cli/{telemetry-kvhe94gs.js → telemetry-9szfdfqv.js} +1 -1
  91. package/dist/cli/{workspace-snapshot-30kdf018.js → workspace-snapshot-9f12p1s1.js} +3 -3
  92. package/dist/cli/{worktree-collision-ownership-0bxj9f0t.js → worktree-collision-ownership-3c7xyc4p.js} +14 -14
  93. package/dist/cli/{worktree-isolation-h0c22pm2.js → worktree-isolation-jggdf28m.js} +46 -44
  94. package/dist/commands/coupling.d.ts +21 -4
  95. package/dist/commands/epic-learning.d.ts +28 -0
  96. package/dist/commands/epic.d.ts +81 -36
  97. package/dist/commands/registry.d.ts +8 -8
  98. package/dist/commands/turbo.d.ts +16 -1
  99. package/dist/config/constants.d.ts +11 -1
  100. package/dist/config/loader.d.ts +2 -0
  101. package/dist/config/schema.d.ts +291 -77
  102. package/dist/db/coordination-store.d.ts +6 -0
  103. package/dist/epic/close.d.ts +209 -0
  104. package/dist/{turbo/epic → epic}/cochange-conflict.d.ts +5 -4
  105. package/dist/{turbo/epic → epic}/cochange-source.d.ts +10 -1
  106. package/dist/epic/components.d.ts +238 -0
  107. package/dist/epic/config-gate.d.ts +25 -0
  108. package/dist/epic/config.d.ts +101 -0
  109. package/dist/{turbo/epic → epic}/coupling-report.d.ts +3 -1
  110. package/dist/epic/declared-scopes.d.ts +37 -0
  111. package/dist/epic/epic-branch.d.ts +157 -0
  112. package/dist/epic/gate-policy.d.ts +114 -0
  113. package/dist/epic/git-once.d.ts +26 -0
  114. package/dist/epic/learning-store.d.ts +176 -0
  115. package/dist/epic/learning.d.ts +198 -0
  116. package/dist/epic/legacy-migration.d.ts +26 -0
  117. package/dist/epic/lifecycle.d.ts +437 -0
  118. package/dist/epic/markers.d.ts +123 -0
  119. package/dist/epic/merge-epoch.d.ts +90 -0
  120. package/dist/epic/next-wave-format.d.ts +101 -0
  121. package/dist/epic/next-wave.d.ts +102 -0
  122. package/dist/epic/phase-readiness.d.ts +221 -0
  123. package/dist/epic/plan-key.d.ts +104 -0
  124. package/dist/epic/plan-shaping-seam.d.ts +112 -0
  125. package/dist/epic/planning-signals.d.ts +38 -0
  126. package/dist/epic/report.d.ts +152 -0
  127. package/dist/epic/residue-commit.d.ts +151 -0
  128. package/dist/epic/scorecard.d.ts +130 -0
  129. package/dist/epic/shaping-sizing.d.ts +108 -0
  130. package/dist/epic/shaping-suggestions.d.ts +172 -0
  131. package/dist/epic/shaping.d.ts +112 -0
  132. package/dist/epic/sizing.d.ts +60 -0
  133. package/dist/epic/start.d.ts +187 -0
  134. package/dist/epic/task-landing.d.ts +83 -0
  135. package/dist/epic/wave-close.d.ts +112 -0
  136. package/dist/epic/wave-select.d.ts +95 -0
  137. package/dist/evaluation/contracts.d.ts +1 -1
  138. package/dist/evaluation/public-api.d.ts +1 -1
  139. package/dist/full-auto/policy.d.ts +12 -1
  140. package/dist/hooks/delegation-gate/worktree-isolation.d.ts +16 -0
  141. package/dist/hooks/delegation-gate.d.ts +11 -0
  142. package/dist/hooks/guardrails/index.d.ts +7 -0
  143. package/dist/hooks/promotion-evidence-store.d.ts +2 -2
  144. package/dist/index.js +814 -807
  145. package/dist/plan/manager.d.ts +6 -8
  146. package/dist/plan/parallel-verdict.d.ts +13 -2
  147. package/dist/retention/caps.d.ts +1 -1
  148. package/dist/review/contracts.d.ts +8 -1
  149. package/dist/services/config-doctor.d.ts +38 -0
  150. package/dist/session/snapshot-reader.d.ts +2 -0
  151. package/dist/session/snapshot-writer.d.ts +13 -2
  152. package/dist/state.d.ts +13 -18
  153. package/dist/tools/epic-next-wave.d.ts +20 -0
  154. package/dist/tools/epic-phase-review.d.ts +43 -0
  155. package/dist/tools/index.d.ts +2 -3
  156. package/dist/tools/manifest.d.ts +2 -3
  157. package/dist/tools/phase-complete.d.ts +5 -1
  158. package/dist/tools/save-plan.d.ts +7 -0
  159. package/dist/tools/tool-metadata.d.ts +4 -8
  160. package/dist/worktree/merge.d.ts +14 -1
  161. package/opencode-swarm.schema.json +273 -28
  162. package/package.json +1 -1
  163. package/dist/cli/curator-llm-factory-nrn6n2p1.js +0 -82
  164. package/dist/cli/guardrail-explain-9jmr8ezt.js +0 -83
  165. package/dist/tools/epic-plan-waves.d.ts +0 -79
  166. package/dist/tools/epic-record-divergence.d.ts +0 -73
  167. package/dist/tools/epic-run-phase.d.ts +0 -179
  168. package/dist/turbo/epic/activation.d.ts +0 -193
  169. package/dist/turbo/epic/calibration-engine.d.ts +0 -88
  170. package/dist/turbo/epic/calibration.d.ts +0 -80
  171. package/dist/turbo/epic/divergence-recorder.d.ts +0 -123
  172. package/dist/turbo/epic/index.d.ts +0 -24
  173. package/dist/turbo/epic/promotion-evidence.d.ts +0 -42
  174. package/dist/turbo/epic/state.d.ts +0 -69
  175. package/dist/turbo/epic/task-commit.d.ts +0 -110
  176. package/dist/turbo/epic/upstream-commits.d.ts +0 -82
  177. package/dist/turbo/epic/wave-planner.d.ts +0 -83
@@ -0,0 +1,187 @@
1
+ /**
2
+ * `/swarm epic start` orchestration (Epic v2 C1a).
3
+ *
4
+ * Refusals, checked in this order (the first one wins):
5
+ * 1. epic-disabled-by-config `epic.mode.enabled !== true` (fail closed)
6
+ * 2. no-plan / plan-ledger-unreadable
7
+ * 3. epic-state-unreadable, then an existing epic: the same plan ⇒
8
+ * `already-open` (idempotent success, not a refusal), another plan ⇒
9
+ * epic-open-for-other-plan
10
+ * 4. turbo-active config `turbo_mode: true`, any in-memory
11
+ * session with Turbo on, or a running durable
12
+ * Lean run (read without migrating Lean state)
13
+ * 5. dirty-baseline git only: changes outside `.swarm/`
14
+ * detached-head git + epic-branch policy: HEAD is detached
15
+ * (or the branch has no commit yet)
16
+ * epic-branch-exists git + epic-branch policy:
17
+ * `swarm/epic/<epicKey>` already exists (left
18
+ * by an earlier, abandoned epic of this plan)
19
+ * 6. in-flight-coders project-wide (see `findInFlightCoderWork`)
20
+ * 7. not-epic-sized sizing verdict (`--force` overrides; recorded)
21
+ * 8. branch-create-failed `git checkout -b` failed after the row was
22
+ * created — row and sentinel rolled back
23
+ *
24
+ * Learning (Epic v2 C6, `epic.learning.enabled` not false): before
25
+ * the sizing dry-run the Epic v1 calibration files are imported into the
26
+ * project prior once (`learning-store.ts`); the sizing plans with the
27
+ * prior's learned signals; the record keeps the prior's digest
28
+ * (`priorDigest`) and, once the epic is open, the epic's posterior starts
29
+ * as a copy of that prior.
30
+ *
31
+ * Commit policy (`epic.commit_policy`, default `epic-branch`): after
32
+ * the CAS create a git epic checks out `swarm/epic/<epicKey>` and records it
33
+ * (`git.epicBranch`) only once the checkout succeeded (M-e). Non-git
34
+ * projects (always `current-branch`) may open an epic but run it serially
35
+ * (maxParallel 1, M-i).
36
+ */
37
+ import { readDelegationsDetailed } from '../background/pending-delegations.js';
38
+ import { loadPluginConfigWithMeta } from '../config/index.js';
39
+ import type { Plan } from '../config/plan-schema.js';
40
+ import type { PluginConfig } from '../config/schema.js';
41
+ import { scanWorktreeProvisioningOwnersForRecovery } from '../hooks/delegation-gate/worktree-provisioning-owner.js';
42
+ import { scanWorktreeRecoveryAuthoritiesForRecovery } from '../hooks/delegation-gate/worktree-recovery-authority.js';
43
+ import { readPlanEpochIdentity } from '../plan/ledger.js';
44
+ import { loadPlanJsonOnly } from '../plan/manager.js';
45
+ import { listRecoveryRecords, recoveryReadErrored } from '../turbo/lean/recovery.js';
46
+ import { listCoderSettlementWalStates } from '../workflow/coder-settlement.js';
47
+ import { getCoChangeData } from './cochange-source.js';
48
+ import { resolveEpicDeclaredScopes } from './declared-scopes.js';
49
+ import { checkoutNewEpicBranch, localBranchExists, readCurrentBranch, undoEpicBranchCreate } from './epic-branch.js';
50
+ import { type EpicPriorRead, importLegacyEpicCalibrationOnce, initEpicPosterior, loadEpicLearningView, readEpicPrior } from './learning-store.js';
51
+ import { createEpicRecord, deleteEpicState, type EpicRecordV1, inspectEpic, recordEpicBranch } from './lifecycle.js';
52
+ import { syncEpicRefs } from './markers.js';
53
+ import { type EpicPlanningSignals } from './planning-signals.js';
54
+ import { type EpicShapingReport, shapeEpicPlan } from './shaping.js';
55
+ import type { EpicSizingVerdict } from './sizing.js';
56
+ export type EpicStartRefusal = 'epic-disabled-by-config' | 'host-unsupported' | 'no-plan' | 'plan-ledger-unreadable' | 'epic-open-for-other-plan' | 'epic-state-unreadable' | 'turbo-active' | 'dirty-baseline' | 'detached-head' | 'epic-branch-exists' | 'in-flight-coders' | 'not-epic-sized' | 'branch-create-failed';
57
+ /** What the started epic inherited from the project prior. */
58
+ export interface EpicStartLearning {
59
+ enabled: boolean;
60
+ prior: EpicPriorRead['status'];
61
+ /** Learned files / co-write edges / hot files in the inherited prior. */
62
+ files: number;
63
+ coWrites: number;
64
+ hotFiles: number;
65
+ /** The one-time Epic v1 import done by this start, if any. */
66
+ imported: {
67
+ calibrationHotModules: number;
68
+ divergenceRecords: number;
69
+ } | null;
70
+ }
71
+ export type EpicStartResult = {
72
+ status: 'started';
73
+ record: EpicRecordV1;
74
+ learning: EpicStartLearning;
75
+ } | {
76
+ status: 'already-open';
77
+ record: EpicRecordV1;
78
+ } | {
79
+ status: 'refused';
80
+ reason: EpicStartRefusal;
81
+ details: string[];
82
+ sizing?: EpicSizingVerdict;
83
+ /** Plan shaping advisory (`not-epic-sized` only; Epic v2 C7). */
84
+ shaping?: EpicShapingReport;
85
+ };
86
+ export interface EpicStartOptions {
87
+ directory: string;
88
+ sessionID: string;
89
+ force: boolean;
90
+ }
91
+ /**
92
+ * Why `/swarm epic start` refuses on a host without an OpenCode SDK client.
93
+ * Every git-epic coder needs worktree isolation and every phase needs the
94
+ * `epic_phase_review` dispatch, and both create sessions through that client
95
+ * (`worktree-isolation.ts` STANDARD_WORKTREE_ISOLATION_UNAVAILABLE,
96
+ * `src/review/contracts.ts`). The OpenCode 2 adapter initializes the plugin
97
+ * with `client: undefined` (`src/host/v2/setup.ts`), so an epic there could
98
+ * neither dispatch a coder nor complete a phase.
99
+ */
100
+ export declare const EPIC_HOST_UNSUPPORTED_MESSAGE = "This OpenCode host gives the plugin no SDK client (OpenCode 2 does not yet, see docs/host/v2-hook-inventory.md). Epic needs it for worktree-isolated coders and for the epic_phase_review reviewer/critic, so an epic here could neither run its coders nor complete a phase. Run the plan in Balanced, or use an OpenCode 1.x host (1.18.29+).";
101
+ /** Durable Lean run marked `running` — read without the migrating Lean reader. */
102
+ declare function findRunningLeanRun(directory: string): string | null;
103
+ /** Why Turbo blocks the start, or null (M-a). */
104
+ export declare function findTurboActivity(directory: string, config: Pick<PluginConfig, 'turbo_mode'>): string[];
105
+ /** Changes outside `.swarm/` (git only). Throws when git fails. */
106
+ export declare function findDirtyBaseline(directory: string): string[];
107
+ /**
108
+ * Project-wide in-flight coder work (MINOR 2), read-only:
109
+ * - tracked standard worktree dispatches / lanes awaiting merge-back
110
+ * (in-memory, this process);
111
+ * - non-terminal durable background delegations;
112
+ * - unsettled coder settlement WALs (DISPATCHED / PREPARED / unreadable);
113
+ * - preserved Lean recovery lanes, preserved/claimed worktree recovery
114
+ * authorities, and lanes being provisioned.
115
+ * Uncertain stores fail closed (reported as in flight).
116
+ */
117
+ export declare function findInFlightCoderWork(directory: string): Promise<string[]>;
118
+ /**
119
+ * Sizing inputs from the plan: pending tasks, scoped tasks, and the serial
120
+ * step count L of a dry run of the Epic component planner
121
+ * (`components.ts`, the planner `epic_next_wave` issues waves with) over
122
+ * every phase, under `maxParallel`, over the estimated scopes and the same
123
+ * planning signals (learned hot files and co-writes, co-change, density
124
+ * threshold). L = waves
125
+ * + tasks the planner can never schedule (a dependency cycle). Cross-phase
126
+ * dependencies count as satisfied (phases run in order). The computation
127
+ * is `sizeEpicPlan` (`shaping-sizing.ts`), shared with plan shaping, bounded
128
+ * by {@link MAX_START_SIZING_WORK} (beyond it the remaining tasks count as
129
+ * serial — a pessimistic L).
130
+ */
131
+ export declare function computeEpicSizing(directory: string, plan: Plan, config: PluginConfig, maxParallel: number, signals: EpicPlanningSignals): EpicSizingVerdict;
132
+ /**
133
+ * Phases already finished when the epic starts (every task completed or
134
+ * closed, or the phase closed) are recorded complete: `epic_next_wave`
135
+ * starts at the first unfinished phase. Later phases become complete only
136
+ * through `phase_complete` (phases are iterations).
137
+ */
138
+ export declare function initialEpicPhases(plan: Plan): EpicRecordV1['phases'];
139
+ export declare function startEpic(options: EpicStartOptions): Promise<EpicStartResult>;
140
+ /**
141
+ * DI seam (AGENTS.md invariant 7) — tests replace collaborators without
142
+ * `mock.module`. Restore in `afterEach`.
143
+ */
144
+ export declare const _internals: {
145
+ loadPluginConfigWithMeta: typeof loadPluginConfigWithMeta;
146
+ loadPlanJsonOnly: typeof loadPlanJsonOnly;
147
+ readPlanEpochIdentity: typeof readPlanEpochIdentity;
148
+ inspectEpic: typeof inspectEpic;
149
+ createEpicRecord: typeof createEpicRecord;
150
+ deleteEpicState: typeof deleteEpicState;
151
+ recordEpicBranch: typeof recordEpicBranch;
152
+ localBranchExists: typeof localBranchExists;
153
+ checkoutNewEpicBranch: typeof checkoutNewEpicBranch;
154
+ readCurrentBranch: typeof readCurrentBranch;
155
+ undoEpicBranchCreate: typeof undoEpicBranchCreate;
156
+ resolveEpicDeclaredScopes: typeof resolveEpicDeclaredScopes;
157
+ loadEpicLearningView: typeof loadEpicLearningView;
158
+ readEpicPrior: typeof readEpicPrior;
159
+ importLegacyEpicCalibrationOnce: typeof importLegacyEpicCalibrationOnce;
160
+ initEpicPosterior: typeof initEpicPosterior;
161
+ getCoChangeData: typeof getCoChangeData;
162
+ shapeEpicPlan: typeof shapeEpicPlan;
163
+ hasActiveTurboMode: () => boolean;
164
+ /**
165
+ * False only when the plugin was initialized on a host that supplies no
166
+ * SDK client: the v1 init stores the host client, the OpenCode 2 adapter
167
+ * stores `undefined`, and an uninitialized process (tests, scripts) keeps
168
+ * the initial `null` — which is not a host verdict, so it is allowed.
169
+ * Capability-based: once a v2 client is wired, Epic starts there too.
170
+ */
171
+ hostProvidesClient: () => boolean;
172
+ findRunningLeanRun: typeof findRunningLeanRun;
173
+ gitExec: (args: string[], cwd: string) => string;
174
+ getGitRepositoryStatus: (cwd: string) => import("../git/branch.js").GitRepositoryStatus;
175
+ /** In-memory worktree dispatches (lazy: the maps live in an import cycle). */
176
+ countTrackedWorktreeDispatches: () => number;
177
+ readDelegationsDetailed: typeof readDelegationsDetailed;
178
+ listCoderSettlementWalStates: typeof listCoderSettlementWalStates;
179
+ listRecoveryRecords: typeof listRecoveryRecords;
180
+ recoveryReadErrored: typeof recoveryReadErrored;
181
+ scanWorktreeRecoveryAuthoritiesForRecovery: typeof scanWorktreeRecoveryAuthoritiesForRecovery;
182
+ scanWorktreeProvisioningOwnersForRecovery: typeof scanWorktreeProvisioningOwnersForRecovery;
183
+ syncEpicRefs: typeof syncEpicRefs;
184
+ now: () => number;
185
+ newToken: () => string;
186
+ };
187
+ export {};
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Epic v2 C3 — how an epic task's coder work reaches the epic branch.
3
+ *
4
+ * Two seams in shared code rely on this module, both Epic-gated and both
5
+ * costing exactly one `existsSync` (the epic sentinel) when no epic is open:
6
+ *
7
+ * - `finishStandardWorktreeDispatch` (worktree-isolation.ts) asks
8
+ * {@link epicCommitLandingFor}: for a task of the open epic, on the epic
9
+ * branch, the lane lands as a real merge commit
10
+ * (`git merge --no-ff --no-edit -m <message>`, see `src/worktree/merge.ts`)
11
+ * whose message is `swarm(task <id>): <description>` + the plan's
12
+ * `Swarm-Plan:` trailer — instead of the default squash-unstaged landing.
13
+ * The work is therefore COMMITTED before `update_task_status(completed)`,
14
+ * so a rework coder (whose worktree is cut from HEAD) starts from it and
15
+ * its own landing no longer overlaps uncommitted bytes (critic B2).
16
+ * - the delegation gate's Epic dispatch policy (`gate-policy.ts`, C4)
17
+ * isolates every coder of an open git epic in a worktree (policy treated
18
+ * as `required`), whatever `parallelization_enabled`, the session's
19
+ * concurrency override or the preset say; when isolation cannot be
20
+ * provided the dispatch is refused with
21
+ * {@link epicIsolationDegradedMessage} instead of running un-isolated in
22
+ * the main tree (M-b).
23
+ *
24
+ * Non-git epics run serially in the main tree (one task per wave, M-i) and
25
+ * never reach the landing seam's Epic branch.
26
+ */
27
+ import { checkEpicBranch as checkEpicBranch_import } from './epic-branch.js';
28
+ import { gitExecOnce as gitExecOnce_import } from './git-once.js';
29
+ import { type EpicPlanTaskRef, type EpicRecordV1, epicSentinelExists as epicSentinelExists_import, getOpenEpic as getOpenEpic_import, readPlanTaskRef as readPlanTaskRef_import } from './lifecycle.js';
30
+ /** DI seam (AGENTS.md invariant 7). Restore in `afterEach`. */
31
+ export declare const _internals: {
32
+ epicSentinelExists: typeof epicSentinelExists_import;
33
+ getOpenEpic: typeof getOpenEpic_import;
34
+ readPlanTaskRef: typeof readPlanTaskRef_import;
35
+ checkEpicBranch: typeof checkEpicBranch_import;
36
+ gitExecOnce: typeof gitExecOnce_import;
37
+ };
38
+ /** An open epic and one of its plan's tasks. */
39
+ export interface EpicTaskContext {
40
+ epic: EpicRecordV1;
41
+ task: EpicPlanTaskRef;
42
+ }
43
+ /**
44
+ * The open epic and the task, when `taskId` is a task of the plan the open
45
+ * epic is bound to; otherwise null. Sentinel first: one `existsSync` and
46
+ * nothing else when no epic is open. Unreadable lifecycle state counts as
47
+ * "no epic" here (Epic behaviour is off until repaired; `/swarm epic
48
+ * status` reports it).
49
+ */
50
+ export declare function resolveEpicTaskContext(directory: string, taskId: string | null | undefined): EpicTaskContext | null;
51
+ /** The landing options an epic task's worktree merge-back uses. */
52
+ export interface EpicLandingOptions {
53
+ commitLanding: true;
54
+ landingCommitMessage: string;
55
+ }
56
+ /**
57
+ * The epic task must NOT be landed now: a committed merge requires the
58
+ * primary index to match HEAD, so unrelated staged entries would make it
59
+ * fail (and could be swept into the merge). `message` starts with
60
+ * `EPIC_LANDING_INDEX_DIRTY` and carries the remedy.
61
+ */
62
+ export interface EpicLandingRefusal {
63
+ refused: true;
64
+ stage: typeof EPIC_LANDING_INDEX_STAGE;
65
+ message: string;
66
+ }
67
+ /** Merge-failure stage recorded for an {@link EpicLandingRefusal}. */
68
+ export declare const EPIC_LANDING_INDEX_STAGE = "epic-landing-index";
69
+ /**
70
+ * Landing override for a worktree coder of `planTaskId`: a committed landing
71
+ * with the Epic task message when the task belongs to the open git epic and
72
+ * HEAD is on the epic's branch. Undefined otherwise — the caller keeps its
73
+ * own (default) landing. A branch mismatch also yields undefined: the work
74
+ * must never be COMMITTED onto a foreign branch; `epic_next_wave` blocks
75
+ * `epic-branch-mismatch` until HEAD is back.
76
+ */
77
+ export declare function epicCommitLandingFor(directory: string, planTaskId: string | null | undefined): EpicLandingOptions | EpicLandingRefusal | undefined;
78
+ /**
79
+ * Refusal text for an epic coder whose worktree dispatch could not be set
80
+ * up. It wraps ANY error of that setup (isolation, provisioning, lifecycle
81
+ * lock, …), so the original error is quoted verbatim.
82
+ */
83
+ export declare function epicIsolationDegradedMessage(taskId: string, reason: string): string;
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Epic v2 C2 — closing a wave.
3
+ *
4
+ * `epic_next_wave` closes the active wave once every task in it is resolved
5
+ * (plan status completed / closed, or removed from the plan) and none has a
6
+ * relevant worktree merge-back failure. Closing records, in the epic record:
7
+ *
8
+ * - `closeHead` (HEAD at close — every task's work is already committed:
9
+ * its coder's worktree landing is a merge commit and non-coder writes
10
+ * are residue commits, see `task-landing.ts` / `residue-commit.ts`);
11
+ * - one {@link EpicTaskOutcome} per wave task: resolution and time (plan
12
+ * ledger), evidence workflow generation, Stage A/B failure LOWER BOUNDS
13
+ * (the evidence `retryHistory` keeps only its last 3 entries), the merge
14
+ * failure snapshot observed while the wave was blocked, reopen count
15
+ * (ledger transitions out of `completed`), declared (frozen) and
16
+ * undeclared files, and the task's commit (`marker`: its newest
17
+ * `swarm(task <id>):` commit for this plan inside the wave, else the
18
+ * close HEAD) that `markers.ts` mirrors to `refs/swarm/epics/…/tasks/<id>`;
19
+ * - undeclared files (divergence), computed automatically: a task's actual files are its
20
+ * write attribution unioned across every same-project session (coder
21
+ * writes are attributed on the coder's CHILD session). When no session
22
+ * holds attribution the git fallback applies: files changed since the
23
+ * wave's `baseHead` (committed or not), attributed to the task only when it was the wave's single
24
+ * member, and otherwise kept at WAVE level (`wave.undeclared`) minus
25
+ * every declared and attributed file.
26
+ *
27
+ * After the close is committed, the epic's learning posterior applies the
28
+ * closed wave's outcomes once ({@link recordEpicWaveLearning},
29
+ * `learning-store.ts`): undeclared writes teach learned co-writes and,
30
+ * with merge conflicts, rework, Stage B failures and reopens, the decaying
31
+ * hot set the planner uses for later waves (`components.ts`). A failed
32
+ * update never blocks the wave flow; the next close (or the epic close)
33
+ * catches it up from the record.
34
+ */
35
+ import type { Plan } from '../config/plan-schema.js';
36
+ import type { PluginConfig } from '../config/schema.js';
37
+ import { readTaskEvidence as readTaskEvidence_import } from '../gate-evidence.js';
38
+ import { readLedgerEvents as readLedgerEvents_import } from '../plan/ledger.js';
39
+ import { hydrationProjectKey as hydrationProjectKey_import } from '../session/hydration-ownership.js';
40
+ import { type AgentSessionState, getAgentSession as getAgentSession_import, getModifiedFilesForTask as getModifiedFilesForTask_import, resetModifiedFilesForTask as resetModifiedFilesForTask_import } from '../state.js';
41
+ import { applyClosedWavesToPosterior as applyClosedWavesToPosterior_import } from './learning-store.js';
42
+ import type { EpicRecordV1, EpicTaskOutcome, EpicWaveRecord } from './lifecycle.js';
43
+ import { findTaskCommits as findTaskCommits_import } from './markers.js';
44
+ /** DI seam (AGENTS.md invariant 7). Restore in `afterEach`. */
45
+ export declare const _internals: {
46
+ gitExec: (args: string[], cwd: string) => string;
47
+ readTaskEvidence: typeof readTaskEvidence_import;
48
+ readLedgerEvents: typeof readLedgerEvents_import;
49
+ listAgentSessions: () => Iterable<[string, AgentSessionState]>;
50
+ getAgentSession: typeof getAgentSession_import;
51
+ getModifiedFilesForTask: typeof getModifiedFilesForTask_import;
52
+ resetModifiedFilesForTask: typeof resetModifiedFilesForTask_import;
53
+ hydrationProjectKey: typeof hydrationProjectKey_import;
54
+ applyClosedWavesToPosterior: typeof applyClosedWavesToPosterior_import;
55
+ findTaskCommits: typeof findTaskCommits_import;
56
+ };
57
+ export interface EpicWaveCloseComputation {
58
+ closeHead: string | null;
59
+ outcomes: EpicTaskOutcome[];
60
+ waveUndeclared: string[];
61
+ }
62
+ /**
63
+ * Files changed since `baseHead` — committed (`git diff baseHead HEAD`) or
64
+ * not (`git status`, untracked included) — outside `.swarm/`. Null when git
65
+ * fails or there is no base.
66
+ */
67
+ export declare function changedFilesSinceBase(directory: string, baseHead: string | null): string[] | null;
68
+ /**
69
+ * The task's write attribution unioned across the calling session and every
70
+ * session owned by the same project (read-only), canonicalized
71
+ * repo-relative. Sessions without an owning project key are never read
72
+ * (cross-project safety), except the calling session itself.
73
+ */
74
+ export declare function collectTaskAttribution(directory: string, callerSessionID: string | undefined, taskId: string): string[];
75
+ /**
76
+ * Compute everything a wave close records. Reads only (git, ledger,
77
+ * evidence, in-memory attribution); the caller CASes the result into the
78
+ * record with {@link applyWaveClose}.
79
+ */
80
+ export declare function computeWaveClose(args: {
81
+ directory: string;
82
+ epic: EpicRecordV1;
83
+ wave: EpicWaveRecord;
84
+ plan: Plan;
85
+ sessionID: string | undefined;
86
+ nowIso: string;
87
+ }): Promise<EpicWaveCloseComputation>;
88
+ /**
89
+ * Pure record mutation for a wave close. Returns the record unchanged when
90
+ * the wave is no longer the issued active wave (a concurrent close won).
91
+ */
92
+ export declare function applyWaveClose(record: EpicRecordV1, seq: number, computation: EpicWaveCloseComputation, nowIso: string): EpicRecordV1;
93
+ /**
94
+ * After a committed close (by the call that closed the wave): apply every
95
+ * closed wave's outcomes not applied yet to the epic's learning posterior
96
+ * (idempotent per wave seq, `learning-store.ts`) unless
97
+ * `epic.learning.enabled` is false. Never throws: a failure is a
98
+ * critical warning and the next update (or the epic close) catches it up.
99
+ */
100
+ export declare function recordEpicWaveLearning(args: {
101
+ directory: string;
102
+ config: PluginConfig;
103
+ record: EpicRecordV1;
104
+ }): number[];
105
+ /**
106
+ * Release the closed wave's retained write attribution (Epic retains
107
+ * completed-task attribution until its wave closes — see
108
+ * `completeModifiedFilesForTask`) in the calling session and in EVERY
109
+ * session owned by the same project (coder child sessions hold it too).
110
+ * Sessions of other projects are never touched. Best-effort.
111
+ */
112
+ export declare function releaseWaveAttribution(directory: string, sessionID: string | undefined, taskIds: readonly string[]): void;
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Epic v2 C2/C5 — choose the NEXT wave of the current phase.
3
+ *
4
+ * `epic_next_wave` issues one wave at a time. This module decides which
5
+ * tasks that wave contains with the Epic component planner
6
+ * (`components.ts`: conflict graph → components → modes → greedy wave). It
7
+ * never writes: the caller freezes the result into the epic record.
8
+ *
9
+ * Inputs and rules:
10
+ * - batch = the phase's tasks that are not completed / closed / blocked;
11
+ * - a dependency OUTSIDE the batch is satisfied only when that task is
12
+ * `completed` in the plan AND (under git) its commit is on the epic
13
+ * branch (`isCommitted`: its epic task ref is an ancestor of HEAD, see
14
+ * `markers.ts`, or it was completed before the epic started); a
15
+ * dependency on a closed or removed task, on a later-phase task, or a
16
+ * completed task without that evidence makes the dependent
17
+ * `predecessor-missing` (the plan must be fixed — it can never run);
18
+ * - scopes: the live `declare_scope` binding, else `files_touched` (an
19
+ * estimate); the chosen members must all have a live binding, otherwise
20
+ * the result is `declare-scopes` (suggested files = `files_touched`);
21
+ * - components over the batch: a task touching a global file, a
22
+ * protected path or a learned hot file (`learning.ts`), or with no
23
+ * usable scope, is exclusive and runs ALONE first; other tasks are
24
+ * grouped into conflict components (path ∪ co-change, the wave
25
+ * verdict's predicate, with each scope expanded by learned co-writes
26
+ * for the path half — stricter than the verdict, never looser) and a
27
+ * densely coupled component
28
+ * (`serial-component`) contributes at most one task per wave;
29
+ * - the wave records every batch task's component and each component's
30
+ * mode (`components`), shown by `/swarm epic status`; past waves'
31
+ * records age components so none starves.
32
+ */
33
+ import type { Plan } from '../config/plan-schema.js';
34
+ import type { LeanTurboConfig } from '../config/schema.js';
35
+ import { type EpicCochangeSignal, type EpicWaveComponents, type EpicWaveHistoryEntry } from './components.js';
36
+ import type { EpicCoWriteIndex } from './learning.js';
37
+ import type { EpicCochangePair } from './lifecycle.js';
38
+ /** Max co-change pairs frozen into one wave record. */
39
+ export declare const MAX_WAVE_COCHANGE_PAIRS = 256;
40
+ export interface EpicWaveSelectionInput {
41
+ directory: string;
42
+ plan: Plan;
43
+ phaseId: number;
44
+ /** Live declared scope per task (`[]` = no live binding). */
45
+ liveScopes: Record<string, string[]>;
46
+ maxParallel: number;
47
+ leanConfig: LeanTurboConfig;
48
+ /**
49
+ * Predecessor evidence for a completed out-of-batch task (git: its task
50
+ * ref is an ancestor of HEAD; non-git: always true). Precomputed by the
51
+ * caller, which maps a git failure to `git-failed`.
52
+ */
53
+ isCommitted: (taskId: string) => boolean;
54
+ /** Learned hot files (`learning.ts`); tasks declaring them run alone. */
55
+ hotFiles: readonly string[];
56
+ /** Learned co-writes expanding scopes in the conflict graph (null: none). */
57
+ coWrites: EpicCoWriteIndex | null;
58
+ /** Co-change signal (null = disabled by config). */
59
+ cochange: EpicCochangeSignal | null;
60
+ /** Intra-component density above which a component runs serially. */
61
+ densityThreshold: number;
62
+ /** This phase's earlier waves, oldest first (component ages). */
63
+ waveHistory: readonly EpicWaveHistoryEntry[];
64
+ }
65
+ export interface EpicPredecessorProblem {
66
+ taskId: string;
67
+ dependency: string;
68
+ why: 'removed' | 'closed' | 'later-phase' | 'not-committed' | 'cycle';
69
+ }
70
+ export type EpicWaveSelection = {
71
+ kind: 'wave';
72
+ waveKind: 'parallel' | 'exclusive' | 'serial-component';
73
+ taskIds: string[];
74
+ files: Record<string, string[]>;
75
+ cochangePairs: EpicCochangePair[];
76
+ components: EpicWaveComponents;
77
+ } | {
78
+ kind: 'declare-scopes';
79
+ tasks: {
80
+ taskId: string;
81
+ suggestedFiles: string[];
82
+ }[];
83
+ } | {
84
+ kind: 'task-blocked';
85
+ taskIds: string[];
86
+ } | {
87
+ kind: 'predecessor-missing';
88
+ problems: EpicPredecessorProblem[];
89
+ } | {
90
+ kind: 'none';
91
+ };
92
+ /** Threshold-passing pairs whose both files lie within `files`. */
93
+ export declare function cochangePairsWithin(files: readonly string[], cochange: EpicCochangeSignal): EpicCochangePair[];
94
+ /** Choose the next wave of `phaseId` (see the module header). */
95
+ export declare function selectNextEpicWave(input: EpicWaveSelectionInput): EpicWaveSelection;
@@ -279,8 +279,8 @@ export declare const PromotionDecisionV1Schema: z.ZodObject<{
279
279
  decidedAt: z.ZodISODateTime;
280
280
  status: z.ZodEnum<{
281
281
  inconclusive: "inconclusive";
282
- accept: "accept";
283
282
  reject: "reject";
283
+ accept: "accept";
284
284
  }>;
285
285
  reasons: z.ZodArray<z.ZodString>;
286
286
  baseline: z.ZodObject<{
@@ -33,7 +33,7 @@ export declare const evaluationV1: ((options: EvaluateCandidateV1Options) => Pro
33
33
  decisionId: string;
34
34
  runId: string;
35
35
  decidedAt: string;
36
- status: "inconclusive" | "accept" | "reject";
36
+ status: "inconclusive" | "reject" | "accept";
37
37
  reasons: string[];
38
38
  baseline: {
39
39
  baselineRunId: string;
@@ -65,7 +65,18 @@ export interface FullAutoClassifierInput {
65
65
  enabled?: boolean;
66
66
  };
67
67
  };
68
- turbo?: unknown;
68
+ turbo?: {
69
+ epic?: {
70
+ mode?: {
71
+ enabled?: boolean;
72
+ };
73
+ };
74
+ };
75
+ epic?: {
76
+ mode?: {
77
+ enabled?: boolean;
78
+ };
79
+ };
69
80
  skills?: {
70
81
  enabled?: boolean;
71
82
  };
@@ -9,6 +9,7 @@
9
9
  * The _internals seam allows test injection of worktree operations.
10
10
  */
11
11
  import type { PluginConfig, WorktreeIsolationConfig } from '../../config';
12
+ import { epicCommitLandingFor } from '../../epic/task-landing.js';
12
13
  import { tryAcquireLock } from '../../parallel/file-locks';
13
14
  import { bunSpawn } from '../../utils/bun-compat';
14
15
  import { resolveGitExecutable } from '../../utils/git-executable.js';
@@ -252,6 +253,13 @@ export declare function precreateStandardWorktreeSession(args: {
252
253
  taskId: string;
253
254
  files: string[];
254
255
  };
256
+ /**
257
+ * Epic v2 C3 (M-b): the coder belongs to the open epic, so an `auto`
258
+ * policy is treated as `required` — an isolation failure throws instead
259
+ * of degrading (serializing) the session to the main tree. Absent ⇒ the
260
+ * configured policy, unchanged.
261
+ */
262
+ isolationRequired?: boolean;
255
263
  }): Promise<void>;
256
264
  /**
257
265
  * Create a durable ownership tag without touching an in-flight background
@@ -338,6 +346,12 @@ options?: {
338
346
  * @param directory - The project root (required for git worktree/branch commands).
339
347
  */
340
348
  export declare function abortStandardWorktreeDispatch(callID: string, reason: 'denied' | 'cancelled', directory: string): Promise<void>;
349
+ /**
350
+ * Epic v2 C3: run `task` on the standard merge-back queue, so it never
351
+ * writes to the primary checkout's index concurrently with a worktree
352
+ * merge-back (Epic residue commits). Only Epic calls it.
353
+ */
354
+ export declare function runSerializedWithMergeBacks<T>(task: () => T | Promise<T>): Promise<T>;
341
355
  export declare function finishStandardWorktreeDispatch(directory: string, dispatch: StandardWorktreeDispatch, config?: PluginConfig,
342
356
  /**
343
357
  * Optional callID for cleanup of awaitingMergeByCallID. When omitted,
@@ -368,6 +382,8 @@ export declare function readLaneEnvFileFromDisk(worktreePath: string, laneIndex:
368
382
  * here via getters/setters) to mock worktree provisioning, merge-back, etc.
369
383
  */
370
384
  export declare const _internals: {
385
+ /** Epic v2 C3: committed landing for a task of the open epic. */
386
+ epicCommitLandingFor: typeof epicCommitLandingFor;
371
387
  provisionWorktree: typeof provisionWorktree;
372
388
  removeWorktree: typeof removeWorktree;
373
389
  attemptMergeBackFromDirty: typeof attemptMergeBackFromDirty;
@@ -9,6 +9,9 @@ import { deleteStageBDispatchBindings, readStageBDispatchBindings, recordStageBD
9
9
  import type { PluginConfig } from '../config';
10
10
  import { type Plan } from '../config/plan-schema';
11
11
  import { type QaGates } from '../db/qa-gate-profile.js';
12
+ import { resolveEpicDispatchPolicy, resolveEpicPrFeedbackConflict } from '../epic/gate-policy.js';
13
+ import { epicSentinelExists, isEpicOpenForProject } from '../epic/lifecycle.js';
14
+ import { commitEpicResidueAfterDelegation } from '../epic/residue-commit.js';
12
15
  import { loadPlanJsonOnly } from '../plan/manager';
13
16
  import type { AgentSessionState } from '../state';
14
17
  import type { DelegationEnvelope, EnvelopeValidationResult } from '../types/delegation.js';
@@ -518,6 +521,14 @@ declare function resolveEvidenceTaskId(args: Record<string, unknown> | undefined
518
521
  * that test mutations on this object propagate to the extracted module.
519
522
  */
520
523
  export declare const _internals: {
524
+ isEpicOpenForProject: typeof isEpicOpenForProject;
525
+ /** Epic v2 C4: wave-only coder admission + the wave's parallel/isolation policy. */
526
+ resolveEpicDispatchPolicy: typeof resolveEpicDispatchPolicy;
527
+ resolveEpicPrFeedbackConflict: typeof resolveEpicPrFeedbackConflict;
528
+ /** Epic v2 C3 (X1): commit a non-coder writer's residue for an epic task. */
529
+ commitEpicResidueAfterDelegation: typeof commitEpicResidueAfterDelegation;
530
+ /** Epic sentinel probe (one existsSync) gating the residue seam. */
531
+ epicSentinelExists: typeof epicSentinelExists;
521
532
  recordStageBDispatchBindings: typeof recordStageBDispatchBindings;
522
533
  readStageBDispatchBindings: typeof readStageBDispatchBindings;
523
534
  deleteStageBDispatchBindings: typeof deleteStageBDispatchBindings;
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { extractSwarmIdFromAgentName, getSwarmAgents, resolveFallbackModel } from '../../agents/index';
10
10
  import { type AuthorityConfig, type GuardrailsConfig } from '../../config/schema';
11
+ import { resolveEpicGateTaskAttribution } from '../../epic/gate-policy';
11
12
  import { assessSandboxEnforcement, getExecutor } from '../../sandbox/executor';
12
13
  import { dcCheckJunctionCreation } from './destructive-command';
13
14
  import { getMostRecentAssistantText, getProviderFailureFingerprint, isTransientProviderFailureText } from './messages-transform';
@@ -22,6 +23,12 @@ export declare const _internals: {
22
23
  extractErrorSignal: typeof extractErrorSignal;
23
24
  getSandboxExecutor: typeof getExecutor;
24
25
  assessSandboxEnforcement: typeof assessSandboxEnforcement;
26
+ /**
27
+ * Epic seam (sentinel-first: one existsSync when Epic is off): while an
28
+ * epic runs a multi-task wave, the wave task whose frozen scope owns the
29
+ * gate run's files. See `resolveEpicGateTaskAttribution`.
30
+ */
31
+ resolveEpicGateTaskAttribution: typeof resolveEpicGateTaskAttribution;
25
32
  /** Test-only compatibility for legacy direct-after hook tests. */
26
33
  allowUncorrelatedGateReceipts: boolean;
27
34
  MAX_PENDING_GATE_RECEIPTS_PER_SESSION: number;
@@ -10,8 +10,8 @@
10
10
  *
11
11
  * Per-worktree by design: promotion evidence records THIS worktree's observed
12
12
  * applications. It is intentionally NOT a member of `KNOWLEDGE_FAMILY` (the
13
- * linked-cohort shared-artifact manifest), matching the precedent set by
14
- * `src/turbo/epic/promotion-evidence.ts`. It lives under the project-root
13
+ * linked-cohort shared-artifact manifest), matching the precedent set by the
14
+ * former Epic promotion-evidence log. It lives under the project-root
15
15
  * `.swarm/` (via {@link validateSwarmPath}), NOT the link-aware shared store
16
16
  * dir, so it stays per-worktree.
17
17
  */