Repository navigation
site: Factory — lifecycle figure redrawn as a pipeline + 3 diagram fixes - #60
Merged
Merged
Conversation
The concept above `mazeFigure()` was always right — "the road is the path CODE takes, from a commit to a published package, and the checkpoints are where the standard set's checks sit along it" — and the shape contradicted it. `carve()` + `solve()` generated a PERFECT MAZE: an enclosed labyrinth over the whole 12x8 lattice with exactly one path between any two cells. So the figure read as a puzzle a reader has to solve rather than as a pipeline they can follow. No legible direction, no start or end that said "commit → published package", and no visible systems — a route free to double back into an earlier column is a maze's defining property, and code does not double back into a repository it has already left. That is a direct hit on this design's own principle: the motion has to mean something, and the meaning has to be true. WHAT IT IS NOW. A directed left-to-right circuit trace through the four real systems the six phases already belong to, monotonically non-decreasing in column by construction: Repository (SCM) P1 Commit integrity Build (CI) P2 Dependencies · P3 Build receipts · P4 Code & build hardening Production P5 Ongoing posture Registry (CD) P6 Distribution & publishing `STAGE_ZONES` is NOT a new taxonomy — `PHASES` and `PHASE_NAMES` are untouched and in their own order, and the table only says which system each existing phase sits in. The zone WIDTHS are the phase counts, so Build is three lattice columns to either neighbour's one (measured: 2/6/2/2 of 12), which is the figure saying out loud that half the standard set is a build-time concern. A phase the table does not name falls into the last zone rather than off the board, and `zonesFor(n)` deals any n across the same weighted span, so the generator still follows `PHASES.length` rather than a literal. The jogs are seeded, and their DIRECTION alternates while only their size is random. A free coin drifts: six steps of an unbiased walk put the entire run in the top half of a board it is supposed to cross (measured — rows 3,1,2,3,2,4 before the fix). Alternating keeps the trace oscillating about the middle while the seeded magnitude keeps it from reading as a regular zigzag. A jog is also required at every step, because two checkpoints on one row give a flat run with no corner, and a flat run is the serpentine the first cut of this figure was rebuilt to stop being. The board behind it is the frame, one full-height divider per system boundary, and two dead stubs per zone. The stubs are what make it read as a board rather than an empty box — they are unused traces that deliberately go nowhere, and they sit in rows 0 and 7, which the trace never uses. The one line that means anything is the blue one. NOTHING ABOUT THE MOTION OR THE DATA CHANGED. Same `tracedFigure`, same `pathLength="1"` with scroll-bound `stroke-dashoffset`, same `data-node-at` / `data-reached`, same markup-carries-the-finished-state, same 532x374 viewBox, same six checkpoints from `PHASE_NAMES` in `PHASES` order, same `legend: true`. Only the shape the trace draws is new. The honesty constraint is untouched and its test still passes: nothing near this figure says walks, passes, in order, or none is skipped. The four zone names are generic structural labels rather than per-repository facts, so they are authored — and drawn as HTML over the drawing, not as SVG text, for the reason the ranked figure already learned: an SVG label renders at whatever the viewBox scales to, so a declared 14px measured ~8px at 390. They sit in the empty band above the frame, where they cannot cross the trace or a checkpoint at any width, and drop to 8px at 390 where a zone is 51px wide against 80 at 1440. Measured in a real browser with the lifecycle live (61-65 rAF ticks/s), at both widths: four labels in JetBrains Mono, 0 overlaps, 0 crossing the frame, the document never widens (scrollWidth === clientWidth at 390 and 1440). Mid-scroll at progress 0.549 the trace is drawn through Build with 3 of 6 checkpoints lit and the legend dimming the other three — the scroll binding is intact. Determinism proven the way it matters: two consecutive builds, `diff -r` over the whole of `dist/`, 0 differences. `mazeRoute`/`MAZE_GRID` are gone, and so are `carve`, `solve` and `mazeWalls`; `pipelineRoute`/`PIPELINE_GRID`/`STAGE_ZONES` replace them, and `.fy-maze` becomes `.fy-pipeline`. The maze tests are rewritten rather than deleted — the "perfect maze, every wall drawn" assertion is now its own inverse (a perfect maze over this lattice draws 77 interior walls, and every one of them must be gone), plus a new directedness test and a new test that the zones are the phases regrouped. 889 pass / 0 fail / 1 pre-existing skip; tsc 0; build 0; dist byte-identical across two builds. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017N6Qc2T7buVAXHZ9vYa1xm
THE OUTGOING WIRE POINTED AT EMPTY GRID. Round 2 top-anchored the explorer's three columns so each head sits on its own content — correct, and the cost was that the wire stayed in the CHECKS band, where it stretched to that band's ~2000px row. Its arrowhead's `inset-block-start: 50%` therefore resolved to y=779, on bare dotted background, ~330px below the "One listing" Record card at y 349-510. An arrow IS the claim that the middle column produces the right one, and it was landing on nothing — while the inbound bracket beside it was drawn correctly, which made the outbound half look worse. The fix is structural rather than a number: the run moves into the OUT band, so it shares one auto grid row with the Record card and 50% of that row IS the card's vertical centre. Its SVG is taken out of flow (`position: absolute; inset: 0`) so the wire contributes no intrinsic height of its own — in flow, the SVG's viewBox aspect would set the row and 50% would mean the wire's own midpoint again, which is the defect. Nothing in the stylesheet has to be kept in step with the card's content. Measured at 1440: arrowhead y **11626.0**, card centre **11626.0**, delta **0.00px**, arrow inside the card's box, and the wire's right edge meets the card's left edge at **0.0px**. The inbound bracket's arms still land at **14.6 / 46.7 / 82.1%** of the input cards. The 390 connector is a second element rather than the same one moved, because reading order at that width has to stay checks-cards → connector → Record head, and an element inside the out band comes after the out head. Each width paints exactly one: `[data-flow-wire="stack"]` is `display: none` at >=768 and `block` at <=767, and `[data-flow-wire="out"]` the reverse. THE RANK WORD SAT IN THE LABEL BAND. "strongest", placed 10 units above its rung, shared a horizontal band with the first node's centred label, and the descenders of "The project's own build, signed" ran through its cap height — 40.5 x 4.0px at 1440 and 39.8 x 5.1px at 390, the only text overlap on the whole site and, since round 2 centred that label on its node, at both widths. Horizontal separation is not available here and it is worth saying why: node 1 sits 40 units right of the ladder's own left edge, so any label centred on it reaches into the rank gutter at any width. So the separation is vertical, and the rule is now the same for both words — the rank word hangs 14 units UNDER the rung it names (110 and 270 against rungs at 96 and 256), clear of the rung's own line, with the first speed label lifted 4 units further off its node. Measured: **0 text overlaps on home at both widths** (per-line-box probe over every text node, closed `<details>` and the visually-hidden idiom excluded), with the rank word **22.3px** clear of the label above it at 1440 and **12.8px** at 390. THE PHASE PICKER HID FOUR OF ITS SIX PHASES. At 390 `.fy-segmented` is a scrollbar-less horizontal scroller: measured **2 of 6** labels fully visible, under a rounded cap 20px inside the screen edge that reads as the end of the control rather than as more to come. It is the site's one interactive device and its own copy says "pick a phase", while the page's chart, sheet and directory all say six. The `.table-scroll` containers two selectors away already had the mask, the `data-overflow-*` attributes and the cue; the chapter rail already had scroll-into-view. This gives the control all of it: same mask, same cue element, and the checked label is scrolled fully into view on change, padded by the mask's own 20px so a revealed label never lands under the fade that says there is more. Measured at 390: `data-overflow-end="true"` with the cue visible while it overflows, and after checking the sixth radio its label box **172.9-365.7** sits fully inside the control's **20.0-370.0**, with `data-overflow-start` flipping to true and `-end` to false at the end of the track. The radio semantics, keyboard behaviour and the no-sliding-thumb rule are untouched — `role="radiogroup"`, one checked input, the panel shown, and `transition-property: background-color, color` with no thumb element. At 1440 the control does not overflow and the cue computes `display: none`. Two round-1 assertions pinned the old wire count and the old head padding; both are updated rather than deleted, and the new count is two-sided (three wire elements, exactly one of them the untagged inbound bracket). 892 pass / 0 fail / 1 pre-existing skip; tsc 0; build 0. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017N6Qc2T7buVAXHZ9vYa1xm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Factory follow-up — the lifecycle figure redrawn as a pipeline, and three diagram-connector fixes
Two commits on top of #59 (already on
main), per the principal's live review of the first interim ship.The lifecycle figure — replaced, not tweaked
The home page's "One record covers the whole lifecycle" figure previously drew its six checkpoints along a perfect maze — a solvable labyrinth generated by a seeded depth-first carve. The concept behind it was always right (the checkpoints are
PHASE_NAMESinPHASESorder — Commit integrity, Dependencies, Build receipts, Code & build hardening, Ongoing posture, Distribution & publishing — already real SDLC order), but the maze shape read as a puzzle to solve, not a pipeline to follow.It's now a directed, left-to-right circuit-trace through four zones grounded in what those six phases actually are: Repository (commit integrity) → Build (dependencies, build receipts, code & build hardening — the three build-time concerns, so this zone is proportionally wider) → Production (ongoing posture) → Registry (distribution & publishing). Same motion mechanism (
pathLength=1, scroll-bound dash-offset), same six data-bound checkpoints, same honesty constraints (no copy says "walks," "passes," "in order," or "none is skipped" — a scan reads a clone once), same deterministic byte-identical build. A new test asserts the route never doubles back into a zone it has already left.Three diagram-connector fixes (round-3 findings)
Gates
bun test892 pass / 0 fail / 1 skip ·tsc --noEmit0 ·bun run build0 (36 pages) · Factory-page greps clean (0 workstation paths, 0 "nobody could answer/check", 0 OpenAI references, 0 remaining maze markup) · five-design regression diff againstmain: 0 lines (main already carries Factory from #59; nothing outside Factory changed).🤖 Generated with Claude Code
https://claude.ai/code/session_017N6Qc2T7buVAXHZ9vYa1xm