joulecontract: the published negative vectors were never actually run #94

Merged
dcharlot merged 2 commits from joulecontract/run-negative-vectors into main 2026-09-18 11:35:25 -04:00
Owner

The pack had two tests: every file's content address against MANIFEST.json, and the positive DSSE envelope. Neither executed a negative vector. All eleven negative-*.json were published, digest-pinned, and never read by a verifier — so the vectors written to catch a verifier that stops demoting were exactly the ones that could not catch it.

This replays each through validate_sealed under the context they were generated in, comparing all four recorded fields: the demotion list, the maximum profile, the rendered §15 claim string, and whether the claimed profile is permitted.

Equality, not "it demoted"

These are degradation vectors, not accept/reject ones. Each records the verdict a conformant verifier must produce — metered_unattested demotes Energy to ModelBased, generator_unattested caps Governance at declared. Asserting merely that something was demoted would pass a verifier that demoted the wrong axis, or by the wrong amount, or that refused the receipt outright — and refusing isn't the specified behaviour either, so the replay also asserts each vector still validates structurally.

A wrong assumption the vectors corrected

My first version asserted every negative vector must leave its claimed profile impermissible. Two do not. recourse_undeclared and static_only_frame record a disclosure demotion rather than a cap, and static_only is prohibited only at JR-4 while these vectors claim JR-3 — so the honest verdict is "permitted, and here is what you are trusting". Asserting !permits would have pressured two published vectors toward a stricter reading than the spec takes. The invariant is the demotion list instead.

Falsified, not assumed

Removing the EngagementUndisclosed demotion rule from the verifier leaves the entire pre-existing workspace suite green, and fails this replay naming the vector and the axis.

StaticOnly, EngagementUndisclosed and IndependentKeyOnly appear in no unit test in joulecontract-receipt at all — the published pack was their only coverage, and it was not running.

Worth stating precisely: a probe against MeteredUnattested is not silent — two unit tests catch that one. The gap is uneven, which is itself worth knowing, and this PR does not claim more than it closes.

Anti-vacuity

The replay asserts it saw at least eleven vectors, so a wrong path, a renamed prefix or an empty glob fails rather than passing having checked nothing — the same vacuity that let the original gap hide. It also pins the three context scalars it replays under, so a pack regenerated under a different context fails rather than silently comparing two different questions.

joulecontract-rs is already in the CI matrix, so these vectors now run on every change.

Verification

15 test binaries green across the workspace, 1 new. The verifier crate is byte-identical to main — the falsification probes were reverted and the revert checked with git diff --quiet.

🤖 Generated with Claude Code

The pack had two tests: every file's content address against `MANIFEST.json`, and the positive DSSE envelope. **Neither executed a negative vector.** All eleven `negative-*.json` were published, digest-pinned, and never read by a verifier — so the vectors written to catch a verifier that stops demoting were exactly the ones that could not catch it. This replays each through `validate_sealed` under the context they were generated in, comparing all four recorded fields: the demotion list, the maximum profile, the rendered §15 claim string, and whether the claimed profile is permitted. ## Equality, not "it demoted" These are **degradation** vectors, not accept/reject ones. Each records the verdict a conformant verifier must produce — `metered_unattested` demotes Energy to `ModelBased`, `generator_unattested` caps Governance at `declared`. Asserting merely that *something* was demoted would pass a verifier that demoted the wrong axis, or by the wrong amount, or that refused the receipt outright — and refusing isn't the specified behaviour either, so the replay also asserts each vector still validates structurally. ## A wrong assumption the vectors corrected My first version asserted every negative vector must leave its claimed profile impermissible. **Two do not.** `recourse_undeclared` and `static_only_frame` record a *disclosure* demotion rather than a cap, and `static_only` is prohibited only at JR-4 while these vectors claim JR-3 — so the honest verdict is "permitted, and here is what you are trusting". Asserting `!permits` would have pressured two published vectors toward a stricter reading than the spec takes. The invariant is the demotion list instead. ## Falsified, not assumed Removing the `EngagementUndisclosed` demotion rule from the verifier leaves the **entire pre-existing workspace suite green**, and fails this replay naming the vector and the axis. `StaticOnly`, `EngagementUndisclosed` and `IndependentKeyOnly` appear in **no unit test** in `joulecontract-receipt` at all — the published pack was their only coverage, and it was not running. Worth stating precisely: a probe against `MeteredUnattested` is *not* silent — two unit tests catch that one. The gap is uneven, which is itself worth knowing, and this PR does not claim more than it closes. ## Anti-vacuity The replay asserts it saw at least eleven vectors, so a wrong path, a renamed prefix or an empty glob fails rather than passing having checked nothing — the same vacuity that let the original gap hide. It also pins the three context scalars it replays under, so a pack regenerated under a different context fails rather than silently comparing two different questions. `joulecontract-rs` is already in the CI matrix, so these vectors now run on every change. ## Verification 15 test binaries green across the workspace, 1 new. The verifier crate is byte-identical to `main` — the falsification probes were reverted and the revert checked with `git diff --quiet`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
joulecontract: the published negative vectors were never actually run
Some checks failed
standards workspaces build + test / aac-rs (pull_request) Successful in 49s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 55s
standards workspaces build + test / jouleclaw-rs (pull_request) Failing after 3m58s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 1m15s
standards workspaces build + test / map-rs (pull_request) Successful in 1m33s
standards workspaces build + test / mesh-rs (pull_request) Successful in 34s
standards workspaces build + test / openpay (pull_request) Successful in 2m38s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m51s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m17s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m13s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m5s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m38s
standards workspaces build + test / arl-rs (pull_request) Successful in 2m48s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 2m27s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 2m25s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 2m7s
standards workspaces build + test / sense-rs (pull_request) Successful in 2m41s
5350ed3c49
The pack had two tests: every file's content address against `MANIFEST.json`,
and the positive DSSE envelope. Neither *executed* a negative vector. All eleven
`negative-*.json` were published, digest-pinned, and never read by a verifier —
so the vectors written to catch a verifier that stops demoting were exactly the
ones that could not catch it.

This replays each through `validate_sealed` under the context they were generated
in, and compares all four recorded fields: the demotion list, the maximum
profile, the rendered §15 claim string, and whether the claimed profile is
permitted.

**Equality, not "it demoted".** These are degradation vectors, not accept/reject
ones. Each records the verdict a conformant verifier must produce —
`metered_unattested` demotes Energy to `ModelBased`, `generator_unattested` caps
Governance at `declared`. Asserting merely that something was demoted would pass
a verifier that demoted the wrong axis, or by the wrong amount, or that refused
the receipt outright — and refusing is not the specified behaviour either, so the
replay also asserts each vector still validates structurally.

**A wrong assumption the vectors corrected.** My first version asserted every
negative vector must leave its claimed profile impermissible. Two do not:
`recourse_undeclared` and `static_only_frame` record a *disclosure* demotion
rather than a cap, and `static_only` is prohibited only at JR-4 while these
vectors claim JR-3. The honest verdict there is "permitted, and here is what you
are trusting". Asserting `!permits` would have pressured two published vectors
toward a stricter reading than the spec takes, so the invariant is the demotion
list instead.

**Falsified, not assumed.** Removing the `EngagementUndisclosed` demotion rule
from the verifier leaves the *entire* pre-existing workspace suite green, and
fails this replay naming the vector and the axis. `StaticOnly`,
`EngagementUndisclosed` and `IndependentKeyOnly` appear in no unit test in
`joulecontract-receipt` at all — the published pack was their only coverage, and
it was not running. (A probe against `MeteredUnattested` is *not* silent: two
unit tests catch that one. The gap is uneven, which is itself worth knowing.)

The replay asserts it saw at least eleven vectors, so a wrong path, a renamed
prefix or an empty glob fails rather than passing having checked nothing — the
same vacuity that let the original gap hide. It also pins the three context
scalars it replays under, so a regenerated pack under a different context is a
failure rather than a silent comparison between two different questions.

`joulecontract-rs` is already in the CI matrix, so these vectors now run on every
change.

Verified: 15 test binaries green across the workspace, 1 new. The verifier crate
is byte-identical to `main` — the falsification probes were reverted and the
revert checked with `git diff --quiet`.

Co-Authored-By: Claude Opus 5 <[email protected]>
dcharlot force-pushed joulecontract/run-negative-vectors from 5350ed3c49
Some checks failed
standards workspaces build + test / aac-rs (pull_request) Successful in 49s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 55s
standards workspaces build + test / jouleclaw-rs (pull_request) Failing after 3m58s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 1m15s
standards workspaces build + test / map-rs (pull_request) Successful in 1m33s
standards workspaces build + test / mesh-rs (pull_request) Successful in 34s
standards workspaces build + test / openpay (pull_request) Successful in 2m38s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m51s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m17s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m13s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m5s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m38s
standards workspaces build + test / arl-rs (pull_request) Successful in 2m48s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 2m27s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 2m25s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 2m7s
standards workspaces build + test / sense-rs (pull_request) Successful in 2m41s
to d5aa3635d7
Some checks failed
standards workspaces build + test / aac-rs (pull_request) Successful in 37s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 50s
standards workspaces build + test / eoc-rs (pull_request) Successful in 2m0s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m18s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m13s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m6s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m37s
standards workspaces build + test / jouleclaw-rs (pull_request) Failing after 8m38s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 2m33s
standards workspaces build + test / map-rs (pull_request) Failing after 1m2s
standards workspaces build + test / mesh-rs (pull_request) Successful in 1m26s
standards workspaces build + test / openpay (pull_request) Failing after 2m21s
standards workspaces build + test / arl-rs (pull_request) Successful in 23m29s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 3m37s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 13m52s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 26m31s
standards workspaces build + test / sense-rs (pull_request) Successful in 12m25s
2026-09-17 06:54:03 -04:00
Compare
dcharlot force-pushed joulecontract/run-negative-vectors from d5aa3635d7
Some checks failed
standards workspaces build + test / aac-rs (pull_request) Successful in 37s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 50s
standards workspaces build + test / eoc-rs (pull_request) Successful in 2m0s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m18s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m13s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m6s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m37s
standards workspaces build + test / jouleclaw-rs (pull_request) Failing after 8m38s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 2m33s
standards workspaces build + test / map-rs (pull_request) Failing after 1m2s
standards workspaces build + test / mesh-rs (pull_request) Successful in 1m26s
standards workspaces build + test / openpay (pull_request) Failing after 2m21s
standards workspaces build + test / arl-rs (pull_request) Successful in 23m29s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 3m37s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 13m52s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 26m31s
standards workspaces build + test / sense-rs (pull_request) Successful in 12m25s
to 7eee267a06
All checks were successful
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m56s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m19s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 3m37s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m12s
standards workspaces build + test / aac-rs (pull_request) Successful in 52s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m7s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 2m54s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m34s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 2m3s
standards workspaces build + test / map-rs (pull_request) Successful in 2m24s
standards workspaces build + test / mesh-rs (pull_request) Successful in 1m52s
standards workspaces build + test / arl-rs (pull_request) Successful in 18m13s
standards workspaces build + test / openpay (pull_request) Successful in 6m30s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 24m22s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 40m4s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 12m31s
standards workspaces build + test / sense-rs (pull_request) Successful in 18m28s
2026-09-17 21:08:03 -04:00
Compare
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!94
No description provided.