diff --git a/data/compare/browser-agents.json b/data/compare/browser-agents.json new file mode 100644 index 0000000..e4da28c --- /dev/null +++ b/data/compare/browser-agents.json @@ -0,0 +1,163 @@ +{ + "slug": "browser-agents", + "competitor": "browser-use agents (Workflow Use and Browser Use)", + "positioningSummary": + "Workflow Use and Browser Use are the fastest-moving open-source stack for web tasks, and their deterministic-rerun direction validates demonstration-based authoring. OpenAdapt targets repeated consequential workflows that cross beyond the browser and must end in an independently verified business result.", + "dimensions": [ + { + "id": "determinism-on-drift", + "label": "Determinism when interfaces drift", + "openadapt": + "Compiled replay resolves its target from retained evidence at run time; drift it was never shown halts instead of guessing, and repair is governed rather than improvised.", + "them": + "Workflow Use records browser interactions into deterministic workflows with variables; when a step fails it falls back to the Browser Use agent - a model re-reasons the step. The project describes itself as in very early development and not recommended for production.", + "sources": [ + { + "label": "Workflow Use README: deterministic workflows with agent fallback", + "url": "https://github.com/browser-use/workflow-use/blob/main/README.md" + } + ] + }, + { + "id": "cost-per-run", + "label": "Cost per run", + "openadapt": + "Healthy runs are local and make zero model calls at $0 model cost on the MIT runtime; model spend is reserved for compilation and reviewable repair.", + "them": + "Browser Use Cloud advertises deterministic rerun of a cached script with no LLM at up to 99% lower cost, agent runs measured at $0.17 per solved task on its internal benchmark, hosted model tokens from $0.24/1M input and $1.44/1M output, plus $0.02 per browser-hour.", + "sources": [ + { + "label": "Browser Use developer index: pricing and benchmarks", + "url": "https://browser-use.com/" + }, + { + "label": "Browser Use docs: deterministic rerun", + "url": "https://docs.browser-use.com/cloud/agent/cache-script" + }, + { + "label": "Frappe Lending benchmark: $0 model cost", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/tree/main/benchmark/frappe_lending" + } + ] + }, + { + "id": "verification-of-effects", + "label": "Verification of business effects", + "openadapt": + "Success is judged out of band against the system of record (SQL, REST readback, table-delta audit, file arrival); the acting session cannot certify its own result.", + "them": + "Both stacks judge success in band: the session that acted reports completion. Workflow Use offers progress events, recordings, and observability; no independent read-back of a business system of record is part of the published loop.", + "sources": [ + { + "label": "Browser Use developer index: recordings and observability", + "url": "https://browser-use.com/" + } + ] + }, + { + "id": "halting-behavior", + "label": "Halting behavior", + "openadapt": + "Ambiguity or wrong identity halts before acting; a refuted effect ends the run HALTED with evidence preserved for reconciliation - never a silent third state.", + "them": + "Failure handling is retry-or-fallback oriented: Workflow Use's advertised roadmap item is improving LLM fallback when a step fails, which hands control back to the model rather than stopping for review.", + "sources": [ + { + "label": "Workflow Use README: roadmap and fallback", + "url": "https://github.com/browser-use/workflow-use/blob/main/README.md" + } + ] + }, + { + "id": "data-locality", + "label": "Data locality", + "openadapt": + "The runtime is MIT licensed and local-first; screenshots-may-leave-box is an explicit per-run flag observed false in the published demo evidence pack.", + "them": + "The open-source libraries can run locally against your own Chromium, but the managed path routes tasks, tokens, and browser time through Browser Use Cloud infrastructure.", + "sources": [ + { + "label": "Browser Use developer index: cloud vs open source", + "url": "https://browser-use.com/" + }, + { + "label": "mockmed-triage-v3 pack: egress observed false", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/public-demo/evidence-packs/mockmed-triage-v3/manifest.json" + } + ] + }, + { + "id": "scope", + "label": "Scope: browser, desktop, RDP/Citrix", + "openadapt": + "Browser in production today plus native desktop and external-lane remote execution for managed RDP/Citrix estates, each surface carrying published acceptance evidence.", + "them": + "Web only: Workflow Use records browser sessions and Browser Use drives managed or local Chromium; desktop applications and remote desktop surfaces are outside the published scope.", + "sources": [ + { + "label": "Workflow Use README: browser recording focus", + "url": "https://github.com/browser-use/workflow-use/blob/main/README.md" + }, + { + "label": "OpenAdapt qualification evidence per surface", + "url": "https://docs.openadapt.ai/get-started/what-works-today/" + } + ] + } + ], + "strengths": [ + { + "text": + "Fastest setup for web tasks: point a Browser Use agent at a URL and useful behavior often emerges in minutes; Workflow Use converts one recording into a reusable workflow file.", + "source": null + }, + { + "text": + "Deterministic rerun without an LLM: Browser Use Cloud advertises cached-script reruns at up to 99% lower cost than an agent run.", + "source": { + "label": "Browser Use docs: deterministic rerun", + "url": "https://docs.browser-use.com/cloud/agent/cache-script" + } + }, + { + "text": + "Published benchmark results: 82% of 106 internal Bench Hard tasks solved at $0.17 per solved task and 98% across Online-Mind2Web.", + "source": { + "label": "Browser Use developer index: benchmarks", + "url": "https://browser-use.com/" + } + }, + { + "text": + "Active open-source ecosystem iterating quickly, with managed cloud-browser infrastructure ($0.02/browser-hour) if you do not want to run browsers yourself.", + "source": { + "label": "Browser Use developer index: browser infrastructure", + "url": "https://browser-use.com/" + } + } + ], + "faq": [ + { + "question": "Is Workflow Use production ready?", + "answer": + "Not by its own description: the README states the project is in very early development and recommends against production use. It is a strong signal of where demonstration-based authoring is heading.", + "sources": [ + { + "label": "Workflow Use README", + "url": "https://github.com/browser-use/workflow-use/blob/main/README.md" + } + ] + }, + { + "question": "What does OpenAdapt add over deterministic browser replay?", + "answer": + "Out-of-band verification against the system of record, explicit VERIFIED-or-HALTED outcomes with preserved evidence, identity checks before consequential actions, and execution beyond the browser - native desktop and zero-install remote lanes - with published qualification evidence per surface.", + "sources": [ + { + "label": "OpenAdapt qualification evidence", + "url": "https://docs.openadapt.ai/get-started/what-works-today/" + } + ] + } + ] +} diff --git a/data/compare/computer-use-agents.json b/data/compare/computer-use-agents.json new file mode 100644 index 0000000..95b81f4 --- /dev/null +++ b/data/compare/computer-use-agents.json @@ -0,0 +1,156 @@ +{ + "slug": "computer-use-agents", + "competitor": "computer-use agents (OpenAI and Anthropic)", + "positioningSummary": + "Computer-use models from OpenAI and Anthropic point a frontier model at the screen and reason their way through a task; that flexibility is real and improving fast. OpenAdapt compiles a demonstration once and replays it deterministically, reserving models for compilation and reviewable repair.", + "dimensions": [ + { + "id": "determinism-on-drift", + "label": "Determinism when interfaces drift", + "openadapt": + "Healthy runs replay the same compiled steps deterministically with zero model calls; drift outside what was demonstrated halts for a governed decision.", + "them": + "Every run re-reasons from screenshots: OpenAI's loop sends a screenshot back after each action batch so the model can plan the next step, which adapts to novelty but makes each run non-deterministic by construction.", + "sources": [ + { + "label": "OpenAI computer use guide: screenshot-action loop", + "url": "https://platform.openai.com/docs/guides/tools-computer-use" + } + ] + }, + { + "id": "cost-per-run", + "label": "Cost per run", + "openadapt": + "$0 model cost per healthy run on the MIT runtime - published trials across MockMed triage (18 trials), Frappe Lending (6/6), and openIMIS eligibility (6 runs) all recorded zero model calls.", + "them": + "Metered per model turn: screenshots are billed as image inputs every step. Claude's computer-use toolset definition alone adds about 4,500 input tokens to a request before any screenshot; OpenAI recommends original-detail screenshots each turn for click accuracy.", + "sources": [ + { + "label": "Claude computer use tool: pricing", + "url": "https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool" + }, + { + "label": "OpenAI computer use guide: screenshot detail guidance", + "url": "https://platform.openai.com/docs/guides/tools-computer-use" + }, + { + "label": "OpenAdapt published trials with 0 model calls", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/public-demo/evidence-packs/mockmed-triage-v3/manifest.json" + } + ] + }, + { + "id": "verification-of-effects", + "label": "Verification of business effects", + "openadapt": + "Every consequential run ends VERIFIED or HALTED based on an independent check of the system of record, with silent incorrect success counted as a tracked failure metric in published evidence.", + "them": + "The acting model reports task completion from what it sees; providers direct developers to keep a human in the loop for high-impact actions rather than providing an out-of-band business-effect oracle.", + "sources": [ + { + "label": "OpenAI computer use guide: human-in-the-loop safeguards", + "url": "https://platform.openai.com/docs/guides/tools-computer-use" + } + ] + }, + { + "id": "halting-behavior", + "label": "Halting behavior", + "openadapt": + "Halting is a designed outcome: ambiguity, wrong identity, or a refuted effect stops the run with preserved evidence instead of proceeding or retrying blindly.", + "them": + "The model keeps attempting until it believes the task is done or its budget is exhausted; stopping criteria are prompt- and harness-level, not contract-level.", + "sources": [ + { + "label": "OpenAI computer use guide: agent loop semantics", + "url": "https://platform.openai.com/docs/guides/tools-computer-use" + } + ] + }, + { + "id": "data-locality", + "label": "Data locality", + "openadapt": + "Runs execute locally inside your boundary; egress is an explicit observed flag (false in the published demo pack), and Claude computer use is documented as ZDR eligible when your application controls storage.", + "them": + "Screen content leaves the machine to the model provider on every step: OpenAI's reference loop ships screenshots to the API each action batch, and Anthropic bills those screenshots as image input under standard API data handling.", + "sources": [ + { + "label": "Claude computer use tool: data retention and ZDR", + "url": "https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool" + }, + { + "label": "mockmed-triage-v3 pack: off-box egress observed false", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/public-demo/evidence-packs/mockmed-triage-v3/artifacts/cases/representative/trial-01/outcome.json" + } + ] + }, + { + "id": "scope", + "label": "Scope: browser, desktop, RDP/Citrix", + "openadapt": + "Browser in production today plus native desktop and external-lane remote execution into managed RDP/Citrix estates, with published acceptance evidence per surface.", + "them": + "Any UI a screenshot can describe, including desktops inside VMs or containers the harness controls; consumer agents such as Operator extend the same approach to end users.", + "sources": [ + { + "label": "OpenAI computer use guide: browser and VM harnesses", + "url": "https://platform.openai.com/docs/guides/tools-computer-use" + } + ] + } + ], + "strengths": [ + { + "text": + "Genuine flexibility on novel, one-off, or loosely specified tasks with no authoring step at all.", + "source": null + }, + { + "text": + "They generalize across unfamiliar interfaces, recovering from situations nobody anticipated in advance, and improve with every model generation without changes to your workflow definitions.", + "source": null + }, + { + "text": + "A plain-language instruction is the whole interface; OpenAI documents harness shapes from built-in loops to code-execution environments mixing visual and programmatic interaction.", + "source": { + "label": "OpenAI computer use guide: integration paths", + "url": "https://platform.openai.com/docs/guides/tools-computer-use" + } + }, + { + "text": + "Anthropic provides a reference implementation with a web UI, Docker container, example tools, and an agent loop to get started quickly.", + "source": { + "label": "Claude computer use tool: quick start", + "url": "https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool" + } + } + ], + "faq": [ + { + "question": "Are computer-use agents and OpenAdapt rivals?", + "answer": + "They are complementary. Agent providers themselves recommend isolated environments and human oversight for high-impact actions; OpenAdapt uses models too - at compile and repair time - while healthy runs replay deterministically with zero model calls.", + "sources": [ + { + "label": "OpenAI computer use guide: safeguards", + "url": "https://platform.openai.com/docs/guides/tools-computer-use" + } + ] + }, + { + "question": "Which should run the same workflow a thousand times?", + "answer": + "When correctness matters, replay a verified program: OpenAdapt's published evidence counts verified outcomes, expected halts, and silent incorrect successes per workflow - for example 18 MockMed triage trials with 0 model calls and 0 silent incorrect successes - instead of re-reasoning the task on every run.", + "sources": [ + { + "label": "mockmed-triage-v3 evidence pack", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/public-demo/evidence-packs/mockmed-triage-v3/manifest.json" + } + ] + } + ] +} diff --git a/data/compare/power-automate.json b/data/compare/power-automate.json new file mode 100644 index 0000000..3b4a24d --- /dev/null +++ b/data/compare/power-automate.json @@ -0,0 +1,158 @@ +{ + "slug": "power-automate", + "competitor": "Microsoft Power Automate", + "positioningSummary": + "Power Automate is the default automation layer of the Microsoft ecosystem and is very hard to beat there on integration and per-seat price. OpenAdapt is designed for the non-API last mile where a wrong write matters and the result must be verified against the system of record.", + "dimensions": [ + { + "id": "determinism-on-drift", + "label": "Determinism when interfaces drift", + "openadapt": + "Compiled replay is deterministic with zero model calls on healthy runs; undemonstrated states halt, and repairs pass through governed re-resolution before a new version deploys.", + "them": + "Desktop flows replay recorded UI steps deterministically; cloud flows are deterministic API orchestrations. Drift handling relies on standard error handling and retry configuration rather than evidence-based re-resolution.", + "sources": [ + { + "label": "Power Automate plans: desktop flows (RPA)", + "url": "https://www.microsoft.com/en-us/power-platform/products/power-automate/pricing" + } + ] + }, + { + "id": "cost-per-run", + "label": "Cost per run", + "openadapt": + "The local runtime carries no license fee and healthy runs make zero model calls; published trials recorded $0 model cost per run.", + "them": + "Published list pricing: Premium $15.00 user/month, Process $150.00 bot/month for unattended desktop flows, Hosted Process $215.00 bot/month including a Microsoft-hosted Azure VM (paid yearly). A bot executes one unattended run at a time.", + "sources": [ + { + "label": "Power Automate pricing page", + "url": "https://www.microsoft.com/en-us/power-platform/products/power-automate/pricing" + }, + { + "label": "Frappe Lending benchmark: $0 model cost", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/tree/main/benchmark/frappe_lending" + } + ] + }, + { + "id": "verification-of-effects", + "label": "Verification of business effects", + "openadapt": + "Every consequential run ends VERIFIED or HALTED based on an out-of-band check of the system of record - REST readback, SQL, table-delta audit, or file arrival - never the acting session's own report.", + "them": + "Cloud flows surface run history and error details in the Power Platform admin center; Dataverse stores the data flows act on. Verification of a desktop flow's business effect is typically expressed as configured assertions or downstream checks the builder authors.", + "sources": [ + { + "label": "Power Automate pricing: admin and capacity features", + "url": "https://www.microsoft.com/en-us/power-platform/products/power-automate/pricing" + } + ] + }, + { + "id": "halting-behavior", + "label": "Halting behavior", + "openadapt": + "Ambiguity halts before acting; a refuted effect halts after acting without blind retry, classifying delivery as uncertain for operator reconciliation.", + "them": + "Desktop flows support configurable error handling, retries, and timeouts defined by the flow author; unattended runs proceed under the machine/bot license without a human unless the flow requests one.", + "sources": [ + { + "label": "Power Automate pricing: attended vs unattended desktop flows", + "url": "https://www.microsoft.com/en-us/power-platform/products/power-automate/pricing" + } + ] + }, + { + "id": "data-locality", + "label": "Data locality", + "openadapt": + "Execution is local-first and customer-controlled: recordings, bundles, and evidence can remain inside your boundary on an inspectable MIT runtime.", + "them": + "Runs ride Microsoft-hosted infrastructure; the Hosted Process tier explicitly places the automation VM on Azure-managed infrastructure, and capacities pool at the tenant level in Dataverse.", + "sources": [ + { + "label": "Power Automate pricing: Hosted Process plan", + "url": "https://www.microsoft.com/en-us/power-platform/products/power-automate/pricing" + } + ] + }, + { + "id": "scope", + "label": "Scope: browser, desktop, RDP/Citrix", + "openadapt": + "Browser in production today, native desktop via accessibility plus visual evidence, and an external zero-install lane into managed RDP/Citrix estates qualified per customer before consequential use.", + "them": + "Deep Microsoft 365 coverage plus hundreds of prebuilt connectors for API-first work; desktop RPA covers Windows applications, with remote scenarios handled through the hosted VM tier.", + "sources": [ + { + "label": "OpenAdapt qualification evidence per surface", + "url": "https://docs.openadapt.ai/get-started/what-works-today/" + }, + { + "label": "Power Automate pricing: connectors and hosted VM rows", + "url": "https://www.microsoft.com/en-us/power-platform/products/power-automate/pricing" + } + ] + } + ], + "strengths": [ + { + "text": + "Premium per-user pricing starts around $15.00 user/month paid yearly, which makes broad light automation inexpensive across many seats.", + "source": { + "label": "Power Automate pricing: Premium plan", + "url": "https://www.microsoft.com/en-us/power-platform/products/power-automate/pricing" + } + }, + { + "text": + "Unattended automation scales through Process ($150.00 bot/month) and Hosted Process ($215.00 bot/month with a Microsoft-hosted Azure VM), both paid yearly.", + "source": { + "label": "Power Automate pricing: Process plans", + "url": "https://www.microsoft.com/en-us/power-platform/products/power-automate/pricing" + } + }, + { + "text": + "Native integration with Microsoft 365, Dataverse entitlements pooled at the tenant level, and centralized administration through the Power Platform admin center.", + "source": { + "label": "Power Automate pricing: included features", + "url": "https://www.microsoft.com/en-us/power-platform/products/power-automate/pricing" + } + }, + { + "text": + "Process mining is available as a first-class add-on ($5,000 tenant/month) for discovering what to automate.", + "source": { + "label": "Power Automate pricing: Process Mining add-on", + "url": "https://www.microsoft.com/en-us/power-platform/products/power-automate/pricing" + } + } + ], + "faq": [ + { + "question": "If a supported connector reaches my system, which tool should I use?", + "answer": + "Use the connector. OpenAdapt exists for the UI-only remainder where no practical API exists and correctness has to be proved against the system of record rather than assumed.", + "sources": [ + { + "label": "OpenAdapt comparison guide", + "url": "https://openadapt.ai/compare/power-automate" + } + ] + }, + { + "question": "How does per-run verification differ?", + "answer": + "OpenAdapt's published trials verify writes out of band - for example 3/3 OpenEMR patient-record runs confirmed by REST readback agreeing with direct SQL plus a non-target delta audit, with 0 model calls. Desktop-flow runs report their own execution status; independent system-of-record confirmation is not part of the published plan features.", + "sources": [ + { + "label": "Reference qualification results", + "url": "https://app.openadapt.ai/demo" + } + ] + } + ] +} diff --git a/data/compare/uipath.json b/data/compare/uipath.json new file mode 100644 index 0000000..730be7e --- /dev/null +++ b/data/compare/uipath.json @@ -0,0 +1,158 @@ +{ + "slug": "uipath", + "competitor": "UiPath", + "positioningSummary": + "UiPath is the most mature enterprise RPA platform, and for fleet-scale automation programs it is a strong default. OpenAdapt is designed for the narrower problem of repeated consequential GUI transactions that must end in an independently verified business result.", + "dimensions": [ + { + "id": "determinism-on-drift", + "label": "Determinism when interfaces drift", + "openadapt": + "A compiled workflow replays deterministically with zero model calls on healthy runs; drift it was never shown halts instead of guessing, and repair goes through governed, reviewable re-resolution.", + "them": + "Studio workflows replay deterministically; when UI changes break selectors, UiPath's Enterprise tier offers the Healing Agent, which suggests fixes and heals UI issues at runtime (available for purchase).", + "sources": [ + { + "label": "UiPath plans and pricing: Healing Agent", + "url": "https://www.uipath.com/pricing" + } + ] + }, + { + "id": "cost-per-run", + "label": "Cost per run", + "openadapt": + "The local runtime is MIT licensed with no per-run license fee: healthy runs make zero model calls at $0 model cost, as measured in the published Frappe Lending trials.", + "them": + "License-based pricing: Automation Cloud Basic starts at $25 per month for individuals and small teams; Standard and Enterprise are quoted by sales, and users/robots may require additional licenses. No per-run price is published.", + "sources": [ + { + "label": "UiPath plans and pricing", + "url": "https://www.uipath.com/pricing" + }, + { + "label": "Frappe Lending benchmark: 0 model calls, $0 model cost", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/tree/main/benchmark/frappe_lending" + } + ] + }, + { + "id": "verification-of-effects", + "label": "Verification of business effects", + "openadapt": + "Success is established out of band - read-only API reads, SQL queries, table-delta audits, or file checks against the system of record - and every run ends VERIFIED or HALTED with preserved evidence.", + "them": + "Orchestrator provides centralized audit trails, search, filter, and export of audit events, and queue-based transaction status. The acting session's own success signals remain the primary in-band check; an independent read-back of the business system of record is not part of the published core loop.", + "sources": [ + { + "label": "UiPath pricing comparison: audit and governance features", + "url": "https://www.uipath.com/pricing" + } + ] + }, + { + "id": "halting-behavior", + "label": "Halting behavior", + "openadapt": + "Ambiguity, wrong identity, or a refuted effect stops the run before or after the consequential action with a preserved halt report; uncertain delivery is classified for reconciliation rather than retried blindly.", + "them": + "Unattended robots are designed to run task-heavy, long-running processes without human supervision; attended robots put the human in the loop. Queue items expose retry and exception statuses for operators.", + "sources": [ + { + "label": "UiPath pricing comparison: robot limits descriptions", + "url": "https://www.uipath.com/pricing" + } + ] + }, + { + "id": "data-locality", + "label": "Data locality", + "openadapt": + "Recordings, bundles, and evidence stay inside your boundary by design: local execution is the default path, and screenshots-may-leave-box is an explicit per-run flag observed false in the published demo pack.", + "them": + "Strong enterprise options: self-hosted deployment including air-gapped installs, bring-your-own encryption keys and credential vaults (Enterprise), and opt-out of data collection (Standard and above). Basic-tier cloud hosting is Europe-region only.", + "sources": [ + { + "label": "UiPath plans and pricing: deployment and governance rows", + "url": "https://www.uipath.com/pricing" + } + ] + }, + { + "id": "scope", + "label": "Scope: browser, desktop, RDP/Citrix", + "openadapt": + "Browser runs in production today; native desktop through accessibility plus visual evidence; managed remote estates through an external zero-install lane qualified against a stand-in and a real FreeRDP round trip, with real ICA/HDX qualified per customer before consequential use.", + "them": + "Broadest published surface coverage in the market: web, desktop, Citrix virtual desktops, SAP, and APIs, with a very large activity library and mature Orchestrator fleet management.", + "sources": [ + { + "label": "OpenAdapt qualification evidence per surface", + "url": "https://docs.openadapt.ai/get-started/what-works-today/" + }, + { + "label": "UiPath platform overview", + "url": "https://www.uipath.com/pricing" + } + ] + } + ], + "strengths": [ + { + "text": + "Mature enterprise platform: Orchestrator provides scheduling, work queues, credential vaults, role-based access, audit export, and cold data retention up to five years on Enterprise.", + "source": { + "label": "UiPath plans and pricing", + "url": "https://www.uipath.com/pricing" + } + }, + { + "text": + "Self-hosted deployment including air-gapped Kubernetes installs, dedicated cloud, and delayed release rings are available on upper tiers.", + "source": { + "label": "UiPath plans and pricing: deploy anywhere section", + "url": "https://www.uipath.com/pricing" + } + }, + { + "text": + "Healing Agent runtime healing of broken UI automation is available for purchase on the Enterprise tier.", + "source": { + "label": "UiPath plans and pricing: Healing Agent row", + "url": "https://www.uipath.com/pricing" + } + }, + { + "text": + "Automation Cloud Basic starts at $25 per month, giving individuals and small teams a low entry point.", + "source": { + "label": "UiPath plans and pricing: Basic tier", + "url": "https://www.uipath.com/pricing" + } + } + ], + "faq": [ + { + "question": "Is OpenAdapt replacing UiPath?", + "answer": + "No. For standardized enterprise programs with hundreds of automations, existing licenses, and a center of excellence, UiPath is often the right answer. OpenAdapt is designed for consequential GUI transactions where the system of record must be independently confirmed after every run.", + "sources": [ + { + "label": "OpenAdapt comparison guide", + "url": "https://openadapt.ai/compare/uipath" + } + ] + }, + { + "question": "Which tool publishes per-run verification results?", + "answer": + "OpenAdapt publishes per-workflow trial counts, verified/halt outcomes, silent incorrect success, and model-call counts tied to immutable evidence packs, for example the MockMed triage pack with 18 trials (3 verified, 15 expected halts, 0 model calls). UiPath publishes product capabilities and service uptime, not per-workflow verification trials.", + "sources": [ + { + "label": "mockmed-triage-v3 evidence pack", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/public-demo/evidence-packs/mockmed-triage-v3/manifest.json" + } + ] + } + ] +} diff --git a/data/templates/batch-worklist-loop.json b/data/templates/batch-worklist-loop.json new file mode 100644 index 0000000..6b565b0 --- /dev/null +++ b/data/templates/batch-worklist-loop.json @@ -0,0 +1,73 @@ +{ + "slug": "batch-worklist-loop", + "name": "Process a batch worklist with one demonstrated workflow", + "application": "OpenEMR", + "surface": "browser", + "vertical": "operations", + "proof": "reference", + "dataStatus": "published", + "route": true, + "order": 70, + "title": "Process a batch worklist with one demonstrated workflow", + "metaDescription": + "Wrap one demonstrated OpenEMR note-entry workflow in a bounded loop that runs once per worklist record: deterministic, zero-model iteration, per-record identity gates and effect checks, and a fail-safe halt when the worklist exceeds the bound.", + "summary": + "The committed showcase-loop bundle wraps the real 18-step OpenEMR recording in a LOOP that runs the demonstrated body once per record of a CSV worklist, binding each record's note column to the workflow parameter. Iteration is deterministic and makes zero model calls; every iteration re-runs the same identity gate and effect verifier as a single replay, so iteration N acts on the right record or halts.", + "runsOn": + "OpenEMR (the recorded reference workflow) or your own browser application: provide the worklist as a CSV whose columns map to the workflow's parameters. This covers the provided-worklist case; reading a queue off the screen mid-run is not yet supported and is stated as future work upstream.", + "steps": [ + "Record or reuse the single-demonstration body - here, the 18-step OpenEMR add-note workflow", + "Author the loop over a worklist CSV with openadapt flow for-each, mapping columns to parameters", + "Set max_iterations to the intended bound", + "Replay: the runtime executes the compiled program once per record, verifying each write against its declared effect", + "Any ambiguous or poisoned record triggers a safe halt for that run instead of a wrong write or silent skip" + ], + "parameters": ["worklist.csv columns mapped to demonstrated workflow parameters"], + "verification": + "Per-record: each iteration re-runs the hardened per-action pipeline - identity gate plus system-of-record effect verifier - so the write for record N is confirmed against the value it actually wrote. Bounded: a worklist longer than max_iterations halts rather than running unbounded. Zero-model: loop iteration, per-row binding, and worklist resolution are deterministic code. No trial counts are published for this shape yet; what is published is the committed bundle, its regeneration procedure, and the interpreter behavior it demonstrates.", + "verificationOracles": [ + "per-iteration record_written + field_equals effect contracts", + "identity gates re-checked on every iteration", + "bounded max_iterations halt" + ], + "install": { + "command": "pip install 'openadapt[browser]'", + "note": "Installs the OpenAdapt launcher, compiler, and browser capability." + }, + "tryItCommand": + "openadapt flow for-each --records worklist.csv --out my-loop-bundle --map note=note", + "provenance": [ + { + "label": "Data-driven LOOP showcase (committed bundle + README)", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/tree/main/docs/showcase-loop" + }, + { + "label": "Compact encounter-loop companion showcase", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/tree/main/docs/showcase-encounter-loop" + } + ], + "faq": [ + { + "question": "Are there published trial counts for batch runs?", + "answer": + "No. The repository publishes the committed bundle, a deterministic regeneration script, and the documented halt behaviors - not a per-workflow trial matrix. We do not quote numbers that have not been measured.", + "sources": [ + { + "label": "showcase-loop README", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/docs/showcase-loop/README.md" + } + ] + }, + { + "question": "What happens if the worklist has more rows than the loop allows?", + "answer": + "The run halts. The loop is bounded by max_iterations and treats an over-length worklist as fail-safe, never running unbounded.", + "sources": [ + { + "label": "showcase-loop README", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/docs/showcase-loop/README.md" + } + ] + } + ] +} diff --git a/data/templates/exception-routing-human-approval.json b/data/templates/exception-routing-human-approval.json new file mode 100644 index 0000000..51221ba --- /dev/null +++ b/data/templates/exception-routing-human-approval.json @@ -0,0 +1,26 @@ +{ + "slug": "exception-routing-human-approval", + "name": "Route exceptions to one authorized human decision", + "application": null, + "surface": "browser", + "vertical": "operations", + "proof": "pattern", + "dataStatus": "pending-evidence", + "route": false, + "order": 100, + "summary": + "A cross-application workflow that pauses at an approved policy choice, asks one authorized person one clear question on their phone, re-checks the live application after the answer, and only then continues to the verified result. The public Cloud demo shows all six pause types with synthetic data.", + "evidenceNote": + "Evidence in progress. The pause-and-decide mechanics are demonstrated end to end in the public Cloud demo (six pause reasons, synthetic tasks, runner receipts), but no per-workflow trial counts have been published for this template shape. This card makes no performance claim.", + "provenance": [ + { + "label": "Public Cloud demo: mobile decision experience and pause types", + "url": "https://app.openadapt.ai/demo" + } + ], + "install": { + "command": "pip install 'openadapt[browser]'", + "note": "Installs the OpenAdapt launcher, compiler, and browser capability." + }, + "faq": [] +} diff --git a/data/templates/frappe-loan-application.json b/data/templates/frappe-loan-application.json new file mode 100644 index 0000000..1155ecb --- /dev/null +++ b/data/templates/frappe-loan-application.json @@ -0,0 +1,64 @@ +{ + "slug": "frappe-loan-application", + "name": "Automate loan application entry in Frappe Lending", + "application": "Frappe Lending", + "surface": "browser", + "vertical": "lending", + "proof": "reference", + "dataStatus": "published", + "route": true, + "order": 40, + "demonstrates": + "A loan application entered once on a pinned Frappe Lending v16.2.0 fixture and accepted only when three independent oracles - a separately authenticated read-only REST session, a direct SQL read-back, and an exact table-delta audit - agree that exactly one application was written.", + "install": { + "command": "pip install 'openadapt[browser]'", + "note": "Installs the OpenAdapt launcher, compiler, and browser capability." + }, + "tryItCommand": + "openadapt flow record --url http://localhost:8000/app/loan-application --out rec && openadapt flow compile rec --out bundle --name loan-application", + "runStats": { + "sourceLabel": "Compiled-replay arm across the pinned baseline and a cosmetic-drift variant", + "environment": + "Frappe Lending v16.2.0 pinned synthetic fixture; every trial restores the same SHA-256-bound database snapshot", + "trials": 6, + "verifiedRuns": 6, + "expectedHalts": 0, + "silentIncorrectSuccesses": 0, + "overHalts": 0, + "modelCallsPerRun": 0, + "modelCostPerRunUsd": 0, + "comparisonArm": + "Separate small-N paid-agent run: 6/6 correct writes (5/6 clean), 1/6 post-write cost-cap over-halt, 0/6 silent incorrect, $0.4240 per run; baselines were not matched, so this remains engineering evidence rather than a publication benchmark", + "measuredOn": "openadapt-flow benchmark harness; see benchmark/frappe_lending raw results" + }, + "provenance": [ + { + "label": "Benchmark harness and raw results (openadapt-flow)", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/tree/main/benchmark/frappe_lending" + } + ], + "faq": [ + { + "question": "Why three oracles instead of checking the screen?", + "answer": + "Pixels and actor self-report never establish success here. The REST session is authenticated as a different fixture user than the writer, the SQL read-back reads the target fields directly, and the exact table-delta contract accepts only one new Loan Application row - so a duplicate write, a wrong-customer write, or a collateral insert fails loudly.", + "sources": [ + { + "label": "benchmark/frappe_lending", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/tree/main/benchmark/frappe_lending" + } + ] + }, + { + "question": "What did the compiled trials cost?", + "answer": + "$0 model cost with zero model calls across all six compiled trials. A separate small-N paid-agent comparison arm averaged $0.4240 per run, but the baselines were not matched.", + "sources": [ + { + "label": "Template registry evidence note", + "url": "https://github.com/OpenAdaptAI/openadapt-web/blob/main/data/templates.js" + } + ] + } + ] +} diff --git a/data/templates/native-desktop-data-entry.json b/data/templates/native-desktop-data-entry.json new file mode 100644 index 0000000..c09d945 --- /dev/null +++ b/data/templates/native-desktop-data-entry.json @@ -0,0 +1,26 @@ +{ + "slug": "native-desktop-data-entry", + "name": "Automate native desktop application data entry", + "application": null, + "surface": "native", + "vertical": "operations", + "proof": "pattern", + "dataStatus": "pending-evidence", + "route": false, + "order": 80, + "summary": + "Data entry into a Windows, macOS, or Linux desktop application - demonstrated once by your team through the native interface, compiled, and replayed with per-record parameters. The runtime resolves targets from native accessibility evidence plus retained visuals.", + "evidenceNote": + "Evidence in progress. The native execution surface is described on the product surfaces page, but we have not yet published per-workflow trial counts for a desktop-application template. This card makes no performance claim; when qualified evidence exists it will be published here with the same structure as the proven templates.", + "provenance": [ + { + "label": "Execution surfaces (browser in production today; desktop through customer-controlled qualification)", + "url": "https://openadapt.ai/" + } + ], + "install": { + "command": "pip install 'openadapt[browser]'", + "note": "Installs the OpenAdapt launcher, compiler, and capture capability." + }, + "faq": [] +} diff --git a/data/templates/openemr-create-patient-record.json b/data/templates/openemr-create-patient-record.json new file mode 100644 index 0000000..e8cfd2f --- /dev/null +++ b/data/templates/openemr-create-patient-record.json @@ -0,0 +1,104 @@ +{ + "slug": "openemr-create-patient-record", + "name": "Automate patient record creation in OpenEMR", + "application": "OpenEMR", + "surface": "browser", + "vertical": "healthcare", + "proof": "reference", + "dataStatus": "published", + "route": true, + "order": 20, + "title": "Automate patient record creation in OpenEMR", + "metaDescription": + "Create exactly one complete synthetic patient record in OpenEMR from structured demographics. Published qualification: 3/3 Standard VERIFIED runs, REST readback agreed with direct SQL, median runtime 59.8 seconds, 0 model calls.", + "summary": + "A complete synthetic patient is created from structured demographics on a pinned local OpenEMR 8.0.0.3 fixture. The run returns VERIFIED only when a separately authenticated REST readback agrees with a direct SQL read and a non-target table-delta audit - the screen never certifies its own write.", + "runsOn": + "OpenEMR 8.0.0.3 on a pinned local synthetic fixture - fake patients only, everything binds to localhost. Never point this at a real install without qualification.", + "steps": [ + "Log in to the OpenEMR fixture as the demo admin", + "Open the patient creation flow from the main dashboard", + "Enter the structured demographic fields - each value a parameter substituted per run", + "Save exactly one complete patient record", + "Wait for the independent effect check: separately authenticated REST readback must agree with direct SQL and the non-target delta audit" + ], + "parameters": [ + "the structured demographics demonstrated in the recording (one parameter each)" + ], + "verification": + "All three fresh Standard-profile runs created exactly one synthetic patient and returned VERIFIED only after a separately authenticated REST readback agreed with a direct SQL read and a non-target delta audit. Observed silent incorrect success was 0/3.", + "verificationOracles": [ + "separately authenticated REST readback", + "direct SQL read of the patient row", + "non-target table-delta audit (exactly one new patient, nothing else changed)" + ], + "install": { + "command": "pip install 'openadapt[browser]'", + "note": "Installs the OpenAdapt launcher, compiler, and browser capability." + }, + "tryItCommand": + "openadapt flow record --url http://localhost/openemr --out rec && openadapt flow compile rec --out bundle --name create-patient", + "runStats": { + "sourceLabel": "Reference qualification published on openadapt.ai and app.openadapt.ai/demo", + "environment": "OpenEMR 8.0.0.3 pinned local synthetic fixture", + "trials": 3, + "verifiedRuns": 3, + "expectedHalts": 0, + "silentIncorrectSuccesses": 0, + "modelCallsPerRun": 0, + "medianRunDurationSeconds": 59.8, + "durationBasis": "published median end-to-end runtime across the three Standard-profile runs", + "measuredOn": "compiler 1.23.0 line; evidence pack fe6a3e778f16 referenced by the live demo" + }, + "media": [ + { + "label": "Recorded demonstration and verified replay footage (live demo)", + "url": "https://app.openadapt.ai/demo" + } + ], + "provenance": [ + { + "label": "Landing page reference qualification block", + "url": "https://openadapt.ai/" + }, + { + "label": "Live governed-execution demo with evidence pack link", + "url": "https://app.openadapt.ai/demo" + } + ], + "faq": [ + { + "question": "How is success established for this workflow?", + "answer": + "By an out-of-band check of the system of record: a separately authenticated REST readback that agrees with a direct SQL read plus an audit that no other table changed. The browser session cannot certify its own result.", + "sources": [ + { + "label": "How the result was checked (landing page)", + "url": "https://openadapt.ai/" + } + ] + }, + { + "question": "What did the three published trials cost in model calls?", + "answer": + "Zero. All three Standard-profile runs recorded zero model calls, and observed silent incorrect success was 0 out of 3.", + "sources": [ + { + "label": "Reference qualification stats", + "url": "https://app.openadapt.ai/demo" + } + ] + }, + { + "question": "Can I run this against a real EMR?", + "answer": + "Not without qualification. The published evidence is against a pinned local synthetic fixture with fake patients; a real deployment requires your own identity, effect, and policy contracts qualified against your system of record.", + "sources": [ + { + "label": "Qualification approach", + "url": "https://docs.openadapt.ai/get-started/what-works-today/" + } + ] + } + ] +} diff --git a/data/templates/openemr-patient-note.json b/data/templates/openemr-patient-note.json new file mode 100644 index 0000000..9c3ee2a --- /dev/null +++ b/data/templates/openemr-patient-note.json @@ -0,0 +1,67 @@ +{ + "slug": "openemr-patient-note", + "name": "Automate patient note entry in OpenEMR", + "application": "OpenEMR", + "surface": "browser", + "vertical": "healthcare", + "proof": "field", + "dataStatus": "published", + "route": true, + "order": 30, + "demonstrates": + "An 18-step add-patient-note workflow on the real third-party OpenEMR public demo: log in, find the patient, open the chart, navigate to Patient Messages, enter a parameterized note, save - with each replay substituting a distinct note value.", + "install": { + "command": "pip install 'openadapt[browser]'", + "note": "Installs the OpenAdapt launcher, compiler, and browser capability." + }, + "tryItCommand": + "openadapt flow record --url https://demo.openemr.io/openemr --out rec && openadapt flow compile rec --out bundle --name add-note", + "runStats": { + "sourceLabel": "Field run on the OpenEMR public demo, measured 2026-07-08", + "environment": + "Third-party OpenEMR public demo (fake patients only; shared instance that resets daily)", + "trials": 20, + "verifiedRuns": 20, + "expectedHalts": 0, + "silentIncorrectSuccesses": 0, + "modelCallsPerRun": 0, + "comparisonArm": + "A computer-use agent baseline completed 10/10 trials under the same conditions; compiled replay was faster with zero model calls", + "measuredOn": + "openadapt-flow 0.1.0 (a pre-v0.2.0 source build), 2026-07-08; not re-measured since" + }, + "provenance": [ + { + "label": "Benchmark harness and raw results (openadapt-flow)", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/tree/main/benchmark/openemr_e2e" + }, + { + "label": "Spike findings write-up", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/docs/showcase-openemr/FINDINGS.md" + } + ], + "faq": [ + { + "question": "Was this measured in CI or in the field?", + "answer": + "In the field, against the real third-party OpenEMR public demo. It is not CI-reproducible: the demo is shared and resets daily, and the agent sample is small. The verifier and task-prompt units do run in CI.", + "sources": [ + { + "label": "Template registry evidence note", + "url": "https://github.com/OpenAdaptAI/openadapt-web/blob/main/data/templates.js" + } + ] + }, + { + "question": "How does the run know the write actually happened?", + "answer": + "The Save step carries system-of-record effect contracts (record_written plus a field_equals check on the note). Under an injected fault where the screen paints Saved while the record drops the note, effect verification refutes the run and it halts.", + "sources": [ + { + "label": "benchmark/openemr_e2e", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/tree/main/benchmark/openemr_e2e" + } + ] + } + ] +} diff --git a/data/templates/openimis-claim-intake.json b/data/templates/openimis-claim-intake.json new file mode 100644 index 0000000..78aeb1f --- /dev/null +++ b/data/templates/openimis-claim-intake.json @@ -0,0 +1,63 @@ +{ + "slug": "openimis-claim-intake", + "name": "Automate health insurance claim intake in openIMIS", + "application": "openIMIS", + "surface": "browser", + "vertical": "insurance", + "proof": "reference", + "dataStatus": "published", + "route": true, + "order": 50, + "demonstrates": + "A health-facility claim entered once in openIMIS - the open-source system used by national health-insurance schemes - compiled, and replayed with a fresh claim number, accepted only when a direct SQL read shows exactly one new claim row in status Entered for the right policyholder and facility.", + "install": { + "command": "pip install 'openadapt[browser]'", + "note": "Installs the OpenAdapt launcher, compiler, and browser capability." + }, + "tryItCommand": + "openadapt flow record --url http://localhost:8000/ --out rec && openadapt flow compile rec --out bundle --name claim-intake", + "runStats": { + "sourceLabel": "Reference environment replays (deliberately not a benchmark)", + "environment": + "openIMIS 25.10 from digest-pinned images with the upstream synthetic demo dataset; everything binds to localhost", + "trials": 3, + "verifiedRuns": 3, + "expectedHalts": 0, + "silentIncorrectSuccesses": 0, + "modelCallsPerRun": null, + "comparisonArm": + "Separate small-N paid-agent run on a different flow build: 3/3 correct, 0/3 over-halt, 0/3 silent incorrect, $0.4793 per run; no matched timing matrix, so no comparative claim is made", + "measuredOn": + "compiled arm on openadapt-flow 1.11.0 (evidence committed 2026-07-17); agent arm on openadapt-flow 1.19.0 (2026-07-21)" + }, + "provenance": [ + { + "label": "Reference environment and raw results (openadapt-flow)", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/tree/main/benchmark/openimis_claims" + } + ], + "faq": [ + { + "question": "What failure does the SQL oracle catch?", + "answer": + "The costly one: the claim silently entered twice, or against the wrong policyholder, surfacing weeks later in reconciliation. A duplicate or missing claim row fails the run loudly instead of reporting success.", + "sources": [ + { + "label": "benchmark/openimis_claims", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/tree/main/benchmark/openimis_claims" + } + ] + }, + { + "question": "Is this a benchmark result?", + "answer": + "No. The repository describes it as a reference environment, deliberately not a benchmark: there is no matched timing matrix or publication protocol behind the 3/3 compiled replays.", + "sources": [ + { + "label": "Template registry evidence note", + "url": "https://github.com/OpenAdaptAI/openadapt-web/blob/main/data/templates.js" + } + ] + } + ] +} diff --git a/data/templates/openimis-eligibility-enquiry.json b/data/templates/openimis-eligibility-enquiry.json new file mode 100644 index 0000000..314c873 --- /dev/null +++ b/data/templates/openimis-eligibility-enquiry.json @@ -0,0 +1,104 @@ +{ + "slug": "openimis-eligibility-enquiry", + "name": "Automate insurance eligibility enquiries in openIMIS", + "application": "openIMIS", + "surface": "browser", + "vertical": "insurance", + "proof": "reference", + "dataStatus": "published", + "route": true, + "order": 60, + "title": "Automate insurance eligibility enquiries in openIMIS", + "metaDescription": + "Run an openIMIS eligibility enquiry as a compiled workflow with a read-only SQL oracle: 3/3 eligible-policy runs VERIFIED, 3/3 expired-policy runs HALTED on the refuted business condition, mean runtime 19.7 seconds, 0 model calls.", + "summary": + "The same compiled browser workflow - insuree number in, coverage answer out - run six fresh times against openIMIS 25.10 with synthetic data. When read-only SQL confirmed the policy state, all three runs returned VERIFIED. When SQL returned Ineligible where the declared effect required Eligible, all three runs halted instead of trusting the screen.", + "runsOn": + "openIMIS 25.10, browser surface, synthetic sample data bound to localhost. openIMIS exposes a GraphQL API that a real deployment should prefer; this demonstration stands in for commercial eligibility portals that expose no API.", + "steps": [ + "Click the Insuree enquiry control", + "Type the insuree number - parameterized per replay", + "Press Enter to resolve the policyholder", + "Search and select the demonstrated service option", + "Read the eligibility result and confirm it against an independent read-only SQL query of the policy state" + ], + "parameters": ["insurance_no", "service_code", "as_of_date"], + "verification": + "A Tier 1 independent system interface: the campaign queried openIMIS through a separate read-only SQL connection, so the browser that performed the task could not certify its own result. The workflow required at least Tier 3 evidence and received the stronger Tier 1 proof. On expired policies the SQL result contradicted the declared effect and every run halted with no blind retry of the consequential action.", + "verificationOracles": [ + "read-only SQL confirmation of policy, product, service, and effective-date state (Tier 1)", + "identity gates on three consequential actions", + "declared-effect check with explicit halt path" + ], + "install": { + "command": "pip install 'openadapt[browser]'", + "note": "Installs the OpenAdapt launcher, compiler, and browser capability." + }, + "tryItCommand": + "openadapt flow record --url http://localhost:8000/ --out rec && openadapt flow compile rec --out bundle --name eligibility-enquiry", + "runStats": { + "sourceLabel": "openIMIS Standard execution evidence campaign (live demo deep-dive)", + "environment": "openIMIS 25.10, browser, synthetic sample data, off-box transmissions observed: 0", + "trials": 6, + "verifiedRuns": 3, + "expectedHalts": 3, + "silentIncorrectSuccesses": 0, + "overHalts": 0, + "modelCallsPerRun": 0, + "meanRunDurationSeconds": 19.7, + "durationBasis": "published mean runtime across the six fresh Standard-profile runs", + "representativeDurationsSeconds": { + "eligibleVerified": [20.3, 12.7, 17.8], + "expiredPolicyHalted": [25.3, 19.4, 22.6] + }, + "contractsPassed": "16/16 contracts on the representative VERIFIED run; 15/16 on the representative HALTED run, where the refuted effect check is exactly the failed contract", + "measuredOn": "compiler 1.23.0; evidence manifest d163375358f1 referenced by the live demo" + }, + "media": [ + { + "label": "Guided and raw footage plus halt clip (live demo)", + "url": "https://app.openadapt.ai/demo" + } + ], + "provenance": [ + { + "label": "openIMIS Standard execution evidence deep-dive", + "url": "https://app.openadapt.ai/demo" + } + ], + "faq": [ + { + "question": "Why did half the trials end in HALTED?", + "answer": + "By design. Three trials ran against an expired policy: read-only SQL returned Ineligible where the declared effect required Eligible, so OpenAdapt refused the contradictory result, did not accept the browser screen as success, and did not retry the consequential action blindly. Zero over-halts were observed across the campaign.", + "sources": [ + { + "label": "Expired-policy trial results", + "url": "https://app.openadapt.ai/demo" + } + ] + }, + { + "question": "What evidence tier verified the eligible runs?", + "answer": + "Tier 1, an independent system interface: a separate read-only SQL connection confirmed the policy, product, service, and effective-date state. The workflow only required Tier 3; it received the stronger proof.", + "sources": [ + { + "label": "Evidence classification notes", + "url": "https://app.openadapt.ai/demo" + } + ] + }, + { + "question": "How long does one enquiry take?", + "answer": + "Mean runtime across the six published runs was 19.7 seconds; individual verified runs ranged from 12.7 to 20.3 seconds as published in the trial list.", + "sources": [ + { + "label": "Campaign summary", + "url": "https://app.openadapt.ai/demo" + } + ] + } + ] +} diff --git a/data/templates/patient-triage-note.json b/data/templates/patient-triage-note.json new file mode 100644 index 0000000..d4f0aa5 --- /dev/null +++ b/data/templates/patient-triage-note.json @@ -0,0 +1,98 @@ +{ + "slug": "patient-triage-note", + "name": "Automate patient triage note entry", + "application": "MockMed", + "surface": "browser", + "vertical": "healthcare", + "proof": "reference", + "dataStatus": "published", + "route": true, + "order": 10, + "summary": null, + "demonstrates": + "A nurse's triage-note workflow demonstrated once in a synthetic clinic app, compiled into a deterministic local program, and replayed with the note text as a parameter - including five injected fault classes that must halt instead of proceeding.", + "install": { + "command": "pip install 'openadapt[browser]'", + "note": "Installs the OpenAdapt launcher, compiler, and browser capability." + }, + "tryItCommand": "openadapt flow replay bundle --param note=\"Triage note from $(date +%F)\"", + "runStats": { + "sourceLabel": "Immutable public-demo evidence pack mockmed-triage-v3", + "environment": "MockMed synthetic clinic app (MIT, synthetic data only)", + "trials": 18, + "verifiedRuns": 3, + "expectedHalts": 15, + "silentIncorrectSuccesses": 0, + "wrongTargetActions": 0, + "modelCallsPerRun": 0, + "medianVerifiedRunDurationMs": 4706.64, + "durationBasis": "median of the three verified representative-run durations published in the pack outcomes (4820.51 ms, 4706.64 ms, 4697.14 ms)", + "faultClassesHalted": [ + "ambiguous target", + "missing effect", + "stale identity", + "weak effect", + "wrong identity" + ], + "measuredOn": "openadapt-flow 1.23.0, commit 7cc518ee0b83dd571c0902423134a5525635e6b2, pack generated 2026-07-26" + }, + "media": [ + { + "label": "Verified replay (derived presentation view)", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/public-demo/evidence-packs/mockmed-triage-v3/artifacts/presentation/verified.webm" + }, + { + "label": "Safe halt footage (derived presentation view)", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/public-demo/evidence-packs/mockmed-triage-v3/artifacts/presentation/halted.webm" + } + ], + "provenance": [ + { + "label": "Evidence pack manifest (byte inventory, SHA-256 bound)", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/public-demo/evidence-packs/mockmed-triage-v3/manifest.json" + }, + { + "label": "Qualification report for the same pack", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/public-demo/evidence-packs/mockmed-triage-v3/artifacts/qualification/report.json" + }, + { + "label": "Live governed-execution demo", + "url": "https://app.openadapt.ai/demo" + } + ], + "faq": [ + { + "question": "Does this template make model calls when it runs?", + "answer": + "No. Every one of the 18 published trials in evidence pack mockmed-triage-v3 recorded 0 model calls, including the 15 fault trials.", + "sources": [ + { + "label": "Pack outcome envelopes", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/tree/main/public-demo/evidence-packs/mockmed-triage-v3/artifacts/cases" + } + ] + }, + { + "question": "What happens when the target is ambiguous?", + "answer": + "The run halts before acting. In the published fault trials, an ambiguous locator produced a structural safety refusal - no action was admitted - in 3 of 3 trials.", + "sources": [ + { + "label": "fault-ambiguity outcome example", + "url": "https://github.com/OpenAdaptAI/openadapt-flow/blob/main/public-demo/evidence-packs/mockmed-triage-v3/artifacts/cases/fault-ambiguity/trial-01/outcome.json" + } + ] + }, + { + "question": "Is the clinical-write bundle certified?", + "answer": + "No. The bundled tutorial is runnable but intentionally not certified for clinical writes; lint reports its unarmed irreversible final click and the strict policy gate refuses certification. That refusal is the safety boundary working.", + "sources": [ + { + "label": "Template gallery source registry", + "url": "https://github.com/OpenAdaptAI/openadapt-web/blob/main/data/templates.js" + } + ] + } + ] +} diff --git a/data/templates/rdp-citrix-hosted-app-update.json b/data/templates/rdp-citrix-hosted-app-update.json new file mode 100644 index 0000000..a39e3b9 --- /dev/null +++ b/data/templates/rdp-citrix-hosted-app-update.json @@ -0,0 +1,30 @@ +{ + "slug": "rdp-citrix-hosted-app-update", + "name": "Automate updates inside hosted RDP and Citrix applications", + "application": null, + "surface": "remote", + "vertical": "operations", + "proof": "pattern", + "dataStatus": "pending-evidence", + "route": false, + "order": 90, + "summary": + "A record-keeping update inside an application that lives on a managed remote desktop or Citrix session - driven from the local client window from outside the session, so nothing is installed inside the managed environment. Pixels, keyboard, and mouse carry the same identity and result checks as local surfaces.", + "evidenceNote": + "Evidence in progress. The external remote lane is qualified today against a deterministic stand-in and a real FreeRDP round trip; a real ICA/HDX environment is qualified per customer before consequential use. No workflow-level trial counts are published yet, so this card makes no performance claim.", + "provenance": [ + { + "label": "Remote lane qualification status (comparison data disclosure)", + "url": "https://openadapt.ai/compare/uipath" + }, + { + "label": "Execution surfaces", + "url": "https://openadapt.ai/" + } + ], + "install": { + "command": "pip install 'openadapt[browser]'", + "note": "Installs the OpenAdapt launcher, compiler, and capture capability." + }, + "faq": [] +} diff --git a/lib/generators/buildComparisons.js b/lib/generators/buildComparisons.js new file mode 100644 index 0000000..2d506a3 --- /dev/null +++ b/lib/generators/buildComparisons.js @@ -0,0 +1,135 @@ +/** + * Build-time loader for the structured capability-dimension data behind + * /compare/. + * + * Each file in data/compare/.json carries per-dimension facts about + * OpenAdapt and one alternative, where every factual claim names its public + * source URL. The renderer (pages/compare/[slug].js) shows each dimension + * row with its citations; nothing here replaces the honesty rules enforced + * by tests/comparisonPages.test.js on data/comparisons.js - it structures + * and cites them. + * + * Validation fails the build loudly when a dimension is missing, a claim + * has no source, or a priced claim lacks a citation. + */ + +const fs = require('node:fs') +const path = require('node:path') + +const REQUIRED_DIMENSIONS = [ + 'determinism-on-drift', + 'cost-per-run', + 'verification-of-effects', + 'halting-behavior', + 'data-locality', + 'scope', +] + +function assertHttpsUrl(url, label) { + if (typeof url !== 'string' || !/^https:\/\/\S+$/.test(url)) { + throw new Error(`${label}: source URLs must be https (${url})`) + } +} + +function validateSources(sources, label) { + if (!Array.isArray(sources) || sources.length === 0) { + throw new Error(`${label}: at least one source is required`) + } + sources.forEach((s) => { + if (!s.label) throw new Error(`${label}: every source needs a label`) + assertHttpsUrl(s.url, label) + }) +} + +function validateComparison(data, file) { + const fail = (message) => { + throw new Error(`data/compare/${file}: ${message}`) + } + + if (!data.slug || data.slug !== file.replace(/\.json$/, '')) { + fail('slug must match the file name') + } + if (!data.competitor || !data.positioningSummary) { + fail('competitor and positioningSummary are required') + } + if (!Array.isArray(data.dimensions)) fail('dimensions array is required') + + const ids = data.dimensions.map((d) => d.id) + for (const required of REQUIRED_DIMENSIONS) { + if (!ids.includes(required)) fail(`missing dimension: ${required}`) + } + if (new Set(ids).size !== ids.length) fail('duplicate dimension ids') + if (ids.some((id) => !REQUIRED_DIMENSIONS.includes(id))) { + fail(`unknown dimension ids; allowed: ${REQUIRED_DIMENSIONS.join(', ')}`) + } + + for (const dimension of data.dimensions) { + const label = `${data.slug}/${dimension.id}` + if (!dimension.openadapt || !dimension.them) { + fail(`${label}: both openadapt and them text are required`) + } + try { + validateSources(dimension.sources, label) + } catch (error) { + fail(error.message) + } + } + + ;(data.strengths || []).forEach((strength, i) => { + const label = `${data.slug}/strengths[${i}]` + if (!strength.text) fail(`${label}: text is required`) + // Priced claims must cite their published pricing source. + if (/\$\d/.test(strength.text)) { + try { + validateSources([strength.source], label) + } catch (error) { + fail(`${label}: dollar figures require a cited source (${error.message})`) + } + } else if (strength.source) { + try { + validateSources([strength.source], label) + } catch (error) { + fail(error.message) + } + } + }) + + ;(data.faq || []).forEach((item, i) => { + const label = `${data.slug}/faq[${i}]` + if (!item.question || !item.answer) fail(`${label}: question and answer are required`) + try { + validateSources(item.sources || [], label) + } catch (error) { + fail(error.message) + } + }) + + return data +} + +function loadComparisons(dataDir) { + return fs + .readdirSync(dataDir) + .filter((file) => file.endsWith('.json')) + .sort() + .map((file) => { + let parsed + try { + parsed = JSON.parse(fs.readFileSync(path.join(dataDir, file), 'utf8')) + } catch (error) { + throw new Error(`data/compare/${file}: invalid JSON (${error.message})`) + } + return validateComparison(parsed, file) + }) +} + +function findComparison(comparisons, slug) { + return comparisons.find((c) => c.slug === slug) || null +} + +module.exports = { + REQUIRED_DIMENSIONS, + loadComparisons, + findComparison, + validateComparison, +} diff --git a/lib/generators/buildTemplates.js b/lib/generators/buildTemplates.js new file mode 100644 index 0000000..295eef0 --- /dev/null +++ b/lib/generators/buildTemplates.js @@ -0,0 +1,330 @@ +/** + * Build-time generator for the workflow template gallery. + * + * Reads the structured evidence files in data/templates/*.json and merges + * them with the copy registry in data/templates.js by slug: + * + * - registry slug + JSON entry -> registry copy enriched with structured + * runStats, media, provenance, and FAQ data + * - JSON-only entry with "route": true -> a standalone template rendered + * from the JSON file itself + * - JSON-only entry with "route": false -> an honest "evidence in progress" + * card in the gallery grid; no detail route, no performance claims + * + * Every published number must come from the cited source. The validator + * below enforces shape (counts, zero-model calls, bounded durations, HTTPS + * provenance) and fails loudly at build time rather than rendering a card + * that implies unmeasured evidence. + */ + +const fs = require('node:fs') +const path = require('node:path') + +const SURFACES = ['browser', 'native', 'remote'] +const PROOF_LEVELS = ['reference', 'field', 'pattern'] +const DATA_STATUSES = ['published', 'pending-evidence'] + +function assertHttpsUrl(url, label) { + if (typeof url !== 'string' || !/^https:\/\/\S+$/.test(url)) { + throw new Error(`${label}: provenance/source URLs must be https (${url})`) + } +} + +function validateEntry(entry, file) { + const fail = (message) => { + throw new Error(`data/templates/${file}: ${message}`) + } + + if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(entry.slug)) fail('slug must be kebab-case') + if (!DATA_STATUSES.includes(entry.dataStatus)) fail('dataStatus must be published or pending-evidence') + if (!SURFACES.includes(entry.surface)) fail(`surface must be one of ${SURFACES.join(', ')}`) + if (!PROOF_LEVELS.includes(entry.proof)) fail(`proof must be one of ${PROOF_LEVELS.join(', ')}`) + if (typeof entry.order !== 'number') fail('order must be a number') + if (!entry.name) fail('name is required') + + const hasRoute = entry.route === true || entry.route === false + if (!hasRoute) fail('route must be true or false') + + if (entry.route === false && entry.dataStatus !== 'pending-evidence') { + fail('non-routed cards must be dataStatus "pending-evidence"') + } + if (entry.dataStatus === 'pending-evidence') { + if (entry.runStats) fail('pending-evidence cards must not carry runStats') + if (!entry.evidenceNote) fail('pending-evidence cards must explain what evidence is missing') + if (entry.route !== false) fail('pending-evidence cards must not be routed pages') + } + + if (entry.dataStatus === 'published') { + if (!entry.summary && !entry.demonstrates) fail('published entries need summary or demonstrates') + if (!Array.isArray(entry.provenance) || entry.provenance.length === 0) { + fail('published entries need at least one provenance link') + } + entry.provenance.forEach((p) => { + if (!p.label) fail('provenance needs a label') + assertHttpsUrl(p.url, entry.slug) + }) + } + + if ((entry.install && !entry.install.command) || (entry.install && !entry.install.note)) { + fail('install requires command and note') + } + if (entry.tryItCommand && typeof entry.tryItCommand !== 'string') { + fail('tryItCommand must be a string') + } + + ;(entry.media || []).forEach((m) => { + if (!m.label) fail('media needs a label') + assertHttpsUrl(m.url, entry.slug) + }) + + ;(entry.faq || []).forEach((item) => { + if (!item.question || !item.answer) fail('faq items need question and answer') + ;(item.sources || []).forEach((s) => { + if (!s.label) fail('faq sources need a label') + assertHttpsUrl(s.url, entry.slug) + }) + }) + + if (entry.runStats) validateRunStats(entry.runStats, file) + + return entry +} + +function validateRunStats(stats, file) { + const fail = (message) => { + throw new Error(`data/templates/${file}: runStats ${message}`) + } + + const isCount = (n) => Number.isInteger(n) && n >= 0 + if (!stats.sourceLabel) fail('needs sourceLabel naming where the numbers were published') + if (!isCount(stats.trials) || stats.trials < 1) fail('trials must be a positive integer') + + for (const key of [ + 'verifiedRuns', + 'expectedHalts', + 'silentIncorrectSuccesses', + 'wrongTargetActions', + 'overHalts', + ]) { + if (stats[key] !== undefined && !isCount(stats[key])) fail(`${key} must be a non-negative integer`) + } + + if ( + stats.verifiedRuns !== undefined && + stats.expectedHalts !== undefined && + stats.verifiedRuns + stats.expectedHalts > stats.trials + ) { + fail('verifiedRuns + expectedHalts cannot exceed trials') + } + + if (stats.modelCallsPerRun !== undefined && stats.modelCallsPerRun !== 0 && stats.modelCallsPerRun !== null) { + fail('modelCallsPerRun must be 0 or null; healthy runs make no model calls') + } + if (stats.silentIncorrectSuccesses > 0) { + fail('silent incorrect successes above zero are never publishable marketing data') + } + + const durations = ['medianVerifiedRunDurationMs', 'medianRunDurationSeconds', 'meanRunDurationSeconds'] + const hasDuration = durations.some((key) => typeof stats[key] === 'number' && stats[key] > 0) + if (hasDuration && !stats.durationBasis) { + fail('any quoted duration needs durationBasis explaining how it was computed/published') + } + + if (!stats.measuredOn) fail('needs measuredOn naming the build/date the numbers come from') +} + +function loadTemplateEntries(dataDir) { + return fs + .readdirSync(dataDir) + .filter((file) => file.endsWith('.json')) + .sort() + .map((file) => { + const raw = fs.readFileSync(path.join(dataDir, file), 'utf8') + let parsed + try { + parsed = JSON.parse(raw) + } catch (error) { + throw new Error(`data/templates/${file}: invalid JSON (${error.message})`) + } + return validateEntry(parsed, file) + }) + .sort((a, b) => a.order - b.order) +} + +function toQuickstart(entry) { + if (entry.quickstart) return entry.quickstart + if (!entry.install || !entry.tryItCommand) return undefined + return [ + { cmd: entry.install.command, what: entry.install.note }, + { + cmd: entry.tryItCommand, + what: 'Demonstrate or reuse the recording, compile it into a deterministic bundle, then replay locally.', + }, + ] +} + +function stripUndefined(value) { + if (Array.isArray(value)) return value.map(stripUndefined) + if (value && typeof value === 'object') { + const clean = {} + for (const [key, inner] of Object.entries(value)) { + if (inner !== undefined) clean[key] = stripUndefined(inner) + } + return clean + } + return value +} + +/** + * Merge the copy registry (data/templates.js) with the structured JSON + * evidence entries. Returns everything the two template pages need: + * + * - routableTemplates: full objects for /templates/[slug] (registry ∪ routed JSON) + * - galleryEntries: ordered cards for the index grid, including the honest + * pending-evidence cards + * + * Every returned object is free of `undefined` values so getStaticProps can + * serialize it directly. + */ +function buildTemplateGallery(registryTemplates, entries) { + const registryBySlug = new Map(registryTemplates.map((t) => [t.slug, t])) + const seenSlugs = new Set() + + const routableTemplates = [] + const galleryEntries = [] + + for (const entry of entries) { + if (seenSlugs.has(entry.slug)) { + throw new Error(`duplicate slug across data/templates/*.json: ${entry.slug}`) + } + seenSlugs.add(entry.slug) + + const registry = registryBySlug.get(entry.slug) + + if (entry.route === false) { + galleryEntries.push({ + slug: entry.slug, + name: entry.name, + application: entry.application, + surface: entry.surface, + vertical: entry.vertical, + proof: entry.proof, + dataStatus: entry.dataStatus, + summary: entry.summary, + evidenceNote: entry.evidenceNote, + provenance: entry.provenance, + runStats: null, + href: null, + }) + continue + } + + if (registry) { + const enriched = { + ...registry, + application: entry.application, + surface: entry.surface, + demonstrates: entry.demonstrates || registry.summary, + install: entry.install, + tryItCommand: entry.tryItCommand, + runStats: entry.runStats || null, + media: entry.media || [], + provenance: entry.provenance || [], + faq: entry.faq || [], + dataStatus: entry.dataStatus, + } + routableTemplates.push(enriched) + galleryEntries.push(toGalleryCard(enriched)) + } else { + const standalone = { + slug: entry.slug, + title: entry.title || entry.name, + metaDescription: entry.metaDescription, + proof: entry.proof, + vertical: entry.vertical, + application: entry.application, + surface: entry.surface, + summary: entry.summary, + runsOn: entry.runsOn, + steps: entry.steps, + parameters: entry.parameters || [], + verification: entry.verification, + verificationOracles: entry.verificationOracles || [], + quickstart: toQuickstart(entry), + source: (entry.provenance && entry.provenance[0] && entry.provenance[0].url) || undefined, + anchors: entry.anchors || [], + demonstrates: entry.demonstrates, + install: entry.install, + tryItCommand: entry.tryItCommand, + runStats: entry.runStats || null, + media: entry.media || [], + provenance: entry.provenance || [], + faq: entry.faq || [], + dataStatus: entry.dataStatus, + } + if (!standalone.title || !standalone.metaDescription || !standalone.steps || !standalone.verification) { + throw new Error( + `data/templates/${entry.slug}.json: routed JSON-only entries need title, metaDescription, steps, verification` + ) + } + if (!standalone.quickstart) { + throw new Error(`data/templates/${entry.slug}.json: routed entries need install + tryItCommand or quickstart`) + } + routableTemplates.push(standalone) + galleryEntries.push(toGalleryCard(standalone)) + } + } + + // Registry patterns without a JSON evidence file still appear in the grid. + for (const t of registryTemplates) { + if (seenSlugs.has(t.slug)) continue + galleryEntries.push({ + slug: t.slug, + name: t.title, + application: null, + surface: null, + vertical: t.vertical, + proof: t.proof, + dataStatus: 'pattern-shape', + summary: t.summary, + evidenceNote: null, + provenance: [], + runStats: null, + href: `/templates/${t.slug}`, + }) + } + + galleryEntries.sort((a, b) => { + const orderA = (entries.find((e) => e.slug === a.slug) || {}).order || Number.MAX_SAFE_INTEGER + const orderB = (entries.find((e) => e.slug === b.slug) || {}).order || Number.MAX_SAFE_INTEGER + return orderA - orderB + }) + + return stripUndefined({ routableTemplates, galleryEntries }) +} + +function toGalleryCard(t) { + return { + slug: t.slug, + name: t.title || t.name, + application: t.application, + surface: t.surface, + vertical: t.vertical, + proof: t.proof, + dataStatus: t.dataStatus, + summary: t.summary, + evidenceNote: null, + provenance: t.provenance || [], + runStats: t.runStats || null, + href: `/templates/${t.slug}`, + } +} + +module.exports = { + SURFACES, + PROOF_LEVELS, + DATA_STATUSES, + loadTemplateEntries, + buildTemplateGallery, + validateEntry, +} diff --git a/pages/compare/[slug].js b/pages/compare/[slug].js index 8acfd87..395560c 100644 --- a/pages/compare/[slug].js +++ b/pages/compare/[slug].js @@ -8,6 +8,7 @@ import { OPENADAPT_DIFFERENTIATORS, QUALIFICATION_EVIDENCE_URL, } from '../../data/comparisons' +import { loadComparisons, findComparison } from '../../lib/generators/buildComparisons' // Targeted alternative pages under /compare/. The overview table stays // on /compare; these pages go deeper on one alternative at a time under the @@ -15,6 +16,10 @@ import { // real strengths, differentiate only on what OpenAdapt actually does, and // never lean on commoditized capabilities (recording, visual targeting, // Citrix awareness, self-healing) as if they were unique. +// +// The capability-dimension grid below is generated from +// data/compare/.json, where every factual claim names its public +// source; those citations are rendered next to the claims they support. export async function getStaticPaths() { return { @@ -25,10 +30,35 @@ export async function getStaticPaths() { export async function getStaticProps({ params }) { const comparison = COMPARISONS.find(({ slug }) => slug === params.slug) - return { props: { comparison } } + let dimensionData = null + try { + const structured = loadComparisons('data/compare') + dimensionData = findComparison(structured, params.slug) + } catch (error) { + if (process.env.NODE_ENV !== 'production') throw error + dimensionData = null + } + return { props: { comparison, dimensionData } } +} + +function SourceLinks({ sources }) { + if (!sources || sources.length === 0) return null + return ( +

+ Source:{' '} + {sources.map((s, i) => ( + + {i > 0 && ' · '} + + {s.label} + + + ))} +

+ ) } -export default function ComparisonDetailPage({ comparison }) { +export default function ComparisonDetailPage({ comparison, dimensionData }) { const url = `https://openadapt.ai/compare/${comparison.slug}` const webPageSchema = { '@context': 'https://schema.org', @@ -44,6 +74,36 @@ export default function ComparisonDetailPage({ comparison }) { inLanguage: 'en', } + const itemListSchema = { + '@context': 'https://schema.org', + '@type': 'ItemList', + name: 'OpenAdapt alternative comparisons', + itemListElement: [ + ...COMPARISON_LINKS.map((link, i) => ({ + '@type': 'ListItem', + position: i + 1, + name: link.title, + url: `https://openadapt.ai${link.href}`, + })), + ], + } + + const faqSchema = + dimensionData && dimensionData.faq && dimensionData.faq.length > 0 + ? { + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: dimensionData.faq.map((item) => ({ + '@type': 'Question', + name: item.question, + acceptedAnswer: { '@type': 'Answer', text: item.answer }, + })), + } + : null + + const citedStrengths = + (dimensionData && dimensionData.strengths && dimensionData.strengths.filter((s) => s.source)) || [] + return (
@@ -65,6 +125,20 @@ export default function ComparisonDetailPage({ comparison }) { __html: JSON.stringify(webPageSchema), }} /> +