tracking(cleanup): monthly scavenger sweep — 2026-09
- Dominant language
- TypeScript
- Stars
- 5.4k
- Forks
- 502
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 715
Description
> We would rather Maka did not grow heavier than it needs to be, so this opens a **monthly scavenger sweep**. A new one starts on the first of each month. This round runs from 2026-09-04; the next is 2026-10-01.
Maka carries about 576,000 lines of product code and 486,000 lines of test code. Very little of that is wrong. A lot of it is more than it needs to be: two implementations of one rule, a fixture rebuilt in twenty files, a 7,000-line module that grew one honest commit at a time. None of it is anyone's fault and none of it will be fixed by a rewrite. It gets fixed by someone taking one area for one month and leaving it smaller than they found it.
How to claim:
1. Choose an area below, or a smaller piece of one — good refactors are welcome at any size — and check that nobody else is already on it.
2. Open a new issue describing the redundancy or the weight you mean to remove, with a plan detailed enough to argue with.
3. Comment on this month's issue with a link to that issue.
Areas are drawn along package and directory lines, so two claimants never need to coordinate. One person can hold several. A claim that stops moving for a long time is released, and its area goes back on the board.
## What counts as done
Every claim ends in one or more pull requests that state a **measured** result. "Simplified X" is not a result. These are:
- a rule that had two implementations now has one, and the second is deleted;
- a type, helper or fixture that existed in N places now exists once;
- a module over 2,000 lines is split along a seam that already existed in it, with no behaviour change;
- dead code removed, with the search that proves nothing reaches it;
- a debt counter in `apps/desktop/renderer-architecture.json` goes down.
**Not** results: renaming things, reformatting, moving files without reducing anything, replacing a clear loop with a clever one, or deleting a test.
## Part A — product code
| # | Area | Scope | Size | Where to start |
|---|---|---|---|---|
| A1 | Storage · session metadata | `packages/storage/src/sqlite-session-metadata-store.ts` and its callers | 7,288 lines in one file | The largest file in the repository. The read face and the write face barely touch. |
| A2 | Storage · runtime store and policy | `sqlite-runtime-store.ts`, `runtime-policy/`, `agent-run-store.ts` | ~11,000 lines | Three files above 2,000 lines each. |
| A3 | Storage · everything else | the remaining 118 top-level files | ~44,000 lines | 121 files sit flat at the top level with almost no grouping. |
| A4 | Runtime · session kernel | `session-manager.ts`, `runtime-kernel.ts` | 9,005 lines | Two cores that grew together. |
| A5 | Runtime · provider backend | `ai-sdk-backend.ts`, `model-*.ts` | ~8,000 lines | 4,930 lines in one file, changed constantly. |
| A6 | Runtime · tool runtime | `tool-runtime.ts`, `computer-use-tools.ts` | 6,881 lines | Two files near 3,000 lines. |
| A7 | Runtime · everything else | the remaining ~250 files | ~90,000 lines | Compaction, context, permissions. Large enough to split further — say so when claiming. |
| A8 | Runtime Host · server coordinators | `packages/runtime-host/src/server/`, 130 files | ~50,000 lines | Several coordinators above 2,000 lines. |
| A9 | Runtime Host · everything else | peer mesh, client, protocol, operator | ~50,000 lines | `peer-mesh/node.ts` is 2,426 lines. |
| A10 | Core | `packages/core/src`, 157 files | 51,620 lines | Types and contracts. Simplification here pays out in every other area. |
| A11 | Desktop · main process | `apps/desktop/src/main/`, 190 files | 56,280 lines | Updates, Host boot, IPC. |
| A12 | Desktop · renderer | `apps/desktop/src/renderer/`, 393 files across 11 feature slices | 85,685 lines | The renderer ratchet already records per-file debt, so results here are countable without argument. |
| A13 | CLI and TUI | `packages/cli/src`, 91 files | 42,375 lines | `pi-tui-runner.ts` is 4,238 lines. |
| A14 | UI component library | `packages/ui/src`, 129 files | 31,019 lines | `composer.tsx` is 2,180 lines. |
| A15 | Preload and bridge | `apps/desktop/src/preload/`, 16 files | 6,566 lines | `preload.ts` alone is 3,754 lines and is the only channel between main and renderer. Narrowing it pays on both sides. |
| A16 | Architecture documents | `docs/architecture/`, 31 files | — | Several are kept in two languages, and drift between a document and its implementation has been found more than once. Reconcile or retire. |
## Part B — test code
Tests are 486,000 lines across 1,942 files. In `packages/runtime` there is more test than source. This half needs its own rules, because the obvious way to make a test suite smaller is to make it prove less.
| # | Area | Scope | Size | Where to start |
|---|---|---|---|---|
| T1 | Runtime backend and kernel tests | `ai-sdk-backend.test.ts` (16,206), `session-manager.test.ts` (14,887) | 31,000 lines in two files | Both are over three times the size of what they test. |
| T2 | Runtime · remaining tests | 229 files | ~106,000 lines | Test-to-source ratio 1.22, the highest in the repository. |
| T3 | Runtime Host coordinator tests | `root-turn-coordinator` (6,451), `message-coordinator` (4,041), `host-kernel` (3,848) and neighbours | ~30,000 lines | 21 fixture files here; much of the setup repeats. |
| T4 | Runtime Host · remaining tests | ~170 files | ~74,000 lines | |
| T5 | Storage tests and fixtures | 112 files including 28 fixtures | 50,578 lines | The most fixture-heavy package; table setup is rebuilt repeatedly. |
| T6 | CLI and TUI tests | `pi-tui-runner.test.ts` (10,499), `pi-transcript.test.ts` (5,187) | 41,784 lines | |
| T7 | Desktop tests | 290 files across main and renderer | 80,576 lines | |
| T8 | End-to-end, stories and scripts | e2e 37 files (7,423), stories 16 files (10,171), `scripts/*.test.mjs` 44 files (12,375) | ~30,000 lines | e2e flakiness is a standing cost; three separate flakes surfaced in one week of recent work. |
`packages/core` and `packages/ui` have ratios of 0.40 and 0.31 and are thin rather than heavy, so their tests stay with A10 and A14 rather than becoming their own areas.
### Acceptance for Part B
The same measured-result rule applies, with three additions, because a smaller suite is not automatically a better one.
1. **Coverage may not fall.** A deleted test is only a result when a named other test already proves the same thing, and the claim says which.
2. **Every test touched must fail without the code it tests.** Remove the implementation line, watch it go red, put it back. Say in the pull request that this was done. This is not ceremony: in recent work three new tests passed against the unchanged code because a fixture default happened to satisfy them, and a reviewer found it rather than the author.
3. **Prefer driving the real entry point.** A test that hands a value directly to an internal function still passes when the call site that produces that value is deleted. Where that is cheap to fix, fix it.
## Rules
- One pull request per coherent change, not per area. A 4,000-line file does not need to be finished in one pass.
- No behaviour change. If you find a bug, open an issue and keep it out of the cleanup pull request.
- Existing gates decide the argument: `renderer-architecture`, the protocol epoch check, ASF headers, lint, format, typecheck.
- If an area turns out to be two areas, say so here rather than quietly widening the claim.
## Carry-over
Areas nobody claims roll into next month's issue, along with whatever the current round leaves unfinished.
简体中文
> 我们并不希望 Maka 在非必要情况下变得过于臃肿,所以现在发起 **每月进行一次的清道夫行动。** 每月一号开新的一份。本轮从 2026-09-04 开始,下一轮 2026-10-01。
Maka 现在有约 57.6 万行产品代码和 48.6 万行测试代码。其中错的很少,多余的不少:同一条规则有两处实现,同一个夹具在二十个文件里各建一遍,一个七千行的模块是靠一次次诚实的提交长出来的。这不怪谁,也不会被一次重写解决。它只会被这样解决:有人认领一个板块,做一个月,走的时候让它比来时更小。
认领方式如下:
1、选择你想认领的板块(也可能是比 issue 中划分的板块更小的范围,我们欢迎各种级别的优秀重构),并确认没有其他人在处理
2、开启一个新的 issue,描述清楚现在想解决的冗余/臃肿部分,并提出详细的处理方案
3、在当前月开启的 issue 下评论并链接到你的设计 issue
对于认领但是长久没有推进的工作,我们会取消认领,并重新放开相关部分的可认领状态
## 怎样算做完
每次认领最终落成一个或多个 PR,PR 里要写出**可度量**的结果。"简化了 X"不是结果。下面这些是:
- 一条规则原本有两处实现,现在只剩一处,另一处被删除;
- 一个类型、辅助函数或夹具原本存在于 N 处,现在只有一处;
- 一个两千行以上的模块,沿着它本来就存在的接缝拆开,行为不变;
- 删除死代码,并给出"没有任何路径能到达它"的检索证据;
- `apps/desktop/renderer-architecture.json` 里的某个债务计数下降。
**不算**结果:改名、重排格式、只挪文件而不减少任何东西、把清楚的循环换成聪明的写法、删测试。
## 第一部分 · 产品代码
| # | 板块 | 范围 | 规模 | 从哪下手 |
|---|---|---|---|---|
| A1 | 存储 · 会话元数据 | `packages/storage/src/sqlite-session-metadata-store.ts` 及其调用方 | 单文件 7,288 行 | 全仓最大的文件,读面和写面几乎不相干 |
| A2 | 存储 · 运行时存储与策略 | `sqlite-runtime-store.ts`、`runtime-policy/`、`agent-run-store.ts` | 约 11,000 行 | 三个 2,000 行以上的文件 |
| A3 | 存储 · 其余 | 顶层剩余 118 个文件 | 约 44,000 行 | 121 个文件平铺在顶层,几乎没有分组 |
| A4 | Runtime · 会话内核 | `session-manager.ts`、`runtime-kernel.ts` | 9,005 行 | 两个一起长大的核心 |
| A5 | Runtime · 供应商后端 | `ai-sdk-backend.ts`、`model-*.ts` | 约 8,000 行 | 单文件 4,930 行,改动最频繁 |
| A6 | Runtime · 工具运行时 | `tool-runtime.ts`、`computer-use-tools.ts` | 6,881 行 | 两个接近 3,000 行的文件 |
| A7 | Runtime · 其余 | 剩余约 250 个文件 | 约 90,000 行 | 压缩、上下文、权限。大到应当再切分,认领时请说明 |
| A8 | Runtime Host · server 协调器 | `packages/runtime-host/src/server/`,130 个文件 | 约 50,000 行 | 多个 2,000 行以上的 coordinator |
| A9 | Runtime Host · 其余 | peer mesh、client、protocol、operator | 约 50,000 行 | `peer-mesh/node.ts` 2,426 行 |
| A10 | Core | `packages/core/src`,157 个文件 | 51,620 行 | 类型与契约层,这里的简化会外溢到其他所有板块 |
| A11 | Desktop · 主进程 | `apps/desktop/src/main/`,190 个文件 | 56,280 行 | 更新、Host 引导、IPC |
| A12 | Desktop · 渲染层 | `apps/desktop/src/renderer/`,393 个文件、11 个 feature 切片 | 85,685 行 | 已有渲染层债务台账逐文件记账,成果无需争辩即可计量 |
| A13 | CLI 与 TUI | `packages/cli/src`,91 个文件 | 42,375 行 | `pi-tui-runner.ts` 4,238 行 |
| A14 | UI 组件库 | `packages/ui/src`,129 个文件 | 31,019 行 | `composer.tsx` 2,180 行 |
| A15 | 预加载与桥接 | `apps/desktop/src/preload/`,16 个文件 | 6,566 行 | 仅 `preload.ts` 就 3,754 行,是主进程与渲染层之间唯一的通道,收窄它两边都受益 |
| A16 | 架构文档 | `docs/architecture/`,31 篇 | — | 其中多篇维护中英两份,文档与实现漂移已不止一次被发现。要么对齐,要么退役 |
## 第二部分 · 测试代码
测试有 1,942 个文件、48.6 万行。在 `packages/runtime` 里,测试比源码还多。这一半需要自己的规则,因为让测试套件变小最省事的办法,就是让它少证明一些东西。
| # | 板块 | 范围 | 规模 | 从哪下手 |
|---|---|---|---|---|
| T1 | Runtime 后端与内核测试 | `ai-sdk-backend.test.ts`(16,206)、`session-manager.test.ts`(14,887) | 两个文件 31,000 行 | 都是被测源文件的三倍以上 |
| T2 | Runtime · 其余测试 | 229 个文件 | 约 106,000 行 | 测源比 1.22,全仓最高 |
| T3 | Runtime Host 协调器测试 | `root-turn-coordinator`(6,451)、`message-coordinator`(4,041)、`host-kernel`(3,848)及邻近文件 | 约 30,000 行 | 这里有 21 个夹具文件,大量准备代码重复 |
| T4 | Runtime Host · 其余测试 | 约 170 个文件 | 约 74,000 行 | |
| T5 | 存储测试与夹具 | 112 个文件,含 28 个夹具 | 50,578 行 | 夹具最重的包,建表准备被反复重建 |
| T6 | CLI 与 TUI 测试 | `pi-tui-runner.test.ts`(10,499)、`pi-transcript.test.ts`(5,187) | 41,784 行 | |
| T7 | Desktop 测试 | 主进程与渲染层共 290 个文件 | 80,576 行 | |
| T8 | 端到端、stories 与脚本 | e2e 37 个文件(7,423)、stories 16 个(10,171)、`scripts/*.test.mjs` 44 个(12,375) | 约 30,000 行 | e2e 抖动是长期成本,近期一周的工作里就撞上三种不同的抖动 |
`packages/core` 与 `packages/ui` 的测源比只有 0.40 和 0.31,属于偏薄而非偏重,因此它们的测试并入 A10 与 A14,不单列板块。
### 第二部分的验收
同样要求可度量的结果,另加三条,因为更小的套件并不自动等于更好的套件。
1. **覆盖不得下降。** 删掉一个测试只有在"另一个具名测试已经证明同一件事"时才算结果,并且要在 PR 里点名是哪一个。
2. **动过的每个测试,去掉它所测的实现后必须失败。** 把那行实现删掉,看它变红,再放回去,并在 PR 里说明做过这一步。这不是仪式:近期就出现过三个新测试在未改动的代码上照样通过,因为夹具默认值恰好满足了它们,而且是评审发现的,不是作者。
3. **优先驱动真实入口。** 一个把值直接喂给内部函数的测试,在产生这个值的调用点被删掉之后依然会通过。凡是修起来不贵的,就修。
## 规则
- 一个 PR 对应一处自洽的改动,而不是一个板块一个 PR。四千行的文件不必一次改完。
- 不改变行为。发现 bug 就单独开 issue,别混进清理 PR。
- 争议由现有门禁裁决:`renderer-architecture`、协议 epoch 检查、ASF 头、lint、format、typecheck。
- 如果发现某个板块其实是两个板块,请在这里说明,而不是悄悄扩大认领范围。
## 顺延
无人认领的板块顺延到下个月那一份,本轮未做完的部分同样顺延。
Contributor guide
Research direction
Choose one area from the product or test tables, then read its named files and callers or tests to identify a specific redundancy or source of weight. Open a scoped design issue before claiming it here. Done means a behavior-preserving pull request reports a measured reduction, passes the relevant tests and existing lint, format, typecheck, and architecture gates.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- developer-experience, tooling
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100