v0.3.2 — change-control every recorded human decision
Extends the register policy diff from "reviewed items cannot silently disappear" (v0.3.1) to change control over every recorded human decision: acceptance, terminal dispositions, accountability, re-review commitments, both residual assessment axes, and the assurance-graph edges. From a fifth external review of v0.3.1. No schema changes; existing adopters see stricter drift findings only on pull requests that change a reviewed decision. See CHANGELOG.md.
Canonical pin for adopters: v0.3.2 @ aac49ef7f0d8a8e8762113df8b7bf1784eaa2e54 (this tag's commit).
Review class: SOLE_OWNER_ATTESTED + AUTOMATION_VERIFIED. The external technical review is cited, not counted as an approving review (GOVERNANCE.md §2).
Fixed — register policy diff: human decisions are change-controlled
- Residual acceptance is gated. Any status transition into
ACCEPTEDis now a finding. Accepting a risk is a human decision (PROFILE.md §3, §12) and the acceptance fields are self-declared strings, so an agent could previously fabricateaccepted_by/accepted_at/acceptance_rationale, flip a critical residualOPEN → ACCEPTED, and turn a failingCONFORMANTstate green with no finding. Rewriting or removing an existing acceptance record is likewise a finding. - A recorded judgement value cannot be silently unset. Every weakening check is pair-keyed, so unsetting a value was a free first hop — drop it in one pull request (nothing to compare, silent), record the weaker value in the next (no baseline, silent), while the one-step edit was an error the whole time. Removing, emptying, or de-stringing
status(all registers),severity,proof_tier,impact,uncertainty, or anINTENDEDintent.classificationis now a finding. The residual/defeater disposition gates additionally fire on the head arriving at a gated status whatever the base recorded. - Defeater terminal dispositions are gated.
MITIGATED → RESOLVEDandMITIGATED → WITHDRAWNwere invisible inside a single "closed" class, though the schema definesMITIGATEDas risk reduced, not eliminated. - Assurance-graph edges are protected. Removing items from claims'
defeaters/residuals, invariants'assumptions/limitations/defeaters/residuals(at every severity — edges are graph structure, not evidence volume), defeaters'affected_claims/affected_invariants/evidence, and residuals'affected_claims/affected_invariants/mitigation. review_afteris a kept commitment. Removal, replacement with an unparsable value, and pushing out a date that has already passed are findings. Rescheduling a future date is deliberately not one.- Also: residual
uncertaintydowngrades (impact's previously unprotected twin axis), entryownerchanges, andhuman_review.reviewer/human_review.recordchanges in the adoption declaration.
Security
- Symlinked base registers no longer fail open. The drift job materializes the base side as a detached
git worktreeinstead of per-filegit showwrites.git showrenders a symlink blob as its target-path string, so a symlinked register materialized as a regular file holding a path string, loaded as unusable, and dropped out of the policy diff silently — one innocuous pull request converting a register to a symlink disabled its protection for every later one. - A register that parses but is not a mapping with its list, a lite assurance file that is not a mapping or whose section is not a list, and a path that exists but is not a readable regular file (directory, broken symlink) are now reported instead of silently skipped.
- Duplicate head IDs fail closed. The diff compares by stable ID (last-one-wins), so a shadow entry under a duplicated ID was invisible to it. This no longer depends on the structure job being configured as a required check.
Deliberately not added
Recorded so the reasoning survives: disclosure reclassification (not a strength axis; the risky direction on a public repository is already a CONFORMANT error; retriage is routine), rescheduling a review_after date that has not yet passed (a red check on the act the schedule exists to produce would teach adopters to ignore the check), strengthening promotions, and unrecognized-string overwrites (pair-keyed the same way, but flagging them would also flag an adopter repairing a value that predates the stricter schema — that remains the schema enum check's job).
Upgrade actions when re-pinning
None required. Update upstream.version, upstream.commit, and the reusable workflow's @ reference to this tag's commit in the same change. Pull requests that change a reviewed decision now need the same stage-proportional Assurance policy change: acknowledgment as deletions and closures. Adopters whose registers are in-tree symlinks: the base side of the policy diff previously dropped such registers silently; they are now compared like regular files.