Skip to content

A result says which question set it is, and an arm's CLI is on PATH - #11

Open
lex00 wants to merge 3 commits into
mainfrom
fix/scenario-and-arm-path
Open

A result says which question set it is, and an arm's CLI is on PATH#11
lex00 wants to merge 3 commits into
mainfrom
fix/scenario-and-arm-path

Conversation

@lex00

@lex00 lex00 commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Two things standing between the negative question set and a published number, one of which was invalidating runs outright.

A result says which question set it is

emit-result.py hardcoded SCENARIO = "ec2-multiregion", so a negatives run — two questions, six trials — emitted a record claiming to be a run of the eight-question board.

The emitter cannot work this out for itself. result.json names the tasks but not the set they came from, and deriving a set from its members would make a partial run look like a different scenario. So the script that ran it stamps jobs/<job>/scenario and the emitter reads that. Absent, it stays ec2-multiregion — which is what every job recorded before this was, so the 45 existing ones emit exactly as they did.

Worth saying why this is load-bearing rather than tidy: validate_results.py groups runs by (bench, scenario) and fails a group whose runs disagree on expected_trials. A negatives record emitted under the board's name does not quietly land beside 24-trial runs with a denominator of 6 — it breaks the whole group. That check is right and should stay; what was missing is a second scenario for such a record to be valid under.

An arm's CLI, under the name its own briefing uses

chant's briefing teaches chant search …. alchemy's teaches alchemy state list. Neither was on PATH, so the agent's first call died with command not found and it spent turns rediscovering npx <tool>.

Every trial of a chant run did this, and the audit — correctly — treats a missing CLI as disqualifying:

24 of 24 trials could not find chant on PATH — the run is not a measurement of this arm
TOOLING NOT EXERCISED: chant-r1 — these are not tool comparisons

That run also shows what the recovery costs: 218 tool invocations where a clean run takes 67, and 5 of 24 trials passing.

The arm's node_modules/.bin now joins PATH in its image, in dockerfile_for, so it is one rule for every arm rather than a per-arm patch.

This is not a thumb on the scale. The briefing is part of the experiment. An environment that does not provide the command its own instruction names is measuring the agent's recovery from a broken setup, not the tool. terraform, pulumi and cdk are unaffected — theirs are already on PATH or invoked through npx, which is why this never showed up as a cross-arm anomaly the way the alchemy v2 entrypoint did.

Checked

  • A job with no scenario file emits ec2-multiregion, unchanged.
  • command -v chant in the rebuilt image resolves to /workspace/chant/node_modules/.bin/chant.
  • The rebuilt arm records all four stacks and preflight passes.

🤖 Generated with Claude Code

https://claude.ai/code/session_014KoduiMJRyLqjFYBUbMskE

lex00 and others added 2 commits August 3, 2026 11:05
…is on PATH

Two things that stop the negative question set being publishable, and one of
them was invalidating runs.

## The scenario a job scored

`emit-result.py` hardcoded `SCENARIO = "ec2-multiregion"`, so a negatives run —
two questions, six trials — emitted a record claiming to be a run of the
eight-question board. The emitter cannot work it out for itself: `result.json`
names the tasks but not the set they came from, and deriving the set from its
members would make a partial run look like a different scenario.

So the script that ran it writes `jobs/<job>/scenario`, and the emitter reads
it. Absent, it stays `ec2-multiregion`, which is what every job recorded before
this was.

This is not cosmetic. The board is over 24 trials and the negative set is over
6; `validate_results.py` groups by `(bench, scenario)` and rejects a group whose
runs disagree on `expected_trials`, so a mislabelled record does not quietly
join the board — it fails the whole group.

## The arm's CLI, under the name its briefing uses

chant's briefing teaches `chant search …` and alchemy's teaches
`alchemy state list`. Neither was on PATH. The agent's first call died with
`command not found`, and it then spent turns rediscovering `npx <tool>`.

Every trial of a chant run did this, and the audit — correctly — reads a missing
CLI as "this run did not measure the arm" and invalidates the run:

    24 of 24 trials could not find chant on PATH — the run is not a measurement
    of this arm
    TOOLING NOT EXERCISED

That run also showed what the flailing costs: 218 tool invocations against the
67 a clean run takes, and 5 of 24 trials passing.

The arm's `node_modules/.bin` now joins PATH in its image. This is not a thumb
on the scale for the arms that have a local CLI — the briefing is part of the
experiment, and an environment that does not provide the command its own
instruction names is measuring the agent's recovery from a broken setup rather
than the tool. terraform, pulumi and cdk are unaffected: theirs are already on
PATH or invoked through npx.

Claude-Session: https://claude.ai/code/session_014KoduiMJRyLqjFYBUbMskE

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
The first version of this set ENV PATH in the arm image. That image is not what
a trial runs: prepare.py exports the workspace and the harness bind-mounts it
into a container built from the dataset's own image, so the ENV never reached a
trial. prepare.py's own docstring says as much — "a trial's image comes from the
dataset, so the prepared image cannot be the container the agent runs in" — and
I put it in the one place that cannot work.

It goes in the agent env the runner passes instead, which is what actually
reaches the trial. The base PATH is read out of the tools image rather than
written down, so it cannot drift from the Dockerfile that sets it.

Measured rather than assumed this time: chant-r2 ran with the arm-image version
in place and was still voided, 24 of 24 trials, at 21/24 with 72 healthy
invocations and a 1% failure rate.

Claude-Session: https://claude.ai/code/session_014KoduiMJRyLqjFYBUbMskE

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
lex00 added a commit to INTENTIUS/chant-bench that referenced this pull request Aug 3, 2026
The chant arm vendored 0.33.1. It now carries INTENTIUS/chant#1425 and #1429, so
its published g-series describes a build the arm no longer runs: different
harness commit, different workspace fingerprint. By the rule method.md states,
that is a different experiment.

Three replicates rather than one. A single new run would have joined a set whose
other two members are the old build, and the board ranks on the MEDIAN of three
— so the figure would have described neither build. The set is now homogeneous:

    chant-r3  24/24   workspace 3912387ce569  harness 4f3ab36-dirty
    chant-r4  22/24   workspace 3912387ce569  harness 4f3ab36-dirty
    chant-r5  22/24   workspace 3912387ce569  harness 4f3ab36-dirty

Median 0.9167, which is exactly what the g-series median was. **The two fixes do
not move the board**, and that is the expected result rather than a
disappointment: the arm's 0.33.1 read the estate through the CLI, which passed
`--region` and signed it, so it already saw all three regions. #1429 is a
regression against a build the board never ran.

Where they do move the number is the negative set, which asks the question the
board does not: 0/6 to 3/6.

All three runs answered with zero account reads, entirely from the recorded
snapshot, and all three passed the audit — 6/6, 24/24 and 24/24 trials using
chant's own tooling, at 3%, 5% and 1% invocation failure rates.

Two earlier attempts are not published. Both were voided for the same reason,
before lex00/aws-bench#11 put the arm's CLI on PATH where a trial could see it.

Claude-Session: https://claude.ai/code/session_014KoduiMJRyLqjFYBUbMskE

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ported since

`workspace_fingerprint()` read `<arm>.fingerprint`, which every
`prepare.py --export` overwrites. Emit a run after the next export and it is
stamped with a workspace it never saw.

Silent, and easiest to hit exactly when it matters: several runs ingested
together after the rebuild that follows them. Three published runs claimed a
build that postdated them — measured before a fix, stamped as though measured
after it, which is the difference the field exists to record.

Same shape as the `harness_commit` fault in INTENTIUS/chant-bench#26: a
provenance field derived at emit time from state that moves, rather than
captured when the thing it describes happened.

The runner now copies the fingerprint into the job, and the emitter prefers what
the run recorded. Older jobs have no such file and fall back to the previous
behaviour, so nothing already published changes shape.

Claude-Session: https://claude.ai/code/session_014KoduiMJRyLqjFYBUbMskE

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
lex00 added a commit to INTENTIUS/chant-bench that referenced this pull request Aug 3, 2026
The middle of a replicate set rather than a single run, the same rule the board
uses — and here it matters more, not less. Six trials move further than
twenty-four do: on one build these questions returned 3, 4 and 6 of 6 with
nothing changed between the runs.

    before the kind fix   3/6, 4/6, 6/6   median 4/6
    after                 6/6, 6/6, 6/6   median 6/6, no spread at all

That is a real shift rather than another draw from the same distribution, and
the variance collapsing is the more convincing half.

## What was making it noisy

Not the traversal — the counting. `kind:` is a substring, and a substring of a
CloudFormation type crosses kind boundaries: `kind:EC2::VPC` also matched
`AWS::EC2::VPCGatewayAttachment` and `kind:EC2::Subnet` also matched
`AWS::EC2::SubnetRouteTableAssociation`. An estate holding 6 VPCs answered 9.

Agents were naming exactly the right VPCs and reporting "9 VPCs in the estate"
beside them, and the grader failed the answer for contradicting the estate —
correctly, because it did. The finding was right and the census next to it was
of a set nobody asked for. Fixed in INTENTIUS/chant#1451.

The traversal work that made the questions answerable at all is
INTENTIUS/chant#1452, which replaced a per-rule opt-in with containment being
traversable by construction.

## A provenance error, found and corrected

`chant-neg-3/4/5` were published claiming workspace `30c405b9a8f5`. They ran
against `787ab0fd5bd0`; the emitter read the fingerprint file at emit time and
that file had been overwritten by a later export. Corrected here from the build
logs, and made impossible in lex00/aws-bench#11 — the runner now records the
fingerprint into the job.

Worth stating plainly because the correction changes what the table says: the
three runs either side of the kind fix are NOT the same experiment, and the
mis-stamp had made them look like they were.

Refs #27

Claude-Session: https://claude.ai/code/session_014KoduiMJRyLqjFYBUbMskE

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
lex00 added a commit to INTENTIUS/chant-bench that referenced this pull request Aug 4, 2026
…ll I built

The arm vendored a packed build. Every figure until now was measured against a
tarball produced on this machine, which is a different claim from "the released
package does this" — the code being right and what ships being right are not the
same fact, and only one of them is reproducible by a reader.

The arm is pinned to published `@intentius/chant` 0.41.0 and
`@intentius/chant-lexicon-aws` 0.41.0. Nothing local remains in its dependency
tree, so `npm install` reproduces these runs.

## Both sets re-measured on the published package

    board       23/24, 23/24, 23/24    median 0.9583   (was 0.9167)
    negatives   6/6, 6/6, 6/6          median 6/6      (was 0/6 at the start)

Both sets homogeneous — one workspace fingerprint, one harness commit, one
briefing SHA — and both with no spread at all. Every run answered with ZERO
account reads, entirely from its recorded snapshot, and every run passed the
audit.

The negatives figure reproduces the local build's exactly, which is what this
re-run existed to check. The board moved up rather than staying still; the
published package carries more than my six fixes (the CloudFormation spec
upgrade among them), so that difference is not attributed here.

## Provenance is now recorded rather than inferred

These carry workspace `09766f0396b7`, distinct from the local build's
`30c405b9a8f5`, because lex00/aws-bench#11 makes the runner stamp the
fingerprint into the job at run time. Under the previous behaviour — read from
the export at emit time — ingesting these after any later rebuild would have
labelled them with a workspace they never ran against, which is exactly the
error that had to be corrected by hand two commits ago.

Refs #27

Claude-Session: https://claude.ai/code/session_014KoduiMJRyLqjFYBUbMskE

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant