Repository navigation
refactor: second-pass sink-file and boundary governance #1084
Description
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 refactor(desktop): split main process orchestration #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(done: refactor(runtime): extract provider error classification #1214) — extract the ~270-line provider-error classification taxonomy (classifyError, regex tables, evidence normalization) into its own module. -
session-manager.ts(in flight: refactor(runtime): extract session branching into session-branch.ts #1253, needs rebase after feat(runtime): migrate agent tools to child sessions #1385) — 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(done: refactor(runtime): extract active compact facts #1259) — 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(in flight: refactor(headless): extract fixed prompt WAL types #1261, needs rebase after feat(headless): add createPierTaskRunner for DeepSWE via Pier #1352) — extract the ~340 lines of WAL event schema types intofixed-prompt-wal-types.ts.
packages/core + storage
-
core/settings.ts(done: refactor(core): split settings into domain owners #1265) — 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(done: refactor(storage): extract usage stats store #1266) — extract the usage-stats JSONL aggregation engine into a siblingusage-stats-store.tsthatSettingsStoredelegates to. -
core/local-memory.ts(blocked on feat(memory): add measurement foundation and scoped read gates #820 — coordinate before starting) — 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(done: refactor(desktop): centralize preload bridge contract #1204) — 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 (in flight: refactor: reuse shared result and hashing helpers #1374, approved) —
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) (done).
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. Declined after re-verification — the toggle reducers and renderer are bidirectionally coupled through shared render geometry (entryFirstLine/viewportTop); no clean boundary.core/settings.tsUsageRequestLog/UsageSummaryvsusage-stats/types.tstype overlap. Moved out of scope — two generations of the usage data model (Settings page v1 vs telemetry v2); needs its own migration issue, not a mechanical dedup.headless/fixed-prompt-controller.ts: second, production-unused Harbor result parser (readHarborTaskRunOutput). Suggested: fold into refactor(headless): extract fixed prompt WAL types #1261 — demote to test-private or delete.headless/ahe-evidence-export.ts: evidence export vs target-snapshot building split. Declined after re-verification — export and target-snapshot building share one result type; split value is low.
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
- refactor: split sink files before visual polish #363 first-pass sink-file governance (predecessor; closed with the instruction to open this follow-up).
- refactor(desktop): split main process orchestration #385
main/main.tsfirst split (theregister*Ipcpattern this issue extends). - chore(desktop): CSS/token governance and magic-number cleanup #1046 CSS/token governance (adjacent, separate track).
Status update (2026-07-23)
A full re-verification against current main confirmed the remaining unclaimed slices are still valid; refreshed scopes now live in per-slice sub-issues (#1405–#1414) so they can be claimed individually. In-flight: #1253 and #1261 need a rebase; #1374 is approved. A third-pass full-repo scan found a new set of verified findings, tracked in #1404; source-regex extraction-contract test governance is tracked in #1403.
Activity
refactor(headless): keep MAKA_CELL_TIMEOUT_SEC lenient per the shared…
refactor: correct containment-guard doc and dedupe office-document-to…
refactor(headless): correct lenient-parse contract docs and decouple …
test(desktop): scope project-root contract to owning files and unit-t…
refactor(runtime): centralize filesystem-containment guards (#1136)
refactor(headless): split harbor-cell.ts into context-budget, tool-ex…
chore(desktop): drop dead network-patch exports surfaced by the IPC s…
refactor(desktop): split registerIpc into per-domain register*Ipc mod…
Nyvo-io commentedon Jul 18, 2026
I would like to claim the
apps/desktop/src/preload/preload.tsbridge-contract slice from #1084.I will first audit the current
window.makadeclarations, the object exposed throughcontextBridge, every preload consumer, and the browser-API attachment encoder that currently crosses the preload/main dependency boundary.Planned scope:
window.makabridge shape once in a preload-safe shared module;preload.tssatisfy that contract and linkglobal.d.tsto the same type;src/main/without changing its wire format or IPC channel behavior;window.makasurface;This will remain behavior- and visually-neutral. It will not rename IPC channels, widen renderer capabilities, add preload-to-main imports, or redesign the bridge.
Planned verification:
git diff --check;I will wait for maintainer confirmation of this slice before creating a branch or starting implementation.
Nyvo-io commentedon Jul 18, 2026
Implemented the claimed preload bridge-contract slice in PR #1204: #1204
The PR centralizes the
MakaBridgecontract undersrc/preload, makes the exposed bridge satisfy it, moves attachment encoding out ofsrc/main, and adds dedicated preload typechecking. IPC channels and attachment wire format are unchanged.xuruiray commentedon Jul 18, 2026
Implemented the
tool-runtime.tsprovider-error classification slice in PR #1214: #1214It extracts the taxonomy and evidence normalization into a dedicated dependency-free module, preserves existing runtime behavior, and adds focused classification and boundary tests. Typecheck, test, and e2e CI checks are green.
Astro-Han commentedon Jul 19, 2026
I'd like to claim the
context-budget.tssplit from the runtime/compaction lane, and the followingai-sdk-backend.tsorchestrator extraction as the same owner (per the lane's "sequence them under one owner to avoid import churn" note).PR1 —
context-budget.ts: extract the synthesis-cache subsystem intosynthesis-cache.ts(pairing the existingsynthesis-cache-artifacts.ts) and the history-compact block engine intohistory-compact.ts(pairinghistory-compact-checkpoint.ts/compaction-boundary.ts); move the cross-block shared pure helpers into acontext-budget-helpers.tsleaf; keep budget shaping + orchestration hooks incontext-budget.tsas the compatibility re-export surface. Behavior- and visually-neutral; public imports preserved via re-exports; no reverse imports from new leaves; co-migrate source-reading contract tests.PR2 (after PR1 lands) —
ai-sdk-backend.ts: extract the ~1800-line history-compaction/context-budget orchestrator (build*PrepareStepfamily, mid-turn compaction, overflow recovery, compact/synthesis-cache load/write) into a dedicated collaborator;AiSdkBackendkeeps only streamText↔event/permission adaptation.Will wait for maintainer confirmation before opening a branch.
fix(runtime): use resolved charsPerToken in checkpoint replay diagnos…
26 remaining items
github-actions commentedon Sep 2, 2026
This issue has had no human activity for 30 days and has been marked stale. It will be closed in 30 days unless someone comments.
If the issue is still current, please confirm it against the latest
mainand add any information that would help move it forward. Assigned issues and issues labelledpinnedare exempt from this policy.github-actions commentedon Sep 18, 2026
This issue has had no human activity for 30 days and has been marked stale. It will be closed in 30 days unless someone comments.
If the issue is still current, please confirm it against the latest
mainand add any information that would help move it forward. Assigned issues and issues labelledpinnedare exempt from this policy.github-actions commentedon Oct 18, 2026
This issue has been closed because it received no human response during the 30-day grace period. This is not a judgement on the value of the report.
If the issue still applies to the latest
main, please comment with updated evidence so a maintainer can reopen it, or open a follow-up issue with the missing information.