refactor: second-pass sink-file and boundary governance
#1084 aperta il 16 lug 2026
Metriche repository
- Star
- (1 star)
- Metriche merge PR
- (Metriche PR in attesa)
Descrizione
Context
First-pass sink-file governance (#363) split components.tsx, SettingsModal.tsx, ProvidersPanel.tsx, renderer/main.tsx, and main/main.ts, and closed with the instruction to track a fresh second-pass scan in a follow-up issue. This is that issue.
A full-repo scan (38 area/file audit agents + per-finding adversarial verification against current main, calibrated with #363's rules) confirmed ~40 findings. As in #363, the problem is never file length by itself: every finding below is about unrelated responsibilities sharing one module, a broken verification boundary, a parallel implementation that can silently diverge, or a name/location that misleads. Large single-responsibility data/fixture/generated files were explicitly excluded.
Headline evidence
apps/desktop/src/main/main.tsregrew from 1663 lines (post #385) to 2412.registerIpc()is ~800 lines inlining ≥8 feature domains, while 11 sibling*-ipc-main.tsfiles already follow aregister*Ipc(deps)pattern — the seam exists but was applied inconsistently. Its own contract test regex-matches raw source text becauseregisterIpcruns as a module side effect and cannot be invoked in isolation: the verification boundary is already broken.packages/headless/src/harbor-cell.ts(1810 lines) fuses session orchestration, a ~600-line env→ContextBudgetPolicy compiler, subprocess/tool-executor plumbing, and credential resolution.runtime-policy-ab-run.tsimports one env-key list from it and drags innode:child_process, runtime backends, and credentials.json reading. 44 commits have touched this file for unrelated reasons.- Security-relevant duplication: the filesystem-containment guards (
isContainedPath/isSafeSkillId,isInside/toRelative) exist as byte-identical private copies inpackages/runtime/src/skills.ts,apps/desktop/src/main/explore-agent-tool.ts, andapps/desktop/src/main/managed-skill-sources.ts. A future fix to the containment check must currently be applied in multiple places.
PR mapping
- High and medium slices: one file, one PR — each checkbox below is one independently reviewable, independently revertible PR.
- Low-severity mechanical items: batched into two cleanup PRs (one per area) instead of one PR per one-line change.
- Every PR follows the worktree/branch convention; flat off
main, no stacking.
Order of work
- The two high-severity sinks first (
main.ts,harbor-cell.ts) plus the security-relevant guard dedup. - Remaining splits grouped by package, in parallel lanes (see Parallelization).
- The two mechanical cleanup batches last (or whenever a lane frees up — they conflict with nothing outside their own files).
Invariants
Same as #363: behavior- and visually-neutral; preserve public imports (keep re-export compatibility where a moved symbol is public); no reverse imports from new leaf files; co-migrate source-reading contract tests; flat PRs off main; proportional verification (typecheck/build + targeted contract tests for pure moves).
Slices
High
-
apps/desktop/src/main/main.ts— migrate the un-migratedregisterIpc()domains (sessions, onboarding, settings/bots/network, permissions+capabilities+health, quickChat+expertTeam, gateway, workspaceInstructions, git, workspace search) intoregister*Ipc(deps)modules following the existing 11-file pattern;registerIpcbecomes pure composition. The backing logic modules (onboarding-service.ts,quick-chat.ts,expert-team-start.ts,permissions-actions.ts,capability-snapshot.ts) already exist. -
packages/headless/src/harbor-cell.ts— four-way split: context-budget env compiler →harbor-cell-context-budget-env.ts; tool executors + subprocess helpers →harbor-cell-tool-executor.ts; provider/credential resolution → merge into the existingprovider-env.tsseam;harbor-cell.tskeeps orchestration + backend wiring. Also dedupebooleanEnv/positiveIntEnv/numericEnvintoheadless-run-env.ts(a third private copy lives inharbor-task-runner.ts). - Containment-guard dedup (security) — single shared home for
isContainedPath/isSafeSkillId(runtime) andisInside/toRelative(desktop);managed-skill-sources.tsandexplore-agent-tool.tsimport instead of keeping byte-for-byte copies.
packages/runtime
-
context-budget.ts(3001) — extract the history-compact block engine intohistory-compact-*.tssiblings and the full synthesis-cache subsystem intosynthesis-cache.ts(pairing existingsynthesis-cache-artifacts.ts); keep only budget shaping + orchestration hooks, withcontext-budget.tsas the compatibility export surface. -
ai-sdk-backend.ts(4347) — extract the ~1800-line history-compaction/context-budget orchestrator (thebuild*PrepareStepfamily, mid-turn compaction, overflow recovery, compact/synthesis-cache load/write methods) into a dedicated collaborator;AiSdkBackendkeeps the streamText↔event/permission adaptation. Land after thecontext-budget.tssplit to avoid import churn. -
runtime-kernel.ts— extract the history-compact checkpoint cache/CAS-write/cleanup coordinator into a sibling next tohistory-compact-checkpoint.ts; resolve the privateAsyncEventQueueduplicate againstasync-queue.ts(reuse or rename with documented contract difference). -
tool-runtime.ts— extract the ~270-line provider-error classification taxonomy (classifyError, regex tables, evidence normalization) into its own module. -
session-manager.ts— extract branch-session creation + runtime-ledger cloning (~250 lines, own verification boundary) intosession-branch.ts; importheaderLineagefromagent-run-recovery.tsinstead of the verbatim copy. -
agent-run.ts— extract the prior-run context assembly (buildPriorRuntimeContext+ repair/backfill helpers) intoprior-run-context.ts; move the pure status-projection helpers intosession-projection-helpers.tswhere their siblings already live. -
skills.ts(1189) — split along the package's existing convention into discovery / scan / metadata / (remaining) modules, keeping the@maka/runtimepublic exports stable. -
active-full-compact.ts— extract the ~380-line regex fact-extraction engine (summary fields only) into a sibling file. -
computer-use-tools.ts(1763) — extract the wire-protocol codec (zod schemas,adaptToCuAction,snapshotComputerParams) mirroringopenai-computer-codec.ts; move theCuDispatchBackend/CuRunResult/… contract types into a dedicated types module so adapters stop importing the implementation file.
packages/headless
-
prompt-candidate-loop.ts(1007) — extract the git safety/rollback wrapper and the trajectory/tool-failure digest extraction into siblings; dedupe the two hand-rolled "held-in task set hash" implementations (rsi-round-analysis.tsre-implements it and the outputs are compared with strict equality across the WAL boundary). -
task-agent-controller.ts— extract the permission-intervention decision engine intopermission-intervention.tsbesidepermission-grants.ts. -
fixed-prompt-controller.ts— extract the ~340 lines of WAL event schema types intofixed-prompt-wal-types.ts.
packages/core + storage
-
core/settings.ts— extract the bot-chat channel subsystem (types, defaults, ~250-line readiness state machine) intobot-chat-settings.ts; move the web-search credential-reconciliation logic intoweb-search.ts; resolve theNetworkSettingsname collision withsettings/network-settings.ts. -
storage/settings-store.ts— extract the usage-stats JSONL aggregation engine into a siblingusage-stats-store.tsthatSettingsStoredelegates to. -
core/local-memory.ts— replace the embedded hand-rolled SHA-256 with the same digest-injection seamoauth-subscription.tsuses; collapse the duplicated meta-value sanitizer ontonormalizeMetaValue.
apps/desktop + cli + computer-use
-
preload/preload.ts— define thewindow.makabridge shape once and linkpreload.ts(satisfies) andglobal.d.tsto it (today they are two hand-maintained declarations with no compiler link); relocate the browser-API attachment encoder out ofsrc/main/(preload's own header forbids main-process deps). -
cli/pi-tui-runner.ts— extract the shell-run hydration/buffering state machine intoshell-run-hydration.ts. -
computer-use/cua-driver-backend.ts(2701) — extract the TOCTOU target staleness/occlusion re-verification intocua-driver-target-resolution.ts, mirroringcua-driver-snapshot.ts.
Mechanical cleanup batches (low severity, one PR each)
- Batch: core + runtime mechanical —
semantic-compact.tsreusesrequest-shape.ts's exportedstableHash/stableStringifyinstead of its localsortJson/sha256trio; move the genericResult<T>helper fromcore/settings/result.tsto@maka/core/result. - Batch: desktop + ui mechanical — rename
OnboardingHero.tsx,FirstRunChecklist.tsx,SettingsModal.tsx,ProvidersPanel.tsxto kebab-case; replaceapp-shell.tsx's hand-rolled pending-set with theuseKeyedPendingRegistryhook it already uses four times; move the four authored Markdown skill bodies out ofmain/skills.tsinto content files; extractcomposer.tsx's self-contained workspace/branch-picker row intocomposer-workspace-row.tsx(mirroringchat-model-switcher.tsx).
Parallelization
All slices touch disjoint files except two ordered pairs, so the work splits into independent lanes that different contributors can pick up concurrently (one worktree + branch per slice):
- Lane desktop —
main.ts, preload, desktop+ui mechanical batch (batch last; it sharesapp-shell.tsximport-line churn with nothing else). - Lane runtime/compaction —
context-budget.tsthenai-sdk-backend.ts(same feature family; sequence them under one owner to avoid import churn);runtime-kernel.tsis same-family but disjoint files, can go to a second owner. - Lane runtime/other —
tool-runtime.ts,session-manager.ts,agent-run.ts,skills.ts,active-full-compact.ts,computer-use-tools.ts: six disjoint files, up to six owners. - Lane headless —
harbor-cell.ts,prompt-candidate-loop.ts,task-agent-controller.ts,fixed-prompt-controller.ts: disjoint. - Lane core/storage —
settings.ts,settings-store.ts,local-memory.ts, core+runtime mechanical batch. - Lane cli/cua —
pi-tui-runner.ts,cua-driver-backend.ts.
Ordering constraints: (1) context-budget.ts split lands before the ai-sdk-backend.ts orchestrator extraction; (2) the containment-guard dedup and the runtime/skills.ts split both involve skills.ts — they compose cleanly as long as the @maka/runtime public exports stay stable, but prefer one owner for both.
Borderline (evidence confirmed, worth-a-PR disputed — decide per slice, default skip)
cli/pi-transcript.ts: pure transcript reducer vs ANSI rendering layer separation.core/settings.tsUsageRequestLog/UsageSummaryvsusage-stats/types.tstype overlap.headless/fixed-prompt-controller.ts: second, production-unused Harbor result parser (readHarborTaskRunOutput).headless/ahe-evidence-export.ts: evidence export vs target-snapshot building split.
Out of scope
Same as #363: visual redesign, breaking public imports, splitting large single-purpose data files for line count, rewriting runtime behavior while moving files, new dependency/import-cycle tooling.
References
- #363 first-pass sink-file governance (predecessor; closed with the instruction to open this follow-up).
- #385
main/main.tsfirst split (theregister*Ipcpattern this issue extends). - #1046 CSS/token governance (adjacent, separate track).