Skip to content

Commit 943abd2

Browse files
committed
Merge remote-tracking branch 'origin/main' into HEAD
* origin/main: perf: bundle runtime dependencies and report full install size (#2310) ci: avoid unrelated Apple runner cache invalidation (#2303) fix(web): preserve the backend ref so snapshot refs match actionable refs (#2283) test(daemon): session-open-url-prewarm through the request seam (#2304) test(daemon): session-devices-batch-runtime through the request seam (#2305) chore(gates): layering baselines ratchet against merge-base (#2299) test(daemon): one typed conformance helper for the daemon runtime suites (#2298) chore(layering): derive the contracts export inventory from package.json (#2297) perf: bundle tar-stream to reduce install footprint (#2286) docs: simplify agent context and resolve conflicting guidance (#2287) refactor(cli): let help resolve command aliases itself and retire R12 (#2293)
2 parents 453d28e + 7a2d48d commit 943abd2

71 files changed

Lines changed: 2590 additions & 2871 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/setup-apple-runner-build/action.yml

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ runs:
4444
id: source-hash
4545
run: |
4646
set -euo pipefail
47-
echo "value=${{ hashFiles('apple/runner/**', 'apple/snapshot-presentation/**', 'scripts/build-xcuitest-apple.sh', 'scripts/patch-xcuitest-runner-icon.ts', 'scripts/write-xcuitest-cache-metadata.mjs', 'packages/platform-apple/src/runner/apple-runner-platform.ts', 'packages/platform-apple/src/runner/runner-cache-metadata.ts', 'packages/platform-apple/src/runner/runner-icon.ts', 'packages/platform-apple/src/runner/runner-xctestrun.ts', 'packages/platform-apple/src/runner/runner-xctestrun-products.ts', '.github/actions/setup-apple-runner-build/action.yml', 'package.json', 'pnpm-lock.yaml') }}" >> "$GITHUB_OUTPUT"
47+
echo "value=${{ hashFiles('apple/runner/**', 'apple/snapshot-presentation/**', 'scripts/build-xcuitest-apple.sh', 'scripts/swift-toolchain-tmpdir.ts', 'scripts/patch-xcuitest-runner-icon.ts', 'scripts/write-xcuitest-cache-metadata.mjs', 'packages/platform-apple/src/runner/apple-runner-platform.ts', 'packages/platform-apple/src/runner/runner-cache-metadata.ts', 'packages/platform-apple/src/runner/runner-icon.ts', 'packages/platform-apple/src/runner/runner-xctestrun.ts', 'packages/platform-apple/src/runner/runner-xctestrun-products.ts', '.github/actions/setup-apple-runner-build/action.yml') }}" >> "$GITHUB_OUTPUT"
4848
shell: bash
4949

5050
- name: Resolve Apple runner build variant
@@ -55,12 +55,19 @@ runs:
5555
INPUT_XCUITEST_DESTINATION: ${{ inputs.xcuitest-destination }}
5656
run: |
5757
set -euo pipefail
58+
BUILD_COMMANDS="$(node -p 'JSON.stringify(Object.entries(require("./package.json").scripts).filter(([name]) => name.startsWith("build:xcuitest:")))')"
5859
VARIANT="$(
5960
printf '%s\n' \
6061
"$INPUT_GATE" \
62+
"$BUILD_COMMANDS" \
63+
"$(uname -m)" \
6164
"$INPUT_XCUITEST_PLATFORM" \
6265
"$INPUT_XCUITEST_DESTINATION" \
6366
"${AGENT_DEVICE_XCUITEST_INCLUDE_UNIT_TESTS:-0}" \
67+
"${AGENT_DEVICE_XCUITEST_ARCHS:-}" \
68+
"${AGENT_DEVICE_IOS_BUNDLE_ID:-}" \
69+
"${AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID:-}" \
70+
"${AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID:-}" \
6471
| shasum -a 256 \
6572
| cut -c1-16
6673
)"
@@ -89,4 +96,23 @@ runs:
8996
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.2.3
9097
with:
9198
path: ${{ inputs.derived-path }}
92-
key: ${{ inputs.cache-key-prefix }}-${{ steps.xcode.outputs.key }}${{ inputs.cache-key-suffix }}-${{ steps.build-variant.outputs.key }}-${{ steps.source-hash.outputs.value }}
99+
key: ${{ steps.restore-runner-build.outputs.cache-primary-key }}
100+
101+
- name: Report Apple runner build cache
102+
env:
103+
CACHE_HIT: ${{ steps.restore-runner-build.outputs.cache-hit }}
104+
CACHE_KEY: ${{ steps.restore-runner-build.outputs.cache-primary-key }}
105+
BUILD_GATE: ${{ inputs.gate }}
106+
run: |
107+
set -euo pipefail
108+
if [ "$CACHE_HIT" = 'true' ]; then
109+
RESULT='restored exact prebuilt runner; compilation skipped'
110+
else
111+
RESULT='cache miss; built runner and attempted cache save'
112+
fi
113+
{
114+
printf '### Apple runner cache (%s)\n\n' "$BUILD_GATE"
115+
printf '%s\n\n' "$RESULT"
116+
printf 'Key: `%s`\n' "$CACHE_KEY"
117+
} >> "$GITHUB_STEP_SUMMARY"
118+
shell: bash

.github/workflows/ci.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,12 @@ jobs:
100100
runs-on: ubuntu-latest
101101
timeout-minutes: 15
102102
steps:
103+
# The layering ratchets (R6/R9/R10) measure the merge-base with origin/main, which a
104+
# shallow checkout cannot reach.
103105
- name: Checkout
104106
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
107+
with:
108+
fetch-depth: 0
105109

106110
# The layering gate parses production sources with `oxc-parser`, so
107111
# dependencies are required; keep install-deps enabled.
@@ -117,7 +121,7 @@ jobs:
117121

118122
# Model tests for the dependency-graph report and its blast-radius query. The report
119123
# reads the gate's model (scripts/layering/model.ts) and applies the gate's own R6
120-
# counting rule, so it is not a second measurement of TYPE_INVERSION_BASELINE.
124+
# counting rule, so it is not a second measurement of the R6 ratchet.
121125
- name: Check the depgraph report model
122126
uses: ./.github/actions/run-gate
123127
with: { gate: depgraph }

.github/workflows/size.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@ jobs:
9999
--startup-runs 7 \
100100
--json .tmp/size-report.json \
101101
--markdown .tmp/size-report.md
102+
cp /tmp/agent-device-size-base.json .tmp/size-report-base.json
103+
104+
- name: Upload detailed size reports
105+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
106+
with:
107+
name: size-report
108+
path: .tmp/size-report*.json
109+
include-hidden-files: true
110+
if-no-files-found: error
102111

103112
- name: Add job summary
104113
run: cat .tmp/size-report.md >> "$GITHUB_STEP_SUMMARY"

AGENTS.md

Lines changed: 30 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
`agent-device` is a CLI and daemon for automating Apple, Android, HarmonyOS, Vega, Linux, and web
44
targets. A long-lived daemon owns sessions; registry-derived commands route to platform runtimes.
55

6-
This file contains repository-specific traps and invariants that are expensive to rediscover. Load
7-
task procedures only when needed:
6+
## Task routing
7+
8+
Load only the procedures relevant to the task:
89

910
| When the task involves | Read |
1011
| --- | --- |
@@ -14,35 +15,28 @@ task procedures only when needed:
1415
| Selector capture, polling, or interaction fast paths | `docs/agents/selector-capture.md` |
1516
| Adding or changing a CLI flag | `docs/agents/cli-flags.md` |
1617
| Opening or reviewing a PR | `docs/agents/pull-requests.md` |
17-
| Running against a real device | `docs/agents/device-verification.md` |
18+
| Apple runner changes or manual device verification | `docs/agents/device-verification.md` |
1819
| Writing issues or PRDs, and triage labels | `docs/agents/issue-tracker.md`, `docs/agents/triage-labels.md` |
1920
| Web backend setup or diagnostics | `docs/agents/web-backend.md` |
2021

21-
Versioned CLI help is the source of truth for command behavior. Start with `agent-device help
22-
workflow`, then the relevant topic help.
22+
Versioned CLI help owns command semantics. Read the relevant topic when behavior is unclear;
23+
normal app-driving startup follows the skill's routing card.
2324

2425
## Incident-derived principles
2526

26-
- Guarantees erode at path boundaries. Classify every interaction dispatch path in
27-
`packages/contracts/src/interaction-guarantees.ts`; a registry claim is not proof that the native
28-
implementation satisfies the guarantee's definition.
27+
- Classify interaction dispatch paths in `packages/contracts/src/interaction-guarantees.ts` and
28+
verify each claim against the native implementation.
2929
- Delegation on error proves no success-path parity. A fast path may succeed on a candidate the
3030
shared rules would refuse.
31-
- Prove that a code path can fire before measuring it. An A/B test with an unreachable arm is two
32-
green runs without evidence.
33-
- A green regression test counts only after it has been observed red against the pre-fix code. Plant
34-
a violation for new structural gates and verify the gate names the invariant.
35-
- Repair recurring failures at their owning interface with types, a registry, or one construction
36-
path. A custom guard that reconstructs another source of truth needs redesign, not another
37-
exception.
38-
- Treat explanatory implementation comments as a failed design review. Do not narrate control flow,
39-
preserve review history, or justify a workaround in code. Express the invariant through names,
40-
types, module boundaries, and tests; put history in the PR or an ADR. Allow only public API docs,
41-
tool directives, and a brief citation to an external constraint that cannot be encoded.
42-
- Key behavior on typed reasons and details, never error text. Existing message sniffs are owned debt
43-
and must not be copied.
44-
- Snapshot output is the token budget: do not add per-node metadata when response-level metadata can
45-
be emitted once. Append warnings through the shared response builder; never replace prior warnings.
31+
- Prove both paths are reachable before measuring a fast path against its baseline.
32+
- Repair recurring failures at the owning type, registry, or construction path; do not add guards
33+
that reconstruct another source of truth.
34+
- Keep control-flow narration and review history out of implementation comments. Encode invariants
35+
in names, types, boundaries, and tests; reserve comments for public API docs, tool directives,
36+
and non-obvious constraints that cannot be encoded.
37+
- Key behavior on typed reasons and details, never error text; do not copy existing message sniffs.
38+
- Keep metadata at response level when it applies to the whole snapshot. Append warnings through
39+
the shared response builder; never replace prior warnings.
4640
- Before preserving a compatibility shape, run `git tag --contains <commit>`. Unreleased API has no
4741
external compatibility obligation.
4842

@@ -66,10 +60,10 @@ and progress in `@agent-device/capture-kit` (`request-cancel`, `request-progress
6660
contracts in `@agent-device/contracts`; CLI flags in `src/commands/cli-grammar`; cross-surface schema
6761
composition in `src/cli-schema`.
6862

69-
The enforced registries are self-declaring. A failing completeness, parity, coverage, timeout,
70-
layering, or construction gate means the new cell or path is unclassified; do not suppress or
71-
allowlist it. Interaction responses are built only through `buildInteractionResponseData`, and
72-
cross-language rules change through golden tables under `contracts/fixtures/`.
63+
Resolve registry completeness failures at the missing declaration. Diagnose other gate failures
64+
at their reported invariant; do not suppress them or add an allowlist to get a pass. Build interaction
65+
responses through `buildInteractionResponseData`; change cross-language rules through golden tables
66+
under `contracts/fixtures/`.
7367

7468
## Hard repository rules
7569

@@ -78,9 +72,9 @@ cross-language rules change through golden tables under `contracts/fixtures/`.
7872
- Apple target changes keep the kernel device model, runtime-fact admission, dispatch resolution,
7973
Apple discovery, and xctestrun preparation in sync.
8074
- iOS simulator-set scoping must never hide the host macOS desktop target.
81-
- Skills may carry a minimal start/routing card; command semantics belong in versioned CLI help.
82-
- Do not add compatibility or fallback behavior without explicit approval. Complete migrations and
83-
remove superseded paths.
75+
- Skills stay minimal routing cards.
76+
- Add compatibility or fallback behavior only when explicitly requested or approved. Otherwise,
77+
complete the migration and remove superseded paths.
8478
- Keep changes within one command family or module group unless the task explicitly crosses a
8579
boundary. Platform-neutral work does not license inspecting every platform implementation.
8680

@@ -93,7 +87,6 @@ cross-language rules change through golden tables under `contracts/fixtures/`.
9387
- Tests mirror source topology one-to-one. Split a source module and its test together; do not add to
9488
the legacy `interaction.test.ts` or platform `index.test.ts` aggregations. Pure moves carry their
9589
tests unchanged; rename-only hunks owe no new coverage.
96-
- Shared fixtures are named exports in a sibling fixture module, not repeated inline literals.
9790
- `src/daemon/handlers/session.ts` is already over budget; extract the relevant platform-specific
9891
concept before adding behavior.
9992

@@ -103,30 +96,14 @@ cross-language rules change through golden tables under `contracts/fixtures/`.
10396
repository-wide, not path-scoped.
10497
- A fresh worktree requires `pnpm install --frozen-lockfile && pnpm build`. Until then package and
10598
optional-peer resolution may point at another checkout and produce false failures.
106-
- Source-checkout daemon state is worktree-scoped, but devices are not. Use `pnpm daemon:state-dir`
107-
to inspect it and different devices for concurrent worktrees.
108-
- Run one full gate per host at a time. Subprocess-backed tests under concurrent worktrees produce
109-
timeout-shaped contention failures.
110-
- Before pushing, run `pnpm check:affected --run && git push`. Use `pnpm check` for broad refactors.
111-
GitHub remains authoritative for native, device, provider, and full-coverage lanes.
99+
- Parallel work needs disjoint edit ownership and distinct devices. Run one full gate per host;
100+
concurrent subprocess-backed suites can produce contention timeouts.
112101
- The layering scan reads tracked files only. Stage a new module before trusting its result.
113102
- Fallow baselines are path-keyed. Move the matching baseline entry when renaming a file; never bulk
114103
regenerate baselines to accept unrelated findings.
115-
- The first Node process after a newly signed Apple runner launches may block during Gatekeeper
116-
verification. Warm it with a throwaway `node -e 0` before measuring.
117-
- `DEVICE_IN_USE` has two flavors. "already in use by session X" is this daemon — follow its
118-
`close --session` hint. "owned by session X in workspace Y" is another worktree's device
119-
claim — non-retriable; run the error's `device status`/`device release --stale` recovery,
120-
never PID hunting.
121-
- A changing timeout failure set that passes in isolation is host contention. Reproduce the same
122-
test on `origin/main` under the same load before treating it as a regression.
123104

124105
## Runtime and diagnostics seams
125106

126-
The OS-neutral Apple runner lives under `packages/platform-apple/src/runner/`. For connection errors,
127-
retry policy, or command typing, start at `runner-contract.ts`; transport stays below session/client
128-
behavior, and xctestrun build/cache logic stays outside request execution.
129-
130107
Diagnostics use `@agent-device/capture-kit/diagnostics`. Request diagnostics belong in the session request log;
131108
session artifact paths come from `src/daemon/session-store.ts`. App/device logs remain in `app.log`;
132109
Apple runner and xcodebuild output remains in `runner.log`.
@@ -150,11 +127,8 @@ translate through the interaction root frame. Prefer selector or ref tests over
150127

151128
## Documentation ownership
152129

153-
Before adding guidance, decide whether the command surface, CLI grammar/help, MCP projection, daemon
154-
runtime, ADR, or task procedure owns it. Link to executable registries instead of copying their
155-
contents. Keep a sentence in this file only when no gate, lint rule, versioned help, ADR, or
156-
decision-site comment can own it. `CONTEXT.md` is glossary-only: no implementation paths,
157-
architecture decisions, migration state, or workflows.
130+
Keep this file to repository traps and routing. Put task procedures in `docs/agents/`, decisions in
131+
ADRs, and command semantics in versioned help. Link to executable registries instead of duplicating
132+
their rules. `CONTEXT.md` is glossary-only: no implementation paths, decisions, or migration status.
158133

159-
Behavior changes update their owning help/metadata and user docs. In the final summary,
160-
state whether docs or skills changed and why.
134+
Behavior changes update owning help/metadata and user docs. Report docs or skill changes when relevant.

docs/agents/cli-flags.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
# Adding a CLI Flag
22

3-
A new flag touches only the layers that need to understand it. Stop at the layer where it stops
4-
mattering — threading it further is the common failure, not stopping too early.
3+
Thread a flag only through the layers that consume it:
54

65
1. `packages/contracts/src/cli-flags.ts`: add to `CliFlags`; add the definition to the matching
76
`src/commands/cli-grammar/flag-definitions-*.ts` owner and the relevant group in `flag-groups.ts`
87
(for example `SNAPSHOT_FLAGS`). Then update the command family metadata/schema that exposes the
98
flag; find the owner with
109
`rg -n "<command>|supportedFlags|allowedFlags" src/commands src/cli-schema src/cli/parser`. For
11-
schema-only CLI commands (`cdp`, `auth`, `connect`, `proxy`, `react-devtools`, `web`) the owner is
12-
`SCHEMA_ONLY_CLI_COMMAND_SCHEMAS` in `src/cli-schema/command-overrides.ts`. New flags are
13-
operator-only by default. Add a flag to `PROJECT_CONFIG_FLAG_KEYS` in
10+
schema-only CLI commands, the owner is `SCHEMA_ONLY_CLI_COMMAND_SCHEMAS` in
11+
`src/cli-schema/command-overrides.ts`. New flags are operator-only by default. Add a flag to `PROJECT_CONFIG_FLAG_KEYS` in
1412
`src/cli-schema/cli-config.ts` only when repository control is safe; this positive allowlist is
1513
the completeness gate.
1614
2. `src/commands/cli-grammar/*`: read the CLI flag into command input.

0 commit comments

Comments
 (0)