@iamu-dev/iamu 0.8.0-beta.3 → 0.8.0-beta.4

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.
@@ -4,6 +4,12 @@ You are the advisor. A walker has used the product as a specific person in a spe
4
4
 
5
5
  Unlike the walker, you may read the project's code (read-only) and look at the screenshots. You do not drive the product.
6
6
 
7
+ **Read budget (run mode):**
8
+ - Open only the step screenshots linked in `findings[].steps`.
9
+ - Open **at most 3–5 source files** directly responsible for the screens where `F<n>` occurred (find them in `panorama.source_files`, which lists the walked app first, or by searching for the literal `ui_fact` text). **Do not crawl unrelated screens.**
10
+ - In step 13, compare `walked_paths` with `panorama.code_routes` and `panorama.source_files`; do not crawl the repository to discover routes.
11
+ - `panorama.code_index: { partial: true }` means the scan of the code was cut short by its time budget: those lists are incomplete, so a route missing from them is not evidence that it does not exist or was never walked.
12
+
7
13
  You decide with the same product principles the walker observes with. They follow this method under "Product principles". Apply them at every step, not as a checklist at the end.
8
14
 
9
15
  ## How to work
@@ -53,7 +59,7 @@ Work in this order. Do not skip ahead to writing fixes.
53
59
  - which scenarios must be re-run to check it actually helped (`verify`, including this one).
54
60
  These are predictions, not observations. Give a reason for each. If a person who is clearly affected has no scenario, say so in the direction's `change` text rather than guessing.
55
61
 
56
- 13. **Look at what nobody walked.** The panorama lists, per scenario, where it starts (`entry_path`) and which pages its runs visited (`walked_paths`). Compare that with the routes in the code. A surface every person passes through (a home page, a dashboard, the navigation) that no walk examined is a blind spot: every finding so far is silent about it. You cannot propose a direction for it without evidence, but you can name it as a `coverage_gap` observation and suggest the scenario that would test it (who, in what situation, starting where).
62
+ 13. **Look at what nobody walked.** The panorama lists, per scenario, where it starts (`entry_path`) and which pages its runs visited (`walked_paths`, empty for a scenario never walked), alongside the routes (`panorama.code_routes`) and source files (`panorama.source_files`) pre-extracted from the code, the walked app first. Compare `walked_paths` with them (do not crawl the codebase to discover routes). A surface every person passes through (a home page, a dashboard, the navigation) that no walk examined is a blind spot: every finding so far is silent about it. You cannot propose a direction for it without evidence, but you can name it as a `coverage_gap` observation and suggest the scenario that would test it (who, in what situation, starting where).
57
63
 
58
64
  14. **Question a feature's premise when it carries real risk.** Some features are risky as a premise, not only in their execution: processing health or other sensitive personal data, monitoring employees, automated decisions about people, dark patterns. If a feature in this product has that kind of legal, privacy or trust risk in this domain and country, say so as a `feature_risk` observation: what the risk is and what a safer form of the feature would be. Do not drop the feature from your advice on your own.
59
65
 
@@ -70,66 +76,7 @@ Work in this order. Do not skip ahead to writing fixes.
70
76
 
71
77
  ## Answer
72
78
 
73
- Reply with one JSON object and nothing else.
74
-
75
- For a run:
76
-
77
- ```json
78
- {
79
- "groups": [{ "id": "g1", "root_cause": "…" }],
80
- "advice": [
81
- {
82
- "finding_id": "<ref from the bundle, e.g. F3>",
83
- "scope": "local | systemic",
84
- "recommendation": "…",
85
- "quick_fix": "… or null",
86
- "builds_on": [{ "path": "relative/path/from/project/root", "symbol": "text that occurs in that file" }],
87
- "group": "g1 or null",
88
- "direction": "<direction slug> or null",
89
- "heuristic": "the UX principle at stake (e.g. recognition_over_recall) or null",
90
- "check": {
91
- "verdict": "confirmed | overstated | understated | setup",
92
- "severity": "for overstated or understated: the severity it deserves, else null",
93
- "why": "What the code or a screenshot shows, citing the step"
94
- }
95
- }
96
- ],
97
- "directions": [
98
- {
99
- "slug": "kebab-case-name",
100
- "title": "Short imperative title",
101
- "problem": "The shared cause, in product terms",
102
- "change": "What the person would experience instead",
103
- "leading_practice": "How leading systems in this domain handle it, scaled to this product",
104
- "size": "small | medium | large",
105
- "absorbs": ["<ref, e.g. F3>", "<ref, e.g. F12>"],
106
- "reach": [{ "scenario": "<scenario slug>", "effect": "helps | risk", "reason": "…" }],
107
- "verify": ["<scenario slug>"],
108
- "builds_on": [{ "path": "…", "symbol": "…" }]
109
- }
110
- ],
111
- "observations": [
112
- {
113
- "kind": "coverage_gap | feature_risk",
114
- "title": "Short title",
115
- "detail": "What is missing or risky, and why it matters here",
116
- "suggested_scenario": "Who, in what situation, starting where (coverage gaps) or null"
117
- }
118
- ],
119
- "design_proposals": [
120
- {
121
- "slug": "kebab-case",
122
- "kind": "challenge | new",
123
- "file": "The design file it changes (from design.files)",
124
- "rule": "For challenge: the rule's name as the doc writes it; else null",
125
- "before": "Text copied exactly from the doc: the rule's text (challenge) or the passage the addition follows (new)",
126
- "after": "The better wording (challenge), or that passage followed by the addition (new)",
127
- "why": "What the evidence shows",
128
- "evidence": ["<ref, e.g. F3 or S2>"]
129
- }
130
- ]
131
- }
132
- ```
79
+ Reply with one JSON object and nothing else. Its exact shape, for this bundle's mode, is under "Output JSON schema (strict)" at the very end of this prompt, after the bundle. For a run it carries `groups`, `advice`, `directions`, `observations` and `design_proposals`.
133
80
 
134
81
  An observation earns its place only by meeting step 13 (a surface every person passes through that no walk examined) or step 14 (a feature whose premise carries real legal, privacy or trust risk here). Each names its own surface or risk: one that repeats a finding, a direction or another observation adds nothing. Raise every one that meets the bar and none that does not. `observations` never absorb findings and are never treated as evidence.
135
82
 
@@ -17,10 +17,11 @@ The person already judged what it was like: whether the product fits their role,
17
17
  - `walker_summary`: what worked for them, what they still wondered, and how the walk ended.
18
18
  - `screens`: the run's screens in walk order. A screen's `key` is its URL path (with the host when the run crossed hosts; else the walker's name for it). A screen visited twice has two `visits`. Screenshot paths are relative to `run_dir`. Open every screenshot in `key_frames` and look at it; open `other_screenshots` when you need to see more. `steps` carry what the person did and thought at each step.
19
19
  - `design.files`: the team's design docs (`design`) and product docs (`product`), by absolute path. A file with a `heading` means that section only. A file whose `applies_to` names only app directories may not concern these screens: judge that from the screens. Each `design` file entry also carries `rules`: the parser's canonical list of rule names extracted from that file (`Section > Name` when a name repeats). `design.proposals` lists edits already proposed, each with its `before` and `after`: to support an open one, propose the same change (the same `before` and `after`); never raise a rejected one again.
20
+ - `facts`: computed from the team's code and docs, not taste; `null` when nothing is off. `facts.stale_references` lists references the design docs make (a path, a `path#Symbol`, a `--token`) that no longer exist. `facts.contrast_clashes` lists token pairs, by name, whose text contrast is flagged or whose status/brand fills are too close to tell apart, per `theme`. Raise one only where a screen you looked at shows it, and cite it as computed from the docs and tokens (with the ratio) rather than as something you saw; a clash on a screen the person never reached is a conformance issue, not a persona one. Never treat a missing `facts` as proof that the docs are current.
20
21
  - `judged_against`: `design-docs` when the team's design docs apply to this run, else `general-craft`.
21
22
  - `ignored`: issues a person has read and dismissed (one with no `screen` was about the whole run). Do not raise them again unless they got worse; if one did, say how.
22
23
  - `guidance`: the team's active guidance rules and settled constraints (`iamu/guidance/`), including test-locked copy or styling and domain conventions. Treat these as binding decisions: never raise a new issue or re-confirm an earlier `P<n>` (`same_as`) when it contradicts a rule in `guidance`.
23
- - `open_findings`: your earlier issues on these screens that are still being worked on, as refs `P<n>`. When you see one again on this run (and it is not covered by `ignored` or `guidance`), raise it as an issue of this run with `same_as: "P<n>"`; one you no longer see, leave out (that is how a fix is confirmed). In the summary, say which still show and which are gone.
24
+ - `open_findings`: your earlier issues on these screens that are still being worked on, as refs `P<n>`. When you see one again on this run (and it is not covered by `ignored` or `guidance`), raise it as an issue of this run with `same_as: "P<n>"`. One you looked for and no longer see goes under `checked` (see below): that is how a fix is confirmed. One you did not look for goes in neither list and stays uncertain; leaving it out never confirms a fix. In the summary, say which still show and which are gone.
24
25
  - `setup_notes`: about the test setup (accounts, seeded data), not the product. Never judge the product by them.
25
26
 
26
27
  ## What you open
@@ -90,6 +91,9 @@ Reply with one JSON object and nothing else:
90
91
  "same_as": "P<n> when it is an earlier issue seen again, else null"
91
92
  }
92
93
  ],
94
+ "checked": [
95
+ { "ref": "P<n>", "screen": "<that finding's screen>", "steps": [<n>], "note": "One line: what you saw instead" }
96
+ ],
93
97
  "conflicts": [
94
98
  { "rule": "The rule's name", "file": "The entry it is in", "before": "The rule's text, copied exactly", "after": "Better wording", "why": "How following it failed the person", "evidence": ["F<n>"] }
95
99
  ],
@@ -99,4 +103,6 @@ Reply with one JSON object and nothing else:
99
103
  }
100
104
  ```
101
105
 
102
- `screen` is a screen's `key` from the bundle, and `steps` are step numbers from it. With `general-craft`, leave `rules`, `conflicts` and `design_proposals` empty and every `breaks` null.
106
+ `screen` is a screen's `key` from the bundle, and `steps` are step numbers from it.
107
+
108
+ **checked** (optional): for an earlier designer finding listed under `P<n>` whose screen you actually judged in this run, and which you looked for and no longer see, add `{ "ref": "P<n>", "screen": "<that finding's screen>", "steps": [<the step numbers where you looked>], "note": "<one line: what you saw instead>" }`. List a `P<n>` only when its screen is one of the screens in this bundle and you looked at it at the steps you name. A finding you see again is answered with `same_as` on your issue instead. One you did not look for goes in neither list: it stays uncertain. Never list a check for a screen you did not judge, or without steps. With `general-craft`, leave `rules`, `conflicts` and `design_proposals` empty and every `breaks` null.
@@ -59,7 +59,7 @@ A project set up with an earlier version keeps its rules in `iamu/design.md`, wi
59
59
  A surface is a page with its states and the flows through it. Review a surface, not a single finding: a page that collected eight separate fixes needs to be seen whole.
60
60
 
61
61
  1. Run `iamu design review <target> --json`. The target is a path (`/request`), a finding (its page), or a direction slug (the pages its findings are on). It writes a prompt with the surface's dossier: who passes through and what they said there, open problems with each person's need, strengths, fixes already tried and whether they held, what was dismissed, and the design docs that apply to the page. If it returns `warnings` (an installed prompt that differs from the shipped one), show them.
62
- 2. Tell the user in a line or two what the reviewer looks at, from the result: the surface and its `paths`, how many visitors, open problems and strengths it weighs, and whether there are design docs to judge against. Then dispatch a subagent (thorough tier) **with browser access** and the prompt file (`prompt_file_abs`) as its only context. It opens `target_url` + the path, signs in as the testability notes say, opens menus and states, compares with the walks' screenshots, and answers with JSON. Run it in the foreground where your host allows, so its progress shows. If it runs in the background, say what it is doing while you wait, and do not end your turn with only a wait notice.
62
+ 2. Tell the user in a line or two what the reviewer looks at, from the result: the surface and its `paths`, how many visitors, open problems and strengths it weighs, and whether there are design docs to judge against. Then dispatch a subagent (thorough tier) **with browser access** and the prompt file (`prompt_file_abs`) as its only context. It opens the product's target URL (named in the prompt's dossier) + the path, signs in as the testability notes say, opens menus and states, compares with the walks' screenshots, and answers with JSON. Run it in the foreground where your host allows, so its progress shows. If it runs in the background, say what it is doing while you wait, and do not end your turn with only a wait notice.
63
63
  3. Write the answer to `answer_file_abs` (from the review result) and record it: `iamu design review-record <target> --file <answer_file_abs>`. Show anything it reports as `rejected` or in `warnings` (a dropped proposal, a rule not found): never let it disappear silently.
64
64
  4. Present, in this order:
65
65
  - the summary (what the surface is for, for whom, how well it serves them);
@@ -42,9 +42,14 @@ Determine the mode based on `$ARGUMENTS` and user intent:
42
42
  1. Ground in `iamu/context.yml` actors, domain, and jurisdiction.
43
43
  2. Define role, disposition, key biases, friction triggers, and domain vocabulary.
44
44
  3. Propose the persona candidate to the user (name, role, disposition, expectations).
45
- 4. Once confirmed, scaffold the persona into `iamu/personas/` with its background narrative and `## Today` section passed via `--body` (or update later with `iamu set persona <slug> --body "..."`):
45
+ 4. Once confirmed, scaffold the persona into `iamu/personas/` with its background narrative and `## Today` section passed via `--body-file` (or update later with `iamu set persona <slug> --body-file <path>`; `-` reads stdin). Never put `\n` inside `--body`, it is stored literally:
46
46
  ```bash
47
- iamu new persona --name "<Name>" --role "<Role>" --disposition "<Disposition>" --body "<Background narrative and test expectations>\n\n## Today\n<How this person does the job today without the product>" --json
47
+ iamu new persona --name "<Name>" --role "<Role>" --disposition "<Disposition>" --body-file - --json <<'EOF'
48
+ <Background narrative and test expectations>
49
+
50
+ ## Today
51
+ <How this person does the job today without the product>
52
+ EOF
48
53
  ```
49
54
  5. Ensure the persona's markdown body includes their background narrative and test expectations, ending with a `## Today` section: how this person does the job the product is for today, without it (a paper sheet, a spreadsheet, phone calls, a colleague, another tool), and what that costs or gives them. The walker holds the product against it and the judge weighs voluntary use against it.
50
55
  6. Run `iamu validate --all`.
@@ -239,9 +244,14 @@ The `--capability`, `--additional-capabilities`, `--tension`, `--narrative`, and
239
244
 
240
245
  **3. Persona** (if user picked a new persona to scaffold):
241
246
  ```bash
242
- iamu new persona --name "Maria Gomez" --role "Site Safety Coordinator" --disposition "Time-pressured, prefers physical paper over complex forms" --body "<Persona background narrative and test expectations>\n\n## Today\n<How this person does the job today without the product>" --json
247
+ iamu new persona --name "Maria Gomez" --role "Site Safety Coordinator" --disposition "Time-pressured, prefers physical paper over complex forms" --body-file - --json <<'EOF'
248
+ <Persona background narrative and test expectations>
249
+
250
+ ## Today
251
+ <How this person does the job today without the product>
252
+ EOF
243
253
  ```
244
- The `--role`, `--disposition`, and `--body` flags populate frontmatter and the markdown body directly (or you can update the body via `iamu set persona <slug> --body "..."`). Leave `access` out — which product account the persona uses is decided when the scenario is staged in `iamu-run`. End the `--body` with a `## Today` section: how this person does the job the product is for today, without it (a paper sheet, a spreadsheet, phone calls, a colleague, another tool), and what that costs or gives them. The walker holds the product against it and the judge weighs voluntary use against it.
254
+ The `--role`, `--disposition`, and `--body-file` flags populate frontmatter and the markdown body directly (or you can update the body via `iamu set persona <slug> --body-file <path>`; `-` reads stdin). Never put `\n` inside `--body`: it is stored literally. Leave `access` out — which product account the persona uses is decided when the scenario is staged in `iamu-run`. End the body with a `## Today` section: how this person does the job the product is for today, without it (a paper sheet, a spreadsheet, phone calls, a colleague, another tool), and what that costs or gives them. The walker holds the product against it and the judge weighs voluntary use against it.
245
255
 
246
256
  **4. Scenario** (the binding):
247
257
  ```bash
@@ -14,9 +14,9 @@ This skill resolves what scenario to run following a clear **Target Scenario Res
14
14
 
15
15
  **`--target <url>` (or a bare `http(s)://...` URL in `$ARGUMENTS`):** when `$ARGUMENTS` contains `--target <url>` or a URL, take it out before resolving the scenario and persist it immediately with `iamu set testability --target <url>` (and if the resolved scenario had its own `target_url` override that was shadowing the project target, clear it with `iamu set scenario <slug> --no-target` unless the user asked for a scenario-only URL).
16
16
 
17
- **`--no-ux`:** when `$ARGUMENTS` contains `--no-ux`, take it out before resolving the scenario and skip the designer's review (step C3) for this run only: after A, record `iamu designer-record <run-id> --skipped "--no-ux"` so the report says it was skipped. There is no project setting for it: every other run gets a designer's review.
17
+ **`--no-ux`:** when `$ARGUMENTS` contains `--no-ux`, take it out before resolving the scenario and skip the designer's review (step C3) for this run only. Pass `--no-ux` to `iamu post-walk`, which records the skip itself (reason `--no-ux`). Only on the manual path (no `post-walk`), run `iamu designer-record <run-id> --skipped "--no-ux"` after A. Never both: a second record is refused. Either way the report says it was skipped. There is no project setting for it: every other run gets a designer's review.
18
18
 
19
- **`--critic`:** when `$ARGUMENTS` contains `--critic`, take it out before resolving the scenario. This run is one critic pass in a builder ↔ critic loop (a gauntlet loop) the user orchestrates: the builder needs the verdict and the findings fast, not fixes or a design review. Skip the advisor (C2) entirely and skip the designer's review (C3): after A, record `iamu designer-record <run-id> --skipped "critic mode"`. Run A, B, C, D (and E in linked mode) as usual. In step 5, present the glance without the Advisor and Designer lines, and do not offer **directions** or **designer**. Per invocation only, like `--no-ux`. When the loop looks converged (every human test passes, or no open major or critical findings), add one line: `Loop looks converged: run once without --critic for the advisor's and designer's review.`
19
+ **`--critic`:** when `$ARGUMENTS` contains `--critic`, take it out before resolving the scenario. This run is one critic pass in a builder ↔ critic loop (a gauntlet loop) the user orchestrates: the builder needs the verdict and the findings fast, not fixes or a design review. Skip the advisor (C2) entirely and skip the designer's review (C3): pass `--critic` to `iamu post-walk`, which records the skip itself (reason `--critic`); only on the manual path, run `iamu designer-record <run-id> --skipped "--critic"` after A. Never both. Run A, B, C, D (and E in linked mode) as usual. In step 5, present the glance without the Advisor and Designer lines, and do not offer **directions** or **designer**. Per invocation only, like `--no-ux`. When the loop looks converged (every human test passes, or no open major or critical findings), add one line: `Loop looks converged: run once without --critic for the advisor's and designer's review.`
20
20
 
21
21
  **`--fresh`:** when `$ARGUMENTS` contains `--fresh`, take it out before resolving the scenario. Clear the app's storage after `iamu browse start` (step 4) so the walk starts from clean storage, not from what an earlier walk left behind. `iamu browse` only; per invocation, like `--no-ux`.
22
22
 
@@ -236,7 +236,7 @@ Never silently guess login credentials or auth strategy without confirming with
236
236
 
237
237
  **Interactive Auth Handshake (for `interactive`, enterprise auth, SSO, 2FA, BankID):**
238
238
  If `auth_strategy` is `interactive` or the product is behind enterprise login where automated dev persona switching is not configured:
239
- 1. Open the browser to the target URL (`iamu browse start --run <run-id>` or browser tool).
239
+ 1. Open the browser to the target URL (`iamu browse start` or browser tool). There is no run id yet; step 4 creates the run, and `iamu browse start --run <run-id>` there sizes the already open browser for the persona.
240
240
  2. Prompt the human user:
241
241
  > 👉 **Please log in as `<persona.role>` (`<persona.name>`) in the opened browser window.** Tell me once you reach the dashboard (e.g. "I'm logged in") to hand control to the walker...
242
242
  3. Wait for the user to confirm, then let the walker drive the authenticated session.
@@ -269,7 +269,7 @@ Use the returned `run_id` and `path` for all subsequent operations.
269
269
  iamu browse start --run <run-id>
270
270
  ```
271
271
 
272
- It sizes the page as the device the persona's tags name (`mobile`/`phone`, `tablet`/`ipad`, `desktop`/`laptop`; `start-run` prints it as `device`) and resizes a browser left at another persona's size.
272
+ It sizes the page as the device the persona's tags name (`mobile`/`phone`, `tablet`/`ipad`, `desktop`/`laptop`; `start-run --json` returns it as `viewport.device`) and resizes a browser left at another persona's size.
273
273
 
274
274
  **Fresh walk (`--fresh`, `iamu browse` only).** When `--fresh` was given, or when running iterative passes against a browser left open (e.g. with `--critic`), clear the origin's storage after `browse start` so each walk starts from clean app storage:
275
275
 
@@ -287,10 +287,10 @@ iamu instructions walk --scenario <scenario-slug> --run <run-id> --surface brows
287
287
 
288
288
  The result's `walker_prompt` is the walker's entire prompt (also persisted at `walker_prompt_path`). Pass it verbatim — do not rewrite, summarize or trim it. The prompt already carries the dismissed findings, the active tester guidance rules (`iamu/guidance/`) for this scenario, and — when fixes await a re-run — the places they were seen (places only, never what was wrong; the list is in `revisit`). The rest of the bundle (`persona`, `outline`, `access`, `dismissed_findings`, `tester_guidance`, …) is there for you, not the walker. If `access` is missing a half, fill it in first (step 3) and re-run this command.
289
289
 
290
- **Preflight: Unattended execution check.** A walkthrough executes 15–30 terminal commands sequentially (`iamu browse step`, `iamu new-finding`). If your agent host requires manual confirmation for terminal/shell commands (standard interactive mode in Claude Code, Cursor, Antigravity, Cline, Windsurf, etc.), the walker subagent will stall waiting for approval on every step. Before dispatching, verify that command auto-approval / unattended execution is enabled in your environment, or warn the user once:
290
+ **Preflight: Unattended execution check.** A walkthrough executes 15–30 terminal commands sequentially (`iamu browse step`, `iamu new-finding`). If your agent host requires manual confirmation for terminal/shell commands (the standard interactive mode of most agent hosts), the walker subagent will stall waiting for approval on every step. Before dispatching, verify that command auto-approval / unattended execution is enabled in your environment, or warn the user once:
291
291
  "Autonomous walkthroughs require auto-approving terminal commands so the walker can drive the product unattended. If command approvals are prompted, please enable auto-approval or expect to approve steps manually."
292
292
 
293
- **CRITICAL: Dispatch the walker as an isolated subagent.** Spawn a fresh subagent using your host editor's subagent mechanism (e.g. `Agent(...)` in Claude Code, `invoke_subagent` in Antigravity, or host-native subagent launcher). The subagent gets ONLY the walking prompt (`walker_prompt`) — no prior conversation history.
293
+ **CRITICAL: Dispatch the walker as an isolated subagent.** Spawn a fresh subagent using your host's own subagent mechanism. The subagent gets ONLY the walking prompt (`walker_prompt`) — no prior conversation history.
294
294
 
295
295
  A fresh subagent is NOT blind by default. On most hosts it still loads the project's agent instructions and can read files in the repo, so it may know the domain model, the route table, and why a screen was built the way it was — none of which the persona knows. The methodology's "Stay outside the product" rule is what keeps it honest; it is part of `walker_prompt` — never remove or soften it.
296
296
 
@@ -300,17 +300,18 @@ A fresh subagent is NOT blind by default. On most hosts it still loads the proje
300
300
  - **Child Session Suppression:** The walker must never execute parent workflow routines (`iamu init`, `iamu triage`, `iamu new`). All steps, findings, and summaries are recorded atomically via `iamu browse step`, `iamu new-finding`, and `iamu summary`.
301
301
 
302
302
  **Model tiering & subagent dispatch:**
303
- - **Walker (Browser Navigation):** High turn count, and a judgement at every screen about what fits the persona's role. Use the **mid** tier (`sonnet` in Claude Code, `flash` in Antigravity) by default: on the role-fit benchmark in Claude Code it found the same problems as `haiku` about 1.7× faster, at a higher price per token. In `--critic` loops, where cost per walk matters more than the time of one walk, the **fastest** tier (`haiku` in Claude Code) is an option.
304
- - **Matcher:** Short-text classification (same problem or not) into strict JSON that `match-record` validates. Use the **fastest** tier (`haiku` in Claude Code, `flash_lite` in Antigravity, else the mid tier).
305
- - **Judge:** Evaluates the human tests from the walk's recorded steps and findings (`judge_prompt.md`, text-only reading comprehension). Use the **mid** tier (`sonnet` in Claude Code, `flash` in Antigravity).
303
+ - **Walker (Browser Navigation):** High turn count, and a judgement at every screen about what fits the persona's role. Use the **mid** tier by default: on the role-fit benchmark it found the same problems as the fastest tier about 1.7× faster, at a higher price per token. In `--critic` loops, where cost per walk matters more than the time of one walk, the **fastest** tier is an option.
304
+ - **Matcher:** Short-text classification (same problem or not) into strict JSON that `match-record` validates. Use the **fastest** tier (else the mid tier).
305
+ - **Judge:** Evaluates the human tests from the walk's recorded steps and findings (`judge_prompt.md`, text-only reading comprehension). Use the **mid** tier.
306
+ - **Advisor and designer:** the **thorough** tier.
306
307
 
307
- ```
308
- # In Claude Code:
309
- Agent({ description: "Walk <scenario-slug> as <persona.name>", model: "sonnet", prompt: "<walker_prompt, verbatim>" })
308
+ Dispatch each with your host's subagent launcher, giving it the model for the tier, the walker prompt verbatim (or, for the other stages, the path to the prompt file). Example model names per host, which change over time; use what your host offers at that tier:
310
309
 
311
- # In Antigravity / generic subagent hosts:
312
- invoke_subagent(Role="Persona Walker", Model="flash", Prompt="<walker_prompt, verbatim>")
313
- ```
310
+ | Tier | Claude Code | Antigravity |
311
+ |------|-------------|-------------|
312
+ | fastest | `haiku` | `flash_lite` |
313
+ | mid | `sonnet` | `flash` |
314
+ | thorough | `opus` | the host's strongest model |
314
315
 
315
316
  The subagent inherits the driving-surface tools and drives the product independently. It does not see this conversation.
316
317
 
@@ -385,19 +386,23 @@ iamu summary <run-id> --worked "What worked 1" --worked "What worked 2" --questi
385
386
 
386
387
  **Post-walk pipeline (MANDATORY — do NOT skip any step):**
387
388
 
388
- After the walker returns, you MUST complete ALL of the following before presenting findings to the user. Do NOT present findings early. Do NOT ask the user anything. Execute A, then B and C in parallel, then C2; the designer's review (C3) starts right after A and runs beside B, C and C2. D and E wait until every record (B, C, C2, C3) is in, so the report you read and the run you publish are complete.
389
+ After the walker returns, you MUST complete ALL of the following before presenting findings to the user. Do NOT present findings early. Do NOT ask the user anything. Execute A, then B and C in parallel, then C2 once the judge's verdict is recorded (the advisor reads it); the designer's review (C3) starts right after A and runs beside B, C and C2. D and E wait until every record (B, C, C2, C3) is in, so the report you read and the run you publish are complete.
389
390
 
390
391
  > **CRITICAL EXECUTION RULE (Zero Host File Tools):**
391
392
  > Never invoke host edit or write tools (`write_to_file`, `create_file`, `replace_file_content`, etc.) on any files in `iamu/` (including run artifacts, steps, findings, outlines, personas, scenarios, or guidance). All files in `iamu/` must be generated and modified exclusively via `iamu` CLI commands (`iamu new`, `iamu set`, `iamu step`, `iamu new-finding`, `iamu evaluate-record`, `iamu match-record`, `iamu post-walk`, etc.). If an entity needs a field updated (e.g. adding a capability to an outline), run `iamu set <type> <slug> ...` instead of editing files by hand. Record subagent JSON outputs via stdin heredoc (`--file - <<'EOF' ... EOF`), `--file <path>`, or `--data '<json>'`.
392
393
 
393
394
  **Fast path — prepare all post-walk prompts in one hop:**
394
- You can complete the run locally AND generate `match_prompt.md`, `judge_prompt.md`, `advise_prompt.md`, and `designer_prompt.md` in a single command:
395
+ You can complete the run locally AND generate `match_prompt.md`, `judge_prompt.md` and `designer_prompt.md` in a single command; the advisor's prompt waits for the judge:
395
396
 
396
397
  ```bash
397
398
  iamu post-walk <run-id> --json
398
399
  ```
399
400
 
400
- `iamu post-walk <run-id> --json` returns the `needed` status, `prompt_file_abs`, and `answer_file_abs` for `match`, `evaluate`, `advise`, and `designer` in one JSON object (pass `--critic` or `--no-ux` when applicable). If subagent JSON outputs are later written to their `answer_file_abs` paths in `<run-dir>/`, running `iamu post-walk <run-id> --json` again records all of them in lock-safe order automatically.
401
+ `iamu post-walk <run-id> --json` returns the `needed` status, `prompt_file_abs`, and `answer_file_abs` for `match`, `evaluate`, `advise`, and `designer` in one JSON object (pass `--critic` or `--no-ux` when applicable; it records those skips itself). The advisor reads the judge's verdict, so until `verdicts.json` exists `advise` comes back as `needed: false` with `reason: "awaiting judge"` and no prompt.
402
+
403
+ Call `post-walk` twice:
404
+ 1. After the walk: dispatch the matcher, the judge and the designer from the prompts it wrote, and write each answer to its `answer_file_abs` (or record it with the `*-record` command).
405
+ 2. After `evaluate-record` has recorded the verdict: run `iamu post-walk <run-id> --json` again. It records every answer file that has arrived, in lock-safe order, and now builds `advise_prompt.md`. Dispatch the advisor from it (C2) and record its answer the same way.
401
406
 
402
407
  **A. Assemble canonical + report (local).** Use `--no-push` so post-processing stays fast, local, and synchronous (already done if you ran `iamu post-walk <run-id> --json`):
403
408
 
@@ -421,7 +426,7 @@ This reads all steps, findings, and entity files, assembles `canonical.json`, ge
421
426
  iamu match <run-id> --json
422
427
  ```
423
428
 
424
- If `needed` is `false` (no earlier findings for this scenario, or none this run), there is no matcher subagent. Otherwise, read the prompt from `iamu/.runs/<run-id>/match_prompt.md` directly and dispatch a matcher subagent with it as its only context (use the **fastest** model tier: `haiku` in Claude Code, `Model="flash_lite"` in Antigravity). Record its JSON answer via `--file - <<'EOF'` (or `--data`):
429
+ If `needed` is `false` (no earlier findings for this scenario, or none this run), there is no matcher subagent. Otherwise, read the prompt from `iamu/.runs/<run-id>/match_prompt.md` directly and dispatch a matcher subagent with it as its only context (use the **fastest** model tier). Record its JSON answer via `--file - <<'EOF'` (or `--data`):
425
430
 
426
431
  ```bash
427
432
  iamu match-record <run-id> --file - <<'EOF'
@@ -438,7 +443,7 @@ This links recurrences to their earlier canonical finding, marks earlier finding
438
443
  iamu evaluate <run-id> --json
439
444
  ```
440
445
 
441
- Read the evaluation prompt from `iamu/.runs/<run-id>/judge_prompt.md` directly. Dispatch the evaluator as a subagent with that prompt, at the same time as the matcher (use the **mid** model tier: `sonnet` in Claude Code, `Model="flash"` in Antigravity). After the evaluator returns verdicts, record them via `--file - <<'EOF'` (or `--data`). Like every record command it stays local and never prompts; E publishes:
446
+ Read the evaluation prompt from `iamu/.runs/<run-id>/judge_prompt.md` directly. Dispatch the evaluator as a subagent with that prompt, at the same time as the matcher (use the **mid** model tier). After the evaluator returns verdicts, record them via `--file - <<'EOF'` (or `--data`). Like every record command it stays local and never prompts; E publishes:
442
447
 
443
448
  ```bash
444
449
  iamu evaluate-record <run-id> --file - <<'EOF'
@@ -449,13 +454,13 @@ EOF
449
454
 
450
455
  This links findings to human tests (`human_test_id`) and updates the report with judge verdicts.
451
456
 
452
- **C2. Advise: fixes and directions.** Skip in `--critic` mode. Otherwise get the advisor prompt (if not already prepared via `iamu post-walk`):
457
+ **C2. Advise: fixes and directions.** Skip in `--critic` mode. The advisor starts from the judge's verdict, so it runs only after `evaluate-record` has recorded it, never beside the judge. Get the advisor prompt (a second `iamu post-walk <run-id> --json` after `evaluate-record` builds it; before that `advise` says `needed: false`, `reason: "awaiting judge"`):
453
458
 
454
459
  ```bash
455
460
  iamu advise <run-id> --json
456
461
  ```
457
462
 
458
- If `needed` is `false` (blocked run, nothing open to advise, or already advised), skip to D. Otherwise read the prompt from `iamu/.runs/<run-id>/advise_prompt.md` and dispatch an advisor subagent with it as its only context (use the **thorough** model tier). Unlike the walker, the advisor reads the project's code (read-only) and the screenshots: it classifies each finding local or systemic, writes the fix from the persona's need, looks at how leading systems in the domain handle the moment, and proposes directions for the flow with their predicted reach on other personas. Record its JSON answer via `--file - <<'EOF'` (or `--data`):
463
+ If `needed` is `false` (blocked run, nothing open to advise, or already advised), skip to D. Otherwise read the prompt from `iamu/.runs/<run-id>/advise_prompt.md` and dispatch an advisor subagent with it as its only context (use the **thorough** model tier). Unlike the walker, the advisor reads the project's code (read-only) and the screenshots: it classifies each finding local or systemic, writes the fix from the persona's need, looks at how leading systems in the domain handle the moment, and proposes directions for the flow with their predicted reach on other personas. Tell the advisor to read the whole prompt (its answer schema is at the end) and to open at most 3–5 source files behind the screens where its findings occurred, found through `panorama.source_files` and `panorama.code_routes` in the bundle, rather than crawling unrelated screens. Record its JSON answer via `--file - <<'EOF'` (or `--data`):
459
464
 
460
465
  ```bash
461
466
  iamu advise-record <run-id> --file - <<'EOF'
@@ -466,7 +471,7 @@ EOF
466
471
 
467
472
  Each entry is checked on its own. Entries that come back rejected (an invented file or symbol, a path in the prose, a direction with too little evidence) stay unadvised and the rest is kept; a run is advised once, so do not record again. Mention rejected entries in step 5. Keep the result's `directions` and `rerun` for step 5.
468
473
 
469
- The judge (C) and the advisor (C2) are independent, so their subagents may run in parallel, but run `evaluate-record` and `advise-record` one after the other: both rewrite finding files. On a host without subagents, run the advise prompt yourself inline and record it the same way.
474
+ Dispatch the advisor (C2) after `evaluate-record`, never in parallel with the judge: it reads the verdict. Run `evaluate-record` and `advise-record` one after the other too: both rewrite finding files. On a host without subagents, run the advise prompt yourself inline and record it the same way.
470
475
 
471
476
  **C3. Designer's review.** For every run (unless `--no-ux` or `--critic` was given), start it as soon as A is done:
472
477
 
@@ -474,7 +479,7 @@ The judge (C) and the advisor (C2) are independent, so their subagents may run i
474
479
  iamu designer <run-id> --json
475
480
  ```
476
481
 
477
- If `needed` is `false` (`reason` is `blocked`, `no_screens` or `already_recorded`), skip it. Otherwise dispatch a fresh subagent that can look at images (the **thorough** model tier) with `iamu/.runs/<run-id>/designer_prompt.md` as its only context, alongside the matcher (B), the judge (C) and the advisor (C2) where the host allows. The subagent MUST open and look at the key screenshots the prompt lists (their paths are `key_screenshots` in the result) with its own file-viewing tool, judging visual hierarchy, layout, contrast and typography against the design docs the prompt names, else general craft. What it finds are designer findings: judgement, never the persona's experience, and never counted with the persona's findings or in the verdict.
482
+ If `needed` is `false` (`reason` is `blocked`, `no_screens` or `already_recorded`), skip it. Otherwise dispatch a fresh subagent that can look at images (the **thorough** model tier) with `iamu/.runs/<run-id>/designer_prompt.md` as its only context, alongside the matcher (B), the judge (C) and, once the verdict is in, the advisor (C2) where the host allows. The subagent MUST open and look at the key screenshots the prompt lists (their paths are `key_screenshots` in the result) with its own file-viewing tool, judging visual hierarchy, layout, contrast and typography against the design docs the prompt names, else general craft. What it finds are designer findings: judgement, never the persona's experience, and never counted with the persona's findings or in the verdict.
478
483
 
479
484
  The advisor (C2) does not wait for the designer, but D and E do: when its answer arrives, record it:
480
485
 
@@ -648,8 +653,15 @@ When the user asks to review findings one by one:
648
653
  > • **By design / intended behavior:** (Why this pattern is expected)
649
654
  > • **Walker error:** (What the walker misread or did wrong)
650
655
  > • **Out of scope:** (Non-issue for this product/flow)
656
+ > • **Duplicate:** (Same problem as another finding)
651
657
  > What specific rule should future walkers follow?"
652
-
658
+
659
+ Map the user's choice to the `--reason` value; no other value is accepted (`invalid_reason`):
660
+ - By design / intended behavior → `not_relevant`
661
+ - Walker error → `walker_error`
662
+ - Out of scope → `out_of_scope`
663
+ - Duplicate → `duplicate` (add `--duplicate-of <slug>`; it writes no guidance rule)
664
+
653
665
  Once the user provides their reasoning (or if already clear from discussion):
654
666
  Derive a concise, actionable guidance rule string.
655
667
  Execute: `iamu triage <slug> --status dismissed --reason <reason> --note "<user rationale>" --rule "<rule string>"`.
@@ -390,8 +390,14 @@ Step 3b: Walk Surface & Persona Login
390
390
  ```
391
391
  3. **Scaffold Persona**:
392
392
  ```bash
393
- iamu new persona --name "<Name>" --role "<Role>" --disposition "<Disposition>" --body "<2-4 sentence narrative detailing technical habits, patience level, and specific friction triggers>\n\n## Today\n<how they do this job today without the product, and what that costs or gives them>" [--access "<confirmed-account-or-role>"] --json
393
+ iamu new persona --name "<Name>" --role "<Role>" --disposition "<Disposition>" [--access "<confirmed-account-or-role>"] --body-file - --json <<'EOF'
394
+ <2-4 sentence narrative detailing technical habits, patience level, and specific friction triggers>
395
+
396
+ ## Today
397
+ <how they do this job today without the product, and what that costs or gives them>
398
+ EOF
394
399
  ```
400
+ Pass a multi-line body with `--body-file` (a path, or `-` for stdin as above), never with `\n` inside `--body`: the shell does not turn `\n` into a newline, so the file would store a literal backslash-n.
395
401
  4. **Scaffold Bound Scenario**:
396
402
  ```bash
397
403
  iamu new scenario --name "<persona-slug>--<outline-slug>" --outline "<outline-slug>" --persona "<persona-slug>" --entry "<confirmed_entry_path>" --body "<Persona's first-person test brief describing what they intend to achieve>" --json
@@ -45,10 +45,10 @@ Run `iamu instructions stage [slug] --json` to inspect the scenario's paired per
45
45
  iamu instructions stage <slug> --json
46
46
  ```
47
47
  This loads:
48
- - **Who:** Persona role, technical disposition, and required account access.
49
- - **Where:** What screen/page does the persona start on? (The landing URL / route prefix).
50
- - **What:** What world state must exist for the situation to make sense? (e.g. "Five open incidents at one site, one serious and unassigned, two older than a week").
51
- - **Human Tests:** What specific questions will be evaluated? (e.g. "Can Maria see which incident is unassigned without clicking each row?").
48
+ - **Who:** `persona.role`, `persona.disposition`, and `persona.access` (the persona's own account or role key; null when unset).
49
+ - **Where:** `scenario.entry_path` (the landing route; null when unset) and `scenario.target_url`.
50
+ - **What:** `scenario.state` and `outline.narrative`: what world state must exist for the situation to make sense? (e.g. "Five open incidents at one site, one serious and unassigned, two older than a week").
51
+ - **Human Tests:** `outline.human_tests`, the questions that will be evaluated (e.g. "Can Maria see which incident is unassigned without clicking each row?").
52
52
 
53
53
  ### 2. Scout the Codebase & Environment (The "How")
54
54
 
@@ -59,12 +59,17 @@ export interface HtmlReportSinceItem {
59
59
  title: string;
60
60
  note?: string;
61
61
  step_ids?: string[];
62
+ visited?: boolean;
62
63
  fixed_before?: boolean;
63
64
  severity_before?: string;
64
65
  severity_now?: string;
66
+ /** `resolvedUntriaged` only: the finding file to triage. */
67
+ slug?: string;
65
68
  }
66
69
  export interface HtmlReportVerification {
67
70
  resolved: HtmlReportSinceItem[];
71
+ /** Gone this run per the matcher, but never marked addressed. */
72
+ resolvedUntriaged?: HtmlReportSinceItem[];
68
73
  persists: HtmlReportSinceItem[];
69
74
  notObserved?: HtmlReportSinceItem[];
70
75
  newFindings: Array<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iamu-dev/iamu",
3
- "version": "0.8.0-beta.3",
3
+ "version": "0.8.0-beta.4",
4
4
  "type": "module",
5
5
  "description": "Test your product as realistic personas — scenario-driven development CLI",
6
6
  "license": "MIT",