Skip to content

Sealed code generation cannot seat: graph activation loops on 'code graph database conflict' every retry, no generation ever serves #765

Description

@ScriptedAlchemy

Observed on the operator daemon (proj_a5b3d7e3ebe14ca7), 2026-08-31, PR #707 tip binary

After the #762 fix handoff (pin adb623efecb7, binary built from PR branch + #764 shutdown lane), the operator daemon runs memory-stable (HWM 29.9 GiB, RSS returning to ~14 GiB after each phase, no OOM in 2+ hours — the #762 shape is gone). But the code index never converges to a serving generation:

  • The startup active generation is refused: active generation is incompatible with the production owner configuration (expected after the binary upgrade — sanitizer/chunker/policy revisions moved).
  • The scheduler stages and seals a fresh generation (staging finished ~07:46, sealed artifact tracedecay.sealed/278bea7a…).
  • Every graph activation attempt fails with code-index graph projection failed: code graph database conflict (GraphDbError::Conflict), including attempts made after the fresh seal (07:48, 07:58, 08:11, spaced by the 600 s seat backoff). Each attempt burns ~30–70 s before failing, consistent with a full replay/verification pass.
  • event=code_index_graph_activation_retry_scheduled repeats forever; retention passes log no code generation is currently serving for this project and graph_replay_release_failed error=DeadlineExceeded every ~100 s.

Journal state at the time (read-only sqlite, project db)

  • graph_publication_replay_v1: newest code rows are sequences 10 and 11 (two code-scope namespaces); newest overall is 14 (project-memory). No new journal row was ever written for the freshly sealed generation — the publish conflicts before journaling.
  • graph_publication_replay_tombstones_v1: empty.
  • graph_verified_heads_v1: heads exist at replay sequences 6, 7, 8, 10, 11 (five code-scope namespaces).

So the wedge is deterministic and pre-journal: GraphPublicationOperations prepare/replay returns Conflict on every attempt for both the crashed incarnation's sealed generation and a freshly sealed one. Candidate sites are the expected-prior-head mismatch arm (registry/publication.rs, the return Err(GraphDbError::Conflict) after the historical-seat guard) and the sealed-digest mismatch checks; the mapped Conflict is fieldless, so the log line carries no discriminating context.

Why this matters

Repro pointers

  • Live daemon PID 2408079 journal, 06:29–08:15 UTC window (journalctl --user -u tracedecay.service), plus RSS curves in /fast/tmp/td-sem-verify/rss5.ndjson.
  • The wedge survived a clean daemon restart (same conflicts on the prior incarnation from 06:36) and a fresh seal, so it reproduces from the durable journal + store state.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions