python-docs-mcp-server 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. python_docs_mcp_server-0.3.0/.coderabbit.yaml +24 -0
  2. python_docs_mcp_server-0.3.0/.github/CODEOWNERS +49 -0
  3. python_docs_mcp_server-0.3.0/.github/ISSUE_TEMPLATE/autonomous-agent.yml +108 -0
  4. python_docs_mcp_server-0.3.0/.github/PULL_REQUEST_TEMPLATE/agent.md +42 -0
  5. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.github/RELEASE.md +1 -0
  6. python_docs_mcp_server-0.3.0/.planning/agent-context/adr-001-source-adapters.md +49 -0
  7. python_docs_mcp_server-0.3.0/.planning/agent-context/adr-006-serialization.md +55 -0
  8. python_docs_mcp_server-0.3.0/.planning/agent-context/cpython-source-sha-pin.md +78 -0
  9. python_docs_mcp_server-0.3.0/.planning/agent-context/pyyaml-safe-loader-audit.md +52 -0
  10. python_docs_mcp_server-0.3.0/.planning/agent-context/readme-glama-six-tool-refresh.md +54 -0
  11. python_docs_mcp_server-0.3.0/.planning/agent-context/zstd-cache-codec.md +71 -0
  12. python_docs_mcp_server-0.3.0/.planning/issues/v0.3.0/00-README.md +63 -0
  13. python_docs_mcp_server-0.3.0/.planning/issues/v0.3.0/01-zstd-cache-codec.md +83 -0
  14. python_docs_mcp_server-0.3.0/.planning/issues/v0.3.0/02-readme-glama-six-tool-refresh.md +59 -0
  15. python_docs_mcp_server-0.3.0/.planning/issues/v0.3.0/03-pyyaml-safe-loader-audit.md +50 -0
  16. python_docs_mcp_server-0.3.0/.planning/issues/v0.3.0/04-adr-006-serialization.md +91 -0
  17. python_docs_mcp_server-0.3.0/.planning/issues/v0.3.0/05-adr-001-source-adapters.md +76 -0
  18. python_docs_mcp_server-0.3.0/.planning/issues/v0.3.0/06-cpython-source-sha-pin.md +61 -0
  19. python_docs_mcp_server-0.3.0/AGENT-EXECUTION-PIPELINE.md +287 -0
  20. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/AGENTS.md +16 -0
  21. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/CHANGELOG.md +46 -0
  22. python_docs_mcp_server-0.3.0/OPENCLAW-FORGE-PROTOCOL.md +293 -0
  23. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/PKG-INFO +3 -2
  24. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/README.md +1 -1
  25. python_docs_mcp_server-0.3.0/STRATEGIC-ROADMAP-2026-05-29.md +271 -0
  26. python_docs_mcp_server-0.3.0/docs/architecture/ADR-001-source-adapters.md +128 -0
  27. python_docs_mcp_server-0.3.0/docs/architecture/ADR-006-serialization.md +87 -0
  28. python_docs_mcp_server-0.3.0/docs/architecture/YAML-TRUST-BOUNDARY.md +23 -0
  29. python_docs_mcp_server-0.3.0/glama.json +7 -0
  30. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/pyproject.toml +2 -1
  31. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/server.json +2 -2
  32. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/__main__.py +35 -1
  33. python_docs_mcp_server-0.3.0/src/mcp_server_python_docs/cache/__init__.py +1 -0
  34. python_docs_mcp_server-0.3.0/src/mcp_server_python_docs/cache/codec.py +114 -0
  35. python_docs_mcp_server-0.3.0/src/mcp_server_python_docs/ingestion/cpython_versions.py +53 -0
  36. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/ingestion/sphinx_json.py +21 -1
  37. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/services/persistent_cache.py +35 -7
  38. python_docs_mcp_server-0.3.0/tests/cache/__init__.py +1 -0
  39. python_docs_mcp_server-0.3.0/tests/cache/test_codec.py +49 -0
  40. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_ingestion.py +52 -1
  41. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_mcp_get_docs_cache_smoke.py +9 -10
  42. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_persistent_docs_cache.py +71 -1
  43. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_stdio_smoke.py +82 -68
  44. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_synonyms.py +44 -0
  45. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/uv.lock +60 -1
  46. python_docs_mcp_server-0.2.0/glama.json +0 -7
  47. python_docs_mcp_server-0.2.0/src/mcp_server_python_docs/ingestion/cpython_versions.py +0 -32
  48. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.cursorignore +0 -0
  49. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.github/INTEGRATION-TEST.md +0 -0
  50. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.github/TEST-STRATEGY.md +0 -0
  51. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.github/dependabot.yml +0 -0
  52. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.github/workflows/ci.yml +0 -0
  53. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.github/workflows/codeql.yml +0 -0
  54. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.github/workflows/e2e.yml +0 -0
  55. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.github/workflows/release.yml +0 -0
  56. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.github/workflows/scorecard.yml +0 -0
  57. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.github/workflows/security.yml +0 -0
  58. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.gitignore +0 -0
  59. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/POSITIONING.md +0 -0
  60. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/ROADMAP.md +0 -0
  61. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-01-data-shape-spike-PLAN.md +0 -0
  62. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-01-data-shape-spike-SUMMARY.md +0 -0
  63. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-02-result-models-PLAN.md +0 -0
  64. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-02-result-models-SUMMARY.md +0 -0
  65. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-03-compare-service-PLAN.md +0 -0
  66. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-03-compare-service-SUMMARY.md +0 -0
  67. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-04-mcp-tool-wiring-PLAN.md +0 -0
  68. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-04-mcp-tool-wiring-SUMMARY.md +0 -0
  69. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-05-user-facing-docs-PLAN.md +0 -0
  70. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-05-user-facing-docs-SUMMARY.md +0 -0
  71. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-CONTEXT.md +0 -0
  72. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-REVIEW.md +0 -0
  73. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/09-compare-versions/09-VERIFICATION.md +0 -0
  74. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/10-whatsnew/10-CONTEXT.md +0 -0
  75. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/.planning/phases/11-detect-venv/11-CONTEXT.md +0 -0
  76. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/CLAUDE.md +0 -0
  77. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/CONTRIBUTING.md +0 -0
  78. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/LICENSE +0 -0
  79. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/SECURITY.md +0 -0
  80. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/__init__.py +0 -0
  81. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/app_context.py +0 -0
  82. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/data/synonyms.yaml +0 -0
  83. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/detection.py +0 -0
  84. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/diagnostics.py +0 -0
  85. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/errors.py +0 -0
  86. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/ingestion/__init__.py +0 -0
  87. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/ingestion/inventory.py +0 -0
  88. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/ingestion/publish.py +0 -0
  89. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/models.py +0 -0
  90. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/py.typed +0 -0
  91. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/retrieval/__init__.py +0 -0
  92. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/retrieval/budget.py +0 -0
  93. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/retrieval/query.py +0 -0
  94. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/retrieval/ranker.py +0 -0
  95. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/server.py +0 -0
  96. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/services/__init__.py +0 -0
  97. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/services/cache.py +0 -0
  98. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/services/compare.py +0 -0
  99. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/services/content.py +0 -0
  100. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/services/observability.py +0 -0
  101. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/services/package_docs.py +0 -0
  102. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/services/search.py +0 -0
  103. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/services/version.py +0 -0
  104. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/services/version_resolution.py +0 -0
  105. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/storage/__init__.py +0 -0
  106. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/storage/db.py +0 -0
  107. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/src/mcp_server_python_docs/storage/schema.sql +0 -0
  108. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/__init__.py +0 -0
  109. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/conftest.py +0 -0
  110. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/fixtures/retrieval_regression_cases.json +0 -0
  111. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/fixtures/sample_broken.fjson +0 -0
  112. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/fixtures/sample_library.fjson +0 -0
  113. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/fixtures/schema-get_docs-input.json +0 -0
  114. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/fixtures/schema-get_docs-output.json +0 -0
  115. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/fixtures/schema-list_versions-output.json +0 -0
  116. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/fixtures/schema-search_docs-input.json +0 -0
  117. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/fixtures/schema-search_docs-output.json +0 -0
  118. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_ci_workflows.py +0 -0
  119. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_compare_versions.py +0 -0
  120. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_compare_versions_spike.py +0 -0
  121. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_detection.py +0 -0
  122. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_doctor.py +0 -0
  123. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_multi_version.py +0 -0
  124. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_package_docs.py +0 -0
  125. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_packaging.py +0 -0
  126. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_phase1_integration.py +0 -0
  127. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_publish.py +0 -0
  128. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_retrieval.py +0 -0
  129. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_retrieval_regression.py +0 -0
  130. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_schema.py +0 -0
  131. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_schema_snapshot.py +0 -0
  132. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_services.py +0 -0
  133. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_stability.py +0 -0
  134. {python_docs_mcp_server-0.2.0 → python_docs_mcp_server-0.3.0}/tests/test_stdio_hygiene.py +0 -0
@@ -0,0 +1,24 @@
1
+ # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
2
+ language: "en-US"
3
+
4
+ reviews:
5
+ profile: "chill"
6
+ request_changes_workflow: false
7
+ high_level_summary: true
8
+ review_status: true
9
+ path_filters:
10
+ - "src/**"
11
+ - "tests/**"
12
+ path_instructions:
13
+ - path: "src/**"
14
+ instructions: |
15
+ Focus review on correctness, MCP tool behavior, runtime compatibility,
16
+ cache/index compatibility, packaging impact, and security boundaries.
17
+ Avoid comments about planning docs, release docs, or repository process
18
+ unless the changed source code makes those docs materially inaccurate.
19
+ - path: "tests/**"
20
+ instructions: |
21
+ Focus review on meaningful assertions, regression coverage, fixture
22
+ correctness, deterministic behavior, and avoiding network- or
23
+ environment-dependent tests unless the test is explicitly marked as an
24
+ integration smoke test.
@@ -0,0 +1,49 @@
1
+ # CODEOWNERS — requests maintainer visibility on forbidden-territory paths.
2
+ #
3
+ # Source of truth: AGENT-EXECUTION-PIPELINE.md §2 (Forbidden Territory),
4
+ # required by §10 (Pre-flight Checklist).
5
+ #
6
+ # For these rules to be ENFORCED, branch protection on `main` must enable
7
+ # "Require review from Code Owners". CODEOWNERS alone only requests review;
8
+ # branch protection only blocks merge when review rules are enabled.
9
+ #
10
+ # Autonomous agents may NOT modify these paths without explicit Vision approval
11
+ # (pipeline §2). Any agent PR touching them must add the `supervisor-review`
12
+ # label and stop short of self-merging (pipeline §7).
13
+
14
+ # --- Project identity, dependencies, classifiers (only `version` is agent-editable) ---
15
+ /pyproject.toml @ayhammouda
16
+
17
+ # --- Permanent commitments and trust posture ---
18
+ /LICENSE @ayhammouda
19
+ /SECURITY.md @ayhammouda
20
+
21
+ # --- Load-bearing brand assets ---
22
+ /README.md @ayhammouda
23
+ /.planning/POSITIONING.md @ayhammouda
24
+
25
+ # --- Release history (adding entries is fine; rewriting history is not) ---
26
+ /CHANGELOG.md @ayhammouda
27
+
28
+ # --- CI/CD and supply chain (release path especially) ---
29
+ # The single /.github/ rule covers workflows and release.yml. Last-matching-
30
+ # pattern wins in CODEOWNERS — adding narrower entries with the same owner
31
+ # below would be no-ops and would silently *override* this rule if a different
32
+ # owner is ever added here, so we keep ownership of /.github/ uniform.
33
+ /.github/ @ayhammouda
34
+
35
+ # --- Index schema and migrations (rebuilds existing user indexes) ---
36
+ # NOTE: the retrieved-docs *cache* table lives in
37
+ # src/mcp_server_python_docs/services/persistent_cache.py and is NOT covered
38
+ # here — it is best-effort, fingerprint-scoped, and agent-editable per
39
+ # decision 5.7. Only the canonical *index* schema is forbidden territory.
40
+ **/storage/schema.sql @ayhammouda
41
+ **/migrations/ @ayhammouda
42
+
43
+ # --- Archival roadmap history ---
44
+ /.planning/ROADMAP.md @ayhammouda
45
+
46
+ # --- Governing policy + strategy documents ---
47
+ /AGENT-EXECUTION-PIPELINE.md @ayhammouda
48
+ /OPENCLAW-FORGE-PROTOCOL.md @ayhammouda
49
+ /STRATEGIC-ROADMAP-2026-05-29.md @ayhammouda
@@ -0,0 +1,108 @@
1
+ name: Autonomous Agent Task
2
+ description: A task spec scoped for unattended execution by an autonomous coding agent (Claude Code or similar).
3
+ title: "[vX.Y.Z] <scope> — <verb> <thing>"
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ This template enforces the issue structure required by
9
+ `AGENT-EXECUTION-PIPELINE.md` §3 (in the repo root). An issue missing
10
+ any required section is **not** agent-ready and will not pass the §10
11
+ pre-flight checklist. Do not apply the `agent-ready` label from this
12
+ template; a maintainer applies it only after reading the completed
13
+ issue end-to-end. Read the pipeline doc and
14
+ `STRATEGIC-ROADMAP-2026-05-29.md` before filling this out.
15
+ - type: textarea
16
+ id: context
17
+ attributes:
18
+ label: Context (self-containment)
19
+ description: Link to the per-issue context file, this pipeline doc, the roadmap, any relevant ADR or `.planning/phases/0X-*` directory, and prior related issues.
20
+ value: |
21
+ - Per-issue context file: `.planning/agent-context/<issue-slug>.md` (read this first)
22
+ - Pipeline: `AGENT-EXECUTION-PIPELINE.md`
23
+ - Roadmap: `STRATEGIC-ROADMAP-2026-05-29.md` §<section>
24
+ - Related issues:
25
+ validations:
26
+ required: true
27
+ - type: textarea
28
+ id: goal
29
+ attributes:
30
+ label: Goal (one sentence)
31
+ description: The single outcome that counts as success.
32
+ validations:
33
+ required: true
34
+ - type: textarea
35
+ id: acceptance
36
+ attributes:
37
+ label: Acceptance criteria (testable checkbox list)
38
+ description: Each criterion must be testable, atomic, achievable without touching forbidden territory, and verifiable in <5 minutes (pipeline §4). Prefer exact commands and expected output.
39
+ value: |
40
+ - [ ] `<exact command>` <expected result>
41
+ - [ ] `<exact command>` <expected result>
42
+ validations:
43
+ required: true
44
+ - type: textarea
45
+ id: scope
46
+ attributes:
47
+ label: Scope boundaries
48
+ description: Explicit In scope / Out of scope. Out-of-scope work is a stop-and-comment trigger, never silent expansion.
49
+ value: |
50
+ **In scope:**
51
+ -
52
+
53
+ **Out of scope:**
54
+ -
55
+ validations:
56
+ required: true
57
+ - type: textarea
58
+ id: forbidden
59
+ attributes:
60
+ label: Forbidden-territory reminders
61
+ description: Repeat the AGENT-EXECUTION-PIPELINE.md §2 items relevant to THIS issue. If the task appears to require touching any of them, stop and comment.
62
+ validations:
63
+ required: true
64
+ - type: textarea
65
+ id: validation
66
+ attributes:
67
+ label: Validation commands (pipeline §5 gate)
68
+ description: The exact canonical gate, in order, plus any change-type-specific gates. Must pass before any PR is opened.
69
+ value: |
70
+ ```bash
71
+ uv run ruff check src/ tests/
72
+ uv run pyright src/
73
+ uv run pytest --tb=short -q
74
+ uv run python-docs-mcp-server doctor
75
+ ```
76
+ validations:
77
+ required: true
78
+ - type: textarea
79
+ id: pr-and-recovery
80
+ attributes:
81
+ label: PR requirements & recovery
82
+ description: What the PR description must include (pipeline §6) and where to go if blocked (pipeline §8).
83
+ value: |
84
+ - PR title matches this issue title verbatim; body uses
85
+ `.github/PULL_REQUEST_TEMPLATE/agent.md`.
86
+ - Branch: `agent/<issue-number>-<kebab-summary>`.
87
+ - If blocked: stop, write `WORKING-NOTES.md` on the branch, comment on
88
+ this issue per pipeline §8. **No PR and no silent scope expansion.**
89
+ validations:
90
+ required: true
91
+ - type: input
92
+ id: effort
93
+ attributes:
94
+ label: Effort estimate (hours)
95
+ description: Rough hours. Agent must bail and escalate if work exceeds 2× this estimate (pipeline §8).
96
+ validations:
97
+ required: true
98
+ - type: checkboxes
99
+ id: acknowledgements
100
+ attributes:
101
+ label: Agent acknowledgements
102
+ options:
103
+ - label: I will work on a branch, never on `main`, and will not self-merge.
104
+ required: true
105
+ - label: I will stop and comment rather than silently expand scope or touch forbidden territory.
106
+ required: true
107
+ - label: I will add `supervisor-review` if any pipeline §7 trigger fires.
108
+ required: true
@@ -0,0 +1,42 @@
1
+ <!--
2
+ Autonomous-agent PR template. Enforces AGENT-EXECUTION-PIPELINE.md §6.
3
+ PR title MUST match the issue title verbatim. Never self-merge.
4
+ -->
5
+
6
+ Closes #<issue-number>
7
+
8
+ ## Acceptance criteria
9
+ <!-- Copy every criterion from the issue. Check the box only when satisfied,
10
+ and add one line of evidence (command + observed result) per item. -->
11
+ - [ ] <criterion 1> — <evidence>
12
+ - [ ] <criterion 2> — <evidence>
13
+
14
+ ## Validation gate output
15
+ <!-- Paste the tail of each gate command. All must be green before opening this PR. -->
16
+ ```text
17
+ $ uv run ruff check src/ tests/
18
+ $ uv run pyright src/
19
+ $ uv run pytest --tb=short -q
20
+ $ uv run python-docs-mcp-server doctor
21
+ ```
22
+ <!-- Plus any change-type-specific gates from pipeline §5 (stdio smoke,
23
+ validate-corpus, uv lock --check) that applied to this change. -->
24
+
25
+ ## CodeRabbit review
26
+ <!-- After CodeRabbit comments, summarize findings as:
27
+ - Blocking: <items or None>
28
+ - Follow-up: <items or None>
29
+ - False positive: <items or None>
30
+ If CodeRabbit has not run yet, write "Pending." Do not mark findings green
31
+ by silence. -->
32
+ Pending.
33
+
34
+ ## Why this approach
35
+ <!-- One paragraph max. If the issue fully prescribed the approach, say so.
36
+ If you cite a design choice NOT in the issue, that is a §7 trigger. -->
37
+
38
+ ## Why this triggered supervisor review
39
+ <!-- List any pipeline §7 triggers and explain each. If none, write "None."
40
+ If any fired: this PR is opened for supervisor review only; do not merge it yourself,
41
+ and ensure the `supervisor-review` label is applied. -->
42
+ None.
@@ -51,6 +51,7 @@ Replace `X.Y.Z` below with the version you are releasing (e.g. `0.1.7`). Complet
51
51
  ```
52
52
  Must report `✅ server.json is valid`. If validation fails, shorten `server.json` `description` on `main` before tagging (the `pyproject.toml` description is unbounded by this constraint and can stay longer).
53
53
  - [ ] Integration tests from `.github/INTEGRATION-TEST.md` are complete and signed off
54
+ - [ ] Refresh README `## Tools`, `glama.json`, and registry/version badges to match the current tool surface.
54
55
  - [ ] `Doctor` subcommand passes:
55
56
  ```bash
56
57
  uv run python-docs-mcp-server doctor
@@ -0,0 +1,49 @@
1
+ # Agent Context — ADR-001 (Source Adapters)
2
+
3
+ > One-read working context for issue `[v0.3.0] docs — write ADR-001 (Source Adapters)`.
4
+ > A **writing** task. Every claim must match the code — verify before you assert.
5
+
6
+ ## 1. Roadmap excerpts (the principles you are recording)
7
+
8
+ - **Principle 2.1:** Canonical source only. CPython at a pinned tag for stdlib
9
+ docs; PyPI metadata API for package URLs. No scraped mirrors. No third-party indexers.
10
+ - **Principle 2.2:** Offline-first *runtime*. No network access at query time.
11
+ - **Principle 2.7:** Layered design with stable contracts; the **source
12
+ connector** is layer 1 of 8 and is what makes the pattern cloneable.
13
+
14
+ ## 2. The two source adapters that exist today (describe these)
15
+
16
+ 1. **CPython documentation source** (`src/mcp_server_python_docs/ingestion/`):
17
+ - `cpython_versions.py` — pinned build targets (`CPYTHON_DOCS_BUILD_CONFIG`:
18
+ per-version `tag` + `sphinx_pin`). Five versions: 3.10–3.14.
19
+ - `__main__.py` `build-index` path — `git clone --depth 1 --branch <tag>` of
20
+ `python/cpython`, builds docs with `sphinx-build -b json` in a dedicated venv.
21
+ - `sphinx_json.py` — parses the Sphinx JSON output into the index; also loads
22
+ `synonyms.yaml`. `inventory.py` — parses `objects.inv` for exact symbol resolution.
23
+ 2. **PyPI metadata source** (`src/mcp_server_python_docs/services/package_docs.py`):
24
+ - Backs `lookup_package_docs`. A **controlled** PyPI metadata lookup
25
+ (`GET /pypi/<project>/json`) that returns only project/docs/homepage/source
26
+ URLs — not a generic web fetch, not scraped docs.
27
+
28
+ ## 3. The one documented exception to "offline-first"
29
+
30
+ - `lookup_package_docs` performs a network call to PyPI's metadata API. This is
31
+ **not** a docs-*query*-time call against the canonical stdlib index — it is a
32
+ controlled, narrowly-scoped metadata lookup. The ADR must state this exception
33
+ explicitly so the offline-first invariant (2.2) stays honest. (See README's
34
+ "Why not Context7" section and `SECURITY.md` scope for the existing framing.)
35
+
36
+ ## 4. Known pitfalls
37
+
38
+ - **Verify, don't assume.** Open each cited file and confirm the behavior before
39
+ writing it into the ADR. An ADR that misstates current behavior is worse than none.
40
+ - Don't document adapters that don't exist (Rust/Go) beyond a single "future
41
+ adopters clone this contract" sentence — that's the cloneability point, not a claim.
42
+ - No code, schema, or workflow changes — writing only.
43
+ - Keep it factual; "reference architecture" is not claimed externally (5.6).
44
+
45
+ ## 5. Decision log
46
+
47
+ - File path:
48
+ - Claims you verified against code (file:line):
49
+ - Anything ambiguous about the layer contract that you flagged for the maintainer:
@@ -0,0 +1,55 @@
1
+ # Agent Context — ADR-006 (Serialization)
2
+
3
+ > One-read working context for issue `[v0.3.0] docs — write ADR-006 (Serialization)`.
4
+ > This is a **writing** task. You are recording locked decisions, not making new ones.
5
+
6
+ ## 1. Roadmap excerpts (the decisions you are recording — verbatim)
7
+
8
+ - **Principle 2.5:** Wire format is explicit and pluggable on structured tools
9
+ only. Compact JSON default; TOON opt-in *if and only if* the empirical study
10
+ supports it. `get_docs` stays markdown. *Token economy is empirical, not architectural.*
11
+ - **Principle 2.7:** Layered design with stable contracts — eight layers, the
12
+ **serializer** being one of them.
13
+ - **Decision 5.3:** Storage stays SQLite + markdown. **TOON-as-storage killed.**
14
+ - **Decision 5.4:** Empirical Claude-tokenizer study **gates** the `format="toon"` decision.
15
+ - **Decision 5.5:** `format` parameter on `search_docs`, `list_versions`,
16
+ `compare_versions` **only**. JSON default; TOON opt-in. `get_docs` stays markdown.
17
+ - **Decision 5.8:** The study measures **client-side rewrap**, not just raw
18
+ payload tokens; reports tokens AND latency per tool family.
19
+
20
+ ## 2. Code touch-points (for accuracy — describe, do NOT change)
21
+
22
+ - Tool results are Pydantic models in `src/mcp_server_python_docs/models.py`
23
+ (e.g. `GetDocsResult`); tools live in `server.py` and return those models,
24
+ which FastMCP serializes. The "serializer layer" is the conceptual seam where
25
+ a structured result becomes a wire string — that's what the `format` parameter
26
+ will eventually parameterize. You are documenting that seam, not building it.
27
+ - `get_docs` returns markdown content (`GetDocsResult.content`) — this is why it
28
+ is carved out of the `format` parameter (markdown is already the canonical body).
29
+
30
+ ## 3. Pattern to follow
31
+
32
+ - There is no `docs/architecture/` ADR yet — you are establishing the house
33
+ style. Use the exact skeleton embedded in the issue. Keep it tight (1–2 pages).
34
+ - Number/name the file `docs/architecture/ADR-006-serialization.md` to match the
35
+ roadmap's ADR numbering (ADR-001 and ADR-006 are the first two written).
36
+
37
+ ## 4. Known pitfalls
38
+
39
+ - **Do not invent.** If you find yourself making a serialization choice that is
40
+ not in §2 above, that's a pipeline §7 trigger ("cites a design choice not in
41
+ the issue") — stop and comment.
42
+ - **Do not implement `format`.** That is v0.3.x and is gated by the study.
43
+ - Don't claim a TOON token win — the study hasn't run. The ADR records that TOON
44
+ is *opt-in and gated*, with the bar being "win holds after client rewrap" (5.8).
45
+ - "Reference architecture" is **not** claimed externally (decision 5.6) — keep
46
+ the ADR factual, not promotional.
47
+
48
+ ## 5. Decision log
49
+
50
+ - Final file path: `docs/architecture/ADR-006-serialization.md`
51
+ - Any wording you were unsure mapped to a locked decision (and how you resolved it):
52
+ none; the ADR records only roadmap principles 2.5 and 2.7 plus decisions
53
+ 5.3, 5.4, 5.5, and 5.8.
54
+ - Open follow-ups: link the ADR to the v0.3.0 TOKEN-STUDY.md once that study
55
+ exists.
@@ -0,0 +1,78 @@
1
+ # Agent Context — CPython source SHA pin
2
+
3
+ > One-read working context for issue `[v0.3.0] ingestion — pin CPython source by commit SHA`.
4
+ > PARTIAL issue: you do the pin + verification; Vision handles the SECURITY.md prose.
5
+
6
+ ## 1. Roadmap excerpt
7
+
8
+ > **Build-time supply-chain hardening** (roadmap §4, v0.3.0): Pin CPython source
9
+ > by SHA, not by tag. Document the threat model in SECURITY.md (the `build-index`
10
+ > CPython clone is the largest non-runtime attack surface). Verify Sphinx-build
11
+ > environment isolation.
12
+ >
13
+ > **Decision 5.10 (locked):** Build-time supply chain (the `build-index` CPython
14
+ > clone) is an explicit risk area; threat model documented in SECURITY.md;
15
+ > CPython source pinned by SHA.
16
+
17
+ ## 2. Code touch-points
18
+
19
+ - `src/mcp_server_python_docs/ingestion/cpython_versions.py`
20
+ - `CPythonDocsBuildConfig(TypedDict)` — add `sha: str`.
21
+ - `CPYTHON_DOCS_BUILD_CONFIG` — five entries, currently `{"tag": ..., "sphinx_pin": ...}`:
22
+ `3.10→v3.10.20`, `3.11→v3.11.15`, `3.12→v3.12.13`, `3.13→v3.13.13`, `3.14→v3.14.4`.
23
+ Add the resolved SHA to each. Resolve with:
24
+ `git ls-remote https://github.com/python/cpython.git refs/tags/<tag>`
25
+ (use the dereferenced commit — the `<tag>^{}` line — not the annotated-tag object).
26
+ - `src/mcp_server_python_docs/__main__.py:210–226` — the clone:
27
+ `git clone --depth 1 --branch config["tag"] https://github.com/python/cpython.git <clone_dir>`.
28
+ After it, add: `rev = git -C <clone_dir> rev-parse HEAD`; if `rev != config["sha"]`,
29
+ log a clear error and **abort this version's build** (raise / skip-with-failure —
30
+ match the existing error-handling style in this function; do not silently continue).
31
+ - `tests/test_ingestion.py:53` — existing assertion
32
+ `config["tag"].startswith(f"v{version}.")`. Add a sibling assertion that
33
+ `config["sha"]` matches `^[0-9a-f]{40}$`.
34
+
35
+ ## 3. Patterns to follow
36
+
37
+ - `tests/test_ingestion.py` iterates `CPYTHON_DOCS_BUILD_CONFIG.items()` for the
38
+ tag assertion — extend that same loop for the SHA assertion. No new fixtures.
39
+ - The clone block already uses `subprocess.run([...], check=True, capture_output=True, text=True)`
40
+ — reuse that idiom for the `rev-parse` call.
41
+
42
+ ## 4. Known pitfalls
43
+
44
+ - **`--branch <tag>` cannot take a raw SHA** on a shallow clone against GitHub by
45
+ default. Keep the tag-based shallow fetch; make the **SHA a post-clone
46
+ verification gate**, not the fetch ref. That is the integrity win: a moved/re-tagged
47
+ tag now fails the build instead of silently changing canonical content.
48
+ - Use the **dereferenced commit SHA** (peeled tag), not the annotated tag object's
49
+ own SHA — `rev-parse HEAD` after checkout gives the commit; match that.
50
+ - **Do not edit `SECURITY.md`** (forbidden). Draft the threat-model paragraph in
51
+ the PR body + decision log below for Vision to apply.
52
+ - A full `build-index` clones over the network and takes minutes — do not gate the
53
+ PR on it. The unit tests cover the config + verification logic offline.
54
+ - Don't bump any tag to a newer CPython point release; pin the SHA of the
55
+ **current** tag only.
56
+
57
+ ## 5. Decision log
58
+
59
+ - Resolved SHAs (tag → 40-hex commit), one line each:
60
+ - 3.10 / v3.10.20 → 842e987df856a5d4db37933c62a3456930a19092
61
+ - 3.11 / v3.11.15 → 2340a037f7450e70fccfe411e6531afb4d57a312
62
+ - 3.12 / v3.12.13 → 3bb231a6a5dc02b95658877318bf61501a7209e9
63
+ - 3.13 / v3.13.13 → 01104ce1beb3135c2e0c01ec835b994c1f55a1c0
64
+ - 3.14 / v3.14.4 → 23116f998f6789d8c2fbe5ed5b8146854c8c2a4f
65
+ - Where/how the verification aborts on mismatch: after the shallow
66
+ tag-based clone in `build-index`, `git -C <clone_dir> rev-parse HEAD` is
67
+ compared to the authoritative config SHA. A mismatch logs the version, tag,
68
+ actual SHA, and expected SHA, then raises `SystemExit(1)` before Sphinx setup
69
+ or content ingestion can proceed.
70
+ - **Draft SECURITY.md threat-model paragraph (for Vision to apply):**
71
+ > The largest build-time supply-chain input is the `build-index` clone of the
72
+ > upstream CPython repository, which provides the source tree used to generate
73
+ > canonical documentation content. Each supported CPython docs release is pinned
74
+ > to the exact commit SHA that its human-readable release tag currently resolves
75
+ > to; the tag is retained for operator readability, but the SHA is the
76
+ > authoritative integrity anchor. If a tag is reissued, moved, or otherwise
77
+ > resolves to different source content, the build fails before Sphinx setup or
78
+ > content ingestion rather than silently publishing changed documentation.
@@ -0,0 +1,52 @@
1
+ # Agent Context — PyYAML safe-loader audit
2
+
3
+ > One-read working context for issue `[v0.3.0] security — audit and document PyYAML safe-loader discipline`.
4
+
5
+ ## 1. Roadmap excerpt
6
+
7
+ > **PyYAML safe-loader audit** (roadmap §4, v0.3.0): `synonyms.yaml` is loaded at
8
+ > startup; confirm only `yaml.safe_load` is used; document the trust boundary.
9
+ >
10
+ > **Decision 5.11 (locked):** PyYAML safe-loader-only discipline; `synonyms.yaml`
11
+ > is the only YAML input and is packaged with the wheel.
12
+
13
+ ## 2. Code touch-points (already audited for you — verify, then lock in)
14
+
15
+ - `src/mcp_server_python_docs/server.py:54–57` — loads `data/synonyms.yaml` via
16
+ `importlib.resources` and `yaml.safe_load(path.read_text())`. ✅ safe.
17
+ - `src/mcp_server_python_docs/ingestion/sphinx_json.py:595–603` — loads the same
18
+ file via `importlib.resources` + `yaml.safe_load`, then type-checks it is a
19
+ mapping. ✅ safe.
20
+ - `src/mcp_server_python_docs/data/synonyms.yaml` — the only YAML data input;
21
+ packaged with the wheel.
22
+ - No other `yaml.load(` / `yaml.unsafe_load(` / custom-`Loader=` call sites were
23
+ found in `src/`. Your job is to **prove** this with a regression test, not just
24
+ assert it.
25
+
26
+ ## 3. Patterns to follow
27
+
28
+ - `tests/test_synonyms.py` already exists — add the discipline test there.
29
+ - A clean way to assert the discipline: walk `src/` `.py` files and fail if any
30
+ line matches `yaml.load(` or `yaml.unsafe_load(` or `Loader=` (excluding
31
+ `SafeLoader`). Keep it simple and fast; no new deps.
32
+ - `tests/test_packaging.py` already verifies `synonyms.yaml` ships in the wheel —
33
+ reference it; you don't need to duplicate that.
34
+
35
+ ## 4. Known pitfalls
36
+
37
+ - **Do not edit `SECURITY.md`** (forbidden). Capture the trust-boundary write-up
38
+ in a new `docs/architecture/YAML-TRUST-BOUNDARY.md` and recommend SECURITY.md
39
+ wording for Vision.
40
+ - The two `safe_load` sites both also exist as `.pyc` in `__pycache__`; grep
41
+ source dirs only (`src/`, `tests/`), not `__pycache__`.
42
+ - If the codebase is already clean (expected), the deliverable is the **lock-in**
43
+ (regression test + doc note), not a code fix. Say so plainly in the PR.
44
+ - A literal `yaml.load(` string inside your *test* (as a pattern to search for)
45
+ is fine and expected — the test asserts it does not appear in non-test `src/`.
46
+
47
+ ## 5. Decision log
48
+
49
+ - Audit result (clean / findings):
50
+ - Regression test name + what it scans:
51
+ - Trust-boundary doc location:
52
+ - Recommended SECURITY.md wording (for Vision):
@@ -0,0 +1,54 @@
1
+ # Agent Context — README / glama 6-tool refresh
2
+
3
+ > One-read working context for issue `[v0.3.0] docs — refresh public surfaces to the 6-tool surface`.
4
+
5
+ ## 1. Roadmap excerpt
6
+
7
+ > **README + PyPI + glama.json refresh** (roadmap §4, v0.3.0): Reflect the 6-tool
8
+ > surface including `compare_versions`. **Decision 5.9:** adopt as a release-cycle
9
+ > discipline going forward — every release updates the public-facing tool table.
10
+ > Roadmap §3 notes the surface "still lists 5 in some surfaces."
11
+
12
+ ## 2. Code / file touch-points
13
+
14
+ - **Tool order of truth:** `src/mcp_server_python_docs/server.py`, the `@mcp.tool`
15
+ declarations in this order: `search_docs` (≈297), `get_docs` (≈318),
16
+ `lookup_package_docs` (≈341), `list_versions` (≈358), `detect_python_version`
17
+ (≈372), `compare_versions` (≈394).
18
+ - `README.md`:
19
+ - `## Tools` section at **line ~178**: already a six-row table in the correct
20
+ order. Verify, don't churn it.
21
+ - **Stale badge near the top:** `MCP%20Registry-v0.1.4`. Current published
22
+ registry/PyPI version is **0.2.1**. This is the concrete fix and the only
23
+ allowed edit above the first install code block.
24
+ - Hero section = everything **above the first install code block** (~line 125)
25
+ — FORBIDDEN except the stale registry/version badge above.
26
+ - `glama.json`: `description` field (prose, no tool list today).
27
+ - `.github/RELEASE.md`: add one checklist line for decision 5.9.
28
+
29
+ ## 3. Patterns to follow
30
+
31
+ - `tests/test_packaging.py` asserts packaging consistency — run it; if you add a
32
+ surface, see whether a cheap assertion belongs there (optional, not required).
33
+ - Badge lines in `README.md` are markdown image links; match the existing style
34
+ when updating the version.
35
+
36
+ ## 4. Known pitfalls
37
+
38
+ - **False positive — do NOT "fix":** `.github/INTEGRATION-TEST.md:139` says
39
+ "all five versions". That is the **five Python versions (3.10–3.14)**, not five
40
+ tools. Leave it alone.
41
+ - **PyPI short description is forbidden.** It comes from `pyproject.toml`
42
+ `[project].description`. If it's stale, comment — do not edit `pyproject.toml`.
43
+ (The README *body* you edit *is* the PyPI long description on the next release,
44
+ which is fine; only the hero is off-limits.)
45
+ - `README.md`, `.github/RELEASE.md`, and `glama.json` are all CODEOWNERS-owned.
46
+ Your PR will request maintainer review by design — note it, don't fight it.
47
+ - Don't bump `server.json` / package versions here; that's release-managed.
48
+
49
+ ## 5. Decision log
50
+
51
+ - Badge: pinned to `0.2.1` vs made version-agnostic — which and why:
52
+ - Surfaces audited and their state (README Tools / glama / server.json):
53
+ - RELEASE.md checklist line added:
54
+ - Anything left for the maintainer (e.g. stale pyproject short description):
@@ -0,0 +1,71 @@
1
+ # Agent Context — zstd cache codec
2
+
3
+ > One-read working context for issue `[v0.3.0] cache — add zstd codec layer`.
4
+ > Everything you need is here; do not go fishing in `.planning/` archive material.
5
+
6
+ ## 1. Roadmap excerpt (the goal — do not re-derive)
7
+
8
+ > **Workstream J — app-level zstd cache compression** (roadmap §4, v0.3.0):
9
+ > Targets the retrieved-docs cache *value column only*. Trained dict on a
10
+ > representative `get_docs` corpus. Codec column for forward-compat. Expected
11
+ > ratio strong because zstd's dictionary mode is especially effective on small
12
+ > correlated records — exactly the cache-entry shape.
13
+ >
14
+ > **Decision 5.7 (locked):** App-level zstd on retrieved-docs cache, *no gate*.
15
+ > Versioned codec column for forward-compat.
16
+
17
+ ## 2. Code touch-points (file paths + symbols)
18
+
19
+ - `src/mcp_server_python_docs/services/persistent_cache.py`
20
+ - `retrieved_docs_cache` table — created inline with `CREATE TABLE IF NOT EXISTS` at **line ~47**. Columns today: `index_fingerprint, version, slug, anchor, max_chars, start_index, result_json TEXT, created_at`. PK is the first six columns.
21
+ - `put(...)` — **line ~118**, `INSERT OR REPLACE ... result_json` = `result.model_dump_json()`.
22
+ - `get(...)` — **line ~80**, `SELECT result_json ...` then `GetDocsResult.model_validate_json(row[0])`.
23
+ - This is **best-effort**: every read/write is wrapped in try/except and the cache disables cleanly (`self._conn = None`) on error. Preserve that posture.
24
+ - **New module:** `src/mcp_server_python_docs/cache/codec.py` (create the `cache/` package with `__init__.py`). Public API the pipeline §4 example expects:
25
+ - `list_supported() -> list[str]` → `['none', 'zstd', 'zstd-dict-v1']`
26
+ - `encode(text: str, codec: str, *, dictionary=None) -> bytes`, `decode(blob: bytes, codec: str, *, dictionary=None) -> str`.
27
+ - **Tests:** new dir `tests/cache/` with `__init__.py` and `test_codec.py`.
28
+
29
+ ## 3. Existing test patterns to follow
30
+
31
+ - `tests/test_persistent_docs_cache.py` shows the established cache-test idiom:
32
+ the `_cache(tmp_path, marker)` helper builds an index fingerprint file +
33
+ `PersistentDocsCache`, and `populated_db` (a fixture from `tests/conftest.py`)
34
+ provides a live SQLite index. Reuse this shape for the no-regression test.
35
+ - The "survives restart" test (`test_cache_survives_restart_and_miss_falls_back`)
36
+ is the exact pattern for your "value reads back identically after restart" criterion:
37
+ build a `PersistentDocsCache`, write, construct a *second* instance on the same
38
+ files, assert `hits == 1` and equality.
39
+ - Tests are plain `pytest` functions, `from __future__ import annotations`, type-annotated args. Match that.
40
+
41
+ ## 4. Known pitfalls
42
+
43
+ - **The cache table is NOT `storage/schema.sql`.** `schema.sql` is the canonical
44
+ *index* schema and is forbidden territory. The cache table is owned by
45
+ `persistent_cache.py` and is yours to evolve per 5.7. Do not confuse them.
46
+ - **Existing on-disk caches lack the new column.** `CREATE TABLE IF NOT EXISTS`
47
+ will *not* add a column to an existing table. Detect the column
48
+ (`PRAGMA table_info(retrieved_docs_cache)`) and `ALTER TABLE ... ADD COLUMN
49
+ compression TEXT NOT NULL DEFAULT 'none'` when missing, inside the same
50
+ try/except that already tolerates a broken cache.
51
+ - **Value column type.** `result_json` is `TEXT`. Compressed output is `bytes`.
52
+ Either store the blob in a new `BLOB` column and keep `result_json` for the
53
+ `'none'` path, or store all payloads as `BLOB` and record the codec. Simplest
54
+ forward-compatible design: keep `result_json` semantics for `'none'`, add a
55
+ `result_blob BLOB` for compressed codecs, and let `compression` select which
56
+ column to read. Document whichever you choose in the decision log below.
57
+ - **`zstandard` must already be importable** (maintainer pre-req). If
58
+ `import zstandard` fails, STOP and comment — do not edit `pyproject.toml`/`uv.lock`.
59
+ - **`zstd-dict-v1` has no production dictionary in this issue.** Make the codec
60
+ *work* only when an explicit dictionary object is supplied by tests. The
61
+ cache's default production codec is `'zstd'`. Shipping a trained dictionary
62
+ artifact is a separate, Vision-gated follow-up.
63
+ - Decode must dispatch off the stored `compression` value, never off the current
64
+ default — otherwise old `'none'` rows break the day the default flips.
65
+
66
+ ## 5. Decision log (fill this in as you work)
67
+
68
+ - Chosen value-storage layout (`result_blob` vs reuse `result_json`):
69
+ - How `zstd-dict-v1` round-trips in tests (dict training approach):
70
+ - Default production codec wired into `put()`:
71
+ - Anything you deferred or escalated: