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
25 changes: 24 additions & 1 deletion openadapt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,17 @@ def _run_flow(argv: list[str]) -> None:
@click.option(
"--headed", is_flag=True, help="Show the browser while the tutorial runs."
)
def quickstart(out: Path, headed: bool) -> None:
@click.option(
"--break-it",
"break_it",
is_flag=True,
help=(
"After the verified run, rerun the same certified bundle against a "
"fault-injecting backend and watch the engine halt instead of "
"trusting the screen."
),
)
def quickstart(out: Path, headed: bool, break_it: bool) -> None:
"""Run a verified local tutorial against the bundled synthetic app.

This is the shortest path to a real OpenAdapt run. It uses the bundled
Expand All @@ -195,6 +205,8 @@ def quickstart(out: Path, headed: bool) -> None:
]
if headed:
argv.append("--headed")
if break_it:
argv.append("--break-it")

# The bundled tutorial contains only fixed synthetic data. Keep an
# installed-but-unconfigured privacy provider from blocking this known-safe
Expand Down Expand Up @@ -224,7 +236,18 @@ def quickstart(out: Path, headed: bool) -> None:
"The synthetic write was confirmed through a read-only system-of-record API."
)
click.echo("No model or Cloud call was enabled.")
if break_it:
click.echo(
"The rerun against the fault-injecting backend HALTED as designed: "
"the screen claimed success and the system of record disagreed."
)
click.echo(f"Caught-fault evidence: {root / 'run-broken' / 'REPORT.md'}")
click.echo(f"Inspect qualification gaps: openadapt flow lint {root / 'bundle'}")
if not break_it:
click.echo(
"Watch it catch a lie: openadapt quickstart --break-it --out "
f"{root}-break-it"
)
click.echo(
"See a fail-safe halt: openadapt flow replay "
f"{root / 'bundle'} --drift modal --run-dir {root}-halt"
Expand Down
18 changes: 9 additions & 9 deletions platform-manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_kind": "openadapt-platform-release-manifest",
"schema_version": "1.0.0",
"generated_at": "2026-08-02T16:33:44+00:00",
"generated_at": "2026-08-02T19:53:33+00:00",
"release_channel": "beta",
"components": {
"launcher": {
Expand All @@ -26,21 +26,21 @@
},
"flow": {
"package": "openadapt-flow",
"version": "1.28.0",
"version": "1.29.0",
"source": "pypi",
"requires_python": "<3.13,>=3.10",
"artifacts": [
{
"type": "bdist_wheel",
"filename": "openadapt_flow-1.28.0-py3-none-any.whl",
"url": "https://files.pythonhosted.org/packages/2b/ce/1a43d30411e6abd35ddfaad5fbf00321c14f0cf1082ebcaee7f993ec17b5/openadapt_flow-1.28.0-py3-none-any.whl",
"sha256": "4d156035ea411e3cbdbc40978d653d50727a7d8664646be62f7f9e95ba0c7202"
"filename": "openadapt_flow-1.29.0-py3-none-any.whl",
"url": "https://files.pythonhosted.org/packages/8f/ab/f05f65adb368a6135a32eb201e341e00e5ccc7334715d4381aad2e656c3a/openadapt_flow-1.29.0-py3-none-any.whl",
"sha256": "2c5f49199161fb2964bb43cfae2470fb79e5dbcb264e3031d6f8802ecb161a6a"
},
{
"type": "sdist",
"filename": "openadapt_flow-1.28.0.tar.gz",
"url": "https://files.pythonhosted.org/packages/f2/a7/9a109b155c11b5edfc2c3ed765858a976c7565f73c7f0c818a04c5ae34b8/openadapt_flow-1.28.0.tar.gz",
"sha256": "6e108f3469da20226427fee7a11378e067ca08c1fbbfcdbb4018ab9c3d142a8b"
"filename": "openadapt_flow-1.29.0.tar.gz",
"url": "https://files.pythonhosted.org/packages/a1/4f/53d31b2a8600a61e35ab9aa469e25591e327eb2301039c5e55f788044a82/openadapt_flow-1.29.0.tar.gz",
"sha256": "d4ba0fb0af915d8fbf642fdf0843524f04992e8b3080febfb618febe507311a7"
}
]
},
Expand Down Expand Up @@ -95,7 +95,7 @@
">=0.1.0"
],
"openadapt-flow": [
">=1.25.1,<2.0.0"
">=1.29.0,<2.0.0"
],
"openadapt-grounding": [
">=0.1.0"
Expand Down
16 changes: 8 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ classifiers = [
# All other capabilities (capture, ml, evals, ...) remain opt-in extras.
dependencies = [
"click>=8.0.0",
"openadapt-flow[hosted]>=1.25.1,<2.0.0",
"openadapt-flow[hosted]>=1.29.0,<2.0.0",
]

[project.optional-dependencies]
Expand All @@ -49,22 +49,22 @@ browser = [
# separately provisioned executable, not a Python-package dependency.
capture = [
"openadapt-capture>=1.0.4,<2.0.0",
"openadapt-flow[capture]>=1.25.1,<2.0.0",
"openadapt-flow[capture]>=1.29.0,<2.0.0",
]
# Replay substrate dependencies stay separate from capture: recording observes
# the human on the local interactive desktop, while replay may target a WAA
# agent, a native app, or a remote framebuffer.
windows = [
"openadapt-flow[windows]>=1.25.1,<2.0.0",
"openadapt-flow[windows]>=1.29.0,<2.0.0",
]
macos = [
"openadapt-flow[macos]>=1.25.1,<2.0.0; sys_platform == 'darwin'",
"openadapt-flow[macos]>=1.29.0,<2.0.0; sys_platform == 'darwin'",
]
linux = [
"openadapt-flow[linux]>=1.25.1,<2.0.0; sys_platform == 'linux'",
"openadapt-flow[linux]>=1.29.0,<2.0.0; sys_platform == 'linux'",
]
rdp = [
"openadapt-flow[rdp]>=1.25.1,<2.0.0",
"openadapt-flow[rdp]>=1.29.0,<2.0.0",
]
ml = [
"openadapt-ml>=0.2.0",
Expand All @@ -82,13 +82,13 @@ retrieval = [
"openadapt-retrieval>=0.1.0",
]
privacy = [
"openadapt-flow[privacy]>=1.25.1,<2.0.0",
"openadapt-flow[privacy]>=1.29.0,<2.0.0",
]
# `flow` now ships in the base install (see `dependencies` above). This
# extra is kept for backward compatibility so `pip install openadapt[flow]`
# and the `all` bundle still resolve.
flow = [
"openadapt-flow>=1.25.1,<2.0.0",
"openadapt-flow>=1.29.0,<2.0.0",
]
# Bundles
core = [
Expand Down
40 changes: 32 additions & 8 deletions tests/test_cli_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,30 @@ def test_quickstart_forwards_the_headed_tutorial_option(monkeypatch):
assert calls[0][-1] == "--headed"


def test_quickstart_forwards_the_break_it_option_and_names_the_evidence(
monkeypatch,
):
calls = []
monkeypatch.setattr(
"openadapt.cli._invoke_flow",
lambda argv: calls.append(list(argv)) or 0,
)

runner = CliRunner()
with runner.isolated_filesystem():
result = runner.invoke(
cli_main,
["quickstart", "--break-it", "--out", "break-run"],
)

assert result.exit_code == 0, result.output
assert len(calls) == 1
assert calls[0][0] == "tutorial"
assert calls[0][-1] == "--break-it"
assert "run-broken" in result.output
assert "HALTED" in result.output


def test_quickstart_restores_the_operator_scrub_setting(monkeypatch):
monkeypatch.setenv("OPENADAPT_FLOW_SCRUB", "auto")
monkeypatch.setattr("openadapt.cli._invoke_flow", lambda _argv: 0)
Expand Down Expand Up @@ -253,22 +277,22 @@ def test_launcher_flow_and_substrate_extras_metadata():
)["project"]
extras = metadata["optional-dependencies"]

assert metadata["dependencies"].count("openadapt-flow[hosted]>=1.25.1,<2.0.0") == 1
assert extras["flow"] == ["openadapt-flow>=1.25.1,<2.0.0"]
assert metadata["dependencies"].count("openadapt-flow[hosted]>=1.29.0,<2.0.0") == 1
assert extras["flow"] == ["openadapt-flow>=1.29.0,<2.0.0"]
assert extras["browser"] == ["playwright>=1.44"]
assert extras["privacy"] == ["openadapt-flow[privacy]>=1.25.1,<2.0.0"]
assert extras["privacy"] == ["openadapt-flow[privacy]>=1.29.0,<2.0.0"]
assert extras["capture"] == [
"openadapt-capture>=1.0.4,<2.0.0",
"openadapt-flow[capture]>=1.25.1,<2.0.0",
"openadapt-flow[capture]>=1.29.0,<2.0.0",
]
assert extras["windows"] == ["openadapt-flow[windows]>=1.25.1,<2.0.0"]
assert extras["windows"] == ["openadapt-flow[windows]>=1.29.0,<2.0.0"]
assert extras["macos"] == [
"openadapt-flow[macos]>=1.25.1,<2.0.0; sys_platform == 'darwin'"
"openadapt-flow[macos]>=1.29.0,<2.0.0; sys_platform == 'darwin'"
]
assert extras["linux"] == [
"openadapt-flow[linux]>=1.25.1,<2.0.0; sys_platform == 'linux'"
"openadapt-flow[linux]>=1.29.0,<2.0.0; sys_platform == 'linux'"
]
assert extras["rdp"] == ["openadapt-flow[rdp]>=1.25.1,<2.0.0"]
assert extras["rdp"] == ["openadapt-flow[rdp]>=1.29.0,<2.0.0"]
assert extras["all"] == [
"openadapt[browser,core,grounding,retrieval,privacy,flow,windows,rdp]",
"openadapt[macos]; sys_platform == 'darwin'",
Expand Down