@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.
Files changed (150) hide show
  1. package/MAST_SPEC.md +169 -44
  2. package/README.md +266 -20
  3. package/assets/prime.md +18 -0
  4. package/assets/signals.md +51 -0
  5. package/assets/skill.md +13 -15
  6. package/dist/ast/types.d.ts +137 -1
  7. package/dist/ast/types.d.ts.map +1 -1
  8. package/dist/cli/docs-cmd.d.ts +1 -0
  9. package/dist/cli/docs-cmd.d.ts.map +1 -1
  10. package/dist/cli/docs-cmd.js +2 -1
  11. package/dist/cli/docs-cmd.js.map +1 -1
  12. package/dist/cli/hook-cmd.d.ts +3 -0
  13. package/dist/cli/hook-cmd.d.ts.map +1 -0
  14. package/dist/cli/hook-cmd.js +13 -0
  15. package/dist/cli/hook-cmd.js.map +1 -0
  16. package/dist/cli/hook-state-dir.d.ts +24 -0
  17. package/dist/cli/hook-state-dir.d.ts.map +1 -0
  18. package/dist/cli/hook-state-dir.js +57 -0
  19. package/dist/cli/hook-state-dir.js.map +1 -0
  20. package/dist/cli/hook.d.ts +44 -0
  21. package/dist/cli/hook.d.ts.map +1 -0
  22. package/dist/cli/hook.js +200 -0
  23. package/dist/cli/hook.js.map +1 -0
  24. package/dist/cli/index.js +12 -2
  25. package/dist/cli/index.js.map +1 -1
  26. package/dist/cli/installed-artifacts.d.ts +23 -0
  27. package/dist/cli/installed-artifacts.d.ts.map +1 -0
  28. package/dist/cli/installed-artifacts.js +39 -0
  29. package/dist/cli/installed-artifacts.js.map +1 -0
  30. package/dist/cli/prime-cmd.d.ts +17 -0
  31. package/dist/cli/prime-cmd.d.ts.map +1 -0
  32. package/dist/cli/prime-cmd.js +70 -0
  33. package/dist/cli/prime-cmd.js.map +1 -0
  34. package/dist/cli/program.d.ts.map +1 -1
  35. package/dist/cli/program.js +6 -0
  36. package/dist/cli/program.js.map +1 -1
  37. package/dist/cli/query.d.ts +40 -1
  38. package/dist/cli/query.d.ts.map +1 -1
  39. package/dist/cli/query.js +36 -2
  40. package/dist/cli/query.js.map +1 -1
  41. package/dist/cli/search-cmd.d.ts +6 -1
  42. package/dist/cli/search-cmd.d.ts.map +1 -1
  43. package/dist/cli/search-cmd.js +9 -2
  44. package/dist/cli/search-cmd.js.map +1 -1
  45. package/dist/cli/serve.d.ts +6 -1
  46. package/dist/cli/serve.d.ts.map +1 -1
  47. package/dist/cli/serve.js +14 -4
  48. package/dist/cli/serve.js.map +1 -1
  49. package/dist/cli/setup-cmd.d.ts +34 -0
  50. package/dist/cli/setup-cmd.d.ts.map +1 -0
  51. package/dist/cli/setup-cmd.js +205 -0
  52. package/dist/cli/setup-cmd.js.map +1 -0
  53. package/dist/cli/setup-command.d.ts +32 -0
  54. package/dist/cli/setup-command.d.ts.map +1 -0
  55. package/dist/cli/setup-command.js +43 -0
  56. package/dist/cli/setup-command.js.map +1 -0
  57. package/dist/cli/setup-plan.d.ts +52 -0
  58. package/dist/cli/setup-plan.d.ts.map +1 -0
  59. package/dist/cli/setup-plan.js +221 -0
  60. package/dist/cli/setup-plan.js.map +1 -0
  61. package/dist/cli/setup-rules.d.ts +41 -0
  62. package/dist/cli/setup-rules.d.ts.map +1 -0
  63. package/dist/cli/setup-rules.js +76 -0
  64. package/dist/cli/setup-rules.js.map +1 -0
  65. package/dist/cli/setup-static.d.ts +13 -0
  66. package/dist/cli/setup-static.d.ts.map +1 -0
  67. package/dist/cli/setup-static.js +116 -0
  68. package/dist/cli/setup-static.js.map +1 -0
  69. package/dist/cli/skill-install.d.ts +2 -0
  70. package/dist/cli/skill-install.d.ts.map +1 -1
  71. package/dist/cli/skill-install.js +2 -0
  72. package/dist/cli/skill-install.js.map +1 -1
  73. package/dist/cli/status.d.ts +15 -0
  74. package/dist/cli/status.d.ts.map +1 -1
  75. package/dist/cli/status.js +32 -6
  76. package/dist/cli/status.js.map +1 -1
  77. package/dist/cli/upgrade-cmd.d.ts +5 -1
  78. package/dist/cli/upgrade-cmd.d.ts.map +1 -1
  79. package/dist/cli/upgrade-cmd.js +28 -3
  80. package/dist/cli/upgrade-cmd.js.map +1 -1
  81. package/dist/indexer/freshness.d.ts +10 -0
  82. package/dist/indexer/freshness.d.ts.map +1 -1
  83. package/dist/indexer/freshness.js +7 -1
  84. package/dist/indexer/freshness.js.map +1 -1
  85. package/dist/indexer/import-resolver.js +28 -16
  86. package/dist/indexer/import-resolver.js.map +1 -1
  87. package/dist/indexer/index.d.ts +38 -3
  88. package/dist/indexer/index.d.ts.map +1 -1
  89. package/dist/indexer/index.js +47 -4
  90. package/dist/indexer/index.js.map +1 -1
  91. package/dist/indexer/watcher.d.ts +94 -0
  92. package/dist/indexer/watcher.d.ts.map +1 -1
  93. package/dist/indexer/watcher.js +172 -19
  94. package/dist/indexer/watcher.js.map +1 -1
  95. package/dist/mcp/context.d.ts +16 -0
  96. package/dist/mcp/context.d.ts.map +1 -1
  97. package/dist/mcp/freshness-probe.d.ts +82 -0
  98. package/dist/mcp/freshness-probe.d.ts.map +1 -0
  99. package/dist/mcp/freshness-probe.js +111 -0
  100. package/dist/mcp/freshness-probe.js.map +1 -0
  101. package/dist/mcp/instructions.d.ts +7 -0
  102. package/dist/mcp/instructions.d.ts.map +1 -0
  103. package/dist/mcp/instructions.js +10 -0
  104. package/dist/mcp/instructions.js.map +1 -0
  105. package/dist/mcp/server.d.ts +54 -3
  106. package/dist/mcp/server.d.ts.map +1 -1
  107. package/dist/mcp/server.js +79 -4
  108. package/dist/mcp/server.js.map +1 -1
  109. package/dist/mcp/tools/_helpers.d.ts +40 -0
  110. package/dist/mcp/tools/_helpers.d.ts.map +1 -1
  111. package/dist/mcp/tools/_helpers.js +27 -0
  112. package/dist/mcp/tools/_helpers.js.map +1 -1
  113. package/dist/mcp/tools/callers.d.ts.map +1 -1
  114. package/dist/mcp/tools/callers.js +6 -1
  115. package/dist/mcp/tools/callers.js.map +1 -1
  116. package/dist/mcp/tools/dependencies.d.ts.map +1 -1
  117. package/dist/mcp/tools/dependencies.js +2 -1
  118. package/dist/mcp/tools/dependencies.js.map +1 -1
  119. package/dist/mcp/tools/exports.d.ts.map +1 -1
  120. package/dist/mcp/tools/exports.js +2 -1
  121. package/dist/mcp/tools/exports.js.map +1 -1
  122. package/dist/mcp/tools/implementors.d.ts.map +1 -1
  123. package/dist/mcp/tools/implementors.js +2 -1
  124. package/dist/mcp/tools/implementors.js.map +1 -1
  125. package/dist/mcp/tools/project-skeleton.d.ts.map +1 -1
  126. package/dist/mcp/tools/project-skeleton.js +2 -1
  127. package/dist/mcp/tools/project-skeleton.js.map +1 -1
  128. package/dist/mcp/tools/reindex.d.ts.map +1 -1
  129. package/dist/mcp/tools/reindex.js +3 -0
  130. package/dist/mcp/tools/reindex.js.map +1 -1
  131. package/dist/mcp/tools/rename-impact.d.ts.map +1 -1
  132. package/dist/mcp/tools/rename-impact.js +4 -1
  133. package/dist/mcp/tools/rename-impact.js.map +1 -1
  134. package/dist/mcp/tools/search.d.ts.map +1 -1
  135. package/dist/mcp/tools/search.js +13 -2
  136. package/dist/mcp/tools/search.js.map +1 -1
  137. package/dist/mcp/tools/signature.d.ts.map +1 -1
  138. package/dist/mcp/tools/signature.js +2 -1
  139. package/dist/mcp/tools/signature.js.map +1 -1
  140. package/dist/mcp/tools/status.d.ts.map +1 -1
  141. package/dist/mcp/tools/status.js +8 -2
  142. package/dist/mcp/tools/status.js.map +1 -1
  143. package/dist/store/config.d.ts.map +1 -1
  144. package/dist/store/config.js +4 -5
  145. package/dist/store/config.js.map +1 -1
  146. package/dist/store/defaults.d.ts +9 -0
  147. package/dist/store/defaults.d.ts.map +1 -0
  148. package/dist/store/defaults.js +12 -0
  149. package/dist/store/defaults.js.map +1 -0
  150. package/package.json +5 -2
@@ -0,0 +1,200 @@
1
+ // Entry module for `mast hook`. Run by the harness before every Grep, so everything
2
+ // reachable through its STATIC imports must be Node built-ins or repo modules that are
3
+ // themselves built-in-only (asserted by hook-import-graph.test.ts, ADR 017 section 5).
4
+ // The session-start branch loads the heavy modules with a dynamic import() instead.
5
+ import { existsSync, readFileSync, statSync } from 'node:fs';
6
+ import { join, resolve } from 'node:path';
7
+ import { resolveHookConfigLight } from './hook-state-dir.js';
8
+ export const SEARCH_REMINDER = 'mast: for TypeScript, JavaScript and Markdown code, try mast_search first (use code tokens such as function and type names); ' +
9
+ 'grep is still right for other languages and for exact-text regex.';
10
+ // Ripgrep type names (what Claude Code's Grep `type` takes) mapped to the extensions
11
+ // they cover. Hand-kept and deliberately small: only the types whose name differs from
12
+ // their extensions. Any other type name is read as its own extension (`py` as `.py`,
13
+ // `vue` as `.vue`), so a project that indexes extra extensions is still matched.
14
+ const RG_TYPE_EXTENSIONS = {
15
+ ts: ['.ts', '.tsx', '.cts', '.mts'],
16
+ js: ['.js', '.jsx', '.cjs', '.mjs'],
17
+ md: ['.md', '.markdown'],
18
+ markdown: ['.md', '.markdown'],
19
+ };
20
+ function isRecord(value) {
21
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
22
+ }
23
+ function isHarness(value) {
24
+ return value === 'claude' || value === 'cursor' || value === 'vscode';
25
+ }
26
+ function isHookEvent(value) {
27
+ return value === 'session-start' || value === 'search';
28
+ }
29
+ function anyIn(indexed, extensions) {
30
+ return extensions.some((e) => indexed.includes(e.toLowerCase()));
31
+ }
32
+ /** A trailing `.ext` of a path segment. All-digit suffixes (`v1.2`) are versions, not extensions. */
33
+ function trailingExtension(segment) {
34
+ const m = /\.([A-Za-z0-9_]*[A-Za-z_][A-Za-z0-9_]*)$/.exec(segment);
35
+ return m?.[1] === undefined ? null : `.${m[1]}`;
36
+ }
37
+ /** Extensions a glob can match, or null when they cannot be determined (`src/**`, `*.[jt]s`). */
38
+ function globExtensions(glob) {
39
+ const segment = glob.slice(glob.lastIndexOf('/') + 1);
40
+ const braces = /\.\{([^{}]*)\}$/.exec(segment);
41
+ if (braces?.[1] !== undefined) {
42
+ const items = braces[1].split(',').map((s) => s.trim());
43
+ return items.every((s) => /^[A-Za-z0-9_]+$/.test(s)) ? items.map((s) => `.${s}`) : null;
44
+ }
45
+ const single = trailingExtension(segment);
46
+ return single === null ? null : [single];
47
+ }
48
+ function stringField(input, key) {
49
+ const value = input[key];
50
+ return typeof value === 'string' ? value : null;
51
+ }
52
+ /**
53
+ * True when the search's own scoping fields restrict it to files mast does not index.
54
+ * Unrecognised fields and shapes count as "not scoped": a missed reminder is cheaper
55
+ * than a wrong one only when we know the language, and here we do not.
56
+ */
57
+ function isScopedAwayFromIndex(input, facts) {
58
+ if (!isRecord(input) || !isRecord(input['tool_input']))
59
+ return false;
60
+ const toolInput = input['tool_input'];
61
+ const indexed = facts.indexedExtensions;
62
+ const type = stringField(toolInput, 'type');
63
+ if (type !== null && !anyIn(indexed, RG_TYPE_EXTENSIONS[type] ?? [`.${type}`]))
64
+ return true;
65
+ // For the Glob tool the `pattern` IS the glob; for Grep it is a regex and says nothing.
66
+ const glob = input['tool_name'] === 'Glob' ? stringField(toolInput, 'pattern') : stringField(toolInput, 'glob');
67
+ const globExts = glob === null ? null : globExtensions(glob);
68
+ if (globExts !== null && !anyIn(indexed, globExts))
69
+ return true;
70
+ const path = facts.searchPathIsDirectory ? null : stringField(toolInput, 'path');
71
+ const pathExt = path === null ? null : trailingExtension(path.slice(path.lastIndexOf('/') + 1));
72
+ if (pathExt !== null && !anyIn(indexed, [pathExt]))
73
+ return true;
74
+ return false;
75
+ }
76
+ function envelope(harness, event, text) {
77
+ if (harness === 'cursor')
78
+ return { additional_context: text };
79
+ return {
80
+ hookSpecificOutput: {
81
+ hookEventName: event === 'session-start' ? 'SessionStart' : 'PreToolUse',
82
+ additionalContext: text,
83
+ },
84
+ };
85
+ }
86
+ /**
87
+ * The whole decision, pure. Returns the harness's envelope, or null for "print nothing".
88
+ * Unknown harness or event is null rather than a throw: see `runHook` for why.
89
+ */
90
+ export function decide(harness, event, input, facts) {
91
+ if (!isHarness(harness) || !isHookEvent(event))
92
+ return null;
93
+ if (event === 'session-start')
94
+ return envelope(harness, event, facts.primeText);
95
+ if (!facts.indexExists || isScopedAwayFromIndex(input, facts))
96
+ return null;
97
+ return envelope(harness, event, SEARCH_REMINDER);
98
+ }
99
+ /** `cwd`, else the first workspace root, else null (caller falls back to process cwd). */
100
+ function projectRootOf(input) {
101
+ if (typeof input['cwd'] === 'string' && input['cwd'] !== '')
102
+ return input['cwd'];
103
+ const roots = input['workspace_roots'];
104
+ if (Array.isArray(roots) && typeof roots[0] === 'string' && roots[0] !== '')
105
+ return roots[0];
106
+ return null;
107
+ }
108
+ function searchPathOf(input) {
109
+ const toolInput = input['tool_input'];
110
+ return isRecord(toolInput) ? stringField(toolInput, 'path') : null;
111
+ }
112
+ /**
113
+ * I/O shell around `decide`.
114
+ *
115
+ * Never throws and never sets a failing exit code. A hook that fails breaks the user's
116
+ * session, and anything on stdout that is not the envelope is a malformed hook response,
117
+ * so every problem here ends as empty stdout plus one stderr line. Ordinary quiet cases
118
+ * (no index, a search scoped to another language) say nothing at all.
119
+ */
120
+ export async function runHook(harness, event, io) {
121
+ if (!isHarness(harness) || !isHookEvent(event)) {
122
+ io.warn(`mast hook: unknown harness "${harness}" or event "${event}"; expected claude|cursor|vscode and session-start|search`);
123
+ return;
124
+ }
125
+ try {
126
+ const raw = await io.readStdin();
127
+ if (raw.trim() === '') {
128
+ io.warn('mast hook: empty stdin, expected the harness hook JSON');
129
+ return;
130
+ }
131
+ let input;
132
+ try {
133
+ input = JSON.parse(raw);
134
+ }
135
+ catch {
136
+ io.warn('mast hook: stdin is not valid JSON');
137
+ return;
138
+ }
139
+ if (!isRecord(input)) {
140
+ io.warn('mast hook: stdin JSON is not an object');
141
+ return;
142
+ }
143
+ const projectRoot = projectRootOf(input) ?? io.cwd();
144
+ const out = decide(harness, event, input, await gatherFacts(event, input, projectRoot, io));
145
+ if (out !== null)
146
+ io.write(JSON.stringify(out));
147
+ }
148
+ catch (error) {
149
+ io.warn(`mast hook ${harness} ${event}: ${error instanceof Error ? error.message : String(error)}`);
150
+ }
151
+ }
152
+ async function gatherFacts(event, input, projectRoot, io) {
153
+ if (event === 'session-start') {
154
+ return {
155
+ indexExists: false,
156
+ primeText: await io.prime(projectRoot),
157
+ searchPathIsDirectory: false,
158
+ indexedExtensions: [],
159
+ };
160
+ }
161
+ const config = resolveHookConfigLight(projectRoot, io.env);
162
+ const searchPath = searchPathOf(input);
163
+ return {
164
+ indexExists: io.fileExists(join(config.stateDir, 'index.json')),
165
+ primeText: '',
166
+ searchPathIsDirectory: searchPath !== null && io.isDirectory(resolve(projectRoot, searchPath)),
167
+ indexedExtensions: config.fileExtensions.map((e) => e.toLowerCase()),
168
+ };
169
+ }
170
+ async function readProcessStdin() {
171
+ // A TTY means someone ran the command by hand; waiting for EOF would just hang.
172
+ if (process.stdin.isTTY)
173
+ return '';
174
+ // Streamed rather than readFileSync(0): that throws EAGAIN on some non-blocking pipes.
175
+ process.stdin.setEncoding('utf8');
176
+ let text = '';
177
+ for await (const chunk of process.stdin)
178
+ text += String(chunk);
179
+ return text;
180
+ }
181
+ /** Production wiring, called from `cli/index.ts` and from the commander registration. */
182
+ export async function runHookFromProcess(harness, event) {
183
+ await runHook(harness, event, {
184
+ readStdin: readProcessStdin,
185
+ write: (text) => { process.stdout.write(text); },
186
+ warn: (line) => { process.stderr.write(`${line}\n`); },
187
+ env: process.env,
188
+ cwd: () => process.cwd(),
189
+ fileExists: existsSync,
190
+ isDirectory: (path) => statSync(path, { throwIfNoEntry: false })?.isDirectory() ?? false,
191
+ prime: async (projectRoot) => {
192
+ // Dynamic so the search path never pays for them (ADR 017 section 5).
193
+ const { buildStatus } = await import('./status.js');
194
+ const { renderPrime, PRIME_ASSET_PATH } = await import('./prime-cmd.js');
195
+ const status = await buildStatus({ path: projectRoot });
196
+ return renderPrime(status, readFileSync(PRIME_ASSET_PATH, 'utf8'), new Date());
197
+ },
198
+ });
199
+ }
200
+ //# sourceMappingURL=hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/cli/hook.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -1,4 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import { buildProgram } from './program.js';
3
- await buildProgram().parseAsync(process.argv);
2
+ // `hook` is dispatched before the program is imported: a hook runs ahead of every Grep,
3
+ // and importing the program (commander, zod, typescript, kysely, the MCP SDK) costs about
4
+ // a second. See ADR 017 section 5 and hook-import-graph.test.ts.
5
+ if (process.argv[2] === 'hook') {
6
+ const { runHookFromProcess } = await import('./hook.js');
7
+ await runHookFromProcess(process.argv[3] ?? '', process.argv[4] ?? '');
8
+ }
9
+ else {
10
+ const { buildProgram } = await import('./program.js');
11
+ await buildProgram().parseAsync(process.argv);
12
+ }
13
+ export {};
4
14
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,YAAY,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,wFAAwF;AACxF,0FAA0F;AAC1F,iEAAiE;AACjE,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;IAC/B,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IACzD,MAAM,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AACzE,CAAC;KAAM,CAAC;IACN,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IACtD,MAAM,YAAY,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { Harness } from './hook.js';
2
+ /**
3
+ * What of mast's own writing `mast upgrade` found installed, so it can say what to re-check
4
+ * after upgrading. `mast upgrade` runs on the OLD binary and cannot know what a newer
5
+ * version's files should contain; it can only know that they exist.
6
+ */
7
+ export interface InstalledArtifacts {
8
+ /** Harnesses whose project-level hook file holds a mast hook command. */
9
+ readonly projectHooks: readonly Harness[];
10
+ /** Harnesses whose user-level hook file holds a mast hook command. */
11
+ readonly globalHooks: readonly Harness[];
12
+ /** Harnesses with a mast-owned rules file in the project. */
13
+ readonly rulesHarnesses: readonly ('cursor' | 'windsurf')[];
14
+ /** Zed rules files, outside the `mast skill --install` set, that carry the marked block. */
15
+ readonly zedOnlyBlockFiles: readonly string[];
16
+ /** Files `mast skill --install` reaches that carry the marked block. */
17
+ readonly skillBlockFiles: readonly string[];
18
+ }
19
+ export declare const NO_INSTALLED_ARTIFACTS: InstalledArtifacts;
20
+ /** Null for a file that is absent or unreadable: an advisory scan cannot fail `mast upgrade`. */
21
+ export declare function readFileOrNull(path: string): string | null;
22
+ export declare function findInstalledArtifacts(projectRoot: string, home: string, readFile: (path: string) => string | null): InstalledArtifacts;
23
+ //# sourceMappingURL=installed-artifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installed-artifacts.d.ts","sourceRoot":"","sources":["../../src/cli/installed-artifacts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,SAAS,OAAO,EAAE,CAAC;IAC1C,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,SAAS,OAAO,EAAE,CAAC;IACzC,6DAA6D;IAC7D,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC,QAAQ,GAAG,UAAU,CAAC,EAAE,CAAC;IAC5D,4FAA4F;IAC5F,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,wEAAwE;IACxE,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED,eAAO,MAAM,sBAAsB,EAAE,kBAEpC,CAAC;AAIF,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM1D;AAOD,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GACxC,kBAAkB,CAiBpB"}
@@ -0,0 +1,39 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { hookFilePath } from './setup-command.js';
4
+ import { cursorRulesPath, windsurfRulesPaths, ZED_RULES_FILES } from './setup-rules.js';
5
+ import { BEGIN_MARKER, SKILL_TARGET_FILES } from './skill-install.js';
6
+ export const NO_INSTALLED_ARTIFACTS = {
7
+ projectHooks: [], globalHooks: [], rulesHarnesses: [], zedOnlyBlockFiles: [], skillBlockFiles: [],
8
+ };
9
+ const HOOK_HARNESSES = ['claude', 'cursor', 'vscode'];
10
+ /** Null for a file that is absent or unreadable: an advisory scan cannot fail `mast upgrade`. */
11
+ export function readFileOrNull(path) {
12
+ try {
13
+ return readFileSync(path, 'utf8');
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
19
+ // A plain substring test on the raw text, not a JSON parse: a file that does not parse is
20
+ // still worth a `--check`, which will report the parse problem itself.
21
+ const hasMastHook = (text, harness) => text !== null && (text.includes(` hook ${harness} session-start`) || text.includes(` hook ${harness} search`));
22
+ export function findInstalledArtifacts(projectRoot, home, readFile) {
23
+ const hooksIn = (scope) => HOOK_HARNESSES.filter((h) => hasMastHook(readFile(hookFilePath(h, scope, projectRoot, home)), h));
24
+ const present = (path) => readFile(path) !== null;
25
+ const carriesBlock = (rel) => readFile(join(projectRoot, rel))?.includes(BEGIN_MARKER) === true;
26
+ const rulesHarnesses = [];
27
+ if (present(cursorRulesPath(projectRoot)))
28
+ rulesHarnesses.push('cursor');
29
+ if (windsurfRulesPaths(projectRoot).some(present))
30
+ rulesHarnesses.push('windsurf');
31
+ return {
32
+ projectHooks: hooksIn('project'),
33
+ globalHooks: hooksIn('global'),
34
+ rulesHarnesses,
35
+ zedOnlyBlockFiles: ZED_RULES_FILES.filter((f) => !SKILL_TARGET_FILES.includes(f) && carriesBlock(f)),
36
+ skillBlockFiles: SKILL_TARGET_FILES.filter(carriesBlock),
37
+ };
38
+ }
39
+ //# sourceMappingURL=installed-artifacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installed-artifacts.js","sourceRoot":"","sources":["../../src/cli/installed-artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAoBtE,MAAM,CAAC,MAAM,sBAAsB,GAAuB;IACxD,YAAY,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE;CAClG,CAAC;AAEF,MAAM,cAAc,GAAuB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAE1E,iGAAiG;AACjG,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,0FAA0F;AAC1F,uEAAuE;AACvE,MAAM,WAAW,GAAG,CAAC,IAAmB,EAAE,OAAgB,EAAW,EAAE,CACrE,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,OAAO,gBAAgB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,OAAO,SAAS,CAAC,CAAC,CAAC;AAEjH,MAAM,UAAU,sBAAsB,CACpC,WAAmB,EACnB,IAAY,EACZ,QAAyC;IAEzC,MAAM,OAAO,GAAG,CAAC,KAA2B,EAAa,EAAE,CACzD,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACpG,MAAM,OAAO,GAAG,CAAC,IAAY,EAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IACnE,MAAM,YAAY,GAAG,CAAC,GAAW,EAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;IAEjH,MAAM,cAAc,GAA8B,EAAE,CAAC;IACrD,IAAI,OAAO,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QAAE,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzE,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAEnF,OAAO;QACL,YAAY,EAAE,OAAO,CAAC,SAAS,CAAC;QAChC,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC;QAC9B,cAAc;QACd,iBAAiB,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;QACpG,eAAe,EAAE,kBAAkB,CAAC,MAAM,CAAC,YAAY,CAAC;KACzD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { Command } from 'commander';
2
+ import { type StatusReport } from './status.js';
3
+ /** Absolute path of the shipped rules text; `assets` is in the package's `files`. */
4
+ export declare const PRIME_ASSET_PATH: string;
5
+ /**
6
+ * Renders the session primer for one of four index states.
7
+ *
8
+ * The rules are printed only when the index can be trusted to answer (fresh, or
9
+ * stale with a reindex instruction). Telling a model to use an index that does not
10
+ * exist, or one that describes a different tree, teaches it to ignore the primer,
11
+ * so those two states say what is wrong instead.
12
+ *
13
+ * Pure: `now` is a parameter so the age line is deterministic.
14
+ */
15
+ export declare function renderPrime(status: StatusReport, rules: string, now: Date): string;
16
+ export declare function registerPrimeCommand(program: Command): void;
17
+ //# sourceMappingURL=prime-cmd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prime-cmd.d.ts","sourceRoot":"","sources":["../../src/cli/prime-cmd.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAG7D,qFAAqF;AACrF,eAAO,MAAM,gBAAgB,QAA2C,CAAC;AAEzE;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,MAAM,CAgClF;AAWD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAa3D"}
@@ -0,0 +1,70 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { buildStatus } from './status.js';
4
+ import { PACKAGE_ROOT } from './docs-cmd.js';
5
+ /** Absolute path of the shipped rules text; `assets` is in the package's `files`. */
6
+ export const PRIME_ASSET_PATH = join(PACKAGE_ROOT, 'assets', 'prime.md');
7
+ /**
8
+ * Renders the session primer for one of four index states.
9
+ *
10
+ * The rules are printed only when the index can be trusted to answer (fresh, or
11
+ * stale with a reindex instruction). Telling a model to use an index that does not
12
+ * exist, or one that describes a different tree, teaches it to ignore the primer,
13
+ * so those two states say what is wrong instead.
14
+ *
15
+ * Pure: `now` is a parameter so the age line is deterministic.
16
+ */
17
+ export function renderPrime(status, rules, now) {
18
+ if (!status.initialised) {
19
+ return [
20
+ `mast has no index at ${status.state_dir}.`,
21
+ 'Use ordinary search tools (grep, glob, reading files) here.',
22
+ 'Run `mast init` in the project to create an index.',
23
+ ].join('\n') + '\n';
24
+ }
25
+ if (status.freshness_cause === 'root_mismatch') {
26
+ return [
27
+ `The mast index at ${status.state_dir} describes a different tree than ${status.project_root}.`,
28
+ 'mast results here cannot be trusted, and reindexing will not fix it.',
29
+ 'Use ordinary search tools, and check the project path and --state-dir.',
30
+ ].join('\n') + '\n';
31
+ }
32
+ const health = [
33
+ `mast index: ${String(status.indexed_files ?? 0)} files, last indexed ${describeAge(status.last_indexed, now)}.`,
34
+ ];
35
+ if (!status.index_fresh) {
36
+ const b = status.stale_breakdown;
37
+ const split = b === null
38
+ ? ''
39
+ : ` (changed ${String(b.changed)}, unindexed ${String(b.unindexed)}, deleted ${String(b.deleted)})`;
40
+ health.push(`The index is stale: ${String(status.stale_files ?? 0)} files differ from disk${split}.`, 'Call mast_reindex before relying on mast results.');
41
+ }
42
+ return rules.trimEnd() + '\n\n' + health.join('\n') + '\n';
43
+ }
44
+ function describeAge(lastIndexed, now) {
45
+ if (lastIndexed === null)
46
+ return 'never';
47
+ const seconds = Math.max(0, Math.floor((now.getTime() - new Date(lastIndexed).getTime()) / 1_000));
48
+ if (seconds < 60)
49
+ return `${seconds}s ago`;
50
+ if (seconds < 3_600)
51
+ return `${Math.floor(seconds / 60)}m ago`;
52
+ if (seconds < 86_400)
53
+ return `${Math.floor(seconds / 3_600)}h ago`;
54
+ return `${Math.floor(seconds / 86_400)}d ago`;
55
+ }
56
+ export function registerPrimeCommand(program) {
57
+ program
58
+ .command('prime [path]')
59
+ .description('Print the session primer: how to use mast here, and the live index health')
60
+ .option('--state-dir <dir>', 'State directory')
61
+ .action(async (projectPath, opts) => {
62
+ // Exit 0 in every state, unlike `mast status`: this runs from a session-start
63
+ // hook, where a non-zero exit is a failure the user sees. "No index" is a
64
+ // state the primer reports in its text, not an error of the command.
65
+ const status = await buildStatus({ path: projectPath, stateDir: opts.stateDir });
66
+ const rules = readFileSync(PRIME_ASSET_PATH, 'utf8');
67
+ process.stdout.write(renderPrime(status, rules, new Date()));
68
+ });
69
+ }
70
+ //# sourceMappingURL=prime-cmd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prime-cmd.js","sourceRoot":"","sources":["../../src/cli/prime-cmd.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../src/cli/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC;;;;;;;;GAQG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAmBtC;AAED,0FAA0F;AAC1F,wBAAgB,sBAAsB,IAAI,SAAS,MAAM,EAAE,CAE1D"}
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../src/cli/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC;;;;;;;;GAQG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAsBtC;AAED,0FAA0F;AAC1F,wBAAgB,sBAAsB,IAAI,SAAS,MAAM,EAAE,CAE1D"}
@@ -10,6 +10,9 @@ import { registerMetricsCommand } from './metrics-cmd.js';
10
10
  import { registerQueryCommand } from './query.js';
11
11
  import { registerDocsCommand, registerSkillCommand } from './docs-cmd.js';
12
12
  import { registerUpgradeCommand } from './upgrade-cmd.js';
13
+ import { registerPrimeCommand } from './prime-cmd.js';
14
+ import { registerHookCommand } from './hook-cmd.js';
15
+ import { registerSetupCommand } from './setup-cmd.js';
13
16
  /**
14
17
  * Builds the CLI. This is the *only* place commands are registered.
15
18
  *
@@ -34,6 +37,9 @@ export function buildProgram() {
34
37
  registerQueryCommand(program);
35
38
  registerDocsCommand(program);
36
39
  registerSkillCommand(program);
40
+ registerPrimeCommand(program);
41
+ registerHookCommand(program);
42
+ registerSetupCommand(program);
37
43
  registerUpgradeCommand(program);
38
44
  return program;
39
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"program.js","sourceRoot":"","sources":["../../src/cli/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE;SAC1B,IAAI,CAAC,MAAM,CAAC;SACZ,WAAW,CAAC,+FAA+F,CAAC;SAC5G,OAAO,CAAC,WAAW,CAAC,CAAC;IAExB,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,2BAA2B,CAAC,OAAO,CAAC,CAAC;IACrC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAChC,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAEhC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,sBAAsB;IACpC,OAAO,YAAY,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7D,CAAC"}
1
+ {"version":3,"file":"program.js","sourceRoot":"","sources":["../../src/cli/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE;SAC1B,IAAI,CAAC,MAAM,CAAC;SACZ,WAAW,CAAC,+FAA+F,CAAC;SAC5G,OAAO,CAAC,WAAW,CAAC,CAAC;IAExB,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,2BAA2B,CAAC,OAAO,CAAC,CAAC;IACrC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAChC,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAEhC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,sBAAsB;IACpC,OAAO,YAAY,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7D,CAAC"}
@@ -1,4 +1,6 @@
1
1
  import type { Command } from 'commander';
2
+ import { type ResolvedConfig } from '../store/config.js';
3
+ import { type IndexResult } from '../indexer/index.js';
2
4
  /**
3
5
  * D0 (IMPLEMENTATION_PLAN.md "Stage 4: Determinism, hygiene, and the
4
6
  * measurement harness", "### D0 — CLI query surface"): `mast query <tool>
@@ -29,6 +31,37 @@ export interface RunQueryOptions {
29
31
  readonly stateDir?: string;
30
32
  /** Project root path (the CLI's positional `[path]`); defaults to cwd via `resolveConfig`. */
31
33
  readonly path?: string;
34
+ /**
35
+ * Refresh the index incrementally before dispatching the query.
36
+ *
37
+ * The CLI has neither of the freshness mechanisms the MCP server has — no
38
+ * watcher, and no cached freshness probe, because a one-shot process has no
39
+ * lifetime to amortise a TTL over. This flag is its answer.
40
+ *
41
+ * Opt-in rather than default, because it adds a whole incremental index run
42
+ * to an invocation that would otherwise be a single query. Measured on this
43
+ * repository (212 indexable files) on 2026-09-03: a no-op incremental run
44
+ * reports 25-34 ms of index work inside ~0.5 s of process wall clock, and a
45
+ * run that found 11 changed files reported 424 ms. It scales with the tree,
46
+ * so on a large monorepo it is materially more — which is punishing in the
47
+ * scripts and loops where `mast search` gets used.
48
+ *
49
+ * Incremental, never full. Refreshes an existing index; it does not create
50
+ * one — see the never-indexed guard in {@link runQuery}.
51
+ */
52
+ readonly reindex?: boolean;
53
+ /**
54
+ * Test-only injection point (§4.4 DI): substitutes for the real incremental
55
+ * `runIndex`, so the lock-contention degradation path can be driven without
56
+ * standing up a competing writer. Production passes nothing.
57
+ */
58
+ readonly reindexer?: (config: ResolvedConfig) => Promise<IndexResult>;
59
+ /**
60
+ * Where `--reindex` reports itself. Defaults to stderr, deliberately: the
61
+ * refresh is a side effect of the query, not part of its answer, and
62
+ * `--json` consumers must keep a parseable stdout.
63
+ */
64
+ readonly warn?: (message: string) => void;
32
65
  }
33
66
  /**
34
67
  * Dispatch a single CLI query through the exact registered MCP tool handler
@@ -42,5 +75,11 @@ export interface RunQueryOptions {
42
75
  * would over the MCP transport.
43
76
  */
44
77
  export declare function runQuery(toolName: string, jsonArgs: string, options?: RunQueryOptions): Promise<string>;
45
- export declare function registerQueryCommand(program: Command): void;
78
+ /**
79
+ * @param run Injected so the flag wiring can be tested without a real index
80
+ * (§4.4). Production passes {@link runQuery}. A `--reindex` flag that is
81
+ * declared but never threaded through would be an asserted-and-unimplemented
82
+ * property (SHAPES S-04), which is why it is pinned rather than assumed.
83
+ */
84
+ export declare function registerQueryCommand(program: Command, run?: typeof runQuery): void;
46
85
  //# sourceMappingURL=query.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/cli/query.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQzC;;;;;;;;;;;GAWG;AACH,qBAAa,UAAW,SAAQ,KAAK;CAAG;AAoCxC;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,IAAI,SAAS,MAAM,EAAE,CAW3D;AAED,MAAM,WAAW,eAAe;IAC9B,2FAA2F;IAC3F,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,8FAA8F;IAC9F,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6DjH;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwB3D"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/cli/query.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMjE;;;;;;;;;;;GAWG;AACH,qBAAa,UAAW,SAAQ,KAAK;CAAG;AAoCxC;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,IAAI,SAAS,MAAM,EAAE,CAW3D;AAED,MAAM,WAAW,eAAe;IAC9B,2FAA2F;IAC3F,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,8FAA8F;IAC9F,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IACtE;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAuFjH;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,GAAE,OAAO,QAAmB,GAAG,IAAI,CA2B5F"}
package/dist/cli/query.js CHANGED
@@ -3,6 +3,7 @@ import { existsSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
4
  import { z, ZodError } from 'zod';
5
5
  import { resolveConfig } from '../store/config.js';
6
+ import { runIndex } from '../indexer/index.js';
6
7
  import { openDatabase } from '../graph/db.js';
7
8
  import { SqliteChunkStore } from '../store/sqliteChunkStore.js';
8
9
  import { registerAllTools } from '../mcp/register-tools.js';
@@ -86,6 +87,30 @@ export async function runQuery(toolName, jsonArgs, options = {}) {
86
87
  if (!existsSync(graphDbPath)) {
87
88
  throw new QueryError(`no index found at ${config.resolved_state_dir}; run \`mast init\` / \`mast index\` first`);
88
89
  }
90
+ // AFTER the never-indexed guard above, and deliberately so. Running the
91
+ // indexer first would create graph.db as a side effect and let the guard
92
+ // pass, silently promoting `--reindex` from "refresh" to "bootstrap" and
93
+ // masking the very state the guard reports — the same ordering hazard its
94
+ // own comment describes for `openDatabase`. `mast index` creates; this
95
+ // refreshes.
96
+ if (options.reindex === true) {
97
+ const warn = options.warn ?? ((message) => process.stderr.write(`${message}\n`));
98
+ const reindex = options.reindexer ?? ((c) => runIndex(c, { incremental: true }));
99
+ try {
100
+ const result = await reindex(config);
101
+ warn(`[mast] reindexed: ${String(result.filesIndexed)} file(s) indexed, ` +
102
+ `${String(result.filesSkipped)} unchanged, +${String(result.chunksAdded)}/` +
103
+ `-${String(result.chunksRemoved)} chunks (${String(result.durationMs)} ms)`);
104
+ }
105
+ catch (err) {
106
+ // Never fatal. `runIndex` takes `structure.lock`, and `mast serve` now
107
+ // watches by default, so losing the race to a concurrent writer is an
108
+ // ordinary outcome. Failing the query over a refresh that did not happen
109
+ // would be a worse answer than a slightly stale one — but staying silent
110
+ // about it would be worse than both, because the caller asked for fresh.
111
+ warn(`[mast] --reindex failed, querying the existing index instead: ${String(err)}`);
112
+ }
113
+ }
89
114
  let parsedArgs;
90
115
  try {
91
116
  parsedArgs = JSON.parse(jsonArgs);
@@ -128,15 +153,24 @@ export async function runQuery(toolName, jsonArgs, options = {}) {
128
153
  await db.destroy();
129
154
  }
130
155
  }
131
- export function registerQueryCommand(program) {
156
+ /**
157
+ * @param run Injected so the flag wiring can be tested without a real index
158
+ * (§4.4). Production passes {@link runQuery}. A `--reindex` flag that is
159
+ * declared but never threaded through would be an asserted-and-unimplemented
160
+ * property (SHAPES S-04), which is why it is pinned rather than assumed.
161
+ */
162
+ export function registerQueryCommand(program, run = runQuery) {
132
163
  program
133
164
  .command('query <tool> [json] [path]')
134
165
  .description('Invoke an MCP read tool directly from the CLI — identical output to the MCP transport (MAST_SPEC.md §8)')
135
166
  .option('--state-dir <dir>', 'State directory')
167
+ .option('--reindex', 'Incrementally reindex before querying — the CLI has no watcher (see `mast serve`)')
136
168
  .option('--json', 'Emit the exact single-line MCP response text (machine use); default pretty-prints for humans')
137
169
  .action(async (toolName, jsonArg, path, opts) => {
138
170
  try {
139
- const text = await runQuery(toolName, jsonArg ?? '{}', { stateDir: opts.stateDir, path });
171
+ const text = await run(toolName, jsonArg ?? '{}', {
172
+ stateDir: opts.stateDir, path, reindex: opts.reindex === true,
173
+ });
140
174
  if (opts.json) {
141
175
  process.stdout.write(text + '\n');
142
176
  }
@@ -1 +1 @@
1
- {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/cli/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAoB,MAAM,KAAK,CAAC;AAGpD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;CAAG;AAYxC;;;;;;;;;;;;;GAaG;AACH,SAAS,mBAAmB;IAC1B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC9C,MAAM,OAAO,GAAG;QACd,IAAI,CAAC,IAAY,EAAE,YAAoB,EAAE,WAAwB,EAAE,OAAoB;YACrF,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5C,CAAC;KACF,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,OAA+B,EAAE,KAAK,EAAE,CAAC;AAC5D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB;IACrC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,mBAAmB,EAAE,CAAC;IAChD,MAAM,SAAS,GAAG,IAAI,KAAK,CAAC,EAAE,EAAE;QAC9B,GAAG,CAAC,EAAE,EAAE,IAAI;YACV,MAAM,IAAI,KAAK,CACb,8BAA8B,MAAM,CAAC,IAAI,CAAC,wDAAwD,CACnG,CAAC;QACJ,CAAC;KACF,CAAe,CAAC;IACjB,gBAAgB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAClC,CAAC;AASD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAgB,EAAE,QAAgB,EAAE,UAA2B,EAAE;IAC9F,MAAM,MAAM,GAAG,aAAa,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEhG,0EAA0E;IAC1E,yEAAyE;IACzE,4EAA4E;IAC5E,0EAA0E;IAC1E,2EAA2E;IAC3E,iDAAiD;IACjD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;IAChE,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,UAAU,CAClB,qBAAqB,MAAM,CAAC,kBAAkB,4CAA4C,CAC3F,CAAC;IACJ,CAAC;IAED,IAAI,UAAmB,CAAC;IACxB,IAAI,CAAC;QACH,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,UAAU,CAClB,4BAA4B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC/E,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,GAAG,YAAY,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAC5C,qEAAqE;QACrE,wEAAwE;QACxE,0CAA0C;QAC1C,MAAM,GAAG,GAAe,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,CAAC;QAE5E,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,mBAAmB,EAAE,CAAC;QAChD,gBAAgB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAE9B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,SAAS,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtD,MAAM,IAAI,UAAU,CAAC,iBAAiB,QAAQ,uBAAuB,SAAS,EAAE,CAAC,CAAC;QACpF,CAAC;QAED,IAAI,aAAsC,CAAC;QAC3C,IAAI,CAAC;YACH,wEAAwE;YACxE,mEAAmE;YACnE,gEAAgE;YAChE,gDAAgD;YAChD,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC/D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;gBAC5B,MAAM,IAAI,UAAU,CAAC,0BAA0B,QAAQ,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACtG,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QACjD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChC,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC;IACrB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,4BAA4B,CAAC;SACrC,WAAW,CAAC,yGAAyG,CAAC;SACtH,MAAM,CAAC,mBAAmB,EAAE,iBAAiB,CAAC;SAC9C,MAAM,CAAC,QAAQ,EAAE,8FAA8F,CAAC;SAChH,MAAM,CAAC,KAAK,EACX,QAAgB,EAChB,OAA2B,EAC3B,IAAwB,EACxB,IAA2C,EAC3C,EAAE;QACF,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,IAAI,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1F,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;YACpC,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC9E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/cli/query.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { Command } from 'commander';
2
+ import { runQuery } from './query.js';
2
3
  /**
3
4
  * `mast search <query>` — the readable front door to `mast_search`.
4
5
  *
@@ -29,5 +30,9 @@ export declare function buildSearchArgs(query: string, flags: SearchFlags): stri
29
30
  * severity scale is built around.
30
31
  */
31
32
  export declare function formatSearchResults(responseText: string): string;
32
- export declare function registerSearchCommand(program: Command): void;
33
+ /**
34
+ * @param run Injected so the `--reindex` wiring can be tested without a real
35
+ * index (§4.4). Production passes {@link runQuery}.
36
+ */
37
+ export declare function registerSearchCommand(program: Command, run?: typeof runQuery): void;
33
38
  //# sourceMappingURL=search-cmd.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"search-cmd.d.ts","sourceRoot":"","sources":["../../src/cli/search-cmd.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,+FAA+F;AAC/F,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,MAAM,CAczE;AAqBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CA8EhE;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoB5D"}
1
+ {"version":3,"file":"search-cmd.d.ts","sourceRoot":"","sources":["../../src/cli/search-cmd.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAc,MAAM,YAAY,CAAC;AAElD;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,+FAA+F;AAC/F,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,MAAM,CAczE;AAqBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CA8EhE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,GAAE,OAAO,QAAmB,GAAG,IAAI,CAuB7F"}