Compare commits
6 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c362717818 | |||
| e56812eb39 | |||
| f0a511369d | |||
| c75c546614 | |||
| c23aea9062 | |||
| 757570dd49 |
8 changed files with 312 additions and 15 deletions
218
CHANGELOG.md
218
CHANGELOG.md
|
|
@ -9,6 +9,224 @@ Versioning note: the repository tag versions **the contract** (file set, key nam
|
|||
case ids, disposition semantics). Each JSON file additionally carries its own
|
||||
`"version"` field, bumped when that file changes.
|
||||
|
||||
## [0.9.0] — 2026-08-13
|
||||
|
||||
**A normative rule stated its own premise and then applied itself beyond it.**
|
||||
`spec/conformance-corpus.md` §7 justified the fixture-is-ground-truth ordering with *"**Two
|
||||
implementations** that return different verdicts…"* and then stated the rule with no scope at
|
||||
all. For `signatures/active-content.json` there is no second implementation — the seed runtime
|
||||
authored both the payloads and the table — and that runtime has stated that the classification
|
||||
behind it is calibration it does not freeze. §7 as written made a reserved change on their side
|
||||
into a bug on their side.
|
||||
|
||||
**Breaking in category, minor in number.** This changes disposition semantics, which the
|
||||
versioning note at the top of this file counts as contract. The repository is in 0.x, where a
|
||||
breaking change is a minor bump by the rules — the same reading `[0.3.0]` recorded: *read the
|
||||
entry, not the version number*.
|
||||
|
||||
### Changed
|
||||
|
||||
- **`spec/conformance-corpus.md` — new §7.1, *Where the second paragraph does not hold*.** The
|
||||
scope is keyed on a **structural property**, never on a table name: a case whose scope is a
|
||||
table only one runtime implements, whose payload that runtime authored. A rule naming
|
||||
`active-content` would rot the day a second runtime implements it. §7's own second paragraph
|
||||
already carried the premise; §7.1 makes it explicit and states the disposition for the case
|
||||
the premise excludes — the fixture is not rewritten on the divergence alone, the divergence is
|
||||
recorded against the version pinned, and re-pinning is a separate release. That is the
|
||||
disposition §5 already applies to a stale `observed_out_of_scope` entry, extended to the one
|
||||
place where it can reach a verdict.
|
||||
|
||||
**It creates no fourth verdict, and that constraint shaped the wording.**
|
||||
`schema/conformance-declaration.schema.json` closes `result` with `additionalProperties: false`
|
||||
over four counts plus two arithmetic invariants; a fifth verdict would have broken every
|
||||
consumer's parser, which is a worse break than the one intended. A case whose expected findings
|
||||
are not produced still **fails** and is still named in `failed_cases`. What §7.1 changes is what
|
||||
the failure licenses concluding, not what is reported.
|
||||
|
||||
Two limits stated in the section rather than left to be inferred: it does **not** reach a
|
||||
third-party implementer of the same table — against them the fixture is the contract, exactly
|
||||
as §7 says, and that is the only thing these cases can prove while one runtime is all there is
|
||||
— and it is **not** a licence for a runtime to self-declare, since the exemption is carried by
|
||||
the corpus's provenance record for the scope and not asserted per case by whoever failed.
|
||||
|
||||
Superseded text is named rather than edited away, following §6's own pattern: *"Through corpus
|
||||
version 0.8.1 this section stated the rule above with no scope at all."*
|
||||
|
||||
**The competing reading was tested and disposed of**, because it is the one that would have
|
||||
avoided this release: that §7's existing hatch (*"unless the fixture itself is proven wrong"*)
|
||||
already covered it. It does not. The hatch's consequence is that **the fixture changes**, and
|
||||
the manifest field asserts the opposite — pinned, not rewritten, re-pinning a separate
|
||||
decision. And a runtime recalibrating does not prove the earlier classification wrong: the
|
||||
fixture measured `de09711` / `0.4.0` correctly, and a later release does not reach back and
|
||||
falsify an earlier measurement. The case fits neither of §7's two dispositions, which is the
|
||||
defect.
|
||||
|
||||
- **`conformance/manifest.json` `0.6.1` → `0.6.2` —
|
||||
`active_content_provenance.pins_a_version_not_a_frozen_classification` no longer records an
|
||||
open question.** The retirement is **partial and it is quoted, not dropped**, per the house
|
||||
style this field established one release ago (*"a correction that does not say what it corrects
|
||||
cannot be audited"*). What falls is only the open-question status; the clause *"section 7 …
|
||||
is NOT amended by this block"* **stays true and is kept**, because §7 was amended by its own
|
||||
release and not by a data file. Value change only — read back from disk against `HEAD` with a
|
||||
flattened key diff: `added: 0, removed: 0, changed: 2` (the field and `version`), and the new
|
||||
string printed and read rather than inferred from the count, since a value edit reports
|
||||
`changed: 1` whatever it wrote.
|
||||
|
||||
Six prose dashes in the new text were written `--` and promoted to `—` before commit: `--` is
|
||||
the variant-suffix separator token of §6's case-id grammar, and every other occurrence of it in
|
||||
this file is that token, a real case id, or a CLI flag.
|
||||
|
||||
### Neighbours — measured, and the ones left alone are named
|
||||
|
||||
A sweep for the retired premise was run over the whole repository, widened past *"ground truth"*
|
||||
to the second paragraph's own wording (*"one of them has a bug"*, *"two implementations"*), since
|
||||
a restatement in that phrasing would have survived the first search.
|
||||
|
||||
- **`CONVENTIONS.md` — changed.** Carried the rule unscoped and called the proven-wrong hatch
|
||||
*"the one way that reverses"*. There are now two, and both are listed.
|
||||
- **`CLAUDE.md` — changed.** The Norwegian restatement that governs sessions in this repository
|
||||
carried the same unscoped rule; left alone, the next session here would have acted on it.
|
||||
- **`SECURITY.md` §2 — minimal cross-reference only.** Its claim is about a fixture that expects
|
||||
**too little**, and §7.1 narrows *who the rule reaches*, not that direction. The conclusion
|
||||
survives intact, so it was not rewritten.
|
||||
- **`SECURITY.md` "Why a confirmed defect is usually not fixed here first" — untouched.** Its
|
||||
*"two implementations answering differently"* is about extracted **data** diverging from its
|
||||
source, not about fixtures.
|
||||
- **`README.md` — untouched.** Its conformance row says *"Ground truth"* as a descriptor and does
|
||||
not restate the disagreement rule, and it already names the asymmetry it would otherwise hide:
|
||||
the seven active-content cases are *"measured against the one runtime that implements that
|
||||
table"*. Nothing there became false.
|
||||
- **`docs/extraction-plan.md` — untouched, and it is supporting evidence rather than a stale
|
||||
neighbour.** It already records that the calibration file *"inverts this repository's central
|
||||
rule"* — so this is the second place the unscoped rule was known not to hold, and the first was
|
||||
documented before this release.
|
||||
|
||||
### Not in this release
|
||||
|
||||
Whether the seven active-content cases still pass at the seed runtime's `v1.1.0` is **unmeasured**,
|
||||
and §7.1 is silent on it. No case was minted, no data file touched, no id string proposed.
|
||||
|
||||
## [0.8.1] — 2026-08-13
|
||||
|
||||
**The field 0.8.0 added to make the exposure precise stated it with a hand-derived count, and the
|
||||
count was wrong.** Caught in the same session, before any consumer read it, and corrected inside
|
||||
the field rather than by rewriting it. No measurement changed and no verdict moved.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **`conformance/manifest.json` 0.6.0 → 0.6.1 —
|
||||
`active_content_provenance.pins_a_version_not_a_frozen_classification` now enumerates instead of
|
||||
totalling.** As published it read *"three of the four dimensions they name as calibration cannot
|
||||
move one of these cases at all. The fourth can: which `active:` ids a payload yields IS the
|
||||
classification"*. Two defects in one sentence. First, the total was derived by hand over a
|
||||
taxonomy the field had itself recategorized: the seed runtime's four calibration dimensions are
|
||||
severities, thresholds, **lexicon entries** and dispositions, and lexicon entries are *not* absent
|
||||
from these fixtures — `active__data-uri` carries `data-uri:executable` and `active__raw-html`
|
||||
carries `hybrid-xss:script-tag` in `observed_out_of_scope`, both verified as members of
|
||||
`lexicon/injection-lexicon.json` and non-members of `signatures/active-content.json`. Second,
|
||||
*"the fourth"* silently substituted the classification for lexicon entries as the fourth item of
|
||||
their sentence, which it is not — the classification is what they addressed separately.
|
||||
|
||||
- The replacement names three things and totals none of them: severities/thresholds/dispositions
|
||||
are absent and move no verdict; lexicon entries move no verdict either — spec section 5 forbids
|
||||
failing a runtime over `observed_out_of_scope` — but a lexicon calibration change **ages** those
|
||||
two entries as evidence, which is the exposure
|
||||
`active_content_measurement_0_7_0.movement_sweep.residue_is_the_field_no_test_protects` already
|
||||
names as a class, and this corpus pins a stale residue entry rather than rewriting it; and the
|
||||
active-content classification is the one thing that can move a verdict. The retired sentence is
|
||||
**quoted** in the field's `AMENDED IN 0.6.1` clause, not merely dropped, for the same reason
|
||||
`scope_planned.$comment` quotes what it retired: a correction that does not say what it corrects
|
||||
cannot be audited.
|
||||
|
||||
## [0.8.0] — 2026-08-13
|
||||
|
||||
**The seven active-content fixtures pin a VERSION of the seed runtime, and nothing said so.**
|
||||
That runtime tagged `v1.0.0` on 2026-08-13 and stated that the freeze covers its exported Python
|
||||
surface only, excluding detection behaviour: severities, thresholds, lexicon entries and
|
||||
dispositions are calibration there and move in minor and patch releases. The manifest already
|
||||
pinned commit and version per measurement block, but nowhere recorded that the thing pinned is a
|
||||
version rather than a frozen classification. No case is minted, no data file is touched, no id is
|
||||
proposed.
|
||||
|
||||
### Added
|
||||
|
||||
- **`conformance/manifest.json` 0.5.2 → 0.6.0 —
|
||||
`active_content_provenance.pins_a_version_not_a_frozen_classification`.** One field, scoping the
|
||||
neighbouring `asymmetry` rather than replacing it, and deliberately narrower than the runtime's
|
||||
own statement. The exposure is bounded by what the fixtures assert, which was read from all seven
|
||||
rather than assumed: every finding carries `pattern_id` and nothing else — no severity, no
|
||||
threshold, no disposition — so three of the four dimensions that runtime names as calibration
|
||||
cannot move one of these cases at all. The fourth can, because which `active:` ids a payload
|
||||
yields *is* the classification. The field names both pins (six at 0.4.0 / `de09711`, the seventh
|
||||
at 0.7.0 / `be9759b`) rather than one, since a single version would flatten two measurements into
|
||||
one header — the defect `superseded_for_one_case` exists to prevent. Their v1.0.0 statement is
|
||||
**attributed** to their coord message of 2026-08-13T20:40:31Z, not restated as a fact measured
|
||||
from this side.
|
||||
|
||||
- The field also names the disposition of a future divergence, so it is not left to be inferred: a
|
||||
later 1.x that classifies one of these payloads differently is not a breach by them and does not
|
||||
make the fixture wrong. The fixture stays ground truth at its pinned version, the divergence is
|
||||
measured and recorded, and re-pinning is a separate decision — the same disposition this corpus
|
||||
already applies to a stale `observed_out_of_scope` entry.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **`docs/secret-egress-divergence.md:75-76` carried the same misquote `conformance/manifest.json`
|
||||
had corrected in 0.7.3**, named there as a deliberate omission and closed here. The field's value
|
||||
ends ``ascending `order` `` — the backticks are the field's own. The fix is *not* the one the
|
||||
omission note implied: those two lines are a single code span delimited by **single** backticks
|
||||
across a line break, so inserting the field's backticks inside it would have terminated the span
|
||||
at the first one and rendered the quote broken. The outer delimiter is promoted to double
|
||||
backticks instead, which is what lets the inner singles survive. The manifest's correction ported
|
||||
as a literal string because JSON has no backtick semantics; markdown does. Verified by extracting
|
||||
the span from the file on disk, unfolding the line break, and comparing to the decoded value in
|
||||
`signatures/secret-egress.json` — equal — and by confirming no backtick run of length ≥ 2 sits
|
||||
inside the span.
|
||||
|
||||
### Not done, and named rather than left silent
|
||||
|
||||
- **`spec/conformance-corpus.md` section 7 is untouched.** It states the disagreement rule without
|
||||
scope: *"The fixture is ground truth. A runtime that disagrees is wrong."* Read against the
|
||||
active-content scope, whose only implementing runtime has now said in writing that its
|
||||
classification may legitimately move, that rule would call a calibration change there a bug. The
|
||||
manifest field records the interaction and explicitly does not amend the spec. Whether the
|
||||
normative rule needs a scope is a decision for its own release.
|
||||
|
||||
## [0.7.3] — 2026-08-13
|
||||
|
||||
**The README still argued the premise 0.7.2 retired, and the two files sat on a public remote
|
||||
disagreeing.** `README.md` opened the egress gap with "It is not an id question at all"; the
|
||||
blocker it sends the reader to for authority now opens reason (1) with "NO ID SPACE ON THE
|
||||
COMMONS SIDE. This is the hard blocker." Before 0.7.2 the README was merely out of date. After
|
||||
it, our own commit had made it contradictory — the same defect class 0.7.1 existed to close. No
|
||||
data moves, no case is minted, no id is proposed.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **The README now carries the three measured reasons instead of the retired one.** (1) No id
|
||||
space on the commons side — the hard blocker, and the only one an answer can resolve; the
|
||||
answer belongs to the runtimes that own the seeds. (2) Match semantics disagree, and an id
|
||||
space would not close it. (3) Membership diverges in both directions and the divergence is
|
||||
inherited: the two sides hold 19 entries and 25, and they are ports of two *different* source
|
||||
tables in one source repository. The counts survived the falsification; only the causal claim
|
||||
fell, so `different tables` is kept and "cut at different granularities" is gone. The
|
||||
paragraph deliberately does **not** restate the outgoing question's status: that is true on
|
||||
the day it is written, nothing tests README prose, and `conformance/manifest.json` already
|
||||
carries the date. The standing `entry_points_by_scope` requirement is likewise left out rather
|
||||
than printed as a fourth reason.
|
||||
|
||||
- **`conformance/manifest.json` 0.5.1 → 0.5.2: the blocker misquoted the contract it cites.** It
|
||||
rendered the field as `match_semantics: "… evaluated in ascending order"`; the value in
|
||||
`signatures/secret-egress.json` ends ``ascending `order` `` — the backticks are the field's
|
||||
own. A blocker that misquotes the semantics it is blocking on invites a consumer to implement
|
||||
the wrong one. The data file is
|
||||
unchanged and was never wrong — only the quotation of it was, which `scope_planned.$comment`
|
||||
now records. Verified by reading the edited file back from disk and matching the decoded
|
||||
string against the data file that owns it; `json.tool` passes on wrong escaping.
|
||||
|
||||
Known and deliberately left: `docs/secret-egress-divergence.md` renders the same value without
|
||||
its backticks. That document is `Status: informative` and was outside this release's scope.
|
||||
|
||||
## [0.7.2] — 2026-08-13
|
||||
|
||||
**`scope_planned.blockers` named the premise that `docs/secret-egress-divergence.md`
|
||||
|
|
|
|||
|
|
@ -65,6 +65,13 @@ Ingen. Data + prosa. Filformater: JSON (data + schema), Markdown (spec), rå tek
|
|||
- `expected.json` er ground truth. Er en runtime uenig med `expected.json`, er runtimen
|
||||
feil — med mindre fixturen selv bevises feil, og da endres fixturen i eget commit med
|
||||
begrunnelse.
|
||||
- **Regelen over er skopet, og skopet er bærende.** Er casens scope en tabell bare ÉN runtime
|
||||
implementerer, og den runtimen skrev payloaden, finnes ikke den andre implementasjonen
|
||||
regelen dømmer mellom. Da er en divergens fra *den* runtimen verken en bevist feil fixture
|
||||
eller nødvendigvis deres bug: fixturen skrives ikke om på divergensen alene, den føres mot
|
||||
versjonen som er pinnet, og re-pinning er en egen release. Mot en TREDJEPARTS-implementasjon
|
||||
av samme tabell gjelder §7 uendret. Til og med `v0.8.1` sto regelen uskopet. Se
|
||||
`spec/conformance-corpus.md` §7.1.
|
||||
- **En case er ikke mintbar uten inngangspunkt for sitt scope.** Korpuset pinner ikke
|
||||
lenger ett inngangspunkt per runtime for alt — `manifest.json` →
|
||||
`entry_points_by_scope` bærer inngangspunkt, **findings-accessor** og
|
||||
|
|
|
|||
|
|
@ -107,10 +107,16 @@ this document:
|
|||
- `<case-id>` is stable and descriptive. **Changing a case id is a breaking change** — a
|
||||
published conformance result names it.
|
||||
- `expected.json` is **ground truth**. If a runtime disagrees with it, the runtime is wrong.
|
||||
- The one way that reverses: the fixture is proven wrong. Then the fixture changes **in its own
|
||||
- One way that reverses: the fixture is proven wrong. Then the fixture changes **in its own
|
||||
commit, with the reason written down** — never folded into a change that does something else,
|
||||
because a fixture edit is the one edit that can make every conforming runtime wrong
|
||||
identically.
|
||||
- The other, added in `v0.9.0`: where a case's scope is a table only one runtime implements and
|
||||
that runtime authored the payload, a divergence by **that** runtime is neither a proven-wrong
|
||||
fixture nor necessarily its bug. The fixture is not rewritten on the divergence alone — it is
|
||||
recorded against the version pinned, and re-pinning is a separate release. Through `v0.8.1`
|
||||
this list carried only the first way. See
|
||||
[`spec/conformance-corpus.md` §7.1](spec/conformance-corpus.md).
|
||||
- A case declares the data files it is `scope`d to. A runtime that does not implement a scoped
|
||||
table reports the case `not-applicable` — a third verdict beside pass and fail, and one that
|
||||
must be reported rather than dropped from the denominator. See
|
||||
|
|
|
|||
33
README.md
33
README.md
|
|
@ -16,6 +16,18 @@ unicode-carrier smuggling or active content in untrusted text, on any runtime.
|
|||
|
||||
**It holds no runnable code.** Data, specifications and fixtures only.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Install](#install)
|
||||
- [Requirements](#requirements)
|
||||
- [What it does](#what-it-does)
|
||||
- [Non-goals](#non-goals)
|
||||
- [Known limitations](#known-limitations)
|
||||
- [Contributing](#contributing)
|
||||
- [Reporting a wrong entry](#reporting-a-wrong-entry)
|
||||
- [Changelog](#changelog)
|
||||
- [License](#license)
|
||||
|
||||
## Install
|
||||
|
||||
Nothing to install — this repository is **vendored into consumers**, not installed.
|
||||
|
|
@ -109,11 +121,22 @@ number would misreport all three:
|
|||
missing **name** rather than a missing capability. It lapses the moment that runtime names
|
||||
its label and the alias is added.
|
||||
|
||||
One case remains unshipped, for the secret-egress table, and it is not blocked on effort.
|
||||
It is not an id question at all — the two runtimes carry *different tables*, 19 entries
|
||||
against 25, cut at different granularities, and a shared id space presupposes a reconciliation
|
||||
nobody has performed. `conformance/manifest.json` records that blocker under
|
||||
`scope_planned.blockers`, measured, so the gap is visible rather than inferred.
|
||||
One case remains unshipped, for the secret-egress table, and it is not blocked on effort. The
|
||||
reasons are three, they were measured, and they are independent — none of them dissolves under
|
||||
anything this repository can run alone. **(1) There is no id space on the commons side.** The
|
||||
seed this table was ported from carries a name and a pattern per entry and nothing else, so its
|
||||
entries are keyed by human-readable name while the other runtime emits `egress:<id>` labels —
|
||||
and a fixture names labels. This is the hard blocker, and the only one of the three that an
|
||||
answer can resolve; the answer belongs to the runtimes that own the seeds, not to a name coined
|
||||
here. **(2) Match semantics disagree**, and an id space would not close it: this table declares
|
||||
first-match-wins with `ordering.normative: true`, the other runtime reports every match, and one
|
||||
witness — an `Authorization` header holding a three-part JWT — produces one label here and two
|
||||
there. That difference is exactly what an `expected.json` encodes. **(3) Membership diverges in
|
||||
both directions, and the divergence is inherited rather than introduced.** The two sides hold 19
|
||||
entries and 25, but they are ports of two *different* source tables in one source repository, so
|
||||
re-measuring either port cannot close it. `conformance/manifest.json` records all three under
|
||||
`scope_planned.blockers`, and the method behind every number is in
|
||||
[the divergence measurement](docs/secret-egress-divergence.md).
|
||||
|
||||
The carrier blocker closed in v0.5.0 and is kept, with its retired text, under
|
||||
`scope_planned.blockers_resolved` — including the correction one runtime volunteered against
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ detector, and that is a working bypass against every consumer until it is closed
|
|||
|
||||
Report privately by email:
|
||||
|
||||
- **hello@fromaitochitta.com**, with `SECURITY` at the start of the subject.
|
||||
- **security@fromaitochitta.com**, with `SECURITY` at the start of the subject.
|
||||
|
||||
Pull requests are not the channel either — they are switched off on the canonical
|
||||
repository, and not as an oversight. This repository is vendored into independent runtimes
|
||||
|
|
@ -45,8 +45,9 @@ In scope — all of these are real reports:
|
|||
escaping is wrong for the declared dialect, missing or wrong flags, a pattern that fails
|
||||
to compile in a documented engine and gets skipped rather than reported.
|
||||
2. **A conformance fixture that sanctions a miss.** `expected.json` is ground truth: a
|
||||
runtime that disagrees with it is deemed wrong. A fixture that expects too little makes
|
||||
every conforming runtime wrong identically, and the corpus will not catch it.
|
||||
runtime that disagrees with it is deemed wrong (as scoped by `spec/conformance-corpus.md`
|
||||
§7.1, which narrows who that reaches and not this direction). A fixture that expects too
|
||||
little makes every conforming runtime wrong identically, and the corpus will not catch it.
|
||||
3. **A normative clause that mandates unsafe behaviour.** The `spec/` files bind the
|
||||
implementations that consume them, so a weak rule propagates to all of them.
|
||||
4. **A real secret or personal data in the repository or its history.** The history is
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -72,8 +72,8 @@ rather than by measurement.
|
|||
This is the finding a membership table would hide, and it is the one a consumer implementing
|
||||
from commons will get wrong first.
|
||||
|
||||
`signatures/secret-egress.json` declares `match_semantics: "first match wins; patterns are
|
||||
evaluated in ascending order"`, marks `ordering.normative: true`, and names
|
||||
`signatures/secret-egress.json` declares ``match_semantics: "first match wins; patterns are
|
||||
evaluated in ascending `order`"``, marks `ordering.normative: true`, and names
|
||||
`last_entry_is_load_bearing: "JWT (three-part token)"` — the JWT entry is placed last
|
||||
precisely so a token inside an `Authorization` header is reported as the header, not as a
|
||||
bare JWT.
|
||||
|
|
|
|||
|
|
@ -284,6 +284,47 @@ This ordering is the whole point of the repository. Two implementations that ret
|
|||
different verdicts on the same input are not holding different opinions; one of them has a
|
||||
bug.
|
||||
|
||||
### 7.1 Where the second paragraph does not hold
|
||||
|
||||
**Through corpus version 0.8.1 this section stated the rule above with no scope at all**, and
|
||||
the scope was load-bearing: the justification names *two* implementations. Where a case's
|
||||
scope is a table only one runtime implements, and that runtime authored the payload the case
|
||||
was extracted from, there is no second implementation whose disagreement the paragraph could
|
||||
adjudicate. Which cases those are is recorded in the corpus, not asserted per run — see
|
||||
`active_content_provenance.asymmetry` in
|
||||
[`conformance/manifest.json`](../conformance/manifest.json).
|
||||
|
||||
For such a case, a disagreement by the **seed runtime itself** is a third thing, and it is
|
||||
neither of the two the paragraph offers:
|
||||
|
||||
- The fixture is not proven wrong. It recorded that runtime's behaviour correctly at the
|
||||
commit and version its own measurement block pins, and a later classification does not
|
||||
reach back and falsify an earlier measurement.
|
||||
- The runtime does not necessarily have a bug. Where the seed runtime has stated that the
|
||||
classification behind such a table is calibration it does not freeze, a release that
|
||||
classifies the payload differently is a change it reserved, not a defect.
|
||||
|
||||
So: the fixture MUST NOT be rewritten on the strength of the divergence alone; the divergence
|
||||
SHOULD be recorded against the version pinned; and re-pinning the case to a later version of
|
||||
the seed runtime is a separate decision, taken deliberately and released on its own. This is
|
||||
the disposition §5 already applies to a stale `observed_out_of_scope` entry, extended to the
|
||||
one place where it can reach a verdict — and a divergence recorded here is the signal that
|
||||
the re-pinning decision is due, not a reason to leave it open.
|
||||
|
||||
Three things this does **not** do.
|
||||
|
||||
- **It creates no fourth verdict.** The counts of §1.1 and
|
||||
[`schema/conformance-declaration.schema.json`](../schema/conformance-declaration.schema.json)
|
||||
are unchanged: a case whose expected findings are not produced still **fails**, and is still
|
||||
named in `failed_cases`. What changes is what the failure licenses concluding, not what is
|
||||
reported.
|
||||
- **It does not reach a third-party implementer** of the same table. Against them the fixture
|
||||
is the contract, exactly as §7 states — which is what these cases were minted to provide,
|
||||
and the only thing they can prove while one runtime is all there is.
|
||||
- **It is not a licence to self-declare.** The exemption is carried by the corpus's own
|
||||
provenance record for the scope. A runtime MUST NOT claim it for a case by asserting that
|
||||
its own divergence is calibration.
|
||||
|
||||
## 8. What conformance does and does not prove
|
||||
|
||||
Passing this corpus proves that a runtime agrees with the other runtimes that pass it, on
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue