Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,36 @@

<!-- version list -->

## v1.19.0 (2026-11-02)

### Breaking Changes

- Require openadapt-flow 2.5 (`>=2.5.0,<3.0.0`). `openadapt shadow` forwards
to Flow's shadow command, and `openadapt verify serve` offers its recheck;
neither is in Flow 2.4 or earlier. `openadapt doctor` and `openadapt deploy`
report an older Flow as unsupported.

### Features

- `openadapt shadow` runs beside an agent you already have, as a loopback
pass-through proxy. It checks each write the agent makes against the
system of record, checks each confirmed write again later, and writes
`report.html` and `report.json`. It never blocks, changes or resends a write
([#1678](https://github.com/OpenAdaptAI/OpenAdapt/pull/1678)).
- `openadapt verify` checks any agent's writes against a contract you own
and returns `CONFIRMED`, `REFUTED` or `UNCERTAIN`. `openadapt verify serve`
offers the same check to any MCP client, recheck included, and `openadapt
verify ledger` lists, reconciles and releases writes whose outcome isn't
known yet ([#1589](https://github.com/OpenAdaptAI/OpenAdapt/pull/1589),
[#1628](https://github.com/OpenAdaptAI/OpenAdapt/pull/1628),
[#1669](https://github.com/OpenAdaptAI/OpenAdapt/pull/1669)).
- `openadapt bench medplum` runs the public Medplum write benchmark with your
own agent ([#1652](https://github.com/OpenAdaptAI/OpenAdapt/pull/1652)).
- `openadapt setup` adds the OpenAdapt MCP server and a skill to Claude Code,
Cursor, Codex and Gemini CLI, so the agent can turn a read-only browser
task into a tool it calls again. It prints every change, and `--dry-run`
and `--undo` are there.

## v1.18.0 (2026-10-20)

### Breaking Changes
Expand Down
32 changes: 16 additions & 16 deletions docs/platform-compatibility-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<!-- Generated by scripts/render_platform_versions.py. Do not edit. -->

- Generated: `2026-10-20T17:25:50+00:00`
- Generated: `2026-11-03T00:23:35+00:00`
- Selection: `explicit-published`
- Compatibility: **dependency-compatible**
- Signature: `unsigned (signing infrastructure pending)`
Expand All @@ -12,7 +12,7 @@
| Role | Package | Version | Release source reference | Published artifacts |
|---|---|---:|---|---|
| launcher | `openadapt` | `1.17.0` | [`v1.17.0`](https://github.com/OpenAdaptAI/OpenAdapt/tree/v1.17.0)<br>commit `e022d97ee8b3c3992f4a4cb6e522f1532fef0834`<br>tree `2e0efeaa337a26d3425320ffa8f9aa3ac31d3f9c` | `openadapt-1.17.0-py3-none-any.whl` `c33c069c8cd9c270562200339b631fb77423b5b7f24364b5f0a6a0730e5ca8b8`<br>`openadapt-1.17.0.tar.gz` `03926f94f4d9d37eeb8c6c9cbdc94516d43c0ace971f2282b3310d77d73b6547` |
| flow | `openadapt-flow` | `2.3.0` | [`openadapt-flow-v2.3.0`](https://github.com/OpenAdaptAI/OpenAdapt/tree/openadapt-flow-v2.3.0/packages/flow)<br>commit `b6a9d46b00b92454c18e844f0a8f6929330e87b6`<br>tree `14bf88ccefe00708bb51003d6262876c555e7271` | `openadapt_flow-2.3.0-py3-none-any.whl` `6a2dbd22eb15bd449fc12a6dc36dcc8da7c0316f9faac80cbff8d6e9a433222b`<br>`openadapt_flow-2.3.0.tar.gz` `39f3b853987227063257a1ffcd402ca3a3120e508d901578622cd0351f1ce12d` |
| flow | `openadapt-flow` | `2.5.0` | [`openadapt-flow-v2.5.0`](https://github.com/OpenAdaptAI/OpenAdapt/tree/openadapt-flow-v2.5.0/packages/flow)<br>commit `5a3bf49a0bf2d662430386295a1c34036c064d58`<br>tree `cab536c90e79fcfe887b8876e884ec2ed651f23e` | `openadapt_flow-2.5.0-py3-none-any.whl` `1dbc5d42d103cfa8a452d95805dde60c7d460035ec4d81df5cc642a32f118339`<br>`openadapt_flow-2.5.0.tar.gz` `54d99e77976ee7d9e6bc171b2ea148497528ead77b226fdf6fd4713b37c689b3` |
| capture | `openadapt-capture` | `1.2.2` | [`v1.2.2`](https://github.com/OpenAdaptAI/openadapt-capture/tree/v1.2.2)<br>commit `06ade22948c12dcc6608bd54b5cca5c9c306e77c`<br>tree `b0a3b5b53f23536e01314f36aa46fd5b2d8baba6` | `openadapt_capture-1.2.2-py3-none-any.whl` `550fffe50990fa8431d332bdd5fe4755976d83baa7ad62553f50ad9e4ddcd1ae`<br>`openadapt_capture-1.2.2.tar.gz` `6f4298d3daadf9cced8994207e34b3116a79209ef792e98f778a0770e2f3406c` |
| privacy | `openadapt-privacy` | `1.1.2` | [`v1.1.2`](https://github.com/OpenAdaptAI/openadapt-privacy/tree/v1.1.2)<br>commit `9ae96d8ed73ea5b9e445d0604b5db48788936a04`<br>tree `fe59ca5f04fc99d16424e9228dcd797b05115cb8` | `openadapt_privacy-1.1.2-py3-none-any.whl` `6e542b2fea44bdf8872430687946ec805fef22dc7d228a56a1e65871beebe47a`<br>`openadapt_privacy-1.1.2.tar.gz` `d90287edaa13470955f15d5f6eeb37b075678aeb55de324f8b8207682009bcc2` |
| types | `openadapt-types` | `0.24.0` | [`openadapt-types-v0.24.0`](https://github.com/OpenAdaptAI/OpenAdapt/tree/openadapt-types-v0.24.0/packages/types)<br>commit `f2f04c5b432d88b262d46103a542b0e2c3dcc8a9`<br>tree `38ccf341ec74a0dd0facc9f64343c27644a7ca7d` | `openadapt_types-0.24.0-py3-none-any.whl` `8025e8a4dc9235fd81d4b24ae7fa7e544120abdb8d4ee7df160e4f50d9230d75`<br>`openadapt_types-0.24.0.tar.gz` `16dcd1da1c2c78c08d650a19eb9cc439474f996812a87198b316d51bfac443db` |
Expand All @@ -23,10 +23,10 @@

| Unit | Version | Selected or locked OpenAdapt packages |
|---|---:|---|
| launcher_environment | `1.17.0` | `openadapt==1.17.0`<br>`openadapt-flow==2.3.0` |
| customer_runner | `2.3.0` | `openadapt-flow==2.3.0`<br>`openadapt-types==0.24.0` |
| launcher_environment | `1.17.0` | `openadapt==1.17.0`<br>`openadapt-flow==2.5.0` |
| customer_runner | `2.5.0` | `openadapt-flow==2.5.0`<br>`openadapt-types==0.24.0` |
| desktop_sidecar | `0.16.0` | `openadapt-capture==1.2.1`<br>`openadapt-flow==1.34.0`<br>`openadapt-privacy==1.0.0`<br>`openadapt-types==0.10.0` |
| agent_bridge | `2.2.1` | `openadapt-agent==2.2.1`<br>`openadapt-flow==2.3.0` |
| agent_bridge | `2.2.1` | `openadapt-agent==2.2.1`<br>`openadapt-flow==2.5.0` |

## Selected-platform dependency compatibility

Expand All @@ -38,29 +38,29 @@ These edges show whether each selected integration version satisfies its publish
| desktop-sidecar-lock | `openadapt-desktop==0.16.0` | `openadapt-flow` | `==1.34.0` | `1.34.0` | `extra == "build"` |
| desktop-sidecar-lock | `openadapt-desktop==0.16.0` | `openadapt-privacy` | `>=1.0.0` | `1.0.0` | `always` |
| desktop-sidecar-lock | `openadapt-desktop==0.16.0` | `openadapt-types` | `==0.10.0` | `0.10.0` | `always` |
| selected-platform | `openadapt-agent==2.2.1` | `openadapt-flow` | `<3,>=2.2.0` | `2.3.0` | `always`<br>`extra == "tutorial"` |
| selected-platform | `openadapt-agent==2.2.1` | `openadapt-flow` | `<3,>=2.2.0` | `2.5.0` | `always`<br>`extra == "tutorial"` |
| selected-platform | `openadapt-agent==2.2.1` | `openadapt-privacy` | `>=1.1.2` | `1.1.2` | `extra == "repair-screens"` |
| selected-platform | `openadapt-capture==1.2.2` | `openadapt-privacy` | `>=0.1.0` | `1.1.2` | `extra == "all"`<br>`extra == "privacy"` |
| selected-platform | `openadapt-flow==2.3.0` | `openadapt-capture` | `>=1.2.0` | `1.2.2` | `extra == "capture"` |
| selected-platform | `openadapt-flow==2.3.0` | `openadapt-privacy` | `>=1.0.0` | `1.1.2` | `extra == "privacy"` |
| selected-platform | `openadapt-flow==2.3.0` | `openadapt-types` | `<0.25.0,>=0.24.0` | `0.24.0` | `always` |
| selected-platform | `openadapt-flow==2.5.0` | `openadapt-capture` | `>=1.2.0` | `1.2.2` | `extra == "capture"` |
| selected-platform | `openadapt-flow==2.5.0` | `openadapt-privacy` | `>=1.0.0` | `1.1.2` | `extra == "privacy"` |
| selected-platform | `openadapt-flow==2.5.0` | `openadapt-types` | `<0.25.0,>=0.24.0` | `0.24.0` | `always` |
| selected-platform | `openadapt==1.17.0` | `openadapt-agent` | `<3,>=2.1.0` | `2.2.1` | `python_version < "3.13"`<br>`python_version < "3.13" and extra == "agent"`<br>`python_version < "3.13" and extra == "all"` |
| selected-platform | `openadapt==1.17.0` | `openadapt-capture` | `<2.0.0,>=1.2.0` | `1.2.2` | `extra == "all"`<br>`extra == "capture"`<br>`extra == "core"` |
| selected-platform | `openadapt==1.17.0` | `openadapt-flow` | `<3.0.0,>=2.0.0` | `2.3.0` | `(sys_platform == "darwin" and python_version < "3.13") and extra == "all"`<br>`(sys_platform == "darwin" and python_version < "3.13") and extra == "macos"`<br>`(sys_platform == "linux" and python_version < "3.13") and extra == "all"`<br>`(sys_platform == "linux" and python_version < "3.13") and extra == "linux"`<br>`python_version < "3.13"`<br>`python_version < "3.13" and extra == "all"`<br>`python_version < "3.13" and extra == "browser"`<br>`python_version < "3.13" and extra == "capture"`<br>`python_version < "3.13" and extra == "core"`<br>`python_version < "3.13" and extra == "flow"`<br>`python_version < "3.13" and extra == "privacy"`<br>`python_version < "3.13" and extra == "rdp"`<br>`python_version < "3.13" and extra == "windows"` |
| selected-platform | `openadapt==1.17.0` | `openadapt-flow` | `<3.0.0,>=2.0.0` | `2.5.0` | `(sys_platform == "darwin" and python_version < "3.13") and extra == "all"`<br>`(sys_platform == "darwin" and python_version < "3.13") and extra == "macos"`<br>`(sys_platform == "linux" and python_version < "3.13") and extra == "all"`<br>`(sys_platform == "linux" and python_version < "3.13") and extra == "linux"`<br>`python_version < "3.13"`<br>`python_version < "3.13" and extra == "all"`<br>`python_version < "3.13" and extra == "browser"`<br>`python_version < "3.13" and extra == "capture"`<br>`python_version < "3.13" and extra == "core"`<br>`python_version < "3.13" and extra == "flow"`<br>`python_version < "3.13" and extra == "privacy"`<br>`python_version < "3.13" and extra == "rdp"`<br>`python_version < "3.13" and extra == "windows"` |

## Cross-component schemas

| Contract | Owner | Accepted versions | Exact source |
|---|---|---|---|
| `workflow_bundle` | `flow` | `schema_version` [1, 2] | [`packages/flow/openadapt_flow/bundle_validation.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/b6a9d46b00b92454c18e844f0a8f6929330e87b6/packages/flow/openadapt_flow/bundle_validation.py) `936c42daa7618a07222a6807080045aa5e8a25ebcf4dd2c7488351fc13663d18`<br>[`packages/flow/openadapt_flow/ir.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/b6a9d46b00b92454c18e844f0a8f6929330e87b6/packages/flow/openadapt_flow/ir.py) `739fe7f4841a018668840559cead446d25c6a22d1a33ed3721bd553d10e9366a` |
| `workflow_bundle` | `flow` | `schema_version` [1, 2] | [`packages/flow/openadapt_flow/bundle_validation.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/5a3bf49a0bf2d662430386295a1c34036c064d58/packages/flow/openadapt_flow/bundle_validation.py) `63532fb8e49f25a8aba8dccca505362a9293b8db9cbc0f2904dd8f9a6e23fea8`<br>[`packages/flow/openadapt_flow/ir.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/5a3bf49a0bf2d662430386295a1c34036c064d58/packages/flow/openadapt_flow/ir.py) `efb7fdce6fa625f631901389ca767b016f4db3111caa2905321ff3da675e376d` |
| `capture_structural_observation` | `capture` | `openadapt.capture.structural-observation/v` [1] | [`openadapt_capture/structural.py`](https://github.com/OpenAdaptAI/openadapt-capture/blob/06ade22948c12dcc6608bd54b5cca5c9c306e77c/openadapt_capture/structural.py) `8f8bce37148a3357ace147c46a7c45e6d5501b70622b24b1ac2490f2def304fc` |
| `control_overlay_frame` | `types` | `openadapt.control-overlay-frame/v` [1, 2] | [`packages/types/openadapt_types/control_overlay.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/f2f04c5b432d88b262d46103a542b0e2c3dcc8a9/packages/types/openadapt_types/control_overlay.py) `3aa01f89b43e12478c9e2ff1a9e61689397370691d15247ded9dcd5b05242790`<br>[`packages/types/openadapt_types/control_overlay_tracking.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/f2f04c5b432d88b262d46103a542b0e2c3dcc8a9/packages/types/openadapt_types/control_overlay_tracking.py) `af8d934f0572c5f4e9c63ba720d4a1d0e73c8cdf3f7b87cc4562c01a8a551755` |
| `control_overlay_timeline` | `types` | `openadapt.control-overlay-timeline/v` [1, 2] | [`packages/types/openadapt_types/control_overlay.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/f2f04c5b432d88b262d46103a542b0e2c3dcc8a9/packages/types/openadapt_types/control_overlay.py) `3aa01f89b43e12478c9e2ff1a9e61689397370691d15247ded9dcd5b05242790`<br>[`packages/types/openadapt_types/control_overlay_tracking.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/f2f04c5b432d88b262d46103a542b0e2c3dcc8a9/packages/types/openadapt_types/control_overlay_tracking.py) `af8d934f0572c5f4e9c63ba720d4a1d0e73c8cdf3f7b87cc4562c01a8a551755` |
| `human_decision_task` | `types` | `openadapt.human-decision-task/v` [1, 2] | [`packages/types/openadapt_types/human_decision.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/f2f04c5b432d88b262d46103a542b0e2c3dcc8a9/packages/types/openadapt_types/human_decision.py) `0bb39a3575f511e10d01d92858b340982adee2f0fc20d2409441dbc0b2c55c4f` |
| `human_decision_receipt` | `types` | `openadapt.human-decision-receipt/v` [1] | [`packages/types/openadapt_types/human_decision.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/f2f04c5b432d88b262d46103a542b0e2c3dcc8a9/packages/types/openadapt_types/human_decision.py) `0bb39a3575f511e10d01d92858b340982adee2f0fc20d2409441dbc0b2c55c4f` |
| `human_decision_relay` | `flow` | `openadapt.human-decision-relay/v` [2] | [`packages/flow/openadapt_flow/console/decision_relay.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/b6a9d46b00b92454c18e844f0a8f6929330e87b6/packages/flow/openadapt_flow/console/decision_relay.py) `d5320404d4342dbb52be1f2ead1cdb5cf0e22877feaaa1e47974b301df697292` |
| `remote_decision_projection` | `flow` | `openadapt.remote-decision-projection/v` [1] | [`packages/flow/openadapt_flow/console/human_decisions.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/b6a9d46b00b92454c18e844f0a8f6929330e87b6/packages/flow/openadapt_flow/console/human_decisions.py) `02651ad8888a5c17bfff6fb47165ba861193243dc0f7c951f8b94f544ca19477` |
| `runtime_validation` | `flow` | `openadapt.runtime-validation/v` [1, 2, 3] | [`packages/flow/openadapt_flow/runtime_validation.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/b6a9d46b00b92454c18e844f0a8f6929330e87b6/packages/flow/openadapt_flow/runtime_validation.py) `a5a220f570c5ee5769ac2f21d8d140bb69373d4de2ccc0ebfd08540122883f0e` |
| `human_decision_relay` | `flow` | `openadapt.human-decision-relay/v` [2] | [`packages/flow/openadapt_flow/console/decision_relay.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/5a3bf49a0bf2d662430386295a1c34036c064d58/packages/flow/openadapt_flow/console/decision_relay.py) `d5320404d4342dbb52be1f2ead1cdb5cf0e22877feaaa1e47974b301df697292` |
| `remote_decision_projection` | `flow` | `openadapt.remote-decision-projection/v` [1] | [`packages/flow/openadapt_flow/console/human_decisions.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/5a3bf49a0bf2d662430386295a1c34036c064d58/packages/flow/openadapt_flow/console/human_decisions.py) `02651ad8888a5c17bfff6fb47165ba861193243dc0f7c951f8b94f544ca19477` |
| `runtime_validation` | `flow` | `openadapt.runtime-validation/v` [1, 2, 3] | [`packages/flow/openadapt_flow/runtime_validation.py`](https://github.com/OpenAdaptAI/OpenAdapt/blob/5a3bf49a0bf2d662430386295a1c34036c064d58/packages/flow/openadapt_flow/runtime_validation.py) `a5a220f570c5ee5769ac2f21d8d140bb69373d4de2ccc0ebfd08540122883f0e` |

## Host operating systems

Expand All @@ -82,5 +82,5 @@ Compatibility and delivery facts do not assign lifecycle state. Use the signed P
## Qualification evidence

- [openadapt-public-status](https://openadapt.ai/status.json): Canonical machine-readable release, capability, and substrate qualification status, maintained in openadapt-web (public/status.json).
- [flow-public-demo-evidence-packs](https://github.com/OpenAdaptAI/OpenAdapt/tree/b6a9d46b00b92454c18e844f0a8f6929330e87b6/packages/flow/public-demo/evidence-packs): Versioned public evidence packs with per-pack manifest files, replay evidence, and fault-case results.
- [flow-effectbench-task-pack](https://github.com/OpenAdaptAI/OpenAdapt/blob/b6a9d46b00b92454c18e844f0a8f6929330e87b6/packages/flow/benchmark/effectbench/task_pack/manifest.json): Effect-verification benchmark task pack manifest used by the flow qualification harness.
- [flow-public-demo-evidence-packs](https://github.com/OpenAdaptAI/OpenAdapt/tree/5a3bf49a0bf2d662430386295a1c34036c064d58/packages/flow/public-demo/evidence-packs): Versioned public evidence packs with per-pack manifest files, replay evidence, and fault-case results.
- [flow-effectbench-task-pack](https://github.com/OpenAdaptAI/OpenAdapt/blob/5a3bf49a0bf2d662430386295a1c34036c064d58/packages/flow/benchmark/effectbench/task_pack/manifest.json): Effect-verification benchmark task pack manifest used by the flow qualification harness.
2 changes: 2 additions & 0 deletions llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2253,6 +2253,8 @@ Shadow mode checks the writes of an agent you already run against the system of

### Features

- Self-repair's new clicks no longer need a browser. On a backend with an accessibility tree, a click with no record identity under it is admitted when its element (role, name, ancestry, window) is the only one with that locator in the pinned window and a record check covers every save: a system-of-record verifier, a `standard` or `regulated` profile, and confirmed effects and an armed identity check on each save. On a pixel-only backend the record check alone admits it. The new step carries the dialog around it as its identity band, a screen pre-check, and only a person approves such a fix; a signed standard change can't. The browser rule is unchanged. `MacOSBackend.element_identity_at` reads the AX element, the repair hold answers `element_identity`, and agent teach takes the dialog box from it. Design: `docs/REPAIR_ON_EVERY_BACKEND.md` ([#1709](https://github.com/OpenAdaptAI/OpenAdapt/pull/1709)).

- Shadow mode: `openadapt shadow` runs beside an agent you already have, as a loopback pass-through proxy, and checks each write it makes against the system of record (`CONFIRMED`, `REFUTED`, `UNCERTAIN`). It never blocks, changes or resends a write; the only delay is the read before a write, at most `hold_ms`, measured per write. FHIR writes are checked by `ensure_record.verify_ensure` and SQL writes by `verifier.begin_write`/`verify_write` with the whole-database frame. Each `CONFIRMED` is checked again later (`recheck_s`, or the contract's `recheck_after_s`), and a late `REFUTED` gets its own line in `report.html` and `report.json`. `verify_ensure` takes `declared`: resources of other writes the caller saw, judged on their own ([#1678](https://github.com/OpenAdaptAI/OpenAdapt/pull/1678)).

- The whole-database frame (`frame.database`) and its recheck now work on PostgreSQL (`dialect: postgresql`). The snapshot is one read-only repeatable-read transaction over every schema but the system ones. Every column type is read as text by a declared rule, in a session pinned to UTC and exact float output: `numeric` at full precision (with its stored scale when it has no declared one), floats exactly, `bytea` as hex, `json` as stored and `jsonb` canonical, arrays, ranges, enums, domains, `uuid`, network, time, `interval`, `money`, bit, `xml`, text-search and geometric types. A table without a primary key is keyed by the whole row, with duplicates counted. A column type without a rule, a table the account can't read in full (no `SELECT`, row-level security), a foreign table and an unreadable sequence are refused unless the allow-list skips them with a reason. A sequence a column owns is that table's counter, and a counter set back counts as a change; any other sequence is compared as a one-row table. Large objects are read by the SHA-256 of their content. `frame.database.schemas` means the same as on MySQL (each must be visible, and every visible schema is read); a schema is left out only by an `allow_tables` entry `<schema>.*` with `mode: skip` and a reason.
Expand Down
Loading
Loading