feat(coord): price a workflow fan-out by width times depth (BACKLOG #1400) - #811
Merged
Merged
Conversation
…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.
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.
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 namedwatch.pyexists 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:WORKFLOW_GATE_AToutsidedocs/PUBLIC_BACKLOG_FLOORoutsidedocs/(positive control)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 ahead, 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.pyprices a workflow script statically as fan width times depth. On the item's own worked example it returns 13 wheregrep -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), andfor (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 floorinstead ofTOTAL (exact)whenever any exist.The load-bearing part is the catch-all: after pricing, every
agenttoken the pricer did not attribute to a site is reported asunattributed. 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:
[...].map(cb)fan read as a list of thunks and priced at zero.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 insideparallel().parallel(turned a known array into a runtime width, through an offset that double-counted leading whitespace.for (const x of ROWS)fan over a literal array filed as an unknown loop.Findings 3, 4 and 5 came out of the
/simplifyreview 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
* widthand 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
ruff check+ruff format --checkmypy --strict scripts/coord/workflow_cost.pymypy messagefoundrypytest tests/test_coord_workflow_cost.pypytest test_tooling_partition + test_cp1252_console_safety + test_licence_header_gateNot 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.txtgains the new test, which its three coord siblings are already in. Without that entrytest_tooling_partition.pywould 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.ps1already recordsstatedInFlight, 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:11says there is no-Laneor-BoxKeyparameter and that adding one defeats the design. Every toucher of that directory is first-person: exactly two,scripts/coord/lane.ps1:71andscripts/hooks/lane-level.ps1:181.fleet.ps1does not read it at all; it is a pure reader overseats/.But
statedInFlightcounts 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.