@illuminis/comprism 0.1.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 (80) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +281 -0
  3. package/out/agent/command.d.ts +86 -0
  4. package/out/agent/command.js +259 -0
  5. package/out/agent/render.d.ts +97 -0
  6. package/out/agent/render.js +255 -0
  7. package/out/agent/session.d.ts +175 -0
  8. package/out/agent/session.js +573 -0
  9. package/out/commands/ask.d.ts +1 -0
  10. package/out/commands/ask.js +146 -0
  11. package/out/commands/codemap.d.ts +2 -0
  12. package/out/commands/codemap.js +151 -0
  13. package/out/commands/commands-thin.d.ts +39 -0
  14. package/out/commands/commands-thin.js +182 -0
  15. package/out/commands/install.d.ts +163 -0
  16. package/out/commands/install.js +543 -0
  17. package/out/commands/keys.d.ts +55 -0
  18. package/out/commands/keys.js +344 -0
  19. package/out/commands/login.d.ts +9 -0
  20. package/out/commands/login.js +384 -0
  21. package/out/commands/repl.d.ts +1 -0
  22. package/out/commands/repl.js +752 -0
  23. package/out/commands/settings.d.ts +21 -0
  24. package/out/commands/settings.js +244 -0
  25. package/out/commands/welcome.d.ts +1 -0
  26. package/out/commands/welcome.js +196 -0
  27. package/out/executor/documents.d.ts +40 -0
  28. package/out/executor/documents.js +170 -0
  29. package/out/executor/files.d.ts +2 -0
  30. package/out/executor/files.js +360 -0
  31. package/out/executor/git.d.ts +48 -0
  32. package/out/executor/git.js +132 -0
  33. package/out/executor/hooks.d.ts +67 -0
  34. package/out/executor/hooks.js +247 -0
  35. package/out/executor/index.d.ts +29 -0
  36. package/out/executor/index.js +221 -0
  37. package/out/executor/notebook.d.ts +2 -0
  38. package/out/executor/notebook.js +147 -0
  39. package/out/executor/paths.d.ts +15 -0
  40. package/out/executor/paths.js +126 -0
  41. package/out/executor/shell.d.ts +41 -0
  42. package/out/executor/shell.js +336 -0
  43. package/out/graph/build.d.ts +45 -0
  44. package/out/graph/build.js +91 -0
  45. package/out/graph/facts.d.ts +47 -0
  46. package/out/graph/facts.js +12 -0
  47. package/out/graph/files.d.ts +45 -0
  48. package/out/graph/files.js +207 -0
  49. package/out/graph/read-locales.d.ts +29 -0
  50. package/out/graph/read-locales.js +246 -0
  51. package/out/graph/read-python.d.ts +11 -0
  52. package/out/graph/read-python.js +115 -0
  53. package/out/graph/read-typescript.d.ts +16 -0
  54. package/out/graph/read-typescript.js +292 -0
  55. package/out/graph/sync.d.ts +66 -0
  56. package/out/graph/sync.js +242 -0
  57. package/out/lib/attach.d.ts +62 -0
  58. package/out/lib/attach.js +228 -0
  59. package/out/lib/config.d.ts +93 -0
  60. package/out/lib/config.js +198 -0
  61. package/out/lib/connection.d.ts +73 -0
  62. package/out/lib/connection.js +188 -0
  63. package/out/lib/gateway.d.ts +239 -0
  64. package/out/lib/gateway.js +171 -0
  65. package/out/lib/prompt.d.ts +34 -0
  66. package/out/lib/prompt.js +108 -0
  67. package/out/lib/types.d.ts +417 -0
  68. package/out/lib/types.js +21 -0
  69. package/out/lib/ui.d.ts +114 -0
  70. package/out/lib/ui.js +265 -0
  71. package/out/lib/version.d.ts +24 -0
  72. package/out/lib/version.js +27 -0
  73. package/out/lib/voice.d.ts +50 -0
  74. package/out/lib/voice.js +218 -0
  75. package/out/postinstall.d.ts +2 -0
  76. package/out/postinstall.js +92 -0
  77. package/out/thin.d.ts +2 -0
  78. package/out/thin.js +259 -0
  79. package/package.json +101 -0
  80. package/scripts/read_python.py +270 -0
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.findPython = findPython;
37
+ exports.readPython = readPython;
38
+ /**
39
+ * Run the Python reader and collect its facts.
40
+ *
41
+ * The parsing is done by Python itself, because the only reader that agrees
42
+ * with the language is the language's own. A regular expression reader would
43
+ * produce a map that disagrees with the code, and a map that disagrees with the
44
+ * code is worse than no map at all: the agent trusts it.
45
+ *
46
+ * A machine with no Python interpreter gets an honest answer rather than a
47
+ * guessed one. The map then says it covers no Python files, and the count is
48
+ * visible everywhere the map is described.
49
+ */
50
+ const child_process_1 = require("child_process");
51
+ const fs = __importStar(require("fs"));
52
+ const os = __importStar(require("os"));
53
+ const path = __importStar(require("path"));
54
+ /** The reader script, beside the built code in both a checkout and an install. */
55
+ function scriptPath() {
56
+ return path.resolve(__dirname, "..", "..", "scripts", "read_python.py");
57
+ }
58
+ let interpreter;
59
+ /** Which Python this machine has, or null. Asked once per process. */
60
+ function findPython() {
61
+ if (interpreter !== undefined)
62
+ return interpreter;
63
+ for (const candidate of ["python3", "python"]) {
64
+ try {
65
+ const probe = (0, child_process_1.spawnSync)(candidate, ["-c", "import ast,sys;print(sys.version_info[0])"], { encoding: "utf8", timeout: 10_000 });
66
+ if (probe.status === 0 && String(probe.stdout).trim() === "3") {
67
+ interpreter = candidate;
68
+ return interpreter;
69
+ }
70
+ }
71
+ catch {
72
+ /* try the next one */
73
+ }
74
+ }
75
+ interpreter = null;
76
+ return interpreter;
77
+ }
78
+ function readPython(root, rels) {
79
+ if (!rels.length)
80
+ return { facts: {}, failures: [], available: true };
81
+ const python = findPython();
82
+ const script = scriptPath();
83
+ if (!python || !fs.existsSync(script)) {
84
+ return { facts: {}, failures: [], available: false };
85
+ }
86
+ // The file list goes in a file, not on the command line. A project with three
87
+ // thousand Python files produces a command line longer than the operating
88
+ // system will accept, and the failure is a confusing one: the process simply
89
+ // does not start.
90
+ const listFile = path.join(fs.mkdtempSync(path.join(os.tmpdir(), "comprism-map-")), "files.txt");
91
+ try {
92
+ fs.writeFileSync(listFile, `${rels.join("\n")}\n`, "utf8");
93
+ const out = (0, child_process_1.spawnSync)(python, [script, root, listFile], {
94
+ encoding: "utf8",
95
+ maxBuffer: 512 * 1024 * 1024,
96
+ timeout: 300_000,
97
+ });
98
+ if (out.status !== 0 || !out.stdout) {
99
+ return { facts: {}, failures: [], available: false };
100
+ }
101
+ const parsed = JSON.parse(out.stdout);
102
+ return { facts: parsed.facts || {}, failures: parsed.failures || [], available: true };
103
+ }
104
+ catch {
105
+ return { facts: {}, failures: [], available: false };
106
+ }
107
+ finally {
108
+ try {
109
+ fs.rmSync(path.dirname(listFile), { recursive: true, force: true });
110
+ }
111
+ catch {
112
+ /* a temporary folder that will not delete is not worth failing a job over */
113
+ }
114
+ }
115
+ }
@@ -0,0 +1,16 @@
1
+ import type { FactSet } from "./facts";
2
+ type Ts = any;
3
+ /** The TypeScript compiler, or null when this installation has none. */
4
+ export declare function loadCompiler(): Ts | null;
5
+ /** Read every named file. A file that cannot be parsed is REPORTED, never
6
+ * silently dropped: a map that quietly covers less than it claims is the one
7
+ * failure mode worth engineering against. */
8
+ export declare function readTypeScript(root: string, rels: string[]): {
9
+ facts: Record<string, FactSet>;
10
+ failures: {
11
+ file: string;
12
+ reason: string;
13
+ }[];
14
+ available: boolean;
15
+ };
16
+ export {};
@@ -0,0 +1,292 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.loadCompiler = loadCompiler;
37
+ exports.readTypeScript = readTypeScript;
38
+ /**
39
+ * Read TypeScript and JavaScript files into code map facts, using the
40
+ * TypeScript compiler's own parser.
41
+ *
42
+ * This guesses nothing. Every object and every link is taken from the syntax
43
+ * tree, so the same file always produces the same facts and two machines
44
+ * reading the same project agree. Nothing here calls a model, so it costs
45
+ * nothing and cannot drift.
46
+ *
47
+ * The compiler is loaded lazily and by name. A copy of the tool installed
48
+ * without it still works: the map simply says it covers no TypeScript, which is
49
+ * an honest answer, and it is a great deal better than a map built by regular
50
+ * expression that quietly disagrees with the code.
51
+ */
52
+ const fs = __importStar(require("fs"));
53
+ const path = __importStar(require("path"));
54
+ let compiler;
55
+ /** The TypeScript compiler, or null when this installation has none. */
56
+ function loadCompiler() {
57
+ if (compiler !== undefined)
58
+ return compiler;
59
+ try {
60
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
61
+ compiler = require("typescript");
62
+ }
63
+ catch {
64
+ compiler = null;
65
+ }
66
+ return compiler;
67
+ }
68
+ /** The HTTP verbs a call on an API client uses. */
69
+ const HTTP_VERBS = new Set(["get", "post", "put", "patch", "delete", "head", "request"]);
70
+ /** Looks like an API path rather than an ordinary string.
71
+ *
72
+ * Scanning for anything that starts with a slash picks up image URLs, browser
73
+ * routes and CSS paths, and a map full of those is a map nobody trusts. */
74
+ function looksLikeEndpoint(value) {
75
+ if (!value.startsWith("/") || value.length < 2)
76
+ return false;
77
+ if (value.includes(" ") || value.includes("\n"))
78
+ return false;
79
+ if (/\.(png|jpg|jpeg|svg|css|ico|webp|woff2?|json|js|map|txt|pdf)$/i.test(value))
80
+ return false;
81
+ return /^\/[A-Za-z0-9_\-/{}$:.]+$/.test(value);
82
+ }
83
+ function resolveImport(root, fromFile, spec) {
84
+ if (!spec.startsWith("."))
85
+ return null;
86
+ const base = path.resolve(path.dirname(path.join(root, fromFile)), spec);
87
+ const candidates = [
88
+ base, `${base}.ts`, `${base}.tsx`, `${base}.js`, `${base}.jsx`,
89
+ path.join(base, "index.ts"), path.join(base, "index.tsx"),
90
+ path.join(base, "index.js"), path.join(base, "index.jsx"),
91
+ ];
92
+ for (const candidate of candidates) {
93
+ try {
94
+ if (fs.statSync(candidate).isFile()) {
95
+ return path.relative(root, candidate).split(path.sep).join("/");
96
+ }
97
+ }
98
+ catch {
99
+ /* not this one */
100
+ }
101
+ }
102
+ return null;
103
+ }
104
+ function readOne(ts, root, rel) {
105
+ const source = fs.readFileSync(path.join(root, rel), "utf8");
106
+ const kind = rel.endsWith(".tsx") || rel.endsWith(".jsx")
107
+ ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
108
+ const sf = ts.createSourceFile(rel, source, ts.ScriptTarget.Latest, true, kind);
109
+ const objects = [];
110
+ const links = [];
111
+ const lineOf = (node) => sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
112
+ objects.push({
113
+ id: rel, kind: "file", name: path.basename(rel), file: rel, line: 1,
114
+ lang: rel.endsWith("x") ? "tsx" : "ts",
115
+ lines: source.split("\n").length,
116
+ });
117
+ const owner = [rel];
118
+ /** The symbol a call or a rendered tag belongs to. Never empty: `rel` sits at
119
+ * the bottom of the stack and is only ever pushed onto. */
120
+ const holder = () => owner[owner.length - 1] ?? rel;
121
+ const declare = (name, node, objectKind, extra = {}) => {
122
+ const id = `${rel}::${name}`;
123
+ objects.push({ id, kind: objectKind, name, file: rel, line: lineOf(node), ...extra });
124
+ links.push({ from: rel, kind: "defines", to: id });
125
+ return id;
126
+ };
127
+ const exported = (node) => !!node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
128
+ const tagName = (node) => {
129
+ const tag = node.tagName;
130
+ if (ts.isIdentifier(tag))
131
+ return tag.text;
132
+ if (ts.isPropertyAccessExpression(tag))
133
+ return tag.getText();
134
+ return null;
135
+ };
136
+ const calleeName = (expr) => {
137
+ if (ts.isIdentifier(expr))
138
+ return { leaf: expr.text, full: expr.text };
139
+ if (ts.isPropertyAccessExpression(expr))
140
+ return { leaf: expr.name.text, full: expr.getText() };
141
+ return null;
142
+ };
143
+ /** The string value of a literal or a template, holes flattened. */
144
+ const pathText = (node) => {
145
+ if (!node)
146
+ return null;
147
+ if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node))
148
+ return node.text;
149
+ if (ts.isTemplateExpression(node)) {
150
+ return node.head.text + node.templateSpans
151
+ .map((span) => `{}${span.literal.text}`).join("");
152
+ }
153
+ return null;
154
+ };
155
+ function visit(node) {
156
+ let pushed = false;
157
+ if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
158
+ const spec = node.moduleSpecifier.text;
159
+ const resolved = resolveImport(root, rel, spec);
160
+ links.push({
161
+ from: rel, kind: "imports", line: lineOf(node),
162
+ ...(resolved ? { to: resolved } : { to_name: spec }),
163
+ });
164
+ }
165
+ if (ts.isFunctionDeclaration(node) && node.name) {
166
+ const name = node.name.text;
167
+ const objectKind = /^[A-Z]/.test(name) && rel.endsWith("x") ? "component" : "function";
168
+ owner.push(declare(name, node, objectKind, { exported: exported(node) || undefined }));
169
+ pushed = true;
170
+ }
171
+ else if (ts.isClassDeclaration(node) && node.name) {
172
+ owner.push(declare(node.name.text, node, "class", { exported: exported(node) || undefined }));
173
+ pushed = true;
174
+ for (const base of node.heritageClauses || []) {
175
+ for (const t of base.types || []) {
176
+ const name = t.expression?.getText?.();
177
+ if (name)
178
+ links.push({ from: holder(), kind: "inherits", to_name: name, line: lineOf(node) });
179
+ }
180
+ }
181
+ }
182
+ else if (ts.isVariableStatement(node)) {
183
+ for (const decl of node.declarationList.declarations) {
184
+ if (!ts.isIdentifier(decl.name) || !decl.initializer)
185
+ continue;
186
+ const init = decl.initializer;
187
+ if (!ts.isArrowFunction(init) && !ts.isFunctionExpression(init))
188
+ continue;
189
+ const name = decl.name.text;
190
+ const objectKind = /^[A-Z]/.test(name) && rel.endsWith("x") ? "component" : "function";
191
+ const id = declare(name, decl, objectKind, { exported: exported(node) || undefined });
192
+ owner.push(id);
193
+ ts.forEachChild(init, visit);
194
+ owner.pop();
195
+ }
196
+ }
197
+ if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
198
+ const tag = tagName(node);
199
+ if (tag && /^[A-Z]/.test(tag)) {
200
+ links.push({ from: holder(), kind: "renders", to_name: tag, line: lineOf(node) });
201
+ }
202
+ }
203
+ if (ts.isCallExpression(node)) {
204
+ const callee = calleeName(node.expression);
205
+ if (callee && !callee.leaf.startsWith("_")) {
206
+ links.push({
207
+ from: holder(), kind: "calls",
208
+ to_name: callee.leaf, full_name: callee.full, line: lineOf(node),
209
+ });
210
+ }
211
+ // An API call found by the CALL, never by the string. `api.get("/x")`,
212
+ // `client.post(...)`, `fetch(...)`. Looking for anything path shaped
213
+ // picks up image URLs and browser routes and the map stops being worth
214
+ // trusting.
215
+ const isFetch = callee && callee.full === "fetch";
216
+ const isVerb = callee && HTTP_VERBS.has(callee.leaf)
217
+ && /api|client|http|request/i.test(callee.full);
218
+ if (isFetch || isVerb) {
219
+ const value = pathText(node.arguments[0]);
220
+ if (value && looksLikeEndpoint(value)) {
221
+ links.push({
222
+ from: holder(), kind: "calls_endpoint",
223
+ to_name: value, line: lineOf(node),
224
+ ...(isVerb && callee ? { method: callee.leaf.toUpperCase() } : {}),
225
+ });
226
+ }
227
+ }
228
+ }
229
+ // A data fetching slice: { url: "/things" } or query: () => "/things".
230
+ if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name)) {
231
+ const key = node.name.text;
232
+ if (key === "url" || key === "query") {
233
+ let value = pathText(node.initializer);
234
+ if (!value && ts.isArrowFunction(node.initializer)
235
+ && !ts.isBlock(node.initializer.body)) {
236
+ value = pathText(node.initializer.body);
237
+ }
238
+ if (value && looksLikeEndpoint(value)) {
239
+ links.push({
240
+ from: holder(), kind: "calls_endpoint",
241
+ to_name: value, line: lineOf(node),
242
+ });
243
+ }
244
+ }
245
+ if (key === "path") {
246
+ const value = pathText(node.initializer);
247
+ if (value && value.startsWith("/")) {
248
+ links.push({
249
+ from: holder(), kind: "browser_route",
250
+ to_name: value, line: lineOf(node),
251
+ });
252
+ }
253
+ }
254
+ }
255
+ if (ts.isJsxAttribute(node) && ts.isIdentifier(node.name)
256
+ && node.name.text === "path" && node.initializer) {
257
+ const inner = ts.isJsxExpression(node.initializer)
258
+ ? node.initializer.expression : node.initializer;
259
+ const value = pathText(inner);
260
+ if (value && value.startsWith("/")) {
261
+ links.push({
262
+ from: holder(), kind: "browser_route",
263
+ to_name: value, line: lineOf(node),
264
+ });
265
+ }
266
+ }
267
+ ts.forEachChild(node, visit);
268
+ if (pushed)
269
+ owner.pop();
270
+ }
271
+ ts.forEachChild(sf, visit);
272
+ return { objects, links };
273
+ }
274
+ /** Read every named file. A file that cannot be parsed is REPORTED, never
275
+ * silently dropped: a map that quietly covers less than it claims is the one
276
+ * failure mode worth engineering against. */
277
+ function readTypeScript(root, rels) {
278
+ const ts = loadCompiler();
279
+ if (!ts)
280
+ return { facts: {}, failures: [], available: false };
281
+ const facts = {};
282
+ const failures = [];
283
+ for (const rel of rels) {
284
+ try {
285
+ facts[rel] = readOne(ts, root, rel);
286
+ }
287
+ catch (err) {
288
+ failures.push({ file: rel, reason: err?.name || "Error" });
289
+ }
290
+ }
291
+ return { facts, failures, available: true };
292
+ }
@@ -0,0 +1,66 @@
1
+ export interface SyncOutcome {
2
+ /** Whether the service now holds a map of this project that matches disk. */
3
+ current: boolean;
4
+ /** Whether this company uses the map at all. */
5
+ enabled: boolean;
6
+ /** What happened, in one sentence a person can read. */
7
+ message: string;
8
+ filesRead: number;
9
+ filesTotal: number;
10
+ seconds: number;
11
+ /** Files present that no reader on this machine could read. */
12
+ unread: number;
13
+ }
14
+ /** What the service holds for this project, and whether it matches disk. */
15
+ export declare function status(root: string, workspace: string, opts?: {
16
+ withStamps?: boolean;
17
+ }): Promise<{
18
+ enabled: boolean;
19
+ autoRefresh: boolean;
20
+ fresh: boolean;
21
+ hasMap: boolean;
22
+ held: Record<string, unknown> | null;
23
+ reachable: boolean;
24
+ stamps: Record<string, string> | null;
25
+ definedNames: string[];
26
+ }>;
27
+ /**
28
+ * Bring the map up to date, reading only the files that moved.
29
+ *
30
+ * `force` reads everything again, which is what the manual refresh does: a
31
+ * person asking for a rebuild has usually just had an answer they did not
32
+ * believe, and telling them nothing needed doing is not an answer.
33
+ */
34
+ export declare function refresh(root: string, workspace: string, opts?: {
35
+ force?: boolean;
36
+ }): Promise<SyncOutcome>;
37
+ /** What was read and what was not, in one sentence an answer can carry.
38
+ *
39
+ * Said out loud rather than hidden. A map that quietly covers less than it
40
+ * claims is the one failure worth engineering against: the agent believes it
41
+ * has seen everything, and writes a confident change that misses a caller. */
42
+ export declare function coverageSentence(unread: {
43
+ python: number;
44
+ typescript: number;
45
+ }, total: number): string;
46
+ /** What this machine can read at all. Asked before anything else, so a person
47
+ * is told why their map is thin rather than left to guess. */
48
+ export declare function readerReport(): string;
49
+ /**
50
+ * Put ONE file back into the map, now, and wait for it.
51
+ *
52
+ * The fast path, and it exists because the slow one loses a race that matters.
53
+ * An agent writes a file and asks the map about it in the same step, because
54
+ * asking for several actions at once is what a well behaved agent does. A
55
+ * refresh started in the background after the write has not finished by the
56
+ * time the question runs, so the question reaches a map that is one file
57
+ * behind, and the agent is told the thing it just created does not exist.
58
+ *
59
+ * So this is awaited before the write's result goes back. One round trip: the
60
+ * file's facts and the project's new fingerprint travel together, and the
61
+ * service stores, stamps and rejoins in that single call.
62
+ *
63
+ * Failure is silent on purpose. A map that could not be updated must never turn
64
+ * a successful write into a failed one; the next check picks the file up.
65
+ */
66
+ export declare function pushFile(root: string, workspace: string, rels: string[]): Promise<boolean>;