amicus 0.3.0__tar.gz → 0.4.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 (528) hide show
  1. {amicus-0.3.0 → amicus-0.4.0}/.claude-plugin/plugin.json +1 -1
  2. {amicus-0.3.0 → amicus-0.4.0}/.codex-plugin/plugin.json +1 -1
  3. {amicus-0.3.0 → amicus-0.4.0}/.github/dependabot.yml +11 -0
  4. {amicus-0.3.0 → amicus-0.4.0}/.github/workflows/test.yml +17 -0
  5. {amicus-0.3.0 → amicus-0.4.0}/.mcp.json +1 -1
  6. {amicus-0.3.0 → amicus-0.4.0}/AGENTS.md +20 -12
  7. {amicus-0.3.0 → amicus-0.4.0}/CHANGELOG.md +185 -1
  8. {amicus-0.3.0 → amicus-0.4.0}/PKG-INFO +29 -32
  9. {amicus-0.3.0 → amicus-0.4.0}/README.md +28 -30
  10. {amicus-0.3.0 → amicus-0.4.0}/docs/DEPRECATING-SIBLINGS.md +10 -6
  11. {amicus-0.3.0 → amicus-0.4.0}/docs/MIGRATION.md +41 -15
  12. {amicus-0.3.0 → amicus-0.4.0}/docs/RELEASING.md +27 -17
  13. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0003-workspace-resolution.md +1 -0
  14. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0015-mcp-json-pins-an-already-published-release.md +2 -1
  15. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0023-dependency-loggers-are-owned-at-a-warning-floor.md +6 -2
  16. amicus-0.4.0/docs/adr/0029-the-backend-sdk-lives-in-tree.md +63 -0
  17. amicus-0.4.0/docs/adr/0030-the-sdk-keeps-what-a-backend-imports.md +46 -0
  18. amicus-0.4.0/docs/adr/0031-the-marketplace-pointer-decides-what-users-run.md +47 -0
  19. amicus-0.4.0/docs/adr/0032-a-claude-review-defaults-to-readonly-access.md +43 -0
  20. amicus-0.4.0/docs/adr/0033-an-unreadable-review-answer-is-delivered-unstructured.md +63 -0
  21. amicus-0.4.0/docs/adr/0034-claude-usage-is-read-from-model-usage.md +29 -0
  22. amicus-0.4.0/docs/adr/0035-a-backend-answer-is-kept-on-the-job-record.md +53 -0
  23. amicus-0.4.0/docs/claude-help/2.1.274/FINDINGS.md +39 -0
  24. amicus-0.4.0/docs/claude-help/2.1.274/budget-stop-envelope-shape.json +52 -0
  25. amicus-0.4.0/docs/claude-help/2.1.274/claude-version.txt +1 -0
  26. {amicus-0.3.0 → amicus-0.4.0}/docs/superpowers/specs/2026-09-04-amicus-design.md +21 -24
  27. amicus-0.4.0/docs/superpowers/specs/2026-09-15-amicus-M8-sdk-in-tree-design.md +224 -0
  28. amicus-0.4.0/docs/superpowers/specs/2026-09-16-amicus-release-activation-design.md +343 -0
  29. {amicus-0.3.0 → amicus-0.4.0}/prek.toml +2 -1
  30. {amicus-0.3.0 → amicus-0.4.0}/pyproject.toml +38 -3
  31. {amicus-0.3.0 → amicus-0.4.0}/scripts/check_commit_message.py +1 -0
  32. {amicus-0.3.0 → amicus-0.4.0}/scripts/check_release_state.py +250 -40
  33. {amicus-0.3.0 → amicus-0.4.0}/skills/collaborating-with-amicus/SKILL.md +17 -5
  34. amicus-0.4.0/skills/collaborating-with-amicus/references/blind-comparison.md +149 -0
  35. {amicus-0.3.0 → amicus-0.4.0}/skills/collaborating-with-amicus/references/choosing-a-backend.md +5 -1
  36. {amicus-0.3.0 → amicus-0.4.0}/skills/collaborating-with-amicus/references/options-and-errors.md +3 -1
  37. {amicus-0.3.0 → amicus-0.4.0}/skills/collaborating-with-amicus/references/reading-results.md +16 -1
  38. {amicus-0.3.0 → amicus-0.4.0}/skills/collaborating-with-amicus/references/sync-vs-async.md +5 -0
  39. {amicus-0.3.0 → amicus-0.4.0}/skills/collaborating-with-amicus/tests/scenarios.md +89 -1
  40. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/__init__.py +1 -1
  41. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/_worker.py +30 -4
  42. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/__init__.py +1 -1
  43. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/claude/__init__.py +4 -5
  44. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/claude/adapter.py +14 -11
  45. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/claude/adversarial.py +7 -1
  46. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/claude/cli.py +19 -19
  47. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/claude/config.py +31 -14
  48. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/claude/contract.py +6 -2
  49. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/claude/normalize.py +66 -18
  50. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/claude/options.py +9 -2
  51. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/claude/status.py +1 -2
  52. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/codex/__init__.py +4 -5
  53. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/codex/adapter.py +6 -9
  54. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/codex/binary.py +1 -2
  55. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/codex/cli.py +71 -21
  56. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/codex/config.py +9 -10
  57. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/codex/contract.py +67 -13
  58. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/codex/models.py +2 -3
  59. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/codex/normalize.py +22 -4
  60. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/codex/status.py +5 -5
  61. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/kimi/__init__.py +4 -5
  62. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/kimi/adapter.py +6 -8
  63. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/kimi/cli.py +7 -8
  64. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/kimi/config.py +8 -10
  65. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/kimi/contract.py +2 -2
  66. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/kimi/models.py +1 -2
  67. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/kimi/normalize.py +1 -2
  68. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/kimi/status.py +2 -4
  69. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/config/__init__.py +21 -17
  70. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/config/envspec.py +56 -14
  71. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/errors.py +7 -6
  72. amicus-0.4.0/src/amicus/jobs/__init__.py +2 -0
  73. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/jobs/delivery.py +1 -1
  74. amicus-0.4.0/src/amicus/jobs/idempotency.py +466 -0
  75. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/jobs/lifecycle.py +4 -5
  76. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/jobs/lookup.py +1 -2
  77. amicus-0.4.0/src/amicus/jobs/polling.py +33 -0
  78. amicus-0.4.0/src/amicus/jobs/store.py +1049 -0
  79. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/jobs/taskmap.py +3 -3
  80. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/manifest.py +3 -3
  81. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/middleware.py +1 -1
  82. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/obs.py +29 -28
  83. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/orchestration/finalize.py +53 -24
  84. amicus-0.4.0/src/amicus/orchestration/gitdiff.py +1179 -0
  85. amicus-0.4.0/src/amicus/orchestration/gitproc.py +205 -0
  86. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/orchestration/isolation.py +10 -8
  87. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/orchestration/prompts.py +131 -9
  88. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/orchestration/review.py +3 -4
  89. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/orchestration/run.py +4 -6
  90. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/orchestration/workspace.py +68 -12
  91. amicus-0.4.0/src/amicus/orchestration/worktree.py +665 -0
  92. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/plugin.py +8 -9
  93. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/registry.py +4 -5
  94. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/request.py +4 -4
  95. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/schemas/codes.py +5 -5
  96. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/schemas/envelope.py +1 -1
  97. amicus-0.4.0/src/amicus/schemas/fingerprint.py +184 -0
  98. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/schemas/options.py +3 -2
  99. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/schemas/params.py +7 -3
  100. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/schemas/results.py +12 -5
  101. amicus-0.4.0/src/amicus/schemas/structured.py +95 -0
  102. amicus-0.4.0/src/amicus/sdk/__init__.py +14 -0
  103. amicus-0.4.0/src/amicus/sdk/backend/__init__.py +19 -0
  104. amicus-0.4.0/src/amicus/sdk/backend/contract.py +137 -0
  105. amicus-0.4.0/src/amicus/sdk/backend/protocol.py +311 -0
  106. amicus-0.4.0/src/amicus/sdk/conventions/__init__.py +8 -0
  107. amicus-0.4.0/src/amicus/sdk/conventions/annotations.py +97 -0
  108. amicus-0.4.0/src/amicus/sdk/conventions/envelope.py +380 -0
  109. amicus-0.4.0/src/amicus/sdk/conventions/preflight.py +100 -0
  110. amicus-0.4.0/src/amicus/sdk/core/__init__.py +7 -0
  111. amicus-0.4.0/src/amicus/sdk/core/jsoncache.py +42 -0
  112. amicus-0.4.0/src/amicus/sdk/core/pathalias.py +430 -0
  113. amicus-0.4.0/src/amicus/sdk/core/redaction.py +1515 -0
  114. amicus-0.4.0/src/amicus/sdk/core/runtime.py +617 -0
  115. amicus-0.4.0/src/amicus/sdk/core/streamcap.py +286 -0
  116. amicus-0.4.0/src/amicus/sdk/testing/__init__.py +7 -0
  117. amicus-0.4.0/src/amicus/sdk/testing/conformance.py +119 -0
  118. amicus-0.4.0/src/amicus/sdk/testing/surface_honesty.py +52 -0
  119. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/surface.py +1 -1
  120. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/tools/_meta.py +2 -3
  121. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/tools/_prepare.py +2 -3
  122. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/tools/_resolve.py +9 -0
  123. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/tools/consult.py +4 -2
  124. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/tools/delegate.py +3 -3
  125. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/tools/discovery.py +26 -10
  126. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/tools/dry_run.py +2 -2
  127. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/tools/jobs.py +2 -2
  128. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/tools/review.py +7 -5
  129. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/wire_shape_snapshot.py +27 -4
  130. {amicus-0.3.0 → amicus-0.4.0}/tests/conftest.py +47 -14
  131. amicus-0.4.0/tests/fixtures/claude_budget_stop_envelope.json +82 -0
  132. {amicus-0.3.0 → amicus-0.4.0}/tests/fixtures/fakebackend/src/fakebackend/__init__.py +11 -12
  133. {amicus-0.3.0 → amicus-0.4.0}/tests/fixtures/manifest_snapshot.all.json +52 -46
  134. {amicus-0.3.0 → amicus-0.4.0}/tests/fixtures/manifest_snapshot.claude.json +52 -46
  135. {amicus-0.3.0 → amicus-0.4.0}/tests/fixtures/manifest_snapshot.codex-kimi.json +52 -46
  136. {amicus-0.3.0 → amicus-0.4.0}/tests/fixtures/result_format_snapshot.json +6 -4
  137. {amicus-0.3.0 → amicus-0.4.0}/tests/fixtures/wire_shape_snapshot.json +183 -1
  138. amicus-0.4.0/tests/sdk/conftest.py +96 -0
  139. amicus-0.4.0/tests/sdk/test_annotations.py +85 -0
  140. amicus-0.4.0/tests/sdk/test_classified_failure_fields.py +70 -0
  141. amicus-0.4.0/tests/sdk/test_conformance_fakes.py +510 -0
  142. amicus-0.4.0/tests/sdk/test_conformance_inspector.py +94 -0
  143. amicus-0.4.0/tests/sdk/test_contract.py +88 -0
  144. amicus-0.4.0/tests/sdk/test_envelope.py +92 -0
  145. amicus-0.4.0/tests/sdk/test_fingerprint.py +93 -0
  146. amicus-0.4.0/tests/sdk/test_git_isolation.py +65 -0
  147. amicus-0.4.0/tests/sdk/test_gitdiff.py +2153 -0
  148. amicus-0.4.0/tests/sdk/test_gitproc.py +205 -0
  149. amicus-0.4.0/tests/sdk/test_idempotency.py +490 -0
  150. amicus-0.4.0/tests/sdk/test_jobs.py +1548 -0
  151. amicus-0.4.0/tests/sdk/test_jsoncache.py +59 -0
  152. amicus-0.4.0/tests/sdk/test_orphan_sweep.py +245 -0
  153. amicus-0.4.0/tests/sdk/test_outcome_inspector.py +90 -0
  154. amicus-0.4.0/tests/sdk/test_pair_parity_kit.py +72 -0
  155. amicus-0.4.0/tests/sdk/test_pathalias.py +614 -0
  156. amicus-0.4.0/tests/sdk/test_preflight.py +132 -0
  157. amicus-0.4.0/tests/sdk/test_prompts.py +119 -0
  158. amicus-0.4.0/tests/sdk/test_redaction.py +3411 -0
  159. amicus-0.4.0/tests/sdk/test_run_request.py +156 -0
  160. amicus-0.4.0/tests/sdk/test_runtime.py +1018 -0
  161. amicus-0.4.0/tests/sdk/test_runtime_kill_and_sweep_paths.py +145 -0
  162. amicus-0.4.0/tests/sdk/test_streamcap.py +351 -0
  163. amicus-0.4.0/tests/sdk/test_surface_honesty_kit.py +49 -0
  164. amicus-0.4.0/tests/sdk/test_usage_cache_fields.py +49 -0
  165. amicus-0.4.0/tests/sdk/test_workspace.py +53 -0
  166. amicus-0.4.0/tests/sdk/test_worktree.py +1004 -0
  167. amicus-0.4.0/tests/sdk/test_worktree_config.py +93 -0
  168. amicus-0.4.0/tests/support/__init__.py +0 -0
  169. {amicus-0.3.0 → amicus-0.4.0}/tests/support/claudefixtures.py +6 -3
  170. {amicus-0.3.0 → amicus-0.4.0}/tests/support/codexfixtures.py +2 -3
  171. {amicus-0.3.0 → amicus-0.4.0}/tests/support/fakeplugin.py +11 -12
  172. {amicus-0.3.0 → amicus-0.4.0}/tests/support/kimifixtures.py +2 -3
  173. amicus-0.4.0/tests/support/pair_parity.py +62 -0
  174. {amicus-0.3.0 → amicus-0.4.0}/tests/test_adversarial.py +10 -3
  175. {amicus-0.3.0 → amicus-0.4.0}/tests/test_async_tools.py +1 -1
  176. {amicus-0.3.0 → amicus-0.4.0}/tests/test_cache_hints.py +3 -2
  177. {amicus-0.3.0 → amicus-0.4.0}/tests/test_check_commit_message.py +6 -0
  178. {amicus-0.3.0 → amicus-0.4.0}/tests/test_claude_adapter.py +55 -4
  179. {amicus-0.3.0 → amicus-0.4.0}/tests/test_claude_argv_differential.py +1 -1
  180. {amicus-0.3.0 → amicus-0.4.0}/tests/test_claude_cli.py +2 -2
  181. {amicus-0.3.0 → amicus-0.4.0}/tests/test_claude_config.py +46 -14
  182. {amicus-0.3.0 → amicus-0.4.0}/tests/test_claude_contract.py +2 -2
  183. amicus-0.4.0/tests/test_claude_golden_envelope.py +158 -0
  184. amicus-0.4.0/tests/test_claude_normalize.py +190 -0
  185. {amicus-0.3.0 → amicus-0.4.0}/tests/test_claude_plugin.py +14 -1
  186. {amicus-0.3.0 → amicus-0.4.0}/tests/test_claude_result_differential.py +14 -7
  187. {amicus-0.3.0 → amicus-0.4.0}/tests/test_claude_status.py +1 -1
  188. {amicus-0.3.0 → amicus-0.4.0}/tests/test_claude_sync_tools.py +96 -1
  189. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codes.py +4 -5
  190. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codex_adapter.py +73 -5
  191. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codex_argv_differential.py +5 -5
  192. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codex_binary.py +1 -1
  193. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codex_cli.py +168 -7
  194. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codex_config.py +13 -5
  195. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codex_contract.py +120 -1
  196. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codex_normalize.py +26 -0
  197. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codex_result_differential.py +15 -3
  198. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codex_status.py +23 -4
  199. {amicus-0.3.0 → amicus-0.4.0}/tests/test_config.py +23 -11
  200. {amicus-0.3.0 → amicus-0.4.0}/tests/test_delivery.py +2 -3
  201. {amicus-0.3.0 → amicus-0.4.0}/tests/test_discovery.py +46 -1
  202. {amicus-0.3.0 → amicus-0.4.0}/tests/test_discovery_cost.py +35 -2
  203. {amicus-0.3.0 → amicus-0.4.0}/tests/test_dry_run.py +1 -1
  204. amicus-0.4.0/tests/test_envspec.py +208 -0
  205. {amicus-0.3.0 → amicus-0.4.0}/tests/test_errors.py +3 -3
  206. {amicus-0.3.0 → amicus-0.4.0}/tests/test_fastmcp_argument_log.py +9 -15
  207. {amicus-0.3.0 → amicus-0.4.0}/tests/test_finalize.py +84 -20
  208. {amicus-0.3.0 → amicus-0.4.0}/tests/test_fingerprint.py +3 -3
  209. amicus-0.4.0/tests/test_import_contracts.py +47 -0
  210. {amicus-0.3.0 → amicus-0.4.0}/tests/test_isolation.py +1 -1
  211. {amicus-0.3.0 → amicus-0.4.0}/tests/test_job_tools.py +99 -3
  212. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_adapter.py +3 -3
  213. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_argv_differential.py +5 -5
  214. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_cli.py +2 -2
  215. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_config.py +12 -9
  216. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_contract.py +2 -2
  217. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_models.py +1 -2
  218. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_result_differential.py +15 -3
  219. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_status.py +4 -2
  220. {amicus-0.3.0 → amicus-0.4.0}/tests/test_lifecycle.py +7 -7
  221. {amicus-0.3.0 → amicus-0.4.0}/tests/test_log_redaction.py +42 -26
  222. {amicus-0.3.0 → amicus-0.4.0}/tests/test_manifest.py +8 -7
  223. {amicus-0.3.0 → amicus-0.4.0}/tests/test_migration_doc.py +21 -15
  224. {amicus-0.3.0 → amicus-0.4.0}/tests/test_obs.py +8 -1
  225. {amicus-0.3.0 → amicus-0.4.0}/tests/test_packaging.py +19 -28
  226. {amicus-0.3.0 → amicus-0.4.0}/tests/test_plugin.py +2 -2
  227. amicus-0.4.0/tests/test_poll_hint.py +57 -0
  228. {amicus-0.3.0 → amicus-0.4.0}/tests/test_prepare.py +1 -1
  229. {amicus-0.3.0 → amicus-0.4.0}/tests/test_registry.py +1 -1
  230. {amicus-0.3.0 → amicus-0.4.0}/tests/test_release_state.py +357 -47
  231. {amicus-0.3.0 → amicus-0.4.0}/tests/test_review.py +1 -1
  232. {amicus-0.3.0 → amicus-0.4.0}/tests/test_run.py +4 -5
  233. amicus-0.4.0/tests/test_sdk_in_tree.py +183 -0
  234. {amicus-0.3.0 → amicus-0.4.0}/tests/test_skill_contract.py +3 -3
  235. amicus-0.4.0/tests/test_structured.py +111 -0
  236. {amicus-0.3.0 → amicus-0.4.0}/tests/test_surface_honesty.py +41 -1
  237. {amicus-0.3.0 → amicus-0.4.0}/tests/test_sync_tools.py +27 -0
  238. {amicus-0.3.0 → amicus-0.4.0}/tests/test_worker.py +114 -1
  239. {amicus-0.3.0 → amicus-0.4.0}/tests/test_workspace.py +58 -0
  240. {amicus-0.3.0 → amicus-0.4.0}/uv.lock +13 -27
  241. amicus-0.3.0/src/amicus/jobs/__init__.py +0 -1
  242. amicus-0.3.0/src/amicus/jobs/polling.py +0 -36
  243. amicus-0.3.0/src/amicus/schemas/fingerprint.py +0 -62
  244. amicus-0.3.0/src/amicus/schemas/structured.py +0 -64
  245. amicus-0.3.0/tests/test_claude_golden_envelope.py +0 -79
  246. amicus-0.3.0/tests/test_claude_normalize.py +0 -86
  247. amicus-0.3.0/tests/test_envspec.py +0 -93
  248. amicus-0.3.0/tests/test_import_contracts.py +0 -17
  249. amicus-0.3.0/tests/test_poll_hint.py +0 -38
  250. amicus-0.3.0/tests/test_structured.py +0 -44
  251. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-docs/SKILL.md +0 -0
  252. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-docs/references/design-workflow.md +0 -0
  253. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-docs/references/docs-checklist.md +0 -0
  254. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-docs/references/examples.md +0 -0
  255. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-docs/references/review-workflow.md +0 -0
  256. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-docs/tests/scenarios.md +0 -0
  257. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/SKILL.md +0 -0
  258. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/decisions/001-github-fact-sheet.md +0 -0
  259. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/audit-workflow.md +0 -0
  260. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/config-checklist.md +0 -0
  261. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/examples/README.md +0 -0
  262. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/examples/codeowners.md +0 -0
  263. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/examples/harness-deny.md +0 -0
  264. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/examples/identity.md +0 -0
  265. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/examples/repo-files.md +0 -0
  266. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/examples/required-checks.md +0 -0
  267. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/examples/rulesets.md +0 -0
  268. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/examples/workflows.md +0 -0
  269. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/operating-playbook.md +0 -0
  270. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/setup-workflow.md +0 -0
  271. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/references/threat-model.md +0 -0
  272. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/tests/check_authority.py +0 -0
  273. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-github/tests/scenarios.md +0 -0
  274. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/SKILL.md +0 -0
  275. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/decisions/001-mcp-2026-07-28-rebase.md +0 -0
  276. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/decisions/002-machine-code-rename-rationale.md +0 -0
  277. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/decisions/003-offending-value-omission.md +0 -0
  278. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/decisions/004-ownership-boundaries.md +0 -0
  279. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/references/contract-checklist.md +0 -0
  280. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/references/design-workflow.md +0 -0
  281. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/references/examples.md +0 -0
  282. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/references/mcp-2025-11-25-compat.md +0 -0
  283. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/references/mcp-vs-cli.md +0 -0
  284. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/references/native-wire-shapes.md +0 -0
  285. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/references/review-workflow.md +0 -0
  286. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/references/vocabulary.md +0 -0
  287. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/check_fact_sync.py +0 -0
  288. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/check_rule_ids.py +0 -0
  289. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/check_stale_terms.py +0 -0
  290. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/fixtures/github_issues.json +0 -0
  291. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/fixtures/github_repo_resource.json +0 -0
  292. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/rule-ids.txt +0 -0
  293. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-baseline.md +0 -0
  294. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-outputschema-error.md +0 -0
  295. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-with-skill.md +0 -0
  296. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario2-baseline.md +0 -0
  297. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario2-with-skill.md +0 -0
  298. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario3-baseline.md +0 -0
  299. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario3-with-skill.md +0 -0
  300. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario4-baseline.md +0 -0
  301. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario4-with-skill.md +0 -0
  302. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario5-baseline.md +0 -0
  303. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario5-with-skill.md +0 -0
  304. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario6-baseline.md +0 -0
  305. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario6-with-skill.md +0 -0
  306. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario7-trigger.md +0 -0
  307. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario1-baseline.md +0 -0
  308. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario1-with-skill.md +0 -0
  309. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario3-baseline.md +0 -0
  310. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario3-with-skill.md +0 -0
  311. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario5-baseline.md +0 -0
  312. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario5-with-skill.md +0 -0
  313. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-30-scenario1-with-skill.md +0 -0
  314. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-30-scenario8-severity-calibration.md +0 -0
  315. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/scenarios.md +0 -0
  316. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/test_check_fact_sync.py +0 -0
  317. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/test_check_rule_ids.py +0 -0
  318. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/test_validate_fixture.py +0 -0
  319. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/agent-friendly-mcp/tests/validate_fixture.py +0 -0
  320. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/SKILL.md +0 -0
  321. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/agents/openai.yaml +0 -0
  322. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/references/example-audit.md +0 -0
  323. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/rescore-2026-08-06/preregistration.md +0 -0
  324. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/rescore-2026-08-06/results.md +0 -0
  325. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario1-baseline.md +0 -0
  326. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario1-with-skill.md +0 -0
  327. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario2-baseline.md +0 -0
  328. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario2-with-skill.md +0 -0
  329. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario3-baseline.md +0 -0
  330. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario3-with-skill.md +0 -0
  331. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario4-baseline.md +0 -0
  332. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario4-with-skill.md +0 -0
  333. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario5-baseline.md +0 -0
  334. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario5-with-skill.md +0 -0
  335. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario6-baseline.md +0 -0
  336. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario6-with-skill.md +0 -0
  337. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario7-baseline.md +0 -0
  338. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario7-with-skill.md +0 -0
  339. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario8-baseline.md +0 -0
  340. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario8-with-skill.md +0 -0
  341. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario9-trigger.md +0 -0
  342. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-06-scenario1-with-skill.md +0 -0
  343. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-06-scenario6-with-skill.md +0 -0
  344. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-confirmation-r1-both-directions.md +0 -0
  345. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario1-with-skill.md +0 -0
  346. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario2-with-skill.md +0 -0
  347. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario5-with-skill.md +0 -0
  348. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario6-with-skill.md +0 -0
  349. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario7-with-skill.md +0 -0
  350. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario8-with-skill.md +0 -0
  351. {amicus-0.3.0 → amicus-0.4.0}/.agents/skills/separating-context-from-constraints/tests/scenarios.md +0 -0
  352. {amicus-0.3.0 → amicus-0.4.0}/.claude-plugin/marketplace.json +0 -0
  353. {amicus-0.3.0 → amicus-0.4.0}/.gitattributes +0 -0
  354. {amicus-0.3.0 → amicus-0.4.0}/.github/CODEOWNERS +0 -0
  355. {amicus-0.3.0 → amicus-0.4.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  356. {amicus-0.3.0 → amicus-0.4.0}/.github/copilot-instructions.md +0 -0
  357. {amicus-0.3.0 → amicus-0.4.0}/.github/workflows/ci.yml +0 -0
  358. {amicus-0.3.0 → amicus-0.4.0}/.github/workflows/codeql.yml +0 -0
  359. {amicus-0.3.0 → amicus-0.4.0}/.github/workflows/dependency-review.yml +0 -0
  360. {amicus-0.3.0 → amicus-0.4.0}/.github/workflows/publish.yml +0 -0
  361. {amicus-0.3.0 → amicus-0.4.0}/.gitignore +0 -0
  362. {amicus-0.3.0 → amicus-0.4.0}/CLAUDE.md +0 -0
  363. {amicus-0.3.0 → amicus-0.4.0}/LICENSE +0 -0
  364. {amicus-0.3.0 → amicus-0.4.0}/commands/amicus/adversarial.md +0 -0
  365. {amicus-0.3.0 → amicus-0.4.0}/commands/amicus/consult.md +0 -0
  366. {amicus-0.3.0 → amicus-0.4.0}/commands/amicus/delegate-async.md +0 -0
  367. {amicus-0.3.0 → amicus-0.4.0}/commands/amicus/delegate.md +0 -0
  368. {amicus-0.3.0 → amicus-0.4.0}/commands/amicus/dry-run.md +0 -0
  369. {amicus-0.3.0 → amicus-0.4.0}/commands/amicus/jobs.md +0 -0
  370. {amicus-0.3.0 → amicus-0.4.0}/commands/amicus/review.md +0 -0
  371. {amicus-0.3.0 → amicus-0.4.0}/commands/amicus/status.md +0 -0
  372. {amicus-0.3.0 → amicus-0.4.0}/docs/2026-09-04-naming-and-scoping-notes.md +0 -0
  373. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0001-annotations-follow-the-worst-enabled-backend.md +0 -0
  374. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0002-backend-options-is-a-closed-superset.md +0 -0
  375. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0004-tasks-and-jobs.md +0 -0
  376. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0005-error-envelope-and-repair-precedence.md +0 -0
  377. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0006-fingerprint-and-surface-digest.md +0 -0
  378. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0007-m1-codex-port-decisions.md +0 -0
  379. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0008-m2-jobs-surface-decisions.md +0 -0
  380. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0009-m3-kimi-port-decisions.md +0 -0
  381. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0010-m4-claude-port-decisions.md +0 -0
  382. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0011-m5-tasks-decisions.md +0 -0
  383. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0012-m6-packaging-decisions.md +0 -0
  384. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0013-proceed-without-trademark-clearance.md +0 -0
  385. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0014-release-predicate-on-the-tag.md +0 -0
  386. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0016-skill-rules-are-a-complete-contract.md +0 -0
  387. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0017-an-unreadable-machine-enum-falls-to-its-own-floor.md +0 -0
  388. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0018-the-catalog-carries-a-ttl-and-resource-reads-do-not.md +0 -0
  389. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0019-review-results-disclose-coverage-as-a-field.md +0 -0
  390. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0020-idempotency-keys-on-the-sync-tools.md +0 -0
  391. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0021-repair-arguments-are-a-complete-call.md +0 -0
  392. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0022-consume-reports-its-discard-outcome.md +0 -0
  393. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0024-prose-list-loss-is-disclosed-never-folded.md +0 -0
  394. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0025-success-meta-is-sparse-on-every-tool.md +0 -0
  395. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0026-a-not-run-review-carries-no-confidence-rating.md +0 -0
  396. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0027-every-instructions-rule-fits-the-shown-prefix.md +0 -0
  397. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/0028-a-deprecated-tool-keeps-its-record-beside-one-marker.md +0 -0
  398. {amicus-0.3.0 → amicus-0.4.0}/docs/adr/README.md +0 -0
  399. {amicus-0.3.0 → amicus-0.4.0}/docs/claude-help/2.1.263/FINDINGS.md +0 -0
  400. {amicus-0.3.0 → amicus-0.4.0}/docs/claude-help/2.1.263/claude-help.txt +0 -0
  401. {amicus-0.3.0 → amicus-0.4.0}/docs/claude-help/2.1.263/claude-version.txt +0 -0
  402. {amicus-0.3.0 → amicus-0.4.0}/docs/claude-help/2.1.263/envelope-shape.json +0 -0
  403. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/claude-code/2.1.263/FINDINGS.md +0 -0
  404. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/claude-code/2.1.263/connection.log +0 -0
  405. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/claude-code/2.1.263/host-output.json +0 -0
  406. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/codex/0.153.4/FINDINGS.md +0 -0
  407. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/codex/0.153.4/connection.log +0 -0
  408. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/codex/0.153.4/host-output.jsonl +0 -0
  409. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/notes.md +0 -0
  410. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/server.log +0 -0
  411. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/transcript.md +0 -0
  412. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/install-smoke/claude-code/2.1.263/notes.md +0 -0
  413. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/install-smoke/claude-code/2.1.263/server.log +0 -0
  414. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/install-smoke/claude-code/2.1.263/transcript.md +0 -0
  415. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/install-smoke/codex/0.153.4/notes.md +0 -0
  416. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/install-smoke/codex/0.153.4/server.log +0 -0
  417. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/install-smoke/codex/0.153.4/transcript.md +0 -0
  418. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/notes.md +0 -0
  419. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/server.log +0 -0
  420. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/transcript.md +0 -0
  421. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s6-old-text-new-grader/claude-code/2.1.263/notes.md +0 -0
  422. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s6-old-text-new-grader/claude-code/2.1.263/server.log +0 -0
  423. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s6-old-text-new-grader/claude-code/2.1.263/transcript.md +0 -0
  424. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/notes.md +0 -0
  425. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/server.log +0 -0
  426. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/transcript.md +0 -0
  427. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/notes.md +0 -0
  428. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/server.log +0 -0
  429. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/transcript.md +0 -0
  430. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/notes.md +0 -0
  431. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/server.log +0 -0
  432. {amicus-0.3.0 → amicus-0.4.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/transcript.md +0 -0
  433. {amicus-0.3.0 → amicus-0.4.0}/docs/kimi-help/0.41.0/FINDINGS.md +0 -0
  434. {amicus-0.3.0 → amicus-0.4.0}/docs/kimi-help/0.41.0/kimi-help.txt +0 -0
  435. {amicus-0.3.0 → amicus-0.4.0}/docs/kimi-help/0.41.0/kimi-version.txt +0 -0
  436. {amicus-0.3.0 → amicus-0.4.0}/docs/kimi-help/0.41.0/provider-list-shape.json +0 -0
  437. {amicus-0.3.0 → amicus-0.4.0}/docs/kimi-help/0.42.0/FINDINGS.md +0 -0
  438. {amicus-0.3.0 → amicus-0.4.0}/docs/kimi-help/0.42.0/kimi-help.txt +0 -0
  439. {amicus-0.3.0 → amicus-0.4.0}/docs/kimi-help/0.42.0/kimi-version.txt +0 -0
  440. {amicus-0.3.0 → amicus-0.4.0}/docs/kimi-help/0.42.0/provider-list-shape.json +0 -0
  441. {amicus-0.3.0 → amicus-0.4.0}/docs/kimi-help/0.43.1/FINDINGS.md +0 -0
  442. {amicus-0.3.0 → amicus-0.4.0}/docs/kimi-help/0.43.1/kimi-help.txt +0 -0
  443. {amicus-0.3.0 → amicus-0.4.0}/docs/kimi-help/0.43.1/kimi-version.txt +0 -0
  444. {amicus-0.3.0 → amicus-0.4.0}/docs/kimi-help/0.43.1/provider-list-shape.json +0 -0
  445. {amicus-0.3.0 → amicus-0.4.0}/docs/reviews/2026-09-07-agent-friendly-mcp-walk.md +0 -0
  446. {amicus-0.3.0 → amicus-0.4.0}/docs/superpowers/plans/2026-09-04-amicus-execution-model.md +0 -0
  447. {amicus-0.3.0 → amicus-0.4.0}/scripts/capture_claude_differentials.py +0 -0
  448. {amicus-0.3.0 → amicus-0.4.0}/scripts/capture_codex_differentials.py +0 -0
  449. {amicus-0.3.0 → amicus-0.4.0}/scripts/capture_kimi_differentials.py +0 -0
  450. {amicus-0.3.0 → amicus-0.4.0}/scripts/check_github_actions_pinning.py +0 -0
  451. {amicus-0.3.0 → amicus-0.4.0}/scripts/record_live_gate_evidence.py +0 -0
  452. {amicus-0.3.0 → amicus-0.4.0}/skills/collaborating-with-amicus/references/active-workflows.md +0 -0
  453. {amicus-0.3.0 → amicus-0.4.0}/skills/collaborating-with-amicus/references/independent-attempt.md +0 -0
  454. {amicus-0.3.0 → amicus-0.4.0}/skills/collaborating-with-amicus/references/review-revise.md +0 -0
  455. {amicus-0.3.0 → amicus-0.4.0}/skills/collaborating-with-amicus/references/reviewing-a-returned-diff.md +0 -0
  456. {amicus-0.3.0 → amicus-0.4.0}/skills/collaborating-with-amicus/references/server-down-fallback.md +0 -0
  457. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/appstate.py +0 -0
  458. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/claude/binary.py +0 -0
  459. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/claude/models.py +0 -0
  460. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/codex/options.py +0 -0
  461. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/kimi/binary.py +0 -0
  462. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/backends/kimi/options.py +0 -0
  463. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/compaction.py +0 -0
  464. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/orchestration/__init__.py +0 -0
  465. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/packaging.py +0 -0
  466. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/py.typed +0 -0
  467. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/result_format_snapshot.py +0 -0
  468. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/schemas/__init__.py +0 -0
  469. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/schemas/field_policy.py +0 -0
  470. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/schemas/instructions.py +0 -0
  471. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/schemas/publish.py +0 -0
  472. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/server.py +0 -0
  473. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/tools/__init__.py +0 -0
  474. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/tools/_guard.py +0 -0
  475. {amicus-0.3.0 → amicus-0.4.0}/src/amicus/tools/resources.py +0 -0
  476. {amicus-0.3.0 → amicus-0.4.0}/tests/fixtures/claude_differentials.json +0 -0
  477. {amicus-0.3.0 → amicus-0.4.0}/tests/fixtures/claude_golden_envelope.json +0 -0
  478. {amicus-0.3.0 → amicus-0.4.0}/tests/fixtures/codex_differentials.json +0 -0
  479. {amicus-0.3.0 → amicus-0.4.0}/tests/fixtures/fakebackend/pyproject.toml +0 -0
  480. {amicus-0.3.0 → amicus-0.4.0}/tests/fixtures/kimi_differentials.json +0 -0
  481. {amicus-0.3.0/tests/support → amicus-0.4.0/tests/sdk}/__init__.py +0 -0
  482. {amicus-0.3.0 → amicus-0.4.0}/tests/support/fake_claude.py +0 -0
  483. {amicus-0.3.0 → amicus-0.4.0}/tests/support/fake_codex.py +0 -0
  484. {amicus-0.3.0 → amicus-0.4.0}/tests/support/fake_kimi.py +0 -0
  485. {amicus-0.3.0 → amicus-0.4.0}/tests/test_check_github_actions_pinning.py +0 -0
  486. {amicus-0.3.0 → amicus-0.4.0}/tests/test_claude_binary.py +0 -0
  487. {amicus-0.3.0 → amicus-0.4.0}/tests/test_claude_live.py +0 -0
  488. {amicus-0.3.0 → amicus-0.4.0}/tests/test_claude_models.py +0 -0
  489. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codex_live.py +0 -0
  490. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codex_models.py +0 -0
  491. {amicus-0.3.0 → amicus-0.4.0}/tests/test_codex_plugin.py +0 -0
  492. {amicus-0.3.0 → amicus-0.4.0}/tests/test_commands.py +0 -0
  493. {amicus-0.3.0 → amicus-0.4.0}/tests/test_compaction.py +0 -0
  494. {amicus-0.3.0 → amicus-0.4.0}/tests/test_conftest_guards.py +0 -0
  495. {amicus-0.3.0 → amicus-0.4.0}/tests/test_envelope.py +0 -0
  496. {amicus-0.3.0 → amicus-0.4.0}/tests/test_field_policy.py +0 -0
  497. {amicus-0.3.0 → amicus-0.4.0}/tests/test_guard.py +0 -0
  498. {amicus-0.3.0 → amicus-0.4.0}/tests/test_host_captures.py +0 -0
  499. {amicus-0.3.0 → amicus-0.4.0}/tests/test_instructions.py +0 -0
  500. {amicus-0.3.0 → amicus-0.4.0}/tests/test_job_durability.py +0 -0
  501. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_binary.py +0 -0
  502. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_live.py +0 -0
  503. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_normalize.py +0 -0
  504. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_plugin.py +0 -0
  505. {amicus-0.3.0 → amicus-0.4.0}/tests/test_kimi_sync_tools.py +0 -0
  506. {amicus-0.3.0 → amicus-0.4.0}/tests/test_live_gate_report.py +0 -0
  507. {amicus-0.3.0 → amicus-0.4.0}/tests/test_live_suite_hygiene.py +0 -0
  508. {amicus-0.3.0 → amicus-0.4.0}/tests/test_lookup.py +0 -0
  509. {amicus-0.3.0 → amicus-0.4.0}/tests/test_meta.py +0 -0
  510. {amicus-0.3.0 → amicus-0.4.0}/tests/test_middleware.py +0 -0
  511. {amicus-0.3.0 → amicus-0.4.0}/tests/test_options.py +0 -0
  512. {amicus-0.3.0 → amicus-0.4.0}/tests/test_paid_tools.py +0 -0
  513. {amicus-0.3.0 → amicus-0.4.0}/tests/test_params.py +0 -0
  514. {amicus-0.3.0 → amicus-0.4.0}/tests/test_prompts.py +0 -0
  515. {amicus-0.3.0 → amicus-0.4.0}/tests/test_publish.py +0 -0
  516. {amicus-0.3.0 → amicus-0.4.0}/tests/test_release_evidence.py +0 -0
  517. {amicus-0.3.0 → amicus-0.4.0}/tests/test_request.py +0 -0
  518. {amicus-0.3.0 → amicus-0.4.0}/tests/test_resources.py +0 -0
  519. {amicus-0.3.0 → amicus-0.4.0}/tests/test_result_format.py +0 -0
  520. {amicus-0.3.0 → amicus-0.4.0}/tests/test_results.py +0 -0
  521. {amicus-0.3.0 → amicus-0.4.0}/tests/test_review_artifact.py +0 -0
  522. {amicus-0.3.0 → amicus-0.4.0}/tests/test_server.py +0 -0
  523. {amicus-0.3.0 → amicus-0.4.0}/tests/test_surface.py +0 -0
  524. {amicus-0.3.0 → amicus-0.4.0}/tests/test_taskmap.py +0 -0
  525. {amicus-0.3.0 → amicus-0.4.0}/tests/test_tasks_client.py +0 -0
  526. {amicus-0.3.0 → amicus-0.4.0}/tests/test_tasks_spike.py +0 -0
  527. {amicus-0.3.0 → amicus-0.4.0}/tests/test_wheel_seam.py +0 -0
  528. {amicus-0.3.0 → amicus-0.4.0}/tests/test_wire_shape.py +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amicus",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "One MCP server for every second-opinion model: consult, review, and delegate with the backend as a parameter.",
5
5
  "author": { "name": "Brian Connelly", "url": "https://github.com/briandconnelly" },
6
6
  "homepage": "https://github.com/briandconnelly/amicus",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amicus",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "One MCP server for every second-opinion model: consult, review, and delegate with the backend as a parameter.",
5
5
  "author": { "name": "Brian Connelly", "url": "https://github.com/briandconnelly" },
6
6
  "homepage": "https://github.com/briandconnelly/amicus",
@@ -15,6 +15,17 @@ updates:
15
15
  dependency-type: "development"
16
16
  python-runtime:
17
17
  dependency-type: "production"
18
+ # pyproject.toml caps fastmcp and mcp to a minor line because fastmcp
19
+ # documents breaking changes in minor releases. Widening a cap is a
20
+ # hand-written upgrade PR (#106), so Dependabot is told not to propose the
21
+ # minor or major that would move it; patch releases inside the cap still
22
+ # arrive through the python-runtime group. `ignore` also covers security
23
+ # updates, which changes nothing: the cap already excludes those versions.
24
+ ignore:
25
+ - dependency-name: "fastmcp"
26
+ update-types: ["version-update:semver-minor", "version-update:semver-major"]
27
+ - dependency-name: "mcp"
28
+ update-types: ["version-update:semver-minor", "version-update:semver-major"]
18
29
 
19
30
  # GitHub Actions used in workflows (keeps SHA pins current).
20
31
  - package-ecosystem: "github-actions"
@@ -37,3 +37,20 @@ jobs:
37
37
  run: uv run lint-imports
38
38
  - name: Test (95% coverage floor)
39
39
  run: uv run pytest
40
+
41
+ marketplace-pointer:
42
+ name: marketplace pointer
43
+ # Only a pull request has a base to compare the pointer against.
44
+ if: github.event_name == 'pull_request'
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
48
+ with:
49
+ persist-credentials: false
50
+ # Full history and tags: the pointer's tag is checked, and the base commit is read.
51
+ fetch-depth: 0
52
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
53
+ - name: The marketplace pointer is consistent and never moves backwards
54
+ env:
55
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
56
+ run: uv run python scripts/check_release_state.py --base "$BASE_SHA"
@@ -4,7 +4,7 @@
4
4
  "command": "uvx",
5
5
  "args": [
6
6
  "--from",
7
- "git+https://github.com/briandconnelly/amicus.git@v0.2.0",
7
+ "git+https://github.com/briandconnelly/amicus.git@v0.4.0",
8
8
  "amicus-mcp"
9
9
  ],
10
10
  "env_vars": [
@@ -31,10 +31,11 @@ The rules bind; the context after them explains and points elsewhere.
31
31
  This binds amicus's own handling and everything it commits, including host captures and eval prompt bodies, which are recorded as an id and a `sha256` instead.
32
32
  A backend's own native carrier is exempt where that backend offers no alternative and the carrier is disclosed in its `CARRIERS` string and surfaced on `amicus_backends`; the two that exist today are Kimi's handshake file, because kimi ignores stdin, and Codex's `-c developer_instructions` argv token.
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
- 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.
34
+ No exemption reaches text that amicus itself, or anyone working in this repository, copies, derives or replays from a prompt anyone sent: that stays bound however it is later stored or relabelled.
35
+ A backend's answer, and the result amicus builds from it — its parsed fields and, for a delegate, the diff captured from the worktree — is output, not a prompt input, even where it quotes or paraphrases one: amicus keeps it only on the job record (`result.json`, written through a staging file in the same directory), under the job retention the tool surface discloses (`AMICUS_JOB_TTL`, the per-workspace cap, `amicus_job_consume_result`), and writes it to no log, argv or other file; what this repository commits of an answer stays bound by the sentence before this one wherever the answer repeats a prompt anyone sent.
35
36
  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` 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
+ The literals are `pyproject.toml`, `src/amicus/__init__.py`, `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json` and `.mcp.json`'s `--from` pin, which names the tag of the release being made; README's "Any other MCP client" example moves with that pin.
38
+ `.claude-plugin/marketplace.json`'s pointer is NOT one of them; rule 24 governs it, and a release must not touch it.
38
39
  `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.
39
40
  Only the maintainer merges that PR, and only the maintainer pushes the tag.
40
41
  Push the matching tag before any other work follows that merge: until it exists, `main` declares a version that has no release.
@@ -47,16 +48,20 @@ The rules bind; the context after them explains and points elsewhere.
47
48
  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.
48
49
  23. Never describe the rule-20 record, in any document or output, as proof that the live gates ran.
49
50
  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.
51
+ 24. `.claude-plugin/marketplace.json`'s plugin entry names a release that is already published, by `ref` and a `sha` equal to that tag's peeled commit, never the one being released, and it may never name a version newer than the one the tree declares.
52
+ A release PR under rule 19 leaves it untouched; advance it to the new tag in its own `chore(release):` PR after that tag is published and its install has been checked, and a release is not complete until that PR merges.
52
53
  That PR is not a release: it needs no rule-20 evidence, because it moves a pointer to a tag that already exists.
54
+ Until the 0.4.0 pointer PR merges the entry's `source` is `"./"`; for 0.4.0 only, nothing else merges to `main` between the release PR and that pointer PR.
53
55
 
54
56
  ## Context
55
57
 
56
58
  ### What this is
57
59
 
58
- One MCP server for every second-opinion model: a verb-first tool surface with the backend as a parameter, built on FastMCP and the [pontonier](https://github.com/briandconnelly/pontonier) backend SDK.
60
+ One MCP server for every second-opinion model: a verb-first tool surface with the backend as a parameter, built on FastMCP and its own in-tree backend SDK, `amicus.sdk`.
59
61
  The package is `amicus` under `src/`; each backend is a plugin under `src/amicus/backends/<id>/` behind the `BackendPlugin` seam in `src/amicus/plugin.py`.
62
+ `amicus.sdk` (under `src/amicus/sdk/`) is the backend-facing layer: the backend protocol and contract, the error vocabulary, annotations and preflight, the subprocess runtime with stream capping, redaction, path-alias sanitizing and a bounded JSON reader, and the conformance kit a plugin must pass before the registry will use it.
63
+ It was copied from [pontonier](https://github.com/briandconnelly/pontonier) v0.9.0, and amicus no longer depends on pontonier (ADR 0029).
64
+ ADR 0030 holds it to that role, so what only the server uses lives in the amicus package that owns it: the job store is `amicus.jobs`, worktrees and diff gathering are `amicus.orchestration`, and the fingerprint mechanics are `amicus.schemas.fingerprint`.
60
65
  Import boundaries between layers are enforced by the import-linter contracts in `pyproject.toml`.
61
66
  A backend's own prompt carriers (for Codex, the developer-instructions argv token and the stdin prompt) are disclosed on `amicus_backends`.
62
67
 
@@ -76,12 +81,14 @@ The README's "Where things are" table indexes the rest.
76
81
 
77
82
  ### Releases
78
83
 
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.
84
+ Users add this repository as a plugin marketplace, and a host copies the plugin into a directory keyed by `plugin.json`'s version, re-reading it only when that version changes.
85
+ ADR 0031 is shaped by that fact, established by probe on Claude Code and Codex, and it supersedes ADR 0015, which had assumed a host re-reads `.mcp.json`.
86
+ Under ADR 0015 the pin trailed the release, so an install taken before the pin-move PR, or anywhere mid-cycle, kept running an older server than its own skills (issue #117).
87
+ So `.mcp.json` names its own release, and from 0.4.0 the marketplace entry pins a published tag by `ref` and `sha`, so hosts install that self-consistent tag snapshot rather than `main`.
88
+ Until the 0.4.0 pointer PR merges, the entry is still `"./"` and hosts install `main`, which is why rule 24 bars anything else from merging during that one transition.
89
+ Rule 24's invariant, that the pointer users follow names an already-published release, moved with it from `.mcp.json` to the marketplace entry.
90
+ `sha` is required because a host serves `sha` over a disagreeing `ref` without complaint, and the `v*` ruleset's admin bypass means a tag can be moved.
91
+ `uvx` reuses a cached tool environment without querying any index, so the version in `.mcp.json`'s requirement string is still what makes an existing install pick up a new server.
85
92
  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.
86
93
  That evidence is an honest-mistake guard, not an attestation; it is a local file its author can write by hand.
87
94
  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.
@@ -101,6 +108,7 @@ Those are held by the platform controls around the release — rule 21's ruleset
101
108
  ### Siblings
102
109
 
103
110
  The sibling checkouts named in rule 17 are read for porting, and their virtualenvs are used to capture differential fixtures (`scripts/capture_codex_differentials.py` runs inside codex-in-claude's).
111
+ `~/projects/pontonier` is a sibling in the same sense: amicus no longer depends on it, its `v0.9.0` tag is where `amicus.sdk` came from, and it stays published only for the three older siblings until they are archived (ADR 0029).
104
112
 
105
113
  ### Local hooks
106
114
 
@@ -20,6 +20,189 @@ per-change, as its own lead says.
20
20
 
21
21
  ## [Unreleased]
22
22
 
23
+ ## [0.4.0] - 2026-09-18
24
+
25
+ Across this release the discovery surface moves `amicus/0.1/schema-30`, what 0.3.0 shipped, to
26
+ `amicus/0.1/schema-35`, and stored job results move `RESULT_FORMAT` 6 to 7, so a job result 0.3.0
27
+ stored cannot be delivered after upgrading. The entries labelled **Breaking** are the changes a
28
+ caller or operator using 0.3.0 has to handle, and `docs/MIGRATION.md` ("Upgrading from 0.3.0")
29
+ walks through each.
30
+
31
+ ### Added
32
+
33
+ - The `collaborating-with-amicus` skill gains a blind-comparison workflow
34
+ (`references/blind-comparison.md`): two or more finalized candidates, compared by a backend
35
+ that wrote none of them, blinded, against criteria fixed before the call, returning
36
+ per-criterion reasons and one preference the host verifies as a finding rather than a score it
37
+ adopts. A new root rule says a backend's stated preference never stands in for the decision.
38
+ No tool or server surface changes and `FINGERPRINT` does not move.
39
+
40
+ ### Changed
41
+
42
+ - Every paid tool, sync and async, and the `detail` parameter now disclose that the job record
43
+ keeps the backend's whole answer whatever `detail` delivered it, that the answer can quote the
44
+ caller's inputs, and what ends it: expiry under `AMICUS_JOB_TTL` (an expired record is removed
45
+ on a later job call, not by a daemon), the per-workspace cap or `amicus_job_consume_result`
46
+ (#163, ADR 0035). Nothing stored or delivered changes: the record has kept the answer since M2,
47
+ and the decision recorded is that rule 18 binds the inputs amicus writes, not the answer a
48
+ backend returns. **Surface**: `FINGERPRINT` moves to schema-35 for the description text.
49
+ - amicus no longer depends on `pontonier`. Its backend SDK is now part of amicus, as
50
+ `amicus.sdk` (#13, ADR 0029): the same code as pontonier 0.9.0, copied from its `v0.9.0`
51
+ tag with the imports rewritten. Nothing on the wire or in a stored job result changes, and
52
+ `FINGERPRINT` does not move. A third-party backend distribution imports the SDK types from
53
+ `amicus.sdk` instead of `pontonier` and declares plugin API version 2: `PLUGIN_API_VERSION`
54
+ moved from 1 to 2, so the registry rejects a plugin that pins `api_version=1` (#115 covers
55
+ one that leaves it unset). No release can enable a third-party backend yet, so no running
56
+ deployment is affected. SDK log records are no longer named `pontonier.*` in stderr and
57
+ `AMICUS_LOG_FILE`, since the log format prints the logger name, which matters for an
58
+ operator who filters logs by name: they are named `amicus.sdk.*`, except the job store and
59
+ its idempotency index, which are `amicus.jobs.store` and `amicus.jobs.idempotency`. These
60
+ `amicus.sdk` import paths are not yet stable for a third-party backend. ADR 0030 settles
61
+ where they end up, and this release leaves that move finished (#118–#123): `amicus.sdk`
62
+ holds what a backend imports — the backend protocol and contract, the error vocabulary,
63
+ annotations and preflight, the subprocess runtime, stream capping, redaction, path-alias
64
+ sanitizing and a bounded JSON reader — plus the conformance kit, which is the one thing
65
+ there that a backend does not import: the registry imports it and runs it against a plugin
66
+ before it will use one. The job store, the git layer, the fingerprint mechanics and the
67
+ prompt framings live in the amicus package that owns each. Of the pontonier-named literals
68
+ the copy brought with it, one was visible outside the code: the throwaway directory amicus
69
+ creates to run git with its hooks disabled is now named `amicus-nohooks-*` under the system
70
+ temp dir, not `pontonier-nohooks-*`. Nothing keys on that name.
71
+
72
+ ### Removed
73
+
74
+ - **Breaking.** The three siblings' environment names — `CODEX_IN_CLAUDE_*`, `MOONBRIDGE_*`
75
+ and `CLAUDE_IN_CODEX_*` — are no longer read (#176), as 0.3.0's warnings and
76
+ `docs/MIGRATION.md` said they would not be from 0.4.0. An operator who still sets one gets
77
+ the `AMICUS_*` default instead of the value, which for `CODEX_IN_CLAUDE_ISOLATION` or
78
+ `CLAUDE_IN_CODEX_CLAUDE_CONFIG` is looser than what was set. Each former name is now a
79
+ tombstone on the `AMICUS_*` declaration that replaced it: a name still set is reported by
80
+ `amicus_backends`, in `env_warnings` for a global setting and in the backend's
81
+ `status.warnings` for a backend one (so only while that backend is enabled and loaded),
82
+ naming the `AMICUS_*` name to set; its value is never read, not even to recognise a
83
+ placeholder, so it neither supplies the setting nor conflicts with the `AMICUS_*` value,
84
+ and the conflict error of the window is gone with it. The tombstones have no removal window: they
85
+ are the migration table's data and a diagnostic, not a compatibility path. The shim itself
86
+ (`EnvVar.legacy`) and the release guard that refuses a release at or past
87
+ `LEGACY_REMOVAL_VERSION` while an alias is declared both stay, so a later rename gets the
88
+ same window. `FINGERPRINT` moves to `schema-34` only because the `amicus_backends`
89
+ description no longer says "legacy-env warnings"; no schema changes.
90
+
91
+ ### Fixed
92
+
93
+ - **Surface.** A Claude budget stop no longer reports `input_tokens: 0` and
94
+ `output_tokens: 0` beside a nonzero `cost_usd` (#158). claude prints its top-level `usage`
95
+ block zeroed on that envelope while `modelUsage` carries the real counts, and its own
96
+ result schema names `modelUsage` as the accounting field, so `meta.usage` now comes from
97
+ `modelUsage` (summed across models) whenever at least one of its entries is an object,
98
+ and from the top-level block only when none is (ADR 0034). A field is read from one
99
+ block, never both: once `modelUsage` is in use, a field any one entry leaves out is
100
+ `null`, and a non-object entry beside an object one makes every count `null`. So an older
101
+ envelope whose `modelUsage` has no cache keys now reports `cached_input_tokens` and
102
+ `cache_creation_input_tokens` as `null` where it used to copy the block's numbers.
103
+ `budget_exceeded`'s message and repair, the `max_budget_usd` option description and the
104
+ `AMICUS_CLAUDE_MAX_BUDGET_USD` description now say claude checks the threshold only
105
+ between model calls, so one call can carry the estimated cost past it; none states an
106
+ overshoot bound, and the repair no longer suggests a 0.10-0.20 floor it had no evidence
107
+ for. The recorded 2.1.274 budget-stop envelope is `tests/fixtures/claude_budget_stop_envelope.json`,
108
+ documented in `docs/claude-help/2.1.274/`. `RESULT_FORMAT` does not move.
109
+
110
+ - Every tool that resolves a workspace no longer fails as a retryable `internal_error`
111
+ (`FileNotFoundError`) when the server process's working directory has been deleted under
112
+ it, as happens when the Claude Code worktree the server was started in is removed (#170).
113
+ The resolver now reads the process cwd only on the one branch where it decides the
114
+ outcome (no `workspace_root`, no client root, and `AMICUS_ALLOW_CWD_WORKSPACE=1`), so a
115
+ call that names its workspace never consults it. When that branch is reached and the cwd
116
+ is gone, the call fails as a non-temporary `invalid_workspace_root` whose message says to
117
+ pass `workspace_root`, configure an MCP root, or restart the server from an existing
118
+ directory, instead of a `retry_then_report` repair that could never succeed. No error
119
+ code was added and `FINGERPRINT` does not move.
120
+
121
+ - Codex usage-limit failures without a parseable relative delay now report
122
+ `retry_after_ms: null` with an `inspect_and_retry` repair instead of inventing a
123
+ 60-second delay for a reset that may be days away (#165). When codex states the reset
124
+ as a clock time (`try again at Sep 19th, 2026 8:37 AM.` or `try again at 12:39 PM.`),
125
+ that phrase is echoed in `error.message`, `error.details.reason` and the repair, marked
126
+ as a clock time with no time zone stated when it names none, so the caller can read the
127
+ reset it must wait for. Only a clock-time shape is echoed; other wording gets the generic
128
+ guidance. Explicit relative delays and the 60-second fallback for ordinary rate limits are
129
+ unchanged.
130
+
131
+ - Codex failure classification now reads backend error events and stderr instead of
132
+ matching authentication, contract-drift and rate-limit terms in model answers or tool
133
+ output (#166). Model prose can no longer override the backend's diagnosis or retry delay.
134
+ Generic failure details also exclude model and tool items, preventing that text from
135
+ being copied into a background job's stored error.
136
+ Plain-text startup diagnostics and error events containing only an HTTP status remain
137
+ supported. Neither `FINGERPRINT` nor `RESULT_FORMAT` moves.
138
+
139
+ - `amicus_backends` no longer reports `authenticated: false` whenever the Codex login-status
140
+ probe exits nonzero (#169). Only a recognized authentication failure reports `false`; a
141
+ configuration error or other probe failure reports `authenticated: null` and adds a sanitized
142
+ diagnostic to the backend's warnings. `FINGERPRINT` does not move.
143
+
144
+ - **Surface.** `amicus_review_changes` on the `claude` backend now defaults to
145
+ `backend_options.access = "readonly"` (#116, ADR 0032). On the previous `toolless` default a
146
+ review had no tool to read the code it was judging, and answered with tool-call markup
147
+ instead of the review: amicus reported `invalid_json`, or under the default
148
+ `config_mode = "inherit"` ran to the budget stop. A Claude review that omits `access` can now
149
+ read files with `Read`, `Grep` and `Glob`, inside and outside the workspace, which bypasses
150
+ diff redaction; pass `access: "toolless"` to keep the old behaviour for one call.
151
+ `amicus_consult` and `amicus_adversarial_review` still default to `toolless`, and setting
152
+ `AMICUS_CLAUDE_ACCESS` sets the default for every verb, reviews included. A structured Claude
153
+ review also now carries the output guardrails adversarial reviews already had, telling the
154
+ model never to simulate a tool call. `amicus_backends` reports `access` under
155
+ `default_by_verb`. `FINGERPRINT` moves to `amicus/0.1/schema-31`.
156
+ - **Breaking.** A review whose answer amicus cannot read as one JSON object is no longer
157
+ discarded (#139, ADR 0033). `amicus_review_changes` and `amicus_adversarial_review` used to
158
+ return `invalid_json` or `schema_violation`. They kept a 300-character preview of the answer,
159
+ lost the rest, and prescribed a retry that could fail the same way. They now return
160
+ `ok: true` with the new `review_status: unstructured`: `verdict` and `confidence` are
161
+ `unknown`, `findings` and the prose lists are empty with diagnostics saying nothing was
162
+ parsed, and the whole answer, redacted, is `raw_response.text`, at `detail="full"` on the call
163
+ or free from `amicus_job_result`. A caller that read the verdict after checking `ok` must now
164
+ handle this value. An answer that wraps exactly one object in a preamble, a fence or a
165
+ sign-off is now read as that object. A repeated key is still refused (#51). Only an empty
166
+ answer is still an error (`invalid_json`, or `empty_response` on Kimi), and
167
+ `schema_violation` is no longer a review outcome. `empty_response`, which Kimi already
168
+ returned for an empty answer, is now listed in the `error_codes` of every paid tool that can
169
+ select Kimi.
170
+ `RESULT_FORMAT` moves to 7 and `FINGERPRINT` to `amicus/0.1/schema-32`.
171
+
172
+ - A plugin install no longer runs an older release's server than its bundled skills (#117,
173
+ ADR 0031, superseding ADR 0015). Hosts key an installed plugin by `plugin.json`'s version and
174
+ do not re-read it until that version changes, so a plugin whose `.mcp.json` named the previous
175
+ release kept launching that older server. `.mcp.json` now names its own release, and after
176
+ 0.4.0 is published the marketplace entry pins that tag by `ref` and `sha`, so the installed
177
+ skills and server come from one release snapshot. Installs already stuck on an older server
178
+ recover when the 0.4.0 version change reaches them.
179
+
180
+ - **Security.** An exception's own text can no longer reach a background job's `stderr.log`
181
+ (#128). The job worker never called `obs.configure`, so nothing in that process installed
182
+ the handlers that withhold exception text, and an `amicus.*` record fell through to
183
+ `logging.lastResort` — which renders the exception's `str()` and a full traceback. The
184
+ worker's stdout and stderr are both `<job_dir>/stderr.log`, so that text was written to a
185
+ file the job keeps. The reachable call site is the SDK runtime's
186
+ `logger.error("stdout capture failed: %s", exc, exc_info=True)` on a capture failure, and
187
+ an exception raised inside a backend adapter can embed the prompt text that provoked it,
188
+ which AGENTS.md rule 18 forbids writing to a log. `_worker.main` now configures logging
189
+ before anything else it does, so such a record renders as the exception's type and its
190
+ frame locations, the same policy the server has always applied. The worker inherits the
191
+ server's environment, so it honours the same `AMICUS_LOG_LEVEL` and `AMICUS_LOG_FILE` —
192
+ except a *relative* `AMICUS_LOG_FILE`, which it drops: `logging.FileHandler` resolves a
193
+ relative path against the process's cwd, and the worker's cwd is the job directory, so
194
+ honouring it would leave a differently-located log file inside every job directory instead
195
+ of adding to the one file the operator asked for. An absolute path is honoured, and the
196
+ server's own handler is unaffected either way. Nothing about a job's result, status or
197
+ wire shape changes, and `FINGERPRINT` does not move.
198
+ - A `codex` run that hit its usage limit could fail as `backend_auth_required` instead of
199
+ `backend_rate_limited` (#160). The classifier checks authentication first and matched the bare
200
+ substring `401`, so any output carrying those digits, such as a token count of 14012, read as
201
+ "not authenticated". The repair then told the caller to log in again, and marked the failure
202
+ not temporary. A `401` now counts only as an HTTP status, and codex's own "could not be
203
+ refreshed" token failures are recognized as authentication failures. `FINGERPRINT` does not
204
+ move.
205
+
23
206
  ## [0.3.0] - 2026-09-15
24
207
 
25
208
  Across this release the discovery surface moves `amicus/0.1/schema-13`, what 0.2.0 shipped, to
@@ -532,7 +715,8 @@ per-change rather than net, so they also name intermediate states that no releas
532
715
  - The tagged publish path to pypi.org has never run. Only the TestPyPI dispatch path has been exercised.
533
716
  - 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.
534
717
 
535
- [Unreleased]: https://github.com/briandconnelly/amicus/compare/v0.3.0...HEAD
718
+ [Unreleased]: https://github.com/briandconnelly/amicus/compare/v0.4.0...HEAD
719
+ [0.4.0]: https://github.com/briandconnelly/amicus/compare/v0.3.0...v0.4.0
536
720
  [0.3.0]: https://github.com/briandconnelly/amicus/compare/v0.2.0...v0.3.0
537
721
  [0.2.0]: https://github.com/briandconnelly/amicus/compare/v0.1.0...v0.2.0
538
722
  [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.3.0
3
+ Version: 0.4.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
@@ -24,7 +24,6 @@ Requires-Python: >=3.11
24
24
  Requires-Dist: anyio>=4
25
25
  Requires-Dist: fastmcp<4.1,>=4.0
26
26
  Requires-Dist: mcp<2.3,>=2.1
27
- Requires-Dist: pontonier==0.9.0
28
27
  Requires-Dist: pydantic>=2
29
28
  Description-Content-Type: text/markdown
30
29
 
@@ -74,7 +73,7 @@ The plugins launch the server from a published release tag, pinned in
74
73
  "mcpServers": {
75
74
  "amicus": {
76
75
  "command": "uvx",
77
- "args": ["--from", "git+https://github.com/briandconnelly/amicus.git@v0.2.0", "amicus-mcp"]
76
+ "args": ["--from", "git+https://github.com/briandconnelly/amicus.git@v0.4.0", "amicus-mcp"]
78
77
  }
79
78
  }
80
79
  }
@@ -115,7 +114,9 @@ anything.
115
114
 
116
115
  ## The tools
117
116
 
118
- Nineteen tools, in five groups, one of them a deprecated alias. Everything paid has a free way to inspect it first.
117
+ Nineteen tools, in five groups, one of them a deprecated alias. Discovery, previews and job
118
+ management are free; the verbs and their background twins invoke the selected backend and spend
119
+ its quota.
119
120
 
120
121
  | Group | Tools |
121
122
  | --- | --- |
@@ -133,13 +134,10 @@ Not every backend does everything:
133
134
  | `delegate` | yes | yes | no |
134
135
  | `adversarial_review` | no | no | yes |
135
136
 
136
- A `no` is amicus's routing decision, not a claim about the model. `delegate` is absent on Claude
137
- by a deliberate review-only policy. `adversarial_review` is scoped to Claude for v1, but the verb
138
- is amicus's own: the prompt it builds and the result shape it returns are amicus's for any
139
- backend, and what Claude contributes is a critic stance layered on top. So nothing about
140
- Codex or Kimi stops either from reviewing adversarially — ask them through `consult` or
141
- `review_changes` and supply the adversarial stance yourself. What the verb adds is that stance
142
- fixed, plus its `target` and `evidence` carriers.
137
+ A `no` is amicus's routing policy, not a model limitation. Claude is review-only, and the
138
+ dedicated adversarial-review verb is scoped to Claude. To ask Codex or Kimi for an adversarial
139
+ review, use `consult` or `review_changes` and supply the stance yourself; the dedicated verb adds
140
+ a fixed critic stance and the `target` and `evidence` inputs.
143
141
 
144
142
  Asking a backend for something it does not support returns a `feature_unsupported` error naming
145
143
  the backend and the feature, rather than failing obscurely.
@@ -154,6 +152,11 @@ the backend and the feature, rather than failing obscurely.
154
152
  annotations — see [`docs/MIGRATION.md`](docs/MIGRATION.md).
155
153
  - **Your prompts go to whichever provider you selected**, through that provider's own CLI. Each
156
154
  backend discloses how it carries your text — visible on `amicus_backends`.
155
+ - **A paid call's whole answer stays on disk** in the job record under `AMICUS_STATE_DIR`,
156
+ whatever `detail` delivered it and after only best-effort secret redaction, until it expires
157
+ (`AMICUS_JOB_TTL`, default 24h; an expired record is removed on a later job call, not by a
158
+ daemon), the per-workspace cap evicts it or `amicus_job_consume_result` removes it. It can
159
+ quote what you sent. Your inputs themselves are never written there ([ADR 0035](docs/adr/0035-a-backend-answer-is-kept-on-the-job-record.md)).
157
160
 
158
161
  ## Configuration
159
162
 
@@ -162,12 +165,10 @@ reasoning effort, and binary path (`AMICUS_CODEX_MODEL`, `AMICUS_KIMI_REASONING_
162
165
  `AMICUS_CLAUDE_BIN`, and so on), and there are limits for timeouts, job retention and payload
163
166
  sizes. The full list is the `env_vars` array in [`.mcp.json`](.mcp.json).
164
167
 
165
- Logging goes to stderr, and `AMICUS_LOG_FILE` mirrors amicus's own records to a file. The
166
- `fastmcp` and `mcp` libraries' records also reach stderr, but never below WARNING whatever
167
- `AMICUS_LOG_LEVEL` says, never the file, and with every unaudited FastMCP server record
168
- reduced to its level, logger and exception type. That is deliberate (ADR 0023): those
169
- libraries can log a caller's prompt text, so a FastMCP-side failure is diagnosed from the
170
- exception type and frames rather than its message.
168
+ Logging goes to stderr, and `AMICUS_LOG_FILE` mirrors amicus's own records to a file. To reduce
169
+ the risk of prompt text leaking through dependency logs, `fastmcp` and `mcp` records are limited
170
+ to WARNING or higher on stderr, reduced to non-message diagnostics, and never written to that
171
+ file (ADR 0023).
171
172
 
172
173
  ## Coming from codex-in-claude, moonbridge, or claude-in-codex
173
174
 
@@ -176,20 +177,16 @@ the new ones.
176
177
 
177
178
  ## Status and known limits
178
179
 
179
- 0.3.0 is the current release, and it is a breaking one: the discovery surface moved from
180
- `amicus/0.1/schema-13` to `amicus/0.1/schema-30` and stored job results from `RESULT_FORMAT` 4 to
181
- `6`, so a job result 0.2.0 stored cannot be read after upgrading.
182
- [`docs/MIGRATION.md`](docs/MIGRATION.md#upgrading-from-020) walks through what a caller written
183
- against 0.2.0 has to change, and [`CHANGELOG.md`](CHANGELOG.md) lists everything that moved. The
184
- server's wire contract is exercised by the test suite and by host captures against Claude Code and
185
- Codex, but:
186
-
187
- - Two router-skill evaluation scenarios are unresolved — S6 (diff-safety wording) and S7 (approval
188
- friction) — recorded in [`docs/adr/0012-m6-packaging-decisions.md`](docs/adr/0012-m6-packaging-decisions.md).
189
- Neither is a defect in the server's wire contract.
190
- - A third-party backend distribution loads through the `amicus.backends` entry-point group, but
191
- cannot yet be enabled or called: `AMICUS_BACKENDS` and the `backend` parameter accept only the
192
- in-tree ids.
180
+ 0.4.0 is the current release, and it is a breaking one: sibling environment names are no longer
181
+ read, and an unreadable review is now delivered as `review_status: unstructured` instead of an
182
+ error. The discovery surface moved from `amicus/0.1/schema-30` to `amicus/0.1/schema-35` and stored
183
+ job results from `RESULT_FORMAT` 6 to `7`, so a job result 0.3.0 stored cannot be read after
184
+ upgrading. [`docs/MIGRATION.md`](docs/MIGRATION.md#upgrading-from-030) explains how to upgrade,
185
+ and [`CHANGELOG.md`](CHANGELOG.md) lists every user-visible change.
186
+
187
+ One known limit: a third-party backend distribution can load through the `amicus.backends`
188
+ entry-point group, but cannot yet be enabled or called. `AMICUS_BACKENDS` and the `backend`
189
+ parameter accept only the three in-tree ids.
193
190
 
194
191
  ## Development
195
192
 
@@ -203,7 +200,7 @@ version.
203
200
 
204
201
  | Question | Read |
205
202
  | --- | --- |
206
- | What is being built and why | `docs/superpowers/specs/2026-09-04-amicus-design.md` |
203
+ | What is being built and why | `docs/superpowers/specs/2026-09-04-amicus-design.md`; for M8, `docs/superpowers/specs/2026-09-15-amicus-M8-sdk-in-tree-design.md` |
207
204
  | How milestones are executed by agents | `docs/superpowers/plans/2026-09-04-amicus-execution-model.md` |
208
205
  | Architecture decisions | `docs/adr/` |
209
206
  | How a release is cut | `docs/RELEASING.md` |
@@ -44,7 +44,7 @@ The plugins launch the server from a published release tag, pinned in
44
44
  "mcpServers": {
45
45
  "amicus": {
46
46
  "command": "uvx",
47
- "args": ["--from", "git+https://github.com/briandconnelly/amicus.git@v0.2.0", "amicus-mcp"]
47
+ "args": ["--from", "git+https://github.com/briandconnelly/amicus.git@v0.4.0", "amicus-mcp"]
48
48
  }
49
49
  }
50
50
  }
@@ -85,7 +85,9 @@ anything.
85
85
 
86
86
  ## The tools
87
87
 
88
- Nineteen tools, in five groups, one of them a deprecated alias. Everything paid has a free way to inspect it first.
88
+ Nineteen tools, in five groups, one of them a deprecated alias. Discovery, previews and job
89
+ management are free; the verbs and their background twins invoke the selected backend and spend
90
+ its quota.
89
91
 
90
92
  | Group | Tools |
91
93
  | --- | --- |
@@ -103,13 +105,10 @@ Not every backend does everything:
103
105
  | `delegate` | yes | yes | no |
104
106
  | `adversarial_review` | no | no | yes |
105
107
 
106
- A `no` is amicus's routing decision, not a claim about the model. `delegate` is absent on Claude
107
- by a deliberate review-only policy. `adversarial_review` is scoped to Claude for v1, but the verb
108
- is amicus's own: the prompt it builds and the result shape it returns are amicus's for any
109
- backend, and what Claude contributes is a critic stance layered on top. So nothing about
110
- Codex or Kimi stops either from reviewing adversarially — ask them through `consult` or
111
- `review_changes` and supply the adversarial stance yourself. What the verb adds is that stance
112
- fixed, plus its `target` and `evidence` carriers.
108
+ A `no` is amicus's routing policy, not a model limitation. Claude is review-only, and the
109
+ dedicated adversarial-review verb is scoped to Claude. To ask Codex or Kimi for an adversarial
110
+ review, use `consult` or `review_changes` and supply the stance yourself; the dedicated verb adds
111
+ a fixed critic stance and the `target` and `evidence` inputs.
113
112
 
114
113
  Asking a backend for something it does not support returns a `feature_unsupported` error naming
115
114
  the backend and the feature, rather than failing obscurely.
@@ -124,6 +123,11 @@ the backend and the feature, rather than failing obscurely.
124
123
  annotations — see [`docs/MIGRATION.md`](docs/MIGRATION.md).
125
124
  - **Your prompts go to whichever provider you selected**, through that provider's own CLI. Each
126
125
  backend discloses how it carries your text — visible on `amicus_backends`.
126
+ - **A paid call's whole answer stays on disk** in the job record under `AMICUS_STATE_DIR`,
127
+ whatever `detail` delivered it and after only best-effort secret redaction, until it expires
128
+ (`AMICUS_JOB_TTL`, default 24h; an expired record is removed on a later job call, not by a
129
+ daemon), the per-workspace cap evicts it or `amicus_job_consume_result` removes it. It can
130
+ quote what you sent. Your inputs themselves are never written there ([ADR 0035](docs/adr/0035-a-backend-answer-is-kept-on-the-job-record.md)).
127
131
 
128
132
  ## Configuration
129
133
 
@@ -132,12 +136,10 @@ reasoning effort, and binary path (`AMICUS_CODEX_MODEL`, `AMICUS_KIMI_REASONING_
132
136
  `AMICUS_CLAUDE_BIN`, and so on), and there are limits for timeouts, job retention and payload
133
137
  sizes. The full list is the `env_vars` array in [`.mcp.json`](.mcp.json).
134
138
 
135
- Logging goes to stderr, and `AMICUS_LOG_FILE` mirrors amicus's own records to a file. The
136
- `fastmcp` and `mcp` libraries' records also reach stderr, but never below WARNING whatever
137
- `AMICUS_LOG_LEVEL` says, never the file, and with every unaudited FastMCP server record
138
- reduced to its level, logger and exception type. That is deliberate (ADR 0023): those
139
- libraries can log a caller's prompt text, so a FastMCP-side failure is diagnosed from the
140
- exception type and frames rather than its message.
139
+ Logging goes to stderr, and `AMICUS_LOG_FILE` mirrors amicus's own records to a file. To reduce
140
+ the risk of prompt text leaking through dependency logs, `fastmcp` and `mcp` records are limited
141
+ to WARNING or higher on stderr, reduced to non-message diagnostics, and never written to that
142
+ file (ADR 0023).
141
143
 
142
144
  ## Coming from codex-in-claude, moonbridge, or claude-in-codex
143
145
 
@@ -146,20 +148,16 @@ the new ones.
146
148
 
147
149
  ## Status and known limits
148
150
 
149
- 0.3.0 is the current release, and it is a breaking one: the discovery surface moved from
150
- `amicus/0.1/schema-13` to `amicus/0.1/schema-30` and stored job results from `RESULT_FORMAT` 4 to
151
- `6`, so a job result 0.2.0 stored cannot be read after upgrading.
152
- [`docs/MIGRATION.md`](docs/MIGRATION.md#upgrading-from-020) walks through what a caller written
153
- against 0.2.0 has to change, and [`CHANGELOG.md`](CHANGELOG.md) lists everything that moved. The
154
- server's wire contract is exercised by the test suite and by host captures against Claude Code and
155
- Codex, but:
156
-
157
- - Two router-skill evaluation scenarios are unresolved — S6 (diff-safety wording) and S7 (approval
158
- friction) — recorded in [`docs/adr/0012-m6-packaging-decisions.md`](docs/adr/0012-m6-packaging-decisions.md).
159
- Neither is a defect in the server's wire contract.
160
- - A third-party backend distribution loads through the `amicus.backends` entry-point group, but
161
- cannot yet be enabled or called: `AMICUS_BACKENDS` and the `backend` parameter accept only the
162
- in-tree ids.
151
+ 0.4.0 is the current release, and it is a breaking one: sibling environment names are no longer
152
+ read, and an unreadable review is now delivered as `review_status: unstructured` instead of an
153
+ error. The discovery surface moved from `amicus/0.1/schema-30` to `amicus/0.1/schema-35` and stored
154
+ job results from `RESULT_FORMAT` 6 to `7`, so a job result 0.3.0 stored cannot be read after
155
+ upgrading. [`docs/MIGRATION.md`](docs/MIGRATION.md#upgrading-from-030) explains how to upgrade,
156
+ and [`CHANGELOG.md`](CHANGELOG.md) lists every user-visible change.
157
+
158
+ One known limit: a third-party backend distribution can load through the `amicus.backends`
159
+ entry-point group, but cannot yet be enabled or called. `AMICUS_BACKENDS` and the `backend`
160
+ parameter accept only the three in-tree ids.
163
161
 
164
162
  ## Development
165
163
 
@@ -173,7 +171,7 @@ version.
173
171
 
174
172
  | Question | Read |
175
173
  | --- | --- |
176
- | What is being built and why | `docs/superpowers/specs/2026-09-04-amicus-design.md` |
174
+ | What is being built and why | `docs/superpowers/specs/2026-09-04-amicus-design.md`; for M8, `docs/superpowers/specs/2026-09-15-amicus-M8-sdk-in-tree-design.md` |
177
175
  | How milestones are executed by agents | `docs/superpowers/plans/2026-09-04-amicus-execution-model.md` |
178
176
  | Architecture decisions | `docs/adr/` |
179
177
  | How a release is cut | `docs/RELEASING.md` |