amicus 0.6.0__tar.gz → 0.7.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.6.0 → amicus-0.7.0}/.claude-plugin/marketplace.json +2 -2
- {amicus-0.6.0 → amicus-0.7.0}/.claude-plugin/plugin.json +1 -1
- {amicus-0.6.0 → amicus-0.7.0}/.codex-plugin/plugin.json +1 -1
- {amicus-0.6.0 → amicus-0.7.0}/.mcp.json +1 -1
- {amicus-0.6.0 → amicus-0.7.0}/CHANGELOG.md +115 -1
- {amicus-0.6.0 → amicus-0.7.0}/PKG-INFO +19 -12
- {amicus-0.6.0 → amicus-0.7.0}/README.md +18 -11
- {amicus-0.6.0 → amicus-0.7.0}/commands/amicus/jobs.md +7 -3
- {amicus-0.6.0 → amicus-0.7.0}/docs/MIGRATION.md +28 -1
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0003-workspace-resolution.md +1 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0010-m4-claude-port-decisions.md +1 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0018-the-catalog-carries-a-ttl-and-resource-reads-do-not.md +2 -0
- amicus-0.7.0/docs/adr/0038-the-job-cap-never-evicts-an-unreturned-result.md +52 -0
- amicus-0.7.0/docs/adr/0039-a-deadline-timeout-is-never-temporary.md +51 -0
- amicus-0.7.0/docs/adr/0040-the-backend-enum-is-the-set-the-verb-accepts.md +32 -0
- amicus-0.7.0/docs/adr/0041-static-resource-reads-carry-the-catalog-ttl.md +26 -0
- amicus-0.7.0/docs/adr/0042-amicus-job-list-pages-by-an-opaque-cursor.md +26 -0
- amicus-0.7.0/docs/adr/0043-each-paid-verb-is-one-tool-with-a-wait-flag.md +57 -0
- amicus-0.7.0/docs/adr/0044-the-fingerprint-pins-each-codes-repair-contract.md +42 -0
- amicus-0.7.0/docs/codex-help/0.157.0/codex-help.txt +112 -0
- amicus-0.7.0/docs/codex-help/0.157.0/codex-version.txt +1 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/superpowers/specs/2026-09-04-amicus-design.md +3 -2
- {amicus-0.6.0 → amicus-0.7.0}/pyproject.toml +1 -1
- {amicus-0.6.0 → amicus-0.7.0}/skills/collaborating-with-amicus/SKILL.md +8 -4
- {amicus-0.6.0 → amicus-0.7.0}/skills/collaborating-with-amicus/references/choosing-a-backend.md +5 -2
- {amicus-0.6.0 → amicus-0.7.0}/skills/collaborating-with-amicus/references/options-and-errors.md +8 -3
- {amicus-0.6.0 → amicus-0.7.0}/skills/collaborating-with-amicus/references/sync-vs-async.md +9 -3
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/__init__.py +1 -1
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/claude/__init__.py +0 -6
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/claude/cli.py +4 -13
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/codex/cli.py +5 -1
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/codex/contract.py +7 -4
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/errors.py +126 -22
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/jobs/delivery.py +1 -1
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/jobs/lifecycle.py +52 -12
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/jobs/store.py +80 -16
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/manifest.py +18 -1
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/orchestration/gitdiff.py +22 -8
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/orchestration/gitproc.py +4 -2
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/orchestration/isolation.py +21 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/orchestration/review.py +6 -1
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/orchestration/run.py +31 -4
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/orchestration/workspace.py +25 -1
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/orchestration/worktree.py +17 -2
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/request.py +27 -2
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/schemas/codes.py +20 -2
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/schemas/fingerprint.py +4 -1
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/schemas/params.py +70 -20
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/schemas/results.py +23 -3
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/backend/protocol.py +5 -2
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/server.py +81 -7
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/tools/_prepare.py +17 -1
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/tools/_resolve.py +8 -3
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/tools/consult.py +2 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/tools/delegate.py +5 -3
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/tools/discovery.py +17 -12
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/tools/dry_run.py +24 -3
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/tools/jobs.py +62 -6
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/tools/resources.py +16 -7
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/tools/review.py +10 -4
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/wire_shape_snapshot.py +4 -2
- {amicus-0.6.0 → amicus-0.7.0}/tests/fixtures/manifest_snapshot.all.json +1722 -68
- {amicus-0.6.0 → amicus-0.7.0}/tests/fixtures/manifest_snapshot.claude.json +1722 -68
- {amicus-0.6.0 → amicus-0.7.0}/tests/fixtures/manifest_snapshot.codex-kimi.json +1722 -68
- {amicus-0.6.0 → amicus-0.7.0}/tests/fixtures/result_format_snapshot.json +1 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/fixtures/wire_shape_snapshot.json +5 -3
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_gitdiff.py +29 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_gitproc.py +16 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_jobs.py +168 -11
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_workspace.py +12 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_worktree.py +39 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_cache_hints.py +41 -8
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_cli.py +2 -2
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_plugin.py +5 -4
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_sync_tools.py +53 -3
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codes.py +9 -1
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codex_cli.py +5 -1
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codex_config.py +2 -1
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codex_contract.py +1 -1
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codex_result_differential.py +3 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_delivery.py +1 -1
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_discovery.py +5 -5
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_discovery_cost.py +58 -2
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_dry_run.py +62 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_errors.py +131 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_fingerprint.py +3 -3
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_isolation.py +36 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_job_tools.py +137 -1
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_result_differential.py +3 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_lifecycle.py +224 -2
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_lookup.py +10 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_manifest.py +124 -7
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_paid_tools.py +43 -14
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_params.py +18 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_prepare.py +90 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_request.py +39 -1
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_resources.py +16 -1
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_review.py +16 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_surface_honesty.py +1 -1
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_sync_tools.py +89 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_wire_shape.py +3 -2
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_workspace.py +11 -0
- {amicus-0.6.0 → amicus-0.7.0}/uv.lock +1 -1
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-docs/SKILL.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-docs/references/design-workflow.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-docs/references/docs-checklist.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-docs/references/examples.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-docs/references/review-workflow.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-docs/tests/scenarios.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/SKILL.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/decisions/001-github-fact-sheet.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/audit-workflow.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/config-checklist.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/examples/README.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/examples/codeowners.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/examples/harness-deny.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/examples/identity.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/examples/repo-files.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/examples/required-checks.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/examples/rulesets.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/examples/workflows.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/operating-playbook.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/setup-workflow.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/references/threat-model.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/tests/check_authority.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-github/tests/scenarios.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/SKILL.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/decisions/001-mcp-2026-07-28-rebase.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/decisions/002-machine-code-rename-rationale.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/decisions/003-offending-value-omission.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/decisions/004-ownership-boundaries.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/decisions/005-content-fallback-roles.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/references/contract-checklist.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/references/design-workflow.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/references/examples.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/references/mcp-2025-11-25-compat.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/references/mcp-vs-cli.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/references/native-wire-shapes.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/references/review-workflow.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/references/vocabulary.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/check_fact_sync.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/check_rule_ids.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/check_stale_terms.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/fixtures/github_issues.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/fixtures/github_repo_resource.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/rule-ids.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-outputschema-error.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario1-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario2-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario2-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario3-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario3-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario4-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario4-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario5-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario5-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario6-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario6-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-11-scenario7-trigger.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario1-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario1-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario3-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario3-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario5-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-29-scenario5-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-30-scenario1-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/runs/2026-07-30-scenario8-severity-calibration.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/scenarios.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/test_check_fact_sync.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/test_check_rule_ids.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/test_validate_fixture.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/agent-friendly-mcp/tests/validate_fixture.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/SKILL.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/agents/openai.yaml +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/references/example-audit.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/rescore-2026-08-06/preregistration.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/rescore-2026-08-06/results.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario1-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario1-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario2-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario2-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario3-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario3-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario4-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario4-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario5-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario5-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario6-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario6-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario7-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario7-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario8-baseline.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario8-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-07-11-scenario9-trigger.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-06-scenario1-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-06-scenario6-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-confirmation-r1-both-directions.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario1-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario2-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario5-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario6-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario7-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-08-23-scenario8-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-09-14-scenario1-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-09-14-scenario2-with-skill-prior-wording.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-09-14-scenario2-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/runs/2026-09-14-scenario6-with-skill.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.agents/skills/separating-context-from-constraints/tests/scenarios.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.gitattributes +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.github/CODEOWNERS +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.github/copilot-instructions.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.github/dependabot.yml +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.github/workflows/ci.yml +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.github/workflows/codeql.yml +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.github/workflows/dependency-review.yml +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.github/workflows/publish.yml +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.github/workflows/test.yml +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/.gitignore +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/AGENTS.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/CLAUDE.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/LICENSE +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/commands/amicus/adversarial.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/commands/amicus/consult.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/commands/amicus/delegate-async.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/commands/amicus/delegate.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/commands/amicus/dry-run.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/commands/amicus/review.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/commands/amicus/status.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/2026-09-04-naming-and-scoping-notes.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/DEPRECATING-SIBLINGS.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/RELEASING.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0001-annotations-follow-the-worst-enabled-backend.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0002-backend-options-is-a-closed-superset.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0004-tasks-and-jobs.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0005-error-envelope-and-repair-precedence.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0006-fingerprint-and-surface-digest.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0007-m1-codex-port-decisions.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0008-m2-jobs-surface-decisions.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0009-m3-kimi-port-decisions.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0011-m5-tasks-decisions.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0012-m6-packaging-decisions.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0013-proceed-without-trademark-clearance.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0014-release-predicate-on-the-tag.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0015-mcp-json-pins-an-already-published-release.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0016-skill-rules-are-a-complete-contract.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0017-an-unreadable-machine-enum-falls-to-its-own-floor.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0019-review-results-disclose-coverage-as-a-field.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0020-idempotency-keys-on-the-sync-tools.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0021-repair-arguments-are-a-complete-call.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0022-consume-reports-its-discard-outcome.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0023-dependency-loggers-are-owned-at-a-warning-floor.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0024-prose-list-loss-is-disclosed-never-folded.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0025-success-meta-is-sparse-on-every-tool.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0026-a-not-run-review-carries-no-confidence-rating.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0027-every-instructions-rule-fits-the-shown-prefix.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0028-a-deprecated-tool-keeps-its-record-beside-one-marker.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0029-the-backend-sdk-lives-in-tree.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0030-the-sdk-keeps-what-a-backend-imports.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0031-the-marketplace-pointer-decides-what-users-run.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0032-a-claude-review-defaults-to-readonly-access.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0033-an-unreadable-review-answer-is-delivered-unstructured.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0034-claude-usage-is-read-from-model-usage.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0035-a-backend-answer-is-kept-on-the-job-record.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0036-a-refused-answer-file-is-answer-unavailable.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/0037-a-lost-stream-answer-is-answer-unavailable.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/adr/README.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/claude-help/2.1.263/FINDINGS.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/claude-help/2.1.263/claude-help.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/claude-help/2.1.263/claude-version.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/claude-help/2.1.263/envelope-shape.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/claude-help/2.1.274/FINDINGS.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/claude-help/2.1.274/budget-stop-envelope-shape.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/claude-help/2.1.274/claude-version.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/claude-help/2.1.278/claude-help.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/claude-help/2.1.278/claude-version.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/codex-help/0.155.1/codex-help.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/codex-help/0.155.1/codex-version.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/codex-help/0.156.1/codex-help.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/codex-help/0.156.1/codex-version.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/claude-code/2.1.263/FINDINGS.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/claude-code/2.1.263/connection.log +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/claude-code/2.1.263/host-output.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/codex/0.153.4/FINDINGS.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/codex/0.153.4/connection.log +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/codex/0.153.4/host-output.jsonl +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/notes.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/server.log +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/free-scenarios/claude-code/2.1.263/transcript.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/install-smoke/claude-code/2.1.263/notes.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/install-smoke/claude-code/2.1.263/server.log +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/install-smoke/claude-code/2.1.263/transcript.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/install-smoke/codex/0.153.4/notes.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/install-smoke/codex/0.153.4/server.log +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/install-smoke/codex/0.153.4/transcript.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/notes.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/server.log +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s6-f3-recon-attempt/claude-code/2.1.265/transcript.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s6-old-text-new-grader/claude-code/2.1.263/notes.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s6-old-text-new-grader/claude-code/2.1.263/server.log +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s6-old-text-new-grader/claude-code/2.1.263/transcript.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/notes.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/server.log +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s6-rerun/claude-code/2.1.263/transcript.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/notes.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/server.log +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s6-response-contract/claude-code/2.1.263/transcript.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/notes.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/server.log +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/host-captures/s7-rule5-recheck/claude-code/2.1.265/transcript.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/0.41.0/FINDINGS.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/0.41.0/kimi-help.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/0.41.0/kimi-version.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/0.41.0/provider-list-shape.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/0.42.0/FINDINGS.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/0.42.0/kimi-help.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/0.42.0/kimi-version.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/0.42.0/provider-list-shape.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/0.43.1/FINDINGS.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/0.43.1/kimi-help.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/0.43.1/kimi-version.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/0.43.1/provider-list-shape.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/2.0.2/FINDINGS.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/2.0.2/kimi-help.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/2.0.2/kimi-version.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/2.0.2/provider-list-shape.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/2.1.0/FINDINGS.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/2.1.0/kimi-help.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/2.1.0/kimi-version.txt +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/kimi-help/2.1.0/provider-list-shape.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/reviews/2026-09-07-agent-friendly-mcp-walk.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/reviews/2026-09-20-agent-friendly-mcp-walk.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/superpowers/plans/2026-09-04-amicus-execution-model.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/superpowers/specs/2026-09-15-amicus-M8-sdk-in-tree-design.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/docs/superpowers/specs/2026-09-16-amicus-release-activation-design.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/prek.toml +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/scripts/capture_claude_differentials.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/scripts/capture_codex_differentials.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/scripts/capture_kimi_differentials.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/scripts/check_backend_compat.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/scripts/check_commit_message.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/scripts/check_github_actions_pinning.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/scripts/check_release_state.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/scripts/check_sentence_per_line.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/scripts/probe_review_surface.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/scripts/record_live_gate_evidence.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/skills/collaborating-with-amicus/references/active-workflows.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/skills/collaborating-with-amicus/references/blind-comparison.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/skills/collaborating-with-amicus/references/independent-attempt.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/skills/collaborating-with-amicus/references/reading-results.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/skills/collaborating-with-amicus/references/review-revise.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/skills/collaborating-with-amicus/references/reviewing-a-returned-diff.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/skills/collaborating-with-amicus/references/server-down-fallback.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/skills/collaborating-with-amicus/tests/scenarios.md +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/_worker.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/appstate.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/claude/adapter.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/claude/adversarial.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/claude/binary.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/claude/config.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/claude/contract.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/claude/models.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/claude/normalize.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/claude/options.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/claude/status.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/codex/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/codex/adapter.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/codex/binary.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/codex/config.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/codex/models.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/codex/normalize.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/codex/options.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/codex/status.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/kimi/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/kimi/adapter.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/kimi/binary.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/kimi/cli.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/kimi/config.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/kimi/contract.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/kimi/models.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/kimi/normalize.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/kimi/options.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/backends/kimi/status.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/compaction.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/config/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/config/envspec.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/jobs/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/jobs/idempotency.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/jobs/lookup.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/jobs/polling.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/jobs/taskmap.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/middleware.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/obs.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/orchestration/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/orchestration/finalize.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/orchestration/prompts.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/packaging.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/plugin.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/py.typed +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/registry.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/result_format_snapshot.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/schemas/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/schemas/envelope.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/schemas/field_policy.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/schemas/instructions.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/schemas/options.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/schemas/publish.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/schemas/structured.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/backend/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/backend/contract.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/conventions/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/conventions/annotations.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/conventions/envelope.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/conventions/preflight.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/core/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/core/jsoncache.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/core/pathalias.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/core/redaction.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/core/runtime.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/core/streamcap.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/testing/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/testing/conformance.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/sdk/testing/surface_honesty.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/surface.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/tools/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/tools/_guard.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/src/amicus/tools/_meta.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/conftest.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/fixtures/claude_budget_stop_envelope.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/fixtures/claude_differentials.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/fixtures/claude_golden_envelope.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/fixtures/codex_differentials.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/fixtures/fakebackend/pyproject.toml +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/fixtures/fakebackend/src/fakebackend/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/fixtures/kimi_differentials.json +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/conftest.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_annotations.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_classified_failure_fields.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_conformance_fakes.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_conformance_inspector.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_contract.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_envelope.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_fingerprint.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_git_isolation.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_idempotency.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_jsoncache.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_orphan_sweep.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_outcome_inspector.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_pair_parity_kit.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_pathalias.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_preflight.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_prompts.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_redaction.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_run_request.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_runtime.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_runtime_kill_and_sweep_paths.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_streamcap.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_surface_honesty_kit.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_usage_cache_fields.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/sdk/test_worktree_config.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/support/__init__.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/support/claudefixtures.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/support/codexfixtures.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/support/fake_claude.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/support/fake_codex.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/support/fake_kimi.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/support/fakeplugin.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/support/kimifixtures.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/support/livegate.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/support/pair_parity.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_adversarial.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_artifact_references.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_async_tools.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_check_backend_compat.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_check_commit_message.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_check_github_actions_pinning.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_check_sentence_per_line.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_adapter.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_argv_differential.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_binary.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_config.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_contract.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_golden_envelope.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_live.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_models.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_normalize.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_result_differential.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_claude_status.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codex_adapter.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codex_argv_differential.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codex_binary.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codex_live.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codex_models.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codex_normalize.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codex_plugin.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_codex_status.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_commands.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_compaction.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_config.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_conftest_guards.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_envelope.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_envspec.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_fastmcp_argument_log.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_field_policy.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_finalize.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_guard.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_host_captures.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_import_contracts.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_instructions.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_job_durability.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_adapter.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_argv_differential.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_binary.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_cli.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_config.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_contract.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_live.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_models.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_normalize.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_plugin.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_status.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_kimi_sync_tools.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_live_gate_report.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_live_suite_hygiene.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_livegate.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_log_redaction.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_meta.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_middleware.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_migration_doc.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_obs.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_options.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_packaging.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_plugin.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_poll_hint.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_prompts.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_publish.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_registry.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_relative_config_paths.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_release_evidence.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_release_state.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_result_format.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_results.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_review_artifact.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_run.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_sdk_in_tree.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_server.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_skill_contract.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_structured.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_surface.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_taskmap.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_tasks_client.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_tasks_spike.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_wheel_seam.py +0 -0
- {amicus-0.6.0 → amicus-0.7.0}/tests/test_worker.py +0 -0
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"source": {
|
|
11
11
|
"source": "url",
|
|
12
12
|
"url": "https://github.com/briandconnelly/amicus.git",
|
|
13
|
-
"ref": "v0.
|
|
14
|
-
"sha": "
|
|
13
|
+
"ref": "v0.6.0",
|
|
14
|
+
"sha": "539b414b1a597a644e94f0707506137db91069b7"
|
|
15
15
|
},
|
|
16
16
|
"description": "One MCP server for every second-opinion model: consult, review, and delegate with the backend as a parameter."
|
|
17
17
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amicus",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.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.7.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",
|
|
@@ -20,6 +20,119 @@ per-change, as its own lead says.
|
|
|
20
20
|
|
|
21
21
|
## [Unreleased]
|
|
22
22
|
|
|
23
|
+
## [0.7.0] - 2026-09-26
|
|
24
|
+
|
|
25
|
+
Across this release the discovery surface moves `amicus/0.1/schema-43`, what 0.6.0 shipped, to
|
|
26
|
+
`amicus/0.1/schema-50`, and `RESULT_FORMAT` stays 9, so a job result 0.6.0 stored can still be
|
|
27
|
+
delivered. Two entries are labelled **Breaking**: a sync paid call past its deadline returns a
|
|
28
|
+
`timeout` that is never temporary and whose repair names the verb's `_async` twin when
|
|
29
|
+
`AMICUS_JOB_MAX_SECONDS` exceeds the deadline that passed (#245); and a backend a verb never
|
|
30
|
+
accepts fails at the boundary as `invalid_arguments` rather than `feature_unsupported` (#246). A
|
|
31
|
+
new paid call can now be refused with the new code `job_cap_reached` rather than evicting a
|
|
32
|
+
result nobody has fetched, though a result 0.6.0 stored is still evictable (#244), and a stale
|
|
33
|
+
client root is `invalid_workspace_root` rather than `git_unavailable` (#248).
|
|
34
|
+
`docs/MIGRATION.md` ("Upgrading from 0.6.0") says what to do for each. It was checked against
|
|
35
|
+
codex-cli 0.157.0, Kimi Code 2.1.1 and Claude Code 2.1.283.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- **Surface.** `amicus_job_list` pages (#249, ADR 0042). A page that omits matching jobs
|
|
40
|
+
carries `has_more: true` and `next_cursor`; pass it as `cursor` with the same filters for
|
|
41
|
+
the jobs after it, and a cursor whose job has since been consumed still resolves, because
|
|
42
|
+
it names the anchor's start time and id rather than a position. `truncated` and
|
|
43
|
+
`truncation_hint` report what they did in 0.6.0, now documented as an alias of `has_more`
|
|
44
|
+
on this tool. A cursor not in the form the tool returns is `invalid_arguments`. Omitting
|
|
45
|
+
`limit` still returns every retained match; the description now names the per-workspace
|
|
46
|
+
cap `AMICUS_JOB_MAX_COUNT`, which server processes sharing a state root can each exceed by
|
|
47
|
+
one start.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- codex-cli 0.157 is a supported version, so `amicus_backends` no longer warns on it. It was
|
|
52
|
+
checked against 0.156.1 at zero spend: top-level `--help`, `exec --help`, `exec review --help`
|
|
53
|
+
and `login --help` are identical apart from trailing whitespace. The unknown-feature error, the
|
|
54
|
+
logged-out `login status` line, and the strict-config, invalid-value and retired-setting
|
|
55
|
+
rejections are unchanged; the four config keys amicus pins with `-c` are still accepted, and
|
|
56
|
+
all three features amicus disables on every run are still `stable`. The tool list sent to each
|
|
57
|
+
bundled model is the same as 0.156.1's with and without those disables, and the served model
|
|
58
|
+
catalog is unchanged. Of the two features 0.157 turns on by default, `daemon_auto_start` is
|
|
59
|
+
read only by the interactive TUI and `guardianv2.thread_context` only shapes Guardian approval
|
|
60
|
+
reviews, so neither is enabled or disabled here. No paid call was part of the check.
|
|
61
|
+
- **Surface.** `amicus_capabilities`' `fingerprint_covers` gains `repair_rules` (#252, ADR
|
|
62
|
+
0044): each error code's `temporary`, `repair.next_step`, `repair.tool` and lookup
|
|
63
|
+
`repair.arguments`, as the envelope carries them by default for each in-tree backend, are
|
|
64
|
+
now part of what the fingerprint guards, so a change to any of them moves `fingerprint`.
|
|
65
|
+
The repair prose (`alternative`) is not. No error envelope changes.
|
|
66
|
+
- **Surface.** Six minor contract findings of the 2026-09-24 audit (#250). Reads of
|
|
67
|
+
`amicus://error-envelope`, `amicus://result-meta` and `amicus://params` carry the catalog
|
|
68
|
+
TTL (`ttlMs: 300000`) where they said `0`; `amicus://capabilities` and the two templates
|
|
69
|
+
still say `0` (ADR 0041). The `logging` capability is no longer advertised: amicus sends no
|
|
70
|
+
log message. The two resource templates carry written one-line descriptions, and the models
|
|
71
|
+
template no longer claims a resource read has no repair carrier. A sync call's progress
|
|
72
|
+
notifications report elapsed seconds against the deadline as `progress`/`total`, with the
|
|
73
|
+
backend event count in the message. `amicus_capabilities.tool_details[].stability` is each
|
|
74
|
+
tool's effective tier rather than `null`, so the two stability surfaces agree. Every tool,
|
|
75
|
+
resource and template record on the wire no longer carries FastMCP's `_meta.fastmcp` block.
|
|
76
|
+
Item 1 of the issue, echoing `workspace_root` in `repair.arguments`, was declined under ADR
|
|
77
|
+
0021.
|
|
78
|
+
- **Surface.** `timeout_seconds` and `detail` carry a one-line summary and an `amicus://params`
|
|
79
|
+
pointer on every tool that declares them, with the keyed-call and retention elaboration in
|
|
80
|
+
the resource's `full` text (#247, part), 1,270 bytes of `tools/list`. With the other
|
|
81
|
+
changes in this release, `tools/list` on the `all` profile is 112,105 bytes (-578 since
|
|
82
|
+
0.6.0's 112,683, o200k 27,659 tokens). ADR 0043 proposes merging each sync tool
|
|
83
|
+
with its `_async` twin behind a `wait` flag; that change, and the deprecation of the twins,
|
|
84
|
+
is not in this release.
|
|
85
|
+
- **Breaking.** A sync paid call that passes its deadline returns `timeout` with `temporary:
|
|
86
|
+
false`, `retry_after_ms: null` and `repair.next_step: start_new_job` on every backend, where
|
|
87
|
+
codex and kimi said `temporary: true` / `retry_after_delay` while their own prose said a retry
|
|
88
|
+
would time out again (#245, ADR 0039). The repair names the verb's `_async` twin in
|
|
89
|
+
`repair.tool` when `AMICUS_JOB_MAX_SECONDS`, the deadline that twin runs to, exceeds the
|
|
90
|
+
deadline that passed, and otherwise names no tool; it carries no arguments, since they would
|
|
91
|
+
echo your inputs. Its text says so and states that any next attempt is a new paid run. Claude's `temporary` and `next_step` are
|
|
92
|
+
unchanged; it now also names the `_async` tool and shares the new text. A background run (an
|
|
93
|
+
`_async` job or a keyed sync call) that passes `AMICUS_JOB_MAX_SECONDS` returns `timeout` with
|
|
94
|
+
no `repair.tool` and prose naming that deadline, since its `_async` twin would hit the same
|
|
95
|
+
one. Codex's capture-failed timeout, whose repair says to retry the same
|
|
96
|
+
call once, now says `temporary: true` itself and its repair names no other tool, except on
|
|
97
|
+
a keyed call, where the same call would replay this error: there it is `temporary: false` and
|
|
98
|
+
its text first says to retry under a new `idempotency_key`. A keyed sync wait's timeout is
|
|
99
|
+
unchanged (ADR 0020).
|
|
100
|
+
- **Breaking.** `amicus_delegate`, `amicus_delegate_async` and `amicus_delegate_dry_run`
|
|
101
|
+
publish `backend` as `codex | kimi`, and `amicus_adversarial_review` and its async twin as
|
|
102
|
+
`claude`, the sets those verbs accept (#246, ADR 0040). A backend outside the set now fails
|
|
103
|
+
at the boundary as `invalid_arguments` with `allowed_values`, where it failed after
|
|
104
|
+
resolution as `feature_unsupported`; that code remains only as a defensive check, returned if
|
|
105
|
+
the named backend's declared features lack the verb, which no backend a tool's enum accepts
|
|
106
|
+
does today, and its repair now lists every backend rather than the one that failed.
|
|
107
|
+
`amicus_capabilities.tool_details[].backends` derives from the same table.
|
|
108
|
+
|
|
109
|
+
### Fixed
|
|
110
|
+
|
|
111
|
+
- A new paid call no longer deletes a finished result nobody has fetched (#244). Every paid call
|
|
112
|
+
records a job, and recording one evicted the oldest finished records past the per-workspace
|
|
113
|
+
cap (`AMICUS_JOB_MAX_COUNT`, default 50) whether or not their results had ever been read, while
|
|
114
|
+
the paid tools advertised `destructiveHint: false` in the codex and kimi profile. The cap now
|
|
115
|
+
evicts only expired records, terminal errors, results amicus has already returned once and
|
|
116
|
+
records written by an earlier release, which did not track delivery. An unfetched result in
|
|
117
|
+
another release's result format is kept too, since a server of that release sharing the state
|
|
118
|
+
root can still deliver it. When only running jobs and unfetched results it must keep remain, a
|
|
119
|
+
new paid call is refused before anything is spent with the new error code
|
|
120
|
+
`job_cap_reached`, whose repair lists the workspace's jobs: fetch or consume a result, or
|
|
121
|
+
cancel a running job, then retry; a result another release wrote is fetched by that release, or
|
|
122
|
+
expires after `AMICUS_JOB_TTL`. Running jobs now count toward the cap, so a workspace can
|
|
123
|
+
no longer run more jobs than the cap at once. "Returned once" means amicus handed the result
|
|
124
|
+
back, from `amicus_job_result`, `amicus_job_consume_result` or the sync call that awaited it,
|
|
125
|
+
not that the client received it (ADR 0038).
|
|
126
|
+
- **Surface.** A client file root that no longer exists is refused before any work as
|
|
127
|
+
`invalid_workspace_root` with the new `details.reason` token `root_not_a_directory`, where it
|
|
128
|
+
was accepted as the workspace and every git-based call then failed as `git_unavailable`,
|
|
129
|
+
steering the agent to install git (#248). Only handshake-era clients advertise roots. A
|
|
130
|
+
workspace that vanishes after resolution is now `invalid_workspace_root` too, with the token of
|
|
131
|
+
its source (`root_not_a_directory`, `not_a_directory`, or `cwd_gone` for the cwd opt-in), from
|
|
132
|
+
every git wrapper, the delegate preflight and dry run, and a delegate job's worktree setup; a
|
|
133
|
+
cwd that is a file is handled the same way.
|
|
134
|
+
The token list in the `workspace_root` contract at `amicus://params` grew by one.
|
|
135
|
+
|
|
23
136
|
## [0.6.0] - 2026-09-24
|
|
24
137
|
|
|
25
138
|
Across this release the discovery surface moves `amicus/0.1/schema-39`, what 0.5.0 shipped, to
|
|
@@ -967,7 +1080,8 @@ per-change rather than net, so they also name intermediate states that no releas
|
|
|
967
1080
|
- The tagged publish path to pypi.org has never run. Only the TestPyPI dispatch path has been exercised.
|
|
968
1081
|
- 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.
|
|
969
1082
|
|
|
970
|
-
[Unreleased]: https://github.com/briandconnelly/amicus/compare/v0.
|
|
1083
|
+
[Unreleased]: https://github.com/briandconnelly/amicus/compare/v0.7.0...HEAD
|
|
1084
|
+
[0.7.0]: https://github.com/briandconnelly/amicus/compare/v0.6.0...v0.7.0
|
|
971
1085
|
[0.6.0]: https://github.com/briandconnelly/amicus/compare/v0.5.0...v0.6.0
|
|
972
1086
|
[0.5.0]: https://github.com/briandconnelly/amicus/compare/v0.4.0...v0.5.0
|
|
973
1087
|
[0.4.0]: https://github.com/briandconnelly/amicus/compare/v0.3.0...v0.4.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: amicus
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: One MCP server for every second-opinion model: consult, review, and delegate with the backend as a parameter
|
|
5
5
|
Project-URL: Homepage, https://github.com/briandconnelly/amicus
|
|
6
6
|
Project-URL: Repository, https://github.com/briandconnelly/amicus
|
|
@@ -73,7 +73,7 @@ The plugins launch the server from a published release tag, pinned in
|
|
|
73
73
|
"mcpServers": {
|
|
74
74
|
"amicus": {
|
|
75
75
|
"command": "uvx",
|
|
76
|
-
"args": ["--from", "git+https://github.com/briandconnelly/amicus.git@v0.
|
|
76
|
+
"args": ["--from", "git+https://github.com/briandconnelly/amicus.git@v0.7.0", "amicus-mcp"]
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
}
|
|
@@ -139,8 +139,11 @@ dedicated adversarial-review verb is scoped to Claude. To ask Codex or Kimi for
|
|
|
139
139
|
review, use `consult` or `review_changes` and supply the stance yourself; the dedicated verb adds
|
|
140
140
|
a fixed critic stance and the `target` and `evidence` inputs.
|
|
141
141
|
|
|
142
|
-
Asking a
|
|
143
|
-
|
|
142
|
+
Asking a tool for a backend outside its `backend` enum, in-tree or not, is rejected before any
|
|
143
|
+
spend as an `invalid_arguments` error whose `details.allowed_values` lists the backends that tool
|
|
144
|
+
accepts (the enum is that set). `feature_unsupported` is only a defensive check: it is returned
|
|
145
|
+
if the named backend's declared features lack the verb, which no backend a tool's enum accepts
|
|
146
|
+
does today.
|
|
144
147
|
|
|
145
148
|
## Safety
|
|
146
149
|
|
|
@@ -155,7 +158,10 @@ the backend and the feature, rather than failing obscurely.
|
|
|
155
158
|
- **A paid call's whole answer stays on disk** in the job record under `AMICUS_STATE_DIR`,
|
|
156
159
|
whatever `detail` delivered it and after only best-effort secret redaction, until it expires
|
|
157
160
|
(`AMICUS_JOB_TTL`, default 24h; an expired record is removed on a later job call, not by a
|
|
158
|
-
daemon),
|
|
161
|
+
daemon), `amicus_job_consume_result` removes it or, once amicus has returned it, the
|
|
162
|
+
per-workspace cap evicts it. The cap never evicts a result nobody has fetched that was
|
|
163
|
+
recorded since delivery tracking (#244), whichever release recorded it. When only running jobs
|
|
164
|
+
and such results remain, a new paid call is refused with `job_cap_reached` instead ([ADR 0038](docs/adr/0038-the-job-cap-never-evicts-an-unreturned-result.md)). It can
|
|
159
165
|
quote what you sent. Your inputs themselves are never written there ([ADR 0035](docs/adr/0035-a-backend-answer-is-kept-on-the-job-record.md)).
|
|
160
166
|
- **Kimi keeps its own copy.** The kimi CLI writes its own session files (observed under
|
|
161
167
|
`~/.kimi-code/sessions`), which can hold the whole prompt and any answer produced. amicus found
|
|
@@ -181,13 +187,14 @@ the new ones.
|
|
|
181
187
|
|
|
182
188
|
## Status and known limits
|
|
183
189
|
|
|
184
|
-
0.
|
|
185
|
-
`amicus/0.1/schema-
|
|
186
|
-
read. Two changes ask something of a caller:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
refused
|
|
190
|
+
0.7.0 is the current release. The discovery surface moved from `amicus/0.1/schema-43` to
|
|
191
|
+
`amicus/0.1/schema-50`, and `RESULT_FORMAT` did not move, so a job result 0.6.0 stored can still be
|
|
192
|
+
read. Two changes ask something of a caller: a sync call past its deadline returns a `timeout`
|
|
193
|
+
that is never temporary and whose repair names the verb's `_async` twin when
|
|
194
|
+
`AMICUS_JOB_MAX_SECONDS` exceeds the deadline that passed, and a backend a verb never accepts
|
|
195
|
+
fails as `invalid_arguments` rather than `feature_unsupported`. A new paid call can also be
|
|
196
|
+
refused as `job_cap_reached` rather than evicting a result nobody has fetched.
|
|
197
|
+
[`docs/MIGRATION.md`](docs/MIGRATION.md#upgrading-from-060) explains how to upgrade, and
|
|
191
198
|
[`CHANGELOG.md`](CHANGELOG.md) lists every user-visible change.
|
|
192
199
|
|
|
193
200
|
One known limit: a third-party backend distribution can load through the `amicus.backends`
|
|
@@ -44,7 +44,7 @@ The plugins launch the server from a published release tag, pinned in
|
|
|
44
44
|
"mcpServers": {
|
|
45
45
|
"amicus": {
|
|
46
46
|
"command": "uvx",
|
|
47
|
-
"args": ["--from", "git+https://github.com/briandconnelly/amicus.git@v0.
|
|
47
|
+
"args": ["--from", "git+https://github.com/briandconnelly/amicus.git@v0.7.0", "amicus-mcp"]
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -110,8 +110,11 @@ dedicated adversarial-review verb is scoped to Claude. To ask Codex or Kimi for
|
|
|
110
110
|
review, use `consult` or `review_changes` and supply the stance yourself; the dedicated verb adds
|
|
111
111
|
a fixed critic stance and the `target` and `evidence` inputs.
|
|
112
112
|
|
|
113
|
-
Asking a
|
|
114
|
-
|
|
113
|
+
Asking a tool for a backend outside its `backend` enum, in-tree or not, is rejected before any
|
|
114
|
+
spend as an `invalid_arguments` error whose `details.allowed_values` lists the backends that tool
|
|
115
|
+
accepts (the enum is that set). `feature_unsupported` is only a defensive check: it is returned
|
|
116
|
+
if the named backend's declared features lack the verb, which no backend a tool's enum accepts
|
|
117
|
+
does today.
|
|
115
118
|
|
|
116
119
|
## Safety
|
|
117
120
|
|
|
@@ -126,7 +129,10 @@ the backend and the feature, rather than failing obscurely.
|
|
|
126
129
|
- **A paid call's whole answer stays on disk** in the job record under `AMICUS_STATE_DIR`,
|
|
127
130
|
whatever `detail` delivered it and after only best-effort secret redaction, until it expires
|
|
128
131
|
(`AMICUS_JOB_TTL`, default 24h; an expired record is removed on a later job call, not by a
|
|
129
|
-
daemon),
|
|
132
|
+
daemon), `amicus_job_consume_result` removes it or, once amicus has returned it, the
|
|
133
|
+
per-workspace cap evicts it. The cap never evicts a result nobody has fetched that was
|
|
134
|
+
recorded since delivery tracking (#244), whichever release recorded it. When only running jobs
|
|
135
|
+
and such results remain, a new paid call is refused with `job_cap_reached` instead ([ADR 0038](docs/adr/0038-the-job-cap-never-evicts-an-unreturned-result.md)). It can
|
|
130
136
|
quote what you sent. Your inputs themselves are never written there ([ADR 0035](docs/adr/0035-a-backend-answer-is-kept-on-the-job-record.md)).
|
|
131
137
|
- **Kimi keeps its own copy.** The kimi CLI writes its own session files (observed under
|
|
132
138
|
`~/.kimi-code/sessions`), which can hold the whole prompt and any answer produced. amicus found
|
|
@@ -152,13 +158,14 @@ the new ones.
|
|
|
152
158
|
|
|
153
159
|
## Status and known limits
|
|
154
160
|
|
|
155
|
-
0.
|
|
156
|
-
`amicus/0.1/schema-
|
|
157
|
-
read. Two changes ask something of a caller:
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
refused
|
|
161
|
+
0.7.0 is the current release. The discovery surface moved from `amicus/0.1/schema-43` to
|
|
162
|
+
`amicus/0.1/schema-50`, and `RESULT_FORMAT` did not move, so a job result 0.6.0 stored can still be
|
|
163
|
+
read. Two changes ask something of a caller: a sync call past its deadline returns a `timeout`
|
|
164
|
+
that is never temporary and whose repair names the verb's `_async` twin when
|
|
165
|
+
`AMICUS_JOB_MAX_SECONDS` exceeds the deadline that passed, and a backend a verb never accepts
|
|
166
|
+
fails as `invalid_arguments` rather than `feature_unsupported`. A new paid call can also be
|
|
167
|
+
refused as `job_cap_reached` rather than evicting a result nobody has fetched.
|
|
168
|
+
[`docs/MIGRATION.md`](docs/MIGRATION.md#upgrading-from-060) explains how to upgrade, and
|
|
162
169
|
[`CHANGELOG.md`](CHANGELOG.md) lists every user-visible change.
|
|
163
170
|
|
|
164
171
|
One known limit: a third-party backend distribution can load through the `amicus.backends`
|
|
@@ -29,7 +29,11 @@ Request: $ARGUMENTS
|
|
|
29
29
|
- Recover a lost `job_id`, or see what is in flight: `amicus_job_list`, filterable by
|
|
30
30
|
`backend`, `status`, or `task_id`.
|
|
31
31
|
|
|
32
|
-
Job records expire after `AMICUS_JOB_TTL` (default 24h)
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
Job records expire after `AMICUS_JOB_TTL` (default 24h), so read results promptly
|
|
33
|
+
rather than leaving them to expire. A per-workspace cap evicts the oldest terminal
|
|
34
|
+
records but never a result amicus has tracked and not yet returned (records written
|
|
35
|
+
before delivery tracking are evictable); when unfetched results and running jobs fill
|
|
36
|
+
it, a new paid call is refused with `job_cap_reached` until you fetch, consume or cancel
|
|
37
|
+
one, or, for a result another amicus release wrote, until that release fetches it or it
|
|
38
|
+
expires. Treat a fetched result the same way you would treat the tool it came
|
|
35
39
|
from: verify findings and diffs against the actual code before acting on them.
|
|
@@ -124,7 +124,7 @@ Most amicus tools take `backend` as a required parameter (no default); pick `"co
|
|
|
124
124
|
| `claude_job_cancel` | `amicus_job_cancel(...)` |
|
|
125
125
|
| `claude_job_list` | `amicus_job_list(...)` |
|
|
126
126
|
|
|
127
|
-
`claude-in-codex` had no `claude_delegate`: Claude is review-only in amicus too, so `amicus_delegate` and `amicus_delegate_async` reject `backend="claude"` with `feature_unsupported
|
|
127
|
+
`claude-in-codex` had no `claude_delegate`: Claude is review-only in amicus too, so `amicus_delegate` and `amicus_delegate_async` reject `backend="claude"` at the boundary as `invalid_arguments` with `details.allowed_values`, because each tool's `backend` enum is the set it accepts, and any backend outside it, in-tree or not, is `invalid_arguments`; `feature_unsupported` is only a defensive check, returned if the named backend's declared features lack the verb, which no backend a tool's enum accepts does today.
|
|
128
128
|
`amicus_adversarial_review(_async)` is the only pair that rejects `backend="codex"` and `backend="kimi"`, because only Claude declares the `adversarial_review` capability.
|
|
129
129
|
|
|
130
130
|
## Behavior deltas
|
|
@@ -193,6 +193,33 @@ A `null` there means no loaded plugin declares one.
|
|
|
193
193
|
The `amicus://backends/{backend}` resource is always the full entry.
|
|
194
194
|
`amicus_capabilities(detail="contracts")` is removed: pass `include_tool_details=false` for the same rowless payload, and `detail` now selects only how much each `tool_details` row carries (`summary` is `name`, `cost`, `stability`, `backends`; `full` adds the rest, including `error_codes`).
|
|
195
195
|
|
|
196
|
+
## Upgrading from 0.6.0
|
|
197
|
+
|
|
198
|
+
The changes below are the ones a caller using amicus 0.6.0 may have to handle before running 0.7.0.
|
|
199
|
+
`CHANGELOG.md`'s 0.7.0 section lists every user-visible change since 0.6.0, including the ones that require no migration.
|
|
200
|
+
A job result stored by 0.6.0 is still readable: `RESULT_FORMAT` did not move.
|
|
201
|
+
|
|
202
|
+
**A sync `timeout` is never temporary, and its repair names the `_async` twin (#245).**
|
|
203
|
+
On codex and kimi the envelope said `temporary: true` with `retry_after_delay`; it now says `temporary: false` with `start_new_job` and `repair.tool` set to the verb's `_async` tool.
|
|
204
|
+
Claude's `temporary` and `next_step` are unchanged; it now also names the `_async` tool and shares the new text.
|
|
205
|
+
The `_async` tool runs to `AMICUS_JOB_MAX_SECONDS`, not `timeout_seconds`, so it is named only when `AMICUS_JOB_MAX_SECONDS` exceeds the deadline that passed; otherwise `repair.tool` is absent and the text says to narrow the task or have the operator raise `AMICUS_JOB_MAX_SECONDS`.
|
|
206
|
+
A background run (an `_async` job or a keyed sync call) that passes `AMICUS_JOB_MAX_SECONDS` returns `timeout` with no `repair.tool` and prose naming that deadline.
|
|
207
|
+
A caller that retried the same sync call on `temporary: true` should start the `_async` twin named in `repair.tool`, when there is one, with its original arguments instead; the retry is a new paid run.
|
|
208
|
+
|
|
209
|
+
**A backend a verb never accepts is rejected at the boundary (#246).**
|
|
210
|
+
`amicus_delegate` with `claude`, or `amicus_adversarial_review` with `codex` or `kimi`, now fails as `invalid_arguments` with `details.allowed_values`, where it failed as `feature_unsupported`.
|
|
211
|
+
A caller that branched on `feature_unsupported` for those picks should read the tool's `backend` enum, which is now the accepted set.
|
|
212
|
+
|
|
213
|
+
**A new paid call can be refused as `job_cap_reached` (#244).**
|
|
214
|
+
0.6.0 made room under the per-workspace cap (`AMICUS_JOB_MAX_COUNT`, default 50) by evicting the oldest finished records, including results nobody had fetched.
|
|
215
|
+
0.7.0 evicts only expired records, terminal errors, results it has already returned once and records an earlier release wrote, counts running jobs toward the cap, and refuses a new paid call before anything is spent when only running jobs and unfetched results remain.
|
|
216
|
+
A result 0.6.0 stored carries no delivery record, so 0.7.0 still evicts it at the cap like any other earlier-release record: fetch any 0.6.0 result you still need before the upgraded server starts another paid call in that workspace.
|
|
217
|
+
A caller that starts many jobs without fetching their results should fetch or consume them, or cancel a running job, and then retry; the error's repair lists the workspace's jobs.
|
|
218
|
+
|
|
219
|
+
**A stale client root is refused as `invalid_workspace_root`, reason `root_not_a_directory` (#248).**
|
|
220
|
+
A handshake-era client whose advertised first root no longer exists used to get `git_unavailable` from the first git-based call; it now gets the workspace refusal, with no repair, before any work.
|
|
221
|
+
Fix the root the client advertises, or pass `workspace_root`.
|
|
222
|
+
|
|
196
223
|
## Upgrading from 0.5.0
|
|
197
224
|
|
|
198
225
|
The changes below are the ones a caller or operator using amicus 0.5.0 may have to handle before running 0.6.0.
|
|
@@ -17,3 +17,4 @@ The server cwd is used only under `AMICUS_ALLOW_CWD_WORKSPACE=1`, and then the r
|
|
|
17
17
|
- Sessionless (2026-07-28) clients must pass `workspace_root`; the parameter description says so.
|
|
18
18
|
- M1 implements the resolver (orchestration/workspace.py) and the handshake-era roots probe; a sessionless client without workspace_root receives invalid_workspace_root with zero spend.
|
|
19
19
|
- The server cwd is read only on the branch that would use it (issue #170): an explicit or client root never consults it, so a cwd deleted under the running server cannot fail a call that named its workspace, and when that branch is reached and the cwd is gone the call fails as invalid_workspace_root rather than a retryable internal_error.
|
|
20
|
+
- A client root is checked with `is_dir()` like an explicit path (issue #248): a root the client still advertises after the directory is gone is refused as invalid_workspace_root with reason `root_not_a_directory`, first-root selection stands, and a workspace that vanishes after resolution is reported with the token of its source (`root_not_a_directory`, `not_a_directory` or `cwd_gone`) rather than as a missing git executable, from the git wrappers, the delegate preflight and dry run, and a delegate job's worktree setup.
|
|
@@ -22,6 +22,7 @@ The maintainer approved decisions 1–4 in the M4 planning session.
|
|
|
22
22
|
- The zero-exit envelope is an outcome inspection: `ClaudeBackend.inspect_outcome` returns `invalid_json` for a non-JSON zero-exit stdout, classifies an `is_error`/non-success envelope through the same classifier the process-failure path uses, and returns `claude_permission_error` for denials with no answer.
|
|
23
23
|
- `finalize` returns the workspace hook warning as `ExecResult.warnings`, and `orchestration.finalize.apply_exec` copies backend warnings onto `meta.security_warnings` (a loop change every backend may use).
|
|
24
24
|
- Timeout is the first `repair_overrides` entry (`start_new_job`, not temporary); the classifier marks the failure `retryable=False` too.
|
|
25
|
+
Superseded by [ADR 0039](0039-a-deadline-timeout-is-never-temporary.md): the rule is now amicus-wide and the override is gone.
|
|
25
26
|
- Pre-spend refusals in `validate_request`: effort outside the enumerated levels, `config_mode`/`access` outside the vocabulary, budget outside 0.01–5.00, `bare` without `ANTHROPIC_API_KEY` (`api_key_missing`), any `extra_args`, and the shared `instructions_append` rules for consult and review only.
|
|
26
27
|
- `backend_options.max_budget_usd` is bounded 0.01–5.00 on the wire (the sibling's ceiling) and refused pre-spend outside it; the sibling's configured/effective budget meta is not carried.
|
|
27
28
|
- Names: `AMICUS_CLAUDE_{BIN,CONFIG_MODE,ACCESS,MODEL,REASONING_EFFORT,MAX_BUDGET_USD,SUPPORTED_MAJORS}` with `CLAUDE_IN_CODEX_` twins for all but `BIN`; defaults inherit, toolless, xhigh, 1.00, {2}; no extra-args variable.
|
{amicus-0.6.0 → amicus-0.7.0}/docs/adr/0018-the-catalog-carries-a-ttl-and-resource-reads-do-not.md
RENAMED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**Status:** Accepted (2026-09-09)
|
|
4
4
|
|
|
5
|
+
The `resources/read` clause is superseded by [ADR 0041](0041-static-resource-reads-carry-the-catalog-ttl.md); the rest stands.
|
|
6
|
+
|
|
5
7
|
Supersedes the cache-hint clause of [ADR 0006](0006-fingerprint-and-surface-digest.md); the rest of that record stands.
|
|
6
8
|
|
|
7
9
|
## Context
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# ADR 0038: the job cap never evicts an unreturned result
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted (2026-09-24)
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
Every paid call, sync or async, is recorded as a job, and the job store keeps at most `AMICUS_JOB_MAX_COUNT` records per workspace (50 by default).
|
|
8
|
+
Until this decision, recording a new job evicted the oldest terminal records past that cap, whether or not anyone had fetched their results (#244).
|
|
9
|
+
A new paid call could therefore delete a finished, paid-for result the caller had not read yet, and a later `amicus_job_result` returned `job_not_found`, which looks the same as a mistyped id.
|
|
10
|
+
|
|
11
|
+
In the codex and kimi profile the paid tools also advertise `destructiveHint: false`, and `amicus_capabilities.annotations_reading` justified that without naming eviction.
|
|
12
|
+
ADR 0001 annotates for the worst enabled backend; it never said a paid call may remove state a caller still needs.
|
|
13
|
+
|
|
14
|
+
The issue offered two ways out: make the hint true in fact, or flip every paid tool to `destructiveHint: true`.
|
|
15
|
+
Flipping the hint would have kept the loss and only disclosed it, and would have raised a host approval prompt on every paid call in a profile whose backends write nothing outside a throwaway worktree.
|
|
16
|
+
|
|
17
|
+
## Decision
|
|
18
|
+
|
|
19
|
+
**The cap evicts only what nobody still needs from amicus.**
|
|
20
|
+
It may remove an expired record, a terminal error (`failed`, `cancelled`, `timeout`), a `done` result amicus has already returned once, and a record written before delivery tracking existed.
|
|
21
|
+
It never removes a running job, or a tracked `done` result that has not been returned, whatever its result format.
|
|
22
|
+
|
|
23
|
+
**A full cap refuses the new call before anything is spent.**
|
|
24
|
+
The check runs before the worker spawns: it reaps expired records, evicts what it may oldest first, and raises `JobCapReached` when the workspace still holds `AMICUS_JOB_MAX_COUNT` records.
|
|
25
|
+
The tool returns `job_cap_reached`, temporary with no `retry_after_ms`, because the room comes from the caller's own next step rather than from time: fetch or consume a result, or cancel a running job.
|
|
26
|
+
Its repair lists the workspace's jobs with `amicus_job_list`, and says that a result another release wrote, which this server reports as `job_result_incompatible` and a consume keeps, is fetched by a server of that release or expires after `AMICUS_JOB_TTL`.
|
|
27
|
+
Running jobs count toward the cap, so within one server process the cap bounds how many records a workspace holds, where running jobs used to overshoot it; across processes it is bounded as the last decision below says.
|
|
28
|
+
A refused keyed call leaves its idempotency key unreserved, so the same key works once there is room.
|
|
29
|
+
|
|
30
|
+
**"Returned once" is recorded by the server, not acknowledged by the client.**
|
|
31
|
+
A record carries `delivered_epoch`, `null` until amicus validates its stored result and hands it back, from `amicus_job_result`, `amicus_job_consume_result` or the sync tool that awaited it.
|
|
32
|
+
A status read, a list, a keyed wait that timed out, and a stored result that failed validation never stamp it.
|
|
33
|
+
A sync response lost in transport after the stamp is therefore evictable, as it was before; the prose says "returned", never "received".
|
|
34
|
+
A record without the key predates this decision and is evicted as before, so an upgrade cannot fill a workspace with protected records until their TTL runs out.
|
|
35
|
+
|
|
36
|
+
**Servers of different releases can share a state root.**
|
|
37
|
+
The store never reads a record's result format, because the release that wrote a result can still deliver it from a server sharing the root, whether it is older or newer than the one enforcing the cap.
|
|
38
|
+
This is the rule `amicus_job_consume_result` already follows: it keeps a result it cannot read rather than delete one another release could deliver (#126).
|
|
39
|
+
The cost is that unfetched results in a format no running server reads hold their slots until `AMICUS_JOB_TTL` expires them.
|
|
40
|
+
A release from before this decision still evicts by age alone, and the records it writes carry no delivery stamp, so they are evicted as before; that is unchanged, and it ends when the old server is upgraded.
|
|
41
|
+
|
|
42
|
+
**The store alone enforces it, under the process lock.**
|
|
43
|
+
`_LOCK` is process-local, so server processes sharing a state root can each pass the check at once and overshoot the cap by one start per process.
|
|
44
|
+
An overshoot deletes nothing, which is the property the annotation needs.
|
|
45
|
+
|
|
46
|
+
## Consequences
|
|
47
|
+
|
|
48
|
+
`destructiveHint: false` on the paid tools in the codex and kimi profile now holds for the job store: a paid call never deletes a tracked result amicus has not yet returned.
|
|
49
|
+
`annotations_reading`, the paid tools' retention sentence, the `amicus_job_*` retention sentence and the server instructions say so.
|
|
50
|
+
`job_cap_reached` is a new amicus-local error code, so `FINGERPRINT` moves.
|
|
51
|
+
`RESULT_FORMAT` does not: the code is refused before a job record exists, so no stored `result.json` can carry it.
|
|
52
|
+
An agent that starts many jobs and never fetches them now meets a refusal where it used to lose results silently.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# ADR 0039: a deadline timeout is never temporary
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted (2026-09-24)
|
|
4
|
+
|
|
5
|
+
Amends [ADR 0010](0010-m4-claude-port-decisions.md), whose Claude-only timeout override this makes the rule for every backend.
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
When a sync paid call on codex or kimi passed its deadline, the `timeout` envelope said `temporary: true` with `next_step: "retry_after_delay"`, while its own prose said the same synchronous call would likely time out again (#245).
|
|
10
|
+
`temporary` means the identical call may succeed later; here the identical call is a sync call that spends again and hits the same deadline.
|
|
11
|
+
Claude's plugin already overrode the rule to `temporary: false`, `next_step: "start_new_job"`, because a Claude timeout may already have been charged.
|
|
12
|
+
So one condition had two contracts, chosen by `backend`, and an agent that branched on the machine field rather than the prose burned quota in a loop.
|
|
13
|
+
|
|
14
|
+
## Decision
|
|
15
|
+
|
|
16
|
+
**The `timeout` rule is amicus-wide: `temporary: false`, `next_step: "start_new_job"`, one prose text.**
|
|
17
|
+
It lives in `amicus.errors._LOCAL_RULES`, above the SDK default; Claude's `repair_overrides` entry and its classifier's own `RepairHint` are gone, and the classifier keeps `retryable: false` and its detail about a possibly charged run.
|
|
18
|
+
A plugin cannot override it: `repair_table` re-applies it after a plugin's `local_codes` and `repair_overrides`, so only a single failure's own `retryable` or repair, applied in `render_failure`, changes that failure's envelope.
|
|
19
|
+
The prose states the spend, names the four `_async` twins, and gates polling on `status` as the `job_running` repair does.
|
|
20
|
+
|
|
21
|
+
**On a sync run, the repair names the verb's `_async` twin, when its deadline is longer, and carries no arguments.**
|
|
22
|
+
`repair.tool` is set where the verb is known: the sync await in `jobs.lifecycle` and `errors.render_failure`, which now takes the run's `kind` and whether it is a background run.
|
|
23
|
+
The twin runs to `AMICUS_JOB_MAX_SECONDS` (60 to 7200 seconds) rather than `timeout_seconds` (10 to 600), so it can have the shorter deadline; it is named only when `AMICUS_JOB_MAX_SECONDS` exceeds the deadline that passed.
|
|
24
|
+
The sync await compares the job store's `max_seconds` with its wait, and `render_failure` compares `RunSpec.job_max_seconds`, set from the server's settings for every run, with `timeout_seconds`.
|
|
25
|
+
Otherwise no tool is named, and the prose says that when it names none the job deadline is no longer than the one that passed, so narrow the task or have the operator raise `AMICUS_JOB_MAX_SECONDS`.
|
|
26
|
+
`RunSpec.job_max_seconds` is not a prompt input and stays out of the idempotency identity, like `background`; a record that lacks it loads as `None`, and then the twin is named as before.
|
|
27
|
+
The arguments would echo prompt inputs (rule 18), and ADR 0021 already accepts a repair that names a tool without arguments when the correction is not unique; the prose says the arguments are the caller's own.
|
|
28
|
+
|
|
29
|
+
**A backend-classified CLI timeout is the same condition.**
|
|
30
|
+
On an unkeyed sync call the worker applies the caller's `timeout_seconds` to the backend subprocess, so there the classifier's `timeout` is the one that fires in practice, and it takes the same rule.
|
|
31
|
+
Codex's capture-failed timeout is the one exception: its hint says to retry the same call once, so it sets `retryable: true` itself, and on that one repair no `_async` tool is named, because its hint prescribes retrying the same call.
|
|
32
|
+
On a keyed call that exception does not hold, because the same call under the same key replays this stored error rather than running again (ADR 0020).
|
|
33
|
+
So `RunSpec.keyed` records whether the call passed an `idempotency_key`, and `render_failure` makes a keyed run's temporary timeout `temporary: false` and leads its prose with `KEYED_REPLAY_NOTE`, which says any retry needs a new key.
|
|
34
|
+
`RunSpec.keyed` is not a prompt input, stays out of the idempotency identity like `background`, and loads as `False` from a record that lacks it.
|
|
35
|
+
|
|
36
|
+
**A background run's timeout names no tool.**
|
|
37
|
+
A background run, an `_async` job or a keyed sync call, gives the backend subprocess `AMICUS_JOB_MAX_SECONDS` (default 1800s) rather than the caller's wait, so its `_async` twin is the run that already timed out.
|
|
38
|
+
Its `timeout` keeps `temporary: false` and `next_step: "start_new_job"`, names no `repair.tool`, and carries its own prose, which names that deadline, says the same call, sync or `_async`, will likely time out again and that any next attempt is a new paid run, and suggests narrowing the task or having the operator raise `AMICUS_JOB_MAX_SECONDS`.
|
|
39
|
+
`RunSpec.background` carries the fact to `render_failure`; it is not a prompt input, it stays out of the idempotency identity so a keyed record written before it existed still replays, and a record that lacks it loads as `False`.
|
|
40
|
+
The same condition on a background run can instead surface as `job_timeout`, depending on when the job is polled: the job store's deadline starts when the job is recorded, before the subprocess's own, and a poll past it reaps the job.
|
|
41
|
+
That is a separate code, which this ADR leaves unchanged.
|
|
42
|
+
|
|
43
|
+
**A keyed sync wait's timeout stays temporary.**
|
|
44
|
+
ADR 0020 already made it so whatever the backend's rule said; the run continues and the repair polls it.
|
|
45
|
+
|
|
46
|
+
## Consequences
|
|
47
|
+
|
|
48
|
+
- `error.temporary` on `timeout` changes from `true` to `false` for codex and kimi, and `retry_after_ms` is always null: **Breaking** in the CHANGELOG sense, since a value a caller read has changed meaning.
|
|
49
|
+
- The codex and kimi result differentials record the deviation from the siblings' `temporary: true`.
|
|
50
|
+
- `FINGERPRINT` moves (with #246, to `schema-45`); `RESULT_FORMAT` stays 9.
|
|
51
|
+
- The design spec's "timeout is not retryable for Claude" now reads "never temporary".
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# ADR 0040: the backend enum is the set the verb accepts
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted (2026-09-24)
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
Five tools published a `backend` enum of `codex | kimi | claude` while always rejecting one or two of them: delegate and its async and dry-run forms accept codex and kimi, and adversarial review and its async form accept claude (#246).
|
|
8
|
+
Only description prose carried the restriction; a schema-driven caller, or a client that generates bindings from `inputSchema`, had no signal, and the wrong pick failed after resolution as `feature_unsupported` with a repair that looked up the backend that had just failed.
|
|
9
|
+
`[3.strict-types]` puts a fixed value set in the enum, and the server already knew the true sets in `amicus_capabilities.tool_details[].backends`.
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
|
|
13
|
+
**Each paid verb's tools publish the enum of the backends that verb accepts.**
|
|
14
|
+
`schemas.codes.VERB_BACKENDS` is the table; `DelegateBackendParam` and `AdversarialBackendParam` are the narrowed `Literal`s, and `TOOL_DETAILS[...]["backends"]` derives from the same table, with a test holding the published enums equal to it.
|
|
15
|
+
The narrowing is in the Pydantic type, so the published enum, the boundary validation and `invalid_arguments.allowed_values` change together.
|
|
16
|
+
A one-value enum, adversarial review's `claude`, is published as `enum: ["claude"]` rather than JSON Schema `const`, so the published set and `invalid_arguments.allowed_values` read the same way on every tool.
|
|
17
|
+
|
|
18
|
+
**The enum narrows per verb, not per profile.**
|
|
19
|
+
A per-profile enum would make the profiles differ in more than annotations, which the manifest's byte-difference control pins, and the tool set is the same in every profile by design.
|
|
20
|
+
Every tool no enabled backend can serve stays listed.
|
|
21
|
+
The adversarial review description says so (its call is `backend_unavailable` unless `claude` is enabled); the delegate descriptions, already long, do not.
|
|
22
|
+
|
|
23
|
+
**`feature_unsupported` repairs to the unfiltered `amicus_backends` call.**
|
|
24
|
+
The code is now only a defensive check: it is returned if the named backend's declared features lack the verb, which no backend a tool's enum accepts does today.
|
|
25
|
+
A third-party backend cannot reach it either, because `config._profile` drops an id outside `BACKEND_IDS`, each tool's `backend` `Literal` rejects one, and the registry refuses an entry point that claims an in-tree id (`reserved_id`); such a call is `invalid_arguments`.
|
|
26
|
+
ADR 0021 forbids a repair whose `arguments` are not a complete call, and a correction that carries a prompt input cannot be echoed, so the repair lists every candidate rather than naming one.
|
|
27
|
+
|
|
28
|
+
## Consequences
|
|
29
|
+
|
|
30
|
+
- `amicus_delegate(backend="claude")` and its async and dry-run forms, and `amicus_adversarial_review(backend="codex"|"kimi")` and its async form, now fail at the boundary as `invalid_arguments` with `allowed_values`, where they failed after resolution as `feature_unsupported`: **Breaking**, since the code a caller read for that call changed.
|
|
31
|
+
- `amicus_models` and `amicus_backends` keep the whole set: they answer for any known backend.
|
|
32
|
+
- `FINGERPRINT` moves (with #245, to `schema-45`); `tools/list` grows by 134 bytes on every profile (`all`: 112683 to 112817), most of it the adversarial review description's clause that the tool stays listed in every profile: 27 bytes from the delegate tools dropping `claude` from their enum and rewording its description, and 107 bytes from the adversarial review tools narrowing to `claude` alone and gaining that description clause.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# ADR 0041: static resource reads carry the catalog TTL
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted (2026-09-25)
|
|
4
|
+
|
|
5
|
+
Amends [ADR 0018](0018-the-catalog-carries-a-ttl-and-resource-reads-do-not.md): its "resources/read carries no hint at all" clause is superseded; the rest stands.
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
ADR 0018 left `resources/read` unhinted because the SDK chooses a hint per method and two template reads report live install, auth and model-catalog state.
|
|
10
|
+
`amicus://error-envelope`, `amicus://result-meta` and `amicus://params` change only when the fingerprint moves, yet every read of them said `ttlMs: 0` while `resources/list` said `300000` (#250 item 2, `[8.cacheable-results]`).
|
|
11
|
+
The SDK applies a method hint only to the fields a handler did not set, so a hint can be stamped per URI on the read result; FastMCP 4.0.5 offers no per-resource hint of its own.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
**The three static bodies carry `CATALOG_CACHE_TTL_MS` on their read results, per URI.**
|
|
16
|
+
`server._install_static_read_ttl` re-registers the low-level `resources/read` handler with a wrapper that stamps the TTL and scope on those three URIs and passes every other result through.
|
|
17
|
+
`resources/read` stays out of the method hint map, so `amicus://capabilities`, which embeds the live env report and `surface_digest`, and the two templates keep `ttlMs: 0`.
|
|
18
|
+
|
|
19
|
+
**The set is written out.**
|
|
20
|
+
`STATIC_READ_TTL_URIS` names the three; a test holds it equal to the manifest's static URIs, and the stdio test asserts the TTL on each of them and its absence on the capabilities and template reads.
|
|
21
|
+
|
|
22
|
+
## Consequences
|
|
23
|
+
|
|
24
|
+
- `modern_result_envelopes` moves for the three reads, so `FINGERPRINT` moves (with the rest of #250).
|
|
25
|
+
- A host that honours `ttlMs` re-reads the three bodies at most every five minutes; a fingerprint move within that window is visible on `amicus_capabilities`, which is not cached.
|
|
26
|
+
- The same handler re-registration is how `_meta.fastmcp` is stripped from the three list results (`_install_meta_strip`), because FastMCP adds that key after every transform and middleware has run.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# ADR 0042: amicus_job_list pages by an opaque cursor
|
|
2
|
+
|
|
3
|
+
**Status:** Accepted (2026-09-25)
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
`amicus_job_list` could not page: omitting `limit` returned every retained match, and setting it truncated to the newest N with `truncated: true` and no way to reach an older job except fetching them all (#249, `[8.house-pagination]`).
|
|
8
|
+
The 2026-09-07 review judged house pagination unnecessary because no tool returned an unbounded list; the list is held to the per-workspace cap `AMICUS_JOB_MAX_COUNT`, which an operator may raise to 1,000, and which server processes sharing a state root can each exceed by one start, because the lock that enforces it is process-local (`JobStore._make_room`).
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
|
|
12
|
+
**A page that omits matching jobs carries `has_more: true` and `next_cursor`, and `cursor` returns the jobs after it under the same filters.**
|
|
13
|
+
`has_more` and `next_cursor` are a house pagination convention in the tool's own result, not protocol fields (`[8.house-pagination]`).
|
|
14
|
+
`truncated` and `truncation_hint` keep their 0.6.0 values as a compatibility alias of `has_more` on this tool, and their descriptions say so: under `[8.truncation]` `truncated` should mean rows paging can never return, and no job the listing omits is beyond reach, so a caller should read `has_more`; changing what `truncated` reports would instead tell a 0.6.0 caller it holds every job.
|
|
15
|
+
The cursor is the last returned row's `started_epoch` and `job_id`, joined by a colon; the listing sorts by that pair, newest first, so a page after an anchor is every row that sorts below it, and an anchor that was consumed or evicted between pages still resolves.
|
|
16
|
+
The text is opaque to callers, and only this tool mints it, but only its form is checked: a cursor that is not a finite epoch, a colon and a 32-hex job id is `invalid_arguments` on `cursor` with a repair naming the tool, and a well-formed one is used as an anchor whether or not the tool issued it.
|
|
17
|
+
Signing the cursor would add a server secret to protect nothing: a forged anchor can only select a page of the caller's own workspace listing, which the same call without `cursor` already returns.
|
|
18
|
+
|
|
19
|
+
**"Omit `limit` for all" stays the default.**
|
|
20
|
+
The list is held to the per-workspace cap, so a bounded default page would change a documented default for little protection; the description now names the cap and its per-process overshoot.
|
|
21
|
+
|
|
22
|
+
## Consequences
|
|
23
|
+
|
|
24
|
+
- `JobListResult` gains `has_more` and `next_cursor`, the tool gains `cursor`, and the listing's sort gains a tiebreak, so `FINGERPRINT` moves; `RESULT_FORMAT` stays 9, since a job list is never stored.
|
|
25
|
+
- The `truncation_hint` names the cursor rather than "omit `limit`".
|
|
26
|
+
- `amicus_capabilities.tool_details` lists `cursor` among the tool's optional parameters.
|