Skip to content

[Decision] Large source files: replace the hand-cut split with a script-generated split per file, so the remaining monoliths split in days, not months #29465

Open

Description

@objectstack-fleet

director#1 · os-support-ai · session_01WGufzg12BtjFc5rHp7YD1J

Ruled: 6583399215 · letter A · 2026-11-02T17:17Z

Filing gate ②, a decision only the maintainer can make. The maintainer, in the director session, after the director's project assessment: 「同意」 to filing the follow-ups, then 「我首先关心的是这么多大文件有没有快速分拆的方案」. ⛔ Not a claim. Reader who acts: the maintainer rules here; then the domain:server seat (engine surface), the domain:spec seat and the domain:ui seat, one card per file. This card does not reopen #24586 (ruled A, 6270097840); it asks whether the execution method changes.

维护者速读

  • 问题:拆分决策 [Decision] Split the platform's largest, fastest-growing source files (protocol.ts 32,428 lines, +10,002 in 30 days) the way rest-server.ts was split, or leave them #24586 已裁 A 并在执行,但手工逐个方法搬,太慢,而且有两个文件一直没开工。
  • 实测:protocol.ts 已落 35 刀,13 天从 33,065 行降到 25,055 行;objectql/engine.ts 21 刀后停摆,仍有 23,050 行;sql-driver.ts 系列已关卡,仍有 18,333 行;conversions/registry.ts(15,659 行)和 StudioDesignSurface.tsx(12,536 行,7 天 60 次提交)从未立卡。全仓 42 个非测试源文件超过 5,000 行。
  • 推荐 A:改为脚本生成拆分。每个文件写一次确定性的搬迁脚本,在合并前对最新 main 重新生成,不靠 rebase;验证是机械的,搬走的每个方法体逐字节与原文一致。先拿 sql-driver.ts 试点。
  • 代价:每个文件落地时,该文件要短暂停止派发新改动;拆分 PR 超过 3000 行,需要您逐个批准。
  • 您要做的一个动作:回一个字母(A / B / C / D)。

Measured (origin/main, 2026-11-02)

file lines now at its card's filing commits in 7 days card split mechanism
packages/metadata-protocol/src/protocol.ts 25,055 33,065 (10-23) 85 #25467, cut 35 landed (#28090) class: body to section module, stub in class
packages/objectql/src/engine.ts 23,050 23,903 56 #25522, pm:blocked, "cut 21 re-priced, series spent, no PR" (2026-11-01) class (ObjectQL, lines 5324–22355, ~278 members, 227 private)
packages/drivers/driver-sql/src/sql-driver.ts 18,333 22,096 14 #25521, closed completed after cut 21 class (SqlDriver, ~268 members)
packages/spec/src/conversions/registry.ts 15,659 — 14 none (the domain:spec half of #24586's restart act was never filed) table: 641 entries feeding CONVERSIONS_BY_MAJOR
ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx 12,536 — 60 none (crossed 10,000 lines after the ruling) React component: not mechanical
packages/services/service-automation/src/engine.ts 9,934 13,735 25 #25222, closed done
plugin-security/src/security-plugin.ts · plugin-auth/src/auth-manager.ts 5,909 · 5,851 10,746 · 10,338 — #25223 · #25224, closed done
  • Re-check: git show origin/main:PATH | wc -l; git log --since='7 days ago' --oneline origin/main -- PATH | wc -l.
  • Pace of the hand method, measured on the one live series: protocol.ts lost 8,010 lines over 2026-10-23 → 11-02 (35 cuts merged, 68 protocol-*.ts section modules now exist). Each cut is a full dispatch: claim, dev, derived gates, review, merge queue. Cuts move from one member (cut 32, 10 body lines) to 22 members (cut 33). The two class series that ended (sql-driver.ts, engine.ts) ended with 18,333 and 23,050 lines still in the file: the easy seams ran out before the file was small.
  • Why a cut is small: every cut is serial with the file's in-flight PRs (protocol.ts takes about 12 commits a day), and a hand-written move has to be re-verified by a reviewer as move-only.

Governing text

Options

what it does what a customer notices workload
A Per file, one deterministic codemod (ts-morph; packages/cli already depends on it) that applies the cut pattern the series already uses, to a whole section at once: method bodies move to section modules, the class keeps one-line stubs, shared members are reached through the host pattern. The script is committed with the PR and re-run on the latest main at landing, so the split PR is regenerated, never rebased. Verification is mechanical: every moved body is byte-identical to its source (AST text comparison in the script's own check), the declaration files pass ruling 6348891160's bar, type-check and the full suite run. Landing: a short pause on new claims touching that file, regenerate, land with the maintainer's approval, resume; in-flight PRs re-apply onto the moved code. Tables (registry.ts) split into per-entry files with a generated index, as #7297 did for the migrations registry. StudioDesignSurface.tsx stays on hand slices (a React component's closures are not mechanically separable). Order: pilot sql-driver.ts (lowest churn), then registry.ts, engine.ts, the rest of protocol.ts. The codemod is deleted when the programme ends. Nothing directly. Fixes stop waiting behind same-file work within weeks; AI edits are made on files a reader can hold whole. No precedent for a codemod split in this repo. Measured comparison: the hand series moved protocol.ts 8,010 lines in 10 days with one lane. A needs one dev to write and prove the codemod on the pilot (a draft PR plus the pilot split), then one PR per file, each a maintainer approval.
B Keep ruling A's hand slices as they are; file the two missing cards (registry.ts → domain:spec, StudioDesignSurface.tsx → domain:ui); re-open the stalled engine.ts series with a re-priced seam plan. Same as A, later. Measured precedent: #23050 (18 PRs, ~6 days, one lane, 13,701 → 6,196) and #25467 (35 PRs so far).
C A, plus a size ceiling on the split files that can only go down (a ratchet, as check-skill-line-ratchet does for skill text). Files cannot grow back. A plus one gate. 「新增门禁默认否」: ⛔ only if the maintainer names it.
D Stop the programme; leave the files. Same-file waits keep growing with the files. None.

四轴分析

  • 项目长远合理性:两年后核心协议层、查询引擎和驱动都应当是按职责划分的模块,类本身只是一个薄门面;主流框架都这么组织(NestJS module、Django app、TypeORM 的 driver 按方言与职责分文件)。A 和 B 终点相同,区别是速度和可靠性:脚本生成的拆分每次都可重放、可机械核对,手工拆分每刀都要人看是否只搬不改。实测手工系列在接缝用完后停在 18,000–23,000 行,说明 B 走不到终点。
  • 实际业务拉动:有。protocol.ts 与 engine.ts 一周合计 141 次提交,同文件串行每天都在发生;StudioDesignSurface.tsx 一周 60 次提交,没有卡。
  • 防 AI 犯错:A 最强。拆完后一个模块能被整篇读完;而且拆分本身由脚本做,不是 AI 手搬,搬错的可能被结构排除(逐字节核对)。B 的每一刀都是 AI 在部分视野下手工搬代码。
  • 创业阶段不扩散:A 不新增对外声明、键和门禁;脚本是一次性工具,项目结束即删。C 新增永久门禁,默认否。代价是每个文件一次落地停顿和一次您的批准。

os-decision-facets

自检:只看①选 A;②③④ 是否翻转:否。

推荐:A。 B 不取:实测两条手工系列在接缝耗尽后停摆,走不到终点。C 不取:新增门禁须您点名。D 不取:债每周仍在增长。置信缺口: 本仓库没有脚本拆分的先例;试点前不知道 host 模式能否覆盖 ObjectQL 的 227 个私有成员而不改声明文件,这正是先拿 sql-driver.ts(57 个私有成员)试点的理由。若试点证明不可行,退回 B。

Analysis-tier: claude-opus-5-5 (served at filing; not CONTRACT_REVIEW_TIER).

裁后执行

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    director#1 · os-support-ai · session_01WGufzg12BtjFc5rHp7YD1J

    Brief-claimed-by: session_01WGufzg12BtjFc5rHp7YD1J · batch #457 · 2026-11-02T15:56Z

    ⛔ Not a claim on the work. The director seat presents this card to the maintainer in batch #457, in the director session, with the analysis on this body.

  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p2 · domain:devx · decision card · 2026-11-02T16:07Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    director#1 · os-support-ai · session_01WGufzg12BtjFc5rHp7YD1J

    Landing plan for option A, added at the maintainer's question in the director session 「快速方案(推荐 A)如何落地,是否需要车队不忙的时候派发」 · 2026-11-02T16:27Z

    The maintainer's words on the pause, verbatim: 「车队什么时候空闲是有我安排的」「我可以让大家都停下来」. So the landing pause is a window the maintainer orders, not a quiet hour the fleet waits for. Readings that rule out waiting for a natural lull (origin/main, last 7 days): every UTC hour carries 46–100 merged commits; the three class files take 1–12 commits in every hour; the weekend days carry 218 and 231 commits against 550 on Monday.

    Phase 0 — build and prove, no pause (any lane time after the ruling):

    1. One dev writes the codemod and runs it on sql-driver.ts in a draft PR: the script, its byte-identity check over every moved body, the declaration-file comparison under ruling 6348891160, type-check and the full suite.
    2. Contract review on the script and the generated pilot; the PR is over 3000 lines, so it takes the final four-piece set and the maintainer's approval. Under the pm-dispatch landing rule an authorized approval does not expire on a later push, so the maintainer may approve in phase 0; whether a regenerated output still counts as what was approved is the maintainer's call, and re-approving in the window is the safe default.
    3. In the same phase the same script is pointed at registry.ts (per-entry files), engine.ts and the rest of protocol.ts, each its own draft PR, each verified the same way. Development touches no shared file, so no lane stops.

    Phase 1 — the window the maintainer orders:

    1. Before it: the maintainer says when. The seats land or park every open PR on the target files. Open now: registry.ts feat(spec)!: a view no longer declares itself personal — scope 'personal' and sharing.type retire #29447 and feat(spec)!: a locale tag written in another case is corrected to its BCP-47 case #29190; protocol.ts refactor(metadata-protocol): add the protocol host split machinery and move one pilot member through it (#25467 E1) #29488 and feat(spec): a save of a connector's served form drops a leftover undeclared auth key and names it #29456; none on sql-driver.ts or engine.ts.
    2. In it: the maintainer stops all seats. The dev re-runs each script on the latest main and pushes. CI runs once: the slowest Test Core shard was 12–21 min on five recent runs. Each PR enters the merge queue (15–30 min per entry, measured), each needing the maintainer's approval. The four files sit in four packages, so the four PRs are independent and can queue together; one red PR kicks only its batch.
    3. After it: the maintainer releases the seats. PRs parked in step 1 re-apply onto the moved code.

    Order: the pilot sql-driver.ts gets its own first window. If it lands clean, the other three share the second window. StudioDesignSurface.tsx is not in any window: it stays on hand slices.

    What stops the plan: a pilot that cannot keep the declaration file equal, or a byte-identity failure. Either is reported as a fork on this card, and option B applies; ⛔ the dev does not hand-edit the generated split to make it pass.

  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    director#1 · os-support-ai · session_01WGufzg12BtjFc5rHp7YD1J

    Ruling: batch #457 item 1 · letter A · maintainer 「同意」 2026-11-02T17:11Z

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · os-warren · session_01JQwxbaBjisxkQo9hht9bFB

    Exit stroke for ruling 6583399215 (letter A), done by the domain:devx seat the ruling names. needs-user-decision → pm:blocked in this stroke.

    Ruling-ref: 6583399215
    Blocked-by: #29520

    The pilot card is #29520 (codemod plus the generated sql-driver.ts split, landing plan 6582376616). This card stays open as the programme's anchor: when #29520 merges, the remaining per-file codemod cards are filed into their lanes (registry.ts → domain:spec; engine.ts and the rest of protocol.ts → domain:server), and StudioDesignSurface.tsx keeps hand slices. If the pilot fails byte-identity or the declaration bar, the fork is reported here and option B applies.

  6. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · os-support-ai · session_01WGufzgBDcBNVmSmo7VFHpj

    Post-pilot stroke · domain:devx#1 · 2026-11-03T22:53Z

    The pilot #29520 merged as PR #29598 (d46b1ff23f, 2026-11-03T16:26Z), so the per-file cards the exit stroke 6583664223 names are filed now, at the maintainer's 「现在车队不忙,大文件分拆的问题是否可以优先」 (2026-11-03T22:37Z). ⛔ Not a claim; each card is ungraded until triage's first touch.

    file (main c92b8872) lines card lane
    packages/metadata-protocol/src/protocol.ts 23,135 #29985 (codemod) domain:server
    packages/objectql/src/engine.ts 23,245 #29986 (codemod; #25522 is released into it) domain:server
    packages/spec/src/conversions/registry.ts 16,019 #29987 (codemod, per-entry files + generated index) domain:spec
    ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx 12,882 #29988 (hand slices, #24586) domain:ui

    Blocked-by: #29985
    Blocked-by: #29986
    Blocked-by: #29987

  7. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: unblocked · p2 kept · pm:blocked → pm:queue · 2026-11-03T22:55Z

    ⛔ Not a claim.


    Generated by Claude Code

  8. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: pm:queue → pm:blocked · the anchor waits on its per-file cards · 2026-11-03T23:48Z

    ⛔ Not a claim. This answers domain:devx#1's doorbell (6618424864) and corrects triage's unblock of this round: the anchor's remaining work is the per-file cards, not this card.

    Blocked-by: #29985
    Blocked-by: #29986
    Blocked-by: #29987


    Generated by Claude Code

  9. objectstack-fleet commented on Nov 4, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#6 · os-support-ai · session_01WGufzibcN9oHa8kDbTTnL5

    Fork · #29985 (metadata-protocol protocol.ts) misses the line bar of ruling 6591753301 item 3 · 2026-11-04T01:45Z

    Phase 0 is up as draft PR #29998 (head 32c7bc04, base 9049be26), and every proof passes. Dev report: 6620262710 on #29985.

    • Bar missed: protocol.ts goes from 23,135 to 15,318 lines, against the bar of below 13,000 (6591753301 item 3, carried to the next three files). 61 of 284 methods moved into 9 section modules.
    • Proofs, all passing: byte-identity 61/61 (the undo rebuilds protocol.ts and protocol-host.ts); determinism (same tree sha on two runs, and regenerating gives the committed tree); .d.ts EQUAL under 6441032442 B's second normalisation, with the positive control caught; typecheck 0 at base and head; metadata-protocol 22,339 → 22,340 passed (+1 non-vacuity row); durability census equal at base and head; dispatch-gates 73/73 exit 0.
    • What stays in the file: the class-side docblocks and signatures of the moved methods (E1), plus the 190 one-line stubs the [maintainer] refactor(metadata-protocol): split src/protocol.ts (33,065 lines, +10,169 in 30 days) along its ObjectStackProtocolImplementation seams, one move-only slice per PR #25467 hand series already left. No codemod rule under 6591753301 (a) and (b) reaches either one.
    • Ruling needed (as 6591753301 item 3 says, a design ruling, not B): either (1) docblock ownership: a moved method's docblock moves with its body, and the class keeps a one-line stub with a {@link}; or (2) class decomposition: the protocol class is split into delegating facets. The PR stays a draft, and nothing is hand-cut while this is open.
    • Side finding (not a fork): protocol-packageless-overlay-migration.ts, from the hand series, has a repository.delete( on sys_metadata that falls outside the metadata-protocol: a republish of a view container that drops a member keeps serving the dropped member's expanded view until restart #23198 stored-row census. The widened census reads only codemod modules, so its population is unchanged. This seat files it as its own card.

    The seat routes the ruling question to the maintainer. objectql engine.ts (#29986) is likely to meet the same bar question.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions