feat(cli): compact workflow help card + version header - #1663
Conversation
Shrinks the per-task agent protocol tax of the help/skill surface. `agent-device help workflow` drops from 41025 to 8466 bytes (-79%) by moving depth into new `help scripting` (save-script, secret-safe fills, batch JSON, replay divergence/repair) and `help gestures` (multi-touch shapes/quirks) topics, and folding a few paragraphs into topics that already owned the subject (help debugging, help physical-device, help validate). Content is moved, not deleted. Every `help <topic>` first line is now `agent-device <version> — <topic>`, so the skill router reads the CLI version off the mandatory first help read instead of a separate `agent-device --version` call. SKILL.md is updated to do that and stays a thin router otherwise. The compact card also gains two terse behavioral rules: chain confident consecutive steps with `&&` (falling back to one command at a time when uncertain), and confirm the requested end state is actually visible on screen before declaring a task done. help-conformance-bench (22 cases x 2 runners) improves after the change: 29/44 -> 32/44 passing checks.
Size Report
Startup median (7 runs, lower is better):
Top changed chunks:
|
|
Review found three actionable gaps in the help contract:
The 79% size reduction, version-header consolidation, moved-content organization, deterministic size pin, and live common-loop smoke otherwise look good. I did not apply |
Three fixes from PR review: - Extend the help-conformance plan validator to split a command line on unquoted && and validate each chained segment independently, so a plan that follows the workflow card's "chain confident consecutive steps with &&" guidance is accepted instead of rejected as one shell-projection violation. && inside a quoted selector value (e.g. label="A && B") is not a chain boundary and does not split. Adds unit tests for the splitter and a chains-confident-consecutive- settle-steps conformance case. batch stays out of this: it is deliberately stop-only. - Replace the literal @ref placeholder the compact card used in its own "snapshot -s @ref" example with a concrete ref (snapshot -s @E12 (the current concrete ref)), matching the same card's rule against placeholder targets. Reverts the test to demand the concrete shape. - Give help scripting and help gestures real conformance cases instead of waivers: a secret-safe recorded-fill + publish case, and an Android transform-then-verify case whose exact verification text only appears in the gestures topic. Removes both waivers. help-conformance-bench (25 cases x 2 runners, repeat=1) after these fixes: two full runs landed at 32/50 and 33/50. That is on par with the pre-change baseline (29/44) once the topic-untouched cases' run-to-run swings are accounted for (confirmed noise: one case with zero exposure to any change here flipped 10/10 -> 1/10 on a runner API error, and another swung across all three post-fix runs). The new scripting case now passes 8/8 for both runners; the new chaining case correctly reports the model's choice not to chain as a soft signal, not a validator failure.
|
Thanks — all three fixed, pushed in 80ee870 and 3c47adc:
Re-ran the full help-conformance bench (25 cases × 2 runners) after all three fixes. Two full runs landed at 32/50 and 33/50, on par with the 29/44 pre-fix baseline — read against the framework's real repeat=1 noise floor, which I made concrete this round: a case with zero exposure to anything in this PR ( Also found and fixed a real production-test casualty while chasing this: Full details and the updated before/after table are in the PR description. |
|
Re-reviewed |
splitOnUnquotedAnd() previously trimmed and filtered out empty segments, so a plan with a leading (`&& press ...`), trailing (`press ... &&`), or doubled (`a && && b`) operator passed validPlanCommands even though a real shell rejects all three as a syntax error. The validator would bless a plan that fails at execution. Empty segments are now surfaced as an `empty-chain-operand` issue instead of being silently dropped. The quoted-&& non-split behavior (label="A && B") is unchanged, and a normal single command with no chain still parses identically to before. Adds regression tests for all three empty-operand shapes plus the quoted-&& case.
|
Follow-up P2 fixed, pushed in 5606eea.
Fix: empty segments are no longer dropped. Added 4 regression tests: leading, trailing, and doubled CI is green (all checks pass, including Coverage). |
|
Re-reviewed |
|
Summary
Benchmark evidence (SWM AppControlBench, gpt-5.4-high driving the CLI on 30 Bluesky tasks) showed
agent-device help workflow(~41KB) plus a separateagent-device --versionhandshake were mandated on every task by the shipped skill router, producing 108 boilerplate tool calls across 30 tasks (~3.6 extra model turns/task) and 1266KB of the 1899KB total tool output (67%) being help/version text.This PR:
agent-device help workflowfrom 41025 → 8493 bytes (-79.3%). Content that carries correctness (the open→snapshot→settle→verify→close loop, selector/@ref rules,--settleguidance, platform gotchas, error-recovery hints) stays; duplication, long prose, and rarely-needed depth move to sub-topics — nothing is deleted:help scripting: save-script/destination-guard authoring,--record-assecret-safe fills, batch JSON step shape, replay divergence/resume, agent-supervised repair (heal-by-doing), recording/tracing.help gestures: full multi-touch command shapes (pinch/rotate/transform/drag), iOS XCTest-synthesis vs Android geometric-injection quirks, macOS context-menu/wheel-scroll patterns.help debugging; runner/daemon idle-timeout env vars →help physical-device; Apple-runner CI cache-key note →help validate.help <topic>first line is nowagent-device <version> — <topic>(e.g.agent-device 0.20.6 — workflow), so the skill reads the CLI version off its mandatory first help read instead of a separateagent-device --versioncall.skills/agent-device/SKILL.mdis updated to do that (with explicit fallback semantics: a first line still reading the oldagent-device help <topic>format, or a failed/unrecognized command, means the CLI predates this header and needs upgrading) and otherwise stays a thin router — no behavioral guidance was added there.help workflow:&&(falling back to one command at a time when a step is uncertain — ambiguous match, network-backed result, unseen screen).get textalone, or stopping one screen early, is not enough.scripts/help-conformance-bench.mjs, 25 cases × 2 non-agentic runners) before and after against the live CLI output (never hand-transcribed).Review follow-ups (all three addressed)
&&-chaining guidance conflicted withscripts/help-conformance-plan-validator.mjs, which classified any unquoted&&asshell-projectionand failedvalidPlanCommands— canonical help was teaching a plan shape the conformance contract rejected. Fixed by extending the validator, not by dropping the guidance: it now splits a plan line on unquoted&&and validates each segment independently (&&inside a quoted selector value, e.g.label="A && B", is not a split boundary and stays intact). Added unit tests for the splitter and achains-confident-consecutive-settle-stepsconformance case that exercises a real chained plan end to end.batchstays untouched — it's deliberately stop-only, a settled design decision, not a workaround target.@refplaceholder contradiction (P2). The card said never to target a placeholder like@ref/@eN, then itself wrotesnapshot -s @ref. Replaced with a concrete ref and an explicit label:snapshot -s @e12 (the current concrete ref). Reverted the test that had been changed to require the placeholder shape.help scriptingandhelp gesturesnow each have a dedicated conformance case instead of a "we'll add one if regressions show up" waiver:scripting-secret-safe-recorded-login(arm--save-script,--record-asa fill against an env var, publish without closing) andgestures-android-transform-then-verify(plan a combined pan/scale/rotate transform, then verify with the exact confirmation text that only appears in the gestures topic's own example — so a correct plan proves the model actually read it). Both waivers removed.&&chain operands (P2, follow-up round). The&&splitter above filtered out empty segments, so a plan with a leading (&& foo), trailing (foo &&), or doubled (a && && b) operator passedvalidPlanCommandseven though a real shell rejects all three as a syntax error — the validator would have blessed a plan that fails at execution. Fixed: an empty (post-trim) segment is now a dedicatedempty-chain-operandissue instead of being silently dropped. Added regression tests for all three shapes plus confirmation the quoted-&&case is unaffected.Before / After
agent-device help workflowbytesRead the bench delta with the noise floor this framework actually has at repeat=1, not as a clean signal: one case with zero exposure to any change in this PR (
ios-system-ui-widget-flow, docs are--help:first30+ an untouched topic) swung 10/10 → 7/10 → 1/10 across three consecutive runs — the 1/10 was aclaudeCLI subprocess API error, not a content issue. Across two independent full post-fix runs the combined score was 32/50 and 33/50 — statistically on par with the 29/44 (65.9%) baseline. The two things actually being tested by the new cases behave correctly:scripting-secret-safe-recorded-loginpasses 8/8 for both runners (after one case-authoring bug of my own — anexportline the task didn't need — was found and fixed), andchains-confident-consecutive-settle-stepscorrectly produces a fully valid plan either way, reporting the model's choice not to chain as a soft, informative signal rather than a validator failure (matching the original benchmark finding that models chained only twice in 30 tasks even when told they could).One real regression surfaced and was fixed before any of the numbers above: the compact Bootstrap section initially dropped the explicit "install arguments are id then artifact path" rule (kept only the example command), and both runners on
workflow-install-artifact-before-openstarted omitting the package id frominstallcalls. Re-added the explicit rule sentence; the case now passes for both runners consistently.Live smoke test
Created my own simulator (never touched
bench-golden*or the reserved UDID), booted it, and ran the exact sequence the skill prescribes with an isolatedAGENT_DEVICE_STATE_DIR:All five commands worked end-to-end using only the compact card's guidance — no missing command shapes.
press --settlereturned a full settled diff (+14/-14) showing the General screen's content, matching the "continue from the settled diff" guidance verbatim. Cleaned up: daemon stopped, simulator shut down and deleted.Tests
src/cli/parser/__tests__/cli-help-topics.test.ts,src/__tests__/cli-help.test.ts,src/cli/parser/__tests__/cli-help-command-usage.test.ts— rewritten to match the new compact content, new topics, and version headers.scripts/__tests__/help-conformance-bench.test.ts— new unit tests for the&&segment splitter (splits a chain, leaves a quoted&&alone, still rejects a lone unquoted&, fails only the offending segment of a chain).scripts/help-conformance-cases.mjs— three new conformance cases (chains-confident-consecutive-settle-steps,scripting-secret-safe-recorded-login,gestures-android-transform-then-verify);scripts/__tests__/help-conformance-topic-coverage.test.ts— both waivers removed now thatscripting/gestureshave real cases.src/commands/management/session.test.ts— a pre-existing production test asserted save-script/--record-ascontent directly againsthelp workflow; updated to follow the pointer tohelp scripting, where that content now lives.unit-core+subprocess-stubrun);oxlintandoxfmt --checkare clean repo-wide. CI is green (Coverage, Lint & Format, Typecheck, Layering Guard, Smoke Tests, etc. all pass).What was left out
@e12fix from review. Judged that trade worth it: benchmark-verified correctness over an arbitrary few hundred bytes.