@sanity/ailf 4.1.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/config/package-surface.ts +37 -0
  2. package/config/preflight-scoring.ts +26 -0
  3. package/dist/_vendor/ailf-core/artifact-registry.d.ts +1 -1
  4. package/dist/_vendor/ailf-core/artifact-registry.js +47 -0
  5. package/dist/_vendor/ailf-core/config-helpers.d.ts +35 -0
  6. package/dist/_vendor/ailf-core/config-helpers.js +67 -0
  7. package/dist/_vendor/ailf-core/index.d.ts +1 -1
  8. package/dist/_vendor/ailf-core/index.js +1 -1
  9. package/dist/_vendor/ailf-core/ports/context.d.ts +18 -0
  10. package/dist/_vendor/ailf-core/ports/doc-fetcher.d.ts +30 -0
  11. package/dist/_vendor/ailf-core/ports/index.d.ts +3 -1
  12. package/dist/_vendor/ailf-core/ports/index.js +1 -0
  13. package/dist/_vendor/ailf-core/ports/mode-handler.d.ts +23 -0
  14. package/dist/_vendor/ailf-core/ports/package-surface-resolver.d.ts +71 -0
  15. package/dist/_vendor/ailf-core/ports/package-surface-resolver.js +36 -0
  16. package/dist/_vendor/ailf-core/schemas/eval-config.d.ts +6 -0
  17. package/dist/_vendor/ailf-core/schemas/eval-config.js +14 -0
  18. package/dist/_vendor/ailf-core/schemas/index.d.ts +1 -0
  19. package/dist/_vendor/ailf-core/schemas/index.js +1 -0
  20. package/dist/_vendor/ailf-core/schemas/symbol-preflight-report.d.ts +51 -0
  21. package/dist/_vendor/ailf-core/schemas/symbol-preflight-report.js +57 -0
  22. package/dist/_vendor/ailf-core/types/generalized-task.d.ts +20 -3
  23. package/dist/_vendor/ailf-core/types/index.d.ts +13 -1
  24. package/dist/_vendor/ailf-core/types/index.js +1 -0
  25. package/dist/_vendor/ailf-core/types/package-surface.d.ts +36 -0
  26. package/dist/_vendor/ailf-core/types/package-surface.js +13 -0
  27. package/dist/_vendor/ailf-core/types/preflight-scoring.d.ts +52 -0
  28. package/dist/_vendor/ailf-core/types/preflight-scoring.js +18 -0
  29. package/dist/_vendor/ailf-core/types/repo-config.d.ts +14 -0
  30. package/dist/_vendor/ailf-core/types/symbol-preflight-report.d.ts +66 -0
  31. package/dist/_vendor/ailf-core/types/symbol-preflight-report.js +25 -0
  32. package/dist/adapters/config-sources/file-config-adapter.js +1 -0
  33. package/dist/adapters/doc-fetchers/sanity-doc-fetcher.d.ts +25 -5
  34. package/dist/adapters/doc-fetchers/sanity-doc-fetcher.js +276 -95
  35. package/dist/adapters/index.d.ts +1 -0
  36. package/dist/adapters/index.js +1 -0
  37. package/dist/adapters/package-surface/dts-package-surface.d.ts +46 -0
  38. package/dist/adapters/package-surface/dts-package-surface.js +173 -0
  39. package/dist/adapters/package-surface/in-memory-package-surface.d.ts +15 -0
  40. package/dist/adapters/package-surface/in-memory-package-surface.js +28 -0
  41. package/dist/adapters/package-surface/index.d.ts +9 -0
  42. package/dist/adapters/package-surface/index.js +8 -0
  43. package/dist/adapters/package-surface/parse-dts-exports.d.ts +31 -0
  44. package/dist/adapters/package-surface/parse-dts-exports.js +54 -0
  45. package/dist/adapters/task-sources/repo-schemas.d.ts +22 -0
  46. package/dist/adapters/task-sources/repo-schemas.js +93 -1
  47. package/dist/adapters/task-sources/repo-task-source.js +11 -2
  48. package/dist/commands/pipeline-action.d.ts +2 -0
  49. package/dist/commands/pipeline-action.js +12 -0
  50. package/dist/commands/remote-pipeline.js +9 -2
  51. package/dist/commands/remote-results.d.ts +12 -1
  52. package/dist/commands/remote-results.js +25 -5
  53. package/dist/commands/validate-tasks.js +8 -2
  54. package/dist/composition-root.js +9 -0
  55. package/dist/config/package-surface.ts +37 -0
  56. package/dist/config/preflight-scoring.ts +26 -0
  57. package/dist/index.d.ts +2 -2
  58. package/dist/index.js +1 -1
  59. package/dist/orchestration/build-app-context.js +1 -0
  60. package/dist/orchestration/pipeline-orchestrator.d.ts +19 -1
  61. package/dist/orchestration/pipeline-orchestrator.js +38 -0
  62. package/dist/orchestration/steps/calculate-scores-step.js +11 -0
  63. package/dist/orchestration/steps/generate-configs-step.js +16 -1
  64. package/dist/orchestration/steps/run-eval-step.js +27 -0
  65. package/dist/pipeline/calculate-scores.d.ts +66 -5
  66. package/dist/pipeline/calculate-scores.js +141 -27
  67. package/dist/pipeline/compiler/index.d.ts +1 -1
  68. package/dist/pipeline/compiler/index.js +1 -1
  69. package/dist/pipeline/compiler/literacy-bridge.d.ts +9 -0
  70. package/dist/pipeline/compiler/literacy-bridge.js +2 -0
  71. package/dist/pipeline/compiler/mode-handlers/__fixtures__/agent-harness-example-tasks.js +0 -12
  72. package/dist/pipeline/compiler/mode-handlers/__fixtures__/knowledge-probe-example-tasks.js +0 -12
  73. package/dist/pipeline/compiler/mode-handlers/literacy/assertions.d.ts +1 -1
  74. package/dist/pipeline/compiler/mode-handlers/literacy/assertions.js +31 -4
  75. package/dist/pipeline/compiler/mode-handlers/literacy/compiler.js +190 -6
  76. package/dist/pipeline/compiler/mode-handlers/literacy/index.js +2 -0
  77. package/dist/pipeline/compiler/mode-handlers/literacy/types.d.ts +17 -2
  78. package/dist/pipeline/compiler/rubric-resolution.d.ts +17 -1
  79. package/dist/pipeline/compiler/rubric-resolution.js +78 -2
  80. package/dist/pipeline/compiler/scoring-bridge.d.ts +49 -2
  81. package/dist/pipeline/compiler/scoring-bridge.js +104 -10
  82. package/dist/pipeline/eval-fingerprint.d.ts +9 -0
  83. package/dist/pipeline/eval-fingerprint.js +7 -1
  84. package/dist/pipeline/preflight/compute-preflight.d.ts +67 -0
  85. package/dist/pipeline/preflight/compute-preflight.js +118 -0
  86. package/dist/pipeline/preflight/emit-symbol-preflight.d.ts +51 -0
  87. package/dist/pipeline/preflight/emit-symbol-preflight.js +102 -0
  88. package/dist/pipeline/preflight/load-package-surface.d.ts +14 -0
  89. package/dist/pipeline/preflight/load-package-surface.js +19 -0
  90. package/dist/pipeline/preflight/load-preflight-context.d.ts +13 -0
  91. package/dist/pipeline/preflight/load-preflight-context.js +25 -0
  92. package/dist/pipeline/preflight/load-preflight-scoring.d.ts +12 -0
  93. package/dist/pipeline/preflight/load-preflight-scoring.js +17 -0
  94. package/dist/pipeline/preflight/parse-imports.d.ts +62 -0
  95. package/dist/pipeline/preflight/parse-imports.js +125 -0
  96. package/dist/report-store.d.ts +8 -0
  97. package/dist/report-store.js +55 -6
  98. package/dist/sanity/document-renderers.d.ts +106 -0
  99. package/dist/sanity/document-renderers.js +307 -0
  100. package/dist/sanity/queries.d.ts +32 -11
  101. package/dist/sanity/queries.js +78 -0
  102. package/dist/sanity/symbol-index.d.ts +98 -0
  103. package/dist/sanity/symbol-index.js +615 -0
  104. package/dist/tasks/knowledge-probe/define-type-api.task.ts +2 -6
  105. package/dist/tasks/knowledge-probe/groq-projections.task.ts +0 -5
  106. package/dist/tasks/literacy/content-lake.task.ts +4 -10
  107. package/dist/tasks/literacy/frameworks.task.ts +2 -8
  108. package/dist/tasks/literacy/functions.task.ts +1 -4
  109. package/dist/tasks/literacy/groq.task.ts +3 -12
  110. package/dist/tasks/literacy/image-handling.task.ts +1 -4
  111. package/dist/tasks/literacy/nextjs-live.task.ts +1 -4
  112. package/dist/tasks/literacy/portable-text.task.ts +2 -8
  113. package/dist/tasks/literacy/studio-setup.task.ts +2 -8
  114. package/dist/tasks/literacy/visual-editing.task.ts +2 -8
  115. package/package.json +2 -1
  116. package/tasks/knowledge-probe/define-type-api.task.ts +2 -6
  117. package/tasks/knowledge-probe/groq-projections.task.ts +0 -5
  118. package/tasks/literacy/content-lake.task.ts +4 -10
  119. package/tasks/literacy/frameworks.task.ts +2 -8
  120. package/tasks/literacy/functions.task.ts +1 -4
  121. package/tasks/literacy/groq.task.ts +3 -12
  122. package/tasks/literacy/image-handling.task.ts +1 -4
  123. package/tasks/literacy/nextjs-live.task.ts +1 -4
  124. package/tasks/literacy/portable-text.task.ts +2 -8
  125. package/tasks/literacy/studio-setup.task.ts +2 -8
  126. package/tasks/literacy/visual-editing.task.ts +2 -8
@@ -0,0 +1,17 @@
1
+ /**
2
+ * load-preflight-scoring — read the W0198 preflight scoring config
3
+ * (`config/preflight-scoring.ts`) authored via `definePreflightScoring()`.
4
+ *
5
+ * Returns `undefined` when the file is absent so callers fall back to
6
+ * `DEFAULT_PREFLIGHT_CODE_CORRECTNESS_WEIGHT`. The eval package itself
7
+ * ships a config so the live pipeline always finds one; the optional
8
+ * return path exists for downstream / external callers that may not
9
+ * have authored one yet.
10
+ */
11
+ import { tryLoadConfigFile } from "../compiler/config-loader.js";
12
+ export async function loadPreflightScoring(rootDir) {
13
+ const result = tryLoadConfigFile("preflight-scoring", rootDir);
14
+ if (!result)
15
+ return undefined;
16
+ return result.data;
17
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * parse-imports — pure function that extracts every `import` declaration
3
+ * from a candidate code block as a flat list of per-binding entries.
4
+ *
5
+ * Output shape is intentionally flat: the W0198 preflight checks each
6
+ * `(source, imported)` pair against the resolved package surface, so a
7
+ * flat list is the natural input. Multi-binding declarations
8
+ * (`import { a, b as c } from "pkg"`) produce one entry per binding;
9
+ * default + named combos (`import def, { a } from "pkg"`) likewise.
10
+ *
11
+ * Implementation: delegates to `oxc-parser`'s `staticImports` view, which
12
+ * already decomposes each import statement into entries with explicit
13
+ * `importName` / `localName` / `isType` fields. The TS-aware grammar
14
+ * means dynamic `import(...)`, `import.meta`, and malformed statements
15
+ * are all handled by the parser itself — we just translate the entries
16
+ * into our `CandidateImportBinding` shape.
17
+ *
18
+ * Recognized grammar (handled by oxc-parser):
19
+ * - `import { a, b as c } from "pkg"`
20
+ * - `import def from "pkg"`
21
+ * - `import * as ns from "pkg"`
22
+ * - `import def, { a } from "pkg"` and `import def, * as ns from "pkg"`
23
+ * - `import type { ... } from "pkg"` and `import { type a, b } from "pkg"`
24
+ * - `import "pkg"` (side-effect; surfaced as a single `side-effect` entry)
25
+ * - Multi-line variants of all of the above.
26
+ *
27
+ * Out of scope (intentionally — both regex and oxc-parser ignore these):
28
+ * - Dynamic `import("pkg")` — runtime, not statically resolvable here.
29
+ * - `export { a } from "pkg"` re-exports from candidate code.
30
+ * - TypeScript `import = require()` and `import("...").Type` ambient
31
+ * references — neither pattern shows up in the App SDK / Studio
32
+ * candidate corpus the preflight grades against.
33
+ */
34
+ export type CandidateImportKind = "named" | "default" | "namespace" | "side-effect";
35
+ export interface CandidateImportBinding {
36
+ /** Source specifier as written by the candidate (e.g. `"@sanity/sdk-react"`). */
37
+ source: string;
38
+ /** Which import-clause shape this binding came from. */
39
+ kind: CandidateImportKind;
40
+ /**
41
+ * Name to look up against the package surface:
42
+ * - `kind: "named"` — the imported identifier.
43
+ * - `kind: "default"` — the literal string `"default"`.
44
+ * - `kind: "namespace"` — the literal string `"*"`.
45
+ * - `kind: "side-effect"` — empty string (no binding).
46
+ */
47
+ imported: string;
48
+ /** Local alias used in the candidate's body. Same as `imported` when no alias. */
49
+ local: string;
50
+ /**
51
+ * Whether this binding is type-only — either the whole declaration was
52
+ * `import type`, or this specifier was prefixed with `type`
53
+ * (`import { type X, Y } from "pkg"`).
54
+ */
55
+ isType: boolean;
56
+ /**
57
+ * 1-based line number where the import declaration starts in the
58
+ * source. Useful for surfacing findings back to a reviewer.
59
+ */
60
+ line: number;
61
+ }
62
+ export declare function parseImports(src: string): CandidateImportBinding[];
@@ -0,0 +1,125 @@
1
+ /**
2
+ * parse-imports — pure function that extracts every `import` declaration
3
+ * from a candidate code block as a flat list of per-binding entries.
4
+ *
5
+ * Output shape is intentionally flat: the W0198 preflight checks each
6
+ * `(source, imported)` pair against the resolved package surface, so a
7
+ * flat list is the natural input. Multi-binding declarations
8
+ * (`import { a, b as c } from "pkg"`) produce one entry per binding;
9
+ * default + named combos (`import def, { a } from "pkg"`) likewise.
10
+ *
11
+ * Implementation: delegates to `oxc-parser`'s `staticImports` view, which
12
+ * already decomposes each import statement into entries with explicit
13
+ * `importName` / `localName` / `isType` fields. The TS-aware grammar
14
+ * means dynamic `import(...)`, `import.meta`, and malformed statements
15
+ * are all handled by the parser itself — we just translate the entries
16
+ * into our `CandidateImportBinding` shape.
17
+ *
18
+ * Recognized grammar (handled by oxc-parser):
19
+ * - `import { a, b as c } from "pkg"`
20
+ * - `import def from "pkg"`
21
+ * - `import * as ns from "pkg"`
22
+ * - `import def, { a } from "pkg"` and `import def, * as ns from "pkg"`
23
+ * - `import type { ... } from "pkg"` and `import { type a, b } from "pkg"`
24
+ * - `import "pkg"` (side-effect; surfaced as a single `side-effect` entry)
25
+ * - Multi-line variants of all of the above.
26
+ *
27
+ * Out of scope (intentionally — both regex and oxc-parser ignore these):
28
+ * - Dynamic `import("pkg")` — runtime, not statically resolvable here.
29
+ * - `export { a } from "pkg"` re-exports from candidate code.
30
+ * - TypeScript `import = require()` and `import("...").Type` ambient
31
+ * references — neither pattern shows up in the App SDK / Studio
32
+ * candidate corpus the preflight grades against.
33
+ */
34
+ import { parseSync } from "oxc-parser";
35
+ export function parseImports(src) {
36
+ // Use the `.tsx` filename hint so the parser tolerates JSX in candidate
37
+ // code (App SDK literacy tasks frequently include JSX in their answers).
38
+ const result = parseSync("input.tsx", src, { lang: "tsx" });
39
+ const lineStarts = computeLineStarts(src);
40
+ const offsetToLine = (offset) => binarySearchLine(lineStarts, offset) + 1;
41
+ const out = [];
42
+ for (const imp of result.module.staticImports) {
43
+ const source = imp.moduleRequest.value;
44
+ // The parser recovers from malformed specifiers (e.g. backtick-quoted
45
+ // module requests) by emitting an empty source; the W0198 preflight
46
+ // can't do anything useful with that, so drop those entries.
47
+ if (!source)
48
+ continue;
49
+ const line = offsetToLine(imp.start);
50
+ if (imp.entries.length === 0) {
51
+ // Side-effect form: `import "pkg"`.
52
+ out.push({
53
+ source,
54
+ kind: "side-effect",
55
+ imported: "",
56
+ local: "",
57
+ isType: false,
58
+ line,
59
+ });
60
+ continue;
61
+ }
62
+ for (const entry of imp.entries) {
63
+ const local = entry.localName.value;
64
+ const isType = entry.isType;
65
+ switch (entry.importName.kind) {
66
+ case "Name":
67
+ out.push({
68
+ source,
69
+ kind: "named",
70
+ imported: entry.importName.name ?? local,
71
+ local,
72
+ isType,
73
+ line,
74
+ });
75
+ break;
76
+ case "Default":
77
+ out.push({
78
+ source,
79
+ kind: "default",
80
+ imported: "default",
81
+ local,
82
+ isType,
83
+ line,
84
+ });
85
+ break;
86
+ case "NamespaceObject":
87
+ out.push({
88
+ source,
89
+ kind: "namespace",
90
+ imported: "*",
91
+ local,
92
+ isType,
93
+ line,
94
+ });
95
+ break;
96
+ }
97
+ }
98
+ }
99
+ return out;
100
+ }
101
+ // ---------------------------------------------------------------------------
102
+ // Line-number helpers — oxc-parser returns byte offsets; the W0198
103
+ // preflight surfaces 1-based line numbers in findings so reviewers can
104
+ // jump straight to the citing line.
105
+ // ---------------------------------------------------------------------------
106
+ function computeLineStarts(src) {
107
+ const offsets = [0];
108
+ for (let i = 0; i < src.length; i++) {
109
+ if (src[i] === "\n")
110
+ offsets.push(i + 1);
111
+ }
112
+ return offsets;
113
+ }
114
+ function binarySearchLine(offsets, target) {
115
+ let lo = 0;
116
+ let hi = offsets.length - 1;
117
+ while (lo < hi) {
118
+ const mid = (lo + hi + 1) >>> 1;
119
+ if (offsets[mid] <= target)
120
+ lo = mid;
121
+ else
122
+ hi = mid - 1;
123
+ }
124
+ return lo;
125
+ }
@@ -65,6 +65,10 @@ export declare class ReportStore {
65
65
  * matching `evalFingerprint`. Used by the pipeline to skip the expensive
66
66
  * eval step when identical inputs have already been evaluated.
67
67
  *
68
+ * Advisory lookup: a `ReportSchemaValidationError` from a corrupt prior
69
+ * doc is logged + counted, then null is returned so the current eval
70
+ * proceeds. Use `read(id)` when callers ask for a specific document by id.
71
+ *
68
72
  * @returns The cached report, or null if no match or on error
69
73
  * @see docs/design-docs/content-lake-eval-caching.md
70
74
  */
@@ -78,6 +82,10 @@ export declare class ReportStore {
78
82
  * "Comparable" means: same evaluation mode + same source name.
79
83
  * More granular matching (areas, models) can be added as needed.
80
84
  *
85
+ * Advisory lookup: see `findByFingerprint` — a malformed prior baseline
86
+ * is logged + counted and null is returned so the current run still
87
+ * publishes its report.
88
+ *
81
89
  * @see docs/design-docs/report-store/architecture.md — Auto-comparison
82
90
  */
83
91
  findComparableBaseline(query: LineageQuery): Promise<null | Report>;
@@ -119,6 +119,10 @@ export class ReportStore {
119
119
  * matching `evalFingerprint`. Used by the pipeline to skip the expensive
120
120
  * eval step when identical inputs have already been evaluated.
121
121
  *
122
+ * Advisory lookup: a `ReportSchemaValidationError` from a corrupt prior
123
+ * doc is logged + counted, then null is returned so the current eval
124
+ * proceeds. Use `read(id)` when callers ask for a specific document by id.
125
+ *
122
126
  * @returns The cached report, or null if no match or on error
123
127
  * @see docs/design-docs/content-lake-eval-caching.md
124
128
  */
@@ -131,9 +135,19 @@ export class ReportStore {
131
135
  return doc ? toReport(doc) : null;
132
136
  }
133
137
  catch (error) {
134
- // W0191: schema-validation errors are bugs, not outages surface them.
135
- if (error instanceof ReportSchemaValidationError)
136
- throw error;
138
+ // Advisory lookup a single corrupt prior doc must not break the
139
+ // current eval. Log loudly + emit a counter so ops can alert, and
140
+ // return null so the caller treats it as "no comparable cache hit".
141
+ // Direct read(id) keeps the rethrow behavior because the caller asked
142
+ // for that specific document and silent-null would mask the bug.
143
+ if (error instanceof ReportSchemaValidationError) {
144
+ logAdvisoryQuerySchemaFailure({
145
+ query: "findByFingerprint",
146
+ context: { fingerprint },
147
+ error,
148
+ });
149
+ return null;
150
+ }
137
151
  console.warn(` ⚠️ Failed to query cached report by fingerprint: ${error instanceof Error ? error.message : String(error)}`);
138
152
  return null;
139
153
  }
@@ -147,6 +161,10 @@ export class ReportStore {
147
161
  * "Comparable" means: same evaluation mode + same source name.
148
162
  * More granular matching (areas, models) can be added as needed.
149
163
  *
164
+ * Advisory lookup: see `findByFingerprint` — a malformed prior baseline
165
+ * is logged + counted and null is returned so the current run still
166
+ * publishes its report.
167
+ *
150
168
  * @see docs/design-docs/report-store/architecture.md — Auto-comparison
151
169
  */
152
170
  async findComparableBaseline(query) {
@@ -170,9 +188,21 @@ export class ReportStore {
170
188
  return doc ? toReport(doc) : null;
171
189
  }
172
190
  catch (error) {
173
- // W0191: schema-validation errors are bugs, not outages surface them.
174
- if (error instanceof ReportSchemaValidationError)
175
- throw error;
191
+ // Advisory lookup see findByFingerprint for rationale. A malformed
192
+ // prior baseline returns null + counter so the current run still
193
+ // publishes; direct read(id) preserves the rethrow.
194
+ if (error instanceof ReportSchemaValidationError) {
195
+ logAdvisoryQuerySchemaFailure({
196
+ query: "findComparableBaseline",
197
+ context: {
198
+ mode: query.mode,
199
+ sourceName: query.source?.name,
200
+ before: query.before,
201
+ },
202
+ error,
203
+ });
204
+ return null;
205
+ }
176
206
  console.warn(` ⚠️ Failed to query comparable baseline: ${error instanceof Error ? error.message : String(error)}`);
177
207
  return null;
178
208
  }
@@ -299,6 +329,25 @@ export class ReportSchemaValidationError extends Error {
299
329
  this.name = "ReportSchemaValidationError";
300
330
  }
301
331
  }
332
+ /**
333
+ * Stable log marker for log-aggregator counters. Operators alert on the
334
+ * count of `[report-store.advisory] schema_validation_error` lines per
335
+ * window; the trailing JSON carries enough context (which advisory query,
336
+ * what filter values, error message) to find the offending document
337
+ * without spelunking through GROQ.
338
+ *
339
+ * Emitted via console.error rather than console.warn so it surfaces in
340
+ * the same severity tier as a real failure even though we're swallowing
341
+ * it for the current run.
342
+ */
343
+ function logAdvisoryQuerySchemaFailure(input) {
344
+ const payload = {
345
+ query: input.query,
346
+ context: input.context,
347
+ error: input.error.message,
348
+ };
349
+ console.error(`[report-store.advisory] schema_validation_error ${JSON.stringify(payload)}`);
350
+ }
302
351
  export function toSanityReportDoc(report) {
303
352
  const comparison = report.comparison
304
353
  ? stripComparisonBulk(report.comparison)
@@ -0,0 +1,106 @@
1
+ /**
2
+ * document-renderers.ts
3
+ *
4
+ * Renderer registry that turns a Sanity document into both:
5
+ *
6
+ * - Markdown content for inclusion in a literacy task's grader/candidate
7
+ * context (existing surface, used by the doc fetcher).
8
+ * - A symbol-reference index for the W0197 grader-context pathway —
9
+ * a flat list of identifiers the doc legitimizes, with provenance.
10
+ * The grader prefers this over the rendered markdown when available
11
+ * (smaller, deterministic, harder for the grader's prior to override).
12
+ *
13
+ * Both surfaces dispatch through the same registry. Articles and
14
+ * typesReference docs have hand-written renderers; everything else falls
15
+ * through to the default walker. This keeps "what to do with a document
16
+ * of type X" a single decision point regardless of whether the doc was
17
+ * looked up by slug, path, perspective, or id.
18
+ *
19
+ * Two tiers of fidelity (rendered output):
20
+ *
21
+ * 1. Registered renderers (high fidelity) — `article`, `typesReference`.
22
+ * Hand-written for the document shapes we care about most.
23
+ * 2. Default renderer (best effort) — walks the doc, flattens portable-text
24
+ * fields, surfaces top-level scalars, follows references one level deep,
25
+ * skips framework-internal fields. Lets pinning a `marketingPage`,
26
+ * `glossaryEntry`, etc. work without AILF code changes.
27
+ *
28
+ * Adding a new high-fidelity renderer: implement a `DocumentRenderer`
29
+ * (both `render` and `extractSymbols`) and register it in
30
+ * `BUILT_IN_RENDERERS` keyed by `_type`.
31
+ */
32
+ import { type SymbolIndex } from "./symbol-index.js";
33
+ /**
34
+ * A Sanity document plus any references we've already resolved for it.
35
+ * The resolver fetches the doc once and may include common deref payloads
36
+ * (e.g. `latestVersion->{...}` for typesReference) so renderers don't need
37
+ * to issue additional client.fetch calls themselves.
38
+ */
39
+ export interface DocumentForRender {
40
+ _id: string;
41
+ _type: string;
42
+ [key: string]: unknown;
43
+ }
44
+ export interface RenderContext {
45
+ /**
46
+ * Async URL fetcher for renderers that need to follow `sanity.fileAsset`
47
+ * URLs (e.g. typedoc JSON for `typesReference` docs). Returns the raw
48
+ * body text or `null` on failure.
49
+ */
50
+ fetchUrl?: (url: string) => Promise<string | null>;
51
+ /**
52
+ * Soft cap on rendered content length, in bytes. Renderers should respect
53
+ * this and append a truncation notice rather than blow up grader context.
54
+ */
55
+ maxBytes?: number;
56
+ }
57
+ export interface RenderResult {
58
+ /** The rendered Markdown. Empty string is permitted but produces a warn. */
59
+ content: string;
60
+ /**
61
+ * The fidelity tier used. Resolvers can log differently based on this:
62
+ * - "high" — a registered renderer ran
63
+ * - "default" — fell through to the generic walker (info log)
64
+ */
65
+ fidelity: "high" | "default";
66
+ /**
67
+ * Stable display slug for this document. Articles use `slug.current`;
68
+ * other types fall back to a `<_type>:<_id>` form when no slug exists.
69
+ * Surfaces in `DocContext.slugs` for retrieval-metric attribution.
70
+ */
71
+ slug: string;
72
+ }
73
+ export interface DocumentRenderer {
74
+ /**
75
+ * Produce rendered Markdown for the doc's content surface (for grader
76
+ * + candidate context inclusion).
77
+ */
78
+ render(doc: DocumentForRender, ctx: RenderContext): Promise<RenderResult> | RenderResult;
79
+ /**
80
+ * Produce a symbol-reference index for the doc — a flat list of
81
+ * identifiers the doc legitimizes plus provenance snippets. Used by
82
+ * the grader-context pathway (W0197) instead of injecting the full
83
+ * rendered doc. Returning an empty index signals the caller to fall
84
+ * back to the rendered markdown.
85
+ */
86
+ extractSymbols(doc: DocumentForRender, ctx: RenderContext): Promise<SymbolIndex> | SymbolIndex;
87
+ }
88
+ /**
89
+ * Render a document using the registered renderer for its `_type`, falling
90
+ * back to the default walker. The returned `fidelity` flag tells callers
91
+ * whether to emit the "info: dedicated renderer would help" log.
92
+ */
93
+ export declare function renderDocument(doc: DocumentForRender, ctx?: RenderContext): Promise<RenderResult>;
94
+ /**
95
+ * Extract a symbol-reference index for a document using its registered
96
+ * renderer (or the default walker for unknown types). Used by the
97
+ * grader-context pathway (W0197) to feed the LLM judge a compact
98
+ * deterministic recognition reference instead of the full rendered doc.
99
+ *
100
+ * Returns an empty `SymbolIndex` (`{ symbols: [] }`) when extraction
101
+ * yields nothing — callers interpret this as the signal to fall back to
102
+ * the rendered markdown.
103
+ */
104
+ export declare function extractSymbolsForDoc(doc: DocumentForRender, ctx?: RenderContext): Promise<SymbolIndex>;
105
+ /** Exported for tests and consumers that want the registered set. */
106
+ export declare const REGISTERED_RENDERER_TYPES: string[];