@policyengine/calibration-tree 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -2
  3. package/package.json +73 -4
  4. package/src/calibration-build-comparison.ts +77 -0
  5. package/src/calibration-comparison-blob.ts +367 -0
  6. package/src/calibration-comparison-bundle.ts +149 -0
  7. package/src/calibration-explorer.ts +202 -0
  8. package/src/calibration-release-locator.ts +353 -0
  9. package/src/calibration-tree-artifact.ts +1974 -0
  10. package/src/calibration-tree-blob.ts +403 -0
  11. package/src/calibration-tree-bundle.ts +569 -0
  12. package/src/calibration-tree-manifest.ts +349 -0
  13. package/src/calibration-tree-publication.ts +399 -0
  14. package/src/calibration-tree-worker.ts +637 -0
  15. package/src/calibration-tree.ts +1284 -0
  16. package/src/chronicle-metadata.ts +42 -0
  17. package/src/countries.ts +355 -0
  18. package/src/geography-labels.ts +59 -0
  19. package/src/hierarchy-catalog-reader.ts +297 -0
  20. package/src/hierarchy-target-reader.ts +243 -0
  21. package/src/historical-weight-summary.ts +53 -0
  22. package/src/latest-artifact.ts +3767 -0
  23. package/src/legacy-target-reader.ts +337 -0
  24. package/src/program-label.ts +64 -0
  25. package/src/publish-calibration-tree.ts +1984 -0
  26. package/src/reforms.ts +224 -0
  27. package/src/release-cut.ts +32 -0
  28. package/src/release-record.ts +277 -0
  29. package/src/source-label.ts +5 -0
  30. package/src/source-labels.ts +71 -0
  31. package/src/staging-artifact.ts +1411 -0
  32. package/src/staging-contract.ts +916 -0
  33. package/src/structured-dimension-reader.ts +137 -0
  34. package/src/structured-target-reader.ts +76 -0
  35. package/src/target-change.ts +421 -0
  36. package/src/target-loss-attribution-manifest.ts +436 -0
  37. package/src/target-loss-attribution.ts +1012 -0
  38. package/src/target-representation.ts +69 -0
  39. package/src/target-surface-matcher.ts +266 -0
  40. package/types/next-fetch-cache.d.ts +8 -0
@@ -0,0 +1,3767 @@
1
+ // Data layer for the country-selectable Microcosm dashboard. Published releases
2
+ // are read from each country's registered Hugging Face dataset; an explicit UK
3
+ // local-run directory can replace that source for local diagnostics inspection.
4
+ // Dashboard defaults and historical releases resolve to immutable commits.
5
+
6
+ import { readFile, readdir, stat } from "node:fs/promises";
7
+ import { basename, join } from "node:path";
8
+
9
+ import { createHash } from "node:crypto";
10
+
11
+ import { sourceAuthorityLabel } from "./source-labels";
12
+
13
+ import { normalizeChronicleMetadata } from "./chronicle-metadata";
14
+ import {
15
+ readHierarchyTarget,
16
+ type HierarchyLabelVariant,
17
+ validateHierarchyTargets,
18
+ } from "./hierarchy-target-reader";
19
+ import { expandHierarchyCatalogs } from "./hierarchy-catalog-reader";
20
+ import { historicalWeightSummaryForDiagnostics } from "./historical-weight-summary";
21
+ import {
22
+ chroniclePublisherFromMetadata,
23
+ qualifyingChildrenFromRecordSet,
24
+ readLegacyTarget,
25
+ stateFromGeoId,
26
+ type ParsedLegacyTarget,
27
+ } from "./legacy-target-reader";
28
+ import {
29
+ COUNTRY_REGISTRY,
30
+ DEFAULT_COUNTRY,
31
+ CountryNotConfiguredError,
32
+ countryParam,
33
+ countryRegistration,
34
+ isCountry,
35
+ isCountryCapability,
36
+ resolveRegisteredRepository,
37
+ type CountryCapability,
38
+ type CountryNotConfiguredBody,
39
+ type MicrocosmCountry,
40
+ type RepositoryVisibility,
41
+ } from "./countries";
42
+ import {
43
+ normalizeTargetLossAttribution,
44
+ targetLossAttributionSummary,
45
+ type CalibrationProvenance,
46
+ type FinalTargetLossAttribution,
47
+ type TargetLossAttributionStatus,
48
+ type TargetLossDiagnosticWarning,
49
+ } from "./target-loss-attribution";
50
+ import {
51
+ targetRepresentationForDiagnosticsArtifact,
52
+ type TargetRepresentation,
53
+ type TargetRowRepresentation,
54
+ } from "./target-representation";
55
+ import { readStructuredTarget } from "./structured-target-reader";
56
+ import { matchTargetSurfaces } from "./target-surface-matcher";
57
+ import {
58
+ resolveCalibrationRelease,
59
+ resolveHfCommitPublishedAt,
60
+ } from "./calibration-release-locator";
61
+ import {
62
+ releaseDirectoryOf,
63
+ type CalibrationTreeManifest,
64
+ } from "./calibration-tree-manifest";
65
+ import { levelQualifiedGeographyLabels } from "./geography-labels";
66
+ import { parseReleaseCutTag } from "./release-cut";
67
+ import {
68
+ RELEASES_RECORD_PATH,
69
+ isBuildFolderId,
70
+ isReleaseDirectory,
71
+ recordedBuilds,
72
+ releasesRecordFromResponse,
73
+ type ReleasesRecord,
74
+ } from "./release-record";
75
+
76
+ // The registry is the registration point; these re-exports keep the server
77
+ // modules and routes that import country helpers from here working.
78
+ export { CountryNotConfiguredError, countryParam, isCountry, type MicrocosmCountry };
79
+
80
+ type JsonObject = Record<string, unknown>;
81
+ type TargetRow = JsonObject;
82
+ export type CalibrationLossKind = "normalized_target_loss" | "raw_optimizer_objective";
83
+
84
+ const DEFAULT_GEOGRAPHY = countryRegistration(DEFAULT_COUNTRY).geography;
85
+ const DEFAULT_GEOGRAPHY_LEVEL = "national";
86
+
87
+ // Deprecated upstream identifiers: Microcosm's published HF repositories and
88
+ // deployment variables still use the former Populace names. The names live on
89
+ // each country's registration; they are re-exported here for deployment docs
90
+ // and tests.
91
+ export const MICROCOSM_HF_REPO_ENV = COUNTRY_REGISTRY.us.repo_env;
92
+ export const MICROCOSM_UK_HF_REPO_ENV = COUNTRY_REGISTRY.uk.repo_env;
93
+ export const MICROCOSM_UK_HF_REVISION_ENV = COUNTRY_REGISTRY.uk.revision_env;
94
+ export const MICROCOSM_BE_HF_REPO_ENV = COUNTRY_REGISTRY.be.repo_env;
95
+ export const MICROCOSM_BE_HF_REVISION_ENV = COUNTRY_REGISTRY.be.revision_env;
96
+
97
+ interface MicrocosmCountryRepository {
98
+ repo: string;
99
+ revision: string;
100
+ geography: string;
101
+ }
102
+
103
+ // Server-side view of a registration: the registry defaults with this
104
+ // deployment's repository/revision overrides applied. Keep the national
105
+ // geography beside the repository so downstream shaping does not require a
106
+ // second exhaustive country table.
107
+ function resolveCountryRepository(country: MicrocosmCountry): MicrocosmCountryRepository {
108
+ const registration = countryRegistration(country);
109
+ return {
110
+ ...resolveRegisteredRepository(country, process.env),
111
+ geography: registration.geography,
112
+ };
113
+ }
114
+
115
+ const COUNTRY_REPO = Object.fromEntries(
116
+ (Object.keys(COUNTRY_REGISTRY) as MicrocosmCountry[]).map((country) => [
117
+ country,
118
+ resolveCountryRepository(country),
119
+ ]),
120
+ ) as Record<MicrocosmCountry, MicrocosmCountryRepository>;
121
+
122
+ export function countryRepository(
123
+ country: MicrocosmCountry,
124
+ ): MicrocosmCountryRepository {
125
+ return COUNTRY_REPO[country];
126
+ }
127
+
128
+ // Release/run ids are interpolated into HuggingFace URLs that carry the
129
+ // server's HF token, so an unvalidated id ("../../..") could redirect the
130
+ // authenticated request to arbitrary paths after URL normalization. Every id
131
+ // that reaches a URL path segment must pass this allowlist first. "latest" is
132
+ // the one non-id sentinel callers may pass.
133
+ const RELEASE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
134
+
135
+ export class InvalidReleaseIdError extends Error {}
136
+
137
+ export function assertSafeReleaseId(id: string, label = "release"): string {
138
+ if (id === "latest" || id === "") return id;
139
+ if (!RELEASE_ID_RE.test(id)) {
140
+ throw new InvalidReleaseIdError(`Invalid ${label} id`);
141
+ }
142
+ return id;
143
+ }
144
+
145
+ // A release id, or a build in its own folder (`<release>/<build>`), which is
146
+ // how a repository with releases.json names each build. Each segment
147
+ // passes the same allowlist, and nothing longer is accepted.
148
+ export function assertSafeReleaseOrBuildFolderId(id: string, label = "release"): string {
149
+ return isBuildFolderId(id) ? id : assertSafeReleaseId(id, label);
150
+ }
151
+
152
+ // Route catch → HTTP: a bad id is the caller's fault (400); a country without
153
+ // a configured release is an explicit not-configured state (404); anything
154
+ // else is an upstream/HF failure (502). Keeps status semantics consistent
155
+ // across routes.
156
+ export function classifyApiError(
157
+ error: unknown,
158
+ ): { status: number; body: { detail: string } | CountryNotConfiguredBody } {
159
+ if (error instanceof InvalidReleaseIdError) {
160
+ return { status: 400, body: { detail: error.message } };
161
+ }
162
+ if (error instanceof CountryNotConfiguredError) {
163
+ return { status: 404, body: error.body() };
164
+ }
165
+ return {
166
+ status: 502,
167
+ body: { detail: error instanceof Error ? error.message : String(error) },
168
+ };
169
+ }
170
+
171
+ export function microcosmRepo(country: MicrocosmCountry): string {
172
+ return countryRepository(country).repo;
173
+ }
174
+
175
+ export function microcosmRevision(country: MicrocosmCountry): string {
176
+ return countryRepository(country).revision;
177
+ }
178
+
179
+ export function microcosmCountryGeography(country: MicrocosmCountry): string {
180
+ return countryRepository(country).geography;
181
+ }
182
+
183
+ /**
184
+ * The Hugging Face read token the dashboard server uses: `HF_TOKEN`, or
185
+ * `HUGGINGFACE_TOKEN` when `HF_TOKEN` is unset, as set. An empty value
186
+ * sends no token.
187
+ */
188
+ export function huggingFaceReadToken(
189
+ environment: Readonly<Record<string, string | undefined>> = process.env,
190
+ ): string | undefined {
191
+ return environment.HF_TOKEN ?? environment.HUGGINGFACE_TOKEN;
192
+ }
193
+
194
+ function hfAuthHeaders(): HeadersInit | undefined {
195
+ const token = huggingFaceReadToken();
196
+ return token ? { Authorization: `Bearer ${token}` } : undefined;
197
+ }
198
+
199
+ const FILING_MODIFIERS = new Set(["Surviving Spouse"]);
200
+ const FILING_STATUSES = new Set([
201
+ "All", "Single", "Head of Household", "Married Filing Jointly",
202
+ "Married Filing Separately", "Surviving Spouse",
203
+ ]);
204
+ const RETURN_TYPES = new Set(["taxable", "all returns", "nontaxable"]);
205
+ const MEASURES = new Set(["total", "count", "mean", "filers", "nonfilers"]);
206
+ const QUALIFYING_CHILDREN = new Set([
207
+ "all children",
208
+ "no children",
209
+ "no qualifying children",
210
+ "one child",
211
+ "one qualifying child",
212
+ "two children",
213
+ "two qualifying children",
214
+ "three or more children",
215
+ "three or more qualifying children",
216
+ ]);
217
+
218
+ export function asObject(value: unknown): JsonObject {
219
+ return value && typeof value === "object" && !Array.isArray(value)
220
+ ? (value as JsonObject)
221
+ : {};
222
+ }
223
+
224
+ function isPlainObject(value: unknown): value is JsonObject {
225
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
226
+ const prototype = Object.getPrototypeOf(value);
227
+ return prototype === Object.prototype || prototype === null;
228
+ }
229
+
230
+ export function scrub(value: unknown): unknown {
231
+ if (Array.isArray(value)) return value.map(scrub);
232
+ if (value && typeof value === "object") {
233
+ return Object.fromEntries(
234
+ Object.entries(value as JsonObject).map(([k, v]) => [k, scrub(v)]),
235
+ );
236
+ }
237
+ if (typeof value === "number" && !Number.isFinite(value)) return null;
238
+ return value;
239
+ }
240
+
241
+ function numberOrNull(value: unknown): number | null {
242
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
243
+ }
244
+
245
+ // A count a release writes as metadata. Microcosm stores every metadata value
246
+ // as a string (TargetSpec, registry.py:149-150), so "2" reads as 2; a number
247
+ // still reads as itself. Anything but a whole, non-negative count reads null.
248
+ function countOrNull(value: unknown): number | null {
249
+ const count =
250
+ typeof value === "string" && /^\s*\d+\s*$/.test(value) ? Number(value) : numberOrNull(value);
251
+ return count != null && Number.isSafeInteger(count) && count >= 0 ? count : null;
252
+ }
253
+
254
+ export function calibrationLossKind(
255
+ diag: JsonObject,
256
+ buildManifest: JsonObject,
257
+ attributionStatus: TargetLossAttributionStatus = "unavailable",
258
+ ): CalibrationLossKind {
259
+ const options = asObject(diag.options);
260
+ const diagnosticsBuild = asObject(diag.build);
261
+ if (
262
+ attributionStatus === "reported" ||
263
+ attributionStatus === "exact_reconstructed" ||
264
+ (numberOrNull(diag.schema_version) != null &&
265
+ Number(diag.schema_version) >= 6) ||
266
+ diag.target_loss_basis != null ||
267
+ options.target_loss_scales != null ||
268
+ options.target_loss_weights != null ||
269
+ diagnosticsBuild.target_loss_weighting != null ||
270
+ diagnosticsBuild.target_loss_cap != null ||
271
+ buildManifest.target_loss_weighting != null ||
272
+ buildManifest.target_loss_cap != null
273
+ ) {
274
+ return "normalized_target_loss";
275
+ }
276
+ return "raw_optimizer_objective";
277
+ }
278
+
279
+ // A zero benchmark is a structural zero, not an epsilon denominator. Numerical
280
+ // noise at or below this tolerance is an exact fit; any substantive nonzero
281
+ // estimate is the maximum 100% error used by the Chronicle harness.
282
+ const ZERO_BENCHMARK_ABSOLUTE_TOLERANCE = 1e-4;
283
+
284
+ function relativeError(estimate: number | null, target: number | null): number | null {
285
+ if (estimate == null || target == null) return null;
286
+ if (target === 0) {
287
+ if (Math.abs(estimate) <= ZERO_BENCHMARK_ABSOLUTE_TOLERANCE) return 0;
288
+ return estimate < 0 ? -1 : 1;
289
+ }
290
+ return (estimate - target) / Math.abs(target);
291
+ }
292
+
293
+ type ParsedTarget = ParsedLegacyTarget;
294
+
295
+ interface TargetBreakdownDimension {
296
+ key: string;
297
+ label: string;
298
+ value: string;
299
+ source_key?: string;
300
+ raw_value?: string;
301
+ rank?: number;
302
+ }
303
+
304
+ interface ChronicleFilter {
305
+ key: string;
306
+ label: string;
307
+ value: string;
308
+ raw_value?: string;
309
+ }
310
+
311
+ interface ChronicleFactFields {
312
+ fact_key: string | null;
313
+ source_record_id: string | null;
314
+ semantic_fact_key: string | null;
315
+ aggregate_fact_key: string | null;
316
+ legacy_fact_key: string | null;
317
+ period_type: string | null;
318
+ source_period: string | null;
319
+ target_period: string | null;
320
+ geography_level: string | null;
321
+ geography_id: string | null;
322
+ geography_vintage: string | null;
323
+ domain: string | null;
324
+ entity_name: string | null;
325
+ entity_role: string | null;
326
+ measure_concept: string | null;
327
+ source_concept: string | null;
328
+ concept_relation: string | null;
329
+ concept_authority: string | null;
330
+ measure_unit: string | null;
331
+ value_operation: string | null;
332
+ layout_record_set_id: string | null;
333
+ layout_groupby_dimension: string | null;
334
+ layout_groupby_value_id: string | null;
335
+ layout_measure_id: string | null;
336
+ dimension_set_key: string | null;
337
+ universe_constraint_set_key: string | null;
338
+ universe_constraint_count: number | null;
339
+ filters: ChronicleFilter[];
340
+ }
341
+
342
+ // Deprecated upstream identifiers: Microcosm calibration diagnostics still
343
+ // serialize Chronicle provenance with the former `ledger_*` metadata prefix.
344
+
345
+ function stringValue(value: unknown): string | null {
346
+ return typeof value === "string" && value.trim() ? value : null;
347
+ }
348
+
349
+ function readableToken(value: string | null): string | null {
350
+ if (!value) return null;
351
+ return value.replace(/_/g, " ");
352
+ }
353
+
354
+ function titleCase(value: string): string {
355
+ return value
356
+ .replace(/[_:./#-]+/g, " ")
357
+ .replace(/\s+/g, " ")
358
+ .trim()
359
+ .replace(/\b\w/g, (char) => char.toUpperCase());
360
+ }
361
+
362
+ function dimensionKey(label: string): string {
363
+ return `bd_${label.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "")}`;
364
+ }
365
+
366
+ function addDimension(
367
+ dimensions: TargetBreakdownDimension[],
368
+ label: string,
369
+ value: string | null,
370
+ sourceKey?: string,
371
+ rawValue?: string | null,
372
+ ) {
373
+ if (!value) return;
374
+ const normalized = value.trim();
375
+ if (!normalized) return;
376
+ const key = dimensionKey(label);
377
+ if (dimensions.some((dim) => dim.key === key && dim.value === normalized)) return;
378
+ dimensions.push({
379
+ key,
380
+ label,
381
+ value: normalized,
382
+ source_key: sourceKey,
383
+ raw_value: rawValue ?? undefined,
384
+ });
385
+ }
386
+
387
+ function qualifyingChildrenFromCount(value: string | null): string | null {
388
+ if (value == null) return null;
389
+ if (value === "0") return "no qualifying children";
390
+ if (value === "1") return "one qualifying child";
391
+ if (value === "2") return "two qualifying children";
392
+ if (value === "3" || value === "3+" || value === "3plus") {
393
+ return "three or more qualifying children";
394
+ }
395
+ return readableToken(value);
396
+ }
397
+
398
+ function qualifyingChildrenFromSourceMeasure(variable: string | null, value: string | null): string | null {
399
+ if (variable !== "eitc" || !value) return null;
400
+ if (/^eitc_(amount|claims|returns|total)$/.test(value)) return "all qualifying children";
401
+ if (/^eitc_no_children_/.test(value)) return "no qualifying children";
402
+ if (/^eitc_one_child_/.test(value)) return "one qualifying child";
403
+ if (/^eitc_two_children_/.test(value)) return "two qualifying children";
404
+ if (/^eitc_three_or_more_children_/.test(value)) {
405
+ return "three or more qualifying children";
406
+ }
407
+ return null;
408
+ }
409
+
410
+ function measureFromName(value: string | null): string | null {
411
+ if (!value) return null;
412
+ if (/_amount$|_total$|_collections$|_projected_amount$/.test(value)) return "total";
413
+ if (/_returns$|_claims$|_count$/.test(value)) return "count";
414
+ return null;
415
+ }
416
+
417
+ function measureFromMetadata(metadata: JsonObject): string | null {
418
+ const sourceMeasure = stringValue(metadata.source_measure_id);
419
+ const namedMeasure = measureFromName(sourceMeasure);
420
+ if (namedMeasure) return namedMeasure;
421
+ const unit = stringValue(metadata.ledger_measure_unit);
422
+ if (stringValue(metadata.count) === "true" || unit === "count") return "count";
423
+ if (unit === "usd") return "total";
424
+ return null;
425
+ }
426
+
427
+ function dimensionLabel(value: string | null): string {
428
+ if (!value) return "Breakdown";
429
+ if (value === "us:statutes/26/62#adjusted_gross_income") return "Income band";
430
+ if (value === "census_stc.item") return "Item";
431
+ if (value === "hhs_acf_tanf.spending_category") return "Spending category";
432
+ if (value.startsWith("cms_medicaid.")) return titleCase(value.replace(/^cms_medicaid\./, ""));
433
+ const hash = value.split("#").at(-1);
434
+ const last = hash?.split(".").at(-1) ?? value;
435
+ return titleCase(last);
436
+ }
437
+
438
+ function filterDimensionLabel(key: string): string {
439
+ const suffix = key.replace(/^ledger_filter_/, "");
440
+ if (suffix === "income_range") return "Income band";
441
+ if (suffix === "filing_status") return "Filing status";
442
+ if (suffix === "eitc_child_count") return "Qualifying children";
443
+ return dimensionLabel(suffix);
444
+ }
445
+
446
+ function isGeographyLayoutDimension(value: string | null): boolean {
447
+ return [
448
+ "geography",
449
+ "state",
450
+ "cms_medicaid.state_abbreviation",
451
+ ].includes(value ?? "");
452
+ }
453
+
454
+ function isRedundantGeographyValue(metadata: JsonObject, value: string | null): boolean {
455
+ if (!value) return false;
456
+ const geography = stateFromGeoId(stringValue(metadata.ledger_geography_id));
457
+ return Boolean(geography && value.toLowerCase() === geography.toLowerCase());
458
+ }
459
+
460
+ function readableDimensionValue(value: string | null): string | null {
461
+ if (!value) return null;
462
+ if (value === "all") return "All";
463
+ if (value === "total") return "Total";
464
+ return readableToken(value);
465
+ }
466
+
467
+ function readableFilterValue(key: string, value: string | null): string | null {
468
+ if (key === "ledger_filter_eitc_child_count") {
469
+ return qualifyingChildrenFromCount(value);
470
+ }
471
+ return readableDimensionValue(value);
472
+ }
473
+
474
+ function chronicleFilters(metadata: JsonObject): ChronicleFilter[] {
475
+ return Object.entries(metadata)
476
+ .filter(([key, raw]) => key.startsWith("ledger_filter_") && stringValue(raw))
477
+ .map(([key, raw]) => {
478
+ const rawValue = stringValue(raw)!;
479
+ return {
480
+ key,
481
+ label: filterDimensionLabel(key),
482
+ value: readableFilterValue(key, rawValue) ?? rawValue,
483
+ raw_value: rawValue,
484
+ };
485
+ })
486
+ .sort((a, b) => a.label.localeCompare(b.label) || a.key.localeCompare(b.key));
487
+ }
488
+
489
+ function chronicleFactFields(metadata: JsonObject): ChronicleFactFields {
490
+ return {
491
+ fact_key: stringValue(metadata.ledger_fact_key),
492
+ source_record_id: stringValue(metadata.ledger_source_record_id),
493
+ semantic_fact_key: stringValue(metadata.ledger_semantic_fact_key),
494
+ aggregate_fact_key: stringValue(metadata.ledger_aggregate_fact_key),
495
+ legacy_fact_key: stringValue(metadata.ledger_legacy_fact_key),
496
+ period_type: stringValue(metadata.ledger_period_type),
497
+ source_period: stringValue(metadata.source_period),
498
+ target_period: stringValue(metadata.target_period),
499
+ geography_level: stringValue(metadata.ledger_geography_level),
500
+ geography_id: stringValue(metadata.ledger_geography_id),
501
+ geography_vintage: stringValue(metadata.ledger_geography_vintage),
502
+ domain: stringValue(metadata.ledger_domain),
503
+ entity_name: stringValue(metadata.ledger_entity_name),
504
+ entity_role: stringValue(metadata.ledger_entity_role),
505
+ measure_concept: stringValue(metadata.ledger_measure_concept),
506
+ source_concept: stringValue(metadata.ledger_source_concept),
507
+ concept_relation: stringValue(metadata.ledger_concept_relation),
508
+ concept_authority: stringValue(metadata.ledger_concept_authority),
509
+ measure_unit: stringValue(metadata.ledger_measure_unit),
510
+ value_operation: stringValue(metadata.ledger_value_operation),
511
+ layout_record_set_id: stringValue(metadata.ledger_layout_record_set_id),
512
+ layout_groupby_dimension: stringValue(metadata.ledger_layout_groupby_dimension),
513
+ layout_groupby_value_id: stringValue(metadata.ledger_layout_groupby_value_id),
514
+ layout_measure_id: stringValue(metadata.ledger_layout_measure_id),
515
+ dimension_set_key: stringValue(metadata.ledger_dimension_set_key),
516
+ universe_constraint_set_key: stringValue(metadata.ledger_universe_constraint_set_key),
517
+ universe_constraint_count: countOrNull(metadata.ledger_universe_constraint_count),
518
+ filters: chronicleFilters(metadata),
519
+ };
520
+ }
521
+
522
+ // A JSON list of strings, as Microcosm writes ledger_member_fact_keys
523
+ // (ledger_targets.py:1321-1327 at 0ff293b); anything else reads [].
524
+ function stringListOrEmpty(value: unknown): string[] {
525
+ let list: unknown = value;
526
+ if (typeof value === "string") {
527
+ try {
528
+ list = JSON.parse(value);
529
+ } catch {
530
+ return [];
531
+ }
532
+ }
533
+ return Array.isArray(list) && list.every((item) => typeof item === "string") ? list : [];
534
+ }
535
+
536
+ // How many base cells an allocated_residual_by_ratio receipt lists under
537
+ // fact_keys.base (ledger_targets.py:3069-3071, :3188-3189 at 0ff293b), or
538
+ // null when it cannot be read.
539
+ function allocationBaseCellCount(value: unknown): number | null {
540
+ if (typeof value !== "string") return null;
541
+ try {
542
+ const base = asObject(asObject(JSON.parse(value)).fact_keys).base;
543
+ return Array.isArray(base) ? base.length : null;
544
+ } catch {
545
+ return null;
546
+ }
547
+ }
548
+
549
+ // Whether a multi-fact target's identity is its representative fact alone,
550
+ // read from the metadata Microcosm writes for its value operation. When the
551
+ // metadata does not say, it is not.
552
+ function identityIsRepresentative(metadata: JsonObject): boolean {
553
+ switch (stringValue(metadata.ledger_value_operation)) {
554
+ case "scaled_by_ratio":
555
+ return true;
556
+ case "rolled_forward_by_ratio":
557
+ return countOrNull(metadata.ledger_value_base_cells) === 1;
558
+ case "allocated_residual_by_ratio":
559
+ return allocationBaseCellCount(metadata.ledger_allocation_receipt) === 1;
560
+ default:
561
+ return false;
562
+ }
563
+ }
564
+
565
+ // Whether a target's hierarchy lists the group-by pair its Chronicle fields
566
+ // carry. A listed pair shows that every fact of the target's identity shares
567
+ // it; an omitted pair shows nothing. _calibration_hierarchy builds the
568
+ // hierarchy from the identity facts (ledger_targets.py:1096-1100 at 0ff293b),
569
+ // and _inherited_dimensions (:1578-1611) lists a pair only when every fact's
570
+ // ordinary dimensions share it (_common_dimensions, :1614-1623) or every
571
+ // fact's layout carries the same group-by pair (_constant_text, :1649-1651).
572
+ // The label validator reads a fact's group-by pair as one of its dimensions
573
+ // (:1486-1490), but _inherited_dimensions does not, so two facts that both
574
+ // describe one value, one in its dimensions and one in its layout, leave it
575
+ // out of the hierarchy.
576
+ function hierarchyListsGroupBy(row: TargetRow, chronicle: JsonObject): boolean {
577
+ const groupBy = stringValue(chronicle.layout_groupby_dimension)?.trim();
578
+ const value = stringValue(chronicle.layout_groupby_value_id)?.trim();
579
+ if (row.dimension_adapter !== "hierarchy" || !groupBy || !value) return false;
580
+ const dimensions = Array.isArray(row.target_dimensions) ? row.target_dimensions : [];
581
+ return dimensions.some((dimension) => {
582
+ const listed = asObject(dimension);
583
+ return listed.key === groupBy && listed.value_id === value;
584
+ });
585
+ }
586
+
587
+ // What a multi-fact target's fields establish about the group-by pair its
588
+ // Chronicle fields carry, decided in this order:
589
+ // - no complete pair: null, since the representative carries none;
590
+ // - its identity is one fact, or its hierarchy lists the pair: "shared", since
591
+ // every identity fact then shares it. A one-fact identity counts whether or
592
+ // not the release has a hierarchy;
593
+ // - its release has a hierarchy, which leaves the pair out: "unlisted", which
594
+ // does not show whether the identity facts share it;
595
+ // - otherwise, a several-fact identity with no hierarchy to read: null.
596
+ function groupByAcrossIdentity(
597
+ row: TargetRow,
598
+ chronicle: JsonObject,
599
+ oneFact: boolean,
600
+ ): "shared" | "unlisted" | null {
601
+ if (
602
+ !stringValue(chronicle.layout_groupby_dimension) ||
603
+ !stringValue(chronicle.layout_groupby_value_id)
604
+ ) {
605
+ return null;
606
+ }
607
+ if (oneFact || hierarchyListsGroupBy(row, chronicle)) return "shared";
608
+ return row.dimension_adapter === "hierarchy" ? "unlisted" : null;
609
+ }
610
+
611
+ // The Chronicle fields a page shows for a target. Microcosm stamps a target's
612
+ // single-fact fields from one representative fact (ledger_targets.py:1085-1090
613
+ // at 0ff293b). A target built from several facts also lists every one of them,
614
+ // ratio operands included, in ledger_member_fact_count and
615
+ // ledger_member_fact_keys (_multi_fact_reference_metadata, :1318-1341). Its
616
+ // identity depends on its value operation (identity_facts, :1018-1035):
617
+ // - scaled_by_ratio: the representative alone, the base cell that its
618
+ // numerator and denominator translate;
619
+ // - rolled_forward_by_ratio: its base cells, which ledger_value_base_cells
620
+ // counts (:1174);
621
+ // - allocated_residual_by_ratio: the cells its selector matches, the base its
622
+ // ledger_allocation_receipt lists;
623
+ // - calendar_year_window_scaled_by_ratio: its window, two years of each
624
+ // series (:4270-4272, :4331);
625
+ // - any other operation: every fact.
626
+ // For the first three operations the representative is the first base cell
627
+ // (_value_representative_fact, :1232-1245), so an identity of one fact is the
628
+ // representative. For any other multi-fact operation it is the fact of the
629
+ // latest period, the last in the tuple on a tie, taken from the window for
630
+ // calendar_year_window_scaled_by_ratio (:1012-1016). A sum's tuple comes from
631
+ // its resolver sorted by fact key (:2178-2183), so which identity fact becomes
632
+ // the representative, and so which group-by pair, dimensions and record the
633
+ // target carries, can turn on a fact's key alone.
634
+ //
635
+ // A target whose identity is one fact shows its fields as they are, with
636
+ // member_fact_count, member_fact_keys, layout_groupby_unlisted_across_facts
637
+ // and identity_spans_several_facts (false) added. An identity of several facts
638
+ // has no one record or fact key, so those read null, and
639
+ // identity_spans_several_facts reads true. Like the hierarchy's dimensions,
640
+ // and unlike the representative's group-by pair, it reads the same whichever
641
+ // identity fact is the representative, so the Dimensions column reads it. Its
642
+ // group-by value shows when its hierarchy lists the pair, because every
643
+ // identity fact then shares it, and reads null otherwise.
644
+ // layout_groupby_unlisted_across_facts reads true when its hierarchy leaves
645
+ // out the pair the representative carries, which does not show that the facts
646
+ // differ in it (see hierarchyListsGroupBy and groupByAcrossIdentity for its
647
+ // order). Nothing Microcosm writes says whether the identity facts share a
648
+ // universe constraint, so its set key and count read null.
649
+ // ledger_aggregation_varying_dimensions cannot settle either question: it
650
+ // compares each fact's ordinary dimensions, ratio operands included, and
651
+ // counts a dimension one fact carries and another lacks as varying (:1323,
652
+ // :1626-1646). The row itself keeps every field, so a comparison still matches
653
+ // it by fact key. A single-fact target's fields show as they are, with none of
654
+ // these fields added.
655
+ function shownChronicle(row: TargetRow): unknown {
656
+ const metadata = asObject(row.metadata);
657
+ const memberFactCount = countOrNull(metadata.ledger_member_fact_count);
658
+ if (memberFactCount == null || memberFactCount <= 1) return row.chronicle;
659
+ const chronicle = asObject(row.chronicle);
660
+ const oneFact = identityIsRepresentative(metadata);
661
+ const groupBy = groupByAcrossIdentity(row, chronicle, oneFact);
662
+ const members = {
663
+ member_fact_count: memberFactCount,
664
+ member_fact_keys: stringListOrEmpty(metadata.ledger_member_fact_keys),
665
+ layout_groupby_unlisted_across_facts: groupBy == null ? null : groupBy === "unlisted",
666
+ identity_spans_several_facts: !oneFact,
667
+ };
668
+ if (oneFact) return { ...chronicle, ...members };
669
+ return {
670
+ ...chronicle,
671
+ ...members,
672
+ fact_key: null,
673
+ source_record_id: null,
674
+ semantic_fact_key: null,
675
+ aggregate_fact_key: null,
676
+ legacy_fact_key: null,
677
+ layout_groupby_value_id: groupBy === "shared" ? chronicle.layout_groupby_value_id : null,
678
+ universe_constraint_set_key: null,
679
+ universe_constraint_count: null,
680
+ };
681
+ }
682
+
683
+ function isDuplicateDimension(
684
+ dimensions: TargetBreakdownDimension[],
685
+ label: string,
686
+ value: string | null,
687
+ ): boolean {
688
+ if (!value) return false;
689
+ const key = dimensionKey(label);
690
+ return dimensions.some((dim) => dim.key === key && dim.value === value);
691
+ }
692
+
693
+ function sourceMeasureDetail(metadata: JsonObject): string | null {
694
+ const variable = stringValue(metadata.variable);
695
+ const sourceMeasure = stringValue(metadata.source_measure_id);
696
+ if (!variable || !sourceMeasure) return null;
697
+ const variablePrefix = variable.replace(/\s+/g, "_").toLowerCase();
698
+ const measure = sourceMeasure.toLowerCase();
699
+ if (!measure.startsWith(`${variablePrefix}_`)) return null;
700
+ const detail = measure
701
+ .slice(variablePrefix.length + 1)
702
+ .replace(/_(amount|returns|claims|count|total|collections|projected_amount)$/, "");
703
+ if (!detail || MEASURES.has(detail)) return null;
704
+ if (["amount", "returns", "claims", "count", "total", "collections", "projected_amount"].includes(detail)) {
705
+ return null;
706
+ }
707
+ return readableToken(detail);
708
+ }
709
+
710
+ function metadataDimensions(row: TargetRow): TargetBreakdownDimension[] | null {
711
+ const metadata = asObject(row.metadata);
712
+ if (!Object.keys(metadata).length) return null;
713
+ const dimensions: TargetBreakdownDimension[] = [];
714
+ const layoutDimension = stringValue(metadata.ledger_layout_groupby_dimension);
715
+ const layoutValue = stringValue(metadata.ledger_layout_groupby_value_id);
716
+ if (
717
+ layoutValue &&
718
+ !isGeographyLayoutDimension(layoutDimension) &&
719
+ !isRedundantGeographyValue(metadata, layoutValue)
720
+ ) {
721
+ addDimension(
722
+ dimensions,
723
+ dimensionLabel(layoutDimension),
724
+ readableDimensionValue(layoutValue),
725
+ "ledger_layout_groupby_value_id",
726
+ layoutValue,
727
+ );
728
+ }
729
+ for (const [key, raw] of Object.entries(metadata)) {
730
+ if (!key.startsWith("ledger_filter_")) continue;
731
+ const rawValue = stringValue(raw);
732
+ if (!rawValue) continue;
733
+ const label = filterDimensionLabel(key);
734
+ const value = readableFilterValue(key, rawValue);
735
+ if (isDuplicateDimension(dimensions, label, value)) continue;
736
+ addDimension(dimensions, label, value, key, rawValue);
737
+ }
738
+ addDimension(
739
+ dimensions,
740
+ "Qualifying children",
741
+ qualifyingChildrenFromCount(stringValue(metadata.ledger_filter_eitc_child_count)) ??
742
+ qualifyingChildrenFromRecordSet(stringValue(metadata.ledger_layout_record_set_id)) ??
743
+ qualifyingChildrenFromSourceMeasure(
744
+ stringValue(metadata.variable),
745
+ stringValue(metadata.source_measure_id),
746
+ ),
747
+ stringValue(metadata.ledger_filter_eitc_child_count)
748
+ ? "ledger_filter_eitc_child_count"
749
+ : stringValue(metadata.ledger_layout_record_set_id)
750
+ ? "ledger_layout_record_set_id"
751
+ : "source_measure_id",
752
+ stringValue(metadata.ledger_filter_eitc_child_count) ??
753
+ stringValue(metadata.ledger_layout_record_set_id) ??
754
+ stringValue(metadata.source_measure_id),
755
+ );
756
+ addDimension(dimensions, "Filing status", stringValue(metadata.filing_status));
757
+ const sourceDetail = sourceMeasureDetail(metadata);
758
+ const hasExplicitChildDimension = dimensions.some((dim) => dim.label === "Qualifying children");
759
+ const sourceDetailIsChildDimension = Boolean(sourceDetail && /child|children/.test(sourceDetail));
760
+ if (
761
+ sourceDetail &&
762
+ !(hasExplicitChildDimension && sourceDetailIsChildDimension) &&
763
+ !dimensions.some((dim) => dim.value === sourceDetail)
764
+ ) {
765
+ addDimension(dimensions, "Source measure detail", sourceDetail, "source_measure_id", stringValue(metadata.source_measure_id));
766
+ }
767
+ return dimensions;
768
+ }
769
+
770
+ interface FilterDimensionSpec {
771
+ capture: number;
772
+ label: string;
773
+ role?: "geography";
774
+ valueLabels?: Readonly<Record<string, string>>;
775
+ }
776
+
777
+ interface FilterDecompositionSpec {
778
+ pattern: RegExp;
779
+ geographyLevel: string;
780
+ dimensions: readonly FilterDimensionSpec[];
781
+ }
782
+
783
+ export interface DiagnosticsDimension {
784
+ label: string;
785
+ role?: "geography";
786
+ level?: string;
787
+ values?: Record<string, string>;
788
+ order?: string[];
789
+ }
790
+
791
+ export function diagnosticsDimensions(
792
+ diag: JsonObject,
793
+ ): Record<string, DiagnosticsDimension> {
794
+ if (!isPlainObject(diag.dimensions)) return {};
795
+ return Object.fromEntries(
796
+ Object.entries(diag.dimensions).flatMap(([id, rawDefinition]) => {
797
+ if (!id || !isPlainObject(rawDefinition)) return [];
798
+ const label = stringValue(rawDefinition.label)?.trim();
799
+ if (!label) return [];
800
+ const role = rawDefinition.role === "geography" ? "geography" : undefined;
801
+ const level = stringValue(rawDefinition.level)?.trim();
802
+ const values = isPlainObject(rawDefinition.values)
803
+ ? Object.fromEntries(
804
+ Object.entries(rawDefinition.values).flatMap(([rawValue, rawLabel]) => {
805
+ if (!rawValue || typeof rawLabel !== "string") return [];
806
+ const valueLabel = rawLabel.trim();
807
+ return valueLabel ? [[rawValue, valueLabel]] : [];
808
+ }),
809
+ )
810
+ : undefined;
811
+ const order = Array.isArray(rawDefinition.order)
812
+ ? rawDefinition.order.flatMap((rawValue) => {
813
+ if (typeof rawValue !== "string") return [];
814
+ const value = rawValue.trim();
815
+ return value ? [value] : [];
816
+ })
817
+ : undefined;
818
+ return [[
819
+ id,
820
+ {
821
+ label,
822
+ ...(role ? { role } : {}),
823
+ ...(level ? { level } : {}),
824
+ ...(values ? { values } : {}),
825
+ ...(order ? { order } : {}),
826
+ },
827
+ ]];
828
+ }),
829
+ );
830
+ }
831
+
832
+ // Legacy artifacts encode some dimensions in a compiled filter name. The
833
+ // adapter is selected by the filter pattern, never by country; future artifacts
834
+ // should publish structured target dimensions instead.
835
+ const FILTER_DECOMPOSITION_SPECS: readonly FilterDecompositionSpec[] = [
836
+ {
837
+ pattern: /^cell_([a-z][a-z0-9-]*)_(male|female)_(\d+_(?:\d+|plus))$/,
838
+ geographyLevel: "region",
839
+ dimensions: [
840
+ {
841
+ capture: 1,
842
+ label: "Region",
843
+ role: "geography",
844
+ valueLabels: {
845
+ be1: "Brussels",
846
+ be2: "Flanders",
847
+ be3: "Wallonia",
848
+ },
849
+ },
850
+ { capture: 2, label: "Sex" },
851
+ { capture: 3, label: "Age band" },
852
+ ],
853
+ },
854
+ ];
855
+
856
+ interface DecomposedTargetFilter {
857
+ geography: string;
858
+ level: string;
859
+ dimensions: TargetBreakdownDimension[];
860
+ }
861
+
862
+ function dimensionValue(
863
+ label: string,
864
+ rawValue: string,
865
+ valueLabels?: Readonly<Record<string, string>>,
866
+ ): string {
867
+ const explicit =
868
+ valueLabels && Object.hasOwn(valueLabels, rawValue)
869
+ ? valueLabels[rawValue]
870
+ : undefined;
871
+ if (explicit) return explicit;
872
+ if (label.toLowerCase() === "age band") {
873
+ const range = /^(\d+)_(\d+)$/.exec(rawValue);
874
+ if (range) return `${range[1]}–${range[2]}`;
875
+ const openEnded = /^(\d+)_plus$/.exec(rawValue);
876
+ if (openEnded) return `${openEnded[1]}+`;
877
+ }
878
+ return titleCase(rawValue);
879
+ }
880
+
881
+ function filterDimensionValue(spec: FilterDimensionSpec, rawValue: string): string {
882
+ return dimensionValue(spec.label, rawValue, spec.valueLabels);
883
+ }
884
+
885
+ function decomposeTargetFilter(value: unknown): DecomposedTargetFilter | null {
886
+ const filter = stringValue(value);
887
+ if (!filter) return null;
888
+ for (const spec of FILTER_DECOMPOSITION_SPECS) {
889
+ const match = spec.pattern.exec(filter);
890
+ if (!match) continue;
891
+ let geography = "";
892
+ const dimensions: TargetBreakdownDimension[] = [];
893
+ for (const dimension of spec.dimensions) {
894
+ const rawValue = match[dimension.capture];
895
+ if (!rawValue) continue;
896
+ const valueLabel = filterDimensionValue(dimension, rawValue);
897
+ if (dimension.role === "geography") {
898
+ geography = valueLabel;
899
+ continue;
900
+ }
901
+ dimensions.push({
902
+ key: dimensionKey(dimension.label),
903
+ label: dimension.label,
904
+ value: valueLabel,
905
+ source_key: "filter",
906
+ raw_value: rawValue,
907
+ });
908
+ }
909
+ if (geography) {
910
+ return { geography, level: spec.geographyLevel, dimensions };
911
+ }
912
+ }
913
+ return null;
914
+ }
915
+
916
+ function variableKeyOf(parsed: ParsedTarget): string {
917
+ return [parsed.source, parsed.variable].filter(Boolean).join(" / ");
918
+ }
919
+
920
+ function splitBreakdown(breakdown: string): string[] {
921
+ const raw = breakdown ? breakdown.split(" · ").filter(Boolean) : [];
922
+ const out: string[] = [];
923
+ for (const token of raw) {
924
+ if (FILING_MODIFIERS.has(token) && out.length) {
925
+ out[out.length - 1] = `${out[out.length - 1]} · ${token}`;
926
+ } else {
927
+ out.push(token);
928
+ }
929
+ }
930
+ return out;
931
+ }
932
+
933
+ function classifyDimension(values: string[]): string {
934
+ const v = values.filter(Boolean);
935
+ if (!v.length) return "Breakdown";
936
+ const all = (pred: (s: string) => boolean) => v.every(pred);
937
+ const firstStatus = (s: string) => s.split(" · ")[0];
938
+ if (all((s) => s.startsWith("AGI in "))) return "Income band";
939
+ if (all((s) => RETURN_TYPES.has(s))) return "Return type";
940
+ if (all((s) => FILING_STATUSES.has(firstStatus(s)))) return "Filing status";
941
+ if (all((s) => QUALIFYING_CHILDREN.has(s))) return "Qualifying children";
942
+ if (all((s) => /^\d+$/.test(s))) return "Age";
943
+ if (all((s) => MEASURES.has(s))) return "Measure";
944
+ return "Breakdown";
945
+ }
946
+
947
+ function parseAmount(token: string): number {
948
+ const normalized = token.trim().toLowerCase().replace(/,/g, "");
949
+ if (/^-?inf(?:inity)?$/.test(normalized)) return normalized.startsWith("-") ? -Infinity : Infinity;
950
+ const negative = normalized.startsWith("-");
951
+ const magnitude = parseFloat(normalized);
952
+ if (!Number.isFinite(magnitude)) return 0;
953
+ const mult = /k$/.test(normalized) ? 1e3 : /m$/.test(normalized) ? 1e6 : 1;
954
+ return (negative ? -1 : 1) * Math.abs(magnitude) * mult;
955
+ }
956
+
957
+ function totalDimensionRank(value: string): number {
958
+ return /^(all|total|all returns)$/i.test(value.trim()) ? 0 : 1;
959
+ }
960
+
961
+ function numericRange(value: string): { lower: number; upper: number } | null {
962
+ const body = value
963
+ .replace(/^AGI in\s+/i, "")
964
+ .trim()
965
+ .toLowerCase()
966
+ .replace(/,/g, "")
967
+ .replace(/\s+/g, " ");
968
+ const amount = "-?\\d+(?:\\.\\d+)?[km]?";
969
+
970
+ let match = new RegExp(`^under (${amount})$`).exec(body);
971
+ if (match) return { lower: -Infinity, upper: parseAmount(match[1]) };
972
+
973
+ match = new RegExp(`^(${amount}) plus$`).exec(body);
974
+ if (match) return { lower: parseAmount(match[1]), upper: Infinity };
975
+
976
+ match = new RegExp(`^(${amount}) to (${amount})$`).exec(body);
977
+ if (match) return { lower: parseAmount(match[1]), upper: parseAmount(match[2]) };
978
+
979
+ match = new RegExp(`^(${amount})-(${amount}|inf|infinity)$`).exec(body);
980
+ if (match) return { lower: parseAmount(match[1]), upper: parseAmount(match[2]) };
981
+
982
+ match = new RegExp(`^(${amount})$`).exec(body);
983
+ if (match) {
984
+ const point = parseAmount(match[1]);
985
+ return { lower: point, upper: point };
986
+ }
987
+
988
+ return null;
989
+ }
990
+
991
+ function compareNumericRangesDescending(a: string, b: string): number {
992
+ const totalRank = totalDimensionRank(a) - totalDimensionRank(b);
993
+ if (totalRank !== 0) return totalRank;
994
+
995
+ const ar = numericRange(a);
996
+ const br = numericRange(b);
997
+ if (ar || br) {
998
+ if (!ar) return 1;
999
+ if (!br) return -1;
1000
+ return br.lower - ar.lower || br.upper - ar.upper || a.localeCompare(b);
1001
+ }
1002
+
1003
+ return a.localeCompare(b);
1004
+ }
1005
+
1006
+ function sortDimensionValues(label: string, values: string[]): string[] {
1007
+ if (label === "Income band") return [...values].sort(compareNumericRangesDescending);
1008
+ if (label === "Age") return [...values].sort(compareNumericRangesDescending);
1009
+ if (label === "Qualifying children") {
1010
+ const rank = (value: string) =>
1011
+ [
1012
+ "all qualifying children",
1013
+ "three or more qualifying children",
1014
+ "two qualifying children",
1015
+ "one qualifying child",
1016
+ "no qualifying children",
1017
+ ].indexOf(value);
1018
+ return [...values].sort((a, b) => {
1019
+ const ar = rank(a);
1020
+ const br = rank(b);
1021
+ if (ar >= 0 || br >= 0) return (ar >= 0 ? ar : 99) - (br >= 0 ? br : 99);
1022
+ return compareNumericRangesDescending(a, b);
1023
+ });
1024
+ }
1025
+ return [...values].sort(compareNumericRangesDescending);
1026
+ }
1027
+
1028
+ function rowFacetValue(row: TargetRow, key: string): string | undefined {
1029
+ if (key === "geography") return (row.geography as string) || undefined;
1030
+ if (key === "level") return (row.level as string) || undefined;
1031
+ const targetDimensions = row.target_dimensions as TargetBreakdownDimension[] | undefined;
1032
+ const targetDimension = targetDimensions?.find((dim) => dim.key === key);
1033
+ if (targetDimension) return targetDimension.value;
1034
+ const dim = /^dim(\d+)$/.exec(key);
1035
+ if (dim) return (row.dims as string[] | undefined)?.[Number(dim[1])];
1036
+ const value = row[key];
1037
+ return typeof value === "string" ? value : undefined;
1038
+ }
1039
+
1040
+ function sortFacetValues(label: string, values: string[]): string[] {
1041
+ if (label === "Geography") {
1042
+ return [...values].sort((a, b) =>
1043
+ a === "United States" ? -1 : b === "United States" ? 1 : a.localeCompare(b),
1044
+ );
1045
+ }
1046
+ return sortDimensionValues(label, values);
1047
+ }
1048
+
1049
+ export interface TargetDimension {
1050
+ key: string;
1051
+ label: string;
1052
+ values: string[];
1053
+ }
1054
+
1055
+ // A dimension whose value is its row's geography, such as an FSA state
1056
+ // target's Borrower location, only repeats the Geography facet: under each
1057
+ // geography it holds one value, and the calibration map adds no tier for a
1058
+ // dimension with one value under a node (calibration-tree.ts:601-610). A
1059
+ // dimension that merely has one value per geography in this page (one
1060
+ // target per region, each of a different sex) is a real breakdown and stays.
1061
+ function repeatsGeography(rows: TargetRow[], key: string): boolean {
1062
+ let carried = false;
1063
+ for (const row of rows) {
1064
+ const value = rowFacetValue(row, key);
1065
+ if (!value) continue;
1066
+ if (value !== rowFacetValue(row, "geography")) return false;
1067
+ carried = true;
1068
+ }
1069
+ return carried;
1070
+ }
1071
+
1072
+ function computeDimensions(rows: TargetRow[]): TargetDimension[] {
1073
+ const geographyLabel =
1074
+ rows.length > 0 && rows.every((row) => row.level === "region")
1075
+ ? "Region"
1076
+ : "Geography";
1077
+ const candidates: { key: string; label?: string }[] = [
1078
+ { key: "geography", label: geographyLabel },
1079
+ ];
1080
+ const seenDimensionKeys = new Set<string>();
1081
+ for (const row of rows) {
1082
+ const targetDimensions = row.target_dimensions as TargetBreakdownDimension[] | undefined;
1083
+ for (const dim of targetDimensions ?? []) {
1084
+ if (seenDimensionKeys.has(dim.key)) continue;
1085
+ seenDimensionKeys.add(dim.key);
1086
+ candidates.push({ key: dim.key, label: dim.label });
1087
+ }
1088
+ }
1089
+ const facets: TargetDimension[] = [];
1090
+ for (const candidate of candidates) {
1091
+ const values = [
1092
+ ...new Set(
1093
+ rows.map((row) => rowFacetValue(row, candidate.key)).filter((v): v is string => Boolean(v)),
1094
+ ),
1095
+ ];
1096
+ if (values.length <= 1) continue;
1097
+ if (candidate.key !== "geography" && repeatsGeography(rows, candidate.key)) continue;
1098
+ const label = candidate.label ?? classifyDimension(values);
1099
+ const ranks = new Map<string, number>();
1100
+ let everyValueRanked = true;
1101
+ for (const value of values) {
1102
+ if (candidate.key === "geography") {
1103
+ const matchingRows = rows.filter((row) => row.geography === value);
1104
+ if (
1105
+ !matchingRows.length ||
1106
+ matchingRows.some((row) => typeof row.geography_rank !== "number")
1107
+ ) {
1108
+ everyValueRanked = false;
1109
+ break;
1110
+ }
1111
+ ranks.set(
1112
+ value,
1113
+ Math.min(...matchingRows.map((row) => row.geography_rank as number)),
1114
+ );
1115
+ continue;
1116
+ }
1117
+ const matchingDimensions = rows.flatMap((row) =>
1118
+ ((row.target_dimensions as TargetBreakdownDimension[] | undefined) ?? [])
1119
+ .filter((dimension) =>
1120
+ dimension.key === candidate.key && dimension.value === value,
1121
+ ),
1122
+ );
1123
+ if (
1124
+ !matchingDimensions.length ||
1125
+ matchingDimensions.some((dimension) => typeof dimension.rank !== "number")
1126
+ ) {
1127
+ everyValueRanked = false;
1128
+ break;
1129
+ }
1130
+ ranks.set(
1131
+ value,
1132
+ Math.min(...matchingDimensions.map((dimension) => dimension.rank as number)),
1133
+ );
1134
+ }
1135
+ const sortedValues = everyValueRanked
1136
+ ? [...values].sort(
1137
+ (a, b) =>
1138
+ (ranks.get(a) ?? 0) - (ranks.get(b) ?? 0) || a.localeCompare(b),
1139
+ )
1140
+ : sortFacetValues(label, values);
1141
+ facets.push({ key: candidate.key, label, values: sortedValues });
1142
+ }
1143
+ return facets;
1144
+ }
1145
+
1146
+ function deriveFamily(
1147
+ name: string,
1148
+ parsed: ParsedTarget,
1149
+ usesArtifactFamily: boolean,
1150
+ ): string {
1151
+ if (usesArtifactFamily) {
1152
+ return [parsed.source, parsed.variable].filter(Boolean).join("/");
1153
+ }
1154
+ const parts = name.split("/");
1155
+ if (parts.length < 2) return name;
1156
+ const [geo, second] = parts;
1157
+ if (/^[A-Z]{2}$/.test(second)) return "state_distribution";
1158
+ if (/^US\d{2}$/.test(geo)) return second;
1159
+ return `${geo}/${second}`;
1160
+ }
1161
+
1162
+ function deriveState(name: string): string | null {
1163
+ const parts = name.split("/");
1164
+ return parts.length >= 2 && /^[A-Z]{2}$/.test(parts[1]) ? parts[1] : null;
1165
+ }
1166
+
1167
+ function skippedTargetReasons(skipped: unknown[]): Map<string, string> {
1168
+ const reasons = new Map<string, string>();
1169
+ for (const entry of skipped) {
1170
+ if (typeof entry === "string") {
1171
+ reasons.set(entry, "Skipped by calibration.");
1172
+ continue;
1173
+ }
1174
+ const row = asObject(entry);
1175
+ const name = stringValue(row.name) ?? stringValue(row.target_name);
1176
+ if (!name) continue;
1177
+ reasons.set(name, stringValue(row.reason) ?? "Skipped by calibration.");
1178
+ }
1179
+ return reasons;
1180
+ }
1181
+
1182
+ function targetNames(row: TargetRow, fullName: string, baseName: string): string[] {
1183
+ const names = [
1184
+ fullName,
1185
+ baseName,
1186
+ stringValue(row.name),
1187
+ stringValue(row.target_name),
1188
+ stringValue(asObject(row.metadata).ledger_source_record_id),
1189
+ ];
1190
+ return [...new Set(names.filter((name): name is string => Boolean(name)))];
1191
+ }
1192
+
1193
+ function calibrationStatus(
1194
+ row: TargetRow,
1195
+ names: string[],
1196
+ skippedByName: Map<string, string>,
1197
+ droppedTargetNames: Set<string>,
1198
+ ): {
1199
+ calibration_status: "included" | "skipped" | "not_materialized";
1200
+ calibration_status_label: string;
1201
+ calibration_status_reason: string | null;
1202
+ } {
1203
+ const skippedName = names.find((name) => skippedByName.has(name));
1204
+ if (skippedName) {
1205
+ return {
1206
+ calibration_status: "skipped",
1207
+ calibration_status_label: "Skipped",
1208
+ calibration_status_reason: skippedByName.get(skippedName) ?? "Skipped by calibration.",
1209
+ };
1210
+ }
1211
+ const droppedName = names.find((name) => droppedTargetNames.has(name));
1212
+ if (droppedName) {
1213
+ return {
1214
+ calibration_status: "not_materialized",
1215
+ calibration_status_label: "Not materialized",
1216
+ calibration_status_reason: "The target was declared but no model column/filter was materialized for it.",
1217
+ };
1218
+ }
1219
+ if (numberOrNull(row.initial_estimate) == null && numberOrNull(row.final_estimate) == null) {
1220
+ return {
1221
+ calibration_status: "not_materialized",
1222
+ calibration_status_label: "No estimate",
1223
+ calibration_status_reason: "The diagnostics row has no initial or final estimate.",
1224
+ };
1225
+ }
1226
+ return {
1227
+ calibration_status: "included",
1228
+ calibration_status_label: "Included",
1229
+ calibration_status_reason: null,
1230
+ };
1231
+ }
1232
+
1233
+ // Enrich a raw target row. Schema v2 publishes the canonical registry fields
1234
+ // (source citation, entity, aggregation, measure, period, target_name); we keep
1235
+ // the parsed geography/source/variable/breakdown for navigation and surface the
1236
+ // published metadata alongside. v1 rows simply lack those extra fields.
1237
+ function enrichTargetRow(
1238
+ rawRow: TargetRow,
1239
+ skippedByName: Map<string, string>,
1240
+ droppedTargetNames: Set<string>,
1241
+ artifactCountry: ArtifactCountry,
1242
+ publisherLabels: Record<string, string>,
1243
+ dimensionDefinitions: Record<string, DiagnosticsDimension>,
1244
+ rowRepresentation: TargetRowRepresentation,
1245
+ ): TargetRow {
1246
+ const nationalGeography = artifactCountry.geography_label;
1247
+ const metadata = normalizeChronicleMetadata(rawRow.metadata);
1248
+ const row: TargetRow = { ...rawRow, metadata };
1249
+ const fullName = String(row.name ?? "");
1250
+ // v2 carries target_name (no @period); else strip any @period from the name.
1251
+ const baseName = String(row.target_name ?? fullName.split("@")[0]);
1252
+ const status = calibrationStatus(
1253
+ row,
1254
+ targetNames(row, fullName, baseName),
1255
+ skippedByName,
1256
+ droppedTargetNames,
1257
+ );
1258
+ const target = numberOrNull(row.target);
1259
+ const initial = numberOrNull(row.initial_estimate);
1260
+ const final = numberOrNull(row.final_estimate);
1261
+ const errorKind = "relative";
1262
+ // Published diagnostics may carry a raw absolute miss in `relative_error`
1263
+ // for a zero target. Recompute that case so all releases use the structural-
1264
+ // zero rule consistently.
1265
+ const rawFinalError = target === 0
1266
+ ? relativeError(final, target)
1267
+ : numberOrNull(row.relative_error) ?? relativeError(final, target);
1268
+ const rawInitialError = relativeError(initial, target);
1269
+ const initialMiss = initial != null && target != null ? initial - target : null;
1270
+ const finalMiss = final != null && target != null ? final - target : null;
1271
+ const absInitialMiss = initialMiss == null ? null : Math.abs(initialMiss);
1272
+ const absFinalMiss = finalMiss == null ? null : Math.abs(finalMiss);
1273
+ const absoluteImprovement =
1274
+ absInitialMiss == null || absFinalMiss == null
1275
+ ? null
1276
+ : absInitialMiss - absFinalMiss;
1277
+ const initialError = rawInitialError;
1278
+ const finalError = rawFinalError;
1279
+ const absFinalError = finalError == null ? null : Math.abs(finalError);
1280
+ const improvement =
1281
+ initialError == null || finalError == null
1282
+ ? null
1283
+ : Math.abs(initialError) - Math.abs(finalError);
1284
+ const hierarchyIdentity = rowRepresentation === "hierarchy"
1285
+ ? readHierarchyTarget(row)
1286
+ : null;
1287
+ const structuredIdentity = rowRepresentation === "structured"
1288
+ ? readStructuredTarget(row, dimensionDefinitions, nationalGeography)
1289
+ : null;
1290
+ const filterDecomposition = hierarchyIdentity || structuredIdentity
1291
+ ? null
1292
+ : decomposeTargetFilter(row.filter);
1293
+ const dimensionAdapter = hierarchyIdentity
1294
+ ? "hierarchy"
1295
+ : structuredIdentity
1296
+ ? "structured"
1297
+ : filterDecomposition
1298
+ ? "legacy_filter"
1299
+ : "legacy_name";
1300
+ const legacyParsed = hierarchyIdentity || structuredIdentity
1301
+ ? null
1302
+ : readLegacyTarget(
1303
+ baseName,
1304
+ row,
1305
+ nationalGeography,
1306
+ filterDecomposition,
1307
+ );
1308
+ const parsed: ParsedTarget = hierarchyIdentity
1309
+ ? {
1310
+ geography: hierarchyIdentity.geography,
1311
+ level: hierarchyIdentity.level,
1312
+ source: hierarchyIdentity.source,
1313
+ variable: hierarchyIdentity.variable,
1314
+ breakdown: hierarchyIdentity.breakdown,
1315
+ }
1316
+ : structuredIdentity
1317
+ ? {
1318
+ geography: structuredIdentity.geography,
1319
+ level: structuredIdentity.level,
1320
+ source: structuredIdentity.source,
1321
+ variable: structuredIdentity.variable,
1322
+ breakdown: structuredIdentity.breakdown,
1323
+ }
1324
+ : legacyParsed!;
1325
+ const hasGeography = Boolean(parsed.geography.trim());
1326
+ const geography = hasGeography ? parsed.geography : nationalGeography;
1327
+ const level = hasGeography ? parsed.level : DEFAULT_GEOGRAPHY_LEVEL;
1328
+ const measureCol = asObject(row.measure);
1329
+ const metadataTargetDimensions =
1330
+ hierarchyIdentity?.dimensions ??
1331
+ structuredIdentity?.dimensions ??
1332
+ filterDecomposition?.dimensions ??
1333
+ metadataDimensions(row);
1334
+ const targetDimensions =
1335
+ metadataTargetDimensions ??
1336
+ splitBreakdown(parsed.breakdown).map((value, index) => ({
1337
+ key: `dim${index}`,
1338
+ label: classifyDimension([value]),
1339
+ value,
1340
+ }));
1341
+ const dims = targetDimensions.map((dim) => dim.value);
1342
+ const breakdown = metadataTargetDimensions ? dims.join(" · ") : parsed.breakdown;
1343
+ const sourceMeasureId = stringValue(metadata.source_measure_id);
1344
+ const targetRole = stringValue(metadata.target_role);
1345
+ const policyengineVariables = policyengineVariablesFromMetadata(metadata);
1346
+ // The first breakdown token is the measure (total / count / mean / …). Many
1347
+ // IRS variables publish both a total (dollar amount) and a count (number of
1348
+ // returns), so the measure is part of the variable's identity, not a
1349
+ // breakdown within it — fold it into variable_key so they're distinct things.
1350
+ const measure = structuredIdentity
1351
+ ? structuredIdentity.measure
1352
+ : dims[0] && MEASURES.has(dims[0])
1353
+ ? dims[0]
1354
+ : measureFromMetadata(metadata) ?? measureFromName(baseName.split(".").at(-1) ?? null);
1355
+ const variableKey =
1356
+ variableKeyOf(parsed) + (measure ? ` · ${measure}` : "");
1357
+ // Underscore identifiers and filter-decomposed targets use the structured
1358
+ // publisher/variable identity supplied by the artifact. Dotted identifiers
1359
+ // without filter dimensions retain their legacy family so US/UK releases do
1360
+ // not regroup merely because they also carry Chronicle record IDs.
1361
+ const usesArtifactFamily =
1362
+ hierarchyIdentity != null ||
1363
+ structuredIdentity != null ||
1364
+ filterDecomposition != null ||
1365
+ (chroniclePublisherFromMetadata(metadata) != null &&
1366
+ !baseName.includes("/") &&
1367
+ !baseName.includes("."));
1368
+ return {
1369
+ ...row,
1370
+ name: fullName,
1371
+ base_name: baseName,
1372
+ family: deriveFamily(baseName, parsed, usesArtifactFamily),
1373
+ state: hierarchyIdentity || structuredIdentity
1374
+ ? null
1375
+ : stateFromGeoId(stringValue(metadata.ledger_geography_id)) ??
1376
+ (parsed.level === "state" && /^[A-Z]{2}$/.test(parsed.geography)
1377
+ ? parsed.geography
1378
+ : deriveState(baseName)),
1379
+ geography,
1380
+ geography_id:
1381
+ hierarchyIdentity?.geographyId ??
1382
+ structuredIdentity?.geographyId ??
1383
+ stringValue(metadata.ledger_geography_id),
1384
+ geography_dimension_id: structuredIdentity?.geographyDimensionId ?? null,
1385
+ geography_rank: structuredIdentity?.geographyRank ?? null,
1386
+ level,
1387
+ source: parsed.source,
1388
+ source_label:
1389
+ hierarchyIdentity?.sourceLabel ??
1390
+ (Object.hasOwn(publisherLabels, parsed.source)
1391
+ ? publisherLabels[parsed.source]
1392
+ : undefined) ??
1393
+ structuredIdentity?.sourceLabel ??
1394
+ sourceAuthorityLabel(parsed.source),
1395
+ variable: parsed.variable,
1396
+ variable_label:
1397
+ hierarchyIdentity?.variableLabel ?? structuredIdentity?.variableLabel ?? null,
1398
+ target_label: hierarchyIdentity?.targetLabel,
1399
+ measure,
1400
+ target_role: targetRole,
1401
+ source_measure_id: sourceMeasureId,
1402
+ policyengine_variables: policyengineVariables.length
1403
+ ? policyengineVariables
1404
+ : fallbackPolicyengineVariables(metadata),
1405
+ policyengine_map_to: stringValue(metadata.count_map_to) ?? fallbackPolicyengineMapTo(metadata),
1406
+ policyengine_filter_variable: stringValue(metadata.count_filter_variable) ?? fallbackPolicyengineFilterVariable(metadata),
1407
+ materializer: stringValue(metadata.materializer),
1408
+ measure_mode: stringValue(metadata.measure_mode) ?? fallbackMeasureMode(metadata),
1409
+ error_kind: errorKind,
1410
+ initial_error: initialError,
1411
+ final_error: finalError,
1412
+ initial_miss: initialMiss,
1413
+ final_miss: finalMiss,
1414
+ abs_final_miss: absFinalMiss,
1415
+ absolute_improvement: absoluteImprovement,
1416
+ abs_error: absFinalError,
1417
+ breakdown,
1418
+ dims,
1419
+ target_dimensions: targetDimensions,
1420
+ dimension_adapter: dimensionAdapter,
1421
+ target_representation: rowRepresentation,
1422
+ variable_key: variableKey,
1423
+ // v2 published metadata (null on v1).
1424
+ source_citation:
1425
+ structuredIdentity?.sourceCitation ??
1426
+ (typeof row.source === "string"
1427
+ ? (row.source as string)
1428
+ : null),
1429
+ source_url: structuredIdentity?.sourceUrl ?? null,
1430
+ entity: typeof row.entity === "string" ? (row.entity as string) : null,
1431
+ aggregation: typeof row.aggregation === "string" ? (row.aggregation as string) : null,
1432
+ measure_name: typeof measureCol.name === "string" ? (measureCol.name as string) : null,
1433
+ period: numberOrNull(row.period),
1434
+ chronicle: chronicleFactFields(metadata),
1435
+ relative_error: finalError,
1436
+ initial_relative_error: initialError,
1437
+ abs_relative_error: absFinalError,
1438
+ improvement,
1439
+ direction: finalError == null ? null : finalError > 0 ? "over" : finalError < 0 ? "under" : "exact",
1440
+ ...status,
1441
+ };
1442
+ }
1443
+
1444
+ function estimateScopeKey(row: TargetRow): string | null {
1445
+ if (row.filter != null || row.dimensions != null) return null;
1446
+ const metadata = asObject(row.metadata);
1447
+ const recordSet = stringValue(metadata.ledger_layout_record_set_id);
1448
+ const initial = numberOrNull(row.initial_estimate);
1449
+ const final = numberOrNull(row.final_estimate);
1450
+ if (!recordSet || initial == null || final == null) return null;
1451
+ return [
1452
+ row.source,
1453
+ row.period,
1454
+ metadata.ledger_geography_id,
1455
+ metadata.ledger_layout_groupby_dimension,
1456
+ metadata.ledger_layout_groupby_value_id,
1457
+ metadata.ledger_layout_measure_id,
1458
+ metadata.source_measure_id,
1459
+ metadata.variable,
1460
+ initial,
1461
+ final,
1462
+ ].join("||");
1463
+ }
1464
+
1465
+ function estimateScopeWarning(row: TargetRow): string {
1466
+ const metadata = asObject(row.metadata);
1467
+ const childGroup = qualifyingChildrenFromRecordSet(
1468
+ stringValue(metadata.ledger_layout_record_set_id),
1469
+ );
1470
+ if (childGroup) {
1471
+ return "This Chronicle fact is for a qualifying-children slice, but the calibration diagnostics did not include a compiled model filter for that child-count slice. The estimate may reflect the broader EITC aggregate instead of this exact slice.";
1472
+ }
1473
+ return "This Chronicle fact is one slice of a target family, but the calibration diagnostics did not include a compiled model filter for this slice and sibling slices share the same estimate. The estimate may reflect a broader aggregate than this exact fact.";
1474
+ }
1475
+
1476
+ function addEstimateScopeWarnings(rows: TargetRow[]): TargetRow[] {
1477
+ const groups = new Map<string, TargetRow[]>();
1478
+ for (const row of rows) {
1479
+ const key = estimateScopeKey(row);
1480
+ if (!key) continue;
1481
+ (groups.get(key) ?? groups.set(key, []).get(key)!).push(row);
1482
+ }
1483
+
1484
+ const flagged = new Set<TargetRow>();
1485
+ for (const group of groups.values()) {
1486
+ const recordSets = new Set(
1487
+ group
1488
+ .map((row) => stringValue(asObject(row.metadata).ledger_layout_record_set_id))
1489
+ .filter((value): value is string => Boolean(value)),
1490
+ );
1491
+ const targets = new Set(group.map((row) => numberOrNull(row.target)));
1492
+ if (recordSets.size <= 1 || targets.size <= 1) continue;
1493
+ for (const row of group) flagged.add(row);
1494
+ }
1495
+
1496
+ if (!flagged.size) return rows;
1497
+ return rows.map((row) =>
1498
+ flagged.has(row)
1499
+ ? {
1500
+ ...row,
1501
+ estimate_warning: estimateScopeWarning(row),
1502
+ }
1503
+ : row,
1504
+ );
1505
+ }
1506
+
1507
+ function stringParam(value: string | null): string | null {
1508
+ const trimmed = value?.trim();
1509
+ return trimmed ? trimmed : null;
1510
+ }
1511
+
1512
+ function splitVariableList(value: unknown): string[] {
1513
+ if (Array.isArray(value)) {
1514
+ return value
1515
+ .flatMap(splitVariableList)
1516
+ .filter((variable, index, all) => all.indexOf(variable) === index);
1517
+ }
1518
+ if (typeof value !== "string") return [];
1519
+ return value
1520
+ .split(",")
1521
+ .map((variable) => variable.trim())
1522
+ .filter(Boolean);
1523
+ }
1524
+
1525
+ function policyengineVariablesFromMetadata(metadata: JsonObject): string[] {
1526
+ const variables = [
1527
+ ...splitVariableList(metadata.base_variables),
1528
+ ...splitVariableList(metadata.base_variable),
1529
+ ];
1530
+ return variables.filter((variable, index) => variables.indexOf(variable) === index);
1531
+ }
1532
+
1533
+ // Chronicle measure concept -> the model variable that the
1534
+ // integrations/microcosm_policyengine_us/mappings.yaml entry for that concept
1535
+ // evaluates (`source_expression`). Releases publish these targets without
1536
+ // `base_variables`, so without this table they carry no PolicyEngine
1537
+ // variable. Concepts whose source expression is not a model variable (for
1538
+ // example census_pep.resident_population, `__ones__`) and concepts without a
1539
+ // mapping (for example jct.individual_tax_expenditure_revenue_loss) stay
1540
+ // empty. A test in latest-artifact.test.ts keeps this table in sync
1541
+ // with the mappings file.
1542
+ export const MAPPED_MEASURE_CONCEPT_VARIABLES: Readonly<Record<string, readonly string[]>> = {
1543
+ "census_stc.individual_income_tax_collections": ["state_income_tax"],
1544
+ "irs_soi.individual_income_tax_returns": ["tax_unit_is_filer"],
1545
+ };
1546
+
1547
+ function fallbackPolicyengineVariables(metadata: JsonObject): string[] {
1548
+ const targetRole = stringValue(metadata.target_role);
1549
+ const sourceMeasureId = stringValue(metadata.source_measure_id);
1550
+ const measureConcept = stringValue(metadata.ledger_measure_concept);
1551
+ if (measureConcept && Object.hasOwn(MAPPED_MEASURE_CONCEPT_VARIABLES, measureConcept)) {
1552
+ return [...MAPPED_MEASURE_CONCEPT_VARIABLES[measureConcept]];
1553
+ }
1554
+ if (
1555
+ targetRole === "aca_spending" ||
1556
+ targetRole === "aca_ptc_recipients" ||
1557
+ sourceMeasureId === "premium_tax_credit_amount" ||
1558
+ sourceMeasureId === "premium_tax_credit_returns"
1559
+ ) {
1560
+ return ["assigned_aca_ptc"];
1561
+ }
1562
+ if (targetRole === "aca_enrollment") {
1563
+ return ["has_marketplace_health_coverage_at_interview"];
1564
+ }
1565
+ if (targetRole === "medicaid_spending") {
1566
+ return ["medicaid"];
1567
+ }
1568
+ if (targetRole === "medicaid_enrollment") {
1569
+ return ["medicaid_enrolled"];
1570
+ }
1571
+ if (targetRole === "medicaid_chip_enrollment") {
1572
+ return ["medicaid_enrolled", "chip_enrolled"];
1573
+ }
1574
+ if (targetRole === "medicare_part_b_premium_total") {
1575
+ return ["gross_medicare_part_b_premium"];
1576
+ }
1577
+ return [];
1578
+ }
1579
+
1580
+ function fallbackPolicyengineMapTo(metadata: JsonObject): string | null {
1581
+ return stringValue(metadata.target_role) === "aca_ptc_recipients" ? "person" : null;
1582
+ }
1583
+
1584
+ function fallbackPolicyengineFilterVariable(metadata: JsonObject): string | null {
1585
+ return stringValue(metadata.target_role) === "aca_ptc_recipients"
1586
+ ? "is_aca_ptc_eligible"
1587
+ : null;
1588
+ }
1589
+
1590
+ function fallbackMeasureMode(metadata: JsonObject): string | null {
1591
+ const targetRole = stringValue(metadata.target_role);
1592
+ if (
1593
+ targetRole === "aca_enrollment" ||
1594
+ targetRole === "aca_ptc_recipients" ||
1595
+ targetRole === "medicaid_enrollment" ||
1596
+ targetRole === "medicaid_chip_enrollment"
1597
+ ) {
1598
+ return "positive_count";
1599
+ }
1600
+ if (
1601
+ targetRole === "aca_spending" ||
1602
+ targetRole === "medicaid_spending" ||
1603
+ targetRole === "medicare_part_b_premium_total"
1604
+ ) {
1605
+ return "sum";
1606
+ }
1607
+ return null;
1608
+ }
1609
+
1610
+ function booleanParam(value: string | null): boolean | null {
1611
+ if (value == null || value === "") return null;
1612
+ if (["1", "true", "yes"].includes(value.toLowerCase())) return true;
1613
+ if (["0", "false", "no"].includes(value.toLowerCase())) return false;
1614
+ return null;
1615
+ }
1616
+
1617
+ function matchesSearch(row: TargetRow, search: string): boolean {
1618
+ const haystack = [
1619
+ row.name, row.variable, row.source, row.breakdown, row.geography, row.state,
1620
+ row.source_citation,
1621
+ ]
1622
+ .filter((v) => v != null)
1623
+ .join(" ")
1624
+ .toLowerCase();
1625
+ return haystack.includes(search.toLowerCase());
1626
+ }
1627
+
1628
+ const HEALTHCARE_TARGET_ROLES = new Set([
1629
+ "aca_spending",
1630
+ "aca_enrollment",
1631
+ "aca_ptc_recipients",
1632
+ "aca_bronze_aptc_consumers",
1633
+ "medicaid_spending",
1634
+ "medicaid_enrollment",
1635
+ "medicaid_chip_enrollment",
1636
+ "medicare_part_b_premium_total",
1637
+ ]);
1638
+
1639
+ function isHealthcareTarget(row: TargetRow): boolean {
1640
+ const metadata = asObject(row.metadata);
1641
+ const targetRole = stringValue(metadata.target_role);
1642
+ if (targetRole && HEALTHCARE_TARGET_ROLES.has(targetRole)) return true;
1643
+
1644
+ const haystack = [
1645
+ row.name,
1646
+ row.family,
1647
+ row.source,
1648
+ row.variable,
1649
+ row.variable_key,
1650
+ metadata.source_measure_id,
1651
+ metadata.ledger_measure_concept,
1652
+ metadata.ledger_domain,
1653
+ ]
1654
+ .filter((value) => value != null)
1655
+ .join(" ")
1656
+ .toLowerCase();
1657
+
1658
+ return (
1659
+ haystack.includes("cms_aca") ||
1660
+ haystack.includes("cms_medicaid") ||
1661
+ haystack.includes("cms_medicare") ||
1662
+ haystack.includes("medicaid") ||
1663
+ haystack.includes("chip") ||
1664
+ haystack.includes("medicare") ||
1665
+ haystack.includes("premium tax credit") ||
1666
+ haystack.includes("aca_ptc")
1667
+ );
1668
+ }
1669
+
1670
+ function withinToleranceCount(rows: TargetRow[]): number {
1671
+ return rows.filter((row) => row.within_tolerance === true).length;
1672
+ }
1673
+
1674
+ export function microcosmTargetFamilies(rows: TargetRow[]): string[] {
1675
+ return [...new Set(rows.map((row) => String(row.family ?? "")))].sort();
1676
+ }
1677
+
1678
+ export function microcosmTargetSources(rows: TargetRow[]): string[] {
1679
+ return [...new Set(rows.map((row) => String(row.source ?? "")))].filter(Boolean).sort();
1680
+ }
1681
+
1682
+ export function microcosmTargetLevels(rows: TargetRow[]): string[] {
1683
+ return [...new Set(rows.map((row) => String(row.level ?? "")))].filter(Boolean).sort();
1684
+ }
1685
+
1686
+ export function microcosmTargetGeographies(rows: TargetRow[]): string[] {
1687
+ return [...new Set(rows.map((row) => String(row.geography ?? "")))]
1688
+ .filter(Boolean)
1689
+ .sort((a, b) =>
1690
+ a === "United States" ? -1 : b === "United States" ? 1 : a.localeCompare(b),
1691
+ );
1692
+ }
1693
+
1694
+ // Every level a category's targets sit at, and its one level when it has
1695
+ // just one. A category at two levels (an FSA measure: 14 country and 51 state
1696
+ // targets) has no single level, so its level is null. A category with no
1697
+ // level takes `none`, which each caller keeps from before.
1698
+ function categoryLevels(
1699
+ group: TargetRow[],
1700
+ none: string | null,
1701
+ ): { level: string | null; levels: string[] } {
1702
+ const levels = microcosmTargetLevels(group);
1703
+ return { level: levels.length > 1 ? null : (levels[0] ?? none), levels };
1704
+ }
1705
+
1706
+ export function microcosmVariableSummary(rows: TargetRow[]) {
1707
+ const groups = new Map<string, TargetRow[]>();
1708
+ for (const row of rows) {
1709
+ const key = String(row.variable_key ?? "");
1710
+ if (!key) continue;
1711
+ (groups.get(key) ?? groups.set(key, []).get(key)!).push(row);
1712
+ }
1713
+ return [...groups.entries()]
1714
+ .map(([variable_key, group]) => {
1715
+ const first = group[0];
1716
+ const absErrors = group
1717
+ .map((row) => numberOrNull(row.abs_relative_error))
1718
+ .filter((v): v is number => v != null);
1719
+ const policyengineVariables = [
1720
+ ...new Set(
1721
+ group.flatMap((row) =>
1722
+ Array.isArray(row.policyengine_variables)
1723
+ ? row.policyengine_variables.filter(
1724
+ (value): value is string => typeof value === "string",
1725
+ )
1726
+ : [],
1727
+ ),
1728
+ ),
1729
+ ];
1730
+ const uniqueString = (key: string) => {
1731
+ const values = [
1732
+ ...new Set(
1733
+ group
1734
+ .map((row) => row[key])
1735
+ .filter(
1736
+ (value): value is string =>
1737
+ typeof value === "string" && value.length > 0,
1738
+ ),
1739
+ ),
1740
+ ];
1741
+ return values.length === 1 ? values[0] : null;
1742
+ };
1743
+ return {
1744
+ variable_key,
1745
+ source: String(first.source ?? ""),
1746
+ source_label: String(
1747
+ first.source_label ?? sourceAuthorityLabel(String(first.source ?? "")),
1748
+ ),
1749
+ variable: String(first.variable ?? ""),
1750
+ variable_label: uniqueString("variable_label"),
1751
+ measure: first.measure ? String(first.measure) : null,
1752
+ ...categoryLevels(group, ""),
1753
+ policyengine_variables: policyengineVariables,
1754
+ policyengine_map_to: uniqueString("policyengine_map_to"),
1755
+ policyengine_filter_variable: uniqueString("policyengine_filter_variable"),
1756
+ materializer: uniqueString("materializer"),
1757
+ measure_mode: uniqueString("measure_mode"),
1758
+ n_targets: group.length,
1759
+ within_10pct: group.filter((r) => (numberOrNull(r.abs_relative_error) ?? Infinity) <= 0.1).length,
1760
+ within_tolerance: group.filter((r) => r.within_tolerance === true).length,
1761
+ mean_abs_relative_error: absErrors.length
1762
+ ? absErrors.reduce((s, v) => s + v, 0) / absErrors.length
1763
+ : null,
1764
+ };
1765
+ })
1766
+ .sort((a, b) => b.n_targets - a.n_targets);
1767
+ }
1768
+
1769
+ function familyFitSummary(rows: TargetRow[]) {
1770
+ const groups = new Map<string, TargetRow[]>();
1771
+ for (const row of rows) {
1772
+ const family = String(row.family ?? "");
1773
+ (groups.get(family) ?? groups.set(family, []).get(family)!).push(row);
1774
+ }
1775
+ return [...groups.entries()]
1776
+ .map(([family, group]) => {
1777
+ const absErrors = group
1778
+ .map((row) => numberOrNull(row.abs_relative_error))
1779
+ .filter((v): v is number => v != null);
1780
+ return {
1781
+ family,
1782
+ n_targets: group.length,
1783
+ within_tolerance: withinToleranceCount(group),
1784
+ within_10pct: group.filter((r) => (numberOrNull(r.abs_relative_error) ?? Infinity) <= 0.1).length,
1785
+ mean_abs_relative_error: absErrors.length ? absErrors.reduce((s, v) => s + v, 0) / absErrors.length : null,
1786
+ };
1787
+ })
1788
+ .sort((a, b) => b.n_targets - a.n_targets);
1789
+ }
1790
+
1791
+ // --- calibration map (treemap) ----------------------------------------------
1792
+
1793
+ export type TreemapBreakdown = "program" | "geography";
1794
+
1795
+ export interface TreemapFilters {
1796
+ program?: string;
1797
+ geography?: string;
1798
+ }
1799
+
1800
+ function median(values: number[]): number | null {
1801
+ if (!values.length) return null;
1802
+ const sorted = [...values].sort((a, b) => a - b);
1803
+ const mid = Math.floor(sorted.length / 2);
1804
+ return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
1805
+ }
1806
+
1807
+ export interface TreemapLeaf {
1808
+ key: string;
1809
+ source: string;
1810
+ variable: string;
1811
+ label: string | null;
1812
+ measure: string | null;
1813
+ measure_counts: { measure: string | null; n_targets: number }[];
1814
+ filters: TreemapFilters;
1815
+ n_targets: number;
1816
+ within_10pct: number;
1817
+ scored: number;
1818
+ loss: number;
1819
+ mean_abs_relative_error: number | null;
1820
+ median_abs_relative_error: number | null;
1821
+ }
1822
+
1823
+ export interface TreemapGroup {
1824
+ source: string;
1825
+ label: string;
1826
+ n_targets: number;
1827
+ within_10pct: number;
1828
+ scored: number;
1829
+ loss: number;
1830
+ mean_abs_relative_error: number | null;
1831
+ median_abs_relative_error: number | null;
1832
+ children: TreemapLeaf[];
1833
+ }
1834
+
1835
+ export interface TreemapData {
1836
+ release_id: string;
1837
+ loss_attribution_available: boolean;
1838
+ total_targets: number;
1839
+ total_within_10pct: number;
1840
+ total_scored: number;
1841
+ total_loss: number;
1842
+ groups: TreemapGroup[];
1843
+ }
1844
+
1845
+ function targetProgramKey(row: TargetRow): string {
1846
+ const variableKey = String(row.variable_key ?? "").trim();
1847
+ if (variableKey) return variableKey.replace(/\s+·\s+(count|total|amount|mean)$/i, "");
1848
+ const source = String(row.source ?? "").trim();
1849
+ const variable = String(row.variable ?? "").trim();
1850
+ if (source && variable) return `${source} / ${variable}`;
1851
+ return String(row.name ?? row.target_name ?? "unknown");
1852
+ }
1853
+
1854
+ function targetGeographyKey(row: TargetRow): string {
1855
+ const geography = String(row.geography ?? "").trim();
1856
+ return geography || DEFAULT_GEOGRAPHY;
1857
+ }
1858
+
1859
+ function measureCounts(rows: TargetRow[]): { measure: string | null; n_targets: number }[] {
1860
+ const counts = new Map<string, { measure: string | null; n_targets: number }>();
1861
+ for (const row of rows) {
1862
+ const measure = String(row.measure ?? "").trim() || null;
1863
+ const key = measure ?? "__missing__";
1864
+ const current = counts.get(key) ?? { measure, n_targets: 0 };
1865
+ current.n_targets += 1;
1866
+ counts.set(key, current);
1867
+ }
1868
+ return [...counts.values()].sort((a, b) => {
1869
+ const rank = (value: string | null) =>
1870
+ value === "total" || value == null ? 0 : value === "count" ? 1 : 2;
1871
+ return (
1872
+ rank(a.measure) - rank(b.measure) ||
1873
+ String(a.measure ?? "").localeCompare(String(b.measure ?? ""))
1874
+ );
1875
+ });
1876
+ }
1877
+
1878
+ function treemapRows(
1879
+ rows: TargetRow[],
1880
+ breakdown: TreemapBreakdown,
1881
+ ): Map<string, Map<string, TargetRow[]>> {
1882
+ const groups = new Map<string, Map<string, TargetRow[]>>();
1883
+ for (const row of rows) {
1884
+ const source =
1885
+ breakdown === "geography"
1886
+ ? "geography"
1887
+ : String(row.source ?? "").trim() || "other";
1888
+ const key =
1889
+ breakdown === "geography" ? targetGeographyKey(row) : targetProgramKey(row);
1890
+ const byLeaf = groups.get(source) ?? groups.set(source, new Map()).get(source)!;
1891
+ (byLeaf.get(key) ?? byLeaf.set(key, []).get(key)!).push(row);
1892
+ }
1893
+ return groups;
1894
+ }
1895
+
1896
+ // Build the source → variable hierarchy that powers the calibration map.
1897
+ // Each leaf carries both "how much we calibrate to it" (n_targets) and "how
1898
+ // much weighted capped target error lands here. Loss is the sum of normalized
1899
+ // per-target final_loss_contribution values produced by the artifact adapter;
1900
+ // relative-error metrics remain separate fit diagnostics.
1901
+ export function microcosmTargetTreemap(
1902
+ rows: TargetRow[],
1903
+ releaseId: string,
1904
+ breakdown: TreemapBreakdown = "program",
1905
+ lossAttributionAvailable = rows.length > 0 && rows.every(
1906
+ (row) => numberOrNull(row.final_loss_contribution) != null,
1907
+ ),
1908
+ ): TreemapData {
1909
+ const groups = treemapRows(rows, breakdown);
1910
+
1911
+ const leafOf = (source: string, key: string, group: TargetRow[]): TreemapLeaf => {
1912
+ const absErrors = group
1913
+ .map((row) => numberOrNull(row.abs_relative_error))
1914
+ .filter((v): v is number => v != null && Number.isFinite(v));
1915
+ const first = group[0];
1916
+ const variableLabels = [
1917
+ ...new Set(
1918
+ group
1919
+ .map((row) => stringValue(row.variable_label)?.trim())
1920
+ .filter((label): label is string => Boolean(label)),
1921
+ ),
1922
+ ];
1923
+ const filters: TreemapFilters =
1924
+ breakdown === "geography"
1925
+ ? { geography: key }
1926
+ : { program: key };
1927
+ return {
1928
+ key,
1929
+ source,
1930
+ variable:
1931
+ breakdown === "geography"
1932
+ ? key
1933
+ : String(first.variable ?? key),
1934
+ label:
1935
+ breakdown === "geography" || variableLabels.length !== 1
1936
+ ? null
1937
+ : variableLabels[0],
1938
+ measure: null,
1939
+ measure_counts: measureCounts(group),
1940
+ filters,
1941
+ n_targets: group.length,
1942
+ scored: absErrors.length,
1943
+ within_10pct: absErrors.filter((v) => v <= 0.1).length,
1944
+ loss: group.reduce(
1945
+ (sum, row) => sum + (numberOrNull(row.final_loss_contribution) ?? 0),
1946
+ 0,
1947
+ ),
1948
+ mean_abs_relative_error: absErrors.length
1949
+ ? absErrors.reduce((s, v) => s + v, 0) / absErrors.length
1950
+ : null,
1951
+ median_abs_relative_error: median(absErrors),
1952
+ };
1953
+ };
1954
+
1955
+ const groupList: TreemapGroup[] = [...groups.entries()]
1956
+ .map(([source, byVar]) => {
1957
+ const children = [...byVar.entries()]
1958
+ .map(([key, group]) => leafOf(source, key, group))
1959
+ .sort((a, b) => b.n_targets - a.n_targets);
1960
+ const allErrors = [...byVar.values()]
1961
+ .flat()
1962
+ .map((row) => numberOrNull(row.abs_relative_error))
1963
+ .filter((v): v is number => v != null && Number.isFinite(v));
1964
+ const n_targets = children.reduce((s, c) => s + c.n_targets, 0);
1965
+ const scored = children.reduce((s, c) => s + c.scored, 0);
1966
+ const within_10pct = children.reduce((s, c) => s + c.within_10pct, 0);
1967
+ const loss = children.reduce((s, c) => s + c.loss, 0);
1968
+ const rowSourceLabel = [...byVar.values()]
1969
+ .flat()
1970
+ .map((row) => stringValue(row.source_label))
1971
+ .find((label): label is string => label != null);
1972
+ return {
1973
+ source,
1974
+ label:
1975
+ source === "geography"
1976
+ ? "Geography"
1977
+ : rowSourceLabel ?? sourceAuthorityLabel(source),
1978
+ n_targets,
1979
+ scored,
1980
+ within_10pct,
1981
+ loss,
1982
+ mean_abs_relative_error: allErrors.length
1983
+ ? allErrors.reduce((s, v) => s + v, 0) / allErrors.length
1984
+ : null,
1985
+ median_abs_relative_error: median(allErrors),
1986
+ children,
1987
+ };
1988
+ })
1989
+ .sort((a, b) => b.n_targets - a.n_targets);
1990
+
1991
+ return {
1992
+ release_id: releaseId,
1993
+ loss_attribution_available: lossAttributionAvailable,
1994
+ total_targets: groupList.reduce((s, g) => s + g.n_targets, 0),
1995
+ total_within_10pct: groupList.reduce((s, g) => s + g.within_10pct, 0),
1996
+ total_scored: groupList.reduce((s, g) => s + g.scored, 0),
1997
+ total_loss: groupList.reduce((s, g) => s + g.loss, 0),
1998
+ groups: groupList,
1999
+ };
2000
+ }
2001
+
2002
+ // --- the calibration source (one release) -----------------------------------
2003
+ export interface TargetSchema {
2004
+ diagnostics_schema_version: number | null;
2005
+ structured_dimensions: boolean;
2006
+ target_representation: TargetRepresentation;
2007
+ }
2008
+
2009
+ export interface Calibration {
2010
+ // `huggingface_staged_bundle`: an unreleased candidate read from the staged
2011
+ // bundle its build uploaded to the release repository (`staged/<run_id>/`),
2012
+ // pinned to the commit the run recorded.
2013
+ source:
2014
+ | "huggingface_immutable"
2015
+ | "huggingface_live"
2016
+ | "huggingface_staged_bundle"
2017
+ | "local_filesystem";
2018
+ hf_commit_sha: string | null;
2019
+ country: MicrocosmCountry;
2020
+ // Typed `release_manifest.country` merged over the registration.
2021
+ country_info: ArtifactCountry;
2022
+ presentation: ArtifactPresentation | null;
2023
+ publisher_labels: Record<string, string>;
2024
+ target_schema: TargetSchema;
2025
+ description: string | null;
2026
+ diagnostics_status: DiagnosticsStatus;
2027
+ release_id: string;
2028
+ // The `releases/` folder the files were read from, set for a tagged
2029
+ // Microcosm build (released as its tag but stored under its release's
2030
+ // folder, microcosm#823) and for a build in its own folder (where it equals
2031
+ // release_id); absent for a release folder.
2032
+ release_directory?: string;
2033
+ updated_at: string | null;
2034
+ schema_version: unknown;
2035
+ weight_entity: unknown;
2036
+ options: JsonObject;
2037
+ l0_lambda: number | null;
2038
+ n_nonzero: number | null;
2039
+ n_records: number | null;
2040
+ effective_sample_size: number | null;
2041
+ realized_max_weight_ratio: number | null;
2042
+ top_1pct_weight_share: number | null;
2043
+ initial_loss: number | null;
2044
+ final_loss: number | null;
2045
+ loss_kind: CalibrationLossKind;
2046
+ fraction_within_10pct: number | null;
2047
+ loss_trajectory: number[];
2048
+ skipped: unknown[];
2049
+ declared_targets: number | null;
2050
+ compiled_candidate_targets: number | null;
2051
+ dropped_target_names: string[];
2052
+ included_target_count: number;
2053
+ diagnostics_build: JsonObject;
2054
+ diagnostic_warnings: TargetLossDiagnosticWarning[];
2055
+ target_loss_basis: JsonObject | null;
2056
+ target_loss_attribution: FinalTargetLossAttribution;
2057
+ calibration_provenance: CalibrationProvenance;
2058
+ // Identifiers this file labels more than one way across publishers (schema
2059
+ // 8 hierarchy files only); the first spelling is the one shown.
2060
+ hierarchy_label_variants: HierarchyLabelVariant[];
2061
+ build_manifest: JsonObject;
2062
+ release_manifest: JsonObject;
2063
+ // demographics.json geography_coverage: unweighted household-record counts
2064
+ // by state / congressional district (the release's sub-national resolution
2065
+ // floor). Null for releases published before the section existed.
2066
+ geography_coverage: JsonObject | null;
2067
+ rows: TargetRow[];
2068
+ }
2069
+
2070
+ interface ReleaseCacheEntry {
2071
+ expiresAt: number;
2072
+ promise: Promise<Calibration>;
2073
+ }
2074
+
2075
+ interface TargetDiagnosticsMetadata {
2076
+ sources: string[];
2077
+ levels: string[];
2078
+ geographies: string[];
2079
+ variables: ReturnType<typeof microcosmVariableSummary>;
2080
+ // Targets per named scope (the `scope` query parameter); a scope with no
2081
+ // targets in the release has nothing to focus on.
2082
+ scope_counts: { healthcare: number };
2083
+ }
2084
+
2085
+ interface InvestigationSignal {
2086
+ tone: "critical" | "warning" | "neutral" | "positive";
2087
+ label: string;
2088
+ detail: string;
2089
+ }
2090
+
2091
+ interface InvestigationSearch {
2092
+ label: string;
2093
+ query: string;
2094
+ url: string;
2095
+ }
2096
+
2097
+ const releaseCache = new Map<string, ReleaseCacheEntry>();
2098
+ const targetDiagnosticsMetadataCache = new WeakMap<TargetRow[], TargetDiagnosticsMetadata>();
2099
+
2100
+ // Whether this release's per-target diagnostics could be read at all. "ok" is
2101
+ // the normal case; "empty" is a diagnostics file that declares no targets; and
2102
+ // "incompatible" is a diagnostics file that has target rows we cannot read as
2103
+ // calibration fit under any known schema. The dashboard renders an explicit
2104
+ // state for the last two so a release never silently shows "0 targets".
2105
+ export type DiagnosticsStatus = "ok" | "empty" | "incompatible";
2106
+
2107
+ // The national release pipeline writes each target row with canonical fit
2108
+ // fields (`target`, `final_estimate`, `initial_estimate`). Some non-default
2109
+ // artifacts are built by custom drivers that name the same quantities
2110
+ // `value`/`estimate` instead — the Build L ACS local-area release is the first
2111
+ // (microcosm#398: non-default artifacts route around the national pipeline).
2112
+ // Its rows carry no `target`/`final_estimate`, so every downstream reader —
2113
+ // inclusion status, fit, improvement — read them as "no estimate" and the
2114
+ // dashboard reported zero calibrated targets for a release with 742 of them.
2115
+ // Map the aliases onto the canonical names so one schema flows downstream,
2116
+ // regardless of which driver wrote the file (a copy is made only when a row
2117
+ // actually needs it, and an existing canonical value is never overwritten).
2118
+ const DIAGNOSTICS_FIELD_ALIASES: ReadonlyArray<readonly [string, string]> = [
2119
+ ["target", "value"],
2120
+ ["final_estimate", "estimate"],
2121
+ ["initial_estimate", "initial_value"],
2122
+ ];
2123
+
2124
+ function normalizeDiagnosticsRow(row: TargetRow): TargetRow {
2125
+ let normalized: TargetRow | null = null;
2126
+ for (const [canonical, alias] of DIAGNOSTICS_FIELD_ALIASES) {
2127
+ if (numberOrNull(row[canonical]) != null) continue;
2128
+ const aliased = numberOrNull(row[alias]);
2129
+ if (aliased == null) continue;
2130
+ normalized ??= { ...row };
2131
+ normalized[canonical] = aliased;
2132
+ }
2133
+ return normalized ?? row;
2134
+ }
2135
+
2136
+ function diagnosticsStatus(diag: JsonObject, rows: TargetRow[]): DiagnosticsStatus {
2137
+ if (!Array.isArray(diag.targets)) return "incompatible";
2138
+ if (rows.length === 0) return "empty";
2139
+ // Rows are present but not one carries a usable target value or estimate under
2140
+ // any known schema: the diagnostics exist but cannot be read as fit.
2141
+ const anyUsable = rows.some(
2142
+ (row) => numberOrNull(row.target) != null || numberOrNull(row.final_estimate) != null,
2143
+ );
2144
+ return anyUsable ? "ok" : "incompatible";
2145
+ }
2146
+
2147
+ export interface ArtifactPresentation {
2148
+ overview_intro?: string;
2149
+ targets_intro?: string;
2150
+ }
2151
+
2152
+ function presentationText(value: unknown): string | null {
2153
+ if (typeof value !== "string") return null;
2154
+ const trimmed = value.trim();
2155
+ return trimmed ? trimmed.slice(0, 600) : null;
2156
+ }
2157
+
2158
+ export function releasePresentation(
2159
+ releaseManifest: JsonObject,
2160
+ ): ArtifactPresentation | null {
2161
+ const block = asObject(releaseManifest.presentation);
2162
+ const overviewIntro = presentationText(block.overview_intro);
2163
+ const targetsIntro = presentationText(block.targets_intro);
2164
+ if (!overviewIntro && !targetsIntro) return null;
2165
+ return {
2166
+ ...(overviewIntro ? { overview_intro: overviewIntro } : {}),
2167
+ ...(targetsIntro ? { targets_intro: targetsIntro } : {}),
2168
+ };
2169
+ }
2170
+
2171
+ export function releasePublisherLabels(
2172
+ releaseManifest: JsonObject,
2173
+ ): Record<string, string> {
2174
+ const block = releaseManifest.publisher_labels;
2175
+ if (!isPlainObject(block)) return {};
2176
+ return Object.fromEntries(
2177
+ Object.entries(block).flatMap(([key, value]) => {
2178
+ if (!/^[a-z][a-z0-9_]*$/i.test(key) || typeof value !== "string") return [];
2179
+ const label = value.trim();
2180
+ return label ? [[key, label]] : [];
2181
+ }),
2182
+ );
2183
+ }
2184
+
2185
+ export interface ReleaseRole {
2186
+ dataset_role: string | null;
2187
+ is_default: boolean;
2188
+ is_local_area: boolean;
2189
+ }
2190
+
2191
+ // Classify a release from its manifest so the dashboard can flag non-default,
2192
+ // experimental artifacts (microcosm#398). The national default omits
2193
+ // `dataset_role` and names a `default_datasets.national` artifact; a non-default
2194
+ // artifact sets `dataset_role` (e.g. "non_default_local_area") and
2195
+ // `is_default: false`.
2196
+ export function releaseRole(releaseManifest: JsonObject): ReleaseRole {
2197
+ const datasetRole = stringValue(releaseManifest.dataset_role);
2198
+ const explicitDefault = releaseManifest.is_default;
2199
+ const nationalDefault = asObject(releaseManifest.default_datasets).national;
2200
+ const isDefault =
2201
+ explicitDefault === true ||
2202
+ (explicitDefault == null &&
2203
+ datasetRole == null &&
2204
+ typeof nationalDefault === "string" &&
2205
+ nationalDefault.length > 0);
2206
+ return {
2207
+ dataset_role: datasetRole,
2208
+ is_default: isDefault,
2209
+ is_local_area:
2210
+ datasetRole != null && (datasetRole === "non_default_local_area" || datasetRole.includes("local_area")),
2211
+ };
2212
+ }
2213
+
2214
+ // The country a release presents as, typed: registry defaults, overridden by
2215
+ // the string fields of `release_manifest.country` when present and well-typed.
2216
+ // The dashboard is selected by registry, so the artifact cannot re-route it: a
2217
+ // block whose `code` names another country is ignored whole. Capabilities can
2218
+ // only narrow what a deployment serves (intersection with the registration),
2219
+ // never widen it. Unknown keys are ignored.
2220
+ export interface ArtifactCountry {
2221
+ code: MicrocosmCountry;
2222
+ label: string;
2223
+ geography_id: string | null;
2224
+ geography_label: string;
2225
+ repository_visibility: RepositoryVisibility;
2226
+ capabilities: CountryCapability[];
2227
+ }
2228
+
2229
+ function visibilityValue(value: unknown): RepositoryVisibility | null {
2230
+ return value === "public" || value === "private" ? value : null;
2231
+ }
2232
+
2233
+ export function releaseCountry(
2234
+ releaseManifest: JsonObject,
2235
+ country: MicrocosmCountry,
2236
+ ): ArtifactCountry {
2237
+ const registration = countryRegistration(country);
2238
+ const defaults: ArtifactCountry = {
2239
+ code: country,
2240
+ label: registration.label,
2241
+ geography_id: registration.geography_id,
2242
+ geography_label: registration.geography,
2243
+ repository_visibility: registration.visibility,
2244
+ capabilities: [...registration.capabilities],
2245
+ };
2246
+ const block = asObject(releaseManifest.country);
2247
+ // Presence, not nullishness: an explicit `code: null` is a malformed block,
2248
+ // not an absent field, and must not slip past the whole-block rejection.
2249
+ if (
2250
+ Object.hasOwn(block, "code") &&
2251
+ (typeof block.code !== "string" || block.code.trim().toLowerCase() !== country)
2252
+ ) {
2253
+ return defaults;
2254
+ }
2255
+ const capabilities = Array.isArray(block.capabilities)
2256
+ ? new Set(block.capabilities.filter(isCountryCapability))
2257
+ : null;
2258
+ return {
2259
+ code: country,
2260
+ label: stringValue(block.label)?.trim() ?? defaults.label,
2261
+ geography_id: stringValue(block.geography_id)?.trim() ?? defaults.geography_id,
2262
+ geography_label: stringValue(block.geography_label)?.trim() ?? defaults.geography_label,
2263
+ repository_visibility:
2264
+ visibilityValue(block.repository_visibility) ?? defaults.repository_visibility,
2265
+ capabilities: capabilities
2266
+ ? defaults.capabilities.filter((capability) => capabilities.has(capability))
2267
+ : defaults.capabilities,
2268
+ };
2269
+ }
2270
+
2271
+ export function buildCalibration(
2272
+ diagnostics: JsonObject,
2273
+ releaseId: string,
2274
+ updatedAt: string | null = null,
2275
+ buildManifest: JsonObject = {},
2276
+ releaseManifest: JsonObject = {},
2277
+ demographics: JsonObject = {},
2278
+ country: MicrocosmCountry = "us",
2279
+ source: Calibration["source"] = "huggingface_immutable",
2280
+ diagnosticsSha256: string | null = null,
2281
+ hfCommitSha: string | null = null,
2282
+ ): Calibration {
2283
+ // A schema 9 file's rows carry catalog references; every reader below
2284
+ // sees them as schema 8 rows. Other versions pass through unchanged.
2285
+ const diag = expandHierarchyCatalogs(diagnostics);
2286
+ const targetRepresentation = targetRepresentationForDiagnosticsArtifact(
2287
+ diag.schema_version,
2288
+ { releaseId, sha256: diagnosticsSha256 },
2289
+ );
2290
+ const targets = (Array.isArray(diag.targets) ? (diag.targets as TargetRow[]) : []).map(
2291
+ normalizeDiagnosticsRow,
2292
+ );
2293
+ const hierarchyLabelVariants =
2294
+ targetRepresentation === "hierarchy"
2295
+ ? validateHierarchyTargets(targets).label_variants
2296
+ : [];
2297
+ const skipped = Array.isArray(diag.skipped) ? (diag.skipped as JsonObject[]) : [];
2298
+ const targetCompilation = asObject(asObject(buildManifest.gates).target_compilation);
2299
+ const droppedTargetNames = Array.isArray(targetCompilation.dropped_target_names)
2300
+ ? targetCompilation.dropped_target_names
2301
+ .map((value) => (typeof value === "string" ? value : null))
2302
+ .filter((value): value is string => value != null)
2303
+ : [];
2304
+ const skippedByName = skippedTargetReasons(skipped);
2305
+ const dropped = new Set(droppedTargetNames);
2306
+ const artifactCountry = releaseCountry(releaseManifest, country);
2307
+ const presentation = releasePresentation(releaseManifest);
2308
+ const publisherLabels = releasePublisherLabels(releaseManifest);
2309
+ const dimensionDefinitions = diagnosticsDimensions(diag);
2310
+ // Same-named areas at different geography levels (a UK constituency and
2311
+ // local authority, say) keep separate labels in every view.
2312
+ const enrichedRows = levelQualifiedGeographyLabels(addEstimateScopeWarnings(
2313
+ targets.map((row) =>
2314
+ enrichTargetRow(
2315
+ row,
2316
+ skippedByName,
2317
+ dropped,
2318
+ artifactCountry,
2319
+ publisherLabels,
2320
+ dimensionDefinitions,
2321
+ targetRepresentation,
2322
+ ),
2323
+ ),
2324
+ ), artifactCountry.geography_label);
2325
+ const role = releaseRole(releaseManifest);
2326
+ const normalizedAttribution = normalizeTargetLossAttribution({
2327
+ diagnostics: diag,
2328
+ rows: enrichedRows,
2329
+ releaseId,
2330
+ buildManifest,
2331
+ releaseFamily: role.is_local_area ? "local_area" : "national",
2332
+ diagnosticsSha256,
2333
+ });
2334
+ const historicalWeightSummary = historicalWeightSummaryForDiagnostics(
2335
+ releaseId,
2336
+ diagnosticsSha256,
2337
+ );
2338
+ const rows = normalizedAttribution.rows;
2339
+ const includedTargetCount = rows.filter((row) => row.calibration_status === "included").length;
2340
+ return {
2341
+ source,
2342
+ hf_commit_sha: hfCommitSha,
2343
+ country,
2344
+ country_info: artifactCountry,
2345
+ presentation,
2346
+ publisher_labels: publisherLabels,
2347
+ target_schema: {
2348
+ diagnostics_schema_version: numberOrNull(diag.schema_version),
2349
+ structured_dimensions: isPlainObject(diag.dimensions),
2350
+ target_representation: targetRepresentation,
2351
+ },
2352
+ description:
2353
+ stringValue(diag.description) ??
2354
+ stringValue(releaseManifest.description) ??
2355
+ stringValue(buildManifest.description),
2356
+ diagnostics_status: diagnosticsStatus(diag, rows),
2357
+ release_id: String(diag.release_id ?? releaseId),
2358
+ updated_at: updatedAt,
2359
+ schema_version: diag.schema_version ?? null,
2360
+ weight_entity: historicalWeightSummary?.weight_entity ?? diag.weight_entity ?? null,
2361
+ options: asObject(diag.options),
2362
+ l0_lambda: numberOrNull(diag.l0_lambda),
2363
+ n_nonzero: historicalWeightSummary?.n_nonzero ?? numberOrNull(diag.n_nonzero),
2364
+ n_records: historicalWeightSummary?.n_records ?? numberOrNull(diag.n_records),
2365
+ effective_sample_size:
2366
+ historicalWeightSummary?.effective_sample_size ??
2367
+ numberOrNull(diag.effective_sample_size),
2368
+ realized_max_weight_ratio: numberOrNull(diag.realized_max_weight_ratio),
2369
+ top_1pct_weight_share:
2370
+ historicalWeightSummary?.top_1pct_weight_share ??
2371
+ numberOrNull(diag.top_1pct_weight_share),
2372
+ initial_loss: numberOrNull(diag.initial_loss),
2373
+ final_loss: numberOrNull(diag.final_loss),
2374
+ loss_kind: calibrationLossKind(
2375
+ diag,
2376
+ buildManifest,
2377
+ normalizedAttribution.attribution.status,
2378
+ ),
2379
+ fraction_within_10pct: numberOrNull(diag.fraction_within_10pct),
2380
+ loss_trajectory: Array.isArray(diag.loss_trajectory) ? (diag.loss_trajectory as number[]) : [],
2381
+ skipped,
2382
+ declared_targets: numberOrNull(targetCompilation.declared_targets),
2383
+ compiled_candidate_targets: numberOrNull(targetCompilation.compiled_candidate_targets),
2384
+ dropped_target_names: droppedTargetNames,
2385
+ included_target_count: includedTargetCount,
2386
+ diagnostics_build: asObject(diag.build),
2387
+ diagnostic_warnings: normalizedAttribution.attribution.producer_warnings,
2388
+ hierarchy_label_variants: hierarchyLabelVariants,
2389
+ target_loss_basis: Object.keys(asObject(diag.target_loss_basis)).length
2390
+ ? asObject(diag.target_loss_basis)
2391
+ : null,
2392
+ target_loss_attribution: normalizedAttribution.attribution,
2393
+ calibration_provenance: normalizedAttribution.provenance,
2394
+ build_manifest: buildManifest,
2395
+ release_manifest: releaseManifest,
2396
+ geography_coverage: Object.keys(asObject(demographics.geography_coverage)).length
2397
+ ? asObject(demographics.geography_coverage)
2398
+ : null,
2399
+ rows,
2400
+ };
2401
+ }
2402
+
2403
+ // --- HF access --------------------------------------------------------------
2404
+ export function hfResolveUrl(
2405
+ path: string,
2406
+ country: MicrocosmCountry = "us",
2407
+ revisionOverride?: string,
2408
+ ): string {
2409
+ const { repo, revision } = countryRepository(country);
2410
+ const resolvedRevision = revisionOverride ?? revision;
2411
+ return `https://huggingface.co/datasets/${repo}/resolve/${resolvedRevision}/${path}`;
2412
+ }
2413
+
2414
+ // A hung HF request would otherwise block the function for the whole route
2415
+ // maxDuration and pin the shared in-flight cache promise. The calibration
2416
+ // diagnostics artifact is large enough that a cold authenticated download can
2417
+ // exceed 20 seconds, so leave adequate room below the routes' 300-second limit.
2418
+ const MICROCOSM_RELEASE_FETCH_TIMEOUT_MS = 120_000;
2419
+
2420
+ async function hfFetch(url: string, revalidate: number): Promise<Response> {
2421
+ return fetch(url, {
2422
+ next: { revalidate },
2423
+ headers: hfAuthHeaders(),
2424
+ signal: AbortSignal.timeout(MICROCOSM_RELEASE_FETCH_TIMEOUT_MS),
2425
+ });
2426
+ }
2427
+
2428
+ async function hfJson(url: string, revalidate: number): Promise<JsonObject> {
2429
+ const res = await hfFetch(url, revalidate);
2430
+ if (!res.ok) throw new Error(`HF fetch failed ${res.status}: ${url}`);
2431
+ return asObject(await res.json());
2432
+ }
2433
+
2434
+ interface HashedJsonArtifact {
2435
+ payload: JsonObject;
2436
+ sha256: string;
2437
+ }
2438
+
2439
+ export function parseHashedJsonArtifact(bytes: Uint8Array): HashedJsonArtifact {
2440
+ const sha256 = createHash("sha256").update(bytes).digest("hex");
2441
+ const payload = asObject(JSON.parse(new TextDecoder().decode(bytes)));
2442
+ return { payload, sha256 };
2443
+ }
2444
+
2445
+ async function hfHashedJson(url: string, revalidate: number): Promise<HashedJsonArtifact> {
2446
+ const res = await hfFetch(url, revalidate);
2447
+ if (!res.ok) throw new Error(`HF fetch failed ${res.status}: ${url}`);
2448
+ return parseHashedJsonArtifact(new Uint8Array(await res.arrayBuffer()));
2449
+ }
2450
+
2451
+ // Read one JSON file from the country's registered release repository at an
2452
+ // explicit immutable revision, with the release credential, returning its
2453
+ // bytes' digest beside the payload. `null` when the file is absent there.
2454
+ export async function loadCountryRepositoryHashedJson(
2455
+ path: string,
2456
+ revalidate: number,
2457
+ country: MicrocosmCountry,
2458
+ revision: string,
2459
+ ): Promise<HashedJsonArtifact | null> {
2460
+ const { repo } = countryRepository(country);
2461
+ const url = `https://huggingface.co/datasets/${repo}/resolve/${revision}/${path}`;
2462
+ const res = await hfFetch(url, revalidate);
2463
+ if (res.status === 404) return null;
2464
+ if (!res.ok) throw new Error(`HF fetch failed ${res.status}: ${url}`);
2465
+ return parseHashedJsonArtifact(new Uint8Array(await res.arrayBuffer()));
2466
+ }
2467
+
2468
+ export interface ReleaseEntry {
2469
+ release_id: string;
2470
+ date: string;
2471
+ files: string[];
2472
+ has_calibration: boolean;
2473
+ dataset_role: string | null;
2474
+ is_default: boolean;
2475
+ is_local_area: boolean;
2476
+ // A Microcosm cut's line folder; absent when the folder is release_id.
2477
+ release_directory?: string;
2478
+ // A build in its own folder (release_id is `<release>/<build>`): its
2479
+ // release and build as releases.json names them, and whether releases.json
2480
+ // marks it withdrawn. Absent for release folders and tags.
2481
+ release?: string;
2482
+ build?: string;
2483
+ withdrawn?: boolean;
2484
+ }
2485
+
2486
+ // Trailing timestamp/date in a build id → a real timestamp for ordering. Ids
2487
+ // without the trailing YYYYMMDD[THHMMSSZ] sort oldest (rank 0) instead of
2488
+ // jumping to the top on a lexical whole-id compare.
2489
+ function releaseSortKey(id: string): number {
2490
+ const m = /(\d{4})(\d{2})(\d{2})(?:T(\d{2})(\d{2})(\d{2})Z)?$/.exec(id);
2491
+ if (!m) return 0;
2492
+ const [, y, mo, d, h = "00", mi = "00", s = "00"] = m;
2493
+ return Date.UTC(+y, +mo - 1, +d, +h, +mi, +s);
2494
+ }
2495
+
2496
+ function releaseDate(id: string): string {
2497
+ const m = /(\d{8}(?:T\d{6}Z)?)$/.exec(id);
2498
+ return m ? m[1] : id;
2499
+ }
2500
+
2501
+ export const UK_LOCAL_CALIBRATION_DIR_ENV =
2502
+ "MICROCOSM_UK_LOCAL_CALIBRATION_DIR";
2503
+
2504
+ interface LocalCalibrationRelease {
2505
+ releaseId: string;
2506
+ updatedAt: string;
2507
+ files: string[];
2508
+ diagnostics: JsonObject;
2509
+ buildManifest: JsonObject;
2510
+ releaseManifest: JsonObject;
2511
+ demographics: JsonObject;
2512
+ }
2513
+
2514
+ function localCalibrationDirectory(country: MicrocosmCountry): string | null {
2515
+ if (country !== "uk") return null;
2516
+ const directory = process.env[UK_LOCAL_CALIBRATION_DIR_ENV]?.trim();
2517
+ return directory || null;
2518
+ }
2519
+
2520
+ async function localJson(
2521
+ directory: string,
2522
+ filename: string,
2523
+ ): Promise<JsonObject> {
2524
+ const path = join(directory, filename);
2525
+ try {
2526
+ return asObject(JSON.parse(await readFile(path, "utf8")));
2527
+ } catch (error) {
2528
+ throw new Error(`Unable to read local Microcosm artifact ${path}`, {
2529
+ cause: error,
2530
+ });
2531
+ }
2532
+ }
2533
+
2534
+ async function optionalLocalJson(
2535
+ directory: string,
2536
+ filename: string,
2537
+ ): Promise<JsonObject> {
2538
+ try {
2539
+ return await localJson(directory, filename);
2540
+ } catch {
2541
+ return {};
2542
+ }
2543
+ }
2544
+
2545
+ async function loadLocalCalibrationRelease(
2546
+ country: MicrocosmCountry,
2547
+ ): Promise<LocalCalibrationRelease | null> {
2548
+ const directory = localCalibrationDirectory(country);
2549
+ if (!directory) return null;
2550
+
2551
+ const diagnosticsPath = join(directory, "calibration_diagnostics.json");
2552
+ const [
2553
+ diagnostics,
2554
+ diagnosticsStat,
2555
+ files,
2556
+ buildManifest,
2557
+ releaseManifest,
2558
+ demographics,
2559
+ ] = await Promise.all([
2560
+ localJson(directory, "calibration_diagnostics.json"),
2561
+ stat(diagnosticsPath),
2562
+ readdir(directory),
2563
+ optionalLocalJson(directory, "build_manifest.json"),
2564
+ optionalLocalJson(directory, "release_manifest.json"),
2565
+ optionalLocalJson(directory, "demographics.json"),
2566
+ ]);
2567
+ const diagnosticsBuild = asObject(diagnostics.build);
2568
+ const releaseId = assertSafeReleaseId(
2569
+ String(
2570
+ diagnostics.release_id ?? diagnosticsBuild.build_id ?? basename(directory),
2571
+ ),
2572
+ "local UK calibration release",
2573
+ );
2574
+ return {
2575
+ releaseId,
2576
+ updatedAt: diagnosticsStat.mtime.toISOString(),
2577
+ files: files.sort(),
2578
+ diagnostics,
2579
+ buildManifest,
2580
+ releaseManifest,
2581
+ demographics,
2582
+ };
2583
+ }
2584
+
2585
+ export async function loadReleases(
2586
+ revalidate: number,
2587
+ country: MicrocosmCountry = "us",
2588
+ revisionOverride?: string,
2589
+ ): Promise<ReleaseEntry[]> {
2590
+ const local = await loadLocalCalibrationRelease(country);
2591
+ if (local) {
2592
+ return [
2593
+ {
2594
+ release_id: local.releaseId,
2595
+ date: local.updatedAt,
2596
+ files: local.files,
2597
+ has_calibration: true,
2598
+ dataset_role: null,
2599
+ is_default: true,
2600
+ is_local_area: false,
2601
+ },
2602
+ ];
2603
+ }
2604
+
2605
+ const { repo, revision } = countryRepository(country);
2606
+ const resolvedRevision = revisionOverride ?? revision;
2607
+ const files = new Map<string, Set<string>>();
2608
+ // The HF tree endpoint paginates (~1000 entries/page via a Link cursor);
2609
+ // follow every page so releases don't silently vanish as the repo grows.
2610
+ let url: string | null =
2611
+ `https://huggingface.co/api/datasets/${repo}/tree/${resolvedRevision}/releases?recursive=true`;
2612
+ let page = 0;
2613
+ while (url && page < 50) {
2614
+ const res: Response = await hfFetch(url, revalidate);
2615
+ if (!res.ok) throw new Error(`HF tree failed ${res.status}`);
2616
+ const tree = await res.json();
2617
+ if (Array.isArray(tree)) {
2618
+ for (const entry of tree) {
2619
+ const item = asObject(entry);
2620
+ if (item.type !== "file" || typeof item.path !== "string") continue;
2621
+ const match = item.path.match(/^releases\/([^/]+)\/(.+)$/);
2622
+ if (!match) continue;
2623
+ (files.get(match[1]) ?? files.set(match[1], new Set()).get(match[1])!).add(match[2]);
2624
+ }
2625
+ }
2626
+ const link = res.headers.get("link") ?? "";
2627
+ const next = /<([^>]+)>;\s*rel="next"/.exec(link);
2628
+ url = next ? next[1] : null;
2629
+ page += 1;
2630
+ }
2631
+ const entries: ReleaseEntry[] = [...files.entries()]
2632
+ .map(([release_id, set]) => ({
2633
+ release_id,
2634
+ date: releaseDate(release_id),
2635
+ files: [...set].sort(),
2636
+ has_calibration: set.has("calibration_diagnostics.json"),
2637
+ dataset_role: null as string | null,
2638
+ is_default: true,
2639
+ is_local_area: false,
2640
+ }))
2641
+ .sort((a, b) => releaseSortKey(b.release_id) - releaseSortKey(a.release_id));
2642
+ // Classify each release from its manifest so the picker can flag non-default,
2643
+ // experimental artifacts (microcosm#398). Best-effort and parallel: only
2644
+ // releases that actually publish a release_manifest.json are fetched, and a
2645
+ // missing or slow manifest keeps the safe national-default classification
2646
+ // rather than blocking or failing the listing.
2647
+ await Promise.all(
2648
+ entries
2649
+ .filter((entry) => entry.files.includes("release_manifest.json"))
2650
+ .map(async (entry) => {
2651
+ try {
2652
+ const manifest = await hfJson(
2653
+ hfResolveUrl(
2654
+ `releases/${entry.release_id}/release_manifest.json`,
2655
+ country,
2656
+ resolvedRevision,
2657
+ ),
2658
+ revalidate,
2659
+ );
2660
+ Object.assign(entry, releaseRole(manifest));
2661
+ } catch {
2662
+ // Best-effort: keep the default classification.
2663
+ }
2664
+ }),
2665
+ );
2666
+ return entries;
2667
+ }
2668
+
2669
+ // Published releases the folder listing above cannot name, read from the
2670
+ // dashboard manifest:
2671
+ // - a per-attempt tag of a Microcosm release series (microcosm#823), whose
2672
+ // files are in the series' shared folder, which the folder listing names
2673
+ // only as the mutable copy on main;
2674
+ // - a release published only as a tag (`--no-latest --tag-only`), whose
2675
+ // `releases/<release id>/` exists at the tag's commit and never on main.
2676
+ // A release whose calibrated folder is on main is listed from that folder, as
2677
+ // the publisher reads it. Roles are read from the release's own
2678
+ // release_manifest.json at its pinned commit, best-effort like the listing's.
2679
+ // A build in its own folder (`<release>/<build>`) is listed only from
2680
+ // releases.json (recordedReleaseInventory), so such entries stay readable by
2681
+ // id but are never listed here.
2682
+ export async function loadPublishedCutReleases(
2683
+ revalidate: number,
2684
+ country: MicrocosmCountry,
2685
+ manifest: CalibrationTreeManifest,
2686
+ folders: readonly ReleaseEntry[],
2687
+ ): Promise<ReleaseEntry[]> {
2688
+ if (await loadLocalCalibrationRelease(country)) return [];
2689
+ const calibratedFolders = new Set(
2690
+ folders.filter((folder) => folder.has_calibration).map((folder) => folder.release_id),
2691
+ );
2692
+ const unlisted = (manifest.countries[country]?.builds ?? []).filter(
2693
+ (build) =>
2694
+ build.kind === "release" &&
2695
+ build.releaseId != null &&
2696
+ !isBuildFolderId(build.releaseId) &&
2697
+ (releaseDirectoryOf(build) !== build.releaseId ||
2698
+ !calibratedFolders.has(build.releaseId)),
2699
+ );
2700
+ return Promise.all(unlisted.map(async (build) => {
2701
+ const releaseId = build.releaseId as string;
2702
+ const directory = assertSafeReleaseId(
2703
+ releaseDirectoryOf(build) as string,
2704
+ "release directory",
2705
+ );
2706
+ const entry: ReleaseEntry = {
2707
+ release_id: releaseId,
2708
+ date: parseReleaseCutTag(releaseId)?.cutAt ?? releaseDate(releaseId),
2709
+ files: [],
2710
+ has_calibration: true,
2711
+ dataset_role: null,
2712
+ is_default: true,
2713
+ is_local_area: false,
2714
+ ...(directory !== releaseId ? { release_directory: directory } : {}),
2715
+ };
2716
+ try {
2717
+ const releaseManifest = await hfJson(
2718
+ hfResolveUrl(
2719
+ `releases/${directory}/release_manifest.json`,
2720
+ country,
2721
+ build.hfCommitSha,
2722
+ ),
2723
+ revalidate,
2724
+ );
2725
+ Object.assign(entry, releaseRole(releaseManifest));
2726
+ } catch {
2727
+ // Best-effort: keep the default classification.
2728
+ }
2729
+ return entry;
2730
+ }));
2731
+ }
2732
+
2733
+ // The picker lists every published per-attempt tag and every release
2734
+ // published only as a tag beside the folders on main. A release series'
2735
+ // shared folder is a mutable copy of whichever of its tags was published
2736
+ // last, so it leaves the picker once its tags are listed, unless the
2737
+ // dashboard's latest release still points at it. That holds for the shared
2738
+ // folder's own published build too, which the manifest reader returns when
2739
+ // the folder's copy on main has no calibration diagnostics.
2740
+ // A folder on main without calibration diagnostics gives way to the
2741
+ // published build of the same release. Without such releases the listing is
2742
+ // returned unchanged.
2743
+ export function mergeReleaseInventory(
2744
+ folders: ReleaseEntry[],
2745
+ cuts: ReleaseEntry[],
2746
+ latestReleaseId: string | null,
2747
+ ): ReleaseEntry[] {
2748
+ if (!cuts.length) return folders;
2749
+ const lineFolders = new Set(cuts.map((cut) => cut.release_directory));
2750
+ const publishedReleaseIds = new Set(cuts.map((cut) => cut.release_id));
2751
+ const outsideSharedFolders = (release: ReleaseEntry) =>
2752
+ !lineFolders.has(release.release_id) || release.release_id === latestReleaseId;
2753
+ return [
2754
+ ...folders.filter(
2755
+ (folder) =>
2756
+ outsideSharedFolders(folder) && !publishedReleaseIds.has(folder.release_id),
2757
+ ),
2758
+ ...cuts.filter(outsideSharedFolders),
2759
+ ].sort((left, right) => releaseSortKey(right.date) - releaseSortKey(left.date));
2760
+ }
2761
+
2762
+ // The picker's compact UTC form, YYYYMMDDTHHMMSSZ, of a recorded date-time;
2763
+ // a value that is not one is kept as written.
2764
+ function compactUtcTimestamp(value: string): string {
2765
+ const instant = Date.parse(value);
2766
+ if (!Number.isFinite(instant)) return value;
2767
+ return new Date(instant).toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
2768
+ }
2769
+
2770
+ /**
2771
+ * The country's releases.json at its configured revision, checked as the
2772
+ * release writer checks it, or null when the repository has none (it then
2773
+ * publishes through tags and pointer files) or the release is a local file.
2774
+ * An unreadable or refused record throws: see releasesRecordFromResponse.
2775
+ */
2776
+ export async function loadReleasesRecord(
2777
+ revalidate: number,
2778
+ country: MicrocosmCountry,
2779
+ ): Promise<ReleasesRecord | null> {
2780
+ if (await loadLocalCalibrationRelease(country)) return null;
2781
+ return releasesRecordFromResponse(
2782
+ await hfFetch(hfResolveUrl(RELEASES_RECORD_PATH, country), revalidate),
2783
+ );
2784
+ }
2785
+
2786
+ /**
2787
+ * The release inventory of a repository with releases.json: every build the
2788
+ * record lists, named by its folder (`<release>/<build>`), dated by the
2789
+ * record's `published_at` and classified by its release's role (the record's
2790
+ * default release is the default dataset). A build is calibrated (selectable
2791
+ * for comparison) once the dashboard manifest holds its tree. Withdrawn
2792
+ * builds are listed with their flag, and the picker labels them. The
2793
+ * dashboard's latest release is listed too while releases.json does not
2794
+ * name it (see dashboardLatestRelease).
2795
+ */
2796
+ export function recordedReleaseInventory(
2797
+ record: ReleasesRecord,
2798
+ country: MicrocosmCountry,
2799
+ manifest: CalibrationTreeManifest,
2800
+ ): ReleaseEntry[] {
2801
+ const published = new Set(
2802
+ (manifest.countries[country]?.builds ?? []).flatMap((build) =>
2803
+ build.kind === "release" && build.releaseId ? [build.releaseId] : []
2804
+ ),
2805
+ );
2806
+ const recorded = recordedBuilds(record).map((build): ReleaseEntry => ({
2807
+ release_id: build.id,
2808
+ date: compactUtcTimestamp(build.publishedAt),
2809
+ files: [],
2810
+ has_calibration: published.has(build.id),
2811
+ ...releaseRole({ dataset_role: build.role, is_default: build.inDefaultRelease }),
2812
+ release: build.release,
2813
+ build: build.build,
2814
+ withdrawn: build.withdrawn,
2815
+ }));
2816
+ const recordedIds = new Set(recorded.map((entry) => entry.release_id));
2817
+ const latest = dashboardLatestRelease(manifest, country);
2818
+ return [
2819
+ ...recorded,
2820
+ ...(latest && !recordedIds.has(latest.release_id) ? [latest] : []),
2821
+ ].sort((left, right) => releaseSortKey(right.date) - releaseSortKey(left.date));
2822
+ }
2823
+
2824
+ /**
2825
+ * The release inventory from releases.json (recordedReleaseInventory), or
2826
+ * null when the repository has no releases.json, so the caller lists its
2827
+ * release folders and tagged builds instead. releases.json is the only file
2828
+ * read from the dataset repository.
2829
+ */
2830
+ export async function loadRecordedReleases(
2831
+ revalidate: number,
2832
+ country: MicrocosmCountry,
2833
+ manifest: CalibrationTreeManifest,
2834
+ ): Promise<ReleaseEntry[] | null> {
2835
+ const record = await loadReleasesRecord(revalidate, country);
2836
+ return record ? recordedReleaseInventory(record, country, manifest) : null;
2837
+ }
2838
+
2839
+ /**
2840
+ * The release the dashboard manifest marks latest, as a picker entry. Under
2841
+ * build folders it is releases.json's current build once reconciliation has
2842
+ * run; until then it is the entry published before the switch (a tagged
2843
+ * build or a release folder), which releases.json does not name. Keeping it
2844
+ * listed keeps the page's selected release selectable, which the
2845
+ * deployment's pre-promotion check requires. Read from the dashboard
2846
+ * manifest only; it is classified as the default dataset, as the latest
2847
+ * release is.
2848
+ */
2849
+ function dashboardLatestRelease(
2850
+ manifest: CalibrationTreeManifest,
2851
+ country: MicrocosmCountry,
2852
+ ): ReleaseEntry | null {
2853
+ const countryManifest = manifest.countries[country];
2854
+ const latest = countryManifest?.builds.find(
2855
+ (build) =>
2856
+ build.buildArtifactId === countryManifest.latestReleaseBuildArtifactId &&
2857
+ build.kind === "release",
2858
+ );
2859
+ if (!latest?.releaseId) return null;
2860
+ return {
2861
+ release_id: latest.releaseId,
2862
+ date: latest.createdAt ? compactUtcTimestamp(latest.createdAt) : releaseDate(latest.releaseId),
2863
+ files: [],
2864
+ has_calibration: true,
2865
+ dataset_role: null,
2866
+ is_default: true,
2867
+ is_local_area: false,
2868
+ ...(latest.releaseDirectory && latest.releaseDirectory !== latest.releaseId
2869
+ ? { release_directory: latest.releaseDirectory }
2870
+ : {}),
2871
+ };
2872
+ }
2873
+
2874
+ export async function loadPointerReleaseId(
2875
+ revalidate: number,
2876
+ country: MicrocosmCountry = "us",
2877
+ ): Promise<{ release_id: string; updated_at: string | null }> {
2878
+ const local = await loadLocalCalibrationRelease(country);
2879
+ if (local) {
2880
+ return { release_id: local.releaseId, updated_at: local.updatedAt };
2881
+ }
2882
+
2883
+ const pointer = await resolveCalibrationRelease(country, "latest", revalidate);
2884
+ return {
2885
+ release_id: pointer.releaseId,
2886
+ updated_at: pointer.updatedAt,
2887
+ };
2888
+ }
2889
+
2890
+ // Load one release's manifests + calibration diagnostics. releaseId "latest"
2891
+ // resolves through the dashboard manifest. Historical releases resolve through
2892
+ // their immutable Hugging Face tag commit.
2893
+ export async function loadRelease(
2894
+ releaseId: string,
2895
+ revalidate: number,
2896
+ country: MicrocosmCountry = "us",
2897
+ ): Promise<Calibration> {
2898
+ const requestedRelease = releaseId || "latest";
2899
+ const cacheSeconds = requestedRelease === "latest"
2900
+ ? Math.min(Math.max(revalidate, 1), 60)
2901
+ : Math.max(revalidate, 1);
2902
+ const cacheKey = `${country}:${requestedRelease}:${cacheSeconds}`;
2903
+ const now = Date.now();
2904
+ const cached = releaseCache.get(cacheKey);
2905
+ if (cached && cached.expiresAt > now) return cached.promise;
2906
+
2907
+ const promise = loadReleaseUncached(releaseId, revalidate, country);
2908
+ releaseCache.set(cacheKey, {
2909
+ promise,
2910
+ expiresAt: now + cacheSeconds * 1000,
2911
+ });
2912
+ try {
2913
+ return await promise;
2914
+ } catch (error) {
2915
+ releaseCache.delete(cacheKey);
2916
+ throw error;
2917
+ }
2918
+ }
2919
+
2920
+ async function loadReleaseUncached(
2921
+ releaseId: string,
2922
+ revalidate: number,
2923
+ country: MicrocosmCountry,
2924
+ ): Promise<Calibration> {
2925
+ const local = await loadLocalCalibrationRelease(country);
2926
+ if (
2927
+ local &&
2928
+ (releaseId === "latest" || !releaseId || releaseId === local.releaseId)
2929
+ ) {
2930
+ return buildCalibration(
2931
+ local.diagnostics,
2932
+ local.releaseId,
2933
+ local.updatedAt,
2934
+ local.buildManifest,
2935
+ local.releaseManifest,
2936
+ local.demographics,
2937
+ country,
2938
+ "local_filesystem",
2939
+ );
2940
+ }
2941
+
2942
+ const location = await resolveCalibrationRelease(
2943
+ country,
2944
+ releaseId || "latest",
2945
+ revalidate,
2946
+ );
2947
+ const id = location.releaseId;
2948
+ // A release folder or a build folder (`<release>/<build>`); interpolated
2949
+ // into authenticated Hugging Face URLs.
2950
+ const directory = location.releaseDirectory;
2951
+ if (!isReleaseDirectory(directory) || directory === "latest") {
2952
+ throw new InvalidReleaseIdError("Invalid release directory id");
2953
+ }
2954
+ const updatedAt = location.updatedAt;
2955
+ const prefix = `releases/${directory}`;
2956
+ const [diagnosticsArtifact, buildManifest, releaseManifest, demographics, publishedAt] = await Promise.all([
2957
+ hfHashedJson(
2958
+ hfResolveUrl(
2959
+ `${prefix}/calibration_diagnostics.json`,
2960
+ country,
2961
+ location.hfCommitSha,
2962
+ ),
2963
+ revalidate,
2964
+ ),
2965
+ hfJson(hfResolveUrl(`${prefix}/build_manifest.json`, country, location.hfCommitSha), revalidate).catch(() => ({})),
2966
+ hfJson(hfResolveUrl(`${prefix}/release_manifest.json`, country, location.hfCommitSha), revalidate).catch(() => ({})),
2967
+ hfJson(hfResolveUrl(`${prefix}/demographics.json`, country, location.hfCommitSha), revalidate).catch(() => ({})),
2968
+ // The manifest entry's timestamp is the pinned commit's date; an entry
2969
+ // written before that was recorded is dated from the same commit here.
2970
+ updatedAt
2971
+ ? Promise.resolve(updatedAt)
2972
+ : resolveHfCommitPublishedAt(country, location.hfCommitSha, revalidate).catch(
2973
+ () => null,
2974
+ ),
2975
+ ]);
2976
+ const calibration = buildCalibration(
2977
+ diagnosticsArtifact.payload,
2978
+ id,
2979
+ updatedAt ?? publishedAt,
2980
+ buildManifest,
2981
+ releaseManifest,
2982
+ demographics,
2983
+ country,
2984
+ "huggingface_immutable",
2985
+ diagnosticsArtifact.sha256,
2986
+ location.hfCommitSha,
2987
+ );
2988
+ return calibrationAsReleased(calibration, id, directory);
2989
+ }
2990
+
2991
+ /**
2992
+ * A release build as the picker and the dashboard manifest name it. A tag
2993
+ * keeps its tag, and a build folder keeps `<release>/<build>`, as the release
2994
+ * id the picker, the latest release and this summary share, even when its
2995
+ * diagnostics name its folder or its release instead; both record the folder
2996
+ * they were read from, so their sources are cited at the pinned commit. A
2997
+ * release folder keeps the id its diagnostics carry, as before.
2998
+ */
2999
+ export function calibrationAsReleased(
3000
+ calibration: Calibration,
3001
+ releaseId: string,
3002
+ releaseDirectory: string,
3003
+ ): Calibration {
3004
+ return releaseDirectory === releaseId && !isBuildFolderId(releaseId)
3005
+ ? calibration
3006
+ : { ...calibration, release_id: releaseId, release_directory: releaseDirectory };
3007
+ }
3008
+
3009
+ function targetDiagnosticsMetadata(rows: TargetRow[]): TargetDiagnosticsMetadata {
3010
+ const cached = targetDiagnosticsMetadataCache.get(rows);
3011
+ if (cached) return cached;
3012
+ const metadata = {
3013
+ sources: microcosmTargetSources(rows),
3014
+ levels: microcosmTargetLevels(rows),
3015
+ geographies: microcosmTargetGeographies(rows),
3016
+ variables: microcosmVariableSummary(rows),
3017
+ scope_counts: { healthcare: rows.filter(isHealthcareTarget).length },
3018
+ };
3019
+ targetDiagnosticsMetadataCache.set(rows, metadata);
3020
+ return metadata;
3021
+ }
3022
+
3023
+ function targetResponseRow(row: TargetRow): TargetRow {
3024
+ return {
3025
+ name: row.name,
3026
+ target: row.target,
3027
+ initial_estimate: row.initial_estimate,
3028
+ final_estimate: row.final_estimate,
3029
+ relative_error: row.relative_error,
3030
+ within_tolerance: row.within_tolerance,
3031
+ base_name: row.base_name,
3032
+ family: row.family,
3033
+ state: row.state,
3034
+ geography: row.geography,
3035
+ level: row.level,
3036
+ source: row.source,
3037
+ source_label: row.source_label,
3038
+ variable: row.variable,
3039
+ variable_label: row.variable_label,
3040
+ target_label: row.target_label,
3041
+ measure: row.measure,
3042
+ target_role: row.target_role,
3043
+ source_measure_id: row.source_measure_id,
3044
+ policyengine_variables: row.policyengine_variables,
3045
+ policyengine_map_to: row.policyengine_map_to,
3046
+ policyengine_filter_variable: row.policyengine_filter_variable,
3047
+ materializer: row.materializer,
3048
+ measure_mode: row.measure_mode,
3049
+ error_kind: row.error_kind,
3050
+ initial_error: row.initial_error,
3051
+ final_error: row.final_error,
3052
+ initial_miss: row.initial_miss,
3053
+ final_miss: row.final_miss,
3054
+ abs_final_miss: row.abs_final_miss,
3055
+ absolute_improvement: row.absolute_improvement,
3056
+ abs_error: row.abs_error,
3057
+ breakdown: row.breakdown,
3058
+ dims: row.dims,
3059
+ target_dimensions: row.target_dimensions,
3060
+ dimension_adapter: row.dimension_adapter,
3061
+ target_representation: row.target_representation,
3062
+ hierarchy: row.hierarchy,
3063
+ variable_key: row.variable_key,
3064
+ source_citation: row.source_citation,
3065
+ source_url: row.source_url,
3066
+ entity: row.entity,
3067
+ aggregation: row.aggregation,
3068
+ measure_name: row.measure_name,
3069
+ period: row.period,
3070
+ chronicle: shownChronicle(row),
3071
+ estimate_warning: row.estimate_warning,
3072
+ calibration_status: row.calibration_status,
3073
+ calibration_status_label: row.calibration_status_label,
3074
+ calibration_status_reason: row.calibration_status_reason,
3075
+ initial_relative_error: row.initial_relative_error,
3076
+ abs_relative_error: row.abs_relative_error,
3077
+ improvement: row.improvement,
3078
+ direction: row.direction,
3079
+ };
3080
+ }
3081
+
3082
+ function githubSearchUrl(query: string): string {
3083
+ const scoped = `org:PolicyEngine ${query}`;
3084
+ return `https://github.com/search?type=code&q=${encodeURIComponent(scoped)}`;
3085
+ }
3086
+
3087
+ function investigationSearches(row: TargetRow): InvestigationSearch[] {
3088
+ const chronicle = asObject(shownChronicle(row));
3089
+ const metadata = asObject(row.metadata);
3090
+ const memberFactKeys = Array.isArray(chronicle.member_fact_keys)
3091
+ ? chronicle.member_fact_keys.map(stringValue)
3092
+ : [];
3093
+ const terms: [string, string | null][] = [
3094
+ ["Source record", stringValue(chronicle.source_record_id)],
3095
+ ["Fact key", stringValue(chronicle.fact_key)],
3096
+ ["Semantic fact", stringValue(chronicle.semantic_fact_key)],
3097
+ ["Aggregate fact", stringValue(chronicle.aggregate_fact_key)],
3098
+ ["Legacy fact", stringValue(chronicle.legacy_fact_key)],
3099
+ ...memberFactKeys.map((key): [string, string | null] => ["Member fact", key]),
3100
+ ["Record set", stringValue(chronicle.layout_record_set_id)],
3101
+ ["Measure concept", stringValue(chronicle.measure_concept)],
3102
+ ["Source concept", stringValue(chronicle.source_concept)],
3103
+ ["Source measure", stringValue(metadata.source_measure_id)],
3104
+ ["Variable", stringValue(metadata.variable) ?? stringValue(row.variable)],
3105
+ ];
3106
+ const seen = new Set<string>();
3107
+ const nonEmptyTerms: [string, string][] = [];
3108
+ for (const [label, value] of terms) {
3109
+ if (!value) continue;
3110
+ nonEmptyTerms.push([label, value]);
3111
+ }
3112
+ return nonEmptyTerms
3113
+ .filter(([, value]) => {
3114
+ if (seen.has(value)) return false;
3115
+ seen.add(value);
3116
+ return true;
3117
+ })
3118
+ .map(([label, value]) => ({
3119
+ label,
3120
+ query: `"${value}"`,
3121
+ url: githubSearchUrl(`"${value}"`),
3122
+ }));
3123
+ }
3124
+
3125
+ function investigationSignals(row: TargetRow): InvestigationSignal[] {
3126
+ const signals: InvestigationSignal[] = [];
3127
+ const target = numberOrNull(row.target);
3128
+ const initial = numberOrNull(row.initial_estimate);
3129
+ const final = numberOrNull(row.final_estimate);
3130
+ const initialMiss = numberOrNull(row.initial_miss);
3131
+ const finalMiss = numberOrNull(row.final_miss);
3132
+ const absRel = numberOrNull(row.abs_relative_error);
3133
+ const improvement = numberOrNull(row.improvement);
3134
+ const absoluteImprovement = numberOrNull(row.absolute_improvement);
3135
+ const calibrationStatus = stringValue(row.calibration_status);
3136
+
3137
+ if (calibrationStatus && calibrationStatus !== "included") {
3138
+ signals.push({
3139
+ tone: "critical",
3140
+ label: "Target not included",
3141
+ detail: stringValue(row.calibration_status_reason) ?? "The target was not included in calibration.",
3142
+ });
3143
+ }
3144
+ if (stringValue(row.estimate_warning)) {
3145
+ signals.push({
3146
+ tone: "critical",
3147
+ label: "Estimate scope warning",
3148
+ detail: stringValue(row.estimate_warning)!,
3149
+ });
3150
+ }
3151
+ if (target === 0 && final != null && Math.abs(final) > 0) {
3152
+ signals.push({
3153
+ tone: "warning",
3154
+ label: "Zero target has non-zero estimate",
3155
+ detail: "The dashboard treats a substantive non-zero estimate against a structural-zero target as 100% error.",
3156
+ });
3157
+ }
3158
+ if (absRel != null) {
3159
+ const tone = absRel > 1 ? "critical" : absRel > 0.1 ? "warning" : "positive";
3160
+ signals.push({
3161
+ tone,
3162
+ label: "Final fit",
3163
+ detail:
3164
+ absRel <= 0.1
3165
+ ? "The final estimate is within 10% of the target."
3166
+ : `The final estimate is ${(absRel * 100).toFixed(absRel > 1 ? 1 : 2)}% away from the target.`,
3167
+ });
3168
+ }
3169
+ if (initialMiss != null && finalMiss != null) {
3170
+ const sameDirection = Math.sign(initialMiss) === Math.sign(finalMiss) && Math.sign(finalMiss) !== 0;
3171
+ if (sameDirection && improvement != null && improvement <= 0) {
3172
+ signals.push({
3173
+ tone: "warning",
3174
+ label: "Calibration moved away",
3175
+ detail: "Initial and final miss have the same sign, and the absolute error did not improve.",
3176
+ });
3177
+ } else if (sameDirection && absoluteImprovement != null && absoluteImprovement > 0) {
3178
+ signals.push({
3179
+ tone: absRel != null && absRel > 0.1 ? "warning" : "positive",
3180
+ label: "Same-side miss remains",
3181
+ detail: "Calibration reduced the miss, but the final estimate remains on the same side of the target.",
3182
+ });
3183
+ }
3184
+ }
3185
+ if (initial == null || final == null) {
3186
+ signals.push({
3187
+ tone: "critical",
3188
+ label: "Missing estimate",
3189
+ detail: "The published diagnostics do not contain both initial and final estimates for this target.",
3190
+ });
3191
+ }
3192
+
3193
+ if (!signals.length) {
3194
+ signals.push({
3195
+ tone: "neutral",
3196
+ label: "No artifact-level warnings",
3197
+ detail: "The release artifact does not flag this target; investigate source target construction and model aggregate next.",
3198
+ });
3199
+ }
3200
+ return signals;
3201
+ }
3202
+
3203
+ function investigationNextSteps(row: TargetRow): string[] {
3204
+ const steps = [
3205
+ "Verify the Chronicle fact: source period, target period, geography, unit, measure concept, and every filter/group-by value.",
3206
+ "Verify target materialization: confirm the Populus compiler creates a model selector for the exact Chronicle dimensions, not a broader aggregate.",
3207
+ "Verify model aggregate mapping: confirm the PolicyEngine variable or aggregate used for the estimate has the same unit, tax unit/person entity, sign convention, and period.",
3208
+ "Compare initial versus final miss: if both are badly off in the same direction, inspect source/model scope before tuning calibration weights.",
3209
+ "Inspect competing constraints for the same population slice if calibration improved one target while worsening another.",
3210
+ ];
3211
+ if (row.estimate_warning) {
3212
+ steps.unshift("Start with target materialization: the published diagnostics already indicate this estimate may be broader than the Chronicle slice.");
3213
+ }
3214
+ if (numberOrNull(row.target) === 0) {
3215
+ steps.unshift("Start with the Chronicle target value: confirm whether zero means a real zero, suppressed/missing source data, or a target intentionally dropped to zero.");
3216
+ }
3217
+ if (row.calibration_status !== "included") {
3218
+ steps.unshift("Start with the calibration status: the target was not included as an active calibration constraint.");
3219
+ }
3220
+ return [...new Set(steps)];
3221
+ }
3222
+
3223
+ function targetInvestigationPacket(row: TargetRow, cal: Calibration) {
3224
+ const metadata = asObject(row.metadata);
3225
+ const directory = cal.release_directory ?? cal.release_id;
3226
+ return {
3227
+ release_id: cal.release_id,
3228
+ target: targetResponseRow(row),
3229
+ source_artifact: {
3230
+ hf_repo: microcosmRepo(cal.country),
3231
+ // A cut's folder on main holds whichever cut was published last, so a
3232
+ // cut is cited at the commit it was read from.
3233
+ hf_revision: cal.release_directory && cal.hf_commit_sha
3234
+ ? cal.hf_commit_sha
3235
+ : microcosmRevision(cal.country),
3236
+ calibration_diagnostics_path: `releases/${directory}/calibration_diagnostics.json`,
3237
+ build_manifest_path: `releases/${directory}/build_manifest.json`,
3238
+ release_manifest_path: `releases/${directory}/release_manifest.json`,
3239
+ },
3240
+ source_metadata: {
3241
+ source_measure_id: stringValue(metadata.source_measure_id),
3242
+ variable: stringValue(metadata.variable),
3243
+ source_period: stringValue(metadata.source_period),
3244
+ target_period: stringValue(metadata.target_period),
3245
+ },
3246
+ signals: investigationSignals(row),
3247
+ next_steps: investigationNextSteps(row),
3248
+ repo_searches: investigationSearches(row),
3249
+ limits: [
3250
+ "The dashboard can prove what is in the release artifacts and Chronicle metadata.",
3251
+ "It cannot prove the generated per-record model filter or expression unless Populus exports that compiler trace for the target.",
3252
+ "When the artifact warns about scope, treat the estimate as provisional until the Populus materialized target is inspected.",
3253
+ ],
3254
+ };
3255
+ }
3256
+
3257
+ // --- shaped outputs ---------------------------------------------------------
3258
+ const LABEL_VARIANT_EXAMPLES = 5;
3259
+
3260
+ // One identifier can vary as a geography and again as the matching dimension
3261
+ // value; the count is over distinct identifiers (the trailing id token), the
3262
+ // examples prefer the geography, provider, category and target kinds.
3263
+ export function hierarchyLabelVariantSummary(variants: HierarchyLabelVariant[]) {
3264
+ const identifiers = new Set(
3265
+ variants.map((variant) => variant.id.split(/[\s=]/).pop()?.toLowerCase() ?? variant.id),
3266
+ );
3267
+ const ordered = [...variants].sort(
3268
+ (a, b) => Number(a.kind === "dimension value") - Number(b.kind === "dimension value"),
3269
+ );
3270
+ return {
3271
+ count: identifiers.size,
3272
+ entries: variants.length,
3273
+ examples: ordered
3274
+ .slice(0, LABEL_VARIANT_EXAMPLES)
3275
+ .map((variant) => `${variant.kind} ${variant.id}: ${variant.labels.map((l) => `"${l}"`).join(" · ")}`),
3276
+ };
3277
+ }
3278
+
3279
+ export function latestMicrocosmCalibrationSummary(cal: Calibration) {
3280
+ return {
3281
+ available: true,
3282
+ country: cal.country_info,
3283
+ presentation: cal.presentation,
3284
+ target_schema: cal.target_schema,
3285
+ description: cal.description,
3286
+ diagnostics_status: cal.diagnostics_status,
3287
+ ...releaseRole(cal.release_manifest),
3288
+ source: cal.source,
3289
+ release_id: cal.release_id,
3290
+ schema_version: cal.schema_version,
3291
+ weight_entity: cal.weight_entity,
3292
+ options: cal.options,
3293
+ l0_lambda: cal.l0_lambda,
3294
+ n_nonzero: cal.n_nonzero,
3295
+ n_records: cal.n_records,
3296
+ effective_sample_size: cal.effective_sample_size,
3297
+ realized_max_weight_ratio: cal.realized_max_weight_ratio,
3298
+ top_1pct_weight_share: cal.top_1pct_weight_share,
3299
+ initial_loss: cal.initial_loss,
3300
+ final_loss: cal.final_loss,
3301
+ loss_kind: cal.loss_kind,
3302
+ fraction_within_10pct: cal.fraction_within_10pct,
3303
+ loss_trajectory: cal.loss_trajectory,
3304
+ skipped: cal.skipped,
3305
+ declared_targets: cal.declared_targets,
3306
+ compiled_candidate_targets: cal.compiled_candidate_targets,
3307
+ dropped_target_count: cal.dropped_target_names.length,
3308
+ included_target_count: cal.included_target_count,
3309
+ calibration_provenance: cal.calibration_provenance,
3310
+ label_variants: hierarchyLabelVariantSummary(cal.hierarchy_label_variants),
3311
+ target_loss_attribution: targetLossAttributionSummary(cal.target_loss_attribution),
3312
+ total_targets: cal.rows.length,
3313
+ within_tolerance_count: withinToleranceCount(cal.rows),
3314
+ family_fit: familyFitSummary(cal.rows),
3315
+ geography_coverage: cal.geography_coverage,
3316
+ };
3317
+ }
3318
+
3319
+ const EXTREME_RELATIVE_ERROR_THRESHOLD = 10; // 1000%; usually tiny-denominator artifacts.
3320
+
3321
+ function worstBoundedRelativeFit(rows: TargetRow[], limit: number): TargetRow[] {
3322
+ return [...rows]
3323
+ .filter((row) => {
3324
+ const error = numberOrNull(row.abs_relative_error);
3325
+ return error != null && error <= EXTREME_RELATIVE_ERROR_THRESHOLD;
3326
+ })
3327
+ .sort((a, b) => (numberOrNull(b.abs_relative_error) ?? 0) - (numberOrNull(a.abs_relative_error) ?? 0))
3328
+ .slice(0, limit);
3329
+ }
3330
+
3331
+ function extremeRelativeOutliers(rows: TargetRow[], limit: number): TargetRow[] {
3332
+ return [...rows]
3333
+ .filter((row) => {
3334
+ const error = numberOrNull(row.abs_relative_error);
3335
+ return error != null && error > EXTREME_RELATIVE_ERROR_THRESHOLD;
3336
+ })
3337
+ .sort((a, b) => (numberOrNull(b.abs_relative_error) ?? 0) - (numberOrNull(a.abs_relative_error) ?? 0))
3338
+ .slice(0, limit);
3339
+ }
3340
+
3341
+ function largestAbsoluteMisses(rows: TargetRow[], limit: number): TargetRow[] {
3342
+ return [...rows]
3343
+ .filter((row) => numberOrNull(row.abs_final_miss) != null)
3344
+ .sort((a, b) => (numberOrNull(b.abs_final_miss) ?? 0) - (numberOrNull(a.abs_final_miss) ?? 0))
3345
+ .slice(0, limit);
3346
+ }
3347
+
3348
+ function biggestRelativeImprovements(rows: TargetRow[], limit: number): TargetRow[] {
3349
+ return [...rows]
3350
+ .filter((row) => {
3351
+ const improvement = numberOrNull(row.improvement);
3352
+ const initial = numberOrNull(row.initial_relative_error);
3353
+ const final = numberOrNull(row.abs_relative_error);
3354
+ return (
3355
+ improvement != null &&
3356
+ improvement > 0 &&
3357
+ initial != null &&
3358
+ final != null &&
3359
+ Math.abs(initial) <= EXTREME_RELATIVE_ERROR_THRESHOLD &&
3360
+ final <= EXTREME_RELATIVE_ERROR_THRESHOLD
3361
+ );
3362
+ })
3363
+ .sort((a, b) => (numberOrNull(b.improvement) ?? 0) - (numberOrNull(a.improvement) ?? 0))
3364
+ .slice(0, limit);
3365
+ }
3366
+
3367
+ function biggestAbsoluteImprovements(rows: TargetRow[], limit: number): TargetRow[] {
3368
+ return [...rows]
3369
+ .filter((row) => {
3370
+ const improvement = numberOrNull(row.absolute_improvement);
3371
+ return improvement != null && improvement > 0;
3372
+ })
3373
+ .sort((a, b) => (numberOrNull(b.absolute_improvement) ?? 0) - (numberOrNull(a.absolute_improvement) ?? 0))
3374
+ .slice(0, limit);
3375
+ }
3376
+
3377
+ export function latestMicrocosmCalibrationHighlights(cal: Calibration, limit = 15) {
3378
+ const extremeOutliers = extremeRelativeOutliers(cal.rows, limit);
3379
+ return {
3380
+ worst_fit: worstBoundedRelativeFit(cal.rows, limit),
3381
+ biggest_improvements: biggestRelativeImprovements(cal.rows, limit),
3382
+ worst_bounded_relative_fit: worstBoundedRelativeFit(cal.rows, limit),
3383
+ extreme_relative_outliers: extremeOutliers,
3384
+ extreme_relative_outlier_count: cal.rows.filter((row) => {
3385
+ const error = numberOrNull(row.abs_relative_error);
3386
+ return error != null && error > EXTREME_RELATIVE_ERROR_THRESHOLD;
3387
+ }).length,
3388
+ largest_absolute_misses: largestAbsoluteMisses(cal.rows, limit),
3389
+ biggest_relative_improvements: biggestRelativeImprovements(cal.rows, limit),
3390
+ biggest_absolute_improvements: biggestAbsoluteImprovements(cal.rows, limit),
3391
+ };
3392
+ }
3393
+
3394
+ export function latestMicrocosmTargetDiagnosticsPage(requestUrl: string, cal: Calibration) {
3395
+ const rows = cal.rows;
3396
+ const url = new URL(requestUrl);
3397
+ const limit = Math.min(Math.max(Number(url.searchParams.get("limit") ?? "100") || 100, 1), 500);
3398
+ const offset = Math.max(Number(url.searchParams.get("offset") ?? "0") || 0, 0);
3399
+ const includeFamilies = url.searchParams.get("include_families") === "1";
3400
+ const scope = stringParam(url.searchParams.get("scope")) === "healthcare" ? "healthcare" : null;
3401
+ const family = stringParam(url.searchParams.get("family"));
3402
+ const variable = stringParam(url.searchParams.get("variable"));
3403
+ const program = stringParam(url.searchParams.get("program"));
3404
+ const measure = stringParam(url.searchParams.get("measure"));
3405
+ const source = stringParam(url.searchParams.get("source"));
3406
+ const level = stringParam(url.searchParams.get("level"));
3407
+ const geography = stringParam(url.searchParams.get("geography"));
3408
+ const state = stringParam(url.searchParams.get("state"));
3409
+ const direction = stringParam(url.searchParams.get("direction"));
3410
+ const within = booleanParam(url.searchParams.get("within_tolerance"));
3411
+ const search = stringParam(url.searchParams.get("search"));
3412
+ const sortBy = stringParam(url.searchParams.get("sort_by")) ?? "abs_relative_error";
3413
+ const sortDir = stringParam(url.searchParams.get("sort_dir")) === "asc" ? "asc" : "desc";
3414
+ const facetFilters = url.searchParams
3415
+ .getAll("facet")
3416
+ .map((entry) => {
3417
+ const sep = entry.indexOf(":");
3418
+ return sep < 0 ? null : ([entry.slice(0, sep), entry.slice(sep + 1)] as const);
3419
+ })
3420
+ .filter((v): v is readonly [string, string] => v != null);
3421
+ const scopedRows = scope === "healthcare" ? rows.filter(isHealthcareTarget) : rows;
3422
+ const metadata = targetDiagnosticsMetadata(scopedRows);
3423
+ const scopedWithin10Pct = scopedRows.filter(
3424
+ (row) => (numberOrNull(row.abs_relative_error) ?? Infinity) <= 0.1,
3425
+ ).length;
3426
+
3427
+ let filtered = scopedRows;
3428
+ if (family) filtered = filtered.filter((row) => row.family === family);
3429
+ if (variable) filtered = filtered.filter((row) => row.variable_key === variable);
3430
+ if (program) filtered = filtered.filter((row) => targetProgramKey(row) === program);
3431
+ if (measure) filtered = filtered.filter((row) => row.measure === measure);
3432
+ if (source) filtered = filtered.filter((row) => row.source === source);
3433
+ if (level) filtered = filtered.filter((row) => row.level === level);
3434
+ if (geography) filtered = filtered.filter((row) => row.geography === geography);
3435
+ if (state) filtered = filtered.filter((row) => row.state === state);
3436
+ const dimensions = variable ? computeDimensions(filtered) : [];
3437
+ for (const [key, value] of facetFilters) {
3438
+ filtered = filtered.filter((row) => rowFacetValue(row, key) === value);
3439
+ }
3440
+ if (direction) filtered = filtered.filter((row) => row.direction === direction);
3441
+ // The artifact does not populate row.within_tolerance, so derive the "within
3442
+ // 10%" fit from the relative error — consistent with the within_10pct counts
3443
+ // and the "% on target" shown elsewhere.
3444
+ if (within !== null) {
3445
+ filtered = filtered.filter((row) => {
3446
+ const error = numberOrNull(row.abs_relative_error);
3447
+ const isWithin = error != null && error <= 0.1;
3448
+ return isWithin === within;
3449
+ });
3450
+ }
3451
+ if (search) filtered = filtered.filter((row) => matchesSearch(row, search));
3452
+ const sortValue = (row: TargetRow) =>
3453
+ rowFacetValue(row, sortBy) ?? row[sortBy];
3454
+ filtered = [...filtered].sort((a, b) => {
3455
+ const aVal = sortValue(a);
3456
+ const bVal = sortValue(b);
3457
+ if (aVal == null && bVal == null) return 0;
3458
+ if (aVal == null) return 1;
3459
+ if (bVal == null) return -1;
3460
+ const cmp =
3461
+ typeof aVal === "number" && typeof bVal === "number"
3462
+ ? aVal - bVal
3463
+ : String(aVal).localeCompare(String(bVal));
3464
+ return sortDir === "asc" ? cmp : -cmp;
3465
+ });
3466
+
3467
+ return {
3468
+ available: true,
3469
+ country: cal.country_info,
3470
+ presentation: cal.presentation,
3471
+ target_schema: cal.target_schema,
3472
+ description: cal.description,
3473
+ diagnostics_status: cal.diagnostics_status,
3474
+ ...releaseRole(cal.release_manifest),
3475
+ source: cal.source,
3476
+ release_id: cal.release_id,
3477
+ schema_version: cal.schema_version,
3478
+ metric: "relative_error",
3479
+ families: includeFamilies ? microcosmTargetFamilies(scopedRows) : [],
3480
+ sources: metadata.sources,
3481
+ levels: metadata.levels,
3482
+ geographies: metadata.geographies,
3483
+ variables: metadata.variables,
3484
+ dimensions,
3485
+ scope_counts: metadata.scope_counts,
3486
+ summary: {
3487
+ diagnostics_status: cal.diagnostics_status,
3488
+ total_targets: scopedRows.length,
3489
+ within_tolerance_count: withinToleranceCount(scopedRows),
3490
+ fraction_within_10pct: scopedRows.length ? scopedWithin10Pct / scopedRows.length : null,
3491
+ included_target_count: scopedRows.filter((row) => row.calibration_status === "included").length,
3492
+ skipped_target_count: scopedRows.filter((row) => row.calibration_status === "skipped").length,
3493
+ dropped_target_count: scopedRows.filter((row) => row.calibration_status === "not_materialized").length,
3494
+ declared_targets: cal.declared_targets,
3495
+ compiled_candidate_targets: cal.compiled_candidate_targets,
3496
+ },
3497
+ total_targets: scopedRows.length,
3498
+ filtered_total: filtered.length,
3499
+ returned: filtered.slice(offset, offset + limit).length,
3500
+ limit,
3501
+ offset,
3502
+ has_next: offset + limit < filtered.length,
3503
+ display_limit: limit,
3504
+ targets: filtered.slice(offset, offset + limit).map(targetResponseRow),
3505
+ filters: { scope, family, variable, program, measure, source, level, geography, state, direction, within_tolerance: within, search, sort_by: sortBy, sort_dir: sortDir },
3506
+ };
3507
+ }
3508
+
3509
+ export function latestMicrocosmTargetInvestigation(requestUrl: string, cal: Calibration) {
3510
+ const url = new URL(requestUrl);
3511
+ const target = stringParam(url.searchParams.get("target"));
3512
+ if (!target) {
3513
+ return {
3514
+ available: false,
3515
+ detail: "Missing target query parameter.",
3516
+ };
3517
+ }
3518
+ const row = cal.rows.find((candidate) => {
3519
+ // A target is found by the record and keys it shows: a target whose
3520
+ // identity spans several facts by its own name, not by one member's.
3521
+ const chronicle = asObject(shownChronicle(candidate));
3522
+ return [
3523
+ stringValue(candidate.name),
3524
+ stringValue(candidate.base_name),
3525
+ stringValue(chronicle.source_record_id),
3526
+ stringValue(chronicle.fact_key),
3527
+ stringValue(chronicle.semantic_fact_key),
3528
+ stringValue(chronicle.aggregate_fact_key),
3529
+ stringValue(chronicle.legacy_fact_key),
3530
+ ].some((value) => value === target);
3531
+ });
3532
+ if (!row) {
3533
+ // A member fact is not the target it belongs to, and one fact can be a
3534
+ // member of many targets: Microcosm restates its twelve CGT Table 5
3535
+ // region cells by one Table 1 share (tools/generate_uk_target_references.py:1117-1119
3536
+ // at 0ff293b). So the answer names each, for the caller to choose.
3537
+ const memberOf = cal.rows
3538
+ .filter((candidate) => listsMemberFact(candidate, target))
3539
+ .map((candidate) => ({
3540
+ name: stringValue(candidate.name),
3541
+ target_label: stringValue(candidate.target_label),
3542
+ }));
3543
+ const targets = `${memberOf.length} target${memberOf.length === 1 ? "" : "s"}`;
3544
+ return {
3545
+ available: false,
3546
+ release_id: cal.release_id,
3547
+ detail: memberOf.length
3548
+ ? `Target not found: ${target}. It is a member fact of ${targets}: ` +
3549
+ `${memberOf.map((candidate) => candidate.name).join(", ")}.`
3550
+ : `Target not found: ${target}`,
3551
+ member_of: memberOf,
3552
+ };
3553
+ }
3554
+ return {
3555
+ available: true,
3556
+ ...targetInvestigationPacket(row, cal),
3557
+ };
3558
+ }
3559
+
3560
+ // Whether a target built from several facts lists one of them under this
3561
+ // key: the key Microcosm lists it under in ledger_member_fact_keys, or any
3562
+ // record id or key of its representative, which the row keeps.
3563
+ function listsMemberFact(row: TargetRow, key: string): boolean {
3564
+ const shown = asObject(shownChronicle(row));
3565
+ const members = Array.isArray(shown.member_fact_keys) ? shown.member_fact_keys : [];
3566
+ if (!members.length) return false;
3567
+ if (members.includes(key)) return true;
3568
+ const representative = asObject(row.chronicle);
3569
+ return [
3570
+ representative.source_record_id,
3571
+ representative.fact_key,
3572
+ representative.semantic_fact_key,
3573
+ representative.aggregate_fact_key,
3574
+ representative.legacy_fact_key,
3575
+ ].some((value) => stringValue(value) === key);
3576
+ }
3577
+
3578
+ // --- version-over-version comparison ----------------------------------------
3579
+ function absRel(row: TargetRow | undefined): number | null {
3580
+ return row ? numberOrNull(row.abs_relative_error) : null;
3581
+ }
3582
+
3583
+ function comparableRelative(row: TargetRow | undefined): number | null {
3584
+ return row ? numberOrNull(row.final_error) : null;
3585
+ }
3586
+
3587
+ function absoluteMiss(row: TargetRow | undefined): number | null {
3588
+ if (!row) return null;
3589
+ const estimate = numberOrNull(row.final_estimate);
3590
+ const target = numberOrNull(row.target);
3591
+ return estimate == null || target == null ? null : estimate - target;
3592
+ }
3593
+
3594
+ function mean(values: number[]): number | null {
3595
+ return values.length ? values.reduce((sum, value) => sum + value, 0) / values.length : null;
3596
+ }
3597
+
3598
+ function comparisonVariableRows(rows: TargetRow[]) {
3599
+ const groups = new Map<string, TargetRow[]>();
3600
+ for (const row of rows) {
3601
+ const key = String(row.variable_key ?? row.variable ?? "unknown");
3602
+ (groups.get(key) ?? groups.set(key, []).get(key)!).push(row);
3603
+ }
3604
+ return [...groups.entries()]
3605
+ .map(([variable_key, group]) => {
3606
+ const relativeRows = group.filter((row) => row.error_kind === "relative");
3607
+ const aErrors = relativeRows
3608
+ .map((row) => numberOrNull(row.a_error))
3609
+ .filter((value): value is number => value != null)
3610
+ .map(Math.abs);
3611
+ const bErrors = relativeRows
3612
+ .map((row) => numberOrNull(row.b_error))
3613
+ .filter((value): value is number => value != null)
3614
+ .map(Math.abs);
3615
+ const aMeanAbsError = mean(aErrors);
3616
+ const bMeanAbsError = mean(bErrors);
3617
+ const meanAbsDelta =
3618
+ aMeanAbsError == null || bMeanAbsError == null
3619
+ ? null
3620
+ : bMeanAbsError - aMeanAbsError;
3621
+ const sample = group[0] ?? {};
3622
+ return {
3623
+ variable_key,
3624
+ source: sample.source ?? null,
3625
+ variable: sample.variable ?? null,
3626
+ measure: sample.measure ?? null,
3627
+ ...categoryLevels(group, null),
3628
+ common_targets: group.length,
3629
+ relative_targets: relativeRows.length,
3630
+ improved: relativeRows.filter((row) => (numberOrNull(row.abs_rel_delta) ?? 0) < -1e-9).length,
3631
+ regressed: relativeRows.filter((row) => (numberOrNull(row.abs_rel_delta) ?? 0) > 1e-9).length,
3632
+ unchanged: relativeRows.filter((row) => numberOrNull(row.abs_rel_delta) === 0).length,
3633
+ a_mean_abs_error: aMeanAbsError,
3634
+ b_mean_abs_error: bMeanAbsError,
3635
+ mean_abs_delta: meanAbsDelta,
3636
+ };
3637
+ })
3638
+ .sort((a, b) => {
3639
+ const aDelta = numberOrNull(a.mean_abs_delta);
3640
+ const bDelta = numberOrNull(b.mean_abs_delta);
3641
+ if (aDelta == null && bDelta == null) return b.common_targets - a.common_targets;
3642
+ if (aDelta == null) return 1;
3643
+ if (bDelta == null) return -1;
3644
+ return Math.abs(bDelta) - Math.abs(aDelta) || b.relative_targets - a.relative_targets;
3645
+ });
3646
+ }
3647
+
3648
+ // Diff two releases' calibration using normalized target identities. Shared
3649
+ // targets get a fit delta (|b rel err| - |a rel err|; negative = b fits
3650
+ // better); targets present in only one release are listed as added/removed.
3651
+ // Losses across releases are not comparable when the surfaces differ.
3652
+ export function buildComparison(a: Calibration, b: Calibration) {
3653
+ const matched = matchTargetSurfaces(a, b);
3654
+ const common: TargetRow[] = [];
3655
+ const added = matched.matches.filter((match) => match.comparison_status === "added").length;
3656
+ const removed = matched.matches.filter((match) => match.comparison_status === "removed").length;
3657
+ let improved = 0;
3658
+ let regressed = 0;
3659
+ for (const match of matched.matches) {
3660
+ if (!match.current || !match.candidate) continue;
3661
+ const ar = match.current;
3662
+ const br = match.candidate;
3663
+ const name = String(br.base_name ?? br.name ?? ar.base_name ?? ar.name ?? "");
3664
+ const aAbs = absRel(ar);
3665
+ const bAbs = absRel(br);
3666
+ const delta = aAbs != null && bAbs != null ? bAbs - aAbs : null;
3667
+ if (delta != null && delta < -1e-9) improved += 1;
3668
+ else if (delta != null && delta > 1e-9) regressed += 1;
3669
+ const aRelative = comparableRelative(ar);
3670
+ const bRelative = comparableRelative(br);
3671
+ const errorKind = aRelative != null && bRelative != null ? "relative" : "absolute";
3672
+ common.push({
3673
+ comparison_id: match.comparison_id,
3674
+ match_kind: match.match_kind,
3675
+ current_name: match.current_name,
3676
+ candidate_name: match.candidate_name,
3677
+ current_representation: match.current_representation,
3678
+ candidate_representation: match.candidate_representation,
3679
+ name,
3680
+ target_label:
3681
+ br.target_label ??
3682
+ ar.target_label ??
3683
+ [br.geography ?? ar.geography, br.breakdown ?? ar.breakdown]
3684
+ .filter(Boolean)
3685
+ .join(" · "),
3686
+ source: br.source ?? ar.source,
3687
+ source_label: br.source_label ?? ar.source_label,
3688
+ variable_key: br.variable_key ?? ar.variable_key,
3689
+ variable: br.variable ?? ar.variable,
3690
+ variable_label: br.variable_label ?? ar.variable_label,
3691
+ measure: br.measure ?? ar.measure,
3692
+ level: br.level ?? ar.level,
3693
+ breakdown: br.breakdown ?? ar.breakdown,
3694
+ dims: br.dims ?? ar.dims,
3695
+ target_dimensions: br.target_dimensions ?? ar.target_dimensions,
3696
+ geography: br.geography ?? ar.geography,
3697
+ a_target: numberOrNull(ar.target),
3698
+ b_target: numberOrNull(br.target),
3699
+ a_final_estimate: ar.final_estimate ?? null,
3700
+ b_final_estimate: br.final_estimate ?? null,
3701
+ error_kind: errorKind,
3702
+ a_error: errorKind === "relative" ? aRelative : absoluteMiss(ar),
3703
+ b_error: errorKind === "relative" ? bRelative : absoluteMiss(br),
3704
+ a_relative_error: aRelative,
3705
+ b_relative_error: bRelative,
3706
+ a_within_tolerance: ar.within_tolerance ?? null,
3707
+ b_within_tolerance: br.within_tolerance ?? null,
3708
+ abs_rel_delta: delta,
3709
+ });
3710
+ }
3711
+ common.sort(
3712
+ (x, y) =>
3713
+ Math.abs(numberOrNull(y.abs_rel_delta) ?? 0) -
3714
+ Math.abs(numberOrNull(x.abs_rel_delta) ?? 0),
3715
+ );
3716
+
3717
+ const surfacesDiffer =
3718
+ a.rows.length !== b.rows.length || added > 0 || removed > 0;
3719
+ return {
3720
+ a: {
3721
+ release_id: a.release_id,
3722
+ description: a.description,
3723
+ total_targets: a.rows.length,
3724
+ initial_loss: a.initial_loss,
3725
+ final_loss: a.final_loss,
3726
+ loss_kind: a.loss_kind,
3727
+ weighted_target_error: a.target_loss_attribution.aggregate,
3728
+ fraction_within_10pct: a.fraction_within_10pct,
3729
+ },
3730
+ b: {
3731
+ release_id: b.release_id,
3732
+ description: b.description,
3733
+ total_targets: b.rows.length,
3734
+ initial_loss: b.initial_loss,
3735
+ final_loss: b.final_loss,
3736
+ loss_kind: b.loss_kind,
3737
+ weighted_target_error: b.target_loss_attribution.aggregate,
3738
+ fraction_within_10pct: b.fraction_within_10pct,
3739
+ },
3740
+ summary: {
3741
+ common: common.length,
3742
+ added,
3743
+ removed,
3744
+ improved,
3745
+ regressed,
3746
+ unchanged: common.length - improved - regressed,
3747
+ losses_comparable: !surfacesDiffer && a.loss_kind === b.loss_kind,
3748
+ loss_kind: a.loss_kind === b.loss_kind ? a.loss_kind : "mixed",
3749
+ matching: matched.matching,
3750
+ },
3751
+ variables: comparisonVariableRows(common),
3752
+ rows: common,
3753
+ };
3754
+ }
3755
+
3756
+ export async function loadComparison(
3757
+ aId: string,
3758
+ bId: string,
3759
+ revalidate: number,
3760
+ country: MicrocosmCountry = "us",
3761
+ ) {
3762
+ const [a, b] = await Promise.all([
3763
+ loadRelease(aId, revalidate, country),
3764
+ loadRelease(bId, revalidate, country),
3765
+ ]);
3766
+ return buildComparison(a, b);
3767
+ }