Skip to content

Sync Formal Modeling - P & Occult - #1115

Closed
kans wants to merge 27 commits into
mainfrom
kans/sync-formal-model
Closed

Sync Formal Modeling - P & Occult#1115
kans wants to merge 27 commits into
mainfrom
kans/sync-formal-model

Conversation

@kans

@kans kans commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Source-cache replay (phase 6b) + formal verification of sync scheduling

Status: not for merge as-is. This branch contains the phase 6b
implementation and the formal verification work that characterizes a
structural defect in its composition algorithm. The current algorithm can
seal artifacts containing permanently dead data presented as live (details
below), and that data then replays into subsequent warm syncs. The merge
path is the replacement runtime designed and verified on this branch
(RFC 0011), not the 6b composition as it stands. The branch is published as
the archive of record for both the implementation and its verification.

What's here

Three related bodies of work.

1. Source-cache replay orchestration (phase 6b) — pkg/, internal/, proto/

Warm syncs can reuse partitions of the previous sync's artifact instead of
refetching them. Connectors annotate page responses to either record a
partition (fresh rows, tagged with a validator string) or replay it
(copy the previous artifact's partition forward, optionally overlaying
changed rows and tombstoning deleted ones). The syncer orchestrates:

  • a lookup negotiation (the connector may ask for previous-artifact
    evidence before deciding; bounded to 4 round-trips per request);
  • atomic replay units (partition clear + copy + validator publish commit
    together);
  • integrity verdicts that fall back to a cold fetch on any doubt;
  • crash/resume safety (interrupted replays re-run idempotently).

Touches pkg/sync (orchestration), pkg/dotc1z / pkg/sourcecache
(storage), proto/pb (annotations), internal/chaosconnector (test
harness). Verification evidence: docs/verification/sync-replay-6b/.

2. Formal verification of the scheduling semantics — formal/ (no production code)

Two tools, for readers unfamiliar with them:

  • P is a model checker: you describe a system as communicating state
    machines plus properties that must hold, and it mechanically explores
    very large numbers of crash and interleaving schedules looking for a
    violation, printing the exact schedule when it finds one.
  • Occult is a proof engine: you write algebraic axioms about the
    system's operations and it proves or refuses claimed identities; it can
    also evaluate invariant-checking functions over recorded event logs.

What was done with them:

  • A calibrated model of the current (6b) design. The model earns
    trust by mechanically rediscovering known bugs before being believed
    about anything else. Result: with the shipped mitigations ON, the
    checker still seals a phantom union — individually truthful
    connector responses composing into an artifact containing rows that no
    longer exist upstream, which then replay warm into later syncs as
    live data with unbounded staleness. This is the defect that blocks
    merging 6b's composition as-is (formal/walker/CALIBRATION.md,
    scenario 1; each red cell archives its counterexample schedule).
  • A model of the replacement design (demand-graph runtime: work is
    admitted by tracked demand, every output carries lineage, seal-time
    obligations are checked against a closure oracle). Model-checking found
    five design bugs during calibration — all fixed in the spec before any
    code exists — and a structured bake-off between two lineage designs
    selected observable-causal stamps (formal/graph/BAKEOFF.md).
  • Machine-checked proofs of 15 algebraic laws of the replay/overlay
    composition, a deductive derivation showing the current composition
    rule manufactures the phantom union, and conformance proofs for the
    lookup negotiation protocol (formal/occult/).

Entry point: formal/REPORT.md (verdicts, findings register, and an
explicit statement of what is and is not guaranteed).

3. The bridge: checking real executions against the formal invariants

pkg/sync gains a test-only event recorder
(pkg/sync/sync_trace_audit.go). It is a nil pointer in production —
only test code can enable it, and test files are not compiled into
production binaries; each call site costs one nil check. Chaos tests run
the real syncer, export the recorded commit-order event logs, and an
Occult test suite verifies every exported execution obeys the ordering
and durability invariants (writes only into partitions cleared this sync,
publish before a checkpoint claims quiescence, seal only after
obligations are met — across cold, warm, crash/resume, and tombstone
executions). This instrument also falsified one piece of documented
resume behavior
: a documented "skip the re-copy on resume" mechanism is
unreachable; the code is safe via idempotent re-copy instead. Comments
were corrected (pkg/sync/chaos_source_cache_resume_test.go).

Also included

docs/rfcs/0011-demand-graph-sync-runtime.md — the kickoff design doc
for implementing the verified replacement runtime in pkg/sync.

Reviewer routing

Per docs/REVIEW_CHECKLIST.md: the production-behavior changes are item
1 plus the nil-guarded recorder call sites from item 3 — route HIGH
(silent/combinatorial subsystem). Item 2 is additive models and
documentation; the rest of item 3 is test code and fixtures.

kans and others added 10 commits August 27, 2026 18:40
Wire the end-to-end source-cache replay contract frozen in
docs/verification/sync-replay-6b/plan.md: SourceCacheCapability parsing
and gating, lookup install/teardown with a transport deliverability
probe (CO-6b-001: no production transport delivers this phase; such
syncs run cold and never log warm), compat-record lifecycle with
byte-match consume gating, fresh-page recording with scope stamping,
replay handling with provenance enforcement — the sourceCacheWarm gate,
hit-validator binding to the replay base, and a per-scope page lock
covering replay copies AND record-page application — the warm/cold
ErrReplayIntegrity verdict taxonomy, the CO-017 cross-version fold
fence, produce-side guards blocking unreplayable shapes (child resource
types, InsertResourceGrants) from seeding warm generations, and a sync
token schema fence (reshaped fields take new keys; versioned tokens
that fail to parse error loudly instead of downgrading to v0).

Verified by the chaos-connector suites (gate matrix, collection
semantics, ordering/pagination, interruption/resume, generational
steady state), a bounded verdict-taxonomy enumeration, engine-seam
sentinel-identity tests, benchmarks pinning the disabled-path and
checkpoint-marshal costs, and mutation-verified instruments for every
load-bearing guard. Three independent review rounds drove the
hardening recorded as change orders CO-6b-003 through CO-6b-006;
docs/verification/sync-replay-6b/evidence.md carries the full closure
record, registered exclusions, and explicit limitations.

Co-authored-by: Cursor <cursoragent@cursor.com>
…e triage, witness pin

Closes both round-4 MAJORs: the chaos fixture now asserts no source-cache
scope lock is held at sync end (with per-handler loud-failure cells, each
defer site mutation-verified), and evidence.md gains the structural-
coverage triage ledger with six new instruments for the branches it
judged worth real tests. Minors: MaterializationWitnessReader promoted to
a pinned named interface, the syncer asserts the exported deliverability
probe, the shrunk-type-list permutation is a registered exclusion, and
the token-fence/lock-hold/lock-cardinality wording is corrected.

Co-authored-by: Cursor <cursoragent@cursor.com>
P track: MODEL_SPEC (walker+6b, frozen v6) with 47-cell calibrated
sweep reproducing calibration cases 1-4; GRAPH_MODEL_SPEC (demand-graph
runtime, frozen v4 + GS-CO-001..005) with 66-cell calibrated sweep over
both lineage variants; curated counterexample traces. Occult track:
equational laws (LAWS.md, 15 proved + 5 refused controls), trace-policy
oracle set, MPST protocol projections, phantom-union derivation, and an
executable demand-graph reference implementation checked by the same
oracles. Bake-off protocol registered (GS-CO-005); verdict document to
follow.

Co-authored-by: Cursor <cursoragent@cursor.com>
….md)

Runs the GS-CO-005 declared cells (12/12 on declared verdicts: G6 v1
zero-crash controls, G6b bound-1 probes, G5d seal-world probes via the
new GSEALWORLD monitor) and assembles deliverable 4's written
recommendation under the registered decision rule: tie on property
satisfaction, S wins on the frozen mechanism tally (no new durable
state class; session primitives demote to optimization), redo work
symmetric, seal-world sets identical across variants.

Co-authored-by: Cursor <cursoragent@cursor.com>
Deliverable 6/7's last leg: real pkg/sync executions now feed the
trace-policy oracle. A test-only commit-order recorder
(sync_trace_audit.go, the testQueueAudit pattern — nil in production,
one pointer check per event) fires at the orchestration seams:
consult (lookup resolution), the replay unit's clear+copy legs,
scoped page-row commits, manifest publishes, durable checkpoints, and
EndSync. The chaos harness records the reference source-cache
scenario cold and warm, exports JSONL fixtures, and the Occult host
renders them onto the canonical vocabulary and checks all five
policies: 10/10 cells green, with planted-violation tests validating
the bridge itself (dropped consult reds policy 1; un-regrounded
resume reds policy 2). Rendering conventions (s1/s2 scope mapping,
structural clear for non-resumed attempts) live in the renderer; the
recorder stays purely observational.

Co-authored-by: Cursor <cursoragent@cursor.com>
…path finding

The trace-policy vocabulary gains ev_resume attempt boundaries:
durable facts persist across the marker (checkpoint-durable hit-set,
committed-row grounding, sync-scoped seal obligations) and only
once-per-scope resets — the across-attempt replay re-copy is B5-legal
at-least-once idempotence, the within-attempt duplicate stays the bug.
Matrix grows to 40 cells (green_resume + red_ops_resume). The chaos
harness exports a real crash/resume fixture (EffectCrash after the
replay unit committed, resumed to seal by a new syncer); the oracle is
15/15 green, and TestRealTraceBridgeResumeMarkerLoadBearing proves the
marker is load-bearing (stripping it reds once-per-scope).

Finding: for a mid-chain cut the resume RE-RUNS the replay copy
regardless of checkpoint cadence — checkpoints commit at batch
boundaries and a page chain runs inside one batch, so a cut chain's
MarkSourceCacheReplayed never reaches a checkpoint. The resume suite's
comments claimed the restored replayed-set skips the copy; the trace
recorder is the first instrument able to distinguish skip from
idempotent re-copy and falsified that mechanism (convergence was
always right, via B5 idempotence; the replayed-set's real skip role is
within-attempt). Comments corrected, behavior pinned.

Renderer note: consecutive checkpoints coalesce (verdict-preserving)
because engine ground-evaluation cost roughly doubles per list element
— recorded as an engine ask.

Co-authored-by: Cursor <cursoragent@cursor.com>
The delta protocol's deletion entries (DeletedIds/DeletedPrincipalIds
in the connector response — applied synchronously as row deletes,
nothing durably stored) join the trace vocabulary as ev_delete, a
WRITE with upsert's obligations: grounding (clear-before-write),
quiescent-checkpoint dirtying, and seal-activity marking.

- policies: ev_delete clauses across all five policies; four new
  fixtures (green delete + three reds) take the matrix to 60 cells
- recorder: syncTraceDelete fires per committed store delete call in
  afterUpserts (canonical and principal-scoped legs)
- exporter: tombstone delta chaos scenario with a content oracle
  (tombstoned row absent from the sealed artifact); fixture
  warm_replay_sync_tombstone.jsonl shows B3's within-page order
  (rows, tombstones, validator) directly in a real trace
- renderer: structural clear now grants to the scope's first write
  of either kind; planted ungrounded-delete validation reds
  clear-before-upsert

Real-trace oracle: 20/20 policy cells green across four fixtures.

Co-authored-by: Cursor <cursoragent@cursor.com>
Executive wrap-up of the verification effort: the three-track
verdict (calibration reds, bake-off verdict S, witnessed-conformant
real traces), the findings register (design bugs fixed in spec, the
resume-mechanism falsification, tooling asks), and the explicit
guarantee/non-guarantee boundary (witnessed vs calibrated vs
asserted linkage). README points at it as the entry document.

Co-authored-by: Cursor <cursoragent@cursor.com>
Design-doc kickoff implementing the bake-off verdict: the frozen
mechanism inventory, proposed model-to-Go referents (node = scoped
action, output key = (rowKind, scopeKey) partition), the
sibling-runtime-behind-a-capability strategy with a dual-run
conformance gate, the verification plan keeping the trace oracle
load-bearing, and the open questions that gate phase 1.

Co-authored-by: Cursor <cursoragent@cursor.com>
The 25 trace.json replay files were ~183k lines — 90% of the branch
diff. The committed evidence is now the human-readable
counterexample.txt per red cell plus the sweep summaries; replays
regenerate via each cell's `p check` line (reds reproduce at the
find rates the run log states). gitignore pins the convention.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment on lines +626 to +686
if o.s.state.SourceCacheReplayed(o.rowKind, o.scopeKey) {
// Duplicate page / lost-response retry: the copy already ran this
// sync. Replay is replacement, so re-running it would also wipe
// overlay rows upserted since. Skip the copy; apply the page's
// upserts/tombstones normally.
l.Debug("source-cache replay already completed for scope this sync; skipping copy",
zap.String("row_kind", string(o.rowKind)),
zap.String("scope_key", o.scopeKey),
)
} else {
if o.s.previousSyncReader == nil {
return newReplayIntegrityError(ReplayVerdictCold, o.rowKind, o.scopeKey,
fmt.Errorf("no previous sync artifact available to replay from"))
}
// Bind the hit to the CURRENT replay base. The eligibility gates
// cannot distinguish two artifacts from the same connector and
// config (identical compat keys), so a previous artifact swapped
// between attempts — service-mode spare replaced by a
// rollback/restore — passes every gate while its rows for this
// scope may predate the state the connector actually revalidated.
// The recorded validator is the one the connector's verdict was
// computed against; the base we copy from must still publish
// exactly it. Mismatch, absence, and read failure are all cold:
// the copy's provenance cannot be established.
reader, ok := o.s.previousSyncReader.(sourceCacheEntryReader)
if !ok {
return newReplayIntegrityError(ReplayVerdictCold, o.rowKind, o.scopeKey,
fmt.Errorf("previous sync artifact exposes no source-cache surface to verify the replay base against the recorded hit"))
}
baseEntry, found, err := reader.LookupSourceCacheEntry(ctx, o.rowKind, o.scopeKey)
if err != nil {
return newReplayIntegrityError(ReplayVerdictCold, o.rowKind, o.scopeKey,
fmt.Errorf("reading the replay base's manifest entry to verify the recorded hit: %w", err))
}
if !found {
return newReplayIntegrityError(ReplayVerdictCold, o.rowKind, o.scopeKey,
fmt.Errorf("replay base has no manifest entry for this scope: the recorded hit came from a different artifact"))
}
if baseEntry.CacheValidator != hitValidator {
return newReplayIntegrityError(ReplayVerdictCold, o.rowKind, o.scopeKey,
fmt.Errorf("replay base's validator does not match the one this sync's lookup returned: the previous artifact changed between attempts"))
}
res, err := o.s.sourceCacheStore.ReplaySourceCache(ctx, o.s.previousSyncReader, o.rowKind, o.scopeKey)
if err != nil {
return newReplayIntegrityError(replayCopyVerdict(err), o.rowKind, o.scopeKey,
fmt.Errorf("replay copy: %w", err))
}
// Trace-audit the unit's legs in the store's contractual
// clear-then-copy order (TRACE_BRIDGE.md unit expansion).
o.s.testSyncTraceAudit.record(syncTraceClear, string(o.rowKind), o.scopeKey)
o.s.testSyncTraceAudit.record(syncTraceReplay, string(o.rowKind), o.scopeKey)
if res.NeedsExpansion && !o.s.dontExpandGrants {
o.s.state.SetNeedsExpansion()
}
o.s.state.MarkSourceCacheReplayed(o.rowKind, o.scopeKey)
l.Debug("source-cache replay copied previous sync's scope rows",
zap.String("row_kind", string(o.rowKind)),
zap.String("scope_key", o.scopeKey),
zap.Int64("rows", res.Rows),
)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: the once-per-scope guard is SourceCacheReplayed, but nothing rejects a SourceCacheReplay for a scope that already had SourceCacheRecord rows applied earlier in this sync. ReplaySourceCache is a replacement copy (clear destination scope, then copy the base), so a record→replay page order for one scope silently discards the fresh rows and then afterUpserts publishes a validator over the result — silent, durable, and it seeds the next warm sync. The scope lock added for N1 gives mutual exclusion but not ordering, and with EnqueuePageTokens sibling cursors the arrival order for one scope isn't the connector's to guarantee. Consider tracking "rows recorded for this scope this sync" in state and failing cold here, the same way the no-hit and validator-mismatch gates do, rather than resting on plan B5's "cross-page ordering follows page arrival order exactly".

Comment on lines +743 to +746
if o.pageRows > 0 {
// The page's row puts committed between beforeUpserts and here.
o.s.testSyncTraceAudit.record(syncTraceUpsert, string(o.rowKind), o.scopeKey)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: o.pageRows is len(resp.GetList()) — the pre-filter count — but syncResources only calls putConnectorResources when bulkPutResoruces is non-empty, and filterConnectorData drops rows that fail validateConnectorResource. A resources page whose rows are all dropped therefore emits an upsert event with no committed write, which contradicts sync_trace_audit.go's stated contract ("every event corresponds to a store operation that actually committed"). Since the Occult trace oracle is the model-to-implementation bridge this PR rests on, a fabricated event weakens the evidence rather than production behavior. Consider recording from the actual write site (or from the post-filter row count) instead.

@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

General PR Review: Sync Formal Modeling - P & Occult

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: loaded .claude/skills/ci-review.md from trusted base 1e33787f0262.
Review mode: full
View review run

Review Summary

Scanned the full PR diff (155 files, ~31k additions) for security and correctness: the formal/ P + Occult modeling track and its verdict scripts, and the phase-6b source-cache replay orchestration production code that rides along (pkg/sync/source_cache_orchestration.go, pkg/sync/state.go token schema, pkg/dotc1z store surface, pkg/sourcecache, pkg/connectorbuilder wiring, and the additive C1ZManifestV3.sdk_materialization_generation field 44). The proto change is additive with no renumbering, both generated variants and the hand-written v3 header decoder are in sync, and the sync-token schema fence (new source_cache_hit_validators key + no v0 fallback for version-declaring tokens) correctly closes the silent-restart path. Of the three prior findings, two are addressed by the last two commits (the tc3a_P1 two-shape contract and the walker log's own coverage-limit block); the third is still open — formal/graph/CALIBRATION.md:376 still reads "eight of Monitors.p's 25 alarm strings fire in no red cell", but SEAL-WORLD fires in zero of the 66 sweep cells (only in the separate 12-cell bake-off), so the inventory is nine, not eight.

Risk triage (repo criteria §Risk Triage). Silence: YES — a wrong replay produces well-formed rows, not a crash. Durability: YES — c1z contents, checkpoint tokens, and the new manifest field outlive the process. Uncontrolled dimensions: YES — crash/checkpoint timing, worker schedule, and cross-SDK-version reads. Consumer distance: future SDK versions and the platform. Verdict: HIGH, remediation rung 3 (re-sync the fleet). The PR ships the instruments that class demands — differential cold-truth oracles, a -race chaos corpus wired into make chaos-check, cost-curve benchmarks (BenchmarkStateMarshalSourceCacheSets, BenchmarkSourceCacheScopeLocks), and a permutation table across gates/collection/resume/generational/order suites — and the nine chaos-check test names all resolve to real functions. All gate failures degrade cold rather than erroring, and G5's cross-version fold fence is compile-pinned on both sides. The one gap is a missing ordering permutation, noted below.

Security Issues

None found.

Correctness Issues

None found.

Suggestions

  • pkg/sync/source_cache_orchestration.go:634 — the replay path never consults sourceCacheScopeGrounded, leaving the record→replay page order for one scope in one attempt unguarded; a record page that grounds and writes first can have its rows wiped by the later replacement copy, or (with SourceCacheReplayed restored from a prior attempt) leave the base cleared and never re-copied. Both seal an incomplete scope under a published validator. Medium confidence; needs an out-of-contract connector, but every other out-of-contract shape in this file fails loud.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `pkg/sync/source_cache_orchestration.go`:
- Around line 593-710 (`sourceCachePageOps.beforeUpserts`): the replay branch
  never reads the attempt-local `sourceCacheScopeGrounded` set, so a
  record-only page and a replay page for the SAME (rowKind, scopeKey) in the
  same attempt are unordered. If the record page runs first, `groundRecordScope`
  clears the partition, marks it grounded, and the page's rows commit; the
  later replay page then either runs `ReplaySourceCache` (a REPLACEMENT copy
  that clears the destination scope, deleting those fresh rows) or, when
  `state.SourceCacheReplayed(rowKind, scopeKey)` was restored from a prior
  attempt, skips the copy entirely after grounding already cleared the base.
  Either way `afterUpserts` publishes a validator over an incomplete scope,
  and the next sync validates it clean and replays it forward. The scope lock
  added for CO-6b-003/N1 makes the two pages mutually atomic but does not
  order them, so under WithWorkerCount(>1) the arrival order is worker
  scheduling, not connector intent.
  Fix: in the replay branch of `beforeUpserts`, before deciding to run or skip
  the copy, check whether `sourceCacheScopeGrounded` already holds
  `sourceCacheScopeKey(o.rowKind, o.scopeKey)` while
  `o.s.state.SourceCacheReplayed(o.rowKind, o.scopeKey)` is false for this
  scope's copy having run this sync — i.e. the scope was grounded by a record
  round rather than by a replay. In that case return
  `newReplayIntegrityError(ReplayVerdictCold, o.rowKind, o.scopeKey, ...)`
  explaining that a record round already established this scope's partition
  this attempt, matching how the file already rejects two scope keys on one
  page, duplicate annotations, and `deleted_principal_ids` on an entitlements
  page. Add a permutation cell to `pkg/sync/chaos_source_cache_order_test.go`
  covering record-page-then-replay-page for one scope, in both worker counts.

In `formal/graph/CALIBRATION.md`:
- Around line 376-380: the COVERAGE LIMIT block says "eight of Monitors.p's 25
  alarm strings fire in no red cell" and lists P1-CONTENT, P1-ATTEST-PUBLISH,
  P1-ATTEST-SEAL, P1-ATTEST-EMPTY, P2-CONSULT, P2-STALENESS, P3'-COHERENCE,
  PASS-BUDGET. Scoped to the frozen 66-cell sweep the count is nine: SEAL-WORLD
  appears in zero tag sets in PCheckerOutput/sweep/summary.txt and is witnessed
  only by the separate 12-cell bake-off matrix (4 cells in
  PCheckerOutput/bakeoff/summary.txt). Either add SEAL-WORLD to the inventory
  and change "eight" to "nine" with a note that it is witnessed by the bake-off
  rather than the sweep, or restate the block's scope as "the sweep plus
  bake-off matrices" so the count matches its stated surface. Mirror the same
  correction in REPORT.md's standing-limits list, which repeats the eight-item
  graph inventory. (Previously reported; still open at f853dae8.)

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

…d grounding)

The walker model's scenario-1 red was live in the shipped syncer: a warm
round cut after its replay copy committed but before its validator
published, upstream moving between attempts, and the resume's consult
missing meant the connector's fresh record round composed with the
crashed attempt's copied debris and sealed the union under the fresh
validator — which the next sync validates clean and replays forward.

Fix: a record round is a replacement listing, so before its first write
to a scope this attempt, a partition holding rows no completed round
published is cleared. New store surface ClearSourceCacheScope (the
replay clear leg standalone), groundRecordScope under the scope lock,
attempt-local grounded set so replay/record pages of one round never
re-ground over each other; published entries are untouched, preserving
multi-action accumulation.

Witnessed and pinned by TestChaosSourceCacheRecordFlipOverReplayDebris
(content oracle + the grounding clear visible in attempt 2's trace);
fixtured as warm_replay_sync_record_flip.jsonl, and record rounds now
emit a real ev_clear ("replacement rounds clear first", previously
structural, now witnessed). Oracle 25/25 green; full sync/dotc1z suites
and lint clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment on lines +731 to +746
func (o *sourceCachePageOps) groundRecordScope(ctx context.Context) error {
key := sourceCacheScopeKey(o.rowKind, o.scopeKey)
if _, done := o.s.sourceCacheScopeGrounded.Load(key); done {
return nil
}
_, published, err := o.s.sourceCacheStore.LookupSourceCacheEntry(ctx, o.rowKind, o.scopeKey)
if err != nil {
return newReplayIntegrityError(ReplayVerdictWarm, o.rowKind, o.scopeKey,
fmt.Errorf("record grounding: reading this sync's manifest entry: %w", err))
}
if !published {
deleted, err := o.s.sourceCacheStore.ClearSourceCacheScope(ctx, o.rowKind, o.scopeKey)
if err != nil {
return newReplayIntegrityError(ReplayVerdictWarm, o.rowKind, o.scopeKey,
fmt.Errorf("record grounding: clearing un-attributed rows: %w", err))
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Bug: grounding assumes a resume always re-lists the scope from its root, but not every resume does. The crash path does restart from root (no checkpoint commits mid-chain), which is what the new witness test exercises — but the stop paths do checkpoint mid-batch: handleOperationError calls Checkpoint(ctx, true) after syncParallel returns (parallel_syncer.go:469, and checkpointOnStop at :487), and state.Marshal preserves PageToken for every op except SyncGrantExpansionOp. So a run-duration expiry (or external cancel) part-way through a paginated record round persists a mid-chain token, and already-finished sibling cursors from EnqueuePageTokens are gone from the action map entirely.

On that resume, the scope has no manifest entry yet (PutSourceCacheEntry only runs on the page that carries the validator), so groundRecordScope clears the whole partition — deleting rows attempt 1 durably committed for pages the resumed listing will never re-request. The round then publishes its validator over the truncated set, and the next sync's consult validates it clean and replays it forward: exactly the non-self-healing laundering this fix targets, with missing grants instead of phantom ones. This is silent + durable, and it now also applies to plain cold syncs of any MODE_READ_WRITE connector that paginates a scope.

Grounding needs to be conditioned on the round actually starting from the scope's root — e.g. blank the source-cache-scoped actions' page tokens at marshal time the way the expansion token is blanked, or carry a durable per-scope "grounded this sync" marker instead of the volatile attempt-local set.

Comment on lines +1350 to +1352
func (e *Engine) ClearSourceCacheScope(ctx context.Context, rowKind string, scopeKey string) (int64, error) {
var recordType byte
var prefix []byte

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: ClearSourceCacheScope now runs once per scope per attempt on the default record path, including every cold sync, and each call takes withWrite (serializing against all other writers), builds a NewIter over the scope prefix and allocates a NewRecordBatch even when the partition is born empty. BenchmarkSourceCachePageOps still documents that "no store I/O happens until beforeUpserts/afterUpserts, whose costs are engine-level and benchmarked in pkg/dotc1z/engine/pebble" — but there is no benchmark for this method, only BenchmarkSourceCacheReplay*. Per the repo's cost-contract rule, a new per-scope store operation on the hot path wants a stated cost-curve delta in scope count and a benchmark pinning the empty-partition case.

Comment on lines +33 to +38
clearScopeErr error
}

func (f *fakeSourceCacheStore) ClearSourceCacheScope(context.Context, sourcecache.RowKind, string) (int64, error) {
return 0, f.clearScopeErr
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: clearScopeErr is declared and read by the stub but never set by any test, so both groundRecordScope error paths (manifest-lookup failure and clear failure, each producing a ReplayVerdictWarm replay-integrity error) are unexercised, as is the "already grounded → skip" branch. Engine.ClearSourceCacheScope likewise has no direct unit test — the only coverage is the end-to-end chaos witness. A couple of table cases here would pin the verdict classification cheaply.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking issues found — see review comments.

… (CO-6b-009)

Connector session-store writes are durable in the artifact but commit
outside the checkpoint mechanism, so a resumed attempt inherited the
crashed attempt's cached premises — undetectably, since the connector's
process restarted and sessions were the only surviving state. Under the
source-cache protocol that channel can launder replay-era caches into
rounds whose rows the resume re-grounds (the record-grounding fix clears
the row partition; nothing re-validates session state derived from it).
Sessions have no publish/validation concept, so the attempt boundary is
the only fence 6b has.

groundSessionStoreOnResume: a resumed attempt of a participating sync
clears its session namespace before any connector RPC. Non-participating
syncs keep the long-standing semantics; a capability-withdrawn resume
(CO-6b-003) degrades wholesale as before. Witnessed both ways by
TestChaosSourceCacheSessionGroundingOnResume (probe cleared on a
participating resume, kept on a withdrawn one).

The within-attempt remainder is contractual, pinned in pkg/sourcecache
and pkg/session/README.md: replayed scopes produce no generation-side
session state, and replay/record verdicts must come from upstream
evidence, never session-cached answers. Change order CO-6b-008/009
registered in the 6b plan; REPORT finding extended.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread pkg/sync/source_cache_orchestration.go Outdated
if !ok {
return nil
}
if err := provider.SessionStore().Clear(ctx, sessions.WithSyncID(s.syncID)); err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: this clears the store-side session surface, which sits below the connector's own session-store stack. The established clear (connectorbuilder.builder.Cleanup, connectorbuilder.go:377) goes through b.sessionStore — the same handle passed to list calls as SyncOpAttrs.Session (resource_syncer.go:142) — which in the _connector-service and lambda-server topologies is cli.NewLazyCachingSessionStoresession.MemorySessionCache (otter, 10-min write expiry, explicitly documented as "potentially used across syncs"). A crashed attempt runs no Cleanup, so if the connector process outlives the attempt its in-memory cache still holds the pre-crash values and Get serves them straight past this grounding — the exact stale premise CO-6b-009 fences. The witness test uses the direct in-process chaos transport with no caching layer, so it can't observe this. Either route the clear through the delivered session-store handle, or state the "connector process must not outlive the attempt / must not memoize session values across calls" assumption explicitly in pkg/sourcecache and pkg/session/README.md.

Comment thread pkg/sync/source_cache_orchestration.go Outdated
if s.sourceCacheStore == nil {
return nil
}
provider, ok := s.store.(sessionStoreProvider)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: this assertion can never fail — s.store is statically c1zstore.Store, which already declares SessionStore() sessions.SessionStore (pkg/dotc1z/c1zstore/c1zstore.go:62), so sessionStoreProvider is not an optional capability the way expandedGrantLayerStorer is. The !ok branch is unreachable dead code today, and if the field type is ever narrowed it turns into a silent disable of the fence (no error, no log). Prefer calling s.store.SessionStore() directly so a type change is a build break, or at minimum log/return an error on the missing-capability path.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

…iene

The engine author flagged our axiom universals as unconstrained
(unconstrained-axiom-universal). Adopting the prescribed fix is not
possible today: gating a rewrite universal on a userspace sort of free
constructors requires membership evidence that axiom-side dispatch
never receives, so member-only ground terms stop reducing (probed in
all four documented membership forms; built-in classifiers gate
correctly). New probe suite pins today's behavior and fails loudly
when the engine closes the gap — the signal to constrain the modules.
Modules document the discipline (head-guarded LHS on module-local
constructors); lint noise dropped: canonical ∃, removed a require-
shadowing declaration and stale per-line disable pragmas.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment on lines +861 to +886
if o.rowKind == sourcecache.RowKindResources {
// The store contract requires Baton resource BIDs for resource
// tombstones; a malformed id is a connector bug that fails
// deterministically before any write, so it must not read warm.
for _, id := range canonical {
if !strings.HasPrefix(id, "bid:r:") {
return newReplayIntegrityError(ReplayVerdictCold, o.rowKind, o.scopeKey,
fmt.Errorf("resource tombstone %q is not a Baton resource BID (bid:r:...)", id))
}
}
}
if len(canonical) > 0 {
if err := o.s.sourceCacheStore.DeleteSourceCacheRows(ctx, o.rowKind, o.scopeKey, canonical); err != nil {
return newReplayIntegrityError(ReplayVerdictWarm, o.rowKind, o.scopeKey,
fmt.Errorf("canonical-id tombstones: %w", err))
}
o.s.testSyncTraceAudit.record(syncTraceDelete, string(o.rowKind), o.scopeKey)
}
principals := append(append([]string{}, o.replay.GetDeletedPrincipalIds()...), o.record.GetDeletedPrincipalIds()...)
if len(principals) > 0 {
if _, err := o.s.sourceCacheStore.DeleteSourceCacheRowsInScope(ctx, o.rowKind, o.scopeKey, principals); err != nil {
return newReplayIntegrityError(ReplayVerdictWarm, o.rowKind, o.scopeKey,
fmt.Errorf("principal-scoped tombstones: %w", err))
}
o.s.testSyncTraceAudit.record(syncTraceDelete, string(o.rowKind), o.scopeKey)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: the doc on afterUpserts says "Deterministic input-shape failures (a malformed tombstone id the store can never resolve) are cold — retrying them warm cannot succeed", but the only shape check implemented is the bid:r: prefix guard for resources; every other store rejection is classified ReplayVerdictWarm. DeleteSourceCacheRows still rejects a bid:r:-prefixed but otherwise malformed id via bid.ParseResourceBid, rejects ambiguous grant ids in DeleteGrantRecordsBounded, and can reject entitlement ids — all deterministic connector-input bugs that will re-fail identically on every retry. Latent today (nothing consumes the verdict until 6c), but once the runner ladder honors warm, these become an unbounded warm-retry loop instead of a cold fallback. Consider classifying DeleteSourceCacheRows / DeleteSourceCacheRowsInScope id-resolution failures as cold (e.g. a sentinel from the store's id-parse/ambiguity paths) rather than relying on the prefix approximation. (confidence: medium-high)

// attempt debris) is cleared before the round's first write.
// Idempotent; deletes commit in bounded chunks, so retry converges.
// Returns rows deleted.
ClearSourceCacheScope(ctx context.Context, kind sourcecache.RowKind, scopeKey string) (int64, error)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: SourceCacheStore is an exported interface and this PR adds three methods to it (ClearSourceCacheScope, PutSourceCacheCompat, GetSourceCacheCompat). Any downstream implementation — a test fake, an alternate store — stops compiling, and pkg/sdk/version.go is not touched in this PR, so there is no version signal for the break. Per .claude/skills/ci-review.md, signature-surface changes need at least a 0.x minor bump plus a note. The doc says it is "implemented ONLY by the Pebble engine", which keeps real-world blast radius small; if that is the intent, consider either unexporting it / moving it behind an internal package, or calling the break out in the PR description and bumping the version. (confidence: high on the change, medium on impact)

Comment thread formal/walker/tools/sweep.sh Outdated
Comment on lines +73 to +76
p check -tc "$cell" -s "$S" -o "$OUT/$cell" > "$OUT/$cell.log" 2>&1
ce=$(ls "$OUT/$cell"/BugFinding/walker_[0-9]*_[0-9]*.txt 2>/dev/null | head -1)
if [ -n "$ce" ]; then observed="RED"; else observed="GREEN"; fi
if [ "$observed" = "$expected" ]; then mark="ok"; else mark="MISMATCH"; mismatches=$((mismatches + 1)); fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: p check's exit status is discarded and the verdict is inferred purely from the absence of a counterexample file, so every way the checker can fail to produce output — p not installed, a P-spec compile error, a typo'd -tc name, OOM, a full disk — records observed=GREEN. Every GREEN-expected cell then reports ok, and the checked-in PCheckerOutput/sweep/summary.txt reads as partially-passing evidence for a run that never ran. The script already distrusts the "Found N bugs" tail; it should also distrust a silent no-output run. Capture rc=$? after p check and emit a third ERROR verdict (counted as a mismatch) when the checker exits nonzero or leaves no output directory. formal/graph/tools/sweep.sh:109 has the identical shape. (confidence: high)

…6b-009)

The resume-time session-namespace clear shipped in ab99c65 was
unsound: resume restores the action queue from the checkpoint and
completed actions never re-run, so a wholesale clear destroys session
caches whose producing work will not execute again (accumulate-then-
consume). The change also rewrote the session contract to match the
fix ("attempt-scoped") rather than fixing to the contract.

The hazard analysis stands and is now documented honestly: session
writes commit outside the checkpoint mechanism (verified in code, not
model-derived — the formal models contain no session store), so a
resumed attempt inherits the dead attempt's state including writes
from beyond the restored cursor. Resolution is contractual (no
once-only decisions via sessions; consult verdicts never from session
caches; session state silently partial for replayed scopes), with the
correct mechanical fence — checkpoint-consistent sessions via a
volatile overlay flushed atomically with the checkpoint — registered
as future work in the 6b plan.

TestChaosSourceCacheSessionPersistsAcrossResume replaces the grounding
test: the probe must survive resume with AND without the capability,
standing guard against reintroducing a resume-time clear.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread pkg/sync/syncer.go
}
// Replay copy precedes the page's own rows (frozen order: replay copy →
// page upserts → page tombstones).
if err := scOps.beforeUpserts(ctx); err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: the per-scope mutex acquired here is held until afterUpserts at line 2971, which spans the related-resource loop — including s.store.GetResource per grant and the s.getResourceFromConnector connector RPC at line 2939. The lock's stated purpose (beforeUpserts doc) is to keep the replay copy and the page's row application atomic per scope; it does not need to cover connector fetches. At workerCount > 1, every page of the same scope serializes behind those network calls, and a slow upstream stalls the whole scope. Consider narrowing the held window to beforeUpsertsPutGrants/afterUpserts by moving the related-resource fetch loop before beforeUpserts (it writes only unstamped resource rows).

Comment thread pkg/sync/state.go
// ≤256 bytes, validators typically ETag/delta-token sized), re-sorted
// and re-serialized into the sync token on every checkpoint —
// O(scopes·log scopes) per checkpoint, pinned by
// BenchmarkStateMarshalSourceCacheSets. A connector whose scope count

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: this cost bound assumes "validators typically ETag/delta-token sized", but nothing enforces it. cache_validator is an unbounded connector-supplied proto string, and the only validation on the whole path is a non-emptiness check (pkg/dotc1z/source_cache.go:237, Engine.PutSourceCacheEntry). Its sibling input is capped — sourcecache.ValidateScopeKey rejects scope keys over 256 bytes. Before CO-6b-004 the validator was stored once in the Pebble manifest; now every warm-lookup hit copies it into sourceCacheHits, which Marshal re-serializes into the sync token on every checkpoint, so a connector emitting multi-KB (or worse) validators across many scopes multiplies checkpoint size and live memory with no gate. BenchmarkStateMarshalSourceCacheSets prices the curve but cannot bound it. Consider a sourcecache.ValidateCacheValidator length cap applied at PutSourceCacheEntry and at RecordSourceCacheHit.

Comment on lines +731 to +757
func (o *sourceCachePageOps) groundRecordScope(ctx context.Context) error {
key := sourceCacheScopeKey(o.rowKind, o.scopeKey)
if _, done := o.s.sourceCacheScopeGrounded.Load(key); done {
return nil
}
_, published, err := o.s.sourceCacheStore.LookupSourceCacheEntry(ctx, o.rowKind, o.scopeKey)
if err != nil {
return newReplayIntegrityError(ReplayVerdictWarm, o.rowKind, o.scopeKey,
fmt.Errorf("record grounding: reading this sync's manifest entry: %w", err))
}
if !published {
deleted, err := o.s.sourceCacheStore.ClearSourceCacheScope(ctx, o.rowKind, o.scopeKey)
if err != nil {
return newReplayIntegrityError(ReplayVerdictWarm, o.rowKind, o.scopeKey,
fmt.Errorf("record grounding: clearing un-attributed rows: %w", err))
}
o.s.testSyncTraceAudit.record(syncTraceClear, string(o.rowKind), o.scopeKey)
if deleted > 0 {
ctxzap.Extract(ctx).Warn("record grounding cleared un-attributed rows from a prior attempt",
zap.String("row_kind", string(o.rowKind)),
zap.String("scope_key", o.scopeKey),
zap.Int64("rows", deleted),
)
}
}
o.s.sourceCacheScopeGrounded.Store(key, struct{}{})
return nil

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion (medium confidence): the "no published manifest entry ⇒ un-attributed debris" premise holds for a single paginated cursor (CO-6b-002 restarts it at its root), but not for a scope accumulated by several actions. FinishAction/FinishParentAction delete the completed action from st.actions/st.spawnedInFlight, so a sibling action that finished, stamped rows into scope S, and published no validator is not re-executed after a resume — yet the resumed attempt's first record page for S sees published == false and clears the whole partition. Those rows are then gone from the sealed artifact and, once a later action publishes S's validator, the truncated scope replays forward as if complete. This is the pattern the plan explicitly contemplates ("multi-action accumulation into shared scopes", and the EnqueuePageTokens planning-call fan-out documented on state.sourceCacheHits), so the manifest-entry exemption may be too narrow: consider also exempting scopes with a durable "written this sync by a completed action" marker, or requiring every action that stamps a shared scope to publish.

Worth a chaos cell: two actions (or two EnqueuePageTokens siblings) record into one scope, cut after the first finishes and before any validator publishes, then assert the first action's rows survive the resume.

Comment thread Makefile
chaos-check: ## Run bounded representative chaos checks under race detection.
go test -race -count=1 ./internal/chaosconnector/...
go test -race -count=1 -timeout=10m -run '^TestChaosConnector(LostResponseThenFilesystemFailureResumes|ResourcesAndEntitlementsFaultMatrix|ListGrantsFaultMatrix|ReservedBatonIDOwnershipIsRejected|MalformedKnownAnnotationFailsWithoutSealing|ClearedNextPageTokenSealsOnlyVisiblePrefix|CancellationTerminatesAndColdResumes|DataPolicyLifecycleCorpus|ExternalPrincipalResumeUsesCurrentExternalAnswer|SQLiteExternalPrincipalResumeDegradesWithoutFailure|ExternalPrincipalCleanupUsesOnePassPerKeyspace)$$' ./pkg/sync
go test -race -count=1 -timeout=10m -run '^TestChaosSourceCache(GateMatrix|CollectionSemantics|InterruptResume|GenerationalSteadyState|CompatDriftOnResume|ReplayWithoutHitFailsCold|DriftedResumeRejectsRestoredReplay|DuplicateReplayCursorsParallel|UnsupportedShapesBlockReplaySeed)$$' ./pkg/sync

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: all nine names in this -run regex exist, but TestChaosSourceCacheRecordFlipOverReplayDebris — the named Go-side witness for CO-6b-008 (the phantom-union defect this branch found and fixed) — is not in the bounded set, so it only runs under chaos-full-check/nightly. The primary regression witness for the headline defect is worth having in the representative set.

Comment thread pkg/sync/state.go
Comment on lines +69 to +72
RecordSourceCacheHit(rowKind sourcecache.RowKind, scopeKey string, cacheValidator string)
SourceCacheHitValidator(rowKind sourcecache.RowKind, scopeKey string) (string, bool)
MarkSourceCacheReplayed(rowKind sourcecache.RowKind, scopeKey string)
SourceCacheReplayed(rowKind sourcecache.RowKind, scopeKey string) bool

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: sync.State is an exported interface, so adding four methods is a source-compatibility break for any downstream var _ sync.State = ... pin or wrapper. Impact is limited in practice — there is no exported way to inject a State into a syncer (newState is unexported and no SyncOpt accepts one), so this is a compile-pin break rather than a functional one. Still, per the repo's SDK criteria this plus the new exported surface (ErrReplayIntegrity, ReplayVerdict, SyncOpAttrs.Lookup, sourcecache.CompatKey) is minor-bump material and pkg/sdk/version.go is unchanged at v0.25.1.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

Two findings from the PR's incremental review of the round-1 commit.

The bake-off split regressed the audit: tools/bakeoff.sh carried
sweep.sh's verdict logic but not its firing-monitor extraction, so a
cell was audited for counterexample PRESENCE only. The six GREEN
cells stayed protected (a spurious counterexample flips them to
MISMATCH), but the six expected-RED cells would have recorded "ok" on
a deadlock or liveness counterexample — below the "every red on its
calibrated alarm" standard the calibration program rests on — and the
committed summary carried none of the tags CALIBRATION.md's prose
asserts. bakeoff.sh now extracts and records the alarm, and the
regenerated run of record reads [EXEC-BOUND] on the two G6b probes
and [SEAL-WORLD] on the four reachable-world probes, 12/12, zero
mismatches.

A verbatim port would not have sufficed: sweep.sh's alternation has
SEAL-EXPECT but not SEAL-WORLD, which is exactly what the G5d cells
assert, so those four reds would have been tagged empty. SEAL-WORLD
is added to both scripts (output-neutral for the frozen 66 cells —
the hyphenated string appears only in that assert's message) so a
cell moved between the scripts keeps its tagging. CALIBRATION.md now
states the audit property instead of only asserting the alarms.

Also deleted the orphaned s_rogue / probe_rogue fixture from
probeConstrainedSrc: round 1 moved the refusal assertion to
probeBuiltinSrc (the module with a working positive), leaving that
module's rogue term unreferenced and liable to read as still
exercised. All three constrained-params probes pass.

The review's third item (occult/README.md "all five policies") was
already fixed in the round-2 dispositions.

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

Round-3 review batch. The sweep/bake-off scripts previously ended on a
tee pipeline, so a drifted run read as a green make; now they fail
loudly:
- nonzero exit on any mismatch
- a counterexample-free nonzero p-check exit is CHECKER-ERROR, not
  GREEN ("no bug found" from a checker that died is not evidence)
- an untagged red (firing monitor outside the alternation, or rg
  missing - now guarded) is a MISMATCH
- the bake-off's declared alarms are ENFORCED, not just recorded, and
  the graph alternation is hoisted into tools/alarms.sh (one copy,
  sourced by both scripts)
- tcG5dS_W2 pins --sch-feedbackpct=20: its find is seed-bimodal under
  uniform random (one full-10k seed explored 18 timelines and found
  nothing; five other seeds all found within ~500 schedules at a 0.23%
  buggy-schedule rate) - caught by the hardened gate's own first
  parity run and registered in CALIBRATION.md
- refimpl: drop the write-only durable.checkpoint field (sibling of
  the already-removed hasMarker)

Validated by a planted-violation harness (wrong alarm, unrecognized
monitor, checker crash, drift verdicts, missing rg - each fails with
the right summary line and exit status) and a full bake-off run
through the final script: 12/12 match, exit 0, committed summary
reproduced byte-for-byte. Refimpl build/vet and all four oracle tests
green.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment on lines +52 to +56
case "$rest" in *:*)
rest="${rest#*:}"
alarm="${rest%%:*}"
case "$rest" in *:*) strategy="${rest#*:}";; esac
;; esac

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion (medium confidence): the two scripts' CELLS grammars are now positionally incompatible — sweep.sh reads field 3 as strategy, bakeoff.sh reads it as alarm. Since moving a cell between the scripts is an anticipated operation (alarms.sh and the header comments both reason about it), a sweep entry like tcG2awWA_E:RED:--sch-feedbackpct=20 pasted here parses as alarm="--sch-feedbackpct=20", strategy="": the search pin is silently dropped and the alarm assertion can never match, so the cell permanently reports MISMATCH. For a GREEN cell the drop is fully silent, because the alarm branch is never entered. Consider rejecting a field-3 value that starts with -- (or that is not in MONITOR_ALTERNATION) with a loud parse error, matching the rest of this commit's "never fail quietly" posture.

Comment on lines +38 to +39
tcG5dE_W2:RED:SEAL-WORLD
tcG5dS_W2:RED:SEAL-WORLD:--sch-feedbackpct=20

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion (medium confidence): only the S leg of W2 gets the pin, but CALIBRATION.md's own diagnosis attributes the bimodality to the target ("Some seeds evidently cannot reach the target at all"), and both legs declare the same target {0→1, 1→1} (CALIBRATION.md:392-393). This commit also promotes a miss from a summary line to a nonzero exit that fails make formal-graph-bakeoff, and under GS-CO-005(d) a leg deviating from its declared verdict under exactly one variant is a divergence finding blocking Axis-3 citation — so a seed-unlucky tcG5dE_W2 would now surface as a variant asymmetry rather than a recognizable flake. Either pin the E leg too, or record its measured uniform-random find rate in CALIBRATION.md as the evidence that it is not bimodal.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

Review items:
- bakeoff.sh grammar guard: the fields are positional and the alarm is
  only consulted on the RED branch, so a strategy flag written in the
  alarm slot (cell:GREEN:--flag) was dropped SILENTLY - the cell ran
  without its intended search and still reported ok. Now rejected at
  parse time with the strategy-only form (cell:expected::--flag) in
  the message; validated with a planted scratch run (exit 2).
- sweep headers now state the exit-status division of labor: p check's
  exit gates only the GREEN side (absence of a find from a checker
  that died proves nothing); a found counterexample stands regardless.
- TRACE_BRIDGE Mapping 1: the graph overlay unit also announces
  upserts and tombstones, and its G8b composeDead INJECT branch
  announces the copy with NO clear at all - by design, that missing
  clear IS the tcG8bMut_P1 kill. Stated as the one exception so a
  hand-renderer cannot mask the injected red by supplying a clear the
  model never announced (review comment from the r3899 wave).
- Makefile formal comment untangled: tag differences on multi-shape
  RED cells are exit-0 noise; a missed find fails the gate by design.

Full-pass validation, all through the hardened scripts:
- walker sweep 55/55, exit 0, summary byte-identical
- graph sweep 66/66, exit 0, summary byte-identical
- bake-off 12/12, exit 0, summary byte-identical (prior run)
- Occult host suite green against the engine's ground-eval-perf
  branch (6785def4): full suite in ~32 min wall vs 75+ before -
  verdict-preserving across the laws, MPST, 140-cell policy matrix,
  real-trace fixtures (both standing red pins intact), and refimpl.

Also: cell lists cross-checked against committed evidence (55/66/12
exact), both alternations verified to cover their monitors' full
assert vocabularies, no stale counts or dead refs.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread Makefile
Comment on lines +328 to +331
# shapes) diffs the summary but still exits 0, while a RED cell that
# MISSES its find fails the gate by design — that has happened once,
# from seed-bimodal search on a narrow target, and the remedy is a
# per-cell strategy pin (see the tcG5dS_W2 note in graph CALIBRATION).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: this comment prescribes "a per-cell strategy pin" as the remedy for a missed RED find across both sweeps, but only formal/graph/tools/sweep.sh (field 3 = strategy) and bakeoff.sh (field 4) can express one — formal/walker/tools/sweep.sh parses cell:expected with ${entry##*:} and passes no strategy to p check, so a walker pin lands in expected and reports expected=--sch-feedbackpct=20 … MISMATCH rather than pinning anything. Either give the walker sweep the same optional strategy field (plus the grammar guard this commit adds to bakeoff.sh) or scope this sentence to the graph scripts.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

A PR review comment on the sweep's cell list was stale on all three
of its claims (it predates the trace-archive purge, the probe-cell
row, and the rewritten archival contract), but re-running the
cell-vs-row audit it implied found the real gap next door: scenario 4
(duplicate replay carriers, MODEL_SPEC §9 case 4) has been in every
sweep since the v11 freeze yet never had a section in CALIBRATION.md.
Added with the frozen verdicts; no cell or expectation changed. The
graph log audits clean under the same check (its G3/G4/G6-G9 families
are deliberately collective-prose sections).

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

Review follow-up on the round-4 guard: (1) bakeoff.sh's alarm-slot
guard matched only --* so a single-dash flag still fell through and
was silently dropped on a GREEN cell — the exact failure the guard
exists to stop; alarm names never begin with a dash, so -* is safe.
(2) sweep.sh's mirror field (third field = strategy) had no shape
check, so an entry pasted in from bakeoff's 4-field grammar handed
p check an alarm name as a bogus positional argument; it now fails
loudly at parse time with the grammar named. Both guards exercised
via stub-checker runs: bad entries exit 2 before any checker call,
good entries (real flag; empty-alarm form) still reach GREEN.
Also answered the standing Makefile evidence note: the 2026-09-01
full pass re-ran every cell through the gated scripts and reproduced
all committed summaries byte-identically, which is why no post-gate
summary commit exists.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment on lines +736 to +755
_, published, err := o.s.sourceCacheStore.LookupSourceCacheEntry(ctx, o.rowKind, o.scopeKey)
if err != nil {
return newReplayIntegrityError(ReplayVerdictWarm, o.rowKind, o.scopeKey,
fmt.Errorf("record grounding: reading this sync's manifest entry: %w", err))
}
if !published {
deleted, err := o.s.sourceCacheStore.ClearSourceCacheScope(ctx, o.rowKind, o.scopeKey)
if err != nil {
return newReplayIntegrityError(ReplayVerdictWarm, o.rowKind, o.scopeKey,
fmt.Errorf("record grounding: clearing un-attributed rows: %w", err))
}
o.s.testSyncTraceAudit.record(syncTraceClear, string(o.rowKind), o.scopeKey)
if deleted > 0 {
ctxzap.Extract(ctx).Warn("record grounding cleared un-attributed rows from a prior attempt",
zap.String("row_kind", string(o.rowKind)),
zap.String("scope_key", o.scopeKey),
zap.Int64("rows", deleted),
)
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Bug: "un-published rows" is not the same set as "crashed-attempt debris". The annotation proto explicitly allows a multi-page record round to carry an empty cache_validator on interim pages (SourceCacheRecord.cache_validator: "May be empty on interim pages of a multi-page scope"), so a round in progress has committed rows and no manifest entry. If the sync is cut after page N commits and checkpoints, the resume continues at page N+1 (action.PageToken), sourceCacheScopeGrounded is empty, LookupSourceCacheEntry finds nothing published, and ClearSourceCacheScope deletes pages 1..N — rows that will never be re-listed. The final page then publishes a validator over the truncated partition, so the sealed artifact silently loses rows and replays the truncated scope forward warm.

Suggest distinguishing "debris from a dead attempt" from "rows this round already committed" durably — e.g. record a per-(rowKind, scopeKey) round-grounding marker in the store as part of the same commit as the first grounded page, and skip the clear when the checkpointed action's page token shows the round is mid-flight rather than restarting.

Comment on lines +45 to 49
func (c *directClient) SetSourceCache(ctx context.Context, lookup sourcecache.Lookup) {
if setter, ok := c.server.(sourcecache.SetLookup); ok {
setter.SetSourceCache(ctx, lookup)
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: directClient (and GRPCClient at line 65) satisfy sourcecache.SetLookup structurally but silently drop the lookup when c.server is not a SetLookup, and neither implements sourcecache.LookupDeliverabilityProbe — so installSourceCacheLookup presumes them deliverable, sets sourceCacheWarm = true, and logs "warm" while the connector actually observes NoopLookup. That is exactly the CO-6b-001 false-warm shape the probe exists to close, and these are the only in-tree delivering transports, so a harness misconfiguration would produce silently vacuous warm-path tests. Consider implementing SourceCacheLookupDeliverable() on both (returning whether the server implements SetLookup).

Comment thread pkg/sync/state.go
Comment on lines +613 to +625
if err != nil {
// A token that DECLARES a version is a v1+ token whose full
// parse failed (corrupt, or a field's shape changed under a
// reused key). Falling back to v0 here would misparse it —
// the v0 struct ignores the unknown v1 fields, "succeeds"
// with an empty action stack, and the resume silently
// restarts as a fresh sync. Fail loud instead; only tokens
// without a version field are genuinely v0.
var probe struct {
Version *uint64 `json:"version"`
}
if probeErr := json.Unmarshal([]byte(input), &probe); probeErr == nil && probe.Version != nil {
return fmt.Errorf("syncer token declares version %d but failed to parse: %w", *probe.Version, err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: this converts a previously self-healing failure into a permanently wedged sync. The token lives in the store, so Syncstate.Unmarshal(currentStep) will return this same error on every subsequent attempt; nothing in pkg/tasks/c1api/full_sync.go or pkg/tasks/local/syncer.go reacts by abandoning the sync and starting a fresh one. Failing loud instead of silently restarting is the right direction, but the loud failure needs an escape hatch (a distinct sentinel error the runners can map to "discard the checkpoint and start cold", or an automatic fresh-sync fallback here) or a corrupt v1 token blocks the tenant indefinitely.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking issues found — see review comments.

…ister unwitnessed-clause inventory

Round-5 review found the first substantive gaps in several waves,
all three verified real. (1) tc8overDelete_P8: P8-EXT-MISSING had no
kill — the over-deletion direction of the external-principal seal
clause was asserted, not calibrated (P8's other two clauses and the
P6-C pattern both witness bidirectionally). The kill models a LATE
stale-sweep whose predicate mistakes a live principal for stale;
placement is itself a model fact: the engine-ordered early pass
(delete-stale before copy) is structurally self-healing for
over-deletion because the page-1 copy rewrites every listed id.
Sweep regenerated: 56 cells, 0 mismatches. (2) pipeline_test.go
discarded LoadExpressions' error — a silent failure there would turn
every negative control vacuous (an empty e-graph refuses every
equivalence, which is what the controls assert); now t.Fatalf like
every other engine call, equivalence suites re-run green. (3) The
remaining asserted-but-unwitnessed alarm strings (walker 3, graph 8)
are inventoried in REPORT.md's standing limits and the graph
CALIBRATION so the green matrices are not over-read; the graph
eight are walker-inherited oracles whose graph-side implementations
are calibrated only by review.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread formal/walker/CALIBRATION.md Outdated

| cell | config | property | expected | observed | budget |
|---|---|---|---|---|---|
| tc3a_P1 | shipped (`hitValidatorBinding` ON) — the residual hole | P1 | RED | RED: `P1-CONTENT` is the archived sweep's first find (carrier-first/interleaved content shape); the `P1-ATTEST-SEAL` carrier-last shape (rows(B) sealed under entry V_A) is also live in the config — both require the re-consult's lookup-hit V_B to OVERWRITE the hit map before the carrier's LIVE hit read (last-write-wins rebind) | first find (0.34% of 10k — narrow: needs C dispatched after P's re-consult transition) |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: This row still says ``P1-CONTENT is the archived sweep's first find, but this commit updates the archived run of record to `tc3a_P1 ... ok [P1-ATTEST-SEAL]` (`PCheckerOutput/sweep/summary.txt`). `tools/sweep.sh` explicitly designates CALIBRATION.md — not the script — as "the comparison surface for WHICH monitor fired," so the audit surface and the run of record now disagree and nothing mechanical catches it. Since the row already documents both shapes as live in this config, updating the parenthetical to name `P1-ATTEST-SEAL` as the current archive's find (and, if intended, noting that the first-find shape flipped when the `extOverDelete` config field changed the exploration order) restores the audit. (confidence: high)

Comment on lines +376 to +380
COVERAGE LIMIT of the frozen matrix (registered post-freeze; no cell
or expectation changed): eight of Monitors.p's 25 alarm strings fire
in no red cell — P1-CONTENT, P1-ATTEST-PUBLISH, P1-ATTEST-SEAL,
P1-ATTEST-EMPTY, P2-CONSULT, P2-STALENESS, P3'-COHERENCE,
PASS-BUDGET. They are the walker-inherited content/attestation/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: Scoped to "the frozen matrix" (the 66-cell sweep this paragraph follows), the count is nine, not eight: SEAL-WORLD also fires in no red cell of PCheckerOutput/sweep/summary.txt. It is witnessed only by the separate 12-cell bake-off matrix (PCheckerOutput/bakeoff/summary.txt, 4 cells), which tools/alarms.sh already records ("SEAL-WORLD is asserted only by the bake-off's tcG5d* cells"). A reader regenerating this inventory from the sweep summary alone gets a different answer than the registered one; a half-sentence qualifier naming SEAL-WORLD as bake-off-witnessed makes the count reproducible. REPORT.md's "8 of its 25" is fine as written since it says "frozen matrices" plural. (confidence: medium-high)

# Walker calibration — run log

Status: COMPLETE. CURRENT GATE: the 56-cell full-matrix sweep, 0
mismatches, every red on its calibrated alarm (`tools/sweep.sh`, 10k

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: The graph leg registers its unwitnessed-clause inventory in its own CALIBRATION.md and mirrors it to REPORT.md; the walker's three (P1-ATTEST-EMPTY, P1-ATTEST-PUBLISH, P2-CONSULT) are registered only in REPORT.md. Since this log is the run-of-record audit surface and its status line asserts "every red on its calibrated alarm," a matching COVERAGE LIMIT note here would keep the two legs symmetric and stop the 56-cell green from being over-read by a reader who only opens the walker log. (confidence: medium)

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No new blocking issues found in this increment. Note that the four findings from the previous review are untouched by these commits and still stand — see the summary comment.

… the two-shape contract

Both doc-only, closing the round-6 bot pass: the tc3a_P1 row now
states its conformance contract explicitly (either P1-CONTENT or
P1-ATTEST-SEAL is calibrated — which trips first is seed luck — and
any OTHER alarm is real drift), so a reader diffing the run of record
against this log has a check for the shape flip instead of a stale
"first find" claim; and the walker log now carries the mirror of the
graph's COVERAGE LIMIT block (P1-ATTEST-EMPTY, P1-ATTEST-PUBLISH,
P2-CONSULT are asserted, not calibrated), kept minimal with the
shared doctrine pointed at REPORT.md to avoid a third drifting copy.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment on lines +634 to +643
if o.s.state.SourceCacheReplayed(o.rowKind, o.scopeKey) {
// Duplicate page / lost-response retry: the copy already ran this
// sync. Replay is replacement, so re-running it would also wipe
// overlay rows upserted since. Skip the copy; apply the page's
// upserts/tombstones normally.
l.Debug("source-cache replay already completed for scope this sync; skipping copy",
zap.String("row_kind", string(o.rowKind)),
zap.String("scope_key", o.scopeKey),
)
} else {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: the replay path never consults sourceCacheScopeGrounded, so the record→replay page order for one scope in one attempt is unguarded (the reverse order is). If a record-only page for scope S runs first, groundRecordScope clears/writes and marks the scope grounded; a later replay page for S then either (a) runs the replacement copy — ReplaySourceCache clears the destination scope, deleting the record page's fresh rows — or (b) with SourceCacheReplayed(S) restored from a prior attempt, skips the copy entirely after this attempt's grounding already cleared the base. Both end in a scope sealed under a published validator with rows missing, which the next sync validates clean and replays forward.

This needs the connector to emit both verdicts for one scope (out of contract), but every other out-of-contract shape in this file fails loud (two scope keys per page, duplicate annotations, deleted_principal_ids on entitlements) rather than silently producing a wrong durable artifact. Consider: if sourceCacheScopeGrounded already holds the key when the replay path is entered and the copy has not run this sync, return newReplayIntegrityError(ReplayVerdictCold, ...). Confidence: medium — the ordering permutation isn't covered by TestChaosSourceCacheOrderingAdversary. (Also worth noting the scope lock added for CO-6b-003/N1 makes record and replay pages mutually atomic but does not order them, so parallel mode leaves the arrival order to worker scheduling rather than the connector.)

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

@kans

kans commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

subsumed into other work

@kans kans closed this Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant