amicus 0.3.0__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (545) hide show
  1. {amicus-0.3.0 → amicus-0.5.0}/.claude-plugin/marketplace.json +6 -1
  2. {amicus-0.3.0 → amicus-0.5.0}/.claude-plugin/plugin.json +1 -1
  3. {amicus-0.3.0 → amicus-0.5.0}/.codex-plugin/plugin.json +1 -1
  4. {amicus-0.3.0 → amicus-0.5.0}/.github/dependabot.yml +11 -0
  5. {amicus-0.3.0 → amicus-0.5.0}/.github/workflows/test.yml +17 -0
  6. {amicus-0.3.0 → amicus-0.5.0}/.mcp.json +1 -1
  7. {amicus-0.3.0 → amicus-0.5.0}/AGENTS.md +27 -14
  8. {amicus-0.3.0 → amicus-0.5.0}/CHANGELOG.md +305 -1
  9. {amicus-0.3.0 → amicus-0.5.0}/PKG-INFO +35 -33
  10. {amicus-0.3.0 → amicus-0.5.0}/README.md +34 -31
  11. {amicus-0.3.0 → amicus-0.5.0}/docs/DEPRECATING-SIBLINGS.md +10 -6
  12. {amicus-0.3.0 → amicus-0.5.0}/docs/MIGRATION.md +71 -18
  13. {amicus-0.3.0 → amicus-0.5.0}/docs/RELEASING.md +68 -17
  14. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0003-workspace-resolution.md +1 -0
  15. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0015-mcp-json-pins-an-already-published-release.md +2 -1
  16. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0023-dependency-loggers-are-owned-at-a-warning-floor.md +6 -2
  17. amicus-0.5.0/docs/adr/0029-the-backend-sdk-lives-in-tree.md +63 -0
  18. amicus-0.5.0/docs/adr/0030-the-sdk-keeps-what-a-backend-imports.md +46 -0
  19. amicus-0.5.0/docs/adr/0031-the-marketplace-pointer-decides-what-users-run.md +47 -0
  20. amicus-0.5.0/docs/adr/0032-a-claude-review-defaults-to-readonly-access.md +43 -0
  21. amicus-0.5.0/docs/adr/0033-an-unreadable-review-answer-is-delivered-unstructured.md +64 -0
  22. amicus-0.5.0/docs/adr/0034-claude-usage-is-read-from-model-usage.md +29 -0
  23. amicus-0.5.0/docs/adr/0035-a-backend-answer-is-kept-on-the-job-record.md +54 -0
  24. amicus-0.5.0/docs/adr/0036-a-refused-answer-file-is-answer-unavailable.md +69 -0
  25. amicus-0.5.0/docs/claude-help/2.1.274/FINDINGS.md +39 -0
  26. amicus-0.5.0/docs/claude-help/2.1.274/budget-stop-envelope-shape.json +52 -0
  27. amicus-0.5.0/docs/claude-help/2.1.274/claude-version.txt +1 -0
  28. amicus-0.5.0/docs/claude-help/2.1.278/claude-help.txt +302 -0
  29. amicus-0.5.0/docs/claude-help/2.1.278/claude-version.txt +1 -0
  30. amicus-0.5.0/docs/codex-help/0.155.1/codex-help.txt +112 -0
  31. amicus-0.5.0/docs/codex-help/0.155.1/codex-version.txt +1 -0
  32. {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.43.1/FINDINGS.md +24 -0
  33. amicus-0.5.0/docs/kimi-help/2.0.2/FINDINGS.md +86 -0
  34. amicus-0.5.0/docs/kimi-help/2.0.2/kimi-help.txt +51 -0
  35. amicus-0.5.0/docs/kimi-help/2.0.2/kimi-version.txt +1 -0
  36. amicus-0.5.0/docs/kimi-help/2.0.2/provider-list-shape.json +18 -0
  37. {amicus-0.3.0 → amicus-0.5.0}/docs/superpowers/specs/2026-09-04-amicus-design.md +23 -25
  38. amicus-0.5.0/docs/superpowers/specs/2026-09-15-amicus-M8-sdk-in-tree-design.md +224 -0
  39. amicus-0.5.0/docs/superpowers/specs/2026-09-16-amicus-release-activation-design.md +343 -0
  40. {amicus-0.3.0 → amicus-0.5.0}/prek.toml +2 -1
  41. {amicus-0.3.0 → amicus-0.5.0}/pyproject.toml +38 -3
  42. amicus-0.5.0/scripts/check_backend_compat.py +347 -0
  43. {amicus-0.3.0 → amicus-0.5.0}/scripts/check_commit_message.py +1 -0
  44. {amicus-0.3.0 → amicus-0.5.0}/scripts/check_release_state.py +250 -40
  45. {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/SKILL.md +17 -5
  46. amicus-0.5.0/skills/collaborating-with-amicus/references/blind-comparison.md +149 -0
  47. {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/choosing-a-backend.md +9 -2
  48. {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/options-and-errors.md +7 -3
  49. {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/reading-results.md +33 -2
  50. {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/sync-vs-async.md +9 -2
  51. {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/tests/scenarios.md +89 -1
  52. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/__init__.py +1 -1
  53. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/_worker.py +30 -4
  54. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/__init__.py +1 -1
  55. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/__init__.py +4 -5
  56. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/adapter.py +14 -11
  57. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/adversarial.py +7 -1
  58. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/binary.py +8 -0
  59. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/cli.py +19 -19
  60. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/config.py +32 -15
  61. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/contract.py +6 -2
  62. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/normalize.py +66 -18
  63. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/options.py +9 -2
  64. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/status.py +1 -2
  65. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/__init__.py +4 -5
  66. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/adapter.py +7 -9
  67. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/binary.py +9 -2
  68. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/cli.py +71 -21
  69. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/config.py +10 -11
  70. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/contract.py +73 -17
  71. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/models.py +2 -3
  72. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/normalize.py +22 -4
  73. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/status.py +5 -5
  74. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/__init__.py +12 -6
  75. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/adapter.py +8 -8
  76. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/binary.py +8 -0
  77. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/cli.py +7 -8
  78. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/config.py +9 -11
  79. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/contract.py +10 -6
  80. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/models.py +1 -2
  81. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/normalize.py +1 -2
  82. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/status.py +2 -4
  83. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/config/__init__.py +52 -26
  84. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/config/envspec.py +56 -14
  85. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/errors.py +14 -6
  86. amicus-0.5.0/src/amicus/jobs/__init__.py +2 -0
  87. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/jobs/delivery.py +1 -1
  88. amicus-0.5.0/src/amicus/jobs/idempotency.py +466 -0
  89. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/jobs/lifecycle.py +34 -15
  90. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/jobs/lookup.py +1 -2
  91. amicus-0.5.0/src/amicus/jobs/polling.py +33 -0
  92. amicus-0.5.0/src/amicus/jobs/store.py +1049 -0
  93. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/jobs/taskmap.py +3 -3
  94. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/manifest.py +3 -3
  95. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/middleware.py +1 -1
  96. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/obs.py +29 -28
  97. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/orchestration/finalize.py +244 -46
  98. amicus-0.5.0/src/amicus/orchestration/gitdiff.py +1179 -0
  99. amicus-0.5.0/src/amicus/orchestration/gitproc.py +205 -0
  100. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/orchestration/isolation.py +10 -8
  101. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/orchestration/prompts.py +131 -9
  102. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/orchestration/review.py +3 -4
  103. amicus-0.5.0/src/amicus/orchestration/run.py +368 -0
  104. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/orchestration/workspace.py +68 -12
  105. amicus-0.5.0/src/amicus/orchestration/worktree.py +665 -0
  106. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/plugin.py +8 -9
  107. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/registry.py +4 -5
  108. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/request.py +4 -4
  109. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/codes.py +9 -5
  110. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/envelope.py +1 -1
  111. amicus-0.5.0/src/amicus/schemas/fingerprint.py +188 -0
  112. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/options.py +3 -2
  113. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/params.py +10 -5
  114. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/results.py +34 -19
  115. amicus-0.5.0/src/amicus/schemas/structured.py +95 -0
  116. amicus-0.5.0/src/amicus/sdk/__init__.py +14 -0
  117. amicus-0.5.0/src/amicus/sdk/backend/__init__.py +19 -0
  118. amicus-0.5.0/src/amicus/sdk/backend/contract.py +137 -0
  119. amicus-0.5.0/src/amicus/sdk/backend/protocol.py +321 -0
  120. amicus-0.5.0/src/amicus/sdk/conventions/__init__.py +8 -0
  121. amicus-0.5.0/src/amicus/sdk/conventions/annotations.py +97 -0
  122. amicus-0.5.0/src/amicus/sdk/conventions/envelope.py +381 -0
  123. amicus-0.5.0/src/amicus/sdk/conventions/preflight.py +100 -0
  124. amicus-0.5.0/src/amicus/sdk/core/__init__.py +7 -0
  125. amicus-0.5.0/src/amicus/sdk/core/jsoncache.py +42 -0
  126. amicus-0.5.0/src/amicus/sdk/core/pathalias.py +430 -0
  127. amicus-0.5.0/src/amicus/sdk/core/redaction.py +1515 -0
  128. amicus-0.5.0/src/amicus/sdk/core/runtime.py +617 -0
  129. amicus-0.5.0/src/amicus/sdk/core/streamcap.py +286 -0
  130. amicus-0.5.0/src/amicus/sdk/testing/__init__.py +7 -0
  131. amicus-0.5.0/src/amicus/sdk/testing/conformance.py +119 -0
  132. amicus-0.5.0/src/amicus/sdk/testing/surface_honesty.py +52 -0
  133. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/server.py +4 -0
  134. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/surface.py +1 -1
  135. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/__init__.py +2 -3
  136. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/_meta.py +6 -16
  137. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/_prepare.py +2 -3
  138. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/_resolve.py +9 -0
  139. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/consult.py +4 -2
  140. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/delegate.py +3 -3
  141. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/discovery.py +44 -16
  142. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/dry_run.py +10 -56
  143. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/jobs.py +2 -2
  144. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/review.py +7 -5
  145. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/wire_shape_snapshot.py +27 -4
  146. {amicus-0.3.0 → amicus-0.5.0}/tests/conftest.py +47 -14
  147. amicus-0.5.0/tests/fixtures/claude_budget_stop_envelope.json +82 -0
  148. {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/fakebackend/src/fakebackend/__init__.py +11 -12
  149. {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/manifest_snapshot.all.json +336 -766
  150. {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/manifest_snapshot.claude.json +336 -766
  151. {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/manifest_snapshot.codex-kimi.json +336 -766
  152. {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/result_format_snapshot.json +12 -4
  153. {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/wire_shape_snapshot.json +186 -4
  154. amicus-0.5.0/tests/sdk/conftest.py +96 -0
  155. amicus-0.5.0/tests/sdk/test_annotations.py +85 -0
  156. amicus-0.5.0/tests/sdk/test_classified_failure_fields.py +70 -0
  157. amicus-0.5.0/tests/sdk/test_conformance_fakes.py +510 -0
  158. amicus-0.5.0/tests/sdk/test_conformance_inspector.py +94 -0
  159. amicus-0.5.0/tests/sdk/test_contract.py +88 -0
  160. amicus-0.5.0/tests/sdk/test_envelope.py +92 -0
  161. amicus-0.5.0/tests/sdk/test_fingerprint.py +93 -0
  162. amicus-0.5.0/tests/sdk/test_git_isolation.py +65 -0
  163. amicus-0.5.0/tests/sdk/test_gitdiff.py +2153 -0
  164. amicus-0.5.0/tests/sdk/test_gitproc.py +205 -0
  165. amicus-0.5.0/tests/sdk/test_idempotency.py +490 -0
  166. amicus-0.5.0/tests/sdk/test_jobs.py +1548 -0
  167. amicus-0.5.0/tests/sdk/test_jsoncache.py +59 -0
  168. amicus-0.5.0/tests/sdk/test_orphan_sweep.py +245 -0
  169. amicus-0.5.0/tests/sdk/test_outcome_inspector.py +90 -0
  170. amicus-0.5.0/tests/sdk/test_pair_parity_kit.py +72 -0
  171. amicus-0.5.0/tests/sdk/test_pathalias.py +614 -0
  172. amicus-0.5.0/tests/sdk/test_preflight.py +132 -0
  173. amicus-0.5.0/tests/sdk/test_prompts.py +119 -0
  174. amicus-0.5.0/tests/sdk/test_redaction.py +3411 -0
  175. amicus-0.5.0/tests/sdk/test_run_request.py +156 -0
  176. amicus-0.5.0/tests/sdk/test_runtime.py +1018 -0
  177. amicus-0.5.0/tests/sdk/test_runtime_kill_and_sweep_paths.py +145 -0
  178. amicus-0.5.0/tests/sdk/test_streamcap.py +351 -0
  179. amicus-0.5.0/tests/sdk/test_surface_honesty_kit.py +49 -0
  180. amicus-0.5.0/tests/sdk/test_usage_cache_fields.py +49 -0
  181. amicus-0.5.0/tests/sdk/test_workspace.py +53 -0
  182. amicus-0.5.0/tests/sdk/test_worktree.py +1004 -0
  183. amicus-0.5.0/tests/sdk/test_worktree_config.py +93 -0
  184. amicus-0.5.0/tests/support/__init__.py +0 -0
  185. {amicus-0.3.0 → amicus-0.5.0}/tests/support/claudefixtures.py +6 -3
  186. {amicus-0.3.0 → amicus-0.5.0}/tests/support/codexfixtures.py +2 -3
  187. {amicus-0.3.0 → amicus-0.5.0}/tests/support/fake_codex.py +29 -4
  188. {amicus-0.3.0 → amicus-0.5.0}/tests/support/fake_kimi.py +29 -5
  189. {amicus-0.3.0 → amicus-0.5.0}/tests/support/fakeplugin.py +11 -12
  190. {amicus-0.3.0 → amicus-0.5.0}/tests/support/kimifixtures.py +2 -3
  191. amicus-0.5.0/tests/support/livegate.py +22 -0
  192. amicus-0.5.0/tests/support/pair_parity.py +62 -0
  193. {amicus-0.3.0 → amicus-0.5.0}/tests/test_adversarial.py +10 -3
  194. amicus-0.5.0/tests/test_artifact_references.py +296 -0
  195. {amicus-0.3.0 → amicus-0.5.0}/tests/test_async_tools.py +1 -1
  196. {amicus-0.3.0 → amicus-0.5.0}/tests/test_cache_hints.py +3 -2
  197. amicus-0.5.0/tests/test_check_backend_compat.py +310 -0
  198. {amicus-0.3.0 → amicus-0.5.0}/tests/test_check_commit_message.py +6 -0
  199. {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_adapter.py +55 -4
  200. {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_argv_differential.py +1 -1
  201. {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_cli.py +2 -2
  202. {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_config.py +46 -14
  203. {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_contract.py +39 -2
  204. amicus-0.5.0/tests/test_claude_golden_envelope.py +158 -0
  205. amicus-0.5.0/tests/test_claude_normalize.py +190 -0
  206. {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_plugin.py +14 -1
  207. {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_result_differential.py +14 -7
  208. {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_status.py +1 -1
  209. {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_sync_tools.py +96 -1
  210. {amicus-0.3.0 → amicus-0.5.0}/tests/test_codes.py +5 -5
  211. {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_adapter.py +73 -5
  212. {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_argv_differential.py +5 -5
  213. {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_binary.py +1 -1
  214. {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_cli.py +168 -7
  215. {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_config.py +15 -6
  216. amicus-0.5.0/tests/test_codex_contract.py +320 -0
  217. {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_live.py +5 -0
  218. {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_normalize.py +26 -0
  219. {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_result_differential.py +15 -3
  220. {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_status.py +23 -4
  221. {amicus-0.3.0 → amicus-0.5.0}/tests/test_commands.py +28 -2
  222. {amicus-0.3.0 → amicus-0.5.0}/tests/test_compaction.py +1 -1
  223. {amicus-0.3.0 → amicus-0.5.0}/tests/test_config.py +23 -11
  224. {amicus-0.3.0 → amicus-0.5.0}/tests/test_delivery.py +2 -3
  225. {amicus-0.3.0 → amicus-0.5.0}/tests/test_discovery.py +57 -12
  226. {amicus-0.3.0 → amicus-0.5.0}/tests/test_discovery_cost.py +60 -2
  227. {amicus-0.3.0 → amicus-0.5.0}/tests/test_dry_run.py +100 -57
  228. amicus-0.5.0/tests/test_envspec.py +208 -0
  229. {amicus-0.3.0 → amicus-0.5.0}/tests/test_errors.py +3 -3
  230. {amicus-0.3.0 → amicus-0.5.0}/tests/test_fastmcp_argument_log.py +9 -15
  231. {amicus-0.3.0 → amicus-0.5.0}/tests/test_finalize.py +84 -20
  232. {amicus-0.3.0 → amicus-0.5.0}/tests/test_fingerprint.py +3 -3
  233. amicus-0.5.0/tests/test_import_contracts.py +47 -0
  234. {amicus-0.3.0 → amicus-0.5.0}/tests/test_isolation.py +1 -1
  235. {amicus-0.3.0 → amicus-0.5.0}/tests/test_job_tools.py +99 -3
  236. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_adapter.py +3 -3
  237. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_argv_differential.py +5 -5
  238. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_cli.py +2 -2
  239. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_config.py +12 -9
  240. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_contract.py +7 -4
  241. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_models.py +1 -2
  242. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_plugin.py +26 -0
  243. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_result_differential.py +15 -3
  244. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_status.py +4 -2
  245. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_sync_tools.py +151 -0
  246. {amicus-0.3.0 → amicus-0.5.0}/tests/test_lifecycle.py +39 -10
  247. amicus-0.5.0/tests/test_livegate.py +46 -0
  248. {amicus-0.3.0 → amicus-0.5.0}/tests/test_log_redaction.py +42 -26
  249. {amicus-0.3.0 → amicus-0.5.0}/tests/test_manifest.py +9 -8
  250. {amicus-0.3.0 → amicus-0.5.0}/tests/test_meta.py +61 -22
  251. {amicus-0.3.0 → amicus-0.5.0}/tests/test_migration_doc.py +29 -16
  252. {amicus-0.3.0 → amicus-0.5.0}/tests/test_obs.py +8 -1
  253. {amicus-0.3.0 → amicus-0.5.0}/tests/test_packaging.py +22 -31
  254. {amicus-0.3.0 → amicus-0.5.0}/tests/test_params.py +26 -0
  255. {amicus-0.3.0 → amicus-0.5.0}/tests/test_plugin.py +2 -2
  256. amicus-0.5.0/tests/test_poll_hint.py +57 -0
  257. {amicus-0.3.0 → amicus-0.5.0}/tests/test_prepare.py +1 -1
  258. {amicus-0.3.0 → amicus-0.5.0}/tests/test_registry.py +1 -1
  259. amicus-0.5.0/tests/test_relative_config_paths.py +110 -0
  260. {amicus-0.3.0 → amicus-0.5.0}/tests/test_release_state.py +383 -48
  261. {amicus-0.3.0 → amicus-0.5.0}/tests/test_results.py +27 -11
  262. {amicus-0.3.0 → amicus-0.5.0}/tests/test_review.py +1 -1
  263. {amicus-0.3.0 → amicus-0.5.0}/tests/test_run.py +264 -6
  264. amicus-0.5.0/tests/test_sdk_in_tree.py +183 -0
  265. {amicus-0.3.0 → amicus-0.5.0}/tests/test_skill_contract.py +20 -3
  266. amicus-0.5.0/tests/test_structured.py +111 -0
  267. {amicus-0.3.0 → amicus-0.5.0}/tests/test_surface_honesty.py +41 -1
  268. {amicus-0.3.0 → amicus-0.5.0}/tests/test_sync_tools.py +159 -0
  269. {amicus-0.3.0 → amicus-0.5.0}/tests/test_tasks_client.py +0 -1
  270. {amicus-0.3.0 → amicus-0.5.0}/tests/test_worker.py +114 -1
  271. {amicus-0.3.0 → amicus-0.5.0}/tests/test_workspace.py +58 -0
  272. {amicus-0.3.0 → amicus-0.5.0}/uv.lock +13 -27
  273. amicus-0.3.0/src/amicus/jobs/__init__.py +0 -1
  274. amicus-0.3.0/src/amicus/jobs/polling.py +0 -36
  275. amicus-0.3.0/src/amicus/orchestration/run.py +0 -221
  276. amicus-0.3.0/src/amicus/schemas/fingerprint.py +0 -62
  277. amicus-0.3.0/src/amicus/schemas/structured.py +0 -64
  278. amicus-0.3.0/tests/test_claude_golden_envelope.py +0 -79
  279. amicus-0.3.0/tests/test_claude_normalize.py +0 -86
  280. amicus-0.3.0/tests/test_codex_contract.py +0 -168
  281. amicus-0.3.0/tests/test_envspec.py +0 -93
  282. amicus-0.3.0/tests/test_import_contracts.py +0 -17
  283. amicus-0.3.0/tests/test_poll_hint.py +0 -38
  284. amicus-0.3.0/tests/test_structured.py +0 -44
  285. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-docs/SKILL.md +0 -0
  286. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-docs/references/design-workflow.md +0 -0
  287. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-docs/references/docs-checklist.md +0 -0
  288. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-docs/references/examples.md +0 -0
  289. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-docs/references/review-workflow.md +0 -0
  290. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-docs/tests/scenarios.md +0 -0
  291. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/SKILL.md +0 -0
  292. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/decisions/001-github-fact-sheet.md +0 -0
  293. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/audit-workflow.md +0 -0
  294. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/config-checklist.md +0 -0
  295. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/README.md +0 -0
  296. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/codeowners.md +0 -0
  297. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/harness-deny.md +0 -0
  298. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/identity.md +0 -0
  299. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/repo-files.md +0 -0
  300. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/required-checks.md +0 -0
  301. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/rulesets.md +0 -0
  302. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/workflows.md +0 -0
  303. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/operating-playbook.md +0 -0
  304. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/setup-workflow.md +0 -0
  305. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/threat-model.md +0 -0
  306. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/tests/check_authority.py +0 -0
  307. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/tests/scenarios.md +0 -0
  308. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/SKILL.md +0 -0
  309. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/decisions/001-mcp-2026-07-28-rebase.md +0 -0
  310. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/decisions/002-machine-code-rename-rationale.md +0 -0
  311. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/decisions/003-offending-value-omission.md +0 -0
  312. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/decisions/004-ownership-boundaries.md +0 -0
  313. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/contract-checklist.md +0 -0
  314. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/design-workflow.md +0 -0
  315. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/examples.md +0 -0
  316. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/mcp-2025-11-25-compat.md +0 -0
  317. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/mcp-vs-cli.md +0 -0
  318. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/native-wire-shapes.md +0 -0
  319. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/review-workflow.md +0 -0
  320. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/vocabulary.md +0 -0
  321. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/check_fact_sync.py +0 -0
  322. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/check_rule_ids.py +0 -0
  323. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/check_stale_terms.py +0 -0
  324. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/fixtures/github_issues.json +0 -0
  325. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/fixtures/github_repo_resource.json +0 -0
  326. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/rule-ids.txt +0 -0
  327. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-baseline.md +0 -0
  328. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-outputschema-error.md +0 -0
  329. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-with-skill.md +0 -0
  330. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario2-baseline.md +0 -0
  331. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario2-with-skill.md +0 -0
  332. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario3-baseline.md +0 -0
  333. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario3-with-skill.md +0 -0
  334. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario4-baseline.md +0 -0
  335. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario4-with-skill.md +0 -0
  336. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario5-baseline.md +0 -0
  337. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario5-with-skill.md +0 -0
  338. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario6-baseline.md +0 -0
  339. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario6-with-skill.md +0 -0
  340. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario7-trigger.md +0 -0
  341. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario1-baseline.md +0 -0
  342. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario1-with-skill.md +0 -0
  343. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario3-baseline.md +0 -0
  344. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario3-with-skill.md +0 -0
  345. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario5-baseline.md +0 -0
  346. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario5-with-skill.md +0 -0
  347. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-30-scenario1-with-skill.md +0 -0
  348. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-30-scenario8-severity-calibration.md +0 -0
  349. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/scenarios.md +0 -0
  350. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/test_check_fact_sync.py +0 -0
  351. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/test_check_rule_ids.py +0 -0
  352. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/test_validate_fixture.py +0 -0
  353. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/validate_fixture.py +0 -0
  354. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/SKILL.md +0 -0
  355. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/agents/openai.yaml +0 -0
  356. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/references/example-audit.md +0 -0
  357. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/rescore-2026-08-06/preregistration.md +0 -0
  358. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/rescore-2026-08-06/results.md +0 -0
  359. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario1-baseline.md +0 -0
  360. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario1-with-skill.md +0 -0
  361. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario2-baseline.md +0 -0
  362. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario2-with-skill.md +0 -0
  363. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario3-baseline.md +0 -0
  364. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario3-with-skill.md +0 -0
  365. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario4-baseline.md +0 -0
  366. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario4-with-skill.md +0 -0
  367. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario5-baseline.md +0 -0
  368. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario5-with-skill.md +0 -0
  369. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario6-baseline.md +0 -0
  370. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario6-with-skill.md +0 -0
  371. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario7-baseline.md +0 -0
  372. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario7-with-skill.md +0 -0
  373. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario8-baseline.md +0 -0
  374. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario8-with-skill.md +0 -0
  375. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario9-trigger.md +0 -0
  376. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-06-scenario1-with-skill.md +0 -0
  377. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-06-scenario6-with-skill.md +0 -0
  378. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-confirmation-r1-both-directions.md +0 -0
  379. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario1-with-skill.md +0 -0
  380. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario2-with-skill.md +0 -0
  381. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario5-with-skill.md +0 -0
  382. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario6-with-skill.md +0 -0
  383. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario7-with-skill.md +0 -0
  384. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario8-with-skill.md +0 -0
  385. {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/scenarios.md +0 -0
  386. {amicus-0.3.0 → amicus-0.5.0}/.gitattributes +0 -0
  387. {amicus-0.3.0 → amicus-0.5.0}/.github/CODEOWNERS +0 -0
  388. {amicus-0.3.0 → amicus-0.5.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  389. {amicus-0.3.0 → amicus-0.5.0}/.github/copilot-instructions.md +0 -0
  390. {amicus-0.3.0 → amicus-0.5.0}/.github/workflows/ci.yml +0 -0
  391. {amicus-0.3.0 → amicus-0.5.0}/.github/workflows/codeql.yml +0 -0
  392. {amicus-0.3.0 → amicus-0.5.0}/.github/workflows/dependency-review.yml +0 -0
  393. {amicus-0.3.0 → amicus-0.5.0}/.github/workflows/publish.yml +0 -0
  394. {amicus-0.3.0 → amicus-0.5.0}/.gitignore +0 -0
  395. {amicus-0.3.0 → amicus-0.5.0}/CLAUDE.md +0 -0
  396. {amicus-0.3.0 → amicus-0.5.0}/LICENSE +0 -0
  397. {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/adversarial.md +0 -0
  398. {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/consult.md +0 -0
  399. {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/delegate-async.md +0 -0
  400. {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/delegate.md +0 -0
  401. {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/dry-run.md +0 -0
  402. {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/jobs.md +0 -0
  403. {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/review.md +0 -0
  404. {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/status.md +0 -0
  405. {amicus-0.3.0 → amicus-0.5.0}/docs/2026-09-04-naming-and-scoping-notes.md +0 -0
  406. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0001-annotations-follow-the-worst-enabled-backend.md +0 -0
  407. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0002-backend-options-is-a-closed-superset.md +0 -0
  408. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0004-tasks-and-jobs.md +0 -0
  409. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0005-error-envelope-and-repair-precedence.md +0 -0
  410. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0006-fingerprint-and-surface-digest.md +0 -0
  411. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0007-m1-codex-port-decisions.md +0 -0
  412. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0008-m2-jobs-surface-decisions.md +0 -0
  413. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0009-m3-kimi-port-decisions.md +0 -0
  414. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0010-m4-claude-port-decisions.md +0 -0
  415. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0011-m5-tasks-decisions.md +0 -0
  416. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0012-m6-packaging-decisions.md +0 -0
  417. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0013-proceed-without-trademark-clearance.md +0 -0
  418. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0014-release-predicate-on-the-tag.md +0 -0
  419. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0016-skill-rules-are-a-complete-contract.md +0 -0
  420. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0017-an-unreadable-machine-enum-falls-to-its-own-floor.md +0 -0
  421. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0018-the-catalog-carries-a-ttl-and-resource-reads-do-not.md +0 -0
  422. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0019-review-results-disclose-coverage-as-a-field.md +0 -0
  423. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0020-idempotency-keys-on-the-sync-tools.md +0 -0
  424. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0021-repair-arguments-are-a-complete-call.md +0 -0
  425. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0022-consume-reports-its-discard-outcome.md +0 -0
  426. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0024-prose-list-loss-is-disclosed-never-folded.md +0 -0
  427. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0025-success-meta-is-sparse-on-every-tool.md +0 -0
  428. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0026-a-not-run-review-carries-no-confidence-rating.md +0 -0
  429. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0027-every-instructions-rule-fits-the-shown-prefix.md +0 -0
  430. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0028-a-deprecated-tool-keeps-its-record-beside-one-marker.md +0 -0
  431. {amicus-0.3.0 → amicus-0.5.0}/docs/adr/README.md +0 -0
  432. {amicus-0.3.0 → amicus-0.5.0}/docs/claude-help/2.1.263/FINDINGS.md +0 -0
  433. {amicus-0.3.0 → amicus-0.5.0}/docs/claude-help/2.1.263/claude-help.txt +0 -0
  434. {amicus-0.3.0 → amicus-0.5.0}/docs/claude-help/2.1.263/claude-version.txt +0 -0
  435. {amicus-0.3.0 → amicus-0.5.0}/docs/claude-help/2.1.263/envelope-shape.json +0 -0
  436. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/claude-code/2.1.263/FINDINGS.md +0 -0
  437. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/claude-code/2.1.263/connection.log +0 -0
  438. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/claude-code/2.1.263/host-output.json +0 -0
  439. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/codex/0.153.4/FINDINGS.md +0 -0
  440. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/codex/0.153.4/connection.log +0 -0
  441. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/codex/0.153.4/host-output.jsonl +0 -0
  442. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/notes.md +0 -0
  443. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/server.log +0 -0
  444. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/transcript.md +0 -0
  445. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/install-smoke/claude-code/2.1.263/notes.md +0 -0
  446. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/install-smoke/claude-code/2.1.263/server.log +0 -0
  447. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/install-smoke/claude-code/2.1.263/transcript.md +0 -0
  448. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/install-smoke/codex/0.153.4/notes.md +0 -0
  449. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/install-smoke/codex/0.153.4/server.log +0 -0
  450. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/install-smoke/codex/0.153.4/transcript.md +0 -0
  451. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/notes.md +0 -0
  452. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/server.log +0 -0
  453. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/transcript.md +0 -0
  454. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-old-text-new-grader/claude-code/2.1.263/notes.md +0 -0
  455. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-old-text-new-grader/claude-code/2.1.263/server.log +0 -0
  456. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-old-text-new-grader/claude-code/2.1.263/transcript.md +0 -0
  457. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/notes.md +0 -0
  458. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/server.log +0 -0
  459. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/transcript.md +0 -0
  460. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/notes.md +0 -0
  461. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/server.log +0 -0
  462. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/transcript.md +0 -0
  463. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/notes.md +0 -0
  464. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/server.log +0 -0
  465. {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/transcript.md +0 -0
  466. {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.41.0/FINDINGS.md +0 -0
  467. {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.41.0/kimi-help.txt +0 -0
  468. {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.41.0/kimi-version.txt +0 -0
  469. {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.41.0/provider-list-shape.json +0 -0
  470. {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.42.0/FINDINGS.md +0 -0
  471. {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.42.0/kimi-help.txt +0 -0
  472. {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.42.0/kimi-version.txt +0 -0
  473. {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.42.0/provider-list-shape.json +0 -0
  474. {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.43.1/kimi-help.txt +0 -0
  475. {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.43.1/kimi-version.txt +0 -0
  476. {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.43.1/provider-list-shape.json +0 -0
  477. {amicus-0.3.0 → amicus-0.5.0}/docs/reviews/2026-09-07-agent-friendly-mcp-walk.md +0 -0
  478. {amicus-0.3.0 → amicus-0.5.0}/docs/superpowers/plans/2026-09-04-amicus-execution-model.md +0 -0
  479. {amicus-0.3.0 → amicus-0.5.0}/scripts/capture_claude_differentials.py +0 -0
  480. {amicus-0.3.0 → amicus-0.5.0}/scripts/capture_codex_differentials.py +0 -0
  481. {amicus-0.3.0 → amicus-0.5.0}/scripts/capture_kimi_differentials.py +0 -0
  482. {amicus-0.3.0 → amicus-0.5.0}/scripts/check_github_actions_pinning.py +0 -0
  483. {amicus-0.3.0 → amicus-0.5.0}/scripts/record_live_gate_evidence.py +0 -0
  484. {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/active-workflows.md +0 -0
  485. {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/independent-attempt.md +0 -0
  486. {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/review-revise.md +0 -0
  487. {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/reviewing-a-returned-diff.md +0 -0
  488. {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/server-down-fallback.md +0 -0
  489. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/appstate.py +0 -0
  490. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/models.py +0 -0
  491. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/options.py +0 -0
  492. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/options.py +0 -0
  493. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/compaction.py +0 -0
  494. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/orchestration/__init__.py +0 -0
  495. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/packaging.py +0 -0
  496. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/py.typed +0 -0
  497. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/result_format_snapshot.py +0 -0
  498. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/__init__.py +0 -0
  499. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/field_policy.py +0 -0
  500. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/instructions.py +0 -0
  501. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/publish.py +0 -0
  502. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/_guard.py +0 -0
  503. {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/resources.py +0 -0
  504. {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/claude_differentials.json +0 -0
  505. {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/claude_golden_envelope.json +0 -0
  506. {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/codex_differentials.json +0 -0
  507. {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/fakebackend/pyproject.toml +0 -0
  508. {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/kimi_differentials.json +0 -0
  509. {amicus-0.3.0/tests/support → amicus-0.5.0/tests/sdk}/__init__.py +0 -0
  510. {amicus-0.3.0 → amicus-0.5.0}/tests/support/fake_claude.py +0 -0
  511. {amicus-0.3.0 → amicus-0.5.0}/tests/test_check_github_actions_pinning.py +0 -0
  512. {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_binary.py +0 -0
  513. {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_live.py +0 -0
  514. {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_models.py +0 -0
  515. {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_models.py +0 -0
  516. {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_plugin.py +0 -0
  517. {amicus-0.3.0 → amicus-0.5.0}/tests/test_conftest_guards.py +0 -0
  518. {amicus-0.3.0 → amicus-0.5.0}/tests/test_envelope.py +0 -0
  519. {amicus-0.3.0 → amicus-0.5.0}/tests/test_field_policy.py +0 -0
  520. {amicus-0.3.0 → amicus-0.5.0}/tests/test_guard.py +0 -0
  521. {amicus-0.3.0 → amicus-0.5.0}/tests/test_host_captures.py +0 -0
  522. {amicus-0.3.0 → amicus-0.5.0}/tests/test_instructions.py +0 -0
  523. {amicus-0.3.0 → amicus-0.5.0}/tests/test_job_durability.py +0 -0
  524. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_binary.py +0 -0
  525. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_live.py +0 -0
  526. {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_normalize.py +0 -0
  527. {amicus-0.3.0 → amicus-0.5.0}/tests/test_live_gate_report.py +0 -0
  528. {amicus-0.3.0 → amicus-0.5.0}/tests/test_live_suite_hygiene.py +0 -0
  529. {amicus-0.3.0 → amicus-0.5.0}/tests/test_lookup.py +0 -0
  530. {amicus-0.3.0 → amicus-0.5.0}/tests/test_middleware.py +0 -0
  531. {amicus-0.3.0 → amicus-0.5.0}/tests/test_options.py +0 -0
  532. {amicus-0.3.0 → amicus-0.5.0}/tests/test_paid_tools.py +0 -0
  533. {amicus-0.3.0 → amicus-0.5.0}/tests/test_prompts.py +0 -0
  534. {amicus-0.3.0 → amicus-0.5.0}/tests/test_publish.py +0 -0
  535. {amicus-0.3.0 → amicus-0.5.0}/tests/test_release_evidence.py +0 -0
  536. {amicus-0.3.0 → amicus-0.5.0}/tests/test_request.py +0 -0
  537. {amicus-0.3.0 → amicus-0.5.0}/tests/test_resources.py +0 -0
  538. {amicus-0.3.0 → amicus-0.5.0}/tests/test_result_format.py +0 -0
  539. {amicus-0.3.0 → amicus-0.5.0}/tests/test_review_artifact.py +0 -0
  540. {amicus-0.3.0 → amicus-0.5.0}/tests/test_server.py +0 -0
  541. {amicus-0.3.0 → amicus-0.5.0}/tests/test_surface.py +0 -0
  542. {amicus-0.3.0 → amicus-0.5.0}/tests/test_taskmap.py +0 -0
  543. {amicus-0.3.0 → amicus-0.5.0}/tests/test_tasks_spike.py +0 -0
  544. {amicus-0.3.0 → amicus-0.5.0}/tests/test_wheel_seam.py +0 -0
  545. {amicus-0.3.0 → amicus-0.5.0}/tests/test_wire_shape.py +0 -0
@@ -7,7 +7,12 @@
7
7
  "plugins": [
8
8
  {
9
9
  "name": "amicus",
10
- "source": "./",
10
+ "source": {
11
+ "source": "url",
12
+ "url": "https://github.com/briandconnelly/amicus.git",
13
+ "ref": "v0.4.0",
14
+ "sha": "970905ad7141d2d3e650b7401685b893abf258db"
15
+ },
11
16
  "description": "One MCP server for every second-opinion model: consult, review, and delegate with the backend as a parameter."
12
17
  }
13
18
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amicus",
3
- "version": "0.3.0",
3
+ "version": "0.5.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.5.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.5.0",
8
8
  "amicus-mcp"
9
9
  ],
10
10
  "env_vars": [
@@ -29,12 +29,13 @@ The rules bind; the context after them explains and points elsewhere.
29
29
  17. Never edit a sibling checkout (`~/projects/codex-in-claude`, `~/projects/moonbridge`, `~/projects/claude-in-codex`, `~/projects/pontonier`).
30
30
  18. Never write a prompt input — every field in `INPUT_FIELDS` (`src/amicus/request.py`): `question`, `task`, `extra_context`, `instructions_append`, `focus`, `target`, `evidence` — to disk, to a worker's argv or to a log; it travels over the worker's stdin.
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
- 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.
32
+ A backend's own native carrier is exempt where no documented or observed way to avoid it has been found on the backend CLI release an amicus release is validated against, re-checked before every amicus release on the CLI versions its rule-20 evidence is recorded on, and the carrier is disclosed in its `CARRIERS` string and surfaced on `amicus_backends`; the three that exist today are Kimi's handshake file, the kimi CLI's own session store, 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,18 +48,27 @@ 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
- A backend's own prompt carriers (for Codex, the developer-instructions argv token and the stdin prompt) are disclosed on `amicus_backends`.
66
+ A backend's own prompt carriers (for Codex, the developer-instructions argv token and the stdin prompt; for Kimi, the handshake file and the CLI's own session store) are disclosed on `amicus_backends`.
67
+ Rule 18's exemption is bounded by evidence rather than by proof, because whether a closed-source CLI offers an alternative cannot be proven, only looked for: the condition is that none was found, documented or observed, and the looking is repeated before every amicus release, on the exact CLI versions the rule-20 evidence run uses.
68
+ It is tied to the release rather than to a change in a backend's supported-version set because that set is coarse: a kimi patch release still parses as its minor, and every claude 2.x release is covered by major 2, so a new CLI release can become supported without the set ever changing.
69
+ Kimi's handshake file exists because kimi ignores stdin.
70
+ Codex's argv token exists because `codex exec --help` (0.155.1) offers the prompt, on stdin, and no flag for developer-role instructions, which leaves the `developer_instructions` config value, set with `-c` on argv or from a config file; argv is the one that leaves nothing on disk.
71
+ Kimi's session store is different in kind: the CLI rather than amicus writes it, it outlives the run, and amicus does not delete it; the 0.43.1 probe that found no way to switch it off, and what that probe did not test, are recorded in `docs/kimi-help/0.43.1/FINDINGS.md`.
62
72
 
63
73
  ### The gate
64
74
 
@@ -76,12 +86,14 @@ The README's "Where things are" table indexes the rest.
76
86
 
77
87
  ### Releases
78
88
 
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.
89
+ 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.
90
+ 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`.
91
+ 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).
92
+ 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`.
93
+ 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.
94
+ Rule 24's invariant, that the pointer users follow names an already-published release, moved with it from `.mcp.json` to the marketplace entry.
95
+ `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.
96
+ `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
97
  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
98
  That evidence is an honest-mistake guard, not an attestation; it is a local file its author can write by hand.
87
99
  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 +113,7 @@ Those are held by the platform controls around the release — rule 21's ruleset
101
113
  ### Siblings
102
114
 
103
115
  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).
116
+ `~/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
117
 
105
118
  ### Local hooks
106
119
 
@@ -20,6 +20,308 @@ per-change, as its own lead says.
20
20
 
21
21
  ## [Unreleased]
22
22
 
23
+ ## [0.5.0] - 2026-09-20
24
+
25
+ Across this release the discovery surface moves `amicus/0.1/schema-35`, what 0.4.0 shipped, to
26
+ `amicus/0.1/schema-39`, and stored job results move `RESULT_FORMAT` 7 to 9, so a job result 0.4.0
27
+ stored cannot be delivered after upgrading. The entries labelled **Breaking** are the changes a
28
+ caller or operator using 0.4.0 has to handle, and `docs/MIGRATION.md` ("Upgrading from 0.4.0")
29
+ walks through each. It was checked against codex-cli 0.155, Kimi Code 2.0 and Claude Code 2.1.278.
30
+
31
+ ### Changed
32
+
33
+ - Kimi Code 2.0 is a supported version, so `amicus_backends` no longer warns on it. Kimi Code
34
+ went from 0.43.1 to 2.0.2 in one upgrade; amicus has seen no 1.x and claims none. It was
35
+ checked against the 0.43.1 capture at zero spend: `--help` differs by one new subcommand and no
36
+ option, the `provider list --json` shape is identical, and `kimi session` still offers `list`
37
+ only and still reads the existing session store, so no new way to avoid that carrier was
38
+ found. The kimi live suite then passed on 2.0.2, which exercises consult, the read-only tool
39
+ profile, review and delegate; whether 2.0.2 still writes to the session store was not looked
40
+ at in that run (#202).
41
+ - Releasing now checks the backend CLIs first. `docs/RELEASING.md` gains a precondition, run
42
+ immediately before the release evidence: bring `codex`, `kimi` and `claude` to their latest
43
+ releases, run the new zero-spend `scripts/check_backend_compat.py` (installed and latest
44
+ version, the warnings `amicus_backends` would raise, and the flags each `--help` declares
45
+ against the newest committed capture), and do the AGENTS.md rule-18 carrier re-check by
46
+ reading, which no script can. Codex gains its first committed help capture (0.155.1), held
47
+ to the flags amicus always sends as Kimi's and Claude's already were, and Claude gains one for
48
+ 2.1.278. Nothing about how amicus runs changes (#188).
49
+ - codex-cli 0.155 is a supported version, so `amicus_backends` no longer warns on it. It was
50
+ checked against 0.154.0 at zero spend: `--help`, `exec --help`, `exec review --help` and
51
+ `login --help` are byte-identical, the unknown-feature error and the logged-out `login status`
52
+ line are unchanged, both features amicus disables on every run are still `stable`, the cached
53
+ model list is the same seven slugs in the same order, the tool list sent to `gpt-5.5` is
54
+ identical with and without those disables, and the four config keys amicus pins with `-c` are
55
+ accepted under `--strict-config` while an unknown key is still rejected in the form amicus
56
+ parses. No paid call was part of the check (#187).
57
+
58
+ ### Removed
59
+
60
+ - **Breaking.** `amicus_dry_run`, the deprecated alias of `amicus_review_changes_dry_run`, is
61
+ removed. It was deprecated in 0.3.0 (#98) with a marker in its lifecycle `_meta`, on its
62
+ `amicus_capabilities` row and at the head of its description, each naming 0.5.0, and ADR 0028
63
+ removes a tool at the end of its window. Call `amicus_review_changes_dry_run` with the same
64
+ arguments. The server now lists 18 tools, and no tool carries a deprecation marker; the
65
+ mechanism and `amicus_capabilities.deprecation_policy` stay (#204).
66
+
67
+ ### Fixed
68
+
69
+ - **Surface.** A replayed keyed `_async` call can hand back a job that is already terminal, and
70
+ its handle's `follow_up` still said `poll_job_status` / `amicus_job_status`, which the skill's
71
+ own rules forbid for a finished job. A terminal handle now carries `next_step:
72
+ fetch_job_result` and `tool: amicus_job_result` with the same `job_id` and `workspace_root`; a
73
+ running handle is unchanged. The two are separate correlated shapes in the output schema, so
74
+ no mismatched step/tool pair is admitted. `fetch_job_result` is a new `repair.next_step`
75
+ value. A caller that went by `status`, as the 0.4.0 descriptions told it to, changes nothing
76
+ (#103).
77
+ - **Surface.** The `idempotency_key` parameter description said the key is scoped to "this tool
78
+ + backend + workspace", which reads as though the same key on another backend were a separate
79
+ identity. It never was: the key is scoped to the tool and the workspace, and `backend` is one
80
+ of the arguments that must match, so that call is an `idempotency_conflict`. The description
81
+ now says so; behaviour is unchanged (#178).
82
+ - **Breaking.** An answer file amicus refuses to read is no longer delivered as an empty answer.
83
+ The bounded reader accepts only a regular file within 1,000,000 bytes (ADR 0009), and a file
84
+ it refused was indistinguishable from a backend that wrote nothing: a Codex review came back
85
+ `invalid_json`, and a Codex consult came back `ok: true` with "(the backend returned no
86
+ message)". Both are now the new error `answer_unavailable`, with `error.details.reason` one of
87
+ `artifact_oversize` (carrying `limit_bytes` and, when known, `actual_bytes`),
88
+ `artifact_not_regular` or `artifact_unreadable`, never the path. It is temporary only for an
89
+ unreadable file whose cause passes (descriptor or memory exhaustion); oversize repairs with
90
+ `reduce_input`. Every other failure is still reported as itself, a refusal
91
+ standing in only for a clean exit diagnosed as empty. A Kimi run whose stream carried the
92
+ answer, captured whole, is delivered with a `meta.security_warnings` entry. A delegate with no
93
+ such answer keeps its captured diff, with amicus's own summary saying the backend's could not
94
+ be read and `raw_response.text` left null. An absent or empty file is unchanged: that is the
95
+ backend saying nothing. The reader also now reads to the end of the file, where one short
96
+ `read` could have delivered a prefix as the whole answer. The new error code is one of the two changes that move
97
+ `RESULT_FORMAT` in this release, since an older reader's closed set of codes rejects it (#162).
98
+ - **Breaking.** A finding that cited one of amicus's own temporary files no longer carries it.
99
+ Kimi is handed its prompt as a file, so a finding could come back with `file` set to
100
+ `<tmp>/amicus-kimi-handshake-…/prompt.md` and `line` set to an offset into amicus's framing:
101
+ a path deleted before the result is read, and a line into nothing the caller supplied. Every
102
+ reference to a run's own staged files is now replaced by `[amicus temporary file]`, in the
103
+ summary, the prose lists, a finding's text and `raw_response.text`, before the result is
104
+ built or stored; a `file` that named one is null together with its `line`; and
105
+ `findings_diagnostics.reasons` reports `backend_artifact_reference_removed` at `dropped: 0`.
106
+ It never moves a verdict, and a failed run's error message is scrubbed the same way. Only the
107
+ run's own staged paths match, the files it listed and anything under Kimi's per-run handshake
108
+ directory, at path boundaries, so a workspace file that merely looks like one is untouched.
109
+ A JSON answer is judged by what it decodes to, object keys included, whatever spelling it
110
+ used; an answer that is prose around a JSON fragment is never decoded, so there the `\/` and
111
+ `\u002f` spellings of a separator are recognised and a path spelled wholly in `\uXXXX` is
112
+ not (#207). The new reason is the other change that moves `RESULT_FORMAT`, so a job result
113
+ 0.4.0 stored is `job_result_incompatible` after upgrading: fetch it first
114
+ (`docs/MIGRATION.md`, "Upgrading from 0.4.0") (#140).
115
+
116
+ - The codex live gate, whose passing run is part of the evidence a release is tagged on, could
117
+ pass on a codex version amicus had never checked: it asserted only the `codex-cli` prefix, as
118
+ 0.3.0's run on 0.154.0 showed. It now requires the installed minor to be in the built-in
119
+ `SUPPORTED_VERSIONS` and `amicus_backends` to report no warnings, so neither an ambient
120
+ `AMICUS_CODEX_SUPPORTED_VERSIONS` nor an unparseable version string can vouch for one (#113).
121
+ - Kimi's `carriers` disclosure on `amicus_backends(detail="full")` now names the kimi CLI's own
122
+ session store (observed under `~/.kimi-code/sessions`), whose files can hold the whole prompt and
123
+ any answer produced. amicus does not delete it, and `AMICUS_JOB_TTL`, the per-workspace cap and
124
+ `amicus_job_consume_result` never reach it. Kimi's `readonly_honesty` no longer says Kimi
125
+ "cannot MODIFY anything": read-only removes the agent's shell and write tools, not the CLI's
126
+ own session files. Nothing about what is written changed; only what is said about it (#179).
127
+ - A relative `AMICUS_STATE_DIR`, `AMICUS_CODEX_BIN`, `AMICUS_KIMI_BIN` or `AMICUS_CLAUDE_BIN` is
128
+ now refused instead of being resolved against the process's working directory. The server and
129
+ each job worker resolve configuration separately, and a worker runs from its job directory, so
130
+ a relative value named one place to the server and another to the worker. With a relative
131
+ state directory the server now refuses to start, naming the variable on stderr: falling back
132
+ to the default would keep whole answers somewhere the operator did not choose. A relative
133
+ binary override makes that backend report the override as unusable, as a missing file already
134
+ did. Absolute values are unchanged, and so is a leading `~` in `AMICUS_STATE_DIR`, which is
135
+ still expanded. `$XDG_CACHE_HOME` is different: a value that is not absolute as written,
136
+ `~/cache` included, is ignored and never expanded, as the XDG Base Directory specification
137
+ requires (#173).
138
+ - `config.settings()` no longer documents itself as never raising: it never raises on a
139
+ malformed or conflicting setting, and an unresolvable home directory is a startup failure
140
+ (#147).
141
+
142
+ ## [0.4.0] - 2026-09-18
143
+
144
+ Across this release the discovery surface moves `amicus/0.1/schema-30`, what 0.3.0 shipped, to
145
+ `amicus/0.1/schema-35`, and stored job results move `RESULT_FORMAT` 6 to 7, so a job result 0.3.0
146
+ stored cannot be delivered after upgrading. The entries labelled **Breaking** are the changes a
147
+ caller or operator using 0.3.0 has to handle, and `docs/MIGRATION.md` ("Upgrading from 0.3.0")
148
+ walks through each.
149
+
150
+ ### Added
151
+
152
+ - The `collaborating-with-amicus` skill gains a blind-comparison workflow
153
+ (`references/blind-comparison.md`): two or more finalized candidates, compared by a backend
154
+ that wrote none of them, blinded, against criteria fixed before the call, returning
155
+ per-criterion reasons and one preference the host verifies as a finding rather than a score it
156
+ adopts. A new root rule says a backend's stated preference never stands in for the decision.
157
+ No tool or server surface changes and `FINGERPRINT` does not move.
158
+
159
+ ### Changed
160
+
161
+ - Every paid tool, sync and async, and the `detail` parameter now disclose that the job record
162
+ keeps the backend's whole answer whatever `detail` delivered it, that the answer can quote the
163
+ caller's inputs, and what ends it: expiry under `AMICUS_JOB_TTL` (an expired record is removed
164
+ on a later job call, not by a daemon), the per-workspace cap or `amicus_job_consume_result`
165
+ (#163, ADR 0035). Nothing stored or delivered changes: the record has kept the answer since M2,
166
+ and the decision recorded is that rule 18 binds the inputs amicus writes, not the answer a
167
+ backend returns. **Surface**: `FINGERPRINT` moves to schema-35 for the description text.
168
+ - amicus no longer depends on `pontonier`. Its backend SDK is now part of amicus, as
169
+ `amicus.sdk` (#13, ADR 0029): the same code as pontonier 0.9.0, copied from its `v0.9.0`
170
+ tag with the imports rewritten. Nothing on the wire or in a stored job result changes, and
171
+ `FINGERPRINT` does not move. A third-party backend distribution imports the SDK types from
172
+ `amicus.sdk` instead of `pontonier` and declares plugin API version 2: `PLUGIN_API_VERSION`
173
+ moved from 1 to 2, so the registry rejects a plugin that pins `api_version=1` (#115 covers
174
+ one that leaves it unset). No release can enable a third-party backend yet, so no running
175
+ deployment is affected. SDK log records are no longer named `pontonier.*` in stderr and
176
+ `AMICUS_LOG_FILE`, since the log format prints the logger name, which matters for an
177
+ operator who filters logs by name: they are named `amicus.sdk.*`, except the job store and
178
+ its idempotency index, which are `amicus.jobs.store` and `amicus.jobs.idempotency`. These
179
+ `amicus.sdk` import paths are not yet stable for a third-party backend. ADR 0030 settles
180
+ where they end up, and this release leaves that move finished (#118–#123): `amicus.sdk`
181
+ holds what a backend imports — the backend protocol and contract, the error vocabulary,
182
+ annotations and preflight, the subprocess runtime, stream capping, redaction, path-alias
183
+ sanitizing and a bounded JSON reader — plus the conformance kit, which is the one thing
184
+ there that a backend does not import: the registry imports it and runs it against a plugin
185
+ before it will use one. The job store, the git layer, the fingerprint mechanics and the
186
+ prompt framings live in the amicus package that owns each. Of the pontonier-named literals
187
+ the copy brought with it, one was visible outside the code: the throwaway directory amicus
188
+ creates to run git with its hooks disabled is now named `amicus-nohooks-*` under the system
189
+ temp dir, not `pontonier-nohooks-*`. Nothing keys on that name.
190
+
191
+ ### Removed
192
+
193
+ - **Breaking.** The three siblings' environment names — `CODEX_IN_CLAUDE_*`, `MOONBRIDGE_*`
194
+ and `CLAUDE_IN_CODEX_*` — are no longer read (#176), as 0.3.0's warnings and
195
+ `docs/MIGRATION.md` said they would not be from 0.4.0. An operator who still sets one gets
196
+ the `AMICUS_*` default instead of the value, which for `CODEX_IN_CLAUDE_ISOLATION` or
197
+ `CLAUDE_IN_CODEX_CLAUDE_CONFIG` is looser than what was set. Each former name is now a
198
+ tombstone on the `AMICUS_*` declaration that replaced it: a name still set is reported by
199
+ `amicus_backends`, in `env_warnings` for a global setting and in the backend's
200
+ `status.warnings` for a backend one (so only while that backend is enabled and loaded),
201
+ naming the `AMICUS_*` name to set; its value is never read, not even to recognise a
202
+ placeholder, so it neither supplies the setting nor conflicts with the `AMICUS_*` value,
203
+ and the conflict error of the window is gone with it. The tombstones have no removal window: they
204
+ are the migration table's data and a diagnostic, not a compatibility path. The shim itself
205
+ (`EnvVar.legacy`) and the release guard that refuses a release at or past
206
+ `LEGACY_REMOVAL_VERSION` while an alias is declared both stay, so a later rename gets the
207
+ same window. `FINGERPRINT` moves to `schema-34` only because the `amicus_backends`
208
+ description no longer says "legacy-env warnings"; no schema changes.
209
+
210
+ ### Fixed
211
+
212
+ - **Surface.** A Claude budget stop no longer reports `input_tokens: 0` and
213
+ `output_tokens: 0` beside a nonzero `cost_usd` (#158). claude prints its top-level `usage`
214
+ block zeroed on that envelope while `modelUsage` carries the real counts, and its own
215
+ result schema names `modelUsage` as the accounting field, so `meta.usage` now comes from
216
+ `modelUsage` (summed across models) whenever at least one of its entries is an object,
217
+ and from the top-level block only when none is (ADR 0034). A field is read from one
218
+ block, never both: once `modelUsage` is in use, a field any one entry leaves out is
219
+ `null`, and a non-object entry beside an object one makes every count `null`. So an older
220
+ envelope whose `modelUsage` has no cache keys now reports `cached_input_tokens` and
221
+ `cache_creation_input_tokens` as `null` where it used to copy the block's numbers.
222
+ `budget_exceeded`'s message and repair, the `max_budget_usd` option description and the
223
+ `AMICUS_CLAUDE_MAX_BUDGET_USD` description now say claude checks the threshold only
224
+ between model calls, so one call can carry the estimated cost past it; none states an
225
+ overshoot bound, and the repair no longer suggests a 0.10-0.20 floor it had no evidence
226
+ for. The recorded 2.1.274 budget-stop envelope is `tests/fixtures/claude_budget_stop_envelope.json`,
227
+ documented in `docs/claude-help/2.1.274/`. `RESULT_FORMAT` does not move.
228
+
229
+ - Every tool that resolves a workspace no longer fails as a retryable `internal_error`
230
+ (`FileNotFoundError`) when the server process's working directory has been deleted under
231
+ it, as happens when the Claude Code worktree the server was started in is removed (#170).
232
+ The resolver now reads the process cwd only on the one branch where it decides the
233
+ outcome (no `workspace_root`, no client root, and `AMICUS_ALLOW_CWD_WORKSPACE=1`), so a
234
+ call that names its workspace never consults it. When that branch is reached and the cwd
235
+ is gone, the call fails as a non-temporary `invalid_workspace_root` whose message says to
236
+ pass `workspace_root`, configure an MCP root, or restart the server from an existing
237
+ directory, instead of a `retry_then_report` repair that could never succeed. No error
238
+ code was added and `FINGERPRINT` does not move.
239
+
240
+ - Codex usage-limit failures without a parseable relative delay now report
241
+ `retry_after_ms: null` with an `inspect_and_retry` repair instead of inventing a
242
+ 60-second delay for a reset that may be days away (#165). When codex states the reset
243
+ as a clock time (`try again at Sep 19th, 2026 8:37 AM.` or `try again at 12:39 PM.`),
244
+ that phrase is echoed in `error.message`, `error.details.reason` and the repair, marked
245
+ as a clock time with no time zone stated when it names none, so the caller can read the
246
+ reset it must wait for. Only a clock-time shape is echoed; other wording gets the generic
247
+ guidance. Explicit relative delays and the 60-second fallback for ordinary rate limits are
248
+ unchanged.
249
+
250
+ - Codex failure classification now reads backend error events and stderr instead of
251
+ matching authentication, contract-drift and rate-limit terms in model answers or tool
252
+ output (#166). Model prose can no longer override the backend's diagnosis or retry delay.
253
+ Generic failure details also exclude model and tool items, preventing that text from
254
+ being copied into a background job's stored error.
255
+ Plain-text startup diagnostics and error events containing only an HTTP status remain
256
+ supported. Neither `FINGERPRINT` nor `RESULT_FORMAT` moves.
257
+
258
+ - `amicus_backends` no longer reports `authenticated: false` whenever the Codex login-status
259
+ probe exits nonzero (#169). Only a recognized authentication failure reports `false`; a
260
+ configuration error or other probe failure reports `authenticated: null` and adds a sanitized
261
+ diagnostic to the backend's warnings. `FINGERPRINT` does not move.
262
+
263
+ - **Surface.** `amicus_review_changes` on the `claude` backend now defaults to
264
+ `backend_options.access = "readonly"` (#116, ADR 0032). On the previous `toolless` default a
265
+ review had no tool to read the code it was judging, and answered with tool-call markup
266
+ instead of the review: amicus reported `invalid_json`, or under the default
267
+ `config_mode = "inherit"` ran to the budget stop. A Claude review that omits `access` can now
268
+ read files with `Read`, `Grep` and `Glob`, inside and outside the workspace, which bypasses
269
+ diff redaction; pass `access: "toolless"` to keep the old behaviour for one call.
270
+ `amicus_consult` and `amicus_adversarial_review` still default to `toolless`, and setting
271
+ `AMICUS_CLAUDE_ACCESS` sets the default for every verb, reviews included. A structured Claude
272
+ review also now carries the output guardrails adversarial reviews already had, telling the
273
+ model never to simulate a tool call. `amicus_backends` reports `access` under
274
+ `default_by_verb`. `FINGERPRINT` moves to `amicus/0.1/schema-31`.
275
+ - **Breaking.** A review whose answer amicus cannot read as one JSON object is no longer
276
+ discarded (#139, ADR 0033). `amicus_review_changes` and `amicus_adversarial_review` used to
277
+ return `invalid_json` or `schema_violation`. They kept a 300-character preview of the answer,
278
+ lost the rest, and prescribed a retry that could fail the same way. They now return
279
+ `ok: true` with the new `review_status: unstructured`: `verdict` and `confidence` are
280
+ `unknown`, `findings` and the prose lists are empty with diagnostics saying nothing was
281
+ parsed, and the whole answer, redacted, is `raw_response.text`, at `detail="full"` on the call
282
+ or free from `amicus_job_result`. A caller that read the verdict after checking `ok` must now
283
+ handle this value. An answer that wraps exactly one object in a preamble, a fence or a
284
+ sign-off is now read as that object. A repeated key is still refused (#51). Only an empty
285
+ answer is still an error (`invalid_json`, or `empty_response` on Kimi), and
286
+ `schema_violation` is no longer a review outcome. `empty_response`, which Kimi already
287
+ returned for an empty answer, is now listed in the `error_codes` of every paid tool that can
288
+ select Kimi.
289
+ `RESULT_FORMAT` moves to 7 and `FINGERPRINT` to `amicus/0.1/schema-32`.
290
+
291
+ - A plugin install no longer runs an older release's server than its bundled skills (#117,
292
+ ADR 0031, superseding ADR 0015). Hosts key an installed plugin by `plugin.json`'s version and
293
+ do not re-read it until that version changes, so a plugin whose `.mcp.json` named the previous
294
+ release kept launching that older server. `.mcp.json` now names its own release, and after
295
+ 0.4.0 is published the marketplace entry pins that tag by `ref` and `sha`, so the installed
296
+ skills and server come from one release snapshot. Installs already stuck on an older server
297
+ recover when the 0.4.0 version change reaches them.
298
+
299
+ - **Security.** An exception's own text can no longer reach a background job's `stderr.log`
300
+ (#128). The job worker never called `obs.configure`, so nothing in that process installed
301
+ the handlers that withhold exception text, and an `amicus.*` record fell through to
302
+ `logging.lastResort` — which renders the exception's `str()` and a full traceback. The
303
+ worker's stdout and stderr are both `<job_dir>/stderr.log`, so that text was written to a
304
+ file the job keeps. The reachable call site is the SDK runtime's
305
+ `logger.error("stdout capture failed: %s", exc, exc_info=True)` on a capture failure, and
306
+ an exception raised inside a backend adapter can embed the prompt text that provoked it,
307
+ which AGENTS.md rule 18 forbids writing to a log. `_worker.main` now configures logging
308
+ before anything else it does, so such a record renders as the exception's type and its
309
+ frame locations, the same policy the server has always applied. The worker inherits the
310
+ server's environment, so it honours the same `AMICUS_LOG_LEVEL` and `AMICUS_LOG_FILE` —
311
+ except a *relative* `AMICUS_LOG_FILE`, which it drops: `logging.FileHandler` resolves a
312
+ relative path against the process's cwd, and the worker's cwd is the job directory, so
313
+ honouring it would leave a differently-located log file inside every job directory instead
314
+ of adding to the one file the operator asked for. An absolute path is honoured, and the
315
+ server's own handler is unaffected either way. Nothing about a job's result, status or
316
+ wire shape changes, and `FINGERPRINT` does not move.
317
+ - A `codex` run that hit its usage limit could fail as `backend_auth_required` instead of
318
+ `backend_rate_limited` (#160). The classifier checks authentication first and matched the bare
319
+ substring `401`, so any output carrying those digits, such as a token count of 14012, read as
320
+ "not authenticated". The repair then told the caller to log in again, and marked the failure
321
+ not temporary. A `401` now counts only as an HTTP status, and codex's own "could not be
322
+ refreshed" token failures are recognized as authentication failures. `FINGERPRINT` does not
323
+ move.
324
+
23
325
  ## [0.3.0] - 2026-09-15
24
326
 
25
327
  Across this release the discovery surface moves `amicus/0.1/schema-13`, what 0.2.0 shipped, to
@@ -532,7 +834,9 @@ per-change rather than net, so they also name intermediate states that no releas
532
834
  - The tagged publish path to pypi.org has never run. Only the TestPyPI dispatch path has been exercised.
533
835
  - 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
836
 
535
- [Unreleased]: https://github.com/briandconnelly/amicus/compare/v0.3.0...HEAD
837
+ [Unreleased]: https://github.com/briandconnelly/amicus/compare/v0.5.0...HEAD
838
+ [0.5.0]: https://github.com/briandconnelly/amicus/compare/v0.4.0...v0.5.0
839
+ [0.4.0]: https://github.com/briandconnelly/amicus/compare/v0.3.0...v0.4.0
536
840
  [0.3.0]: https://github.com/briandconnelly/amicus/compare/v0.2.0...v0.3.0
537
841
  [0.2.0]: https://github.com/briandconnelly/amicus/compare/v0.1.0...v0.2.0
538
842
  [0.1.0]: https://github.com/briandconnelly/amicus/releases/tag/v0.1.0