You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.)
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.
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.
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.
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.
Activity
blooop commentedon Aug 24, 2026
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.
New evidence for the split, beyond size:
public-api.rest.txtnameflows::lifecycle; the next largest,flows::launch, is 353.--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).mod testsispub(crate) mod testssoflows/provision.rs:4746andflows/provision/verdict_cache.rs:313can importtests::devpod_home_with— a fixture promoted because a devpod-home module does not exist.One refinement to the plan: the
:2765-2960group 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 toclients/instead, which also removes thepub(crate) mod testsleak. 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.)
blooop commentedon Aug 29, 2026
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.
blooop commentedon Aug 29, 2026
breadcrumb: claimed and building. What I am building, restated:
flows/lifecycle.rsbecomes 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-linemod testsmoved 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:
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 everyflows::lifecycle::Thingpath 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.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.
blooop commentedon Aug 29, 2026
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.rsphrasing:mod.rsis used only for the three directory groupings, and every leaf module with children isfoo.rsbesidefoo/.Three things established rather than asserted:
cargo public-apisnapshots 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.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.Two existing guards learned the new paths without changing what they assert: the one door for
docker volume rm, and the list of files whosecfg(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.
blooop commentedon Aug 29, 2026
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, allpub(super)or doc-link), 159#[test]both sides, and a compiler probe over all 112 top-level items shows the surface outsideflows::lifecycleidentical name-for-name, 16 narrowed and none widened. Six non-blocking follow-ups listed in the verdict.