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.
- {amicus-0.3.0 → amicus-0.5.0}/.claude-plugin/marketplace.json +6 -1
- {amicus-0.3.0 → amicus-0.5.0}/.claude-plugin/plugin.json +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/.codex-plugin/plugin.json +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/.github/dependabot.yml +11 -0
- {amicus-0.3.0 → amicus-0.5.0}/.github/workflows/test.yml +17 -0
- {amicus-0.3.0 → amicus-0.5.0}/.mcp.json +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/AGENTS.md +27 -14
- {amicus-0.3.0 → amicus-0.5.0}/CHANGELOG.md +305 -1
- {amicus-0.3.0 → amicus-0.5.0}/PKG-INFO +35 -33
- {amicus-0.3.0 → amicus-0.5.0}/README.md +34 -31
- {amicus-0.3.0 → amicus-0.5.0}/docs/DEPRECATING-SIBLINGS.md +10 -6
- {amicus-0.3.0 → amicus-0.5.0}/docs/MIGRATION.md +71 -18
- {amicus-0.3.0 → amicus-0.5.0}/docs/RELEASING.md +68 -17
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0003-workspace-resolution.md +1 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0015-mcp-json-pins-an-already-published-release.md +2 -1
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0023-dependency-loggers-are-owned-at-a-warning-floor.md +6 -2
- amicus-0.5.0/docs/adr/0029-the-backend-sdk-lives-in-tree.md +63 -0
- amicus-0.5.0/docs/adr/0030-the-sdk-keeps-what-a-backend-imports.md +46 -0
- amicus-0.5.0/docs/adr/0031-the-marketplace-pointer-decides-what-users-run.md +47 -0
- amicus-0.5.0/docs/adr/0032-a-claude-review-defaults-to-readonly-access.md +43 -0
- amicus-0.5.0/docs/adr/0033-an-unreadable-review-answer-is-delivered-unstructured.md +64 -0
- amicus-0.5.0/docs/adr/0034-claude-usage-is-read-from-model-usage.md +29 -0
- amicus-0.5.0/docs/adr/0035-a-backend-answer-is-kept-on-the-job-record.md +54 -0
- amicus-0.5.0/docs/adr/0036-a-refused-answer-file-is-answer-unavailable.md +69 -0
- amicus-0.5.0/docs/claude-help/2.1.274/FINDINGS.md +39 -0
- amicus-0.5.0/docs/claude-help/2.1.274/budget-stop-envelope-shape.json +52 -0
- amicus-0.5.0/docs/claude-help/2.1.274/claude-version.txt +1 -0
- amicus-0.5.0/docs/claude-help/2.1.278/claude-help.txt +302 -0
- amicus-0.5.0/docs/claude-help/2.1.278/claude-version.txt +1 -0
- amicus-0.5.0/docs/codex-help/0.155.1/codex-help.txt +112 -0
- amicus-0.5.0/docs/codex-help/0.155.1/codex-version.txt +1 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.43.1/FINDINGS.md +24 -0
- amicus-0.5.0/docs/kimi-help/2.0.2/FINDINGS.md +86 -0
- amicus-0.5.0/docs/kimi-help/2.0.2/kimi-help.txt +51 -0
- amicus-0.5.0/docs/kimi-help/2.0.2/kimi-version.txt +1 -0
- amicus-0.5.0/docs/kimi-help/2.0.2/provider-list-shape.json +18 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/superpowers/specs/2026-09-04-amicus-design.md +23 -25
- amicus-0.5.0/docs/superpowers/specs/2026-09-15-amicus-M8-sdk-in-tree-design.md +224 -0
- amicus-0.5.0/docs/superpowers/specs/2026-09-16-amicus-release-activation-design.md +343 -0
- {amicus-0.3.0 → amicus-0.5.0}/prek.toml +2 -1
- {amicus-0.3.0 → amicus-0.5.0}/pyproject.toml +38 -3
- amicus-0.5.0/scripts/check_backend_compat.py +347 -0
- {amicus-0.3.0 → amicus-0.5.0}/scripts/check_commit_message.py +1 -0
- {amicus-0.3.0 → amicus-0.5.0}/scripts/check_release_state.py +250 -40
- {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/SKILL.md +17 -5
- amicus-0.5.0/skills/collaborating-with-amicus/references/blind-comparison.md +149 -0
- {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/choosing-a-backend.md +9 -2
- {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/options-and-errors.md +7 -3
- {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/reading-results.md +33 -2
- {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/sync-vs-async.md +9 -2
- {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/tests/scenarios.md +89 -1
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/__init__.py +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/_worker.py +30 -4
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/__init__.py +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/__init__.py +4 -5
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/adapter.py +14 -11
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/adversarial.py +7 -1
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/binary.py +8 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/cli.py +19 -19
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/config.py +32 -15
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/contract.py +6 -2
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/normalize.py +66 -18
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/options.py +9 -2
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/status.py +1 -2
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/__init__.py +4 -5
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/adapter.py +7 -9
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/binary.py +9 -2
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/cli.py +71 -21
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/config.py +10 -11
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/contract.py +73 -17
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/models.py +2 -3
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/normalize.py +22 -4
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/status.py +5 -5
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/__init__.py +12 -6
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/adapter.py +8 -8
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/binary.py +8 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/cli.py +7 -8
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/config.py +9 -11
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/contract.py +10 -6
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/models.py +1 -2
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/normalize.py +1 -2
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/status.py +2 -4
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/config/__init__.py +52 -26
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/config/envspec.py +56 -14
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/errors.py +14 -6
- amicus-0.5.0/src/amicus/jobs/__init__.py +2 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/jobs/delivery.py +1 -1
- amicus-0.5.0/src/amicus/jobs/idempotency.py +466 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/jobs/lifecycle.py +34 -15
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/jobs/lookup.py +1 -2
- amicus-0.5.0/src/amicus/jobs/polling.py +33 -0
- amicus-0.5.0/src/amicus/jobs/store.py +1049 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/jobs/taskmap.py +3 -3
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/manifest.py +3 -3
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/middleware.py +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/obs.py +29 -28
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/orchestration/finalize.py +244 -46
- amicus-0.5.0/src/amicus/orchestration/gitdiff.py +1179 -0
- amicus-0.5.0/src/amicus/orchestration/gitproc.py +205 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/orchestration/isolation.py +10 -8
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/orchestration/prompts.py +131 -9
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/orchestration/review.py +3 -4
- amicus-0.5.0/src/amicus/orchestration/run.py +368 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/orchestration/workspace.py +68 -12
- amicus-0.5.0/src/amicus/orchestration/worktree.py +665 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/plugin.py +8 -9
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/registry.py +4 -5
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/request.py +4 -4
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/codes.py +9 -5
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/envelope.py +1 -1
- amicus-0.5.0/src/amicus/schemas/fingerprint.py +188 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/options.py +3 -2
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/params.py +10 -5
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/results.py +34 -19
- amicus-0.5.0/src/amicus/schemas/structured.py +95 -0
- amicus-0.5.0/src/amicus/sdk/__init__.py +14 -0
- amicus-0.5.0/src/amicus/sdk/backend/__init__.py +19 -0
- amicus-0.5.0/src/amicus/sdk/backend/contract.py +137 -0
- amicus-0.5.0/src/amicus/sdk/backend/protocol.py +321 -0
- amicus-0.5.0/src/amicus/sdk/conventions/__init__.py +8 -0
- amicus-0.5.0/src/amicus/sdk/conventions/annotations.py +97 -0
- amicus-0.5.0/src/amicus/sdk/conventions/envelope.py +381 -0
- amicus-0.5.0/src/amicus/sdk/conventions/preflight.py +100 -0
- amicus-0.5.0/src/amicus/sdk/core/__init__.py +7 -0
- amicus-0.5.0/src/amicus/sdk/core/jsoncache.py +42 -0
- amicus-0.5.0/src/amicus/sdk/core/pathalias.py +430 -0
- amicus-0.5.0/src/amicus/sdk/core/redaction.py +1515 -0
- amicus-0.5.0/src/amicus/sdk/core/runtime.py +617 -0
- amicus-0.5.0/src/amicus/sdk/core/streamcap.py +286 -0
- amicus-0.5.0/src/amicus/sdk/testing/__init__.py +7 -0
- amicus-0.5.0/src/amicus/sdk/testing/conformance.py +119 -0
- amicus-0.5.0/src/amicus/sdk/testing/surface_honesty.py +52 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/server.py +4 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/surface.py +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/__init__.py +2 -3
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/_meta.py +6 -16
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/_prepare.py +2 -3
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/_resolve.py +9 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/consult.py +4 -2
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/delegate.py +3 -3
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/discovery.py +44 -16
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/dry_run.py +10 -56
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/jobs.py +2 -2
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/review.py +7 -5
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/wire_shape_snapshot.py +27 -4
- {amicus-0.3.0 → amicus-0.5.0}/tests/conftest.py +47 -14
- amicus-0.5.0/tests/fixtures/claude_budget_stop_envelope.json +82 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/fakebackend/src/fakebackend/__init__.py +11 -12
- {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/manifest_snapshot.all.json +336 -766
- {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/manifest_snapshot.claude.json +336 -766
- {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/manifest_snapshot.codex-kimi.json +336 -766
- {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/result_format_snapshot.json +12 -4
- {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/wire_shape_snapshot.json +186 -4
- amicus-0.5.0/tests/sdk/conftest.py +96 -0
- amicus-0.5.0/tests/sdk/test_annotations.py +85 -0
- amicus-0.5.0/tests/sdk/test_classified_failure_fields.py +70 -0
- amicus-0.5.0/tests/sdk/test_conformance_fakes.py +510 -0
- amicus-0.5.0/tests/sdk/test_conformance_inspector.py +94 -0
- amicus-0.5.0/tests/sdk/test_contract.py +88 -0
- amicus-0.5.0/tests/sdk/test_envelope.py +92 -0
- amicus-0.5.0/tests/sdk/test_fingerprint.py +93 -0
- amicus-0.5.0/tests/sdk/test_git_isolation.py +65 -0
- amicus-0.5.0/tests/sdk/test_gitdiff.py +2153 -0
- amicus-0.5.0/tests/sdk/test_gitproc.py +205 -0
- amicus-0.5.0/tests/sdk/test_idempotency.py +490 -0
- amicus-0.5.0/tests/sdk/test_jobs.py +1548 -0
- amicus-0.5.0/tests/sdk/test_jsoncache.py +59 -0
- amicus-0.5.0/tests/sdk/test_orphan_sweep.py +245 -0
- amicus-0.5.0/tests/sdk/test_outcome_inspector.py +90 -0
- amicus-0.5.0/tests/sdk/test_pair_parity_kit.py +72 -0
- amicus-0.5.0/tests/sdk/test_pathalias.py +614 -0
- amicus-0.5.0/tests/sdk/test_preflight.py +132 -0
- amicus-0.5.0/tests/sdk/test_prompts.py +119 -0
- amicus-0.5.0/tests/sdk/test_redaction.py +3411 -0
- amicus-0.5.0/tests/sdk/test_run_request.py +156 -0
- amicus-0.5.0/tests/sdk/test_runtime.py +1018 -0
- amicus-0.5.0/tests/sdk/test_runtime_kill_and_sweep_paths.py +145 -0
- amicus-0.5.0/tests/sdk/test_streamcap.py +351 -0
- amicus-0.5.0/tests/sdk/test_surface_honesty_kit.py +49 -0
- amicus-0.5.0/tests/sdk/test_usage_cache_fields.py +49 -0
- amicus-0.5.0/tests/sdk/test_workspace.py +53 -0
- amicus-0.5.0/tests/sdk/test_worktree.py +1004 -0
- amicus-0.5.0/tests/sdk/test_worktree_config.py +93 -0
- amicus-0.5.0/tests/support/__init__.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/support/claudefixtures.py +6 -3
- {amicus-0.3.0 → amicus-0.5.0}/tests/support/codexfixtures.py +2 -3
- {amicus-0.3.0 → amicus-0.5.0}/tests/support/fake_codex.py +29 -4
- {amicus-0.3.0 → amicus-0.5.0}/tests/support/fake_kimi.py +29 -5
- {amicus-0.3.0 → amicus-0.5.0}/tests/support/fakeplugin.py +11 -12
- {amicus-0.3.0 → amicus-0.5.0}/tests/support/kimifixtures.py +2 -3
- amicus-0.5.0/tests/support/livegate.py +22 -0
- amicus-0.5.0/tests/support/pair_parity.py +62 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_adversarial.py +10 -3
- amicus-0.5.0/tests/test_artifact_references.py +296 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_async_tools.py +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_cache_hints.py +3 -2
- amicus-0.5.0/tests/test_check_backend_compat.py +310 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_check_commit_message.py +6 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_adapter.py +55 -4
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_argv_differential.py +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_cli.py +2 -2
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_config.py +46 -14
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_contract.py +39 -2
- amicus-0.5.0/tests/test_claude_golden_envelope.py +158 -0
- amicus-0.5.0/tests/test_claude_normalize.py +190 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_plugin.py +14 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_result_differential.py +14 -7
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_status.py +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_sync_tools.py +96 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_codes.py +5 -5
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_adapter.py +73 -5
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_argv_differential.py +5 -5
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_binary.py +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_cli.py +168 -7
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_config.py +15 -6
- amicus-0.5.0/tests/test_codex_contract.py +320 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_live.py +5 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_normalize.py +26 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_result_differential.py +15 -3
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_status.py +23 -4
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_commands.py +28 -2
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_compaction.py +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_config.py +23 -11
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_delivery.py +2 -3
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_discovery.py +57 -12
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_discovery_cost.py +60 -2
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_dry_run.py +100 -57
- amicus-0.5.0/tests/test_envspec.py +208 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_errors.py +3 -3
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_fastmcp_argument_log.py +9 -15
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_finalize.py +84 -20
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_fingerprint.py +3 -3
- amicus-0.5.0/tests/test_import_contracts.py +47 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_isolation.py +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_job_tools.py +99 -3
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_adapter.py +3 -3
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_argv_differential.py +5 -5
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_cli.py +2 -2
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_config.py +12 -9
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_contract.py +7 -4
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_models.py +1 -2
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_plugin.py +26 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_result_differential.py +15 -3
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_status.py +4 -2
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_sync_tools.py +151 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_lifecycle.py +39 -10
- amicus-0.5.0/tests/test_livegate.py +46 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_log_redaction.py +42 -26
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_manifest.py +9 -8
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_meta.py +61 -22
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_migration_doc.py +29 -16
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_obs.py +8 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_packaging.py +22 -31
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_params.py +26 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_plugin.py +2 -2
- amicus-0.5.0/tests/test_poll_hint.py +57 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_prepare.py +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_registry.py +1 -1
- amicus-0.5.0/tests/test_relative_config_paths.py +110 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_release_state.py +383 -48
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_results.py +27 -11
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_review.py +1 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_run.py +264 -6
- amicus-0.5.0/tests/test_sdk_in_tree.py +183 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_skill_contract.py +20 -3
- amicus-0.5.0/tests/test_structured.py +111 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_surface_honesty.py +41 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_sync_tools.py +159 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_tasks_client.py +0 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_worker.py +114 -1
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_workspace.py +58 -0
- {amicus-0.3.0 → amicus-0.5.0}/uv.lock +13 -27
- amicus-0.3.0/src/amicus/jobs/__init__.py +0 -1
- amicus-0.3.0/src/amicus/jobs/polling.py +0 -36
- amicus-0.3.0/src/amicus/orchestration/run.py +0 -221
- amicus-0.3.0/src/amicus/schemas/fingerprint.py +0 -62
- amicus-0.3.0/src/amicus/schemas/structured.py +0 -64
- amicus-0.3.0/tests/test_claude_golden_envelope.py +0 -79
- amicus-0.3.0/tests/test_claude_normalize.py +0 -86
- amicus-0.3.0/tests/test_codex_contract.py +0 -168
- amicus-0.3.0/tests/test_envspec.py +0 -93
- amicus-0.3.0/tests/test_import_contracts.py +0 -17
- amicus-0.3.0/tests/test_poll_hint.py +0 -38
- amicus-0.3.0/tests/test_structured.py +0 -44
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-docs/SKILL.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-docs/references/design-workflow.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-docs/references/docs-checklist.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-docs/references/examples.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-docs/references/review-workflow.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-docs/tests/scenarios.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/SKILL.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/decisions/001-github-fact-sheet.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/audit-workflow.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/config-checklist.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/README.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/codeowners.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/harness-deny.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/identity.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/repo-files.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/required-checks.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/rulesets.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/examples/workflows.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/operating-playbook.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/setup-workflow.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/references/threat-model.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/tests/check_authority.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-github/tests/scenarios.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/SKILL.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/decisions/001-mcp-2026-07-28-rebase.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/decisions/002-machine-code-rename-rationale.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/decisions/003-offending-value-omission.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/decisions/004-ownership-boundaries.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/contract-checklist.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/design-workflow.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/examples.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/mcp-2025-11-25-compat.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/mcp-vs-cli.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/native-wire-shapes.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/review-workflow.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/references/vocabulary.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/check_fact_sync.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/check_rule_ids.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/check_stale_terms.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/fixtures/github_issues.json +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/fixtures/github_repo_resource.json +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/rule-ids.txt +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-baseline.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-outputschema-error.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-with-skill.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario2-baseline.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario2-with-skill.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario3-baseline.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario3-with-skill.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario4-baseline.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario4-with-skill.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario5-baseline.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario5-with-skill.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario6-baseline.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario6-with-skill.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario7-trigger.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario1-baseline.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario1-with-skill.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario3-baseline.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario3-with-skill.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario5-baseline.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario5-with-skill.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-30-scenario1-with-skill.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-30-scenario8-severity-calibration.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/scenarios.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/test_check_fact_sync.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/test_check_rule_ids.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/test_validate_fixture.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/agent-friendly-mcp/tests/validate_fixture.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/SKILL.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/agents/openai.yaml +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/references/example-audit.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/rescore-2026-08-06/preregistration.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/rescore-2026-08-06/results.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario1-baseline.md +0 -0
- {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
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario2-baseline.md +0 -0
- {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
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario3-baseline.md +0 -0
- {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
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario4-baseline.md +0 -0
- {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
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario5-baseline.md +0 -0
- {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
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario6-baseline.md +0 -0
- {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
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario7-baseline.md +0 -0
- {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
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario8-baseline.md +0 -0
- {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
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario9-trigger.md +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {amicus-0.3.0 → amicus-0.5.0}/.agents/skills/separating-context-from-constraints/tests/scenarios.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.gitattributes +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.github/CODEOWNERS +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.github/copilot-instructions.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.github/workflows/ci.yml +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.github/workflows/codeql.yml +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.github/workflows/dependency-review.yml +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.github/workflows/publish.yml +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/.gitignore +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/CLAUDE.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/LICENSE +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/adversarial.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/consult.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/delegate-async.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/delegate.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/dry-run.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/jobs.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/review.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/commands/amicus/status.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/2026-09-04-naming-and-scoping-notes.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0001-annotations-follow-the-worst-enabled-backend.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0002-backend-options-is-a-closed-superset.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0004-tasks-and-jobs.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0005-error-envelope-and-repair-precedence.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0006-fingerprint-and-surface-digest.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0007-m1-codex-port-decisions.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0008-m2-jobs-surface-decisions.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0009-m3-kimi-port-decisions.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0010-m4-claude-port-decisions.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0011-m5-tasks-decisions.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0012-m6-packaging-decisions.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0013-proceed-without-trademark-clearance.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0014-release-predicate-on-the-tag.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0016-skill-rules-are-a-complete-contract.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0017-an-unreadable-machine-enum-falls-to-its-own-floor.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0018-the-catalog-carries-a-ttl-and-resource-reads-do-not.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0019-review-results-disclose-coverage-as-a-field.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0020-idempotency-keys-on-the-sync-tools.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0021-repair-arguments-are-a-complete-call.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0022-consume-reports-its-discard-outcome.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0024-prose-list-loss-is-disclosed-never-folded.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0025-success-meta-is-sparse-on-every-tool.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0026-a-not-run-review-carries-no-confidence-rating.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0027-every-instructions-rule-fits-the-shown-prefix.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/0028-a-deprecated-tool-keeps-its-record-beside-one-marker.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/adr/README.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/claude-help/2.1.263/FINDINGS.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/claude-help/2.1.263/claude-help.txt +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/claude-help/2.1.263/claude-version.txt +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/claude-help/2.1.263/envelope-shape.json +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/claude-code/2.1.263/FINDINGS.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/claude-code/2.1.263/connection.log +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/claude-code/2.1.263/host-output.json +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/codex/0.153.4/FINDINGS.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/codex/0.153.4/connection.log +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/codex/0.153.4/host-output.jsonl +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/notes.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/server.log +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/transcript.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/install-smoke/claude-code/2.1.263/notes.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/install-smoke/claude-code/2.1.263/server.log +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/install-smoke/claude-code/2.1.263/transcript.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/install-smoke/codex/0.153.4/notes.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/install-smoke/codex/0.153.4/server.log +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/install-smoke/codex/0.153.4/transcript.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/notes.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/server.log +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/transcript.md +0 -0
- {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
- {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
- {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
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/notes.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/server.log +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/transcript.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/notes.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/server.log +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/transcript.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/notes.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/server.log +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/transcript.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.41.0/FINDINGS.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.41.0/kimi-help.txt +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.41.0/kimi-version.txt +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.41.0/provider-list-shape.json +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.42.0/FINDINGS.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.42.0/kimi-help.txt +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.42.0/kimi-version.txt +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.42.0/provider-list-shape.json +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.43.1/kimi-help.txt +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.43.1/kimi-version.txt +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/kimi-help/0.43.1/provider-list-shape.json +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/reviews/2026-09-07-agent-friendly-mcp-walk.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/docs/superpowers/plans/2026-09-04-amicus-execution-model.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/scripts/capture_claude_differentials.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/scripts/capture_codex_differentials.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/scripts/capture_kimi_differentials.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/scripts/check_github_actions_pinning.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/scripts/record_live_gate_evidence.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/active-workflows.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/independent-attempt.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/review-revise.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/reviewing-a-returned-diff.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/skills/collaborating-with-amicus/references/server-down-fallback.md +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/appstate.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/claude/models.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/codex/options.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/backends/kimi/options.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/compaction.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/orchestration/__init__.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/packaging.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/py.typed +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/result_format_snapshot.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/__init__.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/field_policy.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/instructions.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/schemas/publish.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/_guard.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/src/amicus/tools/resources.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/claude_differentials.json +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/claude_golden_envelope.json +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/codex_differentials.json +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/fakebackend/pyproject.toml +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/fixtures/kimi_differentials.json +0 -0
- {amicus-0.3.0/tests/support → amicus-0.5.0/tests/sdk}/__init__.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/support/fake_claude.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_check_github_actions_pinning.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_binary.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_live.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_claude_models.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_models.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_codex_plugin.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_conftest_guards.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_envelope.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_field_policy.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_guard.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_host_captures.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_instructions.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_job_durability.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_binary.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_live.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_kimi_normalize.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_live_gate_report.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_live_suite_hygiene.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_lookup.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_middleware.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_options.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_paid_tools.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_prompts.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_publish.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_release_evidence.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_request.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_resources.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_result_format.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_review_artifact.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_server.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_surface.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_taskmap.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_tasks_spike.py +0 -0
- {amicus-0.3.0 → amicus-0.5.0}/tests/test_wheel_seam.py +0 -0
- {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
|
+
"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
|
+
"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"
|
|
@@ -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
|
|
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
|
|
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
|
|
37
|
-
`.
|
|
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. `.
|
|
51
|
-
A release PR under rule 19 leaves it untouched;
|
|
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
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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.
|
|
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
|