Plan 006: Correct snapshot backend and custom-action documentation
Executor instructions: Follow this plan step by step. Run every
verification command and confirm the expected result before moving to the
next step. If anything in the "STOP conditions" section occurs, stop and
report — do not improvise. A reviewer maintains the plan index for this work;
do not create or edit plans/README.md.
Drift check (run first):
git diff --stat 13bc70f24..HEAD -- website/docs/docs/snapshots.md website/docs/docs/commands.md src/__tests__/command-doc-coverage.test.ts
If any in-scope file changed since this plan was written, compare the
"Current state" excerpts against the live code before proceeding; on a
mismatch, treat it as a STOP condition.
Status
- Priority: P2
- Effort: S
- Risk: LOW
- Depends on: none
- Category: docs
- Planned at: commit
13bc70f24, 2026-08-08
Why this matters
The snapshot guide says a zero-node XCTest result fails without switching to
AX, but regular iOS capture now has an explicit recursive-tree → query-sweep →
private-AX recovery plan. The public CLI also exposes --actions, while both
website reference pages omit it. Correcting the prose prevents false diagnosis
of recovered/degraded snapshots, makes merged accessibility affordances
discoverable, and adds a schema-derived guard so the canonical snapshot usage
cannot drift from the command reference again.
Current state
-
The command schema is the canonical CLI usage source:
// src/commands/capture/snapshot.ts:49-59
const snapshotCliSchema = {
usageOverride:
'snapshot [--diff] [-i] [-d <depth>] [-s <scope>] [--raw] [--actions] [--force-full] [--timeout <ms>]',
allowedFlags: [
'snapshotDiff',
...SNAPSHOT_FLAGS,
'snapshotCustomActions',
'snapshotForceFull',
'timeoutMs',
'record',
],
} as const;
-
Its field description provides the user contract that documentation must not
overstate:
// src/commands/capture/snapshot.ts:24-32
interactiveOnly: booleanField(),
depth: integerField(),
scope: stringField(),
raw: booleanField(),
customActions: booleanField(
'Name the affordances an element merged away (iOS UIAccessibilityCustomAction, React Native accessibilityActions) — a card whose reply/options controls are not separate elements still lists them here. The names are for PLANNING, not invocation: there is no API to trigger them, so reach the affordance through the element detail screen, through the same control exposed as a labeled element elsewhere, or by coordinates from its rect. iOS simulator only; costs one accessibility round trip per merged element.',
),
forceFull: booleanField(),
timeoutMs: integerField('Maximum wall-clock time for the snapshot command.'),
-
The flag registry repeats the essential short-form limitation:
// src/commands/cli-grammar/flag-definitions-workflow.ts:203-208
{
key: 'snapshotCustomActions',
names: ['--actions'],
type: 'boolean',
usageLabel: '--actions',
usageDescription:
'Snapshot: name the affordances merged inside an element (iOS sim); not directly invokable — reach them via the detail screen, labeled children, or coordinates',
},
-
The accepted snapshot strategy requires fallback for sparse regular output:
<!-- docs/adr/0004-ios-snapshot-backend-strategy.md:38-43 -->
Keep XCTest as the default iOS automation runner and split iOS snapshot capture into explicit
strategies:
- **Regular visible strategy**: use recursive XCTest snapshots, emit the effective user-visible
tree plus visible ancestors and scroll-hidden hints, and fall back through the capture plan when
XCTest returns sparse output.
-
The live plan confirms the backend order:
// apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/
// RunnerTests+SnapshotCapturePlan.swift:115-118
// MARK: Plan definitions
static let regularVisiblePlan: [SnapshotBackendKind] = [.recursiveTree, .querySweep, .privateAX]
static let rawDiagnosticPlan: [SnapshotBackendKind] = [.recursiveTree, .privateAX]
-
The guide currently contradicts those sources and omits current options:
<!-- website/docs/docs/snapshots.md:19-26 -->
| Option | Description |
| ------------ | ---------------------------- |
| `-i` | Interactive-only output |
| `-d <depth>` | Limit tree depth |
| `-s <scope>` | Scope to label or identifier |
Note: If XCTest returns 0 nodes (foreground app changed), agent-device fails explicitly.
It does not automatically switch to AX.
-
The command reference is not the canonical schema usage:
<!-- website/docs/docs/commands.md:306-313 -->
## Snapshot and inspect
```bash
agent-device snapshot [--diff] [-i] [-d <depth>] [-s <scope>] [--raw]
agent-device diff snapshot [-i] [-d <depth>] [-s <scope>] [--raw]
agent-device get text @e1
agent-device get attrs @e1
```
-
src/__tests__/command-doc-coverage.test.ts:7-17 intends to prevent public
command-reference drift, but extractDocumentedCommandTokens at lines 38-54
extracts only the first command token. Follow this test's fs +
node:assert/strict style and derive snapshot usage through
getCliCommandSchema plus buildCommandUsage; do not duplicate the usage
literal in the test.
-
Website CI runs pnpm check:command-docs for docs-only pull requests at
.github/workflows/pr-preview.yml:21-40, and the production docs build runs
pnpm --dir website build through
.github/actions/build-docs/action.yml:16-22.
Commands you will need
| Purpose |
Command |
Expected on success |
| Command-reference gate |
pnpm check:command-docs |
exit 0; command names and canonical snapshot usage are documented |
| Docs build |
pnpm --dir website build |
exit 0; Rspress builds website/doc_build without broken Markdown or links |
| Affected gates |
pnpm check:affected --run |
exit 0 for selected local checks; CI-owned checks are reported only |
| Scope check |
git status --short |
only the three in-scope files are changed; generated docs output is ignored |
Dependencies must already be installed. Use pnpm only; do not create or
restore package-lock.json.
Scope
In scope (the only files you should modify):
website/docs/docs/snapshots.md
website/docs/docs/commands.md
src/__tests__/command-doc-coverage.test.ts
Out of scope (do NOT touch, even though they are evidence for the docs):
src/commands/capture/snapshot.ts
src/commands/cli-grammar/**
src/cli-schema/**
src/daemon/**
apple/runner/**
docs/adr/0004-ios-snapshot-backend-strategy.md
- Any new custom-action invocation API or fallback behavior.
- README, skills, changelog, other website pages, generated
website/doc_build,
plans/README.md, and all other plan files.
Git workflow
- Branch:
advisor/006-snapshot-backend-actions-docs
- Use one logical commit after the red/green proof:
docs: align snapshot fallback and actions guidance
- Do NOT commit the intentionally red test state or generated docs output.
- Do NOT push or open a pull request unless the operator explicitly instructs it.
Steps
Step 1: Add a canonical-usage regression and prove it red
In src/__tests__/command-doc-coverage.test.ts:
-
Import getCliCommandSchema from
../cli-schema/command-schema.ts and buildCommandUsage from
../cli-schema/usage.ts.
-
Reuse COMMANDS_DOC_PATH and the existing filesystem read style.
-
Add a focused test named
commands.md publishes the canonical snapshot CLI usage that computes:
const usage = buildCommandUsage('snapshot', getCliCommandSchema('snapshot'));
and asserts the Markdown contains the executable code-block line
agent-device ${usage}. Do not paste the expected flag list into the test;
the schema must remain the source of truth.
This is deliberately scoped to snapshot. Do not generate the entire command
reference or turn narrative documentation into exact-schema output.
Verify red: pnpm check:command-docs → exit nonzero, with the new test
reporting that the canonical snapshot usage is absent. Record the failing test
name. If it passes before editing commands.md, STOP because the regression is
not checking the intended drift.
Step 2: Publish the canonical command-reference usage
Replace the snapshot usage line in website/docs/docs/commands.md with the exact
value produced by the schema, prefixed by agent-device:
agent-device snapshot [--diff] [-i] [-d <depth>] [-s <scope>] [--raw] [--actions] [--force-full] [--timeout <ms>]
Keep diff snapshot, get, and is examples intact. Add a short bullet below
the code block explaining that --actions names merged custom accessibility
affordances on iOS simulators and is for planning, not direct invocation. Do not
claim physical-device or cross-platform support.
Verify: pnpm check:command-docs → exit 0, including the new canonical-usage
test and all existing bidirectional command-token checks.
Step 3: Correct the snapshot guide from the accepted/live contract
Update website/docs/docs/snapshots.md without changing command behavior:
- Add one concise
agent-device snapshot --actions example near the existing
snapshot examples.
- Expand the options table to cover the canonical snapshot-specific options
shown in the usage line: --diff, -i, -d, -s, --raw, --actions,
--force-full, and --timeout.
- For
--actions, state all of these constraints:
- iOS simulator only;
- names custom actions merged inside an element;
- planning/discovery only, not directly invokable;
- costs an accessibility read per merged element;
- incompatible with
--raw.
- Replace lines 25-26 and the oversimplified backend description at lines
69-72 with an iOS capture behavior section:
- regular visible capture starts with recursive XCTest and may recover
through query sweep and private AX when that backend is available;
- the ladder is bounded and recovery/degradation remains observable through
quality warnings rather than being presented as an empty UI;
- raw is the diagnostic strategy and preserves strict capture failures;
- private AX recovery/custom-action reads are simulator-specific; do not
promise an equivalent independent backend on physical iOS devices.
- Keep visible-first output, off-screen summaries, ref freshness, and Android
guidance unchanged.
Use the terms regular visible strategy, raw diagnostic strategy,
sparse, recovered, and degraded consistently with ADR 0004. Do not
describe the internal backend ladder as user-selectable CLI backends.
Verify:
rg -n -- '--actions|regular visible|raw diagnostic|sparse|degraded' website/docs/docs/snapshots.md website/docs/docs/commands.md
rg -n 'does not automatically switch to AX' website/docs/docs/snapshots.md
Expected: the first command finds the new guidance in both pages; the second
prints no matches.
Step 4: Build the docs and run the owning gates
Run the direct command-reference gate, the same Rspress build CI uses, and the
affected selector. Do not add a formatter path invocation; Markdown is excluded
from the repository formatter.
Verify:
pnpm check:command-docs && pnpm --dir website build && pnpm check:affected --run
Expected: exit 0. Rspress writes only ignored website/doc_build output. The
affected selector runs tests related to the changed TypeScript gate and reports
any CI-only work.
Step 5: Confirm the handoff contains only source documentation and its gate
Verify: git status --short → only the three in-scope files are listed.
If generated docs output appears as tracked or untracked state, STOP and report
instead of changing ignore rules or deleting broad paths.
Test plan
- Add one schema-derived command-doc test in
src/__tests__/command-doc-coverage.test.ts.
- Prove it red against the current
commands.md before updating documentation.
- Preserve all existing forward/reverse command-name and waiver tests.
- Build the full Rspress site to catch malformed tables, fences, and links.
- No device or runner test is needed because no runtime behavior changes.
Done criteria
STOP conditions
Stop and report back; do not improvise if:
- Any in-scope current-state excerpt has drifted since
13bc70f24.
buildCommandUsage('snapshot', getCliCommandSchema('snapshot')) no longer
returns the usage shown in this plan.
- ADR 0004 and
RunnerTests+SnapshotCapturePlan.swift no longer agree on the
regular strategy or backend order.
- The red regression passes before
commands.md changes.
- Accurate docs would require adding custom-action invocation, changing
platform capability, or modifying runtime fallback behavior.
- The docs build changes tracked generated files or requires lockfile changes.
- A verification command fails twice after one reasonable correction.
- Any fix requires touching a file outside the in-scope list.
Maintenance notes
- Reviewers should compare behavior prose to ADR 0004 and the live capture plan,
but compare CLI syntax to the schema-derived test. These are different owners.
- The canonical-usage gate protects
commands.md; the snapshot guide remains
narrative and must be reviewed when user-facing snapshot flags or strategy
semantics change.
- Keep custom-action discovery separate from invocation. Runner research at
RunnerAXSnapshotBridge.h:62-68 says the current runner can read names but
cannot invoke them; this plan must not imply otherwise.
- Docs/skills impact is complete within the two website pages. Skills remain
unchanged because they route to versioned CLI help rather than carrying
command behavior.
Plan 006: Correct snapshot backend and custom-action documentation
Status
13bc70f24, 2026-08-08Why this matters
The snapshot guide says a zero-node XCTest result fails without switching to
AX, but regular iOS capture now has an explicit recursive-tree → query-sweep →
private-AX recovery plan. The public CLI also exposes
--actions, while bothwebsite reference pages omit it. Correcting the prose prevents false diagnosis
of recovered/degraded snapshots, makes merged accessibility affordances
discoverable, and adds a schema-derived guard so the canonical snapshot usage
cannot drift from the command reference again.
Current state
The command schema is the canonical CLI usage source:
Its field description provides the user contract that documentation must not
overstate:
The flag registry repeats the essential short-form limitation:
The accepted snapshot strategy requires fallback for sparse regular output:
The live plan confirms the backend order:
The guide currently contradicts those sources and omits current options:
The command reference is not the canonical schema usage:
src/__tests__/command-doc-coverage.test.ts:7-17intends to prevent publiccommand-reference drift, but
extractDocumentedCommandTokensat lines 38-54extracts only the first command token. Follow this test's
fs+node:assert/strictstyle and derive snapshot usage throughgetCliCommandSchemaplusbuildCommandUsage; do not duplicate the usageliteral in the test.
Website CI runs
pnpm check:command-docsfor docs-only pull requests at.github/workflows/pr-preview.yml:21-40, and the production docs build runspnpm --dir website buildthrough.github/actions/build-docs/action.yml:16-22.Commands you will need
pnpm check:command-docspnpm --dir website buildwebsite/doc_buildwithout broken Markdown or linkspnpm check:affected --rungit status --shortDependencies must already be installed. Use
pnpmonly; do not create orrestore
package-lock.json.Scope
In scope (the only files you should modify):
website/docs/docs/snapshots.mdwebsite/docs/docs/commands.mdsrc/__tests__/command-doc-coverage.test.tsOut of scope (do NOT touch, even though they are evidence for the docs):
src/commands/capture/snapshot.tssrc/commands/cli-grammar/**src/cli-schema/**src/daemon/**apple/runner/**docs/adr/0004-ios-snapshot-backend-strategy.mdwebsite/doc_build,plans/README.md, and all other plan files.Git workflow
advisor/006-snapshot-backend-actions-docsdocs: align snapshot fallback and actions guidanceSteps
Step 1: Add a canonical-usage regression and prove it red
In
src/__tests__/command-doc-coverage.test.ts:Import
getCliCommandSchemafrom../cli-schema/command-schema.tsandbuildCommandUsagefrom../cli-schema/usage.ts.Reuse
COMMANDS_DOC_PATHand the existing filesystem read style.Add a focused test named
commands.md publishes the canonical snapshot CLI usagethat computes:and asserts the Markdown contains the executable code-block line
agent-device ${usage}. Do not paste the expected flag list into the test;the schema must remain the source of truth.
This is deliberately scoped to
snapshot. Do not generate the entire commandreference or turn narrative documentation into exact-schema output.
Verify red:
pnpm check:command-docs→ exit nonzero, with the new testreporting that the canonical snapshot usage is absent. Record the failing test
name. If it passes before editing
commands.md, STOP because the regression isnot checking the intended drift.
Step 2: Publish the canonical command-reference usage
Replace the snapshot usage line in
website/docs/docs/commands.mdwith the exactvalue produced by the schema, prefixed by
agent-device:Keep
diff snapshot,get, andisexamples intact. Add a short bullet belowthe code block explaining that
--actionsnames merged custom accessibilityaffordances on iOS simulators and is for planning, not direct invocation. Do not
claim physical-device or cross-platform support.
Verify:
pnpm check:command-docs→ exit 0, including the new canonical-usagetest and all existing bidirectional command-token checks.
Step 3: Correct the snapshot guide from the accepted/live contract
Update
website/docs/docs/snapshots.mdwithout changing command behavior:agent-device snapshot --actionsexample near the existingsnapshot examples.
shown in the usage line:
--diff,-i,-d,-s,--raw,--actions,--force-full, and--timeout.--actions, state all of these constraints:--raw.69-72 with an iOS capture behavior section:
through query sweep and private AX when that backend is available;
quality warnings rather than being presented as an empty UI;
promise an equivalent independent backend on physical iOS devices.
guidance unchanged.
Use the terms regular visible strategy, raw diagnostic strategy,
sparse, recovered, and degraded consistently with ADR 0004. Do not
describe the internal backend ladder as user-selectable CLI backends.
Verify:
Expected: the first command finds the new guidance in both pages; the second
prints no matches.
Step 4: Build the docs and run the owning gates
Run the direct command-reference gate, the same Rspress build CI uses, and the
affected selector. Do not add a formatter path invocation; Markdown is excluded
from the repository formatter.
Verify:
Expected: exit 0. Rspress writes only ignored
website/doc_buildoutput. Theaffected selector runs tests related to the changed TypeScript gate and reports
any CI-only work.
Step 5: Confirm the handoff contains only source documentation and its gate
Verify:
git status --short→ only the three in-scope files are listed.If generated docs output appears as tracked or untracked state, STOP and report
instead of changing ignore rules or deleting broad paths.
Test plan
src/__tests__/command-doc-coverage.test.ts.commands.mdbefore updating documentation.Done criteria
failing test name was recorded.
commands.mdcontains the exact canonical snapshot usage frombuildCommandUsage.--actionsas iOS-simulator-only andplanning-only.
capture-plan ordering without presenting internal backends as CLI choices.
pnpm check:command-docsexits 0.pnpm --dir website buildexits 0.pnpm check:affected --runexits 0 for local gates.git status --shortlists only the three in-scope files.plans/README.mdare unchanged.STOP conditions
Stop and report back; do not improvise if:
13bc70f24.buildCommandUsage('snapshot', getCliCommandSchema('snapshot'))no longerreturns the usage shown in this plan.
RunnerTests+SnapshotCapturePlan.swiftno longer agree on theregular strategy or backend order.
commands.mdchanges.platform capability, or modifying runtime fallback behavior.
Maintenance notes
but compare CLI syntax to the schema-derived test. These are different owners.
commands.md; the snapshot guide remainsnarrative and must be reviewed when user-facing snapshot flags or strategy
semantics change.
RunnerAXSnapshotBridge.h:62-68says the current runner can read names butcannot invoke them; this plan must not imply otherwise.
unchanged because they route to versioned CLI help rather than carrying
command behavior.