Skip to content

feat(coord): price a workflow fan-out by width times depth (BACKLOG #1400) - #811

Merged
wshallwshall merged 1 commit into
mainfrom
claude/backlog-1400-workflow-cost-estimator
Sep 4, 2026
Merged

feat(coord): price a workflow fan-out by width times depth (BACKLOG #1400)#811
wshallwshall merged 1 commit into
mainfrom
claude/backlog-1400-workflow-cost-estimator

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

Closes the buildable half of BACKLOG #1400. The aggregate limb is measured and deliberately left open.

The gate is not in this tree, and the zero carries its controls

git grep WORKFLOW_GATE_AT -- ':!docs/' exits 1, and no file named watch.py exists on disk, tracked or untracked. A zero from a grep proves nothing without a control, so two ran on the same instrument over the same path exclusion:

probe exit
WORKFLOW_GATE_AT outside docs/ 1
PUBLIC_BACKLOG_FLOOR outside docs/ (positive control) 0
an impossible string (negative control) 1

The instrument can see a real match outside docs/ and does return 1 on a genuine absence. Exit codes were re-taken unpiped after a first attempt read $? through a head, which reports the pager's status and not the grep's -- the CLAUDE.md section 11 trap, hit while checking for it.

So this PR does not touch the gate, and does not lower the threshold, which the item rules out by name because the failure is in the sum rather than in any one launcher's margin.

What is built

scripts/coord/workflow_cost.py prices a workflow script statically as fan width times depth. On the item's own worked example it returns 13 where grep -c 'agent(' returns 3, reproducing the 4.3x under-report from the numbers published in the row.

Every construct that multiplies is scanned in its own right, not just as an argument of parallel(): .map() / .flatMap() / .forEach(), Array.from({length: N}, cb), pipeline(items, ...stages), and for (const x of EXPR). parallel() multiplies nothing; it reports what its argument costs.

The original script was not recoverable, so the fixture is the shape the row's three published numbers force -- two six-wide fans plus a lone synthesis agent, 6 + 6 + 1 behind 3 call sites. It is labelled as a reconstruction in the source.

It reports a floor, and the guarantee is a residue rather than an enumeration

Anything a static read cannot resolve prints as an UNPRICED TERM with its per-unit cost, and the total reads known floor instead of TOTAL (exact) whenever any exist.

The load-bearing part is the catch-all: after pricing, every agent token the pricer did not attribute to a site is reported as unattributed. Without it, unrecognised construct and costs nothing are the same state. ROWS.map(agent) passes the hook as a value and matches no call pattern anywhere in the scanner; only a residue check catches it. An unbalanced construct is likewise reported rather than skipped, so one mask desync cannot truncate the scan while the report still says exact.

Five under-reports found and fixed during the build, every one of the item's own class

Each read as correct before it was measured, which is the general lesson -- this class is not caught by review:

  1. An array of string literals counted one element short, because masking blanks string content and made the last element indistinguishable from a trailing comma.
  2. An inline [...].map(cb) fan read as a list of thunks and priced at zero.
  3. Promise.all(ROWS.map(r => agent(r))) priced at 1 and reported EXACT -- the tool committing the item's headline failure, because .map() was recognised only inside parallel().
  4. One space after parallel( turned a known array into a runtime width, through an offset that double-counted leading whitespace.
  5. A for (const x of ROWS) fan over a literal array filed as an unknown loop.

Findings 3, 4 and 5 came out of the /simplify review pass and prompted the pricing layer to be restructured: width resolution is now a single authority, and the scale-or-name-it tail is one helper instead of three copies.

How it is proved

  • The headline: the worked example prices at 13, naive grep at 3, ratio 4.3x.
  • The discriminating control: a script with no fan-out prices at exactly the naive count. Without this, "reports a bigger number" would be satisfied by a tool that always inflates.
  • Three mutation proofs: delete the * width and the worked example collapses back to 3 (the item's own failure, on demand); force every literal array to one element and an inline fan drops to 1; disable the residue and an unrecognised construct goes quiet. Each mutant also fails the tool's own --self-test. Seams are matched by regex with a count assertion, so a moved target fails loudly instead of turning a negative control into a no-op.

Checks run

check result
ruff check + ruff format --check pass
mypy --strict scripts/coord/workflow_cost.py pass
mypy messagefoundry pass
pytest tests/test_coord_workflow_cost.py 31 passed
pytest test_tooling_partition + test_cp1252_console_safety + test_licence_header_gate 70 passed
pre-commit (11 hooks) pass

Not run: the full suite. The box was saturated tonight -- a peer measured 20 logical cores against 28 concurrent pytest processes at 100 percent CPU. The legs above cover the change; the hosted runners should decide the rest.

tests/tooling_manifest.txt gains the new test, which its three coord siblings are already in. Without that entry test_tooling_partition.py would go red, since the file imports no engine module.

The denominator: measured, not built

The item asks for "fan-outs in flight fleet-wide, and agents REMAINING rather than launched". A measured design note is appended to the item rather than a new coordination surface, because that needs claim and release semantics the item deliberately leaves open.

The gap is a unit gap, not a reader gap. lane.ps1 already records statedInFlight, and the storage is already fleet-wide: one JSON per box under <git-common-dir>/mefor-coord/lanes/, atomically written and keyed by a derived box key. Only the read is first-person, by design -- lane.ps1:11 says there is no -Lane or -BoxKey parameter and that adding one defeats the design. Every toucher of that directory is first-person: exactly two, scripts/coord/lane.ps1:71 and scripts/hooks/lane-level.ps1:181. fleet.ps1 does not read it at all; it is a pure reader over seats/.

But statedInFlight counts items for one box, human-stated and stale by design, while the gate needs agents remaining fleet-wide. Those cannot be summed into each other. The note records what a census would have to record, why it must be written before the first agent starts rather than broadcast after, why release must reuse the existing liveness fence rather than grow a second one, and the ordering crux: read-to-authorise plus write-after-launch reproduces the item's failure one level up.

Not claimed

That any seat launched carelessly. Every measured launch cleared the gate honestly and no seat could have seen the aggregate from where it stood. Nor that the gate is wrong about the question it asks -- it is correct per launch; the question is the wrong one.

The item's banner is left as it stands. Flipping it is the Lander's act.

…1400)

Counting `agent(` call sites under-reports a fan-out, because fan width lives
in the array and not at the call site. On the item's own worked example the
naive grep returns 3 and 13 agents start.

workflow_cost.py reads a workflow script statically and prices every
construct that multiplies: `.map()`/`.flatMap()`/`.forEach()`,
`Array.from({length: N}, cb)`, `pipeline(items, ...stages)` and
`for (const x of EXPR)`. It returns 13 on the worked example and exactly the
naive count on a script with no fan-out, so a pass discriminates rather than
always reporting a bigger number.

Anything a static read cannot resolve prints as an UNPRICED TERM and the
total reads `known floor` instead of `TOTAL (exact)`. The guarantee is a
residue rather than an enumeration: every `agent` the pricer did not
attribute is reported, so an unrecognised construct cannot cost zero in
silence.

Five under-reports were found and fixed while building it, each of the class
the item describes and each of which read as correct before it was measured.
The worst: `Promise.all(ROWS.map(r => agent(r)))` priced at 1 and reported
EXACT, because `.map()` was recognised only inside `parallel()`.

The gate itself is not in this tree. `WORKFLOW_GATE_AT` and `watch.py` return
a real zero here, with a positive control and an impossible-string control
recorded on the item. Lowering the threshold stays ruled out by the item.

The item also gains a measured design note on the fleet-wide denominator that
would close the aggregate limb, which is not built: it needs shared state
with claim and release semantics.
@wshallwshall wshallwshall added the reviewed A reviewer has read this. Removed automatically when new commits arrive. label Sep 3, 2026
@wshallwshall
wshallwshall added this pull request to the merge queue Sep 4, 2026
@wshallwshall
wshallwshall removed this pull request from the merge queue due to a manual request Sep 4, 2026
@wshallwshall
wshallwshall added this pull request to the merge queue Sep 4, 2026
Merged via the queue into main with commit 6a84be7 Sep 4, 2026
41 of 42 checks passed
@wshallwshall
wshallwshall deleted the claude/backlog-1400-workflow-cost-estimator branch September 4, 2026 17:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

reviewed A reviewer has read this. Removed automatically when new commits arrive.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant