Skip to content

fix(graph-db): layer a linked worktree over its sibling's graph - #3071

Open
devin-ai-integration[bot] wants to merge 3 commits into
masterfrom
devin/1791126302-worktree-graph-base
Open

devin-ai-integration[bot] wants to merge 3 commits into
masterfrom
devin/1791126302-worktree-graph-base

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • A linked worktree's first code generation (no same-scope parent) now layers over a sibling scope's installed flat sealed graph of the same projector, instead of sealing every row again.
  • The sibling base container is hard-linked into the layer. When the delta finishes, the base's relations are re-attested under the worktree projection, which gives the row sum and recovered digest a cold build records. The layer keeps its own namespace, generation, marker and verified head.

Motivation

Fixes #2402. A primary sealed graph of about 51 MB grew to about 76 MB after adding an identical linked worktree, because the projection-exact GraphLayeredRowSpill::create rejected any base from another namespace.

Changes

  • sealed_store.rs / registry/publication.rs: sibling_sealed_bases lists installed flat (non-layered) sealed generations of the same projector under other namespaces of the same project GraphDb. This uses the sealed registry, with no filesystem scan and no new shared map. sibling_layered_row_spill opens a delta over one of them.
  • sealed_layer.rs: GraphSiblingSealedBaseV1, GraphLayeredRowSpill::create_over_sibling, and GraphSealedBaseV1::reattested, which streams the base relations under the child projection into the layer's own row index (the shared base index is never rewritten). finish re-attests before it checks the projection.
  • generation.rs: GraphGenerationManifestIdentity::stored_under records the physical namespace where the base rows actually live. SealedBaseReceiptV1::identity restores it on reopen.
  • generation/recovered.rs / row_index.rs: recovered_relation_lanes and RowIndex::write_with_relation_lanes.
  • code_graph_manifest.rs / code_graph.rs: LayeredBaseV1::{Parent, Sibling}. Generations with no parent try sibling bases. Correctness comes from the normal layered delta against the base (any rows that differ go into the delta), not from assuming the trees are identical. An identical tree produces a one-row delta.

Not covered by the test: the test does not assert that the primary's old directory is physically removed. That generation stays retained here because the primary's next generation is itself layered over it, so it is a replay dependency. The base bytes are hard links, so removing the primary directory would not unlink the layer's copy.

Test plan

  • New regression test layered_refresh_tests::a_linked_worktree_at_the_same_tree_layers_over_its_siblings_sealed_graph. It seals a primary, adds an identical git worktree and seals it, then checks:
    • the linked generation is layered over the primary generation;
    • base.grafeo is the same inode as the primary generation.grafeo;
    • the delta is 1 row (the marker);
    • the linked generation matches a cold build (digest, rows, symbols/callers/callees/exact lookup/file deps);
    • after an edit in the linked worktree, the two diverge and the primary is unchanged.
    • unset RUST_LOG && bash scripts/require-exact-test.sh cargo test -p tracedecay-store-runtime --lib session_registry::code_graph::layered_refresh_tests::a_linked_worktree_at_the_same_tree_layers_over_its_siblings_sealed_graph -- --exact: 1 passed. With the production changes stashed, it fails with "the linked worktree layers over its sibling".
  • cargo test -p tracedecay-store-runtime --lib session_registry::code_graph: 50 passed, 2 ignored
  • cargo test -p tracedecay-graph-db: 150 passed, 1 ignored
  • cargo fmt --all -- --check, cargo clippy -p tracedecay-graph-db -p tracedecay-store-runtime --all-targets -- -D warnings: clean
  • python3 scripts/linux-test-partitions.py check and node scripts/lint-commit-range.mjs --repository . origin/master HEAD: pass
  • Full cargo nextest run --workspace left to CI

Checklist

  • CHANGELOG.md updated (not updated)
  • No secrets, credentials, or .env files included
  • Breaking changes documented (none)

Link to Devin session: https://app.devin.ai/sessions/a95fd88f68bd47058c44696790e4d379
Open in Devin Desktop: https://app.devin.ai/desktop/session/a95fd88f68bd47058c44696790e4d379?variant=devin
Requested by: @ScriptedAlchemy


Devin Review

A linked worktree's first generation at the same tree resealed every
row of the graph its sibling scope already sealed. It now layers over the
sibling's installed flat sealed generation of the same projector: the
base container is hard-linked and its relations are re-attested under
the worktree projection, so the delta is just the generation marker and
the row sum and digest match a cold build.

Fixes #2402

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@changeset-bot

changeset-bot Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 6424361

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

devin-ai-integration[bot]

This comment was marked as resolved.

Re-attestation buffered every relation's identity and lanes before
rewriting the row index. Each relation's lanes are now written into a
copy of the index as they are recovered, so memory no longer grows with
the sibling's relation count.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Re-attestation read the sibling's original row index and entity row
offsets, which vanish if the sibling retires after the layer pins them.
It now reads the hard-linked copies in the layer directory.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

This branch has not been deployed

No deployments
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.

worktree sharing: linked worktree duplicates the sealed graph at same tree

1 participant