amicus 0.1.0__tar.gz → 0.2.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 (432) hide show
  1. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/SKILL.md +6 -2
  2. {amicus-0.1.0 → amicus-0.2.0}/.claude-plugin/plugin.json +3 -3
  3. {amicus-0.1.0 → amicus-0.2.0}/.codex-plugin/plugin.json +3 -3
  4. {amicus-0.1.0 → amicus-0.2.0}/AGENTS.md +17 -8
  5. amicus-0.2.0/CHANGELOG.md +226 -0
  6. {amicus-0.1.0 → amicus-0.2.0}/PKG-INFO +16 -7
  7. {amicus-0.1.0 → amicus-0.2.0}/README.md +15 -6
  8. {amicus-0.1.0 → amicus-0.2.0}/docs/RELEASING.md +38 -6
  9. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0006-fingerprint-and-surface-digest.md +4 -1
  10. amicus-0.2.0/docs/adr/0015-mcp-json-pins-an-already-published-release.md +104 -0
  11. amicus-0.2.0/docs/adr/0016-skill-rules-are-a-complete-contract.md +75 -0
  12. amicus-0.2.0/docs/adr/0017-an-unreadable-machine-enum-falls-to-its-own-floor.md +69 -0
  13. amicus-0.2.0/docs/adr/0018-the-catalog-carries-a-ttl-and-resource-reads-do-not.md +94 -0
  14. {amicus-0.1.0 → amicus-0.2.0}/docs/superpowers/specs/2026-09-04-amicus-design.md +5 -2
  15. {amicus-0.1.0 → amicus-0.2.0}/pyproject.toml +1 -1
  16. {amicus-0.1.0 → amicus-0.2.0}/scripts/check_release_state.py +131 -10
  17. amicus-0.2.0/skills/collaborating-with-amicus/SKILL.md +254 -0
  18. amicus-0.2.0/skills/collaborating-with-amicus/references/active-workflows.md +119 -0
  19. amicus-0.2.0/skills/collaborating-with-amicus/references/choosing-a-backend.md +105 -0
  20. amicus-0.2.0/skills/collaborating-with-amicus/references/independent-attempt.md +108 -0
  21. amicus-0.2.0/skills/collaborating-with-amicus/references/options-and-errors.md +81 -0
  22. amicus-0.2.0/skills/collaborating-with-amicus/references/reading-results.md +139 -0
  23. amicus-0.2.0/skills/collaborating-with-amicus/references/review-revise.md +70 -0
  24. amicus-0.2.0/skills/collaborating-with-amicus/references/reviewing-a-returned-diff.md +119 -0
  25. amicus-0.2.0/skills/collaborating-with-amicus/references/server-down-fallback.md +104 -0
  26. amicus-0.2.0/skills/collaborating-with-amicus/references/sync-vs-async.md +67 -0
  27. {amicus-0.1.0 → amicus-0.2.0}/skills/collaborating-with-amicus/tests/scenarios.md +241 -24
  28. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/__init__.py +1 -1
  29. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/errors.py +4 -1
  30. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/jobs/delivery.py +10 -2
  31. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/jobs/lifecycle.py +17 -6
  32. amicus-0.2.0/src/amicus/obs.py +327 -0
  33. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/orchestration/finalize.py +85 -14
  34. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/orchestration/review.py +33 -0
  35. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/orchestration/workspace.py +5 -1
  36. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/schemas/fingerprint.py +6 -2
  37. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/schemas/params.py +23 -0
  38. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/schemas/results.py +63 -4
  39. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/server.py +78 -9
  40. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/tools/_guard.py +12 -5
  41. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/tools/_meta.py +26 -15
  42. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/tools/discovery.py +5 -4
  43. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/tools/jobs.py +5 -3
  44. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/tools/resources.py +3 -3
  45. {amicus-0.1.0 → amicus-0.2.0}/tests/fixtures/manifest_snapshot.all.json +213 -48
  46. {amicus-0.1.0 → amicus-0.2.0}/tests/fixtures/manifest_snapshot.claude.json +213 -48
  47. {amicus-0.1.0 → amicus-0.2.0}/tests/fixtures/manifest_snapshot.codex-kimi.json +213 -48
  48. {amicus-0.1.0 → amicus-0.2.0}/tests/fixtures/result_format_snapshot.json +185 -3
  49. {amicus-0.1.0 → amicus-0.2.0}/tests/fixtures/wire_shape_snapshot.json +14 -4
  50. {amicus-0.1.0 → amicus-0.2.0}/tests/test_async_tools.py +1 -1
  51. amicus-0.2.0/tests/test_cache_hints.py +215 -0
  52. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_golden_envelope.py +12 -4
  53. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codes.py +2 -2
  54. {amicus-0.1.0 → amicus-0.2.0}/tests/test_delivery.py +36 -0
  55. {amicus-0.1.0 → amicus-0.2.0}/tests/test_discovery.py +80 -5
  56. {amicus-0.1.0 → amicus-0.2.0}/tests/test_discovery_cost.py +27 -2
  57. amicus-0.2.0/tests/test_finalize.py +544 -0
  58. {amicus-0.1.0 → amicus-0.2.0}/tests/test_fingerprint.py +3 -3
  59. {amicus-0.1.0 → amicus-0.2.0}/tests/test_lifecycle.py +1 -1
  60. amicus-0.2.0/tests/test_log_redaction.py +579 -0
  61. {amicus-0.1.0 → amicus-0.2.0}/tests/test_manifest.py +84 -11
  62. {amicus-0.1.0 → amicus-0.2.0}/tests/test_meta.py +20 -3
  63. {amicus-0.1.0 → amicus-0.2.0}/tests/test_packaging.py +35 -12
  64. {amicus-0.1.0 → amicus-0.2.0}/tests/test_paid_tools.py +2 -1
  65. {amicus-0.1.0 → amicus-0.2.0}/tests/test_release_state.py +172 -3
  66. amicus-0.2.0/tests/test_skill_contract.py +119 -0
  67. amicus-0.2.0/tests/test_surface_honesty.py +104 -0
  68. {amicus-0.1.0 → amicus-0.2.0}/tests/test_workspace.py +5 -0
  69. {amicus-0.1.0 → amicus-0.2.0}/uv.lock +1 -1
  70. amicus-0.1.0/CHANGELOG.md +0 -33
  71. amicus-0.1.0/skills/collaborating-with-amicus/SKILL.md +0 -137
  72. amicus-0.1.0/skills/collaborating-with-amicus/references/choosing-a-backend.md +0 -51
  73. amicus-0.1.0/skills/collaborating-with-amicus/references/reviewing-a-returned-diff.md +0 -61
  74. amicus-0.1.0/skills/collaborating-with-amicus/references/sync-vs-async.md +0 -55
  75. amicus-0.1.0/src/amicus/obs.py +0 -51
  76. amicus-0.1.0/tests/test_finalize.py +0 -193
  77. amicus-0.1.0/tests/test_surface_honesty.py +0 -44
  78. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-docs/SKILL.md +0 -0
  79. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-docs/references/design-workflow.md +0 -0
  80. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-docs/references/docs-checklist.md +0 -0
  81. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-docs/references/examples.md +0 -0
  82. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-docs/references/review-workflow.md +0 -0
  83. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-docs/tests/scenarios.md +0 -0
  84. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/SKILL.md +0 -0
  85. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/decisions/001-github-fact-sheet.md +0 -0
  86. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/audit-workflow.md +0 -0
  87. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/config-checklist.md +0 -0
  88. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/examples/README.md +0 -0
  89. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/examples/codeowners.md +0 -0
  90. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/examples/harness-deny.md +0 -0
  91. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/examples/identity.md +0 -0
  92. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/examples/repo-files.md +0 -0
  93. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/examples/required-checks.md +0 -0
  94. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/examples/rulesets.md +0 -0
  95. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/examples/workflows.md +0 -0
  96. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/operating-playbook.md +0 -0
  97. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/setup-workflow.md +0 -0
  98. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/references/threat-model.md +0 -0
  99. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/tests/check_authority.py +0 -0
  100. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-github/tests/scenarios.md +0 -0
  101. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/SKILL.md +0 -0
  102. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/decisions/001-mcp-2026-07-28-rebase.md +0 -0
  103. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/decisions/002-machine-code-rename-rationale.md +0 -0
  104. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/decisions/003-offending-value-omission.md +0 -0
  105. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/decisions/004-ownership-boundaries.md +0 -0
  106. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/references/contract-checklist.md +0 -0
  107. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/references/design-workflow.md +0 -0
  108. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/references/examples.md +0 -0
  109. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/references/mcp-2025-11-25-compat.md +0 -0
  110. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/references/mcp-vs-cli.md +0 -0
  111. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/references/native-wire-shapes.md +0 -0
  112. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/references/review-workflow.md +0 -0
  113. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/references/vocabulary.md +0 -0
  114. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/check_fact_sync.py +0 -0
  115. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/check_rule_ids.py +0 -0
  116. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/check_stale_terms.py +0 -0
  117. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/fixtures/github_issues.json +0 -0
  118. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/fixtures/github_repo_resource.json +0 -0
  119. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/rule-ids.txt +0 -0
  120. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-baseline.md +0 -0
  121. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-outputschema-error.md +0 -0
  122. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-with-skill.md +0 -0
  123. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario2-baseline.md +0 -0
  124. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario2-with-skill.md +0 -0
  125. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario3-baseline.md +0 -0
  126. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario3-with-skill.md +0 -0
  127. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario4-baseline.md +0 -0
  128. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario4-with-skill.md +0 -0
  129. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario5-baseline.md +0 -0
  130. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario5-with-skill.md +0 -0
  131. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario6-baseline.md +0 -0
  132. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario6-with-skill.md +0 -0
  133. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario7-trigger.md +0 -0
  134. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario1-baseline.md +0 -0
  135. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario1-with-skill.md +0 -0
  136. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario3-baseline.md +0 -0
  137. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario3-with-skill.md +0 -0
  138. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario5-baseline.md +0 -0
  139. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario5-with-skill.md +0 -0
  140. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-30-scenario1-with-skill.md +0 -0
  141. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-30-scenario8-severity-calibration.md +0 -0
  142. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/scenarios.md +0 -0
  143. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/test_check_fact_sync.py +0 -0
  144. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/test_check_rule_ids.py +0 -0
  145. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/test_validate_fixture.py +0 -0
  146. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/agent-friendly-mcp/tests/validate_fixture.py +0 -0
  147. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/agents/openai.yaml +0 -0
  148. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/references/example-audit.md +0 -0
  149. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/rescore-2026-08-06/preregistration.md +0 -0
  150. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/rescore-2026-08-06/results.md +0 -0
  151. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario1-baseline.md +0 -0
  152. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario1-with-skill.md +0 -0
  153. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario2-baseline.md +0 -0
  154. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario2-with-skill.md +0 -0
  155. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario3-baseline.md +0 -0
  156. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario3-with-skill.md +0 -0
  157. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario4-baseline.md +0 -0
  158. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario4-with-skill.md +0 -0
  159. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario5-baseline.md +0 -0
  160. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario5-with-skill.md +0 -0
  161. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario6-baseline.md +0 -0
  162. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario6-with-skill.md +0 -0
  163. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario7-baseline.md +0 -0
  164. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario7-with-skill.md +0 -0
  165. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario8-baseline.md +0 -0
  166. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario8-with-skill.md +0 -0
  167. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario9-trigger.md +0 -0
  168. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-06-scenario1-with-skill.md +0 -0
  169. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-06-scenario6-with-skill.md +0 -0
  170. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-confirmation-r1-both-directions.md +0 -0
  171. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario1-with-skill.md +0 -0
  172. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario2-with-skill.md +0 -0
  173. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario5-with-skill.md +0 -0
  174. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario6-with-skill.md +0 -0
  175. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario7-with-skill.md +0 -0
  176. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario8-with-skill.md +0 -0
  177. {amicus-0.1.0 → amicus-0.2.0}/.agents/skills/separating-context-from-constraints/tests/scenarios.md +0 -0
  178. {amicus-0.1.0 → amicus-0.2.0}/.claude-plugin/marketplace.json +0 -0
  179. {amicus-0.1.0 → amicus-0.2.0}/.gitattributes +0 -0
  180. {amicus-0.1.0 → amicus-0.2.0}/.github/CODEOWNERS +0 -0
  181. {amicus-0.1.0 → amicus-0.2.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  182. {amicus-0.1.0 → amicus-0.2.0}/.github/dependabot.yml +0 -0
  183. {amicus-0.1.0 → amicus-0.2.0}/.github/workflows/ci.yml +0 -0
  184. {amicus-0.1.0 → amicus-0.2.0}/.github/workflows/codeql.yml +0 -0
  185. {amicus-0.1.0 → amicus-0.2.0}/.github/workflows/dependency-review.yml +0 -0
  186. {amicus-0.1.0 → amicus-0.2.0}/.github/workflows/publish.yml +0 -0
  187. {amicus-0.1.0 → amicus-0.2.0}/.github/workflows/test.yml +0 -0
  188. {amicus-0.1.0 → amicus-0.2.0}/.gitignore +0 -0
  189. {amicus-0.1.0 → amicus-0.2.0}/.mcp.json +0 -0
  190. {amicus-0.1.0 → amicus-0.2.0}/CLAUDE.md +0 -0
  191. {amicus-0.1.0 → amicus-0.2.0}/LICENSE +0 -0
  192. {amicus-0.1.0 → amicus-0.2.0}/commands/amicus/adversarial.md +0 -0
  193. {amicus-0.1.0 → amicus-0.2.0}/commands/amicus/consult.md +0 -0
  194. {amicus-0.1.0 → amicus-0.2.0}/commands/amicus/delegate.md +0 -0
  195. {amicus-0.1.0 → amicus-0.2.0}/commands/amicus/dry-run.md +0 -0
  196. {amicus-0.1.0 → amicus-0.2.0}/commands/amicus/jobs.md +0 -0
  197. {amicus-0.1.0 → amicus-0.2.0}/commands/amicus/review.md +0 -0
  198. {amicus-0.1.0 → amicus-0.2.0}/commands/amicus/status.md +0 -0
  199. {amicus-0.1.0 → amicus-0.2.0}/docs/2026-09-04-naming-and-scoping-notes.md +0 -0
  200. {amicus-0.1.0 → amicus-0.2.0}/docs/DEPRECATING-SIBLINGS.md +0 -0
  201. {amicus-0.1.0 → amicus-0.2.0}/docs/MIGRATION.md +0 -0
  202. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0001-annotations-follow-the-worst-enabled-backend.md +0 -0
  203. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0002-backend-options-is-a-closed-superset.md +0 -0
  204. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0003-workspace-resolution.md +0 -0
  205. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0004-tasks-and-jobs.md +0 -0
  206. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0005-error-envelope-and-repair-precedence.md +0 -0
  207. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0007-m1-codex-port-decisions.md +0 -0
  208. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0008-m2-jobs-surface-decisions.md +0 -0
  209. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0009-m3-kimi-port-decisions.md +0 -0
  210. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0010-m4-claude-port-decisions.md +0 -0
  211. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0011-m5-tasks-decisions.md +0 -0
  212. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0012-m6-packaging-decisions.md +0 -0
  213. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0013-proceed-without-trademark-clearance.md +0 -0
  214. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/0014-release-predicate-on-the-tag.md +0 -0
  215. {amicus-0.1.0 → amicus-0.2.0}/docs/adr/README.md +0 -0
  216. {amicus-0.1.0 → amicus-0.2.0}/docs/claude-help/2.1.263/FINDINGS.md +0 -0
  217. {amicus-0.1.0 → amicus-0.2.0}/docs/claude-help/2.1.263/claude-help.txt +0 -0
  218. {amicus-0.1.0 → amicus-0.2.0}/docs/claude-help/2.1.263/claude-version.txt +0 -0
  219. {amicus-0.1.0 → amicus-0.2.0}/docs/claude-help/2.1.263/envelope-shape.json +0 -0
  220. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/claude-code/2.1.263/FINDINGS.md +0 -0
  221. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/claude-code/2.1.263/connection.log +0 -0
  222. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/claude-code/2.1.263/host-output.json +0 -0
  223. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/codex/0.153.4/FINDINGS.md +0 -0
  224. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/codex/0.153.4/connection.log +0 -0
  225. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/codex/0.153.4/host-output.jsonl +0 -0
  226. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/notes.md +0 -0
  227. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/server.log +0 -0
  228. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/transcript.md +0 -0
  229. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/install-smoke/claude-code/2.1.263/notes.md +0 -0
  230. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/install-smoke/claude-code/2.1.263/server.log +0 -0
  231. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/install-smoke/claude-code/2.1.263/transcript.md +0 -0
  232. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/install-smoke/codex/0.153.4/notes.md +0 -0
  233. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/install-smoke/codex/0.153.4/server.log +0 -0
  234. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/install-smoke/codex/0.153.4/transcript.md +0 -0
  235. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/notes.md +0 -0
  236. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/server.log +0 -0
  237. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/transcript.md +0 -0
  238. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s6-old-text-new-grader/claude-code/2.1.263/notes.md +0 -0
  239. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s6-old-text-new-grader/claude-code/2.1.263/server.log +0 -0
  240. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s6-old-text-new-grader/claude-code/2.1.263/transcript.md +0 -0
  241. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/notes.md +0 -0
  242. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/server.log +0 -0
  243. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/transcript.md +0 -0
  244. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/notes.md +0 -0
  245. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/server.log +0 -0
  246. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/transcript.md +0 -0
  247. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/notes.md +0 -0
  248. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/server.log +0 -0
  249. {amicus-0.1.0 → amicus-0.2.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/transcript.md +0 -0
  250. {amicus-0.1.0 → amicus-0.2.0}/docs/kimi-help/0.41.0/FINDINGS.md +0 -0
  251. {amicus-0.1.0 → amicus-0.2.0}/docs/kimi-help/0.41.0/kimi-help.txt +0 -0
  252. {amicus-0.1.0 → amicus-0.2.0}/docs/kimi-help/0.41.0/kimi-version.txt +0 -0
  253. {amicus-0.1.0 → amicus-0.2.0}/docs/kimi-help/0.41.0/provider-list-shape.json +0 -0
  254. {amicus-0.1.0 → amicus-0.2.0}/docs/reviews/2026-09-07-agent-friendly-mcp-walk.md +0 -0
  255. {amicus-0.1.0 → amicus-0.2.0}/docs/superpowers/plans/2026-09-04-amicus-execution-model.md +0 -0
  256. {amicus-0.1.0 → amicus-0.2.0}/prek.toml +0 -0
  257. {amicus-0.1.0 → amicus-0.2.0}/scripts/capture_claude_differentials.py +0 -0
  258. {amicus-0.1.0 → amicus-0.2.0}/scripts/capture_codex_differentials.py +0 -0
  259. {amicus-0.1.0 → amicus-0.2.0}/scripts/capture_kimi_differentials.py +0 -0
  260. {amicus-0.1.0 → amicus-0.2.0}/scripts/check_commit_message.py +0 -0
  261. {amicus-0.1.0 → amicus-0.2.0}/scripts/check_github_actions_pinning.py +0 -0
  262. {amicus-0.1.0 → amicus-0.2.0}/scripts/record_live_gate_evidence.py +0 -0
  263. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/_worker.py +0 -0
  264. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/appstate.py +0 -0
  265. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/__init__.py +0 -0
  266. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/claude/__init__.py +0 -0
  267. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/claude/adapter.py +0 -0
  268. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/claude/adversarial.py +0 -0
  269. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/claude/binary.py +0 -0
  270. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/claude/cli.py +0 -0
  271. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/claude/config.py +0 -0
  272. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/claude/contract.py +0 -0
  273. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/claude/models.py +0 -0
  274. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/claude/normalize.py +0 -0
  275. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/claude/options.py +0 -0
  276. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/claude/status.py +0 -0
  277. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/codex/__init__.py +0 -0
  278. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/codex/adapter.py +0 -0
  279. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/codex/binary.py +0 -0
  280. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/codex/cli.py +0 -0
  281. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/codex/config.py +0 -0
  282. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/codex/contract.py +0 -0
  283. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/codex/models.py +0 -0
  284. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/codex/normalize.py +0 -0
  285. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/codex/options.py +0 -0
  286. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/codex/status.py +0 -0
  287. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/kimi/__init__.py +0 -0
  288. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/kimi/adapter.py +0 -0
  289. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/kimi/binary.py +0 -0
  290. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/kimi/cli.py +0 -0
  291. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/kimi/config.py +0 -0
  292. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/kimi/contract.py +0 -0
  293. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/kimi/models.py +0 -0
  294. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/kimi/normalize.py +0 -0
  295. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/kimi/options.py +0 -0
  296. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/backends/kimi/status.py +0 -0
  297. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/config/__init__.py +0 -0
  298. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/config/envspec.py +0 -0
  299. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/jobs/__init__.py +0 -0
  300. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/jobs/lookup.py +0 -0
  301. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/jobs/taskmap.py +0 -0
  302. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/manifest.py +0 -0
  303. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/middleware.py +0 -0
  304. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/orchestration/__init__.py +0 -0
  305. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/orchestration/isolation.py +0 -0
  306. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/orchestration/prompts.py +0 -0
  307. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/orchestration/run.py +0 -0
  308. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/packaging.py +0 -0
  309. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/plugin.py +0 -0
  310. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/py.typed +0 -0
  311. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/registry.py +0 -0
  312. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/request.py +0 -0
  313. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/result_format_snapshot.py +0 -0
  314. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/schemas/__init__.py +0 -0
  315. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/schemas/codes.py +0 -0
  316. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/schemas/envelope.py +0 -0
  317. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/schemas/field_policy.py +0 -0
  318. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/schemas/instructions.py +0 -0
  319. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/schemas/options.py +0 -0
  320. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/schemas/publish.py +0 -0
  321. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/schemas/structured.py +0 -0
  322. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/surface.py +0 -0
  323. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/tools/__init__.py +0 -0
  324. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/tools/_prepare.py +0 -0
  325. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/tools/_resolve.py +0 -0
  326. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/tools/consult.py +0 -0
  327. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/tools/delegate.py +0 -0
  328. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/tools/dry_run.py +0 -0
  329. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/tools/review.py +0 -0
  330. {amicus-0.1.0 → amicus-0.2.0}/src/amicus/wire_shape_snapshot.py +0 -0
  331. {amicus-0.1.0 → amicus-0.2.0}/tests/conftest.py +0 -0
  332. {amicus-0.1.0 → amicus-0.2.0}/tests/fixtures/claude_differentials.json +0 -0
  333. {amicus-0.1.0 → amicus-0.2.0}/tests/fixtures/claude_golden_envelope.json +0 -0
  334. {amicus-0.1.0 → amicus-0.2.0}/tests/fixtures/codex_differentials.json +0 -0
  335. {amicus-0.1.0 → amicus-0.2.0}/tests/fixtures/fakebackend/pyproject.toml +0 -0
  336. {amicus-0.1.0 → amicus-0.2.0}/tests/fixtures/fakebackend/src/fakebackend/__init__.py +0 -0
  337. {amicus-0.1.0 → amicus-0.2.0}/tests/fixtures/kimi_differentials.json +0 -0
  338. {amicus-0.1.0 → amicus-0.2.0}/tests/support/__init__.py +0 -0
  339. {amicus-0.1.0 → amicus-0.2.0}/tests/support/claudefixtures.py +0 -0
  340. {amicus-0.1.0 → amicus-0.2.0}/tests/support/codexfixtures.py +0 -0
  341. {amicus-0.1.0 → amicus-0.2.0}/tests/support/fake_claude.py +0 -0
  342. {amicus-0.1.0 → amicus-0.2.0}/tests/support/fake_codex.py +0 -0
  343. {amicus-0.1.0 → amicus-0.2.0}/tests/support/fake_kimi.py +0 -0
  344. {amicus-0.1.0 → amicus-0.2.0}/tests/support/fakeplugin.py +0 -0
  345. {amicus-0.1.0 → amicus-0.2.0}/tests/support/kimifixtures.py +0 -0
  346. {amicus-0.1.0 → amicus-0.2.0}/tests/test_adversarial.py +0 -0
  347. {amicus-0.1.0 → amicus-0.2.0}/tests/test_check_commit_message.py +0 -0
  348. {amicus-0.1.0 → amicus-0.2.0}/tests/test_check_github_actions_pinning.py +0 -0
  349. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_adapter.py +0 -0
  350. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_argv_differential.py +0 -0
  351. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_binary.py +0 -0
  352. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_cli.py +0 -0
  353. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_config.py +0 -0
  354. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_contract.py +0 -0
  355. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_live.py +0 -0
  356. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_models.py +0 -0
  357. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_normalize.py +0 -0
  358. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_plugin.py +0 -0
  359. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_result_differential.py +0 -0
  360. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_status.py +0 -0
  361. {amicus-0.1.0 → amicus-0.2.0}/tests/test_claude_sync_tools.py +0 -0
  362. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codex_adapter.py +0 -0
  363. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codex_argv_differential.py +0 -0
  364. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codex_binary.py +0 -0
  365. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codex_cli.py +0 -0
  366. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codex_config.py +0 -0
  367. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codex_contract.py +0 -0
  368. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codex_live.py +0 -0
  369. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codex_models.py +0 -0
  370. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codex_normalize.py +0 -0
  371. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codex_plugin.py +0 -0
  372. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codex_result_differential.py +0 -0
  373. {amicus-0.1.0 → amicus-0.2.0}/tests/test_codex_status.py +0 -0
  374. {amicus-0.1.0 → amicus-0.2.0}/tests/test_commands.py +0 -0
  375. {amicus-0.1.0 → amicus-0.2.0}/tests/test_config.py +0 -0
  376. {amicus-0.1.0 → amicus-0.2.0}/tests/test_conftest_guards.py +0 -0
  377. {amicus-0.1.0 → amicus-0.2.0}/tests/test_dry_run.py +0 -0
  378. {amicus-0.1.0 → amicus-0.2.0}/tests/test_envelope.py +0 -0
  379. {amicus-0.1.0 → amicus-0.2.0}/tests/test_envspec.py +0 -0
  380. {amicus-0.1.0 → amicus-0.2.0}/tests/test_errors.py +0 -0
  381. {amicus-0.1.0 → amicus-0.2.0}/tests/test_field_policy.py +0 -0
  382. {amicus-0.1.0 → amicus-0.2.0}/tests/test_guard.py +0 -0
  383. {amicus-0.1.0 → amicus-0.2.0}/tests/test_host_captures.py +0 -0
  384. {amicus-0.1.0 → amicus-0.2.0}/tests/test_import_contracts.py +0 -0
  385. {amicus-0.1.0 → amicus-0.2.0}/tests/test_instructions.py +0 -0
  386. {amicus-0.1.0 → amicus-0.2.0}/tests/test_isolation.py +0 -0
  387. {amicus-0.1.0 → amicus-0.2.0}/tests/test_job_durability.py +0 -0
  388. {amicus-0.1.0 → amicus-0.2.0}/tests/test_job_tools.py +0 -0
  389. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_adapter.py +0 -0
  390. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_argv_differential.py +0 -0
  391. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_binary.py +0 -0
  392. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_cli.py +0 -0
  393. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_config.py +0 -0
  394. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_contract.py +0 -0
  395. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_live.py +0 -0
  396. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_models.py +0 -0
  397. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_normalize.py +0 -0
  398. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_plugin.py +0 -0
  399. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_result_differential.py +0 -0
  400. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_status.py +0 -0
  401. {amicus-0.1.0 → amicus-0.2.0}/tests/test_kimi_sync_tools.py +0 -0
  402. {amicus-0.1.0 → amicus-0.2.0}/tests/test_live_gate_report.py +0 -0
  403. {amicus-0.1.0 → amicus-0.2.0}/tests/test_live_suite_hygiene.py +0 -0
  404. {amicus-0.1.0 → amicus-0.2.0}/tests/test_lookup.py +0 -0
  405. {amicus-0.1.0 → amicus-0.2.0}/tests/test_middleware.py +0 -0
  406. {amicus-0.1.0 → amicus-0.2.0}/tests/test_migration_doc.py +0 -0
  407. {amicus-0.1.0 → amicus-0.2.0}/tests/test_obs.py +0 -0
  408. {amicus-0.1.0 → amicus-0.2.0}/tests/test_options.py +0 -0
  409. {amicus-0.1.0 → amicus-0.2.0}/tests/test_params.py +0 -0
  410. {amicus-0.1.0 → amicus-0.2.0}/tests/test_plugin.py +0 -0
  411. {amicus-0.1.0 → amicus-0.2.0}/tests/test_prepare.py +0 -0
  412. {amicus-0.1.0 → amicus-0.2.0}/tests/test_prompts.py +0 -0
  413. {amicus-0.1.0 → amicus-0.2.0}/tests/test_publish.py +0 -0
  414. {amicus-0.1.0 → amicus-0.2.0}/tests/test_registry.py +0 -0
  415. {amicus-0.1.0 → amicus-0.2.0}/tests/test_release_evidence.py +0 -0
  416. {amicus-0.1.0 → amicus-0.2.0}/tests/test_request.py +0 -0
  417. {amicus-0.1.0 → amicus-0.2.0}/tests/test_resources.py +0 -0
  418. {amicus-0.1.0 → amicus-0.2.0}/tests/test_result_format.py +0 -0
  419. {amicus-0.1.0 → amicus-0.2.0}/tests/test_results.py +0 -0
  420. {amicus-0.1.0 → amicus-0.2.0}/tests/test_review.py +0 -0
  421. {amicus-0.1.0 → amicus-0.2.0}/tests/test_review_artifact.py +0 -0
  422. {amicus-0.1.0 → amicus-0.2.0}/tests/test_run.py +0 -0
  423. {amicus-0.1.0 → amicus-0.2.0}/tests/test_server.py +0 -0
  424. {amicus-0.1.0 → amicus-0.2.0}/tests/test_structured.py +0 -0
  425. {amicus-0.1.0 → amicus-0.2.0}/tests/test_surface.py +0 -0
  426. {amicus-0.1.0 → amicus-0.2.0}/tests/test_sync_tools.py +0 -0
  427. {amicus-0.1.0 → amicus-0.2.0}/tests/test_taskmap.py +0 -0
  428. {amicus-0.1.0 → amicus-0.2.0}/tests/test_tasks_client.py +0 -0
  429. {amicus-0.1.0 → amicus-0.2.0}/tests/test_tasks_spike.py +0 -0
  430. {amicus-0.1.0 → amicus-0.2.0}/tests/test_wheel_seam.py +0 -0
  431. {amicus-0.1.0 → amicus-0.2.0}/tests/test_wire_shape.py +0 -0
  432. {amicus-0.1.0 → amicus-0.2.0}/tests/test_worker.py +0 -0
@@ -1,8 +1,12 @@
1
1
  ---
2
- name: separating-context-from-constraints
3
2
  description: Use when auditing or reviewing a skill, system prompt, CLAUDE.md/AGENTS.md, MCP tool or resource description, slash-command prompt, or any document an AI agent consumes as instructions, to check that binding rules are separated from background context. Symptoms include rules buried mid-paragraph in narrative prose, hedged statements ("generally", "try to") that leave unclear whether they bind, untestable directives like "be concise", compound rules bundling several obligations, rule sections padded with explanation, and agents that follow a document's flavor text but miss its requirements. Produces findings with two-level severity and semantic-preserving suggested rewrites; does not score documents, analyze conflicts with parent instruction layers, or review general prose quality.
3
+ metadata:
4
+ github-path: separating-context-from-constraints
5
+ github-ref: refs/heads/main
6
+ github-repo: https://github.com/briandconnelly/skills
7
+ github-tree-sha: 967a99232de22bc967c12a7aefcf272cfe2fb938
8
+ name: separating-context-from-constraints
4
9
  ---
5
-
6
10
  # Separating Context from Constraints
7
11
 
8
12
  Audit agent-consumed instruction documents — skills, system prompts, CLAUDE.md/AGENTS.md, MCP tool and resource descriptions, slash-command prompts — for separation of binding rules from context.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "amicus",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "One MCP server for every second-opinion model: consult, review, and delegate with the backend as a parameter.",
5
- "author": { "name": "Brian Connelly" },
5
+ "author": { "name": "Brian Connelly", "url": "https://github.com/briandconnelly" },
6
6
  "homepage": "https://github.com/briandconnelly/amicus",
7
7
  "repository": "https://github.com/briandconnelly/amicus",
8
8
  "license": "MIT",
@@ -13,7 +13,7 @@
13
13
  "interface": {
14
14
  "displayName": "amicus",
15
15
  "shortDescription": "Consult, review, and delegate to Codex, Kimi, or Claude — one server, backend as a parameter.",
16
- "longDescription": "amicus gives Claude Code one tool surface for every second-opinion model. Pick the backend as a parameter instead of installing a server per model. Delegation runs in a throwaway git worktree and returns a reviewable diff that is never applied to your working tree. Long jobs run asynchronously with a job id you can poll, cancel, and recover. Enabling a backend that can write makes every tool carry that backend's approval annotations — see docs/MIGRATION.md.",
16
+ "longDescription": "amicus gives Claude Code one tool surface for every second-opinion model. Pick the backend as a parameter instead of installing a server per model. Delegation runs in a throwaway git worktree and returns a reviewable diff that is never applied to your working tree. Long jobs run asynchronously with a job id you can poll, cancel, and recover. Enabling a backend that can write makes every tool carry that backend's approval annotations — see https://github.com/briandconnelly/amicus/blob/main/docs/MIGRATION.md.",
17
17
  "developerName": "Brian Connelly",
18
18
  "category": "Developer Tools",
19
19
  "capabilities": ["MCP", "Skills"],
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "amicus",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "One MCP server for every second-opinion model: consult, review, and delegate with the backend as a parameter.",
5
- "author": { "name": "Brian Connelly" },
5
+ "author": { "name": "Brian Connelly", "url": "https://github.com/briandconnelly" },
6
6
  "homepage": "https://github.com/briandconnelly/amicus",
7
7
  "repository": "https://github.com/briandconnelly/amicus",
8
8
  "license": "MIT",
@@ -12,7 +12,7 @@
12
12
  "interface": {
13
13
  "displayName": "amicus (for Codex)",
14
14
  "shortDescription": "Consult, review, and delegate to Codex, Kimi, or Claude — one server, backend as a parameter.",
15
- "longDescription": "amicus gives Codex one tool surface for every second-opinion model. Pick the backend as a parameter instead of installing a server per model. Delegation runs in a throwaway git worktree and returns a reviewable diff that is never applied to your working tree. Long jobs run asynchronously with a job id you can poll, cancel, and recover. Enabling a backend that can write makes every tool carry that backend's approval annotations — see docs/MIGRATION.md.",
15
+ "longDescription": "amicus gives Codex one tool surface for every second-opinion model. Pick the backend as a parameter instead of installing a server per model. Delegation runs in a throwaway git worktree and returns a reviewable diff that is never applied to your working tree. Long jobs run asynchronously with a job id you can poll, cancel, and recover. Enabling a backend that can write makes every tool carry that backend's approval annotations — see https://github.com/briandconnelly/amicus/blob/main/docs/MIGRATION.md.",
16
16
  "developerName": "Brian Connelly",
17
17
  "category": "Developer Tools",
18
18
  "capabilities": ["MCP", "Skills"],
@@ -33,10 +33,11 @@ The rules bind; the context after them explains and points elsewhere.
33
33
  Prompt text that a test or capture script assembles entirely from its own literals is exempt, including the `build_*_prompt` output committed in `tests/fixtures/*_differentials.json`; it stays verbatim, because a differential must show what changed and a hash cannot.
34
34
  No exemption reaches text that was copied, derived or replayed from a prompt anyone sent: that stays bound however it is later stored or relabelled.
35
35
  19. Release in two PRs: the work lands with the version literals untouched, then a `chore(release):` PR moves them together and rolls `## [Unreleased]` in `CHANGELOG.md` into a dated section.
36
- The literals are `pyproject.toml`, `src/amicus/__init__.py`, `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json` and the `.mcp.json` tag pin.
36
+ The literals are `pyproject.toml`, `src/amicus/__init__.py`, `.claude-plugin/plugin.json` and `.codex-plugin/plugin.json`.
37
+ `.mcp.json`'s pin is NOT one of them; rule 24 governs it, and a release must not touch it.
37
38
  `uv.lock` mirrors the version rather than declaring it: regenerate it in that same PR with `uv lock`, or the `uv lock --check` hook fails.
38
39
  Only the maintainer merges that PR, and only the maintainer pushes the tag.
39
- Push the matching tag immediately after that merge, before any other work: the interval in which `main` names a tag that does not yet exist cannot be made zero, so closing it is the only task that may follow the merge.
40
+ Push the matching tag before any other work follows that merge: until it exists, `main` declares a version that has no release.
40
41
  20. Never push a `v*` tag unless the three live gates — `tests/test_codex_live.py`, `tests/test_kimi_live.py` and `tests/test_claude_live.py`, run under rule 5 — have all PASSED on that exact commit, with those passing outcomes recorded.
41
42
  The record is `.release-evidence/live-gates.json`, written by `scripts/record_live_gate_evidence.py`, naming that commit, each suite and its outcome; a terminal transcript or a recollection is not a record.
42
43
  A record showing a failed suite does not satisfy this rule; it is a reason not to tag.
@@ -46,6 +47,9 @@ The rules bind; the context after them explains and points elsewhere.
46
47
  Never move a release check into the `pypi` job: GitHub holds every step of an environment job behind that environment's required reviewer, so a check placed there runs only after the approval it exists to inform.
47
48
  23. Never describe the rule-20 record, in any document or output, as proof that the live gates ran.
48
49
  It is the maintainer's assertion, machine-checked for shape and for naming the tagged commit; the runs happen on the maintainer's machine and the record is written there.
50
+ 24. `.mcp.json`'s `--from` pin names a release that is already published, never the one being released, and it may never name a version newer than the one the tree declares.
51
+ A release PR under rule 19 leaves it untouched; move it to the new tag in its own `chore(release):` PR after that tag is published and its install has been checked.
52
+ That PR is not a release: it needs no rule-20 evidence, because it moves a pointer to a tag that already exists.
49
53
 
50
54
  ## Context
51
55
 
@@ -72,21 +76,26 @@ The README's "Where things are" table indexes the rest.
72
76
 
73
77
  ### Releases
74
78
 
75
- Rules 19 and 20 exist because `.mcp.json` pins `git+https://github.com/briandconnelly/amicus.git@v{version}`.
76
- Until the matching tag exists, a plugin install from `main` fails on an unresolvable ref.
77
- That window opens at every release and cannot be eliminated, because merging and tagging are separate operations; rule 19's last clause keeps it to the seconds between them rather than removing it.
78
- `main` carries exactly that unresolvable pin today, because 0.1.0 has never been tagged, and the first release closes this instance of it.
79
+ `.mcp.json` pins `git+https://github.com/briandconnelly/amicus.git@v{version}`, and that pin is what a fresh plugin install actually fetches: users add this repository as a marketplace, so the manifest they read is the one on `main`.
80
+ Rule 24 therefore keeps it naming a release that is already published rather than the one being released.
81
+ A manifest on `main` cannot name an artifact that only exists after `main` has moved, and pinning the version under release meant every release broke a fresh install for the interval between the release merge and the tag push.
82
+ Rule 24 removes that interval rather than shortening it.
83
+ Two facts decided the shape, and both were established by probe rather than argued: a commit SHA resolves over the same git transport a tag does, so the install path can be rehearsed before any tag exists; and `uvx` reuses a cached tool environment without querying any index, so the version in the requirement string is what makes an existing user pick up a new release — which is why an unpinned source was rejected rather than adopted.
84
+ 0.1.0 was the bootstrap, tagged and published on 2026-09-09; it named the tag it created because no earlier release existed, and that case cannot recur.
79
85
  Rule 20 is a local pre-tag gate rather than a CI job: hosted runners have no authenticated `codex`, `kimi` or `claude`, so the evidence is recorded on the maintainer's machine against the exact commit to be tagged.
80
86
  That evidence is an honest-mistake guard, not an attestation; it is a local file its author can write by hand.
81
87
  Rule 21 covers creation as well as update and deletion because pushing a `v*` tag is by itself what triggers `.github/workflows/publish.yml`: an identity that can create one can publish a release without rules 19 and 20 ever being satisfied, and a moved tag silently changes what users install under a version they already trust.
82
- No such ruleset exists yet, so rule 21 currently forbids tagging; creating it is a maintainer prerequisite of the first release, and `docs/RELEASING.md` reads it back rather than assuming it.
88
+ That ruleset now exists — `release tags`, active, covering `refs/tags/v*` and restricting creation, update and deletion — and 0.1.0 was tagged under it.
89
+ Its bypass list is the part an agent here cannot check: the ruleset response seen from this repository's agent token carries no `bypass_actors` key at all.
90
+ GitHub omits that key from responses to requesters without sufficient permission on the ruleset rather than returning an empty list, so its absence is not evidence that nobody may bypass, and must never be reported as though it were.
91
+ `docs/RELEASING.md` reads that back with the maintainer's own token rather than assuming it.
83
92
  The executable procedure — preconditions, the evidence run, the environment approval pause and the post-tag checks — is `docs/RELEASING.md`.
84
93
 
85
94
  Rules 20, 22 and 23 are shaped by what a CI job can and cannot establish, which is the subject of ADR 0014 and of issue #25 before it.
86
95
  The `verify` job runs `scripts/check_release_state.py` on the tagged commit, and the two halves of that script are worth different amounts.
87
96
  Its release-state coherence half **proves** what it reports: every version literal rule 19 names, the dated `CHANGELOG.md` section, and `uv.lock` are all facts of the tagged tree.
88
97
  Its live-gate half checks only that the record carried on the tag is well formed, names this commit and asserts three passing suites — never that those suites ran, which is why rule 23 forbids saying otherwise.
89
- Everything else rule 19 requires is a convention no CI job can prove: two PRs, an ordinary merge commit rather than a squash, the maintainer merging rather than an agent, and the tag pushed before any other work.
98
+ Everything else rule 19 requires is a convention no CI job can prove: two PRs, an ordinary merge commit rather than a squash, the maintainer merging rather than an agent, and the tag pushed promptly after the merge.
90
99
  Those are held by the platform controls around the release — rule 21's ruleset and the `pypi` environment's required reviewer — and by whoever runs the procedure, and this repository states that plainly rather than implying the workflow checks it.
91
100
 
92
101
  ### Siblings
@@ -0,0 +1,226 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.2.0] - 2026-09-10
11
+
12
+ Across this release the discovery surface moves `amicus/0.1/schema-7` -- what 0.1.0 shipped -- to
13
+ `amicus/0.1/schema-13`, and stored job results move `RESULT_FORMAT` 2 to 4. The entries below are
14
+ per-change rather than net, so they also name intermediate states that no release ever shipped:
15
+ `schema-8` through `schema-12`, and `RESULT_FORMAT` 3.
16
+
17
+ ### Changed
18
+
19
+ - **Breaking (`FINGERPRINT` `schema-13`).** The discovery catalog now advertises a real
20
+ SEP-2549 freshness window instead of the SDK's `ttlMs: 0`. `server/discover`,
21
+ `tools/list`, `resources/list`, `resources/templates/list` and `prompts/list` carry
22
+ `ttlMs: 300000`, `cacheScope: private`; those records are fixed for the life of the
23
+ process, so a modern client that opts into caching no longer re-walks 99,053 bytes of
24
+ `tools/list` to learn nothing changed. `resources/read` deliberately carries no hint and
25
+ stays at `ttlMs: 0`: the SDK chooses a hint per method while the client keys its cache
26
+ per URI, and `amicus://backends/{backend}` and `amicus://models/{backend}` report live
27
+ install, auth and model-catalog state. `tools.listChanged` and `resources.listChanged`
28
+ now report `false` on the handshake era too, matching the modern era and matching
29
+ amicus, which has no `notifications/*/list_changed` emission site -- the handshake `true`
30
+ came from FastMCP's hardcoded `NotificationOptions` and promised a notification that
31
+ could not arrive. The committed manifest also pinned
32
+ `initialize.capabilities.resources.listChanged: true`, a value the shipped stdio
33
+ transport never sent, because it is built over the in-memory transport; both eras'
34
+ capabilities are now asserted against a real `amicus-mcp` subprocess. `RESULT_FORMAT`
35
+ stays `4`. `surface_digest` moves only because `instructions` gained a clause naming it
36
+ as the catalog re-read check: revert that clause and the digest returns to its previous
37
+ value, because the digest covers the catalog records as the server holds them (before
38
+ response middleware) plus `instructions`, and not the capability blocks or the cache
39
+ envelope. The cache hints are inert for both captured hosts, which negotiate the
40
+ handshake era; the `listChanged` flip is not, and is visible to exactly those clients. Supersedes ADR 0006's cache-hint clause; see
41
+ ADR 0018. (#45)
42
+ - **Breaking (`FINGERPRINT` `schema-12`).** The published stability tier is now inside the
43
+ closed set an agent can filter on. Nine of the 18 tools -- the ones absent from the per-tool
44
+ override table -- carried `alpha` in their lifecycle `_meta`, as did all four static resources
45
+ and both resource templates, and `amicus_capabilities.stability` reported it too:
46
+ a value outside both `[9.stability-tiers]`'s `stable | preview | experimental` and amicus's
47
+ own `ToolStability` literal, so a caller filtering on the tier could not interpret it. The
48
+ server-wide tier is now `experimental`, the honest one for a 0.1.x surface and already the
49
+ tier the four `_async` and five `amicus_job_*` tools declared; their per-tool overrides are
50
+ gone, and `amicus_capabilities.tool_details[].stability` is `null` for all 18 tools, which
51
+ means what it always meant -- inherit the top-level tier. `stability` is also published as
52
+ the three-value enum rather than a bare string, so an illegal tier now fails assembly
53
+ instead of reaching a caller. `RESULT_FORMAT` stays `4`: no stored result carries a tier.
54
+ tools/list grows 106 bytes and the discovery-cost ratchet is raised deliberately
55
+ (`tests/test_discovery_cost.py` says what the bytes buy).
56
+ - `FINGERPRINT` moves `amicus/0.1/schema-10` → `amicus/0.1/schema-11` for the scoped
57
+ `workspace_root` prerequisite, which changes `initialize_response` and `capabilities_payload`,
58
+ with every pin regenerated in a dedicated commit (rule 10). `RESULT_FORMAT` stays `4`: no stored
59
+ result changed shape, and no `inputSchema` changed, so the discovery-cost ratchet does not move.
60
+ - **Breaking (`FINGERPRINT` `schema-10`, `RESULT_FORMAT` 4).** `confidence` on a review or
61
+ adversarial-review result gained a fourth value, `unknown`, and both tools now publish what the
62
+ field means. `unknown` is the ABSENCE of a rating -- the backend supplied none amicus could
63
+ read, and the verdict was not withheld either -- never a low one. amicus substitutes `low`
64
+ only where it also withholds the verdict as `unknown` -- partial coverage, findings it could
65
+ not carry, or a `not_run` review -- so a `low` beside any other verdict is the backend's own
66
+ word, and a high confidence is never evidence that coverage was complete. Backends are still asked for `low|medium|high`; the new value is amicus's, not
67
+ theirs. A `RESULT_FORMAT` 3 reader's closed enum rejects a stored result
68
+ carrying it.
69
+ - **Breaking (`FINGERPRINT` `schema-9`, `RESULT_FORMAT` 3).** Every consult, review,
70
+ adversarial-review and delegate result gained `findings_diagnostics`: `null` when nothing was
71
+ lost, otherwise a `dropped` count and reasons from a fixed vocabulary
72
+ (`severity_normalized`, `extra_fields_omitted`, `invalid_entry`, `invalid_container`,
73
+ `missing_findings`). Read the
74
+ reasons rather than the count: `dropped` counts whole entries, so a `0` beside
75
+ `extra_fields_omitted` still means content was lost, and a `null` means the count was
76
+ unknowable, never that nothing was lost.
77
+ - A job result stored under a different `result_format` is now rejected before validation rather
78
+ than after it. It used to pass, because a field added since it was written validates from its
79
+ own default -- and that default would have asserted, on the producing run's behalf, that no
80
+ finding was lost on a run that never measured loss.
81
+ - `FINGERPRINT` moves `amicus/0.1/schema-7` → `amicus/0.1/schema-8` for the `amicus_job_result`
82
+ description change, with every pin regenerated in a dedicated commit (rule 10).
83
+ `RESULT_FORMAT` did not move for it: no stored result changed shape.
84
+ - `SKILL.md`'s rule block is now the complete contract: ten obligations that lived in explanatory
85
+ prose moved into labelled rules, and the facts that motivate them moved to an adjacent
86
+ `Semantics` section ([ADR 0016](docs/adr/0016-skill-rules-are-a-complete-contract.md)).
87
+ - The returned-diff response contract separates the assessment of a proposal
88
+ (`Verdict: accept | reject | cannot-assess`) from the action taken on the working tree
89
+ (`Action: applied | not applied`). S6's recorded pass was graded against the superseded contract
90
+ and is not carried forward as a pass against the new one.
91
+ - Both plugin manifests carry `author.url`, and their `longDescription` names
92
+ `docs/MIGRATION.md` by absolute URL rather than by a repository-root-relative path that
93
+ does not resolve for a consumer who vendors the manifest without the repository around it.
94
+ - `.mcp.json`'s pin now names an already-published release rather than the version being
95
+ released, so `main` never sends a fresh install to a tag that does not exist yet
96
+ ([ADR 0015](docs/adr/0015-mcp-json-pins-an-already-published-release.md), issue #26).
97
+ The pin is no longer a release version literal; a small `chore(release):` PR moves it after the
98
+ tag is pushed.
99
+ - `scripts/check_release_state.py` replaces its `pin == version being released` equality — which was
100
+ true by construction on any tree a release PR had touched — with a shape check, a check that the
101
+ pin never leads the release, and a check that the pinned tag actually exists.
102
+ - `docs/RELEASING.md` gains a pre-tag install rehearsal that runs the committed manifest's own
103
+ command against the release commit's SHA, so git transport, a clean-machine build and the wire
104
+ handshake are all exercised before anything irreversible happens.
105
+ - The README's status section describes 0.2.0 rather than 0.1.0, and names the surface and
106
+ stored-result moves a client upgrading across this release has to account for.
107
+
108
+ ### Fixed
109
+
110
+ - The published prerequisite no longer sends a sessionless client's first call into an
111
+ `invalid_arguments` error (issue #40). Both the server `instructions` and
112
+ `amicus_capabilities.prerequisites` told a sessionless (2026-07-28) client to pass
113
+ `workspace_root` on EVERY call, and the same `instructions` name `amicus_backends` as the call
114
+ to make before the first paid one. `amicus_backends`, `amicus_models` and `amicus_capabilities`
115
+ declare no `workspace_root`, and every `inputSchema` is `additionalProperties: false`, so an
116
+ agent that followed the prerequisite failed at exactly the call the instructions told it to make
117
+ first. The prerequisite was correct for the other fifteen tools, so it is scoped to the calls
118
+ that declare the parameter, and both surfaces now render one shared sentence built from
119
+ `WORKSPACELESS_TOOLS` rather than each stating the rule in its own words; the
120
+ `invalid_workspace_root` repair carried the same "every call" wording and is scoped with it. A
121
+ manifest test binds that tuple to the live schemas, probes that each named tool really does
122
+ reject `workspace_root`, and requires every surface stating the prerequisite to carry the shared
123
+ sentence and no other workspace_root claim. What is machine-checked is the tool set and the
124
+ single source, not the prose: one sentence is what a reviewer has to read, and it can no longer
125
+ disagree with the schemas or with itself.
126
+
127
+ - Exception text no longer reaches the diagnostic log, on any path (issue #39). AGENTS.md rule 18
128
+ forbids writing a prompt input to a log, and an exception raised inside a backend adapter can
129
+ embed the text that provoked it. Two carriers did exactly that: the unexpected-exception guard
130
+ logged with `.exception()`, whose rendered traceback carries the original exception's `str()`,
131
+ and its own message interpolated `exc_summary(exc)` -- which masks secrets and control
132
+ characters, not prompt inputs, so it was never the safe form the guard's comment claimed. A
133
+ third call site, the task-map write warning in `amicus.jobs.lifecycle`, interpolated
134
+ `exc_summary` the same way; its `OSError` carries a path rather than a prompt, so it was a
135
+ latent instance of the pattern rather than a demonstrated leak, and it is gone too. Every
136
+ handler `amicus.obs` installs now renders under one policy: exception types and source
137
+ locations, never message text, notes, or source lines. The policy lives at the handler rather
138
+ than the call site because `pontonier`'s own runtime logs exceptions through these handlers too.
139
+ It is not a claim that no prompt input can ever be logged -- a call site that interpolates a
140
+ prompt field itself still would -- only that the exception-text family is closed.
141
+
142
+ - An unreadable `confidence` no longer defaults UPWARD to `medium` (issue #53). A backend that
143
+ returned nothing amicus could read about its own certainty was delivered as moderately
144
+ confident, with nothing in the envelope to say the value had been invented -- the same
145
+ direction of dishonesty as issue #38, on a different field. It now falls to `unknown`. `low`
146
+ was not the fix: it is the lowest rating a backend can REPORT, so defaulting to it would
147
+ manufacture a claim too. The verdict beside it is untouched, so a backend that reported `fail`
148
+ and said nothing readable about its certainty is delivered as `fail`/`unknown`.
149
+ - Review findings are no longer discarded in silence while the verdict survives (issue #38). A
150
+ finding that failed validation was dropped with no count and no warning, so a backend could
151
+ report a real problem and the caller receive an apparently clean review. Only `codex` is held
152
+ to the output schema natively; `claude` and `kimi` are merely asked for it in the prompt, so an
153
+ added `category` key or a shouted `"HIGH"` was an ordinary return that cost the whole finding.
154
+ Findings now survive case-normalization and unknown keys, anything still unrepresentable is
155
+ counted and named, and a `pass` no longer stands over a loss -- it is delivered as
156
+ `unknown`/`low`, while a `fail` or `concerns` keeps its verdict and its confidence.
157
+
158
+ - `collaborating-with-amicus` no longer tells an agent that delegate runs have no network egress.
159
+ That holds for `codex`, whose sandbox amicus pins to `network_access=false`; it is false for
160
+ `kimi`, which has no sandbox at all. The skill now states containment per backend
161
+ ([ADR 0016](docs/adr/0016-skill-rules-are-a-complete-contract.md)).
162
+ - The skill's async recipe no longer polls terminal jobs forever. `poll_after_ms` is `null` on
163
+ every terminal status and a cancelled job reports `result_available: false`, so the loop is now
164
+ driven by `status == "running"`.
165
+ - The server's own waiting instructions now terminate too. The `job_running` repair, the
166
+ `follow_up` every `*_async` start returns, and `amicus_job_result`'s description all told an
167
+ agent to wait for `result_available`, a flag that never flips for a `cancelled`, `failed` or
168
+ `timeout` job. All three now gate the wait on `status` and name the terminal path, so the
169
+ machine-readable repair agrees with the lifecycle and with the skill (issue #35).
170
+ - `amicus_job_result`'s description no longer tells callers to branch on `tool` unconditionally.
171
+ A stored error is delivered as an `ErrorResult`, which carries no `tool`, so `ok` is what to
172
+ check first.
173
+ - The skill no longer claims a timed-out synchronous call costs the same quota as a completed one.
174
+ Amicus is not told what a terminated call cost; the reason to prefer `_async` is that a sync
175
+ timeout destroys the result.
176
+ - Result guidance no longer stops at `ok`, `verdict` and `diff`. `review_status: not_run`,
177
+ `meta.truncated`, `meta.redacted_paths`, `meta.security_warnings` and `meta.compat_warnings`
178
+ all change what a result means, and `diffstat` is computed before redaction and truncation, so
179
+ it is not an integrity check on the returned `diff`.
180
+ - Rule 5 no longer requires naming the backend whose annotation caused an approval prompt — an
181
+ attribution a host does not supply. It now separates the observed prompt from the annotation
182
+ policy. `effects` is documented as the static per-backend declaration it is, not "call-specific
183
+ truth".
184
+ - The README's verb matrix no longer reads as a claim about what the models can do. A `no` there is
185
+ amicus's routing decision: `delegate` is absent on Claude by a review-only policy, and
186
+ `adversarial_review` is scoped to Claude for v1. The verb itself is amicus's own — the prompt it
187
+ builds and the result shape it returns are amicus's for any backend, with Claude contributing a
188
+ critic stance on top — so Codex and Kimi can review adversarially. The README now says so, points
189
+ at `consult` and `review_changes` for it, and names what the verb adds over them (issue #23).
190
+
191
+ ### Added
192
+
193
+ - `collaborating-with-amicus` gains `reading-results.md`, `active-workflows.md`,
194
+ `options-and-errors.md`, `independent-attempt.md`, `review-revise.md` and
195
+ `server-down-fallback.md`. Backend selection now covers what each backend can actually inspect —
196
+ `claude` defaults to `access="toolless"` and cannot read the repository unless asked — and git
197
+ scope, brief preparation, and `idempotency_key` recovery are documented.
198
+ - Six prospective scenarios (S9–S14) covering git scope, terminal-job lifecycle, coverage
199
+ reporting, backend evidence, delegate containment, and independent-attempt ordering. Schema
200
+ validity now binds every described call in every scenario.
201
+
202
+ ## [0.1.0] - 2026-09-08
203
+
204
+ ### Added
205
+
206
+ - One MCP server for three second-opinion backends — `codex`, `kimi` and `claude` — with the backend as a tool parameter rather than a separate server (M0–M4).
207
+ - Synchronous verbs: `amicus_consult`, `amicus_review_changes`, `amicus_delegate`, `amicus_adversarial_review`, plus free dry-run previews for review (`amicus_dry_run`) and delegate (`amicus_delegate_dry_run`).
208
+ - Discovery surface: `amicus_backends`, `amicus_capabilities`, `amicus_models`, and the MCP resources that back them.
209
+ - A jobs surface: `_async` twins of the paid verbs, `amicus_job_status`, `amicus_job_result`, `amicus_job_consume_result`, `amicus_job_list`, `amicus_job_cancel`, with idempotency keys, restart survival and task-id lookup (M2).
210
+ - `task=True` on the four paid synchronous tools behind the `AMICUS_TASKS` flag (M5).
211
+ - Packaging for both hosts: a `.claude-plugin/` manifest, a `.codex-plugin/` manifest, an `amicus-mcp` console script, and the `collaborating-with-amicus` skill (M6).
212
+ - Release automation: a tag- and dispatch-triggered publish workflow with trusted publishing to TestPyPI and PyPI.
213
+ - A release predicate gating that upload: a `verify` job runs `scripts/check_release_state.py` against the tagged commit, and `pypi` depends on it (issue #25, ADR 0014). It proves the tagged tree's release-state coherence — every version literal, the dated changelog section, `uv.lock` — and checks that the live-gate record carried in the annotated tag's message is well formed and names that commit. That record remains the maintainer's assertion, never proof the live gates ran.
214
+
215
+ ### Fixed
216
+
217
+ - `record_live_gate_evidence.validate` accepted a record that omitted `batch_id` from every backend entry, so the "one shared run produced this record" property it documented was not actually checkable. `batch_id` is now a required backend field.
218
+
219
+ ### Known limitations
220
+
221
+ - The tagged publish path to pypi.org has never run. Only the TestPyPI dispatch path has been exercised.
222
+ - Eval scenario S6 in `skills/collaborating-with-amicus/tests/scenarios.md` passed on one run (status: `pass`, validated by that run alone); an M7 follow-up run against the current skill text did not isolate the still-open F3 finding, so F3 remains open. S7 (real-host approval friction) has failed both of its recorded runs (status: `fail`); an M7 zero-spend recheck reached neither a pass nor a fail and is recorded as inconclusive, so it does not move S7's status. See their `status` fields and ADR 0012.
223
+
224
+ [Unreleased]: https://github.com/briandconnelly/amicus/compare/v0.2.0...HEAD
225
+ [0.2.0]: https://github.com/briandconnelly/amicus/compare/v0.1.0...v0.2.0
226
+ [0.1.0]: https://github.com/briandconnelly/amicus/releases/tag/v0.1.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: amicus
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: One MCP server for every second-opinion model: consult, review, and delegate with the backend as a parameter
5
5
  Project-URL: Homepage, https://github.com/briandconnelly/amicus
6
6
  Project-URL: Repository, https://github.com/briandconnelly/amicus
@@ -66,8 +66,8 @@ Start a new session afterwards so the host loads the bundled skill and tools.
66
66
 
67
67
  ### Any other MCP client
68
68
 
69
- The plugins launch the server from the release tag pinned in [`.mcp.json`](.mcp.json). Point your
70
- client at the same command:
69
+ The plugins launch the server from a published release tag, pinned in
70
+ [`.mcp.json`](.mcp.json). Point your client at the same command:
71
71
 
72
72
  ```json
73
73
  {
@@ -132,6 +132,14 @@ Not every backend does everything:
132
132
  | `delegate` | yes | yes | no |
133
133
  | `adversarial_review` | no | no | yes |
134
134
 
135
+ A `no` is amicus's routing decision, not a claim about the model. `delegate` is absent on Claude
136
+ by a deliberate review-only policy. `adversarial_review` is scoped to Claude for v1, but the verb
137
+ is amicus's own: the prompt it builds and the result shape it returns are amicus's for any
138
+ backend, and what Claude contributes is a critic stance layered on top. So nothing about
139
+ Codex or Kimi stops either from reviewing adversarially — ask them through `consult` or
140
+ `review_changes` and supply the adversarial stance yourself. What the verb adds is that stance
141
+ fixed, plus its `target` and `evidence` carriers.
142
+
135
143
  Asking a backend for something it does not support returns a `feature_unsupported` error naming
136
144
  the backend and the feature, rather than failing obscurely.
137
145
 
@@ -160,11 +168,12 @@ the new ones.
160
168
 
161
169
  ## Status and known limits
162
170
 
163
- 0.1.0 is the first release. The server's wire contract is exercised by the test suite and by host
164
- captures against Claude Code and Codex, but:
171
+ 0.2.0 is the current release, and it is a breaking one: the discovery surface moved from
172
+ `amicus/0.1/schema-7` to `amicus/0.1/schema-13` and stored job results from `RESULT_FORMAT` 2 to
173
+ `4`. [`CHANGELOG.md`](CHANGELOG.md) says what moved and what a cached client should re-read. The
174
+ server's wire contract is exercised by the test suite and by host captures against Claude Code and
175
+ Codex, but:
165
176
 
166
- - 0.1.0 is the first release published from a tag, so the tagged publish path runs for the first
167
- time with it.
168
177
  - Two router-skill evaluation scenarios are unresolved — S6 (diff-safety wording) and S7 (approval
169
178
  friction) — recorded in [`docs/adr/0012-m6-packaging-decisions.md`](docs/adr/0012-m6-packaging-decisions.md).
170
179
  Neither is a defect in the server's wire contract.
@@ -36,8 +36,8 @@ Start a new session afterwards so the host loads the bundled skill and tools.
36
36
 
37
37
  ### Any other MCP client
38
38
 
39
- The plugins launch the server from the release tag pinned in [`.mcp.json`](.mcp.json). Point your
40
- client at the same command:
39
+ The plugins launch the server from a published release tag, pinned in
40
+ [`.mcp.json`](.mcp.json). Point your client at the same command:
41
41
 
42
42
  ```json
43
43
  {
@@ -102,6 +102,14 @@ Not every backend does everything:
102
102
  | `delegate` | yes | yes | no |
103
103
  | `adversarial_review` | no | no | yes |
104
104
 
105
+ A `no` is amicus's routing decision, not a claim about the model. `delegate` is absent on Claude
106
+ by a deliberate review-only policy. `adversarial_review` is scoped to Claude for v1, but the verb
107
+ is amicus's own: the prompt it builds and the result shape it returns are amicus's for any
108
+ backend, and what Claude contributes is a critic stance layered on top. So nothing about
109
+ Codex or Kimi stops either from reviewing adversarially — ask them through `consult` or
110
+ `review_changes` and supply the adversarial stance yourself. What the verb adds is that stance
111
+ fixed, plus its `target` and `evidence` carriers.
112
+
105
113
  Asking a backend for something it does not support returns a `feature_unsupported` error naming
106
114
  the backend and the feature, rather than failing obscurely.
107
115
 
@@ -130,11 +138,12 @@ the new ones.
130
138
 
131
139
  ## Status and known limits
132
140
 
133
- 0.1.0 is the first release. The server's wire contract is exercised by the test suite and by host
134
- captures against Claude Code and Codex, but:
141
+ 0.2.0 is the current release, and it is a breaking one: the discovery surface moved from
142
+ `amicus/0.1/schema-7` to `amicus/0.1/schema-13` and stored job results from `RESULT_FORMAT` 2 to
143
+ `4`. [`CHANGELOG.md`](CHANGELOG.md) says what moved and what a cached client should re-read. The
144
+ server's wire contract is exercised by the test suite and by host captures against Claude Code and
145
+ Codex, but:
135
146
 
136
- - 0.1.0 is the first release published from a tag, so the tagged publish path runs for the first
137
- time with it.
138
147
  - Two router-skill evaluation scenarios are unresolved — S6 (diff-safety wording) and S7 (approval
139
148
  friction) — recorded in [`docs/adr/0012-m6-packaging-decisions.md`](docs/adr/0012-m6-packaging-decisions.md).
140
149
  Neither is a defect in the server's wire contract.
@@ -72,7 +72,8 @@ This is configured on PyPI's own project settings page and has no read-only API
72
72
  Trademark clearance for the name `amicus` is resolved, or the maintainer has decided to proceed without it.
73
73
  This was decided on 2026-09-08: `docs/adr/0013-proceed-without-trademark-clearance.md` records the decision to publish without clearance, the consequences accepted, and what would reopen it.
74
74
  Read that ADR rather than relying on anyone's recollection, and confirm nothing listed under "What would reopen this" has since happened.
75
- TestPyPI already has the name claimed under this project; pypi.org does not yet have a release.
75
+ TestPyPI has the name claimed under this project, and pypi.org has carried a release since 0.1.0 was published on 2026-09-09.
76
+ The name is therefore established on both indexes; this precondition is about clearance, not about claiming the name.
76
77
 
77
78
  ### The README describes the released tool
78
79
 
@@ -86,7 +87,9 @@ Second, its "Status and known limits" section must not claim anything the releas
86
87
 
87
88
  Rules 19 and 20 together shape this sequence, and a future maintainer should not "simplify" it back.
88
89
  Rule 20 requires the live-gate evidence to cover the exact commit being tagged.
89
- Rule 19 requires the tag push to be the only work that follows the PR C merge, because the interval in which `main` names a tag that does not yet exist cannot be made zero, only closed as fast as possible.
90
+ Rule 19 requires the tag push to be the only work that follows the PR C merge, so that `main`'s version literals and the published tag agree without a gap.
91
+ Since ADR 0015 that promptness is no longer about a broken install path: `.mcp.json` pins the newest **already-published** release, so `main` never sends a fresh install to a tag that does not exist.
92
+ The single exception was the first release, which had no earlier tag to name; 0.1.0 was tagged and published on 2026-09-09, which closed that window permanently.
90
93
  The tag does not have to point at `main`'s head; it has to point at the commit the evidence covers.
91
94
  An ordinary merge commit keeps the PR C branch tip in `main`'s history as one of the merge commit's two parents, so tagging that branch tip is legitimate, and it is exactly the commit the evidence names — no fast-forward or branch-protection change is required to satisfy both rules.
92
95
  The tag therefore deliberately points at a commit that is in `main`'s history but is not `main`'s head, and the checks in step 5 below prove the two commits' trees are identical.
@@ -94,8 +97,14 @@ The tag therefore deliberately points at a commit that is in `main`'s history bu
94
97
  1. Merge PR B (the milestone work, version literals untouched).
95
98
  2. Open PR C, the `chore(release):` PR described by AGENTS.md rule 19, and do not merge it yet.
96
99
  Roll `## [Unreleased]` in `CHANGELOG.md` into a dated `## [X.Y.Z] - YYYY-MM-DD` section, and leave a fresh empty `## [Unreleased]` above it.
100
+ That date is **UTC** (`date -u +%F`), not the local date of whoever prepares the PR.
101
+ The two disagree for part of every day in this maintainer's timezone, and the tag, the publish run and the PyPI record are all stamped in UTC, so a local date makes the changelog disagree with every other artifact of the same release.
102
+ 0.1.0 predates this convention and is dated `2026-09-08`, its local date; it was tagged on 2026-09-09 UTC, and that section is left as it shipped rather than rewritten.
97
103
  Change no version literal unless the version itself is changing.
98
- For 0.1.0 no literal moves: `pyproject.toml`, `src/amicus/__init__.py`, both `plugin.json` files, and `.mcp.json`'s `@v0.1.0` pin already agree, and the tag is what makes that pin resolve.
104
+ The literals are `pyproject.toml`, `src/amicus/__init__.py` and both `plugin.json` files.
105
+ Do **not** touch `.mcp.json`: per ADR 0015 its pin names an already-published release, so during this PR it correctly trails the version being released by one, and step 7 moves it after the tag exists.
106
+ 0.1.0 was the bootstrap: no literal moved, and its `@v0.1.0` pin named the tag that release itself created, because no earlier release existed.
107
+ That case is closed and does not recur.
99
108
  Regenerate `uv.lock` with `uv lock` in this same PR, per AGENTS.md rule 19 — `uv.lock` mirrors the version rather than declaring it, and `prek.toml`'s `uv-lock-check` hook runs `uv lock --check` whenever `pyproject.toml` changes, so a release PR that skips this fails its own hook.
100
109
  3. Check out the PR C branch tip (not `main`) into a clean tree and confirm `git status --porcelain` is empty.
101
110
  Record the branch tip's SHA; call it the release commit, and note it well — it is the commit that gets tagged, and it will not be `main`'s head after the next step.
@@ -107,6 +116,18 @@ The tag therefore deliberately points at a commit that is in `main`'s history bu
107
116
  Run `AMICUS_RELEASE_CHECK=1 uv run pytest tests/test_release_evidence.py -v --no-cov` and confirm the freshness assertion passes.
108
117
  Run `uv run python scripts/check_release_state.py` and confirm it prints `release predicate holds`.
109
118
  That is the same tree check the `verify` job will run after the tag is pushed, so a failure here is a failure you would otherwise discover with an immutable tag already in place.
119
+ Rehearse the real install path against the release commit, which is the check that used to be impossible before the tag existed:
120
+
121
+ ```sh
122
+ printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"rehearsal","version":"0"}}}' \
123
+ | UV_CACHE_DIR="$(mktemp -d)" uvx --from "git+https://github.com/briandconnelly/amicus.git@<release-sha>" amicus-mcp
124
+ ```
125
+
126
+ Substitute the release commit's SHA for the tag and change nothing else: a commit SHA resolves over the same git transport a tag does, and it exists before the tag does.
127
+ A clean `UV_CACHE_DIR` is what makes this mean anything — `uvx` reuses a cached tool environment without contacting any index, so a warm cache can answer from a build you already had.
128
+ Confirm the server answers `initialize` with `serverInfo.name == "amicus"` and the version being released.
129
+ This proves git transport, a clean-machine build, the console script and the wire handshake before anything irreversible happens.
130
+ What it does not prove is that the string `vX.Y.Z` resolves, which is the trivial remainder and is covered by the post-tag checks.
110
131
  Run the gate defined by AGENTS.md rule 2.
111
132
  The 24-hour freshness window this evidence carries (`validate`'s `max_age_hours`) is checked only here, at step 3, and deliberately not by CI afterward: a tag is immutable, so a window applied after tagging could let queue time or a slow deployment approval turn a legitimate tag into one that can never be published.
112
133
  The window is therefore yours to honor: merge PR C, the next step, before the day is out — otherwise this step must be repeated.
@@ -136,6 +157,13 @@ The tag therefore deliberately points at a commit that is in `main`'s history bu
136
157
  `--cleanup=verbatim` keeps the JSON byte-for-byte; the default cleanup would also parse, but exactness is free here.
137
158
  Confirm before pushing that `git cat-file -t vX.Y.Z` prints `tag` (not `commit`, which would mean a lightweight tag) and that `git tag -l --format='%(contents)' vX.Y.Z | python -c 'import json,sys; json.load(sys.stdin)'` exits 0.
138
159
  Nothing but step 5's read-only checks happens between step 4 and step 6.
160
+ 7. Once the publish has completed and the post-tag checks below have passed, open a small `chore(release):` PR that moves `.mcp.json`'s pin to `vX.Y.Z`.
161
+
162
+ This is the pin-move PR that ADR 0015 makes part of every release, and it is deliberately *after* the tag rather than before it: the pin names a release that already exists, so moving it earlier would be the very thing ADR 0015 removes.
163
+ It touches `.mcp.json` and nothing else, it is not a release under rule 19, and it needs no live-gate evidence — it moves a pointer to a tag that is already published.
164
+ Until it merges, `main` sends a fresh install to the previous release, which works.
165
+ That is the intended degradation, so do not treat it as an outage or rush the PR through without its checks.
166
+ This step did not apply to 0.1.0, whose pin already reads `@v0.1.0` for the bootstrap reason above; 0.2.0 is the first release to perform it.
139
167
 
140
168
  A maintainer who instead wants the tag to be `main`'s own head has a permitted alternative: a direct fast-forward push of the PR C branch to `main` (`git checkout main && git merge --ff-only <pr-branch> && git push origin main`) achieves that, if this repository's branch protection allows a direct push to `main`.
141
169
  This runbook cannot say whether it does: `gh api repos/briandconnelly/amicus/branches/main/protection` returned `403 Resource not accessible by integration` to the token available while writing it, so that setting is unverified here, and this document does not assert it either way.
@@ -171,12 +199,16 @@ They confirm the release actually landed; they are not a pre-tag gate.
171
199
  2. Install from the public tag exactly as a user would, using the committed manifest's own source:
172
200
 
173
201
  ```sh
174
- uvx --from git+https://github.com/briandconnelly/amicus.git@vX.Y.Z amicus-mcp
202
+ printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"post-tag","version":"0"}}}' \
203
+ | UV_CACHE_DIR="$(mktemp -d)" uvx --from "git+https://github.com/briandconnelly/amicus.git@vX.Y.Z" amicus-mcp
175
204
  ```
176
205
 
177
- Drive it with one JSON-RPC `initialize` request over stdin and assert `serverInfo.name == "amicus"` and the expected version.
178
- This is the first and only check that the `.mcp.json` pin actually resolves; it cannot be run before the tag exists.
206
+ Assert `serverInfo.name == "amicus"` and the expected version in the reply.
207
+ The fresh `UV_CACHE_DIR` is part of the command, not a note beside it: a warm cache answers without resolving anything, so a copy-pasted command without it can pass while proving nothing.
208
+ Step 3's rehearsal already proved transport, build and handshake against the release commit's SHA, so what this adds is narrow but real — that the tag *ref* resolves, which is all that separated the rehearsal from the thing itself.
209
+ This is what step 7's pin-move PR is waiting on: do not move the pin to a tag whose install you have not just run.
179
210
  3. Run a negative control: the same command against a version that does not exist must fail.
211
+ Without it, a warm cache or a silently-substituted binary would make check 2 pass no matter what.
180
212
 
181
213
  ## Rollback
182
214
 
@@ -1,6 +1,7 @@
1
1
  # ADR 0006: Fingerprint plus surface digest; cache hints left at the SDK default
2
2
 
3
- **Status:** Accepted (2026-09-04, M0)
3
+ **Status:** Accepted (2026-09-04, M0).
4
+ Its cache-hint clause is superseded by [ADR 0018](0018-the-catalog-carries-a-ttl-and-resource-reads-do-not.md) (2026-09-09); the fingerprint and surface-digest decisions stand.
4
5
 
5
6
  ## Context
6
7
 
@@ -14,9 +15,11 @@ A hand-bumped string cannot prove the surface changed; a digest cannot be read b
14
15
  The full-manifest hash is a separate, stronger check pinned only in tests; it moves with the fingerprint but is never reported alone as `surface_digest`.
15
16
  The committed snapshot (`tests/fixtures/manifest_snapshot.<profile>.json`) and pinned hash guard both per profile.
16
17
  `ttlMs`/`cacheScope` stay at the SDK default (`ttlMs: 0`, `cacheScope: "private"`): fastmcp applies one server-wide hint to every list and read result, and `amicus://models/{backend}` is volatile, so a positive TTL would be wrong for it.
18
+ (Superseded by ADR 0018: fastmcp's hint is still uniform, but the SDK beneath it takes one per method, and the volatility is confined to `resources/read`.)
17
19
  The manifest pins the emitted values so a framework change is reviewed, not silent.
18
20
 
19
21
  ## Consequences
20
22
 
21
23
  - `surface_digest` and `fingerprint` are excluded from the manifest capture (self-referential), as are release-variable versions.
22
24
  - Revisit the TTL when fastmcp offers per-resource hints.
25
+ Retired rather than met, by ADR 0018: per-METHOD hints proved sufficient.