0047 — A Matrix block moves by its Driver's closed rows, and only if a person linked it
- Status: Accepted 2026-10-08. Retired 2026-10-10 (Gera 2026-10-10, fleet cleanup step 2):
matrix-watcheris deleted. In 556 passes no block was ever linked (linked=0 moved=0every time), and its 6 h job was never installed. A linked block is no longer moved by anything. - Renamed 2026-10-15: Matrix is now Plate (Gera: "it's on my plate"; repo PropFlow-Technologies/plate, CLI
plate,matrixkept as an alias). This record keeps the old name where it describes what was decided at the time. - Date: 2026-10-08
- Deciders: Gera. He asked for "a separate watcher, like the updater, a worker/helper for the Driver" so that "sessions themselves don't have to worry" and nobody adds "fat" to every session. Fede is open to object: Matrix is the weekly board he described on the Oct 5 call.
- Systems: Matrix (matrix.propflowai.co, PropFlow-Technologies/matrix),
matrix-watcherandupdater(local-bin),lib/docks.pyanddock-finisher(the finish line's count).
The problem
Matrix shows each person's plate. It has one column per person for their week and at most 5 blocks in it. A block shrinks as its done% rises. On day one only a person moved a block (matrix half, matrix done), so a block went stale whenever the person forgot. Gera turned down two ways to keep blocks current:
- Sessions report their own progress. Every session would carry instructions and spend tokens to say what one count already says.
- Each merged PR shrinks its block. Nobody can tell whether a PR moved the work 5% or 50%.
Options considered
- A. One block per live Driver, created and moved by the watcher. Ruled out after measuring it on 2026-10-08:
dock-of --livelisted 9 "live" docks against a 5-block plate that already held Gera's 4 hand-made blocks.- One of the 9 was 23/23 done and still live. Another was 0/5 with its task.json untouched for 204 h.
- The rows'
ownercannot say whose plate a Driver belongs on. Values includedsmith,claude,driver 1fdb267c (Phase 11), and 32 ×geramixed with 8 ×fedeon one dock. - Any rule that adds Driver blocks either overflows the plate or evicts what a person typed.
- B. A Claude session that wakes every N hours and updates the board. Ruled out. The job is a count, and a script does it exactly at no cost. A session spends tokens and can misread a number.
- C (this decision). A person links a block to a Driver once. A script moves it from that Driver's rows.
The decision
- The progress number is the finish line's own count.
done% = rows merged or shipped ÷ rows not cancelled, usingdock-finisher'sDONEandSET_ASIDEsets. When the Driver owns a group of a shared dock, only that group is counted (lib/docks.group_of). When every row is closed the block getsdone 100and leaves the board. With a row still open it stays at 99 or below, never 100. Matrix and the finisher therefore cannot disagree about how far a Driver has got. Every row weighs the same, so a large row and a small one move the block equally. That is the price of a number nobody can argue with. - The watcher never puts anything on a plate. It reads the board and PATCHes, by id, only blocks whose
refisdriver:<task>. A person sets that link withmatrix link <item> <task>. The watcher never POSTs. What is on a plate, its size and its 4-word name stay a person's choice. - A parked Driver gets no write. This covers a terminal task state, and a task.json untouched for 48 h while rows are still open. The block then fades after 24 h, which shows truthfully that the work has stopped. A write would stamp the block fresh and hide that.
- It is a script with three triggers, and sessions are not involved:
updaterstarts one detached pass after every successful run, i.e. right after a merge writes its ref. It never waits on the pass, so the updater's exit code cannot depend on Matrix.- A 6 h launchd safety net,
co.propflow.matrix-watcher, installed as a system daemon withfleet-daemon. matrix sync, run by hand.
Consequences
- A linked block shrinks within seconds of the merge that closes a row, and disappears when the Driver's last row closes. Nobody types anything.
- Gera's current blocks came from call notes and are human work, not Driver docks, so they stay moved by hand. Linking is for Drivers started from now on. One example of why the link must stay manual: "Situs onboarding follow-through" covers nudging a customer and a unit-count bug. Its look-alike Driver
onboarding-into-settingsis 23/23 done, so linking the two would close the block on the first pass. - Not built, and next if wanted: a
driver-setuprow that links or creates a Driver's block when the Driver starts (--set matrix=gera 20% 5d "Onboarding wave 3"). It must be possible to turn off. It must never refuse a Driver start because a plate is full; it logs and skips instead. - Liveness:
~/.claude/jobs/matrix-watcher.loggets oneexit=line per pass. It is read by the SYSTEMS.md entrymatrix.
Built in PropFlow-Technologies/matrix #3 (upsert by ref), #4 (matrix link / unlink / sync) and PropFlow-Technologies/local-bin #472 (matrix-watcher, the updater nudge, the plist).