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.
- package/README.md +42 -6
- package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
- package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
- package/dist/agents/architect.d.ts +1 -1
- package/dist/background/completion-observer.d.ts +6 -0
- package/dist/cli/{auto-checkpoint-m7c4x8bk.js → auto-checkpoint-26m3h5f4.js} +9 -9
- package/dist/cli/{checkpoint-m7q9886q.js → checkpoint-7a0achpv.js} +18 -20
- package/dist/cli/{coder-settlement-hh81z2f7.js → coder-settlement-dsb1t39t.js} +13 -13
- package/dist/cli/{config-doctor-0rexy3xt.js → config-doctor-9txawzng.js} +23 -20
- package/dist/cli/{core-ays6stz4.js → core-kv7jz9ty.js} +4 -4
- package/dist/cli/{curation-policy-65ckmmd5.js → curation-policy-6p6fcfjb.js} +6 -6
- package/dist/cli/{curator-dfzkfgs0.js → curator-26yzg8wp.js} +44 -44
- package/dist/cli/{curator-drift-nts5atks.js → curator-drift-kxn5sk3z.js} +9 -9
- package/dist/cli/curator-llm-factory-hs2y9kmw.js +82 -0
- package/dist/cli/{doctor-knowledge-receipt-phase-id-ec40k5hn.js → doctor-knowledge-receipt-phase-id-z8wea03e.js} +9 -9
- package/dist/cli/{evidence-summary-service-vgtm72g5.js → evidence-summary-service-bg5zq78s.js} +21 -22
- package/dist/cli/{gate-evidence-vmn65kxe.js → gate-evidence-0beg9c7r.js} +8 -8
- package/dist/cli/guardrail-explain-n8bm0hpm.js +83 -0
- package/dist/cli/{guardrail-log-hc8fjm4x.js → guardrail-log-r2zazmbn.js} +8 -8
- package/dist/cli/{guardrail-reset-ct00w300.js → guardrail-reset-0q54t44w.js} +44 -44
- package/dist/cli/{hive-promoter-2xax6van.js → hive-promoter-7dr5b9zv.js} +44 -44
- package/dist/cli/{index-9gqb5nkj.js → index-0gve0mkj.js} +4 -4
- package/dist/cli/{index-34vsyj15.js → index-0yrg10jx.js} +5 -5
- package/dist/cli/{index-mfxef20k.js → index-0z8vdkvg.js} +4 -4
- package/dist/cli/{index-2nexf5vz.js → index-1f084tqn.js} +22223 -15395
- package/dist/cli/{index-qx3g1bbe.js → index-26e2s6r1.js} +1 -1
- package/dist/cli/{index-kqegvngt.js → index-2c47efpt.js} +4 -4
- package/dist/cli/{index-9tvjwv01.js → index-2fpv2wmc.js} +1 -1
- package/dist/cli/{index-8q8783g0.js → index-3zwhxk98.js} +1 -1
- package/dist/cli/{index-9j3ybyfs.js → index-4a15347d.js} +7 -7
- package/dist/cli/{index-5cfhwd65.js → index-67a6mk20.js} +2 -2
- package/dist/cli/{index-d3rjvm9e.js → index-7vnr5cmp.js} +2 -2
- package/dist/cli/{index-twb3f4tk.js → index-8bx6vhzk.js} +1 -1
- package/dist/cli/{index-0gejy4cx.js → index-ay8ggtgr.js} +2 -2
- package/dist/cli/{index-8xabhfwr.js → index-b2j231jy.js} +2 -2
- package/dist/cli/{index-cbqkag7q.js → index-bcwmn4d7.js} +3 -3
- package/dist/cli/{index-fbgjj7h5.js → index-bfyh3gpe.js} +101 -13
- package/dist/cli/{index-skdpgjar.js → index-cewpxcwm.js} +862 -1221
- package/dist/cli/{index-bzbxn24k.js → index-dbdkh7pq.js} +5 -5
- package/dist/cli/{index-w4zscz6p.js → index-dnp4qtpf.js} +5 -5
- package/dist/cli/{index-waxvpwbv.js → index-efztf4yw.js} +127 -13
- package/dist/cli/{index-4p3jh14t.js → index-enq166kw.js} +4 -4
- package/dist/cli/{index-g03m5jhw.js → index-f46dbyew.js} +3 -3
- package/dist/cli/{index-ntda6tje.js → index-feaxsjrt.js} +10 -2
- package/dist/cli/{index-89f56ej4.js → index-fthhppnc.js} +46 -46
- package/dist/cli/{index-wqa31xnf.js → index-gqb8etv4.js} +7 -7
- package/dist/cli/{index-1cwmj1gs.js → index-ha0w0a7t.js} +77 -16
- package/dist/cli/{index-nhsafbrh.js → index-hx1fmywk.js} +5 -5
- package/dist/cli/{index-kaqdzhj3.js → index-kfevm0n5.js} +2 -2
- package/dist/cli/{index-z29hksyw.js → index-m28dzyy8.js} +26 -10
- package/dist/cli/{index-x1eh2636.js → index-mcv0v2dp.js} +1 -1
- package/dist/cli/{index-9czp2dcg.js → index-mjfpaxw3.js} +7 -7
- package/dist/cli/{index-f6exny9m.js → index-n8q43eff.js} +2 -2
- package/dist/cli/{index-7hr5m7yp.js → index-nkgzkt7c.js} +1 -1
- package/dist/cli/{index-p2tqzwh6.js → index-qs9myayh.js} +5 -10
- package/dist/cli/{index-hh7pa3yk.js → index-r9yvpr2m.js} +2 -2
- package/dist/cli/{index-cdjxzs2r.js → index-rjzn7hf0.js} +7 -7
- package/dist/cli/{index-zfbxfm2m.js → index-s8b67e6h.js} +33 -12
- package/dist/cli/{index-bskex45z.js → index-s9cgnd2z.js} +2 -2
- package/dist/cli/{index-cj4mp0fm.js → index-sc7t1tev.js} +6 -6
- package/dist/cli/{index-3dx0c7ve.js → index-sfjpbnqs.js} +44 -44
- package/dist/cli/{index-16m2m4ah.js → index-spgfs5y7.js} +1 -1
- package/dist/cli/{index-q9kefh33.js → index-sxj143a4.js} +1 -1
- package/dist/cli/{index-zsrtt42s.js → index-v3bmwmqw.js} +25 -1
- package/dist/cli/{index-5v09zw1q.js → index-v3j9fk16.js} +18 -8
- package/dist/cli/{index-2btybj8w.js → index-xdq6mak1.js} +4 -4
- package/dist/cli/{index-k8sarme1.js → index-y9v41185.js} +1 -1
- package/dist/cli/{index-4a7j5f60.js → index-yy5yyyst.js} +4 -4
- package/dist/cli/{index-1xa8wq76.js → index-z3ahy9c2.js} +2 -2
- package/dist/cli/{index-wrdktgpy.js → index-zk6ttjkt.js} +2 -2
- package/dist/cli/index.js +45 -45
- package/dist/cli/{knowledge-escalator-v3c8w86g.js → knowledge-escalator-hdrqt5pj.js} +15 -15
- package/dist/cli/{knowledge-events-kagaccj9.js → knowledge-events-ttebc8gn.js} +13 -13
- package/dist/cli/{knowledge-link-h4pdcnya.js → knowledge-link-6hw3z6wn.js} +5 -5
- package/dist/cli/{knowledge-store-ywxjk5pb.js → knowledge-store-8cxv6w2n.js} +6 -6
- package/dist/cli/{knowledge-validator-210gkpec.js → knowledge-validator-kr5xmqpa.js} +8 -8
- package/dist/cli/{mcp-58hgx6av.js → mcp-jtk79ygp.js} +1 -1
- package/dist/cli/{model-preflight-e69b48n0.js → model-preflight-d6tt7479.js} +44 -44
- package/dist/cli/{pending-delegations-g24d3qa9.js → pending-delegations-ttk09f50.js} +12 -12
- package/dist/cli/{pr-subscriptions-qprh2zsm.js → pr-subscriptions-2kbeezsr.js} +12 -12
- package/dist/cli/{pr-workflow-gate-pj7dhkv4.js → pr-workflow-gate-3ra6p7k4.js} +44 -44
- package/dist/cli/{runner-4hfmp1ag.js → runner-ssnsje35.js} +6 -6
- package/dist/cli/{scan-cursor-s5wsxxd1.js → scan-cursor-zzccy117.js} +7 -7
- package/dist/cli/{schema-smgngq9m.js → schema-9prswg1x.js} +14 -2
- package/dist/cli/{scope-persistence-tbv2ar4w.js → scope-persistence-eqm8vwnx.js} +16 -16
- package/dist/cli/{server-7p2ds5w2.js → server-swjre81h.js} +45 -45
- package/dist/cli/{skill-generator-r4hsne71.js → skill-generator-d8dk9vps.js} +17 -17
- package/dist/cli/{snapshot-coordination-init-ydjwh56d.js → snapshot-coordination-init-f49y0zr0.js} +44 -44
- package/dist/cli/{speckit-checkoff-aj75vmjq.js → speckit-checkoff-pnb6q9gd.js} +5 -5
- package/dist/cli/{telemetry-kvhe94gs.js → telemetry-9szfdfqv.js} +1 -1
- package/dist/cli/{workspace-snapshot-30kdf018.js → workspace-snapshot-9f12p1s1.js} +3 -3
- package/dist/cli/{worktree-collision-ownership-0bxj9f0t.js → worktree-collision-ownership-3c7xyc4p.js} +14 -14
- package/dist/cli/{worktree-isolation-h0c22pm2.js → worktree-isolation-jggdf28m.js} +46 -44
- package/dist/commands/coupling.d.ts +21 -4
- package/dist/commands/epic-learning.d.ts +28 -0
- package/dist/commands/epic.d.ts +81 -36
- package/dist/commands/registry.d.ts +8 -8
- package/dist/commands/turbo.d.ts +16 -1
- package/dist/config/constants.d.ts +11 -1
- package/dist/config/loader.d.ts +2 -0
- package/dist/config/schema.d.ts +291 -77
- package/dist/db/coordination-store.d.ts +6 -0
- package/dist/epic/close.d.ts +209 -0
- package/dist/{turbo/epic → epic}/cochange-conflict.d.ts +5 -4
- package/dist/{turbo/epic → epic}/cochange-source.d.ts +10 -1
- package/dist/epic/components.d.ts +238 -0
- package/dist/epic/config-gate.d.ts +25 -0
- package/dist/epic/config.d.ts +101 -0
- package/dist/{turbo/epic → epic}/coupling-report.d.ts +3 -1
- package/dist/epic/declared-scopes.d.ts +37 -0
- package/dist/epic/epic-branch.d.ts +157 -0
- package/dist/epic/gate-policy.d.ts +114 -0
- package/dist/epic/git-once.d.ts +26 -0
- package/dist/epic/learning-store.d.ts +176 -0
- package/dist/epic/learning.d.ts +198 -0
- package/dist/epic/legacy-migration.d.ts +26 -0
- package/dist/epic/lifecycle.d.ts +437 -0
- package/dist/epic/markers.d.ts +123 -0
- package/dist/epic/merge-epoch.d.ts +90 -0
- package/dist/epic/next-wave-format.d.ts +101 -0
- package/dist/epic/next-wave.d.ts +102 -0
- package/dist/epic/phase-readiness.d.ts +221 -0
- package/dist/epic/plan-key.d.ts +104 -0
- package/dist/epic/plan-shaping-seam.d.ts +112 -0
- package/dist/epic/planning-signals.d.ts +38 -0
- package/dist/epic/report.d.ts +152 -0
- package/dist/epic/residue-commit.d.ts +151 -0
- package/dist/epic/scorecard.d.ts +130 -0
- package/dist/epic/shaping-sizing.d.ts +108 -0
- package/dist/epic/shaping-suggestions.d.ts +172 -0
- package/dist/epic/shaping.d.ts +112 -0
- package/dist/epic/sizing.d.ts +60 -0
- package/dist/epic/start.d.ts +187 -0
- package/dist/epic/task-landing.d.ts +83 -0
- package/dist/epic/wave-close.d.ts +112 -0
- package/dist/epic/wave-select.d.ts +95 -0
- package/dist/evaluation/contracts.d.ts +1 -1
- package/dist/evaluation/public-api.d.ts +1 -1
- package/dist/full-auto/policy.d.ts +12 -1
- package/dist/hooks/delegation-gate/worktree-isolation.d.ts +16 -0
- package/dist/hooks/delegation-gate.d.ts +11 -0
- package/dist/hooks/guardrails/index.d.ts +7 -0
- package/dist/hooks/promotion-evidence-store.d.ts +2 -2
- package/dist/index.js +814 -807
- package/dist/plan/manager.d.ts +6 -8
- package/dist/plan/parallel-verdict.d.ts +13 -2
- package/dist/retention/caps.d.ts +1 -1
- package/dist/review/contracts.d.ts +8 -1
- package/dist/services/config-doctor.d.ts +38 -0
- package/dist/session/snapshot-reader.d.ts +2 -0
- package/dist/session/snapshot-writer.d.ts +13 -2
- package/dist/state.d.ts +13 -18
- package/dist/tools/epic-next-wave.d.ts +20 -0
- package/dist/tools/epic-phase-review.d.ts +43 -0
- package/dist/tools/index.d.ts +2 -3
- package/dist/tools/manifest.d.ts +2 -3
- package/dist/tools/phase-complete.d.ts +5 -1
- package/dist/tools/save-plan.d.ts +7 -0
- package/dist/tools/tool-metadata.d.ts +4 -8
- package/dist/worktree/merge.d.ts +14 -1
- package/opencode-swarm.schema.json +273 -28
- package/package.json +1 -1
- package/dist/cli/curator-llm-factory-nrn6n2p1.js +0 -82
- package/dist/cli/guardrail-explain-9jmr8ezt.js +0 -83
- package/dist/tools/epic-plan-waves.d.ts +0 -79
- package/dist/tools/epic-record-divergence.d.ts +0 -73
- package/dist/tools/epic-run-phase.d.ts +0 -179
- package/dist/turbo/epic/activation.d.ts +0 -193
- package/dist/turbo/epic/calibration-engine.d.ts +0 -88
- package/dist/turbo/epic/calibration.d.ts +0 -80
- package/dist/turbo/epic/divergence-recorder.d.ts +0 -123
- package/dist/turbo/epic/index.d.ts +0 -24
- package/dist/turbo/epic/promotion-evidence.d.ts +0 -42
- package/dist/turbo/epic/state.d.ts +0 -69
- package/dist/turbo/epic/task-commit.d.ts +0 -110
- package/dist/turbo/epic/upstream-commits.d.ts +0 -82
- 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" | "
|
|
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?:
|
|
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
|
-
*
|
|
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
|
*/
|