wizz-method 2.1.0 → 2.2.0

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 (24) hide show
  1. package/package.json +1 -1
  2. package/src/bmm-skills/4-implementation/wizz-code-review/SKILL.md +2 -2
  3. package/src/bmm-skills/4-implementation/wizz-code-review/customize.toml +102 -8
  4. package/src/bmm-skills/4-implementation/wizz-code-review/references/review-economy.md +75 -0
  5. package/src/bmm-skills/4-implementation/wizz-code-review/steps/step-01-gather-context.md +29 -15
  6. package/src/bmm-skills/4-implementation/wizz-code-review/steps/step-02-review.md +13 -10
  7. package/src/bmm-skills/4-implementation/wizz-code-review/steps/step-03-triage.md +11 -5
  8. package/src/bmm-skills/4-implementation/wizz-code-review/steps/step-04-present.md +4 -0
  9. package/src/bmm-skills/4-implementation/wizz-quick-dev/customize.toml +103 -7
  10. package/src/bmm-skills/4-implementation/wizz-quick-dev/references/review-economy.md +75 -0
  11. package/src/bmm-skills/4-implementation/wizz-quick-dev/step-04-review.md +43 -18
  12. package/src/bmm-skills/4-implementation/wizz-quick-dev/step-05-present.md +4 -0
  13. package/src/bmm-skills/4-implementation/wizz-quick-dev/step-oneshot.md +2 -2
  14. package/src/modules/wizz/_shared/model-ladder.md +1 -0
  15. package/src/modules/wizz/_shared/token-economy.md +1 -1
  16. package/src/modules/wizz/subagents/codex/wizz-exec-review.toml +2 -1
  17. package/src/modules/wizz/subagents/gemini/wizz-exec-review.md +2 -1
  18. package/src/modules/wizz/subagents/opencode/wizz-exec-review.md +2 -1
  19. package/src/modules/wizz/subagents/spec.yaml +2 -1
  20. package/src/modules/wizz/subagents/wizz-exec-review.md +2 -1
  21. package/tools/fetch-assets.mjs +8 -1
  22. package/tools/installer/commands/fetch-assets.js +7 -8
  23. package/tools/installer/core/resolved-customizations.js +58 -10
  24. package/tools/installer/core/resolved-schema.js +116 -18
@@ -40,20 +40,103 @@ persistent_facts = [
40
40
 
41
41
  on_complete = ""
42
42
 
43
+ # Git pathspec globs to exclude from the diff. See references/review-economy.md
44
+ # § 1. This is a plain array, so a team/user override entry is APPENDED to the
45
+ # defaults below (per the merge rules above) — the defaults can never be
46
+ # removed by an override, only added to.
47
+
48
+ review_exclude = [
49
+ "**/package-lock.json",
50
+ "**/npm-shrinkwrap.json",
51
+ "**/yarn.lock",
52
+ "**/pnpm-lock.yaml",
53
+ "**/bun.lock",
54
+ "**/bun.lockb",
55
+ "**/Cargo.lock",
56
+ "**/poetry.lock",
57
+ "**/Pipfile.lock",
58
+ "**/Gemfile.lock",
59
+ "**/composer.lock",
60
+ "**/go.sum",
61
+ "**/uv.lock",
62
+ "**/__snapshots__/**",
63
+ "**/*.snap",
64
+ "**/*.min.js",
65
+ "**/*.min.css",
66
+ "**/*.js.map",
67
+ "**/*.css.map",
68
+ ]
69
+
70
+ # Plain-language sensitive areas the session judges the diff against to
71
+ # decide the `critical` tier — not patterns, guidance for the session's own
72
+ # reading of the changed files. See references/review-economy.md § 2.
73
+
74
+ review_critical_paths = [
75
+ "authentication",
76
+ "sessions",
77
+ "passwords and credentials",
78
+ "authorization",
79
+ "permissions and RLS",
80
+ "payments, billing and checkout",
81
+ "database migrations, schema and SQL",
82
+ "secrets, keys and .env files",
83
+ "cryptography",
84
+ "CI and deploy workflows",
85
+ ]
86
+
43
87
  # Review layers for the review step. `instruction` is the layer's whole
44
88
  # execution recipe — subagents by default, but an override may run anything
45
- # (e.g. an external reviewer via bash). {diff_file} and {claims_file} are
46
- # substituted at run time; both are paths, and {diff_file} is the unified
47
- # diff file the layer reads. Empty `instruction` disables a layer.
89
+ # (e.g. an external reviewer via bash). Layers read `{clean_diff_file}`
90
+ # (the cleaned/tiered diff), never the raw diff. The step substitutes
91
+ # `{clean_diff_file}`, `{diff_file}`, `{claims_file}` and `{max_calls}` at
92
+ # run time (this workflow has no `acceptance-auditor` layer, so `{spec_file}`
93
+ # is never substituted into a review layer here).
94
+ # An optional `tiers` array (`small`/`normal`/`critical`) gates a layer by
95
+ # diff size; absent means every tier. `max_calls` caps the layer's tool
96
+ # calls; at the cap the layer stops and its final message ends with a
97
+ # `PARTIAL:` line. Empty `instruction` disables a layer. See
98
+ # references/review-economy.md.
99
+ #
100
+ # This is an array of tables keyed by `id`: an override entry with the same
101
+ # `id` as one below REPLACES that whole layer, it does not merge field by
102
+ # field. An override that only means to change one field (e.g. `max_calls`)
103
+ # must still restate `tiers` and `max_calls` in full, or the layer loses
104
+ # whichever of those two it did not restate.
105
+ [[workflow.review_layers]]
106
+ id = "blind-verification"
107
+ name = "Blind Hunter + Verification Gap"
108
+ tiers = ["small", "normal"]
109
+ max_calls = 35
110
+ instruction = """
111
+ Launch a context-free `wizz-exec-review` subagent with this prompt — pinned to the platform's Forte tier (`opus` in Claude Code), never inheriting the session model. Tell the user the tier and count of this dispatch.
112
+
113
+ You run two review passes in order, and each pass follows its own instruction file.
114
+
115
+ Pass 1, Blind Hunter: read `{skill-root}/review-prompts/blind-hunter.md` completely and follow it against the review content alone. Do not open any other file during this pass. In this combined layer the minimum-issue count in blind-hunter.md does not apply: report only real issues. Write its findings under a `## Blind Hunter` heading.
116
+
117
+ Pass 2, Verification Gap: only after pass 1 is written, read `{skill-root}/review-prompts/verification-gap.md` completely and follow it. Write its output under a `## Verification Gap` heading.
118
+
119
+ Review content: the unified diff at `{clean_diff_file}`. Read that file — it is the content under review.
120
+
121
+ max_calls: {max_calls}. At the cap, stop and return what you have, ending with a final line `PARTIAL: <what you did not cover>`.
122
+
123
+ Do not invoke any skill, and do not spawn subagents of your own — you are the reviewer. If `blind-hunter.md` is unreadable, report that exact failure and stop. If `verification-gap.md` is unreadable, keep the Blind Hunter output you already wrote and end with a final line `PARTIAL: verification-gap pass not run` instead of stopping empty. Return your findings as text in your final message; do not route them through any findings-reporting tool the host may offer.
124
+
125
+ """
126
+
48
127
  [[workflow.review_layers]]
49
128
  id = "blind-hunter"
50
129
  name = "Blind Hunter"
130
+ tiers = ["critical"]
131
+ max_calls = 20
51
132
  instruction = """
52
133
  Launch a context-free `wizz-exec-review` subagent with this prompt — pinned to the platform's Forte tier (`opus` in Claude Code), never inheriting the session model. Tell the user the tier and count of this dispatch.
53
134
 
54
135
  Read `{skill-root}/review-prompts/blind-hunter.md` completely and follow it as your review instructions.
55
136
 
56
- Review content: the unified diff at `{diff_file}`. Read that file — it is the content under review.
137
+ Review content: the unified diff at `{clean_diff_file}`. Read that file — it is the content under review.
138
+
139
+ max_calls: {max_calls}. At the cap, stop and return what you have, ending with a final line `PARTIAL: <what you did not cover>`.
57
140
 
58
141
  Do not invoke any skill, and do not spawn subagents of your own — you are the reviewer. If the instruction file is unreadable, report that exact failure and stop. Return your findings as text in your final message; do not route them through any findings-reporting tool the host may offer.
59
142
 
@@ -62,6 +145,8 @@ Do not invoke any skill, and do not spawn subagents of your own — you are the
62
145
  [[workflow.review_layers]]
63
146
  id = "edge-case-hunter"
64
147
  name = "Edge Case Hunter"
148
+ tiers = ["normal", "critical"]
149
+ max_calls = 25
65
150
  instruction = """
66
151
  Launch a context-free `wizz-exec-review` subagent with this prompt — pinned to the platform's Forte tier (`opus` in Claude Code), never inheriting the session model. Tell the user the tier and count of this dispatch.
67
152
 
@@ -69,7 +154,9 @@ Read `{skill-root}/review-prompts/edge-case-hunter.md` completely and follow it
69
154
 
70
155
  claims_file (leave unread until your instructions call for it): {claims_file}
71
156
 
72
- Review content: the unified diff at `{diff_file}`. Read that file — it is the content under review.
157
+ Review content: the unified diff at `{clean_diff_file}`. Read that file — it is the content under review.
158
+
159
+ max_calls: {max_calls}. At the cap, stop and return what you have, ending with a final line `PARTIAL: <what you did not cover>`.
73
160
 
74
161
  Do not invoke any skill, and do not spawn subagents of your own — you are the reviewer. If the instruction file is unreadable, report that exact failure and stop. Return your findings as text in your final message; do not route them through any findings-reporting tool the host may offer.
75
162
 
@@ -78,19 +165,25 @@ Do not invoke any skill, and do not spawn subagents of your own — you are the
78
165
  [[workflow.review_layers]]
79
166
  id = "verification-gap"
80
167
  name = "Verification Gap Reviewer"
168
+ tiers = ["critical"]
169
+ max_calls = 25
81
170
  instruction = """
82
171
  Launch a context-free `wizz-exec-review` subagent with this prompt — pinned to the platform's Forte tier (`opus` in Claude Code), never inheriting the session model. Tell the user the tier and count of this dispatch.
83
172
 
84
173
  Read `{skill-root}/review-prompts/verification-gap.md` completely and follow it as your review instructions.
85
174
 
86
- Review content: the unified diff at `{diff_file}`. Read that file — it is the content under review.
175
+ Review content: the unified diff at `{clean_diff_file}`. Read that file — it is the content under review.
176
+
177
+ max_calls: {max_calls}. At the cap, stop and return what you have, ending with a final line `PARTIAL: <what you did not cover>`.
87
178
 
88
179
  Do not invoke any skill, and do not spawn subagents of your own — you are the reviewer. If the instruction file is unreadable, report that exact failure and stop. Return your findings as text in your final message; do not route them through any findings-reporting tool the host may offer.
89
180
 
90
181
  """
91
182
 
92
183
  # Review layers for the one-shot route. Consumed by step-oneshot.md, the same way
93
- # step-04-review.md consumes review_layers above.
184
+ # step-04-review.md consumes review_layers above. The one-shot route has no
185
+ # diff-size tiering — every layer here always runs, so `tiers` is not read
186
+ # and setting it on an entry here has no effect.
94
187
  #
95
188
  # O prompt do Blind Hunter vive em review-prompts/blind-hunter.md (fonte única,
96
189
  # item 22 da auditoria de 2026-09-11), mesmo padrão de edge-case-hunter e
@@ -100,6 +193,7 @@ Do not invoke any skill, and do not spawn subagents of your own — you are the
100
193
  [[workflow.oneshot_review_layers]]
101
194
  id = "blind-hunter"
102
195
  name = "Blind Hunter"
196
+ max_calls = 20
103
197
  instruction = """
104
198
  Launch a context-free `wizz-exec-review` subagent with this prompt — pinned to the platform's Forte tier (`opus` in Claude Code), never inheriting the session model. Tell the user the tier and count of this dispatch.
105
199
 
@@ -107,6 +201,8 @@ Read `{skill-root}/review-prompts/blind-hunter.md` completely and follow it as y
107
201
 
108
202
  Review content: the changed files in the current worktree. Inspect them directly before reviewing.
109
203
 
204
+ max_calls: {max_calls}. At the cap, stop and return what you have, ending with a final line `PARTIAL: <what you did not cover>`.
205
+
110
206
  Do not invoke any skill, and do not spawn subagents of your own — you are the reviewer. If the instruction file is unreadable, report that exact failure and stop. Return your findings as text in your final message; do not route them through any findings-reporting tool the host may offer.
111
207
 
112
208
  """
@@ -0,0 +1,75 @@
1
+ # Review Economy
2
+
3
+ Shared rules that keep the review layers on the Forte tier (`opus` in Claude Code) while cutting what they read and how many of them run. Two byte-identical copies live in `wizz-code-review/references/review-economy.md` and `wizz-quick-dev/references/review-economy.md`. Diffs are built with plain git commands; the tier is picked by session judgment.
4
+
5
+ ## 1. Build the diff
6
+
7
+ Every diff command here runs against the repository root, never a bare `.`: compute `TOP="$(git rev-parse --show-toplevel)"` once, then run every git command as `git -C "$TOP" ...`. Every flag goes before the `--`: `--no-ext-diff --no-color --no-textconv`. `{diff_file}` and `{clean_diff_file}` are written by the identical command for a given source — same flags, same source args — differing only in the pathspecs that follow the single `--`.
8
+
9
+ - **Pathspecs.** Positive pathspecs come first, always: `:(top)` for the whole tree, or one `:(top,literal)<path>` per path for a file-list or chunked source. `{clean_diff_file}` then adds exclude pathspecs after the positive ones — one `:(top,exclude,glob)<pattern>` per `{workflow.review_exclude}` entry (`wizz-quick-dev` adds `:(top,exclude,literal)<repo-relative spec path>` first — see "Spec path" below). `{diff_file}` never carries an exclude pathspec.
10
+ - **Per-source command.** `git -C "$TOP" diff <source-args> --no-ext-diff --no-color --no-textconv -- <pathspecs>`, where `<source-args>` is:
11
+ | Source | `<source-args>` |
12
+ |---|---|
13
+ | Staged changes only | `--cached` |
14
+ | Uncommitted changes (staged + unstaged) | `HEAD` |
15
+ | Branch diff | `<base-branch>...HEAD` — only after `git -C "$TOP" merge-base <base-branch> HEAD` has already succeeded |
16
+ | Commit range | `<range>` |
17
+ | File list / chunk | `HEAD`, with `:(top,literal)<path>` positive pathspecs, one per listed or chunked path |
18
+ - **Exclusions.** `{workflow.review_exclude}` is a list of git pathspec globs. The default in `customize.toml`:
19
+ `**/package-lock.json`, `**/npm-shrinkwrap.json`, `**/yarn.lock`, `**/pnpm-lock.yaml`, `**/bun.lock`, `**/bun.lockb`, `**/Cargo.lock`, `**/poetry.lock`, `**/Pipfile.lock`, `**/Gemfile.lock`, `**/composer.lock`, `**/go.sum`, `**/uv.lock`, `**/__snapshots__/**`, `**/*.snap`, `**/*.min.js`, `**/*.min.css`, `**/*.js.map`, `**/*.css.map`.
20
+ - **Spec path (`wizz-quick-dev` only).** Compute the spec's repo-relative path first — `git -C "$TOP" ls-files --full-name -- <spec-path>` when it is tracked, otherwise a path relative to `$TOP` (e.g. via `realpath`) — then exclude it as `:(top,exclude,literal)<repo-relative path>`, ahead of the `review_exclude` excludes. If that one exclusion alone empties `{clean_diff_file}` (untracked files included) — meaning the spec's own edit was the only change — there is nothing to review: skip the review layers entirely and go straight to triage with no findings. Do not fall back to the raw diff in this case.
21
+ - **Untracked files (uncommitted changes and file-list sources).** List them with `git -C "$TOP" ls-files --others --exclude-standard -z -- <pathspecs>` — the same positive-plus-exclude pathspecs as `{clean_diff_file}` for its own list, the positive pathspecs alone for `{diff_file}`'s list. For every path the `-z` listing returns, append it to that diff with `git -C "$TOP" diff --no-index --no-color -- /dev/null <path>`. Exit code `1` means "files differ" — that is success, append the output; only an exit code greater than `1` is a failure. Both `{diff_file}` and `{clean_diff_file}` include every untracked file that passes their own pathspecs.
22
+ - **Counts.** `files` and `changed_lines` come from `git -C "$TOP" diff <source-args> --no-ext-diff --no-color --no-textconv --numstat -- <pathspecs>` (the same pathspecs as the diff being counted) plus, for every untracked path, `git -C "$TOP" diff --no-index --numstat -- /dev/null <path>`. `files` is the number of lines printed across both; `changed_lines` is the sum of their numeric columns. A binary (`-`) counts as a file with 0 lines.
23
+ - **Provided or pasted diffs, and no VCS.** No git at all — `{clean_diff_file}` = `{diff_file}`. See § 2 for how `files`/`changed_lines` are counted here instead.
24
+ - **Nothing left after exclusions.** `{clean_diff_file}` is empty — untracked files included, not merely that `--numstat` printed nothing for the tracked part. `wizz-code-review` HALTs, lists the exclusions, and asks whether to review the raw diff anyway. `wizz-quick-dev` reviews the raw diff instead, except for the spec-only case above.
25
+ - **Git failure.** Review the raw `{diff_file}` at `critical`.
26
+ - `{clean_diff_file}` is a uniquely-named file in the system temp directory.
27
+
28
+ ## 2. Pick the tier (session judgment)
29
+
30
+ | Tier | Rule | Active layers | Forte subagents |
31
+ |---|---|---|---|
32
+ | `small` | at most 3 files and 80 changed lines (after exclusion), no critical hit | `blind-verification` | 1 |
33
+ | `normal` | anything above `small`, no critical hit | `blind-verification`, `edge-case-hunter` | 2 |
34
+ | `critical` | the change touches a sensitive area, or the user asks for every layer | `blind-hunter`, `edge-case-hunter`, `verification-gap`, `acceptance-auditor` (`wizz-quick-dev` has no `acceptance-auditor` layer: 3 layers there) | up to 4 (`wizz-quick-dev`: up to 3) |
35
+
36
+ The session reads the file list (`git diff --name-status`) and, when unsure, the relevant hunks, then decides the tier itself by judgment.
37
+
38
+ **Provided or pasted diffs, and no VCS.** There is no `git --numstat` to read. Count `files` from the diff's own `diff --git` (or, lacking that, `+++`) headers, and `changed_lines` from the `+`/`-` body lines (the `+++`/`---` header lines themselves don't count). The table above applies without exception in both workflows — `small` included.
39
+
40
+ `{workflow.review_critical_paths}` is a plain-language list of sensitive areas, not a pattern list. Default: authentication, sessions, passwords and credentials, authorization, permissions and RLS, payments, billing and checkout, database migrations, schema and SQL, secrets, keys and `.env` files, cryptography, CI and deploy workflows. Judge by meaning, not by substring: a security check added inside an otherwise generic file counts as `critical`; a document that merely talks about auth does not.
41
+
42
+ Raise the tier when in doubt, never lower it — a change that clearly touches something the list above doesn't name (e.g. a data migration done in application code) still earns `critical`. State the tier, the reason and the resulting layer count to the user before launching any layer.
43
+
44
+ A layer is active only when `{tier}` is listed in its `tiers` field. A layer without `tiers` is active in every tier.
45
+
46
+ If `{tier}` is empty or not one of `small`/`normal`/`critical` when the review step (`wizz-code-review` step 2) or the `wizz-quick-dev` Review section starts, set it to `critical` now and say so before evaluating any layer.
47
+
48
+ Track each configured layer's outcome as `{layer_status}` — every `id` marked `active` or `dropped: <reason>` (tier, disabled by override, or its `when` condition). This list travels into triage so a delegated triager can tell, for example, whether `acceptance-auditor` ran.
49
+
50
+ ## 3. Cap each layer
51
+
52
+ Every layer carries `max_calls` in its config. Substitute `{max_calls}` in its instruction. A layer that hits the cap stops and ends its final message with a line `PARTIAL: <what you did not cover>` — that exact marker is what the steps and triage look for to detect a partial layer. Triage treats a layer that returned that marker like a failed layer: the review may be incomplete and the user is told so.
53
+
54
+ A layer that returns an explicit no-findings result (e.g. `[]`, or "No verification gaps found.") has succeeded, not failed — it found nothing to report. Only errors, timeouts, unreadable output, or a `PARTIAL:` ending count against a layer.
55
+
56
+ A layer whose review-prompts method returns JSON (e.g. Edge Case Hunter's array) may still hit the cap mid-run and end with a trailing `PARTIAL: <...>` line after the JSON payload. Parse the JSON that precedes that line as the layer's findings — the trailing line only marks the run partial, it does not invalidate the JSON before it.
57
+
58
+ When the brief names a `review-prompts/` file, that file owns the method and the output format. The reviewer ignores its generic verdict format and does not re-run the project's test suite unless the review prompt itself asks for it.
59
+
60
+ ## 4. Decide who triages
61
+
62
+ The Forte tier is defined in `_shared/model-ladder.md`.
63
+
64
+ - **Session runs on the Forte tier:** the session triages, as the triage instructions say. It already holds the context, so a subagent would only re-read it.
65
+ - **Any session model other than the Forte tier:** write the collected findings, each with its originating layer `id`, to a uniquely-named temp file and launch one `wizz-exec-opus` subagent. Its brief is: the triage instructions (the path of the step file that holds them), the findings file, `{diff_file}`, `{spec_file}` when present, the paths of any loaded context docs, `{tier}`, `{failed_layers}`, `{layer_status}` (the active/dropped layer ids with drop reasons, so the triager knows which layers actually ran), and — only in workflows that set it (`wizz-code-review`) — `{review_mode}`. The subagent runs the whole pipeline itself: verdicts, the acceptance audit, grouping, and routing into categories. It returns every entry with severity, category and evidence, plus every dismissal with its reason — it never writes to any file; the session writes every log. The session then re-checks the subagent's own verdicts and routing against the evidence it returned — this is the session validating a delegated triager's work, not a new prompt to the user — and carries on per each workflow's own step. In `wizz-code-review`, `decision_needed` entries still get a genuine human confirmation before continuing, exactly as the presentation step already does; a confirmed entry the user rejects there is logged as dismissed with the user's own reason, never forced through. In `wizz-quick-dev`, `intent_gap` still loops back to the human as part of resolving it, and `bad_spec` still loops back automatically — the session's re-check adds no new user prompt for either.
66
+
67
+ `{failed_layers}` stores layer `id`s (append ` (partial)` for a partial layer); every check against it compares ids, not names.
68
+
69
+ **Acceptance audit.** Runs before the per-finding verdicts, as one more source of findings that then get verdicts like any other. In `wizz-code-review`, run it when a spec is present and the `acceptance-auditor` layer did not run to completion for any reason: `{layer_status}` marks it `dropped` (tier, disabled by override, or its `when` condition), or it failed or ended `PARTIAL:` (its id appears in `{failed_layers}`) — a `critical` tier where that layer actually ran to completion does not also get the triage-side audit. In `wizz-quick-dev`, run it on every tier — that workflow has no `acceptance-auditor` layer. Either way, check the diff against the spec's acceptance criteria and constraints, and add a finding with source `triage-acceptance` for each violation, deviation or missing behavior.
70
+
71
+ ## 5. Cleanup
72
+
73
+ Delete `{diff_file}` only when `{diff_file_owned}` is true — never a file the user supplied directly by path. Delete `{clean_diff_file}` only when it is a different path from `{diff_file}`; when the two are the same path (a provided, pasted or no-VCS diff, a git failure, or a raw review after exclusions emptied the clean diff), the `{diff_file}` rule above decides. Also delete `{claims_file}` when it is non-empty, and any findings temp files. Delete them when the workflow ends, including every HALT that ends it outright. The one exception is the subagents-unavailable HALT: it keeps `{diff_file}` and `{clean_diff_file}`, because that HALT resumes when the human pastes findings back rather than ending the workflow.
74
+
75
+ In `wizz-quick-dev`, each review loop iteration writes a new `{diff_file}`/`{clean_diff_file}` generation; before overwriting them for the next loop, save the previous generation's paths and delete those old files per this section.
@@ -1,7 +1,12 @@
1
1
  ---
2
2
  deferred_work_file: '{implementation_artifacts}/deferred-work.md'
3
3
  diff_file: '' # set at runtime: path to the unified diff file
4
+ diff_file_owned: '' # set at runtime: true — this workflow always writes {diff_file} itself
4
5
  claims_file: '' # set at runtime: path to the change's own narrative
6
+ clean_diff_file: '' # set at runtime: path to the cleaned diff the review layers read
7
+ tier: '' # set at runtime: small | normal | critical
8
+ failed_layers: '' # set at runtime: comma-separated list of layer ids that failed, timed out, or ended PARTIAL; reset to '' at the start of every loop
9
+ layer_status: '' # set at runtime: every configured layer's id marked active or dropped (with the drop reason); reset at the start of every loop
5
10
  ---
6
11
 
7
12
  # Step 4: Review
@@ -12,54 +17,74 @@ claims_file: '' # set at runtime: path to the change's own narrative
12
17
  - Review subagents get NO conversation context.
13
18
  - Review subagents run pinned to the platform's Forte tier via `wizz-exec-review` (`opus` in Claude Code) — never at the same model capability as the current session. See `_shared/model-ladder.md`.
14
19
  - Run subagents synchronously: launch them together, then wait for all results before continuing. Never backgrounded or detached, never ending the turn to await results.
20
+ - Review layers scale with `{tier}` and read `{clean_diff_file}`. See `./references/review-economy.md`.
15
21
 
16
22
  ## INSTRUCTIONS
17
23
 
18
- Change `{spec_file}` status to `in-review` in the frontmatter before continuing.
24
+ Change `{spec_file}` status to `in-review` in the frontmatter before continuing. Reset `{failed_layers}` and `{layer_status}` to `''` at the start of this loop, before anything else below.
19
25
 
20
26
  ### Stage the Diff
21
27
 
22
- Read `{baseline_commit}` from `{spec_file}` frontmatter. If `{baseline_commit}` is missing or `NO_VCS`, use best effort to determine what changed. Otherwise use the repository's version-control tooling to write `{diff_file}` — a uniquely-named file in the system temp directory — with a unified diff of all changes since `{baseline_commit}`, untracked files included. The review layers read that file; the diff text is never pasted into their prompts.
28
+ Read `{baseline_commit}` from `{spec_file}` frontmatter. Set `{diff_file_owned}` = `true` — this workflow always generates `{diff_file}` itself; it is never a user-supplied path. Before this section writes the new generation of `{diff_file}`/`{clean_diff_file}`, save the previous loop's paths (if any) in separate variables so they can still be deleted once the new generation exists.
29
+
30
+ **No baseline.** If `{baseline_commit}` is missing or `NO_VCS`, use best effort to determine what changed and write it to `{diff_file}`. Set `{clean_diff_file}` = `{diff_file}`. Pick `{tier}` per § 2 by session judgment from what you can see of the change — `small` is available here exactly like `normal`/`critical`, never ruled out by default; raise it only when the change or a changed path actually warrants it. Skip the rest of this section and go straight to Review with these values.
31
+
32
+ Otherwise, compute `TOP="$(git rev-parse --show-toplevel)"` once and reuse it below. Write `{diff_file}` — a uniquely-named file in the system temp directory — with a unified diff of all changes since `{baseline_commit}`: `git -C "$TOP" diff {baseline_commit} --no-ext-diff --no-color --no-textconv -- ':(top)' > {diff_file}`, then append untracked files per `./references/review-economy.md` § 1: list them with `git -C "$TOP" ls-files --others --exclude-standard -z -- ':(top)'` and append each with `git -C "$TOP" diff --no-index --no-color -- /dev/null <path> >> {diff_file}`.
23
33
 
24
34
  Set `{claims_file}` = `{spec_file}`. The spec is the change's own account of itself, and it goes to the edge-case layer alone — as a path, so that layer reads it only after its own tracing and the other layers never see it at all.
25
35
 
26
- Writing `{diff_file}` is the only change this section makes. Do NOT `git add` anything.
36
+ Compute the spec's repo-relative path first — `git -C "$TOP" ls-files --full-name -- {spec_file}` when it's tracked, otherwise a path relative to `$TOP` (e.g. via `realpath`). Build `{clean_diff_file}` per `./references/review-economy.md` § 1: `git -C "$TOP" diff {baseline_commit} --no-ext-diff --no-color --no-textconv -- ':(top)' ':(top,exclude,literal)<repo-relative spec path>' ':(top,exclude,glob)<pattern>' ...` — the spec exclude first, then one `:(top,exclude,glob)<pattern>` per `{workflow.review_exclude}` entry. Append untracked files to `{clean_diff_file}` the same way as `{diff_file}`, but listed with these same positive-plus-exclude pathspecs, so the spec file and any `review_exclude` match are skipped. Get `files` and `changed_lines` from `git -C "$TOP" diff --no-ext-diff --no-color --no-textconv --numstat` with the same arguments and pathspecs, plus per-file `git -C "$TOP" diff --no-index --numstat -- /dev/null <path>` for the untracked ones.
37
+
38
+ - If a git command in this section fails: set `{clean_diff_file}` = `{diff_file}` and `{tier}` = `critical`, say so, and continue.
39
+ - If `{clean_diff_file}` is empty (untracked files included) and excluding only the spec pathspec — with none of the `review_exclude` globs applied — already empties it too: the spec's own edit was the only change. There is nothing to review: skip the Review section entirely (no layer launches, `{failed_layers}` stays empty) and go straight to Classify, which finds nothing against the empty diff. Do not fall back to the raw diff in this case.
40
+ - Else if nothing is left after exclusions for any other reason (a `review_exclude` glob, not the spec exclude, accounts for the emptiness): review the raw diff per § 1 — `{clean_diff_file}` = `{diff_file}`, tier picked from the raw diff.
41
+ - Otherwise, pick the tier per § 2 (`small` included, on equal footing with `normal`/`critical`) by reading `git -C "$TOP" diff --name-status {baseline_commit} -- ':(top)' ':(top,exclude,literal)<repo-relative spec path>'` and judging it against `{workflow.review_critical_paths}`.
42
+
43
+ Announce the exclusions once, from this run only. Tell the user the tier, the exclusions, and the resulting Forte subagent count before launching any layer.
44
+
45
+ This section's only file changes are temp diff files (`{diff_file}` and `{clean_diff_file}`). Do NOT `git add` anything. Once this section has written the new generation, delete the previous loop's saved paths per `./references/review-economy.md` § 5 — never let two generations pile up.
27
46
 
28
47
  ### Review
29
48
 
30
- 1. The review layers are `{workflow.review_layers}`, resolved during activation. For each layer:
31
- - `instruction` empty or missing → drop the layer silently (an override disabled it).
32
- - `when` condition present and not satisfied by the current context → drop the layer and tell the user.
33
- - otherwise → the layer is active.
49
+ 1. The review layers are `{workflow.review_layers}`, resolved during activation. If `{tier}` is empty or not one of `small`/`normal`/`critical` (and the "no baseline" branch above did not already set it), set it to `critical` now and tell the user why, per `./references/review-economy.md` § 2. For each layer, record the outcome in `{layer_status}` as you go:
50
+ - `tiers` present and `{tier}` not listed in it → drop the layer silently (it does not apply to this diff's size/risk). Record `<id>: dropped (tier)`.
51
+ - `instruction` empty or missing → drop the layer silently (an override disabled it). Record `<id>: dropped (disabled by override)`.
52
+ - `when` condition present and not satisfied by the current context → drop the layer and tell the user. Record `<id>: dropped (when condition not met)`.
53
+ - otherwise → the layer is active. Record `<id>: active`.
34
54
 
35
- If no layer is active, HALT and escalate to the human.
55
+ If no layer is active, delete `{diff_file}`, `{clean_diff_file}` and any findings temp files per `./references/review-economy.md` § 5, then HALT and escalate to the human.
36
56
 
37
- 2. Announce skipped layers first, then launch every active layer before handling any layer's result. Try running all active layers simultaneously: expand `{skill-root}` in each layer's `instruction` to this skill's absolute installed directory, then substitute the runtime placeholders (`{diff_file}`, `{claims_file}`). `{diff_file}` is a path: substitute the absolute path and let the layer read the file — a launch prompt never carries diff text. When an instruction launches a reviewer subagent, launch that child with the prompt text after placeholder substitution; do not load the reviewer instruction file yourself. For any other customized instruction, execute it as written. Do not leave `{skill-root}` unresolved in a child prompt — the child's working directory is not yours. Spawn every reviewer before reading or reacting to any of their output; begin collection and triage only once all are launched.
57
+ 2. Announce skipped layers first, then launch every active layer before handling any layer's result. Try running all active layers simultaneously: expand `{skill-root}` in each layer's `instruction` to this skill's absolute installed directory, then substitute whichever runtime placeholders it contains — `{clean_diff_file}`, `{diff_file}`, `{claims_file}`, `{max_calls}` (the layer's own `max_calls`; a layer without one has no `max_calls:` line to substitute — remove that line entirely). Every diff/file placeholder is a path: substitute the absolute path and let the layer read the file — a launch prompt never carries diff text. The diff the layers actually read, including in the no-subagents inline fallback below, is `{clean_diff_file}`. When an instruction launches a reviewer subagent, launch that child with the prompt text after placeholder substitution; do not load the reviewer instruction file yourself. For any other customized instruction, execute it as written. Do not leave `{skill-root}` unresolved in a child prompt — the child's working directory is not yours. Spawn every reviewer before reading or reacting to any of their output; begin collection and triage only once all are launched.
38
58
 
39
- 3. If a layer's instruction requires subagents and none are available, for each such layer write under `{implementation_artifacts}` that layer's child prompt with every file it points to — the diff, the claims, the reviewer instruction file — replaced inline by that file's contents, and every other line left exactly as written. That session shares no filesystem with this one, so its prompt has to stand alone; this is the only place you read a reviewer instruction file yourself. Then HALT. Ask the human to run each in a separate session (ideally a different LLM) and paste back the findings.
59
+ 3. If a layer's instruction requires subagents and none are available, for each such layer write under `{implementation_artifacts}` that layer's child prompt with every file it points to — `{clean_diff_file}`, the claims, the reviewer instruction file — replaced inline by that file's contents, and every other line left exactly as written. That session shares no filesystem with this one, so its prompt has to stand alone; this is the only place you read a reviewer instruction file yourself. Then HALT — do NOT delete `{diff_file}` or `{clean_diff_file}`; this HALT resumes when findings are pasted back, so triage still needs them. Ask the human to run each in a separate session (ideally a different LLM) and paste back the findings.
40
60
 
41
- 4. If any layer fails, times out, or returns empty, note it and proceed with the remaining layers. Collect all findings, keeping track of each finding's originating layer `id`.
61
+ 4. If any layer errors, times out, or returns unreadable output, append the layer's `id` to `{failed_layers}` (comma-separated) and proceed with the remaining layers. A layer that returns an explicit no-findings result (e.g. `[]`, or "No verification gaps found.") has succeeded — do not append it to `{failed_layers}`. A layer whose final message ends with a `PARTIAL:` line is partial: append `<id> (partial)` to `{failed_layers}` and keep its findings. Collect all findings, keeping track of each finding's originating layer `id`. After collecting findings, if `{failed_layers}` is non-empty, warn the user that the review may be incomplete, and never present it as clean.
42
62
 
43
63
  ### Classify
44
64
 
45
- 1. Once every layer has reported — and not before — render a verdict on each finding on its own, ahead of any deduplication or grouping. For each finding:
65
+ Decide who triages, per `./references/review-economy.md` § 4. When the session runs on the Forte tier, it triages directly, following the instructions below. Otherwise, write the collected findings — each tagged with its originating layer `id` — to a uniquely-named temp file and launch one `wizz-exec-opus` subagent. Its brief is: these Classify instructions (Classify items 1–4 below — the acceptance audit, verdicts, grouping, and routing into intent_gap/bad_spec/patch/defer, including the dismissal reasons), the findings file, `{diff_file}`, `{spec_file}` (when present), the paths of any context docs loaded from `{spec_file}`'s `context:` frontmatter list in step-03, `{tier}`, `{failed_layers}`, and `{layer_status}` (so the triager can tell which layers actually ran) — quick-dev never sets `{review_mode}`, so the brief never carries it. The subagent never writes to any file, including `{spec_file}` — it returns every entry with severity, category and evidence, plus every dismissal with its reason. The session then re-checks the subagent's own verdicts and routing against the evidence it returned — this is the session validating a delegated triager's work, it adds no new prompt to the user — writes the `## Review Triage Log`, and runs Classify item 5 (loopbacks, patches, defers) itself exactly as when the session triages directly.
66
+
67
+ 1. On every tier — this workflow has no `acceptance-auditor` layer — run the acceptance audit from `./references/review-economy.md` § 4 against `{spec_file}`: check the diff against the spec's acceptance criteria and constraints, and add a finding for each violation, deviation or missing behavior, with source `triage-acceptance`, to the unified list, before verdicts. It gets a verdict like any other finding, per Classify item 2.
68
+
69
+ 2. Once every layer has reported — and not before — render a verdict on each finding on its own, ahead of any deduplication or grouping. For each finding:
46
70
  - **Verify its own claimed consequence** at the location it names. Read past the diff hunk — into the callers, the guards upstream, whatever else the site depends on — far enough to tell whether that consequence actually occurs. Another finding's outcome, however adjacent, never settles this one.
47
71
  - **Assign severity** from the verified consequence for the artifact's main consumer (software user, document reader, etc). Disregard any severity assigned by a reviewing subagent. Review subagents operate under by-design information asymmetry and do not have enough context to set final severity for this workflow.
48
72
  - `low`: none or cosmetic
49
73
  - `medium`: tolerable
50
74
  - `high`: intolerable
51
- - **Keep or dismiss.** Keep a finding only where verification confirmed its consequence. Dismiss noise, claims the verification refuted, and claims it could not substantiate — no path to the claimed consequence at the named site is a valid disposal. Whatever the reason, it must dispose of the finding's own claim: a true fact about neighboring code that leaves the claim standing is not a dismissal, and the finding stays kept. Record each dismissal with its reason in the `## Review Triage Log` section of `{spec_file}`; never drop a finding silently.
75
+ - **Keep or dismiss.** Keep a finding only where verification confirmed its consequence. Dismiss noise, claims the verification refuted, and claims it could not substantiate — no path to the claimed consequence at the named site is a valid disposal. Whatever the reason, it must dispose of the finding's own claim: a true fact about neighboring code that leaves the claim standing is not a dismissal, and the finding stays kept. Record each dismissal with its reason; never drop a finding silently. The session (never the subagent) writes it to the `## Review Triage Log` section of `{spec_file}`.
52
76
  - A finding whose fix edits the spec this run is implementing: dismiss. A finding whose fix edits an agent-context document (e.g. CLAUDE.md, AGENTS.md, rules files, other specs): defer, never patch.
53
- 2. Group the survivors by shared root cause — two findings belong in one entry only when the same underlying defect produced both. Same location alone is not a shared root cause, and neither is a shared fix. An entry carries every member's verified consequence and the highest severity among them.
54
- 3. Route each entry into exactly one triage category. The first three are **this story's problem** — caused or exposed by the current change. The last is **not this story's problem**.
77
+
78
+ 3. Group the survivors by shared root cause — two findings belong in one entry only when the same underlying defect produced both. Same location alone is not a shared root cause, and neither is a shared fix. An entry carries every member's verified consequence and the highest severity among them.
79
+ 4. Route each entry into exactly one triage category. The first three are **this story's problem** — caused or exposed by the current change. The last is **not this story's problem**.
55
80
  - **intent_gap** — caused by the change; cannot be resolved from the spec because the captured intent is incomplete. Do not infer intent unless there is exactly one possible reading.
56
81
  - **bad_spec** — caused by the change, including direct deviations from spec. The spec should have been clear enough to prevent it. When in doubt between bad_spec and patch, prefer bad_spec — a spec-level fix is more likely to produce coherent code.
57
82
  - **patch** — caused by the change; trivially fixable without human input. Just part of the diff.
58
83
  - **defer** — pre-existing issue not caused by this story, surfaced incidentally by the review. Collect for later focused attention.
59
- 4. Process findings in cascading order. If intent_gap or bad_spec findings exist, they trigger a loopback — lower findings are moot since code will be re-derived. If neither exists, process patch and defer normally. Before each loopback, read `{spec_file}` frontmatter `review_loop_iteration` (missing means `0`), increment it by 1, and write it back. If it exceeds 5, HALT and escalate to the human.
60
- - **intent_gap** — Root cause is inside `<frozen-after-approval>`. Revert code changes. Loop back to the human to resolve. Once resolved, read fully and follow `./step-02-plan.md` to re-run steps 2–4.
84
+ 5. Process findings in cascading order. If any `intent_gap` or `bad_spec` entries remain, they trigger a loopback — lower findings are moot since code will be re-derived. If neither remains, process patch and defer normally. Before each loopback, read `{spec_file}` frontmatter `review_loop_iteration` (missing means `0`), increment it by 1, and write it back. If it exceeds 5, delete `{diff_file}`, `{clean_diff_file}` and any findings temp files per `./references/review-economy.md` § 5, then HALT and escalate to the human.
85
+ - **intent_gap** — Root cause is inside `<frozen-after-approval>`. Revert code changes. Loop back to the human to resolve — this is where the human sees the finding and its evidence; nothing upstream of this bullet asks them to confirm it first. If the human says the finding is not real, log it as dismissed with their reason (added to the `## Review Triage Log`) and drop it from the cascade instead of proceeding. Otherwise, once resolved, read fully and follow `./step-02-plan.md` to re-run steps 2–4.
61
86
  - **bad_spec** — Root cause is outside `<frozen-after-approval>`. Before reverting code: extract KEEP instructions for positive preservation (what worked well and must survive re-derivation). Revert code changes. Read the `## Spec Change Log` in `{spec_file}` and strictly respect all logged constraints when amending the non-frozen sections that contain the root cause. Append a new change-log entry recording: the triggering finding, what was amended, the known-bad state avoided, and the KEEP instructions. Read fully and follow `./step-03-implement.md` to re-derive the code, then this step will run again.
62
- - **patch** — Auto-fix. These are the only findings that survive loopbacks. If the step-03 implementation subagent can be re-engaged with its context intact, send it all patch findings in one synchronous message — for each: the file, what is wrong, and what the fix must do. If it cannot be re-engaged, apply the patches yourself. Then re-run the checks in `{spec_file}`'s `## Verification` section, if present; if verification fails and the failure cannot be fixed, HALT and escalate to the human.
87
+ - **patch** — Auto-fix. These are the only findings that survive loopbacks. If the step-03 implementation subagent can be re-engaged with its context intact, send it all patch findings in one synchronous message — for each: the file, what is wrong, and what the fix must do. If it cannot be re-engaged, apply the patches yourself. Then re-run the checks in `{spec_file}`'s `## Verification` section, if present; if verification fails and the failure cannot be fixed, delete `{diff_file}`, `{clean_diff_file}` and any findings temp files per `./references/review-economy.md` § 5, then HALT and escalate to the human.
63
88
  - **defer** — Append one new entry to `{deferred_work_file}` using this format. Do not modify existing entries or look for duplicates.
64
89
  ```markdown
65
90
  - source_spec: `{spec_file}`
@@ -69,6 +69,10 @@ Display summary of your work to the user, including the commit hash if one was c
69
69
  - **Navigation tip:** "Ctrl+click (Cmd+click on macOS) the links in the Suggested Review Order to jump to each stop."
70
70
  - Offer to push and/or create a pull request.
71
71
 
72
+ ### Cleanup
73
+
74
+ Once the user's choice above (push/PR or not) is handled, delete `{diff_file}`, `{clean_diff_file}` and any findings temp files, per `./references/review-economy.md` section 5.
75
+
72
76
  Workflow complete.
73
77
 
74
78
  ## On Complete
@@ -26,11 +26,11 @@ Implement the clarified intent directly.
26
26
 
27
27
  If no layer is active, HALT and escalate to the human.
28
28
 
29
- 2. Announce skipped layers first, then launch every active layer before handling any layer's result. Expand `{skill-root}` in each layer's `instruction` to this skill's absolute installed directory — the child's working directory is not yours, so never leave it unresolved in a child prompt. Reviewers get NO conversation context, to avoid anchoring bias: they inspect the changed files in the worktree themselves. When an instruction launches a reviewer subagent, launch that child with the prompt text after expansion; for any other customized instruction, execute it as written. Spawn every reviewer before reading any of their output.
29
+ 2. Announce skipped layers first, then launch every active layer before handling any layer's result. Expand `{skill-root}` in each layer's `instruction` to this skill's absolute installed directory, and substitute `{max_calls}` from the layer's own `max_calls` (a layer without one has no `max_calls:` line to substitute — remove that line entirely) — the child's working directory is not yours, so never leave `{skill-root}` unresolved in a child prompt. Reviewers get NO conversation context, to avoid anchoring bias: they inspect the changed files in the worktree themselves. When an instruction launches a reviewer subagent, launch that child with the prompt text after expansion; for any other customized instruction, execute it as written. Spawn every reviewer before reading any of their output.
30
30
 
31
31
  3. If a layer's instruction requires subagents and none are available, write that layer's child prompt under `{implementation_artifacts}`, with every file it points to replaced inline by that file's contents and every other line left exactly as written — that session shares no filesystem with this one, so its prompt has to stand alone. Then HALT. Ask the human to run it in a separate session and paste back the findings.
32
32
 
33
- 4. If any layer fails, times out, or returns empty, note it and proceed with the remaining layers. Collect all findings.
33
+ 4. If any layer errors, times out, or returns unreadable output, note it and proceed with the remaining layers. A layer that returns an explicit no-findings result (e.g. `[]`, or "No verification gaps found.") has succeeded — do not note it as a failure. A layer whose final message ends with a `PARTIAL:` line is partial: note it and keep its findings. Collect all findings. If any layer failed or was partial, warn the user that the review may be incomplete, and never present it as clean.
34
34
 
35
35
  ### Classify
36
36
 
@@ -31,6 +31,7 @@ A mesma lógica vale em toda plataforma, trocando os nomes pelos da tabela abaix
31
31
  2. Escalada automática por evidência: se o executor devolveu ambiguidade OU os testes falharam 2x no mesmo brief, reemita o MESMO brief 1 degrau acima. Máximo 1 escalada; depois o trabalho volta para o chefe. Em sessão Fable, Sonnet sobe para `wizz-exec-opus`; em sessão Opus, Sonnet sobe direto para o chefe.
32
32
  3. Degrau Forte segue o chefe: em sessão acima de Opus (Fable, Mythos), `wizz-exec-opus` é o destino PADRÃO de bug sem causa clara, refactor cruzando módulos e decisão técnica local; o chefe não faz esse trabalho na própria sessão. Em sessão Opus ou abaixo, o degrau Forte coincide com o chefe ou fica acima dele: pule de Padrão direto para `wizz-exec-review` ou para o chefe (pinar opus numa sessão opus duplica custo sem ganho).
33
33
  4. Implementa barato, revisa forte: diff produzido por `wizz-exec-haiku`/`wizz-exec-sonnet`/`wizz-exec-opus` passa por `wizz-exec-review` antes de integrar. O revisor roda pinado no degrau Forte da plataforma, não no modelo da sessão: em sessão Fable o review sai do Fable e vai para Opus; em sessão Opus nada muda. Conflito entre executor e revisor sobe para o chefe decidir.
34
+ - Workflows de review (`wizz-code-review`, `wizz-quick-dev`) seguem pinados no Forte, mas o número de camadas escala com o tamanho do diff (1, 2 ou até 4), pathspecs do git descartam lockfile e ruído parecido antes de contar linhas, a própria sessão julga se a mudança é crítica, e a triagem fica no Forte (a própria sessão se ela é o Forte; senão 1 `wizz-exec-opus`); ver `wizz-code-review/references/review-economy.md`.
34
35
  5. Decisão de arquitetura ou produto nunca desce a escada: fica com o chefe ou com o usuário.
35
36
  6. Transparência: todo despacho diz no texto ao usuário o degrau e a quantidade ("3 × Sonnet", "1 × Opus para review"). Nunca só "executores".
36
37
  7. Quantidade sem teto: dispare quantos subagentes o trabalho pedir, um por unidade independente (arquivo, módulo, frente de verificação). O mínimo é 2 em paralelo; máximo não existe. O que limita é a partição (dois agentes nunca editam o mesmo arquivo), não um número.
@@ -39,7 +39,7 @@ Trabalho mecânico NUNCA roda na sessão principal. Isso inclui: varredura de ar
39
39
  - **`wizz-exec-haiku`**: varredura, lookup, renomeação, diff mecânico, mudança já 100% especificada. Sem ambiguidade nenhuma.
40
40
  - **`wizz-exec-sonnet`**: implementação do dia a dia, bug com causa raiz já conhecida, edição multi-arquivo, testes.
41
41
  - **`wizz-exec-opus`**: bug sem causa clara, refactor cruzando módulos, decisão técnica local. Destino padrão desse trabalho quando a sessão roda acima de Opus (Fable); em sessão Opus o chefe absorve o degrau e pula para review.
42
- - **`wizz-exec-review`** (pinado no degrau Forte, `opus` em Claude Code): review do diff produzido pelos degraus acima antes de integrar. Não herda a sessão: em sessão Fable o review vai para Opus.
42
+ - **`wizz-exec-review`** (pinado no degrau Forte, `opus` em Claude Code): review do diff produzido pelos degraus acima antes de integrar. Não herda a sessão: em sessão Fable o review vai para Opus. Quantidade de subagentes escala com o tamanho do diff, ver `wizz-code-review/references/review-economy.md`.
43
43
 
44
44
  Todo despacho pode levar `max_calls` (ver handoff-protocol.md): executor que bate no teto devolve parcial, nunca escala sozinho.
45
45
 
@@ -11,6 +11,7 @@ Você é um revisor adversarial do Wizz Method. Recebe um diff ou o resultado de
11
11
 
12
12
  Regras:
13
13
 
14
+ - Quando o brief aponta um arquivo de instrução de camada (`review-prompts/…`) ou traz um método próprio, ele manda: siga o método e o formato de saída dele e ignore o formato de veredito abaixo.
14
15
  - Verifique correção, segurança e regressão, arquivo por arquivo.
15
16
  - Verifique aderência ao escopo: qualquer mudança fora do brief original é finding, não elogio.
16
17
  - Não edite nenhum arquivo. Sua função é avaliar, não implementar.
@@ -19,7 +20,7 @@ Regras:
19
20
 
20
21
  Disciplina de "judge" (Fable Method):
21
22
 
22
- - RE-RUN: re-execute você mesmo TODA verificação que o executor alegou ter feito (teste, build, comando específico) — não confie no relatório dele.
23
+ - Fora de camada com método próprio, RE-RUN: re-execute você mesmo TODA verificação que o executor alegou ter feito (teste, build, comando específico) — não confie no relatório dele. Em camada de review com método próprio, não rode a suíte de testes a menos que o método peça.
23
24
  - DIFF vs NARRATIVA: compare o que o diff realmente faz com o que o relatório do executor diz que fez; qualquer divergência é finding.
24
25
  - Se o brief trouxer `max_calls`, esse é o teto de chamadas de ferramenta: ao atingir, pare e entregue o parcial com pendências explícitas; não escale sozinho.
25
26
  - Tabela de fraudes a caçar:
@@ -11,6 +11,7 @@ Você é um revisor adversarial do Wizz Method. Recebe um diff ou o resultado de
11
11
 
12
12
  Regras:
13
13
 
14
+ - Quando o brief aponta um arquivo de instrução de camada (`review-prompts/…`) ou traz um método próprio, ele manda: siga o método e o formato de saída dele e ignore o formato de veredito abaixo.
14
15
  - Verifique correção, segurança e regressão, arquivo por arquivo.
15
16
  - Verifique aderência ao escopo: qualquer mudança fora do brief original é finding, não elogio.
16
17
  - Não edite nenhum arquivo. Sua função é avaliar, não implementar.
@@ -19,7 +20,7 @@ Regras:
19
20
 
20
21
  Disciplina de "judge" (Fable Method):
21
22
 
22
- - RE-RUN: re-execute você mesmo TODA verificação que o executor alegou ter feito (teste, build, comando específico) — não confie no relatório dele.
23
+ - Fora de camada com método próprio, RE-RUN: re-execute você mesmo TODA verificação que o executor alegou ter feito (teste, build, comando específico) — não confie no relatório dele. Em camada de review com método próprio, não rode a suíte de testes a menos que o método peça.
23
24
  - DIFF vs NARRATIVA: compare o que o diff realmente faz com o que o relatório do executor diz que fez; qualquer divergência é finding.
24
25
  - Se o brief trouxer `max_calls`, esse é o teto de chamadas de ferramenta: ao atingir, pare e entregue o parcial com pendências explícitas; não escale sozinho.
25
26
  - Tabela de fraudes a caçar:
@@ -12,6 +12,7 @@ Você é um revisor adversarial do Wizz Method. Recebe um diff ou o resultado de
12
12
 
13
13
  Regras:
14
14
 
15
+ - Quando o brief aponta um arquivo de instrução de camada (`review-prompts/…`) ou traz um método próprio, ele manda: siga o método e o formato de saída dele e ignore o formato de veredito abaixo.
15
16
  - Verifique correção, segurança e regressão, arquivo por arquivo.
16
17
  - Verifique aderência ao escopo: qualquer mudança fora do brief original é finding, não elogio.
17
18
  - Não edite nenhum arquivo. Sua função é avaliar, não implementar.
@@ -20,7 +21,7 @@ Regras:
20
21
 
21
22
  Disciplina de "judge" (Fable Method):
22
23
 
23
- - RE-RUN: re-execute você mesmo TODA verificação que o executor alegou ter feito (teste, build, comando específico) — não confie no relatório dele.
24
+ - Fora de camada com método próprio, RE-RUN: re-execute você mesmo TODA verificação que o executor alegou ter feito (teste, build, comando específico) — não confie no relatório dele. Em camada de review com método próprio, não rode a suíte de testes a menos que o método peça.
24
25
  - DIFF vs NARRATIVA: compare o que o diff realmente faz com o que o relatório do executor diz que fez; qualquer divergência é finding.
25
26
  - Se o brief trouxer `max_calls`, esse é o teto de chamadas de ferramenta: ao atingir, pare e entregue o parcial com pendências explícitas; não escale sozinho.
26
27
  - Tabela de fraudes a caçar:
@@ -88,6 +88,7 @@ tiers:
88
88
  review:
89
89
  head: Você é um revisor adversarial do Wizz Method. Recebe um diff ou o resultado de um executor mais barato e assume que existe bug, mesmo que o resultado pareça limpo. Procure ativamente.
90
90
  regras: |
91
+ - Quando o brief aponta um arquivo de instrução de camada (`review-prompts/…`) ou traz um método próprio, ele manda: siga o método e o formato de saída dele e ignore o formato de veredito abaixo.
91
92
  - Verifique correção, segurança e regressão, arquivo por arquivo.
92
93
  - Verifique aderência ao escopo: qualquer mudança fora do brief original é finding, não elogio.
93
94
  - Não edite nenhum arquivo. Sua função é avaliar, não implementar.
@@ -96,7 +97,7 @@ tiers:
96
97
  disciplina: |
97
98
  Disciplina de "judge" (Fable Method):
98
99
 
99
- - RE-RUN: re-execute você mesmo TODA verificação que o executor alegou ter feito (teste, build, comando específico) — não confie no relatório dele.
100
+ - Fora de camada com método próprio, RE-RUN: re-execute você mesmo TODA verificação que o executor alegou ter feito (teste, build, comando específico) — não confie no relatório dele. Em camada de review com método próprio, não rode a suíte de testes a menos que o método peça.
100
101
  - DIFF vs NARRATIVA: compare o que o diff realmente faz com o que o relatório do executor diz que fez; qualquer divergência é finding.
101
102
  - Se o brief trouxer `max_calls`, esse é o teto de chamadas de ferramenta: ao atingir, pare e entregue o parcial com pendências explícitas; não escale sozinho.
102
103
  - Tabela de fraudes a caçar:
@@ -10,6 +10,7 @@ Você é um revisor adversarial do Wizz Method. Recebe um diff ou o resultado de
10
10
 
11
11
  Regras:
12
12
 
13
+ - Quando o brief aponta um arquivo de instrução de camada (`review-prompts/…`) ou traz um método próprio, ele manda: siga o método e o formato de saída dele e ignore o formato de veredito abaixo.
13
14
  - Verifique correção, segurança e regressão, arquivo por arquivo.
14
15
  - Verifique aderência ao escopo: qualquer mudança fora do brief original é finding, não elogio.
15
16
  - Não edite nenhum arquivo. Sua função é avaliar, não implementar.
@@ -18,7 +19,7 @@ Regras:
18
19
 
19
20
  Disciplina de "judge" (Fable Method):
20
21
 
21
- - RE-RUN: re-execute você mesmo TODA verificação que o executor alegou ter feito (teste, build, comando específico) — não confie no relatório dele.
22
+ - Fora de camada com método próprio, RE-RUN: re-execute você mesmo TODA verificação que o executor alegou ter feito (teste, build, comando específico) — não confie no relatório dele. Em camada de review com método próprio, não rode a suíte de testes a menos que o método peça.
22
23
  - DIFF vs NARRATIVA: compare o que o diff realmente faz com o que o relatório do executor diz que fez; qualquer divergência é finding.
23
24
  - Se o brief trouxer `max_calls`, esse é o teto de chamadas de ferramenta: ao atingir, pare e entregue o parcial com pendências explícitas; não escale sozinho.
24
25
  - Tabela de fraudes a caçar:
@@ -191,7 +191,14 @@ export async function fetchBundle({ url, sha256, parts, dest, marker, force = fa
191
191
 
192
192
  export class FetchAssetsError extends Error {}
193
193
 
194
- async function fetchNamedBundle(name, { dest, force } = {}) {
194
+ /**
195
+ * Resolve um bundle do catálogo `BUNDLES` pelo nome e baixa. É o ÚNICO lugar
196
+ * que traduz a entrada do catálogo em argumentos de `fetchBundle`: o wrapper
197
+ * do CLI (`tools/installer/commands/fetch-assets.js`) chama esta função, nunca
198
+ * remonta o objeto à mão. Um wrapper que remontava esqueceu `parts` e quebrava
199
+ * todo bundle em partes com "Cannot read properties of undefined" (2026-09-12).
200
+ */
201
+ export async function fetchNamedBundle(name, { dest, force } = {}) {
195
202
  const bundle = BUNDLES[name];
196
203
  if (!bundle) {
197
204
  throw new FetchAssetsError(`Bundle desconhecido: "${name}". Disponíveis: ${Object.keys(BUNDLES).join(', ')}`);
@@ -3,6 +3,8 @@
3
3
  // canvas-design. Wrapper fino de commander sobre tools/fetch-assets.mjs (ESM
4
4
  // puro, sem dependência nova) — o motor real fica lá; este arquivo só expõe
5
5
  // o comando pro CLI e traduz flags/erros pro padrão dos outros comandos.
6
+ // A resolução nome do bundle → argumentos de download é do motor
7
+ // (`fetchNamedBundle`); este wrapper nunca remonta esse objeto.
6
8
  //
7
9
  // `--bundle` (não posicional): o loader genérico em wizz-cli.js registra
8
10
  // `program.command(name)` sem placeholder de argumento pros comandos deste
@@ -28,7 +30,7 @@ module.exports = {
28
30
  ['--all', 'Baixa todos os bundles conhecidos'],
29
31
  ],
30
32
  action: async (options) => {
31
- const { fetchBundle, BUNDLES } = await import('../../fetch-assets.mjs');
33
+ const { fetchNamedBundle, BUNDLES } = await import('../../fetch-assets.mjs');
32
34
 
33
35
  const targets = options.all ? Object.keys(BUNDLES) : options.bundle ? [options.bundle] : [];
34
36
 
@@ -53,13 +55,10 @@ module.exports = {
53
55
  continue;
54
56
  }
55
57
  try {
56
- const result = await fetchBundle({
57
- url: meta.url,
58
- sha256: meta.sha256,
59
- dest: options.dest || meta.dest,
60
- marker: meta.marker,
61
- force: options.force,
62
- });
58
+ // Delega ao helper do motor em vez de remontar os argumentos: o
59
+ // catálogo tem bundles em `parts` (sem `url`), e toda cópia manual
60
+ // desse mapeamento já esqueceu um campo uma vez.
61
+ const result = await fetchNamedBundle(name, { dest: options.dest, force: options.force });
63
62
  console.log(result.cached ? `✓ ${name}: já em cache (${result.dest})` : `✓ ${name}: baixado em ${result.dest}`);
64
63
  } catch (error) {
65
64
  exitCode = 1;