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
37 changes: 11 additions & 26 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.4.0
# OpenAdapt: review brief for openadapt-flow 2.4.1

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 @@ -2042,34 +2042,19 @@ automation into an independently certified transaction system.

---

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

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

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.
Flow runs without its benchmark package, a pinned config with Windows line endings is accepted, and several checks halt where 2.4.0 could act on the wrong row or pass a weaker check.

### Features
### Fixes

- 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)).
- On Windows, `--config-sha256` now hashes the config file's exact bytes. A config with CRLF line endings used to be read in text mode, so its hash never matched and the run was refused with `deployment_config_changed` ([#1593](https://github.com/OpenAdaptAI/OpenAdapt/pull/1593)).
- Product code no longer imports `openadapt_flow.benchmark`. An install or frozen build without the benchmark package, such as Desktop's engine, can now load the JIT adapters, annotation, narration rules and the qualification proposer. The default model, scroll step and API key loader moved to `openadapt_flow.anthropic_defaults`; `openadapt_flow.benchmark.agent_baseline` still exports them ([#1594](https://github.com/OpenAdaptAI/OpenAdapt/pull/1594)).
- Worklists built from plain `div` rows, CSS grid rows or cards are treated as rows. Teach records each row's identity, and replay halts when rows move or look alike, instead of clicking a button by its position (`#open-0`) on another record. A twin row seen at teach time marks the identity ambiguous, and a row nothing can read halts before a write (`identity_uncounted`) ([#1569](https://github.com/OpenAdaptAI/OpenAdapt/pull/1569)).
- The fault gate admits a record check only when it catches every fault class it claims. Two new classes write outside the table the check reads (`other_table`, `side_write`), and a check must claim both `delta` and `frame`. A check that reads one table of a larger store is no longer admitted, so VERIFIED is issued less often, never more. The receipt lists each class as killed, missed, untestable, not applicable or missing ([#1539](https://github.com/OpenAdaptAI/OpenAdapt/pull/1539)).

### Fixes
### Features

- 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).
- A key that changes nothing visible, such as a Tab onto an icon button or an ArrowDown that highlights an option, can now be checked: the new `focus_on` postcondition requires the focused element to have the recorded identity and to be the only element with it. The compiler adds it only for an element with a role and a non-empty accessible name; an element without them gets no check and stays unverified ([#1579](https://github.com/OpenAdaptAI/OpenAdapt/pull/1579), [#1595](https://github.com/OpenAdaptAI/OpenAdapt/pull/1595)).
15 changes: 15 additions & 0 deletions packages/flow/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@

<!-- version list -->

## v2.4.1 (2026-10-28)

Flow runs without its benchmark package, a pinned config with Windows line endings is accepted, and several checks halt where 2.4.0 could act on the wrong row or pass a weaker check.

### Fixes

- On Windows, `--config-sha256` now hashes the config file's exact bytes. A config with CRLF line endings used to be read in text mode, so its hash never matched and the run was refused with `deployment_config_changed` ([#1593](https://github.com/OpenAdaptAI/OpenAdapt/pull/1593)).
- Product code no longer imports `openadapt_flow.benchmark`. An install or frozen build without the benchmark package, such as Desktop's engine, can now load the JIT adapters, annotation, narration rules and the qualification proposer. The default model, scroll step and API key loader moved to `openadapt_flow.anthropic_defaults`; `openadapt_flow.benchmark.agent_baseline` still exports them ([#1594](https://github.com/OpenAdaptAI/OpenAdapt/pull/1594)).
- Worklists built from plain `div` rows, CSS grid rows or cards are treated as rows. Teach records each row's identity, and replay halts when rows move or look alike, instead of clicking a button by its position (`#open-0`) on another record. A twin row seen at teach time marks the identity ambiguous, and a row nothing can read halts before a write (`identity_uncounted`) ([#1569](https://github.com/OpenAdaptAI/OpenAdapt/pull/1569)).
- The fault gate admits a record check only when it catches every fault class it claims. Two new classes write outside the table the check reads (`other_table`, `side_write`), and a check must claim both `delta` and `frame`. A check that reads one table of a larger store is no longer admitted, so VERIFIED is issued less often, never more. The receipt lists each class as killed, missed, untestable, not applicable or missing ([#1539](https://github.com/OpenAdaptAI/OpenAdapt/pull/1539)).

### Features

- A key that changes nothing visible, such as a Tab onto an icon button or an ArrowDown that highlights an option, can now be checked: the new `focus_on` postcondition requires the focused element to have the recorded identity and to be the only element with it. The compiler adds it only for an element with a role and a non-empty accessible name; an element without them gets no check and stays unverified ([#1579](https://github.com/OpenAdaptAI/OpenAdapt/pull/1579), [#1595](https://github.com/OpenAdaptAI/OpenAdapt/pull/1595)).

## v2.4.0 (2026-10-25)

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.
Expand Down
2 changes: 1 addition & 1 deletion packages/flow/openadapt_flow/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""openadapt-flow: record, compile, replay deterministically, heal on drift."""

__version__ = "2.4.0"
__version__ = "2.4.1"

from openadapt_flow.ir import ( # noqa: F401
ActionKind,
Expand Down
2 changes: 1 addition & 1 deletion packages/flow/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "openadapt-flow"
version = "2.4.0"
version = "2.4.1"
description = "Compile demonstrated GUI workflows into deterministic local replay with governed repair and refusal"
readme = "README.md"
license = { text = "MIT" }
Expand Down
2 changes: 1 addition & 1 deletion packages/flow/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading