create-quorum-router 0.1.15 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,7 +18,7 @@ deno task intake
18
18
  deno task supabase:status
19
19
  ```
20
20
 
21
- Current package version: `create-quorum-router@0.1.15`. Releases are published
21
+ Current package version: `create-quorum-router@0.1.17`. Releases are published
22
22
  from an immutable Git tag through GitHub Actions OIDC Trusted Publishing.
23
23
 
24
24
  ## What the generated project supports
@@ -39,6 +39,12 @@ execution. Both demos are local-only; the hierarchy demo does not call provider
39
39
  APIs. On a new Deno installation, the first run resolves the pinned Zod
40
40
  dependency before execution.
41
41
 
42
+ Generated projects also export the opt-in
43
+ `resolveHierarchicalTaskCalibrationWithDriftGuard()` API. It can quarantine a
44
+ child whose Brier score is worse than its immediate parent by more than an
45
+ explicit caller threshold. This is outcome-metric drift handling, not semantic
46
+ label verification; it does not rename labels or affect routing authority.
47
+
42
48
  `deno task intake` is the first real setup command. It detects local provider
43
49
  wrappers, checks OAuth/session status, runs safe list-only model inventory where
44
50
  possible, writes redacted local health artifacts under `out/`, and recommends
@@ -3,7 +3,7 @@ const fs = require("fs");
3
3
  const path = require("path");
4
4
  const { spawnSync } = require("child_process");
5
5
 
6
- const VERSION = "0.1.15";
6
+ const VERSION = "0.1.17";
7
7
  const SUPPORTED_TEMPLATES = new Set(["basic"]);
8
8
 
9
9
  function usage() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-quorum-router",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "Create a local QuorumRouter project.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  # QuorumRouter generated workspace
2
2
 
3
3
  This generated workspace contains the MIT-licensed QuorumRouter current release.
4
- npm latest targets v0.1.15.
4
+ npm latest targets v0.1.17.
5
5
 
6
6
  QuorumRouter is **MIT**. It is **open source**. Commercial and production use
7
7
  are permitted under the MIT License.
@@ -67,6 +67,13 @@ group that reaches the configured sample threshold. Groups never cross exact
67
67
  provider/model source boundaries, labels must not contain raw prompts, and the
68
68
  result remains advisory-only.
69
69
 
70
+ The scaffold also exports opt-in
71
+ `resolveHierarchicalTaskCalibrationWithDriftGuard()`. It can quarantine a child
72
+ whose Brier score is worse than its immediate parent by more than an explicit
73
+ caller threshold and continue parent fallback. This is an outcome-metric
74
+ heuristic, not semantic label verification; it does not rename labels or affect
75
+ routing authority.
76
+
70
77
  `intake` detects local provider wrappers, checks OAuth/session status, runs safe
71
78
  model inventory/list-only probes where possible, writes local health traces
72
79
  under `out/`, and recommends the next command.
@@ -8,6 +8,14 @@ function stableMetric(value: number): number {
8
8
  return rounded === 0 ? 0 : rounded;
9
9
  }
10
10
 
11
+ function isCanonicalBinaryAccuracy(
12
+ sampleCount: number,
13
+ accuracy: number,
14
+ ): boolean {
15
+ const correctCount = Math.round(accuracy * sampleCount);
16
+ return accuracy === stableMetric(correctCount / sampleCount);
17
+ }
18
+
11
19
  function boundedCanonicalText(maxLength: number) {
12
20
  return z.string().trim().transform((value) => value.normalize("NFC")).pipe(
13
21
  z.string().min(1).max(maxLength).refine(
@@ -254,6 +262,7 @@ export function aggregateTaskCalibration(
254
262
 
255
263
  export const MAX_HIERARCHICAL_CALIBRATION_GROUPS =
256
264
  MAX_CALIBRATION_OBSERVATIONS * 3;
265
+ const HIERARCHICAL_ROLLUP_TOLERANCE = 1e-9;
257
266
 
258
267
  export const HierarchicalCalibrationScopeSchema = z.enum([
259
268
  "task_type",
@@ -488,6 +497,344 @@ export const HierarchicalTaskCalibrationSelectionSchema = z.object({
488
497
  }
489
498
  });
490
499
 
500
+ export const HierarchicalCalibrationDriftGuardOptionsSchema = z.object({
501
+ maximum_child_parent_brier_score_delta: z.number().finite().min(0).max(1),
502
+ }).strict();
503
+
504
+ export const HierarchicalTaskCalibrationGuardedReportSchema =
505
+ HierarchicalTaskCalibrationReportSchema.superRefine((report, context) => {
506
+ report.groups.forEach((parent, parentIndex) => {
507
+ if (!isCanonicalBinaryAccuracy(parent.sample_count, parent.accuracy)) {
508
+ context.addIssue({
509
+ code: "custom",
510
+ message:
511
+ "guarded accuracy must be the canonical ratio of integer correct observations",
512
+ path: ["groups", parentIndex, "accuracy"],
513
+ });
514
+ }
515
+
516
+ const childScope = parent.scope === "task_type"
517
+ ? "task_subtype"
518
+ : parent.scope === "task_subtype"
519
+ ? "prompt_pattern"
520
+ : undefined;
521
+ if (childScope === undefined) return;
522
+
523
+ const children = report.groups.filter((child) =>
524
+ child.scope === childScope && child.task_type === parent.task_type &&
525
+ child.source.provider === parent.source.provider &&
526
+ child.source.model === parent.source.model &&
527
+ (parent.scope === "task_type" ||
528
+ child.task_subtype === parent.task_subtype)
529
+ );
530
+ if (children.length === 0) return;
531
+
532
+ const childCount = children.reduce(
533
+ (sum, child) => sum + child.sample_count,
534
+ 0,
535
+ );
536
+ const remainderCount = parent.sample_count - childCount;
537
+ if (remainderCount < 0) {
538
+ context.addIssue({
539
+ code: "custom",
540
+ message:
541
+ "hierarchical child sample counts cannot exceed their parent",
542
+ path: ["groups", parentIndex, "sample_count"],
543
+ });
544
+ return;
545
+ }
546
+
547
+ for (
548
+ const metric of ["accuracy", "mean_confidence", "brier_score"] as const
549
+ ) {
550
+ const parentTotal = parent[metric] * parent.sample_count;
551
+ const childTotal = children.reduce(
552
+ (sum, child) => sum + child[metric] * child.sample_count,
553
+ 0,
554
+ );
555
+ const remainderTotal = parentTotal - childTotal;
556
+ if (
557
+ remainderTotal < -HIERARCHICAL_ROLLUP_TOLERANCE ||
558
+ remainderTotal > remainderCount + HIERARCHICAL_ROLLUP_TOLERANCE
559
+ ) {
560
+ context.addIssue({
561
+ code: "custom",
562
+ message:
563
+ `hierarchical ${metric} totals are incompatible with the parent roll-up`,
564
+ path: ["groups", parentIndex, metric],
565
+ });
566
+ }
567
+ }
568
+ });
569
+ });
570
+
571
+ export const HierarchicalCalibrationDriftStatusSchema = z.enum([
572
+ "not_applicable",
573
+ "not_evaluated",
574
+ "parent_unavailable",
575
+ "within_threshold",
576
+ "quarantined",
577
+ ]);
578
+
579
+ const HierarchicalGuardedCalibrationCandidateSchema = z.object({
580
+ scope: HierarchicalCalibrationScopeSchema,
581
+ sample_count: z.number().int().positive().max(MAX_CALIBRATION_OBSERVATIONS)
582
+ .nullable(),
583
+ sample_status: z.enum(["missing", "insufficient", "sufficient"]),
584
+ accuracy: z.number().finite().min(0).max(1).nullable(),
585
+ mean_confidence: z.number().finite().min(0).max(1).nullable(),
586
+ mean_calibration_bias: z.number().finite().min(-1).max(1).nullable(),
587
+ brier_score: z.number().finite().min(0).max(1).nullable(),
588
+ drift_status: HierarchicalCalibrationDriftStatusSchema,
589
+ parent_scope: HierarchicalCalibrationScopeSchema.nullable(),
590
+ child_parent_brier_score_delta: z.number().finite().min(-1).max(1).nullable(),
591
+ }).strict().superRefine((candidate, context) => {
592
+ const metrics = [
593
+ candidate.accuracy,
594
+ candidate.mean_confidence,
595
+ candidate.mean_calibration_bias,
596
+ candidate.brier_score,
597
+ ];
598
+ if (
599
+ (candidate.sample_status === "missing") !==
600
+ (candidate.sample_count === null)
601
+ ) {
602
+ context.addIssue({
603
+ code: "custom",
604
+ message: "missing candidates must have a null sample_count",
605
+ });
606
+ }
607
+ if (
608
+ candidate.sample_status === "missing"
609
+ ? metrics.some((metric) => metric !== null)
610
+ : metrics.some((metric) => metric === null)
611
+ ) {
612
+ context.addIssue({
613
+ code: "custom",
614
+ message:
615
+ "candidate metrics must be null exactly when the candidate is missing",
616
+ });
617
+ }
618
+ if (
619
+ candidate.sample_count !== null && candidate.accuracy !== null &&
620
+ candidate.mean_confidence !== null &&
621
+ candidate.mean_calibration_bias !== null
622
+ ) {
623
+ if (
624
+ candidate.mean_calibration_bias !==
625
+ stableMetric(candidate.mean_confidence - candidate.accuracy)
626
+ ) {
627
+ context.addIssue({
628
+ code: "custom",
629
+ message:
630
+ "candidate mean_calibration_bias must equal mean_confidence - accuracy",
631
+ path: ["mean_calibration_bias"],
632
+ });
633
+ }
634
+ if (
635
+ !isCanonicalBinaryAccuracy(candidate.sample_count, candidate.accuracy)
636
+ ) {
637
+ context.addIssue({
638
+ code: "custom",
639
+ message:
640
+ "candidate accuracy must be the canonical ratio of integer correct observations",
641
+ path: ["accuracy"],
642
+ });
643
+ }
644
+ }
645
+ });
646
+
647
+ export const HierarchicalTaskCalibrationGuardedSelectionSchema = z.object({
648
+ schema_version: z.literal(
649
+ "quorum-router.hierarchical-guarded-selection.v1",
650
+ ),
651
+ advisory_only: z.literal(true),
652
+ query: HierarchicalTaskCalibrationQuerySchema,
653
+ requested_scope: HierarchicalCalibrationScopeSchema,
654
+ minimum_sample_count: z.number().int().positive().max(
655
+ MAX_CALIBRATION_OBSERVATIONS,
656
+ ),
657
+ drift_guard: HierarchicalCalibrationDriftGuardOptionsSchema,
658
+ resolution_status: z.enum(["selected", "no_eligible_group"]),
659
+ selected_scope: HierarchicalCalibrationScopeSchema.nullable(),
660
+ candidates: z.array(HierarchicalGuardedCalibrationCandidateSchema).min(1)
661
+ .max(3),
662
+ selected_group: HierarchicalTaskCalibrationGroupSchema.optional(),
663
+ }).strict().superRefine((selection, context) => {
664
+ const queryScope = selection.query.prompt_pattern !== undefined
665
+ ? "prompt_pattern"
666
+ : selection.query.task_subtype !== undefined
667
+ ? "task_subtype"
668
+ : "task_type";
669
+ if (selection.requested_scope !== queryScope) {
670
+ context.addIssue({
671
+ code: "custom",
672
+ message: "requested_scope must match the query labels",
673
+ path: ["requested_scope"],
674
+ });
675
+ }
676
+
677
+ const expectedScopes: HierarchicalCalibrationScope[] =
678
+ selection.requested_scope === "prompt_pattern"
679
+ ? ["prompt_pattern", "task_subtype", "task_type"]
680
+ : selection.requested_scope === "task_subtype"
681
+ ? ["task_subtype", "task_type"]
682
+ : ["task_type"];
683
+ if (
684
+ JSON.stringify(selection.candidates.map((candidate) => candidate.scope)) !==
685
+ JSON.stringify(expectedScopes)
686
+ ) {
687
+ context.addIssue({
688
+ code: "custom",
689
+ message: "candidates must follow the requested scope fallback order",
690
+ path: ["candidates"],
691
+ });
692
+ }
693
+
694
+ selection.candidates.forEach((candidate, index) => {
695
+ const expectedSampleStatus = candidate.sample_count === null
696
+ ? "missing"
697
+ : candidate.sample_count < selection.minimum_sample_count
698
+ ? "insufficient"
699
+ : "sufficient";
700
+ if (candidate.sample_status !== expectedSampleStatus) {
701
+ context.addIssue({
702
+ code: "custom",
703
+ message:
704
+ "candidate sample_status must match the configured sample threshold",
705
+ path: ["candidates", index, "sample_status"],
706
+ });
707
+ }
708
+ const isRoot = candidate.scope === "task_type";
709
+ const immediateParent = selection.candidates[index + 1];
710
+ if (isRoot) {
711
+ if (
712
+ candidate.drift_status !== "not_applicable" ||
713
+ candidate.parent_scope !== null ||
714
+ candidate.child_parent_brier_score_delta !== null
715
+ ) {
716
+ context.addIssue({
717
+ code: "custom",
718
+ message: "task_type drift comparison must be not_applicable",
719
+ path: ["candidates", index],
720
+ });
721
+ }
722
+ return;
723
+ }
724
+
725
+ if (candidate.parent_scope !== immediateParent?.scope) {
726
+ context.addIssue({
727
+ code: "custom",
728
+ message: "child candidates must name their immediate parent scope",
729
+ path: ["candidates", index, "parent_scope"],
730
+ });
731
+ }
732
+ if (candidate.sample_status !== "sufficient") {
733
+ if (
734
+ candidate.drift_status !== "not_evaluated" ||
735
+ candidate.child_parent_brier_score_delta !== null
736
+ ) {
737
+ context.addIssue({
738
+ code: "custom",
739
+ message: "non-sufficient child drift must not be evaluated",
740
+ path: ["candidates", index],
741
+ });
742
+ }
743
+ return;
744
+ }
745
+ if (immediateParent?.sample_status !== "sufficient") {
746
+ if (
747
+ candidate.drift_status !== "parent_unavailable" ||
748
+ candidate.child_parent_brier_score_delta !== null
749
+ ) {
750
+ context.addIssue({
751
+ code: "custom",
752
+ message:
753
+ "a sufficient child without a sufficient parent is unavailable",
754
+ path: ["candidates", index],
755
+ });
756
+ }
757
+ return;
758
+ }
759
+
760
+ const delta = candidate.child_parent_brier_score_delta;
761
+ if (
762
+ delta === null || candidate.brier_score === null ||
763
+ immediateParent.brier_score === null
764
+ ) {
765
+ context.addIssue({
766
+ code: "custom",
767
+ message: "comparable child candidates require Brier score evidence",
768
+ path: ["candidates", index, "child_parent_brier_score_delta"],
769
+ });
770
+ return;
771
+ }
772
+ const rawDelta = candidate.brier_score - immediateParent.brier_score;
773
+ if (delta !== stableMetric(rawDelta)) {
774
+ context.addIssue({
775
+ code: "custom",
776
+ message: "Brier score delta must match the candidate metric snapshots",
777
+ path: ["candidates", index, "child_parent_brier_score_delta"],
778
+ });
779
+ }
780
+ const expectedStatus = rawDelta >
781
+ selection.drift_guard.maximum_child_parent_brier_score_delta
782
+ ? "quarantined"
783
+ : "within_threshold";
784
+ if (candidate.drift_status !== expectedStatus) {
785
+ context.addIssue({
786
+ code: "custom",
787
+ message: "drift_status must match the configured Brier score threshold",
788
+ path: ["candidates", index, "drift_status"],
789
+ });
790
+ }
791
+ });
792
+
793
+ const firstEligible = selection.candidates.find((candidate) =>
794
+ candidate.sample_status === "sufficient" &&
795
+ (candidate.drift_status === "within_threshold" ||
796
+ candidate.drift_status === "not_applicable")
797
+ );
798
+ if (firstEligible === undefined) {
799
+ if (
800
+ selection.resolution_status !== "no_eligible_group" ||
801
+ selection.selected_scope !== null ||
802
+ selection.selected_group !== undefined
803
+ ) {
804
+ context.addIssue({
805
+ code: "custom",
806
+ message: "no eligible candidate must produce no selection",
807
+ });
808
+ }
809
+ } else if (
810
+ selection.resolution_status !== "selected" ||
811
+ selection.selected_scope !== firstEligible.scope ||
812
+ selection.selected_group?.scope !== firstEligible.scope ||
813
+ selection.selected_group.sample_count !== firstEligible.sample_count ||
814
+ selection.selected_group.sample_status !== "sufficient" ||
815
+ selection.selected_group.accuracy !== firstEligible.accuracy ||
816
+ selection.selected_group.mean_confidence !==
817
+ firstEligible.mean_confidence ||
818
+ selection.selected_group.mean_calibration_bias !==
819
+ firstEligible.mean_calibration_bias ||
820
+ selection.selected_group.brier_score !== firstEligible.brier_score ||
821
+ selection.selected_group.task_type !== selection.query.task_type ||
822
+ selection.selected_group.source.provider !==
823
+ selection.query.source.provider ||
824
+ selection.selected_group.source.model !== selection.query.source.model ||
825
+ (firstEligible.scope !== "task_type" &&
826
+ selection.selected_group.task_subtype !== selection.query.task_subtype) ||
827
+ (firstEligible.scope === "prompt_pattern" &&
828
+ selection.selected_group.prompt_pattern !==
829
+ selection.query.prompt_pattern)
830
+ ) {
831
+ context.addIssue({
832
+ code: "custom",
833
+ message: "guarded selection must use the first eligible candidate",
834
+ });
835
+ }
836
+ });
837
+
491
838
  export const HierarchicalTaskCalibrationDecisionSchema = z.object({
492
839
  report: HierarchicalTaskCalibrationReportSchema,
493
840
  selection: HierarchicalTaskCalibrationSelectionSchema,
@@ -540,6 +887,38 @@ export const HierarchicalTaskCalibrationDecisionSchema = z.object({
540
887
  }
541
888
  });
542
889
 
890
+ export const HierarchicalTaskCalibrationGuardedDecisionSchema = z.object({
891
+ report: HierarchicalTaskCalibrationGuardedReportSchema,
892
+ selection: HierarchicalTaskCalibrationGuardedSelectionSchema,
893
+ }).strict().superRefine((decision, context) => {
894
+ const parsedReport = HierarchicalTaskCalibrationGuardedReportSchema.safeParse(
895
+ decision.report,
896
+ );
897
+ const parsedSelection = HierarchicalTaskCalibrationGuardedSelectionSchema
898
+ .safeParse(
899
+ decision.selection,
900
+ );
901
+ if (!parsedReport.success || !parsedSelection.success) return;
902
+
903
+ const expected = resolveHierarchicalTaskCalibrationWithDriftGuard(
904
+ parsedReport.data,
905
+ parsedSelection.data.query,
906
+ parsedSelection.data.drift_guard,
907
+ );
908
+ if (JSON.stringify(parsedSelection.data) !== JSON.stringify(expected)) {
909
+ context.addIssue({
910
+ code: "custom",
911
+ message: "guarded selection must be derived from the aggregate report",
912
+ path: ["selection"],
913
+ });
914
+ }
915
+ });
916
+
917
+ export const HierarchicalTaskCalibrationAnyDecisionSchema = z.union([
918
+ HierarchicalTaskCalibrationDecisionSchema,
919
+ HierarchicalTaskCalibrationGuardedDecisionSchema,
920
+ ]);
921
+
543
922
  export type HierarchicalCalibrationScope = z.infer<
544
923
  typeof HierarchicalCalibrationScopeSchema
545
924
  >;
@@ -561,6 +940,18 @@ export type HierarchicalTaskCalibrationSelection = z.infer<
561
940
  export type HierarchicalTaskCalibrationDecision = z.infer<
562
941
  typeof HierarchicalTaskCalibrationDecisionSchema
563
942
  >;
943
+ export type HierarchicalCalibrationDriftGuardOptions = z.infer<
944
+ typeof HierarchicalCalibrationDriftGuardOptionsSchema
945
+ >;
946
+ export type HierarchicalTaskCalibrationGuardedSelection = z.infer<
947
+ typeof HierarchicalTaskCalibrationGuardedSelectionSchema
948
+ >;
949
+ export type HierarchicalTaskCalibrationGuardedDecision = z.infer<
950
+ typeof HierarchicalTaskCalibrationGuardedDecisionSchema
951
+ >;
952
+ export type HierarchicalTaskCalibrationAnyDecision = z.infer<
953
+ typeof HierarchicalTaskCalibrationAnyDecisionSchema
954
+ >;
564
955
 
565
956
  type HierarchicalGroupSeed = {
566
957
  scope: HierarchicalCalibrationScope;
@@ -745,3 +1136,125 @@ export function resolveHierarchicalTaskCalibration(
745
1136
  ...(selected_group === undefined ? {} : { selected_group }),
746
1137
  });
747
1138
  }
1139
+
1140
+ export function resolveHierarchicalTaskCalibrationWithDriftGuard(
1141
+ report: HierarchicalTaskCalibrationReport,
1142
+ query: HierarchicalTaskCalibrationQuery,
1143
+ driftGuard: HierarchicalCalibrationDriftGuardOptions,
1144
+ ): HierarchicalTaskCalibrationGuardedSelection {
1145
+ const parsedReport = HierarchicalTaskCalibrationGuardedReportSchema.parse(
1146
+ report,
1147
+ );
1148
+ const parsedQuery = HierarchicalTaskCalibrationQuerySchema.parse(query);
1149
+ const drift_guard = HierarchicalCalibrationDriftGuardOptionsSchema.parse(
1150
+ driftGuard,
1151
+ );
1152
+ const requested_scope: HierarchicalCalibrationScope =
1153
+ parsedQuery.prompt_pattern !== undefined
1154
+ ? "prompt_pattern"
1155
+ : parsedQuery.task_subtype !== undefined
1156
+ ? "task_subtype"
1157
+ : "task_type";
1158
+ const scopes: HierarchicalCalibrationScope[] = requested_scope ===
1159
+ "prompt_pattern"
1160
+ ? ["prompt_pattern", "task_subtype", "task_type"]
1161
+ : requested_scope === "task_subtype"
1162
+ ? ["task_subtype", "task_type"]
1163
+ : ["task_type"];
1164
+
1165
+ const matchingGroups = scopes.map((scope) =>
1166
+ parsedReport.groups.find((group) =>
1167
+ group.scope === scope && group.task_type === parsedQuery.task_type &&
1168
+ group.source.provider === parsedQuery.source.provider &&
1169
+ group.source.model === parsedQuery.source.model &&
1170
+ (scope === "task_type" ||
1171
+ group.task_subtype === parsedQuery.task_subtype) &&
1172
+ (scope !== "prompt_pattern" ||
1173
+ group.prompt_pattern === parsedQuery.prompt_pattern)
1174
+ )
1175
+ );
1176
+ const candidates = scopes.map((scope, index) => {
1177
+ const group = matchingGroups[index];
1178
+ const base = group === undefined
1179
+ ? {
1180
+ scope,
1181
+ sample_count: null,
1182
+ sample_status: "missing" as const,
1183
+ accuracy: null,
1184
+ mean_confidence: null,
1185
+ mean_calibration_bias: null,
1186
+ brier_score: null,
1187
+ }
1188
+ : {
1189
+ scope,
1190
+ sample_count: group.sample_count,
1191
+ sample_status: group.sample_status,
1192
+ accuracy: group.accuracy,
1193
+ mean_confidence: group.mean_confidence,
1194
+ mean_calibration_bias: group.mean_calibration_bias,
1195
+ brier_score: group.brier_score,
1196
+ };
1197
+ if (scope === "task_type") {
1198
+ return {
1199
+ ...base,
1200
+ drift_status: "not_applicable" as const,
1201
+ parent_scope: null,
1202
+ child_parent_brier_score_delta: null,
1203
+ };
1204
+ }
1205
+
1206
+ const parent_scope = scopes[index + 1] ?? null;
1207
+ if (group?.sample_status !== "sufficient") {
1208
+ return {
1209
+ ...base,
1210
+ drift_status: "not_evaluated" as const,
1211
+ parent_scope,
1212
+ child_parent_brier_score_delta: null,
1213
+ };
1214
+ }
1215
+ const parent = matchingGroups[index + 1];
1216
+ if (parent?.sample_status !== "sufficient") {
1217
+ return {
1218
+ ...base,
1219
+ drift_status: "parent_unavailable" as const,
1220
+ parent_scope,
1221
+ child_parent_brier_score_delta: null,
1222
+ };
1223
+ }
1224
+
1225
+ const rawDelta = group.brier_score - parent.brier_score;
1226
+ const child_parent_brier_score_delta = stableMetric(rawDelta);
1227
+ return {
1228
+ ...base,
1229
+ drift_status: rawDelta >
1230
+ drift_guard.maximum_child_parent_brier_score_delta
1231
+ ? "quarantined" as const
1232
+ : "within_threshold" as const,
1233
+ parent_scope,
1234
+ child_parent_brier_score_delta,
1235
+ };
1236
+ });
1237
+ const selectedCandidate = candidates.find((candidate) =>
1238
+ candidate.sample_status === "sufficient" &&
1239
+ (candidate.drift_status === "within_threshold" ||
1240
+ candidate.drift_status === "not_applicable")
1241
+ );
1242
+ const selected_group = selectedCandidate === undefined
1243
+ ? undefined
1244
+ : matchingGroups[candidates.indexOf(selectedCandidate)];
1245
+
1246
+ return HierarchicalTaskCalibrationGuardedSelectionSchema.parse({
1247
+ schema_version: "quorum-router.hierarchical-guarded-selection.v1",
1248
+ advisory_only: true,
1249
+ query: parsedQuery,
1250
+ requested_scope,
1251
+ minimum_sample_count: parsedReport.minimum_sample_count,
1252
+ drift_guard,
1253
+ resolution_status: selected_group === undefined
1254
+ ? "no_eligible_group"
1255
+ : "selected",
1256
+ selected_scope: selected_group?.scope ?? null,
1257
+ candidates,
1258
+ ...(selected_group === undefined ? {} : { selected_group }),
1259
+ });
1260
+ }