Metadata-Version: 2.5
Name: ordel-cli
Version: 0.4.2
Summary: Ordel free CLI — local QA-automation for individual devs. Drives the deterministic ordel-engine and exposes it to a BYO coding agent over MCP. No account, no DB, no Ordel LLM.
Project-URL: Homepage, https://ordel.io
Author: Ordel
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: coding-agent,mcp,page-object,playwright,qa,self-healing,testing
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.11
Requires-Dist: mcp<2.0,>=1.0
Requires-Dist: ordel-engine==0.4.2
Requires-Dist: ordel-tools==0.4.2
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: hatchling; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# ordel (free CLI)

Local QA automation for individual devs — a persistent, deterministic "QA brain" your
own coding agent (Claude Code / Cursor / Copilot) drives over MCP. **No account, no DB,
no Ordel LLM.** Your agent is the brain; Ordel is the memory + determinism.

> Status: **early build**. The engine loop (map → record → generate → run) works
> locally today; a single-command `npx ordel` distribution is planned but not started.

## What works today (local, anonymous)

```bash
ordel init          # create .ordel/ + an ORDEL.md bridge file. No account.
ordel doctor        # preflight: Node / npx / @playwright/test / Chromium (+ how to fix)
ordel status        # local coverage: pages, elements, run history
ordel graph         # print the local app graph
ordel adopt         # existing Playwright/Cypress suite -> flake report + heal patches
ordel record <name> <url>  # click through a flow yourself -> page objects + a spec using them
ordel run           # run the Playwright suite; one evidence-backed verdict per test
ordel report        # copy-pasteable Markdown report (Slack/Teams/Jira); --json too
ordel catalog export catalog.json   # the element catalog as a portable file (CATALOG.md)
ordel catalog import catalog.json   # merge one in; local elements win, conflicts listed
ordel mcp-install    # print the MCP config to add to Claude Code / Cursor / Copilot
ordel mcp-install --skill   # also install the agent skill (Claude Code, Codex)
```

### Recording a flow yourself

`ordel record signup http://localhost:3000/` opens a visible browser at that URL. Click
and type through the flow as a user would, then close the window to finish (Ctrl+C
works too, and keeps what was recorded).

To assert something, Alt+click it (Option+click on a Mac). That records
`toHaveText(<its text>)`, or `toBeVisible()` when it has no text. The final URL is
asserted automatically. A recording with no assertion runs `unjudged`, because it
proves nothing.

Ordel writes back:
- every page you landed on, into the catalog;
- a page object per page (`pages/<Class>.ts`, or its managed block updated);
- `tests/signup.spec.ts`, which drives those page objects (`homePage.submit.click()`).

A hand-written page object is never overwritten: steps on its page use a direct locator
instead, and the command says so. Passwords are never stored. The spec reads them from
`ORDEL_PASSWORD`, and query strings (where a GET form puts its fields) are dropped from
every recorded URL.

### Adopting an existing suite

`ordel adopt` points Ordel at the suite you already have (Playwright, or Cypress `*.cy.*`
specs) and reports on it without changing it:

- **Ingest:** every functional spec becomes a flow in `.ordel/flows/`. Cypress chains
  are translated to the same flow format; a chain it cannot represent faithfully is
  counted, never guessed.
- **Flake report:** it runs a Playwright suite until `.ordel/runs/` holds `--runs`
  (default 3) judged runs, then classifies each test as `flaky` (passed only on retry,
  or flipped twice), `regressed` (passed, then kept failing), `failing`, `recovered`,
  `stable`, or too few runs to say.
- **Heal report:** each failing test whose test-id locator no longer resolves is healed
  against a live capture of the page it was catalogued on. The page must have been
  captured while the test was green: run `ordel explore <url>` first to build that
  baseline. A confident heal becomes a unified diff under `.ordel/patches/<heal-id>.patch`.
  An element that is simply gone is reported as a real failure, not healed to something else.

Nothing in your code changes until you review a patch:

```bash
ordel adopt --apply heal-0001    # write the fix, mark the heal accepted, refresh the catalog
ordel adopt --reject heal-0001   # write nothing, record the rejection
```

`--apply` refuses a patch whose file changed since it was made. Agents get the same
report through the `adopt_suite` MCP tool. They cannot apply or reject a heal: that is
the human review step.

### Honest verdicts

`ordel run` (and the `run_test` MCP tool) never reports a green it cannot back. Each
executed test gets one verdict: `pass`, `fail`, `flaky`, `skipped` or **`unjudged`**,
with its evidence: the assertions it actually ran and any heal it depends on.

A test that Playwright calls green is `unjudged`, not passed, when:
- it ran no assertion at all (a vacuous pass),
- no assertion evidence was captured for it,
- its spec depends on a heal no human has reviewed yet.

A run that executed no test is `no_tests`, never a pass. `ordel run --json` prints the
full `ordel.run/v1` document, which is also recorded under `.ordel/runs/`.

| Exit code | Meaning |
|---|---|
| 0 | at least one test ran, and every one passed with evidence |
| 1 | a test failed, no test ran, or the run itself errored |
| 3 | nothing failed, but at least one test is unjudged |

Then your coding agent, via MCP, drives the loop (needs Node + `@playwright/test` in the
project — run `ordel doctor` to check):
- `get_app_context` / `heal_selector` — what Ordel knows + **deterministic self-heal**
  of a broken selector (fingerprint match, no LLM; ambiguous cases return `needs_agent`
  with ranked candidates for your agent's *own* LLM to resolve — Ordel never spends inference).
  Every resolved heal is recorded in `.ordel/heals.json` pending human review.
- `explore` / `record_flow` — drive the real browser to map the app + record a flow.
  A value typed into a password-like field (type=password, or named/labelled password,
  secret, token or api key; a step can also say `"secret": true`) is used for the recording
  and never written to disk: the flow keeps a reference, and every generated spec reads it
  from an environment variable such as `ORDEL_SECRET_PASSWORD`, listed in the result's
  `needs_env`. Set it in the shell or in `.ordel/secrets.env` (`KEY=value` lines; `ordel
  init` gitignores it, and `run_test` loads it). Unset, those tests are skipped and the run
  reports `blocked` with the variable's name; Ordel scrubs the value from everything it
  stores, and `run_test` lists any spec or note you copied it into (`secret_leaks`).
- `get_page` — read a mapped page back (inputs, buttons, links or all): each element's
  test id, name, type, placeholder, href, `<select>` options and visible text, exact case.
- `generate_scenarios` / `generate_invariant` / `generate_perf_check` / `generate_pom` —
  turn artifacts into runnable specs (happy/negative/boundary, data-integrity, latency, POM).
- `run_test` — run a spec via `npx playwright test` and read the evidence-backed verdicts.
- QA-mind planning: `coverage_report` / `risk_rank` / `plan_tests` / `regression_set`.

## In progress (honest — no fake success)

- Single `npx ordel` distribution — the plan is a compiled Python engine binary wrapped
  in one npm package; not started (today's install path is `pip`/`uv`, see Dev below).
- `eject` (one-command raw-Playwright export) — scaffold; but there's no lock-in today
  either: generated tests are already plain `tests/*.spec.ts` + `pages/*.ts` on disk.
- Team sync + hosted dashboard = the paid upgrade (this CLI stays free & local).

## The pieces

- **`ordel-engine`** (sibling package) — the pure deterministic core: fingerprint
  matching + self-heal, stdlib-only, zero backend.
- **`ordel_cli.store`** — the `.ordel/` file store (the local shell).
- **`ordel_cli.heal_service`** — heal + per-page circuit-breaker.
- **`ordel_cli.mcp_server`** — the local stdio MCP server your agent connects to.

## Dev

```bash
pip install -e packages/ordel-engine -e packages/ordel-cli
pip install pytest
pytest packages/ordel-cli/tests packages/ordel-engine/tests -q
```

## Known limitations (by design)

- **Single-writer.** The `.ordel/` store is for one dev on one machine. Writes are
  *atomic* (temp-file + `os.replace`, so a crash can't corrupt a file), and a corrupted
  `graph.json` is reported cleanly (never silently overwritten). But two processes
  writing the *same* page concurrently is last-writer-wins — there is no file lock. That
  is deliberate: a single-user local CLI doesn't warrant lock files / their failure
  modes. Team-scale concurrency is the hosted product's job (`ordel push`).
- **Browser tools need a local Node + `@playwright/test`** (`explore`/`record_flow`/`run_test`).
  They don't ship a browser; run `ordel doctor` — if Node/Playwright/Chromium are missing it
  tells you the exact command to fix. Without them these tools report the missing dependency,
  never fake success.

## Privacy

Local-first: **no Ordel LLM, no telemetry, no account, no data sent to Ordel.** The only
network requests are to your own target app and standard package/browser downloads you
initiate. Full policy: https://ordel.io/privacy (also ships as `PRIVACY.md` next to the
installed package, and at the repo root here).
