tcfs: loser-side no-loss guard for git keep-both (TIN-2552)#534
Merged
Conversation
Add the G5-git-13 stage to the .git-as-files fsck/conflict harness — the
PASS counterpart to Stage 4's corruption-risk evidence. It reproduces the
keep-both PR-4 loser-side no-loss guard (design S10) at the ref level with
pure git on BOTH machines and asserts the no-loss invariant: after a
divergent .git pull overwrites refs/heads/main with the winner head, the
loser's committed head is parked at refs/tcfs/theirs/<self_device>/heads/*
first, so both sides' committed heads stay reachable (rev-list --all) and
each .git is fsck-clean. This is the two-machine convergence row that
flips G5-git-5 green (closes the converges-never gap).
Fail-before/pass-after verified: with the park the stage exits 0 (PASS);
neutralizing the park orphans the loser tip and the stage exits 1
("loser tip unreachable (ORPHANED)").
The loser_guard tests' upload_ref_blob helper returned UploadResult.hash (the file-CONTENT hash) as the pull manifest_hash, but the ref blob is retrievable only at its remote-index manifest key (manifest_object_id). download_ref_sha_from_manifest therefore always returned None, so every guard path fell through to the "incoming SHA unreadable" DEFER — which the three defer-expecting tests passed on coincidentally while loser_guard_parks_divergent_local_head_before_ref_pull (which needs the incoming SHA to prove the non-ancestor overwrite and park) failed on CI. Read the manifest key from list_remote_index(...).manifest_hash, matching the working git_ff_resolution seeding pattern. All four loser_guard tests now exercise a real incoming-SHA download: the parks test parks + applies, the defer tests defer via their intended non-parkable/module paths.
614a597 to
0de8d2b
Compare
Owner
Author
Post-merge audit — PASS4-lens adversarial pass over the final delta (6f1ae21..fd699a5, squash-merged as 4c61da4):
No correctness defects found. Tests were strengthened, not weakened. No-loss invariants confirmed: park-before-overwrite, undo-bundle-before-overwrite, CAS overwrite via Three minor findings tracked as follow-ups (see linked ticket): packed-refs validation subprocess-per-ref/per-SHA (no batching), redundant duplicate download/decrypt of incoming packed-refs bytes on the new-packed-refs bootstrap path, and a |
Jesssullivan
added a commit
that referenced
this pull request
Jul 6, 2026
…PR-4 merged) (#536) - Add operator-executable T10/T11 divergent keep-both canary plan (preconditions, per-host command sequences, verification checklist, undo-bundle rollback, G5-git-13 flip criteria). Notes the tcfs-resolve-vs-isolated-state trap found during grounding. - Update current-workstream-truth: PR-4 (#534/4c61da4, TIN-2552) is merged + post-merge audited; deploy + live canary still pending, so G5-git-13 stays red until proven.
Jesssullivan
added a commit
to tinyland-inc/tummycrypt
that referenced
this pull request
Jul 6, 2026
…706-pr534-pr535 codex: sync Jesssullivan/main -> tinyland/main (Jesssullivan#534 keep-both + truth docs, 2026-07-06)
8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the PR-4 loser-side no-loss guard for divergent raw
.gitkeep-both convergence.refs/tcfs/theirs/<self-device>/**.gitref tablepacked-refsas opaque: byte differences defer rather than rewriting packed-only refs-<sha12>and widening the SHA prefix if that suffix is also occupied.gitpath parsing, and suffix collision handlingTracker
Linear: TIN-2552
Parent: TIN-1620
Validation
cargo fmt --allgit diff --checkNo local cargo/nix build was run on neo. This PR is intended to validate through GitHub Actions / remote builders only.
Notes
This is the final keep-both rung from the design doc: it closes the crash/order window where the non-resolving device could pull the winner's
refs/heads/*before its own old head was reachable throughrefs/tcfs/theirs/**.Update — 2026-07-05 docs correction
Latest head
6f1ae21adds a docs-only correction: PR-4 is not framed as blocked on PZM hardware. PZM SSD/RWX re-enumerated and verified clean; builder transport hardening (ssh-ng://Determinate Nix vsssh:///serve-style or GF/remote-cache execution) remains tracked separately under TIN-1620/#524. Code remains the2e05c8bsafety head.Update — 2026-07-05 CAS fix round
Latest head
e5398c8closes the fresh adversarial P1/P2 findings:git update-ref <ref> <incoming> <expected-old>(or zero-OID for a new ref). A live ref move between proof and mutation now defers/replans instead of overwriting.remove_fileafter parking. They usegit update-ref -d <ref> <expected-old>and defer on mismatch.cargo fmt --all -- --checkandgit diff --check; no local build/test.Fix round: ref-class raw fallthrough closure (4a46851)
Confucius adversarial review found three initialized-gitdir paths that could still fall through to raw writes. This head closes them:
refs/tcfs/**now classifies as a guarded non-parkable ref path, so missing-object incoming refs defer instead of raw materializing..git/HEADnow classifies even when symbolic; symbolic HEAD changes and incoming detached-HEAD rewrites defer once the gitdir is initialized.packed-refsnow requires object proof plus create-new semantics once the gitdir is initialized; opaque changes still defer.git_ff_resolutionCI bootstrap failure from e5398c8 without reopening initialized-gitdir raw writes.Local validation on neo remains intentionally lightweight:
cargo fmt --all -- --checkandgit diff --checkonly. Build/test validation is remote GitHub CI / fleet infrastructure.Fix round: symbolic submodule HEAD closure (dfbd98a)
A local read-only review found one more symmetry gap before merge:
.git/modules/<name>/HEADonly classified when already detached, while top-level.git/HEADclassified whenever it existed. Latest head changes submodule HEAD classification to match top-level HEAD and addsloser_guard_defers_symbolic_submodule_head_to_detached_head_pull, proving an initialized submodule symbolic HEAD defers rather than raw-overwriting to detached HEAD.Validation boundary unchanged: only
cargo fmt --all -- --checkandgit diff --checklocally; remote CI owns build/test.Fix round: packed-refs syntax/refname hardening (fd699a5)
Euler's clean adversarial review left one non-blocking residual: new
packed-refsproved object presence but did not validate packed-refs syntax/refnames before create-new. Latest head closes that too:SHA refs/...or peeled^SHA;git check-ref-formatand start withrefs/;HEAD, and malformed peeled lines;loser_guard_defers_new_malformed_packed_refs_even_when_object_exists.Local validation remains
cargo fmt --all -- --checkandgit diff --checkonly; build/test validation is remote CI.