ctxr-cli 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.
- package/LICENSE +201 -0
- package/README.md +25 -0
- package/dist/adapter.d.ts +18 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +4 -0
- package/dist/adapter.js.map +1 -0
- package/dist/adapters/builtin/index.d.ts +10 -0
- package/dist/adapters/builtin/index.d.ts.map +1 -0
- package/dist/adapters/builtin/index.js +11 -0
- package/dist/adapters/builtin/index.js.map +1 -0
- package/dist/adapters/forge/github.d.ts +9 -0
- package/dist/adapters/forge/github.d.ts.map +1 -0
- package/dist/adapters/forge/github.js +36 -0
- package/dist/adapters/forge/github.js.map +1 -0
- package/dist/adapters/forge/types.d.ts +23 -0
- package/dist/adapters/forge/types.d.ts.map +1 -0
- package/dist/adapters/forge/types.js +2 -0
- package/dist/adapters/forge/types.js.map +1 -0
- package/dist/adapters/harness/claude-code.d.ts +9 -0
- package/dist/adapters/harness/claude-code.d.ts.map +1 -0
- package/dist/adapters/harness/claude-code.js +42 -0
- package/dist/adapters/harness/claude-code.js.map +1 -0
- package/dist/adapters/identity/claude-code.d.ts +11 -0
- package/dist/adapters/identity/claude-code.d.ts.map +1 -0
- package/dist/adapters/identity/claude-code.js +18 -0
- package/dist/adapters/identity/claude-code.js.map +1 -0
- package/dist/adapters/registry.d.ts +16 -0
- package/dist/adapters/registry.d.ts.map +1 -0
- package/dist/adapters/registry.js +29 -0
- package/dist/adapters/registry.js.map +1 -0
- package/dist/adapters/types.d.ts +65 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +12 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +6 -0
- package/dist/bin.js.map +1 -0
- package/dist/commands/adapters-generate.d.ts +23 -0
- package/dist/commands/adapters-generate.d.ts.map +1 -0
- package/dist/commands/adapters-generate.js +59 -0
- package/dist/commands/adapters-generate.js.map +1 -0
- package/dist/commands/archive.d.ts +28 -0
- package/dist/commands/archive.d.ts.map +1 -0
- package/dist/commands/archive.js +66 -0
- package/dist/commands/archive.js.map +1 -0
- package/dist/commands/catalog-build.d.ts +7 -0
- package/dist/commands/catalog-build.d.ts.map +1 -0
- package/dist/commands/catalog-build.js +15 -0
- package/dist/commands/catalog-build.js.map +1 -0
- package/dist/commands/catalog-check.d.ts +22 -0
- package/dist/commands/catalog-check.d.ts.map +1 -0
- package/dist/commands/catalog-check.js +49 -0
- package/dist/commands/catalog-check.js.map +1 -0
- package/dist/commands/catalog-show.d.ts +13 -0
- package/dist/commands/catalog-show.d.ts.map +1 -0
- package/dist/commands/catalog-show.js +19 -0
- package/dist/commands/catalog-show.js.map +1 -0
- package/dist/commands/check.d.ts +22 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +43 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/doctor.d.ts +27 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +53 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/graph-build.d.ts +24 -0
- package/dist/commands/graph-build.d.ts.map +1 -0
- package/dist/commands/graph-build.js +36 -0
- package/dist/commands/graph-build.js.map +1 -0
- package/dist/commands/graph-query.d.ts +41 -0
- package/dist/commands/graph-query.d.ts.map +1 -0
- package/dist/commands/graph-query.js +63 -0
- package/dist/commands/graph-query.js.map +1 -0
- package/dist/commands/ingest.d.ts +28 -0
- package/dist/commands/ingest.d.ts.map +1 -0
- package/dist/commands/ingest.js +60 -0
- package/dist/commands/ingest.js.map +1 -0
- package/dist/commands/init.d.ts +28 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +203 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/lint.d.ts +30 -0
- package/dist/commands/lint.d.ts.map +1 -0
- package/dist/commands/lint.js +48 -0
- package/dist/commands/lint.js.map +1 -0
- package/dist/commands/migrate.d.ts +30 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +56 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/note-resolve.d.ts +14 -0
- package/dist/commands/note-resolve.d.ts.map +1 -0
- package/dist/commands/note-resolve.js +24 -0
- package/dist/commands/note-resolve.js.map +1 -0
- package/dist/commands/rollup-gather.d.ts +21 -0
- package/dist/commands/rollup-gather.d.ts.map +1 -0
- package/dist/commands/rollup-gather.js +40 -0
- package/dist/commands/rollup-gather.js.map +1 -0
- package/dist/commands/rollup-write.d.ts +25 -0
- package/dist/commands/rollup-write.d.ts.map +1 -0
- package/dist/commands/rollup-write.js +43 -0
- package/dist/commands/rollup-write.js.map +1 -0
- package/dist/commands/session-abandon.d.ts +13 -0
- package/dist/commands/session-abandon.d.ts.map +1 -0
- package/dist/commands/session-abandon.js +22 -0
- package/dist/commands/session-abandon.js.map +1 -0
- package/dist/commands/session-list.d.ts +14 -0
- package/dist/commands/session-list.d.ts.map +1 -0
- package/dist/commands/session-list.js +19 -0
- package/dist/commands/session-list.js.map +1 -0
- package/dist/commands/session-reap.d.ts +22 -0
- package/dist/commands/session-reap.d.ts.map +1 -0
- package/dist/commands/session-reap.js +47 -0
- package/dist/commands/session-reap.js.map +1 -0
- package/dist/commands/session-start.d.ts +18 -0
- package/dist/commands/session-start.d.ts.map +1 -0
- package/dist/commands/session-start.js +36 -0
- package/dist/commands/session-start.js.map +1 -0
- package/dist/commands/session-submit.d.ts +27 -0
- package/dist/commands/session-submit.d.ts.map +1 -0
- package/dist/commands/session-submit.js +68 -0
- package/dist/commands/session-submit.js.map +1 -0
- package/dist/commands/source-check.d.ts +21 -0
- package/dist/commands/source-check.d.ts.map +1 -0
- package/dist/commands/source-check.js +54 -0
- package/dist/commands/source-check.js.map +1 -0
- package/dist/commands/source-hash.d.ts +14 -0
- package/dist/commands/source-hash.d.ts.map +1 -0
- package/dist/commands/source-hash.js +34 -0
- package/dist/commands/source-hash.js.map +1 -0
- package/dist/commands/update.d.ts +17 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +25 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/verify.d.ts +23 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +126 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/config/defaults.d.ts +69 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +71 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/load.d.ts +11 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +49 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/render.d.ts +9 -0
- package/dist/config/render.d.ts.map +1 -0
- package/dist/config/render.js +15 -0
- package/dist/config/render.js.map +1 -0
- package/dist/config/schema.d.ts +124 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +142 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/agents-doc.d.ts +80 -0
- package/dist/core/agents-doc.d.ts.map +1 -0
- package/dist/core/agents-doc.js +207 -0
- package/dist/core/agents-doc.js.map +1 -0
- package/dist/core/catalog/build.d.ts +49 -0
- package/dist/core/catalog/build.d.ts.map +1 -0
- package/dist/core/catalog/build.js +113 -0
- package/dist/core/catalog/build.js.map +1 -0
- package/dist/core/catalog/model.d.ts +33 -0
- package/dist/core/catalog/model.d.ts.map +1 -0
- package/dist/core/catalog/model.js +58 -0
- package/dist/core/catalog/model.js.map +1 -0
- package/dist/core/checks/catalog-checks.d.ts +4 -0
- package/dist/core/checks/catalog-checks.d.ts.map +1 -0
- package/dist/core/checks/catalog-checks.js +65 -0
- package/dist/core/checks/catalog-checks.js.map +1 -0
- package/dist/core/checks/identity-checks.d.ts +11 -0
- package/dist/core/checks/identity-checks.d.ts.map +1 -0
- package/dist/core/checks/identity-checks.js +39 -0
- package/dist/core/checks/identity-checks.js.map +1 -0
- package/dist/core/checks/integrity-checks.d.ts +23 -0
- package/dist/core/checks/integrity-checks.d.ts.map +1 -0
- package/dist/core/checks/integrity-checks.js +132 -0
- package/dist/core/checks/integrity-checks.js.map +1 -0
- package/dist/core/checks/manifest.d.ts +7 -0
- package/dist/core/checks/manifest.d.ts.map +1 -0
- package/dist/core/checks/manifest.js +20 -0
- package/dist/core/checks/manifest.js.map +1 -0
- package/dist/core/checks/organize-checks.d.ts +18 -0
- package/dist/core/checks/organize-checks.d.ts.map +1 -0
- package/dist/core/checks/organize-checks.js +97 -0
- package/dist/core/checks/organize-checks.js.map +1 -0
- package/dist/core/checks/registry.d.ts +24 -0
- package/dist/core/checks/registry.d.ts.map +1 -0
- package/dist/core/checks/registry.js +33 -0
- package/dist/core/checks/registry.js.map +1 -0
- package/dist/core/checks/types.d.ts +72 -0
- package/dist/core/checks/types.d.ts.map +1 -0
- package/dist/core/checks/types.js +4 -0
- package/dist/core/checks/types.js.map +1 -0
- package/dist/core/checks/write-lifecycle-checks.d.ts +24 -0
- package/dist/core/checks/write-lifecycle-checks.d.ts.map +1 -0
- package/dist/core/checks/write-lifecycle-checks.js +205 -0
- package/dist/core/checks/write-lifecycle-checks.js.map +1 -0
- package/dist/core/command.d.ts +23 -0
- package/dist/core/command.d.ts.map +1 -0
- package/dist/core/command.js +2 -0
- package/dist/core/command.js.map +1 -0
- package/dist/core/content/canonicalize.d.ts +14 -0
- package/dist/core/content/canonicalize.d.ts.map +1 -0
- package/dist/core/content/canonicalize.js +34 -0
- package/dist/core/content/canonicalize.js.map +1 -0
- package/dist/core/conventions.d.ts +21 -0
- package/dist/core/conventions.d.ts.map +1 -0
- package/dist/core/conventions.js +73 -0
- package/dist/core/conventions.js.map +1 -0
- package/dist/core/disclosure/model.d.ts +18 -0
- package/dist/core/disclosure/model.d.ts.map +1 -0
- package/dist/core/disclosure/model.js +45 -0
- package/dist/core/disclosure/model.js.map +1 -0
- package/dist/core/env.d.ts +40 -0
- package/dist/core/env.d.ts.map +1 -0
- package/dist/core/env.js +24 -0
- package/dist/core/env.js.map +1 -0
- package/dist/core/envelope.d.ts +46 -0
- package/dist/core/envelope.d.ts.map +1 -0
- package/dist/core/envelope.js +21 -0
- package/dist/core/envelope.js.map +1 -0
- package/dist/core/errors.d.ts +96 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +267 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/exit-codes.d.ts +32 -0
- package/dist/core/exit-codes.d.ts.map +1 -0
- package/dist/core/exit-codes.js +31 -0
- package/dist/core/exit-codes.js.map +1 -0
- package/dist/core/fs/atomic.d.ts +10 -0
- package/dist/core/fs/atomic.d.ts.map +1 -0
- package/dist/core/fs/atomic.js +31 -0
- package/dist/core/fs/atomic.js.map +1 -0
- package/dist/core/fs/fenced-region.d.ts +47 -0
- package/dist/core/fs/fenced-region.d.ts.map +1 -0
- package/dist/core/fs/fenced-region.js +122 -0
- package/dist/core/fs/fenced-region.js.map +1 -0
- package/dist/core/git/exec.d.ts +28 -0
- package/dist/core/git/exec.d.ts.map +1 -0
- package/dist/core/git/exec.js +21 -0
- package/dist/core/git/exec.js.map +1 -0
- package/dist/core/git/repo.d.ts +63 -0
- package/dist/core/git/repo.d.ts.map +1 -0
- package/dist/core/git/repo.js +91 -0
- package/dist/core/git/repo.js.map +1 -0
- package/dist/core/git/staged.d.ts +10 -0
- package/dist/core/git/staged.d.ts.map +1 -0
- package/dist/core/git/staged.js +49 -0
- package/dist/core/git/staged.js.map +1 -0
- package/dist/core/git/worktree.d.ts +29 -0
- package/dist/core/git/worktree.d.ts.map +1 -0
- package/dist/core/git/worktree.js +61 -0
- package/dist/core/git/worktree.js.map +1 -0
- package/dist/core/graph/model.d.ts +43 -0
- package/dist/core/graph/model.d.ts.map +1 -0
- package/dist/core/graph/model.js +60 -0
- package/dist/core/graph/model.js.map +1 -0
- package/dist/core/graph/persist.d.ts +7 -0
- package/dist/core/graph/persist.d.ts.map +1 -0
- package/dist/core/graph/persist.js +23 -0
- package/dist/core/graph/persist.js.map +1 -0
- package/dist/core/graph/query.d.ts +16 -0
- package/dist/core/graph/query.d.ts.map +1 -0
- package/dist/core/graph/query.js +91 -0
- package/dist/core/graph/query.js.map +1 -0
- package/dist/core/graph/visibility-filter.d.ts +13 -0
- package/dist/core/graph/visibility-filter.d.ts.map +1 -0
- package/dist/core/graph/visibility-filter.js +26 -0
- package/dist/core/graph/visibility-filter.js.map +1 -0
- package/dist/core/hooks.d.ts +34 -0
- package/dist/core/hooks.d.ts.map +1 -0
- package/dist/core/hooks.js +89 -0
- package/dist/core/hooks.js.map +1 -0
- package/dist/core/identity.d.ts +14 -0
- package/dist/core/identity.d.ts.map +1 -0
- package/dist/core/identity.js +36 -0
- package/dist/core/identity.js.map +1 -0
- package/dist/core/ingest/identity.d.ts +15 -0
- package/dist/core/ingest/identity.d.ts.map +1 -0
- package/dist/core/ingest/identity.js +17 -0
- package/dist/core/ingest/identity.js.map +1 -0
- package/dist/core/ingest/model.d.ts +17 -0
- package/dist/core/ingest/model.d.ts.map +1 -0
- package/dist/core/ingest/model.js +24 -0
- package/dist/core/ingest/model.js.map +1 -0
- package/dist/core/json-config-merge.d.ts +13 -0
- package/dist/core/json-config-merge.d.ts.map +1 -0
- package/dist/core/json-config-merge.js +43 -0
- package/dist/core/json-config-merge.js.map +1 -0
- package/dist/core/markers.d.ts +17 -0
- package/dist/core/markers.d.ts.map +1 -0
- package/dist/core/markers.js +16 -0
- package/dist/core/markers.js.map +1 -0
- package/dist/core/migrations/registry.d.ts +6 -0
- package/dist/core/migrations/registry.d.ts.map +1 -0
- package/dist/core/migrations/registry.js +8 -0
- package/dist/core/migrations/registry.js.map +1 -0
- package/dist/core/migrations/rename-visibility-field.d.ts +3 -0
- package/dist/core/migrations/rename-visibility-field.d.ts.map +1 -0
- package/dist/core/migrations/rename-visibility-field.js +62 -0
- package/dist/core/migrations/rename-visibility-field.js.map +1 -0
- package/dist/core/migrations/types.d.ts +27 -0
- package/dist/core/migrations/types.d.ts.map +1 -0
- package/dist/core/migrations/types.js +2 -0
- package/dist/core/migrations/types.js.map +1 -0
- package/dist/core/notes/checks.d.ts +20 -0
- package/dist/core/notes/checks.d.ts.map +1 -0
- package/dist/core/notes/checks.js +58 -0
- package/dist/core/notes/checks.js.map +1 -0
- package/dist/core/notes/list.d.ts +26 -0
- package/dist/core/notes/list.d.ts.map +1 -0
- package/dist/core/notes/list.js +84 -0
- package/dist/core/notes/list.js.map +1 -0
- package/dist/core/notes/parse.d.ts +12 -0
- package/dist/core/notes/parse.d.ts.map +1 -0
- package/dist/core/notes/parse.js +36 -0
- package/dist/core/notes/parse.js.map +1 -0
- package/dist/core/notes/render.d.ts +7 -0
- package/dist/core/notes/render.d.ts.map +1 -0
- package/dist/core/notes/render.js +13 -0
- package/dist/core/notes/render.js.map +1 -0
- package/dist/core/notes/visibility.d.ts +26 -0
- package/dist/core/notes/visibility.d.ts.map +1 -0
- package/dist/core/notes/visibility.js +41 -0
- package/dist/core/notes/visibility.js.map +1 -0
- package/dist/core/procedures.d.ts +44 -0
- package/dist/core/procedures.d.ts.map +1 -0
- package/dist/core/procedures.js +154 -0
- package/dist/core/procedures.js.map +1 -0
- package/dist/core/queue.d.ts +16 -0
- package/dist/core/queue.d.ts.map +1 -0
- package/dist/core/queue.js +75 -0
- package/dist/core/queue.js.map +1 -0
- package/dist/core/reconcile.d.ts +18 -0
- package/dist/core/reconcile.d.ts.map +1 -0
- package/dist/core/reconcile.js +49 -0
- package/dist/core/reconcile.js.map +1 -0
- package/dist/core/records.d.ts +16 -0
- package/dist/core/records.d.ts.map +1 -0
- package/dist/core/records.js +36 -0
- package/dist/core/records.js.map +1 -0
- package/dist/core/reporter.d.ts +20 -0
- package/dist/core/reporter.d.ts.map +1 -0
- package/dist/core/reporter.js +25 -0
- package/dist/core/reporter.js.map +1 -0
- package/dist/core/root.d.ts +24 -0
- package/dist/core/root.d.ts.map +1 -0
- package/dist/core/root.js +51 -0
- package/dist/core/root.js.map +1 -0
- package/dist/core/security/secrets.d.ts +17 -0
- package/dist/core/security/secrets.d.ts.map +1 -0
- package/dist/core/security/secrets.js +21 -0
- package/dist/core/security/secrets.js.map +1 -0
- package/dist/core/session.d.ts +15 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +27 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/store.d.ts +15 -0
- package/dist/core/store.d.ts.map +1 -0
- package/dist/core/store.js +19 -0
- package/dist/core/store.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/prompt/inquirer-prompter.d.ts +14 -0
- package/dist/prompt/inquirer-prompter.d.ts.map +1 -0
- package/dist/prompt/inquirer-prompter.js +27 -0
- package/dist/prompt/inquirer-prompter.js.map +1 -0
- package/dist/prompt/prompter.d.ts +24 -0
- package/dist/prompt/prompter.d.ts.map +1 -0
- package/dist/prompt/prompter.js +2 -0
- package/dist/prompt/prompter.js.map +1 -0
- package/dist/run.d.ts +16 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +464 -0
- package/dist/run.js.map +1 -0
- package/dist/taxonomy/profiles.d.ts +31 -0
- package/dist/taxonomy/profiles.d.ts.map +1 -0
- package/dist/taxonomy/profiles.js +45 -0
- package/dist/taxonomy/profiles.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/package.json +56 -0
- package/templates/.gitkeep +0 -0
- package/templates/hooks/pre-commit.sh +21 -0
- package/templates/hooks/pre-push.sh +24 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { mkdir, readFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { contentHashOfBody } from '../content/canonicalize.js';
|
|
4
|
+
import { upsertFencedRegionInFile } from '../fs/fenced-region.js';
|
|
5
|
+
import { htmlCommentFence } from '../markers.js';
|
|
6
|
+
import { listNotes } from '../notes/list.js';
|
|
7
|
+
import { catalogSectionsFor, parseCatalogGlosses, renderCatalogEntry, sectionFileName, sectionForNote, } from './model.js';
|
|
8
|
+
export const CATALOG_FENCE = htmlCommentFence('catalog');
|
|
9
|
+
async function readIfExists(filePath) {
|
|
10
|
+
try {
|
|
11
|
+
return await readFile(filePath, 'utf8');
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
if (err.code === 'ENOENT')
|
|
15
|
+
return '';
|
|
16
|
+
throw err;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function groupBySection(notes, sections) {
|
|
20
|
+
const grouped = new Map();
|
|
21
|
+
for (const section of sections)
|
|
22
|
+
grouped.set(section.id, []);
|
|
23
|
+
for (const note of notes) {
|
|
24
|
+
grouped.get(sectionForNote(sections, note.path).id).push(note);
|
|
25
|
+
}
|
|
26
|
+
return grouped;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* context-catalog spec: regenerates each section's fenced identity/path
|
|
30
|
+
* entries, preserving any already-authored gloss. Re-running with no
|
|
31
|
+
* underlying change is byte-identical (upsertFencedRegionInFile only writes
|
|
32
|
+
* when content actually differs).
|
|
33
|
+
*/
|
|
34
|
+
export async function buildCatalog(store) {
|
|
35
|
+
const notes = await listNotes(store.root, store.config);
|
|
36
|
+
const sections = catalogSectionsFor(store.config);
|
|
37
|
+
const catalogDir = path.join(store.root, store.config.catalog.path);
|
|
38
|
+
await mkdir(catalogDir, { recursive: true });
|
|
39
|
+
const notesBySection = groupBySection(notes, sections);
|
|
40
|
+
const results = [];
|
|
41
|
+
for (const section of sections) {
|
|
42
|
+
const sectionNotes = notesBySection.get(section.id) ?? [];
|
|
43
|
+
const filePath = path.join(catalogDir, sectionFileName(section));
|
|
44
|
+
const existingGlosses = parseCatalogGlosses(await readIfExists(filePath));
|
|
45
|
+
const lines = sectionNotes.map((note) => renderCatalogEntry(note, existingGlosses));
|
|
46
|
+
const { changed } = await upsertFencedRegionInFile(filePath, CATALOG_FENCE, lines);
|
|
47
|
+
results.push({ id: section.id, file: path.relative(store.root, filePath), noteCount: sectionNotes.length, changed });
|
|
48
|
+
}
|
|
49
|
+
return { sections: results, totalNotes: notes.length };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* context-catalog spec: coverage is a hard invariant in BOTH directions —
|
|
53
|
+
* every retrievable note must have an entry (missing), and every entry must
|
|
54
|
+
* still reference a real, retrievable note (dangling). A deleted note whose
|
|
55
|
+
* stale entry survives a build is exactly the failure this second half
|
|
56
|
+
* catches — `catalog build` only ever ADDS/preserves entries, so removal
|
|
57
|
+
* must be caught here rather than silently left to rot.
|
|
58
|
+
*/
|
|
59
|
+
export async function checkCatalogCoverage(store) {
|
|
60
|
+
const notes = await listNotes(store.root, store.config);
|
|
61
|
+
const notePaths = new Set(notes.map((n) => n.path));
|
|
62
|
+
const sections = catalogSectionsFor(store.config);
|
|
63
|
+
const catalogDir = path.join(store.root, store.config.catalog.path);
|
|
64
|
+
const cataloged = new Set();
|
|
65
|
+
for (const section of sections) {
|
|
66
|
+
const body = await readIfExists(path.join(catalogDir, sectionFileName(section)));
|
|
67
|
+
for (const notePath of parseCatalogGlosses(body).keys())
|
|
68
|
+
cataloged.add(notePath);
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
missing: notes.map((n) => n.path).filter((p) => !cataloged.has(p)),
|
|
72
|
+
dangling: [...cataloged].filter((p) => !notePaths.has(p)).sort(),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/** context-catalog spec: an entry whose note has changed since its gloss was confirmed needs review. */
|
|
76
|
+
export async function checkCatalogStale(store) {
|
|
77
|
+
const notes = await listNotes(store.root, store.config);
|
|
78
|
+
const notesByPath = new Map(notes.map((n) => [n.path, n]));
|
|
79
|
+
const sections = catalogSectionsFor(store.config);
|
|
80
|
+
const catalogDir = path.join(store.root, store.config.catalog.path);
|
|
81
|
+
const stale = [];
|
|
82
|
+
for (const section of sections) {
|
|
83
|
+
const body = await readIfExists(path.join(catalogDir, sectionFileName(section)));
|
|
84
|
+
for (const [notePath, entry] of parseCatalogGlosses(body)) {
|
|
85
|
+
if (!entry.hash)
|
|
86
|
+
continue; // no confirmed gloss yet — nothing to go stale
|
|
87
|
+
const note = notesByPath.get(notePath);
|
|
88
|
+
if (!note)
|
|
89
|
+
continue; // handled by coverage, not staleness
|
|
90
|
+
if (contentHashOfBody(note.body) !== entry.hash) {
|
|
91
|
+
stale.push({ path: notePath, section: section.id });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return stale;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Returns null ONLY when `sectionId` doesn't name a configured section — a
|
|
99
|
+
* real section that simply hasn't been built yet (or has no notes) returns
|
|
100
|
+
* an empty string, which is a valid, uninteresting result, not an error.
|
|
101
|
+
*/
|
|
102
|
+
export async function readCatalogSection(store, sectionId, asContext) {
|
|
103
|
+
const sections = catalogSectionsFor(store.config);
|
|
104
|
+
const section = sections.find((s) => s.id === sectionId);
|
|
105
|
+
if (!section)
|
|
106
|
+
return null;
|
|
107
|
+
void asContext; // visibility filtering wired in Phase 5
|
|
108
|
+
return readIfExists(path.join(store.root, store.config.catalog.path, sectionFileName(section)));
|
|
109
|
+
}
|
|
110
|
+
export function catalogSectionPath(store, section) {
|
|
111
|
+
return path.join(store.root, store.config.catalog.path, sectionFileName(section));
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/core/catalog/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { StoreConfig } from '../../config/schema.js';
|
|
2
|
+
import type { Note } from '../notes/list.js';
|
|
3
|
+
/**
|
|
4
|
+
* context-catalog spec: one section per configured taxonomy layer, plus a
|
|
5
|
+
* catch-all "uncategorized" (or, for a zero-layer profile like
|
|
6
|
+
* Zettelkasten, a single "notes" section covering everything) — so every
|
|
7
|
+
* retrievable note always has exactly one section to belong to, never zero.
|
|
8
|
+
*/
|
|
9
|
+
export interface CatalogSection {
|
|
10
|
+
id: string;
|
|
11
|
+
/** The taxonomy layer path this section corresponds to, or null for the catch-all. */
|
|
12
|
+
layerPath: string | null;
|
|
13
|
+
}
|
|
14
|
+
export declare function catalogSectionsFor(config: StoreConfig): CatalogSection[];
|
|
15
|
+
export declare function sectionForNote(sections: readonly CatalogSection[], notePath: string): CatalogSection;
|
|
16
|
+
export declare function sectionFileName(section: CatalogSection): string;
|
|
17
|
+
export interface CatalogGlossEntry {
|
|
18
|
+
gloss: string;
|
|
19
|
+
/** The content hash at the moment the gloss was last confirmed non-empty — frozen, like source-hash. */
|
|
20
|
+
hash?: string;
|
|
21
|
+
}
|
|
22
|
+
/** Extracts existing entries' glosses (and confirmed hashes) keyed by note path, so a rebuild can preserve them. */
|
|
23
|
+
export declare function parseCatalogGlosses(body: string): Map<string, CatalogGlossEntry>;
|
|
24
|
+
/**
|
|
25
|
+
* Structure (identity + path) is always freshly generated; the gloss is
|
|
26
|
+
* preserved from `existing` when present, and left empty for a note that
|
|
27
|
+
* has never appeared before — never fabricated (context-catalog spec). The
|
|
28
|
+
* confirmed hash is stamped the first time a gloss becomes non-empty, then
|
|
29
|
+
* frozen — the same "frozen at confirmation, not live" discipline
|
|
30
|
+
* context-ingest applies to source-hash.
|
|
31
|
+
*/
|
|
32
|
+
export declare function renderCatalogEntry(note: Note, existing: ReadonlyMap<string, CatalogGlossEntry>): string;
|
|
33
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/core/catalog/model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,sFAAsF;IACtF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,cAAc,EAAE,CAQxE;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,CAQpG;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAE/D;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,wGAAwG;IACxG,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID,oHAAoH;AACpH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAShF;AAQD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,MAAM,CAMvG"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { contentHashOfBody } from '../content/canonicalize.js';
|
|
3
|
+
export function catalogSectionsFor(config) {
|
|
4
|
+
if (config.taxonomy.layers.length === 0) {
|
|
5
|
+
return [{ id: 'notes', layerPath: null }];
|
|
6
|
+
}
|
|
7
|
+
return [
|
|
8
|
+
...config.taxonomy.layers.map((layer) => ({ id: layer.path.replace(/\/+$/, ''), layerPath: layer.path })),
|
|
9
|
+
{ id: 'uncategorized', layerPath: null },
|
|
10
|
+
];
|
|
11
|
+
}
|
|
12
|
+
export function sectionForNote(sections, notePath) {
|
|
13
|
+
for (const section of sections) {
|
|
14
|
+
if (section.layerPath) {
|
|
15
|
+
const prefix = section.layerPath.endsWith('/') ? section.layerPath : `${section.layerPath}/`;
|
|
16
|
+
if (notePath.startsWith(prefix))
|
|
17
|
+
return section;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return sections[sections.length - 1]; // the catch-all is always last
|
|
21
|
+
}
|
|
22
|
+
export function sectionFileName(section) {
|
|
23
|
+
return `${section.id}.md`;
|
|
24
|
+
}
|
|
25
|
+
const ENTRY_RE = /^- \[\[(.*?)\]\] \(`([^`]+)`\) — (.*?)(?:\s*<!-- hash:([0-9a-f]{16}) -->)?$/;
|
|
26
|
+
/** Extracts existing entries' glosses (and confirmed hashes) keyed by note path, so a rebuild can preserve them. */
|
|
27
|
+
export function parseCatalogGlosses(body) {
|
|
28
|
+
const entries = new Map();
|
|
29
|
+
for (const line of body.split('\n')) {
|
|
30
|
+
const match = ENTRY_RE.exec(line);
|
|
31
|
+
if (match) {
|
|
32
|
+
entries.set(match[2], { gloss: match[3] ?? '', hash: match[4] });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return entries;
|
|
36
|
+
}
|
|
37
|
+
function titleFor(note) {
|
|
38
|
+
const fmTitle = note.frontmatter?.title;
|
|
39
|
+
if (typeof fmTitle === 'string' && fmTitle.length > 0)
|
|
40
|
+
return fmTitle;
|
|
41
|
+
return path.basename(note.path, '.md');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Structure (identity + path) is always freshly generated; the gloss is
|
|
45
|
+
* preserved from `existing` when present, and left empty for a note that
|
|
46
|
+
* has never appeared before — never fabricated (context-catalog spec). The
|
|
47
|
+
* confirmed hash is stamped the first time a gloss becomes non-empty, then
|
|
48
|
+
* frozen — the same "frozen at confirmation, not live" discipline
|
|
49
|
+
* context-ingest applies to source-hash.
|
|
50
|
+
*/
|
|
51
|
+
export function renderCatalogEntry(note, existing) {
|
|
52
|
+
const prior = existing.get(note.path);
|
|
53
|
+
const gloss = prior?.gloss ?? '';
|
|
54
|
+
const hash = gloss.length > 0 ? (prior?.hash ?? contentHashOfBody(note.body)) : undefined;
|
|
55
|
+
const hashSuffix = hash ? ` <!-- hash:${hash} -->` : '';
|
|
56
|
+
return `- [[${titleFor(note)}]] (\`${note.path}\`) — ${gloss}${hashSuffix}`;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/core/catalog/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const catalogCoverageCheck: import("./types.js").CheckDefinition;
|
|
2
|
+
export declare const catalogSectionSizeCheck: import("./types.js").CheckDefinition;
|
|
3
|
+
export declare const CATALOG_CHECKS: import("./types.js").CheckDefinition[];
|
|
4
|
+
//# sourceMappingURL=catalog-checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-checks.d.ts","sourceRoot":"","sources":["../../../src/core/checks/catalog-checks.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,oBAAoB,sCAyB/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,sCA8BlC,CAAC;AAEH,eAAO,MAAM,cAAc,wCAAkD,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { catalogSectionPath, checkCatalogCoverage } from '../catalog/build.js';
|
|
4
|
+
import { catalogSectionsFor } from '../catalog/model.js';
|
|
5
|
+
import { defineCheck } from './types.js';
|
|
6
|
+
export const catalogCoverageCheck = defineCheck({
|
|
7
|
+
id: 'catalog.coverage',
|
|
8
|
+
title: 'Every retrievable note has a catalog entry',
|
|
9
|
+
severity: 'invariant',
|
|
10
|
+
capability: 'context-catalog',
|
|
11
|
+
scopes: ['store'],
|
|
12
|
+
async run(ctx) {
|
|
13
|
+
const store = { root: ctx.storeRoot, config: ctx.config };
|
|
14
|
+
const { missing, dangling } = await checkCatalogCoverage(store);
|
|
15
|
+
const findings = [
|
|
16
|
+
...missing.map((notePath) => ({
|
|
17
|
+
code: 'catalog.coverage.missing',
|
|
18
|
+
severity: 'error',
|
|
19
|
+
message: `"${notePath}" is retrievable but has no catalog entry.`,
|
|
20
|
+
subject: notePath,
|
|
21
|
+
})),
|
|
22
|
+
...dangling.map((notePath) => ({
|
|
23
|
+
code: 'catalog.coverage.dangling',
|
|
24
|
+
severity: 'error',
|
|
25
|
+
message: `A catalog entry references "${notePath}", which no longer exists.`,
|
|
26
|
+
subject: notePath,
|
|
27
|
+
})),
|
|
28
|
+
];
|
|
29
|
+
return { status: findings.length > 0 ? 'fail' : 'pass', findings };
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
export const catalogSectionSizeCheck = defineCheck({
|
|
33
|
+
id: 'catalog.section_size',
|
|
34
|
+
title: 'No catalog section exceeds its configured size budget',
|
|
35
|
+
severity: 'invariant',
|
|
36
|
+
capability: 'context-catalog',
|
|
37
|
+
scopes: ['store'],
|
|
38
|
+
async run(ctx) {
|
|
39
|
+
const store = { root: ctx.storeRoot, config: ctx.config };
|
|
40
|
+
const sections = catalogSectionsFor(ctx.config);
|
|
41
|
+
const findings = [];
|
|
42
|
+
for (const section of sections) {
|
|
43
|
+
const filePath = catalogSectionPath(store, section);
|
|
44
|
+
let size = 0;
|
|
45
|
+
try {
|
|
46
|
+
size = (await stat(filePath)).size;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
continue; // section file doesn't exist yet — nothing to measure
|
|
50
|
+
}
|
|
51
|
+
if (size > ctx.config.catalog.section_max_bytes) {
|
|
52
|
+
findings.push({
|
|
53
|
+
code: 'catalog.section_size.exceeded',
|
|
54
|
+
severity: 'error',
|
|
55
|
+
message: `Catalog section "${section.id}" (${path.relative(store.root, filePath)}) is ${size} bytes, exceeding the configured budget of ${ctx.config.catalog.section_max_bytes}. Split it.`,
|
|
56
|
+
subject: section.id,
|
|
57
|
+
details: { size, budget: ctx.config.catalog.section_max_bytes },
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return { status: findings.length > 0 ? 'fail' : 'pass', findings };
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
export const CATALOG_CHECKS = [catalogCoverageCheck, catalogSectionSizeCheck];
|
|
65
|
+
//# sourceMappingURL=catalog-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-checks.js","sourceRoot":"","sources":["../../../src/core/checks/catalog-checks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agent-identity spec: "Identity files... SHALL live under a path declared
|
|
3
|
+
* in the store's retrieval exclusion configuration." Catalog and graph
|
|
4
|
+
* already can't surface anything under an excluded prefix (they're both
|
|
5
|
+
* built from listNotes()) — this check guards the one way that guarantee
|
|
6
|
+
* could quietly break: an operator editing config.retrieval.exclude_paths
|
|
7
|
+
* and dropping the identity path from it.
|
|
8
|
+
*/
|
|
9
|
+
export declare const identityExclusionCheck: import("./types.js").CheckDefinition;
|
|
10
|
+
export declare const IDENTITY_CHECKS: import("./types.js").CheckDefinition[];
|
|
11
|
+
//# sourceMappingURL=identity-checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-checks.d.ts","sourceRoot":"","sources":["../../../src/core/checks/identity-checks.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,sCA2BjC,CAAC;AAEH,eAAO,MAAM,eAAe,wCAA2B,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { defineCheck } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* agent-identity spec: "Identity files... SHALL live under a path declared
|
|
4
|
+
* in the store's retrieval exclusion configuration." Catalog and graph
|
|
5
|
+
* already can't surface anything under an excluded prefix (they're both
|
|
6
|
+
* built from listNotes()) — this check guards the one way that guarantee
|
|
7
|
+
* could quietly break: an operator editing config.retrieval.exclude_paths
|
|
8
|
+
* and dropping the identity path from it.
|
|
9
|
+
*/
|
|
10
|
+
export const identityExclusionCheck = defineCheck({
|
|
11
|
+
id: 'identity.excluded_from_retrieval',
|
|
12
|
+
title: 'The identity path is excluded from retrieval',
|
|
13
|
+
severity: 'invariant',
|
|
14
|
+
capability: 'agent-identity',
|
|
15
|
+
scopes: ['store'],
|
|
16
|
+
async run(ctx) {
|
|
17
|
+
const identityPath = ctx.config.identity.path.replace(/\/+$/, '');
|
|
18
|
+
const covered = ctx.config.retrieval.exclude_paths.some((prefix) => {
|
|
19
|
+
const trimmed = prefix.replace(/\/+$/, '');
|
|
20
|
+
return identityPath === trimmed || identityPath.startsWith(`${trimmed}/`);
|
|
21
|
+
});
|
|
22
|
+
if (covered) {
|
|
23
|
+
return { status: 'pass', findings: [] };
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
status: 'fail',
|
|
27
|
+
findings: [
|
|
28
|
+
{
|
|
29
|
+
code: 'identity.not_excluded',
|
|
30
|
+
severity: 'error',
|
|
31
|
+
message: `The identity path "${ctx.config.identity.path}" is not covered by retrieval.exclude_paths — identity content could leak into the catalog or graph.`,
|
|
32
|
+
subject: ctx.config.identity.path,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
export const IDENTITY_CHECKS = [identityExclusionCheck];
|
|
39
|
+
//# sourceMappingURL=identity-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-checks.js","sourceRoot":"","sources":["../../../src/core/checks/identity-checks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,WAAW,CAAC;IAChD,EAAE,EAAE,kCAAkC;IACtC,KAAK,EAAE,8CAA8C;IACrD,QAAQ,EAAE,WAAW;IACrB,UAAU,EAAE,gBAAgB;IAC5B,MAAM,EAAE,CAAC,OAAO,CAAC;IACjB,KAAK,CAAC,GAAG,CAAC,GAAG;QACX,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACjE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC3C,OAAO,YAAY,KAAK,OAAO,IAAI,YAAY,CAAC,UAAU,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;QACH,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QAC1C,CAAC;QACD,OAAO;YACL,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,uBAAuB;oBAC7B,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,sBAAsB,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,sGAAsG;oBAC7J,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI;iBAClC;aACF;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* store-integrity spec (task 9.3): "derived-artifact staleness." Covers
|
|
3
|
+
* both derived legs in one check — the catalog's confirmed-gloss hash
|
|
4
|
+
* (Phase 3) and the persisted graph compared against a fresh rebuild from
|
|
5
|
+
* the store's current notes. Neither sub-condition being "not built yet"
|
|
6
|
+
* is treated as a failure — there's nothing stale about an artifact that
|
|
7
|
+
* has simply never been built.
|
|
8
|
+
*/
|
|
9
|
+
export declare const derivedArtifactStalenessCheck: import("./types.js").CheckDefinition;
|
|
10
|
+
/**
|
|
11
|
+
* store-integrity spec: "dangling links... (per context-retrieval)." A
|
|
12
|
+
* genuine identity collision is NOT re-checked here — buildGraphFromNotes
|
|
13
|
+
* refuses to persist a graph that has one (core/graph/model.ts), so a
|
|
14
|
+
* persisted graph.json is proof by construction that none exists; there is
|
|
15
|
+
* nothing for a doctor check to find after the fact.
|
|
16
|
+
*/
|
|
17
|
+
export declare const graphDanglingLinksCheck: import("./types.js").CheckDefinition;
|
|
18
|
+
/** store-integrity spec: "schema version currency (per store-lifecycle)." */
|
|
19
|
+
export declare const schemaVersionCurrencyCheck: import("./types.js").CheckDefinition;
|
|
20
|
+
/** store-integrity spec: "adapter compatibility (per adapters)." */
|
|
21
|
+
export declare const adapterCompatibilityCheck: import("./types.js").CheckDefinition;
|
|
22
|
+
export declare const INTEGRITY_CHECKS: import("./types.js").CheckDefinition[];
|
|
23
|
+
//# sourceMappingURL=integrity-checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrity-checks.d.ts","sourceRoot":"","sources":["../../../src/core/checks/integrity-checks.ts"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,sCAkCxC,CAAC;AAEH;;;;;;GAMG;AAGH,eAAO,MAAM,uBAAuB,sCAoBlC,CAAC;AAEH,6EAA6E;AAC7E,eAAO,MAAM,0BAA0B,sCAsBrC,CAAC;AAEH,oEAAoE;AACpE,eAAO,MAAM,yBAAyB,sCAuBpC,CAAC;AAEH,eAAO,MAAM,gBAAgB,wCAK5B,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { resolveAdapter } from '../../adapters/registry.js';
|
|
2
|
+
import { SUPPORTED_SCHEMA_VERSION } from '../../config/schema.js';
|
|
3
|
+
import { checkCatalogStale } from '../catalog/build.js';
|
|
4
|
+
import { buildGraphFromNotes } from '../graph/model.js';
|
|
5
|
+
import { defineCheck } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* store-integrity spec (task 9.3): "derived-artifact staleness." Covers
|
|
8
|
+
* both derived legs in one check — the catalog's confirmed-gloss hash
|
|
9
|
+
* (Phase 3) and the persisted graph compared against a fresh rebuild from
|
|
10
|
+
* the store's current notes. Neither sub-condition being "not built yet"
|
|
11
|
+
* is treated as a failure — there's nothing stale about an artifact that
|
|
12
|
+
* has simply never been built.
|
|
13
|
+
*/
|
|
14
|
+
export const derivedArtifactStalenessCheck = defineCheck({
|
|
15
|
+
id: 'derived_artifacts.stale',
|
|
16
|
+
title: 'Derived artifacts (catalog, graph) match the store\'s current notes',
|
|
17
|
+
severity: 'invariant',
|
|
18
|
+
capability: 'store-integrity',
|
|
19
|
+
scopes: ['store'],
|
|
20
|
+
async run(ctx) {
|
|
21
|
+
const findings = [];
|
|
22
|
+
const store = { root: ctx.storeRoot, config: ctx.config };
|
|
23
|
+
const staleCatalogEntries = await checkCatalogStale(store);
|
|
24
|
+
for (const entry of staleCatalogEntries) {
|
|
25
|
+
findings.push({
|
|
26
|
+
code: 'derived_artifacts.catalog_stale',
|
|
27
|
+
severity: 'error',
|
|
28
|
+
message: `"${entry.path}" in catalog section "${entry.section}" has changed since its gloss was last confirmed.`,
|
|
29
|
+
subject: entry.path,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
const persistedGraph = await ctx.graph();
|
|
33
|
+
if (persistedGraph) {
|
|
34
|
+
const freshGraph = buildGraphFromNotes(await ctx.notes());
|
|
35
|
+
if (JSON.stringify(persistedGraph) !== JSON.stringify(freshGraph)) {
|
|
36
|
+
findings.push({
|
|
37
|
+
code: 'derived_artifacts.graph_stale',
|
|
38
|
+
severity: 'error',
|
|
39
|
+
message: 'The persisted graph does not match what a rebuild would produce from the store\'s current notes. Run `ctxr graph build`.',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { status: findings.length > 0 ? 'fail' : 'pass', findings };
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* store-integrity spec: "dangling links... (per context-retrieval)." A
|
|
48
|
+
* genuine identity collision is NOT re-checked here — buildGraphFromNotes
|
|
49
|
+
* refuses to persist a graph that has one (core/graph/model.ts), so a
|
|
50
|
+
* persisted graph.json is proof by construction that none exists; there is
|
|
51
|
+
* nothing for a doctor check to find after the fact.
|
|
52
|
+
*/
|
|
53
|
+
// Shares detection with organize-checks.ts:brokenLinksCheck (lint, observation) under a
|
|
54
|
+
// different id (task 9.4: two ids, two severity lanes, one condition, never double-counted).
|
|
55
|
+
export const graphDanglingLinksCheck = defineCheck({
|
|
56
|
+
id: 'graph.dangling_links',
|
|
57
|
+
title: 'The graph has no dangling links',
|
|
58
|
+
severity: 'invariant',
|
|
59
|
+
capability: 'context-retrieval',
|
|
60
|
+
scopes: ['store'],
|
|
61
|
+
async run(ctx) {
|
|
62
|
+
const graph = await ctx.graph();
|
|
63
|
+
if (!graph) {
|
|
64
|
+
return { status: 'skip', skipReason: 'graph has not been built yet — run `ctxr graph build`', findings: [] };
|
|
65
|
+
}
|
|
66
|
+
const findings = graph.dangling.map((d) => ({
|
|
67
|
+
code: 'graph.dangling_link',
|
|
68
|
+
severity: 'error',
|
|
69
|
+
message: `"${d.from}" links to "${d.target}", which is ${d.reason === 'ambiguous' ? 'ambiguous' : 'not found'}.`,
|
|
70
|
+
subject: d.from,
|
|
71
|
+
details: { target: d.target, reason: d.reason },
|
|
72
|
+
}));
|
|
73
|
+
return { status: findings.length > 0 ? 'fail' : 'pass', findings };
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
/** store-integrity spec: "schema version currency (per store-lifecycle)." */
|
|
77
|
+
export const schemaVersionCurrencyCheck = defineCheck({
|
|
78
|
+
id: 'store.schema_version_currency',
|
|
79
|
+
title: 'The store is at the current schema version',
|
|
80
|
+
severity: 'invariant',
|
|
81
|
+
capability: 'store-lifecycle',
|
|
82
|
+
scopes: ['store'],
|
|
83
|
+
async run(ctx) {
|
|
84
|
+
if (ctx.config.schema_version >= SUPPORTED_SCHEMA_VERSION) {
|
|
85
|
+
return { status: 'pass', findings: [] };
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
status: 'fail',
|
|
89
|
+
findings: [
|
|
90
|
+
{
|
|
91
|
+
code: 'store.schema_version_behind',
|
|
92
|
+
severity: 'error',
|
|
93
|
+
message: `The store is at schema_version ${ctx.config.schema_version}, behind the supported version ${SUPPORTED_SCHEMA_VERSION}. Run \`ctxr migrate\`.`,
|
|
94
|
+
details: { current: ctx.config.schema_version, supported: SUPPORTED_SCHEMA_VERSION },
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
/** store-integrity spec: "adapter compatibility (per adapters)." */
|
|
101
|
+
export const adapterCompatibilityCheck = defineCheck({
|
|
102
|
+
id: 'adapters.compatibility',
|
|
103
|
+
title: 'Every configured adapter resolves and matches its supported interface version',
|
|
104
|
+
severity: 'invariant',
|
|
105
|
+
capability: 'adapters',
|
|
106
|
+
scopes: ['store'],
|
|
107
|
+
async run(ctx) {
|
|
108
|
+
const findings = [];
|
|
109
|
+
for (const declaration of ctx.config.adapters) {
|
|
110
|
+
try {
|
|
111
|
+
resolveAdapter(declaration);
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
findings.push({
|
|
115
|
+
code: 'adapters.incompatible',
|
|
116
|
+
severity: 'error',
|
|
117
|
+
message: err instanceof Error ? err.message : String(err),
|
|
118
|
+
subject: declaration.id,
|
|
119
|
+
details: { kind: declaration.kind },
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return { status: findings.length > 0 ? 'fail' : 'pass', findings };
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
export const INTEGRITY_CHECKS = [
|
|
127
|
+
derivedArtifactStalenessCheck,
|
|
128
|
+
graphDanglingLinksCheck,
|
|
129
|
+
schemaVersionCurrencyCheck,
|
|
130
|
+
adapterCompatibilityCheck,
|
|
131
|
+
];
|
|
132
|
+
//# sourceMappingURL=integrity-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrity-checks.js","sourceRoot":"","sources":["../../../src/core/checks/integrity-checks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,WAAW,CAAC;IACvD,EAAE,EAAE,yBAAyB;IAC7B,KAAK,EAAE,qEAAqE;IAC5E,QAAQ,EAAE,WAAW;IACrB,UAAU,EAAE,iBAAiB;IAC7B,MAAM,EAAE,CAAC,OAAO,CAAC;IACjB,KAAK,CAAC,GAAG,CAAC,GAAG;QACX,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;QAC1D,MAAM,mBAAmB,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAC3D,KAAK,MAAM,KAAK,IAAI,mBAAmB,EAAE,CAAC;YACxC,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,iCAAiC;gBACvC,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,IAAI,KAAK,CAAC,IAAI,yBAAyB,KAAK,CAAC,OAAO,mDAAmD;gBAChH,OAAO,EAAE,KAAK,CAAC,IAAI;aACpB,CAAC,CAAC;QACL,CAAC;QAED,MAAM,cAAc,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QACzC,IAAI,cAAc,EAAE,CAAC;YACnB,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;YAC1D,IAAI,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;gBAClE,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,+BAA+B;oBACrC,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,0HAA0H;iBACpI,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;IACrE,CAAC;CACF,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,wFAAwF;AACxF,6FAA6F;AAC7F,MAAM,CAAC,MAAM,uBAAuB,GAAG,WAAW,CAAC;IACjD,EAAE,EAAE,sBAAsB;IAC1B,KAAK,EAAE,iCAAiC;IACxC,QAAQ,EAAE,WAAW;IACrB,UAAU,EAAE,mBAAmB;IAC/B,MAAM,EAAE,CAAC,OAAO,CAAC;IACjB,KAAK,CAAC,GAAG,CAAC,GAAG;QACX,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,uDAAuD,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QAC/G,CAAC;QACD,MAAM,QAAQ,GAAc,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACrD,IAAI,EAAE,qBAAqB;YAC3B,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,MAAM,eAAe,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,GAAG;YAChH,OAAO,EAAE,CAAC,CAAC,IAAI;YACf,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;SAChD,CAAC,CAAC,CAAC;QACJ,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;IACrE,CAAC;CACF,CAAC,CAAC;AAEH,6EAA6E;AAC7E,MAAM,CAAC,MAAM,0BAA0B,GAAG,WAAW,CAAC;IACpD,EAAE,EAAE,+BAA+B;IACnC,KAAK,EAAE,4CAA4C;IACnD,QAAQ,EAAE,WAAW;IACrB,UAAU,EAAE,iBAAiB;IAC7B,MAAM,EAAE,CAAC,OAAO,CAAC;IACjB,KAAK,CAAC,GAAG,CAAC,GAAG;QACX,IAAI,GAAG,CAAC,MAAM,CAAC,cAAc,IAAI,wBAAwB,EAAE,CAAC;YAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QAC1C,CAAC;QACD,OAAO;YACL,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,6BAA6B;oBACnC,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,kCAAkC,GAAG,CAAC,MAAM,CAAC,cAAc,kCAAkC,wBAAwB,yBAAyB;oBACvJ,OAAO,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,SAAS,EAAE,wBAAwB,EAAE;iBACrF;aACF;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,oEAAoE;AACpE,MAAM,CAAC,MAAM,yBAAyB,GAAG,WAAW,CAAC;IACnD,EAAE,EAAE,wBAAwB;IAC5B,KAAK,EAAE,+EAA+E;IACtF,QAAQ,EAAE,WAAW;IACrB,UAAU,EAAE,UAAU;IACtB,MAAM,EAAE,CAAC,OAAO,CAAC;IACjB,KAAK,CAAC,GAAG,CAAC,GAAG;QACX,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,KAAK,MAAM,WAAW,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC9C,IAAI,CAAC;gBACH,cAAc,CAAC,WAAW,CAAC,CAAC;YAC9B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,uBAAuB;oBAC7B,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;oBACzD,OAAO,EAAE,WAAW,CAAC,EAAE;oBACvB,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE;iBACpC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;IACrE,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,6BAA6B;IAC7B,uBAAuB;IACvB,0BAA0B;IAC1B,yBAAyB;CAC1B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CheckDefinition } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The only file later phases append to when they add a doctor/lint check:
|
|
4
|
+
* one import, one array entry. Nothing else under checks/ changes.
|
|
5
|
+
*/
|
|
6
|
+
export declare const CHECKS: readonly CheckDefinition[];
|
|
7
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/core/checks/manifest.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,SAAS,eAAe,EAQ5C,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CATALOG_CHECKS } from './catalog-checks.js';
|
|
2
|
+
import { IDENTITY_CHECKS } from './identity-checks.js';
|
|
3
|
+
import { INTEGRITY_CHECKS } from './integrity-checks.js';
|
|
4
|
+
import { failClosedVisibilityCheck, failClosedVisibilityInvariantCheck } from '../notes/checks.js';
|
|
5
|
+
import { ORGANIZE_CHECKS } from './organize-checks.js';
|
|
6
|
+
import { WRITE_LIFECYCLE_CHECKS } from './write-lifecycle-checks.js';
|
|
7
|
+
/**
|
|
8
|
+
* The only file later phases append to when they add a doctor/lint check:
|
|
9
|
+
* one import, one array entry. Nothing else under checks/ changes.
|
|
10
|
+
*/
|
|
11
|
+
export const CHECKS = [
|
|
12
|
+
failClosedVisibilityCheck,
|
|
13
|
+
failClosedVisibilityInvariantCheck,
|
|
14
|
+
...WRITE_LIFECYCLE_CHECKS,
|
|
15
|
+
...CATALOG_CHECKS,
|
|
16
|
+
...ORGANIZE_CHECKS,
|
|
17
|
+
...IDENTITY_CHECKS,
|
|
18
|
+
...INTEGRITY_CHECKS,
|
|
19
|
+
];
|
|
20
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/core/checks/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,kCAAkC,EAAE,MAAM,oBAAoB,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAGrE;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAA+B;IAChD,yBAAyB;IACzB,kCAAkC;IAClC,GAAG,sBAAsB;IACzB,GAAG,cAAc;IACjB,GAAG,eAAe;IAClB,GAAG,eAAe;IAClB,GAAG,gBAAgB;CACpB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** context-organize spec: "orphaned notes" — reported by lint, never failed by doctor. */
|
|
2
|
+
export declare const orphanNotesCheck: import("./types.js").CheckDefinition;
|
|
3
|
+
/** context-organize spec: "broken links" — the graph's dangling links (not_found or ambiguous), reported not failed. Shares detection with the doctor-facing invariant checks/integrity-checks.ts:graphDanglingLinksCheck under a different id (task 9.4: two ids, two severity lanes, one condition, never double-counted within a single run). */
|
|
4
|
+
export declare const brokenLinksCheck: import("./types.js").CheckDefinition;
|
|
5
|
+
/** context-ingest / context-organize: material captured but never stamped with source identity. */
|
|
6
|
+
export declare const uningestedInboxCheck: import("./types.js").CheckDefinition;
|
|
7
|
+
/**
|
|
8
|
+
* context-organize spec: "notes with no catalog entry as covered by
|
|
9
|
+
* context-catalog" — the same underlying condition as `catalogCoverageCheck`
|
|
10
|
+
* (doctor, invariant), surfaced here too as its own observation-severity
|
|
11
|
+
* check id so lint can report it without doctor's invariant double-counting
|
|
12
|
+
* lint's finding or vice versa (same pattern as the fail-closed-visibility
|
|
13
|
+
* pair in Phase 5). Only `missing` is in scope here — `dangling` catalog
|
|
14
|
+
* entries are a stricter integrity concern doctor alone owns.
|
|
15
|
+
*/
|
|
16
|
+
export declare const catalogGapsLintCheck: import("./types.js").CheckDefinition;
|
|
17
|
+
export declare const ORGANIZE_CHECKS: import("./types.js").CheckDefinition[];
|
|
18
|
+
//# sourceMappingURL=organize-checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organize-checks.d.ts","sourceRoot":"","sources":["../../../src/core/checks/organize-checks.ts"],"names":[],"mappings":"AAQA,0FAA0F;AAC1F,eAAO,MAAM,gBAAgB,sCAiB3B,CAAC;AAEH,oVAAoV;AACpV,eAAO,MAAM,gBAAgB,sCAkB3B,CAAC;AAEH,mGAAmG;AACnG,eAAO,MAAM,oBAAoB,sCAqB/B,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,sCAgB/B,CAAC;AAEH,eAAO,MAAM,eAAe,wCAAmF,CAAC"}
|