@fortemi/core 2026.6.7 → 2026.6.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/dist/aiwg-index.d.ts +41 -1
- package/dist/aiwg-index.js +56 -0
- package/dist/aiwg-index.js.map +1 -1
- package/dist/index.d.ts +25 -25
- package/dist/index.js +57 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -126,6 +126,25 @@ Use this subpath for Pagenary-style command palettes, static docs search, and
|
|
|
126
126
|
vanilla JavaScript review surfaces. The top-level `@fortemi/core` export remains
|
|
127
127
|
available for full archive/runtime integrations.
|
|
128
128
|
|
|
129
|
+
The record contract keeps the existing flat fields for filtering and search:
|
|
130
|
+
`facets`, `tags`, `concepts`, `relationships`, and `provenance`. Static
|
|
131
|
+
consumers that render metadata tabs can also read optional rich fields from full
|
|
132
|
+
records:
|
|
133
|
+
|
|
134
|
+
- `skos_concepts`: concept ids plus labels, definitions, schemes, notation, URIs,
|
|
135
|
+
alternate labels, and metadata.
|
|
136
|
+
- `skos_relations`: `broader`, `narrower`, `related`, or project-specific SKOS
|
|
137
|
+
concept edges.
|
|
138
|
+
- `provenance_events`: W3C PROV-style activity records with agents, timestamps,
|
|
139
|
+
source paths, confidence/privacy, and attributes.
|
|
140
|
+
- `relationships[*].metadata`: optional relationship labels, confidence,
|
|
141
|
+
privacy, and structured metadata.
|
|
142
|
+
|
|
143
|
+
These fields are additive to `aiwg.fortemi.index.record.v1`. Existing consumers
|
|
144
|
+
can ignore them and continue querying the flat fields. Chunked indexes with a
|
|
145
|
+
projection keep rich metadata in detail records; call `getRecord(id)` before
|
|
146
|
+
rendering a metadata panel.
|
|
147
|
+
|
|
129
148
|
Large static indexes can use the chunked browser path instead of downloading one
|
|
130
149
|
full `aiwg.fortemi.index.export.v1` file. Host a manifest plus deterministic part
|
|
131
150
|
files:
|
package/dist/aiwg-index.d.ts
CHANGED
|
@@ -11,6 +11,10 @@ interface AiwgFortemiRelationship {
|
|
|
11
11
|
type: string;
|
|
12
12
|
target_id: string;
|
|
13
13
|
source_path?: string;
|
|
14
|
+
label?: string;
|
|
15
|
+
confidence?: number;
|
|
16
|
+
privacy?: AiwgPrivacyClassification;
|
|
17
|
+
metadata?: Record<string, unknown>;
|
|
14
18
|
}
|
|
15
19
|
interface AiwgFortemiProvenance {
|
|
16
20
|
field: string;
|
|
@@ -19,6 +23,36 @@ interface AiwgFortemiProvenance {
|
|
|
19
23
|
confidence: AiwgProvenanceConfidence;
|
|
20
24
|
privacy: AiwgPrivacyClassification;
|
|
21
25
|
}
|
|
26
|
+
type AiwgFortemiSkosRelationType = 'broader' | 'narrower' | 'related' | string;
|
|
27
|
+
interface AiwgFortemiSkosConcept {
|
|
28
|
+
id: string;
|
|
29
|
+
prefLabel: string;
|
|
30
|
+
definition?: string;
|
|
31
|
+
scheme?: string;
|
|
32
|
+
notation?: string;
|
|
33
|
+
uri?: string;
|
|
34
|
+
altLabels?: string[];
|
|
35
|
+
metadata?: Record<string, unknown>;
|
|
36
|
+
}
|
|
37
|
+
interface AiwgFortemiSkosRelation {
|
|
38
|
+
type: AiwgFortemiSkosRelationType;
|
|
39
|
+
source_id: string;
|
|
40
|
+
target_id: string;
|
|
41
|
+
source_path?: string;
|
|
42
|
+
metadata?: Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
interface AiwgFortemiProvenanceEvent {
|
|
45
|
+
id?: string;
|
|
46
|
+
activity: string;
|
|
47
|
+
agent?: string;
|
|
48
|
+
started_at?: string;
|
|
49
|
+
ended_at?: string;
|
|
50
|
+
source?: string;
|
|
51
|
+
path?: string;
|
|
52
|
+
confidence?: AiwgProvenanceConfidence;
|
|
53
|
+
privacy?: AiwgPrivacyClassification;
|
|
54
|
+
attributes?: Record<string, unknown>;
|
|
55
|
+
}
|
|
22
56
|
interface AiwgFortemiRecord {
|
|
23
57
|
schema_version: 'aiwg.fortemi.index.record.v1';
|
|
24
58
|
id: string;
|
|
@@ -31,6 +65,12 @@ interface AiwgFortemiRecord {
|
|
|
31
65
|
concepts: string[];
|
|
32
66
|
relationships: AiwgFortemiRelationship[];
|
|
33
67
|
provenance: AiwgFortemiProvenance[];
|
|
68
|
+
/** Optional rich SKOS metadata for static consumers that need labels/definitions without opening a shard. */
|
|
69
|
+
skos_concepts?: AiwgFortemiSkosConcept[];
|
|
70
|
+
/** Optional SKOS relationship edges among concepts referenced by this record. */
|
|
71
|
+
skos_relations?: AiwgFortemiSkosRelation[];
|
|
72
|
+
/** Optional W3C PROV-style activity chain for this record. */
|
|
73
|
+
provenance_events?: AiwgFortemiProvenanceEvent[];
|
|
34
74
|
privacy: {
|
|
35
75
|
classification: AiwgPrivacyClassification;
|
|
36
76
|
pii: boolean;
|
|
@@ -246,4 +286,4 @@ declare function aiwgFortemiIndexToCommunityGraph(index: AiwgFortemiIndexExport,
|
|
|
246
286
|
}[];
|
|
247
287
|
};
|
|
248
288
|
|
|
249
|
-
export { AIWG_SCAN_REQUIRED_FIELDS, type AiwgChunkedIndexBuildOptions, type AiwgChunkedIndexBuildResult, type AiwgChunkedIndexDetailLoader, type AiwgChunkedIndexLoadOptions, type AiwgChunkedIndexLoader, type AiwgChunkedIndexProgress, type AiwgChunkedIndexProgressPhase, type AiwgChunkedIndexQueryOptions, type AiwgChunkedIndexQueryResult, type AiwgChunkedIndexValidationResult, type AiwgDetailIdEncoding, type AiwgFortemiChunkDetailRef, type AiwgFortemiChunkManifest, type AiwgFortemiChunkPart, type AiwgFortemiChunkPartRef, type AiwgFortemiIndexExport, type AiwgFortemiProjectedRecord, type AiwgFortemiProvenance, type AiwgFortemiRecord, type AiwgFortemiRecordSource, type AiwgFortemiRecordType, type AiwgFortemiRelationship, type AiwgIndexController, type AiwgIndexControllerListener, type AiwgIndexControllerSnapshot, type AiwgIndexGraphOptions, type AiwgIndexQueryMatch, type AiwgIndexQueryOptions, type AiwgIndexQueryRankedItem, type AiwgIndexQueryResult, type AiwgIndexQueryWeights, type AiwgIndexValidationResult, type AiwgPrivacyClassification, type AiwgProvenanceConfidence, type AiwgReviewAction, type AiwgReviewDecision, type AiwgReviewDecisionExport, type AiwgReviewInput, aiwgDetailHrefForId, aiwgFortemiIndexToCommunityGraph, assertAiwgFortemiChunkManifest, assertAiwgFortemiChunkPart, assertAiwgFortemiIndexExport, buildAiwgChunkedIndex, createAiwgFetchChunkLoader, createAiwgFetchDetailLoader, createAiwgIndexController, createAiwgReviewDecisionExport, encodeAiwgDetailId, getAiwgFortemiFacets, queryAiwgFortemiIndex, validateAiwgFortemiChunkManifest, validateAiwgFortemiChunkPart, validateAiwgFortemiIndexExport };
|
|
289
|
+
export { AIWG_SCAN_REQUIRED_FIELDS, type AiwgChunkedIndexBuildOptions, type AiwgChunkedIndexBuildResult, type AiwgChunkedIndexDetailLoader, type AiwgChunkedIndexLoadOptions, type AiwgChunkedIndexLoader, type AiwgChunkedIndexProgress, type AiwgChunkedIndexProgressPhase, type AiwgChunkedIndexQueryOptions, type AiwgChunkedIndexQueryResult, type AiwgChunkedIndexValidationResult, type AiwgDetailIdEncoding, type AiwgFortemiChunkDetailRef, type AiwgFortemiChunkManifest, type AiwgFortemiChunkPart, type AiwgFortemiChunkPartRef, type AiwgFortemiIndexExport, type AiwgFortemiProjectedRecord, type AiwgFortemiProvenance, type AiwgFortemiProvenanceEvent, type AiwgFortemiRecord, type AiwgFortemiRecordSource, type AiwgFortemiRecordType, type AiwgFortemiRelationship, type AiwgFortemiSkosConcept, type AiwgFortemiSkosRelation, type AiwgFortemiSkosRelationType, type AiwgIndexController, type AiwgIndexControllerListener, type AiwgIndexControllerSnapshot, type AiwgIndexGraphOptions, type AiwgIndexQueryMatch, type AiwgIndexQueryOptions, type AiwgIndexQueryRankedItem, type AiwgIndexQueryResult, type AiwgIndexQueryWeights, type AiwgIndexValidationResult, type AiwgPrivacyClassification, type AiwgProvenanceConfidence, type AiwgReviewAction, type AiwgReviewDecision, type AiwgReviewDecisionExport, type AiwgReviewInput, aiwgDetailHrefForId, aiwgFortemiIndexToCommunityGraph, assertAiwgFortemiChunkManifest, assertAiwgFortemiChunkPart, assertAiwgFortemiIndexExport, buildAiwgChunkedIndex, createAiwgFetchChunkLoader, createAiwgFetchDetailLoader, createAiwgIndexController, createAiwgReviewDecisionExport, encodeAiwgDetailId, getAiwgFortemiFacets, queryAiwgFortemiIndex, validateAiwgFortemiChunkManifest, validateAiwgFortemiChunkPart, validateAiwgFortemiIndexExport };
|
package/dist/aiwg-index.js
CHANGED
|
@@ -56,6 +56,61 @@ function isFacetCounts(value) {
|
|
|
56
56
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
57
57
|
return Object.values(value).every((counts) => !!counts && typeof counts === "object" && !Array.isArray(counts) && Object.values(counts).every((count) => hasNonNegativeInteger(count)));
|
|
58
58
|
}
|
|
59
|
+
function isPlainRecord(value) {
|
|
60
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
61
|
+
}
|
|
62
|
+
function isOptionalStringArray(value) {
|
|
63
|
+
return value === void 0 || Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
64
|
+
}
|
|
65
|
+
function validateOptionalRichMetadata(item, index, errors) {
|
|
66
|
+
if (item.skos_concepts !== void 0) {
|
|
67
|
+
if (!Array.isArray(item.skos_concepts)) {
|
|
68
|
+
errors.push("items[" + index + "].skos_concepts must be an array when present");
|
|
69
|
+
} else {
|
|
70
|
+
for (const [conceptIndex, concept] of item.skos_concepts.entries()) {
|
|
71
|
+
if (!hasString(concept.id)) errors.push("items[" + index + "].skos_concepts[" + conceptIndex + "].id is required");
|
|
72
|
+
if (!hasString(concept.prefLabel)) errors.push("items[" + index + "].skos_concepts[" + conceptIndex + "].prefLabel is required");
|
|
73
|
+
if (!isOptionalStringArray(concept.altLabels)) errors.push("items[" + index + "].skos_concepts[" + conceptIndex + "].altLabels must be a string array");
|
|
74
|
+
if (concept.metadata !== void 0 && !isPlainRecord(concept.metadata)) {
|
|
75
|
+
errors.push("items[" + index + "].skos_concepts[" + conceptIndex + "].metadata must be an object");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (item.skos_relations !== void 0) {
|
|
81
|
+
if (!Array.isArray(item.skos_relations)) {
|
|
82
|
+
errors.push("items[" + index + "].skos_relations must be an array when present");
|
|
83
|
+
} else {
|
|
84
|
+
for (const [relationIndex, relation] of item.skos_relations.entries()) {
|
|
85
|
+
if (!hasString(relation.type)) errors.push("items[" + index + "].skos_relations[" + relationIndex + "].type is required");
|
|
86
|
+
if (!hasString(relation.source_id)) errors.push("items[" + index + "].skos_relations[" + relationIndex + "].source_id is required");
|
|
87
|
+
if (!hasString(relation.target_id)) errors.push("items[" + index + "].skos_relations[" + relationIndex + "].target_id is required");
|
|
88
|
+
if (relation.metadata !== void 0 && !isPlainRecord(relation.metadata)) {
|
|
89
|
+
errors.push("items[" + index + "].skos_relations[" + relationIndex + "].metadata must be an object");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (item.provenance_events !== void 0) {
|
|
95
|
+
if (!Array.isArray(item.provenance_events)) {
|
|
96
|
+
errors.push("items[" + index + "].provenance_events must be an array when present");
|
|
97
|
+
} else {
|
|
98
|
+
for (const [eventIndex, event] of item.provenance_events.entries()) {
|
|
99
|
+
if (!hasString(event.activity)) errors.push("items[" + index + "].provenance_events[" + eventIndex + "].activity is required");
|
|
100
|
+
if (event.attributes !== void 0 && !isPlainRecord(event.attributes)) {
|
|
101
|
+
errors.push("items[" + index + "].provenance_events[" + eventIndex + "].attributes must be an object");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (Array.isArray(item.relationships)) {
|
|
107
|
+
for (const [relationshipIndex, relationship] of item.relationships.entries()) {
|
|
108
|
+
if (relationship.metadata !== void 0 && !isPlainRecord(relationship.metadata)) {
|
|
109
|
+
errors.push("items[" + index + "].relationships[" + relationshipIndex + "].metadata must be an object");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
59
114
|
function validateAiwgFortemiIndexExport(value) {
|
|
60
115
|
const errors = [];
|
|
61
116
|
const counts = {};
|
|
@@ -94,6 +149,7 @@ function validateAiwgFortemiIndexExport(value) {
|
|
|
94
149
|
if (!Array.isArray(item.provenance) || item.provenance.length === 0) {
|
|
95
150
|
errors.push("items[" + index + "].provenance must be a non-empty array");
|
|
96
151
|
}
|
|
152
|
+
validateOptionalRichMetadata(item, index, errors);
|
|
97
153
|
if (!item.privacy || typeof item.privacy.pii !== "boolean" || !hasString(item.privacy.classification)) {
|
|
98
154
|
errors.push("items[" + index + "].privacy requires classification and pii");
|
|
99
155
|
}
|
package/dist/aiwg-index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/aiwg-index.ts"],"names":[],"mappings":"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","file":"aiwg-index.js","sourcesContent":["export type AiwgFortemiRecordType =\n | 'crm.contact'\n | 'crm.organization'\n | 'crm.event'\n | 'crm.interaction'\n | 'aiwg.artifact'\n | 'docs.page'\n\nexport type AiwgPrivacyClassification = 'private' | 'sanitized' | 'public'\nexport type AiwgProvenanceConfidence = 'source' | 'candidate' | 'reviewed' | 'rejected'\nexport type AiwgReviewAction = 'accept' | 'reject' | 'defer'\n\nexport interface AiwgFortemiRecordSource {\n path: string\n repo_relative_path: string\n locator: string\n}\n\nexport interface AiwgFortemiRelationship {\n type: string\n target_id: string\n source_path?: string\n}\n\nexport interface AiwgFortemiProvenance {\n field: string\n source: string\n path: string\n confidence: AiwgProvenanceConfidence\n privacy: AiwgPrivacyClassification\n}\n\nexport interface AiwgFortemiRecord {\n schema_version: 'aiwg.fortemi.index.record.v1'\n id: string\n type: AiwgFortemiRecordType\n source: AiwgFortemiRecordSource\n title: string\n text: string\n facets: Record<string, string[]>\n tags: string[]\n concepts: string[]\n relationships: AiwgFortemiRelationship[]\n provenance: AiwgFortemiProvenance[]\n privacy: {\n classification: AiwgPrivacyClassification\n pii: boolean\n }\n updated_at: string\n}\n\nexport interface AiwgFortemiIndexExport {\n schema_version: 'aiwg.fortemi.index.export.v1'\n generated_at: string\n source: {\n repo: string\n privacy: AiwgPrivacyClassification\n }\n items: AiwgFortemiRecord[]\n}\n\nexport interface AiwgFortemiChunkPartRef {\n href: string\n offset: number\n count: number\n}\n\n// Fields a scan part must retain for query/browse/rank/facet to work. The rest\n// (source, provenance, relationships, updated_at) are detail-only and may be\n// dropped from scan parts via `projection`, then resolved on demand by id.\nexport const AIWG_SCAN_REQUIRED_FIELDS: Array<keyof AiwgFortemiRecord> = [\n 'schema_version',\n 'id',\n 'type',\n 'title',\n 'text',\n 'facets',\n 'tags',\n 'concepts',\n 'privacy',\n]\n\n// A record as it appears in a scan part. With no manifest `projection`, this is a\n// full AiwgFortemiRecord. With a projection, detail-only fields are absent — read\n// them via the controller's getRecord(). Typed as the full record for ergonomics;\n// query/browse code guards the projectable fields.\nexport type AiwgFortemiProjectedRecord =\n Pick<AiwgFortemiRecord, 'schema_version' | 'id' | 'type' | 'title' | 'text' | 'facets' | 'tags' | 'concepts' | 'privacy'>\n & Partial<AiwgFortemiRecord>\n\n// How a record id is encoded into a detail filename/path segment.\n// - 'base64url': path-safe, single segment, no '%' — works on every static host,\n// including ids containing '/' (default for new builds; see #177).\n// - 'uri': encodeURIComponent — legacy. Breaks for ids containing '/' on static\n// servers that reject %2F (path-traversal protection → 404).\nexport type AiwgDetailIdEncoding = 'uri' | 'base64url'\n\n// How the controller resolves a full record by id when scan parts are projected.\nexport interface AiwgFortemiChunkDetailRef {\n // href template containing `{id}`, relative to the manifest base — e.g.\n // \"detail/{id}.json\". The `{id}` is encoded per `encoding` at substitution.\n href: string\n // id→segment encoding. Absent is treated as 'uri' for backward compatibility\n // with manifests built before #177; new builds default to 'base64url'.\n encoding?: AiwgDetailIdEncoding\n}\n\nexport interface AiwgFortemiChunkManifest {\n schema_version: 'aiwg.fortemi.index.chunk-manifest.v1'\n generated_at: string\n source: AiwgFortemiIndexExport['source']\n total: number\n part_size: number\n facets?: Record<string, Record<string, number>>\n // Field names present in scan-part items. Absent → scan parts carry whole records.\n // When set, must include AIWG_SCAN_REQUIRED_FIELDS.\n projection?: Array<keyof AiwgFortemiRecord>\n // Resolver for full records by id (used with `projection` to lazy-load detail).\n detail?: AiwgFortemiChunkDetailRef\n parts: AiwgFortemiChunkPartRef[]\n}\n\nexport interface AiwgFortemiChunkPart {\n schema_version: 'aiwg.fortemi.index.chunk.v1'\n manifest_schema_version: 'aiwg.fortemi.index.chunk-manifest.v1'\n offset: number\n items: AiwgFortemiRecord[]\n}\n\nexport interface AiwgIndexValidationResult {\n valid: boolean\n errors: string[]\n counts: Partial<Record<AiwgFortemiRecordType, number>>\n}\n\nexport interface AiwgChunkedIndexValidationResult {\n valid: boolean\n errors: string[]\n}\n\nexport interface AiwgIndexQueryOptions {\n types?: AiwgFortemiRecordType[]\n facets?: Record<string, string[]>\n tags?: string[]\n concepts?: string[]\n privacy?: AiwgPrivacyClassification[]\n relationshipTargetId?: string\n limit?: number\n offset?: number\n rank?: boolean\n snippets?: boolean\n snippetLength?: number\n weights?: Partial<AiwgIndexQueryWeights>\n includeMatches?: boolean\n}\n\nexport interface AiwgIndexQueryWeights {\n title: number\n text: number\n tag: number\n concept: number\n}\n\nexport interface AiwgIndexQueryMatch {\n field: 'title' | 'text' | 'tag' | 'concept'\n value: string\n}\n\nexport interface AiwgIndexQueryRankedItem {\n item: AiwgFortemiRecord\n rank: number\n snippet?: string\n matches?: AiwgIndexQueryMatch[]\n}\n\nexport interface AiwgIndexQueryResult {\n items: AiwgFortemiRecord[]\n total: number\n facets: Record<string, Record<string, number>>\n rankedItems?: AiwgIndexQueryRankedItem[]\n}\n\nexport type AiwgChunkedIndexLoader = (\n part: AiwgFortemiChunkPartRef,\n manifest: AiwgFortemiChunkManifest,\n) => Promise<unknown>\n\n// Resolves a full record by id (used with projected scan parts). Returns the\n// parsed record JSON; validated by the controller before use.\nexport type AiwgChunkedIndexDetailLoader = (\n id: string,\n manifest: AiwgFortemiChunkManifest,\n) => Promise<unknown>\n\nexport interface AiwgChunkedIndexLoadOptions {\n maxCachedParts?: number\n // Required to resolve detail for projected indexes via getRecord(); ignored otherwise.\n detailLoader?: AiwgChunkedIndexDetailLoader\n maxCachedDetails?: number\n // Bounds the filtered/ranked match-set cache used to page a query without\n // re-scanning every part. Counts total cached entries across all queries\n // (LRU-evicted). Defaults to 5000. The cache is keyed on query + filters +\n // weights, so paging the same query (varying only offset/limit/sort/snippets)\n // reuses the scan; see queryChunked.\n maxCachedMatches?: number\n}\n\nexport type AiwgChunkedIndexProgressPhase = 'part' | 'query'\n\nexport interface AiwgChunkedIndexProgress {\n phase: AiwgChunkedIndexProgressPhase\n done: number\n total: number\n href?: string\n}\n\nexport interface AiwgChunkedIndexQueryOptions extends AiwgIndexQueryOptions {\n onProgress?: (progress: AiwgChunkedIndexProgress) => void\n}\n\nexport interface AiwgChunkedIndexQueryResult extends AiwgIndexQueryResult {\n manifestTotal: number\n scannedParts: number\n fetchedParts: number\n complete: boolean\n}\n\nexport interface AiwgReviewDecision {\n item_id: string\n action: AiwgReviewAction\n reason?: string\n updated_at: string\n}\n\nexport interface AiwgReviewDecisionExport {\n schema_version: 'aiwg.fortemi.review-decisions.v1'\n generated_at: string\n source_export_schema_version: string\n decisions: AiwgReviewDecision[]\n}\n\nexport interface AiwgIndexGraphOptions {\n communityFacet?: string\n communityTagPrefix?: string\n relationshipWeights?: Record<string, number>\n includeDanglingRelationships?: boolean\n}\n\nexport interface AiwgReviewInput {\n item_id: string\n action: AiwgReviewAction\n reason?: string\n}\n\nexport interface AiwgIndexControllerSnapshot {\n index: AiwgFortemiIndexExport | null\n chunked: {\n manifest: AiwgFortemiChunkManifest\n cachedParts: number\n maxCachedParts: number\n } | null\n data: AiwgIndexQueryResult | null\n error: Error | null\n reviewDecisions: AiwgReviewDecision[]\n}\n\nexport type AiwgIndexControllerListener = (snapshot: AiwgIndexControllerSnapshot) => void\n\nexport interface AiwgIndexController {\n loadIndex(value: unknown): AiwgFortemiIndexExport\n loadChunkedIndex(\n manifest: unknown,\n loader: AiwgChunkedIndexLoader,\n options?: AiwgChunkedIndexLoadOptions,\n ): AiwgFortemiChunkManifest\n getIndex(): AiwgFortemiIndexExport | null\n getChunkedManifest(): AiwgFortemiChunkManifest | null\n getSnapshot(): AiwgIndexControllerSnapshot\n query(query?: string, options?: AiwgIndexQueryOptions): AiwgIndexQueryResult\n queryChunked(query?: string, options?: AiwgChunkedIndexQueryOptions): Promise<AiwgChunkedIndexQueryResult>\n // Resolve a full record by id. For a projected chunked index, fetches detail via\n // the detailLoader (bounded cache); for a whole-record index/parts, returns the\n // record from loaded data. Rejects if detail is unavailable.\n getRecord(id: string): Promise<AiwgFortemiRecord>\n clearChunkCache(): void\n toCommunityGraph(options?: AiwgIndexGraphOptions): ReturnType<typeof aiwgFortemiIndexToCommunityGraph>\n setReviewDecision(input: AiwgReviewInput): AiwgReviewDecision\n clearReviewDecision(itemId: string): void\n createReviewDecisionExport(generatedAt?: string): AiwgReviewDecisionExport\n subscribe(listener: AiwgIndexControllerListener): () => void\n}\n\nconst REQUIRED_RECORD_FIELDS: Array<keyof AiwgFortemiRecord> = [\n 'schema_version',\n 'id',\n 'type',\n 'source',\n 'title',\n 'text',\n 'facets',\n 'tags',\n 'concepts',\n 'relationships',\n 'provenance',\n 'privacy',\n 'updated_at',\n]\n\nconst VALID_TYPES = new Set<AiwgFortemiRecordType>([\n 'crm.contact',\n 'crm.organization',\n 'crm.event',\n 'crm.interaction',\n 'aiwg.artifact',\n 'docs.page',\n])\n\nconst DEFAULT_QUERY_WEIGHTS: AiwgIndexQueryWeights = {\n title: 4,\n tag: 3,\n concept: 2,\n text: 1,\n}\n\nfunction hasString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0\n}\n\nfunction pushFacet(counts: Record<string, Record<string, number>>, name: string, value: string) {\n counts[name] ??= {}\n counts[name][value] = (counts[name][value] ?? 0) + 1\n}\n\nfunction hasNonNegativeInteger(value: unknown): value is number {\n return Number.isInteger(value) && typeof value === 'number' && value >= 0\n}\n\nfunction hasPositiveInteger(value: unknown): value is number {\n return Number.isInteger(value) && typeof value === 'number' && value > 0\n}\n\nfunction isFacetCounts(value: unknown): value is Record<string, Record<string, number>> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false\n return Object.values(value).every((counts) => (\n !!counts\n && typeof counts === 'object'\n && !Array.isArray(counts)\n && Object.values(counts).every((count) => hasNonNegativeInteger(count))\n ))\n}\n\nexport function validateAiwgFortemiIndexExport(value: unknown): AiwgIndexValidationResult {\n const errors: string[] = []\n const counts: Partial<Record<AiwgFortemiRecordType, number>> = {}\n const data = value as Partial<AiwgFortemiIndexExport>\n\n if (data?.schema_version !== 'aiwg.fortemi.index.export.v1') {\n errors.push('schema_version must be aiwg.fortemi.index.export.v1')\n }\n if (!hasString(data?.generated_at)) errors.push('generated_at is required')\n if (!hasString(data?.source?.repo)) errors.push('source.repo is required')\n if (!hasString(data?.source?.privacy)) errors.push('source.privacy is required')\n if (!Array.isArray(data?.items)) errors.push('items must be an array')\n\n const ids = new Set<string>()\n let previousId = ''\n for (const [index, item] of (data.items ?? []).entries()) {\n for (const field of REQUIRED_RECORD_FIELDS) {\n if (!(field in item)) errors.push('items[' + index + '].' + field + ' is required')\n }\n if (item.schema_version !== 'aiwg.fortemi.index.record.v1') {\n errors.push('items[' + index + '].schema_version must be aiwg.fortemi.index.record.v1')\n }\n if (!hasString(item.id)) errors.push('items[' + index + '].id is required')\n if (hasString(item.id) && ids.has(item.id)) errors.push('duplicate id: ' + item.id)\n if (hasString(item.id)) ids.add(item.id)\n if (previousId && hasString(item.id) && previousId.localeCompare(item.id) > 0) {\n errors.push('items must be sorted by id: ' + previousId + ' before ' + item.id)\n }\n if (hasString(item.id)) previousId = item.id\n if (!VALID_TYPES.has(item.type)) errors.push('items[' + index + '].type is invalid')\n else counts[item.type] = (counts[item.type] ?? 0) + 1\n if (!hasString(item.source?.path)) errors.push('items[' + index + '].source.path is required')\n if (!hasString(item.source?.repo_relative_path)) errors.push('items[' + index + '].source.repo_relative_path is required')\n if (!hasString(item.source?.locator)) errors.push('items[' + index + '].source.locator is required')\n if (!Array.isArray(item.tags)) errors.push('items[' + index + '].tags must be an array')\n if (!Array.isArray(item.concepts)) errors.push('items[' + index + '].concepts must be an array')\n if (!Array.isArray(item.relationships)) errors.push('items[' + index + '].relationships must be an array')\n if (!Array.isArray(item.provenance) || item.provenance.length === 0) {\n errors.push('items[' + index + '].provenance must be a non-empty array')\n }\n if (!item.privacy || typeof item.privacy.pii !== 'boolean' || !hasString(item.privacy.classification)) {\n errors.push('items[' + index + '].privacy requires classification and pii')\n }\n }\n\n return { valid: errors.length === 0, errors, counts }\n}\n\nexport function assertAiwgFortemiIndexExport(value: unknown): AiwgFortemiIndexExport {\n const result = validateAiwgFortemiIndexExport(value)\n if (!result.valid) {\n throw new Error('Invalid AIWG Fortemi index export:\\n' + result.errors.join('\\n'))\n }\n return value as AiwgFortemiIndexExport\n}\n\nexport function validateAiwgFortemiChunkManifest(value: unknown): AiwgChunkedIndexValidationResult {\n const errors: string[] = []\n const data = value as Partial<AiwgFortemiChunkManifest>\n\n if (data?.schema_version !== 'aiwg.fortemi.index.chunk-manifest.v1') {\n errors.push('schema_version must be aiwg.fortemi.index.chunk-manifest.v1')\n }\n if (!hasString(data?.generated_at)) errors.push('generated_at is required')\n if (!hasString(data?.source?.repo)) errors.push('source.repo is required')\n if (!hasString(data?.source?.privacy)) errors.push('source.privacy is required')\n if (!hasNonNegativeInteger(data?.total)) errors.push('total must be a non-negative integer')\n if (!hasPositiveInteger(data?.part_size)) errors.push('part_size must be a positive integer')\n if (data.facets !== undefined && !isFacetCounts(data.facets)) {\n errors.push('facets must be a nested string-to-number count object')\n }\n if (data.projection !== undefined) {\n if (!Array.isArray(data.projection) || !data.projection.every((field) => typeof field === 'string')) {\n errors.push('projection must be an array of field names')\n } else {\n const present = new Set(data.projection)\n for (const field of AIWG_SCAN_REQUIRED_FIELDS) {\n if (!present.has(field)) errors.push('projection must include scan-required field ' + field)\n }\n }\n }\n if (data.detail !== undefined) {\n if (!hasString(data.detail.href)) errors.push('detail.href is required')\n else if (!data.detail.href.includes('{id}')) errors.push('detail.href must contain the {id} placeholder')\n if (\n data.detail.encoding !== undefined &&\n data.detail.encoding !== 'uri' &&\n data.detail.encoding !== 'base64url'\n ) {\n errors.push(\"detail.encoding must be 'uri' or 'base64url'\")\n }\n }\n if (!Array.isArray(data?.parts)) errors.push('parts must be an array')\n\n let expectedOffset = 0\n const parts = Array.isArray(data?.parts) ? data.parts : []\n for (const [index, part] of parts.entries()) {\n if (!hasString(part.href)) errors.push('parts[' + index + '].href is required')\n if (!hasNonNegativeInteger(part.offset)) errors.push('parts[' + index + '].offset must be a non-negative integer')\n if (!hasNonNegativeInteger(part.count)) errors.push('parts[' + index + '].count must be a non-negative integer')\n if (hasNonNegativeInteger(part.offset) && part.offset !== expectedOffset) {\n errors.push('parts[' + index + '].offset must be ' + expectedOffset)\n }\n if (hasNonNegativeInteger(part.count)) expectedOffset += part.count\n }\n if (hasNonNegativeInteger(data?.total) && expectedOffset !== data.total) {\n errors.push('parts counts must add up to total')\n }\n\n return { valid: errors.length === 0, errors }\n}\n\nexport function assertAiwgFortemiChunkManifest(value: unknown): AiwgFortemiChunkManifest {\n const result = validateAiwgFortemiChunkManifest(value)\n if (!result.valid) {\n throw new Error('Invalid AIWG Fortemi chunk manifest:\\n' + result.errors.join('\\n'))\n }\n return value as AiwgFortemiChunkManifest\n}\n\n// Validate projected (slim) scan-part items: scan-required fields only, ids unique + sorted.\nfunction validateProjectedRecords(items: Array<Partial<AiwgFortemiRecord>>): string[] {\n const errors: string[] = []\n const ids = new Set<string>()\n let previousId = ''\n for (const [index, item] of items.entries()) {\n if (item.schema_version !== 'aiwg.fortemi.index.record.v1') {\n errors.push('items[' + index + '].schema_version must be aiwg.fortemi.index.record.v1')\n }\n if (!hasString(item.id)) errors.push('items[' + index + '].id is required')\n if (hasString(item.id) && ids.has(item.id)) errors.push('duplicate id: ' + item.id)\n if (hasString(item.id)) ids.add(item.id)\n if (previousId && hasString(item.id) && previousId.localeCompare(item.id) > 0) {\n errors.push('items must be sorted by id: ' + previousId + ' before ' + item.id)\n }\n if (hasString(item.id)) previousId = item.id\n if (!item.type || !VALID_TYPES.has(item.type)) errors.push('items[' + index + '].type is invalid')\n if (!hasString(item.title)) errors.push('items[' + index + '].title is required')\n if (typeof item.text !== 'string') errors.push('items[' + index + '].text is required')\n if (!item.facets || typeof item.facets !== 'object' || Array.isArray(item.facets)) {\n errors.push('items[' + index + '].facets must be an object')\n }\n if (!Array.isArray(item.tags)) errors.push('items[' + index + '].tags must be an array')\n if (!Array.isArray(item.concepts)) errors.push('items[' + index + '].concepts must be an array')\n if (!item.privacy || !hasString(item.privacy.classification)) {\n errors.push('items[' + index + '].privacy.classification is required')\n }\n }\n return errors\n}\n\nexport function validateAiwgFortemiChunkPart(\n value: unknown,\n partRef?: AiwgFortemiChunkPartRef,\n manifest?: AiwgFortemiChunkManifest,\n): AiwgChunkedIndexValidationResult {\n const errors: string[] = []\n const data = value as Partial<AiwgFortemiChunkPart>\n\n if (data?.schema_version !== 'aiwg.fortemi.index.chunk.v1') {\n errors.push('schema_version must be aiwg.fortemi.index.chunk.v1')\n }\n if (data?.manifest_schema_version !== 'aiwg.fortemi.index.chunk-manifest.v1') {\n errors.push('manifest_schema_version must be aiwg.fortemi.index.chunk-manifest.v1')\n }\n if (!hasNonNegativeInteger(data?.offset)) errors.push('offset must be a non-negative integer')\n if (!Array.isArray(data?.items)) errors.push('items must be an array')\n\n if (partRef && hasNonNegativeInteger(data?.offset) && data.offset !== partRef.offset) {\n errors.push('offset must match manifest part offset ' + partRef.offset)\n }\n if (partRef && Array.isArray(data?.items) && data.items.length !== partRef.count) {\n errors.push('items length must match manifest part count ' + partRef.count)\n }\n\n if (Array.isArray(data?.items)) {\n if (manifest?.projection) {\n errors.push(...validateProjectedRecords(data.items).map((error) => 'items.' + error))\n } else {\n const validation = validateAiwgFortemiIndexExport({\n schema_version: 'aiwg.fortemi.index.export.v1',\n generated_at: manifest?.generated_at ?? '1970-01-01T00:00:00.000Z',\n source: manifest?.source ?? { repo: 'chunk', privacy: 'public' },\n items: data.items,\n })\n errors.push(...validation.errors.map((error) => 'items.' + error))\n }\n }\n\n return { valid: errors.length === 0, errors }\n}\n\nexport function assertAiwgFortemiChunkPart(\n value: unknown,\n partRef?: AiwgFortemiChunkPartRef,\n manifest?: AiwgFortemiChunkManifest,\n): AiwgFortemiChunkPart {\n const result = validateAiwgFortemiChunkPart(value, partRef, manifest)\n if (!result.valid) {\n throw new Error('Invalid AIWG Fortemi chunk part:\\n' + result.errors.join('\\n'))\n }\n return value as AiwgFortemiChunkPart\n}\n\nexport function createAiwgFetchChunkLoader(baseUrl?: string | URL): AiwgChunkedIndexLoader {\n return async (part) => {\n const href = baseUrl ? new URL(part.href, baseUrl).toString() : part.href\n const response = await fetch(href)\n if (!response.ok) throw new Error('Failed to fetch AIWG index chunk ' + href + ': ' + response.status)\n return response.json()\n }\n}\n\n// Encode a record id into a single, path-safe detail filename segment.\n// - 'base64url' (default): UTF-8 → base64url (no '+', '/', '=', '%'). Safe for ids\n// containing '/' on static hosts that reject %2F (#177).\n// - 'uri': encodeURIComponent (legacy).\nexport function encodeAiwgDetailId(id: string, encoding: AiwgDetailIdEncoding = 'base64url'): string {\n if (encoding === 'uri') return encodeURIComponent(id)\n const bytes = new TextEncoder().encode(id)\n let binary = ''\n for (const byte of bytes) binary += String.fromCharCode(byte)\n // btoa is available in browsers and Node ≥16.\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n// Resolve a manifest detail.href template for a given id, honoring detail.encoding\n// (absent → 'uri' for backward compatibility). The writer and the loader both go\n// through this so emitted filenames and fetched paths always agree.\nexport function aiwgDetailHrefForId(detail: AiwgFortemiChunkDetailRef, id: string): string {\n return detail.href.replace('{id}', encodeAiwgDetailId(id, detail.encoding ?? 'uri'))\n}\n\n// Detail loader for projected indexes: resolves the manifest's detail.href {id}\n// template (encoded per detail.encoding) against baseUrl and fetches the full record.\nexport function createAiwgFetchDetailLoader(baseUrl?: string | URL): AiwgChunkedIndexDetailLoader {\n return async (id, manifest) => {\n if (!manifest.detail?.href) throw new Error('Manifest has no detail.href for record resolution')\n const relative = aiwgDetailHrefForId(manifest.detail, id)\n const href = baseUrl ? new URL(relative, baseUrl).toString() : relative\n const response = await fetch(href)\n if (!response.ok) throw new Error('Failed to fetch AIWG index detail ' + href + ': ' + response.status)\n return response.json()\n }\n}\n\nexport function getAiwgFortemiFacets(items: AiwgFortemiRecord[]): Record<string, Record<string, number>> {\n const result: Record<string, Record<string, number>> = {}\n for (const item of items) {\n pushFacet(result, 'type', item.type)\n pushFacet(result, 'privacy', item.privacy.classification)\n for (const tag of item.tags) pushFacet(result, 'tag', tag)\n for (const concept of item.concepts) pushFacet(result, 'concept', concept)\n for (const [name, values] of Object.entries(item.facets)) {\n for (const value of values) pushFacet(result, name, value)\n }\n }\n return result\n}\n\nexport interface AiwgChunkedIndexBuildOptions {\n partSize?: number\n // When set, scan parts carry only these fields; full records go to `details`.\n projection?: Array<keyof AiwgFortemiRecord>\n // Detail href template (with {id}); defaults to \"detail/{id}.json\" when projecting.\n detailHref?: string\n // id→filename encoding for detail files; defaults to 'base64url' (path-safe,\n // works for ids containing '/'; see #177).\n idEncoding?: AiwgDetailIdEncoding\n generatedAt?: string\n}\n\nexport interface AiwgChunkedIndexBuildResult {\n manifest: AiwgFortemiChunkManifest\n parts: Array<{ href: string; part: AiwgFortemiChunkPart }>\n // Empty unless projecting. Each entry carries the full record plus the resolved,\n // encoding-correct `href` to host it at — write the record to that path so the\n // detail loader (which uses the same encoding) can fetch it back.\n details: Array<{ id: string; href: string; record: AiwgFortemiRecord }>\n}\n\n// Pure builder (no I/O): project an index export into the chunked manifest + parts\n// (+ detail records when projecting). The caller writes the returned objects to disk.\n// Manifest facets are computed from the full records, so global counts are exact even\n// when scan parts are slim.\nexport function buildAiwgChunkedIndex(\n index: AiwgFortemiIndexExport,\n options: AiwgChunkedIndexBuildOptions = {},\n): AiwgChunkedIndexBuildResult {\n const partSize = hasPositiveInteger(options.partSize) ? options.partSize : 500\n const projection = options.projection\n const idEncoding = options.idEncoding ?? 'base64url'\n const detailHref = options.detailHref ?? 'detail/{id}.json'\n const items = index.items\n const pad = (value: number): string => String(value).padStart(4, '0')\n const project = (record: AiwgFortemiRecord): AiwgFortemiRecord => {\n if (!projection) return record\n const slim: Record<string, unknown> = {}\n for (const field of projection) slim[field] = record[field]\n return slim as unknown as AiwgFortemiRecord\n }\n\n const parts: Array<{ href: string; part: AiwgFortemiChunkPart }> = []\n const partRefs: AiwgFortemiChunkPartRef[] = []\n for (let offset = 0, partIndex = 0; offset < items.length; offset += partSize, partIndex += 1) {\n const slice = items.slice(offset, offset + partSize)\n const href = 'part-' + pad(partIndex) + '.json'\n parts.push({\n href,\n part: {\n schema_version: 'aiwg.fortemi.index.chunk.v1',\n manifest_schema_version: 'aiwg.fortemi.index.chunk-manifest.v1',\n offset,\n items: slice.map(project),\n },\n })\n partRefs.push({ href, offset, count: slice.length })\n }\n\n const manifest: AiwgFortemiChunkManifest = {\n schema_version: 'aiwg.fortemi.index.chunk-manifest.v1',\n generated_at: options.generatedAt ?? index.generated_at,\n source: index.source,\n total: items.length,\n part_size: partSize,\n facets: getAiwgFortemiFacets(items),\n parts: partRefs,\n ...(projection ? { projection, detail: { href: detailHref, encoding: idEncoding } } : {}),\n }\n\n return {\n manifest,\n parts,\n details: projection\n ? items.map((record) => ({\n id: record.id,\n href: aiwgDetailHrefForId({ href: detailHref, encoding: idEncoding }, record.id),\n record,\n }))\n : [],\n }\n}\n\nfunction includesAll(actual: string[], expected: string[] | undefined): boolean {\n if (!expected || expected.length === 0) return true\n const actualSet = new Set(actual)\n return expected.every((value) => actualSet.has(value))\n}\n\nfunction matchesFacetFilters(item: AiwgFortemiRecord, filters: Record<string, string[]> | undefined): boolean {\n if (!filters) return true\n return Object.entries(filters).every(([name, expected]) => includesAll(item.facets[name] ?? [], expected))\n}\n\nfunction queryMatches(item: AiwgFortemiRecord, q: string): AiwgIndexQueryMatch[] {\n if (!q) return []\n const matches: AiwgIndexQueryMatch[] = []\n if (item.title.toLowerCase().includes(q)) matches.push({ field: 'title', value: item.title })\n if (item.text.toLowerCase().includes(q)) matches.push({ field: 'text', value: item.text })\n for (const tag of item.tags) {\n if (tag.toLowerCase().includes(q)) matches.push({ field: 'tag', value: tag })\n }\n for (const concept of item.concepts) {\n if (concept.toLowerCase().includes(q)) matches.push({ field: 'concept', value: concept })\n }\n return matches\n}\n\nfunction rankMatches(matches: AiwgIndexQueryMatch[], weights: AiwgIndexQueryWeights): number {\n return matches.reduce((total, match) => total + weights[match.field], 0)\n}\n\nfunction clipSnippet(value: string, q: string, maxLength: number): string {\n const normalizedLength = Math.max(20, maxLength)\n if (!value) return ''\n if (!q) return value.length > normalizedLength ? `${value.slice(0, normalizedLength).trimEnd()}...` : value\n\n const lower = value.toLowerCase()\n const index = lower.indexOf(q)\n if (index < 0) return value.length > normalizedLength ? `${value.slice(0, normalizedLength).trimEnd()}...` : value\n\n const context = Math.max(0, Math.floor((normalizedLength - q.length) / 2))\n const start = Math.max(0, index - context)\n const end = Math.min(value.length, start + normalizedLength)\n const prefix = start > 0 ? '...' : ''\n const suffix = end < value.length ? '...' : ''\n return `${prefix}${value.slice(start, end).trim()}${suffix}`\n}\n\nfunction createSnippet(item: AiwgFortemiRecord, matches: AiwgIndexQueryMatch[], q: string, maxLength: number): string {\n const textMatch = matches.find((match) => match.field === 'text')\n const titleMatch = matches.find((match) => match.field === 'title')\n const firstMatch = textMatch ?? titleMatch ?? matches[0]\n return clipSnippet(firstMatch?.value ?? item.text, q, maxLength)\n}\n\ninterface AiwgRankedEntry {\n item: AiwgFortemiRecord\n ordinal: number\n rank: number\n matches: AiwgIndexQueryMatch[]\n}\n\nfunction createRankedEntries(\n items: AiwgFortemiRecord[],\n q: string,\n options: AiwgIndexQueryOptions,\n ordinalBase = 0,\n): AiwgRankedEntry[] {\n const weights = { ...DEFAULT_QUERY_WEIGHTS, ...options.weights }\n return items.map((item, ordinal) => ({ item, ordinal: ordinalBase + ordinal, matches: queryMatches(item, q) }))\n .filter(({ item, matches }) => {\n if (q && matches.length === 0) return false\n if (options.types && !options.types.includes(item.type)) return false\n if (options.privacy && !options.privacy.includes(item.privacy.classification)) return false\n if (!includesAll(item.tags, options.tags)) return false\n if (!includesAll(item.concepts, options.concepts)) return false\n if (!matchesFacetFilters(item, options.facets)) return false\n if (options.relationshipTargetId && !(item.relationships ?? []).some((rel) => rel.target_id === options.relationshipTargetId)) {\n return false\n }\n return true\n })\n .map(({ item, ordinal, matches }) => ({\n item,\n ordinal,\n rank: rankMatches(matches, weights),\n matches,\n }))\n}\n\nfunction sortRankedEntries(entries: AiwgRankedEntry[], rank?: boolean): AiwgRankedEntry[] {\n return [...entries].sort((left, right) => {\n if (rank) return right.rank - left.rank || left.ordinal - right.ordinal\n return left.ordinal - right.ordinal\n })\n}\n\nfunction createQueryResultFromRankedEntries(\n entries: AiwgRankedEntry[],\n query: string,\n options: AiwgIndexQueryOptions,\n): AiwgIndexQueryResult {\n const ranked = sortRankedEntries(entries, options.rank)\n const offset = options.offset ?? 0\n const limit = options.limit ?? ranked.length\n const page = ranked.slice(offset, offset + limit)\n const result: AiwgIndexQueryResult = {\n items: page.map((entry) => entry.item),\n total: ranked.length,\n facets: getAiwgFortemiFacets(ranked.map((entry) => entry.item)),\n }\n if (options.rank || options.snippets || options.includeMatches) {\n const snippetLength = options.snippetLength ?? 160\n result.rankedItems = page.map((entry) => ({\n item: entry.item,\n rank: entry.rank,\n ...(options.snippets ? { snippet: createSnippet(entry.item, entry.matches, query, snippetLength) } : {}),\n ...(options.includeMatches ? { matches: entry.matches } : {}),\n }))\n }\n return result\n}\n\nexport function queryAiwgFortemiIndex(\n index: AiwgFortemiIndexExport,\n query = '',\n options: AiwgIndexQueryOptions = {},\n): AiwgIndexQueryResult {\n const q = query.trim().toLowerCase()\n return createQueryResultFromRankedEntries(createRankedEntries(index.items, q, options), q, options)\n}\n\ninterface AiwgChunkedIndexRuntime {\n manifest: AiwgFortemiChunkManifest\n loader: AiwgChunkedIndexLoader\n maxCachedParts: number\n partCache: Map<string, AiwgFortemiChunkPart>\n detailLoader?: AiwgChunkedIndexDetailLoader\n maxCachedDetails: number\n detailCache: Map<string, AiwgFortemiRecord>\n maxCachedMatches: number\n // query+filter+weights key -> the full filtered/ranked entry set for that\n // query (offset/limit/sort/snippets independent). LRU-ordered; bounded by\n // maxCachedMatches (total entries). Lets pagination reuse a single scan.\n matchCache: Map<string, AiwgRankedEntry[]>\n}\n\nfunction chunkPartCacheKey(part: AiwgFortemiChunkPartRef): string {\n return `${part.offset}:${part.href}`\n}\n\nfunction clampMaxCachedParts(value: number | undefined): number {\n if (!hasPositiveInteger(value)) return 3\n return value\n}\n\nfunction clampMaxCachedDetails(value: number | undefined): number {\n if (!hasPositiveInteger(value)) return 32\n return value\n}\n\nfunction clampMaxCachedMatches(value: number | undefined): number {\n if (!hasPositiveInteger(value)) return 5000\n return value\n}\n\n// Stable key over the inputs that determine the filtered/ranked entry SET and\n// each entry's rank value — but not offset/limit/sort/snippets, which only shape\n// the page projected from a cached set. Caller-stable option objects (same field\n// order each page) hit the cache; a reordered object simply misses (still correct).\nfunction matchSetCacheKey(q: string, options: AiwgIndexQueryOptions): string {\n return JSON.stringify({\n q,\n types: options.types ?? null,\n facets: options.facets ?? null,\n tags: options.tags ?? null,\n concepts: options.concepts ?? null,\n privacy: options.privacy ?? null,\n rel: options.relationshipTargetId ?? null,\n weights: { ...DEFAULT_QUERY_WEIGHTS, ...options.weights },\n })\n}\n\nfunction cacheMatchEntries(runtime: AiwgChunkedIndexRuntime, key: string, entries: AiwgRankedEntry[]): void {\n runtime.matchCache.delete(key)\n runtime.matchCache.set(key, entries)\n let total = 0\n for (const set of runtime.matchCache.values()) total += set.length\n // Evict oldest sets until within budget, but always keep the just-inserted set\n // so paging a large result still benefits from the single scan.\n while (total > runtime.maxCachedMatches && runtime.matchCache.size > 1) {\n const oldest = runtime.matchCache.keys().next().value\n if (oldest === undefined || oldest === key) break\n total -= runtime.matchCache.get(oldest)?.length ?? 0\n runtime.matchCache.delete(oldest)\n }\n}\n\nfunction isDirectChunkBrowse(query: string, options: AiwgIndexQueryOptions): boolean {\n return query.trim() === ''\n && !options.rank\n && !options.snippets\n && !options.includeMatches\n && !options.types\n && !options.facets\n && !options.tags\n && !options.concepts\n && !options.privacy\n && !options.relationshipTargetId\n}\n\nfunction getPartsForRange(\n manifest: AiwgFortemiChunkManifest,\n offset: number,\n limit: number,\n): AiwgFortemiChunkPartRef[] {\n const end = offset + limit\n return manifest.parts.filter((part) => part.count > 0 && part.offset < end && part.offset + part.count > offset)\n}\n\nasync function loadChunkPart(\n runtime: AiwgChunkedIndexRuntime,\n part: AiwgFortemiChunkPartRef,\n): Promise<{ part: AiwgFortemiChunkPart; fetched: boolean }> {\n const key = chunkPartCacheKey(part)\n const cached = runtime.partCache.get(key)\n if (cached) {\n runtime.partCache.delete(key)\n runtime.partCache.set(key, cached)\n return { part: cached, fetched: false }\n }\n\n const parsed = assertAiwgFortemiChunkPart(await runtime.loader(part, runtime.manifest), part, runtime.manifest)\n runtime.partCache.set(key, parsed)\n while (runtime.partCache.size > runtime.maxCachedParts) {\n const oldest = runtime.partCache.keys().next().value\n if (oldest === undefined) break\n runtime.partCache.delete(oldest)\n }\n return { part: parsed, fetched: true }\n}\n\nasync function getChunkRecord(runtime: AiwgChunkedIndexRuntime, id: string): Promise<AiwgFortemiRecord> {\n const cached = runtime.detailCache.get(id)\n if (cached) {\n runtime.detailCache.delete(id)\n runtime.detailCache.set(id, cached)\n return cached\n }\n // Whole-record parts already in cache: serve without a detail fetch.\n if (!runtime.manifest.projection) {\n for (const part of runtime.partCache.values()) {\n const found = part.items.find((item) => item.id === id)\n if (found) return found\n }\n }\n if (!runtime.detailLoader) {\n throw new Error('No detailLoader configured to resolve record ' + id)\n }\n const raw = await runtime.detailLoader(id, runtime.manifest)\n const record = assertAiwgFortemiIndexExport({\n schema_version: 'aiwg.fortemi.index.export.v1',\n generated_at: runtime.manifest.generated_at,\n source: runtime.manifest.source,\n items: [raw],\n }).items[0]\n if (record.id !== id) {\n throw new Error('Detail record id mismatch: expected ' + id + ', got ' + record.id)\n }\n runtime.detailCache.set(id, record)\n while (runtime.detailCache.size > runtime.maxCachedDetails) {\n const oldest = runtime.detailCache.keys().next().value\n if (oldest === undefined) break\n runtime.detailCache.delete(oldest)\n }\n return record\n}\n\nasync function queryChunkedAiwgFortemiIndex(\n runtime: AiwgChunkedIndexRuntime,\n query = '',\n options: AiwgChunkedIndexQueryOptions = {},\n): Promise<AiwgChunkedIndexQueryResult> {\n const q = query.trim().toLowerCase()\n let scannedParts = 0\n let fetchedParts = 0\n\n if (isDirectChunkBrowse(query, options)) {\n const offset = options.offset ?? 0\n const limit = options.limit ?? runtime.manifest.total\n const parts = getPartsForRange(runtime.manifest, offset, limit)\n const items: AiwgFortemiRecord[] = []\n for (const partRef of parts) {\n const loaded = await loadChunkPart(runtime, partRef)\n if (loaded.fetched) fetchedParts += 1\n scannedParts += 1\n options.onProgress?.({ phase: 'part', done: scannedParts, total: parts.length, href: partRef.href })\n const start = Math.max(0, offset - partRef.offset)\n const end = Math.min(loaded.part.items.length, offset + limit - partRef.offset)\n items.push(...loaded.part.items.slice(start, end))\n }\n return {\n items,\n total: runtime.manifest.total,\n facets: runtime.manifest.facets ?? {},\n manifestTotal: runtime.manifest.total,\n scannedParts,\n fetchedParts,\n complete: true,\n }\n }\n\n // Reuse the filtered/ranked entry set across pages of the same query: the\n // expensive part scan is offset/limit/sort/snippet independent. A hit projects\n // a new page from cached entries without touching parts (scanned/fetched = 0).\n const matchKey = matchSetCacheKey(q, options)\n const cached = runtime.matchCache.get(matchKey)\n if (cached) {\n runtime.matchCache.delete(matchKey)\n runtime.matchCache.set(matchKey, cached)\n return {\n ...createQueryResultFromRankedEntries(cached, q, options),\n manifestTotal: runtime.manifest.total,\n scannedParts: 0,\n fetchedParts: 0,\n complete: true,\n }\n }\n\n const entries: AiwgRankedEntry[] = []\n for (const partRef of runtime.manifest.parts) {\n const loaded = await loadChunkPart(runtime, partRef)\n if (loaded.fetched) fetchedParts += 1\n scannedParts += 1\n options.onProgress?.({ phase: 'part', done: scannedParts, total: runtime.manifest.parts.length, href: partRef.href })\n entries.push(...createRankedEntries(loaded.part.items, q, options, partRef.offset))\n options.onProgress?.({ phase: 'query', done: scannedParts, total: runtime.manifest.parts.length, href: partRef.href })\n }\n cacheMatchEntries(runtime, matchKey, entries)\n\n return {\n ...createQueryResultFromRankedEntries(entries, q, options),\n manifestTotal: runtime.manifest.total,\n scannedParts,\n fetchedParts,\n complete: true,\n }\n}\n\nexport function createAiwgReviewDecisionExport(\n // Only the export schema_version is needed — so this works in chunked mode\n // (where no whole index is loaded) by passing a minimal source. See #178.\n source: Pick<AiwgFortemiIndexExport, 'schema_version'>,\n decisions: AiwgReviewDecision[],\n generatedAt = new Date().toISOString(),\n): AiwgReviewDecisionExport {\n return {\n schema_version: 'aiwg.fortemi.review-decisions.v1',\n generated_at: generatedAt,\n source_export_schema_version: source.schema_version,\n decisions: [...decisions].sort((left, right) => left.item_id.localeCompare(right.item_id)),\n }\n}\n\nexport function createAiwgIndexController(initialIndex?: AiwgFortemiIndexExport): AiwgIndexController {\n let index: AiwgFortemiIndexExport | null = initialIndex ?? null\n let chunked: AiwgChunkedIndexRuntime | null = null\n let data: AiwgIndexQueryResult | null = null\n let error: Error | null = null\n let reviewDecisions: AiwgReviewDecision[] = []\n const listeners = new Set<AiwgIndexControllerListener>()\n\n const snapshot = (): AiwgIndexControllerSnapshot => ({\n index,\n chunked: chunked\n ? {\n manifest: chunked.manifest,\n cachedParts: chunked.partCache.size,\n maxCachedParts: chunked.maxCachedParts,\n }\n : null,\n data,\n error,\n reviewDecisions: [...reviewDecisions],\n })\n const notify = () => {\n const current = snapshot()\n for (const listener of listeners) listener(current)\n }\n const requireIndex = (): AiwgFortemiIndexExport => {\n if (!index) throw new Error('No AIWG index export loaded')\n return index\n }\n\n return {\n loadIndex(value: unknown): AiwgFortemiIndexExport {\n try {\n const parsed = assertAiwgFortemiIndexExport(value)\n index = parsed\n chunked = null\n data = null\n reviewDecisions = []\n error = null\n notify()\n return parsed\n } catch (err) {\n error = err instanceof Error ? err : new Error(String(err))\n notify()\n throw error\n }\n },\n loadChunkedIndex(\n manifest: unknown,\n loader: AiwgChunkedIndexLoader,\n options: AiwgChunkedIndexLoadOptions = {},\n ): AiwgFortemiChunkManifest {\n try {\n const parsed = assertAiwgFortemiChunkManifest(manifest)\n index = null\n chunked = {\n manifest: parsed,\n loader,\n maxCachedParts: clampMaxCachedParts(options.maxCachedParts),\n partCache: new Map(),\n detailLoader: options.detailLoader,\n maxCachedDetails: clampMaxCachedDetails(options.maxCachedDetails),\n detailCache: new Map(),\n maxCachedMatches: clampMaxCachedMatches(options.maxCachedMatches),\n matchCache: new Map(),\n }\n data = null\n reviewDecisions = []\n error = null\n notify()\n return parsed\n } catch (err) {\n error = err instanceof Error ? err : new Error(String(err))\n notify()\n throw error\n }\n },\n getIndex(): AiwgFortemiIndexExport | null {\n return index\n },\n getChunkedManifest(): AiwgFortemiChunkManifest | null {\n return chunked?.manifest ?? null\n },\n getSnapshot(): AiwgIndexControllerSnapshot {\n return snapshot()\n },\n query(query = '', options?: AiwgIndexQueryOptions): AiwgIndexQueryResult {\n const result = queryAiwgFortemiIndex(requireIndex(), query, options)\n data = result\n error = null\n notify()\n return result\n },\n async queryChunked(query = '', options?: AiwgChunkedIndexQueryOptions): Promise<AiwgChunkedIndexQueryResult> {\n if (!chunked) throw new Error('No AIWG chunked index manifest loaded')\n try {\n const result = await queryChunkedAiwgFortemiIndex(chunked, query, options)\n data = result\n error = null\n notify()\n return result\n } catch (err) {\n error = err instanceof Error ? err : new Error(String(err))\n notify()\n throw error\n }\n },\n async getRecord(id: string): Promise<AiwgFortemiRecord> {\n if (chunked) {\n try {\n return await getChunkRecord(chunked, id)\n } catch (err) {\n error = err instanceof Error ? err : new Error(String(err))\n notify()\n throw error\n }\n }\n const found = requireIndex().items.find((item) => item.id === id)\n if (!found) throw new Error('Record not found: ' + id)\n return found\n },\n clearChunkCache(): void {\n chunked?.partCache.clear()\n chunked?.detailCache.clear()\n chunked?.matchCache.clear()\n error = null\n notify()\n },\n toCommunityGraph(options?: AiwgIndexGraphOptions) {\n return aiwgFortemiIndexToCommunityGraph(requireIndex(), options)\n },\n setReviewDecision(input: AiwgReviewInput): AiwgReviewDecision {\n const decision: AiwgReviewDecision = {\n ...input,\n updated_at: new Date().toISOString(),\n }\n reviewDecisions = [\n ...reviewDecisions.filter((item) => item.item_id !== decision.item_id),\n decision,\n ].sort((left, right) => left.item_id.localeCompare(right.item_id))\n error = null\n notify()\n return decision\n },\n clearReviewDecision(itemId: string): void {\n reviewDecisions = reviewDecisions.filter((item) => item.item_id !== itemId)\n error = null\n notify()\n },\n createReviewDecisionExport(generatedAt?: string): AiwgReviewDecisionExport {\n // The review-decisions export only needs the export schema_version, not the\n // items — so it works in chunked mode by synthesizing a minimal source (#178).\n const source: Pick<AiwgFortemiIndexExport, 'schema_version'> | null =\n index ?? (chunked ? { schema_version: 'aiwg.fortemi.index.export.v1' } : null)\n if (!source) throw new Error('No AIWG index export or chunked manifest loaded')\n return createAiwgReviewDecisionExport(source, reviewDecisions, generatedAt)\n },\n subscribe(listener: AiwgIndexControllerListener): () => void {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n }\n}\n\nexport function aiwgFortemiIndexToCommunityGraph(\n index: AiwgFortemiIndexExport,\n options: AiwgIndexGraphOptions = {},\n) {\n const ids = new Set(index.items.map((item) => item.id))\n const relationshipWeights = options.relationshipWeights ?? {}\n const edgeCounts = new Map<string, { source: string; target: string; kind: string; weight: number }>()\n\n for (const item of index.items) {\n for (const relationship of item.relationships) {\n if (!ids.has(relationship.target_id) && !options.includeDanglingRelationships) continue\n const kind = relationship.type\n const baseWeight = relationshipWeights[kind] ?? 1\n const key = `${item.id}\\u0000${relationship.target_id}\\u0000${kind}`\n const existing = edgeCounts.get(key)\n if (existing) existing.weight += baseWeight\n else edgeCounts.set(key, { source: item.id, target: relationship.target_id, kind, weight: baseWeight })\n }\n }\n\n const communities = new Map<string, string[]>()\n for (const item of index.items) {\n const communityIds = communityIdsFor(item, options)\n for (const communityId of communityIds) {\n const nodes = communities.get(communityId) ?? []\n nodes.push(item.id)\n communities.set(communityId, nodes)\n }\n }\n\n return {\n nodes: index.items.map((item) => ({ id: item.id })),\n edges: Array.from(edgeCounts.values()).sort((left, right) => (\n left.source.localeCompare(right.source)\n || left.target.localeCompare(right.target)\n || left.kind.localeCompare(right.kind)\n )),\n communities: Array.from(communities.entries())\n .map(([id, nodes]) => ({ id, nodes: [...new Set(nodes)].sort() }))\n .sort((left, right) => left.id.localeCompare(right.id)),\n }\n}\n\nfunction communityIdsFor(item: AiwgFortemiRecord, options: AiwgIndexGraphOptions): string[] {\n if (options.communityFacet) {\n const values = item.facets[options.communityFacet] ?? []\n if (values.length > 0) return values.map((value) => `${options.communityFacet}:${value}`)\n }\n if (options.communityTagPrefix) {\n const prefix = options.communityTagPrefix\n const tags = item.tags.filter((tag) => tag.startsWith(prefix))\n if (tags.length > 0) return tags\n }\n if (item.concepts.length > 0) return item.concepts.map((concept) => `concept:${concept}`)\n return [`type:${item.type}`]\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/aiwg-index.ts"],"names":[],"mappings":"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","file":"aiwg-index.js","sourcesContent":["export type AiwgFortemiRecordType =\n | 'crm.contact'\n | 'crm.organization'\n | 'crm.event'\n | 'crm.interaction'\n | 'aiwg.artifact'\n | 'docs.page'\n\nexport type AiwgPrivacyClassification = 'private' | 'sanitized' | 'public'\nexport type AiwgProvenanceConfidence = 'source' | 'candidate' | 'reviewed' | 'rejected'\nexport type AiwgReviewAction = 'accept' | 'reject' | 'defer'\n\nexport interface AiwgFortemiRecordSource {\n path: string\n repo_relative_path: string\n locator: string\n}\n\nexport interface AiwgFortemiRelationship {\n type: string\n target_id: string\n source_path?: string\n label?: string\n confidence?: number\n privacy?: AiwgPrivacyClassification\n metadata?: Record<string, unknown>\n}\n\nexport interface AiwgFortemiProvenance {\n field: string\n source: string\n path: string\n confidence: AiwgProvenanceConfidence\n privacy: AiwgPrivacyClassification\n}\n\nexport type AiwgFortemiSkosRelationType = 'broader' | 'narrower' | 'related' | string\n\nexport interface AiwgFortemiSkosConcept {\n id: string\n prefLabel: string\n definition?: string\n scheme?: string\n notation?: string\n uri?: string\n altLabels?: string[]\n metadata?: Record<string, unknown>\n}\n\nexport interface AiwgFortemiSkosRelation {\n type: AiwgFortemiSkosRelationType\n source_id: string\n target_id: string\n source_path?: string\n metadata?: Record<string, unknown>\n}\n\nexport interface AiwgFortemiProvenanceEvent {\n id?: string\n activity: string\n agent?: string\n started_at?: string\n ended_at?: string\n source?: string\n path?: string\n confidence?: AiwgProvenanceConfidence\n privacy?: AiwgPrivacyClassification\n attributes?: Record<string, unknown>\n}\n\nexport interface AiwgFortemiRecord {\n schema_version: 'aiwg.fortemi.index.record.v1'\n id: string\n type: AiwgFortemiRecordType\n source: AiwgFortemiRecordSource\n title: string\n text: string\n facets: Record<string, string[]>\n tags: string[]\n concepts: string[]\n relationships: AiwgFortemiRelationship[]\n provenance: AiwgFortemiProvenance[]\n /** Optional rich SKOS metadata for static consumers that need labels/definitions without opening a shard. */\n skos_concepts?: AiwgFortemiSkosConcept[]\n /** Optional SKOS relationship edges among concepts referenced by this record. */\n skos_relations?: AiwgFortemiSkosRelation[]\n /** Optional W3C PROV-style activity chain for this record. */\n provenance_events?: AiwgFortemiProvenanceEvent[]\n privacy: {\n classification: AiwgPrivacyClassification\n pii: boolean\n }\n updated_at: string\n}\n\nexport interface AiwgFortemiIndexExport {\n schema_version: 'aiwg.fortemi.index.export.v1'\n generated_at: string\n source: {\n repo: string\n privacy: AiwgPrivacyClassification\n }\n items: AiwgFortemiRecord[]\n}\n\nexport interface AiwgFortemiChunkPartRef {\n href: string\n offset: number\n count: number\n}\n\n// Fields a scan part must retain for query/browse/rank/facet to work. The rest\n// (source, provenance, relationships, updated_at) are detail-only and may be\n// dropped from scan parts via `projection`, then resolved on demand by id.\nexport const AIWG_SCAN_REQUIRED_FIELDS: Array<keyof AiwgFortemiRecord> = [\n 'schema_version',\n 'id',\n 'type',\n 'title',\n 'text',\n 'facets',\n 'tags',\n 'concepts',\n 'privacy',\n]\n\n// A record as it appears in a scan part. With no manifest `projection`, this is a\n// full AiwgFortemiRecord. With a projection, detail-only fields are absent — read\n// them via the controller's getRecord(). Typed as the full record for ergonomics;\n// query/browse code guards the projectable fields.\nexport type AiwgFortemiProjectedRecord =\n Pick<AiwgFortemiRecord, 'schema_version' | 'id' | 'type' | 'title' | 'text' | 'facets' | 'tags' | 'concepts' | 'privacy'>\n & Partial<AiwgFortemiRecord>\n\n// How a record id is encoded into a detail filename/path segment.\n// - 'base64url': path-safe, single segment, no '%' — works on every static host,\n// including ids containing '/' (default for new builds; see #177).\n// - 'uri': encodeURIComponent — legacy. Breaks for ids containing '/' on static\n// servers that reject %2F (path-traversal protection → 404).\nexport type AiwgDetailIdEncoding = 'uri' | 'base64url'\n\n// How the controller resolves a full record by id when scan parts are projected.\nexport interface AiwgFortemiChunkDetailRef {\n // href template containing `{id}`, relative to the manifest base — e.g.\n // \"detail/{id}.json\". The `{id}` is encoded per `encoding` at substitution.\n href: string\n // id→segment encoding. Absent is treated as 'uri' for backward compatibility\n // with manifests built before #177; new builds default to 'base64url'.\n encoding?: AiwgDetailIdEncoding\n}\n\nexport interface AiwgFortemiChunkManifest {\n schema_version: 'aiwg.fortemi.index.chunk-manifest.v1'\n generated_at: string\n source: AiwgFortemiIndexExport['source']\n total: number\n part_size: number\n facets?: Record<string, Record<string, number>>\n // Field names present in scan-part items. Absent → scan parts carry whole records.\n // When set, must include AIWG_SCAN_REQUIRED_FIELDS.\n projection?: Array<keyof AiwgFortemiRecord>\n // Resolver for full records by id (used with `projection` to lazy-load detail).\n detail?: AiwgFortemiChunkDetailRef\n parts: AiwgFortemiChunkPartRef[]\n}\n\nexport interface AiwgFortemiChunkPart {\n schema_version: 'aiwg.fortemi.index.chunk.v1'\n manifest_schema_version: 'aiwg.fortemi.index.chunk-manifest.v1'\n offset: number\n items: AiwgFortemiRecord[]\n}\n\nexport interface AiwgIndexValidationResult {\n valid: boolean\n errors: string[]\n counts: Partial<Record<AiwgFortemiRecordType, number>>\n}\n\nexport interface AiwgChunkedIndexValidationResult {\n valid: boolean\n errors: string[]\n}\n\nexport interface AiwgIndexQueryOptions {\n types?: AiwgFortemiRecordType[]\n facets?: Record<string, string[]>\n tags?: string[]\n concepts?: string[]\n privacy?: AiwgPrivacyClassification[]\n relationshipTargetId?: string\n limit?: number\n offset?: number\n rank?: boolean\n snippets?: boolean\n snippetLength?: number\n weights?: Partial<AiwgIndexQueryWeights>\n includeMatches?: boolean\n}\n\nexport interface AiwgIndexQueryWeights {\n title: number\n text: number\n tag: number\n concept: number\n}\n\nexport interface AiwgIndexQueryMatch {\n field: 'title' | 'text' | 'tag' | 'concept'\n value: string\n}\n\nexport interface AiwgIndexQueryRankedItem {\n item: AiwgFortemiRecord\n rank: number\n snippet?: string\n matches?: AiwgIndexQueryMatch[]\n}\n\nexport interface AiwgIndexQueryResult {\n items: AiwgFortemiRecord[]\n total: number\n facets: Record<string, Record<string, number>>\n rankedItems?: AiwgIndexQueryRankedItem[]\n}\n\nexport type AiwgChunkedIndexLoader = (\n part: AiwgFortemiChunkPartRef,\n manifest: AiwgFortemiChunkManifest,\n) => Promise<unknown>\n\n// Resolves a full record by id (used with projected scan parts). Returns the\n// parsed record JSON; validated by the controller before use.\nexport type AiwgChunkedIndexDetailLoader = (\n id: string,\n manifest: AiwgFortemiChunkManifest,\n) => Promise<unknown>\n\nexport interface AiwgChunkedIndexLoadOptions {\n maxCachedParts?: number\n // Required to resolve detail for projected indexes via getRecord(); ignored otherwise.\n detailLoader?: AiwgChunkedIndexDetailLoader\n maxCachedDetails?: number\n // Bounds the filtered/ranked match-set cache used to page a query without\n // re-scanning every part. Counts total cached entries across all queries\n // (LRU-evicted). Defaults to 5000. The cache is keyed on query + filters +\n // weights, so paging the same query (varying only offset/limit/sort/snippets)\n // reuses the scan; see queryChunked.\n maxCachedMatches?: number\n}\n\nexport type AiwgChunkedIndexProgressPhase = 'part' | 'query'\n\nexport interface AiwgChunkedIndexProgress {\n phase: AiwgChunkedIndexProgressPhase\n done: number\n total: number\n href?: string\n}\n\nexport interface AiwgChunkedIndexQueryOptions extends AiwgIndexQueryOptions {\n onProgress?: (progress: AiwgChunkedIndexProgress) => void\n}\n\nexport interface AiwgChunkedIndexQueryResult extends AiwgIndexQueryResult {\n manifestTotal: number\n scannedParts: number\n fetchedParts: number\n complete: boolean\n}\n\nexport interface AiwgReviewDecision {\n item_id: string\n action: AiwgReviewAction\n reason?: string\n updated_at: string\n}\n\nexport interface AiwgReviewDecisionExport {\n schema_version: 'aiwg.fortemi.review-decisions.v1'\n generated_at: string\n source_export_schema_version: string\n decisions: AiwgReviewDecision[]\n}\n\nexport interface AiwgIndexGraphOptions {\n communityFacet?: string\n communityTagPrefix?: string\n relationshipWeights?: Record<string, number>\n includeDanglingRelationships?: boolean\n}\n\nexport interface AiwgReviewInput {\n item_id: string\n action: AiwgReviewAction\n reason?: string\n}\n\nexport interface AiwgIndexControllerSnapshot {\n index: AiwgFortemiIndexExport | null\n chunked: {\n manifest: AiwgFortemiChunkManifest\n cachedParts: number\n maxCachedParts: number\n } | null\n data: AiwgIndexQueryResult | null\n error: Error | null\n reviewDecisions: AiwgReviewDecision[]\n}\n\nexport type AiwgIndexControllerListener = (snapshot: AiwgIndexControllerSnapshot) => void\n\nexport interface AiwgIndexController {\n loadIndex(value: unknown): AiwgFortemiIndexExport\n loadChunkedIndex(\n manifest: unknown,\n loader: AiwgChunkedIndexLoader,\n options?: AiwgChunkedIndexLoadOptions,\n ): AiwgFortemiChunkManifest\n getIndex(): AiwgFortemiIndexExport | null\n getChunkedManifest(): AiwgFortemiChunkManifest | null\n getSnapshot(): AiwgIndexControllerSnapshot\n query(query?: string, options?: AiwgIndexQueryOptions): AiwgIndexQueryResult\n queryChunked(query?: string, options?: AiwgChunkedIndexQueryOptions): Promise<AiwgChunkedIndexQueryResult>\n // Resolve a full record by id. For a projected chunked index, fetches detail via\n // the detailLoader (bounded cache); for a whole-record index/parts, returns the\n // record from loaded data. Rejects if detail is unavailable.\n getRecord(id: string): Promise<AiwgFortemiRecord>\n clearChunkCache(): void\n toCommunityGraph(options?: AiwgIndexGraphOptions): ReturnType<typeof aiwgFortemiIndexToCommunityGraph>\n setReviewDecision(input: AiwgReviewInput): AiwgReviewDecision\n clearReviewDecision(itemId: string): void\n createReviewDecisionExport(generatedAt?: string): AiwgReviewDecisionExport\n subscribe(listener: AiwgIndexControllerListener): () => void\n}\n\nconst REQUIRED_RECORD_FIELDS: Array<keyof AiwgFortemiRecord> = [\n 'schema_version',\n 'id',\n 'type',\n 'source',\n 'title',\n 'text',\n 'facets',\n 'tags',\n 'concepts',\n 'relationships',\n 'provenance',\n 'privacy',\n 'updated_at',\n]\n\nconst VALID_TYPES = new Set<AiwgFortemiRecordType>([\n 'crm.contact',\n 'crm.organization',\n 'crm.event',\n 'crm.interaction',\n 'aiwg.artifact',\n 'docs.page',\n])\n\nconst DEFAULT_QUERY_WEIGHTS: AiwgIndexQueryWeights = {\n title: 4,\n tag: 3,\n concept: 2,\n text: 1,\n}\n\nfunction hasString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0\n}\n\nfunction pushFacet(counts: Record<string, Record<string, number>>, name: string, value: string) {\n counts[name] ??= {}\n counts[name][value] = (counts[name][value] ?? 0) + 1\n}\n\nfunction hasNonNegativeInteger(value: unknown): value is number {\n return Number.isInteger(value) && typeof value === 'number' && value >= 0\n}\n\nfunction hasPositiveInteger(value: unknown): value is number {\n return Number.isInteger(value) && typeof value === 'number' && value > 0\n}\n\nfunction isFacetCounts(value: unknown): value is Record<string, Record<string, number>> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false\n return Object.values(value).every((counts) => (\n !!counts\n && typeof counts === 'object'\n && !Array.isArray(counts)\n && Object.values(counts).every((count) => hasNonNegativeInteger(count))\n ))\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isOptionalStringArray(value: unknown): boolean {\n return value === undefined || (Array.isArray(value) && value.every((item) => typeof item === 'string'))\n}\n\nfunction validateOptionalRichMetadata(item: Partial<AiwgFortemiRecord>, index: number, errors: string[]): void {\n if (item.skos_concepts !== undefined) {\n if (!Array.isArray(item.skos_concepts)) {\n errors.push('items[' + index + '].skos_concepts must be an array when present')\n } else {\n for (const [conceptIndex, concept] of item.skos_concepts.entries()) {\n if (!hasString(concept.id)) errors.push('items[' + index + '].skos_concepts[' + conceptIndex + '].id is required')\n if (!hasString(concept.prefLabel)) errors.push('items[' + index + '].skos_concepts[' + conceptIndex + '].prefLabel is required')\n if (!isOptionalStringArray(concept.altLabels)) errors.push('items[' + index + '].skos_concepts[' + conceptIndex + '].altLabels must be a string array')\n if (concept.metadata !== undefined && !isPlainRecord(concept.metadata)) {\n errors.push('items[' + index + '].skos_concepts[' + conceptIndex + '].metadata must be an object')\n }\n }\n }\n }\n if (item.skos_relations !== undefined) {\n if (!Array.isArray(item.skos_relations)) {\n errors.push('items[' + index + '].skos_relations must be an array when present')\n } else {\n for (const [relationIndex, relation] of item.skos_relations.entries()) {\n if (!hasString(relation.type)) errors.push('items[' + index + '].skos_relations[' + relationIndex + '].type is required')\n if (!hasString(relation.source_id)) errors.push('items[' + index + '].skos_relations[' + relationIndex + '].source_id is required')\n if (!hasString(relation.target_id)) errors.push('items[' + index + '].skos_relations[' + relationIndex + '].target_id is required')\n if (relation.metadata !== undefined && !isPlainRecord(relation.metadata)) {\n errors.push('items[' + index + '].skos_relations[' + relationIndex + '].metadata must be an object')\n }\n }\n }\n }\n if (item.provenance_events !== undefined) {\n if (!Array.isArray(item.provenance_events)) {\n errors.push('items[' + index + '].provenance_events must be an array when present')\n } else {\n for (const [eventIndex, event] of item.provenance_events.entries()) {\n if (!hasString(event.activity)) errors.push('items[' + index + '].provenance_events[' + eventIndex + '].activity is required')\n if (event.attributes !== undefined && !isPlainRecord(event.attributes)) {\n errors.push('items[' + index + '].provenance_events[' + eventIndex + '].attributes must be an object')\n }\n }\n }\n }\n if (Array.isArray(item.relationships)) {\n for (const [relationshipIndex, relationship] of item.relationships.entries()) {\n if (relationship.metadata !== undefined && !isPlainRecord(relationship.metadata)) {\n errors.push('items[' + index + '].relationships[' + relationshipIndex + '].metadata must be an object')\n }\n }\n }\n}\n\nexport function validateAiwgFortemiIndexExport(value: unknown): AiwgIndexValidationResult {\n const errors: string[] = []\n const counts: Partial<Record<AiwgFortemiRecordType, number>> = {}\n const data = value as Partial<AiwgFortemiIndexExport>\n\n if (data?.schema_version !== 'aiwg.fortemi.index.export.v1') {\n errors.push('schema_version must be aiwg.fortemi.index.export.v1')\n }\n if (!hasString(data?.generated_at)) errors.push('generated_at is required')\n if (!hasString(data?.source?.repo)) errors.push('source.repo is required')\n if (!hasString(data?.source?.privacy)) errors.push('source.privacy is required')\n if (!Array.isArray(data?.items)) errors.push('items must be an array')\n\n const ids = new Set<string>()\n let previousId = ''\n for (const [index, item] of (data.items ?? []).entries()) {\n for (const field of REQUIRED_RECORD_FIELDS) {\n if (!(field in item)) errors.push('items[' + index + '].' + field + ' is required')\n }\n if (item.schema_version !== 'aiwg.fortemi.index.record.v1') {\n errors.push('items[' + index + '].schema_version must be aiwg.fortemi.index.record.v1')\n }\n if (!hasString(item.id)) errors.push('items[' + index + '].id is required')\n if (hasString(item.id) && ids.has(item.id)) errors.push('duplicate id: ' + item.id)\n if (hasString(item.id)) ids.add(item.id)\n if (previousId && hasString(item.id) && previousId.localeCompare(item.id) > 0) {\n errors.push('items must be sorted by id: ' + previousId + ' before ' + item.id)\n }\n if (hasString(item.id)) previousId = item.id\n if (!VALID_TYPES.has(item.type)) errors.push('items[' + index + '].type is invalid')\n else counts[item.type] = (counts[item.type] ?? 0) + 1\n if (!hasString(item.source?.path)) errors.push('items[' + index + '].source.path is required')\n if (!hasString(item.source?.repo_relative_path)) errors.push('items[' + index + '].source.repo_relative_path is required')\n if (!hasString(item.source?.locator)) errors.push('items[' + index + '].source.locator is required')\n if (!Array.isArray(item.tags)) errors.push('items[' + index + '].tags must be an array')\n if (!Array.isArray(item.concepts)) errors.push('items[' + index + '].concepts must be an array')\n if (!Array.isArray(item.relationships)) errors.push('items[' + index + '].relationships must be an array')\n if (!Array.isArray(item.provenance) || item.provenance.length === 0) {\n errors.push('items[' + index + '].provenance must be a non-empty array')\n }\n validateOptionalRichMetadata(item, index, errors)\n if (!item.privacy || typeof item.privacy.pii !== 'boolean' || !hasString(item.privacy.classification)) {\n errors.push('items[' + index + '].privacy requires classification and pii')\n }\n }\n\n return { valid: errors.length === 0, errors, counts }\n}\n\nexport function assertAiwgFortemiIndexExport(value: unknown): AiwgFortemiIndexExport {\n const result = validateAiwgFortemiIndexExport(value)\n if (!result.valid) {\n throw new Error('Invalid AIWG Fortemi index export:\\n' + result.errors.join('\\n'))\n }\n return value as AiwgFortemiIndexExport\n}\n\nexport function validateAiwgFortemiChunkManifest(value: unknown): AiwgChunkedIndexValidationResult {\n const errors: string[] = []\n const data = value as Partial<AiwgFortemiChunkManifest>\n\n if (data?.schema_version !== 'aiwg.fortemi.index.chunk-manifest.v1') {\n errors.push('schema_version must be aiwg.fortemi.index.chunk-manifest.v1')\n }\n if (!hasString(data?.generated_at)) errors.push('generated_at is required')\n if (!hasString(data?.source?.repo)) errors.push('source.repo is required')\n if (!hasString(data?.source?.privacy)) errors.push('source.privacy is required')\n if (!hasNonNegativeInteger(data?.total)) errors.push('total must be a non-negative integer')\n if (!hasPositiveInteger(data?.part_size)) errors.push('part_size must be a positive integer')\n if (data.facets !== undefined && !isFacetCounts(data.facets)) {\n errors.push('facets must be a nested string-to-number count object')\n }\n if (data.projection !== undefined) {\n if (!Array.isArray(data.projection) || !data.projection.every((field) => typeof field === 'string')) {\n errors.push('projection must be an array of field names')\n } else {\n const present = new Set(data.projection)\n for (const field of AIWG_SCAN_REQUIRED_FIELDS) {\n if (!present.has(field)) errors.push('projection must include scan-required field ' + field)\n }\n }\n }\n if (data.detail !== undefined) {\n if (!hasString(data.detail.href)) errors.push('detail.href is required')\n else if (!data.detail.href.includes('{id}')) errors.push('detail.href must contain the {id} placeholder')\n if (\n data.detail.encoding !== undefined &&\n data.detail.encoding !== 'uri' &&\n data.detail.encoding !== 'base64url'\n ) {\n errors.push(\"detail.encoding must be 'uri' or 'base64url'\")\n }\n }\n if (!Array.isArray(data?.parts)) errors.push('parts must be an array')\n\n let expectedOffset = 0\n const parts = Array.isArray(data?.parts) ? data.parts : []\n for (const [index, part] of parts.entries()) {\n if (!hasString(part.href)) errors.push('parts[' + index + '].href is required')\n if (!hasNonNegativeInteger(part.offset)) errors.push('parts[' + index + '].offset must be a non-negative integer')\n if (!hasNonNegativeInteger(part.count)) errors.push('parts[' + index + '].count must be a non-negative integer')\n if (hasNonNegativeInteger(part.offset) && part.offset !== expectedOffset) {\n errors.push('parts[' + index + '].offset must be ' + expectedOffset)\n }\n if (hasNonNegativeInteger(part.count)) expectedOffset += part.count\n }\n if (hasNonNegativeInteger(data?.total) && expectedOffset !== data.total) {\n errors.push('parts counts must add up to total')\n }\n\n return { valid: errors.length === 0, errors }\n}\n\nexport function assertAiwgFortemiChunkManifest(value: unknown): AiwgFortemiChunkManifest {\n const result = validateAiwgFortemiChunkManifest(value)\n if (!result.valid) {\n throw new Error('Invalid AIWG Fortemi chunk manifest:\\n' + result.errors.join('\\n'))\n }\n return value as AiwgFortemiChunkManifest\n}\n\n// Validate projected (slim) scan-part items: scan-required fields only, ids unique + sorted.\nfunction validateProjectedRecords(items: Array<Partial<AiwgFortemiRecord>>): string[] {\n const errors: string[] = []\n const ids = new Set<string>()\n let previousId = ''\n for (const [index, item] of items.entries()) {\n if (item.schema_version !== 'aiwg.fortemi.index.record.v1') {\n errors.push('items[' + index + '].schema_version must be aiwg.fortemi.index.record.v1')\n }\n if (!hasString(item.id)) errors.push('items[' + index + '].id is required')\n if (hasString(item.id) && ids.has(item.id)) errors.push('duplicate id: ' + item.id)\n if (hasString(item.id)) ids.add(item.id)\n if (previousId && hasString(item.id) && previousId.localeCompare(item.id) > 0) {\n errors.push('items must be sorted by id: ' + previousId + ' before ' + item.id)\n }\n if (hasString(item.id)) previousId = item.id\n if (!item.type || !VALID_TYPES.has(item.type)) errors.push('items[' + index + '].type is invalid')\n if (!hasString(item.title)) errors.push('items[' + index + '].title is required')\n if (typeof item.text !== 'string') errors.push('items[' + index + '].text is required')\n if (!item.facets || typeof item.facets !== 'object' || Array.isArray(item.facets)) {\n errors.push('items[' + index + '].facets must be an object')\n }\n if (!Array.isArray(item.tags)) errors.push('items[' + index + '].tags must be an array')\n if (!Array.isArray(item.concepts)) errors.push('items[' + index + '].concepts must be an array')\n if (!item.privacy || !hasString(item.privacy.classification)) {\n errors.push('items[' + index + '].privacy.classification is required')\n }\n }\n return errors\n}\n\nexport function validateAiwgFortemiChunkPart(\n value: unknown,\n partRef?: AiwgFortemiChunkPartRef,\n manifest?: AiwgFortemiChunkManifest,\n): AiwgChunkedIndexValidationResult {\n const errors: string[] = []\n const data = value as Partial<AiwgFortemiChunkPart>\n\n if (data?.schema_version !== 'aiwg.fortemi.index.chunk.v1') {\n errors.push('schema_version must be aiwg.fortemi.index.chunk.v1')\n }\n if (data?.manifest_schema_version !== 'aiwg.fortemi.index.chunk-manifest.v1') {\n errors.push('manifest_schema_version must be aiwg.fortemi.index.chunk-manifest.v1')\n }\n if (!hasNonNegativeInteger(data?.offset)) errors.push('offset must be a non-negative integer')\n if (!Array.isArray(data?.items)) errors.push('items must be an array')\n\n if (partRef && hasNonNegativeInteger(data?.offset) && data.offset !== partRef.offset) {\n errors.push('offset must match manifest part offset ' + partRef.offset)\n }\n if (partRef && Array.isArray(data?.items) && data.items.length !== partRef.count) {\n errors.push('items length must match manifest part count ' + partRef.count)\n }\n\n if (Array.isArray(data?.items)) {\n if (manifest?.projection) {\n errors.push(...validateProjectedRecords(data.items).map((error) => 'items.' + error))\n } else {\n const validation = validateAiwgFortemiIndexExport({\n schema_version: 'aiwg.fortemi.index.export.v1',\n generated_at: manifest?.generated_at ?? '1970-01-01T00:00:00.000Z',\n source: manifest?.source ?? { repo: 'chunk', privacy: 'public' },\n items: data.items,\n })\n errors.push(...validation.errors.map((error) => 'items.' + error))\n }\n }\n\n return { valid: errors.length === 0, errors }\n}\n\nexport function assertAiwgFortemiChunkPart(\n value: unknown,\n partRef?: AiwgFortemiChunkPartRef,\n manifest?: AiwgFortemiChunkManifest,\n): AiwgFortemiChunkPart {\n const result = validateAiwgFortemiChunkPart(value, partRef, manifest)\n if (!result.valid) {\n throw new Error('Invalid AIWG Fortemi chunk part:\\n' + result.errors.join('\\n'))\n }\n return value as AiwgFortemiChunkPart\n}\n\nexport function createAiwgFetchChunkLoader(baseUrl?: string | URL): AiwgChunkedIndexLoader {\n return async (part) => {\n const href = baseUrl ? new URL(part.href, baseUrl).toString() : part.href\n const response = await fetch(href)\n if (!response.ok) throw new Error('Failed to fetch AIWG index chunk ' + href + ': ' + response.status)\n return response.json()\n }\n}\n\n// Encode a record id into a single, path-safe detail filename segment.\n// - 'base64url' (default): UTF-8 → base64url (no '+', '/', '=', '%'). Safe for ids\n// containing '/' on static hosts that reject %2F (#177).\n// - 'uri': encodeURIComponent (legacy).\nexport function encodeAiwgDetailId(id: string, encoding: AiwgDetailIdEncoding = 'base64url'): string {\n if (encoding === 'uri') return encodeURIComponent(id)\n const bytes = new TextEncoder().encode(id)\n let binary = ''\n for (const byte of bytes) binary += String.fromCharCode(byte)\n // btoa is available in browsers and Node ≥16.\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n// Resolve a manifest detail.href template for a given id, honoring detail.encoding\n// (absent → 'uri' for backward compatibility). The writer and the loader both go\n// through this so emitted filenames and fetched paths always agree.\nexport function aiwgDetailHrefForId(detail: AiwgFortemiChunkDetailRef, id: string): string {\n return detail.href.replace('{id}', encodeAiwgDetailId(id, detail.encoding ?? 'uri'))\n}\n\n// Detail loader for projected indexes: resolves the manifest's detail.href {id}\n// template (encoded per detail.encoding) against baseUrl and fetches the full record.\nexport function createAiwgFetchDetailLoader(baseUrl?: string | URL): AiwgChunkedIndexDetailLoader {\n return async (id, manifest) => {\n if (!manifest.detail?.href) throw new Error('Manifest has no detail.href for record resolution')\n const relative = aiwgDetailHrefForId(manifest.detail, id)\n const href = baseUrl ? new URL(relative, baseUrl).toString() : relative\n const response = await fetch(href)\n if (!response.ok) throw new Error('Failed to fetch AIWG index detail ' + href + ': ' + response.status)\n return response.json()\n }\n}\n\nexport function getAiwgFortemiFacets(items: AiwgFortemiRecord[]): Record<string, Record<string, number>> {\n const result: Record<string, Record<string, number>> = {}\n for (const item of items) {\n pushFacet(result, 'type', item.type)\n pushFacet(result, 'privacy', item.privacy.classification)\n for (const tag of item.tags) pushFacet(result, 'tag', tag)\n for (const concept of item.concepts) pushFacet(result, 'concept', concept)\n for (const [name, values] of Object.entries(item.facets)) {\n for (const value of values) pushFacet(result, name, value)\n }\n }\n return result\n}\n\nexport interface AiwgChunkedIndexBuildOptions {\n partSize?: number\n // When set, scan parts carry only these fields; full records go to `details`.\n projection?: Array<keyof AiwgFortemiRecord>\n // Detail href template (with {id}); defaults to \"detail/{id}.json\" when projecting.\n detailHref?: string\n // id→filename encoding for detail files; defaults to 'base64url' (path-safe,\n // works for ids containing '/'; see #177).\n idEncoding?: AiwgDetailIdEncoding\n generatedAt?: string\n}\n\nexport interface AiwgChunkedIndexBuildResult {\n manifest: AiwgFortemiChunkManifest\n parts: Array<{ href: string; part: AiwgFortemiChunkPart }>\n // Empty unless projecting. Each entry carries the full record plus the resolved,\n // encoding-correct `href` to host it at — write the record to that path so the\n // detail loader (which uses the same encoding) can fetch it back.\n details: Array<{ id: string; href: string; record: AiwgFortemiRecord }>\n}\n\n// Pure builder (no I/O): project an index export into the chunked manifest + parts\n// (+ detail records when projecting). The caller writes the returned objects to disk.\n// Manifest facets are computed from the full records, so global counts are exact even\n// when scan parts are slim.\nexport function buildAiwgChunkedIndex(\n index: AiwgFortemiIndexExport,\n options: AiwgChunkedIndexBuildOptions = {},\n): AiwgChunkedIndexBuildResult {\n const partSize = hasPositiveInteger(options.partSize) ? options.partSize : 500\n const projection = options.projection\n const idEncoding = options.idEncoding ?? 'base64url'\n const detailHref = options.detailHref ?? 'detail/{id}.json'\n const items = index.items\n const pad = (value: number): string => String(value).padStart(4, '0')\n const project = (record: AiwgFortemiRecord): AiwgFortemiRecord => {\n if (!projection) return record\n const slim: Record<string, unknown> = {}\n for (const field of projection) slim[field] = record[field]\n return slim as unknown as AiwgFortemiRecord\n }\n\n const parts: Array<{ href: string; part: AiwgFortemiChunkPart }> = []\n const partRefs: AiwgFortemiChunkPartRef[] = []\n for (let offset = 0, partIndex = 0; offset < items.length; offset += partSize, partIndex += 1) {\n const slice = items.slice(offset, offset + partSize)\n const href = 'part-' + pad(partIndex) + '.json'\n parts.push({\n href,\n part: {\n schema_version: 'aiwg.fortemi.index.chunk.v1',\n manifest_schema_version: 'aiwg.fortemi.index.chunk-manifest.v1',\n offset,\n items: slice.map(project),\n },\n })\n partRefs.push({ href, offset, count: slice.length })\n }\n\n const manifest: AiwgFortemiChunkManifest = {\n schema_version: 'aiwg.fortemi.index.chunk-manifest.v1',\n generated_at: options.generatedAt ?? index.generated_at,\n source: index.source,\n total: items.length,\n part_size: partSize,\n facets: getAiwgFortemiFacets(items),\n parts: partRefs,\n ...(projection ? { projection, detail: { href: detailHref, encoding: idEncoding } } : {}),\n }\n\n return {\n manifest,\n parts,\n details: projection\n ? items.map((record) => ({\n id: record.id,\n href: aiwgDetailHrefForId({ href: detailHref, encoding: idEncoding }, record.id),\n record,\n }))\n : [],\n }\n}\n\nfunction includesAll(actual: string[], expected: string[] | undefined): boolean {\n if (!expected || expected.length === 0) return true\n const actualSet = new Set(actual)\n return expected.every((value) => actualSet.has(value))\n}\n\nfunction matchesFacetFilters(item: AiwgFortemiRecord, filters: Record<string, string[]> | undefined): boolean {\n if (!filters) return true\n return Object.entries(filters).every(([name, expected]) => includesAll(item.facets[name] ?? [], expected))\n}\n\nfunction queryMatches(item: AiwgFortemiRecord, q: string): AiwgIndexQueryMatch[] {\n if (!q) return []\n const matches: AiwgIndexQueryMatch[] = []\n if (item.title.toLowerCase().includes(q)) matches.push({ field: 'title', value: item.title })\n if (item.text.toLowerCase().includes(q)) matches.push({ field: 'text', value: item.text })\n for (const tag of item.tags) {\n if (tag.toLowerCase().includes(q)) matches.push({ field: 'tag', value: tag })\n }\n for (const concept of item.concepts) {\n if (concept.toLowerCase().includes(q)) matches.push({ field: 'concept', value: concept })\n }\n return matches\n}\n\nfunction rankMatches(matches: AiwgIndexQueryMatch[], weights: AiwgIndexQueryWeights): number {\n return matches.reduce((total, match) => total + weights[match.field], 0)\n}\n\nfunction clipSnippet(value: string, q: string, maxLength: number): string {\n const normalizedLength = Math.max(20, maxLength)\n if (!value) return ''\n if (!q) return value.length > normalizedLength ? `${value.slice(0, normalizedLength).trimEnd()}...` : value\n\n const lower = value.toLowerCase()\n const index = lower.indexOf(q)\n if (index < 0) return value.length > normalizedLength ? `${value.slice(0, normalizedLength).trimEnd()}...` : value\n\n const context = Math.max(0, Math.floor((normalizedLength - q.length) / 2))\n const start = Math.max(0, index - context)\n const end = Math.min(value.length, start + normalizedLength)\n const prefix = start > 0 ? '...' : ''\n const suffix = end < value.length ? '...' : ''\n return `${prefix}${value.slice(start, end).trim()}${suffix}`\n}\n\nfunction createSnippet(item: AiwgFortemiRecord, matches: AiwgIndexQueryMatch[], q: string, maxLength: number): string {\n const textMatch = matches.find((match) => match.field === 'text')\n const titleMatch = matches.find((match) => match.field === 'title')\n const firstMatch = textMatch ?? titleMatch ?? matches[0]\n return clipSnippet(firstMatch?.value ?? item.text, q, maxLength)\n}\n\ninterface AiwgRankedEntry {\n item: AiwgFortemiRecord\n ordinal: number\n rank: number\n matches: AiwgIndexQueryMatch[]\n}\n\nfunction createRankedEntries(\n items: AiwgFortemiRecord[],\n q: string,\n options: AiwgIndexQueryOptions,\n ordinalBase = 0,\n): AiwgRankedEntry[] {\n const weights = { ...DEFAULT_QUERY_WEIGHTS, ...options.weights }\n return items.map((item, ordinal) => ({ item, ordinal: ordinalBase + ordinal, matches: queryMatches(item, q) }))\n .filter(({ item, matches }) => {\n if (q && matches.length === 0) return false\n if (options.types && !options.types.includes(item.type)) return false\n if (options.privacy && !options.privacy.includes(item.privacy.classification)) return false\n if (!includesAll(item.tags, options.tags)) return false\n if (!includesAll(item.concepts, options.concepts)) return false\n if (!matchesFacetFilters(item, options.facets)) return false\n if (options.relationshipTargetId && !(item.relationships ?? []).some((rel) => rel.target_id === options.relationshipTargetId)) {\n return false\n }\n return true\n })\n .map(({ item, ordinal, matches }) => ({\n item,\n ordinal,\n rank: rankMatches(matches, weights),\n matches,\n }))\n}\n\nfunction sortRankedEntries(entries: AiwgRankedEntry[], rank?: boolean): AiwgRankedEntry[] {\n return [...entries].sort((left, right) => {\n if (rank) return right.rank - left.rank || left.ordinal - right.ordinal\n return left.ordinal - right.ordinal\n })\n}\n\nfunction createQueryResultFromRankedEntries(\n entries: AiwgRankedEntry[],\n query: string,\n options: AiwgIndexQueryOptions,\n): AiwgIndexQueryResult {\n const ranked = sortRankedEntries(entries, options.rank)\n const offset = options.offset ?? 0\n const limit = options.limit ?? ranked.length\n const page = ranked.slice(offset, offset + limit)\n const result: AiwgIndexQueryResult = {\n items: page.map((entry) => entry.item),\n total: ranked.length,\n facets: getAiwgFortemiFacets(ranked.map((entry) => entry.item)),\n }\n if (options.rank || options.snippets || options.includeMatches) {\n const snippetLength = options.snippetLength ?? 160\n result.rankedItems = page.map((entry) => ({\n item: entry.item,\n rank: entry.rank,\n ...(options.snippets ? { snippet: createSnippet(entry.item, entry.matches, query, snippetLength) } : {}),\n ...(options.includeMatches ? { matches: entry.matches } : {}),\n }))\n }\n return result\n}\n\nexport function queryAiwgFortemiIndex(\n index: AiwgFortemiIndexExport,\n query = '',\n options: AiwgIndexQueryOptions = {},\n): AiwgIndexQueryResult {\n const q = query.trim().toLowerCase()\n return createQueryResultFromRankedEntries(createRankedEntries(index.items, q, options), q, options)\n}\n\ninterface AiwgChunkedIndexRuntime {\n manifest: AiwgFortemiChunkManifest\n loader: AiwgChunkedIndexLoader\n maxCachedParts: number\n partCache: Map<string, AiwgFortemiChunkPart>\n detailLoader?: AiwgChunkedIndexDetailLoader\n maxCachedDetails: number\n detailCache: Map<string, AiwgFortemiRecord>\n maxCachedMatches: number\n // query+filter+weights key -> the full filtered/ranked entry set for that\n // query (offset/limit/sort/snippets independent). LRU-ordered; bounded by\n // maxCachedMatches (total entries). Lets pagination reuse a single scan.\n matchCache: Map<string, AiwgRankedEntry[]>\n}\n\nfunction chunkPartCacheKey(part: AiwgFortemiChunkPartRef): string {\n return `${part.offset}:${part.href}`\n}\n\nfunction clampMaxCachedParts(value: number | undefined): number {\n if (!hasPositiveInteger(value)) return 3\n return value\n}\n\nfunction clampMaxCachedDetails(value: number | undefined): number {\n if (!hasPositiveInteger(value)) return 32\n return value\n}\n\nfunction clampMaxCachedMatches(value: number | undefined): number {\n if (!hasPositiveInteger(value)) return 5000\n return value\n}\n\n// Stable key over the inputs that determine the filtered/ranked entry SET and\n// each entry's rank value — but not offset/limit/sort/snippets, which only shape\n// the page projected from a cached set. Caller-stable option objects (same field\n// order each page) hit the cache; a reordered object simply misses (still correct).\nfunction matchSetCacheKey(q: string, options: AiwgIndexQueryOptions): string {\n return JSON.stringify({\n q,\n types: options.types ?? null,\n facets: options.facets ?? null,\n tags: options.tags ?? null,\n concepts: options.concepts ?? null,\n privacy: options.privacy ?? null,\n rel: options.relationshipTargetId ?? null,\n weights: { ...DEFAULT_QUERY_WEIGHTS, ...options.weights },\n })\n}\n\nfunction cacheMatchEntries(runtime: AiwgChunkedIndexRuntime, key: string, entries: AiwgRankedEntry[]): void {\n runtime.matchCache.delete(key)\n runtime.matchCache.set(key, entries)\n let total = 0\n for (const set of runtime.matchCache.values()) total += set.length\n // Evict oldest sets until within budget, but always keep the just-inserted set\n // so paging a large result still benefits from the single scan.\n while (total > runtime.maxCachedMatches && runtime.matchCache.size > 1) {\n const oldest = runtime.matchCache.keys().next().value\n if (oldest === undefined || oldest === key) break\n total -= runtime.matchCache.get(oldest)?.length ?? 0\n runtime.matchCache.delete(oldest)\n }\n}\n\nfunction isDirectChunkBrowse(query: string, options: AiwgIndexQueryOptions): boolean {\n return query.trim() === ''\n && !options.rank\n && !options.snippets\n && !options.includeMatches\n && !options.types\n && !options.facets\n && !options.tags\n && !options.concepts\n && !options.privacy\n && !options.relationshipTargetId\n}\n\nfunction getPartsForRange(\n manifest: AiwgFortemiChunkManifest,\n offset: number,\n limit: number,\n): AiwgFortemiChunkPartRef[] {\n const end = offset + limit\n return manifest.parts.filter((part) => part.count > 0 && part.offset < end && part.offset + part.count > offset)\n}\n\nasync function loadChunkPart(\n runtime: AiwgChunkedIndexRuntime,\n part: AiwgFortemiChunkPartRef,\n): Promise<{ part: AiwgFortemiChunkPart; fetched: boolean }> {\n const key = chunkPartCacheKey(part)\n const cached = runtime.partCache.get(key)\n if (cached) {\n runtime.partCache.delete(key)\n runtime.partCache.set(key, cached)\n return { part: cached, fetched: false }\n }\n\n const parsed = assertAiwgFortemiChunkPart(await runtime.loader(part, runtime.manifest), part, runtime.manifest)\n runtime.partCache.set(key, parsed)\n while (runtime.partCache.size > runtime.maxCachedParts) {\n const oldest = runtime.partCache.keys().next().value\n if (oldest === undefined) break\n runtime.partCache.delete(oldest)\n }\n return { part: parsed, fetched: true }\n}\n\nasync function getChunkRecord(runtime: AiwgChunkedIndexRuntime, id: string): Promise<AiwgFortemiRecord> {\n const cached = runtime.detailCache.get(id)\n if (cached) {\n runtime.detailCache.delete(id)\n runtime.detailCache.set(id, cached)\n return cached\n }\n // Whole-record parts already in cache: serve without a detail fetch.\n if (!runtime.manifest.projection) {\n for (const part of runtime.partCache.values()) {\n const found = part.items.find((item) => item.id === id)\n if (found) return found\n }\n }\n if (!runtime.detailLoader) {\n throw new Error('No detailLoader configured to resolve record ' + id)\n }\n const raw = await runtime.detailLoader(id, runtime.manifest)\n const record = assertAiwgFortemiIndexExport({\n schema_version: 'aiwg.fortemi.index.export.v1',\n generated_at: runtime.manifest.generated_at,\n source: runtime.manifest.source,\n items: [raw],\n }).items[0]\n if (record.id !== id) {\n throw new Error('Detail record id mismatch: expected ' + id + ', got ' + record.id)\n }\n runtime.detailCache.set(id, record)\n while (runtime.detailCache.size > runtime.maxCachedDetails) {\n const oldest = runtime.detailCache.keys().next().value\n if (oldest === undefined) break\n runtime.detailCache.delete(oldest)\n }\n return record\n}\n\nasync function queryChunkedAiwgFortemiIndex(\n runtime: AiwgChunkedIndexRuntime,\n query = '',\n options: AiwgChunkedIndexQueryOptions = {},\n): Promise<AiwgChunkedIndexQueryResult> {\n const q = query.trim().toLowerCase()\n let scannedParts = 0\n let fetchedParts = 0\n\n if (isDirectChunkBrowse(query, options)) {\n const offset = options.offset ?? 0\n const limit = options.limit ?? runtime.manifest.total\n const parts = getPartsForRange(runtime.manifest, offset, limit)\n const items: AiwgFortemiRecord[] = []\n for (const partRef of parts) {\n const loaded = await loadChunkPart(runtime, partRef)\n if (loaded.fetched) fetchedParts += 1\n scannedParts += 1\n options.onProgress?.({ phase: 'part', done: scannedParts, total: parts.length, href: partRef.href })\n const start = Math.max(0, offset - partRef.offset)\n const end = Math.min(loaded.part.items.length, offset + limit - partRef.offset)\n items.push(...loaded.part.items.slice(start, end))\n }\n return {\n items,\n total: runtime.manifest.total,\n facets: runtime.manifest.facets ?? {},\n manifestTotal: runtime.manifest.total,\n scannedParts,\n fetchedParts,\n complete: true,\n }\n }\n\n // Reuse the filtered/ranked entry set across pages of the same query: the\n // expensive part scan is offset/limit/sort/snippet independent. A hit projects\n // a new page from cached entries without touching parts (scanned/fetched = 0).\n const matchKey = matchSetCacheKey(q, options)\n const cached = runtime.matchCache.get(matchKey)\n if (cached) {\n runtime.matchCache.delete(matchKey)\n runtime.matchCache.set(matchKey, cached)\n return {\n ...createQueryResultFromRankedEntries(cached, q, options),\n manifestTotal: runtime.manifest.total,\n scannedParts: 0,\n fetchedParts: 0,\n complete: true,\n }\n }\n\n const entries: AiwgRankedEntry[] = []\n for (const partRef of runtime.manifest.parts) {\n const loaded = await loadChunkPart(runtime, partRef)\n if (loaded.fetched) fetchedParts += 1\n scannedParts += 1\n options.onProgress?.({ phase: 'part', done: scannedParts, total: runtime.manifest.parts.length, href: partRef.href })\n entries.push(...createRankedEntries(loaded.part.items, q, options, partRef.offset))\n options.onProgress?.({ phase: 'query', done: scannedParts, total: runtime.manifest.parts.length, href: partRef.href })\n }\n cacheMatchEntries(runtime, matchKey, entries)\n\n return {\n ...createQueryResultFromRankedEntries(entries, q, options),\n manifestTotal: runtime.manifest.total,\n scannedParts,\n fetchedParts,\n complete: true,\n }\n}\n\nexport function createAiwgReviewDecisionExport(\n // Only the export schema_version is needed — so this works in chunked mode\n // (where no whole index is loaded) by passing a minimal source. See #178.\n source: Pick<AiwgFortemiIndexExport, 'schema_version'>,\n decisions: AiwgReviewDecision[],\n generatedAt = new Date().toISOString(),\n): AiwgReviewDecisionExport {\n return {\n schema_version: 'aiwg.fortemi.review-decisions.v1',\n generated_at: generatedAt,\n source_export_schema_version: source.schema_version,\n decisions: [...decisions].sort((left, right) => left.item_id.localeCompare(right.item_id)),\n }\n}\n\nexport function createAiwgIndexController(initialIndex?: AiwgFortemiIndexExport): AiwgIndexController {\n let index: AiwgFortemiIndexExport | null = initialIndex ?? null\n let chunked: AiwgChunkedIndexRuntime | null = null\n let data: AiwgIndexQueryResult | null = null\n let error: Error | null = null\n let reviewDecisions: AiwgReviewDecision[] = []\n const listeners = new Set<AiwgIndexControllerListener>()\n\n const snapshot = (): AiwgIndexControllerSnapshot => ({\n index,\n chunked: chunked\n ? {\n manifest: chunked.manifest,\n cachedParts: chunked.partCache.size,\n maxCachedParts: chunked.maxCachedParts,\n }\n : null,\n data,\n error,\n reviewDecisions: [...reviewDecisions],\n })\n const notify = () => {\n const current = snapshot()\n for (const listener of listeners) listener(current)\n }\n const requireIndex = (): AiwgFortemiIndexExport => {\n if (!index) throw new Error('No AIWG index export loaded')\n return index\n }\n\n return {\n loadIndex(value: unknown): AiwgFortemiIndexExport {\n try {\n const parsed = assertAiwgFortemiIndexExport(value)\n index = parsed\n chunked = null\n data = null\n reviewDecisions = []\n error = null\n notify()\n return parsed\n } catch (err) {\n error = err instanceof Error ? err : new Error(String(err))\n notify()\n throw error\n }\n },\n loadChunkedIndex(\n manifest: unknown,\n loader: AiwgChunkedIndexLoader,\n options: AiwgChunkedIndexLoadOptions = {},\n ): AiwgFortemiChunkManifest {\n try {\n const parsed = assertAiwgFortemiChunkManifest(manifest)\n index = null\n chunked = {\n manifest: parsed,\n loader,\n maxCachedParts: clampMaxCachedParts(options.maxCachedParts),\n partCache: new Map(),\n detailLoader: options.detailLoader,\n maxCachedDetails: clampMaxCachedDetails(options.maxCachedDetails),\n detailCache: new Map(),\n maxCachedMatches: clampMaxCachedMatches(options.maxCachedMatches),\n matchCache: new Map(),\n }\n data = null\n reviewDecisions = []\n error = null\n notify()\n return parsed\n } catch (err) {\n error = err instanceof Error ? err : new Error(String(err))\n notify()\n throw error\n }\n },\n getIndex(): AiwgFortemiIndexExport | null {\n return index\n },\n getChunkedManifest(): AiwgFortemiChunkManifest | null {\n return chunked?.manifest ?? null\n },\n getSnapshot(): AiwgIndexControllerSnapshot {\n return snapshot()\n },\n query(query = '', options?: AiwgIndexQueryOptions): AiwgIndexQueryResult {\n const result = queryAiwgFortemiIndex(requireIndex(), query, options)\n data = result\n error = null\n notify()\n return result\n },\n async queryChunked(query = '', options?: AiwgChunkedIndexQueryOptions): Promise<AiwgChunkedIndexQueryResult> {\n if (!chunked) throw new Error('No AIWG chunked index manifest loaded')\n try {\n const result = await queryChunkedAiwgFortemiIndex(chunked, query, options)\n data = result\n error = null\n notify()\n return result\n } catch (err) {\n error = err instanceof Error ? err : new Error(String(err))\n notify()\n throw error\n }\n },\n async getRecord(id: string): Promise<AiwgFortemiRecord> {\n if (chunked) {\n try {\n return await getChunkRecord(chunked, id)\n } catch (err) {\n error = err instanceof Error ? err : new Error(String(err))\n notify()\n throw error\n }\n }\n const found = requireIndex().items.find((item) => item.id === id)\n if (!found) throw new Error('Record not found: ' + id)\n return found\n },\n clearChunkCache(): void {\n chunked?.partCache.clear()\n chunked?.detailCache.clear()\n chunked?.matchCache.clear()\n error = null\n notify()\n },\n toCommunityGraph(options?: AiwgIndexGraphOptions) {\n return aiwgFortemiIndexToCommunityGraph(requireIndex(), options)\n },\n setReviewDecision(input: AiwgReviewInput): AiwgReviewDecision {\n const decision: AiwgReviewDecision = {\n ...input,\n updated_at: new Date().toISOString(),\n }\n reviewDecisions = [\n ...reviewDecisions.filter((item) => item.item_id !== decision.item_id),\n decision,\n ].sort((left, right) => left.item_id.localeCompare(right.item_id))\n error = null\n notify()\n return decision\n },\n clearReviewDecision(itemId: string): void {\n reviewDecisions = reviewDecisions.filter((item) => item.item_id !== itemId)\n error = null\n notify()\n },\n createReviewDecisionExport(generatedAt?: string): AiwgReviewDecisionExport {\n // The review-decisions export only needs the export schema_version, not the\n // items — so it works in chunked mode by synthesizing a minimal source (#178).\n const source: Pick<AiwgFortemiIndexExport, 'schema_version'> | null =\n index ?? (chunked ? { schema_version: 'aiwg.fortemi.index.export.v1' } : null)\n if (!source) throw new Error('No AIWG index export or chunked manifest loaded')\n return createAiwgReviewDecisionExport(source, reviewDecisions, generatedAt)\n },\n subscribe(listener: AiwgIndexControllerListener): () => void {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n }\n}\n\nexport function aiwgFortemiIndexToCommunityGraph(\n index: AiwgFortemiIndexExport,\n options: AiwgIndexGraphOptions = {},\n) {\n const ids = new Set(index.items.map((item) => item.id))\n const relationshipWeights = options.relationshipWeights ?? {}\n const edgeCounts = new Map<string, { source: string; target: string; kind: string; weight: number }>()\n\n for (const item of index.items) {\n for (const relationship of item.relationships) {\n if (!ids.has(relationship.target_id) && !options.includeDanglingRelationships) continue\n const kind = relationship.type\n const baseWeight = relationshipWeights[kind] ?? 1\n const key = `${item.id}\\u0000${relationship.target_id}\\u0000${kind}`\n const existing = edgeCounts.get(key)\n if (existing) existing.weight += baseWeight\n else edgeCounts.set(key, { source: item.id, target: relationship.target_id, kind, weight: baseWeight })\n }\n }\n\n const communities = new Map<string, string[]>()\n for (const item of index.items) {\n const communityIds = communityIdsFor(item, options)\n for (const communityId of communityIds) {\n const nodes = communities.get(communityId) ?? []\n nodes.push(item.id)\n communities.set(communityId, nodes)\n }\n }\n\n return {\n nodes: index.items.map((item) => ({ id: item.id })),\n edges: Array.from(edgeCounts.values()).sort((left, right) => (\n left.source.localeCompare(right.source)\n || left.target.localeCompare(right.target)\n || left.kind.localeCompare(right.kind)\n )),\n communities: Array.from(communities.entries())\n .map(([id, nodes]) => ({ id, nodes: [...new Set(nodes)].sort() }))\n .sort((left, right) => left.id.localeCompare(right.id)),\n }\n}\n\nfunction communityIdsFor(item: AiwgFortemiRecord, options: AiwgIndexGraphOptions): string[] {\n if (options.communityFacet) {\n const values = item.facets[options.communityFacet] ?? []\n if (values.length > 0) return values.map((value) => `${options.communityFacet}:${value}`)\n }\n if (options.communityTagPrefix) {\n const prefix = options.communityTagPrefix\n const tags = item.tags.filter((tag) => tag.startsWith(prefix))\n if (tags.length > 0) return tags\n }\n if (item.concepts.length > 0) return item.concepts.map((concept) => `concept:${concept}`)\n return [`type:${item.type}`]\n}\n"]}
|