diff --git a/README.md b/README.md index e7d09e185..4d7f42414 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,9 @@ [![Discord](https://img.shields.io/badge/Discord-community-5865F2?logo=discord&logoColor=white)](https://discord.gg/yF527cQbDG) Show OpenAdapt a task once. It compiles your demonstration into a program that -runs the task again without a model in the loop, and it checks the result -against the system of record before it calls the run a success. +runs the task again without a generative-model API in the control loop. Before +a governed run reports `VERIFIED`, it checks every declared effect at the +required evidence tier. This is the installer and the `openadapt` command. The compiler and the runtime live in [`openadapt-flow`](https://github.com/OpenAdaptAI/openadapt-flow), and @@ -79,7 +80,7 @@ application boundary, its action risks, its identities, its effect verifiers, its fault cases, and its deployment policy. Start with the [five-minute walkthrough](https://docs.openadapt.ai/get-started/). -## Record your own workflow +## Record and rehearse one workflow ```bash openadapt flow record --backend web --url https://your-app.example --out rec @@ -87,6 +88,13 @@ openadapt flow compile rec --out bundle --name my-workflow openadapt flow replay bundle --url https://your-app.example --run-dir run ``` +These commands record one browser surface and run a permissive local rehearsal; +they do not certify the bundle. One bundle uses one execution surface and does +not switch between browser, native, RDP, or Citrix backends. For work that +crosses applications, qualify each boundary and handoff separately. The +[`openadapt-flow` README](https://github.com/OpenAdaptAI/openadapt-flow#record-and-rehearse-your-workflow) +describes the current boundary and the governed run path. + Native and remote workflows never start or download Chromium. Install only the capability you need: @@ -181,8 +189,8 @@ paywalled. | Evidence | Result | |---|---| -| Public OpenEMR reference workflow | 19/20 effect-verified runs at 39.2s median with 0 model calls; run 20 was a safe halt under the corrected saved-row oracle | -| Heart-care RVU audit, customer deployment | About $75,000/year in recovered billables, and several hours of monthly audit work | +| Public OpenEMR field test | 19/20 attempts passed the saved-row OCR check at 39.2s median; the compiled arm recorded 0 model API calls, and run 20 halted safely | +| Founding-team heart-care RVU audit | About $75,000/year in estimated recovered billables, and several hours of monthly audit work | Both belong to their named task and environment. Qualifying a new workflow is what decides what can be claimed about it. Method and comparison: @@ -202,18 +210,10 @@ self-service API. Partner contract and qualification process: [the Execute guide](https://docs.openadapt.ai/commercial/oem-brief/). -> **Built for qualified production workflows.** -> Current OpenAdapt admission state: **Not actively admitted.** The exact signed -> ledger has no active admission for this target. The path to Production requires -> active signed admissions for all seven product targets and an active signed, -> expiring, revocable workflow admission for the exact compiled workflow version. -> The workflow admission binds the organization and workflow identity; bundle -> version and digest; admitted runtime release; application and environment; input, -> action, identity, effect, and policy contracts; evidence authority; and its issue, -> expiry, and revocation state. Qualification requires at least three trials for -> each task and condition. A closed result schema must report silent incorrect -> success and over-halt. Any bound change requires a new qualification. -> [Check the live signed Production record](https://docs.openadapt.ai/production-lifecycle.json). +Production is per qualified workflow. +A workflow is Production only with an active signed, expiring, revocable +admission for that exact compiled version, application, and environment. +[Check the live signed Production record](https://docs.openadapt.ai/production-lifecycle.json). ## Where the code is diff --git a/scripts/render_readme_maturity.py b/scripts/render_readme_maturity.py index 4494c9e25..3b75496d1 100644 --- a/scripts/render_readme_maturity.py +++ b/scripts/render_readme_maturity.py @@ -459,18 +459,10 @@ def _qualification_block() -> str: return "\n".join( [ BEGIN, - "> **Built for qualified production workflows.**", - "> Current OpenAdapt admission state: **Not actively admitted.** The exact signed", - "> ledger has no active admission for this target. The path to Production requires", - "> active signed admissions for all seven product targets and an active signed,", - "> expiring, revocable workflow admission for the exact compiled workflow version.", - "> The workflow admission binds the organization and workflow identity; bundle", - "> version and digest; admitted runtime release; application and environment; input,", - "> action, identity, effect, and policy contracts; evidence authority; and its issue,", - "> expiry, and revocation state. Qualification requires at least three trials for", - "> each task and condition. A closed result schema must report silent incorrect", - "> success and over-halt. Any bound change requires a new qualification.", - f"> [Check the live signed Production record]({LIVE_RECORD_URL}).", + "Production is per qualified workflow.", + "A workflow is Production only with an active signed, expiring, revocable", + "admission for that exact compiled version, application, and environment.", + f"[Check the live signed Production record]({LIVE_RECORD_URL}).", END, ] ) @@ -508,8 +500,7 @@ def render_block( missing = ", ".join(f"`{target}`" for target in missing_targets) combined_state = [ "> This target record does not establish combined-product Production. The combined", - "> product is **Not actively admitted** in this snapshot because required target", - f"> admissions are missing: {missing}.", + f"> product is missing these required target admissions in this snapshot: {missing}.", ] else: combined_state = [ diff --git a/tests/test_readme_maturity.py b/tests/test_readme_maturity.py index ccfaa1bac..81f0d24d9 100644 --- a/tests/test_readme_maturity.py +++ b/tests/test_readme_maturity.py @@ -173,16 +173,14 @@ def test_empty_registry_uses_positive_qualification_contract(self) -> None: block = MODULE.render_block(projection, {}, now=NOW) self.assertIn(MODULE.LIVE_RECORD_URL, block) - self.assertIn("Current OpenAdapt admission state", block) - self.assertIn("Not actively admitted", block) - self.assertIn("active signed admissions for all seven product targets", block) - self.assertIn("expiring, revocable workflow admission", block) - self.assertIn("exact compiled workflow version", block) - self.assertIn("at least three trials", block) - self.assertIn("each task and condition", block) - self.assertIn("closed result schema", block) - self.assertIn("silent incorrect", block) - self.assertIn("success and over-halt", block) + self.assertIn("Production is per qualified workflow", block) + self.assertIn("exact compiled version", block) + self.assertIn("expiring, revocable", block) + self.assertNotIn("Production status", block) + self.assertNotIn("No current signed admission", block) + self.assertNotIn("seven product targets", block) + self.assertNotIn("at least three trials", block) + self.assertNotIn("silent incorrect", block) self.assertNotIn("Beta", block) self.assertNotIn("not Production", block) @@ -196,10 +194,9 @@ def test_an_active_flow_admission_does_not_admit_the_launcher(self) -> None: ) self.assertNotIn(flow["admission_id"], block) - self.assertIn("Current OpenAdapt admission state", block) - self.assertIn("Not actively admitted", block) - self.assertIn("active signed admissions for all seven product targets", block) - self.assertIn("expiring, revocable workflow admission", block) + self.assertIn("Production is per qualified workflow", block) + self.assertNotIn("Production status", block) + self.assertNotIn("No current signed admission", block) def test_active_launcher_renders_only_a_durable_registry_record(self) -> None: launcher = _admission(target="openadapt", sequence=1) @@ -214,8 +211,7 @@ def test_active_launcher_renders_only_a_durable_registry_record(self) -> None: self.assertIn(launcher["issued_at"], block) self.assertIn(launcher["expires_at"], block) self.assertIn("historical record", block) - self.assertIn("Not actively admitted", block) - self.assertIn("admissions are missing", block) + self.assertIn("missing these required target admissions", block) self.assertIn("`flow`", block) self.assertNotIn("OpenAdapt is Production", block) @@ -231,7 +227,7 @@ def test_openadapt_only_admission_does_not_imply_combined_production(self) -> No self.assertIn("OpenAdapt target admission record", block) self.assertIn("does not establish combined-product Production", block) - self.assertIn("product is **Not actively admitted**", block) + self.assertIn("missing these required target admissions", block) for target in MODULE.EXPECTED_TARGETS - {"openadapt"}: self.assertIn(f"`{target}`", block)