blitz-cli 0.7.0__tar.gz → 0.8.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.7.0 → blitz_cli-0.8.0}/PKG-INFO +22 -22
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/README.md +21 -19
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/_ontology.py +25 -8
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/cli.py +3 -140
- blitz_cli-0.8.0/blitz_cli/templates/locker_room_README.md.tmpl +38 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/templates/locker_room_compose.yml.tmpl +21 -18
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/pyproject.toml +7 -10
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/tests/test_cli.py +9 -23
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/tests/test_scaffold.py +5 -4
- blitz_cli-0.7.0/blitz_cli/_locker_room_mcp.py +0 -117
- blitz_cli-0.7.0/blitz_cli/templates/locker_room_README.md.tmpl +0 -39
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/.github/workflows/homebrew.yml +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/.github/workflows/publish.yml +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/.gitignore +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/LICENSE +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/__init__.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/_activity.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/_code_graph.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/_corpus.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/_dataset.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/_git.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/_make.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/_playbooks.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/_redact.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/_scaffold.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/_tool_schemas.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/_train.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/__init__.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/commands/__init__.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/commands/analyze.md +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/commands/clarify.md +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/commands/implement.md +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/commands/plan.md +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/commands/playbook.md +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/commands/specify.md +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/commands/tasks.md +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/scaffold/.playbooks/memory/playbook.md +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/scaffold/.playbooks/scripts/bash/check-prerequisites.sh +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/scaffold/.playbooks/scripts/bash/common.sh +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/scaffold/.playbooks/scripts/bash/create-new-feature.sh +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/scaffold/.playbooks/scripts/bash/setup-plan.sh +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/scaffold/.playbooks/scripts/bash/setup-tasks.sh +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/scaffold/.playbooks/templates/plan-template.md +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/scaffold/.playbooks/templates/spec-template.md +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/scaffold/.playbooks/templates/tasks-template.md +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/workspace/__init__.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/workspace/huddle.md +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/templates/__init__.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/templates/locker_room_Makefile.tmpl +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/tests/test_activity.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/tests/test_corpus.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/tests/test_make.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/tests/test_playbooks.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/tests/test_redact.py +0 -0
- {blitz_cli-0.7.0 → blitz_cli-0.8.0}/tests/test_tool_schemas.py +0 -0
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blitz-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.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
|
|
7
7
|
Requires-Python: >=3.9
|
|
8
8
|
Requires-Dist: rich>=13
|
|
9
|
-
Provides-Extra: locker-room
|
|
10
|
-
Requires-Dist: mcp>=1.0; extra == 'locker-room'
|
|
11
9
|
Provides-Extra: train
|
|
12
10
|
Requires-Dist: accelerate==1.2.1; extra == 'train'
|
|
13
11
|
Requires-Dist: datasets==3.2.0; extra == 'train'
|
|
@@ -55,14 +53,17 @@ for coordinating a feature across repos. Use `--ignore PATH` to skip a repo and
|
|
|
55
53
|
|
|
56
54
|
## Locker-room: ontology graph, watcher, trainer, MCP
|
|
57
55
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
The locker-room is a **context node**: a set of containers that ingest, build,
|
|
57
|
+
and serve an ontology of your codebase to agents (on your machine, a VPN, or a
|
|
58
|
+
team host). `blitz locker-room init` scaffolds a `docker-compose.yml` that pulls
|
|
59
|
+
the prebuilt node images (from `sparepartslabs/blitz-locker-room`) for four roles
|
|
60
|
+
sharing `./data`:
|
|
61
61
|
|
|
62
62
|
- **watch**: ingests your coding agent's session transcripts into a corpus.
|
|
63
63
|
- **graph**: rebuilds an ontology of your playbook-enabled repos, huddles,
|
|
64
64
|
features, and their code lineage into `data/ontology.db` on a loop.
|
|
65
|
-
- **mcp**: serves that ontology to agents over SSE.
|
|
65
|
+
- **mcp**: serves that ontology to agents over MCP (SSE) and a browser graph view.
|
|
66
|
+
- **train**: on-demand QLoRA trainer (needs a GPU).
|
|
66
67
|
|
|
67
68
|
```bash
|
|
68
69
|
blitz locker-room init # write ./locker-room/docker-compose.yml
|
|
@@ -71,24 +72,23 @@ blitz locker-room up # start watch + graph + mcp
|
|
|
71
72
|
blitz locker-room logs
|
|
72
73
|
```
|
|
73
74
|
|
|
74
|
-
The
|
|
75
|
+
The CLI is just these static commands (`init`, and the `up`/`down`/`logs`/`pull`/
|
|
76
|
+
`train` lifecycle passthroughs). The runtime (ingest, graph build, serving) lives
|
|
77
|
+
in the node images, not the CLI.
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
blitz locker-room ontologize # scan a workspace into ./data/ontology.db
|
|
78
|
-
blitz locker-room list # list playbook-enabled repos + their active feature
|
|
79
|
-
blitz locker-room mcp # stdio MCP server for a local agent
|
|
80
|
-
```
|
|
79
|
+
### The graph agents can query
|
|
81
80
|
|
|
82
|
-
|
|
81
|
+
The graph engine (a blitz-cli library the node runs) reuses playbook discovery and
|
|
82
|
+
static code parsing (Python symbols + imports + calls; File nodes for other
|
|
83
|
+
languages) to build `Workspace`, `Repo`, `AgentTool`, `Playbook`, `Feature` (with
|
|
84
|
+
lifecycle stage), `Huddle`, `File`, and `Symbol` nodes. Each feature's git branch
|
|
85
|
+
diff links it to the code it touches (`Feature -TOUCHES-> File/Symbol`), so an
|
|
86
|
+
agent can walk a spec out to the full lineage of code it implements, and back.
|
|
83
87
|
|
|
84
|
-
`
|
|
85
|
-
|
|
86
|
-
`
|
|
87
|
-
`
|
|
88
|
-
it touches (`Feature -TOUCHES-> File/Symbol`), so an agent can walk a spec out to
|
|
89
|
-
the full lineage of code it implements, and back. The MCP tools expose this:
|
|
90
|
-
`list_repos`, `get_repo`, `list_huddles`, `get_huddle`, `get_playbooks`,
|
|
91
|
-
`get_lineage`, `impact_of`, `get_file`, `get_symbol`, and a generic `neighbors`.
|
|
88
|
+
The `mcp` role serves this: point an agent's MCP config at
|
|
89
|
+
`http://<node>:8848/sse` (tools `list_repos`, `get_repo`, `list_huddles`,
|
|
90
|
+
`get_huddle`, `get_playbooks`, `get_lineage`, `impact_of`, `get_file`,
|
|
91
|
+
`get_symbol`, `neighbors`), or open `http://<node>:8848/graph` in a browser.
|
|
92
92
|
|
|
93
93
|
### Training (optional)
|
|
94
94
|
|
|
@@ -34,14 +34,17 @@ for coordinating a feature across repos. Use `--ignore PATH` to skip a repo and
|
|
|
34
34
|
|
|
35
35
|
## Locker-room: ontology graph, watcher, trainer, MCP
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
The locker-room is a **context node**: a set of containers that ingest, build,
|
|
38
|
+
and serve an ontology of your codebase to agents (on your machine, a VPN, or a
|
|
39
|
+
team host). `blitz locker-room init` scaffolds a `docker-compose.yml` that pulls
|
|
40
|
+
the prebuilt node images (from `sparepartslabs/blitz-locker-room`) for four roles
|
|
41
|
+
sharing `./data`:
|
|
40
42
|
|
|
41
43
|
- **watch**: ingests your coding agent's session transcripts into a corpus.
|
|
42
44
|
- **graph**: rebuilds an ontology of your playbook-enabled repos, huddles,
|
|
43
45
|
features, and their code lineage into `data/ontology.db` on a loop.
|
|
44
|
-
- **mcp**: serves that ontology to agents over SSE.
|
|
46
|
+
- **mcp**: serves that ontology to agents over MCP (SSE) and a browser graph view.
|
|
47
|
+
- **train**: on-demand QLoRA trainer (needs a GPU).
|
|
45
48
|
|
|
46
49
|
```bash
|
|
47
50
|
blitz locker-room init # write ./locker-room/docker-compose.yml
|
|
@@ -50,24 +53,23 @@ blitz locker-room up # start watch + graph + mcp
|
|
|
50
53
|
blitz locker-room logs
|
|
51
54
|
```
|
|
52
55
|
|
|
53
|
-
The
|
|
56
|
+
The CLI is just these static commands (`init`, and the `up`/`down`/`logs`/`pull`/
|
|
57
|
+
`train` lifecycle passthroughs). The runtime (ingest, graph build, serving) lives
|
|
58
|
+
in the node images, not the CLI.
|
|
54
59
|
|
|
55
|
-
|
|
56
|
-
blitz locker-room ontologize # scan a workspace into ./data/ontology.db
|
|
57
|
-
blitz locker-room list # list playbook-enabled repos + their active feature
|
|
58
|
-
blitz locker-room mcp # stdio MCP server for a local agent
|
|
59
|
-
```
|
|
60
|
+
### The graph agents can query
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
The graph engine (a blitz-cli library the node runs) reuses playbook discovery and
|
|
63
|
+
static code parsing (Python symbols + imports + calls; File nodes for other
|
|
64
|
+
languages) to build `Workspace`, `Repo`, `AgentTool`, `Playbook`, `Feature` (with
|
|
65
|
+
lifecycle stage), `Huddle`, `File`, and `Symbol` nodes. Each feature's git branch
|
|
66
|
+
diff links it to the code it touches (`Feature -TOUCHES-> File/Symbol`), so an
|
|
67
|
+
agent can walk a spec out to the full lineage of code it implements, and back.
|
|
62
68
|
|
|
63
|
-
`
|
|
64
|
-
|
|
65
|
-
`
|
|
66
|
-
`
|
|
67
|
-
it touches (`Feature -TOUCHES-> File/Symbol`), so an agent can walk a spec out to
|
|
68
|
-
the full lineage of code it implements, and back. The MCP tools expose this:
|
|
69
|
-
`list_repos`, `get_repo`, `list_huddles`, `get_huddle`, `get_playbooks`,
|
|
70
|
-
`get_lineage`, `impact_of`, `get_file`, `get_symbol`, and a generic `neighbors`.
|
|
69
|
+
The `mcp` role serves this: point an agent's MCP config at
|
|
70
|
+
`http://<node>:8848/sse` (tools `list_repos`, `get_repo`, `list_huddles`,
|
|
71
|
+
`get_huddle`, `get_playbooks`, `get_lineage`, `impact_of`, `get_file`,
|
|
72
|
+
`get_symbol`, `neighbors`), or open `http://<node>:8848/graph` in a browser.
|
|
71
73
|
|
|
72
74
|
### Training (optional)
|
|
73
75
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
SQLite file
|
|
5
|
-
(
|
|
6
|
-
graph
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
"""Ontology graph engine for playbook-enabled workspaces/repos/huddles/features.
|
|
2
|
+
|
|
3
|
+
This is a library: ``ontologize()`` scans a workspace and upserts a small graph
|
|
4
|
+
into a SQLite file, and ``OntologyStore`` reads it back. The locker-room context
|
|
5
|
+
node (the blitz-locker-room images) runs both -- its ontologize loop builds the
|
|
6
|
+
graph and its server serves it over MCP/HTTP. The graph is deliberately tiny
|
|
7
|
+
(dozens of repos, a handful of huddles) and stored as generic ``nodes``/``edges``
|
|
8
|
+
tables so the query surface stays engine-agnostic; a Neo4j/Memgraph backend could
|
|
9
|
+
drop in behind the same query helpers later.
|
|
9
10
|
"""
|
|
10
11
|
|
|
11
12
|
from __future__ import annotations
|
|
@@ -178,6 +179,22 @@ class OntologyStore:
|
|
|
178
179
|
node["coordinates"] = self.neighbors(node["id"], rel="COORDINATES")
|
|
179
180
|
return node
|
|
180
181
|
|
|
182
|
+
def graph_data(self, include_code: bool = False) -> dict:
|
|
183
|
+
"""Nodes + edges for visualization. Structural labels only by default
|
|
184
|
+
(Workspace/Repo/Playbook/AgentTool/Feature/Stage/Huddle); pass
|
|
185
|
+
``include_code`` to add File/Symbol (much larger)."""
|
|
186
|
+
nodes = []
|
|
187
|
+
for r in self.conn.execute("SELECT id, label, props FROM nodes").fetchall():
|
|
188
|
+
if not include_code and r["label"] in ("File", "Symbol"):
|
|
189
|
+
continue
|
|
190
|
+
nodes.append({"id": r["id"], "label": r["label"], **json.loads(r["props"])})
|
|
191
|
+
ids = {n["id"] for n in nodes}
|
|
192
|
+
edges = []
|
|
193
|
+
for e in self.conn.execute("SELECT src, dst, rel FROM edges").fetchall():
|
|
194
|
+
if e["src"] in ids and e["dst"] in ids:
|
|
195
|
+
edges.append({"source": e["src"], "target": e["dst"], "rel": e["rel"]})
|
|
196
|
+
return {"nodes": nodes, "edges": edges}
|
|
197
|
+
|
|
181
198
|
def get_playbooks(self, repo: str | None = None) -> list[dict]:
|
|
182
199
|
if repo:
|
|
183
200
|
node = self.get_node(repo) or self.get_node(f"repo:{Path(repo).resolve()}")
|
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import argparse
|
|
6
|
-
import json
|
|
7
6
|
import os
|
|
8
7
|
import sys
|
|
9
|
-
import time
|
|
10
8
|
from pathlib import Path
|
|
11
9
|
from typing import Optional
|
|
12
10
|
|
|
@@ -51,81 +49,14 @@ def _cmd_locker_room_make(args: argparse.Namespace) -> int:
|
|
|
51
49
|
return _make.run_make(Path(args.run_dir), args.target)
|
|
52
50
|
|
|
53
51
|
|
|
54
|
-
def _cmd_locker_room_ontologize(args: argparse.Namespace) -> int:
|
|
55
|
-
from blitz_cli import _ontology
|
|
56
52
|
|
|
57
|
-
ignore = [Path(p) for p in getattr(args, "ignore", [])]
|
|
58
|
-
|
|
59
|
-
def once() -> str:
|
|
60
|
-
counts = _ontology.ontologize(
|
|
61
|
-
args.workspace, args.db, ignore=ignore,
|
|
62
|
-
code=args.code, max_file_bytes=args.max_file_bytes,
|
|
63
|
-
)
|
|
64
|
-
return ", ".join(f"{k}={v}" for k, v in sorted(counts.items())) or "empty"
|
|
65
|
-
|
|
66
|
-
if not args.loop:
|
|
67
|
-
print(f"Ontologized {Path(args.workspace).resolve()} -> {args.db} ({once()})")
|
|
68
|
-
return 0
|
|
69
|
-
|
|
70
|
-
# Daemon mode (the graph container): rebuild on an interval forever.
|
|
71
|
-
print(f"ontologize: {Path(args.workspace).resolve()} -> {args.db} every {args.interval}s")
|
|
72
|
-
while True:
|
|
73
|
-
try:
|
|
74
|
-
print(f"ontologize: rebuilt ({once()})", flush=True)
|
|
75
|
-
except Exception as exc: # never let one bad scan kill the loop
|
|
76
|
-
print(f"ontologize: error {exc!r}", flush=True)
|
|
77
|
-
time.sleep(args.interval)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def _cmd_locker_room_watch(args: argparse.Namespace) -> int:
|
|
81
|
-
"""Activity-ingest daemon (the watch container): tail coding-agent session
|
|
82
|
-
transcripts into a local corpus on a loop (currently Claude Code's format)."""
|
|
83
|
-
from blitz_cli import _corpus
|
|
84
53
|
|
|
85
|
-
store = _corpus.TurnStore(args.db)
|
|
86
|
-
print(f"watch: {args.projects_dir} -> {args.db} every {args.interval}s")
|
|
87
|
-
while True:
|
|
88
|
-
try:
|
|
89
|
-
n = _corpus.ingest_once(args.projects_dir, store)
|
|
90
|
-
if n:
|
|
91
|
-
print(f"watch: upserted {n} turns", flush=True)
|
|
92
|
-
except Exception as exc:
|
|
93
|
-
print(f"watch: error {exc!r}", flush=True)
|
|
94
|
-
time.sleep(args.interval)
|
|
95
54
|
|
|
96
55
|
|
|
97
|
-
def _cmd_locker_room_list(args: argparse.Namespace) -> int:
|
|
98
|
-
from blitz_cli import _ontology
|
|
99
56
|
|
|
100
|
-
if not Path(args.db).exists():
|
|
101
|
-
_eprint(f"error: no ontology graph at {args.db}. Run `blitz locker-room ontologize` first.")
|
|
102
|
-
return 2
|
|
103
|
-
repos = _ontology.OntologyStore(args.db, read_only=True).list_repos()
|
|
104
|
-
if args.json:
|
|
105
|
-
print(json.dumps(repos, indent=2))
|
|
106
|
-
return 0
|
|
107
|
-
if not repos:
|
|
108
|
-
print("No playbook-enabled repos in the graph.")
|
|
109
|
-
return 0
|
|
110
|
-
for r in repos:
|
|
111
|
-
feat = f"{r['active_feature']} ({r['active_stage']})" if r.get("active_feature") else "-"
|
|
112
|
-
agents = ",".join(r.get("agents", [])) or "-"
|
|
113
|
-
print(f"{r['name']:<24} agents={agents:<28} active={feat} {r['path']}")
|
|
114
|
-
return 0
|
|
115
57
|
|
|
116
58
|
|
|
117
|
-
def _cmd_locker_room_train_run(args: argparse.Namespace) -> int:
|
|
118
|
-
from blitz_cli import _train
|
|
119
59
|
|
|
120
|
-
return _train.run()
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def _cmd_locker_room_mcp(args: argparse.Namespace) -> int:
|
|
124
|
-
from blitz_cli import _locker_room_mcp
|
|
125
|
-
|
|
126
|
-
return _locker_room_mcp.serve(
|
|
127
|
-
args.db, transport=args.transport, host=args.host, port=args.port
|
|
128
|
-
)
|
|
129
60
|
|
|
130
61
|
|
|
131
62
|
def _cmd_activity(args: argparse.Namespace) -> int:
|
|
@@ -412,15 +343,15 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
412
343
|
|
|
413
344
|
lr = sub.add_parser(
|
|
414
345
|
"locker-room",
|
|
415
|
-
help="
|
|
416
|
-
"
|
|
346
|
+
help="Scaffold and manage a locker-room context node (watcher, ontology "
|
|
347
|
+
"graph, MCP/graph server, trainer) as containers.",
|
|
417
348
|
)
|
|
418
349
|
lr_sub = lr.add_subparsers(dest="locker_room_cmd", required=True)
|
|
419
350
|
|
|
420
351
|
lr_init = lr_sub.add_parser(
|
|
421
352
|
"init",
|
|
422
353
|
help="Scaffold a locker-room project here: a docker-compose that pulls the "
|
|
423
|
-
"
|
|
354
|
+
"prebuilt node images (watch / graph / mcp-web / trainer).",
|
|
424
355
|
)
|
|
425
356
|
lr_init.add_argument(
|
|
426
357
|
"-o", "--out", default="./locker-room", help="Output dir (default ./locker-room)"
|
|
@@ -444,74 +375,6 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
444
375
|
)
|
|
445
376
|
leaf.set_defaults(func=_cmd_locker_room_make, target=target)
|
|
446
377
|
|
|
447
|
-
lr_ont = lr_sub.add_parser(
|
|
448
|
-
"ontologize", help="Scan a workspace of playbook-enabled repos into the ontology graph."
|
|
449
|
-
)
|
|
450
|
-
lr_ont.add_argument("--workspace", default=".", help="Workspace root to scan (default: cwd)")
|
|
451
|
-
lr_ont.add_argument("--db", default="./data/ontology.db", help="Ontology SQLite path")
|
|
452
|
-
lr_ont.add_argument(
|
|
453
|
-
"--ignore", action="append", metavar="PATH", default=[],
|
|
454
|
-
help="Path to skip during discovery (repeatable)",
|
|
455
|
-
)
|
|
456
|
-
lr_ont.add_argument(
|
|
457
|
-
"--no-code", dest="code", action="store_false", default=True,
|
|
458
|
-
help="Skip the code graph (File/Symbol/imports/calls); structural ontology only",
|
|
459
|
-
)
|
|
460
|
-
lr_ont.add_argument(
|
|
461
|
-
"--max-file-bytes", type=int, default=1_000_000,
|
|
462
|
-
help="Skip source files larger than this when building the code graph (default 1MB)",
|
|
463
|
-
)
|
|
464
|
-
lr_ont.add_argument(
|
|
465
|
-
"--loop", action="store_true",
|
|
466
|
-
help="Rebuild forever on --interval (the graph container runs this)",
|
|
467
|
-
)
|
|
468
|
-
lr_ont.add_argument(
|
|
469
|
-
"--interval", type=int, default=300, help="Seconds between rebuilds in --loop mode",
|
|
470
|
-
)
|
|
471
|
-
lr_ont.set_defaults(func=_cmd_locker_room_ontologize)
|
|
472
|
-
|
|
473
|
-
lr_watch = lr_sub.add_parser(
|
|
474
|
-
"watch", help="Ingest coding-agent transcripts into a corpus on a loop (the watch container)."
|
|
475
|
-
)
|
|
476
|
-
lr_watch.add_argument(
|
|
477
|
-
"--projects-dir", default=os.environ.get("CLAUDE_PROJECTS_DIR", str(Path.home() / ".claude" / "projects")),
|
|
478
|
-
help="Agent transcript dir to ingest (default: ~/.claude/projects; env CLAUDE_PROJECTS_DIR)",
|
|
479
|
-
)
|
|
480
|
-
lr_watch.add_argument("--db", default="./data/activity.db", help="Corpus SQLite path")
|
|
481
|
-
lr_watch.add_argument(
|
|
482
|
-
"--interval", type=int, default=int(os.environ.get("WATCH_INTERVAL_SECONDS", "45")),
|
|
483
|
-
help="Seconds between ingests (env WATCH_INTERVAL_SECONDS)",
|
|
484
|
-
)
|
|
485
|
-
lr_watch.set_defaults(func=_cmd_locker_room_watch)
|
|
486
|
-
|
|
487
|
-
lr_train_run = lr_sub.add_parser(
|
|
488
|
-
"train-run",
|
|
489
|
-
help="Run the QLoRA training job in-process (the trainer container's entrypoint; "
|
|
490
|
-
"needs blitz-cli[train] + a GPU).",
|
|
491
|
-
)
|
|
492
|
-
lr_train_run.set_defaults(func=_cmd_locker_room_train_run)
|
|
493
|
-
|
|
494
|
-
lr_list = lr_sub.add_parser("list", help="List playbook-enabled repos from the ontology graph.")
|
|
495
|
-
lr_list.add_argument("--db", default="./data/ontology.db", help="Ontology SQLite path")
|
|
496
|
-
lr_list.add_argument("--json", action="store_true", help="Emit JSON")
|
|
497
|
-
lr_list.set_defaults(func=_cmd_locker_room_list)
|
|
498
|
-
|
|
499
|
-
lr_mcp = lr_sub.add_parser(
|
|
500
|
-
"mcp", help="Serve the ontology graph to agents over MCP (needs blitz-cli[locker-room])."
|
|
501
|
-
)
|
|
502
|
-
lr_mcp.add_argument("--db", default="./data/ontology.db", help="Ontology SQLite path")
|
|
503
|
-
lr_mcp.add_argument(
|
|
504
|
-
"--transport", choices=["stdio", "sse", "http"], default="stdio",
|
|
505
|
-
help="stdio (agent spawns it, default) or sse/http (bind a port so a "
|
|
506
|
-
"container can host it and agents connect over the network)",
|
|
507
|
-
)
|
|
508
|
-
lr_mcp.add_argument(
|
|
509
|
-
"--host", default="127.0.0.1",
|
|
510
|
-
help="Bind host for sse/http (use 0.0.0.0 inside a container)",
|
|
511
|
-
)
|
|
512
|
-
lr_mcp.add_argument("--port", type=int, default=8848, help="Bind port for sse/http")
|
|
513
|
-
lr_mcp.set_defaults(func=_cmd_locker_room_mcp)
|
|
514
|
-
|
|
515
378
|
return parser
|
|
516
379
|
|
|
517
380
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# locker-room
|
|
2
|
+
|
|
3
|
+
A locker-room **context node**: a containerized watcher + ontology graph + MCP/web
|
|
4
|
+
server (+ on-demand trainer), scaffolded by `blitz locker-room init`. This dir
|
|
5
|
+
holds only a `docker-compose.yml` that pulls **prebuilt node images** (`:latest`,
|
|
6
|
+
from `sparepartslabs/blitz-locker-room`). Nothing is built locally. Refresh with
|
|
7
|
+
`blitz locker-room pull`.
|
|
8
|
+
|
|
9
|
+
## Roles (all share `./data`)
|
|
10
|
+
|
|
11
|
+
- **watch** — ingests coding-agent session transcripts into `data/activity.db`.
|
|
12
|
+
- **graph** — rebuilds the ontology of your playbook-enabled repos/huddles/features
|
|
13
|
+
and their code lineage into `data/ontology.db` on a loop. Scans `WORKSPACE_DIR`.
|
|
14
|
+
- **mcp** — serves the ontology to agents over MCP (SSE) and a browser graph view.
|
|
15
|
+
- **train** — on-demand QLoRA trainer (profile `train`, needs a GPU).
|
|
16
|
+
|
|
17
|
+
## Run
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
blitz locker-room pull # pull the node images
|
|
21
|
+
blitz locker-room up # start watch + graph + mcp
|
|
22
|
+
blitz locker-room logs
|
|
23
|
+
blitz locker-room train # on-demand QLoRA (GPU); outputs -> ./train-out
|
|
24
|
+
blitz locker-room down
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Override host paths via env, e.g. `WORKSPACE_DIR=/path/to/code blitz locker-room up`.
|
|
28
|
+
Defaults: `CLAUDE_PROJECTS_DIR=$projects_dir`, `WORKSPACE_DIR=$workspace_dir`.
|
|
29
|
+
|
|
30
|
+
## Use the node
|
|
31
|
+
|
|
32
|
+
- **MCP for agents:** the `mcp` service serves SSE at
|
|
33
|
+
`http://localhost:$${MCP_PORT:-8848}/sse` — add that URL to your agent's MCP config
|
|
34
|
+
(on a VPN / team host, point agents at the node's address instead of localhost).
|
|
35
|
+
- **Browser graph view:** open `http://localhost:$${MCP_PORT:-8848}/graph`.
|
|
36
|
+
|
|
37
|
+
The ontology is built and served entirely by the node; there are no host-side
|
|
38
|
+
`ontologize`/`list`/`mcp` commands — query it through the MCP tools or `/graph`.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
# Generated by `blitz locker-room init`.
|
|
2
|
-
#
|
|
3
|
-
# genuinely-separate image (CUDA/torch base).
|
|
4
|
-
# supported blitz-cli range; `blitz locker-room
|
|
5
|
-
# `blitz locker-room <up|down|logs|pull|train>` or
|
|
6
|
-
# Override the ${VAR:-default} paths via the shell env.
|
|
1
|
+
# Generated by `blitz locker-room init`. This runs a locker-room context node:
|
|
2
|
+
# the watch/graph/mcp roles all run the SAME core image (a baked entrypoint per
|
|
3
|
+
# role); the trainer is the one genuinely-separate image (CUDA/torch base).
|
|
4
|
+
# `:latest` tracks the top of the supported blitz-cli range; `blitz locker-room
|
|
5
|
+
# pull` refreshes it. Manage with `blitz locker-room <up|down|logs|pull|train>` or
|
|
6
|
+
# `docker compose` directly. Override the ${VAR:-default} paths via the shell env.
|
|
7
7
|
name: locker-room
|
|
8
8
|
|
|
9
9
|
x-core: &core
|
|
@@ -11,39 +11,42 @@ x-core: &core
|
|
|
11
11
|
restart: unless-stopped
|
|
12
12
|
|
|
13
13
|
services:
|
|
14
|
-
# Ingest
|
|
14
|
+
# Ingest coding-agent transcripts -> data/activity.db
|
|
15
15
|
watch:
|
|
16
16
|
<<: *core
|
|
17
|
-
command: ["
|
|
18
|
-
"--projects-dir", "/claude-projects",
|
|
19
|
-
"--db", "/workspace/data/activity.db"]
|
|
17
|
+
command: ["python", "/app/watch.py"]
|
|
20
18
|
volumes:
|
|
21
19
|
- "$${CLAUDE_PROJECTS_DIR:-$projects_dir}:/claude-projects:ro"
|
|
22
20
|
- ./data:/workspace/data
|
|
23
21
|
environment:
|
|
22
|
+
PROJECTS_DIR: /claude-projects
|
|
23
|
+
ACTIVITY_DB_PATH: /workspace/data/activity.db
|
|
24
24
|
WATCH_INTERVAL_SECONDS: "$${WATCH_INTERVAL_SECONDS:-$interval}"
|
|
25
25
|
|
|
26
26
|
# Rebuild the ontology (repos/huddles/features + code lineage) on a loop.
|
|
27
27
|
graph:
|
|
28
28
|
<<: *core
|
|
29
|
-
command: ["
|
|
30
|
-
"--workspace", "/repos",
|
|
31
|
-
"--db", "/workspace/data/ontology.db",
|
|
32
|
-
"--interval", "$${ONTOLOGIZE_INTERVAL_SECONDS:-300}"]
|
|
29
|
+
command: ["python", "/app/ontologize.py"]
|
|
33
30
|
volumes:
|
|
34
31
|
- "$${WORKSPACE_DIR:-$workspace_dir}:/repos:ro"
|
|
35
32
|
- ./data:/workspace/data
|
|
33
|
+
environment:
|
|
34
|
+
SCAN_DIR: /repos
|
|
35
|
+
ONTOLOGY_DB_PATH: /workspace/data/ontology.db
|
|
36
|
+
ONTOLOGIZE_INTERVAL_SECONDS: "$${ONTOLOGIZE_INTERVAL_SECONDS:-300}"
|
|
36
37
|
|
|
37
|
-
# Serve the ontology to agents over SSE.
|
|
38
|
+
# Serve the ontology to agents over MCP (SSE) + a /graph web view.
|
|
38
39
|
mcp:
|
|
39
40
|
<<: *core
|
|
40
|
-
command: ["
|
|
41
|
-
"--transport", "sse", "--host", "0.0.0.0", "--port", "8848",
|
|
42
|
-
"--db", "/workspace/data/ontology.db"]
|
|
41
|
+
command: ["python", "/app/server.py"]
|
|
43
42
|
ports:
|
|
44
43
|
- "$${MCP_PORT:-8848}:8848"
|
|
45
44
|
volumes:
|
|
46
45
|
- ./data:/workspace/data:ro
|
|
46
|
+
environment:
|
|
47
|
+
ONTOLOGY_DB_PATH: /workspace/data/ontology.db
|
|
48
|
+
MCP_HOST: 0.0.0.0
|
|
49
|
+
MCP_PORT: 8848
|
|
47
50
|
|
|
48
51
|
# On-demand (profile "train"): `docker compose run --rm train` / `make train`.
|
|
49
52
|
train:
|
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "blitz-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.8.0"
|
|
4
4
|
description = "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
|
readme = "README.md"
|
|
6
6
|
license = { text = "MIT" }
|
|
7
7
|
requires-python = ">=3.9"
|
|
8
8
|
# `rich` (the `blitz activity` session viewer) is the only runtime dependency for
|
|
9
|
-
# the core CLI; everything else uses the stdlib (
|
|
10
|
-
# importlib.resources). The
|
|
11
|
-
#
|
|
9
|
+
# the core CLI; everything else uses the stdlib (sqlite3, string.Template,
|
|
10
|
+
# importlib.resources). The ontology engine here is a plain-SQLite library the
|
|
11
|
+
# locker-room node imports; the node (blitz-locker-room images) brings the server
|
|
12
|
+
# deps (mcp). The trainer's heavy ML deps are the optional [train] extra below.
|
|
12
13
|
dependencies = ["rich>=13"]
|
|
13
14
|
|
|
14
|
-
# The locker-room
|
|
15
|
-
# package. It's optional so the core CLI stays dep-light — the ontology graph
|
|
16
|
-
# itself is plain SQLite (stdlib). Install with: pip install 'blitz-cli[locker-room]'.
|
|
17
|
-
[project.optional-dependencies]
|
|
18
|
-
locker-room = ["mcp>=1.0"]
|
|
19
|
-
# The locker-room trainer (`blitz locker-room train-run`, run inside the trainer
|
|
15
|
+
# The locker-room trainer library (blitz_cli._train.run, run inside the trainer
|
|
20
16
|
# image). torch is intentionally omitted -- the CUDA base image ships the matching
|
|
21
17
|
# build, and reinstalling it via pip risks a CPU-only/wrong-arch wheel.
|
|
18
|
+
[project.optional-dependencies]
|
|
22
19
|
train = [
|
|
23
20
|
"transformers==4.48.0",
|
|
24
21
|
"trl==0.13.0",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"""Argparse-shape tests: these don't exercise command behavior (that's
|
|
2
2
|
covered per-module elsewhere), just that `build_parser()` wires tokens to the
|
|
3
|
-
right handler — the `locker-room init` scaffolder and the `locker-room`
|
|
4
|
-
|
|
3
|
+
right handler — the `locker-room init` scaffolder and the `locker-room`
|
|
4
|
+
container-lifecycle make-passthroughs. (The runtime commands moved to the
|
|
5
|
+
locker-room node images; the CLI is static commands only.)"""
|
|
5
6
|
|
|
6
7
|
from blitz_cli import cli
|
|
7
8
|
|
|
@@ -42,25 +43,10 @@ def test_locker_room_make_verbs_resolve_to_the_make_passthrough():
|
|
|
42
43
|
assert logs.run_dir == "./x"
|
|
43
44
|
|
|
44
45
|
|
|
45
|
-
def
|
|
46
|
+
def test_runtime_commands_are_not_in_the_cli():
|
|
47
|
+
# The node runs watch/ontologize/mcp; the CLI must not expose them.
|
|
46
48
|
parser = cli.build_parser()
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
assert ont.loop is False
|
|
52
|
-
|
|
53
|
-
watch = parser.parse_args(["locker-room", "watch"])
|
|
54
|
-
assert watch.func is cli._cmd_locker_room_watch
|
|
55
|
-
|
|
56
|
-
lst = parser.parse_args(["locker-room", "list", "--json"])
|
|
57
|
-
assert lst.func is cli._cmd_locker_room_list
|
|
58
|
-
assert lst.json is True
|
|
59
|
-
|
|
60
|
-
mcp = parser.parse_args(["locker-room", "mcp"])
|
|
61
|
-
assert mcp.func is cli._cmd_locker_room_mcp
|
|
62
|
-
assert mcp.transport == "stdio" # stdio by default; sse/http for the container
|
|
63
|
-
|
|
64
|
-
mcp_sse = parser.parse_args(["locker-room", "mcp", "--transport", "sse", "--port", "9000"])
|
|
65
|
-
assert mcp_sse.transport == "sse"
|
|
66
|
-
assert mcp_sse.port == 9000
|
|
49
|
+
import pytest
|
|
50
|
+
for verb in ("ontologize", "watch", "mcp", "train-run", "list"):
|
|
51
|
+
with pytest.raises(SystemExit):
|
|
52
|
+
parser.parse_args(["locker-room", verb])
|
|
@@ -110,13 +110,14 @@ def test_render_locker_room_compose_pulls_latest_and_shares_core(tmp_path):
|
|
|
110
110
|
compose = (out / "docker-compose.yml").read_text()
|
|
111
111
|
|
|
112
112
|
# watch/graph/mcp all run the one core image (shared via a YAML anchor) at
|
|
113
|
-
# :latest (top of the supported blitz-cli range);
|
|
113
|
+
# :latest (top of the supported blitz-cli range); each runs a baked node
|
|
114
|
+
# entrypoint (the runtime lives in the images, not the CLI)
|
|
114
115
|
assert "ghcr.io/sparepartslabs/blitz-locker-room/core:latest" in compose
|
|
115
116
|
assert compose.count("<<: *core") == 3
|
|
116
117
|
assert "ghcr.io/sparepartslabs/blitz-locker-room/train:latest" in compose
|
|
117
|
-
assert '"
|
|
118
|
-
assert '"
|
|
119
|
-
assert '"
|
|
118
|
+
assert '"python", "/app/watch.py"' in compose
|
|
119
|
+
assert '"python", "/app/ontologize.py"' in compose
|
|
120
|
+
assert '"python", "/app/server.py"' in compose
|
|
120
121
|
# trainer is opt-in via a compose profile
|
|
121
122
|
assert 'profiles: ["train"]' in compose
|
|
122
123
|
# substitutions resolved; no raw template vars leak through
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
"""stdio MCP server exposing the locker-room ontology graph to agentic coders.
|
|
2
|
-
|
|
3
|
-
Run via ``blitz locker-room mcp --db ./data/ontology.db``. Agents add it to their
|
|
4
|
-
MCP config (e.g. ``{"command": "blitz", "args": ["locker-room", "mcp"]}``) and get
|
|
5
|
-
cheap read access to the ontology of playbook-enabled repos, huddles, and
|
|
6
|
-
playbooks. The ``mcp`` package is an optional dependency (``pip install
|
|
7
|
-
blitz-cli[locker-room]``); it is imported lazily so the core CLI stays dep-light.
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
from __future__ import annotations
|
|
11
|
-
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
|
|
14
|
-
_MISSING_MCP = (
|
|
15
|
-
"The MCP server needs the optional 'mcp' dependency.\n"
|
|
16
|
-
"Install it with: pip install 'blitz-cli[locker-room]'"
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
# CLI transport name -> FastMCP transport. "http" is the modern streamable-HTTP.
|
|
21
|
-
_TRANSPORTS = {"stdio": "stdio", "sse": "sse", "http": "streamable-http"}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def serve(db_path: str, transport: str = "stdio", host: str = "127.0.0.1", port: int = 8848) -> int:
|
|
25
|
-
"""Serve the ontology graph at ``db_path`` over MCP.
|
|
26
|
-
|
|
27
|
-
``stdio`` (default) is for an agent that spawns the process locally; ``sse``/
|
|
28
|
-
``http`` bind ``host``:``port`` so a container can host the server and agents
|
|
29
|
-
connect over the network (e.g. the scaffolded `make mcp`)."""
|
|
30
|
-
import sys
|
|
31
|
-
|
|
32
|
-
try:
|
|
33
|
-
from mcp.server.fastmcp import FastMCP
|
|
34
|
-
except ImportError:
|
|
35
|
-
print(_MISSING_MCP, file=sys.stderr)
|
|
36
|
-
return 2
|
|
37
|
-
|
|
38
|
-
from blitz_cli._ontology import OntologyStore
|
|
39
|
-
|
|
40
|
-
db = Path(db_path)
|
|
41
|
-
if not db.exists():
|
|
42
|
-
print(
|
|
43
|
-
f"error: no ontology graph at {db}. Run `blitz locker-room ontologize` first.",
|
|
44
|
-
file=sys.stderr,
|
|
45
|
-
)
|
|
46
|
-
return 2
|
|
47
|
-
|
|
48
|
-
mcp = FastMCP("blitz-locker-room", host=host, port=port)
|
|
49
|
-
|
|
50
|
-
def _store() -> OntologyStore:
|
|
51
|
-
# Open read-only per call — cheap, and safe against the periodic rebuild.
|
|
52
|
-
return OntologyStore(db, read_only=True)
|
|
53
|
-
|
|
54
|
-
@mcp.tool()
|
|
55
|
-
def list_workspaces() -> list[dict]:
|
|
56
|
-
"""List the playbook-enabled workspaces in the ontology."""
|
|
57
|
-
return _store().list_workspaces()
|
|
58
|
-
|
|
59
|
-
@mcp.tool()
|
|
60
|
-
def list_repos() -> list[dict]:
|
|
61
|
-
"""List playbook-enabled repos with their active feature and stage."""
|
|
62
|
-
return _store().list_repos()
|
|
63
|
-
|
|
64
|
-
@mcp.tool()
|
|
65
|
-
def get_repo(repo: str) -> dict | None:
|
|
66
|
-
"""Get one repo (by node id or filesystem path): agents, playbooks, features."""
|
|
67
|
-
return _store().get_repo(repo)
|
|
68
|
-
|
|
69
|
-
@mcp.tool()
|
|
70
|
-
def list_huddles() -> list[dict]:
|
|
71
|
-
"""List cross-repo huddles and which repos each coordinates."""
|
|
72
|
-
return _store().list_huddles()
|
|
73
|
-
|
|
74
|
-
@mcp.tool()
|
|
75
|
-
def get_huddle(huddle: str) -> dict | None:
|
|
76
|
-
"""Get one huddle (by node id): title, status, coordinated repos + roles."""
|
|
77
|
-
return _store().get_huddle(huddle)
|
|
78
|
-
|
|
79
|
-
@mcp.tool()
|
|
80
|
-
def get_playbooks(repo: str | None = None) -> list[dict]:
|
|
81
|
-
"""List playbooks (slash-commands); pass a repo to scope to that repo."""
|
|
82
|
-
return _store().get_playbooks(repo)
|
|
83
|
-
|
|
84
|
-
@mcp.tool()
|
|
85
|
-
def neighbors(node_id: str, rel: str | None = None, incoming: bool = False) -> list[dict]:
|
|
86
|
-
"""Generic graph traversal: nodes adjacent to ``node_id`` (optionally by relation)."""
|
|
87
|
-
return _store().neighbors(node_id, rel=rel, incoming=incoming)
|
|
88
|
-
|
|
89
|
-
@mcp.tool()
|
|
90
|
-
def get_lineage(feature: str, depth: int = 3) -> dict:
|
|
91
|
-
"""Code lineage of a spec/feature (by id or slug): the files/symbols it
|
|
92
|
-
touches plus the transitive CALLS/IMPORTS closure of that code."""
|
|
93
|
-
return _store().lineage(feature, max_depth=depth)
|
|
94
|
-
|
|
95
|
-
@mcp.tool()
|
|
96
|
-
def impact_of(node: str, depth: int = 3) -> dict:
|
|
97
|
-
"""Reverse lineage of a file or symbol (by id or path): what transitively
|
|
98
|
-
depends on it, and which features touch it."""
|
|
99
|
-
return _store().impact(node, max_depth=depth)
|
|
100
|
-
|
|
101
|
-
@mcp.tool()
|
|
102
|
-
def get_file(path: str) -> dict | None:
|
|
103
|
-
"""Get a File node by id or filesystem path."""
|
|
104
|
-
return _store().get_file(path)
|
|
105
|
-
|
|
106
|
-
@mcp.tool()
|
|
107
|
-
def get_symbol(symbol_id: str) -> dict | None:
|
|
108
|
-
"""Get a Symbol node (function/class/method) by id."""
|
|
109
|
-
return _store().get_symbol(symbol_id)
|
|
110
|
-
|
|
111
|
-
if transport != "stdio":
|
|
112
|
-
print(
|
|
113
|
-
f"blitz locker-room mcp: serving {transport} on {host}:{port} (db {db})",
|
|
114
|
-
file=sys.stderr,
|
|
115
|
-
)
|
|
116
|
-
mcp.run(transport=_TRANSPORTS[transport])
|
|
117
|
-
return 0
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# locker-room
|
|
2
|
-
|
|
3
|
-
Composable, containerized watcher + trainer + ontology-graph/MCP stack, scaffolded
|
|
4
|
-
by `blitz locker-room init`. This dir holds only a `docker-compose.yml` that pulls
|
|
5
|
-
**prebuilt images** (`:latest`, from `sparepartslabs/blitz-locker-room`, which
|
|
6
|
-
ship the newest blitz-cli in their supported range). Nothing is built locally.
|
|
7
|
-
Refresh with `blitz locker-room pull`.
|
|
8
|
-
|
|
9
|
-
## Pieces (all share `./data`)
|
|
10
|
-
|
|
11
|
-
- **watch** — ingests Claude Code session transcripts (ALL projects) into
|
|
12
|
-
`data/activity.db`.
|
|
13
|
-
- **graph** — rebuilds the ontology of your playbook-enabled repos/huddles/features
|
|
14
|
-
and their code lineage into `data/ontology.db` on a loop. Scans `WORKSPACE_DIR`.
|
|
15
|
-
- **mcp** — serves the ontology to agents over SSE at `http://localhost:$${MCP_PORT:-8848}/sse`.
|
|
16
|
-
- **train** — on-demand QLoRA trainer (profile `train`, needs a GPU).
|
|
17
|
-
|
|
18
|
-
## Run
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
blitz locker-room pull # pull the pinned images
|
|
22
|
-
blitz locker-room up # start watch + graph + mcp
|
|
23
|
-
blitz locker-room logs
|
|
24
|
-
blitz locker-room train # on-demand QLoRA (GPU); outputs -> ./train-out
|
|
25
|
-
blitz locker-room down
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Override host paths via env, e.g. `WORKSPACE_DIR=/path/to/code blitz locker-room up`.
|
|
29
|
-
Defaults: `CLAUDE_PROJECTS_DIR=$projects_dir`, `WORKSPACE_DIR=$workspace_dir`.
|
|
30
|
-
|
|
31
|
-
## Point your agent at the ontology MCP
|
|
32
|
-
|
|
33
|
-
- **Networked (container):** the `mcp` service serves SSE at
|
|
34
|
-
`http://localhost:$${MCP_PORT:-8848}/sse` — add that URL to your agent's MCP config.
|
|
35
|
-
- **Local (no container):** `blitz locker-room mcp` speaks stdio; add
|
|
36
|
-
`{"command": "blitz", "args": ["locker-room", "mcp"]}`.
|
|
37
|
-
|
|
38
|
-
You can also drive the graph host-side without containers:
|
|
39
|
-
`blitz locker-room ontologize` then `blitz locker-room list`.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/scaffold/.playbooks/memory/playbook.md
RENAMED
|
File without changes
|
|
File without changes
|
{blitz_cli-0.7.0 → blitz_cli-0.8.0}/blitz_cli/playbooks/scaffold/.playbooks/scripts/bash/common.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|