sidegraph 0.4.0__tar.gz → 0.6.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 (381) hide show
  1. {sidegraph-0.4.0 → sidegraph-0.6.0}/.github/workflows/ci.yml +0 -40
  2. sidegraph-0.6.0/.github/workflows/session-link-gate.yml +76 -0
  3. {sidegraph-0.4.0 → sidegraph-0.6.0}/.gitleaks.toml +1 -0
  4. {sidegraph-0.4.0 → sidegraph-0.6.0}/.pre-commit-config.yaml +13 -12
  5. {sidegraph-0.4.0 → sidegraph-0.6.0}/CHANGELOG.md +300 -0
  6. {sidegraph-0.4.0 → sidegraph-0.6.0}/CLAUDE.md +6 -5
  7. {sidegraph-0.4.0 → sidegraph-0.6.0}/PKG-INFO +5 -4
  8. {sidegraph-0.4.0 → sidegraph-0.6.0}/README.md +4 -3
  9. {sidegraph-0.4.0 → sidegraph-0.6.0}/SECURITY.md +13 -5
  10. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/concepts/anchoring.md +19 -11
  11. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/concepts/data-model.md +3 -2
  12. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/concepts/retrieval.md +2 -1
  13. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/getting-started/bootstrap.md +5 -1
  14. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/getting-started/installation.md +8 -5
  15. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/guides/capturing-decisions.md +2 -1
  16. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/guides/retrieval-in-sessions.md +2 -2
  17. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/guides/semantic-docs.md +2 -2
  18. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/guides/surviving-refactors.md +18 -9
  19. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/integrations/claude-code.md +9 -5
  20. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/integrations/graphify.md +13 -8
  21. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/reference/cli.md +185 -70
  22. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/reference/configuration.md +37 -10
  23. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/reference/hooks.md +23 -13
  24. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/reference/mcp-tools.md +69 -21
  25. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/reference/releasing.md +30 -4
  26. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/reference/store-format.md +64 -4
  27. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/.claude-plugin/plugin.json +1 -1
  28. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/.codex-plugin/plugin.json +1 -1
  29. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/heal-anchors/SKILL.md +4 -2
  30. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/import-adrs/SKILL.md +23 -7
  31. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/record-decision/SKILL.md +3 -2
  32. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/record-fact/SKILL.md +4 -2
  33. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/stats/SKILL.md +6 -5
  34. {sidegraph-0.4.0 → sidegraph-0.6.0}/pyproject.toml +1 -1
  35. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/__init__.py +1 -1
  36. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/anchoring.py +3 -20
  37. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/catalog.py +44 -9
  38. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/cli.py +68 -29
  39. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/integrations.py +23 -5
  40. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/capture.py +532 -303
  41. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/cli.py +263 -126
  42. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/config.py +108 -5
  43. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/doc_import.py +202 -43
  44. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/doctor.py +5 -3
  45. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/domains.py +2 -1
  46. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/engine/reader.py +2 -0
  47. sidegraph-0.6.0/src/sidegraph/gitenv.py +41 -0
  48. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/gitio.py +2 -1
  49. sidegraph-0.6.0/src/sidegraph/host/claude_settings.py +244 -0
  50. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/host/hooks.py +32 -4
  51. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/importer.py +15 -3
  52. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/okf.py +260 -23
  53. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/schema.py +11 -0
  54. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/server.py +157 -47
  55. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/stats/model.py +7 -1
  56. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/store.py +464 -55
  57. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/sync.py +472 -57
  58. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/verify.py +183 -26
  59. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/conftest.py +36 -7
  60. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_anchoring.py +2 -14
  61. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_bootstrap_catalog.py +91 -0
  62. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_bootstrap_cli.py +257 -0
  63. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_capture_auto_accept.py +0 -8
  64. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_capture_facts.py +0 -14
  65. sidegraph-0.6.0/tests/test_capture_initiative.py +185 -0
  66. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_capture_neighbors.py +0 -7
  67. sidegraph-0.6.0/tests/test_capture_propose.py +802 -0
  68. sidegraph-0.6.0/tests/test_capture_redact.py +184 -0
  69. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_cli_domains.py +39 -0
  70. sidegraph-0.6.0/tests/test_cli_graph_paths.py +535 -0
  71. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_cli_import.py +283 -25
  72. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_cli_init.py +180 -0
  73. sidegraph-0.6.0/tests/test_cli_okf.py +819 -0
  74. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_cli_stats.py +16 -0
  75. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_cli_sync.py +12 -0
  76. sidegraph-0.6.0/tests/test_cli_unreadable_paths.py +261 -0
  77. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_config.py +45 -0
  78. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_doc_corpus_integration.py +0 -7
  79. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_doc_import.py +496 -6
  80. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_doctor.py +102 -0
  81. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_env_isolation.py +3 -1
  82. sidegraph-0.6.0/tests/test_git_env.py +138 -0
  83. sidegraph-0.6.0/tests/test_host_claude_settings.py +554 -0
  84. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_host_session_start.py +40 -0
  85. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_host_stop.py +99 -0
  86. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_importer.py +42 -0
  87. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_okf.py +29 -1
  88. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_ratify_policy.py +32 -41
  89. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_repoint_integration.py +0 -7
  90. sidegraph-0.6.0/tests/test_sandbox_hygiene.py +328 -0
  91. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_capture.py +115 -0
  92. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_domains.py +40 -0
  93. sidegraph-0.6.0/tests/test_server_graph_path.py +268 -0
  94. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_telemetry.py +20 -0
  95. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_stats_model.py +17 -0
  96. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_meta.py +12 -0
  97. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_migration.py +404 -0
  98. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_mutation_guard.py +6 -0
  99. sidegraph-0.6.0/tests/test_store_record_identity.py +407 -0
  100. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_stamping_marker.py +6 -4
  101. sidegraph-0.6.0/tests/test_store_symlinks.py +79 -0
  102. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_sync_clean.py +0 -7
  103. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_sync_fresh_clone.py +0 -7
  104. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_sync_integration.py +0 -7
  105. sidegraph-0.6.0/tests/test_sync_rebind.py +1310 -0
  106. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_sync_repoint.py +170 -0
  107. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_verify_snapshot.py +109 -0
  108. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_verify_transitions.py +368 -0
  109. sidegraph-0.6.0/tools/check_no_session_links.py +167 -0
  110. {sidegraph-0.4.0 → sidegraph-0.6.0}/uv.lock +5 -4
  111. sidegraph-0.4.0/src/sidegraph/host/claude_settings.py +0 -130
  112. sidegraph-0.4.0/tests/test_capture_propose.py +0 -417
  113. sidegraph-0.4.0/tests/test_capture_redact.py +0 -58
  114. sidegraph-0.4.0/tests/test_cli_okf.py +0 -230
  115. sidegraph-0.4.0/tests/test_host_claude_settings.py +0 -141
  116. sidegraph-0.4.0/tests/test_sandbox_hygiene.py +0 -133
  117. sidegraph-0.4.0/tests/test_sync_rebind.py +0 -457
  118. {sidegraph-0.4.0 → sidegraph-0.6.0}/.agents/plugins/marketplace.json +0 -0
  119. {sidegraph-0.4.0 → sidegraph-0.6.0}/.claude-plugin/marketplace.json +0 -0
  120. {sidegraph-0.4.0 → sidegraph-0.6.0}/.github/CODEOWNERS +0 -0
  121. {sidegraph-0.4.0 → sidegraph-0.6.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  122. {sidegraph-0.4.0 → sidegraph-0.6.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  123. {sidegraph-0.4.0 → sidegraph-0.6.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  124. {sidegraph-0.4.0 → sidegraph-0.6.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  125. {sidegraph-0.4.0 → sidegraph-0.6.0}/.github/secret_scanning.yml +0 -0
  126. {sidegraph-0.4.0 → sidegraph-0.6.0}/.github/workflows/publish.yml +0 -0
  127. {sidegraph-0.4.0 → sidegraph-0.6.0}/.github/workflows/scorecard.yml +0 -0
  128. {sidegraph-0.4.0 → sidegraph-0.6.0}/.gitignore +0 -0
  129. {sidegraph-0.4.0 → sidegraph-0.6.0}/.python-version +0 -0
  130. {sidegraph-0.4.0 → sidegraph-0.6.0}/AGENTS.md +0 -0
  131. {sidegraph-0.4.0 → sidegraph-0.6.0}/CODE_OF_CONDUCT.md +0 -0
  132. {sidegraph-0.4.0 → sidegraph-0.6.0}/CONTRIBUTING.md +0 -0
  133. {sidegraph-0.4.0 → sidegraph-0.6.0}/LICENSE +0 -0
  134. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/README.md +0 -0
  135. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/concepts/decision-memory.md +0 -0
  136. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/concepts/mind-model.md +0 -0
  137. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/getting-started/claude-code-setup.md +0 -0
  138. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/getting-started/codex-setup.md +0 -0
  139. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/getting-started/quickstart.md +0 -0
  140. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/guides/ci-cd-maintenance.md +0 -0
  141. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/guides/naming-your-domains.md +0 -0
  142. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/guides/team-workflow.md +0 -0
  143. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/guides/verifying-your-setup.md +0 -0
  144. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/integrations/codex.md +0 -0
  145. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/llms.txt +0 -0
  146. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/pilot-kit/README.md +0 -0
  147. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/pilot-kit/corpus_fit.py +0 -0
  148. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/pilot-kit/judge-prompt.md +0 -0
  149. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/pilot-kit/questions-prompt.md +0 -0
  150. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/pilot-kit/rubric-template.md +0 -0
  151. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/reference/git-bindings.md +0 -0
  152. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/reference/operations.md +0 -0
  153. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/reference/stability.md +0 -0
  154. {sidegraph-0.4.0 → sidegraph-0.6.0}/docs/whitepaper/index.md +0 -0
  155. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/.mcp.json +0 -0
  156. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/codex/hooks.json +0 -0
  157. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/codex/mcp.json +0 -0
  158. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/hooks/hooks.json +0 -0
  159. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/check-plan/SKILL.md +0 -0
  160. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/check-plan/agents/openai.yaml +0 -0
  161. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/explain-why/SKILL.md +0 -0
  162. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/explain-why/agents/openai.yaml +0 -0
  163. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/heal-anchors/agents/openai.yaml +0 -0
  164. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/import-adrs/agents/openai.yaml +0 -0
  165. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/manage-domains/SKILL.md +0 -0
  166. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/manage-domains/agents/openai.yaml +0 -0
  167. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/name-domains/SKILL.md +0 -0
  168. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/name-domains/agents/openai.yaml +0 -0
  169. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/ratify-decisions/SKILL.md +0 -0
  170. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/ratify-decisions/agents/openai.yaml +0 -0
  171. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/record-decision/agents/openai.yaml +0 -0
  172. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/record-fact/agents/openai.yaml +0 -0
  173. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/setup/SKILL.md +0 -0
  174. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/setup/agents/openai.yaml +0 -0
  175. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/stats/agents/openai.yaml +0 -0
  176. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/triage-drift/SKILL.md +0 -0
  177. {sidegraph-0.4.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/triage-drift/agents/openai.yaml +0 -0
  178. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/__init__.py +0 -0
  179. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/apply.py +0 -0
  180. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/model.py +0 -0
  181. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/planner.py +0 -0
  182. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/proof.py +0 -0
  183. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/review.py +0 -0
  184. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/scan.py +0 -0
  185. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/engine/__init__.py +0 -0
  186. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/host/__init__.py +0 -0
  187. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/profiles.py +0 -0
  188. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/retrieval.py +0 -0
  189. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/stats/__init__.py +0 -0
  190. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/stats/render.py +0 -0
  191. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/viz/__init__.py +0 -0
  192. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/viz/assets/vis-network.min.js +0 -0
  193. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/viz/model.py +0 -0
  194. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/viz/render.py +0 -0
  195. {sidegraph-0.4.0 → sidegraph-0.6.0}/src/sidegraph/viz/template.html +0 -0
  196. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/__init__.py +0 -0
  197. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/auto_policy/parity_goldens.json +0 -0
  198. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/bitfinex_slice.json +0 -0
  199. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/flows/bmad/_bmad-output/planning-artifacts/architecture/cache/ARCHITECTURE-SPINE.md +0 -0
  200. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/flows/generic-adr/docs/adr/001-retry.md +0 -0
  201. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/flows/genkovich-sdd/docs/features/cache/adr/001.md +0 -0
  202. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/flows/spec-kit/specs/cache/plan.md +0 -0
  203. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/flows/superpowers/docs/superpowers/specs/2026-07-01-cache-design.md +0 -0
  204. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/graph.json +0 -0
  205. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/hosts/claude/.claude/settings.json +0 -0
  206. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/hosts/claude/.mcp.json +0 -0
  207. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/hosts/codex/.codex/config.toml +0 -0
  208. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/hosts/codex/.codex/hooks/hooks.json +0 -0
  209. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/scan/docs/adr/001-safe.md +0 -0
  210. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/corpus/PUBLIC_CORPORA.txt +0 -0
  211. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/corpus/openspec/_provenance.json +0 -0
  212. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/corpus/openspec/graph.json +0 -0
  213. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/corpus/self-corpus/_provenance.json +0 -0
  214. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/corpus/self-corpus/expected/retrieval-engine-reader.md +0 -0
  215. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/corpus/self-corpus/graph.json +0 -0
  216. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/adr/0001-use-sessions.md +0 -0
  217. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/bmad/ARCHITECTURE-SPINE.md +0 -0
  218. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/bmad/tree/_bmad-output/planning-artifacts/architecture/architecture-payments-2026-07-30/.memlog.md +0 -0
  219. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/bmad/tree/_bmad-output/planning-artifacts/architecture/architecture-payments-2026-07-30/ARCHITECTURE-SPINE.md +0 -0
  220. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/bmad/tree/_bmad-output/planning-artifacts/prds/prd-payments-2026-07-30/prd.md +0 -0
  221. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/genkovich/0001-queue-backpressure.md +0 -0
  222. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/genkovich/sad.md +0 -0
  223. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/adr/0001-queue-backpressure.md +0 -0
  224. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/sad.md +0 -0
  225. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/spec.md +0 -0
  226. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/design-empty.md +0 -0
  227. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/design-h3-split.md +0 -0
  228. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/design-with-summary.md +0 -0
  229. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/design.md +0 -0
  230. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/proposal-alternatives.md +0 -0
  231. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/proposal.md +0 -0
  232. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/design.md +0 -0
  233. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/proposal.md +0 -0
  234. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/specs/cap/spec.md +0 -0
  235. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/tasks.md +0 -0
  236. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/changes/archive/2026-01-01-add-thing/design.md +0 -0
  237. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/changes/archive/2026-01-01-add-thing/proposal.md +0 -0
  238. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/config.yaml +0 -0
  239. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/specs/cap/spec.md +0 -0
  240. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/spec-kit/plan.md +0 -0
  241. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/spec-kit/tree/specs/003-payment-retries/plan.md +0 -0
  242. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/spec-kit/tree/specs/003-payment-retries/spec.md +0 -0
  243. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/superpowers/2026-07-01-example-design.md +0 -0
  244. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/flows/superpowers/2026-07-01-thin-design.md +0 -0
  245. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/fixtures/mini_graph.json +0 -0
  246. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_anchoring_mapping_refresh.py +0 -0
  247. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_bootstrap_apply.py +0 -0
  248. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_bootstrap_integrations.py +0 -0
  249. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_bootstrap_model.py +0 -0
  250. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_bootstrap_planner.py +0 -0
  251. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_bootstrap_proof.py +0 -0
  252. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_bootstrap_review.py +0 -0
  253. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_bootstrap_scan.py +0 -0
  254. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_capture_integration.py +0 -0
  255. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_cli_compact.py +0 -0
  256. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_cli_doctor.py +0 -0
  257. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_cli_ratify.py +0 -0
  258. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_cli_ratify_facts.py +0 -0
  259. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_cli_sync_check.py +0 -0
  260. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_cli_viz.py +0 -0
  261. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_codex_plugin.py +0 -0
  262. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_community_baseline.py +0 -0
  263. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_corpus_expected_renders.py +0 -0
  264. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_corpus_self_corpus.py +0 -0
  265. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_coverage_telemetry_e2e.py +0 -0
  266. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_digest_integrity.py +0 -0
  267. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_docs_claims.py +0 -0
  268. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_doctor_auto_share.py +0 -0
  269. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_doctor_code_drift.py +0 -0
  270. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_doctor_dangling_supports.py +0 -0
  271. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_doctor_duplicate_entity.py +0 -0
  272. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_doctor_graph_root_mismatch.py +0 -0
  273. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_doctor_never_surfaced.py +0 -0
  274. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_doctor_scan.py +0 -0
  275. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_doctor_stale_instructions.py +0 -0
  276. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_doctor_unratified_accept.py +0 -0
  277. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_domains.py +0 -0
  278. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_entity_duplicate_resolution.py +0 -0
  279. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_entity_get_or_create_race.py +0 -0
  280. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_fact_reachability_gate.py +0 -0
  281. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_flow_profile.py +0 -0
  282. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_git_bindings_blame.py +0 -0
  283. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_git_bindings_hook.py +0 -0
  284. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_git_bindings_provenance.py +0 -0
  285. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_host_drift_nudge.py +0 -0
  286. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_host_pretool.py +0 -0
  287. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_host_session_key.py +0 -0
  288. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_host_touch_events.py +0 -0
  289. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_mind_model_additive_fields.py +0 -0
  290. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_openspec_profile.py +0 -0
  291. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_pathless_descriptor_adoption.py +0 -0
  292. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_pilot_kit_corpus_fit.py +0 -0
  293. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_proposal_lifecycle.py +0 -0
  294. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_ratify_listing_gone_dark.py +0 -0
  295. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_reader_community_labels.py +0 -0
  296. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_reader_doc_nodes.py +0 -0
  297. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_reader_graph.py +0 -0
  298. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_reader_integration.py +0 -0
  299. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_reader_nodes_in_file.py +0 -0
  300. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_reader_perf.py +0 -0
  301. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_reader_rationale.py +0 -0
  302. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_reader_read.py +0 -0
  303. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_reader_resolve.py +0 -0
  304. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_reader_subdir_mismatch.py +0 -0
  305. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_reader_version.py +0 -0
  306. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_redaction_seeded.py +0 -0
  307. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_budget_counters.py +0 -0
  308. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_context.py +0 -0
  309. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_drift_marker.py +0 -0
  310. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_drilldown.py +0 -0
  311. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_facts.py +0 -0
  312. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_ids.py +0 -0
  313. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_integration.py +0 -0
  314. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_rank.py +0 -0
  315. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_seeds.py +0 -0
  316. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_shown_ids.py +0 -0
  317. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_terminal_evidence.py +0 -0
  318. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_thin_tools.py +0 -0
  319. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_toc.py +0 -0
  320. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_toptier.py +0 -0
  321. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_retrieval_unratified.py +0 -0
  322. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_schema_descriptor.py +0 -0
  323. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_schema_domain.py +0 -0
  324. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_schema_fact.py +0 -0
  325. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_add_anchors.py +0 -0
  326. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_anchoring.py +0 -0
  327. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_coverage_events.py +0 -0
  328. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_drilldown.py +0 -0
  329. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_facts.py +0 -0
  330. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_find_entity.py +0 -0
  331. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_get_store.py +0 -0
  332. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_get_task_context.py +0 -0
  333. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_import.py +0 -0
  334. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_mcp_smoke.py +0 -0
  335. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_prewrite_anchor_validation.py +0 -0
  336. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_ratify_facts.py +0 -0
  337. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_redaction.py +0 -0
  338. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_render_events.py +0 -0
  339. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_supersede.py +0 -0
  340. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_sync_anchors.py +0 -0
  341. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_thin_tools.py +0 -0
  342. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_server_verify.py +0 -0
  343. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_stats_graph.py +0 -0
  344. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_stats_render.py +0 -0
  345. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_stats_skill.py +0 -0
  346. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_stats_snapshot.py +0 -0
  347. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store.py +0 -0
  348. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_atomic_write_tmp_names.py +0 -0
  349. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_canonical_stat.py +0 -0
  350. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_compact.py +0 -0
  351. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_compact_review.py +0 -0
  352. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_concurrent_open.py +0 -0
  353. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_coverage_telemetry.py +0 -0
  354. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_derived_community.py +0 -0
  355. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_domains.py +0 -0
  356. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_entities.py +0 -0
  357. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_fact_cascade.py +0 -0
  358. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_facts.py +0 -0
  359. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_mutation_immediate.py +0 -0
  360. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_opens_with_merged_duplicate.py +0 -0
  361. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_persistence.py +0 -0
  362. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_ratification.py +0 -0
  363. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_rebuild_atomicity.py +0 -0
  364. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_render_events.py +0 -0
  365. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_retrieval.py +0 -0
  366. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_slug_conflicts.py +0 -0
  367. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_telemetry.py +0 -0
  368. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_threading.py +0 -0
  369. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_store_tmp_sweep_age.py +0 -0
  370. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_sync_domains.py +0 -0
  371. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_sync_drift_cache.py +0 -0
  372. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_sync_report_has_findings.py +0 -0
  373. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_sync_run.py +0 -0
  374. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_sync_toc_cache.py +0 -0
  375. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_sync_volatile_heal.py +0 -0
  376. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_sync_wiring.py +0 -0
  377. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_telemetry_retention.py +0 -0
  378. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_viz_asset_packaged.py +0 -0
  379. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_viz_model.py +0 -0
  380. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_viz_render_html.py +0 -0
  381. {sidegraph-0.4.0 → sidegraph-0.6.0}/tests/test_viz_render_json.py +0 -0
@@ -105,49 +105,9 @@ jobs:
105
105
  exit 0
106
106
  fi
107
107
  uv sync --locked
108
- git fetch origin "$GITHUB_BASE_REF"
109
108
  base="$(git merge-base "origin/$GITHUB_BASE_REF" HEAD)"
110
109
  uv run sidegraph-verify --against "$base" --json
111
110
 
112
- # A commit-msg hook (see .pre-commit-config.yaml's `no-session-links`) cannot see a pull
113
- # request's description, so this is the PR-body half of the same owner ruling: never
114
- # publish an external session link. Shares tools/check_no_session_links.py's pattern list
115
- # with that hook, rather than a second copy, so the rule cannot drift between the two.
116
- # `if: github.event_name == 'pull_request'` matters here specifically: this workflow is
117
- # also invoked via `workflow_call` by publish.yml on a tag push, which carries no PR body.
118
- # Lives in ci.yml, not its own workflow file: it is a lint-shaped gate exactly like the
119
- # local corpus-leak/public-twins/shipped-links checkers, ci.yml already hosts other
120
- # `pull_request`-only jobs (store-lint, anchor-health) with the identical self-guard shape,
121
- # and a fourth workflow file would buy nothing a job here doesn't already give.
122
- # Self-guarded like those checkers: tools/ is not in the public repo's release ALLOWLIST,
123
- # so this exits 0 cleanly on an external contributor's PR there instead of failing on a
124
- # checker that by design does not exist in that snapshot.
125
- pr-description-link-gate:
126
- if: github.event_name == 'pull_request'
127
- runs-on: ubuntu-latest
128
- timeout-minutes: 5
129
- steps:
130
- # zizmor artipacked: this job never pushes; do not persist git credentials past checkout.
131
- - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
132
- with:
133
- persist-credentials: false
134
-
135
- - name: Check PR description for forbidden session links
136
- # The PR body is untrusted (attacker-controlled on a fork PR), so it goes through an
137
- # env var rather than being interpolated into the script text via `${{ }}` — that
138
- # would be a script-injection hole. `github.event.pull_request.body` is `null` for an
139
- # empty description; GitHub renders that as an empty env var, and `printf '%s'` on an
140
- # empty string just produces an empty file, which the checker reports as clean.
141
- env:
142
- PR_BODY: ${{ github.event.pull_request.body }}
143
- run: |
144
- if [ ! -f tools/check_no_session_links.py ]; then
145
- echo "tools/check_no_session_links.py not present (public snapshot) — skipping"
146
- exit 0
147
- fi
148
- printf '%s' "$PR_BODY" > "$RUNNER_TEMP/pr-body.txt"
149
- python3 tools/check_no_session_links.py "$RUNNER_TEMP/pr-body.txt"
150
-
151
111
  # Recipe 1 self-applied: rebuild the graph from scratch and fail on attention findings
152
112
  # (stale decisions, empty/overbroad domains, slug conflicts, refresh failures). A
153
113
  # cache-less rebuild was verified label-identical to the local cached graph and the
@@ -0,0 +1,76 @@
1
+ # The PR half of the owner ruling "never publish an external session link", shared with the
2
+ # `no-session-links` commit-msg hook (.pre-commit-config.yaml) through
3
+ # tools/check_no_session_links.py, so the rule cannot drift between them. A commit-msg hook
4
+ # cannot see a pull request's title or description, and a commit made without the hook never
5
+ # passes through it, so this checks all three places text gets published:
6
+ # - the PR title and description, verbatim (lines starting with `#` are markdown headings
7
+ # there, not comments), and the title again because the default merge commit carries it;
8
+ # - the PR's recorded commit messages, exactly as they sit in history.
9
+ # Its own workflow file, not a job in ci.yml, so `edited` can re-run it without re-running
10
+ # the whole CI on every description edit. Every event for an open PR runs both steps: an
11
+ # `edited` run that skipped the commit check would go green on the same head SHA and replace
12
+ # a red run in the checks view. Edits to a closed or merged PR skip the commit check, so old
13
+ # history is not re-checked. No `concurrency` block: with one, a later run could cancel an
14
+ # in-flight `synchronize` run and leave the commits unchecked. The job takes seconds.
15
+ # Fails closed: the checker ships in the public snapshot too, and a run without it fails
16
+ # instead of skipping, so deleting or moving it cannot turn the gate green.
17
+ # Actions are pinned to commit SHAs (the tag comment records the version).
18
+ name: session-link-gate
19
+
20
+ on:
21
+ pull_request:
22
+ types: [opened, edited, reopened, synchronize]
23
+
24
+ permissions:
25
+ contents: read
26
+
27
+ jobs:
28
+ pr-description-link-gate:
29
+ runs-on: ubuntu-latest
30
+ timeout-minutes: 5
31
+ steps:
32
+ # zizmor artipacked: this job never pushes; do not persist git credentials past checkout.
33
+ # fetch-depth 0: the commit step needs the whole base..head range.
34
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
35
+ with:
36
+ persist-credentials: false
37
+ fetch-depth: 0
38
+
39
+ - name: Check PR title and description for forbidden session links
40
+ # Title and body are untrusted (attacker-controlled on a fork PR), so they go through
41
+ # env vars rather than `${{ }}` in the script text, which would be a script-injection
42
+ # hole. `github.event.pull_request.body` is `null` for an empty description; GitHub
43
+ # renders that as an empty env var. Reported line numbers run two higher than in the
44
+ # body: the title and a blank line come first.
45
+ env:
46
+ PR_TITLE: ${{ github.event.pull_request.title }}
47
+ PR_BODY: ${{ github.event.pull_request.body }}
48
+ run: |
49
+ if [ ! -f tools/check_no_session_links.py ]; then
50
+ echo "::error::tools/check_no_session_links.py is missing; the session-link gate cannot run"
51
+ exit 1
52
+ fi
53
+ printf '%s\n\n%s\n' "$PR_TITLE" "$PR_BODY" > "$RUNNER_TEMP/pr-text.txt"
54
+ python3 tools/check_no_session_links.py --published "$RUNNER_TEMP/pr-text.txt"
55
+
56
+ - name: Check the PR's commit messages for forbidden session links
57
+ # Runs on every event for an open PR, description edits included: a green run with
58
+ # this step skipped would replace a red one on the same head SHA. A closed or merged
59
+ # PR (its commits predate this gate) is not re-checked. A SHA matches no pattern, so
60
+ # each reported line points into the commit named above it; on failure the step lists
61
+ # the `commit` start lines (SHAs and line numbers only, never the offending text).
62
+ if: github.event.pull_request.state == 'open'
63
+ env:
64
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
65
+ HEAD_SHA: ${{ github.event.pull_request.head.sha }}
66
+ run: |
67
+ if [ ! -f tools/check_no_session_links.py ]; then
68
+ echo "::error::tools/check_no_session_links.py is missing; the session-link gate cannot run"
69
+ exit 1
70
+ fi
71
+ git log --format='commit %H%n%B' "$BASE_SHA..$HEAD_SHA" > "$RUNNER_TEMP/pr-commits.txt"
72
+ python3 tools/check_no_session_links.py --published "$RUNNER_TEMP/pr-commits.txt" || {
73
+ echo "commit start lines in the checked log:"
74
+ grep -n '^commit ' "$RUNNER_TEMP/pr-commits.txt"
75
+ exit 1
76
+ }
@@ -28,5 +28,6 @@ paths = [
28
28
  '''^tests/test_server_redaction\.py$''',
29
29
  '''^design/superpowers/plans/2026-07-06-capture-ratification\.md$''',
30
30
  '''^design/superpowers/plans/2026-07-10-facts-layer\.md$''',
31
+ '''^design/superpowers/reviews/2026-09-28-grok-whole-repo-review\.md$''',
31
32
  '''^src/sidegraph/viz/assets/vis-network\.min\.js$''',
32
33
  ]
@@ -115,10 +115,11 @@ repos:
115
115
  # nothing and would couple the gate to uv project discovery — which fails outright in a
116
116
  # tree whose pyproject uv cannot parse (the release script's own test fixtures).
117
117
  # The `test -f` guard exists because THIS FILE SHIPS: .pre-commit-config.yaml is in the
118
- # release ALLOWLIST while tools/ is not, and the release script verifies the snapshot by
119
- # running `pre-commit run --all-files` inside it. Without the guard, an always_run hook
120
- # would look for a checker that by design does not exist there and fail every release,
121
- # the public repo's CI, and every public contributor's first commit.
118
+ # release ALLOWLIST while tools/ ships only the session-link checker, and the release
119
+ # script verifies the snapshot by running `pre-commit run --all-files` inside it.
120
+ # Without the guard, an always_run hook would look for a checker that by design does
121
+ # not exist there and fail every release, the public repo's CI, and every public
122
+ # contributor's first commit.
122
123
  entry: bash -c 'test ! -f tools/corpus_leak.py || exec python3 tools/corpus_leak.py'
123
124
  language: system
124
125
  pass_filenames: false
@@ -139,8 +140,8 @@ repos:
139
140
  # AGENTS.public.md) with no base counterpart, or a plugin manifest that still points
140
141
  # at the working tree instead of the released package, would otherwise ship broken
141
142
  # and surface only when a consumer's install fails. Self-guarded like
142
- # corpus-leak-gate: tools/ is not in the release ALLOWLIST, so this checker does not
143
- # exist in the public snapshot or its CI.
143
+ # corpus-leak-gate: tools/ ships only the session-link checker, so this checker does
144
+ # not exist in the public snapshot or its CI.
144
145
  entry: bash -c 'test ! -f tools/check_public_twins.py || exec python3 tools/check_public_twins.py'
145
146
  language: system
146
147
  pass_filenames: false
@@ -150,8 +151,8 @@ repos:
150
151
  name: shipped-docs link check
151
152
  # A relative Markdown link that resolves in THIS repo can still 404 once the release
152
153
  # mapping is applied (design/whitepaper/draft.md -> docs/whitepaper/index.md, `.public.`
153
- # twins renamed onto their base names, design/ and tools/ absent) — this catches that
154
- # before the commit lands. Self-guarded: tools/ is not in the release ALLOWLIST.
154
+ # twins renamed onto their base names, design/ absent, tools/ reduced to the
155
+ # session-link checker) — this catches that before the commit lands. Self-guarded: tools/ ships only the session-link checker.
155
156
  entry: bash -c 'test ! -f tools/check_shipped_links.py || exec python3 tools/check_shipped_links.py'
156
157
  language: system
157
158
  pass_filenames: false
@@ -161,15 +162,15 @@ repos:
161
162
  name: no session links in commit message
162
163
  # Reads the commit message file git passes a commit-msg hook, never the changed
163
164
  # files — the forbidden patterns are tools/check_no_session_links.py's four
164
- # session-link shapes, the same ones .github/workflows/ci.yml's
165
- # `pr-description-link-gate` job checks against a PR body.
165
+ # session-link shapes, the same ones .github/workflows/session-link-gate.yml
166
+ # checks against a PR's title, body and recorded commit messages.
166
167
  # `stages: [commit-msg]` is load-bearing, not decoration: a hook with no explicit
167
168
  # `stages` inherits EVERY stage, and `pre-commit run --all-files` (CI's lint job, and
168
169
  # a developer's own habit) defaults to `--hook-stage pre-commit` — without this pin,
169
170
  # that plain run would try to execute this hook anyway, with no COMMIT_EDITMSG file
170
171
  # to check, and fail every lint run for a reason that has nothing to do with lint.
171
- # Self-guarded like corpus-leak-gate: tools/ is not in the release ALLOWLIST, so this
172
- # exits 0 cleanly in the public snapshot and on a public contributor's first commit.
172
+ # Self-guarded like corpus-leak-gate, though the checker does ship: the guard only covers a
173
+ # deleted checker, and the session-link-gate workflow is the gate that fails then.
173
174
  entry: bash -c 'test ! -f tools/check_no_session_links.py || exec python3 tools/check_no_session_links.py "$@"' --
174
175
  language: system
175
176
  stages: [commit-msg]
@@ -7,6 +7,306 @@ interfaces, exactly, and what each one promises: [`docs/reference/stability.md`]
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.6.0] — 2026-10-01
11
+
12
+ ### Added
13
+
14
+ - **`sidegraph-verify` reports `unsafe-record-id`.** A record file, `bindings/` file or
15
+ archive line whose id is not a single safe path segment is now a finding, and a
16
+ non-string id in a record or archive file no longer crashes the run with `unhashable type`.
17
+ - **`sidegraph-verify` reports a symlinked store entry as `symlinked-store-entry`.** One
18
+ violation per store-owned directory or file that is a symlink, so a committed link fails the
19
+ CI gate; `sidegraph-doctor` inherits it.
20
+
21
+ ### Changed
22
+
23
+ - **A `--graph` typed as a relative path resolves against the shell in `sidegraph-ratify`
24
+ and `sidegraph-stats`.** It used to resolve against the store's project. The default and
25
+ `$SIDEGRAPH_GRAPH` still follow the store. The same holds in every command that reads a
26
+ graph, so the copy-and-sync workflow works with `--graph graphify-out/graph.json` typed from
27
+ the repository.
28
+ - **A store in a nested directory needs an absolute `SIDEGRAPH_GRAPH`.** With
29
+ `SIDEGRAPH_DIR=.config/sidegraph` and a relative `SIDEGRAPH_GRAPH`, the CLI now looks for the
30
+ graph under `.config/` (the store's project) instead of using the shell's copy. A command
31
+ that needs the graph fails with a hint; `init`, `ratify`, `doctor` and `stats`, for which it
32
+ is optional, continue and print the hint (`stats` reports its graph metrics as unavailable). Set an absolute `SIDEGRAPH_GRAPH` or pass `--graph`. The MCP server now
33
+ follows the same rule (next entry); the hooks are unaffected.
34
+ - **The MCP server reads the graph that belongs to its store.** A relative `SIDEGRAPH_GRAPH`
35
+ (or the default `graphify-out/graph.json`) used to resolve against the server's working
36
+ directory, so a store reached by an absolute `SIDEGRAPH_DIR`, or a store in a nested directory,
37
+ could be synced against one project's graph by the CLI and another's by `sync_anchors` and the
38
+ retrieval tools, and the store's graph version flipped back and forth. It now resolves against
39
+ the store's project, the same rule the CLI uses, and an empty `SIDEGRAPH_GRAPH` counts as unset.
40
+ With the default layout (`.sidegraph` in the project, the server started there) nothing changes.
41
+ A nested store needs an absolute `SIDEGRAPH_GRAPH`; `sync_anchors` reports `graph not readable`
42
+ with the path and names the graph it found beside the working directory, when there is one.
43
+ - **A document is imported again once, if its `provenance.ref` changes.** A document
44
+ imported before this release from a subdirectory or by an absolute path is imported
45
+ again under its repository path. The old record stays. A leftover that is still `proposed` can be dropped with
46
+ `sidegraph-ratify --drop <id>`. An `accepted` leftover has no one-step retirement: leave
47
+ it, or supersede it by hand with `supersede_decision`, which writes a new record.
48
+ - **`sidegraph-import --path` (and domain `--paths`) match on directory boundaries.**
49
+ `--path payments` no longer imports `payments_v2/b.py`, and a partial-name prefix such as
50
+ `--path docs/adr/00` matches nothing; a prefix matches a file under that directory or
51
+ that exact file. `--path ""` still matches everything, and mixed with a real prefix it is
52
+ ignored. The domain `--paths` help already behaved this way and now says so.
53
+ - **The Stop hook skips the transcript of a session that is already captured.** It now peeks
54
+ at the capture ledger read-only before parsing the transcript, so every Stop after the
55
+ capturing one no longer re-reads the whole file.
56
+
57
+ ### Fixed
58
+
59
+ - **The derived initiative names the store's repository branch.** It used to come from the
60
+ branch of whatever directory the MCP server or CLI ran in. An inherited `GIT_DIR` or
61
+ `GIT_WORK_TREE` no longer redirects either the derived initiative or the captured commit.
62
+ - **A timestamp in the future no longer counts as fresh.** The capture session-id fallback and
63
+ the session attribution of retrieval telemetry treated a marker stamped ahead of the clock
64
+ as current; they now ignore it. The SessionStart dedupe still treats a same-session stamp
65
+ less than 60 seconds ahead as a duplicate (a parallel hook can write one), but a stamp
66
+ further ahead no longer suppresses the map until the clock catches up.
67
+ - **Every CLI command that takes a store and a `--graph` pairs the store with its own
68
+ project's graph by default.** `sidegraph-sync`, `sidegraph-import` (both modes),
69
+ `sidegraph-domains bootstrap`, `sidegraph-doctor` and `sidegraph-init` (whose found/missing
70
+ line used the shell's path) read the default graph relative to the
71
+ shell, so `--db A/.sidegraph` run from project B stamped A's store with B's graph version
72
+ and could rewrite A's anchors, import decisions, or bootstrap domains from B's graph. The
73
+ default and `$SIDEGRAPH_GRAPH` (an empty value counts as unset) now resolve against the
74
+ store's project, as `sidegraph-ratify` and `sidegraph-stats` already did; a store reached
75
+ through a symlinked `.sidegraph` keeps the link's project. When the store's project has no
76
+ graph but the same path exists beside the shell (a store copied elsewhere), one stderr hint
77
+ names `--graph <path>`; when both exist, a note says which was used. Error lines name the
78
+ resolved path.
79
+ - **`SIDEGRAPH_DB` naming a missing path no longer scaffolds its parent.** A missing
80
+ `SIDEGRAPH_DB=/proj/.sidegraph`, or a dangling link, resolved to `/proj` and a store was
81
+ created in the project root. Only a path ending in `.db` is rescued to its parent now; any
82
+ other missing path is used as given, and a dangling link fails to open without creating
83
+ anything.
84
+ - **`sidegraph-sync --check` documents domain-refresh failures.** The help and the module
85
+ docstring omitted the finding that already makes `--check` exit 2.
86
+ - **A move left `moved_uncommitted` is now re-verified after you commit it, even when the
87
+ graph was not rebuilt.** Committing a rename does not change `graph.json`, so the version
88
+ gate skipped every later sync and the leaf kept its old path until `--force`. Sync now
89
+ remembers such entities with the git `HEAD` it saw, and the first sync after `HEAD` moves
90
+ re-verifies just them (a narrow pass that leaves domain membership alone). The comment that
91
+ promised the next sync would heal it was wrong, and is corrected.
92
+ - **A decision with two leaves in one community no longer loses that community's binding when
93
+ one leaf leaves it.** Both leaves share one Tier-1 `community:*` row, and a renumber that
94
+ moved one leaf orphaned the row the other still held, so the decision stopped surfacing for
95
+ that community. Sync now settles a record's community rows after every leaf has been
96
+ rebound, and a new row carries the moved leaf's relation instead of `affects`. Damage from
97
+ earlier syncs is repaired when a later repoint touches the record, or when the index is
98
+ next rebuilt from the committed files.
99
+ - **Secret redaction covers quoted values and quoted keys.** `password: "one two"`,
100
+ `` token: `abc def` `` and `password = 'a b c'` were cut at the first space, leaving the rest
101
+ of the secret in the store, and `{"password": "hunter2 two"}` was not matched at all. A
102
+ quoted value is now taken whole, with any text glued to its closing quote, and a quoted
103
+ key matches too. JSON keys such as `"token_count"` now redact like the unquoted
104
+ `token_count:` already did. An escaped quote (`"alpha\" beta"`) does not end a quoted
105
+ value, and a quoted key stops at the next JSON field, so `{"password":"x y","reason":"z"}`
106
+ keeps `reason`.
107
+ - **A decision whose attached fact failed is left proposed under an auto-ratify policy,** and
108
+ an auto-accepted fact's write-guard message points to `add_anchors` instead of a drop that
109
+ the store refuses.
110
+ - **An initiative name is redacted before it becomes an entity, on every write path.** A
111
+ secret in `initiative`, or in a branch name the propose path derives one from, used to land
112
+ in the canonical `initiative:<name>` entity file. A blank or all-secret initiative now binds
113
+ nothing, and a padded name is trimmed (`" proj "` keys as `initiative:proj`).
114
+ - **`add_decision` binds its initiative with no graph or no anchors.** The Tier-0 binding was
115
+ made only inside the per-anchor loop, so a call without a reader or without an anchor
116
+ dropped it silently.
117
+ - **`add_domain`, `supersede_domain` and `sidegraph-domains add` redact the title and
118
+ summary.** Only `propose_domains` and the bootstrap did. The MCP results now carry
119
+ `redactions`, and the CLI prints a count line when it redacted something.
120
+ - **`propose_decisions` dedups a decision on its redacted title.** A title that held a secret
121
+ was compared raw against the stored, redacted one, so proposing it twice wrote it twice.
122
+ - **One failing draft no longer aborts a propose batch.** A step after the write (anchors,
123
+ initiative, tags, attached facts, auto-ratify) now leaves the result `written` with a
124
+ `reason`; an error before the write makes that draft `rejected`; each attached fact and each
125
+ domain is isolated the same way, and a failed TOC rebuild after `propose_domains` is
126
+ reported as a `toc:` warning. `KeyboardInterrupt` still propagates.
127
+ - **A record id can no longer become a path outside the store.** Every canonical writer built
128
+ `<dir>/<id>.json` from the id as given, so an id like `../../x` wrote outside the store.
129
+ The store now refuses to write an id that is not a single path segment, and the OKF export
130
+ skips such a decision, fact or entity with a warning.
131
+ - **A canonical file whose JSON id does not match its filename is skipped on reload, with a
132
+ warning on every open.** A file with a crafted id was indexed under that id, so one later
133
+ ratify could write outside the store. Duplicate ids let the later file silently win, and a
134
+ file with no id got a fresh ULID on every rebuild. Such files are now left out of the index
135
+ and named in a warning until they are fixed or removed. An existing index reloads once to
136
+ apply the rule. An archive line with an unsafe or non-string id is skipped instead of
137
+ making `Store()` fail.
138
+ - **An interrupted legacy migration no longer loses its staged work.** The legacy file is
139
+ renamed to its backup only after the staged directories have moved in, so an interruption
140
+ leaves it in place and the next open migrates again. A bare-file migration, which has to
141
+ rename first, keeps its staging directory and leaves a sentinel so the next open says what
142
+ to do. A sentinel younger than 60 seconds means a migration is running now: the open
143
+ refuses with "retry in a minute" and touches nothing, and deleting that sentinel early is
144
+ unsafe. A legacy row with an unsafe id fails the migration before anything is written, and
145
+ a row whose JSON omits its id takes its SQL primary key instead of a fresh one per retry.
146
+ - **The bootstrap catalog applies the same identity rule.** A record file with no id was
147
+ given a fresh ULID on every load, so the catalog fingerprint changed between two loads of
148
+ one store. Such files are now skipped with a warning.
149
+ - **The store refuses a symlinked directory or store file inside itself.** A symlinked
150
+ `decisions/` sent every record write, from the MCP server, the hooks and bootstrap alike, to
151
+ the link's target, and a symlinked `index.db` made SQLite write there. `Store()` now raises
152
+ before any migration or write, naming the entry, and `sidegraph-bootstrap` refuses before
153
+ the review prompts. A symlinked store root stays allowed. Bootstrap's action summary now
154
+ names the store path and any symlink between the repository root and it.
155
+ - **`sidegraph-bootstrap --report` no longer overwrites a file it is hard-linked to, and
156
+ protects the Codex hooks file the verifier really reads.** The guard compared resolved
157
+ paths, so a hard link to a host config passed it and the report truncated the shared file.
158
+ It also protected only the legacy `.codex/hooks/hooks.json`, not `.codex/hooks.json`. The
159
+ report is now published by replace, and one list of host-config paths feeds both the
160
+ verifier and the guard. The guard covers every host's config file, whichever `--host` is
161
+ selected.
162
+ - **`sidegraph-import --docs` keys a document inside the repository by its repository path,
163
+ whatever directory it runs from.** Run from a subdirectory or given an absolute path, a
164
+ document used to miss its file node in the graph, skip as unanchorable, and get a
165
+ different `provenance.ref` from the same document imported at the root. Profile discovery
166
+ also finds the profile's documents from any directory in the repository, and the
167
+ unanchorable warning now fires only outside a git work tree, where the current directory
168
+ stands in for the root. Build the graph from the repository root: a graph built from a
169
+ subdirectory leaves documents unanchorable.
170
+ - **`--docs` refuses a markdown file that is a symlink to a target outside the repository.**
171
+ It used to read the target under `--any-doc`. The document is counted as `refused: a symlink
172
+ pointing outside the repository`, and so is a profile-discovery hit that resolves outside
173
+ the repository (for example through a symlinked directory). A symlinked directory inside
174
+ the repository that points inside it imports under the path you named, and one that points
175
+ outside the repository is refused. A symlink to a file inside the repository imports under
176
+ its link path.
177
+ - **A re-import repairs a record that has no anchors.** A document whose record was written
178
+ but whose bindings never landed (a run that stopped in between, leaving no anchor other
179
+ than `tag:` bindings) used to be skipped as existing for good. It is now bound on the next import and reported as `had their anchors
180
+ repaired`.
181
+ - **The `import_docs` docstring describes what it does:** the five compared fields, the
182
+ statuses it matches, the repair and the refusal.
183
+ - **`sidegraph-init` no longer writes `.claude/settings.json` through a symlink, and no
184
+ longer prints a traceback when the write fails.** A symlinked `.claude/` or `settings.json`
185
+ (live or dangling) is left untouched and the `env` line to add by hand is printed. A merge
186
+ into an existing file is now published by replacing it atomically, so an interruption
187
+ cannot leave a truncated file, and any write failure (a read-only `.claude/`, for example)
188
+ is reported the same way instead of raising. An `env` block that is `null` or not an
189
+ object, and a settings file that changes while init runs, are skipped the same way, not
190
+ raised, and a link swapped in just before the write is refused. A write-protected file is
191
+ respected when init runs as root too.
192
+ - **`sidegraph-doctor`, the drift refresh the session hooks run, and `sidegraph-stats` now
193
+ open the index correctly when the store's path contains `#`, `?`, or `%` followed by two
194
+ hex digits.** Their read-only SQLite URI was built from the unquoted path.
195
+ **Doctor reported its index checks as skipped**, blaming a missing index and suggesting
196
+ `sidegraph-sync`, which could not help. **The session drift refresh silently stopped
197
+ excluding orphaned bindings.** **Stats failed.** For `#` and `?`, an empty file was also
198
+ created at the store path cut short at that character, and an unrelated database there
199
+ could be read instead.
200
+ - **The session-link gate checks every line that gets published.** Lines starting with `#` in
201
+ a PR description, and in commit messages made with `git commit -m`/`-F`, which git records,
202
+ are now checked. The PR title and the PR's recorded commit messages are checked too. The
203
+ check re-runs when a PR description is edited. The public repository runs the check too:
204
+ the release snapshot ships the checker, and the workflow fails when the checker is missing
205
+ instead of skipping.
206
+ - **`sidegraph-export-okf` refuses a symlinked `--out`, and a failed export no longer
207
+ destroys the previous one.** A symlinked output directory used to be written through, or
208
+ cleared, wherever it pointed, and a write that failed midway left a partial bundle after
209
+ the old export was already deleted. The new bundle is now built beside `--out` and
210
+ swapped in only when complete, except for a mount point, a `--out` that is the current
211
+ directory, an unwritable or non-directory parent, or a previous export that cannot be
212
+ renamed aside, which are written in place as before (a write failure there can leave a
213
+ partial export). The in-place write goes to the validated, resolved directory.
214
+ - **An unreadable store or graph directory no longer ends in a traceback.** On Python 3.13 a store or
215
+ graph whose directory could not be read (permission denied) made `sidegraph-sync`,
216
+ `sidegraph-import`, `sidegraph-domains bootstrap`, `sidegraph-init`, `sidegraph-stats` and
217
+ `sidegraph-ratify` (on a domain accept) exit with an uncaught `PermissionError`. An unreadable
218
+ store is now reported on the command's error line (exit 1; 2 for `sidegraph-stats`). An
219
+ unreadable graph is treated as a missing one: `sidegraph-sync`, `sidegraph-import` and
220
+ `sidegraph-domains bootstrap` stop with `graph not readable`, and the other commands carry on
221
+ without a graph.
222
+ A working directory that cannot be read skips the graph hint and the `sync_anchors` hint instead of
223
+ raising; other code that resolves a relative path against it may still raise.
224
+ - **A retried Tier-1 reconcile that could not run is no longer reported as done.** A
225
+ remembered community reconcile whose record still has a live or degraded Tier-2 anchor
226
+ with no recorded community kept being treated as a success: the key was cleared, the sync
227
+ said `moved`, and the stale row stayed live. It is now kept, and retried silently on every
228
+ sync.
229
+ - **Sync, verify and doctor ask git about the repository their own files are in.**
230
+ `sidegraph-sync` (the graph's directory), `sidegraph-verify --against` and
231
+ `sidegraph-doctor` (the store's, and its graph-root check's) no longer inherit an ambient `GIT_DIR` or
232
+ `GIT_WORK_TREE`, which could make sync read another repository's `HEAD` and adopt a rename
233
+ that was never committed. The lazy sync run by `SessionStart` and retrieval, and the
234
+ `SessionStart` drift cache, are fixed too. `sidegraph-init` and `sidegraph-import` resolve
235
+ the repository root from the current directory the same way. A work tree whose repository
236
+ is found only through `GIT_DIR` now needs a `.git` file containing `gitdir: <path>`, and
237
+ `core.bare=false` in that repository.
238
+ - **The sync docs list every condition that prevents a skip.** A remembered Tier-1
239
+ reconcile that is repaired or fails again also makes a plain sync report instead of
240
+ skipping.
241
+ - **Documentation and help text match what the code does.** The PreToolUse docs name the
242
+ real `Read|Grep|Edit|Write` matcher and the two nudge forms, each at most once per session.
243
+ The `add_decision`, `supersede_decision`, `add_fact`, `supersede_fact` and
244
+ `propose_decisions` tool descriptions list `anchors_orphaned`. `sidegraph-ratify --help`
245
+ says `--all` also accepts standalone facts, and `--help` for `sidegraph-verify`,
246
+ `-doctor` and `-blame` no longer promises a legacy `*.db` migration they never perform.
247
+ `SECURITY.md` states local retrieval telemetry and the output paths commands write to.
248
+
249
+ ## [0.5.0] — 2026-09-23
250
+
251
+ ### Changed
252
+
253
+ - **The public `main`, which the plugin manifests install from, moves only at releases.**
254
+ The plugin runs whatever `main` holds, so a snapshot pushed between releases used to reach
255
+ every plugin user at once. The release script now pushes `main` only for a release: it
256
+ refuses unless the version it carries is untagged in the public repository and
257
+ `CHANGELOG.md` dates it.
258
+
259
+ ### Fixed
260
+
261
+ - **`sidegraph-init` now says to restart the Claude Code session after it writes
262
+ `SIDEGRAPH_RATIFY_POLICY`.** The Sidegraph MCP server reads the policy from the
263
+ environment it started with, so a server started before `sidegraph-init` kept proposing
264
+ under the old policy until the session restarted, and nothing said so.
265
+ - **`sidegraph-verify --against` no longer flags a ratification of an already-committed
266
+ proposal, or a supersede/drop that touches a record written before a later schema addition
267
+ (`Provenance.commit`, `Domain.seed_anchors`/`path_prefixes`) existed.** Ratifying a
268
+ decision, fact, or domain stamps `ratified_at`/`ratified_by`, and neither field was on the
269
+ transition layer's mutable allow-list, so the stamp alone was reported as an illegal field
270
+ change. Separately, rewriting an old record that predates a field added to its schema
271
+ serializes that field back in as its default, which a plain top-level or whole-list
272
+ comparison also read as a change. The ratifier stamp may now be set once, from a proposed
273
+ record, landing on any state reached through accepted within the diffed range; an absent
274
+ field now counts as the same value as an explicit `null` or an empty list/object, at every
275
+ nesting depth and inside list items. A field whose default is a non-empty value is not
276
+ covered by this.
277
+ - **`sidegraph-import --docs` no longer aborts on a file that is not valid UTF-8.** It
278
+ decoded every document as strict UTF-8 with no handler, so one document saved in
279
+ `cp1251` (or carrying a stray non-UTF-8 byte) raised and stopped the whole run, with
280
+ nothing after it imported and no report printed. The file is now a named skip
281
+ (`skipped_undecodable`) instead: the run continues, and both the real run and
282
+ `--dry-run` print the skipped path(s), last.
283
+ - **`sidegraph-import --docs` now reads a UTF-8 document that starts with a byte-order mark
284
+ (BOM).** The BOM used to survive into the parsed text, so the H1 and any frontmatter never
285
+ matched, and a real decision document was silently counted `skipped_not_decision`. It is
286
+ now stripped before parsing. `sidegraph-bootstrap` still reads such a file without
287
+ stripping it.
288
+
289
+ Re-importing a BOM document that an earlier version did import can change its record,
290
+ once:
291
+ - On the `openspec` profile, a BOM `proposal.md` had imported under a title built from its
292
+ path. The re-import supersedes it with the real H1 title.
293
+ - Frontmatter the BOM hid is now honoured. A document marked `status: superseded` now
294
+ counts `skipped_superseded_frontmatter`, and its earlier live record stays as it is.
295
+ - A document marked as a draft, proposed, pending or under review keeps its earlier
296
+ `accepted` record: a re-import compares content, not status, and the content is
297
+ unchanged.
298
+
299
+ Retiring or re-proposing such a record is manual.
300
+
301
+ ### Security
302
+
303
+ - **The lockfile moves `anyio` from 4.14.1 to 4.15.1**, past three advisories fixed in
304
+ 4.14.2: TLS certificate spoofing through IDNA 2003 host-name encoding (critical),
305
+ `run_process` keeping the parent's supplementary groups (high), and process-pool workers
306
+ blocking on undrained stderr (moderate). The published package does not pin `anyio`, so
307
+ this changes development and CI environments and installs made from `uv.lock`; a fresh
308
+ install already resolves a fixed version.
309
+
10
310
  ## [0.4.0] — 2026-09-22
11
311
 
12
312
  ### Fixed
@@ -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.4.0) — the full loop (capture, ratification, mistakes-first
16
+ Sidegraph is pre-1.0 (v0.6.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
@@ -30,10 +30,11 @@ away for convenience.
30
30
  2. **The store is append-only — and sync-clean.** Never hard-delete a `Decision`, `Fact`, or
31
31
  `Domain`. Reversal = set `valid_to`/flip status on the old record + create a new one with
32
32
  `supersedes`. Superseded records stay retrievable as "tried before, abandoned because…" —
33
- that history *is* the product. A graph rebuild (`sidegraph-sync`) must never produce a git
34
- diff: it only ever touches derived, gitignored state (the local index, entity mappings,
35
- binding status, the TOC cache), never a committed record file (community labels are
36
- derived state, never committed).
33
+ that history *is* the product. A graph rebuild (`sidegraph-sync`) must not produce a git
34
+ diff from regenerable state: it only ever touches derived, gitignored state (the local
35
+ index, entity mappings, binding status, the TOC cache), never a committed record file
36
+ (community labels are derived state, never committed). The one exception: a confirmed
37
+ leaf-file move may update that entity's committed descriptor.
37
38
  3. **The store format is a public contract.** File-per-record JSON, a stamped
38
39
  `schema_version`, and the append-only/merge rules are specified in
39
40
  [`docs/reference/store-format.md`](docs/reference/store-format.md) — that page is the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sidegraph
3
- Version: 0.4.0
3
+ Version: 0.6.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
@@ -84,9 +84,10 @@ only ever reads `graph.json`, so the plain install above is all it needs.
84
84
  uv tool install sidegraph # from PyPI — puts sidegraph-init / sidegraph-mcp / … on PATH
85
85
  sidegraph-init
86
86
 
87
- # Prefer the latest unreleased build straight from git instead of PyPI? Swap step 3 for:
87
+ # Prefer running straight from git instead of PyPI? Swap step 3 for:
88
88
  # uvx --from git+https://github.com/SantyagoSeaman/sidegraph.git@main sidegraph-init
89
- # `@main` is a mutable ref — it moves under you. Pin a tag or a SHA for CI.
89
+ # `@main` moves only when a release is cut. It is still a mutable ref: a later cache refresh can
90
+ # install a newer one. Pin a tag or a SHA for CI.
90
91
  ```
91
92
 
92
93
  4. **Name your domains** — turns the graph's communities into a described table of
@@ -166,7 +167,7 @@ projects the full store, history included, into an OKF v0.1 bundle any OKF consu
166
167
  next session ◀── SessionStart TOC anchored to entities in the
167
168
  of named domains ◀── get_task_context ◀────── engine's graph (read-only);
168
169
  mistakes first drill_down re-anchored after refactors
169
- blind Read/Grep ──▶ nudged back to get_task_context (once per session)
170
+ blind Read/Grep ──▶ nudged back to get_task_context (each form once per session)
170
171
  ```
171
172
 
172
173
  Two layers age differently: the **structure** layer (the code graph — entities,
@@ -56,9 +56,10 @@ only ever reads `graph.json`, so the plain install above is all it needs.
56
56
  uv tool install sidegraph # from PyPI — puts sidegraph-init / sidegraph-mcp / … on PATH
57
57
  sidegraph-init
58
58
 
59
- # Prefer the latest unreleased build straight from git instead of PyPI? Swap step 3 for:
59
+ # Prefer running straight from git instead of PyPI? Swap step 3 for:
60
60
  # uvx --from git+https://github.com/SantyagoSeaman/sidegraph.git@main sidegraph-init
61
- # `@main` is a mutable ref — it moves under you. Pin a tag or a SHA for CI.
61
+ # `@main` moves only when a release is cut. It is still a mutable ref: a later cache refresh can
62
+ # install a newer one. Pin a tag or a SHA for CI.
62
63
  ```
63
64
 
64
65
  4. **Name your domains** — turns the graph's communities into a described table of
@@ -138,7 +139,7 @@ projects the full store, history included, into an OKF v0.1 bundle any OKF consu
138
139
  next session ◀── SessionStart TOC anchored to entities in the
139
140
  of named domains ◀── get_task_context ◀────── engine's graph (read-only);
140
141
  mistakes first drill_down re-anchored after refactors
141
- blind Read/Grep ──▶ nudged back to get_task_context (once per session)
142
+ blind Read/Grep ──▶ nudged back to get_task_context (each form once per session)
142
143
  ```
143
144
 
144
145
  Two layers age differently: the **structure** layer (the code graph — entities,
@@ -20,11 +20,19 @@ Sidegraph is a local-only tool. Its entire data surface:
20
20
  store (`decisions.db`, from before store schema 0.4.0) triggers a one-time migration
21
21
  that renames the legacy file to `decisions.db.migrated-backup` (kept, never deleted)
22
22
  alongside writing the new
23
- directory layout. Outside `.sidegraph/`, the only filesystem writes are the standard
24
- config snippets you install yourself (`.mcp.json`, hook entries) — Sidegraph touches
25
- nothing else. See [`docs/reference/store-format.md`](docs/reference/store-format.md)
26
- for the full layout.
27
- - **Network:** none. No telemetry, no phone-home, nothing leaves your machine. The only
23
+ directory layout. The store is the default persistence location, not the only one:
24
+ `sidegraph-init` can write `.claude/settings.json` (the ratification-policy env entry);
25
+ the visualization, OKF export and bootstrap-report commands write to the output paths you
26
+ give them; and the optional `sidegraph-prepare-commit-msg` git hook, once you install it,
27
+ adds commented decision trailers to the commit message file git hands it
28
+ (normally `.git/COMMIT_EDITMSG`). Beyond those, the only filesystem writes are the standard config
29
+ snippets you install yourself (`.mcp.json`, hook entries) — Sidegraph touches nothing
30
+ else. See [`docs/reference/store-format.md`](docs/reference/store-format.md) for the full
31
+ layout.
32
+ - **Network:** none. No remote telemetry, no phone-home, nothing leaves your machine. Local
33
+ retrieval telemetry is recorded in the gitignored `index.db` by default (which records
34
+ were shown and which files were touched, never uploaded); set `SIDEGRAPH_TELEMETRY=off` to
35
+ stop new recording. The only
28
36
  network-using feature is the *optional* semantic documentation pass, which is executed
29
37
  by the separate Graphify CLI against the LLM provider you configure — not by Sidegraph.
30
38