@cstart/coldstart 2.0.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/README.md +236 -0
- package/dist/cache/disk-cache.d.ts +14 -0
- package/dist/cache/disk-cache.d.ts.map +1 -0
- package/dist/cache/disk-cache.js +371 -0
- package/dist/cache/disk-cache.js.map +1 -0
- package/dist/cli.d.ts +18 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +206 -0
- package/dist/cli.js.map +1 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +111 -0
- package/dist/constants.js.map +1 -0
- package/dist/daemon-lock.d.ts +63 -0
- package/dist/daemon-lock.d.ts.map +1 -0
- package/dist/daemon-lock.js +218 -0
- package/dist/daemon-lock.js.map +1 -0
- package/dist/daemon-log.d.ts +26 -0
- package/dist/daemon-log.d.ts.map +1 -0
- package/dist/daemon-log.js +110 -0
- package/dist/daemon-log.js.map +1 -0
- package/dist/index-manager.d.ts +103 -0
- package/dist/index-manager.d.ts.map +1 -0
- package/dist/index-manager.js +361 -0
- package/dist/index-manager.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +724 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/content-tokens.d.ts +74 -0
- package/dist/indexer/content-tokens.d.ts.map +1 -0
- package/dist/indexer/content-tokens.js +406 -0
- package/dist/indexer/content-tokens.js.map +1 -0
- package/dist/indexer/cpp-include-roots.d.ts +7 -0
- package/dist/indexer/cpp-include-roots.d.ts.map +1 -0
- package/dist/indexer/cpp-include-roots.js +166 -0
- package/dist/indexer/cpp-include-roots.js.map +1 -0
- package/dist/indexer/csharp-synthetic.d.ts +9 -0
- package/dist/indexer/csharp-synthetic.d.ts.map +1 -0
- package/dist/indexer/csharp-synthetic.js +51 -0
- package/dist/indexer/csharp-synthetic.js.map +1 -0
- package/dist/indexer/django-synthetic.d.ts +12 -0
- package/dist/indexer/django-synthetic.d.ts.map +1 -0
- package/dist/indexer/django-synthetic.js +49 -0
- package/dist/indexer/django-synthetic.js.map +1 -0
- package/dist/indexer/extractors/angularjs.d.ts +16 -0
- package/dist/indexer/extractors/angularjs.d.ts.map +1 -0
- package/dist/indexer/extractors/angularjs.js +49 -0
- package/dist/indexer/extractors/angularjs.js.map +1 -0
- package/dist/indexer/extractors/cpp.d.ts +9 -0
- package/dist/indexer/extractors/cpp.d.ts.map +1 -0
- package/dist/indexer/extractors/cpp.js +254 -0
- package/dist/indexer/extractors/cpp.js.map +1 -0
- package/dist/indexer/extractors/csharp.d.ts +19 -0
- package/dist/indexer/extractors/csharp.d.ts.map +1 -0
- package/dist/indexer/extractors/csharp.js +327 -0
- package/dist/indexer/extractors/csharp.js.map +1 -0
- package/dist/indexer/extractors/env.d.ts +9 -0
- package/dist/indexer/extractors/env.d.ts.map +1 -0
- package/dist/indexer/extractors/env.js +43 -0
- package/dist/indexer/extractors/env.js.map +1 -0
- package/dist/indexer/extractors/go.d.ts +9 -0
- package/dist/indexer/extractors/go.d.ts.map +1 -0
- package/dist/indexer/extractors/go.js +227 -0
- package/dist/indexer/extractors/go.js.map +1 -0
- package/dist/indexer/extractors/graphql.d.ts +22 -0
- package/dist/indexer/extractors/graphql.d.ts.map +1 -0
- package/dist/indexer/extractors/graphql.js +88 -0
- package/dist/indexer/extractors/graphql.js.map +1 -0
- package/dist/indexer/extractors/groovy.d.ts +9 -0
- package/dist/indexer/extractors/groovy.d.ts.map +1 -0
- package/dist/indexer/extractors/groovy.js +356 -0
- package/dist/indexer/extractors/groovy.js.map +1 -0
- package/dist/indexer/extractors/java.d.ts +10 -0
- package/dist/indexer/extractors/java.d.ts.map +1 -0
- package/dist/indexer/extractors/java.js +586 -0
- package/dist/indexer/extractors/java.js.map +1 -0
- package/dist/indexer/extractors/kotlin.d.ts +10 -0
- package/dist/indexer/extractors/kotlin.d.ts.map +1 -0
- package/dist/indexer/extractors/kotlin.js +398 -0
- package/dist/indexer/extractors/kotlin.js.map +1 -0
- package/dist/indexer/extractors/node-helpers.d.ts +13 -0
- package/dist/indexer/extractors/node-helpers.d.ts.map +1 -0
- package/dist/indexer/extractors/node-helpers.js +17 -0
- package/dist/indexer/extractors/node-helpers.js.map +1 -0
- package/dist/indexer/extractors/parser-factory.d.ts +4 -0
- package/dist/indexer/extractors/parser-factory.d.ts.map +1 -0
- package/dist/indexer/extractors/parser-factory.js +28 -0
- package/dist/indexer/extractors/parser-factory.js.map +1 -0
- package/dist/indexer/extractors/php.d.ts +17 -0
- package/dist/indexer/extractors/php.d.ts.map +1 -0
- package/dist/indexer/extractors/php.js +363 -0
- package/dist/indexer/extractors/php.js.map +1 -0
- package/dist/indexer/extractors/python.d.ts +14 -0
- package/dist/indexer/extractors/python.d.ts.map +1 -0
- package/dist/indexer/extractors/python.js +449 -0
- package/dist/indexer/extractors/python.js.map +1 -0
- package/dist/indexer/extractors/ruby.d.ts +10 -0
- package/dist/indexer/extractors/ruby.d.ts.map +1 -0
- package/dist/indexer/extractors/ruby.js +996 -0
- package/dist/indexer/extractors/ruby.js.map +1 -0
- package/dist/indexer/extractors/rust.d.ts +9 -0
- package/dist/indexer/extractors/rust.d.ts.map +1 -0
- package/dist/indexer/extractors/rust.js +322 -0
- package/dist/indexer/extractors/rust.js.map +1 -0
- package/dist/indexer/extractors/toml.d.ts +9 -0
- package/dist/indexer/extractors/toml.d.ts.map +1 -0
- package/dist/indexer/extractors/toml.js +84 -0
- package/dist/indexer/extractors/toml.js.map +1 -0
- package/dist/indexer/extractors/xml.d.ts +9 -0
- package/dist/indexer/extractors/xml.d.ts.map +1 -0
- package/dist/indexer/extractors/xml.js +163 -0
- package/dist/indexer/extractors/xml.js.map +1 -0
- package/dist/indexer/extractors/yaml.d.ts +9 -0
- package/dist/indexer/extractors/yaml.d.ts.map +1 -0
- package/dist/indexer/extractors/yaml.js +117 -0
- package/dist/indexer/extractors/yaml.js.map +1 -0
- package/dist/indexer/git.d.ts +19 -0
- package/dist/indexer/git.d.ts.map +1 -0
- package/dist/indexer/git.js +55 -0
- package/dist/indexer/git.js.map +1 -0
- package/dist/indexer/graph.d.ts +7 -0
- package/dist/indexer/graph.d.ts.map +1 -0
- package/dist/indexer/graph.js +20 -0
- package/dist/indexer/graph.js.map +1 -0
- package/dist/indexer/indexed-file.d.ts +15 -0
- package/dist/indexer/indexed-file.d.ts.map +1 -0
- package/dist/indexer/indexed-file.js +50 -0
- package/dist/indexer/indexed-file.js.map +1 -0
- package/dist/indexer/invariants.d.ts +15 -0
- package/dist/indexer/invariants.d.ts.map +1 -0
- package/dist/indexer/invariants.js +96 -0
- package/dist/indexer/invariants.js.map +1 -0
- package/dist/indexer/laravel-synthetic.d.ts +10 -0
- package/dist/indexer/laravel-synthetic.d.ts.map +1 -0
- package/dist/indexer/laravel-synthetic.js +78 -0
- package/dist/indexer/laravel-synthetic.js.map +1 -0
- package/dist/indexer/parser.d.ts +4 -0
- package/dist/indexer/parser.d.ts.map +1 -0
- package/dist/indexer/parser.js +499 -0
- package/dist/indexer/parser.js.map +1 -0
- package/dist/indexer/patch.d.ts +3 -0
- package/dist/indexer/patch.d.ts.map +1 -0
- package/dist/indexer/patch.js +291 -0
- package/dist/indexer/patch.js.map +1 -0
- package/dist/indexer/rails-synthetic.d.ts +11 -0
- package/dist/indexer/rails-synthetic.d.ts.map +1 -0
- package/dist/indexer/rails-synthetic.js +80 -0
- package/dist/indexer/rails-synthetic.js.map +1 -0
- package/dist/indexer/reconcile.d.ts +9 -0
- package/dist/indexer/reconcile.d.ts.map +1 -0
- package/dist/indexer/reconcile.js +96 -0
- package/dist/indexer/reconcile.js.map +1 -0
- package/dist/indexer/resolvers/cpp.d.ts +15 -0
- package/dist/indexer/resolvers/cpp.d.ts.map +1 -0
- package/dist/indexer/resolvers/cpp.js +35 -0
- package/dist/indexer/resolvers/cpp.js.map +1 -0
- package/dist/indexer/resolvers/csharp.d.ts +2 -0
- package/dist/indexer/resolvers/csharp.d.ts.map +1 -0
- package/dist/indexer/resolvers/csharp.js +89 -0
- package/dist/indexer/resolvers/csharp.js.map +1 -0
- package/dist/indexer/resolvers/generic.d.ts +10 -0
- package/dist/indexer/resolvers/generic.d.ts.map +1 -0
- package/dist/indexer/resolvers/generic.js +35 -0
- package/dist/indexer/resolvers/generic.js.map +1 -0
- package/dist/indexer/resolvers/go.d.ts +2 -0
- package/dist/indexer/resolvers/go.d.ts.map +1 -0
- package/dist/indexer/resolvers/go.js +171 -0
- package/dist/indexer/resolvers/go.js.map +1 -0
- package/dist/indexer/resolvers/index.d.ts +26 -0
- package/dist/indexer/resolvers/index.d.ts.map +1 -0
- package/dist/indexer/resolvers/index.js +301 -0
- package/dist/indexer/resolvers/index.js.map +1 -0
- package/dist/indexer/resolvers/java.d.ts +17 -0
- package/dist/indexer/resolvers/java.d.ts.map +1 -0
- package/dist/indexer/resolvers/java.js +104 -0
- package/dist/indexer/resolvers/java.js.map +1 -0
- package/dist/indexer/resolvers/php.d.ts +2 -0
- package/dist/indexer/resolvers/php.d.ts.map +1 -0
- package/dist/indexer/resolvers/php.js +108 -0
- package/dist/indexer/resolvers/php.js.map +1 -0
- package/dist/indexer/resolvers/python.d.ts +17 -0
- package/dist/indexer/resolvers/python.d.ts.map +1 -0
- package/dist/indexer/resolvers/python.js +63 -0
- package/dist/indexer/resolvers/python.js.map +1 -0
- package/dist/indexer/resolvers/ruby.d.ts +13 -0
- package/dist/indexer/resolvers/ruby.d.ts.map +1 -0
- package/dist/indexer/resolvers/ruby.js +199 -0
- package/dist/indexer/resolvers/ruby.js.map +1 -0
- package/dist/indexer/resolvers/rust.d.ts +12 -0
- package/dist/indexer/resolvers/rust.d.ts.map +1 -0
- package/dist/indexer/resolvers/rust.js +61 -0
- package/dist/indexer/resolvers/rust.js.map +1 -0
- package/dist/indexer/resolvers/shared.d.ts +18 -0
- package/dist/indexer/resolvers/shared.d.ts.map +1 -0
- package/dist/indexer/resolvers/shared.js +71 -0
- package/dist/indexer/resolvers/shared.js.map +1 -0
- package/dist/indexer/rust-workspace.d.ts +25 -0
- package/dist/indexer/rust-workspace.d.ts.map +1 -0
- package/dist/indexer/rust-workspace.js +155 -0
- package/dist/indexer/rust-workspace.js.map +1 -0
- package/dist/indexer/symbol-edges.d.ts +19 -0
- package/dist/indexer/symbol-edges.d.ts.map +1 -0
- package/dist/indexer/symbol-edges.js +117 -0
- package/dist/indexer/symbol-edges.js.map +1 -0
- package/dist/indexer/tokenize.d.ts +26 -0
- package/dist/indexer/tokenize.d.ts.map +1 -0
- package/dist/indexer/tokenize.js +200 -0
- package/dist/indexer/tokenize.js.map +1 -0
- package/dist/indexer/ts-parser.d.ts +10 -0
- package/dist/indexer/ts-parser.d.ts.map +1 -0
- package/dist/indexer/ts-parser.js +605 -0
- package/dist/indexer/ts-parser.js.map +1 -0
- package/dist/indexer/walker.d.ts +9 -0
- package/dist/indexer/walker.d.ts.map +1 -0
- package/dist/indexer/walker.js +91 -0
- package/dist/indexer/walker.js.map +1 -0
- package/dist/init.d.ts +111 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +787 -0
- package/dist/init.js.map +1 -0
- package/dist/kb/cli.d.ts +2 -0
- package/dist/kb/cli.d.ts.map +1 -0
- package/dist/kb/cli.js +377 -0
- package/dist/kb/cli.js.map +1 -0
- package/dist/kb/commit.d.ts +6 -0
- package/dist/kb/commit.d.ts.map +1 -0
- package/dist/kb/commit.js +84 -0
- package/dist/kb/commit.js.map +1 -0
- package/dist/kb/fold.d.ts +42 -0
- package/dist/kb/fold.d.ts.map +1 -0
- package/dist/kb/fold.js +285 -0
- package/dist/kb/fold.js.map +1 -0
- package/dist/kb/freshness.d.ts +9 -0
- package/dist/kb/freshness.d.ts.map +1 -0
- package/dist/kb/freshness.js +52 -0
- package/dist/kb/freshness.js.map +1 -0
- package/dist/kb/git.d.ts +4 -0
- package/dist/kb/git.d.ts.map +1 -0
- package/dist/kb/git.js +28 -0
- package/dist/kb/git.js.map +1 -0
- package/dist/kb/ids.d.ts +8 -0
- package/dist/kb/ids.d.ts.map +1 -0
- package/dist/kb/ids.js +42 -0
- package/dist/kb/ids.js.map +1 -0
- package/dist/kb/lint.d.ts +23 -0
- package/dist/kb/lint.d.ts.map +1 -0
- package/dist/kb/lint.js +102 -0
- package/dist/kb/lint.js.map +1 -0
- package/dist/kb/lookup.d.ts +55 -0
- package/dist/kb/lookup.d.ts.map +1 -0
- package/dist/kb/lookup.js +92 -0
- package/dist/kb/lookup.js.map +1 -0
- package/dist/kb/notes-index.d.ts +31 -0
- package/dist/kb/notes-index.d.ts.map +1 -0
- package/dist/kb/notes-index.js +0 -0
- package/dist/kb/notes-index.js.map +1 -0
- package/dist/kb/raw-log.d.ts +34 -0
- package/dist/kb/raw-log.d.ts.map +1 -0
- package/dist/kb/raw-log.js +106 -0
- package/dist/kb/raw-log.js.map +1 -0
- package/dist/kb/render.d.ts +17 -0
- package/dist/kb/render.d.ts.map +1 -0
- package/dist/kb/render.js +101 -0
- package/dist/kb/render.js.map +1 -0
- package/dist/kb/search.d.ts +110 -0
- package/dist/kb/search.d.ts.map +1 -0
- package/dist/kb/search.js +453 -0
- package/dist/kb/search.js.map +1 -0
- package/dist/kb/store.d.ts +35 -0
- package/dist/kb/store.d.ts.map +1 -0
- package/dist/kb/store.js +160 -0
- package/dist/kb/store.js.map +1 -0
- package/dist/kb/types.d.ts +142 -0
- package/dist/kb/types.d.ts.map +1 -0
- package/dist/kb/types.js +13 -0
- package/dist/kb/types.js.map +1 -0
- package/dist/kb/view-template.d.ts +8 -0
- package/dist/kb/view-template.d.ts.map +1 -0
- package/dist/kb/view-template.js +8 -0
- package/dist/kb/view-template.js.map +1 -0
- package/dist/kb/view.d.ts +42 -0
- package/dist/kb/view.d.ts.map +1 -0
- package/dist/kb/view.js +118 -0
- package/dist/kb/view.js.map +1 -0
- package/dist/kb/write.d.ts +72 -0
- package/dist/kb/write.d.ts.map +1 -0
- package/dist/kb/write.js +345 -0
- package/dist/kb/write.js.map +1 -0
- package/dist/keeper-state.d.ts +29 -0
- package/dist/keeper-state.d.ts.map +1 -0
- package/dist/keeper-state.js +89 -0
- package/dist/keeper-state.js.map +1 -0
- package/dist/keeper.d.ts +23 -0
- package/dist/keeper.d.ts.map +1 -0
- package/dist/keeper.js +105 -0
- package/dist/keeper.js.map +1 -0
- package/dist/migrate.d.ts +9 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +102 -0
- package/dist/migrate.js.map +1 -0
- package/dist/restart.d.ts +15 -0
- package/dist/restart.d.ts.map +1 -0
- package/dist/restart.js +48 -0
- package/dist/restart.js.map +1 -0
- package/dist/server/find.d.ts +39 -0
- package/dist/server/find.d.ts.map +1 -0
- package/dist/server/find.js +979 -0
- package/dist/server/find.js.map +1 -0
- package/dist/server/mcp.d.ts +117 -0
- package/dist/server/mcp.d.ts.map +1 -0
- package/dist/server/mcp.js +301 -0
- package/dist/server/mcp.js.map +1 -0
- package/dist/server/searcher.d.ts +14 -0
- package/dist/server/searcher.d.ts.map +1 -0
- package/dist/server/searcher.js +146 -0
- package/dist/server/searcher.js.map +1 -0
- package/dist/server/tools.d.ts +17 -0
- package/dist/server/tools.d.ts.map +1 -0
- package/dist/server/tools.js +875 -0
- package/dist/server/tools.js.map +1 -0
- package/dist/status.d.ts +12 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +157 -0
- package/dist/status.js.map +1 -0
- package/dist/types.d.ts +138 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/watcher.d.ts +11 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +67 -0
- package/dist/watcher.js.map +1 -0
- package/hooks/canonical-find-key.mjs +68 -0
- package/hooks/codex-find-nudge.mjs +15 -0
- package/hooks/codex-find-preguard.mjs +14 -0
- package/hooks/codex-kb-elicit.mjs +329 -0
- package/hooks/codex-kb-recall.mjs +151 -0
- package/hooks/codex-nudge-handler.mjs +370 -0
- package/hooks/codex-preguard-handler.mjs +75 -0
- package/hooks/codex-run-hook.mjs +132 -0
- package/hooks/coldstart-call.mjs +58 -0
- package/hooks/cursor-find-nudge.mjs +15 -0
- package/hooks/cursor-find-preguard.mjs +14 -0
- package/hooks/cursor-input.mjs +72 -0
- package/hooks/cursor-kb-elicit.mjs +335 -0
- package/hooks/cursor-kb-recall.mjs +138 -0
- package/hooks/cursor-nudge-handler.mjs +33 -0
- package/hooks/cursor-preguard-handler.mjs +39 -0
- package/hooks/cursor-run-hook.mjs +129 -0
- package/hooks/find-nudge.mjs +15 -0
- package/hooks/find-preguard.mjs +14 -0
- package/hooks/kb-elicit.mjs +334 -0
- package/hooks/kb-recall.mjs +151 -0
- package/hooks/nudge-handler.mjs +370 -0
- package/hooks/preguard-handler.mjs +75 -0
- package/hooks/run-hook.mjs +132 -0
- package/package.json +69 -0
- package/templates/coldstart.cli.md +60 -0
- package/templates/coldstart.mcp.md +59 -0
package/dist/kb/view.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `coldstart kb view` — generate a single self-contained HTML file that browses
|
|
3
|
+
* the notebook, then open it in the default browser. No server: this is a
|
|
4
|
+
* one-shot generate-and-open. Freshness is computed NOW (whole-file hash
|
|
5
|
+
* tripwire, same as `status`), so the snapshot is accurate at generation time;
|
|
6
|
+
* re-run to refresh.
|
|
7
|
+
*
|
|
8
|
+
* The client is an embedded, dependency-free HTML/JS app (VIEW_TEMPLATE); this
|
|
9
|
+
* module only produces the baked JSON data and drops it into the template.
|
|
10
|
+
*/
|
|
11
|
+
import { writeFileSync, existsSync, readFileSync } from 'node:fs';
|
|
12
|
+
import { join, dirname, basename } from 'node:path';
|
|
13
|
+
import { execFile } from 'node:child_process';
|
|
14
|
+
import { loadAll, notebookDir } from './store.js';
|
|
15
|
+
import { renderNote } from './render.js';
|
|
16
|
+
import { stampAnchors } from './freshness.js';
|
|
17
|
+
const RANK = { fresh: 0, unverified: 1, changed: 2, missing: 3 };
|
|
18
|
+
/** Strip renderNote's frontmatter + leading `# title` to get just the body md. */
|
|
19
|
+
function bodyMarkdown(note) {
|
|
20
|
+
const md = renderNote(note);
|
|
21
|
+
const m = md.match(/^---\n[\s\S]*?\n---\n?([\s\S]*)$/);
|
|
22
|
+
let body = m ? m[1] : md;
|
|
23
|
+
body = body.replace(/^\s*#\s+.*\n?/, ''); // drop the first H1 (dupes the title)
|
|
24
|
+
return body.trim();
|
|
25
|
+
}
|
|
26
|
+
/** FoldedNote → the flat shape the client expects (mirrors the extract script). */
|
|
27
|
+
function toClientNote(root, note) {
|
|
28
|
+
const stamped = stampAnchors(root, note.anchors).map((a) => ({
|
|
29
|
+
path: a.path,
|
|
30
|
+
symbols: a.symbols,
|
|
31
|
+
hash: a.hash,
|
|
32
|
+
state: a.state,
|
|
33
|
+
}));
|
|
34
|
+
let roll = stamped.length ? 'fresh' : 'unverified';
|
|
35
|
+
for (const a of stamped)
|
|
36
|
+
if (RANK[a.state] > RANK[roll])
|
|
37
|
+
roll = a.state;
|
|
38
|
+
const body = bodyMarkdown(note);
|
|
39
|
+
const outLinks = [...new Set([...body.matchAll(/\[\[([^\]]+)\]\]/g)].map((x) => x[1]))];
|
|
40
|
+
return {
|
|
41
|
+
id: note.id,
|
|
42
|
+
type: note.type,
|
|
43
|
+
character: note.character ?? null,
|
|
44
|
+
title: note.title,
|
|
45
|
+
aliases: note.aliases ?? [],
|
|
46
|
+
status: note.status,
|
|
47
|
+
updated: note.updated ?? '',
|
|
48
|
+
edits: note.edits ?? 0,
|
|
49
|
+
anchors: stamped,
|
|
50
|
+
freshness: roll,
|
|
51
|
+
dir: stamped[0] ? dirname(stamped[0].path) : '(unanchored)',
|
|
52
|
+
outLinks,
|
|
53
|
+
body,
|
|
54
|
+
backlinks: [],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** Build the `{ summary, notes }` payload the template bakes in. */
|
|
58
|
+
export function buildViewData(root, generated) {
|
|
59
|
+
const { notes: folded } = loadAll(root);
|
|
60
|
+
const notes = folded
|
|
61
|
+
.filter((n) => n.status !== 'retracted')
|
|
62
|
+
.map((n) => toClientNote(root, n));
|
|
63
|
+
const byId = new Map(notes.map((n) => [n.id, n]));
|
|
64
|
+
for (const n of notes) {
|
|
65
|
+
for (const l of n.outLinks) {
|
|
66
|
+
const t = byId.get(l);
|
|
67
|
+
if (t && l !== n.id && !t.backlinks.includes(n.id))
|
|
68
|
+
t.backlinks.push(n.id);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
notes.sort((a, b) => (b.updated || '').localeCompare(a.updated || ''));
|
|
72
|
+
const byType = {};
|
|
73
|
+
const byFreshness = {};
|
|
74
|
+
for (const n of notes) {
|
|
75
|
+
byType[n.type] = (byType[n.type] || 0) + 1;
|
|
76
|
+
byFreshness[n.freshness] = (byFreshness[n.freshness] || 0) + 1;
|
|
77
|
+
}
|
|
78
|
+
return { summary: { total: notes.length, byType, byFreshness, repo: basename(root), generated }, notes };
|
|
79
|
+
}
|
|
80
|
+
/** Bake data into the template. `</` is neutralized so note text can't break the script tag. */
|
|
81
|
+
export function renderViewHtml(template, data) {
|
|
82
|
+
const json = JSON.stringify(data).replace(/<\//g, '<\\/');
|
|
83
|
+
return template.replace('__DATA_JSON__', () => json);
|
|
84
|
+
}
|
|
85
|
+
/** Best-effort open in the OS default browser. Never throws. */
|
|
86
|
+
function openInBrowser(file) {
|
|
87
|
+
const cmd = process.platform === 'darwin' ? { bin: 'open', args: [file] }
|
|
88
|
+
: process.platform === 'win32' ? { bin: 'cmd', args: ['/c', 'start', '', file] }
|
|
89
|
+
: { bin: 'xdg-open', args: [file] };
|
|
90
|
+
try {
|
|
91
|
+
const child = execFile(cmd.bin, cmd.args, () => { });
|
|
92
|
+
child.unref();
|
|
93
|
+
}
|
|
94
|
+
catch { /* ignore — the path is printed regardless */ }
|
|
95
|
+
}
|
|
96
|
+
/** Ensure the notebook .gitignore excludes the generated index.html. */
|
|
97
|
+
function ignoreIndexHtml(root) {
|
|
98
|
+
const gi = join(notebookDir(root), '.gitignore');
|
|
99
|
+
try {
|
|
100
|
+
const cur = existsSync(gi) ? readFileSync(gi, 'utf8') : '';
|
|
101
|
+
if (!cur.split('\n').some((l) => l.trim() === 'index.html')) {
|
|
102
|
+
writeFileSync(gi, (cur && !cur.endsWith('\n') ? cur + '\n' : cur) + 'index.html\n');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch { /* non-fatal */ }
|
|
106
|
+
}
|
|
107
|
+
/** Returns the written file path. */
|
|
108
|
+
export function kbView(root, template, opts) {
|
|
109
|
+
const data = buildViewData(root, opts.generated);
|
|
110
|
+
const html = renderViewHtml(template, data);
|
|
111
|
+
const outPath = join(notebookDir(root), 'index.html');
|
|
112
|
+
writeFileSync(outPath, html);
|
|
113
|
+
ignoreIndexHtml(root);
|
|
114
|
+
if (opts.open !== false)
|
|
115
|
+
openInBrowser(outPath);
|
|
116
|
+
return outPath;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/kb/view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI9C,MAAM,IAAI,GAA+B,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AAE7F,kFAAkF;AAClF,SAAS,YAAY,CAAC,IAAgB;IACpC,MAAM,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACvD,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzB,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,CAAC,sCAAsC;IAChF,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;AACrB,CAAC;AAED,mFAAmF;AACnF,SAAS,YAAY,CAAC,IAAY,EAAE,IAAgB;IAClD,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3D,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,KAAK,EAAE,CAAC,CAAC,KAAmB;KAC7B,CAAC,CAAC,CAAC;IACJ,IAAI,IAAI,GAAe,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC;IAC/D,KAAK,MAAM,CAAC,IAAI,OAAO;QAAE,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;YAAE,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC;IAExE,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAExF,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI;QACjC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;QAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;QAC3B,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC;QACtB,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,IAAI;QACf,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,cAAc;QAC3D,QAAQ;QACR,IAAI;QACJ,SAAS,EAAE,EAAc;KAC1B,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,SAAiB;IAC3D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,MAAM;SACjB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC;SACvC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAErC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IAEvE,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,MAAM,WAAW,GAA2B,EAAE,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC3C,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC;AAC3G,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,IAAa;IAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D,OAAO,QAAQ,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AACvD,CAAC;AAED,gEAAgE;AAChE,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,GAAG,GACP,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE;QAC7D,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE;YAChF,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACpD,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC,CAAC,6CAA6C,CAAC,CAAC;AAC3D,CAAC;AAED,wEAAwE;AACxE,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;IACjD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,YAAY,CAAC,EAAE,CAAC;YAC5D,aAAa,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC;AAC7B,CAAC;AAOD,qCAAqC;AACrC,MAAM,UAAU,MAAM,CAAC,IAAY,EAAE,QAAgB,EAAE,IAAiB;IACtE,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;IACtD,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC7B,eAAe,CAAC,IAAI,CAAC,CAAC;IACtB,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK;QAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAChD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { FileCharacter, LessonKind, NoteType } from './types.js';
|
|
2
|
+
/** The agent-authored spec (JSON). Flat; unknown fields ride into the record.
|
|
3
|
+
* `type` also accepts the shorthands "file-hub" / "file-single" — sugar for
|
|
4
|
+
* type "file" + the character field (the log stores the canonical form so the
|
|
5
|
+
* tolerant reader's type set never grows). */
|
|
6
|
+
export interface WriteSpec {
|
|
7
|
+
type?: NoteType | 'file-hub' | 'file-single';
|
|
8
|
+
op?: 'put' | 'retract' | 'supersede';
|
|
9
|
+
id?: string;
|
|
10
|
+
/** File notes: the file the note is about (id + sole anchor derive from it). */
|
|
11
|
+
path?: string;
|
|
12
|
+
title?: string;
|
|
13
|
+
aliases?: string[];
|
|
14
|
+
anchors?: {
|
|
15
|
+
path: string;
|
|
16
|
+
symbols?: string[];
|
|
17
|
+
}[];
|
|
18
|
+
verified?: string[];
|
|
19
|
+
summary?: string;
|
|
20
|
+
character?: FileCharacter;
|
|
21
|
+
facets?: unknown[];
|
|
22
|
+
behaviors?: unknown[];
|
|
23
|
+
features?: unknown[];
|
|
24
|
+
steps?: unknown[];
|
|
25
|
+
invariants?: string[];
|
|
26
|
+
kind?: LessonKind;
|
|
27
|
+
body?: string;
|
|
28
|
+
scope?: {
|
|
29
|
+
terms?: string[];
|
|
30
|
+
globs?: string[];
|
|
31
|
+
};
|
|
32
|
+
target?: {
|
|
33
|
+
kind: string;
|
|
34
|
+
key?: string;
|
|
35
|
+
};
|
|
36
|
+
by?: string;
|
|
37
|
+
[key: string]: unknown;
|
|
38
|
+
}
|
|
39
|
+
export interface WriteCandidate {
|
|
40
|
+
id: string;
|
|
41
|
+
type: string;
|
|
42
|
+
title: string;
|
|
43
|
+
summary: string;
|
|
44
|
+
}
|
|
45
|
+
export type WriteResult = {
|
|
46
|
+
status: 'written';
|
|
47
|
+
id: string;
|
|
48
|
+
mdPath: string;
|
|
49
|
+
op: string;
|
|
50
|
+
warnings?: string[];
|
|
51
|
+
} | {
|
|
52
|
+
status: 'candidates';
|
|
53
|
+
candidates: WriteCandidate[];
|
|
54
|
+
message: string;
|
|
55
|
+
} | {
|
|
56
|
+
status: 'error';
|
|
57
|
+
message: string;
|
|
58
|
+
};
|
|
59
|
+
export interface WriteOptions {
|
|
60
|
+
/** Merge into this existing note id (phase-2 answer). */
|
|
61
|
+
into?: string;
|
|
62
|
+
/** Explicitly declare a new concept (phase-2 answer). */
|
|
63
|
+
isNew?: boolean;
|
|
64
|
+
/** Skip ALL candidate gates (fuzzy, exact-address, facet clash) and just
|
|
65
|
+
* write. Validation-run mode: duplicates are observable data. Structural
|
|
66
|
+
* validation (character, facet shape, ids) still applies. */
|
|
67
|
+
force?: boolean;
|
|
68
|
+
/** Session id for the capture-rate metric. */
|
|
69
|
+
session?: string;
|
|
70
|
+
}
|
|
71
|
+
export declare function kbWrite(root: string, spec: WriteSpec, opts?: WriteOptions): Promise<WriteResult>;
|
|
72
|
+
//# sourceMappingURL=write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/kb/write.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAS,aAAa,EAAc,UAAU,EAAkB,QAAQ,EAAE,MAAM,YAAY,CAAC;AAUzG;;;+CAG+C;AAC/C,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,aAAa,CAAC;IAC7C,EAAE,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,WAAW,CAAC;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IACjD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC/C,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAClF;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,cAAc,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,WAAW,YAAY;IAC3B,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;kEAE8D;IAC9D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAsO1G"}
|
package/dist/kb/write.js
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kb write — the single write gate. The agent authors a JSON spec; this
|
|
3
|
+
* validates it, enforces the TWO-PHASE reuse gate for flow/lesson concepts,
|
|
4
|
+
* appends to the `.raw` log (which stamps ts + hashes), re-folds, and renders
|
|
5
|
+
* the derived md.
|
|
6
|
+
*
|
|
7
|
+
* Two-phase (the id-stability answer): a flow/lesson spec arriving WITHOUT an
|
|
8
|
+
* id first runs the note search on its own words. Any plausible matches →
|
|
9
|
+
* exit "candidates": the agent must re-run with `--into <id>` (merge into the
|
|
10
|
+
* existing concept) or `--new` (explicitly declare a new one). Unreliable
|
|
11
|
+
* generation ("produce the identical string") becomes reliable matching
|
|
12
|
+
* ("is this the same as one of these five?"). File notes skip the gate —
|
|
13
|
+
* their id is derived from the path.
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync } from 'node:fs';
|
|
16
|
+
import { isAbsolute, join } from 'node:path';
|
|
17
|
+
import { fileNoteId, coinId, isValidId } from './ids.js';
|
|
18
|
+
import { appendRecord, listIds } from './raw-log.js';
|
|
19
|
+
import { loadNote, loadAll, writeNoteMd, logMetric } from './store.js';
|
|
20
|
+
import { kbSearch } from './search.js';
|
|
21
|
+
const NOTE_TYPES = new Set(['file', 'flow', 'lesson']);
|
|
22
|
+
const LESSON_KINDS = new Set(['absence']);
|
|
23
|
+
const CHARACTERS = new Set(['hub', 'single']);
|
|
24
|
+
export async function kbWrite(root, spec, opts = {}) {
|
|
25
|
+
if (!spec || typeof spec !== 'object' || Array.isArray(spec))
|
|
26
|
+
return err('spec must be a JSON object');
|
|
27
|
+
const op = spec.op ?? 'put';
|
|
28
|
+
if (!['put', 'retract', 'supersede'].includes(op))
|
|
29
|
+
return err(`unknown op ${JSON.stringify(op)} — use put, retract, or supersede`);
|
|
30
|
+
// "file-hub" / "file-single" are spec-level sugar; the log stores type "file"
|
|
31
|
+
// + character (type is fold-immutable, character is a revisable judgment).
|
|
32
|
+
let type = spec.type;
|
|
33
|
+
let character = spec.character;
|
|
34
|
+
if (spec.type === 'file-hub' || spec.type === 'file-single') {
|
|
35
|
+
const sugared = spec.type === 'file-hub' ? 'hub' : 'single';
|
|
36
|
+
if (character && character !== sugared)
|
|
37
|
+
return err(`type "${spec.type}" conflicts with character "${character}"`);
|
|
38
|
+
character = sugared;
|
|
39
|
+
type = 'file';
|
|
40
|
+
}
|
|
41
|
+
if (!type || !NOTE_TYPES.has(type))
|
|
42
|
+
return err('spec needs a `type`: "file" (one real file — or shorthand "file-hub"/"file-single"), "flow" (a cross-file story), or "lesson" (a confirmed absence — "there is no X in this repo", with the search terms that proved it)');
|
|
43
|
+
if (character !== undefined && !CHARACTERS.has(character))
|
|
44
|
+
return err('`character` must be "hub" (no single purpose — knowledge lives as symbol-keyed facets) or "single" (one purpose, one summary)');
|
|
45
|
+
if (character !== undefined && type !== 'file')
|
|
46
|
+
return err('`character` belongs to file notes');
|
|
47
|
+
const facets = spec.facets;
|
|
48
|
+
if (facets !== undefined) {
|
|
49
|
+
if (type !== 'file')
|
|
50
|
+
return err('`facets` belong to file notes — flows point at them via step symbols; lessons anchor to them');
|
|
51
|
+
if (!Array.isArray(facets) || !facets.length)
|
|
52
|
+
return err('`facets` must be a non-empty array');
|
|
53
|
+
for (const f of facets) {
|
|
54
|
+
if (!f || typeof f !== 'object' || typeof f.symbol !== 'string' || !f.symbol.trim() || typeof f.detail !== 'string' || !f.detail.trim()) {
|
|
55
|
+
return err('each facet needs `symbol` (the top-level symbol it is about) and `detail` (+ optional `flows`: related flow-note ids)');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// ---- resolve the id -------------------------------------------------------
|
|
60
|
+
let id = opts.into ?? spec.id;
|
|
61
|
+
let freshlyCoined = false; // a coined id is created EXCLUSIVELY (see appendRecord)
|
|
62
|
+
const existing = new Set(listIds(root));
|
|
63
|
+
if (id !== undefined) {
|
|
64
|
+
if (!isValidId(id))
|
|
65
|
+
return err(`invalid id ${JSON.stringify(id)}`);
|
|
66
|
+
if ((opts.into || op !== 'put') && !existing.has(id))
|
|
67
|
+
return err(`no existing note ${id} — omit the id to create, or check \`kb status\``);
|
|
68
|
+
if (existing.has(id)) {
|
|
69
|
+
// A type-mismatched append would be skipped by the fold — reject it here.
|
|
70
|
+
const { note: target } = loadNote(root, id);
|
|
71
|
+
if (target && target.type !== type) {
|
|
72
|
+
return err(`${id} is a ${target.type} note, but this spec says type ${type} — wrong target id?`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (type === 'file') {
|
|
77
|
+
if (!spec.path)
|
|
78
|
+
return err('a file note needs `path` — the file it is about');
|
|
79
|
+
const derived = fileNoteId(spec.path);
|
|
80
|
+
if (id && id !== derived)
|
|
81
|
+
return err(`file-note ids are derived from the path (${derived}) — omit \`id\``);
|
|
82
|
+
id = derived;
|
|
83
|
+
}
|
|
84
|
+
else if (op === 'put' && !id) {
|
|
85
|
+
if (!spec.title || !String(spec.title).trim())
|
|
86
|
+
return err(`a new ${type} note needs a \`title\` (concept words a future agent would search with)`);
|
|
87
|
+
// ---- the two-phase gate ----
|
|
88
|
+
if (!opts.isNew && !opts.force) {
|
|
89
|
+
if (type === 'lesson' && Array.isArray(spec.anchors) && spec.anchors.length) {
|
|
90
|
+
// File-anchored facts dedup by EXACT (path, symbol) address — never by
|
|
91
|
+
// fuzzy title overlap (title words are whatever this session happened
|
|
92
|
+
// to choose; the address is stable).
|
|
93
|
+
const candidates = exactAddressCandidates(root, spec.anchors);
|
|
94
|
+
if (candidates.length) {
|
|
95
|
+
return {
|
|
96
|
+
status: 'candidates',
|
|
97
|
+
candidates,
|
|
98
|
+
message: 'Existing knowledge at this exact (path, symbol) address. A lesson → re-run with `--into <id>` to reconcile into it. A file-note facet → the fact may belong there instead: re-submit as `{"type": "file-hub", "path": ..., "facets": [...]}` with `--into <file-note-id>`. Only if yours is a genuinely different fact, re-run with `--new`.',
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const queryWords = [spec.title, ...(spec.aliases ?? []), spec.summary ?? ''].join(' ');
|
|
104
|
+
const { hits } = await kbSearch(root, queryWords, { maxResults: 5, noMissLog: true });
|
|
105
|
+
// Same-type only: a lesson about a flow's file always word-overlaps that
|
|
106
|
+
// flow, but they are never the same concept — cross-type candidates would
|
|
107
|
+
// gate every lesson (and merging a lesson --into a flow corrupts the log).
|
|
108
|
+
const candidates = hits
|
|
109
|
+
.filter((h) => h.note.type === type && h.note.status === 'active')
|
|
110
|
+
.map((h) => ({
|
|
111
|
+
id: h.note.id,
|
|
112
|
+
type: h.note.type,
|
|
113
|
+
title: h.note.title,
|
|
114
|
+
summary: (h.note.summary ?? h.note.body ?? '').split('\n')[0].slice(0, 160),
|
|
115
|
+
}));
|
|
116
|
+
if (candidates.length) {
|
|
117
|
+
return {
|
|
118
|
+
status: 'candidates',
|
|
119
|
+
candidates,
|
|
120
|
+
message: 'Existing notes may already cover this concept. If one of these IS your concept, re-run with `--into <id>` to merge into it (reconcile, don\'t duplicate). Only if none match, re-run with `--new`.',
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
id = coinId(spec.title, existing);
|
|
126
|
+
freshlyCoined = true;
|
|
127
|
+
}
|
|
128
|
+
if (!id)
|
|
129
|
+
return err(`op ${op} needs an \`id\` (which note to ${op})`);
|
|
130
|
+
const current = existing.has(id) ? loadNote(root, id).note : null;
|
|
131
|
+
// ---- per-type validation (put only) --------------------------------------
|
|
132
|
+
if (op === 'put') {
|
|
133
|
+
if (type === 'file') {
|
|
134
|
+
const effective = character ?? current?.character;
|
|
135
|
+
if (!effective)
|
|
136
|
+
return err('a file note needs `character` — "hub" (no single purpose; knowledge lives as symbol-keyed facets) or "single" (one purpose, one summary). Shorthand: `"type": "file-hub"` / `"file-single"`');
|
|
137
|
+
if (facets && effective === 'single')
|
|
138
|
+
return err('facets are for hub files — a single-purpose file carries one `summary`. If this file has outgrown one purpose, re-declare it: `"character": "hub"`');
|
|
139
|
+
// ---- facet clash gate: replacing existing knowledge must be informed ----
|
|
140
|
+
if (facets && current && !opts.into && !opts.force) {
|
|
141
|
+
const clashes = facets.filter((f) => current.facets.some((x) => x.symbol === f.symbol));
|
|
142
|
+
if (clashes.length) {
|
|
143
|
+
return {
|
|
144
|
+
status: 'candidates',
|
|
145
|
+
candidates: clashes.map((f) => {
|
|
146
|
+
const cur = current.facets.find((x) => x.symbol === f.symbol);
|
|
147
|
+
return { id: id, type: 'file', title: `${spec.path} :: ${cur.symbol}`, summary: cur.detail.split('\n')[0].slice(0, 160) };
|
|
148
|
+
}),
|
|
149
|
+
message: 'A facet already exists at this symbol address (current knowledge shown above). If yours corrects or extends it, re-run with `--into <file-note-id>` — your detail replaces it, flow links union. If it is about something else, use a different symbol.',
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (type === 'lesson') {
|
|
155
|
+
if (!spec.kind || !LESSON_KINDS.has(spec.kind))
|
|
156
|
+
return err('a lesson needs `kind`: absence (the only lesson kind — a confirmed "there is no X", with the search that proved it)');
|
|
157
|
+
if (spec.kind === 'absence' && !spec.scope?.terms?.length)
|
|
158
|
+
return err('an absence lesson needs `scope.terms` — the search that proved the absence (freshness = re-running it)');
|
|
159
|
+
if (!spec.body && !spec.id && !opts.into)
|
|
160
|
+
return err('a lesson needs a `body` — when it applies + the actual truth');
|
|
161
|
+
}
|
|
162
|
+
if (type === 'flow' && !spec.id && !opts.into && !spec.steps?.length && !spec.summary) {
|
|
163
|
+
return err('a flow note needs `steps` (the ordered cross-file story) or at least a `summary`');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else if (op === 'retract' && (!spec.target || typeof spec.target !== 'object' || !spec.target.kind)) {
|
|
167
|
+
return err('a retract needs `target`: {kind: behavior|feature|anchor|invariant|alias|note, key?}');
|
|
168
|
+
}
|
|
169
|
+
else if (op === 'supersede' && !spec.by) {
|
|
170
|
+
return err('a supersede needs `by` — the id of the note that replaces this one');
|
|
171
|
+
}
|
|
172
|
+
// ---- facet flow-ref resolution (title → id; lexical, warn-never-reject) ---
|
|
173
|
+
// Agents write flows and the file notes that back-link them in ONE chained
|
|
174
|
+
// call, but a flow's coined id isn't predictable (collision suffix), so a
|
|
175
|
+
// facet `flows` entry may be the flow's EXACT title instead. Resolution is
|
|
176
|
+
// strictly lexical: exact id match first, else exact normalized-title match
|
|
177
|
+
// against active flows — never fuzzy, so a wrong id can't be substituted.
|
|
178
|
+
// Anything unresolvable (typo, ambiguous title, non-flow id) is kept AS
|
|
179
|
+
// WRITTEN and warned about — same contract as pathWarnings: the note is
|
|
180
|
+
// never lost over one bad link; the writing agent fixes it right now, and
|
|
181
|
+
// lint flags whatever survives.
|
|
182
|
+
const flowRefWarnings = [];
|
|
183
|
+
if (op === 'put' && facets?.some((f) => f.flows?.length)) {
|
|
184
|
+
const { notes } = loadAll(root);
|
|
185
|
+
const active = notes.filter((n) => n.status === 'active');
|
|
186
|
+
const byId = new Map(active.map((n) => [n.id, n]));
|
|
187
|
+
const norm = (s) => s.toLowerCase().replace(/\s+/g, ' ').trim();
|
|
188
|
+
const byTitle = new Map();
|
|
189
|
+
for (const n of active) {
|
|
190
|
+
if (n.type !== 'flow')
|
|
191
|
+
continue;
|
|
192
|
+
const k = norm(n.title);
|
|
193
|
+
byTitle.set(k, [...(byTitle.get(k) ?? []), n]);
|
|
194
|
+
}
|
|
195
|
+
const resolved = [];
|
|
196
|
+
for (const f of facets) {
|
|
197
|
+
if (!f.flows?.length) {
|
|
198
|
+
resolved.push(f);
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
const out = [];
|
|
202
|
+
for (const ref of f.flows) {
|
|
203
|
+
const hit = byId.get(ref);
|
|
204
|
+
if (hit) {
|
|
205
|
+
out.push(ref);
|
|
206
|
+
if (hit.type !== 'flow')
|
|
207
|
+
flowRefWarnings.push(`facet "${f.symbol}": flows entry "${ref}" is a ${hit.type} note, not a flow — check the id`);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const matches = byTitle.get(norm(ref)) ?? [];
|
|
211
|
+
if (matches.length === 1) {
|
|
212
|
+
out.push(matches[0].id);
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
out.push(ref); // preserved as written — dangling beats lost
|
|
216
|
+
flowRefWarnings.push(matches.length > 1
|
|
217
|
+
? `facet "${f.symbol}": flow title "${ref}" is ambiguous (${matches.map((m) => m.id).join(', ')}) — kept as written; replace with the id`
|
|
218
|
+
: `facet "${f.symbol}": flows entry "${ref}" matches no flow id or exact flow title — kept as written (dangling); fix with the flow's printed id or exact title`);
|
|
219
|
+
}
|
|
220
|
+
resolved.push({ ...f, flows: out });
|
|
221
|
+
}
|
|
222
|
+
spec = { ...spec, facets: resolved };
|
|
223
|
+
}
|
|
224
|
+
// ---- build the record -----------------------------------------------------
|
|
225
|
+
const { type: _t, op: _o, id: _i, path, ...rest } = spec;
|
|
226
|
+
void _t;
|
|
227
|
+
void _o;
|
|
228
|
+
void _i;
|
|
229
|
+
// The fold's tolerant reader validates payload shapes; the spec passes through.
|
|
230
|
+
const record = { ...rest, id, type, op };
|
|
231
|
+
if (type === 'file' && op === 'put' && path) {
|
|
232
|
+
// The file IS the anchor; the writer just deep-read it, so it counts verified.
|
|
233
|
+
// Anchor symbols accumulate (union with what the note already knows +
|
|
234
|
+
// facet symbols). The fold ALSO unions (concurrent writers each see stale
|
|
235
|
+
// state); the write-side union just keeps each record self-contained.
|
|
236
|
+
const symbols = [...new Set([
|
|
237
|
+
...(current?.anchors.find((a) => a.path === path)?.symbols ?? []),
|
|
238
|
+
...(Array.isArray(spec.anchors?.[0]?.symbols) ? spec.anchors[0].symbols : []),
|
|
239
|
+
...(facets?.map((f) => f.symbol) ?? []),
|
|
240
|
+
])];
|
|
241
|
+
record.anchors = [{ path, ...(symbols.length ? { symbols } : {}) }];
|
|
242
|
+
record.verified = [...new Set([path, ...(spec.verified ?? [])])];
|
|
243
|
+
if (character)
|
|
244
|
+
record.character = character; // sugar form ("file-hub") lands here
|
|
245
|
+
}
|
|
246
|
+
// A freshly-coined id is created with O_EXCL: two concurrent sessions can
|
|
247
|
+
// coin the same id (both listed the dir before either created the file) and
|
|
248
|
+
// would otherwise silently merge into one note. The loser lands on EEXIST,
|
|
249
|
+
// marks the id taken, and re-coins — two same-moment captures of one concept
|
|
250
|
+
// become a visible duplicate, never a silent merge.
|
|
251
|
+
try {
|
|
252
|
+
for (let attempt = 0;; attempt++) {
|
|
253
|
+
try {
|
|
254
|
+
appendRecord(root, record, { exclusive: freshlyCoined });
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
catch (e) {
|
|
258
|
+
const code = e?.code;
|
|
259
|
+
if (!freshlyCoined || code !== 'EEXIST' || attempt >= 50)
|
|
260
|
+
throw e;
|
|
261
|
+
existing.add(id);
|
|
262
|
+
id = coinId(spec.title, existing);
|
|
263
|
+
record.id = id;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch (e) {
|
|
268
|
+
return err(e instanceof Error ? e.message : String(e));
|
|
269
|
+
}
|
|
270
|
+
const { note } = loadNote(root, id);
|
|
271
|
+
if (!note)
|
|
272
|
+
return err(`internal: ${id} folded to nothing after write`);
|
|
273
|
+
const mdPath = writeNoteMd(root, note);
|
|
274
|
+
logMetric(root, 'capture', { event: 'write', id, type, op, session: opts.session });
|
|
275
|
+
const warnings = [...(op === 'put' ? pathWarnings(root, spec) : []), ...flowRefWarnings];
|
|
276
|
+
return { status: 'written', id, mdPath, op, ...(warnings.length ? { warnings } : {}) };
|
|
277
|
+
}
|
|
278
|
+
/** Flag step/anchor paths that don't exist on disk — the flow→file join is a
|
|
279
|
+
* static path string, so a typo'd path is a silently dangling link. Warn,
|
|
280
|
+
* never reject: the writing agent is best placed to fix it right now, and a
|
|
281
|
+
* legitimately deleted file is the agent's call to record. */
|
|
282
|
+
function pathWarnings(root, spec) {
|
|
283
|
+
const out = [];
|
|
284
|
+
const check = (p, where) => {
|
|
285
|
+
if (typeof p !== 'string' || !p)
|
|
286
|
+
return;
|
|
287
|
+
if (isAbsolute(p)) {
|
|
288
|
+
out.push(`${where} "${p}" is absolute — use a repo-relative path (links join on the exact string)`);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (!existsSync(join(root, p)))
|
|
292
|
+
out.push(`${where} "${p}" not found on disk — dangling link unless the path is fixed`);
|
|
293
|
+
};
|
|
294
|
+
check(spec.path, 'path');
|
|
295
|
+
for (const a of spec.anchors ?? [])
|
|
296
|
+
check(a?.path, 'anchor');
|
|
297
|
+
for (const s of (spec.steps ?? []))
|
|
298
|
+
check(s?.path, 'step');
|
|
299
|
+
return out;
|
|
300
|
+
}
|
|
301
|
+
function err(message) {
|
|
302
|
+
return { status: 'error', message };
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Exact (path, symbol) dedup for anchored lessons — the S2 walk: "what do we
|
|
306
|
+
* know about models.py::LoadStaging?" resolves by address, never by title
|
|
307
|
+
* words. Same-granularity matching keeps it exact: a symbol-level spec matches
|
|
308
|
+
* symbol-level lessons (overlap) plus the file note's facets at those symbols;
|
|
309
|
+
* a file-level spec (no symbols) matches file-level lessons on the same path.
|
|
310
|
+
*/
|
|
311
|
+
function exactAddressCandidates(root, anchors) {
|
|
312
|
+
const out = [];
|
|
313
|
+
const seen = new Set();
|
|
314
|
+
const { notes } = loadAll(root);
|
|
315
|
+
for (const spec of anchors) {
|
|
316
|
+
if (!spec || typeof spec.path !== 'string' || !spec.path)
|
|
317
|
+
continue;
|
|
318
|
+
const symbols = Array.isArray(spec.symbols) ? spec.symbols.filter((s) => typeof s === 'string') : [];
|
|
319
|
+
for (const n of notes) {
|
|
320
|
+
if (n.status !== 'active' || n.type !== 'lesson')
|
|
321
|
+
continue;
|
|
322
|
+
const hit = n.anchors.some((a) => a.path === spec.path && (symbols.length
|
|
323
|
+
? (a.symbols ?? []).some((s) => symbols.includes(s))
|
|
324
|
+
: !a.symbols?.length));
|
|
325
|
+
if (hit && !seen.has(n.id)) {
|
|
326
|
+
seen.add(n.id);
|
|
327
|
+
out.push({ id: n.id, type: 'lesson', title: n.title, summary: (n.body ?? '').split('\n')[0].slice(0, 160) });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
if (symbols.length) {
|
|
331
|
+
const fnote = notes.find((n) => n.id === fileNoteId(spec.path) && n.status === 'active');
|
|
332
|
+
for (const f of fnote?.facets ?? []) {
|
|
333
|
+
if (!symbols.includes(f.symbol))
|
|
334
|
+
continue;
|
|
335
|
+
const key = `${fnote.id}::${f.symbol}`;
|
|
336
|
+
if (seen.has(key))
|
|
337
|
+
continue;
|
|
338
|
+
seen.add(key);
|
|
339
|
+
out.push({ id: fnote.id, type: 'file', title: `${spec.path} :: ${f.symbol}`, summary: f.detail.split('\n')[0].slice(0, 160) });
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return out;
|
|
344
|
+
}
|
|
345
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/kb/write.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface KeeperEventStamp {
|
|
2
|
+
at: number;
|
|
3
|
+
detail: string;
|
|
4
|
+
}
|
|
5
|
+
export interface KeeperState {
|
|
6
|
+
pid: number;
|
|
7
|
+
startedAt: number;
|
|
8
|
+
lastReconcile?: KeeperEventStamp;
|
|
9
|
+
lastPatch?: KeeperEventStamp;
|
|
10
|
+
lastRebuild?: KeeperEventStamp;
|
|
11
|
+
lastSave?: KeeperEventStamp;
|
|
12
|
+
}
|
|
13
|
+
export interface RepairEvent {
|
|
14
|
+
at: number;
|
|
15
|
+
event: 'patch-failed' | 'rebuild-failed' | 'invariant-violation' | 'reconcile-failed';
|
|
16
|
+
detail: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function keeperStatePath(rootDir: string, baseCacheDir?: string): string;
|
|
19
|
+
export declare function repairLogPath(rootDir: string, baseCacheDir?: string): string;
|
|
20
|
+
/** Read-merge-write. Best-effort and atomic — observability must never take
|
|
21
|
+
* the keeper down, so all failures are swallowed. */
|
|
22
|
+
export declare function updateKeeperState(rootDir: string, patch: Partial<KeeperState>, baseCacheDir?: string): Promise<void>;
|
|
23
|
+
export declare function readKeeperState(rootDir: string, baseCacheDir?: string): KeeperState | null;
|
|
24
|
+
/** Append one failure record. Size-capped: past the cap the file starts over
|
|
25
|
+
* (the tail is what matters; a growing failure log IS the signal). */
|
|
26
|
+
export declare function appendRepairLog(rootDir: string, event: RepairEvent['event'], detail: string, baseCacheDir?: string): Promise<void>;
|
|
27
|
+
/** Last N repair events (tolerant reader — skips corrupt lines). */
|
|
28
|
+
export declare function readRepairTail(rootDir: string, n?: number, baseCacheDir?: string): RepairEvent[];
|
|
29
|
+
//# sourceMappingURL=keeper-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keeper-state.d.ts","sourceRoot":"","sources":["../src/keeper-state.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,gBAAgB,CAAC;IACjC,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,cAAc,GAAG,gBAAgB,GAAG,qBAAqB,GAAG,kBAAkB,CAAC;IACtF,MAAM,EAAE,MAAM,CAAC;CAChB;AAMD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED;sDACsD;AACtD,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,EAC3B,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAO1F;AAED;uEACuE;AACvE,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,EAC3B,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,oEAAoE;AACpE,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,SAAI,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAc3F"}
|