Skip to content

v0.3.162 - Honest Mint-Receipt Reconcile

Choose a tag to compare

@mow-coding mow-coding released this 03 Jul 13:44

v0.3.162 - Honest Mint-Receipt Reconcile

v0.3.162 adds archive remint-reconcile, an honest way to re-issue a mint
receipt's recorded sha256 values after a canonical zet drifts on disk — for
example a CRLF/BOM re-checkout under core.autocrlf, or a human content edit —
without ever masking corruption or waiving human review. It also lands additive
BOM/newline parse tolerance and a doctor/retire route to the new command.

Governing Doctrine (v0.3.162 decision log)

Reconcile NEVER masks corruption, and classification NEVER waives human review.
The draft snapshot only anchors the raw draft bytes (body + draft frontmatter),
while the client's real mutation (a title correction) lives in the
mint-transformed canonical frontmatter. A body-only comparison is therefore
blind to frontmatter edits, so:

  • Every --approve shows the current on-disk content and requires
    --reviewed-by. No computed class unlocks a lower-friction, human-skipped
    path.
  • Classification only DECORATES the human decision (it names which fields
    changed). It never REPLACES it.
  • The default class is the stricter content_change. format_drift is granted
    ONLY on positive, byte-level, independently re-derivable proof of
    content-identity. Any doubt falls to content_change.
  • Hard refusals run BEFORE classification. A state that cannot be honestly
    reconciled is REFUSED; it is never "fixed."

What Changed

  • New command archive remint-reconcile <archive-root> (--zettel-id <id> | --path <rel>) [--dry-run | --approve] [--reviewed-by <actor>] [--content-changed-ack] [--format text|json]. --dry-run (default)
    classifies and previews with zero writes; --approve re-issues after review.
  • format_drift is proven positively: the current canonical body must be
    identical to a CLEAN draft snapshot (raw sha matches the recorded sha) AND the
    FULL content frontmatter — every draft key re-derived from the snapshot, with
    source_refs transformed exactly as mint does — must match the current
    canonical field-by-field. Only the mint-injected keys (status, updated_at,
    mint{}, promotion{}) are excluded from the diff, and status is separately
    required to equal canonical. Because the comparison spans every content field
    rather than a hand-picked subset, an edit to ANY field (title, id, kind,
    visibility, facets, provenance, edges, created_at, …) is caught: a
    canonical-only title edit leaves the body identical but the title differs, so it
    is correctly content_change, and the same holds for every sibling field — no
    content field is invisible to the classifier.
  • Snapshot drift is a first-class fail-safe: a missing, BOM'd, or
    otherwise-mutated snapshot is never treated as a clean anchor and classification
    falls back to content_change.
  • Approval writes BOTH: an in-place mint-receipt update (recomputed shas plus an
    append-only reconcile.history block with a normalized_content_digest) AND a
    separate immutable audit receipt under receipts/mint/reconciles/. Repeats get
    a monotonic suffix. Both writes are atomic (temp file + os.replace).
  • archive doctor routes canonical byte drift: a previously-reconciled receipt
    that re-drifted by newline/BOM only emits the new
    mint_receipt_target_byte_drift_suspected_format ERROR; an un-reconciled sha
    mismatch keeps the plain mint_receipt_sha_mismatch ERROR plus a suggested
    remint-reconcile --dry-run command. Both stay non-clean (fail doctor and
    --strict). The edge-receipt evolution path is unchanged. A UTF-8 BOM on a
    canonical zet surfaces a new zettel_has_bom WARN advisory.
  • archive retire-draft now surfaces a remint-reconcile --dry-run next-safe
    action when — and only when — retirement is blocked by the mint-target
    sha-mismatch blocker. No retire gate was relaxed.
  • Additive parse tolerance: frontmatter parsing and receipt/JSON reads tolerate
    a single leading UTF-8 BOM (utf-8-sig / one-BOM strip). sha256 hashing still
    reads raw bytes, so BOM and newline drift stay visible as a sha mismatch. New
    mints pin the canonical write to LF newlines to prevent immediate re-drift.
  • Schemas: added wom-kit/schemas/mint-reconcile-receipt.schema.json and a
    reconcile object property on mint-receipt.schema.json (not required; legacy
    receipts validate unchanged).

Safety Boundary

  • No archive migration and no hash change: BOM/newline tolerance affects
    parse/read helpers only, never the sha256 functions.
  • Reconcile never edits zet content. --approve records the sha of the bytes as
    they are; it does not rewrite the canonical.
  • Hard refusals (missing/non-mint receipt, id mismatch, non-canonical or
    unparseable target, target.path mismatch) block before any classification, so a
    swap-corrupted or foreign receipt is never laundered into a fresh integrity
    record. mint still refuses to re-mint an already minted zet.

Still Future

  • The remint-reconcile-batch tier is deferred (its receipt directory name is
    reserved). Per-id human judgment on each content_change is the point of the
    doctrine, so a bulk content-change ack is intentionally not shipped yet.

Verification

cd wom-kit
python -m pytest tests/ -q
python tools/check_public_privacy.py
python tools/check_release_readiness.py

Upgrade Notes

No data migration is required. The new command, BOM/newline parse tolerance, and
the LF write pin are additive; existing receipts and canonical files are
unaffected until you choose to run remint-reconcile. See
UPGRADE.md.