Derive a coverage grid from the agent's contract and sample it for any suite size - #75
Draft
KarthikAvinashFI wants to merge 111 commits into
Draft
Derive a coverage grid from the agent's contract and sample it for any suite size#75KarthikAvinashFI wants to merge 111 commits into
KarthikAvinashFI wants to merge 111 commits into
Conversation
…ackend's native sub-agents
…the planning stall
…it for any suite size
…ss and suite-editing tools
…old dial pairs back
…nning but not writing
…der setup as seeding
… treat emergency as prompt-side
…ing a small suite
…tage and its writers
…ot see its siblings
…instead of killing the writer
…es its angles out of the pool
… collapsed them to two
… scenarios filled which bucket
…ted writer never writes folders
…he fan-out is used
… cannot see the grid
…, not a flat number
…at a suite exists
… declared workers
… tool, so blocking it blocked delegation
…ours and not a detached one
… place is not an office
…split is silently dropped
…so a call reports a prompt
…table is built without one
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.
Scenario generation answered "write N scenarios" by writing N, and nobody could say afterwards what was skipped, because nothing had enumerated what was possible. Measured across 718 scenarios this harness had generated: 5% carried any adversarial situation, none covered diagnosis, none covered multi-step navigation. The model wrote the easy cases because nothing required otherwise.
This changes the unit of work from "a scenario" to a coordinate in a grid derived from the agent's own contract, adds a planning stage above it, and makes the plan a ledger the run works from.
The three levels, named once
A scenario is one test: a folder, a setup, checks, a reference solution. A bucket is a kind of case holding several scenarios; its angle says what makes it worth testing. A theme groups buckets and is the unit a large plan is paged in and out by. "Scenario" and "situation" both name single instances, so neither works as the container, which is why a third word exists.
Planning, and why it is a separate stage
Asking for a thousand finished scenarios at once does not fit in a context. Writing them one at a time does fit and quietly converges: each is composed with the last few in view, so by fifty the suite has settled into one shape. Measured here, fifty scenarios came back with nine distinct people in them, forty-two of them American, living in two places, and every writer had been told to vary its work.
A thousand one-line intentions do fit. So
planis its own sub-skill: decide what every bucket is before any scenario is written, while the whole suite is still visible and still cheap to change.The level is enforced rather than requested. An angle over 90 characters is refused as a script rather than an angle, because at the length the first attempt used, a plan for a thousand scenarios is 228KB and 57k tokens to emit in one response.
How a bucket's size is derived
wantused to be guessed, and the guess was 1 everywhere, which is a list of scenarios with extra fields. It is now derived.The planner reads the agent's data and rules and declares state axes: dimensions whose value changes what the agent should do. A level must exist in the data or be reachable by seeding, and must change the correct answer. Each bucket names the axes it crosses in
live, andwantis how many of their combinations survive masking. An axis nobody derived is refused; awantabove one with neither axes nor a stated reason is refused.On a real agent the planner derived seven axes unprompted, including a payment state with eight levels and an account status carrying two values that appear only in the rules rather than in the data.
The canvas is a ledger, not a document
Each bucket carries
done,refused,attempts,state,claimed_byandnotes. The loop claims a slice, dispatches one writer, folds the return, and re-ranks. Ranking weights outstanding work by how much of its theme is untouched, so a theme nobody has started outranks one nearly finished; and a slice never contains two buckets from one cell, because a writer handed a whole cell must invent that cell's variety alone.doneis counted from disk and never from the writer's report. The writer's own number is kept only to notice disagreement, which is itself a bug signal.Writers can open buckets the plan never saw. The plan is written from outside the code; a writer is the first thing to look inside with the source open. It reports what it found, the stage records it with an id the canvas assigns, and it is dealt like any other. Ids are assigned centrally so simultaneous discoveries cannot collide.
The ceiling is measured rather than predicted. Three failed attempts marks a bucket blocked, and what remains when nothing is open is what the agent actually supports.
What a plan has to say about itself
Recording a canvas prints coverage against things outside the plan: which grid cells have nothing on them, how many of the agent's hard rules have a bucket testing them, how many precondition-gated tools are named, and how the scenarios split across happy, edge, adversarial and failing. A plan with nothing in one of those four is reported as such.
The rule line is the one worth reading. A rule with no bucket is something the agent is forbidden to get wrong that nobody is checking.
Defects found and fixed along the way
Each only reachable above the delegation threshold, which is why none had surfaced before:
AgentDefinition.backgrounddefaults to asynchronous, so the stage dispatched five writers, took its next turn, declared success and exited, killing all five. One scenario saved from a plan of fifty, reported as success.restorereloads the snapshot into the store, truncating and reinserting every table, and three tools did it outside the lock. A scenario could be proved against a world a sibling had rewritten underneath it.atexit, which does not run on SIGTERM. Now one engine per image with a database per world, released on signals too.cwdwas the run directory's parent, but the environment bundle lives inside the run directory, so every path the skill names missed by one level. Writers could not read the agent under test, and instead read a neighbouring run's world, a neighbouring run's scenarios, and model-written scripts left in the shared directory that calledaccept_scenariodirectly, around the gates. One helper now resolves all three sessions from the run directory.donewas assigned from the current return's names alone, so a bucket filled over two rounds went three-then-two, burned an attempt per round, and could be marked blocked while genuinely being filled. Progress is now a ledger of credited scenario names on the bucket: rounds add up, and one name can never fill two buckets.Making the fan-out actually fan out
Declaring workers is not the same as using them. Measured on a 200-scenario run: the stage made 59 of the submissions itself and dispatched four writers, then spent its turns proving instead of dealing. Two changes close that.
A stage that has writers can no longer write.
submit_scenariois withheld when workers are declared, exactly asgenerate_suitealready is and for the same reason: offered both, the model does the work itself and the fan-out goes unused. Below the delegation threshold no workers exist, so a small suite keeps the tool and writes its own scenarios as before.Writers run several at a time. The canvas was always built for it, and nothing used it:
claim_slicemarks its angles taken, so a second claim cannot return the first one's work and two writers can never be handed the same scenario. The skill previously said "one writer at a time"; it now claims per writer and dispatches them together.A writer's turn budget follows the slice it can be handed. It was a flat number that predated the slice clamp, leaving 3.8 turns per scenario including the reading a writer does before writing anything, so slices came back part-filled and the next writer paid that reading cost again.
Surviving a long run
A suite of this size takes hours, and every one of these ended a run early before it was fixed.
donewas assigned from the current return's names, so a bucket filled over two rounds went three-then-two and could be marked blocked while being filled. It is now a ledger of credited scenario names, persisted, so rounds add up and one name can never fill two buckets.Verified
understandandbuildrun unattended against a 20-tool voice agent: 12 collections seeded, 13 code-settled sub-goals, 22 probes at 1.00.Planning on that agent: 63 cells, 168 buckets, 16 themes, 7 derived state axes, 500 scenarios planned.
Writing is not yet proven at scale. The largest completed suite is 50. Cost and throughput are recorded in the run notes rather than claimed here.
Coverage the plan cannot get from the grid
A cell is an operation on an object, so it says nothing about order. Two consecutive plans were told
0 of 10 tools with preconditions have a bucket that names themand neither acted on it, while fixing other reported faults in the same pass. Being asked for something before its precondition holds is exactly where this kind of agent fails, so a large plan that names none of those tools is now refused rather than warned about, beside the cell-coverage floor.The bar is zero named, not a share. A share invites spreading tool names through the prose to clear the check without writing the ordering case.
Known weakness, not introduced here
prove.play_reference_steprecords a step as passing without running it when the tool has no endpoint bound, and says so in a warning. Where that happens the proof is partial. This is a build-lane fix and is deliberately not papered over in the scenario lane.Supersedes #73 and #63.