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.
