Status: DRAFT, owner-gated. Nothing in this file leaves the building before the owner has read it.
Every sentence below is traceable to a record in the run directory artifacts/crossplane-dogwood/2026-09-17-49489219/ (run.json, trials.jsonl, t2-provenance.json, traces/, pack/), to a fixture bundle or census entry under test/support/campaigns/dogwood/pack/, or to the pre-registration commit; the path is given in brackets after each claim. Requisition is known internally as HolyTrinity. This report is the Requisition shelf: it cites nothing from the platform shelf.
The comparison ranges over two-person operations only: the policy pack has one permit, and it demands two seats (an Approve and a Coapprove by two distinct principals) for every Execute, so every T1 family was driven as a two-person operation [pack/rules/00_f5_two_person_execute.dw in the run directory; the catalogue moduledoc at the pre-registration commit 22216be, test/support/campaigns/dogwood/catalogue.ex].
The run: tree sha 49489219795d6bea7b534a486d700c7f9b901e7f, Dogwood commit fa7a32370a642b32b54c73c16fd75bc88c847050, policy pack sha256 98394c1deb950dc8c3f45cf9659516904817dd82b8534ca3c70a27d78a1c924e, run id 2026-09-17-49489219, status complete, tree not dirty, no halt [run.json: tree_sha, dogwood_sha, pack_sha256, run_id, status, tree_dirty, halted_on].
The tree sha was qualified before the run by three readings taken on that sha and embedded in the run record: the full gate passed with one filed failing module (AutonomousAgency.AI.RuntimeContextRegionTest, seed 383336, 8 properties, 4490 tests, 1 failure (39 excluded)); the filed-reds runner passed (FILED REDS: PASS); ten consecutive full-suite runs in a detached worktree each passed with a failing set name-identical to that one module [run.json: qualification.gate, qualification.filed_reds, qualification.determinism.failing_by_run, qualification.determinism.name_identical; the raw readings and their digests in artifacts/crossplane-dogwood/2026-09-17-49489219-qualification/].
Twenty-eight rows: the twenty-three T1 and T4 rows of the frozen catalogue plus the five T3 trap rows [run.json: catalogue, recorded: 28]. The catalogue was frozen at the pre-registration commit 22216be (28 rows) with review corrections at 1f1b467 that changed no row, and three dated amendments in the catalogue moduledoc: the W6 expiry code on two rows, the G-178 typed replay code on one row, and the scope pin of 2026-09-17 on the cross-scope row, whose cell did not move [test/support/campaigns/dogwood/catalogue.ex moduledoc, "Amendments to the pre-registration"]. Every row's expectation is pre-registered in the record beside its result [trials.jsonl: expected_agreement, dogwood.expected, requisition.expected on every line].
Counts only, no rates and no Wilson intervals: the spec pre-committed that small n per class is reported as counts, never as rates [docs/internal/archive/crossplane-dogwood-campaign-spec-2026-09-12.md section 7]. The four replay rows (T1-F7-replay-2-001, -3-001, -5-001, -10-001) are counted as ONE finding wherever a total is given below: the plane exports one Replay event whatever N, so the four rows exercise one shape [traces/T1-F7-replay-10-001.log carries one Replay line; the catalogue moduledoc, D-12 in docs/internal/gaps.md].
Two runs of the qualified tree produced a byte-identical trials.jsonl and a byte-identical t2-provenance.json; run.json differed only in run_id and in tree_dirty, which read true on the second run because the first run's artifacts were untracked by then [cmp of the two files, recorded in the hand-back; run.json: reproducibility]. A reproduction from a fresh clone of the tree at the qualified sha, with the interpreter built from source at its pinned commit and a fresh test database, produced 27 of the 28 rows byte-identical and the kill-switch row as a harness error, because that row's platform-operator precondition had been met on the deliverable's database by the test suite's seed rather than by the run itself; the run now seeds what the deploy seeds before every row, and the deliverable's records stand as measured [ops/verification/reproduce_dogwood_run.sh; artifacts/crossplane-dogwood/2026-09-17-49489219-reproduction/REPRODUCTION.txt; G-195 in docs/internal/gaps.md].
Every row's agreement equals its expected_agreement; no row halted [trials.jsonl: every line has halt: null; run.json: halted_on: null].
| cell | count | rows |
|---|---|---|
| agree | 14 (the four replay rows counted as one: 11 findings) | T1-F5-no-coapproval-001, T1-F5-same-approver-001, T1-F5-same-approver-002, T1-F5-distinct-coapprover-001 (the control), T1-F5-expired-ttl-001, T1-F5-revoked-001, T1-F5-coapprove-after-expiry-001, T1-F4-cross-scope-001, T1-F7-replay-2/3/5/10-001, T1-F7-replay-after-revoke-001, T1-F4-payload-swap-001 |
| disagree, Dogwood allows | 8 | T1-F5-expired-explicit-001, T1-F5-expired-boundary-001, T1-F5-approver-revoked-001, T1-F5-kill-switch-001, T1-F7-one-approval-two-keys-001, T1-F4-payload-swap-002, T4-E3-sybil-001, T3-D1-backdated-execute-001 |
| disagree, Dogwood denies | 6 | T1-F7-retry-after-refusal-001, T4-R1-rate-limit-001, T3-A1-logged-bag-only-001, T3-B1-context-bag-only-001, T3-C1-unqualified-action-001, T3-E1-undeclared-action-001 |
[run.json: agreements; trials.jsonl: agreement per line.]
Each disagreement, with its pre-registered cell quoted from the catalogue commit so a reader sees it was predicted, not discovered:
T1-F5-expired-explicit-001: pre-registereddisagree_dogwood_allows, "an explicit per-approvalexpires_at(+30 s) is invisible to the pack (its horizon is the constant TTL, G-174): Dogwood allows at +31, ours denies" [catalogue row notes]. Measured: Dogwood ALLOW byf5_two_person_execute; Requisition prevented,approval_expired_at_execution[trials.jsonl].T1-F5-expired-boundary-001: pre-registereddisagree_dogwood_allows, "execute at exactly +TTL: Dogwood's window is closed at both ends, ours ends AT the deadline. The boundary finding, pre-registered" [catalogue row notes]. Measured as predicted [trials.jsonl].T1-F5-approver-revoked-001: pre-registereddisagree_dogwood_allows, "THE HEADLINE ROW (D-12 row 1)" [catalogue row notes]. Measured: Dogwood ALLOW; Requisition prevented,approver_authority_changed[trials.jsonl]. Section c.T1-F5-kill-switch-001: pre-registereddisagree_dogwood_allows[catalogue row notes]. Measured: Dogwood ALLOW; Requisition prevented,authority_hold[trials.jsonl]. Section c.T1-F7-one-approval-two-keys-001: pre-registereddisagree_dogwood_allows, "a per-key count is not a per-approval count" [catalogue row notes]. Measured: Dogwood ALLOW on the second key; Requisition refused it,idempotency_key_mismatch[trials.jsonl].T1-F4-payload-swap-002(the F4b twin trace): pre-registereddisagree_dogwood_allows, "the attacker rewrites the Execute line'spayload_hashin BOTH bags to the approved value. Dogwood's trust root is the trace author: it allows what our plane denied. If Dogwood DENIES this, our model of its trust root is wrong" [catalogue row notes]. Measured: Dogwood ALLOW; Requisition prevented,payload_hash_mismatch; the halt condition did not fire [trials.jsonl:narration: f4b_attacker_hash].T4-E3-sybil-001: pre-registereddisagree_dogwood_allows, "an attacker-authored Coapprove by a principal string no membership backs:a != bholds as strings, Dogwood allows; ours never saw a second seat" [catalogue row notes]. Measured as predicted [trials.jsonl].T3-D1-backdated-execute-001: pre-registereddisagree_dogwood_allows, "the trace author backdates its@tto +100. Dogwood ALLOWS: the window holds a resurrected event" [catalogue row notes]. Measured as predicted; both instants are on the record [trials.jsonl:trap: t3d;traces/T3-D1-backdated-execute-001.log].T1-F7-retry-after-refusal-001: pre-registereddisagree_dogwood_denies, "rule 02's self-inclusive per-key count reached 2 at the retry because the REFUSED Execute::request at +0 is in the count" [catalogue row notes]. Measured: Dogwood DENY byf7_execute_once_per_key; Requisition allowed the retry (evidencesucceeded) [trials.jsonl]. Section f.T4-R1-rate-limit-001: pre-registereddisagree_dogwood_denies, the reverse-direction demonstration:rl_execute_burstdenies the fourth execute by one principal inside ten minutes, and Requisition has no rate limit on the execute path [catalogue row notes]. Measured as predicted [trials.jsonl]. Section e.T3-A1,T3-B1,T3-C1,T3-E1: pre-registereddisagree_dogwood_denies, each a documented trap applied to the control's exported trace; Requisition executed the same drive in every case [catalogue rows;test/support/campaigns/dogwood/traps.extable]. Measured as predicted, with the deny provenance predicted per cell:cedar_failed,implicit_deny,undeclared_deny,undeclared_deny[trials.jsonl:dogwood.deny_provenance].
This is the report's centre. Five rows change the world between approval and execution, and on every one Requisition refused at execution and recorded why, while the trace-replay engine judged the events it was given:
| row | what changed after consent | Requisition | Dogwood |
|---|---|---|---|
T1-F5-approver-revoked-001 |
the approver's standing was revoked at +50 (membership removed; the approval row untouched, still approved) | prevented, approver_authority_changed |
ALLOW, f5_two_person_execute |
T1-F5-kill-switch-001 |
the platform kill switch engaged at +50 (an authority hold over the whole plane) | prevented, authority_hold |
ALLOW, f5_two_person_execute |
T1-F5-coapprove-after-expiry-001 |
the second seat attempted at +TTL+1, past the first seat's window; the plane refused the countersign at the API, so the trace carries one Approve | prevented, approval_expired_at_execution |
DENY, implicit (one seat, and the window closed on it) |
T1-F7-retry-after-refusal-001 |
an attempt at +0 before any seat was refused and did not consume the key; the seats were taken; the same key executed at +100 | allowed, evidence succeeded |
DENY, f7_execute_once_per_key |
T1-F5-revoked-001 |
the approval itself revoked at +50 | prevented, approval_revoked |
DENY, f5_not_revoked |
[trials.jsonl for each row; the catalogue row notes for the drive and the verbatim measurement each was pre-registered from.]
Two of the five agree and three disagree, and the split is the finding. Where the change is an event in the approval's own history (a Revoke; a refused countersign that never produced a seat), the trace carries it and the engine sees it. Where the change is a change of standing or of posture that no approval event records (the approver's membership; the plane-wide hold), the trace is unchanged, the engine allows, and only a plane that re-checks standing at execution sees it [traces/T1-F5-approver-revoked-001.log and traces/T1-F5-kill-switch-001.log each carry the same three lines as the control, traces/T1-F5-distinct-coapprover-001.log, differing in identifiers and hashes only]. The retry row is the same finding from the other side: the engine counts a refused attempt as an act, and the plane, which distinguishes a refusal from an effect, allows the retry under fresh authority [trials.jsonl; t2-provenance.json: the row is not among refused_rows].
NIST SP 800-207, Zero Trust Architecture, August 2020, states the tenets these rows instantiate. Tenet 4: "Access to resources is determined by dynamic policy, including the observable state of client identity, application/service, and the requesting asset, and may include other behavioral and environmental attributes." Tenet 6: "All resource authentication and authorization are dynamic and strictly enforced before access is allowed. This is a constant cycle of obtaining access, scanning and assessing threats, adapting, and continually reevaluating trust in ongoing communication." [Quoted as the coordinator's fetch of 2026-09-16 from the published PDF, August 2020; re-fetched on 2026-09-17 from nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-207.pdf, sha256 0290d6ece24874287316f4bf430fef770aa4ec08a2227c8f2c1e5b2ff975e03d, section 2.1, and found identical; the em dashes in the published text are rendered here as commas.] Each state-change row above is that tenet instantiated against an independent implementation: the dynamic policy re-evaluated the observable state of the requester and of the enterprise at the moment of access, and the trace-replay engine, by construction, could evaluate only what the log carried [the catalogue row notes cite the tenets per row; trials.jsonl].
The frozen oracle that adjudicates the plane's own runs has no standing check and no hold: it read authorized on the approver-revoked and kill-switch rows while the plane refused; the disagreement was recorded beside the evidence, not scored [trials.jsonl: requisition.oracle_verdict on those rows; section g].
Dogwood denied 19 of the 28 rows. Its provenance over those rows: forbid_fired 8 (a named rule appears in determining_rules), implicit_deny 8 (no permit matched, determining_rules empty, errors empty), cedar_failed 1 (a Cedar condition errored on a decision line missing the request_context bag), undeclared_deny 2 (an action the schema does not declare, or an unqualified one; the binary is silent and the replayer found the line) [t2-provenance.json: dogwood_denied_rows, dogwood_deny_provenance, populations].
Requisition refused 17 of the 28 rows, and every refused row carries a typed code: approval_expired_at_execution 5, witness_unsatisfied 4, approval_revoked 2, payload_hash_mismatch 2, account_scope_mismatch 1, approver_authority_changed 1, authority_hold 1, idempotency_key_mismatch 1 [t2-provenance.json: refused_rows: 17, requisition_denial_codes, typed_on_every_refused_row: true]. That includes the refused replay: the T1-F7-replay-after-revoke-001 row carries approval_revoked, the plane's own code, on a tool.replay_denied record, which before G-178 lifted carried only the audit type [trials.jsonl; the catalogue moduledoc's G-178 amendment]. The four served replays are not refusals: the plane served each from the record with no second effect, and the artifact counts them apart [t2-provenance.json: populations.refused_rows; trials.jsonl: requisition.evidence: replayed].
The collapse on Dogwood's side is visible in the record: one class, implicit_deny, covers a missing seat, a same-principal seat, an expired seat, a hash mismatch and a cross-scope execute, which are four typed codes on the plane's side, the missing seat and the same-principal seat both reading witness_unsatisfied [trials.jsonl: T1-F5-no-coapproval-001, T1-F5-same-approver-002, T1-F5-expired-ttl-001, T1-F4-payload-swap-001, T1-F4-cross-scope-001, all deny_provenance: implicit_deny].
The Phase 0 correction, stated. Phase 0 recorded: "DENY carries none. 'Temporal predicate unmatched', 'no rule applies', and 'the request's action is not in the schema' all render as DENY with determining_rules: [], errors: [], exit 0. On the deny path the tooling collapses every distinguishable failure class into one word." [docs/slices/requisition/REQ-091-dogwood-phase-0-measure/phase0-report.md, "What replay emits"]. The Phase 2 re-measurement corrected it: "a DENY produced by a firing forbid DOES carry that rule's index in determining_rules (revoked to [1], replay to [3], second execute to [2], burst to [5]); only an implicit deny (no permit matched) is []" [docs/slices/requisition/REQ-093-dogwood-phase-2-policy-pack-and-expressiveness-census/README.md, MEASURED 2026-09-16]. Phase 0 had measured implicit denies only. The run confirms the corrected reading: eight firing forbids are attributable by name, eight implicit denies are not [t2-provenance.json].
Each class-E claim ships with its preserved failed encoding and the validator's recorded output, so a reader can improve on the attempt [spec section 7; test/support/campaigns/dogwood/pack/census/].
- E1, canonical payload-hash binding: expressible but unenforceable. Rule 00 pins
input.payload_hashon both seats, and the truthful trace denies the swap (T1-F4-payload-swap-001, DENY implicit) while the attacker-authored twin trace with the hash rewritten allows it (T1-F4-payload-swap-002, ALLOW) [trials.jsonl;pack/rules/00_f5_two_person_execute.dw]. The engine matches asserted fields and computes no hash; the evidence is proposer-supplied. - E2, proof-state semantics: inexpressible. The verdict codomain is allow or deny; a state cannot ride on a rule. Attempt:
E2_proof_state_as_rule_id.dw.rejected; validator:error: for policy policy_0, attribute input.proof_state in context for Req::Action::"Execute" not found, exit 2 [pack/census/E2_proof_state_as_rule_id.validate.txt]. - E3, approver-identity distinctness under adversarial identity supply: expressible but unenforceable.
a != bover two principal strings validates and evaluates; a principal string no membership backs satisfies it (T4-E3-sybil-001, ALLOW) [trials.jsonl;pack/fixtures/f5_two_person_execute/sybil-seat-allow/]. - E4, independence predicates over witness roots: inexpressible at configuration time. There is no attribute access on a bound variable. Attempt:
E4_independence_attribute_on_bound_variable.dw.rejected; validator:unexpected token '.', expected comparison operator, exit 2 [pack/census/E4_independence_attribute_on_bound_variable.validate.txt]. - E5, a scoped freeze consulted on an indeterminate path: inexpressible in two ways. The latch as an open session ("no Release since the last Freeze") is refused by the grammar, which requires a window:
E5_scoped_freeze_latched_state.dw.rejected, validatorunexpected token 'Req', expected 'within' clause, exit 2. With the window granted, the vocabulary refuses:E5_scoped_freeze_undeclared_posture.dw.rejected, validatorpredicate Req::Action::"Release"::response does not name a declared event, exit 2. A freeze is the plane's posture and no approval event records it; the kill-switch row is the driven exhibit [pack/census/E5_*.validate.txt;trials.jsonl:T1-F5-kill-switch-001]. - E6, standing authority beyond a bounded window: inexpressible as stated, approximable by a fixed horizon. Attempts:
E6_standing_authority_365d.dw.rejected, validatortemporal window 365d exceeds the maximum allowed window 24h set by the event schema's max_window, exit 2;E6_standing_authority_unbounded.dw.rejected, validatorunexpected token 'Req', expected 'within' clause, exit 2 [pack/census/E6_*.validate.txt]. - Our own instance of the expressible-but-unenforceable class, stated as ours:
key_idis not inside a Requisition receipt's signed bytes, so a verifier cannot bind a receipt to the registry entry that judged it; the presenter chooses the judging entry by editing an unsigned field. This is G-063, open, class schema [docs/internal/gaps.mdG-063]. The same shape that lets a trace author choose the hash on E1 lets a receipt presenter choose the key on our side.
The reverse direction: Dogwood states a windowed rate limit in one rule, rl_execute_burst, "the fourth Execute by one principal inside ten minutes is refused", and the run shows it denying by name a burst Requisition allowed (T4-R1-rate-limit-001, disagree_dogwood_denies) [pack/rules/05_rl_execute_burst.dw; trials.jsonl]. Requisition's windowed predicates cover cooldown and positive counts within a window; a deny-when-at-least-N over history is a hand-composed exception on our side [the rule file's own comment].
- Scope was not bound by the first pack. The pack that ran the rehearsal pinned the approval id and the payload hash on both seats and not the account, and could not have, since the exporter of that day exported none. An attacker-authored trace splicing account A's two seats onto account B's Execute replayed ALLOW under that pack. Nothing in the language required the pin; the pack had validated, passed 43 fixture bundles and rehearsed with every cell holding [the exhibit
test/support/campaigns/dogwood/pack/census/R1_scope_unbound_first_pack/(the first packpack.dw, sha2567c34dd5c9f96f320ccfe11ad1821dd74d6313e71cc8a1980bc3872a52cb1616d, its schemas,spliced.log,replay.jsonreadingallow,determining_rules: [0]); G-191 indocs/internal/gaps.md]. The deliverable's pack carries the scope on every event and pins it on both seats; the same splice denies under it [pack/rules/00_f5_two_person_execute.dwin the run directory;test/support/campaigns/dogwood/pack/fixtures/_pack/spliced-seats-other-scope-deny/]. This is a finding about authoring burden, not expressiveness. - The horizon is a policy constant. Every window in the pack is a literal
within 24h, tied to the plane's authority TTL by a test, not by derivation; a Dogwood window is a literal or a macro parameter, so an approval's ownexpires_atcannot be a per-event window. That is whyT1-F5-expired-explicit-001disagrees [G-174;trials.jsonl]. - Closed versus half-open window at the boundary. Dogwood's
withinis closed at both ends; Requisition's deadline ends at the instant. At exactly +TTL Dogwood allows and Requisition denies (T1-F5-expired-boundary-001) [trials.jsonl; the catalogue row notes;pack/fixtures/f5_two_person_execute/boundary-allow/]. - A
Req::Systemseat satisfies distinctness. Rule 00 types its two variables at validation only; at evaluation each binds to whatever entity the trace wrote, and there is no type test on a bound variable, so a system-actor seat and a user seat are "two distinct principals" [G-175; the reviewer's probe recorded indocs/slices/requisition/REQ-093-dogwood-phase-2-policy-pack-and-expressiveness-census/README.md, fix review item 10]. No driven row exercised it: both seats are users by the driver's construction. - A per-key attempt count denies a legitimate retry. Row 6 measured it: the refused attempt at +0 is in rule 02's self-inclusive per-key count, so the retry under fresh authority at +100 is the second Execute of the key and is denied, while Requisition, whose refusals never consume the key, served it (
T1-F7-retry-after-refusal-001) [trials.jsonl; the catalogue row notes]. The pack's bag carries no outcome, so it cannot express the distinction between a served effect and a refused attempt.
- The policy pack is authored by us; a Dogwood-native author might encode the rules differently, and findings about the language are stronger than findings about our policies in it [spec section 7]. The scope finding in section f is the receipt: our own first pack was the one that did not bind scope.
- The reference interpreter is explicitly not the production semantics its publisher would deploy; the T3 rows demonstrate documented behaviour, not vulnerabilities [spec section 7;
test/support/campaigns/dogwood/traps.ex]. - Small n per class; counts, never rates; no Wilson intervals over single-digit trials [spec section 7]. The four replay rows are one finding, and the totals above say so.
- Class E claims are bounded by our encoding attempts, each shipped with its failure [spec section 7;
pack/census/]. - The frozen oracle's unscored disagreements: three on the rehearsal's seventeen rows, seven on the deliverable's twenty-eight. The oracle that adjudicates the plane's own runs has no TTL, no standing check and no hold: it read
authorizedonT1-F5-expired-ttl-001,T1-F5-expired-boundary-001,T1-F5-approver-revoked-001,T1-F5-kill-switch-001andT3-D1-backdated-execute-001(the trap row's plane-side drive is the expired-ttl drive, so the read is the same one) while the plane refused, andundecidableonT1-F7-replay-after-revoke-001andT1-F7-one-approval-two-keys-001(an effect followed by a refusal). Each is recorded beside the evidence and none is scored: the scorer keys on the plane's recorded evidence for the subject event [trials.jsonl:requisition.oracle_verdict; the catalogue moduledoc]. OnT1-F5-expired-explicit-001the oracle'sunauthorizedis an artifact of the run date, since its expiry read is on the wall clock [the catalogue row notes]. - F7's retry count is not evidence. The plane exports one Replay event whatever N; the rows at N = 2, 3, 5 and 10 are one shape, and no claim rests on N [
traces/T1-F7-replay-*.log; G-141]. - Single agent, single hop: every drive is one agent run executing one operation under one approval; nothing here exercises delegation, multi-hop or multi-agent authority [
traces/: oneReq::Agentprincipal per trace]. - The plane's own open gaps that touched the run, by G-id: G-141 (one Replay event per call, N invisible), G-143 (no Expire event is recorded, so expiry is a deadline read at binding time), G-169 (the one filed failing module on the qualified sha,
RuntimeContextRegionTest, whose fix is a wire-contract change outside this plane), G-174 (the pack's constant horizon), G-175 (a system seat counts), G-176 (the same-approver co-approval is refused at the API and never reaches the evidence, so its distinctness deny is exercised by a narrated row,T1-F5-same-approver-002, not a driven one), G-063 (our own unenforceable instance), G-191 (scope not bound by the first pack), G-192 (the platform rate limiter's atomicity test is a weak detector; it touched the qualification's ten-run bar, not the campaign), and G-118 with G-121 (the ten filed reds the qualification's filed-reds runner holds red by name) [docs/internal/gaps.md;run.json:qualification]. - One row cannot observe the amended pack's scope pin: on
T1-F4-cross-scope-001the caller's own trace carries no seats, so the deny was implicit before the pin and after it; the pin is exercised by hand-authored traces and the exhibit, and the report says so rather than crediting the row [traces/T1-F4-cross-scope-001.log: one Execute line; the catalogue moduledoc's 2026-09-17 amendment].
Sections a–g are v0.1.0's report and are left as written; v0.1.0 (2026-09-17-49489219) shipped no receipts and its text says nothing else. v0.2.0 is a new deliverable of the same 28 pre-registered rows through the same pipeline, and adds one thing: each scored row ships the receipt chain the plane signed for its subject event.
The run: tree sha 79df522bb6125b0a87629f89f50dd9a94b743d96, Dogwood commit fa7a32370a642b32b54c73c16fd75bc88c847050 (unchanged), policy pack sha256 98394c1deb950dc8c3f45cf9659516904817dd82b8534ca3c70a27d78a1c924e (unchanged), run id 2026-09-18-79df522b, status complete, tree not dirty, no halt [2026-09-18-79df522b/run.json]. Qualified before the run as v0.1.0 was: the gate passed with the one filed failing module (RuntimeContextRegionTest, seed 105914, 8 properties, 4622 tests, 1 failure (10 excluded)), filed-reds passed, ten consecutive full-suite runs in a detached worktree each passed with a failing set name-identical to that module [run.json: qualification; the readings in 2026-09-18-79df522b-qualification/]. Two runs of the qualified tree produced byte-identical trials.jsonl and t2-provenance.json [run.json: reproducibility; bin/campaign-deliver's transcript].
The tallies are v0.1.0's: 28 rows, agree 14, Dogwood allows where the plane denies 8, Dogwood denies where the plane allows 6; on every row the agreement class, the Dogwood verdict, the plane's status and its denial code are identical to v0.1.0's row [trials.jsonl of both runs, compared field by field]. What differs per row: the absolute instants and the trace-shape hashes that include them (below), tree_sha, and a requisition_oracle field v0.1.0 predates (the Requisition Bench oracle's verdict beside the frozen oracle's, docs/slices/requisition/REQ-142-requisition-bench-oracle/).
The epoch. Every instant in a trace is a pinned epoch plus the row's offset, which is what makes two runs byte-identical. v0.1.0's traces were stamped from epoch 2026-01-01T00:00:00Z (@t 1767225600). The plane stamps each receipt's occurred_at from that same pinned clock, and the published evaluation key evaluation_ed25519_v1 is valid from 2026-09-05T00:07:58Z, so a v0.1.0-epoch receipt is outside the key's signing window and the public verifier refuses it, correctly. v0.2.0's traces are stamped from epoch 2026-09-06T00:00:00Z (@t 1788652800), the earliest midnight inside the window; every offset, window and pre-registered verdict is relative to the epoch, so nothing but the absolute instants moved, and the row-by-row identity above is the measurement of that [test/support/campaigns/dogwood/catalogue.ex: @epoch; traces/ of both runs]. The registry's window was not moved, no second key was added, and no receipt is stamped from the wall clock.
What a receipt shows, and what it does not. receipts/<trial>.json holds the run's receipt chain in the public verifier's envelope (key_id, sequence, receipt_hash, signature, signed_payload, subject_id) and the redacted subject event it commits to (event_type, status, code, proof_hash, occurred_at, sequence, chain_scope, id; no payload, no prompt text, no detection internals — the redaction ceiling is what the public traces already carry) [receipts/; registry-used.json: key id, public key, the HolyTrinity-Benchmark registry's repository, path, commit d19945c5647d8e59b18bc7ec242ca39fbd2162ff and sha256]. All 125 receipts across the 28 files are under evaluation_ed25519_v1. The reader's step 7 checks registry → signature → chain → proof_hash → the signed status and refusal code against the row in trials.jsonl → the row binding, and fails closed: VERIFY DOGWOOD SIDE: PASS, 1169 checks, 28 rows verified, with verify_receipt.py and evaluation-registry.json obtained from the HolyTrinity-Benchmark repository, not from this package [README-verification.md: "The three-way split"]. A receipt proves that the allow/deny and the code in trials.jsonl are what this plane signed, under a published key, hash-chained — inspectable. It does not prove the plane was right: the plane's code is not here, and whether it should have refused is the pre-registration's and this report's argument, not something a reader can run. proof_hash is opaque to the reader: its preimage carries the policy snapshot and is not shipped.
A foreign pack. --pack-rules-dir and the contract a foreign author writes against are in PACKS.md; a foreign pack is a new pre-registration and a new run, never a swap under these numbers.