feat(sync): bind registered-root reconcile control state (TIN-2864) - #565
feat(sync): bind registered-root reconcile control state (TIN-2864)#565Jesssullivan wants to merge 34 commits into
Conversation
|
CP20 source checkpoint: This adds the source-only authoritative namespace-writer gateway: non-forgeable capability binding to an exact visible publishing-HEAD receipt, retained live backend lease checks before/after every conditional mutation, complete canonical journal execution across Index/Reservation/Manifest, exact replay/collision handling, and terminal/failed evidence that retains authority. Production remains unreachable: no constructor for the retained lease or publishing-HEAD receipt, no live HEAD write/CAS, no finalization/recovery/high-water writer, and no CLI/RPC/action surface. Exact-source evidence:
PR remains draft and not merge-ready. Hosted checks are exact-head pending, and sanctioned GF exact-head authority remains blocked on TIN-2538 infrastructure. |
|
Authority-spine source checkpoint: This completes the ordered source-only transaction after CP20:
Production remains unreachable: bootstrap, pending-control, retained-lease, and authenticated control authority have no production constructors/implementation. No CLI/RPC/proto/public API, digest, action, deployment, credential, or fleet mutation was added; TIN-2801 remains authoritative. Exact-source evidence:
PR remains draft and not merge-ready. New hosted checks are pending; sanctioned GF exact-head authority remains blocked on TIN-2538 infrastructure. Digest-bound planning/execution remains downstream and TIN-2865 stays blocked. |
|
CI-authority composition checkpoint: This cleanly merges the isolated TIN-2538 GF public-read checkpoint Combined-head local evidence: CI-authority contract 11/11, Rust 1.93 Nix devShell |
|
Exact-head Nix source-realization follow-up: The one-line fix removes the nested The sanctioned GF/held jobs were re-requested at this exact head and remain queued with no assigned runner. PR remains draft; no durable-green or merge-ready claim, and TIN-2801 live freeze remains authoritative. |
|
Additional exact-head Sting evidence for This is source/build evidence only. Sanctioned GF/held checks remain queued with no assigned runner, so there is still no durable-green or merge-ready claim. |
|
Exact-head Sting replay of the complete Passed under the pinned Nix/Rust 1.93 devShell: authority contract 11/11, locked workspace check, fmt, FileProvider surface contract, clippy all targets with This is deliberately non-durable source evidence. GitHub still exposes no online |
|
Source-only exact-head update (2026-07-24) Signed, GitHub-verified head Exact evidence on Sting after the final Buffer change:
This does not claim the larger P0s are closed: storage-side lease atomicity and authenticated cold-process recovery still need separately bounded source work. The PR remains draft, source-only, digestless, and runtime-inert. Its newly created GloriousFlywheel checks are queued and are not yet durable CI evidence; no hosted-runner fallback is authorized. |
…(TIN-3278)
The primary state cache holds duplicate entries for the same logical file
under two key namespaces: an absolute canonicalized local path (the form
path_key() always produces on live get/set/mark_conflict today) and a bare
prefix-relative key left behind by an older keying scheme. Live evidence
on neo: secrets/.audit.log tracked at both
/Users/jess/tcfs/secrets/.audit.log (live, conflict record refreshes each
cycle) and /secrets/.audit.log (orphaned, times_recorded frozen at 1881
since 2026-07-07). Because get/set/remove/mark_conflict all re-derive the
key via path_key(), the orphan is never visited by any live read/write
path -- it just sits there forever, double-counted by raw-entry scans like
StateCache::conflicts() ("tcfs conflicts" reporting 9 vs the daemon's
per-cycle plan line reporting conflicts=8).
Root cause: path_key()'s identity fallback (return the input unchanged
when canonicalize fails) makes an unresolvable key indistinguishable from
an already-canonical one. A bare "/secrets/.audit.log" key's parent
("/secrets") does not exist at the filesystem root, so it canonicalizes to
itself and looks canonical even though it never independently resolves.
Fix: keep path_key() as the sole choke point for live writes (unchanged),
and add a load-time migration pass (migrate_duplicate_keys, wired into both
StateCache::open and StateCache::reload_from_disk):
- resolve_key_on_disk() mirrors path_key() but returns None instead of
falling back to identity, so migration can tell "canonical" apart from
"unresolvable".
- Pass 1 re-keys/merges any key whose independently-resolved form differs
from its stored key.
- Pass 2 handles orphans that cannot independently resolve at all: match
against the other loaded keys using the same suffix convention
get_by_rel_path() already uses for cross-host lookups. Only an
unambiguous single match is merged; zero or 2+ candidates leave the
orphan untouched rather than guess at a target.
- merge_duplicate_sync_states() joins causal history and never drops a
conflict record: vector clocks are merged pointwise-max via the
existing VectorClock::merge (entry vclock, plus same-side joins of a
merged conflict payload's local_vclock/remote_vclock), because
partial_cmp_vc reads a dropped component as 0 and would let a peer
falsely dominate -- classifying RemoteNewer and silently overwriting
the dropped side's divergence. Scalar fields (blake3/size/mtime/
chunk_count/remote_path/device_id) have no join, so they still come
from the higher-last_synced side; if either side carries a conflict the
merged entry keeps one (later detected_at as payload, times_recorded
as the max of the two, remote_manifest_key backfilled from the other
side when missing -- mirroring mark_conflict's preserve-on-missing).
- Load-time migration is IN-MEMORY ONLY and never marks the cache dirty.
StateCache::open is reached from read-only CLI paths that hold no
cross-process StateFileLock (lock_explicit_state_cache only locks when
a --state override is supplied), and Drop flushes on dirty -- so
dirtying here would turn "tcfs conflicts" into an unlocked writer whose
atomic-rename flush can clobber the daemon's concurrent locked update.
The fold is free for readers; it becomes durable on the next flush by a
legitimate lock-holding writer (the daemon dirties on any set /
mark_conflict and flushes the whole map under its own lock). A
debug_assert pins the invariant at construction.
- Each merge is logged via tracing::warn! and recorded in a new
StateCache::key_migration_log() accessor. Reload suppresses records
already seen in-process, so an orphan that disk keeps reintroducing
does not re-emit the same warn line every reconcile cycle.
- One canonicalize attempt per key per call, computed up front and shared
by both passes, so an unresolvable orphan no longer re-stats every
candidate on each reload.
Known boundary (documented on migrate_duplicate_keys): the len() != 1
ambiguity guard does not cover a multi-root host where two registered roots
share a relative suffix but only one materializes the file; closing that
needs root-scoped matching, which state-cache keys carry no attribution for
today.
Also adds StateCache::conflicts_naming_unknown_devices(), a read-only scan
for TIN-3278 defect 2 (ghost device ids, e.g. a stale "yoga" string, named
inside a recorded conflict but absent from the caller-supplied known-device
set). Reports only -- never mutates the entry, never touches devices.json
(that migration is TIN-3277 / TIN-1417 territory).
No file-level overlap with the TIN-3277 fix (#576, reconcile.rs only);
trial merge between the two branches is clean. PR #565 (TIN-2864,
Codex-owned) also touches state.rs but in an unrelated region.
Tests (9 TIN-3278 tests, all run on sting):
- tin3278_dedup_merge_on_load_collapses_duplicate_key_namespaces
- tin3278_dedup_merge_never_drops_a_conflict_record
- tin3278_merge_duplicate_sync_states_keeps_richer_conflict_and_max_times_recorded
- tin3278_merge_joins_vector_clocks_instead_of_dropping_one_side
- tin3278_merge_joins_conflict_side_clocks_same_side_only
- tin3278_migration_does_not_dirty_or_rewrite_for_unlocked_readers
- tin3278_migration_is_idempotent_on_second_load
- tin3278_ambiguous_orphan_suffix_match_is_left_untouched
- tin3278_conflicts_naming_unknown_devices_reports_without_mutating
sting: cargo fmt --all --check PASS, cargo test -p tcfs-sync PASS
(571 passed / 0 failed), cargo clippy -p tcfs-sync --all-targets
-D warnings PASS (0 warnings).
Summary
Publishes the clean TIN-2864 registered-root reconciliation lane for canonical CI and independent review.
mainand the TIN-2538 GF-only CI-authority source checkpointExact source state
0a3a9ceceeab497af614e07e80e91780c7f3be47fix(ci): run protected proof on stacked PRscodex/tin-2864-root-plan-202607196a1f26d6c00e478cbd007895aa364664d374f9f8CP21 storage-fence closure
Every authoritative mutable Publishing
HEAD, Index, Reservation, Manifest, and committedHEADwrite must pass through one retained backend fence.Each request exact-binds the selected root context, storage/control authorities, writer epoch and writer-fence fingerprints, Pending revision/record, mutation-journal ID and count, ordinal, stage, key, conditional-write predicate, payload length, and BLAKE3. The backend contract must atomically reject a stale fence or apply the exact write at the storage authorization point. Advisory liveness checks, an in-process mutex, or a control read followed by raw OpenDAL I/O do not satisfy it.
Raw rereads are receipt validation only and cannot redeem backend rejection. Exact replay and failure retention cover Pending, Publishing
HEAD, namespace mutations, committedHEAD, and Ready.CP22 authenticated cold reconstruction
A fresh process can now reconstruct one exact canonical
PublicationPendingepoch without reusing warm planner/executor objects or treating copied bytes as authority.The adversarial backend fixture now models a one-time exact Ready→Pending CAS. It rejects crossed Ready without state movement and mutates an archived page during reacquisition to prove post-reacquisition rejection with zero receipts, ordinals, or Ready progress.
Claim boundary
This remains SOURCE_ONLY_DIGESTLESS. No production selector, authenticated backend constructor, or live storage-fence implementation exists. The code cannot mint deployed authority, mutate live
HEADor namespace state, emit a plan digest, authorize an action, deploy, activate, reconcile live state, access credentials, enroll a device, or enter a crypto ceremony.The only direct source-path writes outside the fence are content-addressed absent-only immutable archive, journal, payload, page, and root publications. The fence and reacquisition traits have only
cfg(test)implementations.Exact-head validation
Exact head
0b7b789b121cbbadcc6c970fc6cfa8230ac0cc83passed on Sting inside the repo-managednix develop --accept-flake-configshell with the pinned Rust 1.93.0 toolchain:tcfs-coreunit tests: 44/44tcfs-syncunit tests: 698/698tcfs-core/tcfs-syncall-target integration testclippy -D warningscargo fmt --all -- --check0a3a9ceceeab497af614e07e80e91780c7f3be47: 12/12 CI-authority contract tests, Ruff check/format, JSON/Python parse, localactionlint, Sting diff check, and clean exact tree sealThis is strong exact-head local source/build evidence, not durable CI authority.
Durable CI state
Fresh exact-head checks instantiated automatically at
2026-07-25T14:14:55Zon the corrected workflow topology:tinyland-nix/tinyland-dindlabels;matrix.surfaceis intentionally skippedBoth Darwin jobs remain explicitly
HELDand deliberately exit nonzero when scheduled. TIN-2998 is Done; TCFS topology integration and durable native authority remain separate gates.Remaining promotion gates
Coordination and holds
This lane owns registered-root planning/publication surfaces in
tcfs-coreandtcfs-sync. Do not stack unrelated CLI/MCP work onto it; both dirty primary checkouts remain untouched.TIN-2864 stays In Progress and TIN-2865 remains blocked. TIN-2801 remains the authoritative fleet/live-runtime freeze. TIN-3120/TIN-2538 own durable personal-owner multi-capability listener proof; TIN-2998 owns native Darwin authority.
Keep this PR draft. Do not mark ready or merge until exact-head sanctioned CI is durable, the held Darwin topology is resolved, and the selected landing scope’s review findings are dispositioned. No auto-merge or bypass.
Linear: TIN-2864
Related: TIN-2538, TIN-3120, TIN-2998, TIN-2801