sidegraph 0.4.0__tar.gz → 0.5.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.4.0 → sidegraph-0.5.0}/.github/workflows/ci.yml +0 -1
- {sidegraph-0.4.0 → sidegraph-0.5.0}/CHANGELOG.md +61 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/CLAUDE.md +1 -1
- {sidegraph-0.4.0 → sidegraph-0.5.0}/PKG-INFO +4 -3
- {sidegraph-0.4.0 → sidegraph-0.5.0}/README.md +3 -2
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/getting-started/installation.md +8 -5
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/reference/cli.md +61 -19
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/reference/releasing.md +30 -4
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/.claude-plugin/plugin.json +1 -1
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/.codex-plugin/plugin.json +1 -1
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/import-adrs/SKILL.md +7 -2
- {sidegraph-0.4.0 → sidegraph-0.5.0}/pyproject.toml +1 -1
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/__init__.py +1 -1
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/cli.py +26 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/doc_import.py +23 -6
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/verify.py +110 -23
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/conftest.py +11 -7
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_cli_import.py +66 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_cli_init.py +67 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_doc_import.py +67 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_env_isolation.py +3 -1
- sidegraph-0.5.0/tests/test_sandbox_hygiene.py +328 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_verify_transitions.py +368 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/uv.lock +5 -4
- sidegraph-0.4.0/tests/test_sandbox_hygiene.py +0 -133
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.agents/plugins/marketplace.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.claude-plugin/marketplace.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.github/CODEOWNERS +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.github/secret_scanning.yml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.github/workflows/publish.yml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.github/workflows/scorecard.yml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.gitignore +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.gitleaks.toml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.pre-commit-config.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/.python-version +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/AGENTS.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/CODE_OF_CONDUCT.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/CONTRIBUTING.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/LICENSE +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/SECURITY.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/README.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/concepts/anchoring.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/concepts/data-model.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/concepts/decision-memory.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/concepts/mind-model.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/concepts/retrieval.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/getting-started/bootstrap.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/getting-started/claude-code-setup.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/getting-started/codex-setup.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/getting-started/quickstart.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/guides/capturing-decisions.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/guides/ci-cd-maintenance.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/guides/naming-your-domains.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/guides/retrieval-in-sessions.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/guides/semantic-docs.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/guides/surviving-refactors.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/guides/team-workflow.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/guides/verifying-your-setup.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/integrations/claude-code.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/integrations/codex.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/integrations/graphify.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/llms.txt +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/pilot-kit/README.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/pilot-kit/corpus_fit.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/pilot-kit/judge-prompt.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/pilot-kit/questions-prompt.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/pilot-kit/rubric-template.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/reference/configuration.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/reference/git-bindings.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/reference/hooks.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/reference/mcp-tools.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/reference/operations.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/reference/stability.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/reference/store-format.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/docs/whitepaper/index.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/.mcp.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/codex/hooks.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/codex/mcp.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/hooks/hooks.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/check-plan/SKILL.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/check-plan/agents/openai.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/explain-why/SKILL.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/explain-why/agents/openai.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/heal-anchors/SKILL.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/heal-anchors/agents/openai.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/import-adrs/agents/openai.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/manage-domains/SKILL.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/manage-domains/agents/openai.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/name-domains/SKILL.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/name-domains/agents/openai.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/ratify-decisions/SKILL.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/ratify-decisions/agents/openai.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/record-decision/SKILL.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/record-decision/agents/openai.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/record-fact/SKILL.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/record-fact/agents/openai.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/setup/SKILL.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/setup/agents/openai.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/stats/SKILL.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/stats/agents/openai.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/triage-drift/SKILL.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/plugin/sidegraph/skills/triage-drift/agents/openai.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/anchoring.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/bootstrap/__init__.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/bootstrap/apply.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/bootstrap/catalog.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/bootstrap/cli.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/bootstrap/integrations.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/bootstrap/model.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/bootstrap/planner.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/bootstrap/proof.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/bootstrap/review.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/bootstrap/scan.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/capture.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/config.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/doctor.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/domains.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/engine/__init__.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/engine/reader.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/gitio.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/host/__init__.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/host/claude_settings.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/host/hooks.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/importer.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/okf.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/profiles.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/retrieval.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/schema.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/server.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/stats/__init__.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/stats/model.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/stats/render.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/store.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/sync.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/viz/__init__.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/viz/assets/vis-network.min.js +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/viz/model.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/viz/render.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/src/sidegraph/viz/template.html +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/__init__.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/auto_policy/parity_goldens.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/bitfinex_slice.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/bootstrap/flows/bmad/_bmad-output/planning-artifacts/architecture/cache/ARCHITECTURE-SPINE.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/bootstrap/flows/generic-adr/docs/adr/001-retry.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/bootstrap/flows/genkovich-sdd/docs/features/cache/adr/001.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/bootstrap/flows/spec-kit/specs/cache/plan.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/bootstrap/flows/superpowers/docs/superpowers/specs/2026-07-01-cache-design.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/bootstrap/graph.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/bootstrap/hosts/claude/.claude/settings.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/bootstrap/hosts/claude/.mcp.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/bootstrap/hosts/codex/.codex/config.toml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/bootstrap/hosts/codex/.codex/hooks/hooks.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/bootstrap/scan/docs/adr/001-safe.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/corpus/PUBLIC_CORPORA.txt +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/corpus/openspec/_provenance.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/corpus/openspec/graph.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/corpus/self-corpus/_provenance.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/corpus/self-corpus/expected/retrieval-engine-reader.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/corpus/self-corpus/graph.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/adr/0001-use-sessions.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/bmad/ARCHITECTURE-SPINE.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/bmad/tree/_bmad-output/planning-artifacts/architecture/architecture-payments-2026-07-30/.memlog.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/bmad/tree/_bmad-output/planning-artifacts/architecture/architecture-payments-2026-07-30/ARCHITECTURE-SPINE.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/bmad/tree/_bmad-output/planning-artifacts/prds/prd-payments-2026-07-30/prd.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/genkovich/0001-queue-backpressure.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/genkovich/sad.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/adr/0001-queue-backpressure.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/sad.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/genkovich/tree/docs/features/payments/spec.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/design-empty.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/design-h3-split.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/design-with-summary.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/design.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/proposal-alternatives.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/proposal.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/design.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/proposal.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/specs/cap/spec.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/tree/openspec/changes/add-thing/tasks.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/tree/openspec/changes/archive/2026-01-01-add-thing/design.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/tree/openspec/changes/archive/2026-01-01-add-thing/proposal.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/tree/openspec/config.yaml +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/openspec/tree/openspec/specs/cap/spec.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/spec-kit/plan.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/spec-kit/tree/specs/003-payment-retries/plan.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/spec-kit/tree/specs/003-payment-retries/spec.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/superpowers/2026-07-01-example-design.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/flows/superpowers/2026-07-01-thin-design.md +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/fixtures/mini_graph.json +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_anchoring.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_anchoring_mapping_refresh.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_bootstrap_apply.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_bootstrap_catalog.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_bootstrap_cli.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_bootstrap_integrations.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_bootstrap_model.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_bootstrap_planner.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_bootstrap_proof.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_bootstrap_review.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_bootstrap_scan.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_capture_auto_accept.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_capture_facts.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_capture_integration.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_capture_neighbors.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_capture_propose.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_capture_redact.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_cli_compact.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_cli_doctor.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_cli_domains.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_cli_okf.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_cli_ratify.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_cli_ratify_facts.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_cli_stats.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_cli_sync.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_cli_sync_check.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_cli_viz.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_codex_plugin.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_community_baseline.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_config.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_corpus_expected_renders.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_corpus_self_corpus.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_coverage_telemetry_e2e.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_digest_integrity.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_doc_corpus_integration.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_docs_claims.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_doctor.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_doctor_auto_share.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_doctor_code_drift.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_doctor_dangling_supports.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_doctor_duplicate_entity.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_doctor_graph_root_mismatch.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_doctor_never_surfaced.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_doctor_scan.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_doctor_stale_instructions.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_doctor_unratified_accept.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_domains.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_entity_duplicate_resolution.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_entity_get_or_create_race.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_fact_reachability_gate.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_flow_profile.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_git_bindings_blame.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_git_bindings_hook.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_git_bindings_provenance.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_host_claude_settings.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_host_drift_nudge.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_host_pretool.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_host_session_key.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_host_session_start.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_host_stop.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_host_touch_events.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_importer.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_mind_model_additive_fields.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_okf.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_openspec_profile.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_pathless_descriptor_adoption.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_pilot_kit_corpus_fit.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_proposal_lifecycle.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_ratify_listing_gone_dark.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_ratify_policy.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_reader_community_labels.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_reader_doc_nodes.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_reader_graph.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_reader_integration.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_reader_nodes_in_file.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_reader_perf.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_reader_rationale.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_reader_read.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_reader_resolve.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_reader_subdir_mismatch.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_reader_version.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_redaction_seeded.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_repoint_integration.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_budget_counters.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_context.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_drift_marker.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_drilldown.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_facts.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_ids.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_integration.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_rank.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_seeds.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_shown_ids.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_terminal_evidence.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_thin_tools.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_toc.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_toptier.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_retrieval_unratified.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_schema_descriptor.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_schema_domain.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_schema_fact.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_add_anchors.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_anchoring.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_capture.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_coverage_events.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_domains.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_drilldown.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_facts.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_find_entity.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_get_store.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_get_task_context.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_import.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_mcp_smoke.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_prewrite_anchor_validation.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_ratify_facts.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_redaction.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_render_events.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_supersede.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_sync_anchors.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_telemetry.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_thin_tools.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_server_verify.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_stats_graph.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_stats_model.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_stats_render.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_stats_skill.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_stats_snapshot.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_atomic_write_tmp_names.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_canonical_stat.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_compact.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_compact_review.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_concurrent_open.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_coverage_telemetry.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_derived_community.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_domains.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_entities.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_fact_cascade.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_facts.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_meta.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_migration.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_mutation_guard.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_mutation_immediate.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_opens_with_merged_duplicate.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_persistence.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_ratification.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_rebuild_atomicity.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_render_events.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_retrieval.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_slug_conflicts.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_stamping_marker.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_telemetry.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_threading.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_store_tmp_sweep_age.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_sync_clean.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_sync_domains.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_sync_drift_cache.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_sync_fresh_clone.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_sync_integration.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_sync_rebind.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_sync_repoint.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_sync_report_has_findings.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_sync_run.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_sync_toc_cache.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_sync_volatile_heal.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_sync_wiring.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_telemetry_retention.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_verify_snapshot.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_viz_asset_packaged.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_viz_model.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_viz_render_html.py +0 -0
- {sidegraph-0.4.0 → sidegraph-0.5.0}/tests/test_viz_render_json.py +0 -0
|
@@ -7,6 +7,67 @@ interfaces, exactly, and what each one promises: [`docs/reference/stability.md`]
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.5.0] — 2026-09-23
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **The public `main`, which the plugin manifests install from, moves only at releases.**
|
|
15
|
+
The plugin runs whatever `main` holds, so a snapshot pushed between releases used to reach
|
|
16
|
+
every plugin user at once. The release script now pushes `main` only for a release: it
|
|
17
|
+
refuses unless the version it carries is untagged in the public repository and
|
|
18
|
+
`CHANGELOG.md` dates it.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **`sidegraph-init` now says to restart the Claude Code session after it writes
|
|
23
|
+
`SIDEGRAPH_RATIFY_POLICY`.** The Sidegraph MCP server reads the policy from the
|
|
24
|
+
environment it started with, so a server started before `sidegraph-init` kept proposing
|
|
25
|
+
under the old policy until the session restarted, and nothing said so.
|
|
26
|
+
- **`sidegraph-verify --against` no longer flags a ratification of an already-committed
|
|
27
|
+
proposal, or a supersede/drop that touches a record written before a later schema addition
|
|
28
|
+
(`Provenance.commit`, `Domain.seed_anchors`/`path_prefixes`) existed.** Ratifying a
|
|
29
|
+
decision, fact, or domain stamps `ratified_at`/`ratified_by`, and neither field was on the
|
|
30
|
+
transition layer's mutable allow-list, so the stamp alone was reported as an illegal field
|
|
31
|
+
change. Separately, rewriting an old record that predates a field added to its schema
|
|
32
|
+
serializes that field back in as its default, which a plain top-level or whole-list
|
|
33
|
+
comparison also read as a change. The ratifier stamp may now be set once, from a proposed
|
|
34
|
+
record, landing on any state reached through accepted within the diffed range; an absent
|
|
35
|
+
field now counts as the same value as an explicit `null` or an empty list/object, at every
|
|
36
|
+
nesting depth and inside list items. A field whose default is a non-empty value is not
|
|
37
|
+
covered by this.
|
|
38
|
+
- **`sidegraph-import --docs` no longer aborts on a file that is not valid UTF-8.** It
|
|
39
|
+
decoded every document as strict UTF-8 with no handler, so one document saved in
|
|
40
|
+
`cp1251` (or carrying a stray non-UTF-8 byte) raised and stopped the whole run, with
|
|
41
|
+
nothing after it imported and no report printed. The file is now a named skip
|
|
42
|
+
(`skipped_undecodable`) instead: the run continues, and both the real run and
|
|
43
|
+
`--dry-run` print the skipped path(s), last.
|
|
44
|
+
- **`sidegraph-import --docs` now reads a UTF-8 document that starts with a byte-order mark
|
|
45
|
+
(BOM).** The BOM used to survive into the parsed text, so the H1 and any frontmatter never
|
|
46
|
+
matched, and a real decision document was silently counted `skipped_not_decision`. It is
|
|
47
|
+
now stripped before parsing. `sidegraph-bootstrap` still reads such a file without
|
|
48
|
+
stripping it.
|
|
49
|
+
|
|
50
|
+
Re-importing a BOM document that an earlier version did import can change its record,
|
|
51
|
+
once:
|
|
52
|
+
- On the `openspec` profile, a BOM `proposal.md` had imported under a title built from its
|
|
53
|
+
path. The re-import supersedes it with the real H1 title.
|
|
54
|
+
- Frontmatter the BOM hid is now honoured. A document marked `status: superseded` now
|
|
55
|
+
counts `skipped_superseded_frontmatter`, and its earlier live record stays as it is.
|
|
56
|
+
- A document marked as a draft, proposed, pending or under review keeps its earlier
|
|
57
|
+
`accepted` record: a re-import compares content, not status, and the content is
|
|
58
|
+
unchanged.
|
|
59
|
+
|
|
60
|
+
Retiring or re-proposing such a record is manual.
|
|
61
|
+
|
|
62
|
+
### Security
|
|
63
|
+
|
|
64
|
+
- **The lockfile moves `anyio` from 4.14.1 to 4.15.1**, past three advisories fixed in
|
|
65
|
+
4.14.2: TLS certificate spoofing through IDNA 2003 host-name encoding (critical),
|
|
66
|
+
`run_process` keeping the parent's supplementary groups (high), and process-pool workers
|
|
67
|
+
blocking on undrained stderr (moderate). The published package does not pin `anyio`, so
|
|
68
|
+
this changes development and CI environments and installs made from `uv.lock`; a fresh
|
|
69
|
+
install already resolves a fixed version.
|
|
70
|
+
|
|
10
71
|
## [0.4.0] — 2026-09-22
|
|
11
72
|
|
|
12
73
|
### Fixed
|
|
@@ -13,7 +13,7 @@ task-aware retrieval + decision memory riding on the engine's entity graph.
|
|
|
13
13
|
continuing participant in the project. A core feature must preserve, organize, or deliver
|
|
14
14
|
accumulated project understanding. Document search by itself is not the product.
|
|
15
15
|
|
|
16
|
-
Sidegraph is pre-1.0 (v0.
|
|
16
|
+
Sidegraph is pre-1.0 (v0.5.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.5.0
|
|
4
4
|
Summary: Own the memory, rent the graph — a durable decision/lessons layer as a sidecar over a code-graph engine.
|
|
5
5
|
Project-URL: Homepage, https://github.com/SantyagoSeaman/sidegraph
|
|
6
6
|
Project-URL: Repository, https://github.com/SantyagoSeaman/sidegraph
|
|
@@ -84,9 +84,10 @@ only ever reads `graph.json`, so the plain install above is all it needs.
|
|
|
84
84
|
uv tool install sidegraph # from PyPI — puts sidegraph-init / sidegraph-mcp / … on PATH
|
|
85
85
|
sidegraph-init
|
|
86
86
|
|
|
87
|
-
# Prefer
|
|
87
|
+
# Prefer running straight from git instead of PyPI? Swap step 3 for:
|
|
88
88
|
# uvx --from git+https://github.com/SantyagoSeaman/sidegraph.git@main sidegraph-init
|
|
89
|
-
# `@main`
|
|
89
|
+
# `@main` moves only when a release is cut. It is still a mutable ref: a later cache refresh can
|
|
90
|
+
# install a newer one. Pin a tag or a SHA for CI.
|
|
90
91
|
```
|
|
91
92
|
|
|
92
93
|
4. **Name your domains** — turns the graph's communities into a described table of
|
|
@@ -56,9 +56,10 @@ only ever reads `graph.json`, so the plain install above is all it needs.
|
|
|
56
56
|
uv tool install sidegraph # from PyPI — puts sidegraph-init / sidegraph-mcp / … on PATH
|
|
57
57
|
sidegraph-init
|
|
58
58
|
|
|
59
|
-
# Prefer
|
|
59
|
+
# Prefer running straight from git instead of PyPI? Swap step 3 for:
|
|
60
60
|
# uvx --from git+https://github.com/SantyagoSeaman/sidegraph.git@main sidegraph-init
|
|
61
|
-
# `@main`
|
|
61
|
+
# `@main` moves only when a release is cut. It is still a mutable ref: a later cache refresh can
|
|
62
|
+
# install a newer one. Pin a tag or a SHA for CI.
|
|
62
63
|
```
|
|
63
64
|
|
|
64
65
|
4. **Name your domains** — turns the graph's communities into a described table of
|
|
@@ -17,7 +17,8 @@ The `git+…@main` examples below track a mutable branch: a later `uvx` cache re
|
|
|
17
17
|
install different code. That is useful while trying Sidegraph. For CI, shared setup, or a
|
|
18
18
|
measured pilot, replace `@main` with a release tag or commit SHA, for example
|
|
19
19
|
`git+https://github.com/SantyagoSeaman/sidegraph.git@<sha>`. The plugin marketplace is the
|
|
20
|
-
exception: its public manifests intentionally track `main
|
|
20
|
+
exception: its public manifests intentionally track `main`, and the release process moves
|
|
21
|
+
that `main` only when it cuts a release. See
|
|
21
22
|
[`reference/stability.md`](../reference/stability.md) for the promises made by each surface.
|
|
22
23
|
|
|
23
24
|
## Install Sidegraph
|
|
@@ -54,11 +55,13 @@ PyPI package. See
|
|
|
54
55
|
the integration details for [Claude Code](../integrations/claude-code.md#plugin-install-path)
|
|
55
56
|
or [Codex](../integrations/codex.md#plugin-install-path).
|
|
56
57
|
|
|
57
|
-
### Option C — uvx directly from git
|
|
58
|
+
### Option C — uvx directly from git
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
[`uvx`](https://docs.astral.sh/uv/guides/tools/)
|
|
60
|
+
Prefer manual wiring, or need an entry point outside Claude Code (e.g. `sidegraph-init` from
|
|
61
|
+
a plain terminal)? Run it straight from the repository with
|
|
62
|
+
[`uvx`](https://docs.astral.sh/uv/guides/tools/), with no persistent install and no local
|
|
63
|
+
checkout. `@main` moves only when a release is cut. For reproducibility, pin a tag or commit SHA instead
|
|
64
|
+
(see "Mutable development references" above):
|
|
62
65
|
|
|
63
66
|
```bash
|
|
64
67
|
uvx --from git+https://github.com/SantyagoSeaman/sidegraph.git@main sidegraph-init
|
|
@@ -132,6 +132,11 @@ the Sidegraph checkout):
|
|
|
132
132
|
`--ratify-policy VALUE` sets the value with no prompt, still never overwriting an
|
|
133
133
|
existing one, for a fully scripted setup that wants an explicit answer.
|
|
134
134
|
|
|
135
|
+
When the value is written, the line after it says to restart the Claude Code session:
|
|
136
|
+
the Sidegraph MCP server reads the policy from the environment it started with, so a
|
|
137
|
+
server started before `sidegraph-init` keeps proposing under the old policy until the
|
|
138
|
+
session restarts.
|
|
139
|
+
|
|
135
140
|
Whatever happens above, a host without `.claude/settings.json` (Codex CLI, CI) gets the
|
|
136
141
|
equivalent as a plain `export SIDEGRAPH_RATIFY_POLICY=<value>` line. A settings-file
|
|
137
142
|
problem never fails the store creation in step 1.
|
|
@@ -632,24 +637,39 @@ import on their own. Both the real run and `--dry-run` print an extra line whene
|
|
|
632
637
|
`skipped_degenerate_parent > 0`: `N split parent(s) skipped as degenerate (echoed context
|
|
633
638
|
or empty choice) — children imported on their own`.
|
|
634
639
|
|
|
640
|
+
**A file that is not valid UTF-8 is skipped, named, and the run continues.** Every document
|
|
641
|
+
is decoded as `utf-8-sig` — plain UTF-8, with a leading byte-order mark stripped when one is
|
|
642
|
+
present. No encoding is guessed. A file whose bytes don't decode (for example, one saved in
|
|
643
|
+
`cp1251`) is counted `skipped_undecodable` instead of raising and aborting the whole run.
|
|
644
|
+
Both the real run and `--dry-run` print an extra block, last, whenever
|
|
645
|
+
`skipped_undecodable > 0`:
|
|
646
|
+
|
|
647
|
+
```
|
|
648
|
+
N file(s) skipped: not valid UTF-8, re-save as UTF-8 to import:
|
|
649
|
+
path/to/bad-file.md
|
|
650
|
+
```
|
|
651
|
+
|
|
635
652
|
**Real run:** `imported N decision(s), superseded M (skipped: A existing, B unanchorable,
|
|
636
653
|
C not-decision-shaped, D unparseable, E superseded-frontmatter, F outside-profile)`, followed
|
|
637
654
|
by the status-derived-proposed line above when applicable, followed by the template-skip line
|
|
638
|
-
and the degenerate-parent line above when applicable
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
never carries the
|
|
655
|
+
and the degenerate-parent line above when applicable, and the undecodable-file block above
|
|
656
|
+
last when applicable. A non-zero `F` is the profile scope filter, not a parse failure — see
|
|
657
|
+
the `--any-doc` note under the flag table above. Under a non-`manual`
|
|
658
|
+
`SIDEGRAPH_RATIFY_POLICY`: `imported N decision(s), superseded M, auto-ratified K (skipped:
|
|
659
|
+
…)` — only fresh `--propose` writes that land as a new `proposed` record are eligible;
|
|
660
|
+
status-derived and `superseded` re-imports never auto-ratify; each failed auto-ratify attempt
|
|
661
|
+
prints `auto-ratify failure: <id>: <reason>` on stderr; `--dry-run` never carries the
|
|
662
|
+
segment.
|
|
645
663
|
|
|
646
664
|
**`--dry-run`:** one line per candidate — `<path>: [imported|superseded] <title>`, with any
|
|
647
665
|
skipped-anchor reasons indented underneath (` anchor skipped: <name> (<reason>)`) —
|
|
648
666
|
followed by a blank line, `would import N decision(s), supersede M (...)` (same skip breakdown
|
|
649
667
|
as the real-run line above), the status-derived-proposed line when applicable (`N would land
|
|
650
668
|
proposed (...)`), the template-skip line and the degenerate-parent line above when
|
|
651
|
-
applicable, and a per-file breakdown.
|
|
652
|
-
|
|
669
|
+
applicable, and a per-file breakdown. The undecodable-file block above prints last, after
|
|
670
|
+
the per-file breakdown. Both indent their lines by two spaces, so breakdown lines printed
|
|
671
|
+
after the block would read as more undecodable files. No decision or binding is written; opening the
|
|
672
|
+
store may still migrate supported legacy data or rebuild the derived index.
|
|
653
673
|
|
|
654
674
|
**Exit code:** `0` on success, including an empty run and every `--dry-run` invocation.
|
|
655
675
|
Returns `1` before touching the graph or store if `--profile` names an unknown profile
|
|
@@ -903,21 +923,28 @@ plain-text line):
|
|
|
903
923
|
| `illegal-deletion` | transition | a record file — or an already-published archive segment — was deleted with no sanctioned reason. The one exception: a decision/domain whose id is present in an `archive/*.jsonl` segment in the new tree (a legitimate `sidegraph-compact`) |
|
|
904
924
|
|
|
905
925
|
**What's legally mutable** (transition layer only; derived from `store.py`'s write methods,
|
|
906
|
-
not invented — see `verify.py`'s module
|
|
926
|
+
not invented — see `verify.py`'s module comment above the mutable-field tables for exactly
|
|
927
|
+
which methods):
|
|
907
928
|
|
|
908
929
|
- **Decisions:** `status` (only along a real transition — `proposed→accepted`,
|
|
909
930
|
`proposed→rejected`, `proposed→superseded`, `accepted→superseded`, `accepted→deprecated`),
|
|
910
|
-
`valid_to` (`null → value`, once).
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
`
|
|
917
|
-
|
|
931
|
+
`valid_to` (`null → value`, once). `ratified_at`/`ratified_by` may be set once, when a
|
|
932
|
+
proposed record is accepted — even if it moves on to a later state (`superseded`) within the
|
|
933
|
+
same diffed range — and never changes again after that. Everything else (`title`, `kind`,
|
|
934
|
+
`context`, `choice`, `rejected`, `consequences`, `layer`, `valid_from`, `supersedes`,
|
|
935
|
+
`provenance`) is immutable.
|
|
936
|
+
- **Facts:** the same shape, `status`/`valid_to`/the ratifier stamp, but **without**
|
|
937
|
+
`accepted→deprecated` — no live write path ever sets a fact `deprecated` (`schema.py`:
|
|
938
|
+
"DEPRECATED unused for facts", unlike the decision-side forward-compat carve-out above), so
|
|
939
|
+
that jump is *not* legal here and is flagged `illegal-status-jump` if it appears. Legal:
|
|
940
|
+
`proposed→accepted`, `proposed→rejected`, `proposed→superseded`, `accepted→superseded`.
|
|
941
|
+
Everything else (`statement`, `source`, `supports`, `valid_from`, `supersedes`,
|
|
942
|
+
`provenance`) is immutable.
|
|
918
943
|
- **Domains:** `status` (`proposed→accepted`, `proposed→dropped`, `accepted→dropped`,
|
|
919
944
|
`proposed→superseded`, `accepted→superseded`, `dropped→superseded`). `communities` is
|
|
920
|
-
index-only and never appears in the canonical file.
|
|
945
|
+
index-only and never appears in the canonical file. `ratified_at`/`ratified_by` may be set
|
|
946
|
+
once, when a proposed record is accepted — even if it moves on to a later state (`dropped`,
|
|
947
|
+
`superseded`) within the same diffed range — and never changes again after that.
|
|
921
948
|
Everything else (`domain_id`, `slug`, `title`, `summary`, `parent_id`, `path_prefixes`,
|
|
922
949
|
`seed_anchors`, `provenance`) is immutable.
|
|
923
950
|
- **Entities:** `descriptor` may change when sync confirms a durable leaf-file move.
|
|
@@ -933,6 +960,21 @@ not invented — see `verify.py`'s module docstring for the line-numbered deriva
|
|
|
933
960
|
`A`) is legal; any modification or deletion of an already-published one is always
|
|
934
961
|
illegal.
|
|
935
962
|
|
|
963
|
+
A field an older file was written before its schema even had is simply absent from that
|
|
964
|
+
file — whether its default is `null` (`Provenance.commit` today) or an empty list/object
|
|
965
|
+
(`Domain.seed_anchors`/`path_prefixes` today). The next legal rewrite re-serializes the record
|
|
966
|
+
and fills the field back in with that default. That alone is never a change: an absent field
|
|
967
|
+
counts as the same value as an explicit `null` or an empty list/object, inside nested objects
|
|
968
|
+
and inside the items of a list, everywhere this table calls a field immutable. A field whose
|
|
969
|
+
default is a *non-empty* value (`Decision.scope`, `"repo"`) is **not** covered by this — an
|
|
970
|
+
absent key there still reads as changed — but no file in this store lacks `scope` today.
|
|
971
|
+
|
|
972
|
+
**Known limit:** `verify_against` compares only the net change across the whole diffed range
|
|
973
|
+
(see "diffs the CURRENT WORKING TREE" below), not each intermediate commit. So a ratifier
|
|
974
|
+
stamp appearing on a record that ends up `dropped`/`superseded` in that same range cannot be
|
|
975
|
+
told apart from a record that was legally accepted and only later dropped or superseded — the
|
|
976
|
+
store's own git history, not this lint, is the evidence for who ratified what and when.
|
|
977
|
+
|
|
936
978
|
**`--against <ref>` diffs the CURRENT WORKING TREE against `<ref>`'s snapshot — not two fixed
|
|
937
979
|
points in history.** Passing a moving branch name directly (`--against origin/main`) is only
|
|
938
980
|
correct when your checkout's `HEAD` actually sits at that branch's tip; on a PR branch that's
|
|
@@ -58,15 +58,41 @@ Prepare the release on internal `main`, then run the clean-tree preflight:
|
|
|
58
58
|
7. Commit the release preparation on internal `main`. Both the internal and public checkouts
|
|
59
59
|
must now be clean.
|
|
60
60
|
8. Run `uv run python tools/preflight_release.py --online`. It verifies version agreement,
|
|
61
|
-
changelog shape, clean branches, target repository, and
|
|
62
|
-
|
|
63
|
-
prepared yet.
|
|
61
|
+
changelog shape, clean branches, and target repository, and that `vX.Y.Z` is not already
|
|
62
|
+
tagged in the **internal** checkout or its origin. Run it **after** the release changes are
|
|
63
|
+
committed: running it first can only report the work you have not prepared yet.
|
|
64
64
|
9. Cut the allowlisted public snapshot with
|
|
65
65
|
`tools/release-public.sh "release: vX.Y.Z" --push`. This creates and pushes the public
|
|
66
|
-
`main` commit that will receive the release tag.
|
|
66
|
+
`main` commit that will receive the release tag. `--push` itself refuses unless `vX.Y.Z`
|
|
67
|
+
is untagged in the **public** repository and `CHANGELOG.md` dates it (see "The public
|
|
68
|
+
main moves only at releases" below). Refresh `demo` separately when required.
|
|
67
69
|
|
|
68
70
|
Only after all nine steps pass is the public snapshot ready to tag.
|
|
69
71
|
|
|
72
|
+
### The public main moves only at releases
|
|
73
|
+
|
|
74
|
+
Every plugin manifest installs from the public repository's `main`, and `uv` re-resolves that
|
|
75
|
+
branch reference on every call, so pushing `main` reaches every plugin user at once. For that
|
|
76
|
+
reason the public `main` moves only as part of a release: `tools/release-public.sh --push`
|
|
77
|
+
refuses to push it unless the version being published is untagged in the public repository
|
|
78
|
+
and `CHANGELOG.md` dates it, checked before anything is written and again right before the
|
|
79
|
+
push. A docs-only or other non-release change waits for the next release, or ships in an
|
|
80
|
+
urgent patch release.
|
|
81
|
+
|
|
82
|
+
Two consequences follow. First, bump the version in `pyproject.toml` and date its
|
|
83
|
+
`CHANGELOG.md` heading only as part of release preparation (steps 1 and 2 above). Once both
|
|
84
|
+
are on `main`, every snapshot counts as a release until the tag exists, so doing them ahead of
|
|
85
|
+
the release defeats the guard. Second, re-cutting a version whose tag-driven publish failed still needs
|
|
86
|
+
its tag deleted in both the public checkout and its origin before the next `--push`;
|
|
87
|
+
otherwise the push is refused.
|
|
88
|
+
|
|
89
|
+
Between the release-preparation commit and the tag, every `--push` is a re-cut of that same
|
|
90
|
+
release, and the tag goes on the last one. Tag promptly after the push, so the window stays
|
|
91
|
+
short.
|
|
92
|
+
|
|
93
|
+
Never push the public `main` by hand: the gate lives in `tools/release-public.sh`, and a
|
|
94
|
+
manual `git push` from the public checkout bypasses it.
|
|
95
|
+
|
|
70
96
|
## Tag-driven publish flow
|
|
71
97
|
|
|
72
98
|
PyPI publishing is driven entirely by a git tag. There is deliberately no manual dispatch: a
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sidegraph",
|
|
3
3
|
"displayName": "Sidegraph",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"description": "Durable decision/lessons memory over your code graph — ADRs, gotchas, and constraints that survive refactors, retrieved mistakes-first.",
|
|
6
6
|
"author": { "name": "SantyagoSeaman", "url": "https://github.com/SantyagoSeaman" },
|
|
7
7
|
"homepage": "https://github.com/SantyagoSeaman/sidegraph",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sidegraph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Durable decision/lessons memory over your code graph — ADRs, gotchas, and constraints that survive refactors, retrieved mistakes-first.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"skills": "./skills/",
|
|
@@ -49,8 +49,8 @@ Costs nothing, writes nothing, and shows exactly what a real run would do. Read
|
|
|
49
49
|
report closely:
|
|
50
50
|
|
|
51
51
|
- `would import N decision(s), supersede M (skipped: A existing, B unanchorable, C
|
|
52
|
-
not-decision-shaped, D unparseable, E superseded-frontmatter)` — plus
|
|
53
|
-
and per-anchor `anchor skipped: <name> (<reason>)` lines.
|
|
52
|
+
not-decision-shaped, D unparseable, E superseded-frontmatter, F outside-profile)` — plus
|
|
53
|
+
per-file breakdown and per-anchor `anchor skipped: <name> (<reason>)` lines.
|
|
54
54
|
- **Lots of `unanchorable` + you passed an absolute path?** That's the wrong-cwd trap from
|
|
55
55
|
preflight — the command itself warns when ≥ half of anchor-attempted docs miss. Re-run
|
|
56
56
|
from the repo root with a relative path.
|
|
@@ -63,6 +63,11 @@ report closely:
|
|
|
63
63
|
(Context/Decision/Status/... or Trigger/Design/...); narrative or table-structured docs
|
|
64
64
|
don't qualify (by design, for now) — record their content via
|
|
65
65
|
`sidegraph:record-decision` if it matters.
|
|
66
|
+
- **`N file(s) skipped: not valid UTF-8, re-save as UTF-8 to import:`** (printed last, with
|
|
67
|
+
the listed paths) — a file whose bytes aren't valid UTF-8 is skipped and named instead of
|
|
68
|
+
aborting the run. Re-save the listed file(s) as UTF-8 and re-run to import them. No
|
|
69
|
+
encoding is guessed on your behalf. A UTF-8 byte-order mark is fine: it is stripped and the
|
|
70
|
+
file imports, so it never appears in this list.
|
|
66
71
|
|
|
67
72
|
## Gate the real run on the human
|
|
68
73
|
|
|
@@ -145,6 +145,12 @@ def _report_ratify_policy_write(
|
|
|
145
145
|
which already know `value` (whatever they decided to write) before calling this."""
|
|
146
146
|
if result.outcome == "written":
|
|
147
147
|
print(f"wrote {rel_settings}: env.{RATIFY_POLICY_ENV_VAR}={value}")
|
|
148
|
+
# The MCP server reads the policy once, from the environment it started with; a
|
|
149
|
+
# server already running keeps proposing under the old value.
|
|
150
|
+
print(
|
|
151
|
+
" restart your Claude Code session so the Sidegraph MCP server picks it up: "
|
|
152
|
+
"a running server keeps the environment it started with"
|
|
153
|
+
)
|
|
148
154
|
elif result.outcome == "already_set":
|
|
149
155
|
print(
|
|
150
156
|
f"{rel_settings} already sets "
|
|
@@ -923,6 +929,16 @@ def _import_docs_mode(args: argparse.Namespace) -> int:
|
|
|
923
929
|
)
|
|
924
930
|
for fp, n in sorted(report.by_file().items()):
|
|
925
931
|
print(f" {fp}: {n}")
|
|
932
|
+
# D4 (design/superpowers/specs/2026-09-23-doc-import-encoding-design.md): printed
|
|
933
|
+
# LAST. The by_file lines share the block's two-space indent, so any printed after
|
|
934
|
+
# the block would read as more undecodable files.
|
|
935
|
+
if report.skipped_undecodable:
|
|
936
|
+
print(
|
|
937
|
+
f"{report.skipped_undecodable} file(s) skipped: not valid UTF-8, re-save as "
|
|
938
|
+
"UTF-8 to import:"
|
|
939
|
+
)
|
|
940
|
+
for fp in report.undecodable_files:
|
|
941
|
+
print(f" {fp}")
|
|
926
942
|
return 0
|
|
927
943
|
|
|
928
944
|
# Design D6: the count is added to the non-dry-run summary line only, only when the
|
|
@@ -954,6 +970,16 @@ def _import_docs_mode(args: argparse.Namespace) -> int:
|
|
|
954
970
|
f"{report.skipped_degenerate_parent} split parent(s) skipped as degenerate "
|
|
955
971
|
"(echoed context or empty choice) — children imported on their own"
|
|
956
972
|
)
|
|
973
|
+
# D4 (design/superpowers/specs/2026-09-23-doc-import-encoding-design.md): printed last
|
|
974
|
+
# on stdout, after the degenerate-parent line — the auto-ratify-failures loop below
|
|
975
|
+
# goes to stderr, so this stays the last stdout line either way.
|
|
976
|
+
if report.skipped_undecodable:
|
|
977
|
+
print(
|
|
978
|
+
f"{report.skipped_undecodable} file(s) skipped: not valid UTF-8, re-save as "
|
|
979
|
+
"UTF-8 to import:"
|
|
980
|
+
)
|
|
981
|
+
for fp in report.undecodable_files:
|
|
982
|
+
print(f" {fp}")
|
|
957
983
|
for entry in report.auto_ratify_failures:
|
|
958
984
|
print(f"auto-ratify failure: {entry}", file=sys.stderr)
|
|
959
985
|
return 0
|
|
@@ -290,11 +290,8 @@ class _DocDisposition:
|
|
|
290
290
|
class DocImportReport(BaseModel):
|
|
291
291
|
"""Counts (+ dry-run-only listing) for one ``import_docs`` run. Mirrors
|
|
292
292
|
``importer.ImportReport``'s shape, widened for doc-import's extra outcomes: a doc can
|
|
293
|
-
be *superseded* (edited since its last import) as well as freshly *imported*, and
|
|
294
|
-
be skipped for
|
|
295
|
-
unparseable) plus a fifth doc-import-only reason (superseded/deprecated frontmatter —
|
|
296
|
-
a history doc, never (re-)imported as live) and a sixth (a document TEMPLATE — see
|
|
297
|
-
``skipped_template``)."""
|
|
293
|
+
be *superseded* (edited since its last import) as well as freshly *imported*, and each
|
|
294
|
+
reason a document can be skipped for has its own ``skipped_*`` counter below."""
|
|
298
295
|
|
|
299
296
|
imported: int = 0
|
|
300
297
|
superseded: int = 0
|
|
@@ -332,6 +329,15 @@ class DocImportReport(BaseModel):
|
|
|
332
329
|
# `any_doc=True` was NOT passed and at least one enumerated file falls outside the
|
|
333
330
|
# profile's globs (the CLI's `--any-doc` flag restores today's no-filter behavior).
|
|
334
331
|
skipped_outside_profile: int = 0
|
|
332
|
+
# design/superpowers/specs/2026-09-23-doc-import-encoding-design.md D1/D2/D3: a file
|
|
333
|
+
# that passed the profile-glob check above but whose bytes are not valid `utf-8-sig`
|
|
334
|
+
# (plain UTF-8, plus a stripped BOM — no encoding guessing). The decode is wrapped in a
|
|
335
|
+
# narrow try/except right where it happens, AFTER the profile check, so the file is a
|
|
336
|
+
# named skip and the run continues instead of raising `UnicodeDecodeError` and aborting
|
|
337
|
+
# the whole import. Distinct from `skipped_unparseable` (decision-shaped but no usable
|
|
338
|
+
# `choice`): this file was never even decoded far enough to be parsed.
|
|
339
|
+
skipped_undecodable: int = 0
|
|
340
|
+
undecodable_files: list[str] = Field(default_factory=list) # on-disk rel_path, in order
|
|
335
341
|
# E3 (design note §7, review Major 4/Blocker N1): a split-produced parent that is
|
|
336
342
|
# never written because it is degenerate — either an echo of its own `context` (rule
|
|
337
343
|
# 1) or empty even after every fallback (rule 2, which previously discarded the whole
|
|
@@ -1645,7 +1651,18 @@ def import_docs(
|
|
|
1645
1651
|
|
|
1646
1652
|
source_bytes = Path(rel_path).read_bytes()
|
|
1647
1653
|
source_hash = hashlib.sha256(source_bytes).hexdigest()
|
|
1648
|
-
|
|
1654
|
+
# D1/D2 (design/superpowers/specs/2026-09-23-doc-import-encoding-design.md): decode
|
|
1655
|
+
# as utf-8-sig (plain UTF-8 plus a stripped BOM, never guessed) inside a narrow
|
|
1656
|
+
# try/except right where the decode happens — a file that fails is a named skip,
|
|
1657
|
+
# not an aborted run. D3: this sits AFTER the profile-scope check above, so an
|
|
1658
|
+
# out-of-profile file is still never even opened.
|
|
1659
|
+
try:
|
|
1660
|
+
decoded = source_bytes.decode("utf-8-sig")
|
|
1661
|
+
except UnicodeDecodeError:
|
|
1662
|
+
report.skipped_undecodable += 1
|
|
1663
|
+
report.undecodable_files.append(rel_path)
|
|
1664
|
+
continue
|
|
1665
|
+
raw_text = decoded.replace("\r\n", "\n").replace("\r", "\n")
|
|
1649
1666
|
# E2 (design note §6): the NORMALIZED path — not the on-disk `rel_path` — is what
|
|
1650
1667
|
# gets stamped into `context`/children's `effective_ref`/`provenance.ref` (via
|
|
1651
1668
|
# `DocWriteRequest.rel_path` below), so an unedited doc re-imported after an
|