mrplex 0.0.1
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 +21 -0
- package/README.md +284 -0
- package/dist/cli/config.d.ts +28 -0
- package/dist/cli/config.js +48 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/exit-codes.d.ts +13 -0
- package/dist/cli/exit-codes.js +39 -0
- package/dist/cli/exit-codes.js.map +1 -0
- package/dist/cli/format.d.ts +22 -0
- package/dist/cli/format.js +148 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/main.d.ts +16 -0
- package/dist/cli/main.js +1518 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/client/kernel-client.d.ts +97 -0
- package/dist/client/kernel-client.js +14 -0
- package/dist/client/kernel-client.js.map +1 -0
- package/dist/client/local.d.ts +26 -0
- package/dist/client/local.js +103 -0
- package/dist/client/local.js.map +1 -0
- package/dist/client/remote-mcp.d.ts +35 -0
- package/dist/client/remote-mcp.js +174 -0
- package/dist/client/remote-mcp.js.map +1 -0
- package/dist/embed/backfill.d.ts +24 -0
- package/dist/embed/backfill.js +33 -0
- package/dist/embed/backfill.js.map +1 -0
- package/dist/embed/chunker.d.ts +31 -0
- package/dist/embed/chunker.js +121 -0
- package/dist/embed/chunker.js.map +1 -0
- package/dist/embed/cmd-hook.d.ts +21 -0
- package/dist/embed/cmd-hook.js +100 -0
- package/dist/embed/cmd-hook.js.map +1 -0
- package/dist/embed/config.d.ts +61 -0
- package/dist/embed/config.js +109 -0
- package/dist/embed/config.js.map +1 -0
- package/dist/embed/hook.d.ts +38 -0
- package/dist/embed/hook.js +56 -0
- package/dist/embed/hook.js.map +1 -0
- package/dist/embed/http-hook.d.ts +13 -0
- package/dist/embed/http-hook.js +39 -0
- package/dist/embed/http-hook.js.map +1 -0
- package/dist/embed/worker.d.ts +62 -0
- package/dist/embed/worker.js +228 -0
- package/dist/embed/worker.js.map +1 -0
- package/dist/fixtures/hwe/characters/albion-ever.md +12 -0
- package/dist/fixtures/hwe/characters/cent.md +11 -0
- package/dist/fixtures/hwe/concepts/cent-demiurge-resonance.md +10 -0
- package/dist/fixtures/hwe/concepts/phase-looper.md +10 -0
- package/dist/fixtures/hwe/entities/demiurge.md +11 -0
- package/dist/fixtures/hwe/entities/monad.md +11 -0
- package/dist/fixtures/hwe/moc/globocorp-network.md +19 -0
- package/dist/fixtures/hwe/organizations/globocorp.md +11 -0
- package/dist/fixtures/hwe/readme.md +24 -0
- package/dist/fixtures/starship/crew/aria-okonkwo.md +14 -0
- package/dist/fixtures/starship/crew/bexley-orr.md +14 -0
- package/dist/fixtures/starship/crew/dax-thorne.md +14 -0
- package/dist/fixtures/starship/crew/isolde-marsh.md +16 -0
- package/dist/fixtures/starship/crew/kestrel-vance.md +15 -0
- package/dist/fixtures/starship/crew/quill-vasquez.md +14 -0
- package/dist/fixtures/starship/crew/soren-halloway.md +16 -0
- package/dist/fixtures/starship/encounters/the-drift-choir.md +14 -0
- package/dist/fixtures/starship/encounters/the-hollow-signal.md +16 -0
- package/dist/fixtures/starship/encounters/the-wandering-buoy.md +14 -0
- package/dist/fixtures/starship/equipment/coolant-loop-b.md +13 -0
- package/dist/fixtures/starship/equipment/emergency-ration-bars.md +12 -0
- package/dist/fixtures/starship/equipment/long-range-sensors.md +13 -0
- package/dist/fixtures/starship/equipment/plasma-manifold-3.md +15 -0
- package/dist/fixtures/starship/equipment/shuttle-corvid.md +13 -0
- package/dist/fixtures/starship/logs/marsh-4419-1.md +13 -0
- package/dist/fixtures/starship/logs/okonkwo-4415-1.md +13 -0
- package/dist/fixtures/starship/logs/orr-4413-1.md +13 -0
- package/dist/fixtures/starship/logs/orr-4420-1.md +12 -0
- package/dist/fixtures/starship/logs/thorne-4413-2.md +13 -0
- package/dist/fixtures/starship/logs/vance-4419-2.md +13 -0
- package/dist/fixtures/starship/misc/the-galley-ficus.md +11 -0
- package/dist/fixtures/starship/missions/the-cinder-run.md +17 -0
- package/dist/fixtures/starship/missions/the-drift-choir.md +17 -0
- package/dist/fixtures/starship/missions/the-hollow-signal.md +17 -0
- package/dist/fixtures/starship/missions/the-silent-beacon.md +17 -0
- package/dist/fixtures/starship/moc/crew.md +19 -0
- package/dist/fixtures/starship/moc/encounters.md +14 -0
- package/dist/fixtures/starship/moc/missions.md +15 -0
- package/dist/fixtures/starship/readme.md +60 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/auth/glob.d.ts +46 -0
- package/dist/kernel/auth/glob.js +112 -0
- package/dist/kernel/auth/glob.js.map +1 -0
- package/dist/kernel/auth/scope.d.ts +53 -0
- package/dist/kernel/auth/scope.js +83 -0
- package/dist/kernel/auth/scope.js.map +1 -0
- package/dist/kernel/casefold.d.ts +37 -0
- package/dist/kernel/casefold.js +44 -0
- package/dist/kernel/casefold.js.map +1 -0
- package/dist/kernel/constants.d.ts +21 -0
- package/dist/kernel/constants.js +22 -0
- package/dist/kernel/constants.js.map +1 -0
- package/dist/kernel/context.d.ts +70 -0
- package/dist/kernel/context.js +114 -0
- package/dist/kernel/context.js.map +1 -0
- package/dist/kernel/deletion.d.ts +50 -0
- package/dist/kernel/deletion.js +83 -0
- package/dist/kernel/deletion.js.map +1 -0
- package/dist/kernel/diff.d.ts +36 -0
- package/dist/kernel/diff.js +61 -0
- package/dist/kernel/diff.js.map +1 -0
- package/dist/kernel/errors.d.ts +37 -0
- package/dist/kernel/errors.js +55 -0
- package/dist/kernel/errors.js.map +1 -0
- package/dist/kernel/frontmatter-input.d.ts +32 -0
- package/dist/kernel/frontmatter-input.js +85 -0
- package/dist/kernel/frontmatter-input.js.map +1 -0
- package/dist/kernel/graph.d.ts +34 -0
- package/dist/kernel/graph.js +559 -0
- package/dist/kernel/graph.js.map +1 -0
- package/dist/kernel/history.d.ts +74 -0
- package/dist/kernel/history.js +143 -0
- package/dist/kernel/history.js.map +1 -0
- package/dist/kernel/kernel.d.ts +162 -0
- package/dist/kernel/kernel.js +675 -0
- package/dist/kernel/kernel.js.map +1 -0
- package/dist/kernel/path-config.d.ts +101 -0
- package/dist/kernel/path-config.js +171 -0
- package/dist/kernel/path-config.js.map +1 -0
- package/dist/kernel/query/ast.d.ts +24 -0
- package/dist/kernel/query/ast.js +52 -0
- package/dist/kernel/query/ast.js.map +1 -0
- package/dist/kernel/query/cel-parse.d.ts +37 -0
- package/dist/kernel/query/cel-parse.js +88 -0
- package/dist/kernel/query/cel-parse.js.map +1 -0
- package/dist/kernel/query/degrees.d.ts +31 -0
- package/dist/kernel/query/degrees.js +135 -0
- package/dist/kernel/query/degrees.js.map +1 -0
- package/dist/kernel/query/graph-ast.d.ts +51 -0
- package/dist/kernel/query/graph-ast.js +139 -0
- package/dist/kernel/query/graph-ast.js.map +1 -0
- package/dist/kernel/query/query.d.ts +56 -0
- package/dist/kernel/query/query.js +276 -0
- package/dist/kernel/query/query.js.map +1 -0
- package/dist/kernel/validation.d.ts +64 -0
- package/dist/kernel/validation.js +183 -0
- package/dist/kernel/validation.js.map +1 -0
- package/dist/kernel/version-id.d.ts +10 -0
- package/dist/kernel/version-id.js +21 -0
- package/dist/kernel/version-id.js.map +1 -0
- package/dist/kernel/wire.d.ts +148 -0
- package/dist/kernel/wire.js +6 -0
- package/dist/kernel/wire.js.map +1 -0
- package/dist/links/backfill.d.ts +28 -0
- package/dist/links/backfill.js +33 -0
- package/dist/links/backfill.js.map +1 -0
- package/dist/links/extract.d.ts +29 -0
- package/dist/links/extract.js +233 -0
- package/dist/links/extract.js.map +1 -0
- package/dist/links/link-config.d.ts +70 -0
- package/dist/links/link-config.js +107 -0
- package/dist/links/link-config.js.map +1 -0
- package/dist/links/maintain.d.ts +37 -0
- package/dist/links/maintain.js +91 -0
- package/dist/links/maintain.js.map +1 -0
- package/dist/links/repair.d.ts +46 -0
- package/dist/links/repair.js +96 -0
- package/dist/links/repair.js.map +1 -0
- package/dist/links/resolve.d.ts +41 -0
- package/dist/links/resolve.js +121 -0
- package/dist/links/resolve.js.map +1 -0
- package/dist/links/stale.d.ts +32 -0
- package/dist/links/stale.js +73 -0
- package/dist/links/stale.js.map +1 -0
- package/dist/markdown/content-hash.d.ts +34 -0
- package/dist/markdown/content-hash.js +46 -0
- package/dist/markdown/content-hash.js.map +1 -0
- package/dist/markdown/frontmatter.d.ts +69 -0
- package/dist/markdown/frontmatter.js +147 -0
- package/dist/markdown/frontmatter.js.map +1 -0
- package/dist/markdown/hash-backfill.d.ts +22 -0
- package/dist/markdown/hash-backfill.js +43 -0
- package/dist/markdown/hash-backfill.js.map +1 -0
- package/dist/mcp/query-syntax.d.ts +20 -0
- package/dist/mcp/query-syntax.js +194 -0
- package/dist/mcp/query-syntax.js.map +1 -0
- package/dist/mcp/render.d.ts +31 -0
- package/dist/mcp/render.js +110 -0
- package/dist/mcp/render.js.map +1 -0
- package/dist/mcp/server.d.ts +60 -0
- package/dist/mcp/server.js +170 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +93 -0
- package/dist/mcp/tools.js +1218 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/rest/conditional.d.ts +37 -0
- package/dist/rest/conditional.js +58 -0
- package/dist/rest/conditional.js.map +1 -0
- package/dist/rest/negotiate.d.ts +33 -0
- package/dist/rest/negotiate.js +54 -0
- package/dist/rest/negotiate.js.map +1 -0
- package/dist/rest/routes.d.ts +37 -0
- package/dist/rest/routes.js +744 -0
- package/dist/rest/routes.js.map +1 -0
- package/dist/seed/fixture-seed.d.ts +35 -0
- package/dist/seed/fixture-seed.js +75 -0
- package/dist/seed/fixture-seed.js.map +1 -0
- package/dist/seed/starship-config.d.ts +3 -0
- package/dist/seed/starship-config.js +5 -0
- package/dist/seed/starship-config.js.map +1 -0
- package/dist/server/headers.d.ts +36 -0
- package/dist/server/headers.js +30 -0
- package/dist/server/headers.js.map +1 -0
- package/dist/server/http-error.d.ts +53 -0
- package/dist/server/http-error.js +104 -0
- package/dist/server/http-error.js.map +1 -0
- package/dist/server/serve.d.ts +56 -0
- package/dist/server/serve.js +135 -0
- package/dist/server/serve.js.map +1 -0
- package/dist/shell/audit.d.ts +32 -0
- package/dist/shell/audit.js +28 -0
- package/dist/shell/audit.js.map +1 -0
- package/dist/shell/guard.d.ts +50 -0
- package/dist/shell/guard.js +176 -0
- package/dist/shell/guard.js.map +1 -0
- package/dist/shell/keys.d.ts +36 -0
- package/dist/shell/keys.js +64 -0
- package/dist/shell/keys.js.map +1 -0
- package/dist/shell/login.d.ts +56 -0
- package/dist/shell/login.js +130 -0
- package/dist/shell/login.js.map +1 -0
- package/dist/shell/oidc.d.ts +62 -0
- package/dist/shell/oidc.js +102 -0
- package/dist/shell/oidc.js.map +1 -0
- package/dist/shell/policy.d.ts +100 -0
- package/dist/shell/policy.js +232 -0
- package/dist/shell/policy.js.map +1 -0
- package/dist/shell/proxy-policy.d.ts +34 -0
- package/dist/shell/proxy-policy.js +120 -0
- package/dist/shell/proxy-policy.js.map +1 -0
- package/dist/shell/proxy.d.ts +47 -0
- package/dist/shell/proxy.js +253 -0
- package/dist/shell/proxy.js.map +1 -0
- package/dist/shell/serve.d.ts +86 -0
- package/dist/shell/serve.js +0 -0
- package/dist/shell/serve.js.map +1 -0
- package/dist/shell/stdio.d.ts +55 -0
- package/dist/shell/stdio.js +63 -0
- package/dist/shell/stdio.js.map +1 -0
- package/dist/storage/registry.d.ts +20 -0
- package/dist/storage/registry.js +38 -0
- package/dist/storage/registry.js.map +1 -0
- package/dist/storage/search-plan.d.ts +93 -0
- package/dist/storage/search-plan.js +15 -0
- package/dist/storage/search-plan.js.map +1 -0
- package/dist/storage/types.d.ts +448 -0
- package/dist/storage/types.js +14 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/storage/versions-since.d.ts +72 -0
- package/dist/storage/versions-since.js +92 -0
- package/dist/storage/versions-since.js.map +1 -0
- package/dist/storage-postgres/adapter.d.ts +17 -0
- package/dist/storage-postgres/adapter.js +782 -0
- package/dist/storage-postgres/adapter.js.map +1 -0
- package/dist/storage-postgres/compile-postgres.d.ts +22 -0
- package/dist/storage-postgres/compile-postgres.js +830 -0
- package/dist/storage-postgres/compile-postgres.js.map +1 -0
- package/dist/storage-postgres/errors.d.ts +34 -0
- package/dist/storage-postgres/errors.js +50 -0
- package/dist/storage-postgres/errors.js.map +1 -0
- package/dist/storage-postgres/migrations/0001_init.sql +113 -0
- package/dist/storage-postgres/migrations/0002_content_hash.sql +7 -0
- package/dist/storage-postgres/migrations/index.d.ts +22 -0
- package/dist/storage-postgres/migrations/index.js +70 -0
- package/dist/storage-postgres/migrations/index.js.map +1 -0
- package/dist/storage-sqlite/adapter.d.ts +2 -0
- package/dist/storage-sqlite/adapter.js +688 -0
- package/dist/storage-sqlite/adapter.js.map +1 -0
- package/dist/storage-sqlite/compile-filter.d.ts +41 -0
- package/dist/storage-sqlite/compile-filter.js +881 -0
- package/dist/storage-sqlite/compile-filter.js.map +1 -0
- package/dist/storage-sqlite/compile-sqlite.d.ts +19 -0
- package/dist/storage-sqlite/compile-sqlite.js +176 -0
- package/dist/storage-sqlite/compile-sqlite.js.map +1 -0
- package/dist/storage-sqlite/migrations/0001_init.sql +123 -0
- package/dist/storage-sqlite/migrations/0002_content_hash.sql +7 -0
- package/dist/storage-sqlite/migrations/index.d.ts +6 -0
- package/dist/storage-sqlite/migrations/index.js +41 -0
- package/dist/storage-sqlite/migrations/index.js.map +1 -0
- package/dist/storage-sqlite/vec.d.ts +40 -0
- package/dist/storage-sqlite/vec.js +62 -0
- package/dist/storage-sqlite/vec.js.map +1 -0
- package/dist/sync/cursor.d.ts +36 -0
- package/dist/sync/cursor.js +66 -0
- package/dist/sync/cursor.js.map +1 -0
- package/dist/sync/daemon.d.ts +40 -0
- package/dist/sync/daemon.js +202 -0
- package/dist/sync/daemon.js.map +1 -0
- package/dist/sync/feed.d.ts +38 -0
- package/dist/sync/feed.js +125 -0
- package/dist/sync/feed.js.map +1 -0
- package/dist/sync/fs-store.d.ts +8 -0
- package/dist/sync/fs-store.js +76 -0
- package/dist/sync/fs-store.js.map +1 -0
- package/dist/sync/intrinsics.d.ts +52 -0
- package/dist/sync/intrinsics.js +76 -0
- package/dist/sync/intrinsics.js.map +1 -0
- package/dist/sync/paths.d.ts +38 -0
- package/dist/sync/paths.js +56 -0
- package/dist/sync/paths.js.map +1 -0
- package/dist/sync/push.d.ts +48 -0
- package/dist/sync/push.js +328 -0
- package/dist/sync/push.js.map +1 -0
- package/dist/sync/reconcile.d.ts +54 -0
- package/dist/sync/reconcile.js +252 -0
- package/dist/sync/reconcile.js.map +1 -0
- package/dist/sync/run.d.ts +27 -0
- package/dist/sync/run.js +46 -0
- package/dist/sync/run.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kernel.graph — the graph read surface (docs/graph-plan.md).
|
|
3
|
+
*
|
|
4
|
+
* A read-only BFS neighborhood expansion over the repo-local `links` derived
|
|
5
|
+
* index. Given a root set, expand outward under a direction lens, honoring
|
|
6
|
+
* scope and `filter` as *visibility* (traversal happens inside the visible
|
|
7
|
+
* subgraph), and return documents, distinct induced links, a behavioral
|
|
8
|
+
* frontier, and truncation metadata.
|
|
9
|
+
*
|
|
10
|
+
* The whole thing is expressed in the system's own vocabulary — documents and
|
|
11
|
+
* links — with no node/edge layer. See §5 for the pinned decisions.
|
|
12
|
+
*
|
|
13
|
+
* Visibility reuse: rather than re-implement scope/sigil/filter evaluation,
|
|
14
|
+
* every visibility check runs through the existing `versions_search` path via
|
|
15
|
+
* a `SearchPlan`. `$degrees` is bound per round by rewriting the parsed filter
|
|
16
|
+
* to an integer constant (degrees.ts), so both dialect compilers stay unaware
|
|
17
|
+
* of it. This is the "reuse the SearchPlan path" mandate of §4.3.
|
|
18
|
+
*/
|
|
19
|
+
import { BODY_FIELD } from "../links/extract.js";
|
|
20
|
+
import { globToRegexSource } from "./auth/glob.js";
|
|
21
|
+
import { claimsGrantRepo, claimsToScopeGroups } from "./auth/scope.js";
|
|
22
|
+
import { KernelError, repoNotFound } from "./errors.js";
|
|
23
|
+
import { effectivePathConfig, parseRepoOverride } from "./path-config.js";
|
|
24
|
+
import { parseCel } from "./query/cel-parse.js";
|
|
25
|
+
import { bindDegrees } from "./query/degrees.js";
|
|
26
|
+
import { isPathGlobPattern, normalizeExactDocumentPath } from "./validation.js";
|
|
27
|
+
// Defaults + caps (§8). Following query's constant-default style rather than
|
|
28
|
+
// config knobs; a generous links ceiling keeps a hub expansion bounded.
|
|
29
|
+
export const DEFAULT_DEGREES = 1;
|
|
30
|
+
export const MAX_DEGREES = 5;
|
|
31
|
+
export const DEFAULT_MAX_DOCUMENTS = 100;
|
|
32
|
+
export const HARD_MAX_DOCUMENTS = 500;
|
|
33
|
+
export const LINKS_CEILING = 5000;
|
|
34
|
+
export async function runGraph(claims, spec, deps) {
|
|
35
|
+
const repo = await deps.storage.repos_by_slug(spec.repo);
|
|
36
|
+
if (!repo)
|
|
37
|
+
throw repoNotFound(spec.repo);
|
|
38
|
+
if (claims && !claimsGrantRepo(claims, repo.slug))
|
|
39
|
+
throw repoNotFound(spec.repo);
|
|
40
|
+
const internal = buildInternal(claims, spec, deps, repo);
|
|
41
|
+
const rootPatterns = normalizeRoots(spec.roots, deps.pathConfig);
|
|
42
|
+
const emptyResult = {
|
|
43
|
+
documents: [],
|
|
44
|
+
links: [],
|
|
45
|
+
frontier: [],
|
|
46
|
+
complete_degrees: 0,
|
|
47
|
+
truncated: false,
|
|
48
|
+
};
|
|
49
|
+
// 1-2. Resolve roots against visible, filter-matching current docs at
|
|
50
|
+
// $degrees = 0. A glob matching nothing → empty result, not an error.
|
|
51
|
+
const roots = await resolveRoots(internal, rootPatterns);
|
|
52
|
+
if (roots.length === 0)
|
|
53
|
+
return emptyResult;
|
|
54
|
+
// 3-4. BFS by rounds within the effective graph, bounded by max_documents.
|
|
55
|
+
const bfs = await expand(internal, roots);
|
|
56
|
+
// 5. Behavioral frontier: admitted docs with ≥1 effective link to a
|
|
57
|
+
// document not in the result.
|
|
58
|
+
const frontier = await computeFrontier(internal, bfs);
|
|
59
|
+
// 6. Induced links: distinct (source, target, field) over admitted docs.
|
|
60
|
+
const { links, linksTruncated } = await inducedLinks(internal, bfs.admittedIds);
|
|
61
|
+
// 7. Degree counts: scope-visible distinct in/out neighbor counts,
|
|
62
|
+
// independent of this call's filter/fields/degrees.
|
|
63
|
+
const degreeCounts = await degreeCountsFor(internal, bfs.admittedIds);
|
|
64
|
+
// 8. Assemble. Documents ordered ($degrees, $path); links (source,target,field).
|
|
65
|
+
const documents = assembleDocuments(internal, bfs, degreeCounts);
|
|
66
|
+
return {
|
|
67
|
+
documents,
|
|
68
|
+
links,
|
|
69
|
+
frontier,
|
|
70
|
+
complete_degrees: bfs.completeDegrees,
|
|
71
|
+
truncated: bfs.truncated || linksTruncated,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// -----------------------------------------------------------------------------
|
|
75
|
+
// Spec validation + normalization
|
|
76
|
+
// -----------------------------------------------------------------------------
|
|
77
|
+
const KNOWN_FIELDS = new Set([
|
|
78
|
+
"repo",
|
|
79
|
+
"roots",
|
|
80
|
+
"direction",
|
|
81
|
+
"degrees",
|
|
82
|
+
"fields",
|
|
83
|
+
"filter",
|
|
84
|
+
"select",
|
|
85
|
+
"max_documents",
|
|
86
|
+
]);
|
|
87
|
+
function buildInternal(claims, spec, deps, repo) {
|
|
88
|
+
for (const key of Object.keys(spec)) {
|
|
89
|
+
if (!KNOWN_FIELDS.has(key)) {
|
|
90
|
+
throw new KernelError("filter_invalid", {
|
|
91
|
+
reason: `unknown GraphSpec field: ${JSON.stringify(key)}`,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const direction = spec.direction ?? "both";
|
|
96
|
+
if (direction !== "out" && direction !== "in" && direction !== "both") {
|
|
97
|
+
throw new KernelError("filter_invalid", {
|
|
98
|
+
reason: `direction must be "out", "in", or "both" (got ${JSON.stringify(direction)})`,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
let degrees = spec.degrees ?? DEFAULT_DEGREES;
|
|
102
|
+
if (!Number.isSafeInteger(degrees) || degrees < 0) {
|
|
103
|
+
throw new KernelError("filter_invalid", {
|
|
104
|
+
reason: `degrees must be a non-negative integer (got ${JSON.stringify(spec.degrees)})`,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (degrees > MAX_DEGREES)
|
|
108
|
+
degrees = MAX_DEGREES;
|
|
109
|
+
let maxDocuments = spec.max_documents ?? DEFAULT_MAX_DOCUMENTS;
|
|
110
|
+
if (!Number.isSafeInteger(maxDocuments) || maxDocuments <= 0) {
|
|
111
|
+
throw new KernelError("filter_invalid", {
|
|
112
|
+
reason: `max_documents must be a positive integer (got ${JSON.stringify(spec.max_documents)})`,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
if (maxDocuments > HARD_MAX_DOCUMENTS)
|
|
116
|
+
maxDocuments = HARD_MAX_DOCUMENTS;
|
|
117
|
+
// `fields` maps `$body` → the storage sentinel; other members are
|
|
118
|
+
// frontmatter field paths, stored verbatim.
|
|
119
|
+
let fieldSet = null;
|
|
120
|
+
if (spec.fields !== undefined) {
|
|
121
|
+
if (!Array.isArray(spec.fields) || spec.fields.some((f) => typeof f !== "string")) {
|
|
122
|
+
throw new KernelError("filter_invalid", { reason: "fields must be an array of strings" });
|
|
123
|
+
}
|
|
124
|
+
fieldSet = new Set(spec.fields.map((f) => (f === "$body" ? BODY_FIELD : f)));
|
|
125
|
+
}
|
|
126
|
+
const select = spec.select ?? ["title"];
|
|
127
|
+
if (!Array.isArray(select) || select.some((s) => typeof s !== "string")) {
|
|
128
|
+
throw new KernelError("filter_invalid", { reason: "select must be an array of strings" });
|
|
129
|
+
}
|
|
130
|
+
for (const key of select) {
|
|
131
|
+
if (key.startsWith("$")) {
|
|
132
|
+
throw new KernelError("filter_invalid", {
|
|
133
|
+
reason: `select takes bare frontmatter keys, not intrinsics (got ${JSON.stringify(key)})`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
let filterAst;
|
|
138
|
+
if (spec.filter !== undefined) {
|
|
139
|
+
const parsed = parseCel(spec.filter);
|
|
140
|
+
if (!parsed.expr)
|
|
141
|
+
throw new KernelError("filter_invalid", { reason: "empty filter" });
|
|
142
|
+
filterAst = parsed.expr;
|
|
143
|
+
}
|
|
144
|
+
const effectiveConfig = effectivePathConfig(deps.serverPathConfig, parseRepoOverride(repo.path_config));
|
|
145
|
+
const sigils = buildSigilExclusion(repo.id, effectiveConfig);
|
|
146
|
+
const scope = buildScope(claims, repo);
|
|
147
|
+
return {
|
|
148
|
+
storage: deps.storage,
|
|
149
|
+
repo,
|
|
150
|
+
claims,
|
|
151
|
+
scope,
|
|
152
|
+
sigils,
|
|
153
|
+
direction,
|
|
154
|
+
degrees,
|
|
155
|
+
maxDocuments,
|
|
156
|
+
fieldSet,
|
|
157
|
+
filterAst,
|
|
158
|
+
select,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function normalizeRoots(roots, pathConfig) {
|
|
162
|
+
const list = Array.isArray(roots) ? roots : [roots];
|
|
163
|
+
if (list.length === 0 || list.some((r) => typeof r !== "string")) {
|
|
164
|
+
throw new KernelError("filter_invalid", {
|
|
165
|
+
reason: "roots must be a path/glob string or a non-empty array of them",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return list.map((r) => isPathGlobPattern(r) ? r : normalizeExactDocumentPath(r, pathConfig));
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* A graph never surfaces system/hidden docs unless the caller could, but the
|
|
172
|
+
* graph tool has no include_hidden/system flags — expansion always excludes
|
|
173
|
+
* hidden + system namespaces (matching `query`'s defaults). Build the
|
|
174
|
+
* exclusion the same way runQuery does.
|
|
175
|
+
*/
|
|
176
|
+
function buildSigilExclusion(repoId, cfg) {
|
|
177
|
+
const sigils = [...cfg.hidden_sigils, ...cfg.system_sigils];
|
|
178
|
+
if (sigils.length === 0)
|
|
179
|
+
return [];
|
|
180
|
+
return [{ repo_ids: [repoId], sigils }];
|
|
181
|
+
}
|
|
182
|
+
function buildScope(claims, repo) {
|
|
183
|
+
if (claims === null)
|
|
184
|
+
return { kind: "allow_all" };
|
|
185
|
+
const groups = claimsToScopeGroups(claims, [repo]);
|
|
186
|
+
if (groups.length === 0)
|
|
187
|
+
return { kind: "deny_all" };
|
|
188
|
+
return { kind: "groups", groups };
|
|
189
|
+
}
|
|
190
|
+
// -----------------------------------------------------------------------------
|
|
191
|
+
// Visibility (§4.1, §4.3) — reuses versions_search.
|
|
192
|
+
// -----------------------------------------------------------------------------
|
|
193
|
+
/**
|
|
194
|
+
* Max candidate document ids per `versions_search` call. A BFS ring is bounded
|
|
195
|
+
* only by fan-out, not by `max_documents`, so a large ring's candidate/neighbor
|
|
196
|
+
* set could otherwise overflow SQLite's bound-variable cap (via
|
|
197
|
+
* `candidate_document_ids`). We chunk under it and union; the visibility
|
|
198
|
+
* predicate is per-row (no cross-chunk ordering), so the union is exact.
|
|
199
|
+
*/
|
|
200
|
+
const VISIBILITY_CHUNK_SIZE = 20000;
|
|
201
|
+
/** Split ids into chunks of at most VISIBILITY_CHUNK_SIZE. */
|
|
202
|
+
function idChunks(ids) {
|
|
203
|
+
if (ids.length <= VISIBILITY_CHUNK_SIZE)
|
|
204
|
+
return ids.length === 0 ? [] : [[...ids]];
|
|
205
|
+
const out = [];
|
|
206
|
+
for (let i = 0; i < ids.length; i += VISIBILITY_CHUNK_SIZE) {
|
|
207
|
+
out.push(ids.slice(i, i + VISIBILITY_CHUNK_SIZE));
|
|
208
|
+
}
|
|
209
|
+
return out;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Return the subset of `docIds` that are visible at hop `degrees` — i.e. live
|
|
213
|
+
* current documents passing scope∧sigils∧filter (with `$degrees` bound to
|
|
214
|
+
* `degrees`). Runs a `versions_search` pass per id-chunk and unions the rows.
|
|
215
|
+
*/
|
|
216
|
+
async function visibleAt(internal, docIds, degrees) {
|
|
217
|
+
if (docIds.length === 0)
|
|
218
|
+
return [];
|
|
219
|
+
if (internal.scope.kind === "deny_all")
|
|
220
|
+
return [];
|
|
221
|
+
const filterAst = internal.filterAst === undefined ? undefined : bindDegrees(internal.filterAst, degrees);
|
|
222
|
+
const out = [];
|
|
223
|
+
for (const chunk of idChunks(docIds)) {
|
|
224
|
+
const plan = {
|
|
225
|
+
repo_ids: [internal.repo.id],
|
|
226
|
+
// candidate_document_ids already bounds the result to the chunk.
|
|
227
|
+
limit: chunk.length,
|
|
228
|
+
filter_ast: filterAst,
|
|
229
|
+
sigils: internal.sigils,
|
|
230
|
+
scope: internal.scope,
|
|
231
|
+
candidate_document_ids: chunk,
|
|
232
|
+
};
|
|
233
|
+
out.push(...(await internal.storage.versions_search(plan)));
|
|
234
|
+
}
|
|
235
|
+
return out;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Scope+sigil visibility WITHOUT the filter — used for `$links`/`$backlinks`
|
|
239
|
+
* degree counts, which describe true visible connectivity independent of this
|
|
240
|
+
* call's filter/fields/degrees (§2.2, decision 7).
|
|
241
|
+
*/
|
|
242
|
+
async function scopeVisible(internal, docIds) {
|
|
243
|
+
if (docIds.length === 0)
|
|
244
|
+
return new Set();
|
|
245
|
+
if (internal.scope.kind === "deny_all")
|
|
246
|
+
return new Set();
|
|
247
|
+
const visible = new Set();
|
|
248
|
+
for (const chunk of idChunks(docIds)) {
|
|
249
|
+
const plan = {
|
|
250
|
+
repo_ids: [internal.repo.id],
|
|
251
|
+
limit: chunk.length,
|
|
252
|
+
sigils: internal.sigils,
|
|
253
|
+
scope: internal.scope,
|
|
254
|
+
candidate_document_ids: chunk,
|
|
255
|
+
};
|
|
256
|
+
for (const r of await internal.storage.versions_search(plan))
|
|
257
|
+
visible.add(r.document_id);
|
|
258
|
+
}
|
|
259
|
+
return visible;
|
|
260
|
+
}
|
|
261
|
+
// -----------------------------------------------------------------------------
|
|
262
|
+
// Roots (§4.2)
|
|
263
|
+
// -----------------------------------------------------------------------------
|
|
264
|
+
async function resolveRoots(internal, patterns) {
|
|
265
|
+
// Match root patterns against live paths IN SQL (SQLite regexp() / Postgres
|
|
266
|
+
// `~`), so a graph call never materializes the whole repo just to find its
|
|
267
|
+
// roots. Each gitignore-glob compiles to the same anchored regex source the
|
|
268
|
+
// scope/link-predicate compilers use.
|
|
269
|
+
const regexes = patterns.map((p) => `^${globToRegexSource(p)}$`);
|
|
270
|
+
const matchIds = await internal.storage.versions_live_document_ids_matching(internal.repo.id, regexes);
|
|
271
|
+
if (matchIds.length === 0)
|
|
272
|
+
return [];
|
|
273
|
+
// Roots are visible + filter-matching at $degrees = 0.
|
|
274
|
+
return visibleAt(internal, matchIds, 0);
|
|
275
|
+
}
|
|
276
|
+
async function expand(internal, roots) {
|
|
277
|
+
const admitted = new Map();
|
|
278
|
+
const admittedOrder = [];
|
|
279
|
+
// Admit roots (round 0), sorted by path for determinism.
|
|
280
|
+
const sortedRoots = [...roots].sort((a, b) => cmpPath(a.path, b.path));
|
|
281
|
+
let truncated = false;
|
|
282
|
+
let completeDegrees = 0;
|
|
283
|
+
for (const v of sortedRoots) {
|
|
284
|
+
if (admitted.size >= internal.maxDocuments) {
|
|
285
|
+
truncated = true;
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
admitted.set(v.document_id, { degrees: 0, version: v });
|
|
289
|
+
admittedOrder.push(v.document_id);
|
|
290
|
+
}
|
|
291
|
+
// If roots themselves overflowed the budget, round 0 is incomplete.
|
|
292
|
+
if (truncated) {
|
|
293
|
+
completeDegrees = 0;
|
|
294
|
+
return finishState(admitted, admittedOrder, completeDegrees, truncated, [
|
|
295
|
+
// boundary = admitted round-0 docs (all potentially unexpanded)
|
|
296
|
+
...admittedOrder,
|
|
297
|
+
]);
|
|
298
|
+
}
|
|
299
|
+
completeDegrees = 0; // will bump to r on each clean round
|
|
300
|
+
let frontierIds = [...admittedOrder]; // round r-1's newly admitted docs
|
|
301
|
+
for (let r = 1; r <= internal.degrees; r++) {
|
|
302
|
+
if (frontierIds.length === 0) {
|
|
303
|
+
// Nothing left to expand — the whole reachable graph fits; complete
|
|
304
|
+
// through the requested degrees.
|
|
305
|
+
completeDegrees = internal.degrees;
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
// Candidate neighbor document ids reached this round (not yet admitted).
|
|
309
|
+
const neighborIds = await neighborsOf(internal, frontierIds);
|
|
310
|
+
const fresh = [...new Set(neighborIds)].filter((id) => !admitted.has(id));
|
|
311
|
+
if (fresh.length === 0) {
|
|
312
|
+
// Ring r is empty: every neighbor already seen. Complete through r.
|
|
313
|
+
completeDegrees = r;
|
|
314
|
+
frontierIds = [];
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
// Visibility at this round ($degrees = r).
|
|
318
|
+
const visibleRows = await visibleAt(internal, fresh, r);
|
|
319
|
+
// Deterministic admission order within the round: by path.
|
|
320
|
+
visibleRows.sort((a, b) => cmpPath(a.path, b.path));
|
|
321
|
+
const admittedThisRound = [];
|
|
322
|
+
let roundCut = false;
|
|
323
|
+
for (const v of visibleRows) {
|
|
324
|
+
if (admitted.has(v.document_id))
|
|
325
|
+
continue;
|
|
326
|
+
if (admitted.size >= internal.maxDocuments) {
|
|
327
|
+
roundCut = true;
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
admitted.set(v.document_id, { degrees: r, version: v });
|
|
331
|
+
admittedOrder.push(v.document_id);
|
|
332
|
+
admittedThisRound.push(v.document_id);
|
|
333
|
+
}
|
|
334
|
+
if (roundCut) {
|
|
335
|
+
// Budget cut this ring mid-way: the previous ring is the last exhaustive
|
|
336
|
+
// one (§4.4).
|
|
337
|
+
completeDegrees = r - 1;
|
|
338
|
+
truncated = true;
|
|
339
|
+
// Boundary = everything admitted this round PLUS the prior frontier
|
|
340
|
+
// (their onward links weren't fully enumerated) — but the frontier peek
|
|
341
|
+
// handles the general behavioral test, so return the admitted-this-round
|
|
342
|
+
// plus prior frontier as expansion candidates.
|
|
343
|
+
return finishState(admitted, admittedOrder, completeDegrees, truncated, [
|
|
344
|
+
...admittedThisRound,
|
|
345
|
+
...frontierIds,
|
|
346
|
+
]);
|
|
347
|
+
}
|
|
348
|
+
// Clean ring.
|
|
349
|
+
completeDegrees = r;
|
|
350
|
+
frontierIds = admittedThisRound;
|
|
351
|
+
}
|
|
352
|
+
// Boundary docs whose onward links weren't enumerated: those admitted at the
|
|
353
|
+
// final requested degree (they were never expanded).
|
|
354
|
+
const boundaryIds = admittedOrder.filter((id) => admitted.get(id).degrees === internal.degrees);
|
|
355
|
+
return finishState(admitted, admittedOrder, completeDegrees, truncated, boundaryIds);
|
|
356
|
+
}
|
|
357
|
+
function finishState(admitted, admittedOrder, completeDegrees, truncated, boundaryIds) {
|
|
358
|
+
return {
|
|
359
|
+
admitted,
|
|
360
|
+
admittedOrder,
|
|
361
|
+
admittedIds: [...admitted.keys()],
|
|
362
|
+
completeDegrees,
|
|
363
|
+
truncated,
|
|
364
|
+
boundaryIds,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Distinct neighbor document ids of `sourceIds` under the direction lens,
|
|
369
|
+
* `fields`-filtered. Traversal only follows edges whose field passes `fields`.
|
|
370
|
+
*/
|
|
371
|
+
async function neighborsOf(internal, sourceIds) {
|
|
372
|
+
const adj = await adjacencyFor(internal, sourceIds);
|
|
373
|
+
const out = [];
|
|
374
|
+
for (const a of adj) {
|
|
375
|
+
// The "other end" relative to the seed set depends on which direction the
|
|
376
|
+
// edge was fetched for; adjacencyFor already orients this.
|
|
377
|
+
out.push(a.otherId);
|
|
378
|
+
}
|
|
379
|
+
return out;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Fetch adjacency for a seed set under the lens, `fields`-filtered, returning
|
|
383
|
+
* oriented links: `seedId` is the doc in the seed set, `otherId` the neighbor.
|
|
384
|
+
* For "both", out- and in-adjacency are unioned.
|
|
385
|
+
*/
|
|
386
|
+
async function adjacencyFor(internal, seedIds) {
|
|
387
|
+
const oriented = [];
|
|
388
|
+
const passesField = (field) => internal.fieldSet === null || internal.fieldSet.has(field);
|
|
389
|
+
if (internal.direction === "out" || internal.direction === "both") {
|
|
390
|
+
const rows = await internal.storage.links_adjacent_out(internal.repo.id, seedIds);
|
|
391
|
+
for (const r of rows) {
|
|
392
|
+
if (passesField(r.field)) {
|
|
393
|
+
oriented.push({ seedId: r.source_id, otherId: r.target_id, field: r.field });
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (internal.direction === "in" || internal.direction === "both") {
|
|
398
|
+
const rows = await internal.storage.links_adjacent_in(internal.repo.id, seedIds);
|
|
399
|
+
for (const r of rows) {
|
|
400
|
+
if (passesField(r.field)) {
|
|
401
|
+
oriented.push({ seedId: r.target_id, otherId: r.source_id, field: r.field });
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return oriented;
|
|
406
|
+
}
|
|
407
|
+
// -----------------------------------------------------------------------------
|
|
408
|
+
// Frontier (§4.5) — behavioral: admitted docs with ≥1 effective link to a
|
|
409
|
+
// document not in the result.
|
|
410
|
+
// -----------------------------------------------------------------------------
|
|
411
|
+
async function computeFrontier(internal, bfs) {
|
|
412
|
+
if (bfs.boundaryIds.length === 0)
|
|
413
|
+
return [];
|
|
414
|
+
const boundary = [...new Set(bfs.boundaryIds)];
|
|
415
|
+
const oriented = await adjacencyFor(internal, boundary);
|
|
416
|
+
// Candidate neighbor ids not already in the result.
|
|
417
|
+
const neighborIds = new Set();
|
|
418
|
+
for (const o of oriented) {
|
|
419
|
+
if (!bfs.admitted.has(o.otherId))
|
|
420
|
+
neighborIds.add(o.otherId);
|
|
421
|
+
}
|
|
422
|
+
if (neighborIds.size === 0)
|
|
423
|
+
return [];
|
|
424
|
+
// Cheap visibility (§8 "start cheap"): a neighbor counts as potentially-new
|
|
425
|
+
// if it is scope+sigil visible (filter-unknown neighbors treated as
|
|
426
|
+
// potentially-new). This keeps the peek to one batched call.
|
|
427
|
+
const visibleNeighbors = await scopeVisible(internal, [...neighborIds]);
|
|
428
|
+
if (visibleNeighbors.size === 0)
|
|
429
|
+
return [];
|
|
430
|
+
const frontierDocIds = new Set();
|
|
431
|
+
for (const o of oriented) {
|
|
432
|
+
if (!bfs.admitted.has(o.otherId) && visibleNeighbors.has(o.otherId)) {
|
|
433
|
+
frontierDocIds.add(o.seedId);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
const paths = [...frontierDocIds]
|
|
437
|
+
.map((id) => bfs.admitted.get(id).version.path)
|
|
438
|
+
.sort(cmpPath);
|
|
439
|
+
return paths;
|
|
440
|
+
}
|
|
441
|
+
// -----------------------------------------------------------------------------
|
|
442
|
+
// Induced links (§4.6) — distinct (source, target, field) over admitted docs.
|
|
443
|
+
// -----------------------------------------------------------------------------
|
|
444
|
+
async function inducedLinks(internal, admittedIds) {
|
|
445
|
+
if (admittedIds.length === 0)
|
|
446
|
+
return { links: [], linksTruncated: false };
|
|
447
|
+
const admittedSet = new Set(admittedIds);
|
|
448
|
+
// One outbound pass over admitted sources; keep edges whose target is also
|
|
449
|
+
// admitted and whose field passes `fields`. Directional lens does not narrow
|
|
450
|
+
// the induced set — it is the complete picture over the shown documents.
|
|
451
|
+
const rows = await internal.storage.links_adjacent_out(internal.repo.id, admittedIds);
|
|
452
|
+
const passesField = (field) => internal.fieldSet === null || internal.fieldSet.has(field);
|
|
453
|
+
// Map document_id → path for the admitted set.
|
|
454
|
+
const pathById = await pathsForAdmitted(internal, admittedIds);
|
|
455
|
+
const seen = new Set();
|
|
456
|
+
const links = [];
|
|
457
|
+
for (const r of rows) {
|
|
458
|
+
if (!admittedSet.has(r.target_id))
|
|
459
|
+
continue;
|
|
460
|
+
if (!passesField(r.field))
|
|
461
|
+
continue;
|
|
462
|
+
const source = pathById.get(r.source_id);
|
|
463
|
+
const target = pathById.get(r.target_id);
|
|
464
|
+
if (source === undefined || target === undefined)
|
|
465
|
+
continue;
|
|
466
|
+
const field = r.field;
|
|
467
|
+
const key = `${source}${target}${field}`;
|
|
468
|
+
if (seen.has(key))
|
|
469
|
+
continue;
|
|
470
|
+
seen.add(key);
|
|
471
|
+
links.push({ source, target, field });
|
|
472
|
+
}
|
|
473
|
+
links.sort((a, b) => cmpPath(a.source, b.source) ||
|
|
474
|
+
cmpPath(a.target, b.target) ||
|
|
475
|
+
(a.field < b.field ? -1 : a.field > b.field ? 1 : 0));
|
|
476
|
+
if (links.length > LINKS_CEILING) {
|
|
477
|
+
return { links: links.slice(0, LINKS_CEILING), linksTruncated: true };
|
|
478
|
+
}
|
|
479
|
+
return { links, linksTruncated: false };
|
|
480
|
+
}
|
|
481
|
+
// Cache of admitted-doc paths keyed by the concrete BfsState.admitted map is
|
|
482
|
+
// awkward to thread; recompute once here from storage in a single batch.
|
|
483
|
+
async function pathsForAdmitted(internal, admittedIds) {
|
|
484
|
+
const rows = await internal.storage.versions_current_by_documents(internal.repo.id, admittedIds);
|
|
485
|
+
const map = new Map();
|
|
486
|
+
for (const r of rows)
|
|
487
|
+
map.set(r.document_id, r.path);
|
|
488
|
+
return map;
|
|
489
|
+
}
|
|
490
|
+
async function degreeCountsFor(internal, admittedIds) {
|
|
491
|
+
const result = new Map();
|
|
492
|
+
for (const id of admittedIds)
|
|
493
|
+
result.set(id, { links: 0, backlinks: 0 });
|
|
494
|
+
if (admittedIds.length === 0)
|
|
495
|
+
return result;
|
|
496
|
+
// All outbound + inbound adjacency of the admitted docs, unfiltered by
|
|
497
|
+
// `fields`/`filter`/`degrees` (decision 7). Collect the neighbor ids so we
|
|
498
|
+
// can apply scope-only visibility in one batch.
|
|
499
|
+
const outRows = await internal.storage.links_adjacent_out(internal.repo.id, admittedIds);
|
|
500
|
+
const inRows = await internal.storage.links_adjacent_in(internal.repo.id, admittedIds);
|
|
501
|
+
const neighborIds = new Set();
|
|
502
|
+
for (const r of outRows)
|
|
503
|
+
neighborIds.add(r.target_id);
|
|
504
|
+
for (const r of inRows)
|
|
505
|
+
neighborIds.add(r.source_id);
|
|
506
|
+
const visible = await scopeVisible(internal, [...neighborIds]);
|
|
507
|
+
// Distinct visible neighbor documents per admitted doc.
|
|
508
|
+
const outSets = new Map();
|
|
509
|
+
const inSets = new Map();
|
|
510
|
+
for (const id of admittedIds) {
|
|
511
|
+
outSets.set(id, new Set());
|
|
512
|
+
inSets.set(id, new Set());
|
|
513
|
+
}
|
|
514
|
+
for (const r of outRows) {
|
|
515
|
+
if (visible.has(r.target_id))
|
|
516
|
+
outSets.get(r.source_id)?.add(r.target_id);
|
|
517
|
+
}
|
|
518
|
+
for (const r of inRows) {
|
|
519
|
+
if (visible.has(r.source_id))
|
|
520
|
+
inSets.get(r.target_id)?.add(r.source_id);
|
|
521
|
+
}
|
|
522
|
+
for (const id of admittedIds) {
|
|
523
|
+
result.set(id, {
|
|
524
|
+
links: outSets.get(id)?.size ?? 0,
|
|
525
|
+
backlinks: inSets.get(id)?.size ?? 0,
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
return result;
|
|
529
|
+
}
|
|
530
|
+
// -----------------------------------------------------------------------------
|
|
531
|
+
// Assembly (§4.8)
|
|
532
|
+
// -----------------------------------------------------------------------------
|
|
533
|
+
function assembleDocuments(internal, bfs, degreeCounts) {
|
|
534
|
+
const docs = [];
|
|
535
|
+
for (const [docId, { degrees, version }] of bfs.admitted) {
|
|
536
|
+
const counts = degreeCounts.get(docId) ?? { links: 0, backlinks: 0 };
|
|
537
|
+
const doc = {
|
|
538
|
+
$path: version.path,
|
|
539
|
+
$degrees: degrees,
|
|
540
|
+
$links: counts.links,
|
|
541
|
+
$backlinks: counts.backlinks,
|
|
542
|
+
};
|
|
543
|
+
for (const key of internal.select) {
|
|
544
|
+
const value = version.frontmatter[key];
|
|
545
|
+
if (value !== undefined)
|
|
546
|
+
doc[key] = value;
|
|
547
|
+
}
|
|
548
|
+
docs.push(doc);
|
|
549
|
+
}
|
|
550
|
+
docs.sort((a, b) => a.$degrees - b.$degrees || cmpPath(a.$path, b.$path));
|
|
551
|
+
return docs;
|
|
552
|
+
}
|
|
553
|
+
// -----------------------------------------------------------------------------
|
|
554
|
+
// Ordering — stable, byte-for-byte deterministic (§2.2 "Ordering").
|
|
555
|
+
// -----------------------------------------------------------------------------
|
|
556
|
+
function cmpPath(a, b) {
|
|
557
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
558
|
+
}
|
|
559
|
+
//# sourceMappingURL=graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/kernel/graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `history` namespace (sync/history plan §3) — a top-level read surface
|
|
3
|
+
* keyed by position in the version log, spanning documents. `history.since` is
|
|
4
|
+
* the global change feed: it wraps `Storage.versions_since` (the gap-aware
|
|
5
|
+
* walk, §3.2) and enriches each settled row into a `VersionRef` — deriving
|
|
6
|
+
* `op` and resolving `prev_path` — so consumers never parse path sigils.
|
|
7
|
+
*/
|
|
8
|
+
import type { Storage } from "../storage/types.js";
|
|
9
|
+
import type { HistoryIndexPage, HistorySincePage, VersionOp } from "./wire.js";
|
|
10
|
+
/** Default feed page size when a caller omits `limit` (§3.3). */
|
|
11
|
+
export declare const HISTORY_SINCE_DEFAULT_LIMIT = 500;
|
|
12
|
+
/** Default `history.index` page size when a caller omits `limit` (§3.4). */
|
|
13
|
+
export declare const HISTORY_INDEX_DEFAULT_LIMIT = 1000;
|
|
14
|
+
/**
|
|
15
|
+
* Safety-window duration (§3.2): a gap's successor visible longer than this is
|
|
16
|
+
* treated as settled (the hole is burned, cross it); younger means the hole may
|
|
17
|
+
* still be committing (truncate before it). ~30s dwarfs any real write-tx.
|
|
18
|
+
*/
|
|
19
|
+
export declare const HISTORY_SAFETY_WINDOW_MS = 30000;
|
|
20
|
+
/**
|
|
21
|
+
* Derive the operation a version row represents (§3.3): no prev → create; same
|
|
22
|
+
* path → update; a new path in the system namespace (a `:deleted/…` tombstone)
|
|
23
|
+
* → delete; any other new path → move.
|
|
24
|
+
*/
|
|
25
|
+
export declare function deriveOp(hasPrev: boolean, path: string, prevPath: string | null, isSystemPath: (p: string) => boolean): VersionOp;
|
|
26
|
+
export type HistorySinceInput = {
|
|
27
|
+
after_version: string;
|
|
28
|
+
repo_id?: number;
|
|
29
|
+
limit: number;
|
|
30
|
+
now_ms: number;
|
|
31
|
+
window_ms: number;
|
|
32
|
+
};
|
|
33
|
+
export type HistorySinceDeps = {
|
|
34
|
+
storage: Storage;
|
|
35
|
+
/** repo id → slug, for stamping refs. */
|
|
36
|
+
repoSlug: (repoId: number) => string;
|
|
37
|
+
/** Whether a path lives in the system namespace (delete tombstones). */
|
|
38
|
+
isSystemPath: (path: string) => boolean;
|
|
39
|
+
/** Visibility gate: true when the caller may see this repo+path. */
|
|
40
|
+
canRead: (repoId: number, path: string) => boolean;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The global change feed. Advances the cursor to the storage safe frontier
|
|
44
|
+
* regardless of how many refs survive the visibility filter, so a caller with
|
|
45
|
+
* narrow scope still makes progress rather than stalling on hidden rows.
|
|
46
|
+
*/
|
|
47
|
+
export declare function runHistorySince(input: HistorySinceInput, deps: HistorySinceDeps): Promise<HistorySincePage>;
|
|
48
|
+
export type HistoryIndexInput = {
|
|
49
|
+
repo_id: number;
|
|
50
|
+
through_version?: string;
|
|
51
|
+
after_version?: string;
|
|
52
|
+
limit: number;
|
|
53
|
+
now_ms: number;
|
|
54
|
+
window_ms: number;
|
|
55
|
+
};
|
|
56
|
+
export type HistoryIndexDeps = {
|
|
57
|
+
storage: Storage;
|
|
58
|
+
/** Exclude a path from the index (system/hidden namespaces, as query does). */
|
|
59
|
+
isExcluded: (path: string) => boolean;
|
|
60
|
+
/** Visibility gate for the caller's scope. */
|
|
61
|
+
canRead: (path: string) => boolean;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Page the live set as of a safe head `R` (§3.4). On the first call (no
|
|
65
|
+
* `through_version`) the server captures `R = versions_safe_head(...)` and
|
|
66
|
+
* echoes it; subsequent pages pass it back. Keyset over current-version id in
|
|
67
|
+
* `(after, R]`, never offset — a document updated mid-pagination gets a new id
|
|
68
|
+
* > R, drops out of the remaining pages, and is delivered by
|
|
69
|
+
* `history.since(R)` afterward. System/hidden paths and out-of-scope rows are
|
|
70
|
+
* dropped here (the storage page is lightweight and unfiltered), so a raw page
|
|
71
|
+
* may yield fewer visible items than `limit`; we keep pulling storage pages
|
|
72
|
+
* until we fill `limit` or reach R.
|
|
73
|
+
*/
|
|
74
|
+
export declare function runHistoryIndex(input: HistoryIndexInput, deps: HistoryIndexDeps): Promise<HistoryIndexPage>;
|