livespec 0.24.0__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 (53) hide show
  1. livespec-0.24.0.dist-info/METADATA +703 -0
  2. livespec-0.24.0.dist-info/RECORD +53 -0
  3. livespec-0.24.0.dist-info/WHEEL +4 -0
  4. livespec-0.24.0.dist-info/entry_points.txt +3 -0
  5. livespec_mcp/__init__.py +22 -0
  6. livespec_mcp/cli.py +185 -0
  7. livespec_mcp/config.py +377 -0
  8. livespec_mcp/domain/__init__.py +0 -0
  9. livespec_mcp/domain/extractors.py +1945 -0
  10. livespec_mcp/domain/graph.py +242 -0
  11. livespec_mcp/domain/indexer.py +708 -0
  12. livespec_mcp/domain/languages.py +72 -0
  13. livespec_mcp/domain/matcher.py +222 -0
  14. livespec_mcp/domain/md_specs.py +455 -0
  15. livespec_mcp/domain/openspec_changes.py +311 -0
  16. livespec_mcp/domain/openspec_discover.py +80 -0
  17. livespec_mcp/domain/openspec_export.py +212 -0
  18. livespec_mcp/domain/openspec_validate.py +199 -0
  19. livespec_mcp/domain/rag.py +660 -0
  20. livespec_mcp/domain/specs_sync.py +428 -0
  21. livespec_mcp/domain/watcher.py +188 -0
  22. livespec_mcp/error_middleware.py +73 -0
  23. livespec_mcp/explorer/__init__.py +23 -0
  24. livespec_mcp/explorer/asgi.py +162 -0
  25. livespec_mcp/explorer/autowire.py +105 -0
  26. livespec_mcp/explorer/fastapi.py +105 -0
  27. livespec_mcp/explorer/install.py +147 -0
  28. livespec_mcp/instrumentation.py +174 -0
  29. livespec_mcp/plugin_visibility.py +153 -0
  30. livespec_mcp/prompts.py +162 -0
  31. livespec_mcp/resources.py +226 -0
  32. livespec_mcp/server.py +59 -0
  33. livespec_mcp/state.py +252 -0
  34. livespec_mcp/storage/__init__.py +0 -0
  35. livespec_mcp/storage/db.py +597 -0
  36. livespec_mcp/storage/schema.sql +349 -0
  37. livespec_mcp/storage/trends.py +110 -0
  38. livespec_mcp/templates/AGENT_PLAYBOOK.md +321 -0
  39. livespec_mcp/templates/fastapi/SESSION_PROMPT.md +20 -0
  40. livespec_mcp/templates/fastapi/cursor/rules/livespec-fastapi.mdc +44 -0
  41. livespec_mcp/templates/fastapi/cursor/skills/livespec-fastapi/SKILL.md +63 -0
  42. livespec_mcp/tools/__init__.py +0 -0
  43. livespec_mcp/tools/_errors.py +31 -0
  44. livespec_mcp/tools/analysis.py +3718 -0
  45. livespec_mcp/tools/docs.py +384 -0
  46. livespec_mcp/tools/explorer.py +2678 -0
  47. livespec_mcp/tools/indexing.py +227 -0
  48. livespec_mcp/tools/plugins/__init__.py +189 -0
  49. livespec_mcp/tools/plugins/docs.py +24 -0
  50. livespec_mcp/tools/plugins/spec.py +33 -0
  51. livespec_mcp/tools/search.py +88 -0
  52. livespec_mcp/tools/specs.py +1488 -0
  53. livespec_mcp/workspace_param.py +57 -0
@@ -0,0 +1,703 @@
1
+ Metadata-Version: 2.4
2
+ Name: livespec
3
+ Version: 0.24.0
4
+ Summary: Code intelligence for AI agents: call graph, impact analysis, and bidirectional Spec <-> code traceability
5
+ Author-email: Juan Pablo Diaz <juanpablo516@gmail.com>
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: fastmcp<4,>=3
9
+ Requires-Dist: networkx>=3.2
10
+ Requires-Dist: pathspec>=0.12
11
+ Requires-Dist: pydantic>=2.7
12
+ Requires-Dist: tomli>=2; python_full_version < '3.11'
13
+ Requires-Dist: tree-sitter-language-pack<1.6.3,>=0.7
14
+ Requires-Dist: tree-sitter>=0.25
15
+ Requires-Dist: watchdog>=4.0
16
+ Requires-Dist: xxhash>=3.4
17
+ Provides-Extra: dev
18
+ Requires-Dist: hypothesis>=6.100; extra == 'dev'
19
+ Requires-Dist: psutil>=5.9; extra == 'dev'
20
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
21
+ Requires-Dist: pytest>=8.0; extra == 'dev'
22
+ Requires-Dist: ruff>=0.6; extra == 'dev'
23
+ Provides-Extra: embeddings
24
+ Requires-Dist: fastembed>=0.4; extra == 'embeddings'
25
+ Requires-Dist: sqlite-vec>=0.1.6; extra == 'embeddings'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # livespec
29
+
30
+ **Code intelligence for AI agents** — call graph, impact analysis, and
31
+ bidirectional **Spec ↔ code** traceability (functional requirements, ADRs,
32
+ NFRs, and other spec kinds). Local-first, zero external services.
33
+
34
+ Ships as a **Claude Code plugin** bundling three things: the **MCP server**
35
+ (the tools), a specialized **subagent**, and a preloaded **Skill** (the
36
+ operating manual). Everything an agent sees — the plugin, subagent, Skill, and
37
+ MCP tool namespace — is `livespec`. The MCP server is still distributed as the
38
+ `livespec-mcp` package (`uvx livespec-mcp` / `pip install livespec-mcp`); that
39
+ package/command name is unchanged.
40
+
41
+ Battle-tested on real codebases. Four releases of compounding wins
42
+ on the same Django 5.1.4 queries:
43
+
44
+ | Tool on Django (40K symbols) | v0.8 | v0.9 | v0.10 | v0.14 |
45
+ |---|---:|---:|---:|---:|
46
+ | `find_dead_code` candidates | 824 | 514 | 348 | **344** (−58% cumulative) |
47
+ | `find_endpoints(framework='django')` | 20 | **162** (+8×) | 162 | 162 |
48
+ | `quick_orient` p95 | ~60 ms | ~60 ms | ~60 ms | ~60 ms |
49
+ | Partial reindex (touch 1 file, Django) | — | ~7 s | — | **1.4 s** |
50
+
51
+ Validated across 5 distinct agent profiles (exploration, refactor,
52
+ Spec flow, Django bugfix, TypeScript feature) — see
53
+ [`docs/AGENT_USAGE_DATA.md`](docs/AGENT_USAGE_DATA.md).
54
+
55
+ > Want the agentic flow without reading further?
56
+ > - **MCP prompt `agent_playbook`** — how to use tools *and* annotate code (`@spec:`).
57
+ > - [`docs/AGENT_QUICKSTART.md`](docs/AGENT_QUICKSTART.md) — 10-step cold-open flow.
58
+ > - [`docs/AGENT_PLAYBOOK.md`](docs/AGENT_PLAYBOOK.md) — same content as the prompt.
59
+
60
+ ## 30-second tour
61
+
62
+ ```bash
63
+ # Wire as an MCP server next to your editor (claude.ai/code, Cursor, ...).
64
+ # Every tool call carries workspace="/abs/path" — one server, N repos.
65
+ livespec-mcp
66
+ ```
67
+
68
+ ```jsonc
69
+ // First call: cold-index the workspace once
70
+ > index_project()
71
+ { "files_total": 2898, "symbols_total": 39789, "edges_total": 465179,
72
+ "languages": {"python": 2786, "javascript": 112}, "watcher_started": false }
73
+
74
+ // Composite first-contact on an unfamiliar symbol
75
+ > quick_orient(qname="django.contrib.auth.middleware.AuthenticationMiddleware.process_request")
76
+ { "kind": "method", "is_entry_point": false,
77
+ "callers_count": 56, "callees_count": 3,
78
+ "top_callees": [
79
+ {"qualified_name": "django.contrib.auth.middleware.get_user", "pagerank": 0.000024},
80
+ {"qualified_name": "django.utils.functional.SimpleLazyObject", "pagerank": 0.000209},
81
+ {"qualified_name": "django.core.exceptions.ImproperlyConfigured", "pagerank": 0.000872}
82
+ ],
83
+ "specs": [] }
84
+
85
+ // Wider blast radius on a Spec-active codebase
86
+ > analyze_impact(target_type="spec", target="SPEC-042")
87
+ { "spec_id": "SPEC-042", "implementing_symbols": [...],
88
+ "dependent_specs": ["SPEC-088", "SPEC-091"],
89
+ "impacted_callers": [...] }
90
+ ```
91
+
92
+ Built for the questions an agent asks on an unfamiliar codebase:
93
+
94
+ - ¿Qué código implementa el SPEC-042?
95
+ - Si modifico `auth.verify`, ¿qué Specs y qué llamadores se ven afectados?
96
+ - ¿Qué módulos no tienen ningún Spec asociado?
97
+ - ¿Qué Specs dependen de SPEC-042 transitivamente?
98
+
99
+ Spec traceability is the differentiator. Most code-intel tools stop at "what
100
+ calls this function?". livespec layers Spec ↔ code links (functional
101
+ requirements, ADRs, NFRs, and other kinds) on top so an agent on a
102
+ serious-software-shop codebase can answer *"changing this function affects
103
+ SPEC-042, SPEC-088 and 3 dependent Specs"* in one round-trip. Spec agentic
104
+ tools ship in the default surface; Spec mutation/management tools live in
105
+ the `livespec-spec` plugin. Plugins register at boot (multi-tenant: every
106
+ `workspace=` has its own DB), but **`PluginVisibilityMiddleware`** hides
107
+ mutation/doc tools from `tools/list` until that workspace has `spec`/`doc`
108
+ rows — or you set `LIVESPEC_PLUGINS=spec` / `=all` in MCP config.
109
+
110
+ ### What "living" actually means here
111
+
112
+ | Layer | Lives | How |
113
+ |---|---|---|
114
+ | Symbol index | ✅ | xxh3 content-hash incremental, run `index_project` on demand |
115
+ | Call graph + edges | ✅ | re-resolved on every change; persistent `symbol_ref` |
116
+ | Spec ↔ code links | ✅ | auto-scan of `@spec:` annotations after every `index_project` |
117
+ | Spec ↔ Spec graph | ✅ | explicit, cycle-checked; `link_spec_dependency` (plugin) |
118
+ | Drift detection | ✅ | body_hash + signature_hash on every symbol; `list_docs(only_stale=True)` (plugin) |
119
+ | **Generated docs content** | ❌ on-demand | `generate_docs` (plugin) needs an LLM-capable caller or an MCP host that supports sampling. Drift is *detected*, not *fixed*. |
120
+
121
+ So: traceability is live, docs are not. If your workflow is "give me an
122
+ agent that always knows which code implements which spec, and which
123
+ tests probably break when X changes" — this is exactly what the project is
124
+ good at. If you wanted "writes my doc comments while I sleep" — not yet.
125
+
126
+ ## Stack
127
+
128
+ - **FastMCP 2.14** (stdio transport)
129
+ - **SQLite** (single `docs.db` file, ACID, WAL, explicit migration framework)
130
+ - **tree-sitter + tree-sitter-language-pack** for multi-language parsing
131
+ - **Python `ast`** for high-precision Python extraction
132
+ - **NetworkX** for call graph and topological impact analysis (cached per
133
+ index run)
134
+
135
+ 100% local, zero external services, zero API keys required.
136
+
137
+ ## Language support
138
+
139
+ Honest table — only languages with a passing test suite are claimed.
140
+
141
+ | Language | Status | What's covered |
142
+ |----------|--------|----------------|
143
+ | **Python** | ✅ Tested | Functions, classes, methods, decorators, calls — uses `ast` for full precision. Imports drive scoped resolution (P0.4). |
144
+ | **Go** | ✅ Tested | Functions, struct types via `type_spec`, struct methods, calls. **Scoped resolution** via `import` + alias (P1.A2 v0.4). |
145
+ | **Java** | ✅ Tested | Classes, methods, calls (`method_invocation`) |
146
+ | **JavaScript** | ✅ Tested | Function declarations, **arrow functions** assigned to const/let, classes, methods. **Scoped resolution** via ES6 `import` and CommonJS `require` (P1.A1 v0.4). |
147
+ | **TypeScript** | ✅ Tested | Same as JS plus typed signatures (`.ts` and `.tsx`). **Scoped resolution** via ES6 `import` (P1.A1 v0.4). |
148
+ | **Rust** | ✅ Tested | Free functions, struct/enum types, **`impl` block methods** as `Type::method`, traits. **Scoped resolution** via `use` declarations (P4.A3 v0.5). |
149
+ | **Ruby** | ✅ Tested | `def`, `class`, `module`, `singleton_method`, calls. Best-effort scoped resolution via `require_relative` + receiver field (P1.A4 v0.4). |
150
+ | **PHP** | ✅ Tested | Classes, methods, function/method/scoped call expressions. Best-effort scoped resolution via `use Namespace\X` for `Class::method()` (P1.A4 v0.4); instance-method calls are not scoped. |
151
+ | C, C++, C#, Kotlin, Swift, Scala | ⚠️ Untested | The generic tree-sitter extractor will *attempt* to parse these (they're listed in `EXT_LANGUAGE`) but no test suite covers them. Symbol coverage may be partial — open an issue with a fixture if you need a specific language hardened. |
152
+
153
+ The extractor is a heuristic over hardcoded tree-sitter node types
154
+ (`_DEF_NODE_TYPES`, `_CALL_NODE_TYPES` in `extractors.py`); it intentionally
155
+ trades completeness for simplicity. Use the per-language tests in
156
+ `tests/test_extractors.py` as the contract.
157
+
158
+ ## Install
159
+
160
+ ```bash
161
+ uv venv --python 3.12
162
+ uv pip install -e ".[dev]"
163
+ ```
164
+
165
+ ## Run as MCP server
166
+
167
+ ```bash
168
+ livespec-mcp # stdio MCP server (same as `livespec-mcp serve`)
169
+ livespec # same command — `livespec` is an alias of `livespec-mcp`
170
+ ```
171
+
172
+ > The **product** is `livespec`; the **package/command** stays `livespec-mcp`
173
+ > (`pip install livespec-mcp`, `uvx livespec-mcp`) for back-compat. After a
174
+ > local install both `livespec` and `livespec-mcp` invoke the same entry point.
175
+
176
+ Every tool call requires `workspace="/abs/path"` (no cwd or env fallback
177
+ since v0.12). Persistent state lives in `<workspace>/.mcp-docs/docs.db`.
178
+
179
+ ### Headless CLI (v0.14)
180
+
181
+ The same indexing pipeline without an MCP host — for cron, systemd
182
+ timers, pre-commit hooks, CI:
183
+
184
+ ```bash
185
+ livespec-mcp index /path/to/repo [--force] [--embed] # JSON stats to stdout
186
+ livespec-mcp status /path/to/repo # index status JSON
187
+ ```
188
+
189
+ ### Claude Code / Cursor wiring
190
+
191
+ ```json
192
+ {
193
+ "mcpServers": {
194
+ "livespec": {
195
+ "command": "uv",
196
+ "args": ["--directory", "/path/to/livespec", "run", "livespec-mcp"]
197
+ }
198
+ }
199
+ }
200
+ ```
201
+
202
+ **Multi-repo:** pass `workspace="/abs/path/to/project"` on **every** tool call (required).
203
+ No `LIVESPEC_WORKSPACE` — switching repos is only a different `workspace=` value.
204
+ The server caches up to 8 workspaces (LRU); no MCP restart.
205
+
206
+ ### Keep the index fresh (Claude Code hook)
207
+
208
+ The watcher (`index_project(watch=True)`) works but is a race trap when
209
+ multiple agents write concurrently. For single-user Claude Code sessions
210
+ a `PostToolUse` hook is simpler and exact — re-index incrementally after
211
+ every file edit (hash-skip makes no-op runs cheap):
212
+
213
+ ```json
214
+ {
215
+ "hooks": {
216
+ "PostToolUse": [
217
+ {
218
+ "matcher": "Edit|Write|NotebookEdit",
219
+ "hooks": [
220
+ {
221
+ "type": "command",
222
+ "command": "livespec-mcp index \"$CLAUDE_PROJECT_DIR\" >/dev/null 2>&1 &"
223
+ }
224
+ ]
225
+ }
226
+ ]
227
+ }
228
+ }
229
+ ```
230
+
231
+ The trailing `&` keeps the hook non-blocking; the next tool call sees a
232
+ fresh index.
233
+
234
+ ### FastAPI integration
235
+
236
+ Three steps to serve the Spec Explorer from your API — no manual wiring unless
237
+ you disable autowire:
238
+
239
+ 1. **Install** livespec-mcp in the same environment as your app
240
+ (`pip install livespec-mcp` or `uv add livespec-mcp`).
241
+
242
+ 2. **Index once** (MCP tool or CLI). If the repo has `app = FastAPI(...)` in
243
+ `main.py` or `app.py`, `index_project` auto-builds `.mcp-docs/explorer/`
244
+ and appends `mount_explorer(app)` when `[explorer] auto_mount = true`
245
+ (default in `.livespec.toml`).
246
+
247
+ 3. **Open** `http://localhost:<port>/explorer/` — the Overview tab shows
248
+ spec status, coverage trend, and navigation into API / Changes /
249
+ Coverage gaps. For a quick try without your app:
250
+
251
+ ```bash
252
+ livespec-mcp index /path/to/your/repo
253
+ livespec-mcp explorer serve /path/to/your/repo
254
+ # → http://127.0.0.1:8765/explorer/
255
+ ```
256
+
257
+ Set `[explorer] auto_mount = false` in `.livespec.toml` if you prefer runtime mount:
258
+
259
+ ```python
260
+ from livespec_mcp.explorer import enable_explorer
261
+ enable_explorer(app) # no main.py patch
262
+ ```
263
+
264
+ The API tab **Try it** sends `fetch` to your base URL (CORS must allow the Explorer origin).
265
+
266
+ ### One-shot install (rule + skill + index + autowire)
267
+
268
+ ```bash
269
+ livespec-mcp fastapi init /path/to/your/fastapi-repo
270
+ ```
271
+
272
+ Writes:
273
+
274
+ | Path | Purpose |
275
+ |------|---------|
276
+ | `.livespec.toml` | `[explorer]` defaults |
277
+ | `.mcp-docs/explorer/` | Spec Explorer bundle |
278
+ | `.cursor/rules/livespec-fastapi.mdc` | Agent rule (FastAPI globs) |
279
+ | `.cursor/skills/livespec-fastapi/SKILL.md` | Session workflow skill |
280
+ | `.livespec/SESSION_PROMPT.md` | Copy-paste chat opener |
281
+
282
+ Appends `mount_explorer(app, prefix="/explorer")` to `main.py`/`app.py` when found.
283
+ Flags: `--no-index`, `--no-wire`, `--no-cursor`.
284
+
285
+ ## Workflows — livespec + OpenSpec
286
+
287
+ [OpenSpec](https://github.com/Fission-AI/OpenSpec) is a spec-driven-development
288
+ **framework**: you author the intent (requirements + scenarios) in an
289
+ `openspec/` tree before writing code. **livespec is the code-graph and
290
+ traceability layer beneath it** — it does not replace OpenSpec authoring; it
291
+ links those specs to the code that implements them and keeps the link live.
292
+ Since v0.22 livespec reads *and* writes the OpenSpec format (round-trip).
293
+
294
+ **The pieces you invoke** (Claude Code plugin):
295
+
296
+ | Invocation | What it is | When |
297
+ |---|---|---|
298
+ | `/livespec-onboard <path>` | slash command → delegates to the subagent (cold open) | start on any repo |
299
+ | **`livespec`** subagent | specialized agent, preloads the Skill | heavy exploration / spec work |
300
+ | `/openspec_workflow` | MCP prompt: the sync → trace → validate → export loop | a repo with `openspec/` |
301
+ | `/onboard_project`, `/extract_specs_from_module`, `/audit_spec_coverage` | MCP prompts | brownfield |
302
+
303
+ > **The one rule:** every tool takes `workspace="/abs/repo/root"` (no cwd/env fallback).
304
+
305
+ ### Case 1 — New project from scratch (spec-first)
306
+
307
+ Intent leads (OpenSpec); livespec ties code↔spec as you build.
308
+
309
+ 1. **Author capabilities as specs** — `openspec/specs/<capability>/spec.md` with
310
+ `## Purpose` / `### Requirement:` / `#### Scenario:` (WHEN/THEN). Ask the
311
+ `livespec` subagent to draft them.
312
+ 2. **Ingest + gate the design before coding** —
313
+ `sync_openspec()` → `validate_openspec(strict=True)` (mirrors
314
+ `openspec validate --strict`: every requirement needs ≥1 scenario).
315
+ 3. **Implement feature by feature**, annotating docstrings with `@spec:SPEC-NNN`;
316
+ run `index_project()` after each batch (auto-scans annotations).
317
+ 4. **Trace tests to individual scenarios** —
318
+ `link_scenario_symbol(spec_id, scenario_name, symbol_qname, relation="tests")`.
319
+ 5. **Track coverage live** — `audit_coverage()` and `get_spec_implementation(spec_id)`
320
+ (per-scenario `verified` flag).
321
+ 6. **Behaviour changes = an OpenSpec change** — author `openspec/changes/<name>/`,
322
+ then `sync_openspec()` → `apply_spec_change(name, dry_run=True)` → `apply_spec_change(name)`
323
+ → `archive_spec_change(name)`.
324
+ 7. **Before a PR** — `git_diff_impact(base, head)`; cite spec ids.
325
+
326
+ *Shortcut:* `/openspec_workflow` loads this whole loop.
327
+
328
+ ### Case 2 — Undocumented project (brownfield)
329
+
330
+ livespec reverse-engineers the structure and proposes specs; you curate and link.
331
+
332
+ 1. **Onboard** — `/livespec-onboard /abs/path` (subagent runs `index_project`
333
+ → `get_project_overview` → `list_specs`).
334
+ 2. **Understand the shape** — `quick_orient`, `who_calls`, `find_endpoints`,
335
+ `find_dead_code`.
336
+ 3. **Propose specs from the code** (the brownfield killer feature) —
337
+ `propose_specs_from_codebase()` + `scan_docstrings_for_spec_hints`; per-module
338
+ `/extract_specs_from_module <module>`.
339
+ 4. **Curate + persist** (human in the loop) — `create_spec(...)`, or write
340
+ `docs/specs.md` and `import_specs_from_markdown`.
341
+ 5. **Link code↔spec** — `bulk_link_spec_symbols(mappings=[...])`, or add
342
+ `@spec:SPEC-NNN` annotations and re-`index_project`. Tests via `relation="tests"`.
343
+ 6. **Audit + iterate** — `/audit_spec_coverage` (orphan specs, uncovered modules).
344
+ 7. **Graduate to OpenSpec (optional)** — `export_openspec()` writes a real
345
+ `openspec/` tree, then `validate_openspec(strict=True)`. A repo that had zero
346
+ docs now has a maintainable spec-driven structure.
347
+
348
+ **In one line each:** *new* → OpenSpec defines the contract, `validate_openspec`
349
+ gates it, you build with live links; *brownfield* → `/livespec-onboard` orients,
350
+ `propose_specs_from_codebase` reconstructs the intent, `export_openspec` graduates
351
+ it to spec-driven.
352
+
353
+ ## Tools (44 total: 29 core + 12 Spec plugin + 3 docs plugin)
354
+
355
+ Every tool requires `workspace` (absolute project root). Pass it on each call;
356
+ omitting it is an error (no env fallback). LRU cache (8 workspaces) — one MCP
357
+ server, many projects, no restart.
358
+
359
+ **Menu (v0.19):** plugins register at boot but `PluginVisibilityMiddleware`
360
+ hides Spec mutation / doc tools from `tools/list` until the workspace has
361
+ `spec` rows, a `.mcp-docs/explorer/` bundle (docs plugin), or you set
362
+ `LIVESPEC_PLUGINS`. **`import_specs_from_markdown`** and
363
+ **`export_explorer`** are always visible (brownfield bootstrap — no
364
+ chicken-and-egg). After the first `workspace=` call on a repo with Specs +
365
+ explorer, the menu grows to **44** tools. Reconnect the MCP host if your
366
+ client cached an old tool list.
367
+
368
+ ### Default surface — code intel + Spec agentic (29)
369
+
370
+ These tools answer the questions an agent ASKS on an unfamiliar codebase.
371
+ Always registered (including markdown Spec import + Explorer export).
372
+
373
+ #### Indexing (1)
374
+ - `index_project(force=False, watch=False, embed=False, explorer=False)` — walk, parse,
375
+ persist. Also rebuilds search chunks idempotently. Respects
376
+ `.gitignore` (root + nested, negations included) on top of the
377
+ built-in ignore list (v0.14). Pass `embed=True` to populate vector
378
+ embeddings (requires `[embeddings]` extra). Auto-builds the Spec Explorer
379
+ bundle when `.mcp-docs/explorer/` already exists, `explorer=True`, or a
380
+ FastAPI entry is detected (see **FastAPI integration** above). Read the
381
+ `project://index/status` resource for current status (the legacy
382
+ `get_index_status` tool was dropped in v0.9).
383
+
384
+ Optional per-repo tuning via `.livespec.toml` at the workspace root
385
+ (v0.14) — config patterns outrank `.gitignore`:
386
+
387
+ ```toml
388
+ [index]
389
+ ignore = ["assets/", "*.min.js"] # gitignore syntax, "!" re-includes
390
+ languages = ["python", "typescript"] # allow-list; absent = all 9
391
+ max_file_bytes = 2000000 # skip files larger than this
392
+
393
+ [specs]
394
+ sync_from = ["docs/REQUISITOS_FUNCIONALES.md"] # re-import after every index_project
395
+ links_seed = "docs/requirements/livespec-spec-links.json" # optional bulk_link seed
396
+
397
+ [workspace]
398
+ group_db = "../.livespec-group/docs.db" # cross-project: several repo roots
399
+ # share one DB so a Spec can link
400
+ # symbols across repos (each keeps
401
+ # its own project_id). Absent = the
402
+ # per-repo .mcp-docs/docs.db.
403
+
404
+ [explorer]
405
+ mount_path = "/explorer" # FastAPI mount prefix for autowire
406
+ ```
407
+
408
+ #### Search (1, v0.12)
409
+ - `search(query, scope='all'|'code'|'specs', limit=20)` — hybrid
410
+ retrieval over AST-aware chunks of symbols + Specs. FTS5 keyword lane
411
+ always live (splits `snake_case` into OR tokens); vector lane fuses via
412
+ Reciprocal Rank Fusion (k=60) when `[embeddings]` extra is installed and
413
+ chunks are embedded — falls back to FTS-only if the embedder is offline.
414
+ Use when you want "code that talks about X" without an exact
415
+ symbol-name match. Companion tool `embed_chunks()` (also default
416
+ surface) populates vec0 tables on demand; ~200MB model download on
417
+ first run, cached afterwards in `~/.cache/livespec-mcp/fastembed`
418
+ (shared across workspaces; override with `FASTEMBED_CACHE_PATH`).
419
+ The download shows no progress under MCP — run
420
+ `livespec-mcp index <repo> --embed` in a terminal to watch it.
421
+
422
+ #### Code intelligence (14)
423
+ - `find_symbol(query, kind, limit)` — separator-agnostic name lookup.
424
+ - `get_symbol_source(qname)` — body slice only (lighter than full info).
425
+ - `who_calls(qname, max_depth=1)` — backward cone, slim agentic alias. Adds
426
+ `route_callers` when the symbol is an HTTP endpoint that a frontend calls
427
+ over a route (cross-repo via `group_db`) — *"I changed this endpoint, what
428
+ frontend breaks?"*.
429
+ - `who_does_this_call(qname, max_depth=1)` — forward-direction counterpart.
430
+ Adds `invokes_endpoints`: backend routes this symbol hits via
431
+ `fetch`/`axios`/`requests`.
432
+ - `quick_orient(qname)` — composite snapshot: metadata + docstring lead +
433
+ top-5 callers/callees by PageRank + linked Specs + entry-point flag.
434
+ Replaces 3-4 calls with one when an agent first lands on a symbol.
435
+ - `analyze_impact(target_type, target, max_depth)` — symbol/file/Spec blast
436
+ radius. `max_depth=1` covers the old "find references" use case.
437
+ - `get_project_overview(include_infrastructure=False)` — top symbols by
438
+ PageRank; infra noise filtered by default.
439
+ - `git_diff_impact(base_ref='HEAD~1', head_ref='HEAD', max_depth=5)` —
440
+ changed files → impacted callers → affected Specs → suggested test files.
441
+ PR-review entry point.
442
+ - `find_dead_code(include_infrastructure=False)` — symbols with zero
443
+ callers and zero Spec links. Skips entry-point paths, framework
444
+ decorators, `__main__` guards, list-stored callbacks.
445
+ - `find_orphan_tests(max_depth=10)` — test functions whose forward cone
446
+ never reaches a non-test symbol.
447
+ - `find_endpoints(framework=None)` — framework entry points. Decorator
448
+ markers (`framework` ∈ {flask, fastapi, click, pytest, fastmcp, celery,
449
+ django, spring, angular}), filesystem routing ({nextjs, fresh, sveltekit,
450
+ remix}), Django CBV bases, and call-style routing (`hono`:
451
+ `app.get('/users', handler)` with method + path per route).
452
+ **(v0.19)** FastAPI/Flask decorators also yield `http_method` +
453
+ `http_path` in Explorer and MCP payloads. Default sweep **excludes**
454
+ `tests/**` and `@pytest.fixture` handlers (use `framework='pytest'` for
455
+ fixtures).
456
+ - `grep_in_indexed_files(pattern, path_glob?, kind?, limit=50)` — search
457
+ only files present in the index (avoids `node_modules` / `.venv`).
458
+ - `agent_scratch(qname, note)` / `agent_scratch_clear(qname?)` — ephemeral
459
+ agent notes per project (SQLite, not Specs). Omit `qname` on clear to wipe all.
460
+ - `audit_coverage()` — Spec coverage report: modules without direct Spec,
461
+ modules implicitly covered (transitively reached), modules truly orphan,
462
+ modules in languages whose annotation extractor isn't wired yet
463
+ (`modules_unsupported_language`), Specs without implementation, Specs with
464
+ low avg confidence. **(v0.16)** Also reports auto-derived per-Spec **test
465
+ coverage** (`spec_coverage`, `avg_test_coverage`, `specs_with_any_test_coverage`):
466
+ an implementing symbol counts as tested when a test's forward call-cone
467
+ reaches it (depth 3) or an explicit `relation='tests'` link exists — so
468
+ Spec test-coverage works with no hand-linking for projects whose tests
469
+ call the code directly. The Spec Explorer renders this as a per-Spec test
470
+ coverage meter with a `coverage_source` badge.
471
+
472
+ #### Spec agentic — query + bootstrap (5)
473
+ - `bulk_link_spec_symbols(mappings)` — batch-link N (spec_id, symbol_qname)
474
+ pairs in one transaction. Escape hatch for files/languages where the
475
+ in-source annotation extractor doesn't reach (configs, SQL, YAML).
476
+ Idempotent: re-linking an existing pair is a no-op. Test symbols must be
477
+ **functions** (`tests.pkg.test_mod.test_fn`), not modules (`tests.pkg.test_mod`).
478
+ - `import_specs_from_markdown(path, fmt="auto")` — bulk-create/update Specs
479
+ from Markdown. Auto-detects two dialects: the native `## SPEC-NNN: Title`
480
+ format and **OpenSpec** (Fission-AI) `### Requirement:` / `#### Scenario:`
481
+ specs — point `path` at a single file or at an `openspec/` directory to walk
482
+ its whole tree. Positions livespec as the traceability/graph layer beneath
483
+ spec-driven-development authoring tools. Always visible; warns on duplicate
484
+ Spec headings; idempotent.
485
+ - `list_specs(status, module, priority, kind, has_implementation)` —
486
+ Spec discovery surface.
487
+ - `get_spec_implementation(spec_id)` — answers
488
+ *"¿qué código implementa el SPEC-042?"*.
489
+ - `propose_specs_from_codebase(module_depth=2, min_symbols_per_group=3,
490
+ max_proposals=30, skip_already_covered=True)` — heuristic Spec discovery
491
+ on a Spec-empty repo. Groups symbols by module + PageRank, proposes
492
+ Spec candidates with humanized title + suggested_symbols.
493
+
494
+ #### OpenSpec interop — round-trip + change lifecycle (5, v0.22)
495
+
496
+ Make livespec a first-class citizen of an [OpenSpec](https://github.com/Fission-AI/OpenSpec)
497
+ `openspec/` repo. Scenarios (`#### Scenario:` WHEN/THEN) are first-class rows
498
+ since v0.22 — `get_spec_implementation` returns them (with per-scenario linked
499
+ `symbols` + a `verified` flag) and `list_specs` counts them. Link code/tests to
500
+ an individual scenario with `link_scenario_symbol` (Spec plugin).
501
+
502
+ - `sync_openspec(openspec_dir?)` — import an entire OpenSpec tree in one call:
503
+ canonical requirements from `specs/` **and** every change under `changes/`
504
+ (proposed) / `archive/` (archived); reads `openspec.json`. Always visible
505
+ (bootstrap). For a single file use `import_specs_from_markdown`.
506
+ - `export_openspec(out_dir="openspec", include_changes=True)` — the inverse:
507
+ write the DB back to `specs/<capability>/spec.md` (+ `changes/`, `archive/`).
508
+ Closes the round-trip. Capability == the spec's `module`.
509
+ - `validate_openspec(strict=False)` — mirror `openspec validate [--strict]`;
510
+ the load-bearing check is *every requirement MUST have ≥1 scenario*.
511
+ - `list_spec_changes(status?)` / `get_spec_change(name)` — inspect change
512
+ proposals (proposal/design/tasks prose + ADD/MODIFY/REMOVE/RENAME deltas).
513
+
514
+ #### Spec Explorer (1, always visible)
515
+ - `export_explorer(base?, head?, generated_at?)` — writes
516
+ `.mcp-docs/explorer/` (`data.json` + `index.html`). Swagger-style view by
517
+ Spec; **v0.19** HTTP Try-it for routes with method/path; FastAPI
518
+ autowire on export/index. Preview: `livespec-mcp explorer serve` →
519
+ `http://127.0.0.1:8765/explorer/`.
520
+
521
+ ### `livespec-spec` plugin — Spec mutation (12)
522
+
523
+ Visible in `tools/list` when the workspace DB has `spec` rows, or when
524
+ `LIVESPEC_PLUGINS` includes `spec`. Tools an *operator* runs to mutate Spec state.
525
+
526
+ `bulk_link_spec_symbols` and `import_specs_from_markdown` live in the
527
+ **default surface** (always visible) so brownfield repos can bootstrap without
528
+ setting `LIVESPEC_PLUGINS`.
529
+
530
+ - `create_spec(title, ...)`, `update_spec(spec_id, ...)`,
531
+ `delete_spec(spec_id)` — cascade-removes spec_symbol links.
532
+ - `link_spec_symbol(spec_id, symbol_qname, relation, confidence, source, unlink)` —
533
+ link / unlink a single Spec↔symbol pair.
534
+ - `link_scenario_symbol(spec_id, scenario_name, symbol_qname, ...)` —
535
+ scenario-level traceability: link code/tests to an individual OpenSpec
536
+ `#### Scenario:` (finer than the whole requirement). Surfaced per-scenario in
537
+ `get_spec_implementation` (`verified` + linked `symbols`).
538
+ - `link_spec_dependency(parent_spec_id, child_spec_id, kind='requires')` /
539
+ `unlink_spec_dependency` / `get_spec_dependency_graph` — Spec→Spec graph.
540
+ `kind` ∈ {requires, extends, conflicts}; cycles rejected at insert time.
541
+ - `scan_spec_annotations()` — two-level matcher (`@spec:SPEC-NNN` vs.
542
+ verb-anchored); auto-runs after every `index_project`.
543
+ - `scan_docstrings_for_spec_hints()` — surfaces Spec candidates from existing
544
+ docstrings (first sentence, leading verb). Returns
545
+ `verb_histogram_top` for noticing dominant action verbs.
546
+ - `apply_spec_change(name, dry_run=False)` / `archive_spec_change(name)` —
547
+ OpenSpec change lifecycle: fold a change's deltas into the canonical Spec set
548
+ (ADDED/MODIFIED upsert+activate, REMOVED deprecate, **RENAMED** moves the old
549
+ requirement's traceability links onto the new name and drops the old spec),
550
+ then mark it archived. `dry_run=True` returns the plan + applicability
551
+ `warnings` (missing target, would-overwrite) without mutating.
552
+
553
+ ### Brownfield bootstrap (no Python one-liner)
554
+
555
+ ```text
556
+ index_project(workspace=..., explorer=True)
557
+ → import_specs_from_markdown(path="docs/REQUISITOS_FUNCIONALES.md")
558
+ → bulk_link_spec_symbols(mappings=[...])
559
+ ```
560
+
561
+ Or add `[specs].sync_from` to `.livespec.toml` and run
562
+ `uv run python scripts/sync_livespec_specs.py /path/to/repo` after editing the
563
+ spec without a full re-index.
564
+
565
+ ### `livespec-docs` plugin — doc generation (3)
566
+
567
+ Visible when the workspace has `doc` rows, a `.mcp-docs/explorer/` bundle, or
568
+ `LIVESPEC_PLUGINS` includes `docs`. Human-tier ceremony for managing generated docs.
569
+
570
+ - `generate_docs(target_type, identifier, content?, max_tokens?)` —
571
+ three modes: caller_supplied / sampling / needs_caller_content. Works
572
+ in Claude Code (caller mode) and Cursor/Desktop (sampling mode).
573
+ - `list_docs(target_type, only_stale=False)` — list or surface drifted
574
+ docs (drift triggers on body_hash OR signature_hash mismatch).
575
+ - `export_documentation(format, out_subdir)` — markdown or JSON.
576
+
577
+ ### Migrating from older versions
578
+
579
+ | Removed | Use instead |
580
+ |---|---|
581
+ | `find_references` (v0.1) | `analyze_impact(target_type='symbol', target=qname, max_depth=1)` |
582
+ | `get_symbol_info` (v0.7) | `quick_orient` (composite) + `get_symbol_source` (body) |
583
+ | `get_call_graph` (v0.7) | `who_calls` + `who_does_this_call` |
584
+ | `search`, `rebuild_chunks` (v0.7, dropped v0.8) | `search` is **back in v0.12** wired to a real chunk pipeline + vector lane via Reciprocal Rank Fusion. `rebuild_chunks` is now auto-run inside `index_project` (no separate tool). `find_symbol` + `quick_orient` still cover exact-name lookup. |
585
+ | `list_files` (v0.7) | grep / ripgrep host with path glob |
586
+ | `start_watcher` / `stop_watcher` / `watcher_status` (v0.7) | re-run `index_project` on demand (watcher race-condition trap for editing agents) |
587
+ | `link_requirement_to_code` (v0.6 alias) | `link_spec_symbol` |
588
+ | `link_requirements` / `unlink_requirements` (v0.6 alias) | `link_spec_dependency` / `unlink_spec_dependency` |
589
+ | `get_requirement_dependencies` (v0.6 alias) | `get_spec_dependency_graph` |
590
+ | `get_index_status` (v0.9, deprecated in v0.8) | read the `project://index/status` resource |
591
+ | `list_requirements` / `get_requirement_implementation` / `create_requirement` / etc. (RF nomenclature, removed v0.20 — hard cut) | `list_specs` / `get_spec_implementation` / `create_spec` / etc. |
592
+
593
+ ## Resources
594
+
595
+ - `project://overview`
596
+ - `project://index/status`
597
+ - `project://specs`
598
+ - `project://specs/{spec_id}`
599
+ - `project://files/{path*}`
600
+ - `project://symbols/{qname*}`
601
+ - `doc://symbol/{qname*}`
602
+ - `doc://spec/{spec_id}`
603
+ - `code://symbol/{qname*}` — raw symbol source slice
604
+
605
+ ## Prompts (slash commands)
606
+
607
+ - **`agent_playbook`** — primary agent guide: tool tiers, call patterns, `@spec:` commenting, brownfield Spec workflow, anti-patterns
608
+ - `onboard_project`
609
+ - `analyze_change_impact`
610
+ - `audit_spec_coverage`
611
+ - `extract_specs_from_module`
612
+ - `document_undocumented_symbols`
613
+ - `refresh_stale_docs`
614
+ - `explain_symbol`
615
+
616
+ ## Performance
617
+
618
+ Numbers from the v0.8/v0.9 battle-test harness (4 sessions / 4 profiles
619
+ / 65+ logged calls in [`docs/AGENT_USAGE_DATA.md`](docs/AGENT_USAGE_DATA.md)).
620
+ Cold = first run; warm = cached run on the same workspace. Latency p95
621
+ measured with the in-process middleware
622
+ (`src/livespec_mcp/instrumentation.py`).
623
+
624
+ | Repo | Files / Symbols | `index_project` cold | `quick_orient` p95 | `get_project_overview` p95 |
625
+ |---|---:|---:|---:|---:|
626
+ | url-shortener-demo (Python) | 4 / 23 | ~50 ms | <5 ms | ~10 ms |
627
+ | livespec itself (Python+8 langs) | 84 / 495 | ~400 ms | ~60 ms | ~75 ms |
628
+ | jig (Python) | 130 / 1173 | ~600 ms | ~50 ms | ~80 ms |
629
+ | Django (Python, stress) | 2898 / 39789 | ~25 s | <100 ms | ~250 ms |
630
+ | warp subset (Rust, stress) | 5K / 50K | ~30 s | <100 ms | ~300 ms |
631
+
632
+ For repos > 30K symbols, pass `summary_only=True` on aggregator and
633
+ traversal tools (`audit_coverage`, `find_dead_code`, `find_orphan_tests`,
634
+ `find_endpoints`, `git_diff_impact`, `who_calls`, `who_does_this_call`,
635
+ `analyze_impact`) to keep payloads under ~200 KB. Counts stay exact
636
+ regardless of pagination — see `bench/run.py --large` for the Django
637
+ stress profile.
638
+
639
+ ### Django precision series (same queries, across releases)
640
+
641
+ | Tool | v0.8 | v0.9 | v0.11 | v0.14 | Why |
642
+ |---|---:|---:|---:|---:|---|
643
+ | `find_dead_code` | 824 | 514 | 348 | **344** | non-Python skip → dotted-path string refs → runtime registration → closure-capture |
644
+ | `find_endpoints(django)` | 20 | **162** | 162 | 162 | class-based view detection via inheritance from `View` / mixins |
645
+ | Partial reindex (Django, 1 file) | — | ~7 s | — | **1.4 s** | targeted `_resolve_refs` walk |
646
+ | `index_project` cold (Django) | — | ~148 s | — | **54 s** | (v0.14 re-run on Ryzen 7 4800H; edges 1.05M → 465K from scoped-resolution precision, DB 124 → 71 MB, RSS post-PageRank 609 → 294 MB — those three are machine-independent) |
647
+
648
+ ## Tests
649
+
650
+ ```bash
651
+ uv run pytest -q
652
+ ```
653
+
654
+ In-memory FastMCP `Client(mcp)` so tests run without subprocess or network.
655
+
656
+ ## Agent vs human user
657
+
658
+ livespec ships two user shapes deliberately:
659
+
660
+ - **Agents** see the 24-tool default surface and the agentic-read Spec tools
661
+ (`list_specs`, `get_spec_implementation`,
662
+ `propose_specs_from_codebase`, `audit_coverage`). The composite
663
+ `quick_orient` is the canonical first-contact tool — it returns
664
+ metadata, docstring lead, top callers/callees by PageRank, linked Specs,
665
+ and entry-point flags in one call.
666
+ - **Humans** (or operator scripts) reach for the plugin tools to mutate
667
+ Spec state and manage docs. Auto-load happens once the DB shows real Spec
668
+ or doc rows; before that, set `LIVESPEC_PLUGINS=all` (or `=spec` /
669
+ `=docs`) to bootstrap.
670
+
671
+ This is why dropping `search`/`get_symbol_info` was safe: the battle-test
672
+ harness logged zero agent calls to those tools across 3 codebases. The
673
+ data trumped the prior intuition.
674
+
675
+ ## Roadmap
676
+
677
+ | Fase | Estado | Contenido |
678
+ |------|--------|-----------|
679
+ | 0 — Bootstrap | ✅ | FastMCP server, project structure |
680
+ | 1 — Indexing | ✅ | tree-sitter + Python AST, file-incremental, call graph |
681
+ | 2 — Analysis | ✅ | NetworkX, impact, PageRank |
682
+ | 3 — Requirements | ✅ | CRUD + linking + annotation matcher |
683
+ | 4 — RAG/Embeddings | ✅ | AST chunking, FTS5, fastembed + sqlite-vec optional, RRF |
684
+ | 5 — Doc generation | ✅ | `generate_docs` (dual-mode), drift detect (body+signature), export |
685
+ | 6 — Polish | ✅ | 7 prompts, doc:// resources, two-level @rf: matcher with negation guard |
686
+ | 7 — v0.2 | ✅ | Multi-tenant state, tool consolidation 25→23, persistent refs, watcher, bench suite |
687
+ | 8 — v0.3 | ✅ | Auto-scan post-index, PageRank infra filter, scoped resolution by imports, `git_diff_impact`, embeddings smoke real, Ruby+PHP fixtures, hypothesis property tests, memory bench, GitHub Actions CI, `code://` resource, `delete_requirement`, markdown RF importer |
688
+ | 9 — v0.4 | ✅ | Scoped resolution for TS/JS/Go/Ruby/PHP, `find_dead_code` / `audit_coverage` / `find_orphan_tests`, `did_you_mean` on Symbol-not-found errors, watcher `atexit` cleanup, CI venv fix |
689
+ | 10 — v0.5 | ✅ | Bug fixes from real-repo demo, decorators as first-class field + `find_endpoints`, RF dependency graph (requires/extends/conflicts) with `analyze_impact` cascade, matcher multi-RF + confidence override + `@not_rf:` negation + golden dataset, Rust `use` scoped resolution |
690
+ | 11 — v0.6 | ✅ | Hardening: explicit migration framework, unified error shape, RF link tools renamed, deprecated `use_workspace` removed, Django stress test (40K symbols), graph cache, README pitch reframe |
691
+ | 12 — v0.7 | ✅ | Brownfield onboarding: `propose_requirements_from_codebase`, `bulk_link_rf_symbols`, `scan_docstrings_for_rf_hints`. Pagination on aggregator tools. Rust `pub` visibility-aware dead-code filter. `find_symbol` separator-agnostic |
692
+ | 13 — v0.8 | ✅ | Curation pass driven by 3-session battle-test data: 4 quick-win agentic tools (`quick_orient`, `who_calls`, `who_does_this_call`, `get_symbol_source`). 11 P2 bug fixes on `find_dead_code`, `audit_coverage`, `git_diff_impact`, `propose_requirements_from_codebase`. Plugin auto-detect framework — RF mutation (11 tools) and doc management (3 tools) move into auto-loading plugins. Tier-4 drops: `list_files`, `search`, `rebuild_chunks`, `get_call_graph`, `get_symbol_info`, watcher trio. Default surface 39 → 17 tools |
693
+ | 14 — v0.9 | ✅ | Django readiness: targeted `_resolve_refs` walk on partial reindex (closes v0.7 deferred). Pagination on `who_calls` / `who_does_this_call` / `analyze_impact`. `min_weight=0.6` filter mutes resolver fan-out. Django dead-code accuracy (skip non-Python, recognize dotted-path strings + `class Meta:`). Django CBV detection in `find_endpoints` (LoginView/FormView/LoginRequiredMixin/etc.). Drop `get_index_status`. Default surface 17 → 16. Wire-validated: Django `find_dead_code` 824 → 514, `find_endpoints(django)` 20 → 162 |
694
+ | 15 — v0.10 | ✅ | Library codebase release: `from .x import Y` re-exports + `__all__` lists protect names from `find_dead_code` (closes the largest remaining false-positive bucket on Django). README lift — Django numbers above the fold + 30-second tour. Battle-test session 05 against Deno Fresh (TS/TSX/JS) — 5/5 profiles covered. Wire-validated: Django `find_dead_code` 514 → 348 (−58% cumulative from v0.8 baseline of 824) |
695
+ | 16 — v0.11 | ✅ | TS framework readiness: bundler/build dir filter (`_fresh/`, `dist/`, `build/`, `.next/`, `out/`, `node_modules/`, `.svelte-kit/`, `target/`, …), TS framework entry-point detection (Fresh `islands/`, Next `pages/` + `app/`, SvelteKit `routes/`, Remix `app/routes/`), JSX element refs as call-graph edges, runtime-registration name protection (`Field.register_lookup` / `signal.connect` / `add_middleware`). Closes session-05 bugs #18-#20. Wire-validated: Fresh `find_dead_code` 974 → **0** (default), 974 → 118 (`include_non_python=True`); `find_endpoints(fresh)` returns **340** entry points; `top_symbols` from `_fresh/` 18/20 → **0/20**. Three sonnet subagents in parallel worktrees |
696
+ | 17 — v0.12 | ✅ | Multi-repo workspace: `workspace` required on every call, one server instance serves N repos (LRU per-workspace state). RAG layer wired: `index_project` runs AST-aware chunking, `search` (FTS5 + optional sqlite-vec via RRF) + `embed_chunks` exposed. JSDoc extraction for TS/JS (`@rf:` annotations in JSDoc now scanned). `bulk_link_rf_symbols` promoted out of the RF plugin. Banner-comment filter. `force=True` preserves manual RF links |
697
+ | 18 — v0.13 | ✅ | Framework coverage sprint: Spring Boot (Java annotations → endpoints + DI-aware dead-code), Angular (TS decorators, template-reachability method protection, lifecycle hooks), Hono (call-style route extraction with method+path, named-handler callback refs, module-level registration scan — also covers Express-style apps). TS decorator + Java annotation extraction (migration v8 auto re-extract). Dual-decorator alias fix: `find_dead_code` on livespec-mcp itself 22 → **0** |
698
+ | 19 — v0.14 | ✅ | Personal-fit sprint: gitignore-aware indexing (root + nested + negations via `pathspec`), `.livespec.toml` per-repo config (ignore/languages/max_file_bytes, outranks .gitignore), headless CLI (`livespec-mcp index|status` — cron/systemd/pre-commit sin host MCP), fix resources rotos bajo multi-tenant (MRU binding + `mcp_error` shape), `languages_unsupported` reporting, closure-capture TS/JS/Rust, embed cache persistente XDG, Django re-validation: dead-code **344** (serie 824→514→348→344), partial reindex **1.4s** |
699
+ | 20 — v0.15–0.17 | ✅ | RF Explorer static bundle (`export_explorer`), derived RF test coverage + explorer meters, Changes/drill-down/trend/freshness, reproducible self-RFs (`livespec-rf-links.json`) |
700
+ | 21 — v0.18 | ✅ | `PluginVisibilityMiddleware` (per-workspace tool menu, 19→33 after index). `livespec-mcp explorer serve` + FastAPI `mount_explorer` autowire. Explorer landing + Swagger API tab. Search: FTS snake_case + offline vector fallback. **342** default tests |
701
+ | 22 — v0.19 | ✅ | FastAPI HTTP paths + Explorer Try-it; `fastapi init`; brownfield RF bootstrap (`import_requirements_from_markdown` always visible, `[requirements].sync_from`, duplicate-spec warnings); agent tools + PR RF comment CI. **368** default tests |
702
+ | 23 — v0.20 | ✅ | **Breaking (hard cut):** RF → Spec nomenclature + taxonomy. `rf`/`rf_symbol`/`rf_dependency` tables renamed to `spec`/`spec_symbol`/`spec_dependency` with a new `kind` column (`functional_requirement`, `non_functional_requirement`, `adr`, `design`, `constraint`, `epic`, `other`); migration v11 preserves existing `RF-NNN` ids. `@rf:`/`@not_rf` annotations renamed to `@spec:`/`@not_spec`. All RF-prefixed tools renamed (`list_requirements`→`list_specs`, `create_requirement`→`create_spec`, etc.), `livespec-rf` plugin renamed to `livespec-spec`. No aliases — single breaking release. Followed by an 8-dimension audit whose ~50 fixes landed across six batches (packaging, storage/concurrency, domain correctness, tools, performance, docs). **403** default tests |
703
+ | 24 — v0.23 | ✅ | Cross-repo route edges (`route_ref`, mig v14 — `who_calls.route_callers` / `who_does_this_call.invokes_endpoints`), grouped DB (`[workspace] group_db`), Python callback-arg edges. **Full OpenSpec (Fission-AI) compatibility:** scenarios first-class (migs v15/v17 `spec_scenario`/`scenario_symbol`), `export_openspec` round-trip, `validate_openspec`, change lifecycle (mig v16 `spec_change`/`spec_change_delta`; `sync_openspec`/`apply_spec_change`/`archive_spec_change` — RENAMED FROM/TO + `dry_run`/warnings, mig v18), scenario-level traceability (`link_scenario_symbol`), Purpose round-trip, and agent discoverability (`openspec_workflow` prompt). **Battle-tested** against the real Fission-AI/OpenSpec tree (2 layout bugs fixed). Tools 36 → 44. Rebrand: product name `livespec` + `livespec` command alias (dist/package stay `livespec-mcp`). Trusted-Publishing release workflow. (Supersedes the tag-only, unpublished v0.22.0.) |