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