blitz-cli 0.9.0__tar.gz → 0.10.0__tar.gz
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.
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/.gitignore +1 -1
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/PKG-INFO +14 -14
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/README.md +13 -13
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/__init__.py +2 -2
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_activity.py +2 -2
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_implement.py +6 -6
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_ontology.py +6 -6
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_playbooks.py +10 -10
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_redact.py +1 -1
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/cli.py +51 -64
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/playbooks/commands/analyze.md +13 -13
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/playbooks/commands/clarify.md +4 -4
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/playbooks/commands/implement.md +6 -6
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/playbooks/commands/plan.md +6 -6
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/playbooks/commands/playbook.md +23 -23
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/playbooks/commands/specify.md +6 -6
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/playbooks/commands/tasks.md +7 -7
- {blitz_cli-0.9.0/blitz_cli/playbooks/scaffold/.playbooks → blitz_cli-0.10.0/blitz_cli/playbooks/scaffold/.blitz}/scripts/bash/common.sh +31 -31
- {blitz_cli-0.9.0/blitz_cli/playbooks/scaffold/.playbooks → blitz_cli-0.10.0/blitz_cli/playbooks/scaffold/.blitz}/scripts/bash/create-new-feature.sh +2 -2
- {blitz_cli-0.9.0/blitz_cli/playbooks/scaffold/.playbooks → blitz_cli-0.10.0/blitz_cli/playbooks/scaffold/.blitz}/scripts/bash/setup-tasks.sh +1 -1
- {blitz_cli-0.9.0/blitz_cli/playbooks/scaffold/.playbooks → blitz_cli-0.10.0/blitz_cli/playbooks/scaffold/.blitz}/templates/plan-template.md +3 -3
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/playbooks/workspace/huddle.md +8 -8
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/templates/workspace_playbook.md.tmpl +2 -2
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/pyproject.toml +1 -1
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/tests/test_implement.py +5 -5
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/tests/test_ontology.py +8 -8
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/tests/test_playbooks.py +15 -15
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/.github/workflows/homebrew.yml +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/.github/workflows/publish.yml +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/.mcp.json +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/LICENSE +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_code_graph.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_corpus.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_dataset.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_git.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_make.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_scaffold.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_tool_schemas.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/_train.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/playbooks/__init__.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/playbooks/commands/__init__.py +0 -0
- {blitz_cli-0.9.0/blitz_cli/playbooks/scaffold/.playbooks → blitz_cli-0.10.0/blitz_cli/playbooks/scaffold/.blitz}/memory/playbook.md +0 -0
- {blitz_cli-0.9.0/blitz_cli/playbooks/scaffold/.playbooks → blitz_cli-0.10.0/blitz_cli/playbooks/scaffold/.blitz}/scripts/bash/check-prerequisites.sh +0 -0
- {blitz_cli-0.9.0/blitz_cli/playbooks/scaffold/.playbooks → blitz_cli-0.10.0/blitz_cli/playbooks/scaffold/.blitz}/scripts/bash/setup-plan.sh +0 -0
- {blitz_cli-0.9.0/blitz_cli/playbooks/scaffold/.playbooks → blitz_cli-0.10.0/blitz_cli/playbooks/scaffold/.blitz}/templates/spec-template.md +0 -0
- {blitz_cli-0.9.0/blitz_cli/playbooks/scaffold/.playbooks → blitz_cli-0.10.0/blitz_cli/playbooks/scaffold/.blitz}/templates/tasks-template.md +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/playbooks/workspace/__init__.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/templates/__init__.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/templates/locker_room_Makefile.tmpl +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/templates/locker_room_README.md.tmpl +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/blitz_cli/templates/locker_room_compose.yml.tmpl +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/tests/test_activity.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/tests/test_cli.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/tests/test_corpus.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/tests/test_make.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/tests/test_redact.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/tests/test_scaffold.py +0 -0
- {blitz_cli-0.9.0 → blitz_cli-0.10.0}/tests/test_tool_schemas.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blitz-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: Developer CLI for Blitz locker-room: spec-driven playbooks, a codebase/huddle ontology graph with an MCP tool, and the composable watcher/trainer/graph containers.
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -31,18 +31,18 @@ The core CLI is stdlib plus `rich`. Two optional extras carry heavier deps only
|
|
|
31
31
|
when you need them: `blitz-cli[locker-room]` (the MCP server) and
|
|
32
32
|
`blitz-cli[train]` (the QLoRA trainer).
|
|
33
33
|
|
|
34
|
-
Top-level commands: `
|
|
34
|
+
Top-level commands: `init`, `implement`, `locker-room`.
|
|
35
35
|
|
|
36
36
|
## Playbooks: spec-driven development commands
|
|
37
37
|
|
|
38
|
-
`blitz
|
|
38
|
+
`blitz init` installs a set of spec-driven-development slash-commands
|
|
39
39
|
into a repo, rendered for whichever agent you use (Claude Code, Cursor, GitHub
|
|
40
|
-
Copilot, Gemini CLI, OpenCode), plus a shared `.
|
|
40
|
+
Copilot, Gemini CLI, OpenCode), plus a shared `.blitz/` working area.
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
blitz
|
|
44
|
-
blitz
|
|
45
|
-
blitz
|
|
43
|
+
blitz init # auto-detect the agent(s) in this repo
|
|
44
|
+
blitz init --agent claude # or target one explicitly
|
|
45
|
+
blitz init --all # install for every supported agent
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
The commands are `specify`, `plan`, `tasks`, `implement`, `playbook`, `clarify`,
|
|
@@ -61,7 +61,7 @@ each phase's machine-runnable verification, retries with the failure fed back
|
|
|
61
61
|
`- [x]` in the tasks.md. A task that keeps failing stops the run so the state
|
|
62
62
|
stays inspectable. Per-attempt model replies, snapshots, and exact token
|
|
63
63
|
accounting (`usage.json`, per task and total) land under
|
|
64
|
-
`.
|
|
64
|
+
`.blitz/implement/runs/<timestamp>/`.
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
67
|
blitz implement # auto-detect the open specs/*/tasks.md
|
|
@@ -120,17 +120,17 @@ the base model with `BASE_MODEL_HF` or `blitz locker-room init --base-model`.
|
|
|
120
120
|
|
|
121
121
|
## Activity: replay a coding-agent session
|
|
122
122
|
|
|
123
|
-
`blitz activity` reads your coding agent's own local session transcripts
|
|
123
|
+
`blitz locker-room activity` reads your coding agent's own local session transcripts
|
|
124
124
|
(currently Claude Code's, at `~/.claude/projects`) for the current repo and
|
|
125
125
|
replays each prompt alongside the actions taken to resolve it (tool calls,
|
|
126
126
|
sub-agents) and the final response:
|
|
127
127
|
|
|
128
128
|
```bash
|
|
129
|
-
blitz activity --list # sessions for this repo, most recent first
|
|
130
|
-
blitz activity # the most recent session's timeline
|
|
131
|
-
blitz activity <session-id-prefix> # a specific session
|
|
132
|
-
blitz activity --full # untruncated prompts/responses/tool I/O
|
|
133
|
-
blitz activity --html report.html # also write a self-contained HTML report
|
|
129
|
+
blitz locker-room activity --list # sessions for this repo, most recent first
|
|
130
|
+
blitz locker-room activity # the most recent session's timeline
|
|
131
|
+
blitz locker-room activity <session-id-prefix> # a specific session
|
|
132
|
+
blitz locker-room activity --full # untruncated prompts/responses/tool I/O
|
|
133
|
+
blitz locker-room activity --html report.html # also write a self-contained HTML report
|
|
134
134
|
```
|
|
135
135
|
|
|
136
136
|
The terminal view is compact by default; `--full` shows untruncated text. The
|
|
@@ -12,18 +12,18 @@ The core CLI is stdlib plus `rich`. Two optional extras carry heavier deps only
|
|
|
12
12
|
when you need them: `blitz-cli[locker-room]` (the MCP server) and
|
|
13
13
|
`blitz-cli[train]` (the QLoRA trainer).
|
|
14
14
|
|
|
15
|
-
Top-level commands: `
|
|
15
|
+
Top-level commands: `init`, `implement`, `locker-room`.
|
|
16
16
|
|
|
17
17
|
## Playbooks: spec-driven development commands
|
|
18
18
|
|
|
19
|
-
`blitz
|
|
19
|
+
`blitz init` installs a set of spec-driven-development slash-commands
|
|
20
20
|
into a repo, rendered for whichever agent you use (Claude Code, Cursor, GitHub
|
|
21
|
-
Copilot, Gemini CLI, OpenCode), plus a shared `.
|
|
21
|
+
Copilot, Gemini CLI, OpenCode), plus a shared `.blitz/` working area.
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
blitz
|
|
25
|
-
blitz
|
|
26
|
-
blitz
|
|
24
|
+
blitz init # auto-detect the agent(s) in this repo
|
|
25
|
+
blitz init --agent claude # or target one explicitly
|
|
26
|
+
blitz init --all # install for every supported agent
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
The commands are `specify`, `plan`, `tasks`, `implement`, `playbook`, `clarify`,
|
|
@@ -42,7 +42,7 @@ each phase's machine-runnable verification, retries with the failure fed back
|
|
|
42
42
|
`- [x]` in the tasks.md. A task that keeps failing stops the run so the state
|
|
43
43
|
stays inspectable. Per-attempt model replies, snapshots, and exact token
|
|
44
44
|
accounting (`usage.json`, per task and total) land under
|
|
45
|
-
`.
|
|
45
|
+
`.blitz/implement/runs/<timestamp>/`.
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
48
|
blitz implement # auto-detect the open specs/*/tasks.md
|
|
@@ -101,17 +101,17 @@ the base model with `BASE_MODEL_HF` or `blitz locker-room init --base-model`.
|
|
|
101
101
|
|
|
102
102
|
## Activity: replay a coding-agent session
|
|
103
103
|
|
|
104
|
-
`blitz activity` reads your coding agent's own local session transcripts
|
|
104
|
+
`blitz locker-room activity` reads your coding agent's own local session transcripts
|
|
105
105
|
(currently Claude Code's, at `~/.claude/projects`) for the current repo and
|
|
106
106
|
replays each prompt alongside the actions taken to resolve it (tool calls,
|
|
107
107
|
sub-agents) and the final response:
|
|
108
108
|
|
|
109
109
|
```bash
|
|
110
|
-
blitz activity --list # sessions for this repo, most recent first
|
|
111
|
-
blitz activity # the most recent session's timeline
|
|
112
|
-
blitz activity <session-id-prefix> # a specific session
|
|
113
|
-
blitz activity --full # untruncated prompts/responses/tool I/O
|
|
114
|
-
blitz activity --html report.html # also write a self-contained HTML report
|
|
110
|
+
blitz locker-room activity --list # sessions for this repo, most recent first
|
|
111
|
+
blitz locker-room activity # the most recent session's timeline
|
|
112
|
+
blitz locker-room activity <session-id-prefix> # a specific session
|
|
113
|
+
blitz locker-room activity --full # untruncated prompts/responses/tool I/O
|
|
114
|
+
blitz locker-room activity --html report.html # also write a self-contained HTML report
|
|
115
115
|
```
|
|
116
116
|
|
|
117
117
|
The terminal view is compact by default; `--full` shows untruncated text. The
|
|
@@ -13,7 +13,7 @@ Commands:
|
|
|
13
13
|
- ``blitz traces list`` / ``blitz traces show <trace_id>`` — inspect captured
|
|
14
14
|
traces from the local SQLite store.
|
|
15
15
|
|
|
16
|
-
- ``blitz activity [session] [--list] [--html report.html]`` — replay a
|
|
16
|
+
- ``blitz locker-room activity [session] [--list] [--html report.html]`` — replay a
|
|
17
17
|
Claude Code session for this repo: each prompt you sent, the actions taken
|
|
18
18
|
to resolve it (tool calls, sub-agents), and the final response. Reads
|
|
19
19
|
``~/.claude/projects`` directly; unrelated to Blitz's own captured traces.
|
|
@@ -30,4 +30,4 @@ Commands:
|
|
|
30
30
|
|
|
31
31
|
__all__ = ["__version__"]
|
|
32
32
|
|
|
33
|
-
__version__ = "0.
|
|
33
|
+
__version__ = "0.10.0"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""`blitz activity` — replay a coding-agent session: what you asked, and how it
|
|
1
|
+
"""`blitz locker-room activity` — replay a coding-agent session: what you asked, and how it
|
|
2
2
|
was resolved.
|
|
3
3
|
|
|
4
4
|
The currently-supported transcript format is Claude Code's, at
|
|
@@ -734,7 +734,7 @@ def render_html(session: Session, limit: int) -> str:
|
|
|
734
734
|
'<html lang="en">',
|
|
735
735
|
"<head>",
|
|
736
736
|
'<meta charset="utf-8">',
|
|
737
|
-
f"<title>blitz activity — {html.escape(session.title)}</title>",
|
|
737
|
+
f"<title>blitz locker-room activity — {html.escape(session.title)}</title>",
|
|
738
738
|
f"<style>{_HTML_STYLE}</style>",
|
|
739
739
|
"</head>",
|
|
740
740
|
"<body>",
|
|
@@ -220,12 +220,12 @@ def spec_name(repo: Path, tasks_file: Path) -> str:
|
|
|
220
220
|
|
|
221
221
|
|
|
222
222
|
def local_model_config(repo: Path) -> dict:
|
|
223
|
-
"""The `local_model` block from the nearest `.
|
|
223
|
+
"""The `local_model` block from the nearest `.blitz/config.json`,
|
|
224
224
|
checking the repo first and then walking up to the workspace root. This is
|
|
225
225
|
the same config the `tasks` playbook reads to decide which tasks get the
|
|
226
226
|
[L] (local-model eligible) marker. Returns {} when unconfigured."""
|
|
227
227
|
for d in [repo.resolve(), *repo.resolve().parents]:
|
|
228
|
-
cfg = d / ".
|
|
228
|
+
cfg = d / ".blitz" / "config.json"
|
|
229
229
|
if cfg.is_file():
|
|
230
230
|
try:
|
|
231
231
|
block = json.loads(cfg.read_text()).get("local_model")
|
|
@@ -238,11 +238,11 @@ def local_model_config(repo: Path) -> dict:
|
|
|
238
238
|
|
|
239
239
|
def usage_by_spec(repo: Path) -> dict:
|
|
240
240
|
"""Aggregate every implement run's usage.json under
|
|
241
|
-
.
|
|
241
|
+
.blitz/implement/runs/, keyed by spec: total input/output tokens, model
|
|
242
242
|
calls, run count, and the models used. This is what the locker-room
|
|
243
243
|
ontologizer attaches to Feature nodes so the UI can show per-spec cost."""
|
|
244
244
|
totals: dict = {}
|
|
245
|
-
for f in sorted(repo.glob(".
|
|
245
|
+
for f in sorted(repo.glob(".blitz/implement/runs/*/usage.json")):
|
|
246
246
|
try:
|
|
247
247
|
record = json.loads(f.read_text())
|
|
248
248
|
except (OSError, ValueError):
|
|
@@ -289,7 +289,7 @@ def run(
|
|
|
289
289
|
"""Execute every unchecked task in tasks_file. Returns 0 on success, 1 when a
|
|
290
290
|
task fails after all retries (the run stops there so state stays inspectable)."""
|
|
291
291
|
call_model = call_model or (lambda messages: call_ollama(ollama_url, model, messages))
|
|
292
|
-
run_root = run_root or (repo / ".
|
|
292
|
+
run_root = run_root or (repo / ".blitz" / "implement" / "runs")
|
|
293
293
|
rundir = run_root / datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
294
294
|
snapdir = rundir / "snapshots"
|
|
295
295
|
snapdir.mkdir(parents=True, exist_ok=True)
|
|
@@ -333,7 +333,7 @@ def run(
|
|
|
333
333
|
if local_only and not any(t["local"] for t in tasks):
|
|
334
334
|
print_fn("warning: no [L] markers in this tasks.md — with --local-only "
|
|
335
335
|
"there is nothing to execute (regenerate tasks with a "
|
|
336
|
-
"local_model configured in .
|
|
336
|
+
"local_model configured in .blitz/config.json).")
|
|
337
337
|
last_in_phase = {t["phase"]: t["id"] for t in tasks}
|
|
338
338
|
started = start_at is None
|
|
339
339
|
|
|
@@ -338,8 +338,8 @@ class OntologyStore:
|
|
|
338
338
|
|
|
339
339
|
|
|
340
340
|
def _read_active_feature(repo: Path) -> str | None:
|
|
341
|
-
"""Basename of the repo's active feature dir, from .
|
|
342
|
-
fj = repo / ".
|
|
341
|
+
"""Basename of the repo's active feature dir, from .blitz/feature.json."""
|
|
342
|
+
fj = repo / ".blitz" / "feature.json"
|
|
343
343
|
try:
|
|
344
344
|
val = json.loads(fj.read_text(encoding="utf-8")).get("feature_directory", "")
|
|
345
345
|
except (OSError, ValueError):
|
|
@@ -422,7 +422,7 @@ def _parse_huddle(text: str) -> dict:
|
|
|
422
422
|
|
|
423
423
|
|
|
424
424
|
def _ingest_huddles(ws_root: Path, ws_id: str, store: OntologyStore, repo_ids: dict) -> None:
|
|
425
|
-
huddles_dir = ws_root / ".
|
|
425
|
+
huddles_dir = ws_root / ".blitz" / "huddles"
|
|
426
426
|
if not huddles_dir.is_dir():
|
|
427
427
|
return
|
|
428
428
|
for hd in sorted(huddles_dir.iterdir()):
|
|
@@ -491,19 +491,19 @@ def ontologize(workspace_root, db_path, ignore=None, code=True,
|
|
|
491
491
|
ws_id = f"workspace:{ws_root}"
|
|
492
492
|
store.add_node(ws_id, "Workspace", {"name": ws_root.name, "path": str(ws_root)})
|
|
493
493
|
_ingest_doc_file(store, ws_id, "playbook",
|
|
494
|
-
ws_root / ".
|
|
494
|
+
ws_root / ".blitz" / "memory" / "playbook.md", max_file_bytes)
|
|
495
495
|
|
|
496
496
|
repo_ids: dict[str, str] = {} # name -> node id, for huddle cross-referencing
|
|
497
497
|
ignore_paths = [Path(p) for p in (ignore or [])]
|
|
498
498
|
for repo in _playbooks.find_git_repos(ws_root, ignore=ignore_paths):
|
|
499
|
-
if not (repo / ".
|
|
499
|
+
if not (repo / ".blitz").is_dir():
|
|
500
500
|
continue # only playbook-enabled repos are ontologized
|
|
501
501
|
rid = f"repo:{repo.resolve()}"
|
|
502
502
|
repo_ids[repo.name] = rid
|
|
503
503
|
store.add_node(rid, "Repo", {"name": repo.name, "path": str(repo)})
|
|
504
504
|
store.add_edge(ws_id, rid, "CONTAINS")
|
|
505
505
|
_ingest_doc_file(store, rid, "playbook",
|
|
506
|
-
repo / ".
|
|
506
|
+
repo / ".blitz" / "memory" / "playbook.md", max_file_bytes)
|
|
507
507
|
|
|
508
508
|
for agent in _playbooks.detect_agents(repo):
|
|
509
509
|
aid = f"agent:{agent}"
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
"""`blitz
|
|
1
|
+
"""`blitz init` — install spec-driven-development slash-commands into a repo.
|
|
2
2
|
|
|
3
3
|
The command bodies under ``blitz_cli/playbooks/commands`` are spec-driven-development
|
|
4
4
|
slash-commands adapted from GitHub's spec-kit (https://github.com/github/spec-kit).
|
|
5
5
|
At install time we render each agent-agnostic body into the conventional command
|
|
6
6
|
file for whichever agentic coding tool the user runs (Claude Code, Cursor, GitHub Copilot, Gemini
|
|
7
|
-
CLI, OpenCode), and drop a shared ``.
|
|
7
|
+
CLI, OpenCode), and drop a shared ``.blitz/`` working area (scripts +
|
|
8
8
|
templates) that those commands drive.
|
|
9
9
|
"""
|
|
10
10
|
|
|
@@ -41,11 +41,11 @@ AGENTS: dict[str, AgentSpec] = {
|
|
|
41
41
|
"opencode": AgentSpec(".opencode/command", ".md", "md", "$ARGUMENTS", (".opencode",)),
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
WORKDIR = ".
|
|
44
|
+
WORKDIR = ".blitz"
|
|
45
45
|
|
|
46
46
|
_COMMANDS_PKG = "blitz_cli.playbooks.commands"
|
|
47
47
|
# Workspace-only commands (e.g. /huddle) install into a *folder of repos*, never
|
|
48
|
-
# into an individual repo — they orchestrate across the repos' .
|
|
48
|
+
# into an individual repo — they orchestrate across the repos' .blitz/ dirs.
|
|
49
49
|
_WORKSPACE_PKG = "blitz_cli.playbooks.workspace"
|
|
50
50
|
|
|
51
51
|
# spec-kit cross-references commands as ``__SPECKIT_COMMAND_<NAME>__``; we drop
|
|
@@ -136,7 +136,7 @@ def render(command: str, agent: str, package: str = _COMMANDS_PKG) -> str:
|
|
|
136
136
|
return _wrap(spec.fmt, description, body)
|
|
137
137
|
|
|
138
138
|
|
|
139
|
-
# --- scaffold (shared .
|
|
139
|
+
# --- scaffold (shared .blitz working area) -------------------------------
|
|
140
140
|
|
|
141
141
|
|
|
142
142
|
def _walk(node, prefix: str = ""):
|
|
@@ -231,7 +231,7 @@ def workspace_command_names() -> list[str]:
|
|
|
231
231
|
|
|
232
232
|
|
|
233
233
|
def install_workspace_scaffold(dest_dir: Path) -> Path | None:
|
|
234
|
-
"""Seed the workspace-level ``.
|
|
234
|
+
"""Seed the workspace-level ``.blitz/memory/playbook.md`` from the
|
|
235
235
|
default template. Unlike command installs this NEVER overwrites — the
|
|
236
236
|
file holds user-authored operating knowledge, so even ``--force`` must
|
|
237
237
|
not reset it. Returns the written path, or None when it already exists."""
|
|
@@ -254,8 +254,8 @@ def install_workspace_commands(
|
|
|
254
254
|
"""Install workspace-only commands (/huddle) into ``dest_dir``'s command dirs.
|
|
255
255
|
|
|
256
256
|
``dest_dir`` is a workspace root — a folder of repos, not a repo itself.
|
|
257
|
-
No ``.
|
|
258
|
-
what it needs (``.
|
|
257
|
+
No ``.blitz/`` scaffold is installed here; the huddle command creates
|
|
258
|
+
what it needs (``.blitz/huddles/``) on first use.
|
|
259
259
|
"""
|
|
260
260
|
commands = workspace_command_names()
|
|
261
261
|
results: list[InstallResult] = []
|
|
@@ -271,9 +271,9 @@ def install_workspace_commands(
|
|
|
271
271
|
|
|
272
272
|
|
|
273
273
|
def install_scaffold(dest_dir: Path, force: bool) -> InstallResult:
|
|
274
|
-
"""Copy the shared ``.
|
|
274
|
+
"""Copy the shared ``.blitz/`` working area, rewriting stale paths.
|
|
275
275
|
|
|
276
|
-
Files under ``.
|
|
276
|
+
Files under ``.blitz/memory/`` are seeded once and NEVER overwritten,
|
|
277
277
|
even with ``force`` — they hold user-authored knowledge (a repo's
|
|
278
278
|
constitution/playbook), and ``--force`` is for refreshing rendered
|
|
279
279
|
commands and scaffold templates, not resetting memory."""
|
|
@@ -12,7 +12,7 @@ is exactly the class of thing this module exists to catch, and exactly why
|
|
|
12
12
|
"best-effort" is not "guaranteed."
|
|
13
13
|
|
|
14
14
|
That same real key also surfaced a concrete failure mode worth documenting:
|
|
15
|
-
once displayed via `blitz activity --full`, rich's Tree rendering wrapped the
|
|
15
|
+
once displayed via `blitz locker-room activity --full`, rich's Tree rendering wrapped the
|
|
16
16
|
long token across terminal lines, inserting a real newline plus a
|
|
17
17
|
box-drawing tree-branch prefix (e.g. "\\n│ │ ") *in the middle of the
|
|
18
18
|
token*. If that wrapped output is later captured as another tool's output
|
|
@@ -81,7 +81,7 @@ def _cmd_implement(args: argparse.Namespace) -> int:
|
|
|
81
81
|
return 2
|
|
82
82
|
|
|
83
83
|
# Model resolution: --model flag > BLITZ_IMPLEMENT_MODEL env >
|
|
84
|
-
# .
|
|
84
|
+
# .blitz/config.json local_model.model (repo, then workspace) > default.
|
|
85
85
|
model = (
|
|
86
86
|
args.model
|
|
87
87
|
or os.environ.get("BLITZ_IMPLEMENT_MODEL")
|
|
@@ -152,7 +152,7 @@ def _cmd_activity(args: argparse.Namespace) -> int:
|
|
|
152
152
|
if len(matches) > 1:
|
|
153
153
|
_eprint(
|
|
154
154
|
f"error: {args.session!r} matches {len(matches)} sessions; use more "
|
|
155
|
-
"characters or `blitz activity --list`."
|
|
155
|
+
"characters or `blitz locker-room activity --list`."
|
|
156
156
|
)
|
|
157
157
|
return 2
|
|
158
158
|
summary = matches[0]
|
|
@@ -196,16 +196,9 @@ def _playbooks_install_one(_playbooks, dest: Path, agents: list, force: bool) ->
|
|
|
196
196
|
)
|
|
197
197
|
|
|
198
198
|
|
|
199
|
-
def
|
|
199
|
+
def _cmd_init(args: argparse.Namespace) -> int:
|
|
200
200
|
from blitz_cli import _playbooks
|
|
201
201
|
|
|
202
|
-
if getattr(args, "playbooks_cmd", None) != "init":
|
|
203
|
-
_eprint(
|
|
204
|
-
"usage: blitz playbooks init [--dir .] [--agent NAME]... [--all] "
|
|
205
|
-
"[--each | --root] [--force]"
|
|
206
|
-
)
|
|
207
|
-
return 2
|
|
208
|
-
|
|
209
202
|
dest = Path(args.dir)
|
|
210
203
|
|
|
211
204
|
# Decide per-repo vs. single install. Default to per-repo when --dir is a
|
|
@@ -252,7 +245,7 @@ def _cmd_playbooks(args: argparse.Namespace) -> int:
|
|
|
252
245
|
_playbooks_install_one(_playbooks, repo, agents, args.force)
|
|
253
246
|
workspace_agents.extend(a for a in agents if a not in workspace_agents)
|
|
254
247
|
# A folder of repos also gets the workspace-only /huddle command, which
|
|
255
|
-
# orchestrates cross-repo work over each repo's .
|
|
248
|
+
# orchestrates cross-repo work over each repo's .blitz/ area, plus a
|
|
256
249
|
# seed workspace playbook (topology + cross-repo conventions; never
|
|
257
250
|
# overwritten, even with --force). Only when dest isn't itself a repo —
|
|
258
251
|
# huddle has no meaning inside one.
|
|
@@ -301,7 +294,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
301
294
|
"implement",
|
|
302
295
|
help="Execute a playbook-generated tasks.md with a local model served by "
|
|
303
296
|
"Ollama: one task per call, driver-side verification, bounded retries, "
|
|
304
|
-
"snapshots under .
|
|
297
|
+
"snapshots under .blitz/implement/runs/.",
|
|
305
298
|
)
|
|
306
299
|
impl.add_argument(
|
|
307
300
|
"tasks", nargs="?", default=None,
|
|
@@ -315,7 +308,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
315
308
|
"--model",
|
|
316
309
|
default=None,
|
|
317
310
|
help="Ollama model to drive. Default resolution: this flag, then "
|
|
318
|
-
"BLITZ_IMPLEMENT_MODEL, then local_model.model in .
|
|
311
|
+
"BLITZ_IMPLEMENT_MODEL, then local_model.model in .blitz/config.json "
|
|
319
312
|
"(repo, then workspace), then qwen2.5-14b-28k.",
|
|
320
313
|
)
|
|
321
314
|
impl.add_argument(
|
|
@@ -340,56 +333,9 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
340
333
|
)
|
|
341
334
|
impl.set_defaults(func=_cmd_implement)
|
|
342
335
|
|
|
343
|
-
|
|
344
|
-
"activity",
|
|
345
|
-
help="Replay a coding-agent session: your prompts and how each was "
|
|
346
|
-
"resolved (currently reads Claude Code's local transcripts).",
|
|
347
|
-
)
|
|
348
|
-
act.add_argument(
|
|
349
|
-
"session", nargs="?", default=None,
|
|
350
|
-
help="Session id (or unique prefix) to show; default: the most "
|
|
351
|
-
"recently modified session for the resolved project",
|
|
352
|
-
)
|
|
353
|
-
act.add_argument(
|
|
354
|
-
"--project", default=None,
|
|
355
|
-
help="Repo path whose agent sessions to inspect (default: cwd)",
|
|
356
|
-
)
|
|
357
|
-
act.add_argument(
|
|
358
|
-
"--sessions-dir", "--claude-dir",
|
|
359
|
-
dest="sessions_dir",
|
|
360
|
-
default=os.environ.get("BLITZ_SESSIONS_DIR", os.environ.get("BLITZ_CLAUDE_DIR")),
|
|
361
|
-
help="Override the agent transcript root (default: ~/.claude/projects; "
|
|
362
|
-
"env BLITZ_SESSIONS_DIR)",
|
|
363
|
-
)
|
|
364
|
-
act.add_argument(
|
|
365
|
-
"--list", action="store_true",
|
|
366
|
-
help="List sessions for the resolved project instead of showing one",
|
|
367
|
-
)
|
|
368
|
-
act.add_argument(
|
|
369
|
-
"--limit", type=int, default=30,
|
|
370
|
-
help="Max turns to show, most recent first (default 30)",
|
|
371
|
-
)
|
|
372
|
-
act.add_argument(
|
|
373
|
-
"--full", action="store_true",
|
|
374
|
-
help="Terminal output: show untruncated prompts/responses/tool "
|
|
375
|
-
"input+output instead of the compact single-line labels (the HTML "
|
|
376
|
-
"report always includes full detail, expandable per action, "
|
|
377
|
-
"regardless of this flag)",
|
|
378
|
-
)
|
|
379
|
-
act.add_argument(
|
|
380
|
-
"--html", default=None,
|
|
381
|
-
help="Also write a self-contained HTML report to this path",
|
|
382
|
-
)
|
|
383
|
-
act.set_defaults(func=_cmd_activity)
|
|
384
|
-
|
|
385
|
-
pb = sub.add_parser(
|
|
386
|
-
"playbooks",
|
|
387
|
-
help="Spec-driven development playbooks (slash-commands for your agent tool).",
|
|
388
|
-
)
|
|
389
|
-
pb_sub = pb.add_subparsers(dest="playbooks_cmd", required=True)
|
|
390
|
-
sp_init = pb_sub.add_parser(
|
|
336
|
+
sp_init = sub.add_parser(
|
|
391
337
|
"init",
|
|
392
|
-
help="Install the playbook slash-commands + .
|
|
338
|
+
help="Install the playbook slash-commands + .blitz/ working area into this repo.",
|
|
393
339
|
)
|
|
394
340
|
sp_init.add_argument(
|
|
395
341
|
"--dir", default=".", help="Repo root to install into (default: current dir)."
|
|
@@ -427,8 +373,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
427
373
|
sp_init.add_argument(
|
|
428
374
|
"--force", action="store_true", help="Overwrite existing command/scaffold files."
|
|
429
375
|
)
|
|
430
|
-
sp_init.set_defaults(func=
|
|
431
|
-
pb.set_defaults(func=_cmd_playbooks)
|
|
376
|
+
sp_init.set_defaults(func=_cmd_init)
|
|
432
377
|
|
|
433
378
|
lr = sub.add_parser(
|
|
434
379
|
"locker-room",
|
|
@@ -464,6 +409,48 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
464
409
|
)
|
|
465
410
|
leaf.set_defaults(func=_cmd_locker_room_make, target=target)
|
|
466
411
|
|
|
412
|
+
act = lr_sub.add_parser(
|
|
413
|
+
"activity",
|
|
414
|
+
help="Replay a coding-agent session: your prompts and how each was "
|
|
415
|
+
"resolved (currently reads Claude Code's local transcripts).",
|
|
416
|
+
)
|
|
417
|
+
act.add_argument(
|
|
418
|
+
"session", nargs="?", default=None,
|
|
419
|
+
help="Session id (or unique prefix) to show; default: the most "
|
|
420
|
+
"recently modified session for the resolved project",
|
|
421
|
+
)
|
|
422
|
+
act.add_argument(
|
|
423
|
+
"--project", default=None,
|
|
424
|
+
help="Repo path whose agent sessions to inspect (default: cwd)",
|
|
425
|
+
)
|
|
426
|
+
act.add_argument(
|
|
427
|
+
"--sessions-dir", "--claude-dir",
|
|
428
|
+
dest="sessions_dir",
|
|
429
|
+
default=os.environ.get("BLITZ_SESSIONS_DIR", os.environ.get("BLITZ_CLAUDE_DIR")),
|
|
430
|
+
help="Override the agent transcript root (default: ~/.claude/projects; "
|
|
431
|
+
"env BLITZ_SESSIONS_DIR)",
|
|
432
|
+
)
|
|
433
|
+
act.add_argument(
|
|
434
|
+
"--list", action="store_true",
|
|
435
|
+
help="List sessions for the resolved project instead of showing one",
|
|
436
|
+
)
|
|
437
|
+
act.add_argument(
|
|
438
|
+
"--limit", type=int, default=30,
|
|
439
|
+
help="Max turns to show, most recent first (default 30)",
|
|
440
|
+
)
|
|
441
|
+
act.add_argument(
|
|
442
|
+
"--full", action="store_true",
|
|
443
|
+
help="Terminal output: show untruncated prompts/responses/tool "
|
|
444
|
+
"input+output instead of the compact single-line labels (the HTML "
|
|
445
|
+
"report always includes full detail, expandable per action, "
|
|
446
|
+
"regardless of this flag)",
|
|
447
|
+
)
|
|
448
|
+
act.add_argument(
|
|
449
|
+
"--html", default=None,
|
|
450
|
+
help="Also write a self-contained HTML report to this path",
|
|
451
|
+
)
|
|
452
|
+
act.set_defaults(func=_cmd_activity)
|
|
453
|
+
|
|
467
454
|
return parser
|
|
468
455
|
|
|
469
456
|
|
|
@@ -17,7 +17,7 @@ You **MUST** consider the user input before proceeding (if not empty).
|
|
|
17
17
|
## Pre-Execution Checks
|
|
18
18
|
|
|
19
19
|
**Check for extension hooks (before analysis)**:
|
|
20
|
-
- Check if `.
|
|
20
|
+
- Check if `.blitz/extensions.yml` exists in the project root.
|
|
21
21
|
- If it exists, read it and look for entries under the `hooks.before_analyze` key
|
|
22
22
|
- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
|
|
23
23
|
- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
|
|
@@ -47,7 +47,7 @@ You **MUST** consider the user input before proceeding (if not empty).
|
|
|
47
47
|
Wait for the result of the hook command before proceeding to the Goal.
|
|
48
48
|
```
|
|
49
49
|
After emitting the block above you MUST actually invoke the hook and wait for it to finish before continuing. Run it the same way you would run the command yourself in this agent/session (the invocation may differ from the literal `{command}` id shown above, e.g. a skills-mode agent runs it as `/skill:playbook-...` or `$playbook-...`). Emitting the block alone does not run the hook.
|
|
50
|
-
- If no hooks are registered or `.
|
|
50
|
+
- If no hooks are registered or `.blitz/extensions.yml` does not exist, skip silently
|
|
51
51
|
|
|
52
52
|
## Goal
|
|
53
53
|
|
|
@@ -57,7 +57,7 @@ Identify inconsistencies, duplications, ambiguities, and underspecified items ac
|
|
|
57
57
|
|
|
58
58
|
**STRICTLY READ-ONLY**: Do **not** modify any files. Output a structured analysis report. Offer an optional remediation plan (user must explicitly approve before any follow-up editing commands would be invoked manually).
|
|
59
59
|
|
|
60
|
-
**
|
|
60
|
+
**Playbook Authority**: The project playbook (`/memory/playbook.md`) is **non-negotiable** within this analysis scope. Playbook conflicts are automatically CRITICAL and require adjustment of the spec, plan, or tasks—not dilution, reinterpretation, or silent ignoring of the principle. If a principle itself needs to change, that must occur in a separate, explicit playbook update outside `__SPECKIT_COMMAND_ANALYZE__`.
|
|
61
61
|
|
|
62
62
|
## Execution Steps
|
|
63
63
|
|
|
@@ -99,9 +99,9 @@ Load only the minimal necessary context from each artifact:
|
|
|
99
99
|
- Parallel markers [P]
|
|
100
100
|
- Referenced file paths
|
|
101
101
|
|
|
102
|
-
**From
|
|
102
|
+
**From playbook:**
|
|
103
103
|
|
|
104
|
-
- Load `/memory/
|
|
104
|
+
- Load `/memory/playbook.md` for principle validation
|
|
105
105
|
|
|
106
106
|
### 3. Build Semantic Models
|
|
107
107
|
|
|
@@ -110,7 +110,7 @@ Create internal representations (do not include raw artifacts in output):
|
|
|
110
110
|
- **Requirements inventory**: For each Functional Requirement (FR-###) and Success Criterion (SC-###), record a stable key. Use the explicit FR-/SC- identifier as the primary key when present, and optionally also derive an imperative-phrase slug for readability (e.g., "User can upload file" → `user-can-upload-file`). Include only Success Criteria items that require buildable work (e.g., load-testing infrastructure, security audit tooling), and exclude post-launch outcome metrics and business KPIs (e.g., "Reduce support tickets by 50%").
|
|
111
111
|
- **User story/action inventory**: Discrete user actions with acceptance criteria
|
|
112
112
|
- **Task coverage mapping**: Map each task to one or more requirements or stories (inference by keyword / explicit reference patterns like IDs or key phrases)
|
|
113
|
-
- **
|
|
113
|
+
- **Playbook rule set**: Extract principle names and MUST/SHOULD normative statements
|
|
114
114
|
|
|
115
115
|
### 4. Detection Passes (Token-Efficient Analysis)
|
|
116
116
|
|
|
@@ -132,10 +132,10 @@ Focus on high-signal findings. Limit to 50 findings total; aggregate remainder i
|
|
|
132
132
|
- User stories missing acceptance criteria alignment
|
|
133
133
|
- Tasks referencing files or components not defined in spec/plan
|
|
134
134
|
|
|
135
|
-
#### D.
|
|
135
|
+
#### D. Playbook Alignment
|
|
136
136
|
|
|
137
137
|
- Any requirement or plan element conflicting with a MUST principle
|
|
138
|
-
- Missing mandated sections or quality gates from
|
|
138
|
+
- Missing mandated sections or quality gates from playbook
|
|
139
139
|
|
|
140
140
|
#### E. Coverage Gaps
|
|
141
141
|
|
|
@@ -154,7 +154,7 @@ Focus on high-signal findings. Limit to 50 findings total; aggregate remainder i
|
|
|
154
154
|
|
|
155
155
|
Use this heuristic to prioritize findings:
|
|
156
156
|
|
|
157
|
-
- **CRITICAL**: Violates
|
|
157
|
+
- **CRITICAL**: Violates playbook MUST, missing core spec artifact, or requirement with zero coverage that blocks baseline functionality
|
|
158
158
|
- **HIGH**: Duplicate or conflicting requirement, ambiguous security/performance attribute, untestable acceptance criterion
|
|
159
159
|
- **MEDIUM**: Terminology drift, missing non-functional task coverage, underspecified edge case
|
|
160
160
|
- **LOW**: Style/wording improvements, minor redundancy not affecting execution order
|
|
@@ -176,7 +176,7 @@ Output a Markdown report (no file writes) with the following structure:
|
|
|
176
176
|
| Requirement Key | Has Task? | Task IDs | Notes |
|
|
177
177
|
|-----------------|-----------|----------|-------|
|
|
178
178
|
|
|
179
|
-
**
|
|
179
|
+
**Playbook Alignment Issues:** (if any)
|
|
180
180
|
|
|
181
181
|
**Unmapped Tasks:** (if any)
|
|
182
182
|
|
|
@@ -203,7 +203,7 @@ Ask the user: "Would you like me to suggest concrete remediation edits for the t
|
|
|
203
203
|
|
|
204
204
|
### 9. Check for extension hooks
|
|
205
205
|
|
|
206
|
-
After reporting, check if `.
|
|
206
|
+
After reporting, check if `.blitz/extensions.yml` exists in the project root.
|
|
207
207
|
- If it exists, read it and look for entries under the `hooks.after_analyze` key
|
|
208
208
|
- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
|
|
209
209
|
- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
|
|
@@ -231,7 +231,7 @@ After reporting, check if `.playbooks/extensions.yml` exists in the project root
|
|
|
231
231
|
EXECUTE_COMMAND: {command}
|
|
232
232
|
```
|
|
233
233
|
After emitting the block above you MUST actually invoke the hook and wait for it to finish before continuing. Run it the same way you would run the command yourself in this agent/session (the invocation may differ from the literal `{command}` id shown above, e.g. a skills-mode agent runs it as `/skill:playbook-...` or `$playbook-...`). Emitting the block alone does not run the hook.
|
|
234
|
-
- If no hooks are registered or `.
|
|
234
|
+
- If no hooks are registered or `.blitz/extensions.yml` does not exist, skip silently
|
|
235
235
|
|
|
236
236
|
## Operating Principles
|
|
237
237
|
|
|
@@ -246,7 +246,7 @@ After reporting, check if `.playbooks/extensions.yml` exists in the project root
|
|
|
246
246
|
|
|
247
247
|
- **NEVER modify files** (this is read-only analysis)
|
|
248
248
|
- **NEVER hallucinate missing sections** (if absent, report them accurately)
|
|
249
|
-
- **Prioritize
|
|
249
|
+
- **Prioritize playbook violations** (these are always CRITICAL)
|
|
250
250
|
- **Use examples over exhaustive rules** (cite specific instances, not generic patterns)
|
|
251
251
|
- **Report zero issues gracefully** (emit success report with coverage statistics)
|
|
252
252
|
|
|
@@ -21,7 +21,7 @@ You **MUST** consider the user input before proceeding (if not empty).
|
|
|
21
21
|
## Pre-Execution Checks
|
|
22
22
|
|
|
23
23
|
**Check for extension hooks (before clarification)**:
|
|
24
|
-
- Check if `.
|
|
24
|
+
- Check if `.blitz/extensions.yml` exists in the project root.
|
|
25
25
|
- If it exists, read it and look for entries under the `hooks.before_clarify` key
|
|
26
26
|
- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
|
|
27
27
|
- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
|
|
@@ -51,7 +51,7 @@ You **MUST** consider the user input before proceeding (if not empty).
|
|
|
51
51
|
Wait for the result of the hook command before proceeding to the Outline.
|
|
52
52
|
```
|
|
53
53
|
After emitting the block above you MUST actually invoke the hook and wait for it to finish before continuing. Run it the same way you would run the command yourself in this agent/session (the invocation may differ from the literal `{command}` id shown above, e.g. a skills-mode agent runs it as `/skill:playbook-...` or `$playbook-...`). Emitting the block alone does not run the hook.
|
|
54
|
-
- If no hooks are registered or `.
|
|
54
|
+
- If no hooks are registered or `.blitz/extensions.yml` does not exist, skip silently
|
|
55
55
|
|
|
56
56
|
## Outline
|
|
57
57
|
|
|
@@ -68,7 +68,7 @@ Execution steps:
|
|
|
68
68
|
- If JSON parsing fails, abort and instruct user to re-run `__SPECKIT_COMMAND_SPECIFY__` or verify feature branch environment.
|
|
69
69
|
- For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot").
|
|
70
70
|
|
|
71
|
-
2. **IF EXISTS**: Load `/memory/
|
|
71
|
+
2. **IF EXISTS**: Load `/memory/playbook.md` for project principles and governance constraints.
|
|
72
72
|
|
|
73
73
|
3. Load the current spec file. Perform a structured ambiguity & coverage scan using this taxonomy. For each category, mark status: Clear / Partial / Missing. Produce an internal coverage map used for prioritization (do not output raw map unless no questions will be asked).
|
|
74
74
|
|
|
@@ -236,7 +236,7 @@ Context for prioritization: {ARGS}
|
|
|
236
236
|
|
|
237
237
|
**You MUST complete this section before reporting completion to the user.**
|
|
238
238
|
|
|
239
|
-
Check if `.
|
|
239
|
+
Check if `.blitz/extensions.yml` exists in the project root.
|
|
240
240
|
- If it does not exist, or no hooks are registered under `hooks.after_clarify`, skip to the Completion Report.
|
|
241
241
|
- If it exists, read it and look for entries under the `hooks.after_clarify` key.
|
|
242
242
|
- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue to the Completion Report.
|