@spikedpunch/mast 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MAST_SPEC.md +169 -44
- package/README.md +266 -20
- package/assets/prime.md +18 -0
- package/assets/signals.md +51 -0
- package/assets/skill.md +13 -15
- package/dist/ast/types.d.ts +137 -1
- package/dist/ast/types.d.ts.map +1 -1
- package/dist/cli/docs-cmd.d.ts +1 -0
- package/dist/cli/docs-cmd.d.ts.map +1 -1
- package/dist/cli/docs-cmd.js +2 -1
- package/dist/cli/docs-cmd.js.map +1 -1
- package/dist/cli/hook-cmd.d.ts +3 -0
- package/dist/cli/hook-cmd.d.ts.map +1 -0
- package/dist/cli/hook-cmd.js +13 -0
- package/dist/cli/hook-cmd.js.map +1 -0
- package/dist/cli/hook-state-dir.d.ts +24 -0
- package/dist/cli/hook-state-dir.d.ts.map +1 -0
- package/dist/cli/hook-state-dir.js +57 -0
- package/dist/cli/hook-state-dir.js.map +1 -0
- package/dist/cli/hook.d.ts +44 -0
- package/dist/cli/hook.d.ts.map +1 -0
- package/dist/cli/hook.js +200 -0
- package/dist/cli/hook.js.map +1 -0
- package/dist/cli/index.js +12 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/installed-artifacts.d.ts +23 -0
- package/dist/cli/installed-artifacts.d.ts.map +1 -0
- package/dist/cli/installed-artifacts.js +39 -0
- package/dist/cli/installed-artifacts.js.map +1 -0
- package/dist/cli/prime-cmd.d.ts +17 -0
- package/dist/cli/prime-cmd.d.ts.map +1 -0
- package/dist/cli/prime-cmd.js +70 -0
- package/dist/cli/prime-cmd.js.map +1 -0
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/program.js +6 -0
- package/dist/cli/program.js.map +1 -1
- package/dist/cli/query.d.ts +40 -1
- package/dist/cli/query.d.ts.map +1 -1
- package/dist/cli/query.js +36 -2
- package/dist/cli/query.js.map +1 -1
- package/dist/cli/search-cmd.d.ts +6 -1
- package/dist/cli/search-cmd.d.ts.map +1 -1
- package/dist/cli/search-cmd.js +9 -2
- package/dist/cli/search-cmd.js.map +1 -1
- package/dist/cli/serve.d.ts +6 -1
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +14 -4
- package/dist/cli/serve.js.map +1 -1
- package/dist/cli/setup-cmd.d.ts +34 -0
- package/dist/cli/setup-cmd.d.ts.map +1 -0
- package/dist/cli/setup-cmd.js +205 -0
- package/dist/cli/setup-cmd.js.map +1 -0
- package/dist/cli/setup-command.d.ts +32 -0
- package/dist/cli/setup-command.d.ts.map +1 -0
- package/dist/cli/setup-command.js +43 -0
- package/dist/cli/setup-command.js.map +1 -0
- package/dist/cli/setup-plan.d.ts +52 -0
- package/dist/cli/setup-plan.d.ts.map +1 -0
- package/dist/cli/setup-plan.js +221 -0
- package/dist/cli/setup-plan.js.map +1 -0
- package/dist/cli/setup-rules.d.ts +41 -0
- package/dist/cli/setup-rules.d.ts.map +1 -0
- package/dist/cli/setup-rules.js +76 -0
- package/dist/cli/setup-rules.js.map +1 -0
- package/dist/cli/setup-static.d.ts +13 -0
- package/dist/cli/setup-static.d.ts.map +1 -0
- package/dist/cli/setup-static.js +116 -0
- package/dist/cli/setup-static.js.map +1 -0
- package/dist/cli/skill-install.d.ts +2 -0
- package/dist/cli/skill-install.d.ts.map +1 -1
- package/dist/cli/skill-install.js +2 -0
- package/dist/cli/skill-install.js.map +1 -1
- package/dist/cli/status.d.ts +15 -0
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +32 -6
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/upgrade-cmd.d.ts +5 -1
- package/dist/cli/upgrade-cmd.d.ts.map +1 -1
- package/dist/cli/upgrade-cmd.js +28 -3
- package/dist/cli/upgrade-cmd.js.map +1 -1
- package/dist/indexer/freshness.d.ts +10 -0
- package/dist/indexer/freshness.d.ts.map +1 -1
- package/dist/indexer/freshness.js +7 -1
- package/dist/indexer/freshness.js.map +1 -1
- package/dist/indexer/import-resolver.js +28 -16
- package/dist/indexer/import-resolver.js.map +1 -1
- package/dist/indexer/index.d.ts +38 -3
- package/dist/indexer/index.d.ts.map +1 -1
- package/dist/indexer/index.js +47 -4
- package/dist/indexer/index.js.map +1 -1
- package/dist/indexer/watcher.d.ts +94 -0
- package/dist/indexer/watcher.d.ts.map +1 -1
- package/dist/indexer/watcher.js +172 -19
- package/dist/indexer/watcher.js.map +1 -1
- package/dist/mcp/context.d.ts +16 -0
- package/dist/mcp/context.d.ts.map +1 -1
- package/dist/mcp/freshness-probe.d.ts +82 -0
- package/dist/mcp/freshness-probe.d.ts.map +1 -0
- package/dist/mcp/freshness-probe.js +111 -0
- package/dist/mcp/freshness-probe.js.map +1 -0
- package/dist/mcp/instructions.d.ts +7 -0
- package/dist/mcp/instructions.d.ts.map +1 -0
- package/dist/mcp/instructions.js +10 -0
- package/dist/mcp/instructions.js.map +1 -0
- package/dist/mcp/server.d.ts +54 -3
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +79 -4
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/_helpers.d.ts +40 -0
- package/dist/mcp/tools/_helpers.d.ts.map +1 -1
- package/dist/mcp/tools/_helpers.js +27 -0
- package/dist/mcp/tools/_helpers.js.map +1 -1
- package/dist/mcp/tools/callers.d.ts.map +1 -1
- package/dist/mcp/tools/callers.js +6 -1
- package/dist/mcp/tools/callers.js.map +1 -1
- package/dist/mcp/tools/dependencies.d.ts.map +1 -1
- package/dist/mcp/tools/dependencies.js +2 -1
- package/dist/mcp/tools/dependencies.js.map +1 -1
- package/dist/mcp/tools/exports.d.ts.map +1 -1
- package/dist/mcp/tools/exports.js +2 -1
- package/dist/mcp/tools/exports.js.map +1 -1
- package/dist/mcp/tools/implementors.d.ts.map +1 -1
- package/dist/mcp/tools/implementors.js +2 -1
- package/dist/mcp/tools/implementors.js.map +1 -1
- package/dist/mcp/tools/project-skeleton.d.ts.map +1 -1
- package/dist/mcp/tools/project-skeleton.js +2 -1
- package/dist/mcp/tools/project-skeleton.js.map +1 -1
- package/dist/mcp/tools/reindex.d.ts.map +1 -1
- package/dist/mcp/tools/reindex.js +3 -0
- package/dist/mcp/tools/reindex.js.map +1 -1
- package/dist/mcp/tools/rename-impact.d.ts.map +1 -1
- package/dist/mcp/tools/rename-impact.js +4 -1
- package/dist/mcp/tools/rename-impact.js.map +1 -1
- package/dist/mcp/tools/search.d.ts.map +1 -1
- package/dist/mcp/tools/search.js +13 -2
- package/dist/mcp/tools/search.js.map +1 -1
- package/dist/mcp/tools/signature.d.ts.map +1 -1
- package/dist/mcp/tools/signature.js +2 -1
- package/dist/mcp/tools/signature.js.map +1 -1
- package/dist/mcp/tools/status.d.ts.map +1 -1
- package/dist/mcp/tools/status.js +8 -2
- package/dist/mcp/tools/status.js.map +1 -1
- package/dist/store/config.d.ts.map +1 -1
- package/dist/store/config.js +4 -5
- package/dist/store/config.js.map +1 -1
- package/dist/store/defaults.d.ts +9 -0
- package/dist/store/defaults.d.ts.map +1 -0
- package/dist/store/defaults.js +12 -0
- package/dist/store/defaults.js.map +1 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ MAST takes a different approach:
|
|
|
33
33
|
- **AST-level chunking** — every function, class, interface, and type alias is its own chunk. The assistant gets the exact declaration it needs, not the file it happens to live in.
|
|
34
34
|
- **Ranked search** — BM25 (FTS5) handles keyword and identifier queries; a declaration-exact ranker ("ranker D") catches exact-symbol-name queries that BM25's trigram tokenizer can rank inconsistently. Both are fused via Reciprocal Rank Fusion so a chunk that both rankers agree on outranks one that only one of them found.
|
|
35
35
|
- **Structural queries** — "who calls this function?", "what implements this interface?", "what does this file import?" are answered from a pre-built symbol graph, not by grepping source. Answers are instantaneous and structurally correct.
|
|
36
|
-
- **
|
|
36
|
+
- **Staleness handling that says what it actually does** — five read tools (`mast_signature`, `mast_callers`, `mast_exports`, `mast_dependencies`, `mast_rename_impact`) re-parse a changed file inline before answering; `mast_search` and `mast_implementors` flag affected results with `stale: true` rather than re-parsing. Both only cover files the index *already knows*: a brand-new file is invisible until a reindex, which is why `mast serve` watches by default and why `mast_search` carries an `unindexed_files` warning when it does not.
|
|
37
37
|
- **Token accounting** — every tool response includes `_stats` with the token count returned and the counterfactual "what would a naive full-file read have cost?", giving a concrete measure of efficiency over time.
|
|
38
38
|
|
|
39
39
|
---
|
|
@@ -142,12 +142,21 @@ mast index --incremental # reindex only what changed
|
|
|
142
142
|
mast install-hooks # reindex automatically after commits and checkouts
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
+
Then tell your agent to use it. One command installs what your harness can take — hooks
|
|
146
|
+
that prime the agent at session start and remind it before a built-in search, or a rules
|
|
147
|
+
file where there are no hooks ([details](#tell-the-assistant-how-to-use-it)):
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
mast setup claude # or cursor, vscode, windsurf, zed, desktop
|
|
151
|
+
```
|
|
152
|
+
|
|
145
153
|
Everything shipped with your build is readable offline, so you never have to work out
|
|
146
154
|
which docs match your version:
|
|
147
155
|
|
|
148
156
|
```bash
|
|
149
157
|
mast docs # list the topics
|
|
150
158
|
mast docs spec # the full behavioural specification
|
|
159
|
+
mast docs signals # how to read the flags on an answer (stale, truncated, empty)
|
|
151
160
|
mast skill # the instructions to paste into an agent prompt
|
|
152
161
|
```
|
|
153
162
|
|
|
@@ -170,6 +179,8 @@ claude mcp add mast -- mast serve
|
|
|
170
179
|
Add `--scope project` to write `.mcp.json` into the repository so your team picks it up
|
|
171
180
|
from the checkout.
|
|
172
181
|
|
|
182
|
+
To prime the agent at session start and remind it before a search: `mast setup claude`.
|
|
183
|
+
|
|
173
184
|
### Claude Desktop
|
|
174
185
|
|
|
175
186
|
`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS,
|
|
@@ -190,6 +201,10 @@ from the checkout.
|
|
|
190
201
|
Claude Desktop does not run in your project directory, so `MAST_STATE_DIR` must be
|
|
191
202
|
absolute. The CLI and editor integrations below infer it from the working directory.
|
|
192
203
|
|
|
204
|
+
Claude Desktop has no hook system and no rules file mast can write. The instructions string
|
|
205
|
+
`mast serve` sends in the MCP handshake is its only channel, and it needs no setup;
|
|
206
|
+
`mast setup desktop` just says so.
|
|
207
|
+
|
|
193
208
|
### Cursor
|
|
194
209
|
|
|
195
210
|
`.cursor/mcp.json` in the project, or `~/.cursor/mcp.json` globally:
|
|
@@ -202,6 +217,8 @@ absolute. The CLI and editor integrations below infer it from the working direct
|
|
|
202
217
|
}
|
|
203
218
|
```
|
|
204
219
|
|
|
220
|
+
To add the hooks and a rules file: `mast setup cursor`.
|
|
221
|
+
|
|
205
222
|
### VS Code (GitHub Copilot)
|
|
206
223
|
|
|
207
224
|
`.vscode/mcp.json`:
|
|
@@ -214,6 +231,8 @@ absolute. The CLI and editor integrations below infer it from the working direct
|
|
|
214
231
|
}
|
|
215
232
|
```
|
|
216
233
|
|
|
234
|
+
To add the session-primer hook: `mast setup vscode`.
|
|
235
|
+
|
|
217
236
|
### Windsurf
|
|
218
237
|
|
|
219
238
|
`~/.codeium/windsurf/mcp_config.json`:
|
|
@@ -226,6 +245,8 @@ absolute. The CLI and editor integrations below infer it from the working direct
|
|
|
226
245
|
}
|
|
227
246
|
```
|
|
228
247
|
|
|
248
|
+
To add a rules file: `mast setup windsurf`.
|
|
249
|
+
|
|
229
250
|
### Zed
|
|
230
251
|
|
|
231
252
|
`settings.json`:
|
|
@@ -238,16 +259,43 @@ absolute. The CLI and editor integrations below infer it from the working direct
|
|
|
238
259
|
}
|
|
239
260
|
```
|
|
240
261
|
|
|
262
|
+
To add mast's instructions to a rules file you already keep (`.rules`, `AGENTS.md`, and the
|
|
263
|
+
others Zed reads): `mast setup zed`.
|
|
264
|
+
|
|
241
265
|
### Any other MCP client
|
|
242
266
|
|
|
243
|
-
Run `mast serve` over stdio from the project root. It advertises eleven
|
|
244
|
-
needs no arguments beyond `serve`.
|
|
267
|
+
Run `mast serve` over stdio from the project root. It advertises eleven tools — ten that
|
|
268
|
+
read and `mast_reindex`, which writes — and needs no arguments beyond `serve`.
|
|
245
269
|
|
|
246
270
|
### Tell the assistant how to use it
|
|
247
271
|
|
|
248
272
|
Registering the server gives the model the tools; it does not tell it *when* to reach for
|
|
249
|
-
them
|
|
250
|
-
|
|
273
|
+
them. `mast setup <harness>` installs what each harness can take:
|
|
274
|
+
|
|
275
|
+
| harness | session primer | search reminder | static instructions |
|
|
276
|
+
|---|---|---|---|
|
|
277
|
+
| `claude` (Claude Code) | yes | yes, before `Grep` and `Glob` | none written |
|
|
278
|
+
| `cursor` | yes | yes, but after the search runs | `.cursor/rules/mast.mdc` |
|
|
279
|
+
| `vscode` (VS Code Copilot) | yes | no | none written |
|
|
280
|
+
| `windsurf` | no | no | `.windsurf/rules/mast.md`, or `.devin/rules/mast.md` if `.devin/` exists |
|
|
281
|
+
| `zed` | no | no | a marked block in the first rules file that exists |
|
|
282
|
+
| `desktop` (Claude Desktop) | no | no | none written |
|
|
283
|
+
|
|
284
|
+
The session primer is the rule set plus the live index state, given at session start. The
|
|
285
|
+
search reminder is one line naming `mast_search`, attached to a built-in search. Windsurf,
|
|
286
|
+
Zed and Claude Desktop have no hook system mast can use, so for them `mast setup` installs
|
|
287
|
+
the static file only, and says so. `mast serve` also sends a short instructions string when
|
|
288
|
+
the MCP connection opens; whether a harness passes that to the model is the harness's choice.
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
mast setup claude # project scope; add --global for ~/.claude/settings.json
|
|
292
|
+
mast setup cursor --check # exit 0 only if the hooks and the rules file are current
|
|
293
|
+
mast setup windsurf --dry-run
|
|
294
|
+
mast setup zed --remove
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Anything else, or a harness not listed, can use `mast skill`, which prints the same short
|
|
298
|
+
instructions to paste into a system prompt, `CLAUDE.md`, or a skill file:
|
|
251
299
|
|
|
252
300
|
```bash
|
|
253
301
|
mast skill # print it
|
|
@@ -261,6 +309,12 @@ marked block, so re-running after an upgrade replaces the previous copy instead
|
|
|
261
309
|
a second one. It never runs on its own, and it never creates a config file you did not
|
|
262
310
|
already keep.
|
|
263
311
|
|
|
312
|
+
**What is verified.** In Claude Code, both hooks were observed delivering their text to the
|
|
313
|
+
model in one session. For Cursor, VS Code and Windsurf, the hook formats and rules-file
|
|
314
|
+
locations were read from the vendor's documentation and nothing was run inside the tool.
|
|
315
|
+
The list of files Zed reads was not checked against Zed's documentation. Whether any of
|
|
316
|
+
this changes how often an agent uses mast has not been measured.
|
|
317
|
+
|
|
264
318
|
---
|
|
265
319
|
|
|
266
320
|
## Upgrading
|
|
@@ -279,6 +333,13 @@ it on the next `serve` or `index`. Nothing is lost that cannot be rebuilt — th
|
|
|
279
333
|
derived state — but on a large monorepo it is minutes, and it is better known in advance
|
|
280
334
|
than discovered as an unexplained stall.
|
|
281
335
|
|
|
336
|
+
If mast's hooks, rules files or skill blocks are installed in the project (or hook files
|
|
337
|
+
under your home directory), the report ends with an "After upgrading" block listing the
|
|
338
|
+
commands to re-run, such as `mast setup claude --check` and `mast skill --install`. It runs
|
|
339
|
+
on the version you have now, so it cannot know what the new version would write: it only
|
|
340
|
+
knows the files exist, and `--check` is what compares them. A project with none of these
|
|
341
|
+
gets no such block.
|
|
342
|
+
|
|
282
343
|
---
|
|
283
344
|
|
|
284
345
|
## Using MAST in a monorepo
|
|
@@ -289,7 +350,10 @@ tool rather than one index per package.
|
|
|
289
350
|
|
|
290
351
|
**What is indexed.** `.ts`, `.tsx`, `.js`, `.jsx`, and `.md`, minus `node_modules`,
|
|
291
352
|
`dist`, `build`, `coverage`, `.next`, `.turbo`, `.mast`, and test files. Override with
|
|
292
|
-
`--extensions` and `--exclude` on `mast init`, or
|
|
353
|
+
`--extensions` and `--exclude` on `mast init`, or — for a setting the whole team should
|
|
354
|
+
get — `file_extensions` / `exclude_patterns` in `mast.config.json` at the project root.
|
|
355
|
+
Editing `.mast/config.json` also works and is read back, but that file is gitignored and
|
|
356
|
+
per-machine, so the change will not travel; `mast.config.json` outranks it.
|
|
293
357
|
|
|
294
358
|
**Other languages are not indexed, and this matters.** MAST parses TypeScript and
|
|
295
359
|
JavaScript only. A symbol defined in Python, Go, Java, or Rust is absent from the index,
|
|
@@ -297,7 +361,16 @@ which looks exactly like absent from the repository. Treat an empty result as "M
|
|
|
297
361
|
not find it", never as "it does not exist" — `mast skill` says this to the model too.
|
|
298
362
|
|
|
299
363
|
**Add `.mast/` to `.gitignore`.** It is derived state, it is large, and it is
|
|
300
|
-
machine-specific.
|
|
364
|
+
machine-specific — on a 14k-file monorepo it is around 420 MB, almost all of it `graph.db`.
|
|
365
|
+
Ignore the whole directory, including `.mast/config.json`: that file is a *resolved*
|
|
366
|
+
snapshot and carries absolute paths (`project_root`, `resolved_state_dir`) that mean
|
|
367
|
+
nothing on anyone else's machine. The file meant to be committed is `mast.config.json` at
|
|
368
|
+
the project root — see the next paragraph.
|
|
369
|
+
|
|
370
|
+
**If you move the index, move the ignore rule with it.** `.mast/` is the default location,
|
|
371
|
+
not the only one: a `state_dir` in `mast.config.json`, a `MAST_STATE_DIR` in the
|
|
372
|
+
environment, or a `--state-dir` flag all put the index somewhere else, and a `.gitignore`
|
|
373
|
+
naming `.mast/` then protects nothing.
|
|
301
374
|
|
|
302
375
|
**A custom index location is not remembered between runs.** `--state-dir` applies to the
|
|
303
376
|
one command you pass it to. Path settings are deliberately never read back out of a
|
|
@@ -351,9 +424,19 @@ Options:
|
|
|
351
424
|
-e, --exported Only exported symbols
|
|
352
425
|
-f, --file <glob> Restrict to files matching a glob
|
|
353
426
|
--state-dir <dir> State directory
|
|
427
|
+
--reindex Incrementally reindex before searching
|
|
354
428
|
--json Emit the raw MCP response instead of text
|
|
355
429
|
```
|
|
356
430
|
|
|
431
|
+
`--reindex` exists because the CLI has neither freshness mechanism the MCP server has:
|
|
432
|
+
no file watcher, and no cached freshness probe (a one-shot process has no lifetime to
|
|
433
|
+
amortise one over). Without it, a file created since the last index run is invisible —
|
|
434
|
+
JIT staleness only re-parses files the index already knows. It is opt-in because it adds
|
|
435
|
+
a whole incremental index run to what is otherwise a single query, and it reports what it
|
|
436
|
+
did on **stderr**, so `--json` consumers keep a parseable stdout. A reindex that loses
|
|
437
|
+
`structure.lock` to a concurrent writer — likelier now that `mast serve` watches by
|
|
438
|
+
default — warns and queries the existing index rather than failing the search.
|
|
439
|
+
|
|
357
440
|
**Why:** the fastest way to check what the index actually contains, and the same code path
|
|
358
441
|
the MCP `mast_search` tool uses — it dispatches through the registered handler rather than
|
|
359
442
|
re-implementing ranking, so CLI and assistant results cannot disagree. Staleness and
|
|
@@ -390,10 +473,16 @@ Start the MCP server over stdio.
|
|
|
390
473
|
Options:
|
|
391
474
|
--state-dir <dir> State directory
|
|
392
475
|
--no-startup-reindex Skip the startup staleness check (not recommended)
|
|
476
|
+
--no-watch Do not watch source files (batch/container use)
|
|
393
477
|
--watch Watch source files and incrementally reindex on change
|
|
394
|
-
(
|
|
478
|
+
(the default; accepted for compatibility)
|
|
395
479
|
```
|
|
396
480
|
|
|
481
|
+
Watching is **on by default**. JIT staleness only re-parses files the index already knows,
|
|
482
|
+
so without a watcher a file created during a session stays invisible to every read tool
|
|
483
|
+
until something reindexes — and nothing does. A watcher failure (EMFILE, permissions) logs
|
|
484
|
+
a warning and the server keeps serving, so the default cannot stop `serve` from starting.
|
|
485
|
+
|
|
397
486
|
The server implements a four-step startup ladder so MCP clients get a usable server in under a second even for large projects. See [Startup Ladder](#startup-ladder) for details.
|
|
398
487
|
|
|
399
488
|
---
|
|
@@ -442,6 +531,7 @@ Invoke any MCP read tool directly, with byte-identical output to the MCP transpo
|
|
|
442
531
|
```
|
|
443
532
|
Options:
|
|
444
533
|
--state-dir <dir> State directory
|
|
534
|
+
--reindex Incrementally reindex before querying (see `mast search --reindex`)
|
|
445
535
|
--json Emit the exact single-line MCP response (default pretty-prints)
|
|
446
536
|
```
|
|
447
537
|
|
|
@@ -459,8 +549,9 @@ tool that does not exist lists the ones that do.
|
|
|
459
549
|
|
|
460
550
|
### `mast docs [topic]`
|
|
461
551
|
|
|
462
|
-
Print documentation shipped with the installed build — `readme`, `spec`,
|
|
463
|
-
|
|
552
|
+
Print documentation shipped with the installed build — `readme`, `spec`, `skill`, or
|
|
553
|
+
`signals` (the staleness, truncation and emptiness flags on an answer). No argument lists
|
|
554
|
+
the topics with the version they belong to.
|
|
464
555
|
|
|
465
556
|
**Why:** removes the step where a reader looks up their version and then finds docs for a
|
|
466
557
|
different one. What `mast docs` prints is what the binary in your `node_modules` does.
|
|
@@ -479,10 +570,117 @@ Options:
|
|
|
479
570
|
```
|
|
480
571
|
|
|
481
572
|
**Why:** registering the MCP server gives a model the tools but not the judgement — when to
|
|
482
|
-
search instead of reading, that code tokens beat prose in a query
|
|
483
|
-
|
|
484
|
-
not find it", not "it does not exist", which is the single most
|
|
485
|
-
right about a search tool
|
|
573
|
+
search instead of reading, and that code tokens beat prose in a query. The text is short
|
|
574
|
+
(under 4,000 characters) so it fits a rules file. It also tells the model that an empty
|
|
575
|
+
result means "MAST did not find it", not "it does not exist", which is the single most
|
|
576
|
+
consequential thing to get right about a search tool, and points at `mast docs signals` for
|
|
577
|
+
how to read the individual flags.
|
|
578
|
+
|
|
579
|
+
---
|
|
580
|
+
|
|
581
|
+
### `mast prime [path]`
|
|
582
|
+
|
|
583
|
+
Print the session primer: a short rule set for using mast, plus the live index health.
|
|
584
|
+
|
|
585
|
+
```
|
|
586
|
+
Options:
|
|
587
|
+
--state-dir <dir> State directory
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
**Why:** it is the text an agent should be given at the start of a session. When the index
|
|
591
|
+
is fresh or stale it prints the rules and the file count and age of the index (a stale
|
|
592
|
+
index adds the changed/unindexed/deleted split and a `mast_reindex` instruction). When
|
|
593
|
+
there is no index, or the index describes a different tree, it withholds the rules and says
|
|
594
|
+
what is wrong. It exits 0 in every state, unlike `mast status`.
|
|
595
|
+
|
|
596
|
+
---
|
|
597
|
+
|
|
598
|
+
### `mast hook <harness> <event>`
|
|
599
|
+
|
|
600
|
+
The entry point for agent hooks. Reads the harness's hook JSON on stdin and writes that
|
|
601
|
+
harness's JSON envelope on stdout, or writes nothing. `<harness>` is `claude`, `cursor` or
|
|
602
|
+
`vscode`; `<event>` is `session-start` or `search`.
|
|
603
|
+
|
|
604
|
+
- `session-start` emits the same text `mast prime` prints for the project (the hook's `cwd`,
|
|
605
|
+
else the first workspace root, else the current directory), in every index state.
|
|
606
|
+
- `search` emits a one-line reminder to try `mast_search` first. It stays silent when no
|
|
607
|
+
index exists for the project, or when the search is scoped by `type`, `glob` or `path` to
|
|
608
|
+
a language mast does not index. "Indexes" follows the project's own `file_extensions`
|
|
609
|
+
where it sets one, so a project that indexes `.mjs` is reminded on a `*.mjs` search.
|
|
610
|
+
|
|
611
|
+
```
|
|
612
|
+
Arguments:
|
|
613
|
+
harness claude | cursor | vscode
|
|
614
|
+
event session-start | search
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
**Why:** a hook that fails breaks the user's session, so this command exits 0 for every
|
|
618
|
+
ordinary condition (empty or malformed stdin, an unknown harness or event, a missing index)
|
|
619
|
+
and leaves stdout empty, with one line on stderr where something went wrong. `search` runs
|
|
620
|
+
before every Grep, so it is dispatched before the rest of the CLI loads.
|
|
621
|
+
|
|
622
|
+
---
|
|
623
|
+
|
|
624
|
+
### `mast setup <harness> [path]`
|
|
625
|
+
|
|
626
|
+
Install what tells an agent to use mast: hooks that prime it at session start and remind it
|
|
627
|
+
before a built-in search, and rules files for harnesses that read them. `<harness>` is
|
|
628
|
+
`claude`, `cursor`, `vscode`, `windsurf`, `zed` or `desktop`; `[path]` is the project root
|
|
629
|
+
(default: the current directory).
|
|
630
|
+
|
|
631
|
+
| harness | project file (default) | `--global` |
|
|
632
|
+
|---|---|---|
|
|
633
|
+
| `claude` | `.claude/settings.json` | `~/.claude/settings.json` |
|
|
634
|
+
| `cursor` | `.cursor/hooks.json` and `.cursor/rules/mast.mdc` | `~/.cursor/hooks.json` only; Cursor has no user-level rules file, and a note says so |
|
|
635
|
+
| `vscode` | `.github/hooks/mast.json` | `~/.copilot/hooks/mast.json` |
|
|
636
|
+
| `windsurf` | `.windsurf/rules/mast.md`, or `.devin/rules/mast.md` if a `.devin` directory exists | refused (exit 1) |
|
|
637
|
+
| `zed` | a marked block in the first existing of `.rules`, `.cursorrules`, `.windsurfrules`, `.clinerules`, `.github/copilot-instructions.md`, `AGENT.md`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md` | refused (exit 1) |
|
|
638
|
+
| `desktop` | nothing | nothing |
|
|
639
|
+
|
|
640
|
+
```
|
|
641
|
+
Options:
|
|
642
|
+
--global Write the user-level file instead of the project one
|
|
643
|
+
--check Write nothing; exit 0 only if everything is installed and current
|
|
644
|
+
--remove Remove what mast installed
|
|
645
|
+
--dry-run Print what would be written, and write nothing
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
`claude` and `cursor` get both hooks (`mast hook <harness> session-start` and
|
|
649
|
+
`mast hook <harness> search`). **`vscode` gets the session primer only:** VS Code ignores hook
|
|
650
|
+
matchers, so a search hook would run before every tool call, and the name of its search tool
|
|
651
|
+
is not documented. **`windsurf`, `zed` and `desktop` have no hook system mast can use**, so
|
|
652
|
+
the first line of output says that only static instructions are installed. `desktop` writes
|
|
653
|
+
nothing: its only channel is the instructions string `mast serve` sends in the MCP handshake,
|
|
654
|
+
which needs no setup, and every flag exits 0 after saying so.
|
|
655
|
+
|
|
656
|
+
The rules files carry the text `mast skill` prints. `mast.mdc` (frontmatter `description` and
|
|
657
|
+
`alwaysApply: true`) and the Windsurf `mast.md` (frontmatter `trigger: always_on`) belong to
|
|
658
|
+
mast outright, and are overwritten if they differ; there is no marker, the name is the claim.
|
|
659
|
+
The Windsurf file stays under Windsurf's documented 12,000-character limit, checked in a test.
|
|
660
|
+
`zed` never creates a file: if none of Zed's candidates exists it writes nothing and exits 1,
|
|
661
|
+
telling you to create `.rules` and run it again, and otherwise it splices the same marked
|
|
662
|
+
block `mast skill --install` uses into the first one that exists. `--remove` takes out that
|
|
663
|
+
block, from every candidate that carries it, and leaves the file. The Zed file list is
|
|
664
|
+
from memory of Zed's documentation and has not been checked against it.
|
|
665
|
+
|
|
666
|
+
**Why:** the hook command depends on how mast is installed. A global install writes
|
|
667
|
+
`mast hook ...`; a source checkout writes `node "<path to dist/cli/index.js>" hook ...`, a
|
|
668
|
+
path specific to your machine, so do not commit that file; a project dependency writes a path
|
|
669
|
+
into `node_modules/.bin`. A project dependency cannot be installed with `--global`: a
|
|
670
|
+
user-level hook pointing into one project's `node_modules` breaks in every other project.
|
|
671
|
+
For VS Code the relative `node_modules/.bin/mast` is unverified, because its docs do not
|
|
672
|
+
say what directory hooks run in.
|
|
673
|
+
|
|
674
|
+
For hook files it only ever touches entries whose command ends in `hook <harness> session-start`
|
|
675
|
+
or `hook <harness> search`. Every other key, hook and field in the file is kept, in order, and
|
|
676
|
+
the file keeps its indentation and trailing newline. Re-running changes nothing and does not
|
|
677
|
+
write any file; a changed install (say, source to global) replaces the entry in place. A file
|
|
678
|
+
that is not valid JSON, or whose `hooks` have an unexpected shape, is reported and left
|
|
679
|
+
untouched (exit 1). `--remove` deletes only mast's entries, and for `vscode` deletes
|
|
680
|
+
`mast.json` once nothing else is in it. `--check` cannot be combined with `--remove` or
|
|
681
|
+
`--dry-run` (exit 2), nor can an unknown harness be given (exit 2). For `cursor`, `--check`
|
|
682
|
+
exits 0 only if both the hooks file and the rules file are current. Nothing here has been
|
|
683
|
+
run inside Cursor, VS Code, Windsurf or Zed.
|
|
486
684
|
|
|
487
685
|
---
|
|
488
686
|
|
|
@@ -493,7 +691,9 @@ Check for a newer release; print how to install it, and what it will cost.
|
|
|
493
691
|
**Why:** it detects how MAST was installed and prints the matching command rather than
|
|
494
692
|
running it, because a CLI cannot reliably distinguish a global install from a dev
|
|
495
693
|
dependency. It also reports whether the upgrade bumps the index schema — which forces a
|
|
496
|
-
full reindex on the next `serve` — and your package manager cannot tell you that.
|
|
694
|
+
full reindex on the next `serve` — and your package manager cannot tell you that. When
|
|
695
|
+
mast's hooks, rules files or skill blocks are installed, it lists the `mast setup <harness>
|
|
696
|
+
--check` and `mast skill --install` commands to re-run afterwards.
|
|
497
697
|
|
|
498
698
|
---
|
|
499
699
|
|
|
@@ -512,6 +712,31 @@ MAST registers 11 tools with the MCP server. Every read tool includes a `_stats`
|
|
|
512
712
|
}
|
|
513
713
|
```
|
|
514
714
|
|
|
715
|
+
### The signals
|
|
716
|
+
|
|
717
|
+
Beyond the results, a response carries fields describing what MAST **does not know** about
|
|
718
|
+
the answer it just gave. All but the last are omitted entirely when they do not apply, so
|
|
719
|
+
their absence carries meaning and their presence is never noise. `truncated` is the one
|
|
720
|
+
exception — it is a required field on every `type_context` entry and is present-and-`false`
|
|
721
|
+
in the ordinary case, so read it, don't test for it.
|
|
722
|
+
|
|
723
|
+
| signal | carried by | means |
|
|
724
|
+
|---|---|---|
|
|
725
|
+
| `stale` | per result of `mast_search`, `mast_implementors` | this result's file changed on disk since it was indexed. The content and line numbers shown may be out of date; no re-parse was attempted (see [JIT Staleness Checks](#jit-staleness-checks)) |
|
|
726
|
+
| `file_busy_returning_stale_cache` | `mast_signature`, `mast_callers`, `mast_exports`, `mast_dependencies`, `mast_rename_impact` | a re-parse *was* attempted and lost to a concurrent writer, so the previous chunk was returned. Contended, not wrong by design — retry shortly |
|
|
727
|
+
| `index_empty` | the empty answer of any of the eight tools that return a result set | nothing is indexed at all. The answer is empty because there was nothing to answer from, not because nothing matched |
|
|
728
|
+
| `unindexed_files` | `mast_search`, `mast_callers`, `mast_implementors`, `mast_rename_impact`, `mast_project_skeleton` (always); `mast_signature`, `mast_exports`, `mast_dependencies` (on an empty answer only) | this many files exist on disk and are not in the index. The answer was computed over an incomplete corpus — an empty or thin result may mean "not indexed" rather than "not present". The tools that claim an exhaustive set report it even when they found something, because a short list reads exactly like a complete one; the three that answer about one named thing report it only when that thing was not found |
|
|
729
|
+
| `results_truncated` | `mast_signature`, `mast_implementors` | the list was capped at `limit`; the field carries the real, uncapped total |
|
|
730
|
+
| `exports_truncated` | `mast_exports` | the same, for a module's export list |
|
|
731
|
+
| `potential_truncated` | `mast_callers`, `mast_rename_impact` | the unresolved-candidate fetch was capped at 50; the field carries the real match count |
|
|
732
|
+
| `truncated` | a `type_context` entry of `mast_signature` | that referenced type's declaration was clipped at 50 lines. The one signal that *is* always present, as a boolean |
|
|
733
|
+
|
|
734
|
+
Two distinctions that are not flags but carry the same weight: in `mast_callers` and
|
|
735
|
+
`mast_rename_impact`, a **`verified_caller`** carries a `resolution` naming how the edge was
|
|
736
|
+
statically proven and is safe to act on, while a **`potential_match`** carries a `reason` and
|
|
737
|
+
is a name match with no proven edge — review before editing. And an empty result is never
|
|
738
|
+
proof of absence: MAST indexes TypeScript, JavaScript, and Markdown only.
|
|
739
|
+
|
|
515
740
|
---
|
|
516
741
|
|
|
517
742
|
### `mast_search`
|
|
@@ -529,7 +754,7 @@ Lexical BM25 + declaration-exact search over the indexed codebase.
|
|
|
529
754
|
}
|
|
530
755
|
```
|
|
531
756
|
|
|
532
|
-
**Returns:** `{ results[], suggestions?, _stats }`. Each result includes `file_path`, `start_line`, `end_line`, `content`, `chunk_type`, `symbol_name`, `parent_symbol`, `is_exported`, `match_score` (BM25 score, negative; `null` when the hit came only from ranker D), `rank`, `match_snippet`, and an optional `related` hint when a method and its class shell both matched (only the higher-ranked one is returned). `suggestions` is present, possibly empty, only when `results` is empty — a zero-result "did you mean" assist.
|
|
757
|
+
**Returns:** `{ results[], suggestions?, index_empty?, unindexed_files?, _stats }`. Each result includes `file_path`, `start_line`, `end_line`, `content`, `chunk_type`, `symbol_name`, `parent_symbol`, `is_exported`, `match_score` (BM25 score, negative; `null` when the hit came only from ranker D), `rank`, `match_snippet`, an optional `stale` flag, and an optional `related` hint when a method and its class shell both matched (only the higher-ranked one is returned). `suggestions` is present, possibly empty, only when `results` is empty — a zero-result "did you mean" assist. See [The signals](#the-signals) for `stale`, `index_empty`, and `unindexed_files`.
|
|
533
758
|
|
|
534
759
|
**Why:** `grep` and `glob` find exact strings and require the caller to already know the pattern. `mast_search` ranks by relevance across two signals fused with Reciprocal Rank Fusion:
|
|
535
760
|
|
|
@@ -776,13 +1001,34 @@ with default `k = 60`. A chunk appearing at rank 1 in both lists scores twice as
|
|
|
776
1001
|
|
|
777
1002
|
### JIT Staleness Checks
|
|
778
1003
|
|
|
779
|
-
|
|
1004
|
+
Read tools handle a file that changed since it was indexed in one of **two** ways. Which one a tool
|
|
1005
|
+
uses is fixed per tool, not decided at runtime:
|
|
1006
|
+
|
|
1007
|
+
**Re-parse inline** — `mast_signature`, `mast_callers`, `mast_exports`, `mast_dependencies`,
|
|
1008
|
+
`mast_rename_impact`. Before returning, each calls `jitRefreshFile`, which:
|
|
780
1009
|
|
|
781
|
-
1. Reads the stored mtime for the file from the `files` table.
|
|
1010
|
+
1. Reads the stored mtime for the file from the `files` table. **If there is no row, it returns
|
|
1011
|
+
immediately** — an unindexed file has no stored mtime to compare against, which is the whole of
|
|
1012
|
+
why JIT cannot discover new files.
|
|
782
1013
|
2. Calls `stat()` on the file on disk.
|
|
783
|
-
3. If the disk mtime is newer, acquires the `structure.lock` and re-parses the file immediately
|
|
1014
|
+
3. If the disk mtime is newer, acquires the `structure.lock` and re-parses the file immediately,
|
|
1015
|
+
on the request path — the answer waits for it.
|
|
1016
|
+
|
|
1017
|
+
If the lock is held by a concurrent writer the previous chunk is returned with
|
|
1018
|
+
`file_busy_returning_stale_cache` set, so the caller is told rather than quietly served stale data.
|
|
1019
|
+
|
|
1020
|
+
**Stat and flag** — `mast_search`, `mast_implementors`. These call `findStaleFiles`, which stats the
|
|
1021
|
+
files behind the results and sets `stale: true` on the affected ones. **No re-parse is attempted**:
|
|
1022
|
+
taking a write lock on a ranked result set would serialise the cheapest tools in the package behind
|
|
1023
|
+
the most expensive operation in it. The line coordinates on a flagged result may be off; the caller
|
|
1024
|
+
is expected to re-read or call a re-parsing tool.
|
|
1025
|
+
|
|
1026
|
+
**Neither** — `mast_project_skeleton` (documented exempt) and `mast_efficiency`.
|
|
784
1027
|
|
|
785
|
-
|
|
1028
|
+
Both mechanisms only ever touch files the index **already knows**. Neither can discover a file that
|
|
1029
|
+
was never indexed, so a file created during a session is invisible to every read tool until
|
|
1030
|
+
something reindexes it — which is why `mast serve` watches by default, and why every
|
|
1031
|
+
primary-result tool reports `unindexed_files` when the index is nonetheless behind.
|
|
786
1032
|
|
|
787
1033
|
### Startup Ladder
|
|
788
1034
|
|
package/assets/prime.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Using mast
|
|
2
|
+
|
|
3
|
+
mast indexes this repository's TypeScript, JavaScript and Markdown at the AST level.
|
|
4
|
+
|
|
5
|
+
- To find code (a symbol, its callers, a module's exports), call mast before grep, glob or
|
|
6
|
+
reading whole files. It returns ranked declarations, not line matches.
|
|
7
|
+
- Put code tokens in the query: function, type and column names. An exact symbol name
|
|
8
|
+
anchors its declaration to the top. If a query returns nothing, change the vocabulary.
|
|
9
|
+
- `mast_search`: discover code by name or token.
|
|
10
|
+
- `mast_signature`: a symbol's declaration and resolved parameter types.
|
|
11
|
+
- `mast_callers`: who calls a function. Run it before any refactor.
|
|
12
|
+
- `mast_exports`: a module's public API, without reading the file.
|
|
13
|
+
- `mast_rename_impact`: the checklist for a rename.
|
|
14
|
+
- Use grep for other languages, non-code files, or an exact regex over text.
|
|
15
|
+
- An empty result is not proof of absence. Check `index_empty`, `unindexed_files` and
|
|
16
|
+
`stale` on the response before concluding something does not exist.
|
|
17
|
+
- Call `mast_reindex` after creating or renaming files. A new file is invisible to every
|
|
18
|
+
read tool until an index pass runs.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# MAST signal reference
|
|
2
|
+
|
|
3
|
+
The fields MAST puts on an answer to say what it does not know, and how it treats a file that
|
|
4
|
+
changed after it was indexed. `mast skill` carries the short rules; this is the detail behind them.
|
|
5
|
+
|
|
6
|
+
## How MAST handles a file that changed since it was indexed
|
|
7
|
+
|
|
8
|
+
Two mechanisms, and which one you get depends on the tool. Neither can see a file that
|
|
9
|
+
was never indexed at all.
|
|
10
|
+
|
|
11
|
+
- **Re-parsed for you, before the answer** — `mast_signature`, `mast_callers`,
|
|
12
|
+
`mast_exports`, `mast_dependencies`, `mast_rename_impact`. If the re-parse loses a
|
|
13
|
+
race with a writer, the result carries `file_busy_returning_stale_cache`.
|
|
14
|
+
- **Flagged, not re-parsed** — `mast_search`, `mast_implementors`. Affected results
|
|
15
|
+
carry `stale: true`. The code and line numbers shown may be out of date; call one of
|
|
16
|
+
the tools above, or `mast_reindex`, to get the current version.
|
|
17
|
+
|
|
18
|
+
Both only cover files already in the index. That is why creating a file needs an
|
|
19
|
+
explicit `mast_reindex`.
|
|
20
|
+
|
|
21
|
+
## Reading the answers honestly
|
|
22
|
+
|
|
23
|
+
MAST reports what it does not know. These signals are load-bearing. All but the last are
|
|
24
|
+
**omitted entirely when they do not apply** — so their absence is meaningful, and their
|
|
25
|
+
presence is never `false`. `truncated` is the exception: it is always present on a
|
|
26
|
+
`type_context` entry, so check its value rather than its presence.
|
|
27
|
+
|
|
28
|
+
| signal | on | means |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| `stale` | per result of `mast_search`, `mast_implementors` | this result's file changed since indexing; line numbers may be wrong |
|
|
31
|
+
| `file_busy_returning_stale_cache` | the five re-parsing tools | a refresh was attempted and lost to a writer; retry shortly |
|
|
32
|
+
| `index_empty` | the empty answer of any of the eight tools that return a result set | **nothing is indexed at all.** This is not "no match" — run `mast_reindex`, or check that `mast_status` names the tree you meant |
|
|
33
|
+
| `unindexed_files` | `mast_search`, `mast_callers`, `mast_implementors`, `mast_rename_impact`, `mast_project_skeleton` (always); `mast_signature`, `mast_exports`, `mast_dependencies` (on an empty answer only) | that many files on disk are not in the index, so this answer was computed over an incomplete corpus. **An empty result carrying this is not evidence of absence.** The set-returning tools report it even with hits — a short list of callers reads exactly like a complete one |
|
|
34
|
+
| `results_truncated` | `mast_signature`, `mast_implementors` | you got the first page, not the answer. The field carries the real total; raise `limit` or narrow the query |
|
|
35
|
+
| `exports_truncated` | `mast_exports` | the same, for a module's export list |
|
|
36
|
+
| `potential_truncated` | `mast_callers`, `mast_rename_impact` | the unresolved-candidate set was capped; the real count is larger |
|
|
37
|
+
| `truncated` | a type in `mast_signature`'s `type_context` | that declaration was clipped at 50 lines |
|
|
38
|
+
|
|
39
|
+
Two more things that are not flags:
|
|
40
|
+
|
|
41
|
+
- In `mast_callers` and `mast_rename_impact`, **`verified_callers` and
|
|
42
|
+
`potential_matches` are not the same claim.** A verified caller carries a `resolution`
|
|
43
|
+
and is safe to act on. A potential match carries a `reason` and is a name match with
|
|
44
|
+
no proven edge — review it before editing it.
|
|
45
|
+
- An **empty result is not proof of absence.** MAST indexes TypeScript, JavaScript, and
|
|
46
|
+
Markdown only — a symbol defined in Python, Go, Java, or any other language is absent
|
|
47
|
+
from the index, not absent from the repository. Check `index_empty` and
|
|
48
|
+
`unindexed_files` before concluding "it isn't there", and **never delete or rewrite
|
|
49
|
+
code on the strength of an empty result alone.** Every result-set tool carries
|
|
50
|
+
`unindexed_files` now, not just `mast_search` — so an empty `mast_callers` answer that
|
|
51
|
+
carries it is not a green light to delete the function.
|
package/assets/skill.md
CHANGED
|
@@ -6,13 +6,19 @@ graph, so prefer it over reading files or grepping.
|
|
|
6
6
|
|
|
7
7
|
## Rules
|
|
8
8
|
|
|
9
|
-
- Call `mast_status` at the start of a session to confirm the index is fresh.
|
|
9
|
+
- Call `mast_status` at the start of a session to confirm the index is fresh. Read
|
|
10
|
+
**`stale_breakdown.unindexed`**: any non-zero value means files exist that MAST has never
|
|
11
|
+
seen, and no amount of querying will find them. Read that field rather than
|
|
12
|
+
`freshness_cause`, which reports a single ranked cause and shows `"phase1_stale"` ahead of
|
|
13
|
+
`"unindexed_files"` whenever both are non-zero.
|
|
10
14
|
- **Search before opening any file.** No file path without a MAST result behind it.
|
|
11
15
|
- **Use code tokens in queries** — function names, type names, column names.
|
|
12
16
|
`createTable uuid primaryKey` beats `migration pattern`. An exact symbol name in the
|
|
13
17
|
query anchors its declaration to the top.
|
|
14
18
|
- When a query returns nothing, **change vocabulary — do not repeat it**.
|
|
15
|
-
- Call `mast_reindex` after
|
|
19
|
+
- **Call `mast_reindex` after creating or renaming files**, before any query that depends
|
|
20
|
+
on what you just wrote. Editing the *body* of a file MAST already knows is handled for
|
|
21
|
+
you; a **new** file is not, and is invisible until an index pass runs.
|
|
16
22
|
|
|
17
23
|
## Picking the right tool
|
|
18
24
|
|
|
@@ -30,16 +36,8 @@ graph, so prefer it over reading files or grepping.
|
|
|
30
36
|
| `mast_status` | index freshness and health |
|
|
31
37
|
| `mast_reindex` | refresh the index after edits |
|
|
32
38
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
answer may predate the file on disk. Do not treat it as current.
|
|
39
|
-
- A **`truncated`** or **`potential_truncated`** flag means the set was capped. The real
|
|
40
|
-
count is larger than what you were shown.
|
|
41
|
-
- An **empty result is not proof of absence.** MAST indexes TypeScript, JavaScript, and
|
|
42
|
-
Markdown only — a symbol defined in Python, Go, Java, or any other language is absent
|
|
43
|
-
from the index, not absent from the repository. Check the flags before concluding
|
|
44
|
-
"it isn't there", and never delete or rewrite code on the strength of an empty result
|
|
45
|
-
alone.
|
|
39
|
+
An empty result is not proof of absence. MAST indexes TypeScript, JavaScript, and Markdown
|
|
40
|
+
only, so a symbol in any other language is absent from the index, not from the repository.
|
|
41
|
+
Check `index_empty` and `unindexed_files` on the response before concluding "it isn't
|
|
42
|
+
there", and never delete or rewrite code on an empty result alone. `mast docs signals`
|
|
43
|
+
prints the full signal reference.
|