Skip to content

Split flows/lifecycle.rs along its banners #314

Closed

Description

@blooop

Question

flows/lifecycle.rs holds five unrelated commands — stop, delete, purge, prune, reconcile — plus refresh and state resolution: 2,811 production lines, 45 top-level types, 13 banner-delimited sections that map 1:1 onto modules never created (the whole crate has zero production submodules). Split into flows/lifecycle/{...}.rs along the existing banners. Blocked on the snapshot re-scope so public-api.txt moves once, not twice.

Activity

  1. blooop commented on Aug 24, 2026

    @blooop
    OwnerAuthor

    Re-measured 2026-08-24 at v0.13.0, three months after this was written. The case has grown, and one part of it has moved out.

    when filed now
    total lines — 7,481
    implementation 2,811 3,085 (1,655 excluding comments/blanks)
    top-level types 45 47 exported, plus 66 callable entry points
    banner sections 13 13

    New evidence for the split, beyond size:

    • 28% of the crate's reachable surface is this one module. 644 of the 2,301 rows in public-api.rest.txt name flows::lifecycle; the next largest, flows::launch, is 353.
    • The file's doc contradicts itself. Line 1 says "everything that removes something"; line 37 admits --reconcile "removes nothing at all". Four of the seven groups remove nothing and serve the launch path instead — the refresh latch (:173-390), the fetch sweep (:392-509), identity and container state (:511-705), and devpod's record format (:2765-2960).
    • The test module leaked into crate surface. mod tests is pub(crate) mod tests so flows/provision.rs:4746 and flows/provision/verdict_cache.rs:313 can import tests::devpod_home_with — a fixture promoted because a devpod-home module does not exist.

    One refinement to the plan: the :2765-2960 group is not a lifecycle submodule at all. It is a devpod adapter — it reads and writes devpod's own JSON — and its consumers are almost entirely the launch path. #394 takes it to clients/ instead, which also removes the pub(crate) mod tests leak. Worth landing that first so this split has one less section to place.

    (Found by a fresh architecture review that did not check the open maps first, so this arrived as duplicate #396, now closed.)

  2. blooop commented on Aug 29, 2026

    @blooop
    OwnerAuthor

    Claimed 2026-08-29: queued in the session working map #299's build tickets (waves behind #340/#349's PRs so the api surface and shared JSON writer move once). Build to follow from an opus agent in an isolated worktree. If you are another session seeing this, do not double-build.

  3. self-assigned this
    on Aug 29, 2026
  4. blooop commented on Aug 29, 2026

    @blooop
    OwnerAuthor

    breadcrumb: claimed and building. What I am building, restated: flows/lifecycle.rs becomes a module root that declares and re-exports thirteen submodules cut along the file's own thirteen banners (notices, refresh, fetch sweep, workspace state, stop, delete guard, delete, purge, on-disk locations, and prune's three passes, then reconcile), with the 5.4k-line mod tests moved out to a sibling file as it stands.

    Seams. This is a move, so there is no new behaviour to test at a seam and I am not inventing one. The two seams that matter are both structural and both already exist in this repo:

    • The public-API snapshots (public-api.api.txt / public-api.rest.txt) are the seam that proves the move is a move. Submodules go in private with glob re-exports at the root so every flows::lifecycle::Thing path stays the one it is today, and the target is a byte-identical pair of snapshots. Any row that does move gets named and justified rather than regenerated quietly.
    • A structural guard, in the spirit of devpod_layout: a filesystem-walking test that pins the family as split and cannot be satisfied by putting the code back in one file. Proven red against today's single file before the split exists.

    Content preservation is measured, not asserted: the cut is mechanical by line range, and a reassembly of the new modules is diffed against the original production region so the only surviving hunks are visibility keywords the compiler demanded.

  5. blooop commented on Aug 29, 2026

    @blooop
    OwnerAuthor

    breadcrumb: built and pushed as #532 — Split flows/lifecycle.rs along its banners.

    The file is thirteen modules and a table of contents, one module per banner. The root keeps the family's documentation, thirteen private module declarations and thirteen glob re-exports, and defines nothing itself. Layout follows this repo's own convention rather than the ticket's mod.rs phrasing: mod.rs is used only for the three directory groupings, and every leaf module with children is foo.rs beside foo/.

    Three things established rather than asserted:

    • All three cargo public-api snapshots are byte identical. The members are private and the re-exports are what is public, so there is still exactly one path to each of these types. dl's own lifecycle test file needed no import change at all, which is the same fact seen from outside the crate. A control run first confirmed the toolchain reproduces main's three checked-in files byte for byte, so the unchanged result means something.
    • Every body moved unchanged. The cut was mechanical by line range, and a reassembly of the members was diffed against the pre-split file. What survives is a pub(super) keyword and its rewrap, a doc link spelled out where the member no longer imports the name, the imports the test module used to borrow from its parent, and rustfmt joining lines that the suite's lost indentation level made room for. No statement body changed.
    • The structural guard is red before and green after. Three assertions, all read off the filesystem, no roll call of module names to fall behind: the family is more than one module, the root defines nothing, and no member is past a third of the family. The second is the one that closes the road back, since a lifecycle that is one file again has to be one file in the root, and the root is where a body cannot go.

    Two existing guards learned the new paths without changing what they assert: the one door for docker volume rm, and the list of files whose cfg(test) gate is declared elsewhere.

    Left alone deliberately: the suite moved as one 5,450-line file rather than being redistributed among the thirteen. Splitting it is a judgement about which test belongs to which module, and making that judgement inside a move is how a move stops being provable.

  6. blooop commented on Aug 29, 2026

    @blooop
    OwnerAuthor

    wf-review: Approve, nothing blocking. Two-axis report on #532 — Split flows/lifecycle.rs along its banners. Move verified independently against base 5fa0fd1a: production bodies unchanged (35 hunks, all pub(super) or doc-link), 159 #[test] both sides, and a compiler probe over all 112 top-level items shows the surface outside flows::lifecycle identical name-for-name, 16 narrowed and none widened. Six non-blocking follow-ups listed in the verdict.

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

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions