sidegraph 0.5.0__tar.gz → 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.github/workflows/ci.yml +0 -39
- sidegraph-0.6.0/.github/workflows/session-link-gate.yml +76 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.gitleaks.toml +1 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.pre-commit-config.yaml +13 -12
- {sidegraph-0.5.0 → sidegraph-0.6.0}/CHANGELOG.md +239 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/CLAUDE.md +6 -5
- {sidegraph-0.5.0 → sidegraph-0.6.0}/PKG-INFO +2 -2
- {sidegraph-0.5.0 → sidegraph-0.6.0}/README.md +1 -1
- {sidegraph-0.5.0 → sidegraph-0.6.0}/SECURITY.md +13 -5
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/concepts/anchoring.md +19 -11
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/concepts/data-model.md +3 -2
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/concepts/retrieval.md +2 -1
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/getting-started/bootstrap.md +5 -1
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/guides/capturing-decisions.md +2 -1
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/guides/retrieval-in-sessions.md +2 -2
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/guides/semantic-docs.md +2 -2
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/guides/surviving-refactors.md +18 -9
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/integrations/claude-code.md +9 -5
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/integrations/graphify.md +13 -8
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/reference/cli.md +128 -55
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/reference/configuration.md +37 -10
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/reference/hooks.md +23 -13
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/reference/mcp-tools.md +69 -21
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/reference/store-format.md +64 -4
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/.claude-plugin/plugin.json +1 -1
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/.codex-plugin/plugin.json +1 -1
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/heal-anchors/SKILL.md +4 -2
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/import-adrs/SKILL.md +16 -5
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/record-decision/SKILL.md +3 -2
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/record-fact/SKILL.md +4 -2
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/stats/SKILL.md +6 -5
- {sidegraph-0.5.0 → sidegraph-0.6.0}/pyproject.toml +1 -1
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/__init__.py +1 -1
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/anchoring.py +3 -20
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/catalog.py +44 -9
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/cli.py +68 -29
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/integrations.py +23 -5
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/capture.py +532 -303
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/cli.py +237 -126
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/config.py +108 -5
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/doc_import.py +179 -37
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/doctor.py +5 -3
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/domains.py +2 -1
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/engine/reader.py +2 -0
- sidegraph-0.6.0/src/sidegraph/gitenv.py +41 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/gitio.py +2 -1
- sidegraph-0.6.0/src/sidegraph/host/claude_settings.py +244 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/host/hooks.py +32 -4
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/importer.py +15 -3
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/okf.py +260 -23
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/schema.py +11 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/server.py +157 -47
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/stats/model.py +7 -1
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/store.py +464 -55
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/sync.py +472 -57
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/verify.py +73 -3
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/conftest.py +25 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_anchoring.py +2 -14
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_bootstrap_catalog.py +91 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_bootstrap_cli.py +257 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_capture_auto_accept.py +0 -8
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_capture_facts.py +0 -14
- sidegraph-0.6.0/tests/test_capture_initiative.py +185 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_capture_neighbors.py +0 -7
- sidegraph-0.6.0/tests/test_capture_propose.py +802 -0
- sidegraph-0.6.0/tests/test_capture_redact.py +184 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_cli_domains.py +39 -0
- sidegraph-0.6.0/tests/test_cli_graph_paths.py +535 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_cli_import.py +217 -25
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_cli_init.py +113 -0
- sidegraph-0.6.0/tests/test_cli_okf.py +819 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_cli_stats.py +16 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_cli_sync.py +12 -0
- sidegraph-0.6.0/tests/test_cli_unreadable_paths.py +261 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_config.py +45 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_doc_corpus_integration.py +0 -7
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_doc_import.py +429 -6
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_doctor.py +102 -0
- sidegraph-0.6.0/tests/test_git_env.py +138 -0
- sidegraph-0.6.0/tests/test_host_claude_settings.py +554 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_host_session_start.py +40 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_host_stop.py +99 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_importer.py +42 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_okf.py +29 -1
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_ratify_policy.py +32 -41
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_repoint_integration.py +0 -7
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_capture.py +115 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_domains.py +40 -0
- sidegraph-0.6.0/tests/test_server_graph_path.py +268 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_telemetry.py +20 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_stats_model.py +17 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_meta.py +12 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_migration.py +404 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_mutation_guard.py +6 -0
- sidegraph-0.6.0/tests/test_store_record_identity.py +407 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_stamping_marker.py +6 -4
- sidegraph-0.6.0/tests/test_store_symlinks.py +79 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_sync_clean.py +0 -7
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_sync_fresh_clone.py +0 -7
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_sync_integration.py +0 -7
- sidegraph-0.6.0/tests/test_sync_rebind.py +1310 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_sync_repoint.py +170 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_verify_snapshot.py +109 -0
- sidegraph-0.6.0/tools/check_no_session_links.py +167 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/uv.lock +1 -1
- 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_sync_rebind.py +0 -457
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.agents/plugins/marketplace.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.claude-plugin/marketplace.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.github/CODEOWNERS +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.github/secret_scanning.yml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.github/workflows/publish.yml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.github/workflows/scorecard.yml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.gitignore +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/.python-version +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/AGENTS.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/CODE_OF_CONDUCT.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/CONTRIBUTING.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/LICENSE +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/README.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/concepts/decision-memory.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/concepts/mind-model.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/getting-started/claude-code-setup.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/getting-started/codex-setup.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/getting-started/installation.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/getting-started/quickstart.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/guides/ci-cd-maintenance.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/guides/naming-your-domains.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/guides/team-workflow.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/guides/verifying-your-setup.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/integrations/codex.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/llms.txt +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/pilot-kit/README.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/pilot-kit/corpus_fit.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/pilot-kit/judge-prompt.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/pilot-kit/questions-prompt.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/pilot-kit/rubric-template.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/reference/git-bindings.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/reference/operations.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/reference/releasing.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/reference/stability.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/docs/whitepaper/index.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/.mcp.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/codex/hooks.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/codex/mcp.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/hooks/hooks.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/check-plan/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/check-plan/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/explain-why/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/explain-why/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/heal-anchors/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/import-adrs/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/manage-domains/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/manage-domains/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/name-domains/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/name-domains/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/ratify-decisions/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/ratify-decisions/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/record-decision/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/record-fact/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/setup/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/setup/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/stats/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/triage-drift/SKILL.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/plugin/sidegraph/skills/triage-drift/agents/openai.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/__init__.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/apply.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/model.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/planner.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/proof.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/review.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/bootstrap/scan.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/engine/__init__.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/host/__init__.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/profiles.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/retrieval.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/stats/__init__.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/stats/render.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/viz/__init__.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/viz/assets/vis-network.min.js +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/viz/model.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/viz/render.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/src/sidegraph/viz/template.html +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/__init__.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/auto_policy/parity_goldens.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/bitfinex_slice.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/flows/bmad/_bmad-output/planning-artifacts/architecture/cache/ARCHITECTURE-SPINE.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/flows/generic-adr/docs/adr/001-retry.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/flows/genkovich-sdd/docs/features/cache/adr/001.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/flows/spec-kit/specs/cache/plan.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/flows/superpowers/docs/superpowers/specs/2026-07-01-cache-design.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/graph.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/hosts/claude/.claude/settings.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/hosts/claude/.mcp.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/hosts/codex/.codex/config.toml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/hosts/codex/.codex/hooks/hooks.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/bootstrap/scan/docs/adr/001-safe.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/corpus/PUBLIC_CORPORA.txt +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/corpus/openspec/_provenance.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/corpus/openspec/graph.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/corpus/self-corpus/_provenance.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/corpus/self-corpus/expected/retrieval-engine-reader.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/corpus/self-corpus/graph.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/adr/0001-use-sessions.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/bmad/ARCHITECTURE-SPINE.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.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.6.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.6.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.6.0}/tests/fixtures/flows/genkovich/0001-queue-backpressure.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/genkovich/sad.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/adr/0001-queue-backpressure.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/sad.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/spec.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/design-empty.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/design-h3-split.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/design-with-summary.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/design.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/proposal-alternatives.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/proposal.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/design.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/proposal.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/specs/cap/spec.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/tasks.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/changes/archive/2026-01-01-add-thing/design.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/changes/archive/2026-01-01-add-thing/proposal.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/config.yaml +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/openspec/tree/openspec/specs/cap/spec.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/spec-kit/plan.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/spec-kit/tree/specs/003-payment-retries/plan.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/spec-kit/tree/specs/003-payment-retries/spec.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/superpowers/2026-07-01-example-design.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/flows/superpowers/2026-07-01-thin-design.md +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/fixtures/mini_graph.json +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_anchoring_mapping_refresh.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_bootstrap_apply.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_bootstrap_integrations.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_bootstrap_model.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_bootstrap_planner.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_bootstrap_proof.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_bootstrap_review.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_bootstrap_scan.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_capture_integration.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_cli_compact.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_cli_doctor.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_cli_ratify.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_cli_ratify_facts.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_cli_sync_check.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_cli_viz.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_codex_plugin.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_community_baseline.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_corpus_expected_renders.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_corpus_self_corpus.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_coverage_telemetry_e2e.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_digest_integrity.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_docs_claims.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_doctor_auto_share.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_doctor_code_drift.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_doctor_dangling_supports.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_doctor_duplicate_entity.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_doctor_graph_root_mismatch.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_doctor_never_surfaced.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_doctor_scan.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_doctor_stale_instructions.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_doctor_unratified_accept.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_domains.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_entity_duplicate_resolution.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_entity_get_or_create_race.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_env_isolation.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_fact_reachability_gate.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_flow_profile.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_git_bindings_blame.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_git_bindings_hook.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_git_bindings_provenance.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_host_drift_nudge.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_host_pretool.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_host_session_key.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_host_touch_events.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_mind_model_additive_fields.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_openspec_profile.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_pathless_descriptor_adoption.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_pilot_kit_corpus_fit.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_proposal_lifecycle.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_ratify_listing_gone_dark.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_reader_community_labels.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_reader_doc_nodes.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_reader_graph.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_reader_integration.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_reader_nodes_in_file.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_reader_perf.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_reader_rationale.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_reader_read.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_reader_resolve.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_reader_subdir_mismatch.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_reader_version.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_redaction_seeded.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_budget_counters.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_context.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_drift_marker.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_drilldown.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_facts.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_ids.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_integration.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_rank.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_seeds.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_shown_ids.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_terminal_evidence.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_thin_tools.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_toc.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_toptier.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_retrieval_unratified.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_sandbox_hygiene.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_schema_descriptor.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_schema_domain.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_schema_fact.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_add_anchors.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_anchoring.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_coverage_events.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_drilldown.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_facts.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_find_entity.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_get_store.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_get_task_context.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_import.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_mcp_smoke.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_prewrite_anchor_validation.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_ratify_facts.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_redaction.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_render_events.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_supersede.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_sync_anchors.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_thin_tools.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_server_verify.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_stats_graph.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_stats_render.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_stats_skill.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_stats_snapshot.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_atomic_write_tmp_names.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_canonical_stat.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_compact.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_compact_review.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_concurrent_open.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_coverage_telemetry.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_derived_community.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_domains.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_entities.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_fact_cascade.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_facts.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_mutation_immediate.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_opens_with_merged_duplicate.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_persistence.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_ratification.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_rebuild_atomicity.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_render_events.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_retrieval.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_slug_conflicts.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_telemetry.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_threading.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_store_tmp_sweep_age.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_sync_domains.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_sync_drift_cache.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_sync_report_has_findings.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_sync_run.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_sync_toc_cache.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_sync_volatile_heal.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_sync_wiring.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_telemetry_retention.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_verify_transitions.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_viz_asset_packaged.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_viz_model.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.0}/tests/test_viz_render_html.py +0 -0
- {sidegraph-0.5.0 → sidegraph-0.6.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,245 @@ interfaces, exactly, and what each one promises: [`docs/reference/stability.md`]
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.6.0] — 2026-10-01
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`sidegraph-verify` reports `unsafe-record-id`.** A record file, `bindings/` file or
|
|
15
|
+
archive line whose id is not a single safe path segment is now a finding, and a
|
|
16
|
+
non-string id in a record or archive file no longer crashes the run with `unhashable type`.
|
|
17
|
+
- **`sidegraph-verify` reports a symlinked store entry as `symlinked-store-entry`.** One
|
|
18
|
+
violation per store-owned directory or file that is a symlink, so a committed link fails the
|
|
19
|
+
CI gate; `sidegraph-doctor` inherits it.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- **A `--graph` typed as a relative path resolves against the shell in `sidegraph-ratify`
|
|
24
|
+
and `sidegraph-stats`.** It used to resolve against the store's project. The default and
|
|
25
|
+
`$SIDEGRAPH_GRAPH` still follow the store. The same holds in every command that reads a
|
|
26
|
+
graph, so the copy-and-sync workflow works with `--graph graphify-out/graph.json` typed from
|
|
27
|
+
the repository.
|
|
28
|
+
- **A store in a nested directory needs an absolute `SIDEGRAPH_GRAPH`.** With
|
|
29
|
+
`SIDEGRAPH_DIR=.config/sidegraph` and a relative `SIDEGRAPH_GRAPH`, the CLI now looks for the
|
|
30
|
+
graph under `.config/` (the store's project) instead of using the shell's copy. A command
|
|
31
|
+
that needs the graph fails with a hint; `init`, `ratify`, `doctor` and `stats`, for which it
|
|
32
|
+
is optional, continue and print the hint (`stats` reports its graph metrics as unavailable). Set an absolute `SIDEGRAPH_GRAPH` or pass `--graph`. The MCP server now
|
|
33
|
+
follows the same rule (next entry); the hooks are unaffected.
|
|
34
|
+
- **The MCP server reads the graph that belongs to its store.** A relative `SIDEGRAPH_GRAPH`
|
|
35
|
+
(or the default `graphify-out/graph.json`) used to resolve against the server's working
|
|
36
|
+
directory, so a store reached by an absolute `SIDEGRAPH_DIR`, or a store in a nested directory,
|
|
37
|
+
could be synced against one project's graph by the CLI and another's by `sync_anchors` and the
|
|
38
|
+
retrieval tools, and the store's graph version flipped back and forth. It now resolves against
|
|
39
|
+
the store's project, the same rule the CLI uses, and an empty `SIDEGRAPH_GRAPH` counts as unset.
|
|
40
|
+
With the default layout (`.sidegraph` in the project, the server started there) nothing changes.
|
|
41
|
+
A nested store needs an absolute `SIDEGRAPH_GRAPH`; `sync_anchors` reports `graph not readable`
|
|
42
|
+
with the path and names the graph it found beside the working directory, when there is one.
|
|
43
|
+
- **A document is imported again once, if its `provenance.ref` changes.** A document
|
|
44
|
+
imported before this release from a subdirectory or by an absolute path is imported
|
|
45
|
+
again under its repository path. The old record stays. A leftover that is still `proposed` can be dropped with
|
|
46
|
+
`sidegraph-ratify --drop <id>`. An `accepted` leftover has no one-step retirement: leave
|
|
47
|
+
it, or supersede it by hand with `supersede_decision`, which writes a new record.
|
|
48
|
+
- **`sidegraph-import --path` (and domain `--paths`) match on directory boundaries.**
|
|
49
|
+
`--path payments` no longer imports `payments_v2/b.py`, and a partial-name prefix such as
|
|
50
|
+
`--path docs/adr/00` matches nothing; a prefix matches a file under that directory or
|
|
51
|
+
that exact file. `--path ""` still matches everything, and mixed with a real prefix it is
|
|
52
|
+
ignored. The domain `--paths` help already behaved this way and now says so.
|
|
53
|
+
- **The Stop hook skips the transcript of a session that is already captured.** It now peeks
|
|
54
|
+
at the capture ledger read-only before parsing the transcript, so every Stop after the
|
|
55
|
+
capturing one no longer re-reads the whole file.
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- **The derived initiative names the store's repository branch.** It used to come from the
|
|
60
|
+
branch of whatever directory the MCP server or CLI ran in. An inherited `GIT_DIR` or
|
|
61
|
+
`GIT_WORK_TREE` no longer redirects either the derived initiative or the captured commit.
|
|
62
|
+
- **A timestamp in the future no longer counts as fresh.** The capture session-id fallback and
|
|
63
|
+
the session attribution of retrieval telemetry treated a marker stamped ahead of the clock
|
|
64
|
+
as current; they now ignore it. The SessionStart dedupe still treats a same-session stamp
|
|
65
|
+
less than 60 seconds ahead as a duplicate (a parallel hook can write one), but a stamp
|
|
66
|
+
further ahead no longer suppresses the map until the clock catches up.
|
|
67
|
+
- **Every CLI command that takes a store and a `--graph` pairs the store with its own
|
|
68
|
+
project's graph by default.** `sidegraph-sync`, `sidegraph-import` (both modes),
|
|
69
|
+
`sidegraph-domains bootstrap`, `sidegraph-doctor` and `sidegraph-init` (whose found/missing
|
|
70
|
+
line used the shell's path) read the default graph relative to the
|
|
71
|
+
shell, so `--db A/.sidegraph` run from project B stamped A's store with B's graph version
|
|
72
|
+
and could rewrite A's anchors, import decisions, or bootstrap domains from B's graph. The
|
|
73
|
+
default and `$SIDEGRAPH_GRAPH` (an empty value counts as unset) now resolve against the
|
|
74
|
+
store's project, as `sidegraph-ratify` and `sidegraph-stats` already did; a store reached
|
|
75
|
+
through a symlinked `.sidegraph` keeps the link's project. When the store's project has no
|
|
76
|
+
graph but the same path exists beside the shell (a store copied elsewhere), one stderr hint
|
|
77
|
+
names `--graph <path>`; when both exist, a note says which was used. Error lines name the
|
|
78
|
+
resolved path.
|
|
79
|
+
- **`SIDEGRAPH_DB` naming a missing path no longer scaffolds its parent.** A missing
|
|
80
|
+
`SIDEGRAPH_DB=/proj/.sidegraph`, or a dangling link, resolved to `/proj` and a store was
|
|
81
|
+
created in the project root. Only a path ending in `.db` is rescued to its parent now; any
|
|
82
|
+
other missing path is used as given, and a dangling link fails to open without creating
|
|
83
|
+
anything.
|
|
84
|
+
- **`sidegraph-sync --check` documents domain-refresh failures.** The help and the module
|
|
85
|
+
docstring omitted the finding that already makes `--check` exit 2.
|
|
86
|
+
- **A move left `moved_uncommitted` is now re-verified after you commit it, even when the
|
|
87
|
+
graph was not rebuilt.** Committing a rename does not change `graph.json`, so the version
|
|
88
|
+
gate skipped every later sync and the leaf kept its old path until `--force`. Sync now
|
|
89
|
+
remembers such entities with the git `HEAD` it saw, and the first sync after `HEAD` moves
|
|
90
|
+
re-verifies just them (a narrow pass that leaves domain membership alone). The comment that
|
|
91
|
+
promised the next sync would heal it was wrong, and is corrected.
|
|
92
|
+
- **A decision with two leaves in one community no longer loses that community's binding when
|
|
93
|
+
one leaf leaves it.** Both leaves share one Tier-1 `community:*` row, and a renumber that
|
|
94
|
+
moved one leaf orphaned the row the other still held, so the decision stopped surfacing for
|
|
95
|
+
that community. Sync now settles a record's community rows after every leaf has been
|
|
96
|
+
rebound, and a new row carries the moved leaf's relation instead of `affects`. Damage from
|
|
97
|
+
earlier syncs is repaired when a later repoint touches the record, or when the index is
|
|
98
|
+
next rebuilt from the committed files.
|
|
99
|
+
- **Secret redaction covers quoted values and quoted keys.** `password: "one two"`,
|
|
100
|
+
`` token: `abc def` `` and `password = 'a b c'` were cut at the first space, leaving the rest
|
|
101
|
+
of the secret in the store, and `{"password": "hunter2 two"}` was not matched at all. A
|
|
102
|
+
quoted value is now taken whole, with any text glued to its closing quote, and a quoted
|
|
103
|
+
key matches too. JSON keys such as `"token_count"` now redact like the unquoted
|
|
104
|
+
`token_count:` already did. An escaped quote (`"alpha\" beta"`) does not end a quoted
|
|
105
|
+
value, and a quoted key stops at the next JSON field, so `{"password":"x y","reason":"z"}`
|
|
106
|
+
keeps `reason`.
|
|
107
|
+
- **A decision whose attached fact failed is left proposed under an auto-ratify policy,** and
|
|
108
|
+
an auto-accepted fact's write-guard message points to `add_anchors` instead of a drop that
|
|
109
|
+
the store refuses.
|
|
110
|
+
- **An initiative name is redacted before it becomes an entity, on every write path.** A
|
|
111
|
+
secret in `initiative`, or in a branch name the propose path derives one from, used to land
|
|
112
|
+
in the canonical `initiative:<name>` entity file. A blank or all-secret initiative now binds
|
|
113
|
+
nothing, and a padded name is trimmed (`" proj "` keys as `initiative:proj`).
|
|
114
|
+
- **`add_decision` binds its initiative with no graph or no anchors.** The Tier-0 binding was
|
|
115
|
+
made only inside the per-anchor loop, so a call without a reader or without an anchor
|
|
116
|
+
dropped it silently.
|
|
117
|
+
- **`add_domain`, `supersede_domain` and `sidegraph-domains add` redact the title and
|
|
118
|
+
summary.** Only `propose_domains` and the bootstrap did. The MCP results now carry
|
|
119
|
+
`redactions`, and the CLI prints a count line when it redacted something.
|
|
120
|
+
- **`propose_decisions` dedups a decision on its redacted title.** A title that held a secret
|
|
121
|
+
was compared raw against the stored, redacted one, so proposing it twice wrote it twice.
|
|
122
|
+
- **One failing draft no longer aborts a propose batch.** A step after the write (anchors,
|
|
123
|
+
initiative, tags, attached facts, auto-ratify) now leaves the result `written` with a
|
|
124
|
+
`reason`; an error before the write makes that draft `rejected`; each attached fact and each
|
|
125
|
+
domain is isolated the same way, and a failed TOC rebuild after `propose_domains` is
|
|
126
|
+
reported as a `toc:` warning. `KeyboardInterrupt` still propagates.
|
|
127
|
+
- **A record id can no longer become a path outside the store.** Every canonical writer built
|
|
128
|
+
`<dir>/<id>.json` from the id as given, so an id like `../../x` wrote outside the store.
|
|
129
|
+
The store now refuses to write an id that is not a single path segment, and the OKF export
|
|
130
|
+
skips such a decision, fact or entity with a warning.
|
|
131
|
+
- **A canonical file whose JSON id does not match its filename is skipped on reload, with a
|
|
132
|
+
warning on every open.** A file with a crafted id was indexed under that id, so one later
|
|
133
|
+
ratify could write outside the store. Duplicate ids let the later file silently win, and a
|
|
134
|
+
file with no id got a fresh ULID on every rebuild. Such files are now left out of the index
|
|
135
|
+
and named in a warning until they are fixed or removed. An existing index reloads once to
|
|
136
|
+
apply the rule. An archive line with an unsafe or non-string id is skipped instead of
|
|
137
|
+
making `Store()` fail.
|
|
138
|
+
- **An interrupted legacy migration no longer loses its staged work.** The legacy file is
|
|
139
|
+
renamed to its backup only after the staged directories have moved in, so an interruption
|
|
140
|
+
leaves it in place and the next open migrates again. A bare-file migration, which has to
|
|
141
|
+
rename first, keeps its staging directory and leaves a sentinel so the next open says what
|
|
142
|
+
to do. A sentinel younger than 60 seconds means a migration is running now: the open
|
|
143
|
+
refuses with "retry in a minute" and touches nothing, and deleting that sentinel early is
|
|
144
|
+
unsafe. A legacy row with an unsafe id fails the migration before anything is written, and
|
|
145
|
+
a row whose JSON omits its id takes its SQL primary key instead of a fresh one per retry.
|
|
146
|
+
- **The bootstrap catalog applies the same identity rule.** A record file with no id was
|
|
147
|
+
given a fresh ULID on every load, so the catalog fingerprint changed between two loads of
|
|
148
|
+
one store. Such files are now skipped with a warning.
|
|
149
|
+
- **The store refuses a symlinked directory or store file inside itself.** A symlinked
|
|
150
|
+
`decisions/` sent every record write, from the MCP server, the hooks and bootstrap alike, to
|
|
151
|
+
the link's target, and a symlinked `index.db` made SQLite write there. `Store()` now raises
|
|
152
|
+
before any migration or write, naming the entry, and `sidegraph-bootstrap` refuses before
|
|
153
|
+
the review prompts. A symlinked store root stays allowed. Bootstrap's action summary now
|
|
154
|
+
names the store path and any symlink between the repository root and it.
|
|
155
|
+
- **`sidegraph-bootstrap --report` no longer overwrites a file it is hard-linked to, and
|
|
156
|
+
protects the Codex hooks file the verifier really reads.** The guard compared resolved
|
|
157
|
+
paths, so a hard link to a host config passed it and the report truncated the shared file.
|
|
158
|
+
It also protected only the legacy `.codex/hooks/hooks.json`, not `.codex/hooks.json`. The
|
|
159
|
+
report is now published by replace, and one list of host-config paths feeds both the
|
|
160
|
+
verifier and the guard. The guard covers every host's config file, whichever `--host` is
|
|
161
|
+
selected.
|
|
162
|
+
- **`sidegraph-import --docs` keys a document inside the repository by its repository path,
|
|
163
|
+
whatever directory it runs from.** Run from a subdirectory or given an absolute path, a
|
|
164
|
+
document used to miss its file node in the graph, skip as unanchorable, and get a
|
|
165
|
+
different `provenance.ref` from the same document imported at the root. Profile discovery
|
|
166
|
+
also finds the profile's documents from any directory in the repository, and the
|
|
167
|
+
unanchorable warning now fires only outside a git work tree, where the current directory
|
|
168
|
+
stands in for the root. Build the graph from the repository root: a graph built from a
|
|
169
|
+
subdirectory leaves documents unanchorable.
|
|
170
|
+
- **`--docs` refuses a markdown file that is a symlink to a target outside the repository.**
|
|
171
|
+
It used to read the target under `--any-doc`. The document is counted as `refused: a symlink
|
|
172
|
+
pointing outside the repository`, and so is a profile-discovery hit that resolves outside
|
|
173
|
+
the repository (for example through a symlinked directory). A symlinked directory inside
|
|
174
|
+
the repository that points inside it imports under the path you named, and one that points
|
|
175
|
+
outside the repository is refused. A symlink to a file inside the repository imports under
|
|
176
|
+
its link path.
|
|
177
|
+
- **A re-import repairs a record that has no anchors.** A document whose record was written
|
|
178
|
+
but whose bindings never landed (a run that stopped in between, leaving no anchor other
|
|
179
|
+
than `tag:` bindings) used to be skipped as existing for good. It is now bound on the next import and reported as `had their anchors
|
|
180
|
+
repaired`.
|
|
181
|
+
- **The `import_docs` docstring describes what it does:** the five compared fields, the
|
|
182
|
+
statuses it matches, the repair and the refusal.
|
|
183
|
+
- **`sidegraph-init` no longer writes `.claude/settings.json` through a symlink, and no
|
|
184
|
+
longer prints a traceback when the write fails.** A symlinked `.claude/` or `settings.json`
|
|
185
|
+
(live or dangling) is left untouched and the `env` line to add by hand is printed. A merge
|
|
186
|
+
into an existing file is now published by replacing it atomically, so an interruption
|
|
187
|
+
cannot leave a truncated file, and any write failure (a read-only `.claude/`, for example)
|
|
188
|
+
is reported the same way instead of raising. An `env` block that is `null` or not an
|
|
189
|
+
object, and a settings file that changes while init runs, are skipped the same way, not
|
|
190
|
+
raised, and a link swapped in just before the write is refused. A write-protected file is
|
|
191
|
+
respected when init runs as root too.
|
|
192
|
+
- **`sidegraph-doctor`, the drift refresh the session hooks run, and `sidegraph-stats` now
|
|
193
|
+
open the index correctly when the store's path contains `#`, `?`, or `%` followed by two
|
|
194
|
+
hex digits.** Their read-only SQLite URI was built from the unquoted path.
|
|
195
|
+
**Doctor reported its index checks as skipped**, blaming a missing index and suggesting
|
|
196
|
+
`sidegraph-sync`, which could not help. **The session drift refresh silently stopped
|
|
197
|
+
excluding orphaned bindings.** **Stats failed.** For `#` and `?`, an empty file was also
|
|
198
|
+
created at the store path cut short at that character, and an unrelated database there
|
|
199
|
+
could be read instead.
|
|
200
|
+
- **The session-link gate checks every line that gets published.** Lines starting with `#` in
|
|
201
|
+
a PR description, and in commit messages made with `git commit -m`/`-F`, which git records,
|
|
202
|
+
are now checked. The PR title and the PR's recorded commit messages are checked too. The
|
|
203
|
+
check re-runs when a PR description is edited. The public repository runs the check too:
|
|
204
|
+
the release snapshot ships the checker, and the workflow fails when the checker is missing
|
|
205
|
+
instead of skipping.
|
|
206
|
+
- **`sidegraph-export-okf` refuses a symlinked `--out`, and a failed export no longer
|
|
207
|
+
destroys the previous one.** A symlinked output directory used to be written through, or
|
|
208
|
+
cleared, wherever it pointed, and a write that failed midway left a partial bundle after
|
|
209
|
+
the old export was already deleted. The new bundle is now built beside `--out` and
|
|
210
|
+
swapped in only when complete, except for a mount point, a `--out` that is the current
|
|
211
|
+
directory, an unwritable or non-directory parent, or a previous export that cannot be
|
|
212
|
+
renamed aside, which are written in place as before (a write failure there can leave a
|
|
213
|
+
partial export). The in-place write goes to the validated, resolved directory.
|
|
214
|
+
- **An unreadable store or graph directory no longer ends in a traceback.** On Python 3.13 a store or
|
|
215
|
+
graph whose directory could not be read (permission denied) made `sidegraph-sync`,
|
|
216
|
+
`sidegraph-import`, `sidegraph-domains bootstrap`, `sidegraph-init`, `sidegraph-stats` and
|
|
217
|
+
`sidegraph-ratify` (on a domain accept) exit with an uncaught `PermissionError`. An unreadable
|
|
218
|
+
store is now reported on the command's error line (exit 1; 2 for `sidegraph-stats`). An
|
|
219
|
+
unreadable graph is treated as a missing one: `sidegraph-sync`, `sidegraph-import` and
|
|
220
|
+
`sidegraph-domains bootstrap` stop with `graph not readable`, and the other commands carry on
|
|
221
|
+
without a graph.
|
|
222
|
+
A working directory that cannot be read skips the graph hint and the `sync_anchors` hint instead of
|
|
223
|
+
raising; other code that resolves a relative path against it may still raise.
|
|
224
|
+
- **A retried Tier-1 reconcile that could not run is no longer reported as done.** A
|
|
225
|
+
remembered community reconcile whose record still has a live or degraded Tier-2 anchor
|
|
226
|
+
with no recorded community kept being treated as a success: the key was cleared, the sync
|
|
227
|
+
said `moved`, and the stale row stayed live. It is now kept, and retried silently on every
|
|
228
|
+
sync.
|
|
229
|
+
- **Sync, verify and doctor ask git about the repository their own files are in.**
|
|
230
|
+
`sidegraph-sync` (the graph's directory), `sidegraph-verify --against` and
|
|
231
|
+
`sidegraph-doctor` (the store's, and its graph-root check's) no longer inherit an ambient `GIT_DIR` or
|
|
232
|
+
`GIT_WORK_TREE`, which could make sync read another repository's `HEAD` and adopt a rename
|
|
233
|
+
that was never committed. The lazy sync run by `SessionStart` and retrieval, and the
|
|
234
|
+
`SessionStart` drift cache, are fixed too. `sidegraph-init` and `sidegraph-import` resolve
|
|
235
|
+
the repository root from the current directory the same way. A work tree whose repository
|
|
236
|
+
is found only through `GIT_DIR` now needs a `.git` file containing `gitdir: <path>`, and
|
|
237
|
+
`core.bare=false` in that repository.
|
|
238
|
+
- **The sync docs list every condition that prevents a skip.** A remembered Tier-1
|
|
239
|
+
reconcile that is repaired or fails again also makes a plain sync report instead of
|
|
240
|
+
skipping.
|
|
241
|
+
- **Documentation and help text match what the code does.** The PreToolUse docs name the
|
|
242
|
+
real `Read|Grep|Edit|Write` matcher and the two nudge forms, each at most once per session.
|
|
243
|
+
The `add_decision`, `supersede_decision`, `add_fact`, `supersede_fact` and
|
|
244
|
+
`propose_decisions` tool descriptions list `anchors_orphaned`. `sidegraph-ratify --help`
|
|
245
|
+
says `--all` also accepts standalone facts, and `--help` for `sidegraph-verify`,
|
|
246
|
+
`-doctor` and `-blame` no longer promises a legacy `*.db` migration they never perform.
|
|
247
|
+
`SECURITY.md` states local retrieval telemetry and the output paths commands write to.
|
|
248
|
+
|
|
10
249
|
## [0.5.0] — 2026-09-23
|
|
11
250
|
|
|
12
251
|
### Changed
|
|
@@ -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.6.0) — the full loop (capture, ratification, mistakes-first
|
|
17
17
|
retrieval, refactor-surviving re-anchoring, semantic docs layer, mind-model domains, and the
|
|
18
18
|
facts evidence layer) ships and is exercised end-to-end, but interfaces may still move before
|
|
19
19
|
a stable release. See
|
|
@@ -30,10 +30,11 @@ away for convenience.
|
|
|
30
30
|
2. **The store is append-only — and sync-clean.** Never hard-delete a `Decision`, `Fact`, or
|
|
31
31
|
`Domain`. Reversal = set `valid_to`/flip status on the old record + create a new one with
|
|
32
32
|
`supersedes`. Superseded records stay retrievable as "tried before, abandoned because…" —
|
|
33
|
-
that history *is* the product. A graph rebuild (`sidegraph-sync`) must
|
|
34
|
-
diff: it only ever touches derived, gitignored state (the local
|
|
35
|
-
binding status, the TOC cache), never a committed record file
|
|
36
|
-
derived state, never committed).
|
|
33
|
+
that history *is* the product. A graph rebuild (`sidegraph-sync`) must not produce a git
|
|
34
|
+
diff from regenerable state: it only ever touches derived, gitignored state (the local
|
|
35
|
+
index, entity mappings, binding status, the TOC cache), never a committed record file
|
|
36
|
+
(community labels are derived state, never committed). The one exception: a confirmed
|
|
37
|
+
leaf-file move may update that entity's committed descriptor.
|
|
37
38
|
3. **The store format is a public contract.** File-per-record JSON, a stamped
|
|
38
39
|
`schema_version`, and the append-only/merge rules are specified in
|
|
39
40
|
[`docs/reference/store-format.md`](docs/reference/store-format.md) — that page is the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sidegraph
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Own the memory, rent the graph — a durable decision/lessons layer as a sidecar over a code-graph engine.
|
|
5
5
|
Project-URL: Homepage, https://github.com/SantyagoSeaman/sidegraph
|
|
6
6
|
Project-URL: Repository, https://github.com/SantyagoSeaman/sidegraph
|
|
@@ -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 (once per session)
|
|
170
|
+
blind Read/Grep ──▶ nudged back to get_task_context (each form once per session)
|
|
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 (once per session)
|
|
142
|
+
blind Read/Grep ──▶ nudged back to get_task_context (each form once per session)
|
|
143
143
|
```
|
|
144
144
|
|
|
145
145
|
Two layers age differently: the **structure** layer (the code graph — entities,
|
|
@@ -20,11 +20,19 @@ Sidegraph is a local-only tool. Its entire data surface:
|
|
|
20
20
|
store (`decisions.db`, from before store schema 0.4.0) triggers a one-time migration
|
|
21
21
|
that renames the legacy file to `decisions.db.migrated-backup` (kept, never deleted)
|
|
22
22
|
alongside writing the new
|
|
23
|
-
directory layout.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
directory layout. The store is the default persistence location, not the only one:
|
|
24
|
+
`sidegraph-init` can write `.claude/settings.json` (the ratification-policy env entry);
|
|
25
|
+
the visualization, OKF export and bootstrap-report commands write to the output paths you
|
|
26
|
+
give them; and the optional `sidegraph-prepare-commit-msg` git hook, once you install it,
|
|
27
|
+
adds commented decision trailers to the commit message file git hands it
|
|
28
|
+
(normally `.git/COMMIT_EDITMSG`). Beyond those, the only filesystem writes are the standard config
|
|
29
|
+
snippets you install yourself (`.mcp.json`, hook entries) — Sidegraph touches nothing
|
|
30
|
+
else. See [`docs/reference/store-format.md`](docs/reference/store-format.md) for the full
|
|
31
|
+
layout.
|
|
32
|
+
- **Network:** none. No remote telemetry, no phone-home, nothing leaves your machine. Local
|
|
33
|
+
retrieval telemetry is recorded in the gitignored `index.db` by default (which records
|
|
34
|
+
were shown and which files were touched, never uploaded); set `SIDEGRAPH_TELEMETRY=off` to
|
|
35
|
+
stop new recording. The only
|
|
28
36
|
network-using feature is the *optional* semantic documentation pass, which is executed
|
|
29
37
|
by the separate Graphify CLI against the LLM provider you configure — not by Sidegraph.
|
|
30
38
|
|
|
@@ -31,20 +31,24 @@ the same way any other entity does.
|
|
|
31
31
|
|
|
32
32
|
## Multi-anchor at capture
|
|
33
33
|
|
|
34
|
-
`resolve_and_bind(record_id, ref, reader, store,
|
|
35
|
-
`Descriptor` against the current graph and can create up to
|
|
34
|
+
`resolve_and_bind(record_id, ref, reader, store, relation=None)` resolves one
|
|
35
|
+
`Descriptor` against the current graph and can create up to two bindings for it in one call:
|
|
36
36
|
|
|
37
37
|
- **Tier-2 (leaf)** — the concrete entity itself, when the resolve either succeeded or failed
|
|
38
38
|
outright (not when ambiguous).
|
|
39
39
|
- **Tier-1 (group)** — the entity's Leiden community, whenever one is known — see
|
|
40
40
|
[domain-aware Tier-1](#domain-aware-tier-1) below for what actually gets bound once a domain
|
|
41
41
|
has claimed that community.
|
|
42
|
-
- **Tier-0 (initiative)** — only when the decision names an owning initiative; always `live`.
|
|
43
42
|
|
|
44
43
|
`relation` (optional; `creates` \| `modifies` \| `affects` \| `deprecates` \| `considered`,
|
|
45
44
|
default `"affects"`) overrides the default on the Tier-2 and Tier-1 bindings created for *this*
|
|
46
|
-
anchor
|
|
47
|
-
|
|
45
|
+
anchor. See [data model](data-model.md#anchorbinding--tiered-link).
|
|
46
|
+
|
|
47
|
+
The **Tier-0 initiative** binding is not made per anchor. When the decision names an owning
|
|
48
|
+
initiative (or the propose path derives one from the current branch of the project's
|
|
49
|
+
repository: the directory that holds the store, or its symlink), the write path binds it once,
|
|
50
|
+
`live`, whatever the reader and the anchors: the name is redacted first, and a blank or
|
|
51
|
+
all-secret name binds nothing.
|
|
48
52
|
|
|
49
53
|
A decision typically ends up multi-anchored: a leaf plus its community (or domain), optionally
|
|
50
54
|
plus an initiative — so a single rebuild that only shifts the leaf still leaves the group anchor
|
|
@@ -88,11 +92,14 @@ silently re-pointed, never written to git, whenever Leiden renumbers.
|
|
|
88
92
|
Sidegraph never guesses. `reader.resolve()` returns exactly one of three statuses, and each
|
|
89
93
|
drives different bindings:
|
|
90
94
|
|
|
91
|
-
| Resolve status | Tier-2 leaf | Tier-1 community |
|
|
92
|
-
|
|
93
|
-
| **resolved** (unique match) | created, `live` | created if the node has a community, `live` |
|
|
94
|
-
| **ambiguous** (multiple matches) | **none created** | created only if *all* candidates share one community, `degraded` |
|
|
95
|
-
| **unresolved** (no match) | created, `orphaned` | none (no community to fall back to) |
|
|
95
|
+
| Resolve status | Tier-2 leaf | Tier-1 community |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| **resolved** (unique match) | created, `live` | created if the node has a community, `live` |
|
|
98
|
+
| **ambiguous** (multiple matches) | **none created** | created only if *all* candidates share one community, `degraded` |
|
|
99
|
+
| **unresolved** (no match) | created, `orphaned` | none (no community to fall back to) |
|
|
100
|
+
|
|
101
|
+
The Tier-0 initiative binding does not depend on the resolve status: it is decision-level, made
|
|
102
|
+
once by the write path, `live`, whenever an initiative is named.
|
|
96
103
|
|
|
97
104
|
An ambiguous match with candidates spanning different communities gets **no binding at all**
|
|
98
105
|
beyond a possible initiative — Sidegraph would rather anchor nothing than anchor to a guess.
|
|
@@ -121,7 +128,8 @@ name-only match, then orphaned. No special-casing for concepts versus code symbo
|
|
|
121
128
|
|
|
122
129
|
The sync job (triggered lazily on read — see [retrieval](retrieval.md#lazy-sync-on-read))
|
|
123
130
|
re-resolves every concrete entity through a deterministic ladder (`rebind_entity` in
|
|
124
|
-
`sync.py`), gated on a graph-version check so
|
|
131
|
+
`sync.py`), gated on a graph-version check so the full pass is skipped when nothing changed (entities
|
|
132
|
+
remembered under `pending_uncommitted_moves` are still re-verified once `HEAD` has moved):
|
|
125
133
|
|
|
126
134
|
1. **Exact** — `resolve(name, file_path)` still resolves uniquely -> **rebound** (or
|
|
127
135
|
**unchanged** if the node id didn't move); leaf bindings heal to `live`; the entity's
|
|
@@ -261,8 +261,9 @@ newer/future version, or an unrecognized string) is a hard rejection: use a fres
|
|
|
261
261
|
## `Initiative` — the Tier-0 grouping container
|
|
262
262
|
|
|
263
263
|
The high-level capture APIs use an initiative as a flat Tier-0 abstract entity named
|
|
264
|
-
`initiative:<label>`. Passing a draft's `initiative` field creates that entity and binding
|
|
265
|
-
|
|
264
|
+
`initiative:<label>`. Passing a draft's `initiative` field creates that entity and binding,
|
|
265
|
+
after the name is redacted and trimmed; a blank or all-secret name binds nothing. Omitting
|
|
266
|
+
it creates neither. Capture may derive the label from a branch before it reaches
|
|
266
267
|
this step, but the storage layer does not do so implicitly.
|
|
267
268
|
|
|
268
269
|
The `Initiative` model below is a separate low-level persisted record supported by
|
|
@@ -296,7 +296,8 @@ Before rendering, every retrieval-facing MCP tool — `get_task_context`, `query
|
|
|
296
296
|
`query_decisions`, and `drill_down` — plus the `SessionStart` hook calls `maybe_sync(store,
|
|
297
297
|
reader)` — best-effort, wrapped so a sync failure degrades to un-synced retrieval rather than
|
|
298
298
|
erroring. `maybe_sync` is itself cheap in the common case: it compares the graph's current
|
|
299
|
-
version against the store's `last_synced_graph_version` meta stamp and
|
|
299
|
+
version against the store's `last_synced_graph_version` meta stamp and skips the full pass if they match (an entity remembered under
|
|
300
|
+
`pending_uncommitted_moves` is still re-verified once `HEAD` has moved).
|
|
300
301
|
This is the self-healing mechanism described in
|
|
301
302
|
[anchoring](anchoring.md#what-happens-on-rename-or-move): a missed post-commit hook is simply
|
|
302
303
|
caught by the next read, and it's what keeps each accepted domain's `communities` field current
|
|
@@ -140,7 +140,11 @@ policy is separate.
|
|
|
140
140
|
`--report bootstrap-report.md` writes aggregate counts, separate edit/action rates, candidate
|
|
141
141
|
precision, per-action and CLI-to-proof elapsed seconds, anchor coverage, proof state, review
|
|
142
142
|
debt, and the canonical paths changed. It excludes source content and candidate text and is
|
|
143
|
-
never uploaded automatically.
|
|
143
|
+
never uploaded automatically. The report never overwrites any host's config file, the graph, a scanned
|
|
144
|
+
source or a store file, hard links included. The reviewed action summary starts with the
|
|
145
|
+
resolved `store:` path, and names a symlink when the path or a directory above it in the
|
|
146
|
+
repository is one. A symlinked directory or store file *inside* the store stops the run
|
|
147
|
+
before review. These local metrics are operator/session observations, not a
|
|
144
148
|
first-user cohort or task-benefit result. Inspect the report before sharing.
|
|
145
149
|
|
|
146
150
|
## Reproduce the dogfood path
|