@swmansion/argent 0.32.1-next.0 → 0.32.1-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/cli-cmds.mjs +1 -1
  2. package/dist/installer.mjs +7 -7
  3. package/dist/mcp-server.mjs +1 -1
  4. package/dist/tool-args.generated.d.ts +178 -178
  5. package/dist/tool-server.cjs +1270 -1459
  6. package/package.json +1 -1
  7. package/rules/argent.md +19 -183
  8. package/skills/argent-android-emulator-setup/SKILL.md +5 -13
  9. package/skills/argent-create-e2e/SKILL.md +1 -1
  10. package/skills/argent-create-e2e/references/e2e-yaml.md +12 -17
  11. package/skills/argent-create-e2e/references/live-authoring.md +25 -65
  12. package/skills/argent-create-e2e/references/reliability-and-recovery.md +8 -8
  13. package/skills/argent-device-interact/SKILL.md +65 -367
  14. package/skills/argent-device-interact/references/chromium.md +4 -19
  15. package/skills/argent-device-interact/references/foldables.md +8 -0
  16. package/skills/argent-device-interact/references/harmonyos.md +13 -50
  17. package/skills/argent-ios-device-interact/SKILL.md +0 -1
  18. package/skills/argent-ios-device-setup/SKILL.md +1 -1
  19. package/skills/argent-ios-simulator-setup/SKILL.md +3 -9
  20. package/skills/argent-lens/SKILL.md +20 -75
  21. package/skills/argent-metro-debugger/SKILL.md +35 -101
  22. package/skills/argent-native-profiler/SKILL.md +23 -92
  23. package/skills/argent-qa-e2e/SKILL.md +5 -5
  24. package/skills/argent-react-native-app-workflow/SKILL.md +34 -203
  25. package/skills/argent-react-native-optimization/SKILL.md +10 -26
  26. package/skills/argent-react-native-optimization/references/fix-reference.md +11 -11
  27. package/skills/argent-react-native-optimization/references/lint-rules.md +4 -5
  28. package/skills/argent-react-native-optimization/references/semantic-checklist.md +2 -2
  29. package/skills/argent-react-native-profiler/SKILL.md +46 -110
  30. package/skills/argent-screen-recording/SKILL.md +18 -37
  31. package/skills/argent-screenshot-diff/SKILL.md +8 -52
  32. package/skills/argent-settings-permissions/SKILL.md +15 -117
  33. package/skills/argent-test-ui-flow/SKILL.md +20 -90
  34. package/skills/argent-tv-interact/SKILL.md +9 -34
  35. package/skills/argent-tv-interact/references/vega.md +23 -0
  36. package/agents/argent-environment-inspector.md +0 -107
  37. package/agents/references/quality-control-checklist.md +0 -45
  38. package/skills/argent-device-interact/references/gesture-examples.md +0 -114
  39. package/skills/argent-device-interact/references/secrets.md +0 -23
  40. package/skills/argent-metro-debugger/references/failure-scenarios.md +0 -14
  41. package/skills/argent-metro-debugger/references/source-maps.md +0 -27
  42. package/skills/argent-react-native-profiler/references/diagnostic-tools.md +0 -101
@@ -1,7 +1,8 @@
1
1
  # Phase 1: Lint Rules
2
2
 
3
3
  Run once at the project root. Catches mechanical issues deterministically.
4
- Install missing plugins before running: `npm install --save-dev eslint-plugin-react-perf`.
4
+ Install missing plugins before running. On ESLint 10, `eslint-plugin-react-native` crashes: install with `--legacy-peer-deps` (npm; pnpm only warns) and run `npx eslint@9`.
5
+ With React Compiler active, leave out the react-perf rules, `react/jsx-no-bind` and `react-native/no-inline-styles`, unless the compiler skips some components (`compilationMode: "annotation"`, `"use no memo"`, a `sources` filter).
5
6
 
6
7
  ## Rules
7
8
 
@@ -48,8 +49,6 @@ Install missing plugins before running: `npm install --save-dev eslint-plugin-re
48
49
 
49
50
  ## Procedure
50
51
 
51
- 1. Check if the project has an existing ESLint config.
52
- 2a. If yes, extend it with missing rules from above.
53
- 2b. If no config, create a temporary `.eslintrc.json` with all rules above.
54
- 2. Run: `npx eslint --format json <src_dir>`; replace `<src_dir>` with the project's JS/TS source root (check `package.json` scripts or look for `src/`, `app/`, `lib/`)
52
+ 1. Add the rules above for this run only: extend the project's ESLint config, or on ESLint 10 use a temporary flat config that spreads it. With no project config, create a temporary `eslint.config.mjs`; on a TypeScript project give it `typescript-eslint`'s parser, or every `.tsx` file fails to parse.
53
+ 2. Run: `npx eslint --format json <src_dir>` (`npx eslint@9 -c <temp config>` on ESLint 10); replace `<src_dir>` with the project's JS/TS source root (check `package.json` scripts or look for `src/`, `app/`, `lib/`)
55
54
  3. Parse output into: `file:line -> rule -> message`.
@@ -7,7 +7,7 @@ See [fix-reference.md](fix-reference.md) for concrete fix patterns per finding.
7
7
 
8
8
  ### Memoization
9
9
 
10
- Check every exported function component: is it rendered in a list, a frequently-updating parent, or a context consumer? If yes and props are stable, wrap in `React.memo`. Check context providers for unstable `value` props. Skip `React.memo` if React Compiler is active.
10
+ Check every exported function component: is it rendered in a list, a frequently-updating parent, or a context consumer? If yes and props are stable, wrap in `React.memo`. Check context providers for unstable `value` props. If React Compiler is active, check only the components it skips (`compilationMode: "annotation"`, `"use no memo"`, a `sources` filter).
11
11
 
12
12
  ### List rendering
13
13
 
@@ -27,7 +27,7 @@ Check all `useEffect` hooks that create timers, listeners, or subscriptions. Ver
27
27
 
28
28
  ### State hygiene
29
29
 
30
- Check for unused state (set but never rendered), unbounded state growth (arrays/objects that grow without cap), and derived state that should be computed with `useMemo` instead.
30
+ Check for unused state (set but never rendered), unbounded state growth (arrays/objects that grow without cap), and derived state that should be computed during render instead.
31
31
 
32
32
  ### Monolithic context
33
33
 
@@ -7,162 +7,98 @@ This skill is complementary to `argent-react-native-optimization`, not a replace
7
7
 
8
8
  Physical iPhone: not supported; `react-profiler-*` reject `kind: "device"`. Profile on a simulator.
9
9
 
10
- ## 2. Tool Overview
10
+ ## 1. Tools
11
11
 
12
12
  ### React Profiler (Hermes / React commits)
13
13
 
14
- | Tool | Purpose |
15
- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
16
- | `react-profiler-start` | Start CPU sampling + inject React commit-capture hook. Optional: `sample_interval_us` (default 100). |
17
- | `react-profiler-stop` | Stop recording; stores cpuProfile + commitTree in session. |
18
- | `react-profiler-status` | **Call if you were interrupted in the middle of the flow, never in another scenario** (debugger drop, Metro reload, pause, subagent handoff, any doubt). Returns `session_status: "active" \| "taken_over" \| "stopped" \| "no_react_runtime"`. Side-effect free. |
19
- | `react-profiler-analyze` | Run pipeline -> report with CPU-enriched hot commits, sorted by `totalRenderMs` DESC. Saves raw data to disk. |
20
- | `react-profiler-component-source` | AST lookup: file, line, memoization status, 50 lines of source for a component. |
21
- | `react-profiler-renders` | Live fiber walk: render counts + durations per component (no profiling session required). |
22
- | `react-profiler-fiber-tree` | Live fiber walk: full component hierarchy as JSON. |
14
+ - `react-profiler-start` / `react-profiler-stop`: record CPU samples and React commits around an interaction.
15
+ - `react-profiler-analyze`: turn the recording into a ranked report: hot commits with the JS functions that ran during each.
16
+ - `react-profiler-status`: **only after an interruption** (debugger drop, Metro reload, pause, subagent handoff, any doubt), never otherwise. A debugger drop also ends the recording; check status before stopping or restarting.
17
+ - `react-profiler-component-source`: source, location and memoization status of a component the report flagged.
18
+ - `react-profiler-renders`: how many instances of each component are mounted in the top 30 levels of the tree, with their last render time; no session needed. It does not count re-renders: record a profile for that.
19
+ - `react-profiler-fiber-tree`: live component hierarchy, no session needed, for tracing a component's ancestry.
23
20
 
24
- ### Drill-Down Query Tools (call after analyze)
21
+ ### Drill-down queries (after analyze)
25
22
 
26
- | Tool | Purpose |
27
- | -------------------------- | -------------------------------------------------------------------------------------------- |
28
- | `profiler-cpu-query` | Targeted CPU investigation: top functions, time-windowed CPU, call trees, per-component CPU. |
29
- | `profiler-commit-query` | Targeted commit investigation: by component, time range, commit index, or cascade tree. |
30
- | `profiler-stack-query` | iOS Instruments drill-down: hang stacks, function callers, thread breakdown, leak details. |
31
- | `profiler-combined-report` | Cross-correlated report when both React Profiler and native profiler ran in parallel. |
32
- | `profiler-load` | List and reload previous profiling sessions from disk for re-investigation with query tools. |
23
+ - `profiler-cpu-query`: JS CPU: top functions, a time window, a function's call tree, CPU during a component's commits.
24
+ - `profiler-commit-query`: React commits by component, time range, commit index, or cascade tree.
25
+ - `profiler-stack-query`: native data: hang stacks, function callers, thread breakdown, leak details.
26
+ - `profiler-combined-report`: correlates native hangs with React commits when both profilers ran.
27
+ - `profiler-load`: reload an earlier session from disk for the query tools.
33
28
 
34
- For native profiling (CPU hotspots, UI hangs, memory leaks), see the `argent-native-profiler` skill.
29
+ For native profiling on its own, see the `argent-native-profiler` skill.
35
30
 
36
- ---
37
-
38
- ## 3. Agent Behavior Guidelines
39
-
40
- Follow these rules throughout the profiling workflow:
41
-
42
- - Start `react-profiler-start` and `native-profiler-start` in parallel (two tool calls in one message). Both need `device_id`; use the same UDID for both so their data can be correlated later. This gives best coverage.
43
- - If the user only wants native profiling, use the `argent-native-profiler` skill workflow. Only skip `native-profiler-start` if the user has **already explicitly said** they don't want native profiling in this session
44
-
45
- ### After analysis: ask about next steps
46
-
47
- After presenting the analysis report, always ask the user what they want to do next. Present these options:
48
-
49
- 1. **Investigate further**: drill down into specific findings using query tools (CPU call trees, commit cascades, hang stacks, etc.) to identify root causes with confidence before making changes.
50
- 2. **Implement fixes**: apply changes based on the current findings, then re-profile to measure whether the metric changed (improved, regressed, or stayed flat).
51
- 3. **Done for now**: accept the report as-is.
52
-
53
- Do NOT silently move on after the report. The report is the starting point, not the end; query tools exist specifically to let you dig deeper into anything the report flags.
54
-
55
- ### During investigation: use query tools proactively
56
-
57
- When drilling down, chain query tool calls based on what you find:
58
-
59
- - A hot commit -> `profiler-commit-query` mode=`by_index` to see all components -> `profiler-cpu-query` mode=`component_cpu` for the slowest one -> `profiler-cpu-query` mode=`call_tree` for the hot function -> read the source file -> propose a fix.
60
- - A memory leak -> `profiler-stack-query` mode=`leak_stacks` to identify the responsible module -> read the native source if actionable.
61
- - A native hang -> `profiler-stack-query` mode=`hang_stacks` to get the native call chain -> correlate with React commit timing.
62
-
63
- ### After fixes: always re-profile
64
-
65
- When you apply a fix, always re-profile the same scenario afterward. Compare before/after metrics (commit durations, CPU time, render counts) and report honestly: did the target metric improve, stay flat, or regress? Did any _other_ metric get worse? If you need to reference the original data, use `profiler-load` to reload the pre-fix session. If the fix showed no improvement or introduced a regression, say so explicitly and reconsider the approach.
31
+ ## 2. Guidelines
66
32
 
67
- ### Use e2e tests for reproducible profiling
33
+ - Start `react-profiler-start` and `native-profiler-start` together, as `react-profiler-start` describes. If the user wants only native profiling, follow `argent-native-profiler`.
34
+ - **Never move on silently after a report.** The report is the starting point: ask the user whether to investigate further with the query tools, implement fixes and re-profile, or stop.
35
+ - **Record the interaction as an e2e test** (`argent-create-e2e` skill) before the first run when profiling needs a specific interaction sequence (scroll a list, navigate screens, trigger an animation), then replay it for every later run. This removes interaction variance from before/after comparisons. It matters most when re-profiling after a fix, comparing several sessions, or when the path is more than 2-3 steps.
68
36
 
69
- When profiling requires a specific interaction sequence (scroll a list, navigate screens, trigger an animation), **record the interaction as an e2e test** using the `argent-create-e2e` skill before the first profiling run. Then replay the same e2e test for every subsequent run. This eliminates interaction variance as a confounder and makes before/after comparisons meaningful. Especially important when:
70
-
71
- - You are about to re-profile after applying a fix (Step 8).
72
- - The user asks you to compare multiple profiling sessions.
73
- - The interaction path is more than 2-3 steps long.
74
-
75
- ---
76
-
77
- ## 4. Standard Profiling Workflow
37
+ ## 3. Workflow
78
38
 
79
39
  **Complete all steps in order; do not break mid-flow.**
80
40
 
81
41
  ### Step 1: Start profiling
82
42
 
83
- Mind the react-native and ios-native profiler selection mentioned above when starting the session and start the tools. **Save `startedAtEpochMs` from the response**: you will need it for annotation offsets. Every subsequent profiler/query call in this session must use the same `device_id`. Before beginning, define lightweight success criteria with the user: which metric matters most (e.g., `totalRenderMs`, specific commit duration, render count for a component) and what threshold would be meaningful. This anchors later evaluation. On success:
43
+ Before starting, define lightweight success criteria with the user: which metric matters most (e.g. `totalRenderMs`, a specific commit's duration, a component's render count) and what change would be meaningful.
44
+
45
+ Start the profilers as described in §2. **Save `startedAtEpochMs` from the response** for annotations. Every later profiler and query call in this session must use the same `device_id`. Then:
84
46
 
85
- - if user asked you to perform the profiling, determine how to profile yourself using tools described in `argent-device-interact` skill.
86
- - if the user stated they wish to perform the interaction themselves, suggest what interaction to perform (e.g. "scroll the list", "switch tabs") and wait for their reply.
87
- If you received information about **existing profiling session** being owned by another agent:
88
- - if session is marked as "stale", you may overtake it without prompting the user for allowance
89
- - if session is NOT "stale" - before taking action and terminating the other session, **stop and ask user what you should do**, explaining the situation.
47
+ - If the user asked you to profile, drive the interaction yourself (`argent-device-interact` skill).
48
+ - If the user wants to interact themselves, suggest what to do (e.g. "scroll the list", "switch tabs") and wait for their reply.
90
49
 
91
50
  While a profiler records, interaction tools return no automatic screenshot or element tree, so the capture does not load the app. Call `screenshot` or `describe` when you need to see the screen; interaction tools still wait for the screen to settle before they return, so add no wait of your own; on an Android emulator each screenshot during a profile takes one frame in about 100 ms and does not wake the screen capture; on a physical Android device it takes about 150–200 ms and briefly wakes the device screen capture, so take them sparingly there.
92
51
 
93
52
  #### Annotate every interaction
94
53
 
95
- After each `gesture-tap` or `gesture-swipe` call, record an annotation using the returned `timestampMs`. Compute `offsetMs = timestampMs - startedAtEpochMs`. Do this for _every_ interaction, including back-navigation swipes, not just the primary action. Pass all collected annotations to `react-profiler-analyze` in Step 3.
54
+ After each `gesture-tap` or `gesture-swipe`, record an annotation with `offsetMs = timestampMs - startedAtEpochMs`, using the `timestampMs` the gesture returned. Never use `Date.now()`; only the server-side timestamps. Annotate _every_ interaction, back-navigation swipes included, and pass them all to `react-profiler-analyze` in Step 3.
96
55
 
97
56
  ### Step 2: Stop and collect
98
57
 
99
- Call `react-profiler-stop` **and** `native-profiler-stop` in parallel. Only skip `native-profiler-stop` if you did not start it in Step 1. Note `duration_ms` and `fiber_renders_captured`.
100
- If `fiber_renders_captured: 0`, warn the user: React commit data may be missing.
58
+ Call `react-profiler-stop` **and** `native-profiler-stop` in parallel (skip the native one only if you did not start it). If `fiber_renders_captured` is 0, warn the user that React commit data may be missing.
101
59
 
102
60
  ### Step 3: Analyze
103
61
 
104
- Call `react-profiler-analyze` with `port`, `device_id`, `project_root`, `platform`, and `rn_version`. The report includes metadata such as `reactCompilerEnabled`, `strictModeEnabled`, and `buildMode`; check these in the returned markdown report.
105
-
106
- If you performed interactions using `gesture-tap`/`gesture-swipe`, pass `annotations` to mark when each action occurred. Each annotation's `offsetMs` must be computed as `tapTimestampMs - startedAtEpochMs`, where `tapTimestampMs` is the `timestampMs` returned by the gesture-tap/gesture-swipe tool and `startedAtEpochMs` was returned by `react-profiler-start`. Do **not** use `Date.now()` for this calculation; only server-side timestamps from the tool return values.
62
+ Call `react-profiler-analyze` with your annotations. Check the report's React Compiler and build-mode lines before proposing fixes.
107
63
 
108
- If dual profiling, also call `native-profiler-analyze`, then **you must** call `profiler-combined-report` for the cross-correlated view; do not skip this step when both profilers ran; the combined report surfaces correlations that individual reports miss.
109
-
110
- The analyze report includes **CPU hotspots per commit**, showing exactly which JS functions ran during each slow React commit. Raw data is saved to disk automatically for later reload.
64
+ If both profilers ran, also call `native-profiler-analyze`, then **you must** call `profiler-combined-report`: it surfaces correlations the individual reports miss.
111
65
 
112
66
  ### Step 4: Assess results
113
67
 
114
- Analyze whether the results give you a proper image of what is wrong with the application - **do not assume improvement always exists**, verify results logically with reference to how react-native works. Make sure to give honest feedback and be ready to change the approach if needed.
68
+ Judge whether the results actually explain what is wrong. **Do not assume an improvement always exists**; check the findings against how React Native works, give honest feedback, and be ready to change approach.
115
69
 
116
70
  ### Step 5: Present findings and ask about next steps
117
71
 
118
- Present a concise summary of the key findings - present whether possibilities for improvement exist and how performing further actions could affect performance. Then follow the "After analysis" guideline: ask whether to investigate further, implement fixes (if available), or stop.
72
+ Summarize the key findings, whether there is room for improvement, and how further work could affect performance. Then ask the user how to proceed (§2).
119
73
 
120
74
  ### Step 6: Drill-down investigation (iterative)
121
75
 
122
- Based on findings from the report, use query tools to investigate deeper:
76
+ Chain the query tools from what the report flags:
123
77
 
124
- - **Slow component?** -> `profiler-cpu-query` mode=`component_cpu` component_name=`AppNavigator`: shows what JS functions ran during that component's commits.
125
- - **Want to see the call tree?** -> `profiler-cpu-query` mode=`call_tree` function_name=`expensiveFunction`: shows callers and callees.
126
- - **What happened during a time window?** -> `profiler-commit-query` mode=`by_time_range`: lists all commits in a range.
127
- - **Full commit detail?** -> `profiler-commit-query` mode=`by_index` commit_index=38: all components, props changes, parent cascade.
128
- - **Who triggered whom?** -> `profiler-commit-query` mode=`cascade_tree`: visual parent-child cascade.
129
- - **iOS hang details?** -> `profiler-stack-query` mode=`hang_stacks`: native call stacks during a hang.
78
+ - **Slow commit** → `profiler-commit-query` `by_index` (every component, props changes, parent cascade) or `cascade_tree` (who triggered whom).
79
+ - **Slow component** → `profiler-cpu-query` `component_cpu` → `call_tree` for the hot function → read the source → propose a fix.
80
+ - **A time range** → `profiler-commit-query` `by_time_range`, or `profiler-cpu-query` `time_window`.
81
+ - **Native hang or leak** → `profiler-stack-query` `hang_stacks` / `leak_stacks`; correlate the hang's timing with React commits.
130
82
 
131
- Repeat as needed until you identify the root cause function and file, referring to step 4 for honest evaluation. After each round of investigation, ask the user if they want to continue digging or move to fixing.
83
+ Pass component names exactly as the report prints them; the wrapped name (`Memo(...)`, `Forget(...)`, `ForwardRef(...)`) resolves too. Repeat until you find the root-cause function and file, judging the evidence as in Step 4. After each round, ask the user whether to keep digging or move to fixing.
132
84
 
133
85
  ### Step 7: Reload a previous session
134
86
 
135
- If you profiled multiple scenarios and need to revisit earlier data:
136
-
137
- 1. Call `profiler-load` mode=`list` to see all saved sessions with timestamps (the list now also shows Runtime / Device / Metro bundle columns to help identify the right session).
138
- 2. Call `profiler-load` mode=`load_react` session_id=`<timestamp>` device_id=`<UDID>` to reload React data. `device_id` scopes the reload into the `port:device_id` cache slot.
139
- 3. Call `profiler-load` mode=`load_native` session_id=`<timestamp>` device_id=`<UDID>` to reload native profiler data.
140
- 4. Query tools now operate on the reloaded session data; **pass the same `device_id` you loaded with**, otherwise they will miss the cache.
141
-
142
- This is useful for before/after comparisons: profile, fix, re-profile, then reload the original session to compare metrics side by side.
87
+ To revisit earlier data, e.g. to compare before and after a fix: `profiler-load` mode `list`, then `load_react` and/or `load_native` with the `session_id` and the `device_id`. **Pass that same `device_id` to the query tools afterwards**, or they miss the reloaded data.
143
88
 
144
89
  ### Step 8: Apply fix and re-profile
145
90
 
146
- If fix is present, read the source code of the identified bottleneck using `react-profiler-component-source` or the Read tool. Apply the fix, then re-profile (Step 1 -> user interaction -> Step 2 -> Step 3 -> Step 4). Report whether the target metric improved, stayed flat, or regressed. Also check whether the fix introduced regressions in other metrics (e.g., render count dropped but CPU time increased, or a different component now re-renders more). If the fix showed no net benefit or unacceptable tradeoffs, revert and reconsider.
91
+ Read the bottleneck's source (`react-profiler-component-source` or the Read tool), apply the fix, then re-profile the same scenario (Step 1 → interaction → Steps 2-4). Report honestly whether the target metric improved, stayed flat, or regressed, and whether any _other_ metric got worse (e.g. fewer renders but more CPU time, or a different component now re-renders more). If the fix brought no net benefit or unacceptable tradeoffs, revert and reconsider.
147
92
 
148
- **Tip:** If the interaction sequence was recorded as an e2e test (see "Use e2e tests for reproducible profiling" above), replay it with `e2e-execute` instead of manually repeating the steps. This guarantees identical interaction conditions for the comparison. If the e2e test fails during replay (e.g., a UI fix changed the layout), follow `argent-create-e2e`'s [Diagnose a replay failure](../argent-create-e2e/references/reliability-and-recovery.md#diagnose-a-replay-failure) to repair the e2e test before retrying the profiling cycle.
93
+ If the interaction was recorded as an e2e test, replay it with `e2e-execute` instead of repeating the steps by hand. If the replay fails (e.g. a UI fix changed the layout), follow `argent-create-e2e`'s [Diagnose a replay failure](../argent-create-e2e/references/reliability-and-recovery.md#diagnose-a-replay-failure) before retrying the profiling cycle.
149
94
 
150
- If the user stated that they do not wish for changes, present the profiling report and skip the fix but suggest it to the user.
151
-
152
- **React Compiler rule:** If the analyze report indicates React Compiler is enabled, do NOT propose `useCallback`/`useMemo`/`React.memo` unless you confirmed compiler bail-out (check `react-profiler-fiber-tree` for absent `useMemoCache` on that component).
153
-
154
- ---
95
+ If the user does not want changes, present the report and suggest the fix without applying it.
155
96
 
156
- ## 5. Important Caveats
97
+ **React Compiler rule:** do NOT propose `useCallback`/`useMemo`/`React.memo` for a component the report marks ✓ (compiled). For a component in your source marked ⚠️ (bailout suspected), fix what stops the compiler instead.
157
98
 
158
- - **Dev mode inflation**: `buildMode: "dev"` renders are ~3x slower than production. Prioritize high `normalizedRenderCount`; it scales to prod.
159
- - **Re-run after fixes**: Always re-profile after changes. Report honestly whether the metric improved, regressed, or stayed flat; do not assume improvement.
160
- - **`excluded` is informational**: Components in `animatedSubtrees` and `recyclerChildren` re-render by design.
161
- - **Strict Mode**: Double-invokes renders. The pipeline halves `normalizedRenderCount` automatically when detected.
162
- - **Debugger connection**: If interrupted, started profiling also closes. Before attempting recovery, call `react-profiler-status`: it tells you whether the session is `active`, `taken_over`, `stopped`, or `no_react_runtime`, so you can decide whether to stop, restart, or reconnect first.
163
- - **Confounders to watch for**:
164
- - Live API data may differ between runs (different payload sizes, content counts), which shifts render counts and durations independently of your fix. Note when data-dependent components show variance.
165
- - Profiler overhead inflates CPU measurements. If iOS Instruments shows `JSLexer`, `JSONEmitter`, or Hermes internals dominating the JS thread, that reflects profiler instrumentation cost, not app work. Discount those entries.
166
- - Runs are not perfectly reproducible. Small variations (under ~10-15%) in commit duration may be noise; only treat consistent, directional changes as signal.
99
+ ## 4. Caveats
167
100
 
168
- For standalone diagnostic tools (live render stats, fiber tree, CPU summary), see `references/diagnostic-tools.md`.
101
+ - **Dev builds** render ~3x slower than production (the report notes it). Prioritize render counts over durations: counts carry over to production. They are already halved when Strict Mode double-invokes renders.
102
+ - **Live API data** may differ between runs (payload sizes, item counts) and shift render counts and durations independently of your fix. Note when data-dependent components vary.
103
+ - **Run-to-run noise:** variations under ~10-15% in commit duration may be noise; only treat consistent, directional changes as signal.
104
+ - **Profiler overhead:** if the native profile shows `JSLexer`, `JSONEmitter` or Hermes internals dominating the JS thread, that is instrumentation cost, not app work. Discount those entries.
@@ -3,48 +3,29 @@ name: argent-screen-recording
3
3
  description: Record a video of an iOS simulator or Android emulator/device screen using argent MCP tools. Use when the user asks to record the screen, capture a video of a flow, interaction, or animation, produce a screen recording, or document app behavior as a video clip.
4
4
  ---
5
5
 
6
- ## 1. Tools
6
+ `screen-recording-start` and `screen-recording-stop` carry the options (`timeLimitSeconds`, `trimStatic`, `showTouches`) and the result fields. One recording per device at a time; different devices can record concurrently.
7
7
 
8
- - `screen-recording-start`: start capturing the screen of a booted device to a video file. Frames come from the same simulator-server backend that `screenshot` and the interaction tools already use, and are encoded live to h264 mp4 (constant 30 fps, device-native resolution).
9
- - `screen-recording-stop`: stop the capture, finalize the container, and retrieve the video as a downloadable artifact (`video.hostPath` for co-located clients).
8
+ ## 1. Critical: never leave a recording running
10
9
 
11
- One recording per device at a time; different devices can record concurrently. Recording does not disturb anything else reading the device: a preview window can stay open on the same screen.
10
+ A forgotten recording keeps capturing until its `timeLimitSeconds` cap fires, holding the session and delaying the video. Use both safety nets:
12
11
 
13
- ---
14
-
15
- ## 2. Critical: never leave a recording running
16
-
17
- A recording does not stop itself before its `timeLimitSeconds` cap, so a forgotten one keeps capturing until the cap fires, holding the recording session, wasting disk, and delaying the video you are waiting on (and with `trimStatic: false` it comes back padded with dead air). Two safety nets exist; use both:
18
-
19
- 1. **Set yourself a reminder the moment the recording starts.** You know the expected capture length (the interaction you are about to drive). Immediately after `screen-recording-start` returns, schedule a wake-up for that expected end time using whatever your harness provides: a built-in reminder/wakeup or scheduled-task tool if you have one, otherwise a background shell running `sleep <expected-seconds>` whose completion notification pulls you back. When it fires, call `screen-recording-stop`. Do not rely on remembering.
20
- 2. **Read the tool-result notes.** While a recording is running, every argent tool result carries a `NOTE:` reminding you it is still going and how to stop it. If the note says the recording already ended (time limit hit), still call `screen-recording-stop`; that is what hands you the file.
21
-
22
- ---
23
-
24
- ## 3. Workflow
25
-
26
- 1. Ensure the target device is booted and the app is in the state you want the video to open on (`list-devices`, `launch-app`, `argent-device-interact`).
27
- 2. Call `screen-recording-start` with `udid` and a `timeLimitSeconds` slightly above the expected interaction length (default 180, max 600). Taps and swipes are drawn into the video by default (see the touch-visualizer note below); pass `showTouches: false` for a clean raw-screen capture.
28
- 3. Set the end-of-recording reminder described in §2; this step is not optional.
29
- 4. Drive the interaction to capture: gestures, navigation, typing (`argent-device-interact`). Prefer `run-sequence` for tight multi-step interactions so tool-call latency does not pad the video.
30
- 5. Call `screen-recording-stop` with the same `udid`. It returns `{ video, durationMs, wallClockMs?, trimmedMs?, warning? }`; `video` is an artifact whose resolved path points at the durably-saved file (see below). The video is already final when stop returns (the watermark is stamped during capture, not in a second pass), so stop takes well under a second.
31
- 6. Check `warning`: it reports cap-triggered stops, early encoder exits, a dropped frame stream, and possibly-truncated containers. Verify the file plays (or at least has a sane size) before presenting it to the user.
12
+ 1. **Set yourself a reminder the moment the recording starts**, for the expected end of the interaction. Use whatever your harness provides: a reminder/wakeup or scheduled-task tool if you have one, otherwise a background shell running `sleep <expected-seconds>` whose completion notification pulls you back. When it fires, call `screen-recording-stop`. Do not rely on remembering.
13
+ 2. **Read the tool-result notes.** While a recording runs, every argent tool result carries a `NOTE:` about it. If the note says the recording already ended, still call `screen-recording-stop`: that is what hands you the file.
32
14
 
33
- **Where the file lands (durable, not scratch).** Unlike most argent artifacts (which live in a disposable temp cache the OS reclaims), a finished recording is saved durably on the **client** into `<project>/.argent/recordings/`, the project being the nearest ancestor of the client's working directory with a `.git`/`package.json`/`.argent`, or `~/.argent/recordings/` when the client isn't inside a project. This holds even for a remote `argent link` tool-server: the mp4 is written on the client host, not the server. The destination can be changed with the `recordings.directory` configuration (`argent config set recordings.directory <dir>`, global by default, `--scope project` for a per-repo choice; project wins when both are set); the value may be absolute, `~`-prefixed, or relative to the project root, and is always resolved on the client host. The saved name is `screen-recording-<device>-<timestamp>.mp4`; if that name is already taken the new file lands beside it as `… (2).mp4` rather than overwriting. Because these files persist in the working tree, mention the path to the user (and note that they are untracked; add them to `.gitignore` or clean them up if they shouldn't be committed).
15
+ ## 2. Workflow
34
16
 
35
- **Static-frame trimming (on by default).** Stretches where the screen does not change are collapsed: the first second of each still stretch is kept so pauses read naturally, then unchanged frames are dropped until something moves again (a change of even a couple of pixels counts); on a remote simulator the still stretches are removed whole. So you can leave a recording running across slow steps, waits, or thinking time without padding the clip with dead air: a 40-second session with 5 seconds of real activity comes back as a ~5-7 second video. When trimming removed anything, stop also returns `wallClockMs` (real elapsed time) and `trimmedMs` (how much was cut); `durationMs` is always the length of the video you actually get. Pass `trimStatic: false` to `screen-recording-start` when you want a faithful real-time recording (e.g. to measure how long something took on screen).
17
+ 1. Get the device booted and the app into the state the video should open on (`list-devices`, `launch-app`, `argent-device-interact`).
18
+ 2. Call `screen-recording-start` with `udid` and a `timeLimitSeconds` slightly above the expected interaction length.
19
+ 3. Set the end-of-recording reminder from §1; this step is not optional.
20
+ 4. Drive the interaction (`argent-device-interact`). Prefer `run-sequence` for tight multi-step interactions so tool-call latency does not pad the video.
21
+ 5. Call `screen-recording-stop` with the same `udid`. Check `warning` (cap-triggered stop, early encoder exit, dropped frame stream, possibly truncated file) and confirm the file has a sane size before presenting it.
36
22
 
37
- **Touch visualizer (on by default).** Every interaction argent drives is drawn straight into the video: a pulse marks each tap, a fading comet trail follows swipes and drags, and paired markers show the two contact points of a pinch or rotate. This makes a recording self-explanatory: a viewer can see _where_ each gesture landed rather than watching the UI react to an invisible finger. It is rendered by simulator-server into the frame stream (nothing is composited host-side), so it costs nothing extra and never appears in a `screenshot`. Pass `showTouches: false` to `screen-recording-start` to record the raw screen with no overlay (e.g. when capturing exactly what the user would see). If simulator-server cannot enable it, the recording still succeeds and stop returns a `warning` saying touches are not shown.
38
-
39
- ---
23
+ **Where the file lands.** A finished recording is saved durably on the **client**, even with a remote `argent link` tool-server: into `<project>/.argent/recordings/` (the nearest ancestor of the client's working directory with a `.git`/`package.json`/`.argent`), or `~/.argent/recordings/` outside a project. Change it with `argent config set recordings.directory <dir>` (`--scope project` for a per-repo choice). Mention the path to the user, and that the file is untracked: add it to `.gitignore` or clean it up if it shouldn't be committed.
40
24
 
41
- ## 4. Platform notes and limits
25
+ ## 3. Platform notes and limits
42
26
 
43
- - **What can be recorded**: anything simulator-server drives: iOS simulators, remote (`remote:`) simulators, Android emulators, and physical Android devices. The only length limit is `timeLimitSeconds` (max 600).
44
- - **The timeline is paced to a steady 30 fps**: a device only emits a frame when its screen changes, so captured frames are re-paced onto a fixed timeline rather than bunching up. With static-frame trimming off (`trimStatic: false`) that timeline is wall-clock accurate: a completely still screen still comes back as a full-length video (compressing to almost nothing) and `durationMs` matches the time you actually recorded. With trimming on (the default, see §3) still stretches past the grace window are collapsed, so `durationMs` is the trimmed video length and `wallClockMs` carries the real elapsed time.
45
- - **One size per video**: the video keeps the size of the screen at the start of the recording. If the screen changes size, argent keeps the proportions of the new screen and adds black bars. On a foldable simulator, start the recording on the panel that you need at full size.
46
- - **Android**: records at the device's native resolution; secure screens (DRM, some password fields) come out black.
47
- - **Unsupported**: tvOS simulators, physical iPhones, Chromium apps, and Vega/Fire TV; none of them expose a readable frame stream. For a single still frame use `screenshot`; for a replayable interaction script use `argent-create-e2e` instead of a video.
48
- - **Remote (`remote:`) simulators**: recorded on the remote runner, and `screen-recording-stop` downloads the mp4, so a long recording takes a while to retrieve. Unlike a local recording, the video keeps the portrait orientation of the screen, so a device in landscape plays sideways.
49
- - **ffmpeg is required for local devices**: it is the encoder, so `screen-recording-start` fails up front with an install hint if it is missing (`brew install ffmpeg` on macOS). It is resolved from `PATH` plus the usual Homebrew prefixes. On a remote simulator it is optional; only the post-pass uses it.
50
- - **Watermark**: the Argent logo + "By @swmansion" is stamped bottom-left while encoding, faint (20% opacity) and per-pixel contrast-matched to the background (light logo over dark UI, dark logo over light UI). On by default; turn it off with `argent disable video-watermark` (re-enable with `argent enable video-watermark`). The flag is read when the recording starts.
27
+ - **Recordable**: iOS simulators (local and remote `remote:`), Android emulators and physical Android devices. **Unsupported**: physical iPhones, tvOS simulators, Chromium apps, Vega/Fire TV and HarmonyOS. For a still frame use `screenshot`; for a replayable interaction script use `argent-create-e2e`.
28
+ - **One size per video**: the video keeps the size of the screen at the start; a later size change is letterboxed. On a foldable simulator, start recording on the panel you need at full size.
29
+ - **Remote (`remote:`) simulators**: the video keeps the screen's portrait orientation, so a device in landscape plays sideways.
30
+ - **Android**: secure screens (DRM, some password fields) come out black.
31
+ - **Watermark**: a faint Argent logo is stamped bottom-left. Turn it off with `argent disable video-watermark`; the flag is read when a recording starts.
@@ -5,65 +5,21 @@ description: Compare saved or live app screenshots with the argent screenshot-di
5
5
 
6
6
  ## 1. Role
7
7
 
8
- Use `screenshot-diff` as supporting visual evidence for UI QA and visual regression checks. It highlights pixel-visible change or stability; it does not replace visual inspection, accessibility/component-tree state, frame/attribute checks, logs, network evidence, or app behavior.
8
+ Use `screenshot-diff` as supporting visual evidence for UI QA and visual regression checks. It highlights pixel-visible change or stability; it does not replace visual inspection, accessibility/component-tree state, frame/attribute checks, logs, network evidence, or app behavior. Its description covers the input combinations, physical-iPhone captures and the result.
9
9
 
10
- Do not use screenshot diffing for tap-coordinate discovery. Use `describe`, `debugger-component-tree`, or `native-describe-screen` to find targets first.
11
-
12
- `screenshot-diff` supports physical iPhones (kind `"device"`) for both saved-file diffs and live captures. A live capture on hardware goes through the on-device runner at full resolution, is device-wide, and needs no registered app. Keep baselines per device model and resolution, and note that the `rotation` parameter is ignored on hardware: the capture follows the device's real orientation.
10
+ Do not use screenshot diffing for tap-coordinate discovery. Use `describe` or `native-describe-screen` to find targets first.
13
11
 
14
12
  ## 2. When To Use
15
13
 
16
- Use `screenshot-diff` when pixel comparison can answer the verification question:
17
-
18
14
  - Required for explicit "UI regression test", "visual regression test", "screenshot diff", "compare screenshots", or "before/after visual comparison" requests, unless stable comparable screenshots cannot be produced.
19
- - Good fit when the affected screen has stable before/after states and the expected result is pixel-visible: layout, position, size, spacing, color, typography, image/icon rendering, clipping, overflow, or text rendering.
20
- - Good fit when the risk is unintended visual regression outside the exact element changed.
15
+ - Good fit when the expected result is pixel-visible, or when the risk is an unintended visual regression outside the exact element changed.
21
16
  - Poor fit when the result is better verified structurally: state changes, navigation existence, accessibility tree contents, console/network behavior, or unit tests.
22
17
  - Poor fit when dynamic content, unpausable animation, timestamps, ads, random data, or missing baseline/current screenshots would make the comparison noisy or meaningless.
23
18
 
24
- ## 3. Capture Rules
25
-
26
- Use normal downscaled `screenshot` calls for UI context and state checks. Use full-resolution screenshots only when saving baseline/current PNG files for visual regression comparison. Suppress the image block so the full-size PNG is not loaded into context:
27
-
28
- ```json
29
- { "udid": "<UDID>", "scale": 1.0, "includeImageInContext": false }
30
- ```
31
-
32
- Capture the stable baseline before the relevant interaction or before editing whenever feasible. Compare it to the post-change or post-interaction screen after the app reloads, rebuilds, or reaches the state under test.
33
-
34
- ## 4. Parameters
19
+ ## 3. Deterministic Flow
35
20
 
36
- Provide `udid` and exactly one input for the baseline side and exactly one input for the current side:
37
-
38
- - Common UI regression flow: saved baseline plus live current -> `baselinePath`, `captureCurrent: true`, `udid`, `outputDir`.
39
- - Both screenshots already saved -> `baselinePath`, `currentPath`, `udid`, `outputDir`.
40
- - Rare fixture flow: live baseline plus saved current -> `captureBaseline: true`, `currentPath`, `udid`, `outputDir`.
41
- - Do not combine `captureBaseline: true` with `captureCurrent: true`, or provide both a path and live capture flag for the same side.
42
-
43
- ## 5. Deterministic Flow
44
-
45
- 1. Navigate to the known-good state.
46
- 2. Capture a baseline PNG with `screenshot` using `scale: 1.0` and `includeImageInContext: false`; keep the returned `path`.
47
- 3. Perform the interaction, apply the code change and navigate to the state under test.
48
- 4. Call `screenshot-diff` with the saved `baselinePath`, `captureCurrent: true`, `udid`, and `outputDir`.
21
+ 1. Navigate to the known-good state. Capture the baseline before the relevant interaction or before editing whenever feasible.
22
+ 2. Save a baseline PNG with `screenshot` using `scale: 1.0` and `includeImageInContext: false`, so the full-size image stays out of context; keep the returned `path`. Use normal downscaled screenshots for everything else.
23
+ 3. Perform the interaction, apply the code change and navigate to the state under test, after the app reloads or rebuilds.
24
+ 4. Call `screenshot-diff` with that `baselinePath`, `captureCurrent: true`, `udid`, and `outputDir`. If both images are already saved, pass `currentPath` instead of `captureCurrent`.
49
25
  5. Inspect the summary and artifact paths, then combine the diff with normal visual inspection and any structural/runtime evidence needed for the assertion.
50
-
51
- ```json
52
- {
53
- "baselinePath": "/tmp/baseline.png",
54
- "captureCurrent": true,
55
- "udid": "<UDID>",
56
- "outputDir": "/tmp/argent-diff"
57
- }
58
- ```
59
-
60
- If both images are already saved, use file paths for both sides:
61
-
62
- ```json
63
- {
64
- "baselinePath": "/tmp/baseline.png",
65
- "currentPath": "/tmp/current.png",
66
- "udid": "<UDID>",
67
- "outputDir": "/tmp/argent-diff"
68
- }
69
- ```