When a team evaluates a new library, linter, or service, the reasoning ends up scattered across Slack threads, issue comments, and wikis. Six months later, nobody remembers why the tool was accepted or rejected — or what the trial conditions were. The next team member starts the evaluation over.
ADOP is a CLI that gives each tool evaluation a structured, append-only record. Every decision — from "we noticed this tool" through "we ran a bounded trial" to "we promoted it" or "we rejected it" — is written as a timestamped artifact in your project's .adop/ directory. The record outlasts the discussion.
Teams that:
- evaluate multiple tools or libraries per quarter and need to trace why each was accepted or rejected
- run bounded trials and want to record the trial conditions and outcome, not just the verdict
- need to show auditors or future teammates that adoption decisions were deliberate and documented
- want to know how deeply a tool is embedded before deciding to replace it
Each evaluation is tracked as a scene lane rooted at related_scene, with the chosen tool and adoption unit carried by the artifacts inside that lane. Evaluating ruff as a linter is therefore a separate lane from evaluating ruff as a formatter. Each lane moves through up to 11 states:
watch → proposed → blocked → trial-ready → in-trial
→ promote / hold / reject → deprecated → migrating → archived
State is always derived from what is written on disk. There is no daemon, no database, no central server.
$ adop status
ADOP (.adop/)
lint-pipeline in-trial
Next steps:
[lint-pipeline]
adop quick-close-trial --trial-id tr-001 --verdict <promote|hold|reject> --observed-effect "<what you saw>" # promote also requires explicit judgment fields
$ adop next
[lint-pipeline] (in-trial)
adop quick-close-trial --trial-id tr-001 --verdict <promote|hold|reject> --observed-effect "<what you saw>" # promote also requires explicit judgment fields
Artifacts are plain JSON files in .adop/. They are append-only — nothing is deleted or overwritten. adop lint validates the full record.
Requires Python 3.11 or 3.12.
Option A — pip install (recommended)
pip install git+https://github.com/maruwork/adop.git
adop --version # adop 0.1.1Option B — clone and run
git clone https://github.com/maruwork/adop.git
cd adop
python shared/python/adop_cli.py --version # adop 0.1.1With Option B, all commands run as python shared/python/adop_cli.py <command>.
For convenience, alias it once per shell session:
# Linux / macOS
alias adop="python $(pwd)/shared/python/adop_cli.py"
# Windows (PowerShell)
function adop { python "$PWD\shared\python\adop_cli.py" @args }# 1. In your project directory, scaffold the record store and overlay
adop init
# 2. Record the first candidate
adop quick-intake --candidate ruff --source doc --use-case lint-pipeline --why-now "evaluating faster linter"
# 3. Compare candidates and select one
adop quick-compare --use-case lint-pipeline --candidate ruff --candidate pylint --selected ruff
# 4. Start a bounded trial
adop quick-trial --use-case lint-pipeline --mode read-only-comparison --executor ci --decision-owner eng-lead --landing-target ci/lint
# 5. Check present state at any time
adop status
# 6. Close the trial with a verdict
adop quick-close-trial --trial-id tr-001 --verdict hold --observed-effect "30% faster, but approval scope still needs narrowing"
# 7. Validate the full record
adop lintFull command reference: adop --help
Guided quick-close-trial --verdict promote is intentionally stricter: it requires explicit --judgment-reason, --next-action, --recurring-control-decision, --root-cause-hypothesis, --preventive-action, and --why-this-problem-recurred so that promotion evidence is not silently auto-filled.
Promotion is also blocked if the latest intake still carries unknown tool attributes; placeholders are allowed during guided intake, but they must be resolved before a tool is promoted.
reject is terminal for a scene lane. If a materially new evaluation is needed later, open a new scene name instead of reopening the rejected lane.
See docs/checklists/ before starting adoption work.
All artifacts write to .adop/ in the present working directory by default.
The --artifact-root flag is optional on every command.
adop init creates the directory and a project-local overlay file in one step.
Before replacing or removing a tool, check how deeply it is embedded:
adop scan --target . --tool ruffReports every file that imports, configures, or references the tool, along with an estimated removal cost.
adop.json: machine-readable canonical identity and runtime file manifestshared/python/: CLI and supporting modulesadop_cli.py: command entry pointadop_artifacts.py: artifact IO / atomic writeadop_validation.py: schema and gate validationadop_summary.py: summary projectionadop_types.py: constants and field namesadop_ids.py: id generation and parsingadop_state_machine.py: lifecycle transition rulesadop_sync.py: drift detection and sync for project-local runtime copiescommon.py: bounded runtime helper
docs/checklists/: review checklist before starting an evaluationshared/templates/: record templates for adoption notes and project-local overlaysdocs/design/: design notes and schema referencedocs/ADOP_GENERIC_QUICKSTART.md: fastest path to understand and verify ADOPSUPPORT.md: pre-issue checklist and support contact routes
README.mddocs/design/ADOP_SHELF_CLASSIFICATION.mddocs/ADOP_GENERIC_QUICKSTART.mddocs/checklists/external-tool-adoption-checklist.mdshared/templates/external-tool-adoption-note-template.mdshared/templates/project-local-adop-overlay-template.mdshared/python/adop_types.pyshared/python/adop_cli.pydocs/design/adop-lifecycle-schema-design.mdSUPPORT.md
This repository holds the shared authority: artifact schema, lifecycle states, CLI, generic checklist, and templates.
Each project maintains its own overlay file (scaffolded by adop init) that holds the project-specific trial board, operator flow, and landing target authority. The boundary is defined in docs/design/ADOP_SHELF_CLASSIFICATION.md.
LICENSECONTRIBUTING.mdSECURITY.mdCODE_OF_CONDUCT.mdCHANGELOG.mdSUPPORT.md.github/ISSUE_TEMPLATE/.github/PULL_REQUEST_TEMPLATE.md.github/CODEOWNERS.github/workflows/ci.yml