wizz-method 2.12.0 → 2.14.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 (119) hide show
  1. package/README.md +2 -1
  2. package/THIRD-PARTY-NOTICES.md +2 -0
  3. package/package.json +10 -3
  4. package/skills-registry.yaml +48 -48
  5. package/src/bmm-skills/1-analysis/research/wizz-domain-research/customize.toml +4 -3
  6. package/src/bmm-skills/1-analysis/research/wizz-market-research/customize.toml +4 -3
  7. package/src/bmm-skills/1-analysis/research/wizz-technical-research/customize.toml +3 -1
  8. package/src/bmm-skills/1-analysis/wizz-agent-analyst/customize.toml +3 -1
  9. package/src/bmm-skills/1-analysis/wizz-agent-tech-writer/customize.toml +4 -3
  10. package/src/bmm-skills/1-analysis/wizz-document-project/customize.toml +4 -3
  11. package/src/bmm-skills/1-analysis/wizz-prfaq/customize.toml +4 -3
  12. package/src/bmm-skills/1-analysis/wizz-product-brief/customize.toml +5 -6
  13. package/src/bmm-skills/2-plan-workflows/wizz-agent-pm/customize.toml +3 -1
  14. package/src/bmm-skills/2-plan-workflows/wizz-agent-ux-designer/customize.toml +3 -1
  15. package/src/bmm-skills/2-plan-workflows/wizz-create-prd/customize.toml +4 -3
  16. package/src/bmm-skills/2-plan-workflows/wizz-edit-prd/customize.toml +4 -3
  17. package/src/bmm-skills/2-plan-workflows/wizz-prd/customize.toml +5 -6
  18. package/src/bmm-skills/2-plan-workflows/wizz-ux/customize.toml +4 -3
  19. package/src/bmm-skills/2-plan-workflows/wizz-validate-prd/customize.toml +4 -3
  20. package/src/bmm-skills/3-solutioning/wizz-agent-architect/customize.toml +3 -1
  21. package/src/bmm-skills/3-solutioning/wizz-architecture/customize.toml +5 -6
  22. package/src/bmm-skills/3-solutioning/wizz-check-implementation-readiness/customize.toml +4 -3
  23. package/src/bmm-skills/3-solutioning/wizz-create-architecture/customize.toml +4 -3
  24. package/src/bmm-skills/3-solutioning/wizz-create-epics-and-stories/customize.toml +4 -3
  25. package/src/bmm-skills/3-solutioning/wizz-generate-project-context/steps/step-03-complete.md +7 -0
  26. package/src/bmm-skills/4-implementation/wizz-agent-dev/customize.toml +3 -1
  27. package/src/bmm-skills/4-implementation/wizz-checkpoint-preview/customize.toml +4 -3
  28. package/src/bmm-skills/4-implementation/wizz-code-review/customize.toml +4 -3
  29. package/src/bmm-skills/4-implementation/wizz-code-review/steps/step-03-triage.md +23 -14
  30. package/src/bmm-skills/4-implementation/wizz-code-review/steps/step-04-present.md +2 -2
  31. package/src/bmm-skills/4-implementation/wizz-correct-course/customize.toml +4 -3
  32. package/src/bmm-skills/4-implementation/wizz-create-story/customize.toml +4 -3
  33. package/src/bmm-skills/4-implementation/wizz-dev-story/customize.toml +4 -3
  34. package/src/bmm-skills/4-implementation/wizz-investigate/customize.toml +4 -3
  35. package/src/bmm-skills/4-implementation/wizz-qa-generate-e2e-tests/customize.toml +4 -3
  36. package/src/bmm-skills/4-implementation/wizz-quick-dev/customize.toml +4 -3
  37. package/src/bmm-skills/4-implementation/wizz-quick-dev/spec-template.md +6 -0
  38. package/src/bmm-skills/4-implementation/wizz-quick-dev/step-04-review.md +27 -16
  39. package/src/bmm-skills/4-implementation/wizz-quick-dev/step-oneshot.md +27 -6
  40. package/src/bmm-skills/4-implementation/wizz-retrospective/customize.toml +4 -3
  41. package/src/bmm-skills/4-implementation/wizz-sprint-planning/customize.toml +4 -3
  42. package/src/bmm-skills/4-implementation/wizz-sprint-status/customize.toml +4 -3
  43. package/src/bmm-skills/module.yaml +1 -1
  44. package/src/core-skills/wizz-brainstorming/customize.toml +5 -6
  45. package/src/core-skills/wizz-brainstorming/scripts/brain.py +19 -0
  46. package/src/core-skills/wizz-brainstorming/scripts/tests/test_brain.py +33 -0
  47. package/src/core-skills/wizz-forge-idea/scripts/resolve_personas.py +3 -1
  48. package/src/core-skills/wizz-forge-idea/scripts/tests/test_resolve_personas.py +21 -0
  49. package/src/core-skills/wizz-help/SKILL.md +5 -3
  50. package/src/core-skills/wizz-party-mode/customize.toml +5 -4
  51. package/src/core-skills/wizz-party-mode/scripts/resolve_party.py +3 -1
  52. package/src/core-skills/wizz-party-mode/scripts/tests/test_resolve_party.py +21 -0
  53. package/src/core-skills/wizz-spec/customize.toml +4 -5
  54. package/src/modules/wizz/_shared/model-ladder.md +4 -4
  55. package/src/modules/wizz/_shared/video-pipeline.md +1 -1
  56. package/src/modules/wizz/agents/wizz-maestro/SKILL.md +1 -1
  57. package/src/modules/wizz/subagents/opencode/wizz-exec-review.md +2 -2
  58. package/src/modules/wizz/subagents/opencode/wizz-exec-standard.md +2 -2
  59. package/src/modules/wizz/subagents/opencode/wizz-exec-strong.md +2 -2
  60. package/src/modules/wizz/subagents/spec.yaml +3 -3
  61. package/src/scripts/resolve_config.py +8 -0
  62. package/src/scripts/resolve_customization.py +24 -3
  63. package/src/scripts/tests/test_resolve_config.py +42 -0
  64. package/src/scripts/tests/test_resolve_customization.py +45 -0
  65. package/src/skills-lib/ctc-align/SKILL.md +1 -1
  66. package/src/skills-lib/wizz-agent-browser/SKILL.md +5 -0
  67. package/src/skills-lib/wizz-huashu-design/scripts/html2pptx.js +902 -1061
  68. package/src/skills-lib/wizz-humanizer/README.md +134 -71
  69. package/src/skills-lib/wizz-humanizer/SKILL.md +51 -37
  70. package/src/skills-lib/wizz-humanizer/references/ai-writing-patterns.md +208 -190
  71. package/src/skills-lib/wizz-router/references/routing-table-flat.md +2 -2
  72. package/tools/installer/banner.js +80 -29
  73. package/tools/installer/commands/catalog.js +87 -0
  74. package/tools/installer/commands/install.js +9 -0
  75. package/tools/installer/core/doctor.js +31 -1
  76. package/tools/installer/core/installer.js +32 -0
  77. package/tools/installer/core/project-instructions.js +199 -0
  78. package/tools/installer/guided/detect-tools.js +53 -0
  79. package/tools/installer/guided/flow.js +203 -0
  80. package/tools/installer/guided/labels.js +185 -0
  81. package/tools/installer/guided/messages.js +132 -0
  82. package/tools/installer/guided/outro.js +32 -0
  83. package/tools/installer/guided/profiles.js +95 -0
  84. package/tools/installer/guided/steps.js +154 -0
  85. package/tools/installer/install-messages.yaml +3 -3
  86. package/tools/installer/modules/external-manager.js +4 -0
  87. package/tools/installer/ui.js +57 -22
  88. package/wizz-modules.yaml +1 -0
  89. package/src/bmm-skills/3-solutioning/wizz-architecture/scripts/__pycache__/lint_spine.cpython-313.pyc +0 -0
  90. package/src/bmm-skills/3-solutioning/wizz-architecture/scripts/tests/__pycache__/test_lint_spine.cpython-313-pytest-9.1.1.pyc +0 -0
  91. package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/__pycache__/sprint_status.cpython-313.pyc +0 -0
  92. package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/tests/__pycache__/test_git_evidence.cpython-313-pytest-9.1.1.pyc +0 -0
  93. package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/tests/__pycache__/test_sprint_status.cpython-313-pytest-9.1.1.pyc +0 -0
  94. package/src/bmm-skills/4-implementation/wizz-sprint-planning/scripts/__pycache__/sprint_plan.cpython-313.pyc +0 -0
  95. package/src/bmm-skills/4-implementation/wizz-sprint-planning/scripts/tests/__pycache__/test_sprint_plan.cpython-313-pytest-9.1.1.pyc +0 -0
  96. package/src/core-skills/wizz-advanced-elicitation/scripts/__pycache__/pick_methods.cpython-313.pyc +0 -0
  97. package/src/core-skills/wizz-advanced-elicitation/scripts/tests/__pycache__/test_pick_methods.cpython-313-pytest-9.1.1.pyc +0 -0
  98. package/src/core-skills/wizz-brainstorming/scripts/__pycache__/brain.cpython-313.pyc +0 -0
  99. package/src/core-skills/wizz-brainstorming/scripts/tests/__pycache__/test_brain.cpython-313-pytest-9.1.1.pyc +0 -0
  100. package/src/core-skills/wizz-brainstorming/scripts/tests/__pycache__/test_brain.cpython-314.pyc +0 -0
  101. package/src/core-skills/wizz-customize/scripts/__pycache__/list_customizable_skills.cpython-313.pyc +0 -0
  102. package/src/core-skills/wizz-customize/scripts/tests/__pycache__/test_list_customizable_skills.cpython-313-pytest-9.1.1.pyc +0 -0
  103. package/src/core-skills/wizz-forge-idea/scripts/__pycache__/resolve_personas.cpython-313.pyc +0 -0
  104. package/src/core-skills/wizz-forge-idea/scripts/__pycache__/resolve_personas.cpython-314.pyc +0 -0
  105. package/src/core-skills/wizz-forge-idea/scripts/tests/__pycache__/test_resolve_personas.cpython-313-pytest-9.1.1.pyc +0 -0
  106. package/src/core-skills/wizz-forge-idea/scripts/tests/__pycache__/test_resolve_personas.cpython-314.pyc +0 -0
  107. package/src/core-skills/wizz-party-mode/scripts/__pycache__/resolve_party.cpython-313.pyc +0 -0
  108. package/src/core-skills/wizz-party-mode/scripts/__pycache__/resolve_party.cpython-314.pyc +0 -0
  109. package/src/core-skills/wizz-party-mode/scripts/tests/__pycache__/test_resolve_party.cpython-313-pytest-9.1.1.pyc +0 -0
  110. package/src/core-skills/wizz-party-mode/scripts/tests/__pycache__/test_resolve_party.cpython-314.pyc +0 -0
  111. package/src/scripts/__pycache__/resolve_customization.cpython-314.pyc +0 -0
  112. package/src/skills-lib/wizz-huashu-design/package-lock.json +0 -846
  113. package/src/skills-lib/wizz-humanizer/WARP.md +0 -53
  114. package/src/skills-lib/wizz-humanizer/references/full-example.md +0 -72
  115. package/src/skills-lib/wizz-humanizer/references/personality-and-soul.md +0 -36
  116. package/src/skills-lib/wizz-react-components/package-lock.json +0 -231
  117. package/src/skills-lib/wizz-supabase-postgres-best-practices/CLAUDE.md +0 -68
  118. package/src/skills-lib/wizz-ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
  119. package/src/skills-lib/wizz-ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
@@ -30,9 +30,10 @@ activation_steps_append = []
30
30
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
31
31
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
32
32
 
33
- persistent_facts = [
34
- "file:{project-root}/**/project-context.md",
35
- ]
33
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
34
+ # (the Wizz block imports project-context.md there once per session). Add
35
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
36
+ persistent_facts = []
36
37
 
37
38
  # Scalar: executed when the workflow reaches Step 4 (Final Validation) and the
38
39
  # user confirms [C] Complete — after the epics.md is saved and wizz-help is invoked.
@@ -207,6 +207,13 @@ stage: '{{project_stage}}' # prototype|mvp|production|maintenance
207
207
  **Add Usage Section:**
208
208
  Append the usage guidelines from step 3 to complete the document.
209
209
 
210
+ **Wire it into the Wizz block:** agents no longer load this file on every skill activation; the Wizz block in `CLAUDE.md` / `AGENTS.md` loads it once per session. For each of those files at `{project-root}` that has the `<!-- wizz:begin -->` block and does not yet mention this file, add a line right before `<!-- wizz:end -->`, using the path relative to `{project-root}`:
211
+
212
+ - `CLAUDE.md`: `@<relative path>` on its own line (Claude Code imports it).
213
+ - `AGENTS.md`: ``- Contexto do projeto: leia `<relative path>` antes de implementar (regras de stack e padrões).``
214
+
215
+ The next `wizz install` rewrites the block with the same line, so the edit is stable. If neither file has the block, tell the user to run `npx wizz-method install` to add it.
216
+
210
217
  ### 6. Completion Validation
211
218
 
212
219
  Final checks before completion:
@@ -35,8 +35,10 @@ activation_steps_append = []
35
35
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
36
36
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
37
37
 
38
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
39
+ # (the Wizz block imports project-context.md there once per session). Add
40
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
38
41
  persistent_facts = [
39
- "file:{project-root}/**/project-context.md",
40
42
  "FEATURE: the SessionStart hook already resolves the active feature from the git branch and injects 'FEATURE ATIVA: <slug>'. If it exists, save EVERY planning and implementation artifact in the subfolder with that name ({planning_artifacts}/{active_feature}/, {implementation_artifacts}/{active_feature}/) and write the slug to active_feature in {project-root}/_wizz/bmm/config.yaml on first write, announcing it in ONE line. Memory saved in this session carries the same slug as its theme. With no feature resolved, write to the root folders. NEVER ask the user for the feature: invoke wizz-set-feature only if they ask to switch, or if there are two open features and the request does not decide between them.",
41
43
  "When implementing against a library or framework, consult Context7 for current docs, APIs, and version-specific syntax before relying on training data or web search: call resolve-library-id with the library name, then query-docs with the returned /org/project id and a specific question. If Context7 is unavailable, tell the user once that they can enable it with `npx ctx7 setup`, then fall back to web research.",
42
44
  ]
@@ -30,9 +30,10 @@ activation_steps_append = []
30
30
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
31
31
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
32
32
 
33
- persistent_facts = [
34
- "file:{project-root}/**/project-context.md",
35
- ]
33
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
34
+ # (the Wizz block imports project-context.md there once per session). Add
35
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
36
+ persistent_facts = []
36
37
 
37
38
  # Scalar: executed when the workflow reaches its final step,
38
39
  # after the review decision (approve/rework/discuss) is made. Override wins.
@@ -30,9 +30,10 @@ activation_steps_append = []
30
30
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
31
31
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
32
32
 
33
- persistent_facts = [
34
- "file:{project-root}/**/project-context.md",
35
- ]
33
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
34
+ # (the Wizz block imports project-context.md there once per session). Add
35
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
36
+ persistent_facts = []
36
37
 
37
38
  # Scalar: executed when the workflow reaches its final step,
38
39
  # after review findings are presented and sprint status is synced. Override wins.
@@ -20,21 +20,30 @@
20
20
 
21
21
  2. Run the acceptance audit from `references/review-economy.md` section 4 and add its findings with source `triage-acceptance` to the unified list, before verdicts, when `{review_mode}` = `"full"` 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 this audit. They get a verdict like any other finding, per instruction 3 below.
22
22
 
23
- 3. 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:
24
- - **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.
25
- - **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.
26
- - `low` -- none or cosmetic
27
- - `medium` -- tolerable
28
- - `high` -- intolerable
29
- - **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 for the summary; never drop a finding silently.
30
- - A finding whose fix edits the spec under review: dismiss. A finding whose fix edits an agent-context document (e.g. CLAUDE.md, AGENTS.md, rules files, other specs): defer, never patch.
31
-
32
- 4. **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 in `detail` and the highest severity among them; set `source` to the contributing layers joined with `+` (e.g., `blind-hunter+edge-case-hunter`).
33
-
34
- 5. **Route** each entry into exactly one triage bucket:
23
+ 3. Once every layer has reported -- and not before -- render a verdict on each finding, ahead of any deduplication or grouping. Disregard any severity a reviewing subagent assigned -- they lack the context to grade.
24
+
25
+ For each finding:
26
+ - **Verify the finding's claim.** At the cited file and line, does the bad outcome the reviewer describes actually occur? Read beyond the changed lines -- follow callers, guards upstream, etc -- until you can answer yes or no. A different finding about nearby code does not settle this one. Judge whether the problem is real, not whether the proposed fix is plausible. Code that loudly fails on a situation you never showed the program can reach is correct behavior, not a defect.
27
+ - **Render exactly one verdict** from what verification established -- the verdict is the whole triage decision; there is no separate keep-or-dismiss.
28
+ - `high` (intolerable), `medium` (tolerable), `low` (cosmetic or negligible) -- the bad outcome is real. Assign severity by how much it hurts end users or developers. For developer-only problems (inconsistent design, eroded invariants, duplicated sources of truth), name where it will cause trouble -- which caller will diverge, which rule will break. A vague "this is messy" with no named harm is not a severity grade; use `false` or `maybe-false` instead. When the harm is real but you cannot tell how bad, pick the higher grade.
29
+ - `false` -- you checked, and the bad outcome does not happen at the cited location. Write what disproves this specific claim. A true fact about nearby code that does not disprove the claim does not count.
30
+ - `maybe-false` -- you could not tell whether the bad outcome happens. Write what you would need to check to find out. Use this only when the diff and surrounding code leave the question open; when they are enough to decide, pick `high`, `medium`, `low`, or `false`.
31
+ - Every finding keeps its verdict and evidence (a sentence or two) for the summary; never drop, merge, or silently skip one.
32
+
33
+ Dismiss `false` findings on their refutation.
34
+
35
+ Dismiss `low` findings when it is unlikely that users or developers would meet the defect in everyday use (judged plainly -- no proof needed) and the fix is more than a direct correction or deletion -- adding guards, branches, parameters, or other complexity.
36
+
37
+ Dismiss any finding whose fix is to edit the spec under review.
38
+
39
+ All remaining findings continue to grouping.
40
+
41
+ 4. **Group the survivors by shared root cause** -- two findings belong in one entry only when the same 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 bad outcome in `detail` and the highest verdict among them (`high` > `medium` > `low` > `maybe-false`); set `source` to the contributing layers joined with `+` (e.g., `blind-hunter+edge-case-hunter`).
42
+
43
+ 5. **Route** each entry into exactly one triage bucket. A group that includes verified `high`, `medium`, or `low` members routes by its highest such verdict -- not to defer just because a member is `maybe-false`.
35
44
  - **decision_needed** -- There is an ambiguous choice that requires human input. The code cannot be correctly patched without knowing the user's intent. Only possible if `{review_mode}` = `"full"`.
36
- - **patch** -- Code issue that is fixable without human input. The correct fix is unambiguous.
37
- - **defer** -- Pre-existing issue not caused by the current change. Real but not actionable now.
45
+ - **patch** -- Code issue that is fixable without human input. The correct fix is unambiguous, adds no public surface, and guards no state you did not demonstrate; otherwise `decision_needed`.
46
+ - **defer** -- Pre-existing issue not caused by the current change, real but not actionable now; or an entry whose members are all `maybe-false` and the claim, if true, would be `medium` or `high` -- record that severity marked unverified, plus what would settle it (if it would only be `low`, dismiss it with the same note); or any entry whose fix edits an agent-context document (e.g. CLAUDE.md, AGENTS.md, rules files, other specs) -- defer, never patch.
38
47
 
39
48
  If `{review_mode}` = `"no-spec"` and an entry would otherwise be `decision_needed`, reclassify it as `patch` (if the fix is unambiguous) or `defer` (if not).
40
49
 
@@ -27,7 +27,7 @@ If `{spec_file}` exists and contains a Tasks/Subtasks section, append a `### Rev
27
27
  `- [ ] [Review][Patch] <Title> [<file>:<line>]`
28
28
 
29
29
  3. **`defer`** findings (checked off, marked deferred):
30
- `- [x] [Review][Defer] <Title> [<file>:<line>] — deferred, pre-existing`
30
+ `- [x] [Review][Defer] <Title> [<file>:<line>] — deferred: <pre-existing, or for maybe-false the evidence that would settle it>`
31
31
 
32
32
  Also append each `defer` finding to `{deferred_work_file}` under a heading `## Deferred from: code review ({date})`. If `{spec_file}` is set, include its basename in the heading (e.g., `code review of story-3.3 (2026-03-18)`). One bullet per finding with description.
33
33
 
@@ -37,7 +37,7 @@ Announce what was written:
37
37
 
38
38
  > **Code review complete.** <D> `decision-needed`, <P> `patch`, <W> `defer`, <R> dismissed.
39
39
 
40
- The findings report ends with a `Dismissed` appendix — one line per dismissed finding: the finding and the reason that disposed of its claim — in the story file's `### Review Findings` section when `{spec_file}` is set, at the tail of the chat listing otherwise.
40
+ The findings report ends with a `Dismissed` appendix — one line per dismissed finding: the finding, its verdict and the reason (`false` with its refutation, `low` with why it was not worth fixing, a fix that would edit the spec under review) — in the story file's `### Review Findings` section when `{spec_file}` is set, at the tail of the chat listing otherwise.
41
41
 
42
42
  If `{spec_file}` is set, add: `Findings written to the review findings section in {spec_file}.`
43
43
  Otherwise add: `Findings are listed above. No story file was provided, so nothing was persisted.`
@@ -30,9 +30,10 @@ activation_steps_append = []
30
30
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
31
31
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
32
32
 
33
- persistent_facts = [
34
- "file:{project-root}/**/project-context.md",
35
- ]
33
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
34
+ # (the Wizz block imports project-context.md there once per session). Add
35
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
36
+ persistent_facts = []
36
37
 
37
38
  # Scalar: executed when the workflow reaches Step 6 (Workflow Completion),
38
39
  # after the Sprint Change Proposal is finalized and handoff is confirmed. Override wins.
@@ -30,9 +30,10 @@ activation_steps_append = []
30
30
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
31
31
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
32
32
 
33
- persistent_facts = [
34
- "file:{project-root}/**/project-context.md",
35
- ]
33
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
34
+ # (the Wizz block imports project-context.md there once per session). Add
35
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
36
+ persistent_facts = []
36
37
 
37
38
  # Scalar: executed when the workflow reaches Step 6 (Update sprint status and finalize),
38
39
  # after the story file is saved and sprint-status.yaml is updated. Override wins.
@@ -30,9 +30,10 @@ activation_steps_append = []
30
30
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
31
31
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
32
32
 
33
- persistent_facts = [
34
- "file:{project-root}/**/project-context.md",
35
- ]
33
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
34
+ # (the Wizz block imports project-context.md there once per session). Add
35
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
36
+ persistent_facts = []
36
37
 
37
38
  # Scalar: executed when the workflow reaches its final step,
38
39
  # after the story implementation is complete and status is updated. Override wins.
@@ -33,9 +33,10 @@ activation_steps_append = []
33
33
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
34
34
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
35
35
 
36
- persistent_facts = [
37
- "file:{project-root}/**/project-context.md",
38
- ]
36
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
37
+ # (the Wizz block imports project-context.md there once per session). Add
38
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
39
+ persistent_facts = []
39
40
 
40
41
  # Scalar: path to the case-file template, resolved from the skill root.
41
42
  # Override to point at an org-shaped template (compliance sections,
@@ -30,9 +30,10 @@ activation_steps_append = []
30
30
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
31
31
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
32
32
 
33
- persistent_facts = [
34
- "file:{project-root}/**/project-context.md",
35
- ]
33
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
34
+ # (the Wizz block imports project-context.md there once per session). Add
35
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
36
+ persistent_facts = []
36
37
 
37
38
  # Scalar: executed when the workflow reaches Step 5 (Create Summary),
38
39
  # after all tests pass and the summary document is saved. Override wins.
@@ -30,9 +30,10 @@ activation_steps_append = []
30
30
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
31
31
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
32
32
 
33
- persistent_facts = [
34
- "file:{project-root}/**/project-context.md",
35
- ]
33
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
34
+ # (the Wizz block imports project-context.md there once per session). Add
35
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
36
+ persistent_facts = []
36
37
 
37
38
  # Scalar: executed when the workflow reaches its final step,
38
39
  # after implementation is complete and explanations are provided. Override wins.
@@ -69,6 +69,12 @@ context: [] # optional: `{project-root}/`-prefixed paths to project-wide standar
69
69
  the amendment avoids, and any KEEP instructions (what worked well and must survive re-derivation).
70
70
  Empty until the first bad_spec loopback. -->
71
71
 
72
+ ## Review Triage Log
73
+
74
+ <!-- Append-only. Populated by step-04 on every review pass: one row per reviewer finding —
75
+ verdict (high/medium/low/false/maybe-false) with its evidence: the refutation for
76
+ false, what would settle it for maybe-false. Empty until the first review pass. -->
77
+
72
78
  ## Design Notes
73
79
 
74
80
  <!-- If the approach is straightforward, DELETE THIS ENTIRE SECTION. Do not write "N/A" or "None". -->
@@ -62,34 +62,45 @@ This section's only file changes are temp diff files (`{diff_file}` and `{clean_
62
62
 
63
63
  ### Classify
64
64
 
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-strong` 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.
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-strong` 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 current `## Review Triage Log` rows of `{spec_file}` (for the carry-forward check in Classify item 2), 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 finding with its verdict and evidence, every entry with its category, and 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
66
 
67
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
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:
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.
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.
72
- - `low`: none or cosmetic
73
- - `medium`: tolerable
74
- - `high`: intolerable
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}`.
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.
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**.
69
+ 2. Once every layer has reported — and not before — render a verdict on each finding, ahead of any deduplication or grouping. Disregard any severity a reviewing subagent assigned — they lack the context to grade.
70
+
71
+ If `## Review Triage Log` already has rows — a loopback or a resumed review — check each finding against them first. Same location and same claim as a logged row, and the code there still reads as the row describes: keep the row's verdict and route, write the row again with `carried` in front of the evidence, skip verification, and never patch or defer it again. Verify everything else as below.
72
+
73
+ For each finding:
74
+ - **Verify the finding's claim.** At the cited file and line, does the bad outcome the reviewer describes actually occur? Read beyond the changed lines — follow callers, guards upstream, etc — until you can answer yes or no. A different finding about nearby code does not settle this one. Judge whether the problem is real, not whether the proposed fix is plausible. Code that loudly fails on a situation you never showed the program can reach is correct behavior, not a defect.
75
+ - **Render exactly one verdict** from what verification established — the verdict is the whole triage decision; there is no separate keep-or-dismiss.
76
+ - `high` (intolerable), `medium` (tolerable), `low` (cosmetic or negligible) — the bad outcome is real. Assign severity by how much it hurts end users or developers. For developer-only problems (inconsistent design, eroded invariants, duplicated sources of truth), name where it will cause trouble — which caller will diverge, which rule will break. A vague "this is messy" with no named harm is not a severity grade; use `false` or `maybe-false` instead. When the harm is real but you cannot tell how bad, pick the higher grade.
77
+ - `false` — you checked, and the bad outcome does not happen at the cited location. Write what disproves this specific claim. A true fact about nearby code that does not disprove the claim does not count.
78
+ - `maybe-false` — you could not tell whether the bad outcome happens. Write what you would need to check to find out. Use this only when the diff and surrounding code leave the question open; when they are enough to decide, pick `high`, `medium`, `low`, or `false`.
79
+ - Every finding gets one row in the `## Review Triage Log` section of `{spec_file}` — verdict plus its evidence in a sentence or two; never drop, merge, or silently skip one. The session (never the subagent) writes the rows.
80
+
81
+ Dismiss `false` findings on their refutation.
82
+
83
+ Dismiss `low` findings when it is unlikely that users or developers would meet the defect in everyday use (judged plainly — no proof needed) and the fix is more than a direct correction or deletion — adding guards, branches, parameters, or other complexity.
84
+
85
+ Dismiss any finding whose fix is to edit the spec this run is implementing.
86
+
87
+ All remaining findings continue to grouping.
88
+
89
+ 3. Group the survivors by shared root cause — two findings belong in one entry only when the same 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 bad outcome and the highest verdict among them (`high` > `medium` > `low` > `maybe-false`).
90
+ 4. Route each entry into exactly one triage category. A group that includes verified `high`, `medium`, or `low` members routes by its highest such verdict — not to defer just because a member is `maybe-false`. The first three are **this story's problem** — caused or exposed by the current change. The last is **not this story's problem**.
80
91
  - **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.
81
92
  - **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.
82
- - **patch** — caused by the change; trivially fixable without human input. Just part of the diff.
83
- - **defer** — pre-existing issue not caused by this story, surfaced incidentally by the review. Collect for later focused attention.
93
+ - **patch** — caused by the change; its smallest fix is trivial, adds no public surface, and guards no state you did not demonstrate. Just part of the diff. A finding whose smallest fix fails any of those conditions routes to intent_gap when the spec does not settle that fix, otherwise to bad_spec.
94
+ - **defer** — pre-existing issue not caused by this story, surfaced incidentally by the review; or an entry whose members are all `maybe-false` and the claim, if true, would be `medium` or `high` — record that severity marked unverified, plus what would settle it (if it would only be `low`, dismiss it with the same note); or any entry whose fix edits an agent-context document (e.g. CLAUDE.md, AGENTS.md, rules files, other specs) — defer, never patch.
84
95
  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
96
  - **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.
86
97
  - **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.
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.
98
+ - **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 smallest 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.
88
99
  - **defer** — Append one new entry to `{deferred_work_file}` using this format. Do not modify existing entries or look for duplicates.
89
100
  ```markdown
90
101
  - source_spec: `{spec_file}`
91
102
  summary: <one sentence>
92
- evidence: <why this is real>
103
+ evidence: <why this is real; for a maybe-false finding, what evidence would settle it>
93
104
  ```
94
105
 
95
106
  ## NEXT
@@ -34,13 +34,33 @@ Implement the clarified intent directly.
34
34
 
35
35
  ### Classify
36
36
 
37
- Deduplicate all review findings. Three categories only:
37
+ Once every layer has reported — and not before — render a verdict on each finding, ahead of any deduplication or grouping. Disregard any severity a reviewing subagent assigned — they lack the context to grade.
38
38
 
39
- - **patch** — trivially fixable. Auto-fix immediately.
40
- - **defer** — pre-existing issue not caused by this change. Append to `{deferred_work_file}`.
41
- - **reject** — noise. Drop silently.
39
+ For each finding:
42
40
 
43
- If a finding is caused by this change but too significant for a trivial patch, HALT and present it to the human for decision before proceeding.
41
+ - **Verify the finding's claim.** At the cited file and line, does the bad outcome the reviewer describes actually occur? Read beyond the changed lines — follow callers, guards upstream, etc — until you can answer yes or no. A different finding about nearby code does not settle this one. Judge whether the problem is real, not whether the proposed fix is plausible. Code that loudly fails on a situation you never showed the program can reach is correct behavior, not a defect.
42
+ - **Render exactly one verdict** from what verification established — the verdict is the whole triage decision; there is no separate keep-or-dismiss.
43
+ - `high` (intolerable), `medium` (tolerable), `low` (cosmetic or negligible) — the bad outcome is real. Assign severity by how much it hurts end users or developers. For developer-only problems, name where it will cause trouble; a vague "this is messy" with no named harm is not a severity grade — use `false` or `maybe-false` instead. When the harm is real but you cannot tell how bad, pick the higher grade.
44
+ - `false` — you checked, and the bad outcome does not happen at the cited location. Write what disproves this specific claim. A true fact about nearby code that does not disprove the claim does not count.
45
+ - `maybe-false` — you could not tell whether the bad outcome happens. Write what you would need to check to find out. Use this only when the diff and surrounding code leave the question open; when they are enough to decide, pick `high`, `medium`, `low`, or `false`.
46
+ - Record every finding with its verdict and evidence; never drop one silently.
47
+
48
+ Dismiss `false` findings on their refutation.
49
+
50
+ Dismiss `low` findings when it is unlikely that users or developers would meet the defect in everyday use (judged plainly — no proof needed) and the fix is more than a direct correction or deletion — adding guards, branches, parameters, or other complexity.
51
+
52
+ All remaining findings continue to grouping.
53
+
54
+ Group the survivors by shared root cause — two findings belong in one entry only when the same 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 bad outcome and the highest verdict among them (`high` > `medium` > `low` > `maybe-false`). A group that includes verified `high`, `medium`, or `low` members routes by its highest such verdict — not to defer just because a member is `maybe-false`. Route each entry in this order:
55
+
56
+ - **patch** — Patch every entry caused or exposed by this change that shows a defect that actually occurs, missing coverage for a specific case, or a broken gate or convention — not a state nothing reaches — and whose smallest fix is trivial, adds no public surface, and guards no state the finding did not demonstrate. Apply that smallest fix immediately.
57
+ - **HALT** — HALT on every entry caused or exposed by this change that shows the same evidence but whose smallest fix fails any of those conditions. Present it to the human for decision before proceeding.
58
+ - **defer** — Defer every other entry: pre-existing issues, improvement ideas, entries whose members are all `maybe-false` and would be `medium` or `high` if true (record that severity marked unverified, plus what would settle it; if it would only be `low`, dismiss it with the same note), and any entry whose fix edits an agent-context document (e.g. CLAUDE.md, AGENTS.md, rules files, specs). Append one new entry to `{deferred_work_file}` using this format. Do not modify existing entries or look for duplicates.
59
+ ```markdown
60
+ - source_spec: `{spec_file}`
61
+ summary: <one sentence>
62
+ evidence: <why this is real; for a maybe-false finding, what evidence would settle it>
63
+ ```
44
64
 
45
65
  ### Generate Spec Trace
46
66
 
@@ -51,6 +71,7 @@ Write `{spec_file}` using `./spec-template.md`. Fill only these sections — del
51
71
  1. **Frontmatter** — set `title: '{title}'`, `type`, `created`, `status: 'done'`. Add `route: 'one-shot'`.
52
72
  2. **Title and Intent** — `# {title}` heading and `## Intent` with **Problem** and **Approach** lines. Reuse the summary you already generated for the terminal.
53
73
  3. **Suggested Review Order** — append after Intent. Build using the same convention as `./step-05-present.md` § "Generate Suggested Review Order" (spec-file-relative links, concern-based ordering, ultra-concise framing).
74
+ 4. **Review Triage Log** — only when the review produced findings: add the section with one line per finding with its verdict and evidence — the refutation for `false`, what would settle it for `maybe-false`, why a dismissed `low` was not worth fixing.
54
75
 
55
76
  Follow `./sync-sprint-status.md` with `{target_status}` = `review`.
56
77
 
@@ -66,7 +87,7 @@ If version control is available and the tree is dirty, create a local commit wit
66
87
  2. Display a summary in conversation output, including:
67
88
  - The commit hash (if one was created).
68
89
  - List of files changed with one-line descriptions. Any file paths shown in conversation/terminal output must use CWD-relative format (no leading `/`) with `:line` notation (e.g., `src/path/file.ts:42`) for terminal clickability — this differs from spec-file links which use spec-file-relative paths.
69
- - Review findings breakdown: patches applied, items deferred, items rejected. If all findings were rejected, say so.
90
+ - Review findings breakdown: patches applied, items deferred, and the dismissed count — reasons are recorded in the spec's `## Review Triage Log`. If every finding was dismissed, say so.
70
91
  - A note that the spec is open in their editor (or the file path if it couldn't be opened). Mention that `{spec_file}` now contains a Suggested Review Order.
71
92
  - **Navigation tip:** "Ctrl+click (Cmd+click on macOS) the links in the Suggested Review Order to jump to each stop."
72
93
  3. Offer to push and/or create a pull request.
@@ -30,9 +30,10 @@ activation_steps_append = []
30
30
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
31
31
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
32
32
 
33
- persistent_facts = [
34
- "file:{project-root}/**/project-context.md",
35
- ]
33
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
34
+ # (the Wizz block imports project-context.md there once per session). Add
35
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
36
+ persistent_facts = []
36
37
 
37
38
  # Scalar: executed at the end of Phase 5 (Close), after the retrospective
38
39
  # document is saved and sprint-status is updated. Override wins.
@@ -30,9 +30,10 @@ activation_steps_append = []
30
30
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
31
31
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
32
32
 
33
- persistent_facts = [
34
- "file:{project-root}/**/project-context.md",
35
- ]
33
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
34
+ # (the Wizz block imports project-context.md there once per session). Add
35
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
36
+ persistent_facts = []
36
37
 
37
38
  # Scalar: executed when the workflow reaches its final step,
38
39
  # after sprint-status.yaml is generated and validated. Override wins.
@@ -30,9 +30,10 @@ activation_steps_append = []
30
30
  # - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
31
31
  # (glob patterns are supported; the file's contents are loaded and treated as facts).
32
32
 
33
- persistent_facts = [
34
- "file:{project-root}/**/project-context.md",
35
- ]
33
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
34
+ # (the Wizz block imports project-context.md there once per session). Add
35
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
36
+ persistent_facts = []
36
37
 
37
38
  # Scalar: executed when the workflow reaches its final step,
38
39
  # after sprint status is summarized and risks are surfaced. Override wins.
@@ -1,5 +1,5 @@
1
1
  code: bmm
2
- name: "Wizz Method"
2
+ name: "Wizz Product & Code"
3
3
  description: "Full-lifecycle AI agile development: analysis, planning, architecture, implementation"
4
4
  default_selected: true # This module will be selected by default for new installations
5
5
 
@@ -22,12 +22,11 @@ activation_steps_append = []
22
22
  # Persistent facts the facilitator keeps in mind for the whole session
23
23
  # (domain constraints, house rules, stylistic guardrails). Each entry is a
24
24
  # literal sentence, a skill prefixed with `skill:`, or a `file:`-prefixed
25
- # path/glob whose contents are loaded as facts. Default loads project-context.md
26
- # if wizz-generate-project-context has produced one, giving the facilitator
27
- # persistent awareness of the project's domain without re-asking.
28
- persistent_facts = [
29
- "file:{project-root}/**/project-context.md",
30
- ]
25
+ # path/glob whose contents are loaded as facts.
26
+ # Empty of project-context by default: repo-wide context belongs in CLAUDE.md/AGENTS.md
27
+ # (the Wizz block imports project-context.md there once per session). Add
28
+ # `file:{project-root}/**/project-context.md` here only to load it on every activation.
29
+ persistent_facts = []
31
30
 
32
31
  # The technique library loaded on demand during the session. Swap the path in
33
32
  # team/user TOML to ship a different or extended catalog of creative methods.
@@ -692,7 +692,26 @@ def html_doc(rows: list[dict]) -> str:
692
692
  )
693
693
 
694
694
 
695
+ def pin_utf8(stream):
696
+ """Pin a console stream to UTF-8, keeping its own error handler.
697
+
698
+ `--extra` technique text and the technique names echoed to stderr are
699
+ arbitrary user input, so either stream can carry a character the platform
700
+ default cannot encode (cp1252 on Windows) and print() then raises.
701
+
702
+ errors= is passed through deliberately: reconfigure(encoding=...) alone
703
+ resets the handler to "strict", which would silently downgrade stderr's
704
+ POSIX default of "backslashreplace" and turn a diagnostic about an
705
+ undecodable path into a traceback.
706
+ """
707
+ reconfigure = getattr(stream, "reconfigure", None)
708
+ if reconfigure is not None:
709
+ reconfigure(encoding="utf-8", errors=getattr(stream, "errors", None) or "strict")
710
+
711
+
695
712
  def main(argv: list[str] | None = None) -> int:
713
+ pin_utf8(sys.stdout)
714
+ pin_utf8(sys.stderr)
696
715
  p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
697
716
  p.add_argument("--file", type=Path, default=DEFAULT_FILE, help="technique CSV (default: sibling assets/brain-methods.csv)")
698
717
  p.add_argument("--extra", type=Path, help="JSON overlay of additional techniques (customize.toml additional_techniques), merged into every command")
@@ -3,6 +3,7 @@
3
3
  # dependencies = ["pytest>=8.0"]
4
4
  # ///
5
5
  """Tests for brain.py. Run: uv run -m pytest scripts/tests/test_brain.py"""
6
+ import io
6
7
  import json
7
8
  import sys
8
9
  from pathlib import Path
@@ -237,3 +238,35 @@ def test_shipped_selector_is_in_sync_with_catalog():
237
238
  "assets/brain-selector.html is stale; regenerate: "
238
239
  "uv run brain.py html --out assets/brain-selector.html"
239
240
  )
241
+
242
+
243
+ # --- console encoding (Windows cp1252) ----------------------------------
244
+
245
+ def _cp1252_stream():
246
+ """A text stream that behaves like a Windows console: cp1252, strict."""
247
+ return io.TextIOWrapper(io.BytesIO(), encoding="cp1252", errors="strict", write_through=True)
248
+
249
+
250
+ def test_extra_technique_prints_when_stdout_encoding_is_cp1252(lib, tmp_path, monkeypatch):
251
+ # --extra text is arbitrary user input; the shipped catalog happens to be
252
+ # cp1252-safe, an overlay is not. Unpinned stdout raises UnicodeEncodeError
253
+ # and the command exits having printed nothing.
254
+ overlay = tmp_path / "extra.json"
255
+ overlay.write_text(
256
+ json.dumps([{"category": "wild", "technique_name": "Fikir Fırtınası 🌪", "description": "Beyin fırtınası 日本語"}]),
257
+ encoding="utf-8",
258
+ )
259
+ fake = _cp1252_stream()
260
+ monkeypatch.setattr(sys, "stdout", fake)
261
+ assert brain.main(["--file", str(lib), "--extra", str(overlay), "list", "--all"]) == 0
262
+ out = fake.buffer.getvalue().decode("utf-8")
263
+ assert "Fikir Fırtınası 🌪" in out
264
+ assert "日本語" in out
265
+
266
+
267
+ def test_missing_technique_name_reports_when_stderr_encoding_is_cp1252(lib, monkeypatch):
268
+ # `show` echoes the name it could not find; that name came from argv.
269
+ fake = _cp1252_stream()
270
+ monkeypatch.setattr(sys, "stderr", fake)
271
+ assert brain.main(["--file", str(lib), "show", "日本語"]) == 1
272
+ assert "日本語" in fake.buffer.getvalue().decode("utf-8")
@@ -126,7 +126,9 @@ def load_party_workflow(project_root: Path, party_skill: Path):
126
126
  except (OSError, json.JSONDecodeError):
127
127
  pass
128
128
  resolver = project_root / "_wizz" / "scripts" / "resolve_customization.py"
129
- data = _run_json([sys.executable, str(resolver), "--skill", str(party_skill), "--key", "workflow"])
129
+ data = _run_json(
130
+ [sys.executable, str(resolver), "--skill", str(party_skill), "--project-root", str(project_root), "--key", "workflow"]
131
+ )
130
132
  if data is not None and isinstance(data.get("workflow"), dict):
131
133
  return data["workflow"]
132
134
  # Fallback: base customize.toml directly, no override merge.
@@ -5,6 +5,7 @@
5
5
  """Unit tests for resolve_personas.py — pool merge, alias, party resolution."""
6
6
 
7
7
  import sys
8
+ import tempfile
8
9
  import unittest
9
10
  from pathlib import Path
10
11
 
@@ -134,5 +135,25 @@ class TestOverrideMergeFallback(unittest.TestCase):
134
135
  self.assertEqual([m["code"] for m in wf["party_members"]], ["x", "y"]) # appended
135
136
 
136
137
 
138
+ class TestPassesProjectRootToResolver(unittest.TestCase):
139
+ """Sem snapshot, o wrapper chama resolve_customization.py; a raiz vai explícita (BMAD 6.12, #2802)."""
140
+
141
+ def _captured_command(self, tmp):
142
+ captured = []
143
+ original = rp._run_json
144
+ rp._run_json = lambda cmd: captured.append(cmd) or {"workflow": {}}
145
+ try:
146
+ rp.load_party_workflow(Path(tmp) / "project", Path(tmp) / "skill")
147
+ finally:
148
+ rp._run_json = original
149
+ return captured[0]
150
+
151
+ def test_passes_project_root_to_the_customization_resolver(self):
152
+ with tempfile.TemporaryDirectory() as tmp:
153
+ cmd = self._captured_command(tmp)
154
+ self.assertIn("--project-root", cmd)
155
+ self.assertEqual(cmd[cmd.index("--project-root") + 1], str(Path(tmp) / "project"))
156
+
157
+
137
158
  if __name__ == "__main__":
138
159
  unittest.main()