step.25.diff.txt -- narrative retro for step.25 (U5.4: CCS-unit workflows). Companion: step.25.gdiff.txt via ../scripts/step_gdiff (machine half). Executed: 2026-07-22, same session as steps 22-24. WORK commit 87cbf84. ## Plan vs actual +---+--------------------------------------+--------------------------------------+ | # | Planned (brief) | Actual | +---+--------------------------------------+--------------------------------------+ | 1 | "compile/validate/regenerate arcs | Three arcs as engine functions + | | | in the adaptive loop" | the `b3ubot ccs` CLI; regenerate = | | | | the deliver arc re-run (revision | | | | moves server-side). Round-trip | | | | deliberately NOT an arc: oracles | | | | gate, arcs assist (C-25-C). | | 2 | (implied) deliver artifacts into | The missing ยง2.10 half: write_bytes | | | the workspace | on the tool surface + deliver_unit | | | | unpacking EVERY member through the | | | | trail, workspace-scoped. | | 3 | (not planned) the step.24 table | FOUND by the first full-suite run: | | | regression | 16 table tests red AT d4ca480 -- | | | | the hand-edited ledger note was 1 | | | | char over the border width. Fixed; | | | | lesson: measure AFTER the last edit. | +---+--------------------------------------+--------------------------------------+ ## Surprises / genuine findings 1. **The dogfooding bit its own tail, correctly (Q-25-C).** b3ubot's ledger-table machinery refused MY hand-edited U5.3 note block (39 chars in a 38-char column). Better: the step.24 suite numbers were measured BEFORE that step's docs edits, so its WORK commit shipped red without knowing. Two consequences, both applied HERE: the fixed block was rewritten by a width-ASSERTING helper (which itself caught a second overflow on its first try -- ljust pads, never truncates), and "measure after the last edit" joins the house rules -- docs are data to this machinery exactly like the step files were at step.22. 2. **Artifacts.zip_bytes had no consumer until now** -- U5.1 built the delivery handle, U5.4 is the first code that actually lands it in a workspace. The live tests had been quietly working around it with zipfile.extractall; engine-land now goes through the trail (C-25-B). 3. Probe-before-parse, again: the first draft of the trail assertions used a guessed row key ("op"); the real key is "tool" (trail.py's record_tool_call). Two-minute fix BECAUSE the guess was tested, not narrated. ## Scope discipline In: the U5.4 row + the write_bytes prerequisite + the found regression's repair. Out and named: orchestrated deliver-on-close (Q-25-A -- U5.5 decides with its first real consumer), client-side revision history, a packages/runtime CLI, U5.4a, U5.5. Zero b3u-repo changes. ## Numbers - New: app/ccs/workflows.py (3 arcs + DeliveredBundle), write_bytes (+hub export), CCSWorkflowError, the ccs CLI group + seam, 16 tests (13 hermetic + 3 live). - Suite: 629 -> 647 collected (16 new + 2 own-corpus step.25.txt); 623 passed + 24 skipped (21 + 3 workflows-live), 0 failed -- measured AFTER the final docs edit. - p5_gates: live 10 -> 13 legs; hermetic twin 43+10 -> 56+13; ALL PASS. The step.24 table regression: 16 red -> 0. End of retro.