opencode-swarm 7.188.12 → 7.190.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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-4g963859.js → auto-checkpoint-qvk04fya.js} +9 -9
- package/dist/cli/{checkpoint-y9nbjper.js → checkpoint-9q2r5c3j.js} +18 -20
- package/dist/cli/{coder-settlement-q8ea2jkw.js → coder-settlement-xcparbf3.js} +13 -13
- package/dist/cli/{config-doctor-4v5m6v30.js → config-doctor-by0ak49m.js} +23 -20
- package/dist/cli/{core-879105xb.js → core-b1b3kxzy.js} +4 -4
- package/dist/cli/{curation-policy-65ckmmd5.js → curation-policy-6p6fcfjb.js} +6 -6
- package/dist/cli/{curator-t7g3hamd.js → curator-d7b88mzr.js} +44 -44
- package/dist/cli/{curator-drift-satfdnp2.js → curator-drift-6v604220.js} +9 -9
- package/dist/cli/curator-llm-factory-yvbktznk.js +82 -0
- package/dist/cli/{doctor-knowledge-receipt-phase-id-y3ft2v24.js → doctor-knowledge-receipt-phase-id-kwrvnps9.js} +9 -9
- package/dist/cli/{evidence-summary-service-56rqzmrf.js → evidence-summary-service-mzr2q4bn.js} +21 -22
- package/dist/cli/{gate-evidence-zzmgph9z.js → gate-evidence-78jes9kq.js} +8 -8
- package/dist/cli/guardrail-explain-8kt2mxmw.js +83 -0
- package/dist/cli/{guardrail-log-sxv7q0xw.js → guardrail-log-2sthykag.js} +8 -8
- package/dist/cli/{guardrail-reset-37cr442b.js → guardrail-reset-2n746rzv.js} +44 -44
- package/dist/cli/{hive-promoter-hyeta8d6.js → hive-promoter-s7a5gwhz.js} +44 -44
- package/dist/cli/{index-e638qt2d.js → index-0qc7a88d.js} +3 -3
- package/dist/cli/{index-kap0d52p.js → index-1s95jrgc.js} +3 -3
- package/dist/cli/{index-9tvjwv01.js → index-2fpv2wmc.js} +1 -1
- package/dist/cli/{index-jgr1rsr1.js → index-2kpqqcch.js} +4 -4
- package/dist/cli/{index-msvf6p5y.js → index-3t9t9q2q.js} +44 -44
- package/dist/cli/{index-8q8783g0.js → index-3zwhxk98.js} +1 -1
- package/dist/cli/{index-0b172h6r.js → index-49e65y51.js} +5 -5
- package/dist/cli/{index-5pafc9x6.js → index-69tgdm9t.js} +18 -8
- 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-84pwb6cz.js → index-9gcqmgbc.js} +5 -5
- package/dist/cli/{index-9sps637v.js → index-9xxqdzp4.js} +4 -4
- package/dist/cli/{index-j0qep2zr.js → index-a5ca62vt.js} +1 -1
- package/dist/cli/{index-xy2403g9.js → index-ajzgeb2s.js} +2 -2
- package/dist/cli/{index-8xabhfwr.js → index-b2j231jy.js} +2 -2
- package/dist/cli/{index-19yt5p2t.js → index-dmq7p8s9.js} +6 -6
- package/dist/cli/{index-95pzyv9a.js → index-ej1hdw16.js} +5 -5
- package/dist/cli/{index-1krdj1sc.js → index-ejk34dnw.js} +127 -13
- package/dist/cli/{index-tbyvvq50.js → index-fb5s32c2.js} +862 -1221
- package/dist/cli/{index-ntda6tje.js → index-feaxsjrt.js} +10 -2
- package/dist/cli/{index-94fgbb34.js → index-ffgcdf49.js} +22147 -15396
- package/dist/cli/{index-fhtcx5ag.js → index-h0xhec3d.js} +4 -4
- package/dist/cli/{index-kaqdzhj3.js → index-kfevm0n5.js} +2 -2
- package/dist/cli/{index-z7gakzb5.js → index-kp8k95v9.js} +4 -4
- 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-tmn4pf7q.js → index-mp1s7b0n.js} +7 -7
- package/dist/cli/{index-f0jn2nvs.js → index-mseerehd.js} +26 -10
- 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-8jy605yf.js → index-npe10823.js} +7 -7
- package/dist/cli/{index-yc0y5fjt.js → index-p69k8v0e.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-qha2p47y.js → index-rgkzcw2a.js} +5 -5
- package/dist/cli/{index-zfbxfm2m.js → index-s8b67e6h.js} +33 -12
- package/dist/cli/{index-m3hhaf61.js → index-s92a5ta3.js} +4 -4
- package/dist/cli/{index-dd6p8xb5.js → index-sm01zpqe.js} +46 -46
- package/dist/cli/{index-q9kefh33.js → index-sxj143a4.js} +1 -1
- package/dist/cli/{index-2h13hjbf.js → index-t0gj8s46.js} +77 -16
- package/dist/cli/{index-3dqazqk4.js → index-t73adn9b.js} +2 -2
- package/dist/cli/{index-5cksakjf.js → index-tkhenmms.js} +101 -13
- package/dist/cli/{index-zsrtt42s.js → index-v3bmwmqw.js} +25 -1
- package/dist/cli/{index-w9tfb0am.js → index-vhn4e6rm.js} +7 -7
- package/dist/cli/{index-yjjyapbf.js → index-xyvrfram.js} +2 -2
- package/dist/cli/{index-k8sarme1.js → index-y9v41185.js} +1 -1
- 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-7z2pxxye.js → index-zyg1m9d0.js} +4 -4
- package/dist/cli/index.js +45 -45
- package/dist/cli/{knowledge-escalator-dzd35eb3.js → knowledge-escalator-n1ezv1zp.js} +15 -15
- package/dist/cli/{knowledge-events-wkr5ne5f.js → knowledge-events-nyqk3mr7.js} +13 -13
- package/dist/cli/{knowledge-link-h4pdcnya.js → knowledge-link-6hw3z6wn.js} +5 -5
- package/dist/cli/{knowledge-store-sme6sqrb.js → knowledge-store-mnxqcyet.js} +6 -6
- package/dist/cli/{knowledge-validator-jgzeawa8.js → knowledge-validator-z30113mp.js} +8 -8
- package/dist/cli/{mcp-egrbh8na.js → mcp-mnbqw2s5.js} +1 -1
- package/dist/cli/{model-preflight-h7azh4m4.js → model-preflight-ex482fsy.js} +44 -44
- package/dist/cli/{pending-delegations-pg284vsk.js → pending-delegations-j18afz5z.js} +12 -12
- package/dist/cli/{pr-subscriptions-hzc4fg25.js → pr-subscriptions-yngda8mz.js} +12 -12
- package/dist/cli/{pr-workflow-gate-j3r3g3q7.js → pr-workflow-gate-0vt614f0.js} +44 -44
- package/dist/cli/{runner-4hfmp1ag.js → runner-ssnsje35.js} +6 -6
- package/dist/cli/{scan-cursor-zg0a56c1.js → scan-cursor-8pwfg5g9.js} +7 -7
- package/dist/cli/{schema-p246rqkt.js → schema-e58ytmqt.js} +14 -2
- package/dist/cli/{scope-persistence-7qtsmx5c.js → scope-persistence-9qfx6ext.js} +16 -16
- package/dist/cli/{server-twhpwhgq.js → server-wxcfwsdx.js} +45 -45
- package/dist/cli/{skill-generator-7vfbmyrw.js → skill-generator-tbd4tq9r.js} +17 -17
- package/dist/cli/{snapshot-coordination-init-050hf69t.js → snapshot-coordination-init-sckyzb94.js} +44 -44
- package/dist/cli/{speckit-checkoff-d3v522cb.js → speckit-checkoff-k5jm0abh.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-yy1tp8t9.js → worktree-collision-ownership-3wwfc72t.js} +14 -14
- package/dist/cli/{worktree-isolation-e56skbfw.js → worktree-isolation-zfk7zk6a.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-fx1qnpsh.js +0 -82
- package/dist/cli/guardrail-explain-g03manbh.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
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Epic Mode divergence-record tool (Capability D — capture leg).
|
|
3
|
-
*
|
|
4
|
-
* After the architect marks a task `completed` via `update_task_status`, it
|
|
5
|
-
* calls this tool with `{ directory, taskId, sessionID }`. The tool:
|
|
6
|
-
*
|
|
7
|
-
* 1. Reads the task's DECLARED scope from `.swarm/scopes/scope-{taskId}.json`
|
|
8
|
-
* (the same on-disk record `readScopeFromDisk` consults).
|
|
9
|
-
* 2. Reads the ACTUAL files attributed to this exact task by the guardrails
|
|
10
|
-
* write hook and background-completion ingestion.
|
|
11
|
-
* 3. Appends one record to `.swarm/epic/divergence.jsonl` via
|
|
12
|
-
* `recordTaskDivergence`. The calibration engine reads that file on the
|
|
13
|
-
* next `epic_decide_phase` invocation (the architect-facing decide
|
|
14
|
-
* tool — `epic_run_phase` is the legacy unified path, retained as
|
|
15
|
-
* `executeEpicRunPhase` for composition users only).
|
|
16
|
-
*
|
|
17
|
-
* Best-effort by design — failure to record divergence is logged but never
|
|
18
|
-
* surfaces as a task-blocking error. Worst case: a single observation is
|
|
19
|
-
* missed and the calibration loop sees one fewer data point.
|
|
20
|
-
*
|
|
21
|
-
* Composition contract: this tool does NOT modify `update_task_status` or
|
|
22
|
-
* any maintainer file. The architect is instructed to call it via the
|
|
23
|
-
* `EPIC_MODE_BANNER` system-enhancer injection. If the architect forgets,
|
|
24
|
-
* the only effect is missing calibration signal — Epic Mode keeps working.
|
|
25
|
-
*/
|
|
26
|
-
import type { ToolDefinition } from '@opencode-ai/plugin/tool';
|
|
27
|
-
import { loadPlanJsonOnly as loadPlanJsonOnly_import } from '../plan/manager.js';
|
|
28
|
-
import { readScopeFromDisk as readScopeFromDisk_import } from '../scope/scope-persistence.js';
|
|
29
|
-
import { getAgentSession as getAgentSession_import, getModifiedFilesForTask as getModifiedFilesForTask_import, hasActiveEpicMode as hasActiveEpicMode_import, resetModifiedFilesForTask as resetModifiedFilesForTask_import } from '../state.js';
|
|
30
|
-
import { recordTaskDivergence as recordTaskDivergence_import } from '../turbo/epic/divergence-recorder.js';
|
|
31
|
-
export interface EpicRecordDivergenceArgs {
|
|
32
|
-
directory: string;
|
|
33
|
-
taskId: string;
|
|
34
|
-
sessionID: string;
|
|
35
|
-
}
|
|
36
|
-
export interface EpicRecordDivergenceResult {
|
|
37
|
-
success: boolean;
|
|
38
|
-
/**
|
|
39
|
-
* Either:
|
|
40
|
-
* - `'recorded'` — a record was appended to divergence.jsonl.
|
|
41
|
-
* - `'epic-mode-not-active'` — session has not toggled Epic Mode; no-op.
|
|
42
|
-
* - `'no-scope'` — no declared scope on disk for this task (could be a
|
|
43
|
-
* pure verification task that bypassed `declare_scope`). Skipped.
|
|
44
|
-
* - `'no-session'` — no agent session for `sessionID`; skipped.
|
|
45
|
-
* - `'persist-failed'` — write to JSONL failed (logged); skipped.
|
|
46
|
-
*/
|
|
47
|
-
reason: string;
|
|
48
|
-
/** When `reason === 'recorded'`, summarises the record without the full file lists. */
|
|
49
|
-
summary?: {
|
|
50
|
-
declaredCount: number;
|
|
51
|
-
actualCount: number;
|
|
52
|
-
undeclaredCount: number;
|
|
53
|
-
unusedCount: number;
|
|
54
|
-
divergenceRatio: number;
|
|
55
|
-
isClean: boolean;
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Test-only DI seam (AGENTS.md invariant 7). Mutating this object is
|
|
60
|
-
* file-scoped and trivially restorable via afterEach, avoiding Bun's
|
|
61
|
-
* cross-file `mock.module` leak.
|
|
62
|
-
*/
|
|
63
|
-
export declare const _internals: {
|
|
64
|
-
hasActiveEpicMode: typeof hasActiveEpicMode_import;
|
|
65
|
-
getAgentSession: typeof getAgentSession_import;
|
|
66
|
-
getModifiedFilesForTask: typeof getModifiedFilesForTask_import;
|
|
67
|
-
resetModifiedFilesForTask: typeof resetModifiedFilesForTask_import;
|
|
68
|
-
readScopeFromDisk: typeof readScopeFromDisk_import;
|
|
69
|
-
loadPlanJsonOnly: typeof loadPlanJsonOnly_import;
|
|
70
|
-
recordTaskDivergence: typeof recordTaskDivergence_import;
|
|
71
|
-
};
|
|
72
|
-
export declare function executeEpicRecordDivergence(args: EpicRecordDivergenceArgs): Promise<EpicRecordDivergenceResult>;
|
|
73
|
-
export declare const epic_record_divergence: ToolDefinition;
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Epic Mode run-phase tool (Capability C).
|
|
3
|
-
*
|
|
4
|
-
* The architect invokes this tool — instead of `lean_turbo_run_phase` —
|
|
5
|
-
* when Epic Mode is active. It:
|
|
6
|
-
*
|
|
7
|
-
* 1. Verifies Epic Mode is on for the session (else fails closed).
|
|
8
|
-
* 2. Loads the plan, resolves task scopes the same way the coupling
|
|
9
|
-
* report does, and queries the co-change signal.
|
|
10
|
-
* 3. Runs `decideEpicActivation` over the WHOLE PLAN (per-plan
|
|
11
|
-
* activation per Q1) to get a `promote | demote` verdict.
|
|
12
|
-
* 4. Appends one record to `.swarm/evidence/epic-promotions.jsonl`
|
|
13
|
-
* and updates `.swarm/epic-state.json` with the verdict.
|
|
14
|
-
* 5. If promoted: invokes `LeanTurboRunner` for the given phase by
|
|
15
|
-
* composition (zero edits to `src/turbo/lean/`).
|
|
16
|
-
* 6. If demoted: returns a structured "epic recommends serial"
|
|
17
|
-
* verdict so the caller can fall back to the standard serial
|
|
18
|
-
* flow.
|
|
19
|
-
*
|
|
20
|
-
* Composition contract: this tool is the only architect-facing entry
|
|
21
|
-
* point Capability C adds. It does not modify `lean_turbo_run_phase`,
|
|
22
|
-
* `LeanTurboRunner`, or any Lean Turbo file. Decision happens above
|
|
23
|
-
* Lean Turbo; execution dispatches into Lean Turbo via import only.
|
|
24
|
-
*/
|
|
25
|
-
import type { ToolDefinition } from '@opencode-ai/plugin/tool';
|
|
26
|
-
import { loadPluginConfigWithMeta as loadPluginConfigWithMeta_import } from '../config/index.js';
|
|
27
|
-
import { isGitRepo as isGitRepo_import } from '../git/branch.js';
|
|
28
|
-
import { loadPlanJsonOnly as loadPlanJsonOnly_import } from '../plan/manager.js';
|
|
29
|
-
import type { EpicActivationVerdict } from '../turbo/epic/activation.js';
|
|
30
|
-
import { decideEpicActivation as decideEpicActivation_import } from '../turbo/epic/activation.js';
|
|
31
|
-
import { loadCalibrationState as loadCalibrationState_import, saveCalibrationState as saveCalibrationState_import } from '../turbo/epic/calibration.js';
|
|
32
|
-
import { applyCalibration as applyCalibration_import, effectiveActivationThreshold as effectiveActivationThreshold_import, effectiveHotModules as effectiveHotModules_import } from '../turbo/epic/calibration-engine.js';
|
|
33
|
-
import { getCoChangeData as getCoChangeData_import } from '../turbo/epic/cochange-source.js';
|
|
34
|
-
import { readDivergenceHistory as readDivergenceHistory_import } from '../turbo/epic/divergence-recorder.js';
|
|
35
|
-
import { appendPromotionEvidence as appendPromotionEvidence_import } from '../turbo/epic/promotion-evidence.js';
|
|
36
|
-
import { isEpicModeActive as isEpicModeActive_import, recordEpicDecision as recordEpicDecision_import } from '../turbo/epic/state.js';
|
|
37
|
-
import { buildIsUpstreamCommitted as buildIsUpstreamCommitted_import, buildIsUpstreamCommittedWithStatus as buildIsUpstreamCommittedWithStatus_import } from '../turbo/epic/upstream-commits.js';
|
|
38
|
-
import { readTaskScopes as readTaskScopes_import } from '../turbo/lean/conflicts.js';
|
|
39
|
-
import type { LaneResult } from '../turbo/lean/runner.js';
|
|
40
|
-
import { LeanTurboRunner as LeanTurboRunner_import } from '../turbo/lean/runner.js';
|
|
41
|
-
export interface EpicRunPhaseArgs {
|
|
42
|
-
directory: string;
|
|
43
|
-
phase: number;
|
|
44
|
-
sessionID: string;
|
|
45
|
-
}
|
|
46
|
-
export interface EpicRunPhaseResult {
|
|
47
|
-
success: boolean;
|
|
48
|
-
/** The verdict for this run, persisted to evidence. */
|
|
49
|
-
verdict?: EpicActivationVerdict;
|
|
50
|
-
/** Set when the verdict was `promote` and Lean Turbo ran. */
|
|
51
|
-
lanes?: LaneResult[];
|
|
52
|
-
degradedTasks?: string[];
|
|
53
|
-
serializedTasks?: string[];
|
|
54
|
-
/**
|
|
55
|
-
* Either:
|
|
56
|
-
* - `'demoted'` — epic chose serial; the caller should fall back.
|
|
57
|
-
* - `'promoted'` — epic chose parallel and Lean Turbo ran.
|
|
58
|
-
* - `'epic-mode-not-active'` — the session has not toggled Epic Mode.
|
|
59
|
-
* - `'no-plan'` — `.swarm/plan.json` is missing.
|
|
60
|
-
* - `'no-phase'` — the requested phase number isn't present in the
|
|
61
|
-
* plan. Phase 12 (B11): without this, an unknown phase silently
|
|
62
|
-
* produced `currentPhaseTasks = []` and vacuously-passed the
|
|
63
|
-
* activation gate — promoting a phase that doesn't exist.
|
|
64
|
-
* - `'phase-already-complete'` — every task in the requested phase
|
|
65
|
-
* is already `status: 'completed'`. Phase 15 (B35): without this,
|
|
66
|
-
* re-running an already-completed phase silently produced a
|
|
67
|
-
* vacuous-pass `promote` verdict; the architect then called the
|
|
68
|
-
* wave planner and got an empty plan with no diagnostic.
|
|
69
|
-
* - `'phase-empty'` — the requested phase exists but its `tasks`
|
|
70
|
-
* array is empty (architect created a phase header but never
|
|
71
|
-
* populated it, or a council edit removed every task). Phase 17
|
|
72
|
-
* (E.1): the Phase 15 B35 guard only fired when at least one
|
|
73
|
-
* completed task existed; an empty `tasks: []` slipped through to
|
|
74
|
-
* the same vacuous-pass `promote` B35 was supposed to prevent.
|
|
75
|
-
* - `'lean-runner-error'` — Lean Turbo threw during promoted execution.
|
|
76
|
-
* - `'scopes-missing'` — one or more pending tasks in the phase have
|
|
77
|
-
* neither a declared scope file on disk nor `files_touched` in
|
|
78
|
-
* plan.json. Lean Turbo's lane planner needs scope data to compute
|
|
79
|
-
* parallel lanes; without it the dispatch returns empty lanes and
|
|
80
|
-
* the parallelization promise is silently broken. The architect
|
|
81
|
-
* must call `declare_scope` for each missing task and then
|
|
82
|
-
* re-invoke `epic_decide_phase`.
|
|
83
|
-
*/
|
|
84
|
-
reason: string;
|
|
85
|
-
/** Set when `reason === 'lean-runner-error'`. */
|
|
86
|
-
errors?: string[];
|
|
87
|
-
/** Set when `reason === 'scopes-missing'` — the task ids with no scope. */
|
|
88
|
-
missingScopes?: string[];
|
|
89
|
-
/** Set when `reason === 'scopes-missing'` — actionable message for the architect. */
|
|
90
|
-
message?: string;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Test-only DI seam. Mutating this object is file-scoped and trivially
|
|
94
|
-
* restorable via afterEach, avoiding Bun's cross-file `mock.module`
|
|
95
|
-
* leak (AGENTS.md invariant 7).
|
|
96
|
-
*/
|
|
97
|
-
export declare const _internals: {
|
|
98
|
-
loadPluginConfigWithMeta: typeof loadPluginConfigWithMeta_import;
|
|
99
|
-
loadPlanJsonOnly: typeof loadPlanJsonOnly_import;
|
|
100
|
-
getCoChangeData: typeof getCoChangeData_import;
|
|
101
|
-
decideEpicActivation: typeof decideEpicActivation_import;
|
|
102
|
-
isGitRepo: typeof isGitRepo_import;
|
|
103
|
-
appendPromotionEvidence: typeof appendPromotionEvidence_import;
|
|
104
|
-
recordEpicDecision: typeof recordEpicDecision_import;
|
|
105
|
-
isEpicModeActive: typeof isEpicModeActive_import;
|
|
106
|
-
readTaskScopes: typeof readTaskScopes_import;
|
|
107
|
-
loadCalibrationState: typeof loadCalibrationState_import;
|
|
108
|
-
saveCalibrationState: typeof saveCalibrationState_import;
|
|
109
|
-
applyCalibration: typeof applyCalibration_import;
|
|
110
|
-
effectiveActivationThreshold: typeof effectiveActivationThreshold_import;
|
|
111
|
-
effectiveHotModules: typeof effectiveHotModules_import;
|
|
112
|
-
readDivergenceHistory: typeof readDivergenceHistory_import;
|
|
113
|
-
LeanTurboRunner: typeof LeanTurboRunner_import;
|
|
114
|
-
buildIsUpstreamCommitted: typeof buildIsUpstreamCommitted_import;
|
|
115
|
-
buildIsUpstreamCommittedWithStatus: typeof buildIsUpstreamCommittedWithStatus_import;
|
|
116
|
-
};
|
|
117
|
-
/**
|
|
118
|
-
* Decide-only path: runs stages 1-9 of the phase flow (preflight + calibration
|
|
119
|
-
* + co-change + decision + evidence write + session state mirror) and returns
|
|
120
|
-
* the verdict WITHOUT dispatching Lean Turbo.
|
|
121
|
-
*
|
|
122
|
-
* This is the shared helper between:
|
|
123
|
-
* - `epic_run_phase`: legacy unified tool (decide + dispatch in one call) —
|
|
124
|
-
* calls this then continues with dispatch when verdict is promote.
|
|
125
|
-
* - `epic_decide_phase`: transparent flow (decide only — architect then
|
|
126
|
-
* calls `epic_plan_waves` and dispatches each wave via Task for visibility).
|
|
127
|
-
*
|
|
128
|
-
* Returns the same EpicRunPhaseResult shape with:
|
|
129
|
-
* - reason: 'decided' → verdict is promote, caller may dispatch.
|
|
130
|
-
* - reason: 'demoted' → verdict is demote, caller falls back to serial.
|
|
131
|
-
*
|
|
132
|
-
* Error / non-decision reasons (all set success: false):
|
|
133
|
-
* - 'epic-mode-not-active' — the session has not toggled Epic Mode.
|
|
134
|
-
* - 'no-plan' — `.swarm/plan.json` is missing.
|
|
135
|
-
* - 'no-phase' (Phase 12 B11) — the requested phase number isn't in the plan.
|
|
136
|
-
* - 'phase-empty' (Phase 17 E.1) — phase exists but has zero tasks.
|
|
137
|
-
* - 'phase-already-complete' (Phase 15 B35) — every task already completed.
|
|
138
|
-
* - 'scopes-missing' — one or more pending tasks lack declared scope.
|
|
139
|
-
* - 'epic-state-unreadable' — `.swarm/epic-state.json` is corrupt.
|
|
140
|
-
*/
|
|
141
|
-
export declare function executeEpicDecidePhase(args: EpicRunPhaseArgs): Promise<EpicRunPhaseResult>;
|
|
142
|
-
/**
|
|
143
|
-
* Full unified path: decide + dispatch in one call (legacy behavior).
|
|
144
|
-
*
|
|
145
|
-
* For transparent CLI-visible dispatch, prefer `epic_decide_phase` + lane
|
|
146
|
-
* dispatch via the architect's Task tool — see EPIC_MODE_BANNER. This unified
|
|
147
|
-
* path remains for back-compat and for callers that don't need visibility
|
|
148
|
-
* into the parallel coder agents.
|
|
149
|
-
*/
|
|
150
|
-
export declare function executeEpicRunPhase(args: EpicRunPhaseArgs): Promise<EpicRunPhaseResult>;
|
|
151
|
-
/**
|
|
152
|
-
* NOTE: `epic_run_phase` is intentionally NOT exposed as a tool to the
|
|
153
|
-
* architect. The transparent decide-then-dispatch wave flow (`epic_decide_phase`
|
|
154
|
-
* → `epic_plan_waves` → Task dispatch per wave) is the ONLY supported flow,
|
|
155
|
-
* because it gives the user real-time visibility into each concurrent coder
|
|
156
|
-
* agent. The legacy unified-path function `executeEpicRunPhase` remains
|
|
157
|
-
* exported for tests and any composition users, but no ToolDefinition
|
|
158
|
-
* wraps it — so the architect cannot call it and accidentally fall back
|
|
159
|
-
* to the opaque path. This is a deliberate product decision: one flow,
|
|
160
|
-
* unambiguous, always-visible.
|
|
161
|
-
*/
|
|
162
|
-
/**
|
|
163
|
-
* Transparent decide-only tool. Returns the verdict (promote/demote/error)
|
|
164
|
-
* without dispatching coders. The architect should:
|
|
165
|
-
* 1. Call this after declaring scopes for all pending tasks.
|
|
166
|
-
* 2. Surface the verdict to the user.
|
|
167
|
-
* 3. If verdict is `promote`, call `epic_plan_waves` to get the wave plan,
|
|
168
|
-
* then for each wave dispatch one `Task` per `taskId` in that wave —
|
|
169
|
-
* ALL in one assistant message so the wave runs concurrently. Wait for
|
|
170
|
-
* the wave to complete, then advance. Each Task is a visible subagent
|
|
171
|
-
* the user can click into for live progress.
|
|
172
|
-
* 4. After each task completes (via `update_task_status`), call
|
|
173
|
-
* `epic_record_divergence` to feed the calibration loop.
|
|
174
|
-
*
|
|
175
|
-
* This is the CLI-visibility flow. The legacy `epic_run_phase` bundles
|
|
176
|
-
* decide + dispatch into one opaque tool call where the user can't see
|
|
177
|
-
* the concurrent coder agents.
|
|
178
|
-
*/
|
|
179
|
-
export declare const epic_decide_phase: ToolDefinition;
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Epic Mode activation decision (Capability C).
|
|
3
|
-
*
|
|
4
|
-
* `decideEpicActivation(...)` is the pure heart of M3: given a plan, a
|
|
5
|
-
* co-change pair list, and the activation thresholds, it returns a
|
|
6
|
-
* structured `promote | demote` verdict with the rationale fields a
|
|
7
|
-
* caller can persist for audit. Pure function — no I/O.
|
|
8
|
-
*
|
|
9
|
-
* Three independent gates must all pass for promotion:
|
|
10
|
-
*
|
|
11
|
-
* 1. **p-threshold gate.** Compute the coupling coefficient `p` over
|
|
12
|
-
* the plan's task graph using Capability A's `epicPairConflict` (via
|
|
13
|
-
* Capability B's `computeCouplingReport`). Promote only when
|
|
14
|
-
* `p <= activation_threshold`.
|
|
15
|
-
*
|
|
16
|
-
* 2. **Hot-module gate.** No task in scope may touch a Lean Turbo
|
|
17
|
-
* "global" or "protected" path — these are the same lists Lean
|
|
18
|
-
* Turbo already maintains (reused by import; not duplicated).
|
|
19
|
-
* Touching a hot module forces serial regardless of `p`.
|
|
20
|
-
*
|
|
21
|
-
* 3. **Greenfield gate.** If the co-change history is sparse (fewer
|
|
22
|
-
* than `min_commits_for_signal` distinct commits across the
|
|
23
|
-
* analyzer output), the signal is too weak to trust per brief §4.2's
|
|
24
|
-
* greenfield rule. Force serial.
|
|
25
|
-
*
|
|
26
|
-
* Default-serial-promote-on-proof (brief §4.2): when any gate fails or
|
|
27
|
-
* the data is missing, the decision is `demote`. Promotion requires
|
|
28
|
-
* positive evidence on every gate.
|
|
29
|
-
*/
|
|
30
|
-
import type { CoChangeEntry } from '../../tools/co-change-analyzer.js';
|
|
31
|
-
import type { CouplingTask } from './coupling-report.js';
|
|
32
|
-
/** Thresholds the caller supplies (typically derived from EpicConfigSchema). */
|
|
33
|
-
export interface EpicActivationOptions {
|
|
34
|
-
/** Plan-wide p ceiling. Plans with p > activationThreshold are demoted. */
|
|
35
|
-
activationThreshold: number;
|
|
36
|
-
/** Greenfield floor on the analyzer's commit window. */
|
|
37
|
-
minCommitsForSignal: number;
|
|
38
|
-
/** NPMI floor for the co-change conflict signal — passed through to coupling. */
|
|
39
|
-
cochangeNpmiThreshold: number;
|
|
40
|
-
/** Minimum raw co-change count for the conflict signal. */
|
|
41
|
-
cochangeMinCoChanges: number;
|
|
42
|
-
/**
|
|
43
|
-
* Capability D (calibration) additions to the hot-module list. The static
|
|
44
|
-
* Lean Turbo predicates (`isGlobalFile` / `isProtectedPath`) always apply;
|
|
45
|
-
* these are normalised paths the calibration loop has promoted after
|
|
46
|
-
* observing divergent writes against the static set. Optional — falsy or
|
|
47
|
-
* empty means "no calibration overrides". Path matching is exact (post-
|
|
48
|
-
* `normalizePath`); callers compute that via `effectiveHotModules` in
|
|
49
|
-
* `./calibration-engine.ts`.
|
|
50
|
-
*/
|
|
51
|
-
extraHotModules?: readonly string[];
|
|
52
|
-
/**
|
|
53
|
-
* Greenfield-smart Rule 1: whether the project is under git version control.
|
|
54
|
-
* The greenfield gate exists because co-change signals require git history
|
|
55
|
-
* to compute. When the project is not a git repo, there is no signal type
|
|
56
|
-
* to evaluate — the gate's premise is absent, so it passes trivially
|
|
57
|
-
* rather than fail-closed. Callers (typically `epic_run_phase`) resolve
|
|
58
|
-
* this via `isGitRepo(directory)` from `src/git/branch.ts`.
|
|
59
|
-
*
|
|
60
|
-
* Backward-compat: omitted or `undefined` reverts to legacy behavior
|
|
61
|
-
* (apply the `commitsObserved >= minCommitsForSignal` floor
|
|
62
|
-
* unconditionally). Callers should pass an explicit boolean.
|
|
63
|
-
*/
|
|
64
|
-
isGitProject?: boolean;
|
|
65
|
-
/**
|
|
66
|
-
* Phase 13 (B20): task IDs the architect declared in `depends:` that
|
|
67
|
-
* don't resolve to ANY task in the plan. Typically an LLM typo. The
|
|
68
|
-
* gate fails closed with a dedicated `phantom dep` blocking reason so
|
|
69
|
-
* the architect sees the actual bad ID instead of being misled into
|
|
70
|
-
* hunting a non-existent cross-phase upstream. Pass alongside
|
|
71
|
-
* `crossPhaseUpstreams` (the two lists are disjoint).
|
|
72
|
-
*/
|
|
73
|
-
phantomDeps?: readonly string[];
|
|
74
|
-
/**
|
|
75
|
-
* Phase 10 — predecessor-evidence gate redesign.
|
|
76
|
-
*
|
|
77
|
-
* Cross-phase upstream task IDs for the phase being decided: every
|
|
78
|
-
* task that lives in a strictly-prior phase AND is depended on by a
|
|
79
|
-
* task in the current phase. The gate verifies each one has a
|
|
80
|
-
* `swarm(task <id>):` marker in git log via `isUpstreamCommitted`.
|
|
81
|
-
*
|
|
82
|
-
* Empty array (the legacy default) ⇒ no cross-phase deps to check;
|
|
83
|
-
* predecessor evidence is vacuously satisfied. This is correct for
|
|
84
|
-
* Phase 1 (no prior phase), single-phase projects, and phases the
|
|
85
|
-
* architect explicitly declared as independent.
|
|
86
|
-
*
|
|
87
|
-
* Why this replaces the `commitsObserved >= minCommitsForSignal`
|
|
88
|
-
* floor: the floor was a statistical proxy for "do we have enough
|
|
89
|
-
* history to trust `p`?", but in small projects it permanently
|
|
90
|
-
* blocked parallelism (a 12-task project never reaches 20 commits).
|
|
91
|
-
* The structural check asks the actually-relevant question — "are
|
|
92
|
-
* the things this phase depends on actually in git?" — directly,
|
|
93
|
-
* regardless of project size. The architect's declared dep graph IS
|
|
94
|
-
* the parallelism specification (Lamport happens-before); Rule 2's
|
|
95
|
-
* commits ARE the synchronization point; this check ties them
|
|
96
|
-
* together.
|
|
97
|
-
*
|
|
98
|
-
* Callers (`epic_run_phase`) compute this from the plan's dep graph.
|
|
99
|
-
*/
|
|
100
|
-
crossPhaseUpstreams?: readonly string[];
|
|
101
|
-
/**
|
|
102
|
-
* Predicate for the predecessor-evidence check above. Returns true
|
|
103
|
-
* when the given taskId has a `swarm(task <id>):` marker in git
|
|
104
|
-
* history. Same predicate Rule 3 uses at the lane planner — share
|
|
105
|
-
* one source of truth.
|
|
106
|
-
*
|
|
107
|
-
* Omitted ⇒ the gate treats every cross-phase upstream as
|
|
108
|
-
* uncommitted (fail-closed). Pair `crossPhaseUpstreams` with this
|
|
109
|
-
* predicate, or pass neither.
|
|
110
|
-
*/
|
|
111
|
-
isUpstreamCommitted?: (taskId: string) => boolean;
|
|
112
|
-
}
|
|
113
|
-
/** Each gate's pass/fail outcome plus the evidence behind it. */
|
|
114
|
-
export interface EpicActivationRationale {
|
|
115
|
-
pCheck: {
|
|
116
|
-
passed: boolean;
|
|
117
|
-
p: number;
|
|
118
|
-
threshold: number;
|
|
119
|
-
};
|
|
120
|
-
hotModuleCheck: {
|
|
121
|
-
passed: boolean;
|
|
122
|
-
touchedHotModules: string[];
|
|
123
|
-
};
|
|
124
|
-
greenfieldCheck: {
|
|
125
|
-
passed: boolean;
|
|
126
|
-
commitsObserved: number;
|
|
127
|
-
minCommits: number;
|
|
128
|
-
/**
|
|
129
|
-
* `true` when the caller flagged the project as non-git
|
|
130
|
-
* (`options.isGitProject === false`). In that case the gate is
|
|
131
|
-
* bypassed (`passed: true`) because the co-change signal does not
|
|
132
|
-
* apply — not because the history floor was met. Surfaced for audit
|
|
133
|
-
* so reviewers can distinguish "bypassed" from "satisfied".
|
|
134
|
-
*/
|
|
135
|
-
bypassedNoGit?: boolean;
|
|
136
|
-
/**
|
|
137
|
-
* Phase 10: cross-phase upstream task IDs the gate consulted.
|
|
138
|
-
* Empty when the current phase has no cross-phase deps (Phase 1,
|
|
139
|
-
* single-phase plans, declared-independent phases).
|
|
140
|
-
*
|
|
141
|
-
* Phase 13 (B19): optional because pre-Phase-10 records on disk
|
|
142
|
-
* (`.swarm/evidence/epic-promotions.jsonl`) lack this field.
|
|
143
|
-
* Renderers MUST default to `[]` when reading historical records.
|
|
144
|
-
*/
|
|
145
|
-
crossPhaseUpstreams?: string[];
|
|
146
|
-
/**
|
|
147
|
-
* Phase 10: cross-phase upstreams the predicate reported as NOT
|
|
148
|
-
* yet committed. Non-empty ⇒ the gate failed; the architect
|
|
149
|
-
* needs to wait for those tasks to commit before re-deciding.
|
|
150
|
-
*
|
|
151
|
-
* Phase 13 (B19): optional, same reason as above.
|
|
152
|
-
*/
|
|
153
|
-
missingUpstreams?: string[];
|
|
154
|
-
/**
|
|
155
|
-
* Phase 13 (B20): dep IDs the architect declared that don't
|
|
156
|
-
* resolve to any task in the plan. Usually an LLM typo; the gate
|
|
157
|
-
* fails CLOSED so the architect can see the bad ID and fix the
|
|
158
|
-
* declaration. Distinct from `missingUpstreams` because phantom
|
|
159
|
-
* IDs aren't tasks that need to be "committed" — they don't
|
|
160
|
-
* exist at all, and the remediation is "fix the dep ID", not
|
|
161
|
-
* "wait for the upstream to land".
|
|
162
|
-
*/
|
|
163
|
-
phantomDeps?: string[];
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
/** The verdict `decideEpicActivation` returns. */
|
|
167
|
-
export interface EpicActivationVerdict {
|
|
168
|
-
decision: 'promote' | 'demote';
|
|
169
|
-
p: number;
|
|
170
|
-
rationale: EpicActivationRationale;
|
|
171
|
-
/** Plain-English reasons the verdict went the way it did — for logs and UI. */
|
|
172
|
-
blockingReasons: string[];
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Decide whether the given tasks should be promoted to parallel execution
|
|
176
|
-
* via Lean Turbo's lane planner.
|
|
177
|
-
*
|
|
178
|
-
* Inputs are pre-resolved by the caller:
|
|
179
|
-
* - `tasks`: every task in scope (typically the whole plan), with the
|
|
180
|
-
* same `{ id, scope }` shape Capability B consumes. The caller
|
|
181
|
-
* handles `readTaskScopes` / `files_touched` resolution and any
|
|
182
|
-
* completed-task filtering.
|
|
183
|
-
* - `cochangePairs`: the analyzer's output (unfiltered) plus the
|
|
184
|
-
* `commitsObserved` count from `parseGitLog`. The greenfield gate
|
|
185
|
-
* consults the count directly so the function stays pure.
|
|
186
|
-
* - `options`: thresholds (typically read from
|
|
187
|
-
* `turbo.epic.mode.*` + `turbo.epic.cochange.*`).
|
|
188
|
-
*
|
|
189
|
-
* Output: structured verdict the caller persists to
|
|
190
|
-
* `.swarm/evidence/epic-promotions.jsonl` and surfaces via
|
|
191
|
-
* `/swarm epic status`.
|
|
192
|
-
*/
|
|
193
|
-
export declare function decideEpicActivation(tasks: CouplingTask[], cochangePairs: CoChangeEntry[], commitsObserved: number, options: EpicActivationOptions): EpicActivationVerdict;
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Calibration engine for Epic Mode Capability D.
|
|
3
|
-
*
|
|
4
|
-
* `applyCalibration(state, newRecords, options) → newState` is a pure
|
|
5
|
-
* function that walks fresh divergence records (those not yet processed)
|
|
6
|
-
* and produces an updated calibration state. The wiring code is responsible
|
|
7
|
-
* for: (a) reading the prior state, (b) filtering history to the
|
|
8
|
-
* unprocessed tail, (c) writing the new state.
|
|
9
|
-
*
|
|
10
|
-
* Hard design rules (brief §4.5-D + the user's ratified §20.3 defaults):
|
|
11
|
-
*
|
|
12
|
-
* 1. **Auto-tighten only on threshold.** A divergent task tightens
|
|
13
|
-
* `activationThresholdOverride` toward zero by `tightenStep`,
|
|
14
|
-
* bounded by `floorThreshold` (we never tighten below the floor —
|
|
15
|
-
* a value too small makes Epic Mode never promote anything).
|
|
16
|
-
*
|
|
17
|
-
* 2. **Hot-module list monotonically grows.** Files in a divergent
|
|
18
|
-
* task's `undeclared` set are added to `hotModuleAdditions`. The
|
|
19
|
-
* list is NEVER auto-shrunk; loosening a hot-module promotion
|
|
20
|
-
* requires manual intervention. This is a one-way ratchet.
|
|
21
|
-
*
|
|
22
|
-
* 3. **Loosen only after `loosenWindow` consecutive clean tasks.**
|
|
23
|
-
* Every clean (divergenceRatio === 0) task increments
|
|
24
|
-
* `consecutiveCleanCount`; every divergent task resets it to zero.
|
|
25
|
-
* When the counter reaches `loosenWindow`, the threshold is loosened
|
|
26
|
-
* by `loosenStep` toward the static config value (never past it) and
|
|
27
|
-
* the counter resets to zero. The hot-module list is NOT shrunk by
|
|
28
|
-
* loosening — only the threshold relaxes.
|
|
29
|
-
*
|
|
30
|
-
* 4. **No oscillation.** A clean-then-divergent-then-clean sequence
|
|
31
|
-
* cannot swing the threshold back and forth: every divergent task
|
|
32
|
-
* resets the clean-counter and tightens by `tightenStep`, so the
|
|
33
|
-
* threshold only moves toward zero in the divergent direction and
|
|
34
|
-
* toward the static value (with the clean-window gate) in the
|
|
35
|
-
* clean direction. Tests assert this invariant.
|
|
36
|
-
*/
|
|
37
|
-
import type { CalibrationState } from './calibration.js';
|
|
38
|
-
import type { DivergenceRecord } from './divergence-recorder.js';
|
|
39
|
-
export interface ApplyCalibrationOptions {
|
|
40
|
-
/** Static config value — the absolute ceiling for the threshold. */
|
|
41
|
-
staticThreshold: number;
|
|
42
|
-
/**
|
|
43
|
-
* Floor for the threshold — calibration never tightens past this.
|
|
44
|
-
* Default 0.05 — below that, Epic Mode effectively never promotes
|
|
45
|
-
* even on highly-decoupled plans.
|
|
46
|
-
*/
|
|
47
|
-
floorThreshold?: number;
|
|
48
|
-
/** Per-divergent-task tightening step. Default 0.02. */
|
|
49
|
-
tightenStep?: number;
|
|
50
|
-
/** Per-loosening-event step (toward static). Default 0.01. */
|
|
51
|
-
loosenStep?: number;
|
|
52
|
-
/** Consecutive-clean-tasks required before any loosening. Default 10. */
|
|
53
|
-
loosenWindow?: number;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Apply the calibration rules to a chronological list of NEW divergence
|
|
57
|
-
* records. Pure — no I/O, no side effects, deterministic for a given
|
|
58
|
-
* (state, newRecords, options) triple.
|
|
59
|
-
*
|
|
60
|
-
* The caller is responsible for tracking which records are "new" (typically
|
|
61
|
-
* by reading the full divergence history and slicing past the
|
|
62
|
-
* `processedRecords` count from the current state). This function does
|
|
63
|
-
* not deduplicate — feeding the same record twice will double-count its
|
|
64
|
-
* effect.
|
|
65
|
-
*/
|
|
66
|
-
export declare function applyCalibration(state: CalibrationState, newRecords: readonly DivergenceRecord[], options: ApplyCalibrationOptions): CalibrationState;
|
|
67
|
-
/**
|
|
68
|
-
* Resolve the effective activation threshold by combining the static config
|
|
69
|
-
* value with the calibration override (if any). The override is always a
|
|
70
|
-
* tighter or equal value to the static — calibration can never relax past
|
|
71
|
-
* static. Returns the static value when calibration state is null
|
|
72
|
-
* (fail-closed mode) or when no override is set.
|
|
73
|
-
*
|
|
74
|
-
* Belt-and-braces clamps:
|
|
75
|
-
* - upper bound: static ceiling (calibration never relaxes past it)
|
|
76
|
-
* - lower bound: 0 (a negative or absurdly small override — e.g. from a
|
|
77
|
-
* hand-edited calibration.json — would make Epic Mode never promote
|
|
78
|
-
* anything; treat 0 as the absolute floor here; callers that pass a
|
|
79
|
-
* higher `floor_threshold` to the engine get that bound at WRITE time,
|
|
80
|
-
* so this clamp only matters for corrupt on-disk values)
|
|
81
|
-
*/
|
|
82
|
-
export declare function effectiveActivationThreshold(staticThreshold: number, state: CalibrationState | null): number;
|
|
83
|
-
/**
|
|
84
|
-
* Union the static hot-module list (Lean Turbo's globals + protected) with
|
|
85
|
-
* the calibration's learned additions. Returns a fresh array; callers can
|
|
86
|
-
* pass this to `decideEpicActivation`'s effective-hot-module check.
|
|
87
|
-
*/
|
|
88
|
-
export declare function effectiveHotModules(staticHotModules: readonly string[], state: CalibrationState | null): string[];
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Durable calibration state for Epic Mode Capability D.
|
|
3
|
-
*
|
|
4
|
-
* Persists the LEARNED knob overrides that `decideEpicActivation` consults
|
|
5
|
-
* at runtime — the activation-threshold override (tighter than the static
|
|
6
|
-
* config when divergence has been observed) and the auto-added hot-module
|
|
7
|
-
* list (monotonically grows; never auto-shrinks per design).
|
|
8
|
-
*
|
|
9
|
-
* Lives at `<projectRoot>/.swarm/epic/calibration.json`. Pattern mirrors
|
|
10
|
-
* `src/turbo/epic/state.ts` exactly — atomic `tmp + rename`, per-directory
|
|
11
|
-
* fail-closed marker on malformed file, repair seam.
|
|
12
|
-
*
|
|
13
|
-
* No imports from `src/turbo/lean/` — purely additive to the Epic namespace.
|
|
14
|
-
*/
|
|
15
|
-
/** Persisted shape of `.swarm/epic/calibration.json`. */
|
|
16
|
-
export interface CalibrationState {
|
|
17
|
-
version: 1;
|
|
18
|
-
updatedAt: string;
|
|
19
|
-
/**
|
|
20
|
-
* Effective activation threshold override. When set, supersedes the
|
|
21
|
-
* static `turbo.epic.mode.activation_threshold` config value (which is
|
|
22
|
-
* always the absolute ceiling — calibration can tighten, never loosen
|
|
23
|
-
* past, the static value). Range: same as the static config — [0, 1].
|
|
24
|
-
*/
|
|
25
|
-
activationThresholdOverride?: number;
|
|
26
|
-
/**
|
|
27
|
-
* Modules promoted to the hot-module list by observed divergence.
|
|
28
|
-
* Monotonically grows — never auto-shrinks (loosening the hot-module
|
|
29
|
-
* list requires manual intervention; the calibration loop only adds).
|
|
30
|
-
* Sorted lexicographically for stable diffs. Bounded at
|
|
31
|
-
* {@link MAX_CALIBRATION_MODULES} on every save and load (issue #2483):
|
|
32
|
-
* once the cap binds, late-alphabet module paths are PERMANENTLY
|
|
33
|
-
* excluded from the list and — because additions are monotonic — can
|
|
34
|
-
* never re-enter (critic N5).
|
|
35
|
-
*/
|
|
36
|
-
hotModuleAdditions: string[];
|
|
37
|
-
/**
|
|
38
|
-
* Running counter of consecutive clean (divergenceRatio === 0) task
|
|
39
|
-
* outcomes since the last divergent task or the last loosening event.
|
|
40
|
-
* Drives the loosen-rule (loosen only after `loosenWindow` consecutive
|
|
41
|
-
* clean tasks). Cleared by the engine after any loosening or divergence.
|
|
42
|
-
*/
|
|
43
|
-
consecutiveCleanCount: number;
|
|
44
|
-
/** ISO 8601 timestamp of the most recent calibration-engine invocation. */
|
|
45
|
-
lastCalibrationAt?: string;
|
|
46
|
-
/** Number of divergence records processed by the engine so far. */
|
|
47
|
-
processedRecords: number;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Global cap on the persisted `hotModuleAdditions` list (issue #2483 §2).
|
|
51
|
-
* Enforcement (save AND load) keeps the lexicographically SMALLEST prefix of
|
|
52
|
-
* the sorted list — deterministic and order-respecting, with no invented
|
|
53
|
-
* score. N5 bias, stated plainly: once the cap binds, late-alphabet module
|
|
54
|
-
* paths are permanently excluded from the list and — because additions are
|
|
55
|
-
* monotonic — can never re-enter. The effective value resolves through
|
|
56
|
-
* `resolveRetentionCap` so the #2483 acceptance checks can shrink the cap
|
|
57
|
-
* below this default and prove the truncation clamps.
|
|
58
|
-
*/
|
|
59
|
-
export declare const MAX_CALIBRATION_MODULES = 500;
|
|
60
|
-
export declare function emptyCalibrationState(): CalibrationState;
|
|
61
|
-
export declare function isCalibrationStateUnreadable(directory: string): boolean;
|
|
62
|
-
export declare function repairCalibrationUnreadable(directory: string): void;
|
|
63
|
-
/**
|
|
64
|
-
* Read calibration state from disk. Seeds an empty file on first access so
|
|
65
|
-
* subsequent writes do not race on directory creation. Returns null when
|
|
66
|
-
* the file is malformed (fail-closed via `stateUnreadableMap`).
|
|
67
|
-
*
|
|
68
|
-
* Self-healing: when the in-memory unreadable marker is set, this function
|
|
69
|
-
* first attempts to re-validate the on-disk file. If a user (or another
|
|
70
|
-
* process) has repaired the file out-of-band, the marker auto-clears and the
|
|
71
|
-
* normal read proceeds. Without this, a long-lived plugin process would keep
|
|
72
|
-
* returning null until manually told to repair (adversarial review H2).
|
|
73
|
-
*/
|
|
74
|
-
export declare function loadCalibrationState(directory: string): CalibrationState | null;
|
|
75
|
-
/**
|
|
76
|
-
* Atomic write of calibration state. `tmp + rename` pattern with random
|
|
77
|
-
* suffix to avoid concurrent-collision; tmp file is best-effort cleaned up
|
|
78
|
-
* on rename failure so a failed write does not leave orphans.
|
|
79
|
-
*/
|
|
80
|
-
export declare function saveCalibrationState(directory: string, state: CalibrationState): void;
|