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
68 changes: 24 additions & 44 deletions llms-full.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# OpenAdapt: review brief for openadapt-flow 2.3.0
# OpenAdapt: review brief for openadapt-flow 2.4.0

This file describes the current OpenAdapt release. It is generated from the repository (scripts/build_llms_full.py) and refreshed with every release. Pages, posts and repositories that describe earlier versions are outdated; where they disagree with this file, this file is current.

Expand Down Expand Up @@ -2041,54 +2041,34 @@ automation into an independently certified transaction system.

---

<!-- Changelog: openadapt-flow 2.3.0 -->
<!-- Changelog: openadapt-flow 2.4.0 -->

## What changed in openadapt-flow 2.3.0
## What changed in openadapt-flow 2.4.0

The shared contracts are back in `openadapt-types`, which depends only on Pydantic; this package requires `openadapt-types>=0.24.0,<0.25.0`, and `openadapt_flow.contracts` returns the same modules as `openadapt_types` ([#1270](https://github.com/OpenAdaptAI/OpenAdapt/pull/1270)).
A person's approval counts only when a registered approver key signed it, and the verification, identity and recovery paths below fail closed where they used to pass.

### Features

- Offline Seals can be signed with a key the customer holds: a key file, the OS keychain, or a PKCS#11 token. `local-seal key` creates, pins and revokes keys, and a configured key that can't be used signs nothing ([#1392](https://github.com/OpenAdaptAI/OpenAdapt/pull/1392)).
- `local-seal anchor` records an offline Seal in Sigstore Rekor. Only a digest, the Seal key's public key and a signature leave the machine, and `local-seal verify --require-anchor` checks the stored inclusion proof offline ([#1394](https://github.com/OpenAdaptAI/OpenAdapt/pull/1394)).
- Run authorizations (`openadapt.run-authorization/v1`) are signed with the SSH key a person publishes on GitHub. `local-seal authorize sign` shows what is being authorized before it signs, verification runs offline, and `--live` re-reads the person's keys from GitHub. `local-seal run --authorization` seals only the items, profile and Seal keys the statement covers ([#1401](https://github.com/OpenAdaptAI/OpenAdapt/pull/1401)).
- `local-seal timestamp` adds an RFC 3161 timestamp from Sigstore's TSA (or `--tsa-url`) to a Seal or a run authorization, and `verify --require-timestamp` checks it offline against the bundled TSA root ([#1401](https://github.com/OpenAdaptAI/OpenAdapt/pull/1401)).
- `local-seal profile` writes an operator profile per Seal key: outcome counts, apps, programs and log times from anchored Seals, with no patient data. A report sealed again counts once ([#1401](https://github.com/OpenAdaptAI/OpenAdapt/pull/1401), [#1416](https://github.com/OpenAdaptAI/OpenAdapt/pull/1416)).
- Session tokens, credential headers and bearer tokens are redacted from run reports before they are written, so no Seal covers them. The Seal refuses an unredacted report, and `openadapt-flow redact-report` cleans runs written earlier ([#1407](https://github.com/OpenAdaptAI/OpenAdapt/pull/1407)).
- The compiler groups every program into named sections (`sections.json`) from the consequential write, the recorded form structure and the fields, with no model call ([#1405](https://github.com/OpenAdaptAI/OpenAdapt/pull/1405)). `openadapt_flow.visualize` projects a bundle into the program map that Desktop and openadapt.ai render ([#1387](https://github.com/OpenAdaptAI/OpenAdapt/pull/1387)).
- `openadapt-flow compile-agent` compiles an agent's first verified run into a program that replays with zero model calls, on browser, Windows, macOS, Linux, RDP and Citrix apps, with a code-as-action agent for run 1 ([#1277](https://github.com/OpenAdaptAI/OpenAdapt/pull/1277), [#1283](https://github.com/OpenAdaptAI/OpenAdapt/pull/1283), [#1305](https://github.com/OpenAdaptAI/OpenAdapt/pull/1305), [#1303](https://github.com/OpenAdaptAI/OpenAdapt/pull/1303)).
- Every teach path (JIT capture, compile-agent, teach over MCP and the guard) runs under the task's declared inputs, origins and writes, and a violation leaves no draft ([#1359](https://github.com/OpenAdaptAI/OpenAdapt/pull/1359), [#1386](https://github.com/OpenAdaptAI/OpenAdapt/pull/1386)). An approval shows who asked for a save, the agent's own reason, the screen text it saw, and any of it that reads like an instruction to an agent ([#1359](https://github.com/OpenAdaptAI/OpenAdapt/pull/1359)).
- The MCP server can teach a workflow and then call it with no model calls ([#1335](https://github.com/OpenAdaptAI/OpenAdapt/pull/1335)), keeps a task ledger and can ask the user ([#1332](https://github.com/OpenAdaptAI/OpenAdapt/pull/1332)), and pins authoring to the app a deployment file names ([#1287](https://github.com/OpenAdaptAI/OpenAdapt/pull/1287)).
- A guarded save wraps any agent's write: check the record, hold for approval, read back ([#1258](https://github.com/OpenAdaptAI/OpenAdapt/pull/1258)). A CDP commit guard covers an agent you already run ([#1357](https://github.com/OpenAdaptAI/OpenAdapt/pull/1357)).
- JIT: a person names the record check's idempotency key at `confirm_params` ([#1339](https://github.com/OpenAdaptAI/OpenAdapt/pull/1339)); a retyped input is lifted from the saved record, and distill drops a corrected save ([#1336](https://github.com/OpenAdaptAI/OpenAdapt/pull/1336)).
- API steps: a clean save in a recording's network capture compiles into an API step with the same record check, and falls back to page structure before anything is sent when the API is unavailable ([#1269](https://github.com/OpenAdaptAI/OpenAdapt/pull/1269)). API steps run in durable runs without ever resending a save ([#1358](https://github.com/OpenAdaptAI/OpenAdapt/pull/1358)), under governed runs and the Standard and Regulated profiles ([#1361](https://github.com/OpenAdaptAI/OpenAdapt/pull/1361)), and under per-item approval of the exact request ([#1355](https://github.com/OpenAdaptAI/OpenAdapt/pull/1355)); the read-back is pipelined ([#1362](https://github.com/OpenAdaptAI/OpenAdapt/pull/1362)).
- Self-repair: a halted run can be repaired under one person's approval ([#1265](https://github.com/OpenAdaptAI/OpenAdapt/pull/1265)), including with a short bridge of up to three new steps ([#1325](https://github.com/OpenAdaptAI/OpenAdapt/pull/1325)); repairs a person approved in advance apply as standard changes ([#1294](https://github.com/OpenAdaptAI/OpenAdapt/pull/1294)); and every stop that wrote nothing is repaired by default ([#1360](https://github.com/OpenAdaptAI/OpenAdapt/pull/1360)).
- After a stop: a change ledger, a write-ordering lint and declared undo steps ([#1263](https://github.com/OpenAdaptAI/OpenAdapt/pull/1263)). `openadapt-flow undo propose` proposes an undo for each save and keeps it only if a test copy shows every record restored; a person approves it once with `undo accept` ([#1346](https://github.com/OpenAdaptAI/OpenAdapt/pull/1346)).
- Record checks: `scaffold-verifier` builds a working check from the reads the app made while the person viewed the saved record ([#1284](https://github.com/OpenAdaptAI/OpenAdapt/pull/1284)); the recording teaches the check when the person looks the record up after saving ([#1290](https://github.com/OpenAdaptAI/OpenAdapt/pull/1290)); a desktop, RDP or Citrix save is checked by looking the record up in a separate read-only session ([#1280](https://github.com/OpenAdaptAI/OpenAdapt/pull/1280)), with a fresh session for desktop relaunch and a second RDP session ([#1241](https://github.com/OpenAdaptAI/OpenAdapt/pull/1241)); a check level per save, a learned reopen, a read-only guard and reference capture ([#1239](https://github.com/OpenAdaptAI/OpenAdapt/pull/1239)).
- A save confirmed by a later report or acknowledgment is `SAVED_AWAITING_CHECK` and never counts as done until then ([#1297](https://github.com/OpenAdaptAI/OpenAdapt/pull/1297)). The receipt keeps the server's own answer to a save, labelled `same_screen` ([#1298](https://github.com/OpenAdaptAI/OpenAdapt/pull/1298)), and signs `checked_how` ([#1240](https://github.com/OpenAdaptAI/OpenAdapt/pull/1240)). `verify-run` treats a changed non-target record as collateral, not only a vanished one ([#1375](https://github.com/OpenAdaptAI/OpenAdapt/pull/1375)).
- Identity: extra looks before stopping on a look-alike record ID (fresh frames, the known-ID list, a select-and-copy of the ID) ([#1333](https://github.com/OpenAdaptAI/OpenAdapt/pull/1333)); a hover check on icon-only targets and a fresh-frame re-check right before every pixel click ([#1334](https://github.com/OpenAdaptAI/OpenAdapt/pull/1334)); one re-observation before halting on an identity mismatch ([#1293](https://github.com/OpenAdaptAI/OpenAdapt/pull/1293)).
- Learning from many runs: shadow-mined episodes become candidate drafts, and a program admitted once stops only on problems ([#1212](https://github.com/OpenAdaptAI/OpenAdapt/pull/1212)); `induce --probe-on` settles a disagreement between recordings on a browser, desktop or remote test copy ([#1276](https://github.com/OpenAdaptAI/OpenAdapt/pull/1276)); a deterministic router sends each item to the right admitted variant ([#1264](https://github.com/OpenAdaptAI/OpenAdapt/pull/1264)); narration proposes branch rules that recordings, a probe or a person certify ([#1291](https://github.com/OpenAdaptAI/OpenAdapt/pull/1291)); common local edits are classified from the recording on strict evidence ([#1366](https://github.com/OpenAdaptAI/OpenAdapt/pull/1366)).
- One program switches tabs, popups and backends mid-run ([#1197](https://github.com/OpenAdaptAI/OpenAdapt/pull/1197)); lists and worktables are walked with focus and modal checks before each copy ([#1253](https://github.com/OpenAdaptAI/OpenAdapt/pull/1253)); worklists run in parallel with one session per worker ([#1296](https://github.com/OpenAdaptAI/OpenAdapt/pull/1296)).
- Records: READ is a workflow step ([#1229](https://github.com/OpenAdaptAI/OpenAdapt/pull/1229)), with a record and field schema ([#1214](https://github.com/OpenAdaptAI/OpenAdapt/pull/1214)), an interchange format ([#1215](https://github.com/OpenAdaptAI/OpenAdapt/pull/1215)), one read channel by default with an opt-in double read ([#1218](https://github.com/OpenAdaptAI/OpenAdapt/pull/1218)), a review queue with signed, write-once decisions ([#1219](https://github.com/OpenAdaptAI/OpenAdapt/pull/1219)), and export to CSV, DB-API databases and webhooks ([#1220](https://github.com/OpenAdaptAI/OpenAdapt/pull/1220)).
- Everything that leaves the machine is scrubbed by default ([#1262](https://github.com/OpenAdaptAI/OpenAdapt/pull/1262)), and every PHI file is encrypted at rest under one sealed index ([#1354](https://github.com/OpenAdaptAI/OpenAdapt/pull/1354)).
- The phone approval shows the values a save writes ([#1257](https://github.com/OpenAdaptAI/OpenAdapt/pull/1257)).
- A qualification project can bind to the generic web environment observer (`observe_web_environment`), whose digest is the one a governed browser run on the same machine observes ([#1353](https://github.com/OpenAdaptAI/OpenAdapt/pull/1353)).
- A compatibility matrix, checked against the runtime in CI ([#1364](https://github.com/OpenAdaptAI/OpenAdapt/pull/1364)).
- Harness²: a benchmark adapter scored by read-back, GUI rollouts on pixel-only surfaces, and a Meta-Harness-style trace export ([#1299](https://github.com/OpenAdaptAI/OpenAdapt/pull/1299), [#1301](https://github.com/OpenAdaptAI/OpenAdapt/pull/1301), [#1300](https://github.com/OpenAdaptAI/OpenAdapt/pull/1300), [#1304](https://github.com/OpenAdaptAI/OpenAdapt/pull/1304)).

### Performance

- Apple Vision identity reads match RapidOCR on the dense surface ([#1228](https://github.com/OpenAdaptAI/OpenAdapt/pull/1228)).
- A person's approval of a gated save carries an Ed25519 signature from a key registered under the `approvers` role (`jit register --role approver`), made with the route's own method (`desktop_key` for Desktop, `portal_key` for the decision portal). Item approvals, the durable `approve` and `resume`, the console and the agent tools all verify it; an unsigned, claimed or hand-written answer gives no authority. `approve`, `resume`, `run` and `run-case` take `--key-dir` to name the registry ([#1486](https://github.com/OpenAdaptAI/OpenAdapt/pull/1486), [#1501](https://github.com/OpenAdaptAI/OpenAdapt/pull/1501)).
- Loop induction learns worklists that are not back-to-back repeats: a click names the parameter that identifies its row (`Step.target_param`), and each pass works on, and is checked against, its own row's record ([#1435](https://github.com/OpenAdaptAI/OpenAdapt/pull/1435)).
- Pipelined read-back runs under durable, Standard and Regulated runs. The deferred check is written into the durable pause before the side thread gets it, and a `problems_only` run decides each item from its settled check ([#1442](https://github.com/OpenAdaptAI/OpenAdapt/pull/1442), [#1460](https://github.com/OpenAdaptAI/OpenAdapt/pull/1460)).
- An admitted API step runs inside a multi-surface program on its own surface, under a managed dispatch that names it, and under a qualification admission that qualified its path ([#1439](https://github.com/OpenAdaptAI/OpenAdapt/pull/1439), [#1444](https://github.com/OpenAdaptAI/OpenAdapt/pull/1444), [#1451](https://github.com/OpenAdaptAI/OpenAdapt/pull/1451)).
- `verify-run` judges frame conditions: a record that no effect declares, added, removed or changed, is a collateral change, with optional attribution from an audit log or a modified-by field ([#1443](https://github.com/OpenAdaptAI/OpenAdapt/pull/1443)). A record check is admitted only after it catches its faults on a test copy of the system of record (`fault_gate`, `openadapt.check-coverage/v1`) ([#1445](https://github.com/OpenAdaptAI/OpenAdapt/pull/1445)). A saved record is compared with its source document through a second extraction by a different method (`provenance`) ([#1446](https://github.com/OpenAdaptAI/OpenAdapt/pull/1446)).
- A pinned bundle can be repaired: the fix is re-qualified on a test copy and re-admitted with signed lineage, and the pin accepts the new version only through that lineage ([#1450](https://github.com/OpenAdaptAI/OpenAdapt/pull/1450)). A renamed save button is repaired when the recorded identity hash proves only the label changed ([#1514](https://github.com/OpenAdaptAI/OpenAdapt/pull/1514)). `qualify` handles a bundle that already has a qualification project, an encrypted bundle and a sealed set ([#1454](https://github.com/OpenAdaptAI/OpenAdapt/pull/1454)).
- The record check reads a typed label back as its stored code (`ValueExpr` `map`) and can require exactly the new record (`record.exact_new_set`) ([#1456](https://github.com/OpenAdaptAI/OpenAdapt/pull/1456)).
- Under `problems_only`, problems with an item's own input leave the switch on and send that item to a person; program and environment problems turn it off, and a person re-arms it with one signed tap ([#1517](https://github.com/OpenAdaptAI/OpenAdapt/pull/1517)).
- Look-alike rows are counted on Windows, macOS, Linux and pixel-only surfaces, so a step that picks a row halts when it cannot tell the target from its twin ([#1504](https://github.com/OpenAdaptAI/OpenAdapt/pull/1504), [#1518](https://github.com/OpenAdaptAI/OpenAdapt/pull/1518), [#1557](https://github.com/OpenAdaptAI/OpenAdapt/pull/1557)).
- `openadapt-agent serve --teach-browser` lets a coding agent turn a read-only browser task into a named tool it calls again with new values; `openadapt setup` registers it with Claude Code, Cursor, Codex and Gemini CLI ([#1502](https://github.com/OpenAdaptAI/OpenAdapt/pull/1502)).
- `induce --held-out` scores each held-out item by running it and checking the record independently ([#1527](https://github.com/OpenAdaptAI/OpenAdapt/pull/1527)).

### Fixes

- In a governed run, an armed step whose identity is unreadable halts before acting, whether or not the authorization lists it ([#1397](https://github.com/OpenAdaptAI/OpenAdapt/pull/1397)).
- A scroll skipped because its target was already in view verifies instead of counting as undelivered ([#1395](https://github.com/OpenAdaptAI/OpenAdapt/pull/1395)).
- Bundles certified by earlier releases load and keep their workflow contract hash: an effect's `forbid_collateral_change` is serialized only when it is on ([#1406](https://github.com/OpenAdaptAI/OpenAdapt/pull/1406)).
- A bad `local-seal` input (missing, empty, not JSON, repeated keys, the wrong shape, or a saved web page) fails in one clear line with exit 2, never a traceback ([#1401](https://github.com/OpenAdaptAI/OpenAdapt/pull/1401)).
- Next-step hints repeat the `uvx` form when Flow runs from a uvx environment, so they reach the same version ([#1404](https://github.com/OpenAdaptAI/OpenAdapt/pull/1404)).
- API steps: secrets and tokens in JSON bodies and headers are withheld from network capture ([#1367](https://github.com/OpenAdaptAI/OpenAdapt/pull/1367)); fields bind by the step that typed them, not by equal values ([#1368](https://github.com/OpenAdaptAI/OpenAdapt/pull/1368)); record identifiers in URLs stay run parameters ([#1369](https://github.com/OpenAdaptAI/OpenAdapt/pull/1369)); a step whose span also wrote is refused ([#1370](https://github.com/OpenAdaptAI/OpenAdapt/pull/1370)); native form validation is enforced ([#1371](https://github.com/OpenAdaptAI/OpenAdapt/pull/1371)); an API step binds to the complete definition of the steps it replaces ([#1372](https://github.com/OpenAdaptAI/OpenAdapt/pull/1372)).
- A relabelled Save halts on the Save, not on the scroll before it ([#1337](https://github.com/OpenAdaptAI/OpenAdapt/pull/1337)); a self-closing popup click counts as delivered only when the step expects it ([#1321](https://github.com/OpenAdaptAI/OpenAdapt/pull/1321)).
- Pixel-path replays keep running across display scaling and ClearType ([#1286](https://github.com/OpenAdaptAI/OpenAdapt/pull/1286)); `emit`, `serve-execute`, bench and resume no longer assume a browser ([#1285](https://github.com/OpenAdaptAI/OpenAdapt/pull/1285)).
- The durable authority database is created owner-only before SQLite opens it ([#1363](https://github.com/OpenAdaptAI/OpenAdapt/pull/1363)).
- The agent CLI help states the approval-mode default and the agent approval tools ([#1238](https://github.com/OpenAdaptAI/OpenAdapt/pull/1238)).
- A save that was sent but not confirmed never resumes as a plain retry; the pause offers reconcile or an explicit single retry ([#1485](https://github.com/OpenAdaptAI/OpenAdapt/pull/1485)).
- A value typed whole in one step and inside longer text in another is reported as unlifted, and a canary that reuses run 1's values returns the draft to review ([#1465](https://github.com/OpenAdaptAI/OpenAdapt/pull/1465)).
- Record identity stays stable across the JSON baseline, so rows read back from UUID, decimal and datetime columns are not counted as new ([#1482](https://github.com/OpenAdaptAI/OpenAdapt/pull/1482)).
- An empty or not-found page in a separate-session read-back is indeterminate, not proof that a record is absent ([#1515](https://github.com/OpenAdaptAI/OpenAdapt/pull/1515), thanks @yunusarda-sudo).
- A binary SQL column (such as OpenEMR's `uuid`) is read as hex by `verify-run` and `scaffold-verifier` ([#1503](https://github.com/OpenAdaptAI/OpenAdapt/pull/1503)).
- Recording and replay follow a window by a stable handle after its title changes ([#1468](https://github.com/OpenAdaptAI/OpenAdapt/pull/1468)).
- `seal` works on a bundle certified by a qualification campaign ([#1453](https://github.com/OpenAdaptAI/OpenAdapt/pull/1453)); the approval gate classifies saves with the certifying policy, as the run gate does ([#1455](https://github.com/OpenAdaptAI/OpenAdapt/pull/1455)).
- Process workers always end their child process, even on failure ([#1498](https://github.com/OpenAdaptAI/OpenAdapt/pull/1498)).
- The `run --profile standard` examples name an execution surface ([#1525](https://github.com/OpenAdaptAI/OpenAdapt/pull/1525)). Synthetic referral last names in the OpenEMR benchmark are unique ([#1420](https://github.com/OpenAdaptAI/OpenAdapt/pull/1420), thanks @xiaofeilovecoding).
Loading
Loading