Prove it works before anyone sees it. One command shows exactly what to fix.

ownux test v0 checks L1 and L2. L3 Adaptive waits for Beta.

satin — zsh
$
Publishable

Runs inside Satin's monorepo, worded exactly as the CLI prints them. In your product, you’ll use npx ownux once the SDK is published.

L2 Verified

Reads first. Then six checks for every change. Two test accounts and one test task, with your data reset in between.

ownux test drives your integration through the real broker, not a mock. It changes the test task, reads it back on a fresh connection, and tries it as a viewer.

  • A write that does nothing must never come back verified.
  • Two commits of one change must reach your API once.
  • A viewer must be refused; the version must not move.
How verified actions work

Reads, first

Then, for each declared change

statusdueassign
changes and reads back
a repeated commit writes once
verify is real
falls back to a valid link
an old version is refused
a viewer is refused

task.list_assigned

list pages to the end

Pages through list({ cursor }), at most 50 pages. Each item must be a valid Task, with no repeats.

If it fails, the report says:

✗ task.list_assigned: the list is not valid: task t-7 appears twice
Fix: list({ cursor }) must return { items, next_cursor }: valid Tasks of this app and workspace (see "The Task contract" in AGENTS.md), no task twice, and next_cursor null on the last page.

How the levels map. Three levels. v0 checks the first two and says when it hasn't run one.

L1

In v0

Declared

The manifest is valid: canonical capabilities, the right risk, every precondition, verify on each change, fallback on each action, locked surfaces listed.

$ npx ownux validate <manifest.json>

$ npx ownux test --manifest <file>

--manifest exits 1 even when L1 passes: nothing is publishable before L2.

L2

In v0

Verified

Every declared action passes execute, verify, fallback and permission-denial tests in your test environment, with an editor, a viewer and one test task.

$ npx ownux test --config <ownux.config.ts>

The first level that may carry the OwnUX Ready badge, which is planned and will always state its level.

L3

Planned for Beta

Adaptive

The runtime is integrated, Interface DNA is honoured, accessibility checks pass and locked surfaces are respected.

Not in v0. The report never prints an L3 line it has not checked.

One command line for the whole loop. Today it runs as pnpm ownux in Satin's monorepo. Running npx ownux in your product comes when the SDK is published, soon.

ownux init [folder] --app <id>
Write starter files, with every remaining step marked TODO(ownux). It never overwrites a file.
ownux validate <manifest>
Check a capability manifest at L1 Declared.
ownux test --config <file> [--json]
Run L1 Declared, then L2 Verified against a test target.
ownux test --manifest <file>
Check only a manifest, at L1.
ownux dna check <file>
Check an Interface DNA profile (ownux-dna/1) and explain each problem.
ownux preview --template <name>
Compose a surface from the fixtures and print its outline.
ownux config keygen <key-file>
Make a development signing key. It refuses a path inside your project.
ownux config sign <flags-file> --key <key-file>
Sign a flags file for development and tests, with --kill <id> to switch one off.

Exit codes

  • 0passedpublishable
  • 1a check failedpublishing is blocked
  • 2could not runfor example, the config did not load

Add --json for a machine-readable report. Each failed check carries message and fix, and recommendations carry note: true.

Unfinished steps

A finish line your AI assistant can see. ownux test scans your OwnUX folder and blocks on every TODO(ownux) left in code.

The report names each TODO(ownux) with its file and line. To leave a step on purpose, change it to LATER(ownux): it is listed as a note and never blocks.

  • Starter files: twelve TODO, one LATER (your own components).
  • It loads all TypeScript, including enums and parameter properties.
  • A config that fails to load gets a Fix: line.
The developer platform
src/ownuxClick a marker to change it

integration.ts

21
// TODO(ownux): replace with the task type your API returns.type YourTask = Record<string, unknown>;

view.tsx

21
// LATER(ownux): replace plainRegistry with your own component for each primitive.components={plainRegistry}
23
appName="Your product" // TODO(ownux): your product's name, as people know it
$ npx ownux test --config src/ownux/ownux.config.ts
…
✗ integration.ts:21: an unfinished step is left: // TODO(ownux): replace with the task type your API returns.
Fix: Do the step the comment describes, then remove the comment. To leave it for later on purpose, change TODO(ownux) to LATER(ownux).
! view.tsx:21: left for later: // LATER(ownux): replace plainRegistry with your own component for each primitive.
✗ view.tsx:23: an unfinished step is left: appName="Your product" // TODO(ownux): your product's name, as people know it
Fix: Do the step the comment describes, then remove the comment. To leave it for later on purpose, change TODO(ownux) to LATER(ownux).
Not publishable: 2 checks failed (marked ✗ above).

Example: three markers left, every other check passing.

Conformance questions, answered.

Exit code 0 and publishable: true in the report. Until the developer portal exists, a block means exit code 1 and publishable: false. The portal will enforce it from Beta.

Get your product to Publishable: yes. Start with the free 12-week design partner programme.