mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
59d28e8446
* refactor: add provider-first device lab tests * refactor: tighten device lab provider seams * test: cover provider lab contracts * docs: record device lab harness direction * ci: run device lab integration tests * test: move device lab under integration * test: extract device lab helpers * refactor: centralize apps filter defaults * test: drop lab-covered unit tests * test: fold platform happy paths into device lab * test: reuse device lab helpers * test: move device lab to in-process harness * test: replace session handler cases with device lab * test: harden device lab scenario contracts * docs: define unit test retention policy * test: expand provider device lab coverage * test: harden provider device lab coverage * test: cover manifest install and runner session contracts * chore: remove unused provider cleanup code * test: split android find device lab scenario * test: track provider lab architecture progress * test: clarify provider lab roadmap progress * test: advance provider lab session coverage * test: move menubar click routing to device lab * test: move menubar snapshots to device lab * refactor: centralize screenshot flag plumbing * refactor: colocate screenshot flag metadata * test: cover all public commands in device lab * test: move macos wait success to device lab * test: drop redundant perf and diff units * test: move push payload paths to device lab * test: move network parsing to device lab * test: move log cleanup to device lab * test: move log restart and boot to device lab * test: move ios physical boot to device lab * test: cover perf startup in device lab * test: extract android and ios device lab worlds * test: trim device lab world surface * test: split snapshot capture unit coverage * test: deepen device lab coverage and trim handler units * test: clean up device lab migration scaffolding * test: report device lab public command coverage * refactor: make Apple provider seams semantic * refactor: tighten device inventory and Linux provider seams * refactor: tighten request provider scoping * refactor: add semantic macos host provider * test: broaden device lab find coverage * test: cover workflow flags in device lab * refactor: promote linux input provider seam * test: clarify device lab flag coverage * test: classify snapshot force-full progress * test: enforce device lab progress in ci * test: stabilize device lab ci * test: move packaged metro smoke to integration * test: drop stale provider seam coverage * test: harden provider scope regression coverage * refactor: remove stale platform barrels * refactor: keep linux clipboard and screenshots semantic * refactor: move macos host tools behind provider * fix: honor remote artifact output paths * test: deepen runtime coverage for daemon and runner paths * test: share loopback test helpers * refactor: make daemon runtime importable * fix: honor replay target metadata * chore: tighten final device lab quality gates * test: share device lab setup helpers * test: remove generic apple lab fallback * test: deduplicate device lab helpers * chore: tighten fallow duplication signal * refactor: share apple diagnostic helpers * fix: detect active android ime during fill verification * test: consolidate provider-backed integration suite * ci: fix fallow and iOS smoke setup * chore: consolidate cleanup after ci fixes * test: split vitest unit and integration projects * docs: mention MCP discovery metadata * docs: add agent skills context pointers * fix: close provider recording coverage gaps * fix: restore mcp compatibility smoke * test: cover provider edge regressions * test: consolidate loopback helpers * docs: remove stale provider routing reference * fix: harden final provider review issues * chore: defer mcp cleanup from provider refactor
20 KiB
20 KiB
AGENTS.md
Minimal operating guide for AI coding agents in this repo.
Agent skills
Issue tracker
Issues and PRDs live in GitHub Issues for callstackincubator/agent-device. See docs/agents/issue-tracker.md.
Triage labels
Use the default Matt Pocock skills triage vocabulary: needs-triage, needs-info, ready-for-agent, ready-for-human, and wontfix. See docs/agents/triage-labels.md.
Domain docs
Single-context repo. Read CONTEXT.md for domain language and testing/architecture vocabulary, and docs/adr/ for accepted architecture decisions. See docs/agents/domain.md.
First 60 Seconds
- Classify task type:
- Info-only (triage/review/questions/docs guidance): no code edits and no test runs unless explicitly requested.
- Code change: make minimal scoped edits and run only required checks from Testing Matrix.
- State assumptions explicitly. If uncertain, ask.
- If the task touches tooling/builds/linting, read
package.jsonandtsconfig*.jsonbefore source files. - Prefer repo scripts over reconstructing command bundles by hand:
pnpm check:quick: lint + typecheckpnpm check:tooling: lint + typecheck + buildpnpm check:unit: unit + smokepnpm check: full non-integration validation
- Read at most 3 files first:
- owning handler/module
- one shared helper used by that handler
- one downstream platform file if needed
- Define verifiable success criteria before editing.
- Decide docs/skills impact up front.
Scope
- Solve issues with the smallest context read.
- Keep changes scoped to one command family or module group.
- Preserve daemon session semantics and platform behavior.
- Expand only when contracts cross module boundaries.
- Do not read both iOS and Android paths unless explicitly cross-platform.
- If requested fix expands beyond one command family/module group, stop and confirm before broadening scope.
Code Changes
- Minimum code that solves the problem. No speculative features.
- No abstractions for single-use code.
- Surgical edits only.
- Match existing style.
- Remove imports/variables YOUR changes made unused; do not clean unrelated dead code.
- Keep tests minimal: if TypeScript can enforce a contract or invalid shape, prefer a type-level check over duplicating that assertion in runtime tests.
- Keep modules small for agent context safety:
- target <= 300 LOC per implementation file when practical.
- if a file grows past 500 LOC, plan/extract focused submodules before adding new behavior.
- exception: generated files, schema/fixture snapshots, and integration test aggregations.
Routing
- Keep
src/daemon.tsas a thin router. - Keep command names and daemon routing groups centralized in
src/command-catalog.ts; do not re-create command string sets in handlers or request policy modules. - Keep CLI/client positional grammar in
src/command-codecs.tsand itssrc/command-codecs/*command-family modules. CLI commands, typed client methods, and daemon interaction adapters should reuse these codecs instead of duplicating selector/ref/positionals parsing. - Keep
src/daemon/request-router.tsas request orchestration: auth, diagnostics scope, request admission, locking, handler chain, and fallback dispatch. - Put request policies in focused request modules:
- tenant/lease/selector/lock admission:
src/daemon/request-admission.ts - artifact/error finalization:
src/daemon/request-finalization.ts - request-scoped platform provider scoping:
src/daemon/request-platform-providers.ts - generic fallback dispatch + action recording:
src/daemon/request-generic-dispatch.ts - recording invalidation health:
src/daemon/request-recording-health.ts
- tenant/lease/selector/lock admission:
- Put command logic in handler modules:
- session/apps/appstate/open/close/replay/logs:
src/daemon/handlers/session.ts - click/fill/get/is:
src/daemon/handlers/interaction.ts - snapshot/wait/alert/settings:
src/daemon/handlers/snapshot.ts - find:
src/daemon/handlers/find.ts - record/trace:
src/daemon/handlers/record-trace.ts
- session/apps/appstate/open/close/replay/logs:
- Generic passthrough (press/scroll/type) is daemon fallback only after handlers return null.
Toolchain Snapshot
- Package manager:
pnpmonly. Do not add or restorepackage-lock.json. - Runtime baseline is Node >= 22. Prefer built-in Node APIs such as global
fetch, Web Streams, andAbortSignal.timeoutover compatibility wrappers unless the surrounding code needs a lower-level transport. - Lint/format stack is OXC:
- config:
.oxlintrc.json,.oxfmtrc.json
- config:
- TypeScript is strict enough to surface dead code early:
strict,isolatedModules,noUnusedLocals, andnoUnusedParametersare enabled. - The repo emits with
rslib, nottsc. If declaration generation fails, inspecttsconfig.lib.jsonfirst. tsconfig.lib.jsonneeds an explicitrootDir: "./src"for declaration layout.- Use the aggregate scripts in
package.jsonwhen possible; they encode the expected validation bundles better than ad hoc command lists.
Cheap Exploration
- Prefer these first-pass commands over broader reads:
rg -n "<symbol|command|flag>" src testrg --files src/daemon/handlers src/platforms/ios src/platforms/androidgit diff -- <path>for active-branch context- read
.oxlintrc.jsonbefore treating lint output as source-level bugs
- If build/type errors mention declaration generation, inspect
tsconfig.lib.jsonbefore reading platform code. - If lint failures appear after toolchain edits, check whether the rule is from
eslint/*,typescript/*,import/*, ornode/*in.oxlintrc.jsonbefore assuming source bugs.
Command Family Lookup
logs:src/daemon/handlers/session.ts->src/daemon/app-log.ts->src/daemon/handlers/__tests__/session.test.tsopen/close/replay/apps/appstate:src/daemon/handlers/session.ts->src/daemon/session-store.ts->src/daemon/handlers/__tests__/session.test.tsclick/fill/get/is:src/daemon/handlers/interaction.ts->src/daemon/selectors.ts->src/daemon/handlers/__tests__/interaction.test.tssnapshot/wait/settings/alert:src/daemon/handlers/snapshot.ts->src/daemon/snapshot-processing.ts->src/daemon/handlers/__tests__/snapshot-handler.test.tsrecord/trace:src/daemon/handlers/record-trace.ts->src/platforms/ios/runner-client.ts->src/daemon/handlers/__tests__/record-trace.test.ts
iOS Runner Seams
- Keep dependency direction clean:
runner-client.ts: command execution + retry behaviorrunner-transport.ts: connection/probing/HTTP transportrunner-contract.ts: sharedRunnerCommandtype and runner connect/error helpersrunner-session.ts: session lifecycle and request/response executionrunner-xctestrun.ts: xctestrun preparation/build/cache logic
runner-transport.tsmust not import back fromrunner-client.ts.- If changing runner connect errors, retry policy, or command typing, start in
src/platforms/ios/runner-contract.tsbefore touching client/transport files.
Adding a New CLI Flag
A new snapshot/command flag touches up to 7 files in a fixed order. Follow this checklist:
src/utils/command-schema.ts: add toCliFlagstype,FLAG_DEFINITIONSarray, and the relevant*_FLAGSconstant (e.g.SNAPSHOT_FLAGS). Update the command'susageOverridestring.src/utils/snapshot.ts(or the relevant options type): add toSnapshotOptionsor equivalent.src/client-types.ts: add toCaptureSnapshotOptions(or equivalent public options type) andInternalRequestOptions.src/client-normalizers.ts: map the public option name to the internal flag name inbuildFlags.src/daemon/context.ts: add toDaemonCommandContexttype andcontextFromFlagsfunction.src/core/dispatch-context.ts: add toDispatchContextwhen the flag flows into platform dispatch, then thread it through the relevant dispatcher module.src/cli/commands/<command>.ts: pass the flag fromflags.*to the client call.
Command-only flags (like find --first) that don't flow to the platform layer only need steps 1 and the handler file.
Hard Rules
- Use process helpers from
src/utils/exec.tsfor TypeScript process execution:runCmd,runCmdStreaming,runCmdSync,runCmdBackground, andrunCmdDetached. Do not import rawspawn/spawnSyncoutsidesrc/utils/exec.ts; add or extend an exec helper instead. Plain.mjspackaging fixtures that cannot import TypeScript helpers should keep child-process usage local and preferexecFile/execFileSyncover spawn. - Use daemon session flow for interactions (
openbefore interactions,closeafter). - Use
keyboard dismissfor iOS keyboard dismissal; it may tap safe native controls such asDonebut must not fall back to system back navigation. - Do not remove shared snapshot/session model behavior without full migration.
- Command/device support must come from
src/core/capabilities.ts. - Apple-family target changes must keep
src/utils/device.ts,src/core/capabilities.ts,src/core/dispatch-resolve.ts,src/platforms/ios/devices.ts, andsrc/platforms/ios/runner-xctestrun.tsin sync. - iOS simulator-set scoping is iOS-specific: do not let
iosSimulatorDeviceSethide the host macOS desktop target when--platform macosor--target desktopis requested. - If Swift runner code changes, run
pnpm build:xcuitest. - Use
inferFillTextanduniqueStringsfromsrc/daemon/action-utils.ts. - Use
evaluateIsPredicatefromsrc/daemon/is-predicates.tsfor assertion logic.
Logs Contract
- Logs backend/source of truth is
src/daemon/app-log.ts. session.tsshould orchestrate only (start/stop/path/doctor/mark), not duplicate backend logic.- Preserve external grep/tail workflow in docs/skills.
Diagnostics & Errors
- Diagnostics source of truth:
src/utils/diagnostics.tswithDiagnosticsScope,emitDiagnostic,withDiagnosticTimer,flushDiagnosticsToSessionFile
- Do not add ad-hoc stderr/file logging where diagnostics helpers apply.
- Normalize user-facing failures via
src/utils/errors.ts(normalizeError). - Failure payload contract:
code,message,hint,diagnosticId,logPath,details. - Preserve
hint,diagnosticId,logPathwhen wrapping/rethrowing errors. --debugis canonical;--verboseis backward-compatible alias.- Keep redaction centralized in diagnostics helpers.
Optional Optimizations
- Treat optional optimization calls such as cache/preflight/probe requests as best-effort unless the feature contract says they are required. If an optimization fails, times out, returns non-OK, or returns an unusable shape, prefer falling back to the existing required command path.
- Keep optimization timeouts shorter than the underlying operation timeout. A preflight should not consume the full budget for a later upload or command.
React Native Verification
- After changing runtime code exercised through
bin/agent-device.mjsor the daemon, runpnpm buildandpnpm clean:daemonbefore manual device verification so snapshots use currentdistoutput. - For Android RN/Expo/dev-client apps connected to any local Metro port,
adb reverse tcp:<port> tcp:<port>is harmless and should be run before opening the app or URL on the emulator/device.
Selector System Rules
- Interaction commands (
click,fill,get,is) andwaitaccept selectors and@ref. - Pipeline: parse -> resolve -> act -> record selectorChain -> heal on replay.
- Keep selector parsing/matching in
src/daemon/selectors.ts. - Call
buildSelectorChainForNodeafter resolving target nodes. - New element-targeting interactions must support selector +
@ref, recordselectorChain, and hook replay healing (healReplayActioninsession.ts+ selector helpers insession-replay-heal.ts). - New selector keys remain centralized in
selectors.ts. - New
ispredicates belong inevaluateIsPredicate. - On macOS, snapshot rects are absolute in window space. Point-based runner interactions must translate through the interaction root frame; do not assume app-origin
(0,0)coordinates. - Prefer selector or
@refinteractions over raw x/y commands in tests and docs, especially on macOS where window position can vary across runs.
Shared Test Utilities
- Before writing a new test, check
src/__tests__/test-utils/for existing helpers:device-fixtures.ts: canonicalDeviceInfoconstants (ANDROID_EMULATOR,IOS_SIMULATOR,IOS_DEVICE,MACOS_DEVICE,LINUX_DEVICE, etc.)session-factories.ts:makeSession,makeIosSession,makeAndroidSession,makeMacOsSessionstore-factory.ts:makeSessionStore(creates tempSessionStoreinstances)snapshot-builders.ts:buildNodes,makeSnapshotStatemocked-binaries.ts:withMockedAdb,withMockedXcrun(stub CLI binaries for dispatch tests)
- Use
import { ... } from '<relative-path>/__tests__/test-utils/index.ts'for convenient barrel imports. - Prefer shared fixtures over inlining new
DeviceInfoorSessionStateobjects in tests. - Do not duplicate
makeSessionStore,makeSession, or device constants when a shared helper already exists.
Testing Matrix
- Docs/skills only: no tests required unless a more specific rule below applies.
- CLI help/guidance changes in
src/utils/command-schema.ts: runpnpm exec vitest run src/utils/__tests__/args.test.ts. - SkillGym prompt/assertion changes: run the touched
--casechecks. For broad validation, usepnpm test:skillgym; use--tag fixture-smokeor--tag skill-guidancewhen validating one suite group. - Non-TS, no behavior impact: no tests unless requested.
- Keep tests behavioral; do not assert shapes or cases TypeScript already proves.
- Any TS change:
pnpm typecheckorpnpm check:quick. - Tooling/config change (
package.json,tsconfig*.json,.oxlintrc.json,.oxfmtrc.json):pnpm check:tooling. - Daemon handler/shared module change:
pnpm check:unit. - iOS runner/Swift change:
pnpm build:xcuitest. - Cross-platform behavior change: run
pnpm test:integration. - Any change in:
src/,test/,skills/:pnpm format.
Token Guardrails
- Do not read unrelated files once owning module is identified.
- Do not run integration tests by default.
- Do not inspect both iOS and Android codepaths unless task requires both.
- Prefer targeted
git diff -- <paths>over broad file reads during review. - Prefer
snapshot -i,find, and scoped selectors over repeated full snapshot dumps when exploring Apple desktop UIs. - Keep PR summaries short and scoped.
Common Mistakes
- Adding command logic to
src/daemon.tsinstead of handlers. - Adding capability checks outside
src/core/capabilities.ts. - Inlining
ispredicate logic in handlers. - Returning non-normalized user-facing errors.
- Duplicating logs backend logic in handlers instead of
src/daemon/app-log.ts. - Growing
src/daemon/handlers/session.tsorsrc/platforms/ios/apps.tsfurther without extracting Apple-family/macOS-specific helpers first. - Reintroducing an npm lockfile or assuming ESLint/Prettier still exist in this repo.
- Changing
tsconfig.lib.json/build tooling without runningpnpm check:tooling; declaration generation is stricter thantsc --noEmit.
Docs & Skills
- Versioned CLI help is the agent-facing source of truth. Put workflow guidance in
src/utils/command-schema.tshelp topics and assert important copy insrc/utils/__tests__/args.test.ts. - Skills are thin routers. Keep
skills/**/SKILL.mdfocused on when to use the skill, version gating, whichagent-device help <topic>page to read, and a short default loop. Do not duplicate full CLI manuals in skills. - For behavior/CLI surface changes, update the versioned help instructions in
src/utils/command-schema.tsand assert important help copy insrc/utils/__tests__/args.test.ts. Also updateREADME.mdand relevantwebsite/docs/**when user-facing docs need it. - For behavior/CLI surface changes and command-planning guidance changes, write or update a SkillGym case in
test/skillgym/suites/agent-device-smoke-suite.tsthat captures the expected agent command plan. - Do not update
skills/**/SKILL.mdfor command behavior or workflow guidance unless the user explicitly asks; skills must route to versioned CLI help instead of carrying behavior details. - Keep SkillGym cases behavioral and command-planning oriented. Prefer prompts that assert the user-visible contract and expected command family over brittle exact output, but forbid known bad patterns.
- Build before SkillGym when local CLI help is needed:
pnpm build, thenpnpm exec skillgym run ... --case <id>. - Run SkillGym broad validation with
pnpm test:skillgym; use v0.8--tagfilters for focused suite groups. - Preserve current high-value workflow guidance:
- iOS Expo Go dogfood: prefer
agent-device open "Expo Go" <url> --platform ioswhen the shell is known, thensnapshot -ito confirm the project UI rather than the runner splash. keyboard dismissis the preferred iOS keyboard-dismissal path before manually pressing visible keyboard controls such asDone; it remains best-effort and can report unsupported layouts explicitly.- Empty replacement is not a supported clear-field command; do not document or test
fill <target> ""as clearing. Prefer visible clear/reset controls or report the tool gap. - Mutating commands against one session must run serially. Parallelize only read-only commands or commands on separate sessions/devices.
- iOS Expo Go dogfood: prefer
- In final summaries, state whether docs/skills were updated; if not, explain why.
When Blocked
- If blocked by network/device/auth/permissions, stop and report:
- blocker
- why it blocks completion
- exact next command/action needed to unblock
Key Files
- CLI parse + formatting:
src/bin.ts,src/cli.ts,src/utils/args.ts - Daemon client transport:
src/daemon-client.ts - Daemon state/store:
src/daemon/session-store.ts - Selector DSL and matching:
src/daemon/selectors.ts ispredicate evaluation:src/daemon/is-predicates.ts- Shared action helpers:
src/daemon/action-utils.ts - Snapshot shaping + labels:
src/daemon/snapshot-processing.ts - Handler context helpers:
src/daemon/context.ts,src/daemon/device-ready.ts - Request routing/policy:
src/daemon/request-router.ts,src/daemon/request-admission.ts,src/daemon/request-generic-dispatch.ts - Dispatcher + capability map:
src/core/dispatch.ts,src/core/dispatch-context.ts,src/core/dispatch-interactions.ts,src/core/capabilities.ts - Command catalog + positional codecs:
src/command-catalog.ts,src/command-codecs.ts,src/command-codecs/* - Platform backends:
src/platforms/ios/*,ios-runner/*,src/platforms/android/*
Pull Requests
- Before opening PR: ensure no conflict markers/unmerged paths.
- Commit messages and PR titles should use conventional prefixes such as
feat:,fix:,chore:,perf:,refactor:,docs:,test:,build:, orci:as appropriate. - Do not use bracketed automation prefixes such as
[codex]or similar bot tags in commit messages or PR titles. - Open a ready-for-review PR by default. Use a draft PR only when the user explicitly asks for one or the work is intentionally incomplete.
- Run required checks for touched scope from Testing Matrix.
- PR body must be short and include:
## Summary: describe the user-visible or reviewer-relevant change as before/after when useful, and include the issue closed by the PR usingCloses #123when applicable.## Validation: answer this prompt in concise prose: "How did you verify the change, and what passed or changed on screen?" Prefer evidence over command dumps; mention the relevant check category or scenario, and include screenshots when visual/UI behavior is relevant.
- Call out known gaps/follow-ups explicitly.
- Include touched-file count and note if scope expanded beyond initial command family.
Priority Order
- When guidance conflicts, apply in this order: Hard Rules -> Scope -> Testing Matrix -> style/preferences.