Skip to content

conformance: --pointer can address every element of an array - #11

Merged
coderoast-dev merged 1 commit into
mainfrom
spec/pointer-iterates-arrays
Aug 25, 2026
Merged

coderoast-dev merged 1 commit into
mainfrom
spec/pointer-iterates-arrays

Conversation

@coderoast-dev

Copy link
Copy Markdown
Collaborator

The defect this closes, and why the obvious repair is worse than the bug

--pointer resolves to one document. An envelope carries one document per
comparison its producer performed
, so a real CI report's raw is a list —
raw[0].diff, raw[1].diff, …

The obvious repoint, /raw/0/diff, is not a smaller check. It judges the first
entry and prints the same confident CONFORMANT over the rest — a green covering
a subject nobody chose. Measured on the four-entry fixture this PR adds, whose
only violation sits at entry 2:

pointer exit documents judged verdict
/raw/0/diff 0 1 CONFORMANT — over a file that contains a violation
/raw/-/diff 1 4 NONCONFORMANT, naming report_with_raw_diff_array.json/raw/2/diff

Both rows are fixtures in the same manifest. The second is the fix; the first
is pinned deliberately, so the contrast is executable rather than remembered and
so the fix cannot later be read as an improvement in degree.

The change

- in an array position selects every element; each selected element is
judged and counted as its own document.

--pointer /raw/-/diff          every comparison in one report
--pointer /runs/-/raw/-/diff   every comparison in every run of an aggregate report

The token is safe to give that meaning because RFC 6901 §4 already gives it
exactly one meaning in an array
— the element after the last — and that element
never exists, so no pointer that used to resolve can start resolving differently.
In an object position - stays a literal member name, exactly as RFC 6901
says: this tool does not overrule the standard it cites in order to be helpful.
A fixture carrying a member spelled - pins that half.

Two ways a corpus can shrink are refusals, not verdicts, and both exit 2:

  • a pointer written for a wire shape the envelope no longer has (- against an
    object with no such member) — the message says so, rather than blaming the
    document for a pointer fault;
  • a pointer that resolves onto an empty array. That is the shrink no
    exception-shaped guard can see: every path taken is correct and the subject is
    nothing.

The document count is now printed per corpus file as well as in the total, so
a file that stopped carrying what it used to is visible without a roster. Each
finding names the concrete pointer of the element it came from — 1 of 40 with no
element named is a number nobody can act on.

Nothing moves for a single-document subject

A pointer without the token selects exactly one node and labels it by file,
unchanged. Verified by re-running the three live invocations of this tool, before
and after: identical exit codes and identical findings, the only difference
being the per-file document count added to the corpus line.

In --json, corpus becomes a list of {path, documents, expanded} rather than a
list of paths — one key with one meaning, rather than a second key repeating the
first.

Teeth

Ten mutations each red the self-test:

mutation reds
wildcard judges only the first element the 4-entry fixture + the nested one
wildcard judges only the last element the same two
judges every element, counts one the same two
judges every element, names none the same two
empty selection accepted pointer-empty-selection
token wildcarded against objects too the dash-member fixture + the stale-shape one
a numeric index expands as if it were the token the /raw/0/diff contrast pin
a control tag deleted exit 2 before any fixture runs
a fixture omits which element its finding came from exit 2
a refusal fixture omits the reason exit 2

Unmutated control: 22/22, eight controls armed — against 16/16 and five before
this change.

The last two rows are the manifest's own demands, both derived from a fixture's
own shape rather than kept in a list beside it, and both verified by bypassing
the partner
: remove the demand and the key it asks for, and the suite goes
green on a strictly weaker oracle. That is what each demand costs and why it is
derived rather than remembered.

Scope

conformance/ only — no SPEC.md, no schema/. Not a format change: no document
changes validity, and no producer becomes conformant or stops being so.

…ject nobody chose

An envelope carries one document per comparison its producer performed, so a real
CI report's `raw` is a LIST. `--pointer` resolved to ONE document, and the obvious
repair — pointing at `/raw/0/diff` — is not a smaller check. It judges the first
entry and prints the same confident CONFORMANT over the rest.

Measured on a four-entry envelope whose only violation sits at entry 2:
`/raw/0/diff` reads exit 0, CONFORMANT; `/raw/-/diff` reads exit 1 and names
`report.json/raw/2/diff`. Both readings are pinned as fixtures in one manifest, so
the contrast is executable rather than remembered.

`-` in an ARRAY position now selects EVERY element, each judged and counted as its
own document. The token is safe to give that meaning because RFC 6901 §4 already
gives it exactly one in an array — the element after the last — and that element
never exists, so no pointer that used to resolve can start resolving differently.
In an OBJECT position it stays a literal member name: this tool does not overrule
the standard it cites in order to be helpful.

Two ways the corpus can shrink are refusals, not verdicts, and both are exit 2: a
pointer written for a wire shape the envelope no longer has, and a pointer that
resolves onto an EMPTY array. The second is the shrink no exception-shaped guard
can see — every path taken is correct and the subject is nothing. The document
count is now printed per file as well as in total, so a file that stopped carrying
what it used to is visible without a roster.

Nothing moves for a single-document subject: a pointer without the token selects
one node and labels it by FILE, unchanged. Verified by re-running the three live
invocations of this tool before and after — identical exit codes, identical
findings, the only difference being the per-file count added to the corpus line.

Three new controls, each derived from a mutation the previous fixture set passed:
pointer-array-every-element, pointer-empty-selection, pointer-token-literal-in-object.
The manifest gains two demands derived from a fixture's own shape rather than from
a list: a fixture whose pointer expands must say WHICH element each finding came
from, and a fixture expecting a refusal on a pointer must say WHICH refusal — exit
2 is a class, not a reason. Ten mutations red the suite; both demands verified by
bypassing their partner (remove the demand and the key it asks for, and the suite
goes green on a strictly weaker oracle). Unmutated control: 22/22, eight controls
armed, against 16/16 and five before this change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderoast-dev
coderoast-dev merged commit b4724fb into main Aug 25, 2026
1 check passed
@coderoast-dev
coderoast-dev deleted the spec/pointer-iterates-arrays branch September 19, 2026 08:03
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