Skip to content

The negative question set has a board of its own, and chant's first number on it - #28

Open
lex00 wants to merge 6 commits into
mainfrom
feat/negatives-board
Open

The negative question set has a board of its own, and chant's first number on it#28
lex00 wants to merge 6 commits into
mainfrom
feat/negatives-board

Conversation

@lex00

@lex00 lex00 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

benchmarks/tasks/ec2-multiregion-negatives had scored runs and nowhere to render them (#27). It gets its own scenario, its own page, and none of the board's machinery.

Why not the board

The board ranks replicate sets by what a hundred correct answers cost. This is one run per arm of a two-question set, and dressing six trials in that apparatus would give them a confidence they have not earned.

The page leads with the two things a reader has to know before the number: these are ours, not aws-bench's, and 6 trials do not compare with 24. It also keeps the part of the task README that weakens the questions rather than the part that sells them — the no-tool baseline gets them with a sweep of two API calls, where the security-group question they are modelled on defeats even account-reading agents 72% of the time. They test the same structure, not the same difficulty.

load() takes a scenario instead of hardcoding one. Nothing else needed changing: validate_results.py already groups by (bench, scenario), so the 6-trial run sits beside the 24-trial ones without disturbing a group it is not part of. 67/67 records still satisfy the contract, and mkdocs build --strict is clean.

chant: 3/6

The first publishable number on this set, and a real one rather than the 0/6 in #27. That figure was mostly two defects, both since fixed:

chant#1428 An endpoint override dropped the region, so two of the estate's four stacks were never observed. Not degraded — they returned "stack does not exist", which reads as "not deployed yet", so the snapshot recorded nothing and said nothing. chant saw one region of three.
chant#1416 With all three regions visible, their identically-named default subnets then merged account-wide by physical id.

Fixing only the first gives 7 subnets; fixing both gives all 13. Ground truth is 13 subnets (8 empty) and 6 VPCs (2 empty), computed live off the deployed estate.

The run answered with zero account reads, entirely from its recorded snapshot, at a 0% tool failure rate across 31 invocations.

What is still wrong, and not smoothed over

The 1/3 on subnets is not noise. The trial that passed listed exactly the right eight; the two that failed over-reported, counting occupied subnets as empty. That is a live question about the ENI edges in the snapshot and it is filed separately — the page publishes 1/3 rather than waiting for a better number.

Two runs not published

Both earlier attempts were voided by the audit for the same reason: the briefing teaches chant search …, chant was not on PATH in the trial container, the agent's first call died with command not found, and the gate correctly refused the run. One of them was otherwise healthy at 21/24. Fixed in lex00/aws-bench#11; this run passed the gate 6 trials of 6.

The board's figures are untouched by any of this — the chant arm there pins a vendored 0.33.1, which predates the region regression.

Refs #27

🤖 Generated with Claude Code

https://claude.ai/code/session_014KoduiMJRyLqjFYBUbMskE

lex00 and others added 2 commits August 3, 2026 11:18
…umber on it

`benchmarks/tasks/ec2-multiregion-negatives` had scored runs and nowhere to
render them (#27). It gets its own scenario, its own page, and none of the
board's machinery.

Deliberately not the board. That ranks replicate sets by what a hundred correct
answers cost; this is one run per arm of a two-question set, and dressing six
trials in that apparatus would give them a confidence they have not earned. The
page says in its first paragraph that these are ours rather than aws-bench's and
that 6 trials do not compare with 24, and it keeps the part of the task README
that weakens the questions — the no-tool baseline gets them with two API calls,
where the security-group question they are modelled on defeats even
account-reading agents 72% of the time.

`load()` takes a scenario instead of hardcoding one. Nothing else needed
changing: `validate_results.py` already groups by `(bench, scenario)`, so the
6-trial run sits beside the 24-trial ones without disturbing the group it is not
part of — 67/67 records still satisfy the contract.

## chant: 3/6

The first publishable number on this set, and it is a real one rather than the
0/6 recorded in #27. That figure was mostly an artifact of two defects:

- **INTENTIUS/chant#1428** — an endpoint override dropped the region, so two of
  the estate's four stacks were never observed at all. Not degraded: they came
  back as "stack does not exist", which reads as "not deployed yet", so the
  snapshot recorded nothing for them and said nothing about it. chant saw one
  region of three.
- **INTENTIUS/chant#1416** — with all three regions visible, their
  identically-named default subnets then merged account-wide by physical id.
  Fixing only the first gives 7 subnets; fixing both gives all 13.

Ground truth is 13 subnets (8 empty) and 6 VPCs (2 empty). The run answered with
**zero account reads**, entirely from its recorded snapshot, at a 0% tool
failure rate across 31 invocations.

The 1/3 on subnets is not noise and is not fixed: the trial that passed listed
exactly the right 8, and the two that failed over-reported by counting occupied
subnets as empty. That is a live question about the ENI edges in the snapshot,
filed separately rather than smoothed over here.

Two earlier attempts at this run are not published. Both were voided by the
audit for the same reason — the briefing teaches `chant search …` and `chant`
was not on PATH in the trial container, so the agent's first call died and the
gate correctly refused the run. Fixed in lex00/aws-bench#11; this run passed it
6 trials of 6.

Refs #27

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

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

lex00 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

The 1/3 on the subnet question now has an issue: INTENTIUS/chant#1432.

Ambient resources are recorded as nodes with no edges — observeAwsAmbient deliberately leaves attachment to the graph, and observeDependencies, which is where observation edges come from, only resolves outward from what is declared. So an ambient ENI never gets an edge to its subnet:

ENIs recorded:      4
Subnets recorded:   6
edges total:       18
edges from an ENI:  0

with every ENI carrying SubnetId in its attributes.

That is exactly the 1/3. The trial that passed read SubnetId off each ENI and did the join by hand. The two that failed asked the graph, which has no ENI edges, and got back every subnet — 11 of 13 including subnet-default-c, which has an ENI in it.

I had assumed this was a side effect of the region-qualified node ids from #1416 and checked before writing it up: it is not. buildLiveGraphIr never derives edges from attributes on any path, so this predates both fixes.

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>
@lex00

lex00 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Added chant's board figures on the fixed build, as three replicates rather than one.

A single new run would have joined a replicate set whose other two members are the vendored 0.33.1 — two workspace fingerprints and two harness commits inside one set that the board takes a median across. The figure would have described neither build. The set is homogeneous now:

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

Median 0.9167 — exactly the g-series median. The two chant fixes do not move the board, and that is the expected result rather than a letdown: 0.33.1 read the estate by shelling out to the CLI, which passes --region and signs it, so the arm already saw all three regions. INTENTIUS/chant#1429 is a regression against a build the board never ran.

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

All three runs answered with zero account reads, entirely from the recorded snapshot, and all three passed the audit at 3%, 5% and 1% invocation failure rates.

70/70 records satisfy the contract; mkdocs build --strict clean.

5/6, up from 3/6. The subnet question went 1/3 to 3/3; the VPC question is
unchanged at 2/3, which was predicted rather than hoped for.

Two more chant defects, both pre-existing and both found by measuring rather
than reading:

- **INTENTIUS/chant#1437** — `AWS::EC2::NetworkInterface -> Subnet` was declared
  as containment with no traversal name, so `reconstructEdges` recorded a
  boundary hint and emitted no edge. `kind:EC2::Subnet
  !<-kind:EC2::NetworkInterface` — the query the grammar exists to express —
  matched 23 of 23 subnets. An inert negation is indistinguishable from one that
  searched and found nothing.
- **INTENTIUS/chant#1440** — a subnet its own stack declares is also recorded as
  a dependency, so 13 subnets replayed as 16. A duplicate always reads as empty,
  because the edges resolve to the other copy: the three false positives were
  the three OCCUPIED subnets.

Each of the four fixes was necessary and none was sufficient. Measured against
the estate at each stage, the query returned 5 (one region visible), 7 (regions
merged), 11 (negation inert), 11 (duplicates read as empty), and finally 8 —
the correct 8, keeping us-east-1's occupied default-c out.

The VPC question stays at 2/3 because containment INTO a VPC is deliberately not
traversable — `reference-catalog.test.ts` asserts it — and flipping that to
improve this number is a decision for its own change, not a side effect of this
one. Left on #1437.

## The page now shows every run

A second run of an arm is usually a different build, and which build produced a
number is the whole question this repo exists to keep answerable. Showing only
the newest quietly dropped the evidence that the number moved, so both runs are
listed with their workspace fingerprints — which is what says they are not the
same experiment.

Refs #27

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

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

lex00 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

5/6. The subnet question went 1/3 → 3/3; the VPC question is unchanged at 2/3, which was predicted rather than hoped for.

Two more chant defects, both pre-existing, both found by measuring rather than reading:

Each fix was necessary; none was sufficient

Measured against the deployed estate at each stage, with ground truth 8 of 13:

build returns why
as published (0.33.1) 5 total, 2 empty one region visible
+ #1429 region 7 regions merged by id
+ #1425 dedup 11 negation inert
+ #1437 traversal 11 duplicates read as empty
+ #1440 duplicates 8 correct, keeping occupied default-c out

Why the VPC question stays at 2/3

Containment into a VPC is deliberately not traversable — reference-catalog.test.ts asserts expect(edges.some((e) => e.to === "vpc")).toBe(false). My first patch to #1437 flipped that and the test caught it. Flipping an explicit invariant to improve a benchmark number is a decision for its own change, not a side effect of this one, so I reverted it and left the question open on #1437.

The page now lists every run

A second run of an arm is usually a different build, and showing only the newest quietly drops the evidence that a number moved. Both runs are listed with their workspace fingerprints, which is what says they are not the same experiment.

Gates on chant-neg-2: 6/6 trials on chant's own tooling, 41 invocations, 0% failure, 0 account reads. 71/71 records satisfy the contract; strict build clean.

lex00 and others added 2 commits August 3, 2026 15:13
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>
…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