sidegraph 0.6.0__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (397) hide show
  1. {sidegraph-0.6.0 → sidegraph-0.7.0}/CHANGELOG.md +195 -0
  2. {sidegraph-0.6.0 → sidegraph-0.7.0}/CLAUDE.md +1 -1
  3. {sidegraph-0.6.0 → sidegraph-0.7.0}/PKG-INFO +2 -2
  4. {sidegraph-0.6.0 → sidegraph-0.7.0}/README.md +1 -1
  5. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/concepts/anchoring.md +34 -6
  6. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/concepts/mind-model.md +7 -7
  7. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/concepts/retrieval.md +58 -25
  8. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/getting-started/claude-code-setup.md +13 -6
  9. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/getting-started/codex-setup.md +10 -2
  10. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/guides/capturing-decisions.md +19 -7
  11. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/guides/retrieval-in-sessions.md +14 -4
  12. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/guides/semantic-docs.md +3 -2
  13. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/guides/surviving-refactors.md +41 -5
  14. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/guides/verifying-your-setup.md +3 -2
  15. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/integrations/claude-code.md +69 -25
  16. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/integrations/codex.md +53 -6
  17. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/integrations/graphify.md +65 -6
  18. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/reference/cli.md +17 -4
  19. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/reference/configuration.md +27 -9
  20. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/reference/hooks.md +194 -42
  21. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/reference/mcp-tools.md +42 -0
  22. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/reference/operations.md +1 -1
  23. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/reference/store-format.md +10 -1
  24. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/.claude-plugin/plugin.json +1 -1
  25. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/.codex-plugin/plugin.json +1 -1
  26. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/codex/hooks.json +2 -2
  27. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/hooks/hooks.json +3 -3
  28. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/record-decision/SKILL.md +9 -6
  29. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/record-fact/SKILL.md +5 -3
  30. {sidegraph-0.6.0 → sidegraph-0.7.0}/pyproject.toml +1 -1
  31. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/__init__.py +1 -1
  32. sidegraph-0.7.0/src/sidegraph/config.py +533 -0
  33. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/doctor.py +36 -0
  34. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/engine/reader.py +332 -6
  35. sidegraph-0.7.0/src/sidegraph/freshness.py +59 -0
  36. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/host/hooks.py +435 -95
  37. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/retrieval.py +157 -71
  38. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/schema.py +12 -1
  39. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/server.py +222 -18
  40. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/stats/model.py +16 -1
  41. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/stats/render.py +23 -3
  42. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/store.py +135 -12
  43. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/sync.py +226 -49
  44. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/auto_policy/parity_goldens.json +1 -1
  45. sidegraph-0.7.0/tests/fixtures/member_names_python_graph.json +109 -0
  46. sidegraph-0.7.0/tests/fixtures/member_names_swift_graph.json +77 -0
  47. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_graph_paths.py +1 -1
  48. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_sync.py +7 -4
  49. sidegraph-0.7.0/tests/test_config_ancestor_lookup.py +265 -0
  50. sidegraph-0.7.0/tests/test_config_borrowed_graph.py +279 -0
  51. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_digest_integrity.py +23 -0
  52. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_docs_claims.py +33 -0
  53. sidegraph-0.7.0/tests/test_doctor_graph_stale.py +90 -0
  54. sidegraph-0.7.0/tests/test_graph_freshness.py +552 -0
  55. sidegraph-0.7.0/tests/test_hook_spawn_guard.py +291 -0
  56. sidegraph-0.7.0/tests/test_host_agent_state.py +300 -0
  57. sidegraph-0.7.0/tests/test_host_borrowed_graph.py +288 -0
  58. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_host_pretool.py +6 -6
  59. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_host_session_start.py +171 -6
  60. sidegraph-0.7.0/tests/test_host_session_start_concurrent.py +151 -0
  61. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_host_stop.py +658 -24
  62. sidegraph-0.7.0/tests/test_host_subdirectory_launch.py +282 -0
  63. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_host_touch_events.py +1 -1
  64. sidegraph-0.7.0/tests/test_member_anchor_wiring.py +320 -0
  65. sidegraph-0.7.0/tests/test_reader_member_names.py +369 -0
  66. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_toc.py +180 -3
  67. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_schema_descriptor.py +34 -0
  68. sidegraph-0.7.0/tests/test_server_borrowed_graph.py +543 -0
  69. sidegraph-0.7.0/tests/test_server_graph_freshness.py +373 -0
  70. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_graph_path.py +3 -2
  71. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_render_events.py +1 -1
  72. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_stats_graph.py +47 -0
  73. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_stats_render.py +97 -0
  74. sidegraph-0.7.0/tests/test_store_agent_state.py +282 -0
  75. sidegraph-0.7.0/tests/test_store_binding_index.py +91 -0
  76. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_mutation_guard.py +19 -1
  77. sidegraph-0.7.0/tests/test_store_update_meta_if.py +60 -0
  78. sidegraph-0.7.0/tests/test_sync_canonical_writes.py +171 -0
  79. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_sync_clean.py +11 -10
  80. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_sync_integration.py +10 -7
  81. sidegraph-0.7.0/tests/test_sync_moved_adoption.py +708 -0
  82. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_sync_rebind.py +25 -16
  83. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_sync_run.py +11 -8
  84. sidegraph-0.7.0/tests/test_sync_toc_cache.py +251 -0
  85. {sidegraph-0.6.0 → sidegraph-0.7.0}/uv.lock +1 -1
  86. sidegraph-0.6.0/src/sidegraph/config.py +0 -259
  87. sidegraph-0.6.0/tests/test_sync_toc_cache.py +0 -125
  88. {sidegraph-0.6.0 → sidegraph-0.7.0}/.agents/plugins/marketplace.json +0 -0
  89. {sidegraph-0.6.0 → sidegraph-0.7.0}/.claude-plugin/marketplace.json +0 -0
  90. {sidegraph-0.6.0 → sidegraph-0.7.0}/.github/CODEOWNERS +0 -0
  91. {sidegraph-0.6.0 → sidegraph-0.7.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  92. {sidegraph-0.6.0 → sidegraph-0.7.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  93. {sidegraph-0.6.0 → sidegraph-0.7.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  94. {sidegraph-0.6.0 → sidegraph-0.7.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  95. {sidegraph-0.6.0 → sidegraph-0.7.0}/.github/secret_scanning.yml +0 -0
  96. {sidegraph-0.6.0 → sidegraph-0.7.0}/.github/workflows/ci.yml +0 -0
  97. {sidegraph-0.6.0 → sidegraph-0.7.0}/.github/workflows/publish.yml +0 -0
  98. {sidegraph-0.6.0 → sidegraph-0.7.0}/.github/workflows/scorecard.yml +0 -0
  99. {sidegraph-0.6.0 → sidegraph-0.7.0}/.github/workflows/session-link-gate.yml +0 -0
  100. {sidegraph-0.6.0 → sidegraph-0.7.0}/.gitignore +0 -0
  101. {sidegraph-0.6.0 → sidegraph-0.7.0}/.gitleaks.toml +0 -0
  102. {sidegraph-0.6.0 → sidegraph-0.7.0}/.pre-commit-config.yaml +0 -0
  103. {sidegraph-0.6.0 → sidegraph-0.7.0}/.python-version +0 -0
  104. {sidegraph-0.6.0 → sidegraph-0.7.0}/AGENTS.md +0 -0
  105. {sidegraph-0.6.0 → sidegraph-0.7.0}/CODE_OF_CONDUCT.md +0 -0
  106. {sidegraph-0.6.0 → sidegraph-0.7.0}/CONTRIBUTING.md +0 -0
  107. {sidegraph-0.6.0 → sidegraph-0.7.0}/LICENSE +0 -0
  108. {sidegraph-0.6.0 → sidegraph-0.7.0}/SECURITY.md +0 -0
  109. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/README.md +0 -0
  110. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/concepts/data-model.md +0 -0
  111. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/concepts/decision-memory.md +0 -0
  112. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/getting-started/bootstrap.md +0 -0
  113. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/getting-started/installation.md +0 -0
  114. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/getting-started/quickstart.md +0 -0
  115. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/guides/ci-cd-maintenance.md +0 -0
  116. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/guides/naming-your-domains.md +0 -0
  117. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/guides/team-workflow.md +0 -0
  118. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/llms.txt +0 -0
  119. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/pilot-kit/README.md +0 -0
  120. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/pilot-kit/corpus_fit.py +0 -0
  121. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/pilot-kit/judge-prompt.md +0 -0
  122. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/pilot-kit/questions-prompt.md +0 -0
  123. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/pilot-kit/rubric-template.md +0 -0
  124. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/reference/git-bindings.md +0 -0
  125. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/reference/releasing.md +0 -0
  126. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/reference/stability.md +0 -0
  127. {sidegraph-0.6.0 → sidegraph-0.7.0}/docs/whitepaper/index.md +0 -0
  128. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/.mcp.json +0 -0
  129. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/codex/mcp.json +0 -0
  130. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/check-plan/SKILL.md +0 -0
  131. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/check-plan/agents/openai.yaml +0 -0
  132. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/explain-why/SKILL.md +0 -0
  133. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/explain-why/agents/openai.yaml +0 -0
  134. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/heal-anchors/SKILL.md +0 -0
  135. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/heal-anchors/agents/openai.yaml +0 -0
  136. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/import-adrs/SKILL.md +0 -0
  137. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/import-adrs/agents/openai.yaml +0 -0
  138. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/manage-domains/SKILL.md +0 -0
  139. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/manage-domains/agents/openai.yaml +0 -0
  140. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/name-domains/SKILL.md +0 -0
  141. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/name-domains/agents/openai.yaml +0 -0
  142. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/ratify-decisions/SKILL.md +0 -0
  143. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/ratify-decisions/agents/openai.yaml +0 -0
  144. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/record-decision/agents/openai.yaml +0 -0
  145. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/record-fact/agents/openai.yaml +0 -0
  146. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/setup/SKILL.md +0 -0
  147. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/setup/agents/openai.yaml +0 -0
  148. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/stats/SKILL.md +0 -0
  149. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/stats/agents/openai.yaml +0 -0
  150. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/triage-drift/SKILL.md +0 -0
  151. {sidegraph-0.6.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/triage-drift/agents/openai.yaml +0 -0
  152. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/anchoring.py +0 -0
  153. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/__init__.py +0 -0
  154. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/apply.py +0 -0
  155. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/catalog.py +0 -0
  156. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/cli.py +0 -0
  157. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/integrations.py +0 -0
  158. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/model.py +0 -0
  159. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/planner.py +0 -0
  160. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/proof.py +0 -0
  161. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/review.py +0 -0
  162. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/scan.py +0 -0
  163. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/capture.py +0 -0
  164. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/cli.py +0 -0
  165. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/doc_import.py +0 -0
  166. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/domains.py +0 -0
  167. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/engine/__init__.py +0 -0
  168. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/gitenv.py +0 -0
  169. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/gitio.py +0 -0
  170. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/host/__init__.py +0 -0
  171. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/host/claude_settings.py +0 -0
  172. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/importer.py +0 -0
  173. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/okf.py +0 -0
  174. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/profiles.py +0 -0
  175. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/stats/__init__.py +0 -0
  176. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/verify.py +0 -0
  177. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/viz/__init__.py +0 -0
  178. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/viz/assets/vis-network.min.js +0 -0
  179. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/viz/model.py +0 -0
  180. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/viz/render.py +0 -0
  181. {sidegraph-0.6.0 → sidegraph-0.7.0}/src/sidegraph/viz/template.html +0 -0
  182. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/__init__.py +0 -0
  183. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/conftest.py +0 -0
  184. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/bitfinex_slice.json +0 -0
  185. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/flows/bmad/_bmad-output/planning-artifacts/architecture/cache/ARCHITECTURE-SPINE.md +0 -0
  186. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/flows/generic-adr/docs/adr/001-retry.md +0 -0
  187. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/flows/genkovich-sdd/docs/features/cache/adr/001.md +0 -0
  188. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/flows/spec-kit/specs/cache/plan.md +0 -0
  189. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/flows/superpowers/docs/superpowers/specs/2026-07-01-cache-design.md +0 -0
  190. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/graph.json +0 -0
  191. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/hosts/claude/.claude/settings.json +0 -0
  192. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/hosts/claude/.mcp.json +0 -0
  193. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/hosts/codex/.codex/config.toml +0 -0
  194. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/hosts/codex/.codex/hooks/hooks.json +0 -0
  195. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/scan/docs/adr/001-safe.md +0 -0
  196. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/corpus/PUBLIC_CORPORA.txt +0 -0
  197. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/corpus/openspec/_provenance.json +0 -0
  198. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/corpus/openspec/graph.json +0 -0
  199. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/corpus/self-corpus/_provenance.json +0 -0
  200. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/corpus/self-corpus/expected/retrieval-engine-reader.md +0 -0
  201. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/corpus/self-corpus/graph.json +0 -0
  202. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/adr/0001-use-sessions.md +0 -0
  203. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/bmad/ARCHITECTURE-SPINE.md +0 -0
  204. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/bmad/tree/_bmad-output/planning-artifacts/architecture/architecture-payments-2026-07-30/.memlog.md +0 -0
  205. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/bmad/tree/_bmad-output/planning-artifacts/architecture/architecture-payments-2026-07-30/ARCHITECTURE-SPINE.md +0 -0
  206. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/bmad/tree/_bmad-output/planning-artifacts/prds/prd-payments-2026-07-30/prd.md +0 -0
  207. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/genkovich/0001-queue-backpressure.md +0 -0
  208. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/genkovich/sad.md +0 -0
  209. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/adr/0001-queue-backpressure.md +0 -0
  210. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/sad.md +0 -0
  211. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/spec.md +0 -0
  212. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/design-empty.md +0 -0
  213. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/design-h3-split.md +0 -0
  214. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/design-with-summary.md +0 -0
  215. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/design.md +0 -0
  216. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/proposal-alternatives.md +0 -0
  217. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/proposal.md +0 -0
  218. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/design.md +0 -0
  219. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/proposal.md +0 -0
  220. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/specs/cap/spec.md +0 -0
  221. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/tasks.md +0 -0
  222. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/changes/archive/2026-01-01-add-thing/design.md +0 -0
  223. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/changes/archive/2026-01-01-add-thing/proposal.md +0 -0
  224. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/config.yaml +0 -0
  225. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/specs/cap/spec.md +0 -0
  226. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/spec-kit/plan.md +0 -0
  227. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/spec-kit/tree/specs/003-payment-retries/plan.md +0 -0
  228. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/spec-kit/tree/specs/003-payment-retries/spec.md +0 -0
  229. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/superpowers/2026-07-01-example-design.md +0 -0
  230. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/flows/superpowers/2026-07-01-thin-design.md +0 -0
  231. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/fixtures/mini_graph.json +0 -0
  232. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_anchoring.py +0 -0
  233. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_anchoring_mapping_refresh.py +0 -0
  234. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_bootstrap_apply.py +0 -0
  235. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_bootstrap_catalog.py +0 -0
  236. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_bootstrap_cli.py +0 -0
  237. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_bootstrap_integrations.py +0 -0
  238. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_bootstrap_model.py +0 -0
  239. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_bootstrap_planner.py +0 -0
  240. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_bootstrap_proof.py +0 -0
  241. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_bootstrap_review.py +0 -0
  242. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_bootstrap_scan.py +0 -0
  243. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_capture_auto_accept.py +0 -0
  244. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_capture_facts.py +0 -0
  245. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_capture_initiative.py +0 -0
  246. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_capture_integration.py +0 -0
  247. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_capture_neighbors.py +0 -0
  248. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_capture_propose.py +0 -0
  249. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_capture_redact.py +0 -0
  250. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_compact.py +0 -0
  251. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_doctor.py +0 -0
  252. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_domains.py +0 -0
  253. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_import.py +0 -0
  254. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_init.py +0 -0
  255. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_okf.py +0 -0
  256. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_ratify.py +0 -0
  257. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_ratify_facts.py +0 -0
  258. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_stats.py +0 -0
  259. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_sync_check.py +0 -0
  260. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_unreadable_paths.py +0 -0
  261. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_cli_viz.py +0 -0
  262. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_codex_plugin.py +0 -0
  263. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_community_baseline.py +0 -0
  264. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_config.py +0 -0
  265. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_corpus_expected_renders.py +0 -0
  266. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_corpus_self_corpus.py +0 -0
  267. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_coverage_telemetry_e2e.py +0 -0
  268. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_doc_corpus_integration.py +0 -0
  269. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_doc_import.py +0 -0
  270. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_doctor.py +0 -0
  271. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_doctor_auto_share.py +0 -0
  272. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_doctor_code_drift.py +0 -0
  273. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_doctor_dangling_supports.py +0 -0
  274. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_doctor_duplicate_entity.py +0 -0
  275. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_doctor_graph_root_mismatch.py +0 -0
  276. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_doctor_never_surfaced.py +0 -0
  277. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_doctor_scan.py +0 -0
  278. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_doctor_stale_instructions.py +0 -0
  279. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_doctor_unratified_accept.py +0 -0
  280. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_domains.py +0 -0
  281. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_entity_duplicate_resolution.py +0 -0
  282. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_entity_get_or_create_race.py +0 -0
  283. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_env_isolation.py +0 -0
  284. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_fact_reachability_gate.py +0 -0
  285. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_flow_profile.py +0 -0
  286. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_git_bindings_blame.py +0 -0
  287. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_git_bindings_hook.py +0 -0
  288. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_git_bindings_provenance.py +0 -0
  289. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_git_env.py +0 -0
  290. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_host_claude_settings.py +0 -0
  291. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_host_drift_nudge.py +0 -0
  292. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_host_session_key.py +0 -0
  293. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_importer.py +0 -0
  294. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_mind_model_additive_fields.py +0 -0
  295. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_okf.py +0 -0
  296. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_openspec_profile.py +0 -0
  297. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_pathless_descriptor_adoption.py +0 -0
  298. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_pilot_kit_corpus_fit.py +0 -0
  299. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_proposal_lifecycle.py +0 -0
  300. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_ratify_listing_gone_dark.py +0 -0
  301. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_ratify_policy.py +0 -0
  302. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_reader_community_labels.py +0 -0
  303. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_reader_doc_nodes.py +0 -0
  304. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_reader_graph.py +0 -0
  305. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_reader_integration.py +0 -0
  306. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_reader_nodes_in_file.py +0 -0
  307. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_reader_perf.py +0 -0
  308. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_reader_rationale.py +0 -0
  309. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_reader_read.py +0 -0
  310. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_reader_resolve.py +0 -0
  311. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_reader_subdir_mismatch.py +0 -0
  312. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_reader_version.py +0 -0
  313. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_redaction_seeded.py +0 -0
  314. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_repoint_integration.py +0 -0
  315. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_budget_counters.py +0 -0
  316. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_context.py +0 -0
  317. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_drift_marker.py +0 -0
  318. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_drilldown.py +0 -0
  319. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_facts.py +0 -0
  320. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_ids.py +0 -0
  321. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_integration.py +0 -0
  322. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_rank.py +0 -0
  323. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_seeds.py +0 -0
  324. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_shown_ids.py +0 -0
  325. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_terminal_evidence.py +0 -0
  326. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_thin_tools.py +0 -0
  327. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_toptier.py +0 -0
  328. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_retrieval_unratified.py +0 -0
  329. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_sandbox_hygiene.py +0 -0
  330. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_schema_domain.py +0 -0
  331. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_schema_fact.py +0 -0
  332. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_add_anchors.py +0 -0
  333. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_anchoring.py +0 -0
  334. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_capture.py +0 -0
  335. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_coverage_events.py +0 -0
  336. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_domains.py +0 -0
  337. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_drilldown.py +0 -0
  338. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_facts.py +0 -0
  339. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_find_entity.py +0 -0
  340. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_get_store.py +0 -0
  341. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_get_task_context.py +0 -0
  342. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_import.py +0 -0
  343. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_mcp_smoke.py +0 -0
  344. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_prewrite_anchor_validation.py +0 -0
  345. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_ratify_facts.py +0 -0
  346. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_redaction.py +0 -0
  347. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_supersede.py +0 -0
  348. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_sync_anchors.py +0 -0
  349. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_telemetry.py +0 -0
  350. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_thin_tools.py +0 -0
  351. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_server_verify.py +0 -0
  352. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_stats_model.py +0 -0
  353. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_stats_skill.py +0 -0
  354. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_stats_snapshot.py +0 -0
  355. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store.py +0 -0
  356. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_atomic_write_tmp_names.py +0 -0
  357. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_canonical_stat.py +0 -0
  358. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_compact.py +0 -0
  359. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_compact_review.py +0 -0
  360. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_concurrent_open.py +0 -0
  361. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_coverage_telemetry.py +0 -0
  362. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_derived_community.py +0 -0
  363. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_domains.py +0 -0
  364. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_entities.py +0 -0
  365. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_fact_cascade.py +0 -0
  366. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_facts.py +0 -0
  367. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_meta.py +0 -0
  368. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_migration.py +0 -0
  369. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_mutation_immediate.py +0 -0
  370. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_opens_with_merged_duplicate.py +0 -0
  371. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_persistence.py +0 -0
  372. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_ratification.py +0 -0
  373. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_rebuild_atomicity.py +0 -0
  374. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_record_identity.py +0 -0
  375. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_render_events.py +0 -0
  376. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_retrieval.py +0 -0
  377. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_slug_conflicts.py +0 -0
  378. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_stamping_marker.py +0 -0
  379. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_symlinks.py +0 -0
  380. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_telemetry.py +0 -0
  381. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_threading.py +0 -0
  382. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_store_tmp_sweep_age.py +0 -0
  383. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_sync_domains.py +0 -0
  384. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_sync_drift_cache.py +0 -0
  385. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_sync_fresh_clone.py +0 -0
  386. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_sync_repoint.py +0 -0
  387. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_sync_report_has_findings.py +0 -0
  388. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_sync_volatile_heal.py +0 -0
  389. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_sync_wiring.py +0 -0
  390. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_telemetry_retention.py +0 -0
  391. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_verify_snapshot.py +0 -0
  392. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_verify_transitions.py +0 -0
  393. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_viz_asset_packaged.py +0 -0
  394. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_viz_model.py +0 -0
  395. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_viz_render_html.py +0 -0
  396. {sidegraph-0.6.0 → sidegraph-0.7.0}/tests/test_viz_render_json.py +0 -0
  397. {sidegraph-0.6.0 → sidegraph-0.7.0}/tools/check_no_session_links.py +0 -0
@@ -7,6 +7,201 @@ interfaces, exactly, and what each one promises: [`docs/reference/stability.md`]
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.7.0] — 2026-10-02
11
+
12
+ ### Changed
13
+
14
+ - **The hooks and the MCP server look a missing relative store up inside the repository.** The
15
+ precedence between `--db`, `SIDEGRAPH_DIR`, `SIDEGRAPH_DB` and the default is unchanged, and a
16
+ store that exists where its relative path is anchored still wins. What is new: when a relative
17
+ `SIDEGRAPH_DIR` (or the default `.sidegraph`) does not exist there, the three hooks and the MCP
18
+ server visit the parent directories, nearest first, up to and including the repository root (the
19
+ nearest directory holding a `.git` entry, a directory or a file), and use the first store found.
20
+ The lookup never leaves the repository (a `.git` entry at your home directory or above it is not
21
+ a repository root, so a dotfiles repository does not turn `~/.sidegraph` into every project's
22
+ store) and does not run for `--db`, an absolute `SIDEGRAPH_DIR`, `SIDEGRAPH_DB`, a value with a
23
+ `..` part, or an anchor that is a symlink. The CLI, `sidegraph-init`
24
+ and `sidegraph-bootstrap` are unchanged: from a subdirectory they still need `--db`. To keep the
25
+ old outcome on a host surface, pass an absolute `SIDEGRAPH_DIR`.
26
+
27
+ ### Fixed
28
+
29
+ - **A SessionStart hook registered twice on one host no longer injects the map twice.** Two
30
+ copies firing for one session at once both read the old duplicate-check ledger and both emitted;
31
+ the check now decides and stamps inside one write transaction, and a duplicate still answers
32
+ without waiting for a lock. The ledger keeps one row, so a repeat is still let through when
33
+ another session starts in between, or when two sessions with doubled hooks start together.
34
+ - **Sync's moved rung adopts only a real move.** When an anchor's file is gone, sync looks the
35
+ name up across the whole graph and follows a unique hit to its new file. That lookup ignores
36
+ case and decoration, and the check behind it (the old path is out of `HEAD`, the new one is in
37
+ it) did not ask whether the new path was there before. A type deleted together with its file
38
+ could therefore be re-anchored onto an unrelated file that held an old member of the same name:
39
+ a deleted `Priority` followed `.priority` into another file, silently rewriting the entity's
40
+ committed `descriptor.file_path`. Two rules now close it. The hit must be the same name once
41
+ the call decoration (`()`, a leading `.`) is stripped from both sides, with case kept. And git
42
+ must show the new path arriving in the change that removed the old one: the mainline commit that
43
+ deleted the old path (a branch merged with `--no-ff` counts as one change) must have a first
44
+ parent without the new path and must hold it itself. With `SIDEGRAPH_TRUST_DIRTY_TREE=on` and the
45
+ old path still in `HEAD`, the new path must be absent from `HEAD`. Every git failure refuses, as
46
+ does a history with no deletion in it, so a move out of a path git never held (a gitignored
47
+ directory) and a move that a shallow clone cannot prove now end `orphaned`, which
48
+ `sidegraph:heal-anchors` repairs, instead of being adopted. An uncommitted delete onto a path
49
+ that is already in `HEAD` is `orphaned` too, not remembered as a move waiting for a commit: no
50
+ commit can make it one. The search matches the old path literally (a path such as
51
+ `app/[id]/view.tsx` is not a glob) and ignores `log.showSignature`.
52
+
53
+ Some real moves are refused as well, because git's history alone does not show them as one
54
+ change. Each ends `orphaned` and `sidegraph:heal-anchors` re-anchors it:
55
+ - the new file added in one commit and the old one deleted in another on the first-parent line,
56
+ including a branch merged fast-forward or rebase-merged;
57
+ - a second move before any sync ran (`A` to `B` to `C` while the descriptor still names `A`);
58
+ - an old path that was re-added and then deleted again.
59
+
60
+ To check what an earlier release adopted, list the descriptor rewrites:
61
+ `git log -p --diff-filter=M -- .sidegraph/entities/ | grep -E '^(commit |[-+]\s+"file_path")'`.
62
+ A rewrite is a real move only if the new path was added by the commit that deleted the old one
63
+ (`git log --first-parent -m -1 --diff-filter=D -- <old path>` finds that commit; the new path
64
+ must be missing from its first parent and present in it). Re-anchor a wrong one by superseding
65
+ the record with fresh anchors.
66
+
67
+ - **The `SessionStart` instruction names a call the tool accepts, and a domain's mistake count
68
+ counts what the domain holds.** The standing line told the agent to call
69
+ `get_task_context(seeds)`, but the tool takes `files` and `entities` and rejects anything else,
70
+ so an agent that followed it made a call that failed validation. It now says
71
+ `get_task_context(files=[…])` with repo-relative paths, points at the check-plan skill before a
72
+ non-trivial change when it is available, and says to load the tool first if the host lists it
73
+ only by name. Separately, the per-domain count in the `SessionStart` map read "0 mistake(s)"
74
+ over a domain whose gotchas were anchored to its own code, because it counted only decisions
75
+ tagged to the domain itself. It now counts the accepted `gotcha`, `lesson` and `constraint`
76
+ decisions that `drill_down` serves for the domain, so the two show one number. The map's cache
77
+ records the store's digest, so a retrieval call on an unchanged store no longer rebuilds it, and
78
+ `SessionStart` reads the unratified list without building the whole map. The bindings table gains
79
+ an index by entity (an existing store gets it on its next open), which takes a rebuild of the map
80
+ from about 0.1 s to under 0.03 s on a real store, so the cost of a session start is what it was
81
+ before the count changed, also right after a store change and in a linked worktree. A worktree
82
+ builds its map with the main checkout's graph reader, so it counts the same decisions the main
83
+ checkout does. A map written by a path that has no graph reader (ratify, capture) leaves out
84
+ decisions anchored to a whole document until the next sync.
85
+
86
+ - **A Claude Code subagent gets its own read nudges, and its touches are told apart.** A
87
+ subagent's hook payload carries its parent's session id plus an `agent_id` of its own, and
88
+ the `PreToolUse` nudge keys were per session: once the main agent had been nudged, every
89
+ subagent it started read anchored files blind. Each agent, the session's own and every
90
+ subagent, now gets one generic and one path-specific nudge. The
91
+ keys are claimed in a single statement, so a subagent's parallel opening reads cannot both
92
+ nudge, and `SessionStart` expires keys older than 30 days. The `retrieval_events` journal
93
+ gains a nullable `agent` column, added to an existing index on its next open, that records
94
+ which subagent made a touch; the row stays under the parent's session, so `sidegraph-stats`
95
+ counts the same sessions as before. Only `agent_id` counts, never `agent_type`: a main
96
+ session started with `claude --agent <name>` is still the session's own agent.
97
+
98
+ - **An anchor written `Type.member` now resolves to the member.** Graphify labels a method
99
+ `.playClip()` and links it to its type, an agent writes `AudioPlayback.playClip`, and the two
100
+ never met: the anchor was born orphaned, and a seed naming it never reached the record, which
101
+ surfaced only through its community, as an unratified proposal. With a `file_path`, a name
102
+ with no exact match now falls back to a member of the named type in that file. It is for code
103
+ identifiers only (prose, a numbered heading or a hyphenated file name never reads as a
104
+ member). The name is split at the last `.`, `::` or `#` and the member is compared with its
105
+ case kept. A candidate that an edge ties to a different type is refused, and the answer stays
106
+ orphaned, never guessed, when several remain or when the file holds a case-only twin of the
107
+ member (a struct `Message` beside a method `.message()`, which the store treats as one
108
+ anchor). Without a file, and for a path-qualified name (`src/pkg/mod.py`), nothing changes.
109
+ On the read path a seed that names a stored anchor, and every node a seed resolves to, now
110
+ map to their store entities by the engine mapping, in the neighbour walk as well, so such a
111
+ record ranks as a mistake or decision again. The first `sidegraph-sync` after the upgrade
112
+ reruns once on its own (the sync stamp now carries a resolver revision, which a report does
113
+ not show) and heals the orphans this left behind. The skills and guides no longer say
114
+ `Type.member` names never resolve; the bare name with its file stays the preferred form.
115
+
116
+ - **A hook command that cannot start no longer blocks or loops the host.** On `Stop`, both hosts
117
+ feed a hook's stderr back when the hook exits 2: Codex continues the turn, and Claude Code
118
+ continues the conversation, and Claude Code also blocks the tool call on `PreToolUse`. `uv`
119
+ exits 2 on some of its own errors (a project it cannot find, a cache it cannot write) and `dash`
120
+ exits 2 when the `cd` fails, so a hook command that never reached Python could do exactly that,
121
+ over and over in a headless `codex exec` run. Every shipped hook command, in both plugins and in
122
+ the manual recipes in the docs, now ends with a guard: `Stop` and `PreToolUse` answer `{}`, and
123
+ `SessionStart` answers a one-line `systemMessage` that says the hook could not start and to run
124
+ the hook command in a terminal to see the error. A command that starts Python behaves as
125
+ before. **Codex users: approve the two hooks again once after updating.** Codex records trust
126
+ per hook definition and the definition includes its command, so the changed commands do not run
127
+ until you approve them in `/hooks` or at the next interactive session's trust prompt. **If you
128
+ wired the hooks by hand**, append the guard to your own commands in `.claude/settings.json` or
129
+ `.codex/hooks.json`; the recipes in the docs show it. The Codex page also now says how to run a
130
+ headless review without Sidegraph's hooks.
131
+ - **The capture nudge now arms on Codex.** The Stop hook's substance gate understood only Claude
132
+ Code transcripts, so on a Codex rollout it counted zero prompts and never nudged: every Codex
133
+ session ended without the capture reminder. The gate now reads a rollout too. A person's prompt
134
+ is a user message that is not text Codex wrote itself (the project instructions and environment
135
+ blocks, plugin and skill blocks, an aborted-turn note, a Stop hook's own block reason fed back);
136
+ nor does an answer to the agent's question, which arrives mid-turn, count as one. Each prompt
137
+ counts once although Codex mirrors it as an event. A thread arms after two real prompts, never
138
+ on tool calls. Subagent threads, Codex's automatic reviewer and headless `codex exec` runs, including
139
+ ones started through the Codex TypeScript SDK, never arm, so a review panel's `-o` output is
140
+ never replaced by a continuation. The nudge text, the once-per-session ledger and the hook
141
+ definitions are unchanged, so Codex's trust in the installed hooks stays valid. Claude Code
142
+ sessions are counted exactly as before.
143
+ - **A session started in a subdirectory no longer opens a second, empty store.** Claude Code sets
144
+ `CLAUDE_PROJECT_DIR` to the directory it was launched in, so a launch in `repo/pkg` with the
145
+ plugin active created `repo/pkg/.sidegraph` beside the repository's own store, and the session
146
+ saw no memory. The hooks and the MCP server now use `repo/.sidegraph`, record touches relative
147
+ to it (`pkg/a.py`, so they join the anchors) and keep the nested-store case (`.config/sidegraph`)
148
+ repo-relative. The hooks also read the graph the store's project holds, as the CLI and the MCP
149
+ server do, so a store in a nested directory finds its own `graphify-out/graph.json`; a relative
150
+ `SIDEGRAPH_GRAPH` is no longer looked up under `$CLAUDE_PROJECT_DIR`. A store the old behaviour
151
+ already created is not touched: when the store a session uses is empty and the repository's
152
+ store above it holds records, `SessionStart` adds one line naming both. Remove the empty
153
+ `<subdirectory>/.sidegraph` to use the repository's. A stray store that holds any record (one
154
+ proposed decision from an old capture is enough) is not reported and keeps hiding the
155
+ repository's: review it with `sidegraph-ratify --db <subdirectory>/.sidegraph`, record what
156
+ matters again in the repository's store, then remove the stray directory.
157
+
158
+ - **A code graph that never caught up with `HEAD` now says so.** Nothing compared the commit
159
+ `graph.json` was built at (`built_at_commit`) with `HEAD`, so a graph stuck at an old commit
160
+ looked up to date for good, and every `get_task_context` call seeded with a file added since
161
+ returned a bare `No context found.` The comparison now runs in the engine reader and counts a
162
+ graph as stale only when a file it should hold changed or appeared since the build (a commit
163
+ touching only file types the graph does not hold does not, and a graph built from a dirty tree
164
+ and committed afterwards does not). It surfaces in four places:
165
+ - `SessionStart` adds one line when the graph is stale, with the rebuild command
166
+ (`graphify update .` from the repository root);
167
+ - `get_task_context` appends a `## Not in the code graph` block after its answer when a seed is
168
+ not a file the graph holds, saying whether the graph is stale, shows no committed change since
169
+ its build (the file may be newer than the build, or one the engine skips) or could not be
170
+ compared, or whether the path is a directory, missing or not a normalized repo-relative path
171
+ (an absolute path, `./x`). Seeds the graph holds leave the answer byte-identical and cost no git call;
172
+ - `sidegraph-doctor` reports a new advisory finding, `graph-stale`. **`sidegraph-doctor --check`
173
+ now exits `2` on a stale graph**; a CI job that rebuilds the graph before running doctor is
174
+ unaffected;
175
+ - `sidegraph-stats` adds a `stale:` continuation line under the GRAPH counts, and its `--json`
176
+ gains `graph.freshness`, `built_at`, `commits_behind` and `stale_files`.
177
+
178
+ The docs no longer call a missed refresh "self-healing": the lazy check re-syncs a graph that
179
+ was rebuilt, and only a rebuild fixes one that never was.
180
+
181
+ - **A linked worktree reads the main checkout's code graph, and a missing graph is said.**
182
+ `graphify-out/` is gitignored, so a `git worktree add` checkout had the tracked store and no
183
+ graph, and `get_task_context` resolved nothing there. When the store's own graph is missing and
184
+ its repository is a linked worktree of a main checkout, the read tools (`get_task_context`,
185
+ `query_structure`, `query_decisions`, `drill_down`) and `SessionStart` now open the main
186
+ checkout's graph, found from the worktree's `.git` file alone (no git call). That graph is synced
187
+ index-only: a worktree's index starts cold, and without the derived state (domain communities,
188
+ community bindings, engine mappings) `drill_down` lost most of a domain's decisions and
189
+ `get_task_context` its `## Related` section. The sync never rewrites a tracked file (its moved
190
+ rung, the one step that can, abstains), so the worktree's store stays as git checked it out.
191
+ `SessionStart` builds the domain map in memory from the store, adds a line saying whose graph it
192
+ reads, and names the main checkout in its stale-graph line. `get_task_context` tells a file that
193
+ exists only on the branch apart from one the main checkout's graph is stale for. A file the
194
+ branch changed that the main checkout also has is described as it is in the main checkout (its
195
+ symbols and the edges between them), and nothing warns about it.
196
+ `sync_anchors`, `list_domain_candidates`, every write tool and every CLI default keep reading the
197
+ store's own graph. A bare repository (also one cloned into `x/.git`), a git directory that is
198
+ separate and not itself named `.git`, a submodule and a plain `git clone` have no main checkout
199
+ to borrow from.
200
+ - **`get_task_context` says when there is no code graph at all.** With no reader and at least one
201
+ seed, the answer ends with a `## No code graph` block naming the path that was looked at and
202
+ how to build it, instead of an answer that looked like a search with no hits. A graph that is
203
+ there and cannot be read is reported as not readable, not as missing.
204
+
10
205
  ## [0.6.0] — 2026-10-01
11
206
 
12
207
  ### Added
@@ -13,7 +13,7 @@ task-aware retrieval + decision memory riding on the engine's entity graph.
13
13
  continuing participant in the project. A core feature must preserve, organize, or deliver
14
14
  accumulated project understanding. Document search by itself is not the product.
15
15
 
16
- Sidegraph is pre-1.0 (v0.6.0) — the full loop (capture, ratification, mistakes-first
16
+ Sidegraph is pre-1.0 (v0.7.0) — the full loop (capture, ratification, mistakes-first
17
17
  retrieval, refactor-surviving re-anchoring, semantic docs layer, mind-model domains, and the
18
18
  facts evidence layer) ships and is exercised end-to-end, but interfaces may still move before
19
19
  a stable release. See
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sidegraph
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: Own the memory, rent the graph — a durable decision/lessons layer as a sidecar over a code-graph engine.
5
5
  Project-URL: Homepage, https://github.com/SantyagoSeaman/sidegraph
6
6
  Project-URL: Repository, https://github.com/SantyagoSeaman/sidegraph
@@ -167,7 +167,7 @@ projects the full store, history included, into an OKF v0.1 bundle any OKF consu
167
167
  next session ◀── SessionStart TOC anchored to entities in the
168
168
  of named domains ◀── get_task_context ◀────── engine's graph (read-only);
169
169
  mistakes first drill_down re-anchored after refactors
170
- blind Read/Grep ──▶ nudged back to get_task_context (each form once per session)
170
+ blind Read/Grep ──▶ nudged back to get_task_context (each form once per agent)
171
171
  ```
172
172
 
173
173
  Two layers age differently: the **structure** layer (the code graph — entities,
@@ -139,7 +139,7 @@ projects the full store, history included, into an OKF v0.1 bundle any OKF consu
139
139
  next session ◀── SessionStart TOC anchored to entities in the
140
140
  of named domains ◀── get_task_context ◀────── engine's graph (read-only);
141
141
  mistakes first drill_down re-anchored after refactors
142
- blind Read/Grep ──▶ nudged back to get_task_context (each form once per session)
142
+ blind Read/Grep ──▶ nudged back to get_task_context (each form once per agent)
143
143
  ```
144
144
 
145
145
  Two layers age differently: the **structure** layer (the code graph — entities,
@@ -15,6 +15,22 @@ enclosing-module info, so `name` + `file_path` is all identity has to work with.
15
15
  (lowercase, strip a leading `.`, drop call-decoration like `()`), so `.foo()` in a decision's
16
16
  anchor matches the graph node named `foo`.
17
17
 
18
+ **`Type.member` names.** Graphify labels a method `.foo()` and links it to its type with a
19
+ `method` edge (an enum case with `case_of`), so a name written `Type.foo` has no exact match.
20
+ When none is found and the descriptor has a `file_path`, `resolve()` falls back to the member.
21
+ It is for code identifiers only: the owner (its last segment, so `Outer.Inner.foo` reads as
22
+ `Inner`) and the member must both be identifiers, and the candidate must be a `code` node, so
23
+ prose with a dot in it, a numbered heading or `verify-release.sh` never reads as a member.
24
+ The name is split at its last `.`, `::` or `#`, the node in that file whose label is the member
25
+ is found (case kept), a candidate the graph ties to a different type is rejected, and, of
26
+ several, those tied to the named type are kept. Anything that does not narrow to exactly one
27
+ node is `unresolved`, the orphaned, healable leaf a bare miss has always been, never
28
+ `ambiguous`. So is a name with a case-only twin in the file (a struct `Message` beside a
29
+ method `.message()`): the store dedups an anchor by its lowercased name, so the two spellings
30
+ are one entity, and binding either node would put the other's record on it. Without a file the
31
+ fallback never runs, and a path-qualified name (`src/pkg/mod.py`, which reads as the member
32
+ `py`) still never resolves.
33
+
18
34
  ## Lazy `Entity` creation
19
35
 
20
36
  An `Entity` is created the first time a decision references it — via
@@ -121,8 +137,8 @@ node and a file node are both just nodes.
121
137
  The same pattern applies to `concept` nodes from the semantic pass: a concept has no stable id
122
138
  either, so **anchor concept + file together**, not the concept alone. Re-extracting an edited
123
139
  file can rename or drop the concepts inside it — the same churn a code refactor causes to
124
- symbol names — and the rebind ladder below handles it identically: exact match, then unique
125
- name-only match, then orphaned. No special-casing for concepts versus code symbols.
140
+ symbol names — and the rebind ladder below handles it identically: exact match, then a unique
141
+ same-name match in a file that arrived with the old one's removal, then orphaned. No special-casing for concepts versus code symbols.
126
142
 
127
143
  ## What happens on rename or move
128
144
 
@@ -137,10 +153,13 @@ remembered under `pending_uncommitted_moves` are still re-verified once `HEAD` h
137
153
  re-pointing](../guides/surviving-refactors.md#community-re-pointing)).
138
154
  2. **Ambiguous** — leaf bindings flip to `degraded`; the node mapping is left untouched
139
155
  (never guess); community is re-pointed if a shared one is still resolvable.
140
- 3. **Moved** — exact fails but a name-only retry resolves uniquely, *and* the new file has
141
- the same suffix as the old `descriptor.file_path` (e.g. `.py` -> `.py`, `.md` -> `.md`),
142
- *and* the old `file_path` is confirmed gone from the checkout ->
143
- `descriptor.file_path` is updated to follow the file, leaf bindings heal to `live`.
156
+ 3. **Moved** — exact fails but a name-only retry resolves uniquely, *and* the hit is the
157
+ same name (decoration such as `()` or a leading `.` stripped from both sides, **case
158
+ kept**), *and* the new file has the same suffix as the old `descriptor.file_path` (e.g.
159
+ `.py` -> `.py`, `.md` -> `.md`), *and* the old `file_path` is confirmed gone from the
160
+ checkout, *and* git's history shows the new file arriving in the same change that
161
+ removed the old one -> `descriptor.file_path` is updated to follow the file, leaf
162
+ bindings heal to `live`.
144
163
  **Suffix guard:** a unique name-only hit whose file suffix *differs* from the old one
145
164
  (e.g. a vanished code symbol whose name happens to collide with a doc heading) is a
146
165
  **collision, not a move** — it is never adopted, and falls through to orphaned instead.
@@ -148,6 +167,15 @@ remembered under `pending_uncommitted_moves` are still re-verified once `HEAD` h
148
167
  still there — a symbol renamed *inside* a surviving file is not a move, however unique
149
168
  the name-only hit elsewhere looks, and "can't verify" counts as "still there" (see [why
150
169
  `moved` checks the disk](../guides/surviving-refactors.md#why-moved-checks-the-disk)).
170
+ **Name guard:** the name-only lookup ignores case, so a deleted type `Priority` can find
171
+ an old member `.priority` in an unrelated file. That is a different symbol, not a move,
172
+ and is never adopted. **Arrival guard:** a new path that already existed before the old
173
+ one was removed is a collision, not a move. So is an old path git cannot account for
174
+ (never committed, or beyond the history a shallow clone holds): any git answer that is
175
+ not a clear yes refuses. A refused move falls through to orphaned, which
176
+ `sidegraph:heal-anchors` repairs.
177
+ This rung resolves by name only, so a `Type.member` anchor cannot follow its file being
178
+ moved; the bare member name can.
151
179
  4. **Orphaned** — nothing resolves; leaf bindings flip to `orphaned`. Sync still tries to
152
180
  derive the entity's current community from its surviving file's nodes (useful when a
153
181
  symbol renamed but its file didn't move); that derivation only happens when the file's
@@ -39,19 +39,19 @@ that suffices:
39
39
  summary, a mistake count, and a subdomain count (see
40
40
  [retrieval](retrieval.md#sessionstart-toc)). This is what an agent reads before touching
41
41
  anything — "what areas does this project have, and what should I already know about each."
42
- The mistake count is narrower than "mistakes in this area": it counts only decisions
43
- Tier-1-bound to the domain's own `domain:<slug>` entity (captured, or re-anchored, after
44
- the domain was ratified) — a gotcha anchored to a leaf entity that happens to live in the
45
- domain still surfaces in that entity's task context, just not in this count.
42
+ The mistake count is what `drill_down` would serve for the domain: the accepted `gotcha`,
43
+ `lesson` and `constraint` decisions in the union described under `drill_down` below, so a
44
+ gotcha anchored to a leaf entity that lives in the domain is counted too. Proposed and
45
+ superseded records are not.
46
46
  2. **`drill_down(domain_slug)`** — walk one domain: its full summary, its accepted subdomains,
47
47
  a capped sample of the code/doc entities that currently belong to it, and the decisions
48
- about it (mistakes first). Unlike the TOC's narrower mistake count, `drill_down`'s
49
- `decisions` list is the **union** of decisions tagged directly to the `domain:<slug>` entity,
48
+ about it (mistakes first). Its `decisions` list is the **union** of decisions tagged
49
+ directly to the `domain:<slug>` entity,
50
50
  decisions anchored to any code/doc entity that lives in one of the domain's communities
51
51
  (a community-membership join, deduplicated), and decisions anchored to a whole *document*
52
52
  entity whose file_path is one of the domain's covered files — so a gotcha anchored to a leaf
53
53
  entity in the domain, or an imported ADR that anchored to a doc rather than the domain
54
- abstraction, *does* surface here even though it isn't counted in the TOC. The document branch
54
+ abstraction, *does* surface here, and is counted in the TOC. The document branch
55
55
  matters specifically on doc corpora: `sidegraph-import --docs` anchors an ADR to the
56
56
  document's own file-level node, but Graphify clusters every doc file-level node into one hub
57
57
  community, so that node's community is essentially never among the domain's `communities`
@@ -16,12 +16,14 @@ whether the store has any accepted domains yet:
16
16
  first domain is ratified — no sync required, see [below](#when-the-toc-goes-live)): one line
17
17
  per accepted domain (title, one-line summary truncated to 100 characters, mistake count,
18
18
  subdomain count when non-zero), then initiatives, then global mistakes. This is what "the
19
- mind model comes alive" means in practice. The per-domain mistake count
20
- (`_domain_mistake_count`) is narrower than "all mistakes in this area": it counts only
21
- decisions Tier-1-bound to the domain's own `domain:<slug>` entity, i.e. captured (or
22
- re-anchored) after the domain existed — a `gotcha`/`lesson`/`constraint` anchored only to a
23
- leaf entity within the domain still surfaces in that entity's `get_task_context` output, it
24
- just doesn't add to this count.
19
+ mind model comes alive" means in practice. The per-domain mistake count is what
20
+ [`drill_down`](#drill_downdomain_slug--the-axis-1-operation) would serve for that domain:
21
+ the accepted `gotcha`/`lesson`/`constraint` decisions in the union of those tagged to the
22
+ domain's own `domain:<slug>` entity, those anchored to a code or doc entity that lives in one
23
+ of its communities, and, when a graph reader is on hand, those anchored to a whole document
24
+ it covers. Proposed and superseded records are not counted. A TOC built without a reader
25
+ (the ratify and capture paths) leaves out the document branch until the next sync pass that
26
+ has one.
25
27
  - **`top_tier_map(store, reader)`** — the legacy, nameless fallback: top communities by member
26
28
  count (labeled only by god-node name), initiatives, global mistakes. Runs on demand (no
27
29
  cache) whenever the store has zero accepted domains — a fresh repo, or one that hasn't
@@ -33,34 +35,41 @@ prepends it once, at the hook-assembly level, ahead of whichever renderer's text
33
35
  `render_toc`/`top_tier_map` stay pure content formatters (see
34
36
  [`reference/hooks.md`](../reference/hooks.md#sidegraph-session-start)). The instruction now
35
37
  covers every search surface, not just `Read`/`Grep`: *"When you need to find or understand
36
- code in this project, call `get_task_context(seeds)` before any grep or file search —
37
- decisions, gotchas and a domain map are indexed here."* Both degrade gracefully — an empty
38
+ code in this project, call `get_task_context(files=[…])` with repo-relative paths before any
39
+ grep or file search — decisions, gotchas and a domain map are indexed here. Before a
40
+ non-trivial change, run the sidegraph check-plan skill if it is available. If the tool is
41
+ listed only by name, load it first."* Both degrade gracefully — an empty
38
42
  store still gets the instruction plus just the header. The `SessionStart` hook itself never
39
43
  blocks startup: any failure, or a cache it can't parse, falls back to `top_tier_map` rather
40
44
  than crashing; any failure in *that* prints `{}` and exits 0.
41
45
 
42
46
  ### When the TOC goes live
43
47
 
44
- `build_toc(store, reader=None)` precomputes the cache from store content alone (domains,
45
- initiatives, global mistakes — no graph needed) and is written to `store` meta under the
48
+ `build_toc(store, reader=None)` precomputes the cache from the store (domains, initiatives,
49
+ global mistakes; a graph reader is optional and only adds the document branch of the mistake
50
+ count) and is written to `store` meta under the
46
51
  `toc_cache` key (see [configuration](../reference/configuration.md#domain-sync-and-the-toc-cache))
47
52
  at two points:
48
53
 
49
54
  1. **Every completed `sidegraph-sync` pass** (fresh or forced) — after the domain-community
50
55
  refresh, so the cache reflects that pass's own updates. **Also on a skipped
51
- (already-up-to-date) pass**, whenever at least one accepted domain exists: a content-only
52
- change such as `add_decision` bound to an existing domain entity never moves
53
- `graph_version`, so without this a lazy `sidegraph-sync` right after it would report
54
- "up to date" and leave the cache stale until an unrelated domain accept/drop happened to
55
- rebuild it.
56
+ (already-up-to-date) pass**, whenever at least one accepted domain exists and the store
57
+ changed since the cache was built: a content-only change such as `add_decision` bound to an
58
+ existing domain entity never moves `graph_version`, so without this a lazy
59
+ `sidegraph-sync` right after it would report "up to date" and leave the cache stale until
60
+ an unrelated domain accept/drop happened to rebuild it. Every retrieval call runs this
61
+ pass, and a build counts every domain's decisions, so the cache records the store's
62
+ canonical digest and an unchanged digest keeps it. A cache written without a graph reader
63
+ carries no digest and is rebuilt once.
56
64
  2. **Every `ratify` call (MCP tool or `sidegraph-ratify` CLI) that actually accepted or dropped
57
65
  at least one domain** — immediately, without waiting for the next sync. This is what makes
58
66
  `bootstrap → ratify` visibly turn the TOC on in the very same session, even when no graph
59
67
  sync is needed.
60
68
 
61
69
  A decisions-only ratify (no domain ids in the batch) does not rebuild the cache immediately.
62
- It can change a rendered mistake count; the next completed or skipped sync refreshes that
63
- count. Domain acceptance is the special case refreshed in the ratify operation itself.
70
+ It can change a rendered mistake count; the next completed sync pass, or skipped one that
71
+ finds the store changed, refreshes that count, and so does the count after `add_decision`.
72
+ Domain acceptance is the special case refreshed in the ratify operation itself.
64
73
 
65
74
  ## `drill_down(domain_slug)` — the Axis-1 operation
66
75
 
@@ -77,8 +86,8 @@ an empty list with an explanatory `"note"` key — everything store-derived (`do
77
86
 
78
87
  ## `get_task_context`: seeded, budgeted, mistakes-first
79
88
 
80
- `get_task_context(seeds, store, reader, budget)` is the core UX: given what the agent is
81
- about to touch, return a compact slice of structure *and* memory, memory ranked so the things
89
+ `get_task_context(seeds, store, reader, budget)` is the core UX (the MCP tool of that name
90
+ takes the seeds as `files` and `entities`): given what the agent is about to touch, return a compact slice of structure *and* memory, memory ranked so the things
82
91
  most likely to save it from a repeat mistake come first.
83
92
 
84
93
  ### Seeds
@@ -89,6 +98,11 @@ A `Seed` is either:
89
98
  anchors (see [anchoring](anchoring.md#descriptors-name--file)); an ambiguous ref keeps
90
99
  *all* candidates rather than guessing or dropping the seed.
91
100
 
101
+ A seed reaches the store's entities two ways, and both count: a named seed that matches a
102
+ stored anchor name is that entity directly (whatever the graph calls the node, so a stored
103
+ `Type.member` is found), and every node a seed resolves to is mapped to the entity the store
104
+ last saw it as (`last_seen_node_id`), with the node's own label still looked up beside that.
105
+
92
106
  Seeds are explicit — there is no semantic/embedding query matching; the caller (typically an
93
107
  MCP tool call with `files=[...]` and/or `entities=[{"name", "file_path"}, ...]`) names exactly
94
108
  what it's working on.
@@ -295,13 +309,22 @@ a decision doesn't vanish just because its most precise anchor did.
295
309
  Before rendering, every retrieval-facing MCP tool — `get_task_context`, `query_structure`,
296
310
  `query_decisions`, and `drill_down` — plus the `SessionStart` hook calls `maybe_sync(store,
297
311
  reader)` — best-effort, wrapped so a sync failure degrades to un-synced retrieval rather than
298
- erroring. `maybe_sync` is itself cheap in the common case: it compares the graph's current
299
- version against the store's `last_synced_graph_version` meta stamp and skips the full pass if they match (an entity remembered under
312
+ erroring. A linked worktree that reads the main checkout's graph because it has none of its own
313
+ syncs it too, index-only: the derived state fills its cold index, and no tracked file is rewritten
314
+ (the moved rung abstains; see
315
+ [the Graphify integration](../integrations/graphify.md#linked-worktrees-read-the-main-checkouts-graph)).
316
+ `maybe_sync` is itself cheap in the common case: it compares the graph's current
317
+ version (plus the reader's resolver revision, so an upgrade that changes how names resolve reruns the pass once) against the store's `last_synced_graph_version` meta stamp and skips the full pass if they match (an entity remembered under
300
318
  `pending_uncommitted_moves` is still re-verified once `HEAD` has moved).
301
319
  This is the self-healing mechanism described in
302
- [anchoring](anchoring.md#what-happens-on-rename-or-move): a missed post-commit hook is simply
303
- caught by the next read, and it's what keeps each accepted domain's `communities` field current
304
- too (see [mind model](mind-model.md#how-domains-relate-to-engine-communities)).
320
+ [anchoring](anchoring.md#what-happens-on-rename-or-move): a graph that was rebuilt after a
321
+ missed post-commit sync is caught by the next read, and it's what keeps each accepted domain's
322
+ `communities` field current too (see
323
+ [mind model](mind-model.md#how-domains-relate-to-engine-communities)). It cannot catch a graph
324
+ that was never rebuilt, because the version it compares is the file's own: that case is
325
+ reported separately, by comparing the graph's build commit with `HEAD` (see
326
+ [the Graphify integration](../integrations/graphify.md#keeping-the-graph-fresh-git-hooks)), and
327
+ only a rebuild fixes it.
305
328
 
306
329
  ### Rendering
307
330
 
@@ -310,7 +333,17 @@ accepted inline `evidence:` lines nested under the decision they support), **Kno
310
333
  (accepted standalone facts — see above), **Structural map** (the budgeted subgraph around the
311
334
  seeds, rendered as pointers — `- name (file_type) [file_path:line]`, never inlined code),
312
335
  **Related**, then **Unratified proposals**.
313
- Missing sections are omitted; an empty result renders `"No context found."`.
336
+ Missing sections are omitted; an empty result renders `"No context found."`. After the
337
+ rendered text, `get_task_context` appends a `## Not in the code graph` block when a seed path is
338
+ not a file the graph holds, saying why: a file that exists but is missing from a stale graph
339
+ (rebuild it), from a graph with no committed change since its build (the file may be newer than
340
+ the build and uncommitted, or sit on a path or have a type the engine skips), or a path that is
341
+ not a normalized repo-relative path to a file (check it). In a linked worktree that borrows the
342
+ main checkout's graph, a file that exists only on the branch gets one sentence saying the graph
343
+ does not hold it, and the rebuild advice for any other file names the main checkout. With no graph
344
+ at all and at least one seed, a `## No code graph` block names the path looked at and says to build
345
+ it (or, when the graph is there and cannot be read, that it is not readable). `render()` itself
346
+ does not produce either block.
314
347
 
315
348
  ## See also
316
349
 
@@ -90,7 +90,7 @@ Add to `.claude/settings.json` (merge into an existing file):
90
90
  "hooks": [
91
91
  {
92
92
  "type": "command",
93
- "command": "SIDEGRAPH_DIR=.sidegraph SIDEGRAPH_GRAPH=graphify-out/graph.json uvx --from git+https://github.com/SantyagoSeaman/sidegraph.git@main sidegraph-session-start"
93
+ "command": "SIDEGRAPH_DIR=.sidegraph SIDEGRAPH_GRAPH=graphify-out/graph.json uvx --from git+https://github.com/SantyagoSeaman/sidegraph.git@main sidegraph-session-start || printf '%s\\n' '{\"systemMessage\":\"Sidegraph: the SessionStart hook could not start (uv/uvx, network or project path); run the hook command in a terminal to see the error\"}'"
94
94
  }
95
95
  ]
96
96
  }
@@ -100,7 +100,7 @@ Add to `.claude/settings.json` (merge into an existing file):
100
100
  "hooks": [
101
101
  {
102
102
  "type": "command",
103
- "command": "SIDEGRAPH_DIR=.sidegraph SIDEGRAPH_GRAPH=graphify-out/graph.json uvx --from git+https://github.com/SantyagoSeaman/sidegraph.git@main sidegraph-stop"
103
+ "command": "SIDEGRAPH_DIR=.sidegraph SIDEGRAPH_GRAPH=graphify-out/graph.json uvx --from git+https://github.com/SantyagoSeaman/sidegraph.git@main sidegraph-stop || printf '{}\\n'"
104
104
  }
105
105
  ]
106
106
  }
@@ -111,7 +111,7 @@ Add to `.claude/settings.json` (merge into an existing file):
111
111
  "hooks": [
112
112
  {
113
113
  "type": "command",
114
- "command": "SIDEGRAPH_DIR=.sidegraph SIDEGRAPH_GRAPH=graphify-out/graph.json uvx --from git+https://github.com/SantyagoSeaman/sidegraph.git@main sidegraph-pre-tool-use"
114
+ "command": "SIDEGRAPH_DIR=.sidegraph SIDEGRAPH_GRAPH=graphify-out/graph.json uvx --from git+https://github.com/SantyagoSeaman/sidegraph.git@main sidegraph-pre-tool-use || printf '{}\\n'"
115
115
  }
116
116
  ]
117
117
  }
@@ -121,7 +121,13 @@ Add to `.claude/settings.json` (merge into an existing file):
121
121
  ```
122
122
 
123
123
  From a source checkout, replace each `uvx --from git+... <entrypoint>` above with `uv run
124
- --project /ABSOLUTE/PATH/TO/sidegraph <entrypoint>` (see the note in step 1).
124
+ --project /ABSOLUTE/PATH/TO/sidegraph <entrypoint>` (see the note in step 1). Keep the trailing
125
+ `|| printf …` on each command: Claude Code treats a hook that exits 2 with text on stderr as a
126
+ block on `Stop` (it continues the conversation) and on `PreToolUse` (it blocks the tool call), and
127
+ `uvx` exits 2 on some of its own errors, so without the guard a command that cannot start would
128
+ block you instead of just doing nothing. The guard makes it exit 0 and answer `{}`, or, on
129
+ `SessionStart`, a `systemMessage` telling you to run the hook command in a terminal to see the
130
+ error (see [`reference/hooks.md`](../reference/hooks.md#if-you-see-this-message)).
125
131
 
126
132
  The env vars are inlined into the command because Claude Code hook entries have no separate
127
133
  `env`/`cwd` fields.
@@ -138,8 +144,9 @@ The env vars are inlined into the command because Claude Code hook entries have
138
144
  nudge text and the substance gate's mechanics.
139
145
  - `PreToolUse` redirects a blind `Read`/`Grep` on a source file toward
140
146
  `get_task_context`/`drill_down` with a one-line, non-blocking nudge: a generic form and a
141
- path-specific form, each firing at most once per session on its own one-shot key, so a
142
- session can see up to two, only when the store actually has decision memory to offer. Set
147
+ path-specific form, each firing at most once per agent on its own one-shot key, so the
148
+ session's own agent can see up to two, and so can each subagent it starts, only when the
149
+ store actually has decision memory to offer. Set
143
150
  `SIDEGRAPH_GREP_NUDGE=off` (alongside the other env vars in the command) to disable it.
144
151
 
145
152
  > **Don't also run `graphify claude install`.** It writes its own `PreToolUse` hooks into
@@ -96,7 +96,7 @@ Create `.codex/hooks.json` in the repo:
96
96
  "hooks": [
97
97
  {
98
98
  "type": "command",
99
- "command": "cd \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)\" && SIDEGRAPH_DIR=.sidegraph SIDEGRAPH_GRAPH=graphify-out/graph.json uv run --project /ABSOLUTE/PATH/TO/sidegraph sidegraph-session-start"
99
+ "command": "cd \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)\" && SIDEGRAPH_DIR=.sidegraph SIDEGRAPH_GRAPH=graphify-out/graph.json uv run --project /ABSOLUTE/PATH/TO/sidegraph sidegraph-session-start || printf '%s\\n' '{\"systemMessage\":\"Sidegraph: the SessionStart hook could not start (uv/uvx, network or project path); run the hook command in a terminal to see the error\"}'"
100
100
  }
101
101
  ]
102
102
  }
@@ -106,7 +106,7 @@ Create `.codex/hooks.json` in the repo:
106
106
  "hooks": [
107
107
  {
108
108
  "type": "command",
109
- "command": "cd \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)\" && SIDEGRAPH_DIR=.sidegraph SIDEGRAPH_GRAPH=graphify-out/graph.json uv run --project /ABSOLUTE/PATH/TO/sidegraph sidegraph-stop"
109
+ "command": "cd \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)\" && SIDEGRAPH_DIR=.sidegraph SIDEGRAPH_GRAPH=graphify-out/graph.json uv run --project /ABSOLUTE/PATH/TO/sidegraph sidegraph-stop || printf '{}\\n'"
110
110
  }
111
111
  ]
112
112
  }
@@ -122,6 +122,14 @@ working on a non-git corpus too (Sidegraph doesn't require the corpus to be a gi
122
122
  [`integrations/graphify.md`](../integrations/graphify.md#non-git-and-doc-only-corpora)), where a
123
123
  bare `git rev-parse --show-toplevel` would fail and leave `cd` with no argument.
124
124
 
125
+ The trailing `|| printf …` is a guard, and it should stay. On `Stop`, Codex feeds a hook's stderr
126
+ back to the model when the hook exits 2, and `uv` exits 2 on some of its own errors (a project it
127
+ cannot find, a cache it cannot write), so a command that never reaches Python could keep
128
+ continuing your session. With the guard the hook exits 0 and answers `{}`. On `SessionStart` it
129
+ answers a `systemMessage` telling you to run the hook command in a terminal to see the error
130
+ (see [`reference/hooks.md`](../reference/hooks.md#if-you-see-this-message)). The same guard ends
131
+ every hook command in the plugin; see [`integrations/codex.md`](../integrations/codex.md#hooks-ga).
132
+
125
133
  No `PreToolUse` entry is included above. Codex can invoke that event for local function tools,
126
134
  but it has no stable `Read`/`Grep` tool pair to which Sidegraph's Claude-specific redirect can
127
135
  attach. Therefore Claude Code's Read/Grep redirect nudge