mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
287cc18c29
* fix(gestures): fail pre-removal gesture forms at .ad parse time (#1216) #1315 removed the timed forms of `swipe`, `gesture fling`, and `gesture swipe` and `gesture rotate`'s `velocity`, but shipped without the migration guide, the repository sweep, or the parse-time error that issue #1216's own checklist gates a removal on. The sweep finds what that left behind: both `06-swipe-gestures.ad` integration fixtures still carried the 5-argument swipe and would fail at replay, two tests still asserted the removed shapes, and two branches still read the retired positional. Argument arity for every public gesture syntax now lives in one table keyed off the canonical `GESTURE_KINDS`, so a new kind cannot skip it and a form removed from the CLI is removed from `.ad` in the same edit. Both callers read it: the CLI argv parse, and a new `.ad` preflight. A stale script now fails when it is parsed — before the replay executes any device action — naming the line and computing its rewrite, instead of running up to that step and failing as a repairable divergence. The preflight checks arity only: `${VAR}` tokens resolve after planning, and interpolation never splits a token, so the count is decidable while the values are not. Deleting the dead duration read in `readSwipeGeometry` would have left `replay export` emitting no duration, handing Maestro's 400ms default to a gesture the script runs at 100ms, so the export now states `duration: 100`. `.ad` positional gesture parsing is NOT removed. Its only remaining callers are the CLI argv parse and the `.ad` line parse, both the current public syntax rather than a bridge to an older one, so there is nothing to migrate off. ADR 0013 records that and drops the "compatibility" framing that made it read as debt. Both migrated fixtures verified on real devices with the repo's own CLI: iOS simulator 34.9s, Android emulator 45.9s. * fix(gestures): reject removed swipe input at the Node/MCP boundary Review findings on d88c6ed8. P1: `interactionDaemonWriters.swipe` hand-projects five fields, so a JavaScript caller's `durationMs` was dropped before the daemon's `readSwipeInput` could reject it and a default-duration fling ran instead — the exact silent reinterpretation the guide promises does not happen. `gesture` was already safe because its writer runs `readGestureInput` -> `readGesturePayload`, which rejects the removed keys; `swipe` was the one surface with no reader of its own. The rejection now lives in contracts and is shared by the client writer and the daemon handler, so there is one rule and one message. The SDK regression covers all four removed keys and asserts the transport is never reached; reverting the writer call fails it on `swipe durationMs`. P2: the preflight's retired-slot test required a numeric token, so `swipe 197 650 197 300 ${DURATION}` fell back to bare usage text. An unresolved `${VAR}` now counts as the retired slot and is carried into the pan rewrite, while a stray flag or word stays a plain usage error. P2: the removal shipped in 0.20.0, not 0.21 — removal commit6d99914f4is contained in tag v0.20.0. The guide said 0.21 because the CHANGELOG still files it under `Unreleased`; the tag is the truth (headings lag several releases repo-wide, so that is pre-existing and left alone). The `.ad` grep recipe now matches variable-backed durations too. * docs(gestures): make the migration sweep and MCP claim accurate Re-review findings on 328bad8e (both migration-guide accuracy). The saved-script sweep matched only the five-argument `swipe` form; it missed timed `gesture fling`, timed `gesture swipe`, and `gesture rotate ... velocity`, so the repository-cleanliness step was incomplete. Provide one grep per retired form (number-or-`${VAR}` token), each verified to flag the removed shape and skip the valid one. The MCP section claimed the structured rejection carries the CLI's concrete replacement command. It does not: `readGesturePayload` and `assertNoRemovedSwipeInput` return a message that names the removed key and the replacement command (e.g. `gesture fling does not accept durationMs; use gesture pan for timed movement`) but not the fully-substituted coordinate rewrite, because the structured request carries no positional string to rewrite. Describe what the structured path actually returns. * docs(gestures): make the .ad sweep parser-aligned Re-review finding on4fd5d39: the documented sweep required literal single spaces and unquoted numeric tokens, but the `.ad` tokenizer separates on any whitespace (`/\s/`, so tabs too) and accepts double-quoted tokens, so tab-separated or quoted-duration stale lines the parser rejects were missed. Rewrite the patterns to follow the tokenizer: `[[:space:]]+` between tokens and a numeric slot that accepts a bare or double-quoted number (optionally signed) or `${VAR}`. Requiring a digit in the numeric slot keeps a trailing flag like `--count` from being read as the retired positional. Verified against a fixture of tab/space/quoted/quoted-var/negative encodings that the four greps flag exactly the lines `parseReplayScriptDetailed` rejects and none it accepts, and that the live repo sweeps clean. Also state plainly what a regex cannot promise: the parser is the authoritative gate — every retired form is rejected at parse time before any device action, so running the suite finds every stale line by construction and a missed grep can never reach execution. The grep stays a bulk pre-flight, and the "every affected line" claim is scoped to that.
ADR index — read this when…
| ADR | Read when you touch… |
|---|---|
| 0001 Provider-First Integration Scenarios | integration testing strategy, provider transcripts, the scenario harness |
| 0002 Persistent Platform Helper Sessions | helper process lifecycle, keep-alive semantics |
| 0003 Daemon Command Registry | daemon routing, request-policy traits |
| 0004 iOS Snapshot Backend Strategy | snapshot capture plans, backend fallbacks, quality verdicts |
| 0005 iOS Runner Interaction Lifecycle | XCTest runner sessions, leases, adoption, idle-stop |
| 0006 Daemon RPC Protocol Version | remote daemon HTTP/JSON-RPC compatibility |
| 0007 Remote Device Leases | leases, tenancy, provider-owned devices |
| 0008 Command Descriptor Registry | adding/changing a command, any surface projection (CLI/MCP/client/batch), timeout policy |
| 0009 Apple Platform Consolidation | Apple platform family, apple/appleOs axes, the apple-leak guard |
| 0010 Error system conventions | error codes, hints, normalizeError, typed error signals |
| 0011 Interaction Guarantee Contract | interaction dispatch paths, fast paths, guards, the guarantee matrix, parity tables |
| 0012 Interactive Replay | replay healing/--update, diagnostic resolution disclosure, bounded .ad target-binding evidence, bounded divergence wire/error handling, plan-bound replay-only --from semantics, and agent-supervised re-record repair ("heal-by-doing") |
| 0013 Unified Gesture Plans | gesture API/routing, contact topology, multi-touch geometry, native pointer injection, two-finger pan |
| 0014 Session Ref-Frame Lifetime | ref authorization epochs, complete/partial issuance, pre-side-effect expiration, replay/batch compatibility, and cross-platform stale-mutation policy |
| 0015 Direct Maestro Compatibility Engine | Maestro YAML parsing/execution, compatibility observation policy, conformance, performance gates, gesture integration |
| 0016 Active-Session Script Publication | publishing an armed open-to-destination .ad script without closing its live session |
| 0017 Parameterized Recorded Inputs | safely authoring sensitive fill inputs as ${VAR} placeholders across recording, replay, and repair |
ADRs record why; the registries and gates they describe are the living source of truth — when prose and a registry disagree, the registry wins and the ADR needs a follow-up.
Shape conventions, so consulting an ADR stays cheap:
- Normative rules first, terse. Status, then a "Rules at a glance" summary a reader can stop after; full contracts and rationale below it.
- Rationale and refuted alternatives stay in the ADR — they are what stops re-litigating settled ideas — but below the fold.
- Process history is deleted once complete, not archived in-file. Migration plans, per-step landing tables, and point-in-time status change-logs go to git history; the Status section keeps one line saying so plus any accepted, still-relevant waiver or evidence gap.
- Once a rule is gate-enforced, the ADR keeps the why and points at the gate rather than restating the rule's details.