wizz-method 1.14.0 → 1.16.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.
- package/package.json +3 -2
- package/skills-registry.yaml +4 -0
- package/src/bmm-skills/3-solutioning/wizz-architecture/scripts/__pycache__/lint_spine.cpython-313.pyc +0 -0
- package/src/bmm-skills/3-solutioning/wizz-architecture/scripts/tests/__pycache__/test_lint_spine.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/bmm-skills/4-implementation/wizz-code-review/SKILL.md +3 -5
- package/src/bmm-skills/4-implementation/wizz-code-review/customize.toml +71 -0
- package/src/bmm-skills/4-implementation/wizz-code-review/references/claims-check.md +14 -0
- package/src/bmm-skills/4-implementation/wizz-code-review/references/deletion-check.md +14 -0
- package/src/bmm-skills/4-implementation/wizz-code-review/review-prompts/edge-case-hunter.md +110 -0
- package/src/bmm-skills/4-implementation/wizz-code-review/review-prompts/verification-gap.md +113 -0
- package/src/bmm-skills/4-implementation/wizz-code-review/steps/step-01-gather-context.md +32 -23
- package/src/bmm-skills/4-implementation/wizz-code-review/steps/step-02-review.md +10 -13
- package/src/bmm-skills/4-implementation/wizz-code-review/steps/step-03-triage.md +16 -22
- package/src/bmm-skills/4-implementation/wizz-code-review/steps/step-04-present.md +4 -2
- package/src/bmm-skills/4-implementation/wizz-quick-dev/customize.toml +76 -0
- package/src/bmm-skills/4-implementation/wizz-quick-dev/references/claims-check.md +14 -0
- package/src/bmm-skills/4-implementation/wizz-quick-dev/references/deletion-check.md +14 -0
- package/src/bmm-skills/4-implementation/wizz-quick-dev/review-prompts/edge-case-hunter.md +110 -0
- package/src/bmm-skills/4-implementation/wizz-quick-dev/review-prompts/verification-gap.md +113 -0
- package/src/bmm-skills/4-implementation/wizz-quick-dev/step-04-review.md +38 -16
- package/src/bmm-skills/4-implementation/wizz-retrospective/SKILL.md +56 -1488
- package/src/bmm-skills/4-implementation/wizz-retrospective/customize.toml +3 -5
- package/src/bmm-skills/4-implementation/wizz-retrospective/references/acceptance-verdict.md +55 -0
- package/src/bmm-skills/4-implementation/wizz-retrospective/references/aggregate-views.md +17 -0
- package/src/bmm-skills/4-implementation/wizz-retrospective/references/evidence-gathering.md +30 -0
- package/src/bmm-skills/4-implementation/wizz-retrospective/references/retro-document.md +84 -0
- package/src/bmm-skills/4-implementation/wizz-retrospective/references/team-discussion.md +22 -0
- package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/__pycache__/sprint_status.cpython-313.pyc +0 -0
- package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/git_evidence.py +304 -0
- package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/sprint_status.py +746 -0
- package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/tests/__pycache__/test_git_evidence.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/tests/__pycache__/test_sprint_status.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/tests/fixtures/sprint-status-template.yaml +71 -0
- package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/tests/test_git_evidence.py +750 -0
- package/src/bmm-skills/4-implementation/wizz-retrospective/scripts/tests/test_sprint_status.py +1579 -0
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/SKILL.md +39 -296
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/customize.toml +1 -3
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/references/fix-sprint-status.md +30 -0
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/references/generate-tracking.md +25 -0
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/references/readiness-gate.md +20 -0
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/references/status-view.md +14 -0
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/references/validate.md +10 -0
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/scripts/__pycache__/sprint_plan.cpython-313.pyc +0 -0
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/scripts/sprint_plan.py +697 -0
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/scripts/tests/__pycache__/test_sprint_plan.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/scripts/tests/test_sprint_plan.py +524 -0
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/sprint-status-template.yaml +9 -7
- package/src/bmm-skills/module-help.csv +3 -3
- package/src/core-skills/_shared/handoff-protocol.md +7 -8
- package/src/core-skills/module-help.csv +1 -0
- package/src/core-skills/wizz-advanced-elicitation/SKILL.md +36 -114
- package/src/core-skills/wizz-advanced-elicitation/{methods.csv → assets/methods.csv} +29 -27
- package/src/core-skills/wizz-advanced-elicitation/customize.toml +54 -0
- package/src/core-skills/wizz-advanced-elicitation/scripts/__pycache__/pick_methods.cpython-313.pyc +0 -0
- package/src/core-skills/wizz-advanced-elicitation/scripts/pick_methods.py +233 -0
- package/src/core-skills/wizz-advanced-elicitation/scripts/tests/__pycache__/test_pick_methods.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/core-skills/wizz-advanced-elicitation/scripts/tests/test_pick_methods.py +228 -0
- package/src/core-skills/wizz-brainstorming/SKILL.md +2 -2
- package/src/core-skills/wizz-brainstorming/assets/brain-selector.html +2 -0
- package/src/core-skills/wizz-brainstorming/references/converge.md +1 -1
- package/src/core-skills/wizz-brainstorming/references/finalize.md +1 -1
- package/src/core-skills/wizz-brainstorming/references/headless.md +1 -1
- package/src/core-skills/wizz-brainstorming/references/mode-autonomous.md +1 -1
- package/src/core-skills/wizz-brainstorming/scripts/__pycache__/brain.cpython-313.pyc +0 -0
- package/src/core-skills/wizz-brainstorming/scripts/brain.py +36 -6
- package/src/core-skills/wizz-brainstorming/scripts/tests/__pycache__/test_brain.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/core-skills/wizz-brainstorming/scripts/tests/__pycache__/test_brain.cpython-314.pyc +0 -0
- package/src/core-skills/wizz-brainstorming/scripts/tests/test_brain.py +24 -2
- package/src/core-skills/wizz-customize/scripts/__pycache__/list_customizable_skills.cpython-313.pyc +0 -0
- package/src/core-skills/wizz-customize/scripts/tests/__pycache__/test_list_customizable_skills.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/core-skills/wizz-forge-idea/SKILL.md +107 -0
- package/src/core-skills/wizz-forge-idea/customize.toml +41 -0
- package/src/core-skills/wizz-forge-idea/scripts/__pycache__/resolve_personas.cpython-313.pyc +0 -0
- package/src/core-skills/wizz-forge-idea/scripts/__pycache__/resolve_personas.cpython-314.pyc +0 -0
- package/src/core-skills/wizz-forge-idea/scripts/resolve_personas.py +275 -0
- package/src/core-skills/wizz-forge-idea/scripts/tests/__pycache__/test_resolve_personas.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/core-skills/wizz-forge-idea/scripts/tests/__pycache__/test_resolve_personas.cpython-314.pyc +0 -0
- package/src/core-skills/wizz-forge-idea/scripts/tests/test_resolve_personas.py +138 -0
- package/src/core-skills/wizz-party-mode/SKILL.md +37 -54
- package/src/core-skills/wizz-party-mode/customize.toml +61 -2
- package/src/core-skills/wizz-party-mode/references/create-party.md +8 -3
- package/src/core-skills/wizz-party-mode/references/mode-agent-team.md +3 -1
- package/src/core-skills/wizz-party-mode/references/mode-subagent.md +16 -4
- package/src/core-skills/wizz-party-mode/references/party-memory.md +51 -0
- package/src/core-skills/wizz-party-mode/scripts/__pycache__/resolve_party.cpython-313.pyc +0 -0
- package/src/core-skills/wizz-party-mode/scripts/__pycache__/resolve_party.cpython-314.pyc +0 -0
- package/src/core-skills/wizz-party-mode/scripts/resolve_party.py +22 -7
- package/src/core-skills/wizz-party-mode/scripts/tests/__pycache__/test_resolve_party.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/core-skills/wizz-party-mode/scripts/tests/__pycache__/test_resolve_party.cpython-314.pyc +0 -0
- package/src/core-skills/wizz-party-mode/scripts/tests/{test-resolve_party.py → test_resolve_party.py} +8 -0
- package/src/core-skills/wizz-review-edge-case-hunter/SKILL.md +17 -3
- package/src/modules/wizz/README.md +1 -1
- package/src/modules/wizz/_shared/model-ladder.md +22 -0
- package/src/modules/wizz/_shared/token-economy.md +6 -2
- package/src/modules/wizz/agents/wizz-ads/customize.toml +1 -1
- package/src/modules/wizz/agents/wizz-copy/customize.toml +1 -1
- package/src/modules/wizz/agents/wizz-designer/customize.toml +1 -1
- package/src/modules/wizz/agents/wizz-growth/customize.toml +11 -1
- package/src/modules/wizz/agents/wizz-maestro/customize.toml +1 -1
- package/src/modules/wizz/agents/wizz-memoria/customize.toml +1 -1
- package/src/modules/wizz/agents/wizz-qa/customize.toml +1 -1
- package/src/modules/wizz/agents/wizz-seo/customize.toml +1 -1
- package/src/modules/wizz/agents/wizz-social/customize.toml +1 -1
- package/src/modules/wizz/overrides/wizz-agent-analyst.toml +1 -1
- package/src/modules/wizz/overrides/wizz-agent-architect.toml +1 -1
- package/src/modules/wizz/overrides/wizz-agent-dev.toml +1 -1
- package/src/modules/wizz/overrides/wizz-agent-pm.toml +1 -1
- package/src/modules/wizz/overrides/wizz-agent-tech-writer.toml +1 -1
- package/src/modules/wizz/overrides/wizz-agent-ux-designer.toml +1 -1
- package/src/modules/wizz/subagents/codex/wizz-exec-haiku.toml +16 -0
- package/src/modules/wizz/subagents/codex/wizz-exec-opus.toml +18 -0
- package/src/modules/wizz/subagents/codex/wizz-exec-review.toml +17 -0
- package/src/modules/wizz/subagents/codex/wizz-exec-sonnet.toml +17 -0
- package/src/modules/wizz/subagents/gemini/wizz-exec-haiku.md +15 -0
- package/src/modules/wizz/subagents/gemini/wizz-exec-opus.md +17 -0
- package/src/modules/wizz/subagents/gemini/wizz-exec-review.md +15 -0
- package/src/modules/wizz/subagents/gemini/wizz-exec-sonnet.md +16 -0
- package/src/modules/wizz/subagents/opencode/wizz-exec-haiku.md +14 -0
- package/src/modules/wizz/subagents/opencode/wizz-exec-opus.md +16 -0
- package/src/modules/wizz/subagents/opencode/wizz-exec-review.md +16 -0
- package/src/modules/wizz/subagents/opencode/wizz-exec-sonnet.md +15 -0
- package/src/modules/wizz/subagents/wizz-exec-opus.md +16 -0
- package/src/modules/wizz/subagents/wizz-exec-review.md +15 -0
- package/src/scripts/__pycache__/memlog.cpython-313.pyc +0 -0
- package/src/scripts/tests/__pycache__/test_memlog.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/scripts/tests/__pycache__/test_resolve_customization.cpython-313-pytest-9.1.1.pyc +0 -0
- package/src/skills-lib/pesquisa-de-publico-do-piva/README.md +83 -0
- package/src/skills-lib/pesquisa-de-publico-do-piva/SKILL.md +65 -0
- package/src/skills-lib/pesquisa-de-publico-do-piva/assets/template.html +414 -0
- package/src/skills-lib/pesquisa-de-publico-do-piva/prompts.md +131 -0
- package/src/skills-lib/wizz-offer-forge/README.md +13 -0
- package/src/skills-lib/wizz-offer-forge/SKILL.md +74 -0
- package/src/skills-lib/wizz-offer-forge/references/empilhamento-valor.md +25 -0
- package/src/skills-lib/wizz-offer-forge/references/garantia-reversa.md +22 -0
- package/src/skills-lib/wizz-offer-forge/references/mecanismo-unico.md +28 -0
- package/src/skills-lib/wizz-offer-forge/references/ponte-trafego.md +21 -0
- package/src/skills-lib/wizz-router/references/routing-table-flat.md +2 -0
- package/tools/installer/core/installer.js +57 -0
- package/tools/installer/ide/_config-driven.js +44 -30
- package/tools/installer/ide/platform-codes.yaml +42 -3
- package/tools/installer/modules/external-manager.js +140 -2
- package/tools/installer/modules/official-modules.js +68 -21
- package/tools/installer/prompts.js +45 -103
- package/tools/installer/ui.js +64 -7
- package/wizz-modules.yaml +65 -11
- package/src/bmm-skills/4-implementation/wizz-sprint-planning/checklist.md +0 -34
- package/src/core-skills/wizz-brainstorming/scripts/memlog.py +0 -202
- package/src/core-skills/wizz-brainstorming/scripts/tests/test_memlog.py +0 -265
|
Binary file
|
package/src/bmm-skills/4-implementation/wizz-sprint-planning/scripts/tests/test_sprint_plan.py
ADDED
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
# /// script
|
|
2
|
+
# requires-python = ">=3.10"
|
|
3
|
+
# dependencies = ["pytest>=8.0", "ruamel.yaml>=0.18"]
|
|
4
|
+
# ///
|
|
5
|
+
"""Tests for sprint_plan.py — deterministic sprint-status generation.
|
|
6
|
+
|
|
7
|
+
Run: python3 scripts/tests/test_sprint_plan.py
|
|
8
|
+
or: python3 --with pytest --with ruamel.yaml -m pytest scripts/tests/test_sprint_plan.py
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import importlib.util
|
|
12
|
+
import json
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
import pytest
|
|
17
|
+
from ruamel.yaml import YAML
|
|
18
|
+
|
|
19
|
+
SCRIPT = Path(__file__).resolve().parents[1] / "sprint_plan.py"
|
|
20
|
+
TEMPLATE = Path(__file__).resolve().parents[2] / "sprint-status-template.yaml"
|
|
21
|
+
|
|
22
|
+
spec = importlib.util.spec_from_file_location("sprint_plan", SCRIPT)
|
|
23
|
+
mod = importlib.util.module_from_spec(spec)
|
|
24
|
+
spec.loader.exec_module(mod)
|
|
25
|
+
|
|
26
|
+
EPICS_FIXTURE = """\
|
|
27
|
+
# Project Epics
|
|
28
|
+
|
|
29
|
+
## Epic 1: Foundation
|
|
30
|
+
Some prose.
|
|
31
|
+
|
|
32
|
+
### Story 1.1: User Authentication
|
|
33
|
+
Acceptance criteria...
|
|
34
|
+
|
|
35
|
+
### Story 1.2: Account Management
|
|
36
|
+
|
|
37
|
+
## Epic 2: Chat
|
|
38
|
+
### Story 2.1: Personality System
|
|
39
|
+
### Story 2.6a: Split Story, With Punctuation!
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
DATE = "08-01-2026 14:30"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def run_generate(tmp_path, epics_text=EPICS_FIXTURE, existing=None, stories=(), extra=()):
|
|
46
|
+
epic_file = tmp_path / "epics.md"
|
|
47
|
+
epic_file.write_text(epics_text, encoding="utf-8")
|
|
48
|
+
status_file = tmp_path / "impl" / "sprint-status.yaml"
|
|
49
|
+
if existing is not None:
|
|
50
|
+
status_file.parent.mkdir(parents=True, exist_ok=True)
|
|
51
|
+
status_file.write_text(existing, encoding="utf-8")
|
|
52
|
+
stories_dir = tmp_path / "impl"
|
|
53
|
+
stories_dir.mkdir(parents=True, exist_ok=True)
|
|
54
|
+
for name in stories:
|
|
55
|
+
(stories_dir / f"{name}.md").write_text("story", encoding="utf-8")
|
|
56
|
+
argv = [
|
|
57
|
+
"generate", "--epic-file", str(epic_file), "--status-file", str(status_file),
|
|
58
|
+
"--stories-dir", str(stories_dir), "--project", "My Project", "--date", DATE,
|
|
59
|
+
*extra,
|
|
60
|
+
]
|
|
61
|
+
mod.main(argv)
|
|
62
|
+
return status_file
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def load(status_file):
|
|
66
|
+
yaml = YAML()
|
|
67
|
+
with open(status_file, encoding="utf-8") as fh:
|
|
68
|
+
return yaml.load(fh)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def out_json(capsys):
|
|
72
|
+
return json.loads(capsys.readouterr().out)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_fresh_generate_orders_and_defaults(tmp_path, capsys):
|
|
76
|
+
status_file = run_generate(tmp_path)
|
|
77
|
+
result = out_json(capsys)
|
|
78
|
+
data = load(status_file)
|
|
79
|
+
keys = list(data["development_status"].keys())
|
|
80
|
+
assert keys == [
|
|
81
|
+
"epic-1", "1-1-user-authentication", "1-2-account-management", "epic-1-retrospective",
|
|
82
|
+
"epic-2", "2-1-personality-system", "2-6a-split-story-with-punctuation", "epic-2-retrospective",
|
|
83
|
+
]
|
|
84
|
+
assert data["development_status"]["epic-1"] == "backlog"
|
|
85
|
+
assert data["development_status"]["1-1-user-authentication"] == "backlog"
|
|
86
|
+
assert data["development_status"]["epic-1-retrospective"] == "optional"
|
|
87
|
+
assert data["project"] == "My Project"
|
|
88
|
+
assert data["generated"] == DATE and data["last_updated"] == DATE
|
|
89
|
+
assert result["ok"] and result["epics"] == 2 and result["stories"] == 4
|
|
90
|
+
text = status_file.read_text(encoding="utf-8")
|
|
91
|
+
assert "STATUS DEFINITIONS" in text
|
|
92
|
+
assert "\n\n epic-2:" in text # blank line between epic groups
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_header_comment_matches_template():
|
|
96
|
+
"""The template's STATUS DEFINITIONS block and the script's HEADER_COMMENT
|
|
97
|
+
are two copies of one contract; this pins them together."""
|
|
98
|
+
lines = TEMPLATE.read_text(encoding="utf-8").splitlines()
|
|
99
|
+
start = lines.index("# STATUS DEFINITIONS:")
|
|
100
|
+
block = []
|
|
101
|
+
for line in lines[start:]:
|
|
102
|
+
if not line.startswith("#"):
|
|
103
|
+
break
|
|
104
|
+
block.append(line[2:] if line.startswith("# ") else line[1:])
|
|
105
|
+
assert "\n".join(block) + "\n" == mod.HEADER_COMMENT
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
EXISTING = """\
|
|
109
|
+
generated: 01-01-2026 09:00
|
|
110
|
+
last_updated: 01-01-2026 09:00
|
|
111
|
+
project: My Project
|
|
112
|
+
project_key: NOKEY
|
|
113
|
+
tracking_system: file-system
|
|
114
|
+
story_location: impl
|
|
115
|
+
|
|
116
|
+
development_status:
|
|
117
|
+
epic-1: in-progress
|
|
118
|
+
1-1-user-authentication: done
|
|
119
|
+
1-2-account-management: backlog
|
|
120
|
+
epic-1-retrospective: optional
|
|
121
|
+
9-9-ghost-story: done
|
|
122
|
+
|
|
123
|
+
action_items:
|
|
124
|
+
- epic: 1
|
|
125
|
+
action: "Add error-handling review; watch: quotes, commas"
|
|
126
|
+
owner: "Charlie"
|
|
127
|
+
status: open
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def test_merge_preserves_and_never_downgrades(tmp_path, capsys):
|
|
132
|
+
status_file = run_generate(tmp_path, existing=EXISTING)
|
|
133
|
+
result = out_json(capsys)
|
|
134
|
+
data = load(status_file)
|
|
135
|
+
assert data["development_status"]["epic-1"] == "in-progress"
|
|
136
|
+
assert data["development_status"]["1-1-user-authentication"] == "done"
|
|
137
|
+
assert data["generated"] == "01-01-2026 09:00"
|
|
138
|
+
assert data["last_updated"] == DATE
|
|
139
|
+
assert result["dropped_orphans"] == [{"key": "9-9-ghost-story", "status": "done"}]
|
|
140
|
+
assert "9-9-ghost-story" not in data["development_status"]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_legacy_statuses_merge_by_meaning_not_reset(tmp_path, capsys):
|
|
144
|
+
existing = (EXISTING
|
|
145
|
+
.replace("1-2-account-management: backlog", "1-2-account-management: drafted")
|
|
146
|
+
.replace("epic-1: in-progress", "epic-1: contexted"))
|
|
147
|
+
status_file = run_generate(tmp_path, existing=existing)
|
|
148
|
+
result = out_json(capsys)
|
|
149
|
+
data = load(status_file)
|
|
150
|
+
assert data["development_status"]["1-2-account-management"] == "ready-for-dev"
|
|
151
|
+
assert data["development_status"]["epic-1"] == "in-progress"
|
|
152
|
+
assert {"key": "1-2-account-management", "from": "drafted", "to": "ready-for-dev"} in result["legacy_mapped"]
|
|
153
|
+
assert not any("illegal" in w for w in result["warnings"])
|
|
154
|
+
assert result["illegal"] == []
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def test_metadata_preserved_when_flags_omitted(tmp_path, capsys):
|
|
158
|
+
existing = (EXISTING
|
|
159
|
+
.replace("project_key: NOKEY", "project_key: JIRA-PROJ")
|
|
160
|
+
.replace("tracking_system: file-system", "tracking_system: jira")
|
|
161
|
+
.replace("story_location: impl", "story_location: /custom/stories"))
|
|
162
|
+
status_file = run_generate(tmp_path, existing=existing)
|
|
163
|
+
out_json(capsys)
|
|
164
|
+
data = load(status_file)
|
|
165
|
+
assert data["project_key"] == "JIRA-PROJ"
|
|
166
|
+
assert data["tracking_system"] == "jira"
|
|
167
|
+
assert data["story_location"] == "/custom/stories"
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def test_unknown_keys_and_comments_survive_regenerate(tmp_path, capsys):
|
|
171
|
+
existing = EXISTING + "\n# my own note\nsprint_goal: Ship the beta\n"
|
|
172
|
+
status_file = run_generate(tmp_path, existing=existing)
|
|
173
|
+
out_json(capsys)
|
|
174
|
+
data = load(status_file)
|
|
175
|
+
assert data["sprint_goal"] == "Ship the beta"
|
|
176
|
+
assert "# my own note" in status_file.read_text(encoding="utf-8")
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def test_fresh_rebuild_ignores_existing_statuses(tmp_path, capsys):
|
|
180
|
+
status_file = run_generate(tmp_path, existing=EXISTING, extra=("--fresh",))
|
|
181
|
+
result = out_json(capsys)
|
|
182
|
+
data = load(status_file)
|
|
183
|
+
assert data["development_status"]["1-1-user-authentication"] == "backlog"
|
|
184
|
+
assert data["development_status"]["epic-1"] == "backlog"
|
|
185
|
+
assert result["fresh"] is True
|
|
186
|
+
# action_items are retro history, not tracking state — carried even on --fresh
|
|
187
|
+
assert data["action_items"][0]["status"] == "open"
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def test_set_applies_explicit_statuses_even_downgrades(tmp_path, capsys):
|
|
191
|
+
status_file = run_generate(
|
|
192
|
+
tmp_path, existing=EXISTING,
|
|
193
|
+
extra=("--fresh", "--set", "1-1-user-authentication=in-progress", "--set", "epic-1=in-progress"),
|
|
194
|
+
)
|
|
195
|
+
result = out_json(capsys)
|
|
196
|
+
data = load(status_file)
|
|
197
|
+
assert data["development_status"]["1-1-user-authentication"] == "in-progress"
|
|
198
|
+
assert data["development_status"]["epic-1"] == "in-progress"
|
|
199
|
+
assert "1-1-user-authentication=in-progress" in result["explicit_set"]
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def test_set_rejects_unknown_key_and_illegal_status(tmp_path, capsys):
|
|
203
|
+
with pytest.raises(SystemExit) as excinfo:
|
|
204
|
+
run_generate(tmp_path, extra=("--set", "9-9-nope=done"))
|
|
205
|
+
assert excinfo.value.code == 1
|
|
206
|
+
assert out_json(capsys)["ok"] is False
|
|
207
|
+
with pytest.raises(SystemExit):
|
|
208
|
+
run_generate(tmp_path, extra=("--set", "epic-1=review"))
|
|
209
|
+
assert out_json(capsys)["ok"] is False
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def test_action_items_carried_verbatim(tmp_path):
|
|
213
|
+
status_file = run_generate(tmp_path, existing=EXISTING)
|
|
214
|
+
data = load(status_file)
|
|
215
|
+
assert data["action_items"][0]["action"] == "Add error-handling review; watch: quotes, commas"
|
|
216
|
+
assert data["action_items"][0]["status"] == "open"
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def test_story_file_on_disk_floors_ready_for_dev(tmp_path, capsys):
|
|
220
|
+
status_file = run_generate(tmp_path, stories=["1-2-account-management"])
|
|
221
|
+
result = out_json(capsys)
|
|
222
|
+
data = load(status_file)
|
|
223
|
+
assert data["development_status"]["1-2-account-management"] == "ready-for-dev"
|
|
224
|
+
assert data["development_status"]["1-1-user-authentication"] == "backlog"
|
|
225
|
+
assert result["upgraded_from_disk"] == ["1-2-account-management"]
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def test_story_file_never_downgrades_done(tmp_path):
|
|
229
|
+
status_file = run_generate(tmp_path, existing=EXISTING, stories=["1-1-user-authentication"])
|
|
230
|
+
data = load(status_file)
|
|
231
|
+
assert data["development_status"]["1-1-user-authentication"] == "done"
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def test_illegal_existing_status_warns_and_resets(tmp_path, capsys):
|
|
235
|
+
existing = EXISTING.replace("1-2-account-management: backlog", "1-2-account-management: shipped")
|
|
236
|
+
status_file = run_generate(tmp_path, existing=existing)
|
|
237
|
+
result = out_json(capsys)
|
|
238
|
+
data = load(status_file)
|
|
239
|
+
assert data["development_status"]["1-2-account-management"] == "backlog"
|
|
240
|
+
assert any("illegal status 'shipped'" in w for w in result["warnings"])
|
|
241
|
+
assert {"key": "1-2-account-management", "status": "shipped"} in result["illegal"]
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def test_fenced_code_blocks_are_not_parsed(tmp_path, capsys):
|
|
245
|
+
text = EPICS_FIXTURE + "\n```\n## Epic 9: Example Format\n### Story 9.1: Sample\n```\n"
|
|
246
|
+
status_file = run_generate(tmp_path, epics_text=text)
|
|
247
|
+
result = out_json(capsys)
|
|
248
|
+
data = load(status_file)
|
|
249
|
+
assert "epic-9" not in data["development_status"]
|
|
250
|
+
assert result["epics"] == 2
|
|
251
|
+
assert not any("Epic 9" in w for w in result["warnings"])
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def test_non_ascii_titles_keep_distinct_keys(tmp_path, capsys):
|
|
255
|
+
text = "## Epic 1: 基础\n### Story 1.1: 用户认证\n### Story 1.2: 账户管理\n"
|
|
256
|
+
status_file = run_generate(tmp_path, epics_text=text)
|
|
257
|
+
out_json(capsys)
|
|
258
|
+
keys = list(load(status_file)["development_status"].keys())
|
|
259
|
+
assert "1-1-用户认证" in keys and "1-2-账户管理" in keys
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def test_suspect_heading_is_reported(tmp_path, capsys):
|
|
263
|
+
text = EPICS_FIXTURE + "\n### Story Two point one: Bad Format\n"
|
|
264
|
+
run_generate(tmp_path, epics_text=text)
|
|
265
|
+
result = out_json(capsys)
|
|
266
|
+
assert any("unparsed Epic/Story-like heading" in w for w in result["warnings"])
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def test_dry_run_writes_nothing_and_reports_drift(tmp_path, capsys):
|
|
270
|
+
epic_file = tmp_path / "epics.md"
|
|
271
|
+
epic_file.write_text(EPICS_FIXTURE, encoding="utf-8")
|
|
272
|
+
status_file = tmp_path / "sprint-status.yaml"
|
|
273
|
+
status_file.write_text(EXISTING, encoding="utf-8")
|
|
274
|
+
original = status_file.read_bytes()
|
|
275
|
+
mod.main([
|
|
276
|
+
"generate", "--epic-file", str(epic_file), "--status-file", str(status_file),
|
|
277
|
+
"--stories-dir", str(tmp_path), "--project", "P", "--date", DATE, "--dry-run",
|
|
278
|
+
])
|
|
279
|
+
result = out_json(capsys)
|
|
280
|
+
assert result["dry_run"] is True and result["ok"] is True
|
|
281
|
+
assert result["in_sync"] is False
|
|
282
|
+
assert "epic-2" in result["new_entries"]
|
|
283
|
+
assert result["dropped_orphans"] == [{"key": "9-9-ghost-story", "status": "done"}]
|
|
284
|
+
assert status_file.read_bytes() == original
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def test_dry_run_in_sync_after_generate(tmp_path, capsys):
|
|
288
|
+
status_file = run_generate(tmp_path)
|
|
289
|
+
capsys.readouterr()
|
|
290
|
+
mod.main([
|
|
291
|
+
"generate", "--epic-file", str(tmp_path / "epics.md"), "--status-file", str(status_file),
|
|
292
|
+
"--stories-dir", str(tmp_path / "impl"), "--project", "My Project", "--date", DATE,
|
|
293
|
+
"--dry-run",
|
|
294
|
+
])
|
|
295
|
+
result = out_json(capsys)
|
|
296
|
+
assert result["in_sync"] is True
|
|
297
|
+
assert result["new_entries"] == [] and result["dropped_orphans"] == [] and result["illegal"] == []
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def test_no_epics_fails_with_json(tmp_path, capsys):
|
|
301
|
+
epic_file = tmp_path / "notes.md"
|
|
302
|
+
epic_file.write_text("just prose, no epics", encoding="utf-8")
|
|
303
|
+
with pytest.raises(SystemExit) as excinfo:
|
|
304
|
+
mod.main([
|
|
305
|
+
"generate", "--epic-file", str(epic_file), "--status-file", str(tmp_path / "s.yaml"),
|
|
306
|
+
"--stories-dir", str(tmp_path), "--project", "P", "--date", DATE,
|
|
307
|
+
])
|
|
308
|
+
assert excinfo.value.code == 1
|
|
309
|
+
assert out_json(capsys)["ok"] is False
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def test_non_mapping_yaml_fails_with_json(tmp_path, capsys):
|
|
313
|
+
epic_file = tmp_path / "epics.md"
|
|
314
|
+
epic_file.write_text(EPICS_FIXTURE, encoding="utf-8")
|
|
315
|
+
status_file = tmp_path / "sprint-status.yaml"
|
|
316
|
+
status_file.write_text("- just\n- a\n- list\n", encoding="utf-8")
|
|
317
|
+
with pytest.raises(SystemExit) as excinfo:
|
|
318
|
+
mod.main([
|
|
319
|
+
"generate", "--epic-file", str(epic_file), "--status-file", str(status_file),
|
|
320
|
+
"--stories-dir", str(tmp_path), "--project", "P", "--date", DATE,
|
|
321
|
+
])
|
|
322
|
+
assert excinfo.value.code == 1
|
|
323
|
+
assert "not a mapping" in out_json(capsys)["error"]
|
|
324
|
+
with pytest.raises(SystemExit):
|
|
325
|
+
mod.main(["status", "--status-file", str(status_file)])
|
|
326
|
+
assert "not a mapping" in out_json(capsys)["error"]
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def test_argument_errors_emit_json(capsys):
|
|
330
|
+
with pytest.raises(SystemExit) as excinfo:
|
|
331
|
+
mod.main(["generate"])
|
|
332
|
+
assert excinfo.value.code == 2
|
|
333
|
+
assert out_json(capsys)["ok"] is False
|
|
334
|
+
with pytest.raises(SystemExit) as excinfo:
|
|
335
|
+
mod.main(["-h"])
|
|
336
|
+
assert excinfo.value.code == 2
|
|
337
|
+
assert out_json(capsys)["ok"] is False
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
STATUS_FIXTURE = """\
|
|
341
|
+
generated: 01-01-2026 09:00
|
|
342
|
+
last_updated: 07-30-2026 09:00
|
|
343
|
+
project: My Project
|
|
344
|
+
project_key: NOKEY
|
|
345
|
+
tracking_system: file-system
|
|
346
|
+
story_location: impl
|
|
347
|
+
|
|
348
|
+
development_status:
|
|
349
|
+
epic-1: in-progress
|
|
350
|
+
1-1-user-authentication: done
|
|
351
|
+
1-2-account-management: drafted
|
|
352
|
+
epic-1-retrospective: optional
|
|
353
|
+
epic-2: backlog
|
|
354
|
+
2-1-personality-system: backlog
|
|
355
|
+
epic-2-retrospective: optional
|
|
356
|
+
|
|
357
|
+
action_items:
|
|
358
|
+
- epic: 1
|
|
359
|
+
action: "Tighten error handling"
|
|
360
|
+
owner: "Charlie"
|
|
361
|
+
status: open
|
|
362
|
+
- epic: 1
|
|
363
|
+
action: "Old item"
|
|
364
|
+
owner: "Charlie"
|
|
365
|
+
status: done
|
|
366
|
+
"""
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def run_status(tmp_path, capsys, fixture=STATUS_FIXTURE, extra=()):
|
|
370
|
+
status_file = tmp_path / "sprint-status.yaml"
|
|
371
|
+
status_file.write_text(fixture, encoding="utf-8")
|
|
372
|
+
mod.main(["status", "--status-file", str(status_file), "--date", DATE, *extra])
|
|
373
|
+
return json.loads(capsys.readouterr().out)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def test_status_counts_and_recommendation(tmp_path, capsys):
|
|
377
|
+
result = run_status(tmp_path, capsys)
|
|
378
|
+
assert result["stories"] == {"done": 1, "ready-for-dev": 1, "backlog": 1}
|
|
379
|
+
assert result["epics"] == {"in-progress": 1, "backlog": 1}
|
|
380
|
+
assert result["retrospectives"] == {"optional": 2}
|
|
381
|
+
assert result["recommendation"]["skill"] == "wizz-quick-dev"
|
|
382
|
+
assert result["recommendation"]["story_key"] == "1-2-account-management"
|
|
383
|
+
assert result["all_done"] is False
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def test_status_maps_legacy_values(tmp_path, capsys):
|
|
387
|
+
result = run_status(tmp_path, capsys)
|
|
388
|
+
assert {"key": "1-2-account-management", "from": "drafted", "to": "ready-for-dev"} in result["legacy_mapped"]
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
def test_status_open_action_items(tmp_path, capsys):
|
|
392
|
+
result = run_status(tmp_path, capsys)
|
|
393
|
+
assert len(result["open_action_items"]) == 1
|
|
394
|
+
assert result["open_action_items"][0]["action"] == "Tighten error handling"
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def test_status_malformed_action_items_are_flagged_not_dropped(tmp_path, capsys):
|
|
398
|
+
fixture = STATUS_FIXTURE + " - \"just a string\"\n - epic: 2\n action: \"No status\"\n"
|
|
399
|
+
result = run_status(tmp_path, capsys, fixture=fixture)
|
|
400
|
+
assert any("not a mapping" in w for w in result["warnings"])
|
|
401
|
+
assert any("missing or unknown status" in w for w in result["warnings"])
|
|
402
|
+
assert len(result["open_action_items"]) == 1
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
def test_status_review_beats_ready(tmp_path, capsys):
|
|
406
|
+
fixture = STATUS_FIXTURE.replace("2-1-personality-system: backlog", "2-1-personality-system: review")
|
|
407
|
+
result = run_status(tmp_path, capsys, fixture=fixture)
|
|
408
|
+
assert result["recommendation"]["skill"] == "wizz-code-review"
|
|
409
|
+
assert result["recommendation"]["story_key"] == "2-1-personality-system"
|
|
410
|
+
assert any("review" in r for r in result["risks"])
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
def test_status_in_progress_beats_all(tmp_path, capsys):
|
|
414
|
+
fixture = STATUS_FIXTURE.replace("2-1-personality-system: backlog", "2-1-personality-system: in-progress")
|
|
415
|
+
result = run_status(tmp_path, capsys, fixture=fixture)
|
|
416
|
+
assert result["recommendation"]["skill"] == "wizz-quick-dev"
|
|
417
|
+
assert result["recommendation"]["story_key"] == "2-1-personality-system"
|
|
418
|
+
assert result["recommendation"]["reason"] == "resume the in-progress story"
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def test_status_staleness_and_orphan_risks(tmp_path, capsys):
|
|
422
|
+
fixture = (STATUS_FIXTURE
|
|
423
|
+
.replace("last_updated: 07-30-2026 09:00", "last_updated: 01-02-2026 09:00")
|
|
424
|
+
.replace(" epic-2-retrospective: optional",
|
|
425
|
+
" epic-2-retrospective: optional\n 5-1-ghost: backlog"))
|
|
426
|
+
result = run_status(tmp_path, capsys, fixture=fixture)
|
|
427
|
+
assert any("stale" in r for r in result["risks"])
|
|
428
|
+
assert any("orphaned story '5-1-ghost'" in r for r in result["risks"])
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def test_status_unparseable_timestamp_warns_instead_of_silence(tmp_path, capsys):
|
|
432
|
+
fixture = STATUS_FIXTURE.replace("last_updated: 07-30-2026 09:00", "last_updated: whenever")
|
|
433
|
+
result = run_status(tmp_path, capsys, fixture=fixture)
|
|
434
|
+
assert any("staleness check skipped" in w for w in result["warnings"])
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def test_status_iso_and_date_typed_stamps_do_not_crash(tmp_path, capsys):
|
|
438
|
+
fixture = (STATUS_FIXTURE
|
|
439
|
+
.replace("generated: 01-01-2026 09:00", "generated: 2026-01-01")
|
|
440
|
+
.replace("last_updated: 07-30-2026 09:00", "last_updated: 2026-01-02"))
|
|
441
|
+
result = run_status(tmp_path, capsys, fixture=fixture)
|
|
442
|
+
assert result["ok"] is True
|
|
443
|
+
assert result["generated"] == "2026-01-01"
|
|
444
|
+
assert any("stale" in r for r in result["risks"]) # ISO stamp still parses
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
def test_status_all_done_recommends_retro_then_nothing(tmp_path, capsys):
|
|
448
|
+
fixture = (STATUS_FIXTURE
|
|
449
|
+
.replace("1-2-account-management: drafted", "1-2-account-management: done")
|
|
450
|
+
.replace("2-1-personality-system: backlog", "2-1-personality-system: done"))
|
|
451
|
+
result = run_status(tmp_path, capsys, fixture=fixture)
|
|
452
|
+
assert result["recommendation"]["skill"] == "wizz-retrospective"
|
|
453
|
+
assert "epic-1-retrospective" in result["recommendation"]["reason"]
|
|
454
|
+
fixture_done = fixture.replace("epic-1-retrospective: optional", "epic-1-retrospective: done") \
|
|
455
|
+
.replace("epic-2-retrospective: optional", "epic-2-retrospective: done")
|
|
456
|
+
result = run_status(tmp_path, capsys, fixture=fixture_done)
|
|
457
|
+
assert result["all_done"] is True and result["recommendation"] is None
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def test_status_odd_retro_key_reports_instead_of_crashing(tmp_path, capsys):
|
|
461
|
+
fixture = (STATUS_FIXTURE
|
|
462
|
+
.replace("1-2-account-management: drafted", "1-2-account-management: done")
|
|
463
|
+
.replace("2-1-personality-system: backlog", "2-1-personality-system: done")
|
|
464
|
+
.replace("epic-1-retrospective: optional", "epic-1-retrospective: done")
|
|
465
|
+
.replace("epic-2-retrospective: optional",
|
|
466
|
+
"epic-2-retrospective: done\n epic-abc-retrospective: optional"))
|
|
467
|
+
result = run_status(tmp_path, capsys, fixture=fixture)
|
|
468
|
+
assert result["ok"] is True
|
|
469
|
+
assert {"key": "epic-abc-retrospective", "status": "optional"} in result["unrecognized"]
|
|
470
|
+
assert any("unrecognized key" in r for r in result["risks"])
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def test_status_illegal_status_reported(tmp_path, capsys):
|
|
474
|
+
fixture = STATUS_FIXTURE.replace("2-1-personality-system: backlog", "2-1-personality-system: shipped")
|
|
475
|
+
result = run_status(tmp_path, capsys, fixture=fixture)
|
|
476
|
+
assert {"key": "2-1-personality-system", "status": "shipped"} in result["illegal"]
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
def test_status_missing_file_fails_json(tmp_path, capsys):
|
|
480
|
+
with pytest.raises(SystemExit) as excinfo:
|
|
481
|
+
mod.main(["status", "--status-file", str(tmp_path / "nope.yaml")])
|
|
482
|
+
assert excinfo.value.code == 1
|
|
483
|
+
assert json.loads(capsys.readouterr().out)["ok"] is False
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
def run_validate(tmp_path, capsys, content):
|
|
487
|
+
status_file = tmp_path / "sprint-status.yaml"
|
|
488
|
+
if content is not None:
|
|
489
|
+
status_file.write_text(content, encoding="utf-8")
|
|
490
|
+
mod.main(["validate", "--status-file", str(status_file)])
|
|
491
|
+
return json.loads(capsys.readouterr().out)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def test_validate_clean_file(tmp_path, capsys):
|
|
495
|
+
clean = STATUS_FIXTURE.replace("1-2-account-management: drafted", "1-2-account-management: backlog")
|
|
496
|
+
result = run_validate(tmp_path, capsys, clean)
|
|
497
|
+
assert result["valid"] is True and result["problems"] == []
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def test_validate_reports_problems_without_crashing(tmp_path, capsys):
|
|
501
|
+
broken = (STATUS_FIXTURE
|
|
502
|
+
.replace("2-1-personality-system: backlog", "2-1-personality-system: shipped")
|
|
503
|
+
.replace("epic-2-retrospective: optional",
|
|
504
|
+
"epic-2-retrospective: optional\n weird-key: done")
|
|
505
|
+
.replace("last_updated: 07-30-2026 09:00", "last_updated: whenever"))
|
|
506
|
+
result = run_validate(tmp_path, capsys, broken)
|
|
507
|
+
assert result["valid"] is False
|
|
508
|
+
assert any("illegal story status 'shipped'" in p for p in result["problems"])
|
|
509
|
+
assert any("unrecognized key 'weird-key'" in p for p in result["problems"])
|
|
510
|
+
assert any("'last_updated' timestamp" in p for p in result["problems"])
|
|
511
|
+
assert {"key": "1-2-account-management", "from": "drafted", "to": "ready-for-dev"} in result["legacy_mapped"]
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
def test_validate_missing_file_and_bad_yaml(tmp_path, capsys):
|
|
515
|
+
result = run_validate(tmp_path, capsys, None)
|
|
516
|
+
assert result["valid"] is False and "does not exist" in result["problems"][0]
|
|
517
|
+
result = run_validate(tmp_path, capsys, "development_status: [unclosed\n")
|
|
518
|
+
assert result["valid"] is False and "not valid YAML" in result["problems"][0]
|
|
519
|
+
result = run_validate(tmp_path, capsys, "- a\n- b\n")
|
|
520
|
+
assert result["valid"] is False and any("not a mapping" in p for p in result["problems"])
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
if __name__ == "__main__":
|
|
524
|
+
sys.exit(pytest.main([__file__, "-q"]))
|
|
@@ -33,19 +33,21 @@
|
|
|
33
33
|
#
|
|
34
34
|
# WORKFLOW NOTES:
|
|
35
35
|
# ===============
|
|
36
|
-
# -
|
|
37
|
-
# -
|
|
38
|
-
# -
|
|
39
|
-
# -
|
|
36
|
+
# - Epic transitions to 'in-progress' automatically when its first story starts (via build's sprint sync)
|
|
37
|
+
# - Stories can be worked in parallel if team capacity allows
|
|
38
|
+
# - Developer typically creates the next story after the previous one is 'done' to incorporate learnings
|
|
39
|
+
# - Dev moves story to 'review', then runs code-review (fresh context, different LLM recommended)
|
|
40
|
+
# - Retrospective appends its action items to action_items; the status view surfaces open ones
|
|
40
41
|
|
|
41
42
|
# EXAMPLE STRUCTURE (your actual epics/stories will replace these):
|
|
43
|
+
# Timestamps use MM-DD-YYYY HH:MM.
|
|
42
44
|
|
|
43
|
-
generated: 05-06-
|
|
44
|
-
last_updated: 05-06-
|
|
45
|
+
generated: 05-06-2025 21:30
|
|
46
|
+
last_updated: 05-06-2025 21:30
|
|
45
47
|
project: My Awesome Project
|
|
46
48
|
project_key: NOKEY
|
|
47
49
|
tracking_system: file-system
|
|
48
|
-
story_location: "
|
|
50
|
+
story_location: "docs/stories"
|
|
49
51
|
|
|
50
52
|
development_status:
|
|
51
53
|
epic-1: backlog
|
|
@@ -21,7 +21,7 @@ Wizz Method,wizz-ux,Create UX,CU,"Guidance through realizing the plan for your U
|
|
|
21
21
|
Wizz Method,wizz-architecture,Architecture,CA,Offer once requirements exist (a PRD or spec; plus UX if present) and the user is ready to move from what to how. Also offer any time independently-built parts risk diverging. Produces the architecture spine: the invariants that keep features epics and stories consistent. Comes before epics and stories and scales from a quick spine to a full architecture (brownfield: ratifies the existing codebase).,,,3-solutioning,,,true,planning_artifacts,architecture
|
|
22
22
|
Wizz Method,wizz-create-epics-and-stories,Create Epics and Stories,CE,,,,3-solutioning,wizz-architecture,,true,planning_artifacts,epics and stories
|
|
23
23
|
Wizz Method,wizz-check-implementation-readiness,Check Implementation Readiness,IR,Ensure PRD UX Architecture and Epics Stories are aligned.,,,3-solutioning,wizz-create-epics-and-stories,,true,planning_artifacts,readiness report
|
|
24
|
-
Wizz Method,wizz-sprint-planning,Sprint Planning,SP,
|
|
24
|
+
Wizz Method,wizz-sprint-planning,Sprint Planning,SP,"Checks the planning is complete enough to implement (PASS/CONCERNS/FAIL), then generates the sprint status file that implementation agents follow for every story. Can also show progress, validate or repair the tracking file.",,,4-implementation,,,true,implementation_artifacts,sprint status
|
|
25
25
|
Wizz Method,wizz-sprint-status,Sprint Status,SS,Anytime: Summarize sprint status and route to next workflow.,,,4-implementation,wizz-sprint-planning,,false,,
|
|
26
26
|
Wizz Method,wizz-create-story,Create Story,CS,Story cycle start: Prepare first found story in the sprint plan that is next or a specific epic/story designation.,create,,4-implementation,wizz-sprint-planning,wizz-create-story:validate,true,implementation_artifacts,story
|
|
27
27
|
Wizz Method,wizz-create-story,Validate Story,VS,Validates story readiness and completeness before development work begins.,validate,,4-implementation,wizz-create-story:create,wizz-dev-story,false,implementation_artifacts,story validation report
|
|
@@ -29,5 +29,5 @@ Wizz Method,wizz-dev-story,Dev Story,DS,Story cycle: Execute story implementatio
|
|
|
29
29
|
Wizz Method,wizz-code-review,Code Review,CR,Story cycle: If issues back to DS if approved then next CS or ER if epic complete.,,,4-implementation,wizz-dev-story,,false,,
|
|
30
30
|
Wizz Method,wizz-checkpoint-preview,Checkpoint,CK,Guided walkthrough of a change from purpose and context into details. Use for human review of commits branches or PRs.,,,4-implementation,,,false,,
|
|
31
31
|
Wizz Method,wizz-qa-generate-e2e-tests,QA Automation Test,QA,Generate automated API and E2E tests for implemented code. NOT for code review or story validation — use CR for that.,,,4-implementation,wizz-dev-story,,false,implementation_artifacts,test suite
|
|
32
|
-
Wizz Method,wizz-retrospective,Retrospective,ER,Optional at
|
|
33
|
-
Wizz Method,wizz-investigate,Investigate,IN,Forensic case investigation calibrated to the input. Evidence-graded analysis with hypothesis tracking. Produces a structured case file.,,4-implementation,,,false,implementation_artifacts,investigation report
|
|
32
|
+
Wizz Method,wizz-retrospective,Retrospective,ER,"Optional at the end of an epic: review the completed work against its own artifacts and lessons learned, and look ahead to the next epic. Rejects an epic with unfinished stories. If major issues surfaced, consider Correct Course.",,,4-implementation,wizz-code-review,,false,implementation_artifacts,retrospective
|
|
33
|
+
Wizz Method,wizz-investigate,Investigate,IN,Forensic case investigation calibrated to the input. Evidence-graded analysis with hypothesis tracking. Produces a structured case file.,,4-implementation,,,false,implementation_artifacts,investigation report,
|
|
@@ -20,14 +20,13 @@ a seção da skill que importa (progressive disclosure), não a skill inteira.
|
|
|
20
20
|
- seção relevante da skill: aponte o arquivo ou seção específica a
|
|
21
21
|
carregar, não a skill inteira (ex: paid-ads/references/budget.md). Quem
|
|
22
22
|
recebe carrega só isso, não o pacote completo da skill.
|
|
23
|
-
- model_hint (opcional):
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
não trava nada.
|
|
23
|
+
- model_hint (opcional): degrau da escada, não modelo cru. Valores:
|
|
24
|
+
`haiku | sonnet | opus | review`. Quem recebe despacha `wizz-exec-<hint>`
|
|
25
|
+
(nativo em Claude Code, Codex, OpenCode e Gemini CLI). Escalada: no
|
|
26
|
+
máximo 1 degrau acima se o executor devolver ambiguidade ou os testes
|
|
27
|
+
falharem 2x. `opus` é condicional, só quando a sessão que delega roda
|
|
28
|
+
acima de Opus (detalhe completo em `_shared/model-ladder.md`, no
|
|
29
|
+
módulo wizz). Campo opcional: sem ele o handoff funciona normal.
|
|
31
30
|
- precisa planejar (opcional): veredito sim/não do fator de planejamento
|
|
32
31
|
do sinal de complexidade, avaliado por quem delega. Evita que quem
|
|
33
32
|
recebe re-derive o sinal para aplicar o Gate de Planejamento
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
module,skill,display-name,menu-code,description,action,args,phase,preceded-by,followed-by,required,output-location,outputs
|
|
2
2
|
Core,_meta,,,,,,,,,false,https://docs.wizz-method.org/llms.txt,
|
|
3
3
|
Core,wizz-brainstorming,Brainstorming,BSP,Use early in ideation or when stuck generating ideas.,,,anytime,,,false,{output_folder}/brainstorming,brainstorming session
|
|
4
|
+
Core,wizz-forge-idea,Forge Idea,FI,"Test an idea — software, business, creative, research, or personal — through probing questions from different personas until you can act on it or drop it with confidence. Can hand the result to wizz-spec or wizz-quick-dev.",,,anytime,,,false,{output_folder}/forge,refined-idea brief (optional)
|
|
4
5
|
Core,wizz-party-mode,Party Mode,PM,Orchestrate multi-agent discussions when you need multiple perspectives or want agents to collaborate.,,,anytime,,,false,,
|
|
5
6
|
Core,wizz-help,Wizz Help,BH,,,,anytime,,,false,,
|
|
6
7
|
Core,wizz-index-docs,Index Docs,ID,Use when LLM needs to understand available docs without loading everything.,,,anytime,,,false,,
|