* docs(design): #742 research-family profile contract + preregistered usability protocol design freeze
Freezes the research-workflow-profile/1.0 field set, the shared stage/task-family
vocabulary co-consumed by the #745 matrix, the field_general fallback semantics,
selection/correction receipts, the branch-budget carrier for #743/#744, and the
preregistered usability guardrails (all evidence NOT_RUN). No schema, validator,
runtime consumer, or default change ships with this freeze.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BPU2Hg2WufTjMVyBoje753
* docs(design): #742 review round 1 — deterministic shapes, provenance digests, budget counting semantics, executable-protocol gates
Closes the 9 P1 + 3 P2 codex findings: frozen stage_id mapping beside the
task-family grain; deterministic field shapes for stage_map / alternative_categories
(declared-vs-unresolved split) / overlays / authority_points; content_sha256 +
freshness_state provenance with receipt binding; fallback kernel-primitives
clarification; live-branch counting semantics reconciled with the fallback
rationale; user-confirmed-or-visible-fallback wording; correction marks
dependent artifacts stale with authority re-check; operational definitions,
per-task prompt ceiling, simple-task isolation outcome, complete default-on
decision rule, and a frozen pre-recruitment amendment gate for the deferred
statistical items; v1 family-enum restriction documented; data-boundary
paragraph added.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BPU2Hg2WufTjMVyBoje753
* docs(design): #742 review round 2 — arm-B recovery criterion, field_general authority semantics, canonical-storage digest, matrix-hook coordination
Closes the round-2 findings: wrong-profile recovery is arm-B-only against a
§8-A-frozen absolute criterion; decision-usefulness instrument/margin,
session timeout, simple_path card set, and safety/authority-regression rubric
join the mandatory §8-A amendment items; consequential decision, simple-path
task card, and safety/authority regression are operationally defined; every
field_general profile (shipped or user_authored) inherits empty-means-ask
authority semantics; published profiles are stored in canonical form so the
digest binds exact bytes; §2/§9 align with the shipped stage-capability-matrix
row shape (checkpoint grain in row text, single task family per row).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BPU2Hg2WufTjMVyBoje753
* docs(design): #742 review round 3 — content_sha256 is a canonical-content digest with a fixed recompute procedure, not a raw-file digest
Closes the last open P2: the placeholder-zeroed canonical digest cannot equal
the stored file's raw bytes (the file carries the finalized hash), so the
contract now names the verification procedure — reject non-canonical storage,
zero the field, recompute, compare against both the embedded value and the
receipt — and the receipt wording binds canonical content, not raw bytes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BPU2Hg2WufTjMVyBoje753
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(probe): pipeline wiring for #655 PR-C — trigger, consent surface, freshness, transmission ledger
- claim_verification_protocol.md gains the Claim-Standing Probe Offer section:
user-requested advisory view after the Phase E Claim Registry at Stage
2.5/4.5; HIGH-IMPACT-only trigger; ambiguity ineligible until researcher
confirmation; never part of the integrity result (gate 12 boundary).
- scripts/build_claim_standing_query_plan.py: §3.1 eligibility (gate 1) +
§3.2 propose/bind consent surface (gate 2); emits schema-valid query-plan
1.0/1.1 or an explicit not_checked declination on cancel.
- scripts/check_claim_standing_freshness.py: §7 probe-identity drift ->
stale with closed reasons (gate 13); corrupt digests are errors.
- shared/contracts/claim_standing/transmission_ledger.schema.json +
scripts/check_claim_standing_transmissions.py: closed §6 per-event
accounting; consented allowlist/roster fail-closed (gate 14).
- 82 new tests across four files; CI manifest + integration-guard markers,
protocol doc, contracts README, CHANGELOG aligned.
Zero-spend: no live index, model, or network call anywhere; every probe
surface still says STANCE CLASSIFICATION UNMEASURED. #655 stays open.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeJS63dMYTADV8FPR4Mx1m
* fix(probe): PR-C review round 2 — consent binds full projection, honest declinations, freshness coverage, transmission completeness
Applies the converged three-track findings (codex 5 P1 + 2 P2, security
2 P2 + 6 P3, simplify/reuse/altitude):
- Gate 1: Stage 2.5 HIGH-IMPACT tier alone is the registry witness; E1 now
records the five-part high_impact_basis; basis provenance recorded on the
consent surface, never in the registry.
- Gate 2: consent surface embeds the complete consentable-plan projection
(surface hash covers every receipt-bound field; bind asserts digest
equality); absence/invalidation/cancel each produce an explicit local
not_checked declination (consent_absent/consent_invalidated/
consent_cancelled); bind --output is consent-gated to the derived
.query-plan.json path.
- Gate 13: freshness consumes the runner's single expected_identity
authority, requires the record's ledger, compares consented
provider/model, and declares assessed/unassessed bindings.
- Gate 14: schema + self-digest validation of both inputs, duplicate
attempt and off-target index refusal, explicit stance-transmission
requirement, stance-record cross-check, event-kind fixed field-by-field,
conservative-accounting semantics documented; uniqueItems on events.
- Gate 12: attribute-level containment of the discovery module, no direct
write calls, CLI paths included in the no-file-creation run; doc pins
consolidated into the #655 integration guard (incl. Phase E surface and
a forbidden-stale-sentence check).
- Substrate: validator memoization, shared export-consent helpers
(trailing-separator refusal), exported trigger constants pinned to the
plan schema; falsey decisions refused, deep copies via copy.deepcopy.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeJS63dMYTADV8FPR4Mx1m
* fix(probe): PR-C review round 3 — intake invariants in gate 14, cancel-flow fidelity, complete artifact roster
codex R2 (1 P1 + 4 P2 + 1 P3) and security R2 (6 P3) convergence:
- Gate 14: adopt substrate.validate_input so a re-sealed retrieval input
omitting a planned attempt is refused; stance-record cross-check now
schema-validates + digest-replays the record and compares per-row prompt
hash and result state (closed row->event mapping).
- Gate 2: an explicit cancel records consent_cancelled even after a
retrieval_plus_stance surface was proposed (checked before the surface
hash comparison); falsey filter lists refused at proposal; bind CLI
exits 3 on declinations.
- Consent surface: complete consented-artifact roster from new
substrate.ARTIFACT_SUFFIXES (test-pinned to every owning module's suffix
constant); trailing-separator authorized paths refused at proposal, in
validate_plan, and via the shared helper now used by discovery and the
renderer too.
- Freshness: fail-closed parity guard between the runner's
expected_identity and the stale-reason map; eligibility verdict gains a
dispatchable flag distinct from the tier witness.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeJS63dMYTADV8FPR4Mx1m
* fix(probe): PR-C review round 4 — failed stance calls bind their prompt hash
codex R3's remaining P2: a judge_timeout / judge_error / oversized-output
row left prompt_sha256 null, so the gate-14 cross-check could not hold a
tampered failure event to the hash actually sent. The runner now binds
prompt_sha256 + assessment_input_sha256 into the row BEFORE the transport
call; validate_stance_record replays those hashes on transport-reaching
failure rows (and requires them null on undispatched abstract_missing
rows); the transmission cross-check requires a non-null, exactly-matching
prompt hash for every transport-reaching row.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeJS63dMYTADV8FPR4Mx1m
* test(probe): close the remaining capability-scan evasion forms
Dotted from-imports of discovery symbols, discovery-alias rebinding, and
getattr() dynamic lookup now fail the gate-12 wiring scan (security R2
P3-6 residue).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeJS63dMYTADV8FPR4Mx1m
* chore: ignore the maintainer-local deliverables/ directory
Local working documents are not part of the public project; keep the
directory permanently out of version control on every checkout.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeJS63dMYTADV8FPR4Mx1m
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Promote all release-worthy changes since v3.20.0, align suite and component versions, refresh all five release summaries, and close merge-provenance coverage for v3.20.1.
[doc-aligned: 2026-08-15]
* feat(probe): stance runner and presentation renderer for #655 Track B
The stance runner consumes a finalized ledger under a
retrieval_plus_stance consent: transport identity and prompt-contract
version are consent-bound, the judge grammar is closed four-line output
with a verbatim-substring 25-word evidence quotation sealed as a
verified_exact_match evidence row, deviations become
not_checked/parse_error with raw output retained, and transport failures
map to judge_timeout/judge_error. validate_stance_record is the
contract-named semantic verifier (identity hashes, distribution sum,
exact selected-family coverage, per-evidence-row hash replay); its CLI
refuses until a live provider adapter ships with its own consent
surface. The renderer produces the three-part §5.3 view with §5.4
bounded vocabulary, fixed empty wording, all-selected denominator with
performed-only marked secondary, inert escaping, a leading UNMEASURED
banner, and stale-record refusal. Package-first imports unify exception
identity across the claim-standing tools. 17 new tests; sweep 198.
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(probe): harden #655 stance runner/renderer per dual-track review R1
- validate_stance_record now rechecks stance consent, binds
stance_runtime to the consented stance_plan, and deep-replays every
referenced evidence row against the exact ledger (claim/candidate/
ledger bindings, coverage, sealed source hash, byte-span excerpt);
cross-candidate reuse and orphan rows are rejected
- judge grammar is exactly four labeled lines in order; schema bounds
(rationale/conditions/excerpt/raw-output ceilings) enforced at parse
so a verbose or unspaced-script judge degrades one row, never the run;
non-string returns are judge_error
- every transport call records a §6 transmission event returned beside
the record; evidence sharing_scope never inherits persistence
authority (fixes a schema failure under authorized-export plans)
- renderer: _inert flattens line breaks and escapes Markdown link/image
syntax (a hostile title can no longer forge bounded sentences or emit
a tracking beacon); per-source rows carry the §5.3 fields in the §5.4
sentence form; consented stance provider and retention disclosure
surfaced; ledger self-binding checked on the no-record path; view
persistence gated on explicit_local_export with a hash-bound derived
path and exclusive no-follow 0600 fsynced write
- 28 tests across runner/renderer; family sweep 205 green
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(probe): #655 stance runner/renderer R2 — output replay, control chars, versions
- validate_stance_record replays every performed row from its retained
raw output (a resealed stance/rationale/conditions the judge never
produced fails) and replays spans for both positive excerpt states
- judge grammar rejects blank lines anywhere in the four-line output
- _inert strips C0/C1 and bidi control characters (terminal escapes and
RLO tricks cannot reach stdout); per-source rows list the family's
other versions with their original provider ranks; the view exporter
fsyncs the parent directory
- 32 tests across runner/renderer; family sweep 209 green
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(probe): #655 stance runner/renderer R3 — downgrade forgery, family binding, span bounds
- a parse_error row whose retained output parses cleanly is rejected as
a downgrade forgery; stance rows bind to the ledger family's canonical
hit and coverage; span replay enforces bounds and source byte length
- four-line grammar rejects edge blank lines; empty CONDITIONS degrades
the row instead of aborting the run
- _inert strips every Cc/Cf character (tab flattened to space)
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(probe): #655 stance validator R4 — complete the hash-replay surface
Ledger content hash replays from the inspected bytes; every retained
raw output replays its digest on every row state; performed rows replay
prompt_sha256 from the frozen template and assessment_input_sha256 from
its canonical projection. Every hash inside a stance record is now
recomputed, none trusted.
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(probe): #655 stance validator R5 — close the downgrade family
Any not_checked row whose retained output parses cleanly is rejected
regardless of its declared failure state, and abstract_missing must
agree with the ledger family's content state.
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(probe): #655 stance validator R6 — bidirectional failure/content binding
Content-unavailable ledger families accept only abstract_missing as
their row failure (they are never dispatched), completing the
equivalence both ways.
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* chore: retrigger CI for updated PR body ([skip-closes-check] bypass)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(probe): stance-side contracts for #655 (query-plan 1.1, stance record, evidence-row 1.3)
Three closed contracts precede any stance execution: query-plan 1.1
makes consent stance-authorizable (hash-bound stance_plan naming the
exact provider/model, extended content classes, fail-closed bindings;
1.0 semantics byte-unchanged and both versions accepted end-to-end);
evidence-row 1.3 is the #656-owned claim_standing_advisory surface
reusing the family's excerpt/cache/content-handling blocks verbatim,
provenance-only; stance-record 1.0 freezes the future runner's output
with full probe-identity hashes, closed per-family vocabulary, the
all-selected distribution, a mandatory UNMEASURED banner, and no scalar
score property anywhere. 21 tests; no runner/model/measurement exists.
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(probe): harden #655 stance contracts per dual-track review R1
- integration guard's _replace no longer leaves later marker
occurrences behind (the second UNMEASURED literal broke the guard)
- query-plan 1.1 schema binds decision to authorized_content_classes and
stance_plan presence at the schema layer, matching the runtime
- evidence-row 1.3 carries the family's cross-field invariants (rights
coupling, retrieved-vs-null payload, metadata-only coverage), drops
the two anchor-derived states the surface cannot express, and couples
contains_external_text to the excerpt state
- stance rows bind evidence rows by id AND row hash; runtime-verified
wording corrected to name the future verifier honestly
- protocol/evidence-row family docs updated (v1.3 section, stale
exclusion list); rehash helper shared between test files
- 22 stance-contract tests; family sweep 179 green
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(probe): schema-couple stance_plan retention state and reference
known requires a string reference, unknown requires null, at the schema
layer as well as the runtime; mutation-tested both directions.
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(probe): live discovery adapters for #655 Track A
Four closed discovery adapters (Semantic Scholar, OpenAlex, Crossref,
arXiv) turn a consent-bound query plan into a schema-valid retrieval
input: single-page requests up to the frozen caps, adapter-boundary
truncation with exact counts, closed failure vocabulary with one
transport call per attempt and no retry, honest unknown-retention
provider blocks, and an arXiv year filter refused before any network
call. The retrieve CLI refuses persistence under session_only consent
and writes exclusively. relevance_assessments stays empty by design
(caller-supplied per the #719 contracts; the assessor is a later
consented slice). Resolver clients untouched and never imported.
16 offline fake-transport tests; no live index called.
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(probe): harden #655 discovery per simplify+security review R1
- output path is now bound to consent: retrieve writes only to the
hash-bound authorized_output_path plus a fixed .retrieval-input.json
suffix, through the substrate's no-follow fsynced exclusive writer
- live transport refuses provider redirects (an off-roster Location
cannot receive the consented query) and maps DNS/connection/TLS
failures to service_unavailable
- untrusted provider records that raise AttributeError/IndexError now
land in malformed_response instead of escaping the closed vocabulary
- structure: shared provider-block builder, _run_attempt extraction,
spread-based raw-hit assembly, _year_filter helper, stderr errors,
dead code removed, sys.path bridge + standard test imports
- CHANGELOG: resolve conflict markers that PR #729's squash carried
onto main (three Unreleased entries under one heading)
- 22 offline tests
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(probe): #655 discovery R2 — roster binding, attempt isolation, exact abstracts
Per cross-model review: consented provider blocks must equal the
executing adapter's declared block; provider-contract violations
(overlong fields, bad types, underreported counts) poison only their own
attempt as malformed_response; plain 4xx maps to unsupported_query;
provider bodies are bounded at 8 MiB; quote-bearing arXiv phrase queries
are refused before transport; abstract text is retained exactly as
returned. The OpenAlex per-page parameter was challenged and verified
correct against the live API (meta.per_page honored) — retained.
28 offline tests.
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(probe): #655 discovery R3 — status mapping, typed counts, NFKC row checks
Provider publication types map conservatively onto the closed status
vocabulary (OpenAlex preprint/article, S2 JournalArticle; unmapped stays
unknown) so a preprint can no longer outrank its published version in
canonical selection. Untyped provider counts and undigestible values
become that attempt's malformed_response inside the attempt boundary,
and per-row checks now include the substrate's NFKC semantic-text
invariants so a nonsemantic provider id cannot poison finalization.
31 offline tests.
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(evals): claim-standing stance seed set (#655 §8 seed, v0.1)
32 cross-model-authored synthetic claim/candidate items (16 en + 16
zh-TW) covering every closed stance label plus missing-evidence,
metadata-only, irrelevant, and full-text slots; five closed schemas
(seed set, expert label, adjudicated ground truth, subject output with
no scalar-score field, score report); criterion-keyed expert label
guide; asset validator with slot/binding/simplified-char/registration
invariants; and the §8 mechanical scorer (no model in the loop, macro
and micro separate, blocked rows never imputed). The suite is
deliberately unregistered until an implementation PR carries a valid
baseline row; design_target is construction intent, never ground truth.
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(evals): harden #655 stance seed per dual-track review R1
- schema-level §5.1 cross-field rules in all three record schemas
(relevant+not_checked requires a failure state; not_relevant forces
not_checked/null/null); expert files must cover all 32 items
- scorer: abstention on a gold-performed row lands in an explicit
NOT_CHECKED confusion column (recall cannot be inflated by refusing);
blocked/partial rows keep their failure classes visible; full-row
accuracy includes evidence scope; adjudication must bind two distinct
experts; strict duplicate-key-rejecting JSON loads
- validator: strict loads, dead branches removed, Counter-based slot
check, simplified-char list purged of Traditional homographs,
discipline included in the zh screen
- README documents accepted seed boundaries (runtime failure classes via
future fault injection; expert-packet byte sealing belongs to the
implementation PR); 17 tests including enum-sync across schemas
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(evals): #655 stance seed R2 — expert-gate tightening + blocked-row failure visibility
- adjudication binding requires distinct file hashes, not just distinct
expert ids; new validate-expert-file subcommand checks one expert
file's complete distinct coverage of the 32 items
- subject schema requires a failure state on every blocked/partial row,
so a silent null cannot vanish from the failure-class report
- README/CHANGELOG state the actual report granularity: counts for
evidence-scope and failure-class dimensions; accuracy strata by those
dimensions belong to the future baseline-row compiler
- 20 tests
Refs #655
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(evals): closed first-round assignment-ledger gate for #659
Implements the assignment-ledger gate the #659 no-call envelope requires
before any first-round packet delivery, deliberately outside the runner so
its own boundary statement stays true. verify replays the finalized bundle,
enforces coverage (>=2 distinct judges per packet), roster exactness, and
pair-level exposure blocking (subsumes scenario/role-card sharing, incl.
cross-experiment), then seals a write-once pass receipt embedding the exact
accepted ledger. deliver consumes only the sealed receipt, re-checks
bindings and private-map modes, and publishes exactly one isolated packet
per verified assignment with a write-once claim marker. Gate artifacts live
in a sibling <run>-assignment-gate/ directory so the runner's exact
run-inventory validation stays green. 14 tests on a genuine finalized
48-packet bundle; exposure check mutation-verified.
Refs #659
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(evals): harden #659 assignment gate per cross-model review R1
- deliver replays roster/coverage/exposure against the embedded ledger:
the sealed receipt is evidence, not authority, so a hand-fabricated
receipt cannot authorize a delivery verify would refuse
- exposure diagnostics name the judge only; naming the conflicting blind
ids would itself disclose pair structure
- a write-once completion marker closes each delivered assignment so a
retired packet is never silently re-issued (exact-resume only for an
interrupted delivery)
- 3 new regression tests (17 total)
Refs #659
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(evals): #659 gate R2 — delivery replays full bundle, identifier-free exposure diagnostics
- deliver now runs the complete bundle replay plus binding checks (the
exact verify path), so a fabricated receipt over a consistently
tampered bundle fails DELIVERY-DRIFT; hash-only recheck helpers removed
- exposure diagnostics carry no judge or blind identifiers at all
- accepted residual documented: a crash between publication and the
completion marker leaves that one assignment resumable with identical
bytes for the same judge (no blinding property affected)
- 18 tests, including the tampered-bundle fabricated-receipt replay
Refs #659
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(evals): #659 gate R3 — post-publication desk isolation re-scan
A concurrent delivery racing the pre-publication emptiness check could
put two packets on one desk; the gate now re-scans the destination after
publishing and fails closed before the completion marker, so both racers
are detected and a desk is certified only by a successful exit over
exactly one packet. Regression test with an injected racing writer.
Refs #659
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(evals): #659 gate R4 — mkdir as the atomic desk claim
The post-publication re-scan alone still allowed one racer to certify a
desk the other later contaminated. Desk ownership is now acquired
atomically: a new delivery requires the destination not to exist and the
gate creates it itself, so two racing deliveries cannot both own one
desk; the re-scan remains as defense in depth. Resume keeps accepting a
desk holding exactly the claimed packet.
Refs #659
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* fix(evals): #659 gate R5 — unconditional mkdir closes the claim TOCTOU
The R4 fix still guarded mkdir behind an existence check, letting a
losing racer skip the claim and write into a certified desk. A new
delivery now attempts mkdir unconditionally; FileExistsError refuses
unless resuming.
Refs #659
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
* docs(evals): record accepted concurrency boundaries of the #659 gate
Per review disposition: a lost atomic desk claim needs manual marker
recovery, and concurrent identical resumes can both report success.
Neither interleaving affects exposure, desk certification, or re-issue
guarantees; parallel gate commands on one desk are themselves a protocol
violation.
Refs #659
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z2pMsRNu386PDHeNvxR5r
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Promote the accumulated Unreleased changes, align the suite and component
versions, refresh all five release summaries, and close merge-provenance
coverage for the v3.20.0 release.
Release gates:
- version and spec consistency
- CHANGELOG merge coverage
- pipeline boundary content locks
- pytest manifest and agents mirror checks
- 197 focused tests
[doc-aligned: 2026-08-14]
Add a closed-schema, citation-only Codex subscription transport with structured app-server web-search provenance, hermetic containment, fail-visible degradation, producer wiring, tests, and CI guards.
Supersedes #567 and closes#630.
Co-authored-by: dcs-scd <dcs-scd@github.com>
Implements and closes#673 with frozen contracts, deterministic local runtime, terminal-first advisory wiring, adversarial regressions, integration guards, and CI coverage.