v0.3.167 - Snapshot-Drift-Aware Reconcile + Retire-Draft Reconcile
v0.3.167 - Snapshot-Drift-Aware Reconcile + Retire-Draft Reconcile
v0.3.167 extends the honest mint-receipt reconcile family without ever loosening
its prime directive: a real content change must NEVER be misclassified as
format drift. Classification only decorates the human decision; every reconcile
still shows on-disk content and stays approval-gated, and every uncertain case
falls back to the stricter content_change (which requires an explicit
--content-changed-ack). Five changes ship together.
The prime directive (unchanged)
Classification only decorates. When normalized-content comparison is at all
uncertain, classifycontent_changeand require acknowledgment. A snapshot that
is content-tampered NEVER anchorsformat_drift.
What ships
-
Snapshot-drift-aware
format_drift(Item 1).remint-reconcilenow grants
format_drifteven when the draft snapshot itself has drifted — but ONLY behind
a two-independent-proofs rule sourced from un-tampered inputs. A new anchor tier,
normalized_content_match(Tier B), sits between the existing raw-sha
clean_anchor(Tier A) and thecontent_changefallback. Tier B is granted only
when: (1) the current canonical body is byte-identical to the snapshot body under
the one normalized-equality definition (CRLF/CR→LF, strip one leading BOM, zero
Unicode normalization, no space collapsing); (2) the snapshot's own raw-vs-
normalized delta is provably newline/BOM-only; and (3) the frontmatter field-diff
is empty. Because the drifted snapshot is only newline/BOM-anchored (not
sha-anchored), that field-diff is the union of two independent checks, both of
which must be empty: a full-field reconstruction comparing every content
frontmatter field of the current canonical against the snapshot (visibility,
kind,facets,provenance,edges,created_at,source_refs, …, not just
id/title), and a cross-check against the mint receipt's recordedzettel
(id/title). This closes the tampered-snapshot hole in full: a canonical edit
to ANY content field falls tocontent_change, and a snapshot whose frontmatter
was tampered to match a tampered canonical (which would make the full-field diff
reproduce itself and read empty) is still caught by the receipt cross-check. A new
classification_basisfield (clean_anchor/normalized_content_match/
content_change_fallback) records why aformat_driftwas granted. -
retire-draft-reconcilesibling command (Item 2). A new CLI-only command
honestly reconciles a retire-draft receipt with its four refs
(source / target / mint_receipt / snapshot) after newline/BOM or content drift.
It reuses the same honesty primitives and inherits the Item 1 discipline: a
target/snapshot ref isformat_driftonly when the shared mint-reconcile
classifier proves the canonical and snapshot content-identical AND the structural
newline/BOM delta guard holds; themint_receiptpointer ref has no format
dimension and iscontent_changeon any mismatch; a removedsourcedraft is
not a drift. The doctor now attaches asuggested_commandroute to the
mint_retired_draft_sha_mismatchfinding (previously a bare error with no
discoverability), mirroring the mint route. New sibling audit receipts live under
receipts/mint/retired-draft-reconciles/. -
--strip-bom(Item 3). An opt-in boolean on bothremint-reconcileand
retire-draft-reconcilethat removes exactly the 3-byte leading UTF-8 BOM.
Stripping a leading BOM isformat_driftby definition (text content unchanged).
Guards: a no-op refusal when there is no leading BOM (nothing is rewritten); a
hard content-preserving invariant asserted before an atomic rewrite; and — the
load-bearing one — a BOM strip NEVER bypasses the content-change ack gate. When a
file also carries a real content edit,--strip-bomstill requires
--content-changed-ack. -
live_execution_allowed_nowhonesty (Item 4). The object-storage upload
run-outcome payload previously reportedlive_execution_allowed_now: falseeven
on a genuinely executed upload — a self-contradiction with
execution_status: executed. The RUN-outcome field now truthfully reports what
the run did (trueonly on a real executed upload;falseon preview/blocked).
The static contract-preview capability fields elsewhere are a different signal
and remain unchanged. -
--multipart-thresholdoverride (Item 5). A clearly-labeled
validation/testing aid onobject-storage-upload. The 5 GiB default is unchanged;
an override is code-bounded to[64 MiB, 5 GiB](below the part-size floor or
above the default ceiling is refused with a blocker, so a forced multipart still
exercises the real part-splitting path and cannot fragment a tiny object). The
effective threshold andpart_countare now recorded in the durable upload
receipt. The override affects only the recorded/used threshold, never the local
sha256 == object_idcheck nor the provider-HEAD-after gate.
JSON-contract additions (all additive)
mint-reconcile-receipt.schema.json:classification_basis,bom_stripped.mint-retired-draft-receipt.schema.json: areconcileprovenance block.- new
retire-draft-reconcile-receipt.schema.json. object-storage-upload-receipt.schema.json:effective_multipart_threshold_bytes,
part_count.
The drift_class enum stays exactly ["format_drift", "content_change"]. No schema
uses additionalProperties: false, so every field is additive and non-breaking.
Test honesty note
test_remint_reconcile_drifted_snapshot_falls_back_to_content_change was revised,
not merely kept: its missing / crlf_plus_content / bom_plus_content
subscenarios still classify content_change (a real HUMAN EDIT or no anchor), and
new pure-format subcases were added as a sibling test that flip to format_drift
under Tier B. The three v0.3.162 integrity fences (a content-plus-newline drift is
never softened to format; a title edit is content_change; a non-allowlist
frontmatter edit is content_change) stay green untouched.
Safety and scope
No archive migration and no hash change. New flags and the new command are opt-in.
The reconcile family remains CLI-only (no MCP surface). When in doubt, the
classifier chooses content_change.
Upgrade
See UPGRADE.md. All changes are additive; no migration is required.