sidegraph 0.5.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.
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.github/workflows/ci.yml +0 -39
- sidegraph-0.7.0/.github/workflows/session-link-gate.yml +76 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.gitleaks.toml +1 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.pre-commit-config.yaml +13 -12
- {sidegraph-0.5.0 → sidegraph-0.7.0}/CHANGELOG.md +434 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/CLAUDE.md +6 -5
- {sidegraph-0.5.0 → sidegraph-0.7.0}/PKG-INFO +2 -2
- {sidegraph-0.5.0 → sidegraph-0.7.0}/README.md +1 -1
- {sidegraph-0.5.0 → sidegraph-0.7.0}/SECURITY.md +13 -5
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/concepts/anchoring.md +53 -17
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/concepts/data-model.md +3 -2
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/concepts/mind-model.md +7 -7
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/concepts/retrieval.md +59 -25
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/getting-started/bootstrap.md +5 -1
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/getting-started/claude-code-setup.md +13 -6
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/getting-started/codex-setup.md +10 -2
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/guides/capturing-decisions.md +21 -8
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/guides/retrieval-in-sessions.md +15 -5
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/guides/semantic-docs.md +5 -4
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/guides/surviving-refactors.md +58 -13
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/guides/verifying-your-setup.md +3 -2
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/integrations/claude-code.md +72 -24
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/integrations/codex.md +53 -6
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/integrations/graphify.md +75 -11
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/reference/cli.md +144 -58
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/reference/configuration.md +62 -17
- sidegraph-0.7.0/docs/reference/hooks.md +454 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/reference/mcp-tools.md +111 -21
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/reference/operations.md +1 -1
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/reference/store-format.md +73 -4
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/.claude-plugin/plugin.json +1 -1
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/.codex-plugin/plugin.json +1 -1
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/codex/hooks.json +2 -2
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/hooks/hooks.json +3 -3
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/heal-anchors/SKILL.md +4 -2
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/import-adrs/SKILL.md +16 -5
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/record-decision/SKILL.md +12 -8
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/record-fact/SKILL.md +9 -5
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/stats/SKILL.md +6 -5
- {sidegraph-0.5.0 → sidegraph-0.7.0}/pyproject.toml +1 -1
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/__init__.py +1 -1
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/anchoring.py +3 -20
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/catalog.py +44 -9
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/cli.py +68 -29
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/integrations.py +23 -5
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/capture.py +532 -303
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/cli.py +237 -126
- sidegraph-0.7.0/src/sidegraph/config.py +533 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/doc_import.py +179 -37
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/doctor.py +41 -3
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/domains.py +2 -1
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/engine/reader.py +334 -6
- sidegraph-0.7.0/src/sidegraph/freshness.py +59 -0
- sidegraph-0.7.0/src/sidegraph/gitenv.py +41 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/gitio.py +2 -1
- sidegraph-0.7.0/src/sidegraph/host/claude_settings.py +244 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/host/hooks.py +462 -94
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/importer.py +15 -3
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/okf.py +260 -23
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/retrieval.py +157 -71
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/schema.py +23 -1
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/server.py +378 -64
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/stats/model.py +23 -2
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/stats/render.py +23 -3
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/store.py +599 -67
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/sync.py +685 -93
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/verify.py +73 -3
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/conftest.py +25 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/auto_policy/parity_goldens.json +1 -1
- sidegraph-0.7.0/tests/fixtures/member_names_python_graph.json +109 -0
- sidegraph-0.7.0/tests/fixtures/member_names_swift_graph.json +77 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_anchoring.py +2 -14
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_bootstrap_catalog.py +91 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_bootstrap_cli.py +257 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_capture_auto_accept.py +0 -8
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_capture_facts.py +0 -14
- sidegraph-0.7.0/tests/test_capture_initiative.py +185 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_capture_neighbors.py +0 -7
- sidegraph-0.7.0/tests/test_capture_propose.py +802 -0
- sidegraph-0.7.0/tests/test_capture_redact.py +184 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_cli_domains.py +39 -0
- sidegraph-0.7.0/tests/test_cli_graph_paths.py +535 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_cli_import.py +217 -25
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_cli_init.py +113 -0
- sidegraph-0.7.0/tests/test_cli_okf.py +819 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_cli_stats.py +16 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_cli_sync.py +19 -4
- sidegraph-0.7.0/tests/test_cli_unreadable_paths.py +261 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_config.py +45 -0
- sidegraph-0.7.0/tests/test_config_ancestor_lookup.py +265 -0
- sidegraph-0.7.0/tests/test_config_borrowed_graph.py +279 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_digest_integrity.py +23 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_doc_corpus_integration.py +0 -7
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_doc_import.py +429 -6
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_docs_claims.py +33 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_doctor.py +102 -0
- sidegraph-0.7.0/tests/test_doctor_graph_stale.py +90 -0
- sidegraph-0.7.0/tests/test_git_env.py +138 -0
- sidegraph-0.7.0/tests/test_graph_freshness.py +552 -0
- sidegraph-0.7.0/tests/test_hook_spawn_guard.py +291 -0
- sidegraph-0.7.0/tests/test_host_agent_state.py +300 -0
- sidegraph-0.7.0/tests/test_host_borrowed_graph.py +288 -0
- sidegraph-0.7.0/tests/test_host_claude_settings.py +554 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_host_pretool.py +6 -6
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_host_session_start.py +211 -6
- sidegraph-0.7.0/tests/test_host_session_start_concurrent.py +151 -0
- sidegraph-0.7.0/tests/test_host_stop.py +1471 -0
- sidegraph-0.7.0/tests/test_host_subdirectory_launch.py +282 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_host_touch_events.py +1 -1
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_importer.py +42 -0
- sidegraph-0.7.0/tests/test_member_anchor_wiring.py +320 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_okf.py +29 -1
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_ratify_policy.py +32 -41
- sidegraph-0.7.0/tests/test_reader_member_names.py +369 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_repoint_integration.py +0 -7
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_toc.py +180 -3
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_schema_descriptor.py +34 -0
- sidegraph-0.7.0/tests/test_server_borrowed_graph.py +543 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_capture.py +115 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_domains.py +40 -0
- sidegraph-0.7.0/tests/test_server_graph_freshness.py +373 -0
- sidegraph-0.7.0/tests/test_server_graph_path.py +269 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_render_events.py +1 -1
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_telemetry.py +20 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_stats_graph.py +47 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_stats_model.py +17 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_stats_render.py +97 -0
- sidegraph-0.7.0/tests/test_store_agent_state.py +282 -0
- sidegraph-0.7.0/tests/test_store_binding_index.py +91 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_meta.py +12 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_migration.py +404 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_mutation_guard.py +25 -1
- sidegraph-0.7.0/tests/test_store_record_identity.py +407 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_stamping_marker.py +6 -4
- sidegraph-0.7.0/tests/test_store_symlinks.py +79 -0
- sidegraph-0.7.0/tests/test_store_update_meta_if.py +60 -0
- sidegraph-0.7.0/tests/test_sync_canonical_writes.py +171 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_sync_clean.py +11 -17
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_sync_fresh_clone.py +0 -7
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_sync_integration.py +10 -14
- sidegraph-0.7.0/tests/test_sync_moved_adoption.py +708 -0
- sidegraph-0.7.0/tests/test_sync_rebind.py +1319 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_sync_repoint.py +170 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_sync_run.py +11 -8
- sidegraph-0.7.0/tests/test_sync_toc_cache.py +251 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_verify_snapshot.py +109 -0
- sidegraph-0.7.0/tools/check_no_session_links.py +167 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/uv.lock +1 -1
- sidegraph-0.5.0/docs/reference/hooks.md +0 -292
- sidegraph-0.5.0/src/sidegraph/config.py +0 -156
- sidegraph-0.5.0/src/sidegraph/host/claude_settings.py +0 -130
- sidegraph-0.5.0/tests/test_capture_propose.py +0 -417
- sidegraph-0.5.0/tests/test_capture_redact.py +0 -58
- sidegraph-0.5.0/tests/test_cli_okf.py +0 -230
- sidegraph-0.5.0/tests/test_host_claude_settings.py +0 -141
- sidegraph-0.5.0/tests/test_host_stop.py +0 -738
- sidegraph-0.5.0/tests/test_sync_rebind.py +0 -457
- sidegraph-0.5.0/tests/test_sync_toc_cache.py +0 -125
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.agents/plugins/marketplace.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.claude-plugin/marketplace.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.github/CODEOWNERS +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.github/secret_scanning.yml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.github/workflows/publish.yml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.github/workflows/scorecard.yml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.gitignore +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/.python-version +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/AGENTS.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/CODE_OF_CONDUCT.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/CONTRIBUTING.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/LICENSE +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/README.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/concepts/decision-memory.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/getting-started/installation.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/getting-started/quickstart.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/guides/ci-cd-maintenance.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/guides/naming-your-domains.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/guides/team-workflow.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/llms.txt +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/pilot-kit/README.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/pilot-kit/corpus_fit.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/pilot-kit/judge-prompt.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/pilot-kit/questions-prompt.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/pilot-kit/rubric-template.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/reference/git-bindings.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/reference/releasing.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/reference/stability.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/docs/whitepaper/index.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/.mcp.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/codex/mcp.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/check-plan/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/check-plan/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/explain-why/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/explain-why/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/heal-anchors/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/import-adrs/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/manage-domains/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/manage-domains/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/name-domains/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/name-domains/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/ratify-decisions/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/ratify-decisions/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/record-decision/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/record-fact/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/setup/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/setup/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/stats/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/triage-drift/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/plugin/sidegraph/skills/triage-drift/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/__init__.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/apply.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/model.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/planner.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/proof.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/review.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/bootstrap/scan.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/engine/__init__.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/host/__init__.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/profiles.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/stats/__init__.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/viz/__init__.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/viz/assets/vis-network.min.js +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/viz/model.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/viz/render.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/src/sidegraph/viz/template.html +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/__init__.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/bitfinex_slice.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/flows/bmad/_bmad-output/planning-artifacts/architecture/cache/ARCHITECTURE-SPINE.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/flows/generic-adr/docs/adr/001-retry.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/flows/genkovich-sdd/docs/features/cache/adr/001.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/flows/spec-kit/specs/cache/plan.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/flows/superpowers/docs/superpowers/specs/2026-07-01-cache-design.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/graph.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/hosts/claude/.claude/settings.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/hosts/claude/.mcp.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/hosts/codex/.codex/config.toml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/hosts/codex/.codex/hooks/hooks.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/bootstrap/scan/docs/adr/001-safe.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/corpus/PUBLIC_CORPORA.txt +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/corpus/openspec/_provenance.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/corpus/openspec/graph.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/corpus/self-corpus/_provenance.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/corpus/self-corpus/expected/retrieval-engine-reader.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/corpus/self-corpus/graph.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/adr/0001-use-sessions.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/bmad/ARCHITECTURE-SPINE.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/bmad/tree/_bmad-output/planning-artifacts/architecture/architecture-payments-2026-07-30/.memlog.md +0 -0
- {sidegraph-0.5.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
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/bmad/tree/_bmad-output/planning-artifacts/prds/prd-payments-2026-07-30/prd.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/genkovich/0001-queue-backpressure.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/genkovich/sad.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/adr/0001-queue-backpressure.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/sad.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/spec.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/design-empty.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/design-h3-split.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/design-with-summary.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/design.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/proposal-alternatives.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/proposal.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/design.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/proposal.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/specs/cap/spec.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/tasks.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/changes/archive/2026-01-01-add-thing/design.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/changes/archive/2026-01-01-add-thing/proposal.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/config.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/openspec/tree/openspec/specs/cap/spec.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/spec-kit/plan.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/spec-kit/tree/specs/003-payment-retries/plan.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/spec-kit/tree/specs/003-payment-retries/spec.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/superpowers/2026-07-01-example-design.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/flows/superpowers/2026-07-01-thin-design.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/fixtures/mini_graph.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_anchoring_mapping_refresh.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_bootstrap_apply.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_bootstrap_integrations.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_bootstrap_model.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_bootstrap_planner.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_bootstrap_proof.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_bootstrap_review.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_bootstrap_scan.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_capture_integration.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_cli_compact.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_cli_doctor.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_cli_ratify.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_cli_ratify_facts.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_cli_sync_check.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_cli_viz.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_codex_plugin.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_community_baseline.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_corpus_expected_renders.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_corpus_self_corpus.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_coverage_telemetry_e2e.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_doctor_auto_share.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_doctor_code_drift.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_doctor_dangling_supports.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_doctor_duplicate_entity.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_doctor_graph_root_mismatch.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_doctor_never_surfaced.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_doctor_scan.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_doctor_stale_instructions.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_doctor_unratified_accept.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_domains.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_entity_duplicate_resolution.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_entity_get_or_create_race.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_env_isolation.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_fact_reachability_gate.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_flow_profile.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_git_bindings_blame.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_git_bindings_hook.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_git_bindings_provenance.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_host_drift_nudge.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_host_session_key.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_mind_model_additive_fields.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_openspec_profile.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_pathless_descriptor_adoption.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_pilot_kit_corpus_fit.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_proposal_lifecycle.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_ratify_listing_gone_dark.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_reader_community_labels.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_reader_doc_nodes.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_reader_graph.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_reader_integration.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_reader_nodes_in_file.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_reader_perf.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_reader_rationale.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_reader_read.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_reader_resolve.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_reader_subdir_mismatch.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_reader_version.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_redaction_seeded.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_budget_counters.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_context.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_drift_marker.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_drilldown.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_facts.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_ids.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_integration.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_rank.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_seeds.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_shown_ids.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_terminal_evidence.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_thin_tools.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_toptier.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_retrieval_unratified.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_sandbox_hygiene.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_schema_domain.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_schema_fact.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_add_anchors.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_anchoring.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_coverage_events.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_drilldown.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_facts.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_find_entity.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_get_store.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_get_task_context.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_import.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_mcp_smoke.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_prewrite_anchor_validation.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_ratify_facts.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_redaction.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_supersede.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_sync_anchors.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_thin_tools.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_server_verify.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_stats_skill.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_stats_snapshot.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_atomic_write_tmp_names.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_canonical_stat.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_compact.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_compact_review.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_concurrent_open.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_coverage_telemetry.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_derived_community.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_domains.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_entities.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_fact_cascade.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_facts.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_mutation_immediate.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_opens_with_merged_duplicate.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_persistence.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_ratification.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_rebuild_atomicity.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_render_events.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_retrieval.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_slug_conflicts.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_telemetry.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_threading.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_store_tmp_sweep_age.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_sync_domains.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_sync_drift_cache.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_sync_report_has_findings.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_sync_volatile_heal.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_sync_wiring.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_telemetry_retention.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_verify_transitions.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_viz_asset_packaged.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_viz_model.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_viz_render_html.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.7.0}/tests/test_viz_render_json.py +0 -0
|
@@ -108,45 +108,6 @@ jobs:
|
|
|
108
108
|
base="$(git merge-base "origin/$GITHUB_BASE_REF" HEAD)"
|
|
109
109
|
uv run sidegraph-verify --against "$base" --json
|
|
110
110
|
|
|
111
|
-
# A commit-msg hook (see .pre-commit-config.yaml's `no-session-links`) cannot see a pull
|
|
112
|
-
# request's description, so this is the PR-body half of the same owner ruling: never
|
|
113
|
-
# publish an external session link. Shares tools/check_no_session_links.py's pattern list
|
|
114
|
-
# with that hook, rather than a second copy, so the rule cannot drift between the two.
|
|
115
|
-
# `if: github.event_name == 'pull_request'` matters here specifically: this workflow is
|
|
116
|
-
# also invoked via `workflow_call` by publish.yml on a tag push, which carries no PR body.
|
|
117
|
-
# Lives in ci.yml, not its own workflow file: it is a lint-shaped gate exactly like the
|
|
118
|
-
# local corpus-leak/public-twins/shipped-links checkers, ci.yml already hosts other
|
|
119
|
-
# `pull_request`-only jobs (store-lint, anchor-health) with the identical self-guard shape,
|
|
120
|
-
# and a fourth workflow file would buy nothing a job here doesn't already give.
|
|
121
|
-
# Self-guarded like those checkers: tools/ is not in the public repo's release ALLOWLIST,
|
|
122
|
-
# so this exits 0 cleanly on an external contributor's PR there instead of failing on a
|
|
123
|
-
# checker that by design does not exist in that snapshot.
|
|
124
|
-
pr-description-link-gate:
|
|
125
|
-
if: github.event_name == 'pull_request'
|
|
126
|
-
runs-on: ubuntu-latest
|
|
127
|
-
timeout-minutes: 5
|
|
128
|
-
steps:
|
|
129
|
-
# zizmor artipacked: this job never pushes; do not persist git credentials past checkout.
|
|
130
|
-
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
131
|
-
with:
|
|
132
|
-
persist-credentials: false
|
|
133
|
-
|
|
134
|
-
- name: Check PR description for forbidden session links
|
|
135
|
-
# The PR body is untrusted (attacker-controlled on a fork PR), so it goes through an
|
|
136
|
-
# env var rather than being interpolated into the script text via `${{ }}` — that
|
|
137
|
-
# would be a script-injection hole. `github.event.pull_request.body` is `null` for an
|
|
138
|
-
# empty description; GitHub renders that as an empty env var, and `printf '%s'` on an
|
|
139
|
-
# empty string just produces an empty file, which the checker reports as clean.
|
|
140
|
-
env:
|
|
141
|
-
PR_BODY: ${{ github.event.pull_request.body }}
|
|
142
|
-
run: |
|
|
143
|
-
if [ ! -f tools/check_no_session_links.py ]; then
|
|
144
|
-
echo "tools/check_no_session_links.py not present (public snapshot) — skipping"
|
|
145
|
-
exit 0
|
|
146
|
-
fi
|
|
147
|
-
printf '%s' "$PR_BODY" > "$RUNNER_TEMP/pr-body.txt"
|
|
148
|
-
python3 tools/check_no_session_links.py "$RUNNER_TEMP/pr-body.txt"
|
|
149
|
-
|
|
150
111
|
# Recipe 1 self-applied: rebuild the graph from scratch and fail on attention findings
|
|
151
112
|
# (stale decisions, empty/overbroad domains, slug conflicts, refresh failures). A
|
|
152
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/
|
|
119
|
-
# running `pre-commit run --all-files` inside it.
|
|
120
|
-
# would look for a checker that by design does
|
|
121
|
-
# the public repo's CI, and every public
|
|
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/
|
|
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/
|
|
154
|
-
# before the commit lands. Self-guarded: tools/
|
|
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/
|
|
165
|
-
#
|
|
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
|
|
172
|
-
#
|
|
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,440 @@ 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
|
+
|
|
205
|
+
## [0.6.0] — 2026-10-01
|
|
206
|
+
|
|
207
|
+
### Added
|
|
208
|
+
|
|
209
|
+
- **`sidegraph-verify` reports `unsafe-record-id`.** A record file, `bindings/` file or
|
|
210
|
+
archive line whose id is not a single safe path segment is now a finding, and a
|
|
211
|
+
non-string id in a record or archive file no longer crashes the run with `unhashable type`.
|
|
212
|
+
- **`sidegraph-verify` reports a symlinked store entry as `symlinked-store-entry`.** One
|
|
213
|
+
violation per store-owned directory or file that is a symlink, so a committed link fails the
|
|
214
|
+
CI gate; `sidegraph-doctor` inherits it.
|
|
215
|
+
|
|
216
|
+
### Changed
|
|
217
|
+
|
|
218
|
+
- **A `--graph` typed as a relative path resolves against the shell in `sidegraph-ratify`
|
|
219
|
+
and `sidegraph-stats`.** It used to resolve against the store's project. The default and
|
|
220
|
+
`$SIDEGRAPH_GRAPH` still follow the store. The same holds in every command that reads a
|
|
221
|
+
graph, so the copy-and-sync workflow works with `--graph graphify-out/graph.json` typed from
|
|
222
|
+
the repository.
|
|
223
|
+
- **A store in a nested directory needs an absolute `SIDEGRAPH_GRAPH`.** With
|
|
224
|
+
`SIDEGRAPH_DIR=.config/sidegraph` and a relative `SIDEGRAPH_GRAPH`, the CLI now looks for the
|
|
225
|
+
graph under `.config/` (the store's project) instead of using the shell's copy. A command
|
|
226
|
+
that needs the graph fails with a hint; `init`, `ratify`, `doctor` and `stats`, for which it
|
|
227
|
+
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
|
|
228
|
+
follows the same rule (next entry); the hooks are unaffected.
|
|
229
|
+
- **The MCP server reads the graph that belongs to its store.** A relative `SIDEGRAPH_GRAPH`
|
|
230
|
+
(or the default `graphify-out/graph.json`) used to resolve against the server's working
|
|
231
|
+
directory, so a store reached by an absolute `SIDEGRAPH_DIR`, or a store in a nested directory,
|
|
232
|
+
could be synced against one project's graph by the CLI and another's by `sync_anchors` and the
|
|
233
|
+
retrieval tools, and the store's graph version flipped back and forth. It now resolves against
|
|
234
|
+
the store's project, the same rule the CLI uses, and an empty `SIDEGRAPH_GRAPH` counts as unset.
|
|
235
|
+
With the default layout (`.sidegraph` in the project, the server started there) nothing changes.
|
|
236
|
+
A nested store needs an absolute `SIDEGRAPH_GRAPH`; `sync_anchors` reports `graph not readable`
|
|
237
|
+
with the path and names the graph it found beside the working directory, when there is one.
|
|
238
|
+
- **A document is imported again once, if its `provenance.ref` changes.** A document
|
|
239
|
+
imported before this release from a subdirectory or by an absolute path is imported
|
|
240
|
+
again under its repository path. The old record stays. A leftover that is still `proposed` can be dropped with
|
|
241
|
+
`sidegraph-ratify --drop <id>`. An `accepted` leftover has no one-step retirement: leave
|
|
242
|
+
it, or supersede it by hand with `supersede_decision`, which writes a new record.
|
|
243
|
+
- **`sidegraph-import --path` (and domain `--paths`) match on directory boundaries.**
|
|
244
|
+
`--path payments` no longer imports `payments_v2/b.py`, and a partial-name prefix such as
|
|
245
|
+
`--path docs/adr/00` matches nothing; a prefix matches a file under that directory or
|
|
246
|
+
that exact file. `--path ""` still matches everything, and mixed with a real prefix it is
|
|
247
|
+
ignored. The domain `--paths` help already behaved this way and now says so.
|
|
248
|
+
- **The Stop hook skips the transcript of a session that is already captured.** It now peeks
|
|
249
|
+
at the capture ledger read-only before parsing the transcript, so every Stop after the
|
|
250
|
+
capturing one no longer re-reads the whole file.
|
|
251
|
+
|
|
252
|
+
### Fixed
|
|
253
|
+
|
|
254
|
+
- **The derived initiative names the store's repository branch.** It used to come from the
|
|
255
|
+
branch of whatever directory the MCP server or CLI ran in. An inherited `GIT_DIR` or
|
|
256
|
+
`GIT_WORK_TREE` no longer redirects either the derived initiative or the captured commit.
|
|
257
|
+
- **A timestamp in the future no longer counts as fresh.** The capture session-id fallback and
|
|
258
|
+
the session attribution of retrieval telemetry treated a marker stamped ahead of the clock
|
|
259
|
+
as current; they now ignore it. The SessionStart dedupe still treats a same-session stamp
|
|
260
|
+
less than 60 seconds ahead as a duplicate (a parallel hook can write one), but a stamp
|
|
261
|
+
further ahead no longer suppresses the map until the clock catches up.
|
|
262
|
+
- **Every CLI command that takes a store and a `--graph` pairs the store with its own
|
|
263
|
+
project's graph by default.** `sidegraph-sync`, `sidegraph-import` (both modes),
|
|
264
|
+
`sidegraph-domains bootstrap`, `sidegraph-doctor` and `sidegraph-init` (whose found/missing
|
|
265
|
+
line used the shell's path) read the default graph relative to the
|
|
266
|
+
shell, so `--db A/.sidegraph` run from project B stamped A's store with B's graph version
|
|
267
|
+
and could rewrite A's anchors, import decisions, or bootstrap domains from B's graph. The
|
|
268
|
+
default and `$SIDEGRAPH_GRAPH` (an empty value counts as unset) now resolve against the
|
|
269
|
+
store's project, as `sidegraph-ratify` and `sidegraph-stats` already did; a store reached
|
|
270
|
+
through a symlinked `.sidegraph` keeps the link's project. When the store's project has no
|
|
271
|
+
graph but the same path exists beside the shell (a store copied elsewhere), one stderr hint
|
|
272
|
+
names `--graph <path>`; when both exist, a note says which was used. Error lines name the
|
|
273
|
+
resolved path.
|
|
274
|
+
- **`SIDEGRAPH_DB` naming a missing path no longer scaffolds its parent.** A missing
|
|
275
|
+
`SIDEGRAPH_DB=/proj/.sidegraph`, or a dangling link, resolved to `/proj` and a store was
|
|
276
|
+
created in the project root. Only a path ending in `.db` is rescued to its parent now; any
|
|
277
|
+
other missing path is used as given, and a dangling link fails to open without creating
|
|
278
|
+
anything.
|
|
279
|
+
- **`sidegraph-sync --check` documents domain-refresh failures.** The help and the module
|
|
280
|
+
docstring omitted the finding that already makes `--check` exit 2.
|
|
281
|
+
- **A move left `moved_uncommitted` is now re-verified after you commit it, even when the
|
|
282
|
+
graph was not rebuilt.** Committing a rename does not change `graph.json`, so the version
|
|
283
|
+
gate skipped every later sync and the leaf kept its old path until `--force`. Sync now
|
|
284
|
+
remembers such entities with the git `HEAD` it saw, and the first sync after `HEAD` moves
|
|
285
|
+
re-verifies just them (a narrow pass that leaves domain membership alone). The comment that
|
|
286
|
+
promised the next sync would heal it was wrong, and is corrected.
|
|
287
|
+
- **A decision with two leaves in one community no longer loses that community's binding when
|
|
288
|
+
one leaf leaves it.** Both leaves share one Tier-1 `community:*` row, and a renumber that
|
|
289
|
+
moved one leaf orphaned the row the other still held, so the decision stopped surfacing for
|
|
290
|
+
that community. Sync now settles a record's community rows after every leaf has been
|
|
291
|
+
rebound, and a new row carries the moved leaf's relation instead of `affects`. Damage from
|
|
292
|
+
earlier syncs is repaired when a later repoint touches the record, or when the index is
|
|
293
|
+
next rebuilt from the committed files.
|
|
294
|
+
- **Secret redaction covers quoted values and quoted keys.** `password: "one two"`,
|
|
295
|
+
`` token: `abc def` `` and `password = 'a b c'` were cut at the first space, leaving the rest
|
|
296
|
+
of the secret in the store, and `{"password": "hunter2 two"}` was not matched at all. A
|
|
297
|
+
quoted value is now taken whole, with any text glued to its closing quote, and a quoted
|
|
298
|
+
key matches too. JSON keys such as `"token_count"` now redact like the unquoted
|
|
299
|
+
`token_count:` already did. An escaped quote (`"alpha\" beta"`) does not end a quoted
|
|
300
|
+
value, and a quoted key stops at the next JSON field, so `{"password":"x y","reason":"z"}`
|
|
301
|
+
keeps `reason`.
|
|
302
|
+
- **A decision whose attached fact failed is left proposed under an auto-ratify policy,** and
|
|
303
|
+
an auto-accepted fact's write-guard message points to `add_anchors` instead of a drop that
|
|
304
|
+
the store refuses.
|
|
305
|
+
- **An initiative name is redacted before it becomes an entity, on every write path.** A
|
|
306
|
+
secret in `initiative`, or in a branch name the propose path derives one from, used to land
|
|
307
|
+
in the canonical `initiative:<name>` entity file. A blank or all-secret initiative now binds
|
|
308
|
+
nothing, and a padded name is trimmed (`" proj "` keys as `initiative:proj`).
|
|
309
|
+
- **`add_decision` binds its initiative with no graph or no anchors.** The Tier-0 binding was
|
|
310
|
+
made only inside the per-anchor loop, so a call without a reader or without an anchor
|
|
311
|
+
dropped it silently.
|
|
312
|
+
- **`add_domain`, `supersede_domain` and `sidegraph-domains add` redact the title and
|
|
313
|
+
summary.** Only `propose_domains` and the bootstrap did. The MCP results now carry
|
|
314
|
+
`redactions`, and the CLI prints a count line when it redacted something.
|
|
315
|
+
- **`propose_decisions` dedups a decision on its redacted title.** A title that held a secret
|
|
316
|
+
was compared raw against the stored, redacted one, so proposing it twice wrote it twice.
|
|
317
|
+
- **One failing draft no longer aborts a propose batch.** A step after the write (anchors,
|
|
318
|
+
initiative, tags, attached facts, auto-ratify) now leaves the result `written` with a
|
|
319
|
+
`reason`; an error before the write makes that draft `rejected`; each attached fact and each
|
|
320
|
+
domain is isolated the same way, and a failed TOC rebuild after `propose_domains` is
|
|
321
|
+
reported as a `toc:` warning. `KeyboardInterrupt` still propagates.
|
|
322
|
+
- **A record id can no longer become a path outside the store.** Every canonical writer built
|
|
323
|
+
`<dir>/<id>.json` from the id as given, so an id like `../../x` wrote outside the store.
|
|
324
|
+
The store now refuses to write an id that is not a single path segment, and the OKF export
|
|
325
|
+
skips such a decision, fact or entity with a warning.
|
|
326
|
+
- **A canonical file whose JSON id does not match its filename is skipped on reload, with a
|
|
327
|
+
warning on every open.** A file with a crafted id was indexed under that id, so one later
|
|
328
|
+
ratify could write outside the store. Duplicate ids let the later file silently win, and a
|
|
329
|
+
file with no id got a fresh ULID on every rebuild. Such files are now left out of the index
|
|
330
|
+
and named in a warning until they are fixed or removed. An existing index reloads once to
|
|
331
|
+
apply the rule. An archive line with an unsafe or non-string id is skipped instead of
|
|
332
|
+
making `Store()` fail.
|
|
333
|
+
- **An interrupted legacy migration no longer loses its staged work.** The legacy file is
|
|
334
|
+
renamed to its backup only after the staged directories have moved in, so an interruption
|
|
335
|
+
leaves it in place and the next open migrates again. A bare-file migration, which has to
|
|
336
|
+
rename first, keeps its staging directory and leaves a sentinel so the next open says what
|
|
337
|
+
to do. A sentinel younger than 60 seconds means a migration is running now: the open
|
|
338
|
+
refuses with "retry in a minute" and touches nothing, and deleting that sentinel early is
|
|
339
|
+
unsafe. A legacy row with an unsafe id fails the migration before anything is written, and
|
|
340
|
+
a row whose JSON omits its id takes its SQL primary key instead of a fresh one per retry.
|
|
341
|
+
- **The bootstrap catalog applies the same identity rule.** A record file with no id was
|
|
342
|
+
given a fresh ULID on every load, so the catalog fingerprint changed between two loads of
|
|
343
|
+
one store. Such files are now skipped with a warning.
|
|
344
|
+
- **The store refuses a symlinked directory or store file inside itself.** A symlinked
|
|
345
|
+
`decisions/` sent every record write, from the MCP server, the hooks and bootstrap alike, to
|
|
346
|
+
the link's target, and a symlinked `index.db` made SQLite write there. `Store()` now raises
|
|
347
|
+
before any migration or write, naming the entry, and `sidegraph-bootstrap` refuses before
|
|
348
|
+
the review prompts. A symlinked store root stays allowed. Bootstrap's action summary now
|
|
349
|
+
names the store path and any symlink between the repository root and it.
|
|
350
|
+
- **`sidegraph-bootstrap --report` no longer overwrites a file it is hard-linked to, and
|
|
351
|
+
protects the Codex hooks file the verifier really reads.** The guard compared resolved
|
|
352
|
+
paths, so a hard link to a host config passed it and the report truncated the shared file.
|
|
353
|
+
It also protected only the legacy `.codex/hooks/hooks.json`, not `.codex/hooks.json`. The
|
|
354
|
+
report is now published by replace, and one list of host-config paths feeds both the
|
|
355
|
+
verifier and the guard. The guard covers every host's config file, whichever `--host` is
|
|
356
|
+
selected.
|
|
357
|
+
- **`sidegraph-import --docs` keys a document inside the repository by its repository path,
|
|
358
|
+
whatever directory it runs from.** Run from a subdirectory or given an absolute path, a
|
|
359
|
+
document used to miss its file node in the graph, skip as unanchorable, and get a
|
|
360
|
+
different `provenance.ref` from the same document imported at the root. Profile discovery
|
|
361
|
+
also finds the profile's documents from any directory in the repository, and the
|
|
362
|
+
unanchorable warning now fires only outside a git work tree, where the current directory
|
|
363
|
+
stands in for the root. Build the graph from the repository root: a graph built from a
|
|
364
|
+
subdirectory leaves documents unanchorable.
|
|
365
|
+
- **`--docs` refuses a markdown file that is a symlink to a target outside the repository.**
|
|
366
|
+
It used to read the target under `--any-doc`. The document is counted as `refused: a symlink
|
|
367
|
+
pointing outside the repository`, and so is a profile-discovery hit that resolves outside
|
|
368
|
+
the repository (for example through a symlinked directory). A symlinked directory inside
|
|
369
|
+
the repository that points inside it imports under the path you named, and one that points
|
|
370
|
+
outside the repository is refused. A symlink to a file inside the repository imports under
|
|
371
|
+
its link path.
|
|
372
|
+
- **A re-import repairs a record that has no anchors.** A document whose record was written
|
|
373
|
+
but whose bindings never landed (a run that stopped in between, leaving no anchor other
|
|
374
|
+
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
|
|
375
|
+
repaired`.
|
|
376
|
+
- **The `import_docs` docstring describes what it does:** the five compared fields, the
|
|
377
|
+
statuses it matches, the repair and the refusal.
|
|
378
|
+
- **`sidegraph-init` no longer writes `.claude/settings.json` through a symlink, and no
|
|
379
|
+
longer prints a traceback when the write fails.** A symlinked `.claude/` or `settings.json`
|
|
380
|
+
(live or dangling) is left untouched and the `env` line to add by hand is printed. A merge
|
|
381
|
+
into an existing file is now published by replacing it atomically, so an interruption
|
|
382
|
+
cannot leave a truncated file, and any write failure (a read-only `.claude/`, for example)
|
|
383
|
+
is reported the same way instead of raising. An `env` block that is `null` or not an
|
|
384
|
+
object, and a settings file that changes while init runs, are skipped the same way, not
|
|
385
|
+
raised, and a link swapped in just before the write is refused. A write-protected file is
|
|
386
|
+
respected when init runs as root too.
|
|
387
|
+
- **`sidegraph-doctor`, the drift refresh the session hooks run, and `sidegraph-stats` now
|
|
388
|
+
open the index correctly when the store's path contains `#`, `?`, or `%` followed by two
|
|
389
|
+
hex digits.** Their read-only SQLite URI was built from the unquoted path.
|
|
390
|
+
**Doctor reported its index checks as skipped**, blaming a missing index and suggesting
|
|
391
|
+
`sidegraph-sync`, which could not help. **The session drift refresh silently stopped
|
|
392
|
+
excluding orphaned bindings.** **Stats failed.** For `#` and `?`, an empty file was also
|
|
393
|
+
created at the store path cut short at that character, and an unrelated database there
|
|
394
|
+
could be read instead.
|
|
395
|
+
- **The session-link gate checks every line that gets published.** Lines starting with `#` in
|
|
396
|
+
a PR description, and in commit messages made with `git commit -m`/`-F`, which git records,
|
|
397
|
+
are now checked. The PR title and the PR's recorded commit messages are checked too. The
|
|
398
|
+
check re-runs when a PR description is edited. The public repository runs the check too:
|
|
399
|
+
the release snapshot ships the checker, and the workflow fails when the checker is missing
|
|
400
|
+
instead of skipping.
|
|
401
|
+
- **`sidegraph-export-okf` refuses a symlinked `--out`, and a failed export no longer
|
|
402
|
+
destroys the previous one.** A symlinked output directory used to be written through, or
|
|
403
|
+
cleared, wherever it pointed, and a write that failed midway left a partial bundle after
|
|
404
|
+
the old export was already deleted. The new bundle is now built beside `--out` and
|
|
405
|
+
swapped in only when complete, except for a mount point, a `--out` that is the current
|
|
406
|
+
directory, an unwritable or non-directory parent, or a previous export that cannot be
|
|
407
|
+
renamed aside, which are written in place as before (a write failure there can leave a
|
|
408
|
+
partial export). The in-place write goes to the validated, resolved directory.
|
|
409
|
+
- **An unreadable store or graph directory no longer ends in a traceback.** On Python 3.13 a store or
|
|
410
|
+
graph whose directory could not be read (permission denied) made `sidegraph-sync`,
|
|
411
|
+
`sidegraph-import`, `sidegraph-domains bootstrap`, `sidegraph-init`, `sidegraph-stats` and
|
|
412
|
+
`sidegraph-ratify` (on a domain accept) exit with an uncaught `PermissionError`. An unreadable
|
|
413
|
+
store is now reported on the command's error line (exit 1; 2 for `sidegraph-stats`). An
|
|
414
|
+
unreadable graph is treated as a missing one: `sidegraph-sync`, `sidegraph-import` and
|
|
415
|
+
`sidegraph-domains bootstrap` stop with `graph not readable`, and the other commands carry on
|
|
416
|
+
without a graph.
|
|
417
|
+
A working directory that cannot be read skips the graph hint and the `sync_anchors` hint instead of
|
|
418
|
+
raising; other code that resolves a relative path against it may still raise.
|
|
419
|
+
- **A retried Tier-1 reconcile that could not run is no longer reported as done.** A
|
|
420
|
+
remembered community reconcile whose record still has a live or degraded Tier-2 anchor
|
|
421
|
+
with no recorded community kept being treated as a success: the key was cleared, the sync
|
|
422
|
+
said `moved`, and the stale row stayed live. It is now kept, and retried silently on every
|
|
423
|
+
sync.
|
|
424
|
+
- **Sync, verify and doctor ask git about the repository their own files are in.**
|
|
425
|
+
`sidegraph-sync` (the graph's directory), `sidegraph-verify --against` and
|
|
426
|
+
`sidegraph-doctor` (the store's, and its graph-root check's) no longer inherit an ambient `GIT_DIR` or
|
|
427
|
+
`GIT_WORK_TREE`, which could make sync read another repository's `HEAD` and adopt a rename
|
|
428
|
+
that was never committed. The lazy sync run by `SessionStart` and retrieval, and the
|
|
429
|
+
`SessionStart` drift cache, are fixed too. `sidegraph-init` and `sidegraph-import` resolve
|
|
430
|
+
the repository root from the current directory the same way. A work tree whose repository
|
|
431
|
+
is found only through `GIT_DIR` now needs a `.git` file containing `gitdir: <path>`, and
|
|
432
|
+
`core.bare=false` in that repository.
|
|
433
|
+
- **The sync docs list every condition that prevents a skip.** A remembered Tier-1
|
|
434
|
+
reconcile that is repaired or fails again also makes a plain sync report instead of
|
|
435
|
+
skipping.
|
|
436
|
+
- **Documentation and help text match what the code does.** The PreToolUse docs name the
|
|
437
|
+
real `Read|Grep|Edit|Write` matcher and the two nudge forms, each at most once per session.
|
|
438
|
+
The `add_decision`, `supersede_decision`, `add_fact`, `supersede_fact` and
|
|
439
|
+
`propose_decisions` tool descriptions list `anchors_orphaned`. `sidegraph-ratify --help`
|
|
440
|
+
says `--all` also accepts standalone facts, and `--help` for `sidegraph-verify`,
|
|
441
|
+
`-doctor` and `-blame` no longer promises a legacy `*.db` migration they never perform.
|
|
442
|
+
`SECURITY.md` states local retrieval telemetry and the output paths commands write to.
|
|
443
|
+
|
|
10
444
|
## [0.5.0] — 2026-09-23
|
|
11
445
|
|
|
12
446
|
### Changed
|