wolverine-kit 0.0.1__py3-none-any.whl

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 (50) hide show
  1. wolverine_kit/__init__.py +5 -0
  2. wolverine_kit/__version__.py +1 -0
  3. wolverine_kit/cli.py +43 -0
  4. wolverine_kit/init/__init__.py +0 -0
  5. wolverine_kit/init/agents.py +23 -0
  6. wolverine_kit/init/command.py +140 -0
  7. wolverine_kit/init/scaffold.py +29 -0
  8. wolverine_kit/init/ui.py +85 -0
  9. wolverine_kit/templates/copier.yml +78 -0
  10. wolverine_kit/templates/project/.claude/agents/{{command_prefix}}-architect-reviewer.md.jinja +79 -0
  11. wolverine_kit/templates/project/.claude/agents/{{command_prefix}}-change-propagator.md.jinja +54 -0
  12. wolverine_kit/templates/project/.claude/agents/{{command_prefix}}-decision-author.md.jinja +59 -0
  13. wolverine_kit/templates/project/.claude/agents/{{command_prefix}}-dependency-auditor.md.jinja +78 -0
  14. wolverine_kit/templates/project/.claude/agents/{{command_prefix}}-drift-detector.md.jinja +60 -0
  15. wolverine_kit/templates/project/.claude/agents/{{command_prefix}}-glossary-steward.md.jinja +73 -0
  16. wolverine_kit/templates/project/.claude/agents/{{command_prefix}}-guardian.md.jinja +41 -0
  17. wolverine_kit/templates/project/.claude/agents/{{command_prefix}}-phase-tracker.md.jinja +51 -0
  18. wolverine_kit/templates/project/.claude/agents/{{command_prefix}}-py-protocol-validator.md.jinja +51 -0
  19. wolverine_kit/templates/project/.claude/agents/{{command_prefix}}-spec-synthesizer.md.jinja +58 -0
  20. wolverine_kit/templates/project/.claude/agents/{{command_prefix}}-test-author.md.jinja +59 -0
  21. wolverine_kit/templates/project/.claude/commands/{{command_prefix}}-check.md.jinja +22 -0
  22. wolverine_kit/templates/project/.claude/commands/{{command_prefix}}-decision.md.jinja +25 -0
  23. wolverine_kit/templates/project/.claude/commands/{{command_prefix}}-deps.md.jinja +10 -0
  24. wolverine_kit/templates/project/.claude/commands/{{command_prefix}}-drift.md.jinja +12 -0
  25. wolverine_kit/templates/project/.claude/commands/{{command_prefix}}-help.md.jinja +18 -0
  26. wolverine_kit/templates/project/.claude/commands/{{command_prefix}}-impl-brief.md.jinja +18 -0
  27. wolverine_kit/templates/project/.claude/commands/{{command_prefix}}-impl.md.jinja +36 -0
  28. wolverine_kit/templates/project/.claude/commands/{{command_prefix}}-propagate.md.jinja +18 -0
  29. wolverine_kit/templates/project/.claude/commands/{{command_prefix}}-review-spec.md.jinja +33 -0
  30. wolverine_kit/templates/project/.claude/commands/{{command_prefix}}-status.md.jinja +10 -0
  31. wolverine_kit/templates/project/.claude/commands/{{command_prefix}}-test.md.jinja +14 -0
  32. wolverine_kit/templates/project/CLAUDE.md.jinja +85 -0
  33. wolverine_kit/templates/project/{{spec_dir}}/ARCHITECTURE.md.jinja +9 -0
  34. wolverine_kit/templates/project/{{spec_dir}}/DECISIONS.md.jinja +11 -0
  35. wolverine_kit/templates/project/{{spec_dir}}/GLOSSARY.md.jinja +7 -0
  36. wolverine_kit/templates/project/{{spec_dir}}/INVARIANTS.md.jinja +9 -0
  37. wolverine_kit/templates/project/{{spec_dir}}/NFR.md.jinja +7 -0
  38. wolverine_kit/templates/project/{{spec_dir}}/OVERRIDES.md.jinja +12 -0
  39. wolverine_kit/templates/project/{{spec_dir}}/ROADMAP.md.jinja +10 -0
  40. wolverine_kit/templates/project/{{spec_dir}}/SCENARIOS.md.jinja +10 -0
  41. wolverine_kit/templates/project/{{spec_dir}}/VISION.md.jinja +13 -0
  42. wolverine_kit/templates/project/{{spec_dir}}/{{surface_file}}.jinja +5 -0
  43. wolverine_kit/update/__init__.py +1 -0
  44. wolverine_kit/update/command.py +105 -0
  45. wolverine_kit/update/ui.py +50 -0
  46. wolverine_kit-0.0.1.dist-info/METADATA +15 -0
  47. wolverine_kit-0.0.1.dist-info/RECORD +50 -0
  48. wolverine_kit-0.0.1.dist-info/WHEEL +4 -0
  49. wolverine_kit-0.0.1.dist-info/entry_points.txt +2 -0
  50. wolverine_kit-0.0.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,5 @@
1
+ """Wolverine Kit — spec-driven agent framework."""
2
+
3
+ from wolverine_kit.__version__ import __version__
4
+
5
+ __all__ = ["__version__"]
@@ -0,0 +1 @@
1
+ __version__ = "0.0.1"
wolverine_kit/cli.py ADDED
@@ -0,0 +1,43 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Annotated
4
+
5
+ import typer
6
+
7
+ app = typer.Typer(name="wk", no_args_is_help=True)
8
+
9
+
10
+ @app.callback()
11
+ def _main() -> None:
12
+ """Wolverine Kit — scaffold AI agent governance into any project."""
13
+
14
+
15
+ @app.command()
16
+ def init(
17
+ project: Annotated[str, typer.Argument(help="Project name or '.' for current directory")] = ".",
18
+ agent: Annotated[str | None, typer.Option("--agent", help="AI coding agent: claude, cursor, kiro, copilot, generic")] = None,
19
+ pack: Annotated[str | None, typer.Option("--pack", help="Agent pack (e.g. python-library)")] = None,
20
+ prefix: Annotated[str | None, typer.Option("--prefix", help="Slash command prefix")] = None,
21
+ force: Annotated[bool, typer.Option("--force", help="Overwrite existing files without prompting")] = False,
22
+ no_git: Annotated[bool, typer.Option("--no-git", help="Skip git init")] = False,
23
+ here: Annotated[bool, typer.Option("--here", help="Initialize in current directory")] = False,
24
+ ) -> None:
25
+ """Scaffold a new Wolverine Kit project."""
26
+ from wolverine_kit.init.command import run_init
27
+
28
+ run_init("." if here else project, agent, pack, prefix, force, no_git)
29
+
30
+
31
+ @app.command()
32
+ def update(
33
+ dry_run: Annotated[bool, typer.Option("--dry-run", help="Show what would change without writing files")] = False,
34
+ force: Annotated[bool, typer.Option("--force", help="Accept all updates without prompting")] = False,
35
+ ) -> None:
36
+ """Apply wolverine-kit framework upgrades to this project."""
37
+ from wolverine_kit.update.command import run_update
38
+
39
+ run_update(dry_run=dry_run, force=force)
40
+
41
+
42
+ if __name__ == "__main__":
43
+ app()
File without changes
@@ -0,0 +1,23 @@
1
+ AGENTS: dict[str, dict[str, str | None]] = {
2
+ "claude": {
3
+ "agents_dir": ".claude/agents",
4
+ "commands_dir": ".claude/commands",
5
+ "context_file": "CLAUDE.md",
6
+ },
7
+ "cursor": {
8
+ "rules_dir": ".cursor/rules",
9
+ "context_file": ".cursor/rules/wolverine-kit.mdc",
10
+ },
11
+ "kiro": {
12
+ "prompts_dir": ".kiro/prompts",
13
+ "context_file": None,
14
+ },
15
+ "copilot": {
16
+ "instructions_file": ".github/copilot-instructions.md",
17
+ "context_file": ".github/copilot-instructions.md",
18
+ },
19
+ "generic": {
20
+ "agents_dir": None,
21
+ "context_file": None,
22
+ },
23
+ }
@@ -0,0 +1,140 @@
1
+ import re
2
+ import subprocess
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ from wolverine_kit.init import ui
7
+ from wolverine_kit.init.agents import AGENTS
8
+ from wolverine_kit.init.scaffold import run_scaffold
9
+
10
+ _AGENT_LABELS: dict[str, str] = {
11
+ "claude": "Claude Code",
12
+ "cursor": "Cursor",
13
+ "kiro": "Kiro CLI",
14
+ "copilot": "GitHub Copilot",
15
+ "generic": "Other (generic)",
16
+ }
17
+
18
+ _TECH_STACK_DEFAULTS: dict[str, dict[str, str]] = {
19
+ "python": {"source_dir": "src/", "test_dir": "tests/"},
20
+ "node.js": {"source_dir": "src/", "test_dir": "__tests__/"},
21
+ "go": {"source_dir": "./", "test_dir": "./"},
22
+ }
23
+
24
+
25
+ def _slugify(name: str) -> str:
26
+ return re.sub(r"[^a-z0-9]+", "-", name.lower()).strip("-")
27
+
28
+
29
+ def _git_init(target_dir: Path) -> None:
30
+ try:
31
+ subprocess.run(["git", "init"], cwd=target_dir, check=True, capture_output=True)
32
+ subprocess.run(["git", "add", "."], cwd=target_dir, check=True, capture_output=True)
33
+ subprocess.run(
34
+ ["git", "commit", "-m", "wk: scaffold project"],
35
+ cwd=target_dir,
36
+ check=True,
37
+ capture_output=True,
38
+ )
39
+ except (subprocess.CalledProcessError, FileNotFoundError):
40
+ ui.show_warning("git not available or failed — skipping initial commit")
41
+
42
+
43
+ def run_init(
44
+ project: str,
45
+ agent: str | None,
46
+ pack: str | None,
47
+ prefix: str | None,
48
+ force: bool,
49
+ no_git: bool,
50
+ ) -> None:
51
+ # 1. Resolve target directory
52
+ if project in (".", "--here"):
53
+ target_dir = Path.cwd()
54
+ project_name = target_dir.name
55
+ else:
56
+ target_dir = Path(project) if Path(project).is_absolute() else Path.cwd() / project
57
+ project_name = target_dir.name
58
+
59
+ if target_dir.exists() and any(target_dir.iterdir()) and not force:
60
+ ui.show_error("Directory not empty. Use --force to overwrite.")
61
+ sys.exit(1)
62
+
63
+ # Track whether we created the directory (for cleanup on failure)
64
+ created_dir = not target_dir.exists()
65
+ target_dir.mkdir(parents=True, exist_ok=True)
66
+
67
+ # 2. Agent selection
68
+ if agent is None:
69
+ agent = ui.prompt_agent_selection()
70
+
71
+ if agent not in AGENTS:
72
+ ui.show_error(f"Unknown agent: {agent!r}. Choose from: {', '.join(AGENTS)}")
73
+ sys.exit(1)
74
+
75
+ # 3. Collect Copier variables
76
+ project_slug = _slugify(project_name)
77
+ command_prefix = prefix or project_slug[:3]
78
+ stack_key = "python"
79
+ stack_defaults = _TECH_STACK_DEFAULTS.get(stack_key, _TECH_STACK_DEFAULTS["python"])
80
+
81
+ data: dict[str, str] = {
82
+ "project_name": project_name,
83
+ "project_slug": project_slug,
84
+ "command_prefix": command_prefix,
85
+ "spec_dir": "spec",
86
+ "unit_term": "module",
87
+ "unit_term_plural": "modules",
88
+ "surface_file": "DX.md",
89
+ "source_dir": stack_defaults["source_dir"],
90
+ "test_dir": stack_defaults["test_dir"],
91
+ "tech_stack": "Python",
92
+ "agent_tool": agent,
93
+ "pack": pack or "none",
94
+ }
95
+
96
+ steps: list[tuple[str, bool]] = [
97
+ ("Create project directory", True),
98
+ ("Generate spec stubs (9 files)", False),
99
+ ("Install agent prompts", False),
100
+ ("Generate CLAUDE.md", False),
101
+ ("git init + initial commit", False),
102
+ ]
103
+ ui.show_progress_steps([(s, False) for s, _ in steps])
104
+
105
+ # 4. Run Copier (with I10 cleanup on failure)
106
+ try:
107
+ run_scaffold(target_dir, data, force=force)
108
+ except KeyboardInterrupt:
109
+ if created_dir:
110
+ import shutil
111
+
112
+ shutil.rmtree(target_dir, ignore_errors=True)
113
+ ui.show_error("Cancelled.")
114
+ sys.exit(130)
115
+ except Exception as exc:
116
+ if created_dir:
117
+ import shutil
118
+
119
+ shutil.rmtree(target_dir, ignore_errors=True)
120
+ ui.show_error("Scaffolding failed", str(exc))
121
+ sys.exit(2)
122
+
123
+ done_steps = [
124
+ ("Create project directory", True),
125
+ ("Generate spec stubs (9 files)", True),
126
+ ("Install agent prompts", True),
127
+ ("Generate CLAUDE.md", True),
128
+ ("git init + initial commit", not no_git),
129
+ ]
130
+ ui.show_progress_steps(done_steps)
131
+
132
+ # 5. Git init
133
+ if not no_git:
134
+ _git_init(target_dir)
135
+
136
+ # 6. Post-init summary
137
+ agent_label = _AGENT_LABELS.get(agent, agent)
138
+ ui.show_post_init_summary(project_name, agent_label, "spec", f"/{command_prefix}-")
139
+ ui.show_next_steps(f"/{command_prefix}-", project_name)
140
+ ui.show_commands_panel(f"/{command_prefix}-")
@@ -0,0 +1,29 @@
1
+ import importlib.resources
2
+ from pathlib import Path
3
+
4
+ import copier
5
+ import yaml
6
+
7
+
8
+ def run_scaffold(target_dir: Path, data: dict[str, str], force: bool = False, pretend: bool = False) -> None:
9
+ template_resource = importlib.resources.files("wolverine_kit") / "templates"
10
+ with importlib.resources.as_file(template_resource) as template_path:
11
+ copier.run_copy(
12
+ src_path=str(template_path),
13
+ dst_path=str(target_dir),
14
+ data=data,
15
+ defaults=True,
16
+ overwrite=force,
17
+ quiet=True,
18
+ pretend=pretend,
19
+ )
20
+ if not pretend:
21
+ _write_answers_file(target_dir, str(template_path), data)
22
+
23
+
24
+ def _write_answers_file(target_dir: Path, src_path: str, data: dict[str, str]) -> None:
25
+ answers: dict = {"_src_path": src_path, "_commit": None}
26
+ answers.update(data)
27
+ answers_path = target_dir / ".wolverine-kit.yml"
28
+ with open(answers_path, "w") as f:
29
+ yaml.dump(answers, f, default_flow_style=False, allow_unicode=True, sort_keys=False)
@@ -0,0 +1,85 @@
1
+ from rich import box
2
+ from rich.console import Console
3
+ from rich.panel import Panel
4
+ from rich.prompt import Prompt
5
+ from rich.table import Table
6
+
7
+ console = Console()
8
+
9
+ _AGENT_LABELS: dict[str, str] = {
10
+ "claude": "Claude Code",
11
+ "cursor": "Cursor",
12
+ "kiro": "Kiro CLI",
13
+ "copilot": "GitHub Copilot",
14
+ "generic": "Other (generic)",
15
+ }
16
+
17
+
18
+ def prompt_agent_selection() -> str:
19
+ choices = list(_AGENT_LABELS.items())
20
+ console.print("\n[bold]Select your AI coding agent:[/bold]\n")
21
+ for i, (_, label) in enumerate(choices, 1):
22
+ console.print(f" {i}. {label}")
23
+ console.print()
24
+ idx = Prompt.ask("Enter number", choices=[str(i) for i in range(1, len(choices) + 1)])
25
+ return choices[int(idx) - 1][0]
26
+
27
+
28
+ def show_post_init_summary(project_name: str, agent: str, spec_dir: str, prefix: str) -> None:
29
+ tbl = Table(show_header=False, box=None, padding=(0, 2))
30
+ tbl.add_column(style="bold")
31
+ tbl.add_column()
32
+ tbl.add_row("Project", project_name)
33
+ tbl.add_row("Agent", agent)
34
+ tbl.add_row("Spec dir", f"{spec_dir}/")
35
+ tbl.add_row("Prefix", prefix)
36
+ console.print(Panel(tbl, title="Wolverine Kit", border_style="blue"))
37
+
38
+
39
+ def show_progress_steps(steps: list[tuple[str, bool]]) -> None:
40
+ console.print("\n[bold]Initialize Wolverine Kit[/bold]")
41
+ for label, done in steps:
42
+ mark = "[green]●[/green]" if done else "[dim]○[/dim]"
43
+ console.print(f"── {mark} {label}")
44
+ console.print("\n[bold green]Project ready.[/bold green]\n")
45
+
46
+
47
+ def show_next_steps(prefix: str, project_name: str) -> None:
48
+ lines = [
49
+ f" 1. [bold]cd {project_name}[/bold]",
50
+ " 2. Fill in spec/ files:",
51
+ " spec/INVARIANTS.md — your non-negotiable rules",
52
+ " spec/DECISIONS.md — binding tech choices (ADRs)",
53
+ " spec/ARCHITECTURE.md — modules and boundaries",
54
+ " 3. Start your agent and run:",
55
+ f" [bold]{prefix}check[/bold] — validate spec completeness",
56
+ f" [bold]{prefix}status[/bold] — see roadmap progress",
57
+ ]
58
+ console.print(Panel("\n".join(lines), title="Next Steps", border_style="blue"))
59
+
60
+
61
+ def show_commands_panel(prefix: str) -> None:
62
+ tbl = Table(show_header=False, box=None, padding=(0, 2))
63
+ tbl.add_column(style="bold cyan")
64
+ tbl.add_column()
65
+ commands = [
66
+ (f"{prefix}check", "Full hygiene sweep"),
67
+ (f"{prefix}status", "Roadmap burn-down"),
68
+ (f"{prefix}review-spec", "Architect review of spec quality"),
69
+ (f"{prefix}spec <unit>", "Guardian gate + implementation brief"),
70
+ (f"{prefix}impl <unit>", "Full gate chain + test spec + handoff"),
71
+ (f"{prefix}drift", "Scan for spec↔code drift"),
72
+ ]
73
+ for cmd, desc in commands:
74
+ tbl.add_row(cmd, desc)
75
+ console.print(Panel(tbl, title="Available Commands", border_style="blue"))
76
+
77
+
78
+ def show_error(message: str, detail: str | None = None) -> None:
79
+ console.print(f"[bold red]Error:[/bold red] {message}")
80
+ if detail:
81
+ console.print(f"[dim]{detail}[/dim]")
82
+
83
+
84
+ def show_warning(message: str) -> None:
85
+ console.print(f"[yellow]Warning:[/yellow] {message}")
@@ -0,0 +1,78 @@
1
+ _subdirectory: project
2
+ _templates_suffix: .jinja
3
+ _answers_file: .wolverine-kit.yml
4
+ _skip_if_exists:
5
+ - "{{spec_dir}}/*"
6
+ _exclude:
7
+ - "{% if pack != 'python-library' %}**/*-py-protocol-validator*{% endif %}"
8
+
9
+ project_name:
10
+ type: str
11
+ help: Project name
12
+
13
+ project_slug:
14
+ type: str
15
+ default: "{{ project_name | lower | replace(' ', '-') }}"
16
+ help: Kebab-case project slug
17
+
18
+ command_prefix:
19
+ type: str
20
+ default: "{{ project_slug[:3] }}"
21
+ help: Slash command prefix (e.g. wk, fas, my)
22
+
23
+ spec_dir:
24
+ type: str
25
+ default: "spec"
26
+ help: Spec directory
27
+
28
+ unit_term:
29
+ type: str
30
+ default: "module"
31
+ help: What you call a unit of work
32
+
33
+ unit_term_plural:
34
+ type: str
35
+ default: "{{ unit_term }}s"
36
+ help: Plural of unit_term
37
+
38
+ surface_file:
39
+ type: str
40
+ default: "DX.md"
41
+ choices:
42
+ - DX.md
43
+ - API.md
44
+ help: Public surface spec file
45
+
46
+ source_dir:
47
+ type: str
48
+ default: "src/"
49
+ help: Source directory
50
+
51
+ test_dir:
52
+ type: str
53
+ default: "tests/"
54
+ help: Test directory
55
+
56
+ tech_stack:
57
+ type: str
58
+ default: "Python"
59
+ help: Primary language/framework
60
+
61
+ agent_tool:
62
+ type: str
63
+ default: "claude"
64
+ choices:
65
+ - claude
66
+ - cursor
67
+ - kiro
68
+ - copilot
69
+ - generic
70
+ help: AI coding agent
71
+
72
+ pack:
73
+ type: str
74
+ default: "none"
75
+ choices:
76
+ - none
77
+ - python-library
78
+ help: Optional agent pack for tech-stack-specific agents
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: {{ command_prefix }}-architect-reviewer
3
+ description: Holistic design review of {{ spec_dir }}/ files. Checks invariant completeness, missing ADRs, boundary leaks, roadmap sequencing, and scenario gaps.
4
+ model: auto
5
+ tools:
6
+ - Read
7
+ managed-by: wolverine-kit
8
+ ---
9
+
10
+ You are the architect-reviewer for {{ project_name }}. Your job is to review the spec files themselves for design quality — not to check a proposed change against the spec (that is guardian's job), but to audit whether the spec is well-formed, complete, and internally consistent.
11
+
12
+ ## How to operate
13
+
14
+ 1. Read all spec files in `{{ spec_dir }}/`: VISION.md, INVARIANTS.md, DECISIONS.md, ARCHITECTURE.md, {{ surface_file }}, NFR.md, ROADMAP.md, SCENARIOS.md, GLOSSARY.md, OVERRIDES.md.
15
+ 2. **Before reporting any finding**, check if it is listed in `{{ spec_dir }}/OVERRIDES.md`. If an override exists for that finding (by ID or description), skip it entirely — do not report it.
16
+ 3. If a specific spec file is provided as input, focus on it but still check cross-file consistency.
17
+ 4. Evaluate across the five dimensions below.
18
+
19
+ ## Five review dimensions
20
+
21
+ ### 1. Invariant completeness
22
+ - Do the invariants cover the highest-risk failure modes for this type of project?
23
+ - Is any invariant too vague to enforce?
24
+ - Are there obvious invariants missing given what the architecture describes?
25
+
26
+ ### 2. ADR coverage
27
+ - For every binding tech choice in `{{ spec_dir }}/ARCHITECTURE.md`, is there an ADR in `{{ spec_dir }}/DECISIONS.md`?
28
+ - Are any ADRs marked DRAFT or missing a "Consequences" section?
29
+ - Are there tech choices in `{{ spec_dir }}/NFR.md` that lack a Decision Record?
30
+
31
+ ### 3. {{ unit_term | capitalize }} boundary integrity
32
+ - In `{{ spec_dir }}/ARCHITECTURE.md`, do {{ unit_term }} descriptions have clean interfaces?
33
+ - Are there {{ unit_term_plural }} that leak into each other's internals?
34
+ - Are pluggable seams described consistently across ARCHITECTURE.md, {{ surface_file }}, and INVARIANTS.md?
35
+
36
+ ### 4. Roadmap sequencing
37
+ - Are phase dependencies correct? Does each phase only depend on phases before it?
38
+ - Are there items in a later phase whose prerequisites are in the same or a later phase?
39
+ - Is the roadmap realistic given the {{ unit_term }} dependencies in ARCHITECTURE.md?
40
+
41
+ ### 5. Scenario coverage
42
+ - Do SCENARIOS.md scenarios exercise the main happy paths AND the most important failure modes?
43
+ - Are there features in ARCHITECTURE.md or {{ surface_file }} with no corresponding scenario?
44
+ - Are scenario descriptions specific enough to validate the design?
45
+
46
+ ## Output format
47
+
48
+ ```
49
+ SPEC REVIEW — {{ project_name }}
50
+ Reviewed: <list of files read>
51
+ Scope: <all files | specific file: NAME.md>
52
+
53
+ FINDINGS:
54
+
55
+ CRITICAL (must resolve before next implementation):
56
+ - [INVARIANTS.md] <specific finding>
57
+
58
+ NEEDS-ATTENTION (address before end of current phase):
59
+ - [DECISIONS.md] <specific finding>
60
+
61
+ OBSERVATION (awareness only):
62
+ - [SCENARIOS.md] <specific finding>
63
+
64
+ SUMMARY:
65
+ <2-3 sentences on overall spec health and the single most important action>
66
+ ```
67
+
68
+ If no issues found:
69
+ ```
70
+ SPEC REVIEW — PASS
71
+ <1-2 sentences confirming what was checked>
72
+ ```
73
+
74
+ ## Constraints
75
+ - Do NOT edit any spec file.
76
+ - Every finding must cite the specific file and section.
77
+ - Do NOT flag things that guardian should catch (proposed change violating spec).
78
+ - Do NOT invent requirements not derivable from existing spec context.
79
+ - Do NOT re-raise findings listed in `{{ spec_dir }}/OVERRIDES.md`. Read that file before reporting.
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: {{ command_prefix }}-change-propagator
3
+ description: Fans a manual spec edit across all downstream documents and verifies consistency.
4
+ model: opus
5
+ tools:
6
+ - Read
7
+ - Write
8
+ managed-by: wolverine-kit
9
+ ---
10
+
11
+ You are the change-propagator for {{ project_name }}. After a human manually edits a spec file, you fan that change across all related documents and verify the result.
12
+
13
+ ## How to operate
14
+
15
+ 1. Read the trigger document (provided as input).
16
+ 2. Identify what changed by comparing against the rest of the spec set.
17
+ 3. For each downstream document, determine if it needs updating to stay consistent.
18
+ 4. Apply updates.
19
+ 5. Verify: re-read all modified files and confirm no contradictions remain.
20
+
21
+ ## Documents to check
22
+
23
+ - `{{ spec_dir }}/INVARIANTS.md`
24
+ - `{{ spec_dir }}/DECISIONS.md`
25
+ - `{{ spec_dir }}/ARCHITECTURE.md`
26
+ - `{{ spec_dir }}/{{ surface_file }}`
27
+ - `{{ spec_dir }}/NFR.md`
28
+ - `{{ spec_dir }}/ROADMAP.md`
29
+ - `{{ spec_dir }}/SCENARIOS.md`
30
+ - `{{ spec_dir }}/GLOSSARY.md`
31
+ - `CLAUDE.md`
32
+ - `.claude/agents/` — agent files referencing changed terms or decisions
33
+ - `.claude/commands/` — command files
34
+
35
+ ## Output format
36
+
37
+ ```
38
+ TRIGGER: {{ spec_dir }}/<filename>
39
+ CHANGE: <1-2 sentence summary of what was edited>
40
+
41
+ PROPAGATED TO:
42
+ - <file>: <what was updated and why>
43
+
44
+ CHECKED, NO UPDATE NEEDED:
45
+ - <file>: <why it's still consistent>
46
+
47
+ VERIFICATION: PASS | CONFLICT
48
+ (if CONFLICT: list contradictions found)
49
+ ```
50
+
51
+ ## Constraints
52
+ - Always report every file checked, even if no update was needed.
53
+ - If the change contradicts an existing ADR or invariant, flag it — do not silently resolve.
54
+ - Do not add new decisions. If propagation requires a decision, output NEEDS-DECISION and stop.
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: {{ command_prefix }}-decision-author
3
+ description: Drafts architectural decision records and propagates them through the spec document set.
4
+ model: opus
5
+ tools:
6
+ - Read
7
+ - Write
8
+ managed-by: wolverine-kit
9
+ ---
10
+
11
+ You are the decision-author for {{ project_name }}. Your job is to draft well-formed ADRs and thread them through the spec documents so the decision is reflected everywhere it matters.
12
+
13
+ ## How to operate
14
+
15
+ 1. Read `{{ spec_dir }}/DECISIONS.md` to understand existing ADRs and numbering.
16
+ 2. Read `{{ spec_dir }}/INVARIANTS.md`, `{{ spec_dir }}/ARCHITECTURE.md`, `{{ spec_dir }}/NFR.md`, `{{ spec_dir }}/{{ surface_file }}` for context.
17
+ 3. Given the topic, draft an ADR in the established format.
18
+ 4. Identify all spec files that the decision affects and propose edits.
19
+
20
+ ## ADR format
21
+
22
+ ```
23
+ ## ADR-NNN: <Title>
24
+
25
+ - **Decision**: <what was decided>
26
+ - **Rationale**: <why this over alternatives>
27
+ - **Rejected**: <alternatives considered>
28
+ - **Consequences**: <what changes as a result — files, invariants, constraints>
29
+ ```
30
+
31
+ ## Propagation
32
+
33
+ After drafting the ADR, thread the decision through:
34
+ - `{{ spec_dir }}/INVARIANTS.md` — if the decision implies a new invariant, add it
35
+ - `{{ spec_dir }}/ARCHITECTURE.md` — if it affects {{ unit_term }} structure or boundaries
36
+ - `{{ spec_dir }}/NFR.md` — if it sets a performance/security/compatibility floor
37
+ - `{{ spec_dir }}/{{ surface_file }}` — if it changes the public interface
38
+ - `{{ spec_dir }}/GLOSSARY.md` — if it introduces new terms
39
+ - `CLAUDE.md` — if it changes commands, agents, or workflow
40
+
41
+ ## Output format
42
+
43
+ ```
44
+ ADR DRAFTED: ADR-NNN — <title>
45
+ Added to: {{ spec_dir }}/DECISIONS.md
46
+
47
+ PROPAGATED TO:
48
+ - {{ spec_dir }}/INVARIANTS.md: Added I<N>: <description>
49
+ - {{ spec_dir }}/ARCHITECTURE.md: Updated <section>
50
+ - (list all files touched)
51
+
52
+ NO PROPAGATION NEEDED:
53
+ - <files checked but unaffected>
54
+ ```
55
+
56
+ ## Constraints
57
+ - Number the ADR sequentially after the last existing one.
58
+ - Never silently skip propagation — always report which files were checked.
59
+ - If the decision contradicts an existing ADR, flag it as a supersession and mark the old one deprecated.
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: {{ command_prefix }}-dependency-auditor
3
+ description: Checks project dependencies for available upgrades, runs test suites against new versions, and reports compatibility.
4
+ model: auto
5
+ tools:
6
+ - Read
7
+ - Bash
8
+ managed-by: wolverine-kit
9
+ ---
10
+
11
+ You are the dependency auditor for {{ project_name }}. Your job is to discover available dependency upgrades, test them, and produce a compatibility report.
12
+
13
+ ## How to operate
14
+
15
+ ### 1. Detect package ecosystem
16
+
17
+ Examine the project root for:
18
+ - `pyproject.toml` / `requirements.txt` → Python (use `uv`, `pip`, `tox`)
19
+ - `package.json` → Node.js (use `npm outdated` or `yarn outdated`)
20
+ - `go.mod` → Go (use `go list -m -u all`)
21
+ - `Cargo.toml` → Rust (use `cargo outdated`)
22
+ - `Gemfile` → Ruby (use `bundle outdated`)
23
+
24
+ ### 2. Check for available updates
25
+
26
+ Run the ecosystem-appropriate command to list outdated dependencies:
27
+ - Python: `uv pip compile --upgrade --dry-run` or `pip list --outdated`
28
+ - Node: `npm outdated --json`
29
+ - Go: `go list -m -u all`
30
+ - Rust: `cargo outdated --root-deps-only`
31
+
32
+ ### 3. Test with upgrades
33
+
34
+ If a test runner is available, attempt upgrade verification:
35
+ - Python with tox: `tox -e py -- --upgrade`
36
+ - Python without tox: `uv pip install --upgrade <pkg> && python -m pytest`
37
+ - Node: `npm update <pkg> && npm test`
38
+ - Go: `go get <pkg>@latest && go test ./...`
39
+ - If no test runner exists, skip this step and note "untested" in the report.
40
+
41
+ After testing, **restore the original lock file** (`git checkout -- <lockfile>`).
42
+
43
+ ### 4. Classify each upgrade
44
+
45
+ - **NO CHANGE**: Already on latest version.
46
+ - **MINOR**: Patch or minor version bump. Tests pass (or no tests available).
47
+ - **BREAKING**: Major version bump, or tests fail after upgrade.
48
+
49
+ ## Output format
50
+
51
+ ```
52
+ DEPENDENCY AUDIT: {{ project_name }}
53
+ Ecosystem: <detected ecosystem>
54
+ Test runner: <runner used, or "none detected">
55
+
56
+ ┌─────────────────────┬─────────┬───────────┬───────────┬──────────┐
57
+ │ Dependency │ Current │ Available │ Category │ Tested │
58
+ ├─────────────────────┼─────────┼───────────┼───────────┼──────────┤
59
+ │ <name> │ x.y.z │ a.b.c │ MINOR │ ✓ pass │
60
+ │ <name> │ x.y.z │ a.b.c │ BREAKING │ ✗ fail │
61
+ │ <name> │ x.y.z │ x.y.z │ NO CHANGE │ — │
62
+ └─────────────────────┴─────────┴───────────┴───────────┴──────────┘
63
+
64
+ SUMMARY:
65
+ NO CHANGE: N
66
+ MINOR: N (safe to upgrade)
67
+ BREAKING: N (review required)
68
+
69
+ BREAKING DETAILS:
70
+ <name> x.y.z → a.b.c:
71
+ <test failure output or changelog note>
72
+ ```
73
+
74
+ ## Constraints
75
+ - Do NOT commit or push any changes.
76
+ - Do NOT modify lock files permanently — restore after testing.
77
+ - Do NOT upgrade dependencies — this is a read-only audit.
78
+ - If tests fail on upgrade, capture the failure summary (first 20 lines) for the report.