noteconnection 1.6.8 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/LICENSE +674 -21
  2. package/README.md +258 -64
  3. package/dist/src/agent_workspace.contract.parity.test.js +475 -0
  4. package/dist/src/agent_workspace.frontend.test.js +9989 -0
  5. package/dist/src/agent_workspace.locale.contract.test.js +95 -0
  6. package/dist/src/agent_workspace.runtime.behavior.test.js +5072 -0
  7. package/dist/src/copy.assets.contract.test.js +130 -0
  8. package/dist/src/core/PathBridge.js +28 -3
  9. package/dist/src/export/WorkspaceExportBundle.js +1130 -0
  10. package/dist/src/export/WorkspaceExportBundle.test.js +1480 -0
  11. package/dist/src/export/index.js +18 -0
  12. package/dist/src/export/types.js +2 -0
  13. package/dist/src/fixrisk.issue.verifier.contract.test.js +3 -1
  14. package/dist/src/foundation.ann.runtime.contract.test.js +81 -0
  15. package/dist/src/foundation.release.evidence.contract.test.js +406 -0
  16. package/dist/src/foundation.sqlite.runtime.contract.test.js +82 -0
  17. package/dist/src/frontend/README.md +258 -64
  18. package/dist/src/frontend/agent_workspace.js +5353 -0
  19. package/dist/src/frontend/agent_workspace_runtime.js +4434 -0
  20. package/dist/src/frontend/analysis.js +31 -4
  21. package/dist/src/frontend/app.js +3597 -141
  22. package/dist/src/frontend/focus_mode_interactions.js +33 -0
  23. package/dist/src/frontend/godot_future_path_renderer.js +540 -0
  24. package/dist/src/frontend/godot_tree_interactions.js +178 -0
  25. package/dist/src/frontend/graph_state.mjs +105 -0
  26. package/dist/src/frontend/hosted_future_path_runtime.js +157 -0
  27. package/dist/src/frontend/i18n.mjs +186 -0
  28. package/dist/src/frontend/index.html +641 -266
  29. package/dist/src/frontend/layout_gpu.js +12 -4
  30. package/dist/src/frontend/locales/en.json +721 -5
  31. package/dist/src/frontend/locales/zh.json +721 -5
  32. package/dist/src/frontend/main.mjs +60 -0
  33. package/dist/src/frontend/markdown_runtime.js +827 -0
  34. package/dist/src/frontend/notemd.css +49 -0
  35. package/dist/src/frontend/notemd.html +7 -1
  36. package/dist/src/frontend/notemd.js +64 -0
  37. package/dist/src/frontend/path.html +107 -0
  38. package/dist/src/frontend/path_app.js +2189 -150
  39. package/dist/src/frontend/path_layout.mjs +143 -0
  40. package/dist/src/frontend/path_mermaid_utils.mjs +108 -0
  41. package/dist/src/frontend/path_modules_bridge.js +486 -0
  42. package/dist/src/frontend/path_state.mjs +118 -0
  43. package/dist/src/frontend/path_styles.css +146 -0
  44. package/dist/src/frontend/path_worker_bridge.mjs +85 -0
  45. package/dist/src/frontend/reader.js +522 -27
  46. package/dist/src/frontend/runtime_bridge.js +67 -54
  47. package/dist/src/frontend/runtime_bridge.mjs +279 -0
  48. package/dist/src/frontend/settings.js +130 -12
  49. package/dist/src/frontend/simulationWorker.js +241 -6
  50. package/dist/src/frontend/source_manager.js +190 -21
  51. package/dist/src/frontend/styles.css +2853 -72
  52. package/dist/src/frontend/workbench_state.mjs +101 -0
  53. package/dist/src/frontend/workspace_panes.js +10168 -0
  54. package/dist/src/frontend.locale.contract.test.js +62 -0
  55. package/dist/src/godot.sidecar.bootstrap.contract.test.js +244 -0
  56. package/dist/src/indexing/IndexLifecycle.js +195 -0
  57. package/dist/src/indexing/IndexLifecycle.test.js +49 -0
  58. package/dist/src/indexing/SegmentBuilder.js +64 -0
  59. package/dist/src/indexing/UnitBuilder.js +48 -0
  60. package/dist/src/indexing/types.js +2 -0
  61. package/dist/src/knowledge.api.contract.test.js +170 -0
  62. package/dist/src/learning/KnowledgeLearningPlatform.js +10386 -0
  63. package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +327 -0
  64. package/dist/src/learning/KnowledgeLearningPlatform.program-f.test.js +99 -0
  65. package/dist/src/learning/KnowledgeLearningPlatform.test.js +2971 -0
  66. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +2974 -0
  67. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +3928 -0
  68. package/dist/src/learning/answerReleaseReview.js +4319 -0
  69. package/dist/src/learning/answerReleaseReview.test.js +2888 -0
  70. package/dist/src/learning/api.js +2 -0
  71. package/dist/src/learning/conversationComposer.js +1480 -0
  72. package/dist/src/learning/conversationComposer.test.js +1817 -0
  73. package/dist/src/learning/domains/ConversationManager.js +53 -0
  74. package/dist/src/learning/domains/KnowledgeIngestor.js +238 -0
  75. package/dist/src/learning/domains/KnowledgeQuerier.js +187 -0
  76. package/dist/src/learning/domains/MasteryEngine.js +387 -0
  77. package/dist/src/learning/domains/MemoryPolicyManager.js +408 -0
  78. package/dist/src/learning/domains/QualityEvaluator.js +307 -0
  79. package/dist/src/learning/domains/TutorRouter.js +313 -0
  80. package/dist/src/learning/domains/index.js +33 -0
  81. package/dist/src/learning/domains/types.js +7 -0
  82. package/dist/src/learning/errors.js +29 -0
  83. package/dist/src/learning/evidenceContextAssembler.js +1176 -0
  84. package/dist/src/learning/evidenceContextAssembler.test.js +6332 -0
  85. package/dist/src/learning/graphContextAssembler.js +870 -0
  86. package/dist/src/learning/graphContextAssembler.test.js +1033 -0
  87. package/dist/src/learning/index.js +28 -0
  88. package/dist/src/learning/queryBackend.js +1898 -0
  89. package/dist/src/learning/queryBackend.test.js +955 -0
  90. package/dist/src/learning/ragContextPack.js +257 -0
  91. package/dist/src/learning/ragContextPack.test.js +160 -0
  92. package/dist/src/learning/ragPublicText.js +38 -0
  93. package/dist/src/learning/ragSufficiencyJudge.js +161 -0
  94. package/dist/src/learning/ragSufficiencyJudge.test.js +177 -0
  95. package/dist/src/learning/ragSufficiencyProviderJudge.js +227 -0
  96. package/dist/src/learning/ragSufficiencyProviderJudge.test.js +156 -0
  97. package/dist/src/learning/requestNormalization.js +198 -0
  98. package/dist/src/learning/runtimeCapability.js +4677 -0
  99. package/dist/src/learning/runtimeCapability.test.js +3635 -0
  100. package/dist/src/learning/store.js +1240 -0
  101. package/dist/src/learning/store.test.js +1126 -0
  102. package/dist/src/learning/tutorAdapter.js +2 -0
  103. package/dist/src/learning/types.js +2 -0
  104. package/dist/src/learning/vectorAccelerationAdapter.js +942 -0
  105. package/dist/src/learning/vectorAccelerationAdapter.test.js +382 -0
  106. package/dist/src/lfs.asset.policy.contract.test.js +153 -0
  107. package/dist/src/license.policy.contract.test.js +66 -0
  108. package/dist/src/memory/MemoryGovernance.js +74 -0
  109. package/dist/src/memory/MemoryGovernance.test.js +46 -0
  110. package/dist/src/memory/types.js +2 -0
  111. package/dist/src/mermaid.frontend.guard.contract.test.js +77 -0
  112. package/dist/src/middleware/auth.js +17 -0
  113. package/dist/src/middleware/body-parser.js +45 -0
  114. package/dist/src/middleware/cors.js +44 -0
  115. package/dist/src/middleware/index.js +21 -0
  116. package/dist/src/middleware/request-trace.js +96 -0
  117. package/dist/src/notemd/AppConfigToml.js +6 -4
  118. package/dist/src/notemd/MermaidProcessor.js +400 -50
  119. package/dist/src/notemd/NotemdService.js +498 -13
  120. package/dist/src/notemd/PromptManager.js +15 -0
  121. package/dist/src/notemd/cli/commands.js +357 -0
  122. package/dist/src/notemd/cli/dispatcher.js +225 -0
  123. package/dist/src/notemd/cli/index.js +169 -0
  124. package/dist/src/notemd/cli/parser.js +68 -0
  125. package/dist/src/notemd/cli/types.js +2 -0
  126. package/dist/src/notemd/constants.js +43 -0
  127. package/dist/src/notemd/diagram/diagramGenerationService.js +78 -0
  128. package/dist/src/notemd/diagram/diagramSpec.js +79 -0
  129. package/dist/src/notemd/diagram/diagramSpecResponseParser.js +131 -0
  130. package/dist/src/notemd/diagram/intent.js +95 -0
  131. package/dist/src/notemd/diagram/planner.js +71 -0
  132. package/dist/src/notemd/diagram/prompts/diagramSpecPrompt.js +42 -0
  133. package/dist/src/notemd/diagram/types.js +18 -0
  134. package/dist/src/notemd/index.js +26 -0
  135. package/dist/src/notemd/operations/capabilityManifest.js +23 -0
  136. package/dist/src/notemd/operations/cliContracts.js +17 -0
  137. package/dist/src/notemd/operations/configProfileCommands.js +85 -0
  138. package/dist/src/notemd/operations/registry.contract.test.js +95 -0
  139. package/dist/src/notemd/operations/registry.js +991 -0
  140. package/dist/src/notemd/operations/types.js +2 -0
  141. package/dist/src/notemd/providerDiagnostics.js +220 -0
  142. package/dist/src/notemd/providerProfiles.js +42 -0
  143. package/dist/src/notemd/providerTemplates.js +231 -0
  144. package/dist/src/notemd/search/DuckDuckGoProvider.js +39 -0
  145. package/dist/src/notemd/search/SearchManager.js +13 -0
  146. package/dist/src/notemd/search/SearchProvider.js +2 -0
  147. package/dist/src/notemd/search/TavilyProvider.js +44 -0
  148. package/dist/src/notemd.agent.manifest.test.js +85 -0
  149. package/dist/src/notemd.api.contract.test.js +14 -1
  150. package/dist/src/notemd.app_config_toml.test.js +2 -1
  151. package/dist/src/notemd.batch.workflow.test.js +117 -0
  152. package/dist/src/notemd.cli.e2e.test.js +136 -0
  153. package/dist/src/notemd.core.test.js +51 -0
  154. package/dist/src/notemd.diagram.pipeline.test.js +233 -0
  155. package/dist/src/notemd.providerTemplates.test.js +34 -0
  156. package/dist/src/notemd.server.integration.test.js +143 -35
  157. package/dist/src/notemd.workflow.pipeline.test.js +162 -0
  158. package/dist/src/pathbridge.handshake.contract.test.js +16 -2
  159. package/dist/src/pathmode.background.contract.test.js +69 -0
  160. package/dist/src/pathmode.settings.api.contract.test.js +9 -0
  161. package/dist/src/pkg.sidecar.contract.test.js +9 -3
  162. package/dist/src/platform/ExportProfile.js +58 -0
  163. package/dist/src/platform/PlatformCapabilities.js +45 -0
  164. package/dist/src/platform/PlatformCapabilities.test.js +30 -0
  165. package/dist/src/platform/RenderMaterializer.js +33 -0
  166. package/dist/src/platform/RenderMaterializer.test.js +32 -0
  167. package/dist/src/query_backend.external_http.integration.test.js +410 -0
  168. package/dist/src/reader_renderer.js +404 -3
  169. package/dist/src/reader_renderer.test.js +87 -0
  170. package/dist/src/release.godot.mirror.contract.test.js +73 -0
  171. package/dist/src/resources/ResourceRegistry.js +223 -0
  172. package/dist/src/resources/ResourceRegistry.test.js +61 -0
  173. package/dist/src/resources/types.js +2 -0
  174. package/dist/src/routes/agentWorkspaceDiagnostics.js +173 -0
  175. package/dist/src/routes/data.js +267 -0
  176. package/dist/src/routes/diagnostics.js +51 -0
  177. package/dist/src/routes/index.js +23 -0
  178. package/dist/src/routes/knowledge.js +968 -0
  179. package/dist/src/routes/markdown.js +287 -0
  180. package/dist/src/routes/notemd.js +565 -0
  181. package/dist/src/routes/registry.contract.test.js +130 -0
  182. package/dist/src/routes/render.js +285 -0
  183. package/dist/src/routes/runtimeRunbookRouteOps.js +149 -0
  184. package/dist/src/routes/runtimeRunbookRouteOps.test.js +194 -0
  185. package/dist/src/routes/settings.js +6 -0
  186. package/dist/src/routes/staticFiles.js +94 -0
  187. package/dist/src/routes/types.js +2 -0
  188. package/dist/src/runtime.transport.adapter.contract.test.js +81 -0
  189. package/dist/src/server.js +11090 -1549
  190. package/dist/src/server.migration.test.js +193 -21
  191. package/dist/src/server.port.fallback.contract.test.js +63 -0
  192. package/dist/src/session/SessionStateStore.js +81 -0
  193. package/dist/src/session/SessionStateStore.test.js +58 -0
  194. package/dist/src/session/types.js +2 -0
  195. package/dist/src/settings.runtime.contract.test.js +50 -0
  196. package/dist/src/shared/types.contract.test.js +107 -0
  197. package/dist/src/shared/types.js +22 -0
  198. package/dist/src/sidecar.replacement.boundary.contract.test.js +128 -0
  199. package/dist/src/sidecar.supply.readiness.contract.test.js +144 -0
  200. package/dist/src/source_manager.loadflow.test.js +46 -0
  201. package/dist/src/startup.layout.snapshot.contract.test.js +57 -0
  202. package/dist/src/tauri.frontend.build.contract.test.js +60 -0
  203. package/dist/src/tauri.sidecar.cleanup.contract.test.js +21 -0
  204. package/dist/src/utils/RuntimePaths.js +4 -13
  205. package/dist/src/utils/platform.js +153 -0
  206. package/dist/src/workflows/WorkflowArtifactStore.js +96 -0
  207. package/dist/src/workflows/WorkflowArtifactStore.test.js +80 -0
  208. package/dist/src/workflows/types.js +2 -0
  209. package/dist/src/workspace/WorkspaceRegistry.js +122 -0
  210. package/dist/src/workspace/WorkspaceRegistry.test.js +29 -0
  211. package/dist/src/workspace/types.js +2 -0
  212. package/package.json +61 -10
@@ -0,0 +1,3635 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const runtimeCapability_1 = require("./runtimeCapability");
4
+ function createStoreDiagnostics(overrides = {}) {
5
+ return {
6
+ storeType: 'file',
7
+ exists: true,
8
+ loaded: true,
9
+ ...overrides,
10
+ };
11
+ }
12
+ function createQueryDiagnostics(overrides = {}) {
13
+ return {
14
+ backendId: 'local-hybrid-v1',
15
+ fallbackCount: 0,
16
+ ...overrides,
17
+ };
18
+ }
19
+ describe('runtime capability matrix', () => {
20
+ test('normalizes runtime thresholds and enforces fail>=warn invariant', () => {
21
+ const thresholds = (0, runtimeCapability_1.normalizeRuntimeCapabilityThresholds)({
22
+ minQuerySampleSize: 0,
23
+ queryFallbackWarnRatioPct: 35,
24
+ queryFallbackFailRatioPct: 20,
25
+ queryEvidenceCoverageWarnRatioPct: 82,
26
+ queryEvidenceCoverageFailRatioPct: 93,
27
+ queryTemporalValidityWarnRatioPct: 88,
28
+ queryTemporalValidityFailRatioPct: 95,
29
+ queryBackendExplainabilityGapWarnRatioPct: 32,
30
+ queryBackendExplainabilityGapFailRatioPct: 20,
31
+ queryBackendTrendWarnConfidenceRatioPct: 65,
32
+ queryBackendTrendFailConfidenceRatioPct: 55,
33
+ sessionPlanQualityWarnFailureStreak: 3,
34
+ sessionPlanQualityFailFailureStreak: 1,
35
+ apiInvalidRequestMinErrorSample: 0,
36
+ apiInvalidRequestWarnRatioPct: 45,
37
+ apiInvalidRequestFailRatioPct: 20,
38
+ apiInvalidRequestHotspotWarnCount: 9,
39
+ apiInvalidRequestHotspotFailCount: 4,
40
+ apiServerErrorMinRequestSample: 0,
41
+ apiServerErrorWarnRatioPct: 11,
42
+ apiServerErrorFailRatioPct: 5,
43
+ apiServerErrorHotspotWarnCount: 7,
44
+ apiServerErrorHotspotFailCount: 3,
45
+ apiTransientErrorMinRequestSample: 0,
46
+ apiTransientErrorWarnRatioPct: 19,
47
+ apiTransientErrorFailRatioPct: 11,
48
+ apiTransientErrorHotspotWarnCount: 6,
49
+ apiTransientErrorHotspotFailCount: 3,
50
+ apiLatencyMinRequestSample: 0,
51
+ apiLatencyP95WarnMs: 1400,
52
+ apiLatencyP95FailMs: 900,
53
+ apiLatencyHotspotWarnMs: 2100,
54
+ apiLatencyHotspotFailMs: 1700,
55
+ queryVectorAccelerationShortCircuitWarnCount: 9,
56
+ queryVectorAccelerationShortCircuitFailCount: 4,
57
+ queryVectorAccelerationShortCircuitWarnRatioPct: 30,
58
+ queryVectorAccelerationShortCircuitFailRatioPct: 20,
59
+ queryVectorAccelerationConsecutiveFailuresWarnCount: 5,
60
+ queryVectorAccelerationConsecutiveFailuresFailCount: 3,
61
+ queryVectorAccelerationHalfOpenSuccessWarnRatioPct: 75,
62
+ queryVectorAccelerationHalfOpenSuccessFailRatioPct: 95,
63
+ queryVectorAccelerationPrefilterMinRequestSample: 0,
64
+ queryVectorAccelerationPrefilterWarnCandidateRatioPct: 97,
65
+ queryVectorAccelerationPrefilterFailCandidateRatioPct: 90,
66
+ storeGraphDbConnectorMinRequestSample: 0,
67
+ storeGraphDbConnectorFailureWarnRatioPct: 32,
68
+ storeGraphDbConnectorFailureFailRatioPct: 11,
69
+ storeGraphDbConnectorShortCircuitWarnRatioPct: 18,
70
+ storeGraphDbConnectorShortCircuitFailRatioPct: 7,
71
+ storeGraphDbConnectorConsecutiveFailuresWarnCount: 5,
72
+ storeGraphDbConnectorConsecutiveFailuresFailCount: 2,
73
+ });
74
+ expect(thresholds.minQuerySampleSize).toBe(1);
75
+ expect(thresholds.queryFallbackWarnRatioPct).toBe(35);
76
+ expect(thresholds.queryFallbackFailRatioPct).toBe(35);
77
+ expect(thresholds.queryEvidenceCoverageWarnRatioPct).toBe(82);
78
+ expect(thresholds.queryEvidenceCoverageFailRatioPct).toBe(82);
79
+ expect(thresholds.queryTemporalValidityWarnRatioPct).toBe(88);
80
+ expect(thresholds.queryTemporalValidityFailRatioPct).toBe(88);
81
+ expect(thresholds.queryBackendExplainabilityGapWarnRatioPct).toBe(32);
82
+ expect(thresholds.queryBackendExplainabilityGapFailRatioPct).toBe(32);
83
+ expect(thresholds.queryBackendTrendWarnConfidenceRatioPct).toBe(65);
84
+ expect(thresholds.queryBackendTrendFailConfidenceRatioPct).toBe(65);
85
+ expect(thresholds.sessionPlanQualityWarnFailureStreak).toBe(3);
86
+ expect(thresholds.sessionPlanQualityFailFailureStreak).toBe(3);
87
+ expect(thresholds.apiInvalidRequestMinErrorSample).toBe(1);
88
+ expect(thresholds.apiInvalidRequestWarnRatioPct).toBe(45);
89
+ expect(thresholds.apiInvalidRequestFailRatioPct).toBe(45);
90
+ expect(thresholds.apiInvalidRequestHotspotWarnCount).toBe(9);
91
+ expect(thresholds.apiInvalidRequestHotspotFailCount).toBe(9);
92
+ expect(thresholds.apiServerErrorMinRequestSample).toBe(1);
93
+ expect(thresholds.apiServerErrorWarnRatioPct).toBe(11);
94
+ expect(thresholds.apiServerErrorFailRatioPct).toBe(11);
95
+ expect(thresholds.apiServerErrorHotspotWarnCount).toBe(7);
96
+ expect(thresholds.apiServerErrorHotspotFailCount).toBe(7);
97
+ expect(thresholds.apiTransientErrorMinRequestSample).toBe(1);
98
+ expect(thresholds.apiTransientErrorWarnRatioPct).toBe(19);
99
+ expect(thresholds.apiTransientErrorFailRatioPct).toBe(19);
100
+ expect(thresholds.apiTransientErrorHotspotWarnCount).toBe(6);
101
+ expect(thresholds.apiTransientErrorHotspotFailCount).toBe(6);
102
+ expect(thresholds.apiLatencyMinRequestSample).toBe(1);
103
+ expect(thresholds.apiLatencyP95WarnMs).toBe(1400);
104
+ expect(thresholds.apiLatencyP95FailMs).toBe(1400);
105
+ expect(thresholds.apiLatencyHotspotWarnMs).toBe(2100);
106
+ expect(thresholds.apiLatencyHotspotFailMs).toBe(2100);
107
+ expect(thresholds.queryVectorAccelerationShortCircuitWarnCount).toBe(9);
108
+ expect(thresholds.queryVectorAccelerationShortCircuitFailCount).toBe(9);
109
+ expect(thresholds.queryVectorAccelerationShortCircuitWarnRatioPct).toBe(30);
110
+ expect(thresholds.queryVectorAccelerationShortCircuitFailRatioPct).toBe(30);
111
+ expect(thresholds.queryVectorAccelerationConsecutiveFailuresWarnCount).toBe(5);
112
+ expect(thresholds.queryVectorAccelerationConsecutiveFailuresFailCount).toBe(5);
113
+ expect(thresholds.queryVectorAccelerationHalfOpenSuccessWarnRatioPct).toBe(75);
114
+ expect(thresholds.queryVectorAccelerationHalfOpenSuccessFailRatioPct).toBe(75);
115
+ expect(thresholds.queryVectorAccelerationPrefilterMinRequestSample).toBe(1);
116
+ expect(thresholds.queryVectorAccelerationPrefilterWarnCandidateRatioPct).toBe(97);
117
+ expect(thresholds.queryVectorAccelerationPrefilterFailCandidateRatioPct).toBe(97);
118
+ expect(thresholds.storeGraphDbConnectorMinRequestSample).toBe(1);
119
+ expect(thresholds.storeGraphDbConnectorFailureWarnRatioPct).toBe(32);
120
+ expect(thresholds.storeGraphDbConnectorFailureFailRatioPct).toBe(32);
121
+ expect(thresholds.storeGraphDbConnectorShortCircuitWarnRatioPct).toBe(18);
122
+ expect(thresholds.storeGraphDbConnectorShortCircuitFailRatioPct).toBe(18);
123
+ expect(thresholds.storeGraphDbConnectorConsecutiveFailuresWarnCount).toBe(5);
124
+ expect(thresholds.storeGraphDbConnectorConsecutiveFailuresFailCount).toBe(5);
125
+ });
126
+ test('resolves runtime thresholds from env', () => {
127
+ const thresholds = (0, runtimeCapability_1.resolveRuntimeCapabilityThresholdsFromEnv)({
128
+ NOTE_CONNECTION_RUNTIME_QUERY_MIN_SAMPLE: '12',
129
+ NOTE_CONNECTION_RUNTIME_QUERY_FALLBACK_WARN_RATIO_PCT: '7.5',
130
+ NOTE_CONNECTION_RUNTIME_QUERY_FALLBACK_FAIL_RATIO_PCT: '18.2',
131
+ NOTE_CONNECTION_RUNTIME_QUERY_EVIDENCE_COVERAGE_WARN_RATIO_PCT: '91.1',
132
+ NOTE_CONNECTION_RUNTIME_QUERY_EVIDENCE_COVERAGE_FAIL_RATIO_PCT: '78.2',
133
+ NOTE_CONNECTION_RUNTIME_QUERY_TEMPORAL_VALIDITY_WARN_RATIO_PCT: '92.5',
134
+ NOTE_CONNECTION_RUNTIME_QUERY_TEMPORAL_VALIDITY_FAIL_RATIO_PCT: '81.4',
135
+ NOTE_CONNECTION_RUNTIME_QUERY_BACKEND_EXPLAINABILITY_GAP_WARN_RATIO_PCT: '18.5',
136
+ NOTE_CONNECTION_RUNTIME_QUERY_BACKEND_EXPLAINABILITY_GAP_FAIL_RATIO_PCT: '33.2',
137
+ NOTE_CONNECTION_RUNTIME_QUERY_BACKEND_TREND_WARN_CONFIDENCE_PCT: '42.5',
138
+ NOTE_CONNECTION_RUNTIME_QUERY_BACKEND_TREND_FAIL_CONFIDENCE_PCT: '73.1',
139
+ NOTE_CONNECTION_RUNTIME_SESSION_PLAN_QUALITY_WARN_FAILURE_STREAK: '2',
140
+ NOTE_CONNECTION_RUNTIME_SESSION_PLAN_QUALITY_FAIL_FAILURE_STREAK: '4',
141
+ NOTE_CONNECTION_RUNTIME_API_INVALID_REQUEST_MIN_ERROR_SAMPLE: '6',
142
+ NOTE_CONNECTION_RUNTIME_API_INVALID_REQUEST_WARN_RATIO_PCT: '25',
143
+ NOTE_CONNECTION_RUNTIME_API_INVALID_REQUEST_FAIL_RATIO_PCT: '55',
144
+ NOTE_CONNECTION_RUNTIME_API_INVALID_REQUEST_HOTSPOT_WARN_COUNT: '5',
145
+ NOTE_CONNECTION_RUNTIME_API_INVALID_REQUEST_HOTSPOT_FAIL_COUNT: '12',
146
+ NOTE_CONNECTION_RUNTIME_API_SERVER_ERROR_MIN_REQUEST_SAMPLE: '9',
147
+ NOTE_CONNECTION_RUNTIME_API_SERVER_ERROR_WARN_RATIO_PCT: '6.5',
148
+ NOTE_CONNECTION_RUNTIME_API_SERVER_ERROR_FAIL_RATIO_PCT: '14.2',
149
+ NOTE_CONNECTION_RUNTIME_API_SERVER_ERROR_HOTSPOT_WARN_COUNT: '4',
150
+ NOTE_CONNECTION_RUNTIME_API_SERVER_ERROR_HOTSPOT_FAIL_COUNT: '10',
151
+ NOTE_CONNECTION_RUNTIME_API_TRANSIENT_ERROR_MIN_REQUEST_SAMPLE: '11',
152
+ NOTE_CONNECTION_RUNTIME_API_TRANSIENT_ERROR_WARN_RATIO_PCT: '9.25',
153
+ NOTE_CONNECTION_RUNTIME_API_TRANSIENT_ERROR_FAIL_RATIO_PCT: '18.75',
154
+ NOTE_CONNECTION_RUNTIME_API_TRANSIENT_ERROR_HOTSPOT_WARN_COUNT: '2',
155
+ NOTE_CONNECTION_RUNTIME_API_TRANSIENT_ERROR_HOTSPOT_FAIL_COUNT: '9',
156
+ NOTE_CONNECTION_RUNTIME_API_LATENCY_MIN_REQUEST_SAMPLE: '12',
157
+ NOTE_CONNECTION_RUNTIME_API_LATENCY_P95_WARN_MS: '950',
158
+ NOTE_CONNECTION_RUNTIME_API_LATENCY_P95_FAIL_MS: '2350',
159
+ NOTE_CONNECTION_RUNTIME_API_LATENCY_HOTSPOT_WARN_MS: '1450',
160
+ NOTE_CONNECTION_RUNTIME_API_LATENCY_HOTSPOT_FAIL_MS: '3250',
161
+ NOTE_CONNECTION_RUNTIME_QUERY_VECTOR_ACCELERATION_SHORT_CIRCUIT_WARN_COUNT: '2',
162
+ NOTE_CONNECTION_RUNTIME_QUERY_VECTOR_ACCELERATION_SHORT_CIRCUIT_FAIL_COUNT: '6',
163
+ NOTE_CONNECTION_RUNTIME_QUERY_VECTOR_ACCELERATION_SHORT_CIRCUIT_WARN_RATIO_PCT: '7.5',
164
+ NOTE_CONNECTION_RUNTIME_QUERY_VECTOR_ACCELERATION_SHORT_CIRCUIT_FAIL_RATIO_PCT: '21.5',
165
+ NOTE_CONNECTION_RUNTIME_QUERY_VECTOR_ACCELERATION_CONSECUTIVE_FAILURES_WARN_COUNT: '1',
166
+ NOTE_CONNECTION_RUNTIME_QUERY_VECTOR_ACCELERATION_CONSECUTIVE_FAILURES_FAIL_COUNT: '3',
167
+ NOTE_CONNECTION_RUNTIME_QUERY_VECTOR_ACCELERATION_HALF_OPEN_SUCCESS_WARN_RATIO_PCT: '83',
168
+ NOTE_CONNECTION_RUNTIME_QUERY_VECTOR_ACCELERATION_HALF_OPEN_SUCCESS_FAIL_RATIO_PCT: '55',
169
+ NOTE_CONNECTION_RUNTIME_QUERY_VECTOR_ACCELERATION_PREFILTER_MIN_REQUEST_SAMPLE: '9',
170
+ NOTE_CONNECTION_RUNTIME_QUERY_VECTOR_ACCELERATION_PREFILTER_WARN_CANDIDATE_RATIO_PCT: '88.5',
171
+ NOTE_CONNECTION_RUNTIME_QUERY_VECTOR_ACCELERATION_PREFILTER_FAIL_CANDIDATE_RATIO_PCT: '96.2',
172
+ NOTE_CONNECTION_RUNTIME_STORE_GRAPHDB_CONNECTOR_MIN_REQUEST_SAMPLE: '11',
173
+ NOTE_CONNECTION_RUNTIME_STORE_GRAPHDB_CONNECTOR_FAILURE_WARN_RATIO_PCT: '19.5',
174
+ NOTE_CONNECTION_RUNTIME_STORE_GRAPHDB_CONNECTOR_FAILURE_FAIL_RATIO_PCT: '33.3',
175
+ NOTE_CONNECTION_RUNTIME_STORE_GRAPHDB_CONNECTOR_SHORT_CIRCUIT_WARN_RATIO_PCT: '7.2',
176
+ NOTE_CONNECTION_RUNTIME_STORE_GRAPHDB_CONNECTOR_SHORT_CIRCUIT_FAIL_RATIO_PCT: '16.4',
177
+ NOTE_CONNECTION_RUNTIME_STORE_GRAPHDB_CONNECTOR_CONSECUTIVE_FAILURES_WARN_COUNT: '2',
178
+ NOTE_CONNECTION_RUNTIME_STORE_GRAPHDB_CONNECTOR_CONSECUTIVE_FAILURES_FAIL_COUNT: '6',
179
+ });
180
+ expect(thresholds.minQuerySampleSize).toBe(12);
181
+ expect(thresholds.queryFallbackWarnRatioPct).toBe(7.5);
182
+ expect(thresholds.queryFallbackFailRatioPct).toBe(18.2);
183
+ expect(thresholds.queryEvidenceCoverageWarnRatioPct).toBe(91.1);
184
+ expect(thresholds.queryEvidenceCoverageFailRatioPct).toBe(78.2);
185
+ expect(thresholds.queryTemporalValidityWarnRatioPct).toBe(92.5);
186
+ expect(thresholds.queryTemporalValidityFailRatioPct).toBe(81.4);
187
+ expect(thresholds.queryBackendExplainabilityGapWarnRatioPct).toBe(18.5);
188
+ expect(thresholds.queryBackendExplainabilityGapFailRatioPct).toBe(33.2);
189
+ expect(thresholds.queryBackendTrendWarnConfidenceRatioPct).toBe(42.5);
190
+ expect(thresholds.queryBackendTrendFailConfidenceRatioPct).toBe(73.1);
191
+ expect(thresholds.sessionPlanQualityWarnFailureStreak).toBe(2);
192
+ expect(thresholds.sessionPlanQualityFailFailureStreak).toBe(4);
193
+ expect(thresholds.apiInvalidRequestMinErrorSample).toBe(6);
194
+ expect(thresholds.apiInvalidRequestWarnRatioPct).toBe(25);
195
+ expect(thresholds.apiInvalidRequestFailRatioPct).toBe(55);
196
+ expect(thresholds.apiInvalidRequestHotspotWarnCount).toBe(5);
197
+ expect(thresholds.apiInvalidRequestHotspotFailCount).toBe(12);
198
+ expect(thresholds.apiServerErrorMinRequestSample).toBe(9);
199
+ expect(thresholds.apiServerErrorWarnRatioPct).toBe(6.5);
200
+ expect(thresholds.apiServerErrorFailRatioPct).toBe(14.2);
201
+ expect(thresholds.apiServerErrorHotspotWarnCount).toBe(4);
202
+ expect(thresholds.apiServerErrorHotspotFailCount).toBe(10);
203
+ expect(thresholds.apiTransientErrorMinRequestSample).toBe(11);
204
+ expect(thresholds.apiTransientErrorWarnRatioPct).toBe(9.25);
205
+ expect(thresholds.apiTransientErrorFailRatioPct).toBe(18.75);
206
+ expect(thresholds.apiTransientErrorHotspotWarnCount).toBe(2);
207
+ expect(thresholds.apiTransientErrorHotspotFailCount).toBe(9);
208
+ expect(thresholds.apiLatencyMinRequestSample).toBe(12);
209
+ expect(thresholds.apiLatencyP95WarnMs).toBe(950);
210
+ expect(thresholds.apiLatencyP95FailMs).toBe(2350);
211
+ expect(thresholds.apiLatencyHotspotWarnMs).toBe(1450);
212
+ expect(thresholds.apiLatencyHotspotFailMs).toBe(3250);
213
+ expect(thresholds.queryVectorAccelerationShortCircuitWarnCount).toBe(2);
214
+ expect(thresholds.queryVectorAccelerationShortCircuitFailCount).toBe(6);
215
+ expect(thresholds.queryVectorAccelerationShortCircuitWarnRatioPct).toBe(7.5);
216
+ expect(thresholds.queryVectorAccelerationShortCircuitFailRatioPct).toBe(21.5);
217
+ expect(thresholds.queryVectorAccelerationConsecutiveFailuresWarnCount).toBe(1);
218
+ expect(thresholds.queryVectorAccelerationConsecutiveFailuresFailCount).toBe(3);
219
+ expect(thresholds.queryVectorAccelerationHalfOpenSuccessWarnRatioPct).toBe(83);
220
+ expect(thresholds.queryVectorAccelerationHalfOpenSuccessFailRatioPct).toBe(55);
221
+ expect(thresholds.queryVectorAccelerationPrefilterMinRequestSample).toBe(9);
222
+ expect(thresholds.queryVectorAccelerationPrefilterWarnCandidateRatioPct).toBe(88.5);
223
+ expect(thresholds.queryVectorAccelerationPrefilterFailCandidateRatioPct).toBe(96.2);
224
+ expect(thresholds.storeGraphDbConnectorMinRequestSample).toBe(11);
225
+ expect(thresholds.storeGraphDbConnectorFailureWarnRatioPct).toBe(19.5);
226
+ expect(thresholds.storeGraphDbConnectorFailureFailRatioPct).toBe(33.3);
227
+ expect(thresholds.storeGraphDbConnectorShortCircuitWarnRatioPct).toBe(7.2);
228
+ expect(thresholds.storeGraphDbConnectorShortCircuitFailRatioPct).toBe(16.4);
229
+ expect(thresholds.storeGraphDbConnectorConsecutiveFailuresWarnCount).toBe(2);
230
+ expect(thresholds.storeGraphDbConnectorConsecutiveFailuresFailCount).toBe(6);
231
+ });
232
+ test('returns warn when sample size is below threshold', () => {
233
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
234
+ generatedAt: '2026-04-01T12:00:00.000Z',
235
+ configuredStoreBackend: 'file',
236
+ configuredQueryBackend: 'local_hybrid',
237
+ store: createStoreDiagnostics(),
238
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 2 }),
239
+ queryCount: 3,
240
+ thresholds: {
241
+ minQuerySampleSize: 5,
242
+ queryFallbackWarnRatioPct: 10,
243
+ queryFallbackFailRatioPct: 20,
244
+ },
245
+ });
246
+ const fallbackCheck = matrix.checks.find((check) => check.checkId === 'query_fallback_ratio');
247
+ expect(fallbackCheck?.status).toBe('warn');
248
+ expect(fallbackCheck?.expected).toBe('queryCount>=5');
249
+ expect(fallbackCheck?.debugTraceHint).toEqual({
250
+ pathPrefix: '/api/knowledge/query',
251
+ statusAtLeast: 400,
252
+ method: '',
253
+ errorCode: '',
254
+ });
255
+ expect(Number(fallbackCheck?.priorityScore || 0)).toBeGreaterThan(0);
256
+ expect(matrix.overallStatus).toBe('degraded');
257
+ });
258
+ test('returns fail when fallback ratio exceeds fail threshold', () => {
259
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
260
+ generatedAt: '2026-04-01T12:00:00.000Z',
261
+ configuredStoreBackend: 'file',
262
+ configuredQueryBackend: 'local_hybrid',
263
+ store: createStoreDiagnostics(),
264
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 9 }),
265
+ queryCount: 20,
266
+ thresholds: {
267
+ minQuerySampleSize: 5,
268
+ queryFallbackWarnRatioPct: 10,
269
+ queryFallbackFailRatioPct: 30,
270
+ },
271
+ });
272
+ const fallbackCheck = matrix.checks.find((check) => check.checkId === 'query_fallback_ratio');
273
+ expect(fallbackCheck?.status).toBe('fail');
274
+ expect(fallbackCheck?.expected).toBe('fallbackRatio<=30%');
275
+ expect(matrix.overallStatus).toBe('blocked');
276
+ });
277
+ test('returns pass for local_vector runtime when vector index is ready and persisted', () => {
278
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
279
+ generatedAt: '2026-04-01T12:00:00.000Z',
280
+ configuredStoreBackend: 'file',
281
+ configuredQueryBackend: 'local_vector',
282
+ store: createStoreDiagnostics(),
283
+ queryDiagnostics: createQueryDiagnostics({
284
+ backendId: 'local-vector-v1',
285
+ runtime: {
286
+ backendId: 'local-vector-v1',
287
+ ready: true,
288
+ vectorIndex: {
289
+ enabled: true,
290
+ status: 'ready',
291
+ persisted: true,
292
+ loadedFromDisk: true,
293
+ atomCount: 24,
294
+ location: '/tmp/knowledge_query_vector_index.v1.json',
295
+ acceleration: {
296
+ enabled: true,
297
+ mode: 'ann_prefilter',
298
+ lastSelectionMode: 'token_signature_prefilter',
299
+ lastCandidateCount: 12,
300
+ adapterId: 'local-vector-acceleration-ann-v1',
301
+ healthStatus: 'ready',
302
+ healthMessage: 'local_ann_prefilter_active',
303
+ representationVersion: 'local-vector-representation-v1',
304
+ embeddingModelId: 'local-semantic-tfidf-v1',
305
+ embeddingDimension: 24,
306
+ indexSignature: 'idx_sig_24',
307
+ representationStatus: 'aligned',
308
+ representationStatusReason: 'local_adapter_representation_aligned',
309
+ representationStrictMode: true,
310
+ lastRequestId: 'connector-req-001',
311
+ lastErrorCode: '',
312
+ lastRetryAfterMs: 0,
313
+ circuitState: 'closed',
314
+ consecutiveFailures: 0,
315
+ requestCount: 18,
316
+ retryCount: 2,
317
+ shortCircuitCount: 0,
318
+ successCount: 16,
319
+ failureCount: 2,
320
+ halfOpenProbeSuccessCount: 1,
321
+ halfOpenProbeFailureCount: 0,
322
+ },
323
+ },
324
+ },
325
+ }),
326
+ queryCount: 10,
327
+ });
328
+ const runtimeHealthCheck = matrix.checks.find((check) => check.checkId === 'query_backend_runtime_health');
329
+ const vectorStatusCheck = matrix.checks.find((check) => check.checkId === 'query_vector_index_status');
330
+ const vectorPersistenceCheck = matrix.checks.find((check) => check.checkId === 'query_vector_index_persistence');
331
+ const vectorAccelerationCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_mode');
332
+ const vectorAccelerationRepresentationCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_representation_consistency');
333
+ const vectorAccelerationPrefilterCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_prefilter_effectiveness');
334
+ const vectorAccelerationCalibrationReadinessCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_calibration_readiness');
335
+ const vectorAccelerationHealthCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_health');
336
+ const vectorAccelerationIndexSyncCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_index_sync_health');
337
+ const vectorAccelerationTraceabilityCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_traceability');
338
+ const vectorAccelerationCircuitCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_circuit_state');
339
+ expect(runtimeHealthCheck?.status).toBe('pass');
340
+ expect(vectorStatusCheck?.status).toBe('pass');
341
+ expect(vectorPersistenceCheck?.status).toBe('pass');
342
+ expect(vectorAccelerationCheck?.status).toBe('pass');
343
+ expect(vectorAccelerationRepresentationCheck?.status).toBe('pass');
344
+ expect(vectorAccelerationPrefilterCheck?.status).toBe('pass');
345
+ expect(vectorAccelerationCalibrationReadinessCheck?.status).toBe('pass');
346
+ expect(vectorAccelerationHealthCheck?.status).toBe('pass');
347
+ expect(vectorAccelerationIndexSyncCheck?.status).toBe('pass');
348
+ expect(vectorAccelerationTraceabilityCheck?.status).toBe('pass');
349
+ expect(vectorAccelerationCircuitCheck?.status).toBe('pass');
350
+ expect(matrix.signals.queryBackendRuntimeReady).toBe(true);
351
+ expect(matrix.signals.queryVectorIndexStatus).toBe('ready');
352
+ expect(matrix.signals.queryVectorIndexPersisted).toBe(true);
353
+ expect(matrix.signals.queryVectorIndexLoadedFromDisk).toBe(true);
354
+ expect(matrix.signals.queryVectorIndexAtomCount).toBe(24);
355
+ expect(matrix.signals.queryVectorIndexAccelerationEnabled).toBe(true);
356
+ expect(matrix.signals.queryVectorIndexAccelerationMode).toBe('ann_prefilter');
357
+ expect(matrix.signals.queryVectorIndexAccelerationLastSelectionMode).toBe('token_signature_prefilter');
358
+ expect(matrix.signals.queryVectorIndexAccelerationLastCandidateCount).toBe(12);
359
+ expect(matrix.signals.queryVectorIndexAccelerationAdapterId).toBe('local-vector-acceleration-ann-v1');
360
+ expect(matrix.signals.queryVectorIndexAccelerationHealthStatus).toBe('ready');
361
+ expect(matrix.signals.queryVectorIndexAccelerationHealthMessage).toBe('local_ann_prefilter_active');
362
+ expect(matrix.signals.queryVectorIndexAccelerationIndexSyncStatus).toBe('unknown');
363
+ expect(matrix.signals.queryVectorIndexAccelerationIndexSyncMessage).toBe('');
364
+ expect(matrix.signals.queryVectorIndexAccelerationLastSyncAt).toBe('');
365
+ expect(matrix.signals.queryVectorIndexAccelerationSyncRequestCount).toBe(0);
366
+ expect(matrix.signals.queryVectorIndexAccelerationSyncSuccessCount).toBe(0);
367
+ expect(matrix.signals.queryVectorIndexAccelerationSyncFailureCount).toBe(0);
368
+ expect(matrix.signals.queryVectorIndexAccelerationSyncedIndexSignature).toBe('');
369
+ expect(matrix.signals.queryVectorIndexAccelerationSyncedAtomCount).toBe(0);
370
+ expect(matrix.signals.queryVectorIndexAccelerationRepresentationVersion).toBe('local-vector-representation-v1');
371
+ expect(matrix.signals.queryVectorIndexAccelerationEmbeddingModelId).toBe('local-semantic-tfidf-v1');
372
+ expect(matrix.signals.queryVectorIndexAccelerationEmbeddingDimension).toBe(24);
373
+ expect(matrix.signals.queryVectorIndexAccelerationIndexSignature).toBe('idx_sig_24');
374
+ expect(matrix.signals.queryVectorIndexAccelerationRepresentationStatus).toBe('aligned');
375
+ expect(matrix.signals.queryVectorIndexAccelerationRepresentationStatusReason).toBe('local_adapter_representation_aligned');
376
+ expect(matrix.signals.queryVectorIndexAccelerationRepresentationStrictMode).toBe(true);
377
+ expect(matrix.signals.queryVectorIndexAccelerationLastRequestId).toBe('connector-req-001');
378
+ expect(matrix.signals.queryVectorIndexAccelerationLastErrorCode).toBe('');
379
+ expect(matrix.signals.queryVectorIndexAccelerationLastRetryAfterMs).toBe(0);
380
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitState).toBe('closed');
381
+ expect(matrix.signals.queryVectorIndexAccelerationConsecutiveFailures).toBe(0);
382
+ expect(matrix.signals.queryVectorIndexAccelerationRequestCount).toBe(18);
383
+ expect(matrix.signals.queryVectorIndexAccelerationRetryCount).toBe(2);
384
+ expect(matrix.signals.queryVectorIndexAccelerationShortCircuitCount).toBe(0);
385
+ expect(matrix.signals.queryVectorIndexAccelerationShortCircuitRatioPct).toBe(0);
386
+ expect(matrix.signals.queryVectorIndexAccelerationSuccessCount).toBe(16);
387
+ expect(matrix.signals.queryVectorIndexAccelerationFailureCount).toBe(2);
388
+ expect(matrix.signals.queryVectorIndexAccelerationHalfOpenProbeCount).toBe(1);
389
+ expect(matrix.signals.queryVectorIndexAccelerationHalfOpenSuccessRatePct).toBe(100);
390
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitWarnBudgetExceeded).toBe(false);
391
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitFailBudgetExceeded).toBe(false);
392
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitBudgetStatus).toBe('ok');
393
+ });
394
+ test('returns fail when vector acceleration representation status is mismatch under strict mode', () => {
395
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
396
+ generatedAt: '2026-04-01T12:00:00.000Z',
397
+ configuredStoreBackend: 'file',
398
+ configuredQueryBackend: 'local_vector',
399
+ store: createStoreDiagnostics(),
400
+ queryDiagnostics: createQueryDiagnostics({
401
+ backendId: 'local-vector-v1',
402
+ runtime: {
403
+ backendId: 'local-vector-v1',
404
+ ready: true,
405
+ vectorIndex: {
406
+ enabled: true,
407
+ status: 'ready',
408
+ persisted: true,
409
+ loadedFromDisk: true,
410
+ atomCount: 128,
411
+ acceleration: {
412
+ enabled: true,
413
+ mode: 'ann_prefilter',
414
+ lastSelectionMode: 'token_prefilter',
415
+ lastCandidateCount: 32,
416
+ adapterId: 'external-http-vector-acceleration-v1',
417
+ healthStatus: 'ready',
418
+ healthMessage: 'external_http_ready',
419
+ representationVersion: 'remote-representation-v2',
420
+ embeddingModelId: 'remote-embedding-v2',
421
+ embeddingDimension: 64,
422
+ indexSignature: 'remote_sig_v2',
423
+ representationStatus: 'mismatch',
424
+ representationStatusReason: 'representation_version_mismatch',
425
+ representationStrictMode: true,
426
+ circuitState: 'closed',
427
+ requestCount: 22,
428
+ retryCount: 1,
429
+ shortCircuitCount: 0,
430
+ successCount: 21,
431
+ failureCount: 1,
432
+ },
433
+ },
434
+ },
435
+ }),
436
+ queryCount: 22,
437
+ });
438
+ const vectorAccelerationRepresentationCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_representation_consistency');
439
+ expect(vectorAccelerationRepresentationCheck?.status).toBe('fail');
440
+ expect(String(vectorAccelerationRepresentationCheck?.message || '')).toContain('strict mode');
441
+ expect(String(vectorAccelerationRepresentationCheck?.observed || '')).toContain('representationStatus=mismatch');
442
+ expect(matrix.signals.queryVectorIndexAccelerationRepresentationStatus).toBe('mismatch');
443
+ expect(matrix.signals.queryVectorIndexAccelerationRepresentationStrictMode).toBe(true);
444
+ expect(matrix.overallStatus).toBe('blocked');
445
+ });
446
+ test('returns fail when query backend runtime reports not-ready for local_vector', () => {
447
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
448
+ generatedAt: '2026-04-01T12:00:00.000Z',
449
+ configuredStoreBackend: 'file',
450
+ configuredQueryBackend: 'local_vector',
451
+ store: createStoreDiagnostics(),
452
+ queryDiagnostics: createQueryDiagnostics({
453
+ backendId: 'local-vector-v1',
454
+ runtime: {
455
+ backendId: 'local-vector-v1',
456
+ ready: false,
457
+ vectorIndex: {
458
+ enabled: true,
459
+ status: 'unavailable',
460
+ persisted: false,
461
+ },
462
+ },
463
+ }),
464
+ queryCount: 8,
465
+ });
466
+ const runtimeHealthCheck = matrix.checks.find((check) => check.checkId === 'query_backend_runtime_health');
467
+ const vectorStatusCheck = matrix.checks.find((check) => check.checkId === 'query_vector_index_status');
468
+ expect(runtimeHealthCheck?.status).toBe('fail');
469
+ expect(vectorStatusCheck?.status).toBe('fail');
470
+ expect(matrix.overallStatus).toBe('blocked');
471
+ });
472
+ test('returns warn when local_vector index is stale or non-persistent', () => {
473
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
474
+ generatedAt: '2026-04-01T12:00:00.000Z',
475
+ configuredStoreBackend: 'file',
476
+ configuredQueryBackend: 'local_vector',
477
+ store: createStoreDiagnostics(),
478
+ queryDiagnostics: createQueryDiagnostics({
479
+ backendId: 'local-vector-v1',
480
+ runtime: {
481
+ backendId: 'local-vector-v1',
482
+ ready: true,
483
+ vectorIndex: {
484
+ enabled: true,
485
+ status: 'stale',
486
+ persisted: false,
487
+ loadedFromDisk: false,
488
+ atomCount: 0,
489
+ },
490
+ },
491
+ }),
492
+ queryCount: 8,
493
+ });
494
+ const vectorStatusCheck = matrix.checks.find((check) => check.checkId === 'query_vector_index_status');
495
+ const vectorPersistenceCheck = matrix.checks.find((check) => check.checkId === 'query_vector_index_persistence');
496
+ const vectorAccelerationCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_mode');
497
+ const vectorAccelerationPrefilterCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_prefilter_effectiveness');
498
+ const vectorAccelerationCalibrationReadinessCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_calibration_readiness');
499
+ const vectorAccelerationHealthCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_health');
500
+ const vectorAccelerationTraceabilityCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_traceability');
501
+ const vectorAccelerationCircuitCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_circuit_state');
502
+ expect(vectorStatusCheck?.status).toBe('warn');
503
+ expect(vectorPersistenceCheck?.status).toBe('warn');
504
+ expect(vectorAccelerationCheck?.status).toBe('warn');
505
+ expect(vectorAccelerationPrefilterCheck?.status).toBe('warn');
506
+ expect(vectorAccelerationCalibrationReadinessCheck?.status).toBe('warn');
507
+ expect(vectorAccelerationHealthCheck?.status).toBe('warn');
508
+ expect(vectorAccelerationTraceabilityCheck?.status).toBe('warn');
509
+ expect(vectorAccelerationCircuitCheck?.status).toBe('warn');
510
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitWarnBudgetExceeded).toBe(false);
511
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitFailBudgetExceeded).toBe(false);
512
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitBudgetStatus).toBe('ok');
513
+ expect(vectorStatusCheck?.recommendedActions).toEqual(expect.arrayContaining([
514
+ expect.stringContaining('/api/knowledge/query-backend-diagnostics'),
515
+ ]));
516
+ });
517
+ test('returns fail when vector acceleration health is unavailable while acceleration is enabled', () => {
518
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
519
+ generatedAt: '2026-04-01T12:00:00.000Z',
520
+ configuredStoreBackend: 'file',
521
+ configuredQueryBackend: 'local_vector',
522
+ store: createStoreDiagnostics(),
523
+ queryDiagnostics: createQueryDiagnostics({
524
+ backendId: 'local-vector-v1',
525
+ runtime: {
526
+ backendId: 'local-vector-v1',
527
+ ready: true,
528
+ vectorIndex: {
529
+ enabled: true,
530
+ status: 'ready',
531
+ persisted: true,
532
+ loadedFromDisk: true,
533
+ atomCount: 128,
534
+ acceleration: {
535
+ enabled: true,
536
+ mode: 'ann_prefilter',
537
+ adapterId: 'external-http-vector-acceleration-v1',
538
+ healthStatus: 'unavailable',
539
+ healthMessage: 'external_http_endpoint_missing',
540
+ },
541
+ },
542
+ },
543
+ }),
544
+ queryCount: 14,
545
+ });
546
+ const vectorAccelerationModeCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_mode');
547
+ const vectorAccelerationHealthCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_health');
548
+ const vectorAccelerationIndexSyncCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_index_sync_health');
549
+ const vectorAccelerationCalibrationReadinessCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_calibration_readiness');
550
+ const vectorAccelerationTraceabilityCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_traceability');
551
+ expect(vectorAccelerationModeCheck?.status).toBe('pass');
552
+ expect(vectorAccelerationHealthCheck?.status).toBe('fail');
553
+ expect(vectorAccelerationIndexSyncCheck?.status).toBe('warn');
554
+ expect(vectorAccelerationCalibrationReadinessCheck?.status).toBe('fail');
555
+ expect(vectorAccelerationTraceabilityCheck?.status).toBe('fail');
556
+ expect(String(vectorAccelerationHealthCheck?.observed || '')).toContain('healthStatus=unavailable');
557
+ expect(String(vectorAccelerationIndexSyncCheck?.observed || '')).toContain('indexSyncStatus=unknown');
558
+ expect(String(vectorAccelerationTraceabilityCheck?.observed || '')).toContain('externalConnector=true');
559
+ expect(matrix.signals.queryVectorIndexAccelerationHealthStatus).toBe('unavailable');
560
+ expect(matrix.signals.queryVectorIndexAccelerationHealthMessage).toBe('external_http_endpoint_missing');
561
+ expect(matrix.overallStatus).toBe('blocked');
562
+ });
563
+ test('returns fail when ann prefilter remains full_scan under stable connector conditions', () => {
564
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
565
+ generatedAt: '2026-04-01T12:00:00.000Z',
566
+ configuredStoreBackend: 'file',
567
+ configuredQueryBackend: 'local_vector',
568
+ store: createStoreDiagnostics(),
569
+ queryDiagnostics: createQueryDiagnostics({
570
+ backendId: 'local-vector-v1',
571
+ runtime: {
572
+ backendId: 'local-vector-v1',
573
+ ready: true,
574
+ vectorIndex: {
575
+ enabled: true,
576
+ status: 'ready',
577
+ persisted: true,
578
+ loadedFromDisk: true,
579
+ atomCount: 256,
580
+ acceleration: {
581
+ enabled: true,
582
+ mode: 'ann_prefilter',
583
+ lastSelectionMode: 'full_scan',
584
+ lastCandidateCount: 256,
585
+ adapterId: 'external-http-vector-acceleration-v1',
586
+ healthStatus: 'ready',
587
+ circuitState: 'closed',
588
+ requestCount: 20,
589
+ retryCount: 1,
590
+ successCount: 19,
591
+ failureCount: 1,
592
+ },
593
+ },
594
+ },
595
+ }),
596
+ queryCount: 20,
597
+ });
598
+ const vectorAccelerationPrefilterCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_prefilter_effectiveness');
599
+ expect(vectorAccelerationPrefilterCheck?.status).toBe('fail');
600
+ expect(String(vectorAccelerationPrefilterCheck?.observed || '')).toContain('lastSelectionMode=full_scan');
601
+ expect(String(vectorAccelerationPrefilterCheck?.expected || '')).toContain('lastSelectionMode=token_prefilter|token_signature_prefilter');
602
+ expect(matrix.signals.queryVectorIndexAccelerationMode).toBe('ann_prefilter');
603
+ expect(matrix.signals.queryVectorIndexAccelerationLastSelectionMode).toBe('full_scan');
604
+ expect(matrix.signals.queryVectorIndexAccelerationLastCandidateCount).toBe(256);
605
+ expect(matrix.overallStatus).toBe('blocked');
606
+ });
607
+ test('returns pass when ann prefilter full_scan sample is below dedicated prefilter minimum', () => {
608
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
609
+ generatedAt: '2026-04-01T12:00:00.000Z',
610
+ configuredStoreBackend: 'file',
611
+ configuredQueryBackend: 'local_vector',
612
+ store: createStoreDiagnostics(),
613
+ queryDiagnostics: createQueryDiagnostics({
614
+ backendId: 'local-vector-v1',
615
+ runtime: {
616
+ backendId: 'local-vector-v1',
617
+ ready: true,
618
+ vectorIndex: {
619
+ enabled: true,
620
+ status: 'ready',
621
+ persisted: true,
622
+ loadedFromDisk: true,
623
+ atomCount: 256,
624
+ acceleration: {
625
+ enabled: true,
626
+ mode: 'ann_prefilter',
627
+ lastSelectionMode: 'full_scan',
628
+ lastCandidateCount: 256,
629
+ adapterId: 'external-http-vector-acceleration-v1',
630
+ healthStatus: 'ready',
631
+ circuitState: 'closed',
632
+ requestCount: 6,
633
+ retryCount: 1,
634
+ successCount: 5,
635
+ failureCount: 1,
636
+ },
637
+ },
638
+ },
639
+ }),
640
+ queryCount: 20,
641
+ thresholds: {
642
+ queryVectorAccelerationPrefilterMinRequestSample: 10,
643
+ },
644
+ });
645
+ const vectorAccelerationPrefilterCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_prefilter_effectiveness');
646
+ const vectorAccelerationCalibrationReadinessCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_calibration_readiness');
647
+ expect(vectorAccelerationPrefilterCheck?.status).toBe('pass');
648
+ expect(vectorAccelerationCalibrationReadinessCheck?.status).toBe('warn');
649
+ expect(String(vectorAccelerationPrefilterCheck?.message || '')).toContain('deferred');
650
+ expect(String(vectorAccelerationCalibrationReadinessCheck?.message || '')).toContain('not closed yet');
651
+ expect(matrix.signals.queryVectorIndexAccelerationLastSelectionMode).toBe('full_scan');
652
+ });
653
+ test('returns fail when ann prefilter candidate ratio breaches configured fail threshold', () => {
654
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
655
+ generatedAt: '2026-04-01T12:00:00.000Z',
656
+ configuredStoreBackend: 'file',
657
+ configuredQueryBackend: 'local_vector',
658
+ store: createStoreDiagnostics(),
659
+ queryDiagnostics: createQueryDiagnostics({
660
+ backendId: 'local-vector-v1',
661
+ runtime: {
662
+ backendId: 'local-vector-v1',
663
+ ready: true,
664
+ vectorIndex: {
665
+ enabled: true,
666
+ status: 'ready',
667
+ persisted: true,
668
+ loadedFromDisk: true,
669
+ atomCount: 100,
670
+ acceleration: {
671
+ enabled: true,
672
+ mode: 'ann_prefilter',
673
+ lastSelectionMode: 'token_prefilter',
674
+ lastCandidateCount: 99,
675
+ adapterId: 'external-http-vector-acceleration-v1',
676
+ healthStatus: 'ready',
677
+ circuitState: 'closed',
678
+ requestCount: 20,
679
+ retryCount: 1,
680
+ successCount: 19,
681
+ failureCount: 1,
682
+ },
683
+ },
684
+ },
685
+ }),
686
+ queryCount: 20,
687
+ thresholds: {
688
+ queryVectorAccelerationPrefilterWarnCandidateRatioPct: 80,
689
+ queryVectorAccelerationPrefilterFailCandidateRatioPct: 95,
690
+ },
691
+ });
692
+ const vectorAccelerationPrefilterCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_prefilter_effectiveness');
693
+ expect(vectorAccelerationPrefilterCheck?.status).toBe('fail');
694
+ expect(String(vectorAccelerationPrefilterCheck?.observed || '')).toContain('candidateRatio=99%');
695
+ expect(String(vectorAccelerationPrefilterCheck?.expected || '')).toContain('candidateRatio<95%');
696
+ expect(matrix.overallStatus).toBe('blocked');
697
+ });
698
+ test('returns fail when vector acceleration circuit state is open', () => {
699
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
700
+ generatedAt: '2026-04-01T12:00:00.000Z',
701
+ configuredStoreBackend: 'file',
702
+ configuredQueryBackend: 'local_vector',
703
+ store: createStoreDiagnostics(),
704
+ queryDiagnostics: createQueryDiagnostics({
705
+ backendId: 'local-vector-v1',
706
+ runtime: {
707
+ backendId: 'local-vector-v1',
708
+ ready: true,
709
+ vectorIndex: {
710
+ enabled: true,
711
+ status: 'ready',
712
+ persisted: true,
713
+ loadedFromDisk: true,
714
+ acceleration: {
715
+ enabled: true,
716
+ mode: 'ann_prefilter',
717
+ adapterId: 'external-http-vector-acceleration-v1',
718
+ healthStatus: 'degraded',
719
+ healthMessage: 'external_http_circuit_open',
720
+ circuitState: 'open',
721
+ consecutiveFailures: 4,
722
+ shortCircuitCount: 9,
723
+ requestCount: 20,
724
+ retryCount: 6,
725
+ successCount: 10,
726
+ failureCount: 10,
727
+ halfOpenProbeSuccessCount: 1,
728
+ halfOpenProbeFailureCount: 2,
729
+ },
730
+ },
731
+ },
732
+ }),
733
+ queryCount: 14,
734
+ });
735
+ const vectorAccelerationCircuitCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_circuit_state');
736
+ const vectorAccelerationTraceabilityCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_traceability');
737
+ expect(vectorAccelerationCircuitCheck?.status).toBe('fail');
738
+ expect(vectorAccelerationTraceabilityCheck?.status).toBe('fail');
739
+ expect(String(vectorAccelerationCircuitCheck?.observed || '')).toContain('circuitState=open');
740
+ expect(String(vectorAccelerationTraceabilityCheck?.expected || '')).toContain('lastRequestId|lastErrorCode|lastRetryAfterMs');
741
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitState).toBe('open');
742
+ expect(matrix.signals.queryVectorIndexAccelerationShortCircuitCount).toBe(9);
743
+ expect(matrix.signals.queryVectorIndexAccelerationShortCircuitRatioPct).toBe(45);
744
+ expect(matrix.signals.queryVectorIndexAccelerationHalfOpenProbeCount).toBe(3);
745
+ expect(matrix.signals.queryVectorIndexAccelerationHalfOpenSuccessRatePct).toBeCloseTo(33.3333, 3);
746
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitWarnBudgetExceeded).toBe(true);
747
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitFailBudgetExceeded).toBe(true);
748
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitBudgetStatus).toBe('fail');
749
+ expect(matrix.overallStatus).toBe('blocked');
750
+ });
751
+ test('returns warn when closed circuit exceeds warn budgets', () => {
752
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
753
+ generatedAt: '2026-04-01T12:00:00.000Z',
754
+ configuredStoreBackend: 'file',
755
+ configuredQueryBackend: 'local_vector',
756
+ store: createStoreDiagnostics(),
757
+ queryDiagnostics: createQueryDiagnostics({
758
+ backendId: 'local-vector-v1',
759
+ runtime: {
760
+ backendId: 'local-vector-v1',
761
+ ready: true,
762
+ vectorIndex: {
763
+ enabled: true,
764
+ status: 'ready',
765
+ persisted: true,
766
+ loadedFromDisk: true,
767
+ acceleration: {
768
+ enabled: true,
769
+ mode: 'ann_prefilter',
770
+ adapterId: 'external-http-vector-acceleration-v1',
771
+ healthStatus: 'ready',
772
+ circuitState: 'closed',
773
+ consecutiveFailures: 1,
774
+ shortCircuitCount: 2,
775
+ requestCount: 50,
776
+ retryCount: 3,
777
+ successCount: 45,
778
+ failureCount: 5,
779
+ },
780
+ },
781
+ },
782
+ }),
783
+ queryCount: 14,
784
+ thresholds: {
785
+ queryVectorAccelerationShortCircuitWarnCount: 2,
786
+ queryVectorAccelerationShortCircuitFailCount: 5,
787
+ queryVectorAccelerationShortCircuitWarnRatioPct: 10,
788
+ queryVectorAccelerationShortCircuitFailRatioPct: 30,
789
+ queryVectorAccelerationConsecutiveFailuresWarnCount: 1,
790
+ queryVectorAccelerationConsecutiveFailuresFailCount: 3,
791
+ queryVectorAccelerationHalfOpenSuccessWarnRatioPct: 80,
792
+ queryVectorAccelerationHalfOpenSuccessFailRatioPct: 50,
793
+ },
794
+ });
795
+ const vectorAccelerationCircuitCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_circuit_state');
796
+ expect(vectorAccelerationCircuitCheck?.status).toBe('warn');
797
+ expect(String(vectorAccelerationCircuitCheck?.observed || '')).toContain('circuitState=closed');
798
+ expect(String(vectorAccelerationCircuitCheck?.expected || '')).toContain('shortCircuitCount<2');
799
+ expect(matrix.signals.queryVectorIndexAccelerationShortCircuitRatioPct).toBe(4);
800
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitWarnBudgetExceeded).toBe(true);
801
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitFailBudgetExceeded).toBe(false);
802
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitBudgetStatus).toBe('warn');
803
+ expect(matrix.overallStatus).toBe('degraded');
804
+ });
805
+ test('returns fail when closed circuit exceeds fail budgets', () => {
806
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
807
+ generatedAt: '2026-04-01T12:00:00.000Z',
808
+ configuredStoreBackend: 'file',
809
+ configuredQueryBackend: 'local_vector',
810
+ store: createStoreDiagnostics(),
811
+ queryDiagnostics: createQueryDiagnostics({
812
+ backendId: 'local-vector-v1',
813
+ runtime: {
814
+ backendId: 'local-vector-v1',
815
+ ready: true,
816
+ vectorIndex: {
817
+ enabled: true,
818
+ status: 'ready',
819
+ persisted: true,
820
+ loadedFromDisk: true,
821
+ acceleration: {
822
+ enabled: true,
823
+ mode: 'ann_prefilter',
824
+ adapterId: 'external-http-vector-acceleration-v1',
825
+ healthStatus: 'degraded',
826
+ circuitState: 'closed',
827
+ consecutiveFailures: 3,
828
+ shortCircuitCount: 4,
829
+ requestCount: 10,
830
+ retryCount: 6,
831
+ successCount: 4,
832
+ failureCount: 6,
833
+ halfOpenProbeSuccessCount: 1,
834
+ halfOpenProbeFailureCount: 2,
835
+ },
836
+ },
837
+ },
838
+ }),
839
+ queryCount: 14,
840
+ thresholds: {
841
+ queryVectorAccelerationShortCircuitWarnCount: 1,
842
+ queryVectorAccelerationShortCircuitFailCount: 4,
843
+ queryVectorAccelerationShortCircuitWarnRatioPct: 5,
844
+ queryVectorAccelerationShortCircuitFailRatioPct: 25,
845
+ queryVectorAccelerationConsecutiveFailuresWarnCount: 1,
846
+ queryVectorAccelerationConsecutiveFailuresFailCount: 3,
847
+ queryVectorAccelerationHalfOpenSuccessWarnRatioPct: 80,
848
+ queryVectorAccelerationHalfOpenSuccessFailRatioPct: 50,
849
+ },
850
+ });
851
+ const vectorAccelerationCircuitCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_circuit_state');
852
+ expect(vectorAccelerationCircuitCheck?.status).toBe('fail');
853
+ expect(String(vectorAccelerationCircuitCheck?.observed || '')).toContain('shortCircuitRatio=40%');
854
+ expect(String(vectorAccelerationCircuitCheck?.expected || '')).toContain('shortCircuitRatio<25%');
855
+ expect(matrix.signals.queryVectorIndexAccelerationShortCircuitRatioPct).toBe(40);
856
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitWarnBudgetExceeded).toBe(true);
857
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitFailBudgetExceeded).toBe(true);
858
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitBudgetStatus).toBe('fail');
859
+ expect(matrix.overallStatus).toBe('blocked');
860
+ });
861
+ test('returns fail when half-open circuit recovery success rate is below fail floor', () => {
862
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
863
+ generatedAt: '2026-04-01T12:00:00.000Z',
864
+ configuredStoreBackend: 'file',
865
+ configuredQueryBackend: 'local_vector',
866
+ store: createStoreDiagnostics(),
867
+ queryDiagnostics: createQueryDiagnostics({
868
+ backendId: 'local-vector-v1',
869
+ runtime: {
870
+ backendId: 'local-vector-v1',
871
+ ready: true,
872
+ vectorIndex: {
873
+ enabled: true,
874
+ status: 'ready',
875
+ persisted: true,
876
+ loadedFromDisk: true,
877
+ acceleration: {
878
+ enabled: true,
879
+ mode: 'ann_prefilter',
880
+ adapterId: 'external-http-vector-acceleration-v1',
881
+ healthStatus: 'degraded',
882
+ circuitState: 'half_open',
883
+ consecutiveFailures: 1,
884
+ shortCircuitCount: 1,
885
+ requestCount: 10,
886
+ retryCount: 5,
887
+ successCount: 4,
888
+ failureCount: 6,
889
+ halfOpenProbeSuccessCount: 1,
890
+ halfOpenProbeFailureCount: 4,
891
+ },
892
+ },
893
+ },
894
+ }),
895
+ queryCount: 14,
896
+ thresholds: {
897
+ queryVectorAccelerationShortCircuitWarnCount: 1,
898
+ queryVectorAccelerationShortCircuitFailCount: 5,
899
+ queryVectorAccelerationShortCircuitWarnRatioPct: 5,
900
+ queryVectorAccelerationShortCircuitFailRatioPct: 40,
901
+ queryVectorAccelerationConsecutiveFailuresWarnCount: 1,
902
+ queryVectorAccelerationConsecutiveFailuresFailCount: 4,
903
+ queryVectorAccelerationHalfOpenSuccessWarnRatioPct: 80,
904
+ queryVectorAccelerationHalfOpenSuccessFailRatioPct: 50,
905
+ },
906
+ });
907
+ const vectorAccelerationCircuitCheck = matrix.checks.find((check) => check.checkId === 'query_vector_acceleration_circuit_state');
908
+ expect(vectorAccelerationCircuitCheck?.status).toBe('fail');
909
+ expect(String(vectorAccelerationCircuitCheck?.observed || '')).toContain('circuitState=half_open');
910
+ expect(String(vectorAccelerationCircuitCheck?.observed || '')).toContain('halfOpenSuccessRate=20%');
911
+ expect(String(vectorAccelerationCircuitCheck?.expected || '')).toContain('halfOpenSuccessRate>=50%');
912
+ expect(matrix.signals.queryVectorIndexAccelerationShortCircuitRatioPct).toBe(10);
913
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitWarnBudgetExceeded).toBe(true);
914
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitFailBudgetExceeded).toBe(true);
915
+ expect(matrix.signals.queryVectorIndexAccelerationCircuitBudgetStatus).toBe('fail');
916
+ expect(matrix.overallStatus).toBe('blocked');
917
+ });
918
+ test('returns fail when query explainability evidence/temporal ratios drop below hard floors', () => {
919
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
920
+ generatedAt: '2026-04-01T12:00:00.000Z',
921
+ configuredStoreBackend: 'file',
922
+ configuredQueryBackend: 'local_hybrid',
923
+ store: createStoreDiagnostics(),
924
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
925
+ queryCount: 20,
926
+ queryExplainabilityTelemetry: {
927
+ sampleCount: 20,
928
+ evidenceCoverageRatioPct: 68,
929
+ relationPathCoverageRatioPct: 55,
930
+ temporalValidityPassRatioPct: 70,
931
+ averageEvidenceSpanCount: 1.4,
932
+ averageRelationPathLength: 0.8,
933
+ },
934
+ thresholds: {
935
+ minQuerySampleSize: 5,
936
+ queryEvidenceCoverageWarnRatioPct: 90,
937
+ queryEvidenceCoverageFailRatioPct: 75,
938
+ queryTemporalValidityWarnRatioPct: 92,
939
+ queryTemporalValidityFailRatioPct: 80,
940
+ },
941
+ });
942
+ const evidenceCheck = matrix.checks.find((check) => check.checkId === 'query_evidence_coverage_ratio');
943
+ const temporalCheck = matrix.checks.find((check) => check.checkId === 'query_temporal_validity_ratio');
944
+ expect(evidenceCheck?.status).toBe('fail');
945
+ expect(temporalCheck?.status).toBe('fail');
946
+ expect(evidenceCheck?.expected).toBe('evidenceCoverage>=75%');
947
+ expect(temporalCheck?.expected).toBe('temporalValidity>=80%');
948
+ expect(matrix.signals.queryExplainabilitySampleCount).toBe(20);
949
+ expect(matrix.signals.queryEvidenceCoverageRatioPct).toBe(68);
950
+ expect(matrix.signals.queryRelationPathCoverageRatioPct).toBe(55);
951
+ expect(matrix.signals.queryTemporalValidityPassRatioPct).toBe(70);
952
+ expect(matrix.overallStatus).toBe('blocked');
953
+ });
954
+ test('returns warn when explainability sample count is insufficient', () => {
955
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
956
+ generatedAt: '2026-04-01T12:00:00.000Z',
957
+ configuredStoreBackend: 'file',
958
+ configuredQueryBackend: 'local_hybrid',
959
+ store: createStoreDiagnostics(),
960
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
961
+ queryCount: 20,
962
+ queryExplainabilityTelemetry: {
963
+ sampleCount: 2,
964
+ evidenceCoverageRatioPct: 95,
965
+ temporalValidityPassRatioPct: 96,
966
+ },
967
+ thresholds: {
968
+ minQuerySampleSize: 5,
969
+ },
970
+ });
971
+ const evidenceCheck = matrix.checks.find((check) => check.checkId === 'query_evidence_coverage_ratio');
972
+ const temporalCheck = matrix.checks.find((check) => check.checkId === 'query_temporal_validity_ratio');
973
+ expect(evidenceCheck?.status).toBe('warn');
974
+ expect(temporalCheck?.status).toBe('warn');
975
+ expect(evidenceCheck?.expected).toBe('sampleCount>=5');
976
+ expect(temporalCheck?.expected).toBe('sampleCount>=5');
977
+ });
978
+ test('returns fail when cross-backend explainability gap exceeds hard consistency ceiling', () => {
979
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
980
+ generatedAt: '2026-04-01T12:00:00.000Z',
981
+ configuredStoreBackend: 'file',
982
+ configuredQueryBackend: 'local_hybrid',
983
+ store: createStoreDiagnostics(),
984
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
985
+ queryCount: 24,
986
+ queryBackendComparisonTelemetry: {
987
+ summary: {
988
+ returnedRecords: 12,
989
+ averageLeftEvidenceCoverageRatio: 0.94,
990
+ averageRightEvidenceCoverageRatio: 0.58,
991
+ averageLeftRelationPathCoverageRatio: 0.81,
992
+ averageRightRelationPathCoverageRatio: 0.62,
993
+ averageLeftTemporalValidityPassRatio: 0.97,
994
+ averageRightTemporalValidityPassRatio: 0.63,
995
+ },
996
+ },
997
+ thresholds: {
998
+ minQuerySampleSize: 5,
999
+ queryBackendExplainabilityGapWarnRatioPct: 18,
1000
+ queryBackendExplainabilityGapFailRatioPct: 30,
1001
+ },
1002
+ });
1003
+ const comparisonGapCheck = matrix.checks.find((check) => check.checkId === 'query_backend_explainability_gap');
1004
+ expect(comparisonGapCheck?.status).toBe('fail');
1005
+ expect(comparisonGapCheck?.expected).toBe('maxGap<=30%');
1006
+ expect(comparisonGapCheck?.debugTraceHint).toEqual({
1007
+ pathPrefix: '/api/knowledge/query/compare-backends',
1008
+ statusAtLeast: 400,
1009
+ method: '',
1010
+ errorCode: '',
1011
+ });
1012
+ expect(matrix.signals.queryBackendComparisonSampleCount).toBe(12);
1013
+ expect(matrix.signals.queryBackendComparisonEvidenceGapRatioPct).toBe(36);
1014
+ expect(matrix.signals.queryBackendComparisonRelationGapRatioPct).toBe(19);
1015
+ expect(matrix.signals.queryBackendComparisonTemporalGapRatioPct).toBe(34);
1016
+ expect(matrix.signals.queryBackendComparisonMaxExplainabilityGapRatioPct).toBe(36);
1017
+ expect(matrix.overallStatus).toBe('blocked');
1018
+ });
1019
+ test('returns warn when backend comparison sample size is insufficient', () => {
1020
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1021
+ generatedAt: '2026-04-01T12:00:00.000Z',
1022
+ configuredStoreBackend: 'file',
1023
+ configuredQueryBackend: 'local_hybrid',
1024
+ store: createStoreDiagnostics(),
1025
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1026
+ queryCount: 24,
1027
+ queryBackendComparisonTelemetry: {
1028
+ summary: {
1029
+ returnedRecords: 2,
1030
+ averageLeftEvidenceCoverageRatio: 0.9,
1031
+ averageRightEvidenceCoverageRatio: 0.89,
1032
+ averageLeftRelationPathCoverageRatio: 0.72,
1033
+ averageRightRelationPathCoverageRatio: 0.7,
1034
+ averageLeftTemporalValidityPassRatio: 0.96,
1035
+ averageRightTemporalValidityPassRatio: 0.95,
1036
+ },
1037
+ },
1038
+ thresholds: {
1039
+ minQuerySampleSize: 5,
1040
+ queryBackendExplainabilityGapWarnRatioPct: 15,
1041
+ queryBackendExplainabilityGapFailRatioPct: 25,
1042
+ },
1043
+ });
1044
+ const comparisonGapCheck = matrix.checks.find((check) => check.checkId === 'query_backend_explainability_gap');
1045
+ expect(comparisonGapCheck?.status).toBe('warn');
1046
+ expect(comparisonGapCheck?.expected).toBe('sampleCount>=5');
1047
+ expect(matrix.signals.queryBackendComparisonSampleCount).toBe(2);
1048
+ expect(matrix.overallStatus).toBe('degraded');
1049
+ });
1050
+ test('returns fail when backend comparison trend is regressing with high confidence', () => {
1051
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1052
+ generatedAt: '2026-04-01T12:00:00.000Z',
1053
+ configuredStoreBackend: 'file',
1054
+ configuredQueryBackend: 'local_hybrid',
1055
+ store: createStoreDiagnostics(),
1056
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1057
+ queryCount: 24,
1058
+ queryBackendComparisonTrend: {
1059
+ status: 'regressing',
1060
+ score: -4.4,
1061
+ confidence: 0.81,
1062
+ summary: {
1063
+ reason: 'Recent comparison windows diverged in explainability quality.',
1064
+ },
1065
+ },
1066
+ thresholds: {
1067
+ queryBackendTrendWarnConfidenceRatioPct: 40,
1068
+ queryBackendTrendFailConfidenceRatioPct: 70,
1069
+ },
1070
+ });
1071
+ const trendCheck = matrix.checks.find((check) => check.checkId === 'query_backend_comparison_trend');
1072
+ expect(trendCheck?.status).toBe('fail');
1073
+ expect(trendCheck?.debugTraceHint).toEqual({
1074
+ pathPrefix: '/api/knowledge/query/compare-backends/trend',
1075
+ statusAtLeast: 400,
1076
+ method: '',
1077
+ errorCode: '',
1078
+ });
1079
+ expect(matrix.signals.queryBackendComparisonTrendStatus).toBe('regressing');
1080
+ expect(matrix.signals.queryBackendComparisonTrendScore).toBe(-4.4);
1081
+ expect(matrix.signals.queryBackendComparisonTrendConfidence).toBe(0.81);
1082
+ expect(matrix.overallStatus).toBe('blocked');
1083
+ });
1084
+ test('returns warn/pass based on backend comparison trend status and confidence', () => {
1085
+ const warnMatrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1086
+ generatedAt: '2026-04-01T12:00:00.000Z',
1087
+ configuredStoreBackend: 'file',
1088
+ configuredQueryBackend: 'local_hybrid',
1089
+ store: createStoreDiagnostics(),
1090
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1091
+ queryCount: 24,
1092
+ queryBackendComparisonTrend: {
1093
+ status: 'regressing',
1094
+ score: -2.6,
1095
+ confidence: 0.21,
1096
+ summary: {
1097
+ reason: 'Regression signal detected but confidence remains limited.',
1098
+ },
1099
+ },
1100
+ thresholds: {
1101
+ queryBackendTrendWarnConfidenceRatioPct: 40,
1102
+ queryBackendTrendFailConfidenceRatioPct: 70,
1103
+ },
1104
+ });
1105
+ const warnTrendCheck = warnMatrix.checks.find((check) => check.checkId === 'query_backend_comparison_trend');
1106
+ expect(warnTrendCheck?.status).toBe('warn');
1107
+ expect(warnMatrix.overallStatus).toBe('degraded');
1108
+ const passMatrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1109
+ generatedAt: '2026-04-01T12:00:00.000Z',
1110
+ configuredStoreBackend: 'file',
1111
+ configuredQueryBackend: 'local_hybrid',
1112
+ store: createStoreDiagnostics(),
1113
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1114
+ queryCount: 24,
1115
+ queryBackendComparisonTrend: {
1116
+ status: 'stable',
1117
+ score: 0.3,
1118
+ confidence: 0.62,
1119
+ summary: {
1120
+ reason: 'Trend window remains within explainability guardrails.',
1121
+ },
1122
+ },
1123
+ });
1124
+ const passTrendCheck = passMatrix.checks.find((check) => check.checkId === 'query_backend_comparison_trend');
1125
+ expect(passTrendCheck?.status).toBe('pass');
1126
+ expect(passMatrix.signals.queryBackendComparisonTrendStatus).toBe('stable');
1127
+ expect(passMatrix.signals.queryBackendComparisonTrendScore).toBe(0.3);
1128
+ expect(passMatrix.signals.queryBackendComparisonTrendConfidence).toBe(0.62);
1129
+ });
1130
+ test('returns fail when backend comparison trend config cannot satisfy dual-window minimum records', () => {
1131
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1132
+ generatedAt: '2026-04-01T12:00:00.000Z',
1133
+ configuredStoreBackend: 'file',
1134
+ configuredQueryBackend: 'local_hybrid',
1135
+ store: createStoreDiagnostics(),
1136
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1137
+ queryCount: 24,
1138
+ queryBackendComparisonTelemetry: {
1139
+ summary: {
1140
+ returnedRecords: 10,
1141
+ },
1142
+ },
1143
+ queryBackendComparisonTrendConfig: {
1144
+ limit: 2,
1145
+ windowSize: 2,
1146
+ minSamples: 2,
1147
+ },
1148
+ });
1149
+ const configCheck = matrix.checks.find((check) => check.checkId === 'query_backend_trend_config');
1150
+ expect(configCheck?.status).toBe('fail');
1151
+ expect(configCheck?.expected).toBe('limit>=4');
1152
+ expect(configCheck?.debugTraceHint).toEqual({
1153
+ pathPrefix: '/api/knowledge/query/compare-backends/trend',
1154
+ statusAtLeast: 400,
1155
+ method: '',
1156
+ errorCode: '',
1157
+ });
1158
+ expect(matrix.signals.queryBackendComparisonTrendLimit).toBe(2);
1159
+ expect(matrix.signals.queryBackendComparisonTrendWindowSize).toBe(2);
1160
+ expect(matrix.signals.queryBackendComparisonTrendMinSamples).toBe(2);
1161
+ expect(matrix.signals.queryBackendComparisonTrendRequiredRecords).toBe(4);
1162
+ expect(matrix.overallStatus).toBe('blocked');
1163
+ });
1164
+ test('returns warn when trend config is valid but current comparison sample budget is insufficient', () => {
1165
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1166
+ generatedAt: '2026-04-01T12:00:00.000Z',
1167
+ configuredStoreBackend: 'file',
1168
+ configuredQueryBackend: 'local_hybrid',
1169
+ store: createStoreDiagnostics(),
1170
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1171
+ queryCount: 24,
1172
+ queryBackendComparisonTelemetry: {
1173
+ summary: {
1174
+ returnedRecords: 2,
1175
+ },
1176
+ },
1177
+ queryBackendComparisonTrendConfig: {
1178
+ limit: 8,
1179
+ windowSize: 3,
1180
+ minSamples: 2,
1181
+ },
1182
+ });
1183
+ const configCheck = matrix.checks.find((check) => check.checkId === 'query_backend_trend_config');
1184
+ expect(configCheck?.status).toBe('warn');
1185
+ expect(configCheck?.expected).toBe('sampleCount>=5');
1186
+ expect(matrix.signals.queryBackendComparisonTrendLimit).toBe(8);
1187
+ expect(matrix.signals.queryBackendComparisonTrendWindowSize).toBe(3);
1188
+ expect(matrix.signals.queryBackendComparisonTrendMinSamples).toBe(2);
1189
+ expect(matrix.signals.queryBackendComparisonTrendRequiredRecords).toBe(5);
1190
+ expect(matrix.overallStatus).toBe('degraded');
1191
+ });
1192
+ test('returns pass when trend config and sample budget are aligned', () => {
1193
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1194
+ generatedAt: '2026-04-01T12:00:00.000Z',
1195
+ configuredStoreBackend: 'file',
1196
+ configuredQueryBackend: 'local_hybrid',
1197
+ store: createStoreDiagnostics(),
1198
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1199
+ queryCount: 24,
1200
+ queryBackendComparisonTelemetry: {
1201
+ summary: {
1202
+ returnedRecords: 6,
1203
+ },
1204
+ },
1205
+ queryBackendComparisonTrendConfig: {
1206
+ limit: 10,
1207
+ windowSize: 2,
1208
+ minSamples: 1,
1209
+ },
1210
+ });
1211
+ const configCheck = matrix.checks.find((check) => check.checkId === 'query_backend_trend_config');
1212
+ expect(configCheck?.status).toBe('pass');
1213
+ expect(configCheck?.expected).toBe('limit>=3');
1214
+ expect(matrix.signals.queryBackendComparisonTrendLimit).toBe(10);
1215
+ expect(matrix.signals.queryBackendComparisonTrendWindowSize).toBe(2);
1216
+ expect(matrix.signals.queryBackendComparisonTrendMinSamples).toBe(1);
1217
+ expect(matrix.signals.queryBackendComparisonTrendRequiredRecords).toBe(3);
1218
+ });
1219
+ test('returns fail when invalid-request ratio exceeds fail threshold', () => {
1220
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1221
+ generatedAt: '2026-04-01T12:00:00.000Z',
1222
+ configuredStoreBackend: 'file',
1223
+ configuredQueryBackend: 'local_hybrid',
1224
+ store: createStoreDiagnostics(),
1225
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1226
+ queryCount: 20,
1227
+ apiRequestErrorTelemetry: {
1228
+ totalRequests: 40,
1229
+ errorRequests: 20,
1230
+ invalidRequestErrors: 16,
1231
+ scopePathPrefix: '/api/knowledge',
1232
+ scopeMethod: 'post',
1233
+ invalidRequestTopPaths: [
1234
+ { path: 'POST /api/knowledge/query', count: 9 },
1235
+ { path: 'POST /api/knowledge/mastery/diagnose', count: 7 },
1236
+ ],
1237
+ },
1238
+ thresholds: {
1239
+ apiInvalidRequestMinErrorSample: 5,
1240
+ apiInvalidRequestWarnRatioPct: 35,
1241
+ apiInvalidRequestFailRatioPct: 60,
1242
+ apiInvalidRequestHotspotWarnCount: 4,
1243
+ apiInvalidRequestHotspotFailCount: 8,
1244
+ },
1245
+ });
1246
+ const apiInvalidRequestCheck = matrix.checks.find((check) => check.checkId === 'api_invalid_request_ratio');
1247
+ const apiHotspotCheck = matrix.checks.find((check) => check.checkId === 'api_invalid_request_hotspots');
1248
+ const checkOrder = matrix.checks.map((check) => String(check?.checkId || ''));
1249
+ expect(apiInvalidRequestCheck?.status).toBe('fail');
1250
+ expect(apiHotspotCheck?.status).toBe('fail');
1251
+ expect(apiInvalidRequestCheck?.expected).toBe('invalid/error<=60%');
1252
+ expect(apiHotspotCheck?.expected).toBe('topPathInvalidCount<8');
1253
+ expect(apiInvalidRequestCheck?.debugTraceHint).toEqual({
1254
+ pathPrefix: '/api/knowledge',
1255
+ statusAtLeast: 400,
1256
+ method: 'POST',
1257
+ errorCode: 'invalid_request',
1258
+ });
1259
+ expect(apiInvalidRequestCheck?.recommendedActions).toEqual(expect.arrayContaining([
1260
+ expect.stringContaining('errorCode=invalid_request'),
1261
+ ]));
1262
+ expect(apiHotspotCheck?.debugTraceHint).toEqual({
1263
+ pathPrefix: '/api/knowledge/query',
1264
+ statusAtLeast: 400,
1265
+ method: 'POST',
1266
+ errorCode: 'invalid_request',
1267
+ });
1268
+ expect(apiHotspotCheck?.recommendedActions).toEqual(expect.arrayContaining([
1269
+ expect.stringContaining('POST /api/knowledge/query'),
1270
+ ]));
1271
+ expect(Number(apiInvalidRequestCheck?.priorityScore || 0)).toBeGreaterThan(0);
1272
+ expect(Number(apiHotspotCheck?.priorityScore || 0)).toBeGreaterThan(Number(apiInvalidRequestCheck?.priorityScore || 0));
1273
+ expect(checkOrder.indexOf('api_invalid_request_hotspots')).toBeGreaterThanOrEqual(0);
1274
+ expect(checkOrder.indexOf('api_invalid_request_ratio')).toBeGreaterThanOrEqual(0);
1275
+ expect(checkOrder.indexOf('api_invalid_request_hotspots')).toBeLessThan(checkOrder.indexOf('api_invalid_request_ratio'));
1276
+ expect(matrix.signals.apiTraceWindowRequests).toBe(40);
1277
+ expect(matrix.signals.apiTraceWindowErrors).toBe(20);
1278
+ expect(matrix.signals.apiTraceWindowInvalidRequests).toBe(16);
1279
+ expect(matrix.signals.apiTraceWindowInvalidRequestRatioPct).toBe(80);
1280
+ expect(matrix.signals.apiTraceWindowInvalidRequestToTotalRatioPct).toBe(40);
1281
+ expect(matrix.signals.apiTraceScopePathPrefix).toBe('/api/knowledge');
1282
+ expect(matrix.signals.apiTraceScopeMethod).toBe('POST');
1283
+ expect(matrix.signals.apiTraceWindowInvalidRequestTopPaths.length).toBeGreaterThan(0);
1284
+ expect(matrix.signals.apiTraceWindowInvalidRequestTopPaths[0]?.path).toBe('POST /api/knowledge/query');
1285
+ expect(matrix.signals.apiTraceWindowInvalidRequestTopPaths[0]?.count).toBe(9);
1286
+ expect(matrix.signals.topRiskCheckId).toBe('api_invalid_request_hotspots');
1287
+ expect(matrix.signals.topRiskStatus).toBe('fail');
1288
+ expect(matrix.signals.topRiskPriorityScore).toBeGreaterThan(0);
1289
+ expect(matrix.signals.topRiskRecommendedActions.length).toBeGreaterThan(0);
1290
+ expect(matrix.overallStatus).toBe('blocked');
1291
+ });
1292
+ test('returns fail when server-error ratio exceeds fail threshold', () => {
1293
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1294
+ generatedAt: '2026-04-01T12:00:00.000Z',
1295
+ configuredStoreBackend: 'file',
1296
+ configuredQueryBackend: 'local_hybrid',
1297
+ store: createStoreDiagnostics(),
1298
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1299
+ queryCount: 20,
1300
+ apiRequestErrorTelemetry: {
1301
+ totalRequests: 50,
1302
+ errorRequests: 11,
1303
+ invalidRequestErrors: 3,
1304
+ serverErrorRequests: 9,
1305
+ scopePathPrefix: '/api/knowledge',
1306
+ scopeMethod: 'post',
1307
+ serverErrorTopPaths: [
1308
+ { path: 'POST /api/knowledge/query', count: 7 },
1309
+ { path: 'POST /api/knowledge/session/execute', count: 2 },
1310
+ ],
1311
+ },
1312
+ thresholds: {
1313
+ apiServerErrorMinRequestSample: 8,
1314
+ apiServerErrorWarnRatioPct: 6,
1315
+ apiServerErrorFailRatioPct: 15,
1316
+ },
1317
+ });
1318
+ const serverErrorCheck = matrix.checks.find((check) => check.checkId === 'api_server_error_ratio');
1319
+ const serverErrorHotspotCheck = matrix.checks.find((check) => check.checkId === 'api_server_error_hotspots');
1320
+ const checkOrder = matrix.checks.map((check) => String(check?.checkId || ''));
1321
+ expect(serverErrorCheck?.status).toBe('fail');
1322
+ expect(serverErrorCheck?.expected).toBe('server/total<=15%');
1323
+ expect(serverErrorHotspotCheck?.status).toBe('fail');
1324
+ expect(serverErrorHotspotCheck?.expected).toBe('topPathServerErrorCount<5');
1325
+ expect(serverErrorCheck?.debugTraceHint).toEqual({
1326
+ pathPrefix: '/api/knowledge/query',
1327
+ statusAtLeast: 500,
1328
+ method: 'POST',
1329
+ errorCode: '',
1330
+ });
1331
+ expect(serverErrorHotspotCheck?.debugTraceHint).toEqual({
1332
+ pathPrefix: '/api/knowledge/query',
1333
+ statusAtLeast: 500,
1334
+ method: 'POST',
1335
+ errorCode: '',
1336
+ });
1337
+ expect(serverErrorCheck?.recommendedActions).toEqual(expect.arrayContaining([
1338
+ expect.stringContaining('status>=500'),
1339
+ ]));
1340
+ expect(Number(serverErrorCheck?.priorityScore || 0)).toBeGreaterThan(0);
1341
+ expect(Number(serverErrorHotspotCheck?.priorityScore || 0)).toBeGreaterThan(Number(serverErrorCheck?.priorityScore || 0));
1342
+ expect(checkOrder.indexOf('api_server_error_hotspots')).toBeGreaterThanOrEqual(0);
1343
+ expect(checkOrder.indexOf('api_server_error_ratio')).toBeGreaterThanOrEqual(0);
1344
+ expect(checkOrder.indexOf('api_server_error_hotspots')).toBeLessThan(checkOrder.indexOf('api_server_error_ratio'));
1345
+ expect(matrix.signals.apiTraceWindowServerErrors).toBe(9);
1346
+ expect(matrix.signals.apiTraceWindowServerErrorRatioPct).toBe(18);
1347
+ expect(matrix.signals.apiTraceWindowServerErrorTopPaths.length).toBe(2);
1348
+ expect(matrix.signals.apiTraceWindowServerErrorTopPaths[0]?.path).toBe('POST /api/knowledge/query');
1349
+ expect(matrix.signals.apiTraceWindowServerErrorTopPaths[0]?.count).toBe(7);
1350
+ expect(matrix.overallStatus).toBe('blocked');
1351
+ });
1352
+ test('returns fail when transient-error ratio and hotspot concentration exceed thresholds', () => {
1353
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1354
+ generatedAt: '2026-04-01T12:00:00.000Z',
1355
+ configuredStoreBackend: 'file',
1356
+ configuredQueryBackend: 'local_hybrid',
1357
+ store: createStoreDiagnostics(),
1358
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1359
+ queryCount: 20,
1360
+ apiRequestErrorTelemetry: {
1361
+ totalRequests: 40,
1362
+ errorRequests: 14,
1363
+ invalidRequestErrors: 1,
1364
+ serverErrorRequests: 3,
1365
+ transientErrorRequests: 10,
1366
+ scopePathPrefix: '/api/knowledge',
1367
+ scopeMethod: 'GET',
1368
+ transientErrorTopPaths: [
1369
+ { path: 'GET /api/knowledge/state', count: 7 },
1370
+ { path: 'GET /api/runtime-request-trace', count: 3 },
1371
+ ],
1372
+ },
1373
+ thresholds: {
1374
+ apiTransientErrorMinRequestSample: 5,
1375
+ apiTransientErrorWarnRatioPct: 8,
1376
+ apiTransientErrorFailRatioPct: 20,
1377
+ apiTransientErrorHotspotWarnCount: 3,
1378
+ apiTransientErrorHotspotFailCount: 6,
1379
+ },
1380
+ });
1381
+ const transientRatioCheck = matrix.checks.find((check) => check.checkId === 'api_transient_error_ratio');
1382
+ const transientHotspotCheck = matrix.checks.find((check) => check.checkId === 'api_transient_error_hotspots');
1383
+ expect(transientRatioCheck?.status).toBe('fail');
1384
+ expect(transientHotspotCheck?.status).toBe('fail');
1385
+ expect(transientRatioCheck?.expected).toBe('transient/total<=20%');
1386
+ expect(transientHotspotCheck?.expected).toBe('topPathTransientErrorCount<6');
1387
+ expect(transientRatioCheck?.debugTraceHint).toEqual({
1388
+ pathPrefix: '/api/knowledge/state',
1389
+ statusAtLeast: 400,
1390
+ method: 'GET',
1391
+ errorCode: '',
1392
+ });
1393
+ expect(transientHotspotCheck?.debugTraceHint).toEqual({
1394
+ pathPrefix: '/api/knowledge/state',
1395
+ statusAtLeast: 400,
1396
+ method: 'GET',
1397
+ errorCode: '',
1398
+ });
1399
+ expect(transientHotspotCheck?.recommendedActions).toEqual(expect.arrayContaining([
1400
+ expect.stringContaining('408/425/429/502/503/504'),
1401
+ ]));
1402
+ expect(matrix.signals.apiTraceWindowTransientErrors).toBe(10);
1403
+ expect(matrix.signals.apiTraceWindowTransientErrorRatioPct).toBe(25);
1404
+ expect(matrix.signals.apiTraceWindowTransientErrorTopPaths.length).toBe(2);
1405
+ expect(matrix.signals.apiTraceWindowTransientErrorTopPaths[0]?.path).toBe('GET /api/knowledge/state');
1406
+ expect(matrix.signals.apiTraceWindowTransientErrorTopPaths[0]?.count).toBe(7);
1407
+ expect(matrix.overallStatus).toBe('blocked');
1408
+ });
1409
+ test('returns fail when api p95 latency and slow-route hotspot exceed thresholds', () => {
1410
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1411
+ generatedAt: '2026-04-01T12:00:00.000Z',
1412
+ configuredStoreBackend: 'file',
1413
+ configuredQueryBackend: 'local_hybrid',
1414
+ store: createStoreDiagnostics(),
1415
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1416
+ queryCount: 30,
1417
+ apiRequestErrorTelemetry: {
1418
+ totalRequests: 30,
1419
+ errorRequests: 6,
1420
+ invalidRequestErrors: 1,
1421
+ serverErrorRequests: 2,
1422
+ transientErrorRequests: 3,
1423
+ averageDurationMs: 820,
1424
+ p95DurationMs: 2800,
1425
+ scopePathPrefix: '/api/knowledge',
1426
+ scopeMethod: 'post',
1427
+ slowTopPaths: [
1428
+ { path: 'POST /api/knowledge/session/execute', count: 5, p95DurationMs: 3600 },
1429
+ { path: 'POST /api/knowledge/ingest', count: 3, p95DurationMs: 2400 },
1430
+ ],
1431
+ },
1432
+ thresholds: {
1433
+ apiLatencyMinRequestSample: 10,
1434
+ apiLatencyP95WarnMs: 900,
1435
+ apiLatencyP95FailMs: 2400,
1436
+ apiLatencyHotspotWarnMs: 1500,
1437
+ apiLatencyHotspotFailMs: 3200,
1438
+ },
1439
+ });
1440
+ const latencyP95Check = matrix.checks.find((check) => check.checkId === 'api_latency_p95');
1441
+ const latencyHotspotCheck = matrix.checks.find((check) => check.checkId === 'api_latency_hotspots');
1442
+ expect(latencyP95Check?.status).toBe('fail');
1443
+ expect(latencyHotspotCheck?.status).toBe('fail');
1444
+ expect(latencyP95Check?.expected).toBe('p95<=2400ms');
1445
+ expect(latencyHotspotCheck?.expected).toBe('topPathP95<=3200ms');
1446
+ expect(latencyP95Check?.debugTraceHint).toEqual({
1447
+ pathPrefix: '/api/knowledge/session/execute',
1448
+ statusAtLeast: 0,
1449
+ method: 'POST',
1450
+ errorCode: '',
1451
+ });
1452
+ expect(latencyHotspotCheck?.debugTraceHint).toEqual({
1453
+ pathPrefix: '/api/knowledge/session/execute',
1454
+ statusAtLeast: 0,
1455
+ method: 'POST',
1456
+ errorCode: '',
1457
+ });
1458
+ expect(latencyP95Check?.recommendedActions).toEqual(expect.arrayContaining([
1459
+ expect.stringContaining('Current p95=2800ms'),
1460
+ ]));
1461
+ expect(latencyHotspotCheck?.recommendedActions).toEqual(expect.arrayContaining([
1462
+ expect.stringContaining('hotspot p95=3600ms'),
1463
+ ]));
1464
+ expect(matrix.signals.apiTraceAverageDurationMs).toBe(820);
1465
+ expect(matrix.signals.apiTraceP95DurationMs).toBe(2800);
1466
+ expect(matrix.signals.apiTraceSlowTopPaths.length).toBe(2);
1467
+ expect(matrix.signals.apiTraceSlowTopPaths[0]?.path).toBe('POST /api/knowledge/session/execute');
1468
+ expect(matrix.signals.apiTraceSlowTopPaths[0]?.count).toBe(5);
1469
+ expect(matrix.signals.apiTraceSlowTopPaths[0]?.p95DurationMs).toBe(3600);
1470
+ expect(matrix.overallStatus).toBe('blocked');
1471
+ });
1472
+ test('returns pass when current trace window has no API validation errors', () => {
1473
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1474
+ generatedAt: '2026-04-01T12:00:00.000Z',
1475
+ configuredStoreBackend: 'file',
1476
+ configuredQueryBackend: 'local_hybrid',
1477
+ store: createStoreDiagnostics(),
1478
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1479
+ queryCount: 20,
1480
+ apiRequestErrorTelemetry: {
1481
+ totalRequests: 24,
1482
+ errorRequests: 0,
1483
+ invalidRequestErrors: 0,
1484
+ scopePathPrefix: '/api/knowledge',
1485
+ scopeMethod: 'GET',
1486
+ },
1487
+ learningQualityTrend: {
1488
+ status: 'stable',
1489
+ score: 0.24,
1490
+ confidence: 0.7,
1491
+ },
1492
+ sessionPlanQualityHistory: {
1493
+ summary: {
1494
+ totalRecords: 4,
1495
+ overallPassRatePct: 75,
1496
+ consecutiveFailureCount: 0,
1497
+ commonFailedGates: [],
1498
+ },
1499
+ },
1500
+ sessionPlanQualityTrend: {
1501
+ status: 'stable',
1502
+ score: 0.11,
1503
+ confidence: 0.64,
1504
+ },
1505
+ memoryPolicyDiagnostics: {
1506
+ summary: {
1507
+ totalEntries: 18,
1508
+ expiredEntries: 0,
1509
+ staleEntries: 1,
1510
+ lowConfidenceEntries: 1,
1511
+ healthScore: 92,
1512
+ status: 'healthy',
1513
+ },
1514
+ },
1515
+ memoryPolicyTrend: {
1516
+ status: 'stable',
1517
+ score: 0.08,
1518
+ confidence: 0.54,
1519
+ },
1520
+ });
1521
+ const apiInvalidRequestCheck = matrix.checks.find((check) => check.checkId === 'api_invalid_request_ratio');
1522
+ const apiServerErrorCheck = matrix.checks.find((check) => check.checkId === 'api_server_error_ratio');
1523
+ const apiServerErrorHotspotCheck = matrix.checks.find((check) => check.checkId === 'api_server_error_hotspots');
1524
+ expect(apiInvalidRequestCheck?.status).toBe('pass');
1525
+ expect(apiServerErrorCheck?.status).toBe('pass');
1526
+ expect(apiServerErrorHotspotCheck?.status).toBe('pass');
1527
+ expect(matrix.signals.apiTraceWindowRequests).toBe(24);
1528
+ expect(matrix.signals.apiTraceWindowErrors).toBe(0);
1529
+ expect(matrix.signals.apiTraceWindowInvalidRequests).toBe(0);
1530
+ expect(matrix.signals.apiTraceWindowInvalidRequestRatioPct).toBe(0);
1531
+ expect(matrix.signals.apiTraceWindowInvalidRequestToTotalRatioPct).toBe(0);
1532
+ expect(matrix.signals.apiTraceWindowServerErrors).toBe(0);
1533
+ expect(matrix.signals.apiTraceWindowServerErrorRatioPct).toBe(0);
1534
+ expect(matrix.signals.apiTraceWindowServerErrorTopPaths).toEqual([]);
1535
+ expect(matrix.signals.apiTraceScopePathPrefix).toBe('/api/knowledge');
1536
+ expect(matrix.signals.apiTraceScopeMethod).toBe('GET');
1537
+ });
1538
+ test('returns warn for keyword-only backend and graphdb fallback', () => {
1539
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1540
+ generatedAt: '2026-04-01T12:00:00.000Z',
1541
+ configuredStoreBackend: 'graphdb',
1542
+ configuredQueryBackend: 'keyword_only',
1543
+ store: createStoreDiagnostics({
1544
+ storeType: 'graphdb',
1545
+ usingFallback: true,
1546
+ fallbackStoreType: 'file',
1547
+ backendReady: true,
1548
+ }),
1549
+ queryDiagnostics: createQueryDiagnostics({
1550
+ fallbackCount: 1,
1551
+ lastError: 'backend transient error',
1552
+ }),
1553
+ queryCount: 12,
1554
+ });
1555
+ const checkById = new Map(matrix.checks.map((check) => [check.checkId, check]));
1556
+ expect(checkById.get('store_graphdb_fallback')?.status).toBe('warn');
1557
+ expect(checkById.get('query_graph_retrieval_capability')?.status).toBe('warn');
1558
+ expect(checkById.get('query_backend_last_error')?.status).toBe('warn');
1559
+ expect(checkById.get('query_backend_last_error')?.recommendedActions).toEqual(expect.arrayContaining([
1560
+ expect.stringContaining('/api/knowledge/query'),
1561
+ ]));
1562
+ expect(matrix.overallStatus).toBe('degraded');
1563
+ });
1564
+ test('returns fail when graphdb connector health is unavailable in strict runtime path', () => {
1565
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1566
+ generatedAt: '2026-04-01T12:00:00.000Z',
1567
+ configuredStoreBackend: 'graphdb',
1568
+ configuredQueryBackend: 'local_hybrid',
1569
+ store: createStoreDiagnostics({
1570
+ storeType: 'graphdb',
1571
+ usingFallback: false,
1572
+ backendReady: true,
1573
+ adapterId: 'external-http-graphdb',
1574
+ connector: {
1575
+ healthStatus: 'unavailable',
1576
+ circuitState: 'open',
1577
+ requestCount: 9,
1578
+ retryCount: 3,
1579
+ shortCircuitCount: 2,
1580
+ successCount: 1,
1581
+ failureCount: 8,
1582
+ consecutiveFailures: 4,
1583
+ lastRequestId: 'graphdb-req-009',
1584
+ lastErrorCode: 'circuit_open',
1585
+ lastStatusCode: 503,
1586
+ lastRetryAfterMs: 4200,
1587
+ },
1588
+ }),
1589
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1590
+ queryCount: 12,
1591
+ });
1592
+ const checkById = new Map(matrix.checks.map((check) => [check.checkId, check]));
1593
+ expect(checkById.get('store_graphdb_connector_health')?.status).toBe('fail');
1594
+ expect(checkById.get('store_graphdb_connector_budget')?.status).toBe('fail');
1595
+ expect(matrix.signals.graphDbConnectorHealthStatus).toBe('unavailable');
1596
+ expect(matrix.signals.graphDbConnectorCircuitState).toBe('open');
1597
+ expect(matrix.signals.graphDbConnectorFailureRatioPct).toBeCloseTo(88.8889, 4);
1598
+ expect(matrix.signals.graphDbConnectorShortCircuitRatioPct).toBeCloseTo(22.2222, 4);
1599
+ expect(matrix.signals.graphDbConnectorFailBudgetExceeded).toBe(true);
1600
+ expect(matrix.signals.graphDbConnectorBudgetStatus).toBe('fail');
1601
+ expect(matrix.signals.graphDbConnectorLastErrorCode).toBe('circuit_open');
1602
+ expect(matrix.overallStatus).toBe('blocked');
1603
+ });
1604
+ test('returns warn when graphdb connector budget approaches threshold under strict runtime path', () => {
1605
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1606
+ generatedAt: '2026-04-01T12:00:00.000Z',
1607
+ configuredStoreBackend: 'graphdb',
1608
+ configuredQueryBackend: 'local_hybrid',
1609
+ store: createStoreDiagnostics({
1610
+ storeType: 'graphdb',
1611
+ usingFallback: false,
1612
+ backendReady: true,
1613
+ adapterId: 'external-http-graphdb',
1614
+ connector: {
1615
+ healthStatus: 'ready',
1616
+ circuitState: 'closed',
1617
+ requestCount: 20,
1618
+ retryCount: 2,
1619
+ shortCircuitCount: 2,
1620
+ successCount: 16,
1621
+ failureCount: 4,
1622
+ consecutiveFailures: 1,
1623
+ lastRequestId: 'graphdb-req-020',
1624
+ },
1625
+ }),
1626
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1627
+ queryCount: 12,
1628
+ thresholds: {
1629
+ storeGraphDbConnectorMinRequestSample: 5,
1630
+ storeGraphDbConnectorFailureWarnRatioPct: 15,
1631
+ storeGraphDbConnectorFailureFailRatioPct: 30,
1632
+ storeGraphDbConnectorShortCircuitWarnRatioPct: 5,
1633
+ storeGraphDbConnectorShortCircuitFailRatioPct: 20,
1634
+ storeGraphDbConnectorConsecutiveFailuresWarnCount: 1,
1635
+ storeGraphDbConnectorConsecutiveFailuresFailCount: 3,
1636
+ },
1637
+ });
1638
+ const checkById = new Map(matrix.checks.map((check) => [check.checkId, check]));
1639
+ expect(checkById.get('store_graphdb_connector_health')?.status).toBe('warn');
1640
+ expect(checkById.get('store_graphdb_connector_budget')?.status).toBe('warn');
1641
+ expect(matrix.signals.graphDbConnectorFailureRatioPct).toBe(20);
1642
+ expect(matrix.signals.graphDbConnectorShortCircuitRatioPct).toBe(10);
1643
+ expect(matrix.signals.graphDbConnectorWarnBudgetExceeded).toBe(true);
1644
+ expect(matrix.signals.graphDbConnectorFailBudgetExceeded).toBe(false);
1645
+ expect(matrix.signals.graphDbConnectorBudgetStatus).toBe('warn');
1646
+ expect(matrix.overallStatus).toBe('degraded');
1647
+ });
1648
+ test('returns pass when graphdb connector health telemetry is stable', () => {
1649
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1650
+ generatedAt: '2026-04-01T12:00:00.000Z',
1651
+ configuredStoreBackend: 'graphdb',
1652
+ configuredQueryBackend: 'local_hybrid',
1653
+ store: createStoreDiagnostics({
1654
+ storeType: 'graphdb',
1655
+ usingFallback: false,
1656
+ backendReady: true,
1657
+ adapterId: 'external-http-graphdb',
1658
+ connector: {
1659
+ healthStatus: 'ready',
1660
+ healthMessage: 'graphdb_http_ok',
1661
+ circuitState: 'closed',
1662
+ requestCount: 16,
1663
+ retryCount: 1,
1664
+ shortCircuitCount: 0,
1665
+ successCount: 15,
1666
+ failureCount: 1,
1667
+ consecutiveFailures: 0,
1668
+ lastRequestId: 'graphdb-req-016',
1669
+ lastErrorCode: '',
1670
+ lastStatusCode: 200,
1671
+ lastRetryAfterMs: 0,
1672
+ },
1673
+ }),
1674
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1675
+ queryCount: 12,
1676
+ });
1677
+ const checkById = new Map(matrix.checks.map((check) => [check.checkId, check]));
1678
+ expect(checkById.get('store_graphdb_connector_health')?.status).toBe('pass');
1679
+ expect(checkById.get('store_graphdb_connector_budget')?.status).toBe('pass');
1680
+ expect(matrix.signals.graphDbConnectorHealthStatus).toBe('ready');
1681
+ expect(matrix.signals.graphDbConnectorCircuitState).toBe('closed');
1682
+ expect(matrix.signals.graphDbConnectorRequestCount).toBe(16);
1683
+ expect(matrix.signals.graphDbConnectorFailureRatioPct).toBe(6.25);
1684
+ expect(matrix.signals.graphDbConnectorShortCircuitRatioPct).toBe(0);
1685
+ expect(matrix.signals.graphDbConnectorBudgetStatus).toBe('ok');
1686
+ });
1687
+ test('returns pass when quality trend is improving', () => {
1688
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1689
+ generatedAt: '2026-04-01T12:00:00.000Z',
1690
+ configuredStoreBackend: 'file',
1691
+ configuredQueryBackend: 'local_hybrid',
1692
+ store: createStoreDiagnostics(),
1693
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1694
+ queryCount: 12,
1695
+ learningQualityTrend: {
1696
+ status: 'improving',
1697
+ score: 3.72,
1698
+ confidence: 0.84,
1699
+ reason: 'Recent quality snapshots improved across key signals.',
1700
+ },
1701
+ sessionPlanQualityHistory: {
1702
+ summary: {
1703
+ totalRecords: 6,
1704
+ overallPassRatePct: 83.33,
1705
+ consecutiveFailureCount: 0,
1706
+ commonFailedGates: [],
1707
+ },
1708
+ },
1709
+ sessionPlanQualityTrend: {
1710
+ status: 'improving',
1711
+ score: 3.4,
1712
+ confidence: 0.82,
1713
+ reason: 'Recent plan quality windows improved.',
1714
+ },
1715
+ memoryPolicyDiagnostics: {
1716
+ summary: {
1717
+ totalEntries: 48,
1718
+ expiredEntries: 0,
1719
+ staleEntries: 6,
1720
+ lowConfidenceEntries: 4,
1721
+ healthScore: 92.4,
1722
+ status: 'healthy',
1723
+ reason: 'Memory policy signals are within expected bounds.',
1724
+ },
1725
+ },
1726
+ memoryPolicyTrend: {
1727
+ status: 'improving',
1728
+ score: 4.1,
1729
+ confidence: 0.78,
1730
+ reason: 'Recent memory diagnostics windows improved.',
1731
+ },
1732
+ });
1733
+ const trendCheck = matrix.checks.find((check) => check.checkId === 'quality_trend_direction');
1734
+ const planQualityCheck = matrix.checks.find((check) => check.checkId === 'session_plan_quality_gate');
1735
+ const planQualityTrendCheck = matrix.checks.find((check) => check.checkId === 'session_plan_quality_trend');
1736
+ const memoryPolicyCheck = matrix.checks.find((check) => check.checkId === 'memory_policy_health');
1737
+ const memoryPolicyTrendCheck = matrix.checks.find((check) => check.checkId === 'memory_policy_trend');
1738
+ expect(trendCheck?.status).toBe('pass');
1739
+ expect(trendCheck?.expected).toBe('status in {stable, improving}');
1740
+ expect(planQualityCheck?.status).toBe('pass');
1741
+ expect(planQualityTrendCheck?.status).toBe('pass');
1742
+ expect(memoryPolicyCheck?.status).toBe('pass');
1743
+ expect(memoryPolicyTrendCheck?.status).toBe('pass');
1744
+ expect(matrix.signals.qualityTrendStatus).toBe('improving');
1745
+ expect(matrix.signals.qualityTrendScore).toBe(3.72);
1746
+ expect(matrix.signals.qualityTrendConfidence).toBe(0.84);
1747
+ expect(matrix.signals.sessionPlanQualityRecords).toBe(6);
1748
+ expect(matrix.signals.sessionPlanQualityPassRatePct).toBe(83.33);
1749
+ expect(matrix.signals.sessionPlanQualityFailureStreak).toBe(0);
1750
+ expect(matrix.signals.sessionPlanQualityTrendStatus).toBe('improving');
1751
+ expect(matrix.signals.sessionPlanQualityTrendScore).toBe(3.4);
1752
+ expect(matrix.signals.sessionPlanQualityTrendConfidence).toBe(0.82);
1753
+ expect(matrix.signals.memoryPolicyStatus).toBe('healthy');
1754
+ expect(matrix.signals.memoryPolicyHealthScore).toBe(92.4);
1755
+ expect(matrix.signals.memoryPolicyTotalEntries).toBe(48);
1756
+ expect(matrix.signals.memoryPolicyExpiredEntries).toBe(0);
1757
+ expect(matrix.signals.memoryPolicyStaleEntries).toBe(6);
1758
+ expect(matrix.signals.memoryPolicyLowConfidenceEntries).toBe(4);
1759
+ expect(matrix.signals.memoryPolicyTrendStatus).toBe('improving');
1760
+ expect(matrix.signals.memoryPolicyTrendScore).toBe(4.1);
1761
+ expect(matrix.signals.memoryPolicyTrendConfidence).toBe(0.78);
1762
+ expect(matrix.signals.topRiskCheckId).toBe('');
1763
+ expect(matrix.signals.topRiskStatus).toBe('none');
1764
+ expect(matrix.signals.topRiskPriorityScore).toBe(0);
1765
+ expect(matrix.signals.topRiskRecommendedActions).toEqual([]);
1766
+ expect(matrix.overallStatus).toBe('ready');
1767
+ });
1768
+ test('returns fail when quality trend is regressing', () => {
1769
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1770
+ generatedAt: '2026-04-01T12:00:00.000Z',
1771
+ configuredStoreBackend: 'file',
1772
+ configuredQueryBackend: 'local_hybrid',
1773
+ store: createStoreDiagnostics(),
1774
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1775
+ queryCount: 12,
1776
+ learningQualityTrend: {
1777
+ status: 'regressing',
1778
+ score: -4.11,
1779
+ confidence: 0.91,
1780
+ reason: 'Recent quality snapshots regressed.',
1781
+ },
1782
+ });
1783
+ const trendCheck = matrix.checks.find((check) => check.checkId === 'quality_trend_direction');
1784
+ expect(trendCheck?.status).toBe('fail');
1785
+ expect(trendCheck?.expected).toBe('status in {stable, improving}');
1786
+ expect(trendCheck?.recommendedActions).toEqual(expect.arrayContaining([
1787
+ expect.stringContaining('Trend status=regressing'),
1788
+ ]));
1789
+ expect(matrix.overallStatus).toBe('blocked');
1790
+ });
1791
+ test('returns warn when quality trend has insufficient data', () => {
1792
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1793
+ generatedAt: '2026-04-01T12:00:00.000Z',
1794
+ configuredStoreBackend: 'file',
1795
+ configuredQueryBackend: 'local_hybrid',
1796
+ store: createStoreDiagnostics(),
1797
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1798
+ queryCount: 12,
1799
+ learningQualityTrend: {
1800
+ status: 'insufficient_data',
1801
+ score: 0,
1802
+ confidence: 0,
1803
+ reason: 'Not enough quality snapshots to compare windows.',
1804
+ },
1805
+ });
1806
+ const trendCheck = matrix.checks.find((check) => check.checkId === 'quality_trend_direction');
1807
+ expect(trendCheck?.status).toBe('warn');
1808
+ expect(trendCheck?.expected).toBe('status in {stable, improving}');
1809
+ expect(matrix.overallStatus).toBe('degraded');
1810
+ });
1811
+ test('returns warn when session plan quality history is missing', () => {
1812
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1813
+ generatedAt: '2026-04-01T12:00:00.000Z',
1814
+ configuredStoreBackend: 'file',
1815
+ configuredQueryBackend: 'local_hybrid',
1816
+ store: createStoreDiagnostics(),
1817
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1818
+ queryCount: 16,
1819
+ learningQualityTrend: {
1820
+ status: 'stable',
1821
+ score: 0.12,
1822
+ confidence: 0.64,
1823
+ },
1824
+ });
1825
+ const sessionQualityCheck = matrix.checks.find((check) => check.checkId === 'session_plan_quality_gate');
1826
+ expect(sessionQualityCheck?.status).toBe('warn');
1827
+ expect(sessionQualityCheck?.expected).toBe('records>=1');
1828
+ expect(matrix.overallStatus).toBe('degraded');
1829
+ });
1830
+ test('returns fail when session plan quality gate has repeated failures', () => {
1831
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1832
+ generatedAt: '2026-04-01T12:00:00.000Z',
1833
+ configuredStoreBackend: 'file',
1834
+ configuredQueryBackend: 'local_hybrid',
1835
+ store: createStoreDiagnostics(),
1836
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1837
+ queryCount: 16,
1838
+ learningQualityTrend: {
1839
+ status: 'stable',
1840
+ score: 0.11,
1841
+ confidence: 0.7,
1842
+ },
1843
+ sessionPlanQualityHistory: {
1844
+ summary: {
1845
+ totalRecords: 8,
1846
+ overallPassRatePct: 37.5,
1847
+ consecutiveFailureCount: 3,
1848
+ commonFailedGates: [
1849
+ { gateId: 'policy_budget_alignment', count: 4 },
1850
+ { gateId: 'evidence_coverage_ratio', count: 3 },
1851
+ ],
1852
+ },
1853
+ },
1854
+ sessionPlanQualityTrend: {
1855
+ status: 'regressing',
1856
+ score: -4.6,
1857
+ confidence: 0.88,
1858
+ reason: 'Repeated gate failures increased in recent window.',
1859
+ },
1860
+ thresholds: {
1861
+ sessionPlanQualityWarnFailureStreak: 1,
1862
+ sessionPlanQualityFailFailureStreak: 2,
1863
+ },
1864
+ });
1865
+ const sessionQualityCheck = matrix.checks.find((check) => check.checkId === 'session_plan_quality_gate');
1866
+ const sessionQualityTrendCheck = matrix.checks.find((check) => check.checkId === 'session_plan_quality_trend');
1867
+ expect(sessionQualityCheck?.status).toBe('fail');
1868
+ expect(sessionQualityTrendCheck?.status).toBe('fail');
1869
+ expect(sessionQualityCheck?.expected).toBe('failureStreak<2');
1870
+ expect(sessionQualityCheck?.recommendedActions).toEqual(expect.arrayContaining([
1871
+ expect.stringContaining('failureStreak=3'),
1872
+ ]));
1873
+ expect(String(sessionQualityCheck?.observed || '')).toContain('failedGates=policy_budget_alignment:4|evidence_coverage_ratio:3');
1874
+ expect(matrix.signals.sessionPlanQualityFailureStreak).toBe(3);
1875
+ expect(matrix.signals.sessionPlanQualityTrendStatus).toBe('regressing');
1876
+ expect(matrix.overallStatus).toBe('blocked');
1877
+ });
1878
+ test('passes orchestration path-strategy alignment when trend-driven selections improve mastery', () => {
1879
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1880
+ generatedAt: '2026-04-01T12:00:00.000Z',
1881
+ configuredStoreBackend: 'file',
1882
+ configuredQueryBackend: 'local_hybrid',
1883
+ store: createStoreDiagnostics(),
1884
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1885
+ queryCount: 16,
1886
+ learningQualityTrend: {
1887
+ status: 'stable',
1888
+ score: 0.25,
1889
+ confidence: 0.72,
1890
+ },
1891
+ sessionPlanQualityHistory: {
1892
+ summary: {
1893
+ totalRecords: 6,
1894
+ overallPassRatePct: 84,
1895
+ consecutiveFailureCount: 0,
1896
+ commonFailedGates: [],
1897
+ },
1898
+ },
1899
+ sessionPlanQualityTrend: {
1900
+ status: 'stable',
1901
+ score: 0.19,
1902
+ confidence: 0.63,
1903
+ },
1904
+ memoryPolicyDiagnostics: {
1905
+ summary: {
1906
+ totalEntries: 18,
1907
+ expiredEntries: 0,
1908
+ staleEntries: 2,
1909
+ lowConfidenceEntries: 1,
1910
+ healthScore: 91,
1911
+ status: 'healthy',
1912
+ },
1913
+ },
1914
+ memoryPolicyTrend: {
1915
+ status: 'stable',
1916
+ score: 0.12,
1917
+ confidence: 0.58,
1918
+ },
1919
+ sessionStrategyTelemetry: {
1920
+ totalRecords: 12,
1921
+ strategyRecords: 10,
1922
+ trendAutoSelectionSharePct: 60,
1923
+ trendAutoAverageMasteryDeltaPct: 6.4,
1924
+ trendAutoNegativeRatioPct: 20,
1925
+ modeFallbackSelectionSharePct: 30,
1926
+ selectionSourceCounts: {
1927
+ explicit_request: 2,
1928
+ strategy_trend: 6,
1929
+ mode_fallback: 3,
1930
+ unknown: 1,
1931
+ },
1932
+ strategyBreakdown: [
1933
+ {
1934
+ strategy: 'balanced',
1935
+ executions: 4,
1936
+ averageMasteryDeltaPct: 2.3,
1937
+ positiveRatioPct: 75,
1938
+ negativeRatioPct: 25,
1939
+ },
1940
+ {
1941
+ strategy: 'mastery_recovery',
1942
+ executions: 5,
1943
+ averageMasteryDeltaPct: 6.8,
1944
+ positiveRatioPct: 80,
1945
+ negativeRatioPct: 20,
1946
+ },
1947
+ {
1948
+ strategy: 'exploration_boost',
1949
+ executions: 1,
1950
+ averageMasteryDeltaPct: -1.2,
1951
+ positiveRatioPct: 0,
1952
+ negativeRatioPct: 100,
1953
+ },
1954
+ ],
1955
+ },
1956
+ });
1957
+ const alignmentCheck = matrix.checks.find((check) => check.checkId === 'orchestration_path_strategy_alignment');
1958
+ expect(alignmentCheck?.status).toBe('pass');
1959
+ expect(String(alignmentCheck?.expected || '')).toContain('trendAutoAvgDelta>=0%');
1960
+ expect(Number(matrix.signals.sessionStrategyTrendAutoSelectionSharePct || 0)).toBeCloseTo(60, 4);
1961
+ expect(Number(matrix.signals.sessionStrategyTrendAutoAverageMasteryDeltaPct || 0)).toBeCloseTo(6.4, 4);
1962
+ expect(Number(matrix.signals.sessionStrategyTrendAutoNegativeRatioPct || 0)).toBeCloseTo(20, 4);
1963
+ expect(String(matrix.signals.sessionStrategyTopAverageStrategy || '')).toBe('mastery_recovery');
1964
+ });
1965
+ test('fails orchestration path-strategy alignment when trend-driven selections regress', () => {
1966
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
1967
+ generatedAt: '2026-04-01T12:00:00.000Z',
1968
+ configuredStoreBackend: 'file',
1969
+ configuredQueryBackend: 'local_hybrid',
1970
+ store: createStoreDiagnostics(),
1971
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
1972
+ queryCount: 16,
1973
+ learningQualityTrend: {
1974
+ status: 'stable',
1975
+ score: 0.16,
1976
+ confidence: 0.68,
1977
+ },
1978
+ sessionPlanQualityHistory: {
1979
+ summary: {
1980
+ totalRecords: 5,
1981
+ overallPassRatePct: 72,
1982
+ consecutiveFailureCount: 0,
1983
+ commonFailedGates: [],
1984
+ },
1985
+ },
1986
+ sessionPlanQualityTrend: {
1987
+ status: 'stable',
1988
+ score: 0.11,
1989
+ confidence: 0.61,
1990
+ },
1991
+ memoryPolicyDiagnostics: {
1992
+ summary: {
1993
+ totalEntries: 22,
1994
+ expiredEntries: 1,
1995
+ staleEntries: 3,
1996
+ lowConfidenceEntries: 2,
1997
+ healthScore: 87,
1998
+ status: 'healthy',
1999
+ },
2000
+ },
2001
+ memoryPolicyTrend: {
2002
+ status: 'stable',
2003
+ score: 0.09,
2004
+ confidence: 0.55,
2005
+ },
2006
+ sessionStrategyTelemetry: {
2007
+ totalRecords: 9,
2008
+ strategyRecords: 9,
2009
+ trendAutoSelectionSharePct: 66.6667,
2010
+ trendAutoAverageMasteryDeltaPct: -5.2,
2011
+ trendAutoNegativeRatioPct: 66.6667,
2012
+ modeFallbackSelectionSharePct: 22.2222,
2013
+ selectionSourceCounts: {
2014
+ explicit_request: 1,
2015
+ strategy_trend: 6,
2016
+ mode_fallback: 2,
2017
+ unknown: 0,
2018
+ },
2019
+ strategyBreakdown: [
2020
+ {
2021
+ strategy: 'balanced',
2022
+ executions: 3,
2023
+ averageMasteryDeltaPct: -3.1,
2024
+ positiveRatioPct: 33.3333,
2025
+ negativeRatioPct: 66.6667,
2026
+ },
2027
+ {
2028
+ strategy: 'mastery_recovery',
2029
+ executions: 4,
2030
+ averageMasteryDeltaPct: -6.2,
2031
+ positiveRatioPct: 25,
2032
+ negativeRatioPct: 75,
2033
+ },
2034
+ {
2035
+ strategy: 'exploration_boost',
2036
+ executions: 2,
2037
+ averageMasteryDeltaPct: -1.8,
2038
+ positiveRatioPct: 0,
2039
+ negativeRatioPct: 100,
2040
+ },
2041
+ ],
2042
+ },
2043
+ });
2044
+ const alignmentCheck = matrix.checks.find((check) => check.checkId === 'orchestration_path_strategy_alignment');
2045
+ expect(alignmentCheck?.status).toBe('fail');
2046
+ expect(String(alignmentCheck?.observed || '')).toContain('trendAutoAvgDelta=-5.2%');
2047
+ expect(String(alignmentCheck?.observed || '')).toContain('trendAutoNegative=66.6667%');
2048
+ expect(alignmentCheck?.recommendedActions).toEqual(expect.arrayContaining([
2049
+ expect.stringContaining('/api/knowledge/session/history'),
2050
+ ]));
2051
+ });
2052
+ test('returns fail when memory policy diagnostics report risk status', () => {
2053
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2054
+ generatedAt: '2026-04-01T12:00:00.000Z',
2055
+ configuredStoreBackend: 'file',
2056
+ configuredQueryBackend: 'local_hybrid',
2057
+ store: createStoreDiagnostics(),
2058
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2059
+ queryCount: 16,
2060
+ learningQualityTrend: {
2061
+ status: 'stable',
2062
+ score: 0.08,
2063
+ confidence: 0.64,
2064
+ },
2065
+ sessionPlanQualityHistory: {
2066
+ summary: {
2067
+ totalRecords: 4,
2068
+ overallPassRatePct: 75,
2069
+ consecutiveFailureCount: 0,
2070
+ commonFailedGates: [],
2071
+ },
2072
+ },
2073
+ sessionPlanQualityTrend: {
2074
+ status: 'stable',
2075
+ score: 0.22,
2076
+ confidence: 0.56,
2077
+ },
2078
+ memoryPolicyDiagnostics: {
2079
+ summary: {
2080
+ totalEntries: 120,
2081
+ expiredEntries: 34,
2082
+ staleEntries: 70,
2083
+ lowConfidenceEntries: 82,
2084
+ healthScore: 28.7,
2085
+ status: 'risk',
2086
+ reason: 'Memory policy risk detected.',
2087
+ },
2088
+ },
2089
+ memoryPolicyTrend: {
2090
+ status: 'regressing',
2091
+ score: -5.2,
2092
+ confidence: 0.82,
2093
+ reason: 'Recent windows regressed with rising expired/stale ratios.',
2094
+ },
2095
+ });
2096
+ const memoryPolicyCheck = matrix.checks.find((check) => check.checkId === 'memory_policy_health');
2097
+ const memoryPolicyTrendCheck = matrix.checks.find((check) => check.checkId === 'memory_policy_trend');
2098
+ expect(memoryPolicyCheck?.status).toBe('fail');
2099
+ expect(memoryPolicyTrendCheck?.status).toBe('fail');
2100
+ expect(memoryPolicyCheck?.recommendedActions).toEqual(expect.arrayContaining([
2101
+ expect.stringContaining('Memory status=risk'),
2102
+ ]));
2103
+ expect(matrix.signals.memoryPolicyStatus).toBe('risk');
2104
+ expect(matrix.signals.memoryPolicyExpiredEntries).toBe(34);
2105
+ expect(matrix.signals.memoryPolicyStaleEntries).toBe(70);
2106
+ expect(matrix.signals.memoryPolicyLowConfidenceEntries).toBe(82);
2107
+ expect(matrix.signals.memoryPolicyTrendStatus).toBe('regressing');
2108
+ expect(matrix.overallStatus).toBe('blocked');
2109
+ });
2110
+ test('returns pass when knowledge staleness diagnostics are healthy', () => {
2111
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2112
+ generatedAt: '2026-04-01T12:00:00.000Z',
2113
+ configuredStoreBackend: 'file',
2114
+ configuredQueryBackend: 'local_hybrid',
2115
+ store: createStoreDiagnostics(),
2116
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2117
+ queryCount: 16,
2118
+ knowledgeStalenessDiagnostics: {
2119
+ summary: {
2120
+ totalDocuments: 12,
2121
+ evaluatedDocuments: 12,
2122
+ returnedRecords: 6,
2123
+ upToDateDocuments: 12,
2124
+ hashMismatchDocuments: 0,
2125
+ missingSourceDocuments: 0,
2126
+ readErrorDocuments: 0,
2127
+ staleDocuments: 0,
2128
+ freshnessRatioPct: 100,
2129
+ staleRatioPct: 0,
2130
+ reason: 'All documents are up-to-date.',
2131
+ },
2132
+ },
2133
+ });
2134
+ const dataCheck = matrix.checks.find((check) => check.checkId === 'knowledge_staleness_data');
2135
+ const healthCheck = matrix.checks.find((check) => check.checkId === 'knowledge_staleness_health');
2136
+ expect(dataCheck?.status).toBe('pass');
2137
+ expect(healthCheck?.status).toBe('pass');
2138
+ expect(matrix.signals.knowledgeStalenessStaleDocuments).toBe(0);
2139
+ expect(matrix.signals.knowledgeStalenessFreshnessRatioPct).toBe(100);
2140
+ expect(matrix.signals.knowledgeStalenessHashMismatchDocuments).toBe(0);
2141
+ expect(matrix.signals.knowledgeStalenessMissingSourceDocuments).toBe(0);
2142
+ expect(matrix.signals.knowledgeStalenessReadErrorDocuments).toBe(0);
2143
+ });
2144
+ test('returns warn when knowledge staleness diagnostics include non-severe stale documents', () => {
2145
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2146
+ generatedAt: '2026-04-01T12:00:00.000Z',
2147
+ configuredStoreBackend: 'file',
2148
+ configuredQueryBackend: 'local_hybrid',
2149
+ store: createStoreDiagnostics(),
2150
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2151
+ queryCount: 16,
2152
+ knowledgeStalenessDiagnostics: {
2153
+ summary: {
2154
+ totalDocuments: 10,
2155
+ evaluatedDocuments: 10,
2156
+ returnedRecords: 6,
2157
+ upToDateDocuments: 8,
2158
+ hashMismatchDocuments: 2,
2159
+ missingSourceDocuments: 0,
2160
+ readErrorDocuments: 0,
2161
+ staleDocuments: 2,
2162
+ freshnessRatioPct: 80,
2163
+ staleRatioPct: 20,
2164
+ reason: 'Two documents require refresh.',
2165
+ },
2166
+ },
2167
+ });
2168
+ const healthCheck = matrix.checks.find((check) => check.checkId === 'knowledge_staleness_health');
2169
+ expect(healthCheck?.status).toBe('warn');
2170
+ expect(matrix.signals.knowledgeStalenessStaleDocuments).toBe(2);
2171
+ expect(matrix.signals.knowledgeStalenessHashMismatchDocuments).toBe(2);
2172
+ expect(matrix.overallStatus).toBe('degraded');
2173
+ });
2174
+ test('returns fail when knowledge staleness diagnostics report read errors', () => {
2175
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2176
+ generatedAt: '2026-04-01T12:00:00.000Z',
2177
+ configuredStoreBackend: 'file',
2178
+ configuredQueryBackend: 'local_hybrid',
2179
+ store: createStoreDiagnostics(),
2180
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2181
+ queryCount: 16,
2182
+ knowledgeStalenessDiagnostics: {
2183
+ summary: {
2184
+ totalDocuments: 10,
2185
+ evaluatedDocuments: 10,
2186
+ returnedRecords: 6,
2187
+ upToDateDocuments: 5,
2188
+ hashMismatchDocuments: 3,
2189
+ missingSourceDocuments: 1,
2190
+ readErrorDocuments: 1,
2191
+ staleDocuments: 5,
2192
+ freshnessRatioPct: 50,
2193
+ staleRatioPct: 50,
2194
+ reason: 'Read errors detected for source probes.',
2195
+ },
2196
+ },
2197
+ });
2198
+ const healthCheck = matrix.checks.find((check) => check.checkId === 'knowledge_staleness_health');
2199
+ expect(healthCheck?.status).toBe('fail');
2200
+ expect(healthCheck?.recommendedActions).toEqual(expect.arrayContaining([
2201
+ expect.stringContaining('readError=1'),
2202
+ ]));
2203
+ expect(matrix.signals.knowledgeStalenessReadErrorDocuments).toBe(1);
2204
+ expect(matrix.overallStatus).toBe('blocked');
2205
+ });
2206
+ test('returns pass when tutor routing telemetry is within configured health budgets', () => {
2207
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2208
+ generatedAt: '2026-04-01T12:00:00.000Z',
2209
+ configuredStoreBackend: 'file',
2210
+ configuredQueryBackend: 'local_hybrid',
2211
+ store: createStoreDiagnostics(),
2212
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2213
+ queryCount: 16,
2214
+ learningQualityTrend: {
2215
+ status: 'stable',
2216
+ score: 0.41,
2217
+ confidence: 0.72,
2218
+ },
2219
+ sessionPlanQualityHistory: {
2220
+ summary: {
2221
+ totalRecords: 6,
2222
+ overallPassRatePct: 83.3,
2223
+ consecutiveFailureCount: 0,
2224
+ commonFailedGates: [],
2225
+ },
2226
+ },
2227
+ sessionPlanQualityTrend: {
2228
+ status: 'stable',
2229
+ score: 0.26,
2230
+ confidence: 0.68,
2231
+ },
2232
+ memoryPolicyDiagnostics: {
2233
+ summary: {
2234
+ totalEntries: 28,
2235
+ expiredEntries: 1,
2236
+ staleEntries: 3,
2237
+ lowConfidenceEntries: 2,
2238
+ healthScore: 90.2,
2239
+ status: 'healthy',
2240
+ },
2241
+ },
2242
+ memoryPolicyTrend: {
2243
+ status: 'stable',
2244
+ score: 0.19,
2245
+ confidence: 0.61,
2246
+ },
2247
+ tutorAdapterTelemetry: {
2248
+ summary: {
2249
+ totalAdapters: 2,
2250
+ activeAdapters: 2,
2251
+ totalRequests: 24,
2252
+ successfulResponses: 23,
2253
+ acceptedResponses: 19,
2254
+ downgradedResponses: 4,
2255
+ failedResponses: 1,
2256
+ providerFallbackResponses: 5,
2257
+ providerFallbackRatioPct: 20.8333,
2258
+ averageProviderAttemptCount: 1.22,
2259
+ averageConfidence: 0.84,
2260
+ lastRoutingStrategy: 'adaptive_health_routing',
2261
+ lastRoutingReason: 'Adaptive routing selected cloud-adapter based on healthier telemetry score.',
2262
+ lastRoutingScore: 0.93,
2263
+ lastRoutingDynamicPreferredMode: 'cloud',
2264
+ lastRoutingDynamicModeReason: 'prefer cloud due to local trend penalty=0.140 and cloud penalty=0.000',
2265
+ },
2266
+ },
2267
+ tutorRoutingConfig: {
2268
+ enabled: true,
2269
+ minSamples: 6,
2270
+ maxFailedRatioPct: 20,
2271
+ maxDowngradedRatioPct: 35,
2272
+ minAverageConfidence: 0.7,
2273
+ preferredMode: 'cloud',
2274
+ adapterTimeoutMs: 18000,
2275
+ },
2276
+ });
2277
+ const inventoryCheck = matrix.checks.find((check) => check.checkId === 'tutor_adapter_inventory');
2278
+ const timeoutBudgetCheck = matrix.checks.find((check) => check.checkId === 'tutor_adapter_timeout_budget');
2279
+ const budgetCheck = matrix.checks.find((check) => check.checkId === 'tutor_routing_health_budget');
2280
+ const traceabilityCheck = matrix.checks.find((check) => check.checkId === 'tutor_routing_traceability');
2281
+ const dynamicAlignmentCheck = matrix.checks.find((check) => check.checkId === 'tutor_routing_dynamic_mode_alignment');
2282
+ expect(inventoryCheck?.status).toBe('pass');
2283
+ expect(timeoutBudgetCheck?.status).toBe('pass');
2284
+ expect(budgetCheck?.status).toBe('pass');
2285
+ expect(traceabilityCheck?.status).toBe('pass');
2286
+ expect(dynamicAlignmentCheck?.status).toBe('pass');
2287
+ expect(matrix.signals.tutorAdaptersTotal).toBe(2);
2288
+ expect(matrix.signals.tutorAdaptersActive).toBe(2);
2289
+ expect(matrix.signals.tutorRequests).toBe(24);
2290
+ expect(matrix.signals.tutorFailedRatioPct).toBeCloseTo(4.1667, 3);
2291
+ expect(matrix.signals.tutorDowngradedRatioPct).toBeCloseTo(16.6667, 3);
2292
+ expect(matrix.signals.tutorProviderFallbackResponses).toBe(5);
2293
+ expect(matrix.signals.tutorProviderFallbackRatioPct).toBeCloseTo(20.8333, 3);
2294
+ expect(matrix.signals.tutorAverageProviderAttemptCount).toBe(1.22);
2295
+ expect(matrix.signals.tutorAverageConfidence).toBe(0.84);
2296
+ expect(matrix.signals.tutorRoutingEnabled).toBe(true);
2297
+ expect(matrix.signals.tutorRoutingPreferredMode).toBe('cloud');
2298
+ expect(matrix.signals.tutorRoutingAdapterTimeoutMs).toBe(18000);
2299
+ expect(matrix.signals.tutorLastRoutingStrategy).toBe('adaptive_health_routing');
2300
+ expect(matrix.signals.tutorLastRoutingReason).toContain('cloud-adapter');
2301
+ expect(matrix.signals.tutorLastRoutingScore).toBe(0.93);
2302
+ expect(matrix.signals.tutorRoutingDynamicPreferredMode).toBe('cloud');
2303
+ expect(matrix.signals.tutorRoutingDynamicModeSuggestionActive).toBe(true);
2304
+ expect(matrix.signals.tutorRoutingDynamicModeReason).toContain('prefer cloud due to local trend penalty=0.140');
2305
+ expect(matrix.overallStatus).toBe('ready');
2306
+ });
2307
+ test('warns when dynamic mode suggestion conflicts with pinned preferred mode', () => {
2308
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2309
+ generatedAt: '2026-04-01T12:00:00.000Z',
2310
+ configuredStoreBackend: 'file',
2311
+ configuredQueryBackend: 'local_hybrid',
2312
+ store: createStoreDiagnostics(),
2313
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2314
+ queryCount: 18,
2315
+ tutorAdapterTelemetry: {
2316
+ summary: {
2317
+ totalAdapters: 2,
2318
+ activeAdapters: 2,
2319
+ totalRequests: 18,
2320
+ successfulResponses: 17,
2321
+ acceptedResponses: 14,
2322
+ downgradedResponses: 3,
2323
+ failedResponses: 1,
2324
+ providerFallbackResponses: 2,
2325
+ providerFallbackRatioPct: 11.11,
2326
+ averageProviderAttemptCount: 1.2,
2327
+ averageConfidence: 0.83,
2328
+ lastRoutingStrategy: 'adaptive_health_routing',
2329
+ lastRoutingReason: 'Adaptive routing selected cloud-adapter.',
2330
+ lastRoutingScore: 0.87,
2331
+ lastRoutingDynamicPreferredMode: 'cloud',
2332
+ lastRoutingDynamicModeReason: 'prefer cloud due to local trend penalty=0.180 and cloud penalty=0.000',
2333
+ },
2334
+ },
2335
+ tutorRoutingConfig: {
2336
+ enabled: true,
2337
+ minSamples: 6,
2338
+ maxFailedRatioPct: 20,
2339
+ maxDowngradedRatioPct: 35,
2340
+ minAverageConfidence: 0.7,
2341
+ preferredMode: 'local',
2342
+ adapterTimeoutMs: 18000,
2343
+ },
2344
+ });
2345
+ const dynamicAlignmentCheck = matrix.checks.find((check) => check.checkId === 'tutor_routing_dynamic_mode_alignment');
2346
+ expect(dynamicAlignmentCheck?.status).toBe('warn');
2347
+ expect(String(dynamicAlignmentCheck?.observed || '')).toContain('preferredMode=local');
2348
+ expect(String(dynamicAlignmentCheck?.observed || '')).toContain('dynamicMode=cloud');
2349
+ expect(String(dynamicAlignmentCheck?.expected || '')).toContain('preferredMode=auto or preferredMode=cloud');
2350
+ });
2351
+ test('fails when dynamic mode suggestion conflicts with pinned preferred mode under severe degradation', () => {
2352
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2353
+ generatedAt: '2026-04-01T12:00:00.000Z',
2354
+ configuredStoreBackend: 'file',
2355
+ configuredQueryBackend: 'local_hybrid',
2356
+ store: createStoreDiagnostics(),
2357
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2358
+ queryCount: 18,
2359
+ tutorAdapterTelemetry: {
2360
+ summary: {
2361
+ totalAdapters: 2,
2362
+ activeAdapters: 2,
2363
+ totalRequests: 20,
2364
+ successfulResponses: 8,
2365
+ acceptedResponses: 5,
2366
+ downgradedResponses: 3,
2367
+ failedResponses: 12,
2368
+ providerFallbackResponses: 17,
2369
+ providerFallbackRatioPct: 85,
2370
+ averageProviderAttemptCount: 3.7,
2371
+ averageConfidence: 0.42,
2372
+ lastRoutingStrategy: 'adaptive_health_routing',
2373
+ lastRoutingReason: 'Adaptive routing remained pinned to local mode despite cloud suggestion.',
2374
+ lastRoutingScore: 0.24,
2375
+ lastRoutingDynamicPreferredMode: 'cloud',
2376
+ lastRoutingDynamicModeReason: 'prefer cloud due to local trend penalty=0.250 and cloud penalty=0.000',
2377
+ },
2378
+ },
2379
+ tutorRoutingConfig: {
2380
+ enabled: true,
2381
+ minSamples: 6,
2382
+ maxFailedRatioPct: 25,
2383
+ maxDowngradedRatioPct: 35,
2384
+ minAverageConfidence: 0.7,
2385
+ preferredMode: 'local',
2386
+ adapterTimeoutMs: 18000,
2387
+ },
2388
+ });
2389
+ const dynamicAlignmentCheck = matrix.checks.find((check) => check.checkId === 'tutor_routing_dynamic_mode_alignment');
2390
+ expect(dynamicAlignmentCheck?.status).toBe('fail');
2391
+ expect(String(dynamicAlignmentCheck?.observed || '')).toContain('preferredMode=local');
2392
+ expect(String(dynamicAlignmentCheck?.observed || '')).toContain('dynamicMode=cloud');
2393
+ expect(String(dynamicAlignmentCheck?.expected || '')).toContain('preferredMode=auto or preferredMode=cloud');
2394
+ expect(dynamicAlignmentCheck?.recommendedActions).toEqual(expect.arrayContaining([
2395
+ expect.stringContaining('dynamicMode=cloud'),
2396
+ ]));
2397
+ });
2398
+ test('returns fail when tutor routing telemetry exceeds hard budgets', () => {
2399
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2400
+ generatedAt: '2026-04-01T12:00:00.000Z',
2401
+ configuredStoreBackend: 'file',
2402
+ configuredQueryBackend: 'local_hybrid',
2403
+ store: createStoreDiagnostics(),
2404
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2405
+ queryCount: 16,
2406
+ learningQualityTrend: {
2407
+ status: 'stable',
2408
+ score: 0.21,
2409
+ confidence: 0.67,
2410
+ },
2411
+ sessionPlanQualityHistory: {
2412
+ summary: {
2413
+ totalRecords: 4,
2414
+ overallPassRatePct: 75,
2415
+ consecutiveFailureCount: 0,
2416
+ commonFailedGates: [],
2417
+ },
2418
+ },
2419
+ sessionPlanQualityTrend: {
2420
+ status: 'stable',
2421
+ score: 0.18,
2422
+ confidence: 0.62,
2423
+ },
2424
+ memoryPolicyDiagnostics: {
2425
+ summary: {
2426
+ totalEntries: 12,
2427
+ expiredEntries: 0,
2428
+ staleEntries: 1,
2429
+ lowConfidenceEntries: 1,
2430
+ healthScore: 94,
2431
+ status: 'healthy',
2432
+ },
2433
+ },
2434
+ memoryPolicyTrend: {
2435
+ status: 'stable',
2436
+ score: 0.11,
2437
+ confidence: 0.57,
2438
+ },
2439
+ tutorAdapterTelemetry: {
2440
+ summary: {
2441
+ totalAdapters: 2,
2442
+ activeAdapters: 1,
2443
+ totalRequests: 20,
2444
+ successfulResponses: 12,
2445
+ acceptedResponses: 4,
2446
+ downgradedResponses: 8,
2447
+ failedResponses: 8,
2448
+ averageConfidence: 0.43,
2449
+ },
2450
+ },
2451
+ tutorRoutingConfig: {
2452
+ enabled: true,
2453
+ minSamples: 6,
2454
+ maxFailedRatioPct: 30,
2455
+ maxDowngradedRatioPct: 35,
2456
+ minAverageConfidence: 0.7,
2457
+ preferredMode: 'auto',
2458
+ adapterTimeoutMs: 18000,
2459
+ },
2460
+ });
2461
+ const budgetCheck = matrix.checks.find((check) => check.checkId === 'tutor_routing_health_budget');
2462
+ expect(budgetCheck?.status).toBe('fail');
2463
+ expect(String(budgetCheck?.expected || '')).toContain('failedRatio<=30%');
2464
+ expect(String(budgetCheck?.expected || '')).toContain('downgradedRatio<=35%');
2465
+ expect(String(budgetCheck?.expected || '')).toContain('avgConfidence>=0.5');
2466
+ expect(budgetCheck?.recommendedActions).toEqual(expect.arrayContaining([
2467
+ expect.stringContaining('fail=40%'),
2468
+ ]));
2469
+ expect(matrix.signals.tutorFailedRatioPct).toBe(40);
2470
+ expect(matrix.signals.tutorDowngradedRatioPct).toBe(40);
2471
+ expect(matrix.signals.tutorAverageConfidence).toBe(0.43);
2472
+ expect(matrix.overallStatus).toBe('blocked');
2473
+ });
2474
+ test('returns warn when tutor fallback traffic is concentrated on a single provider', () => {
2475
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2476
+ generatedAt: '2026-04-01T12:00:00.000Z',
2477
+ configuredStoreBackend: 'file',
2478
+ configuredQueryBackend: 'local_hybrid',
2479
+ store: createStoreDiagnostics(),
2480
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2481
+ queryCount: 20,
2482
+ tutorAdapterTelemetry: {
2483
+ summary: {
2484
+ totalAdapters: 2,
2485
+ activeAdapters: 2,
2486
+ totalRequests: 30,
2487
+ successfulResponses: 28,
2488
+ acceptedResponses: 22,
2489
+ downgradedResponses: 6,
2490
+ failedResponses: 2,
2491
+ providerFallbackResponses: 12,
2492
+ providerFallbackRatioPct: 40,
2493
+ averageProviderAttemptCount: 1.7,
2494
+ averageConfidence: 0.81,
2495
+ lastRoutingStrategy: 'adaptive_health_routing',
2496
+ lastRoutingScore: 0.79,
2497
+ },
2498
+ },
2499
+ tutorTraceDiagnostics: {
2500
+ summary: {
2501
+ matchedTraces: 30,
2502
+ llmAdapterTraces: 30,
2503
+ fallbackTraces: 12,
2504
+ fallbackRatioPct: 40,
2505
+ averageProviderAttemptCount: 1.7,
2506
+ },
2507
+ providerBreakdown: [
2508
+ {
2509
+ providerName: 'LMStudio',
2510
+ traces: 18,
2511
+ fallbackTraces: 11,
2512
+ failedTraces: 1,
2513
+ averageConfidence: 0.84,
2514
+ averageProviderAttemptCount: 1.8,
2515
+ },
2516
+ {
2517
+ providerName: 'DeepSeek',
2518
+ traces: 12,
2519
+ fallbackTraces: 1,
2520
+ failedTraces: 1,
2521
+ averageConfidence: 0.76,
2522
+ averageProviderAttemptCount: 1.5,
2523
+ },
2524
+ ],
2525
+ },
2526
+ tutorRoutingConfig: {
2527
+ enabled: true,
2528
+ minSamples: 6,
2529
+ maxFailedRatioPct: 30,
2530
+ maxDowngradedRatioPct: 40,
2531
+ minAverageConfidence: 0.7,
2532
+ preferredMode: 'auto',
2533
+ adapterTimeoutMs: 18000,
2534
+ },
2535
+ });
2536
+ const concentrationCheck = matrix.checks.find((check) => check.checkId === 'tutor_provider_concentration');
2537
+ expect(concentrationCheck?.status).toBe('warn');
2538
+ expect(String(concentrationCheck?.expected || '')).toContain('dominantFallbackProviderShare<80%');
2539
+ expect(matrix.signals.tutorProviderCount).toBe(2);
2540
+ expect(matrix.signals.tutorDominantProviderName).toBe('LMStudio');
2541
+ expect(matrix.signals.tutorDominantProviderSharePct).toBe(60);
2542
+ expect(matrix.signals.tutorDominantFallbackProviderName).toBe('LMStudio');
2543
+ expect(matrix.signals.tutorDominantFallbackProviderSharePct).toBeCloseTo(91.6667, 3);
2544
+ expect(matrix.overallStatus).toBe('degraded');
2545
+ });
2546
+ test('returns fail when tutor provider trend diagnostics detect high-confidence regression', () => {
2547
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2548
+ generatedAt: '2026-04-01T12:00:00.000Z',
2549
+ configuredStoreBackend: 'file',
2550
+ configuredQueryBackend: 'local_hybrid',
2551
+ store: createStoreDiagnostics(),
2552
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2553
+ queryCount: 22,
2554
+ tutorAdapterTelemetry: {
2555
+ summary: {
2556
+ totalAdapters: 2,
2557
+ activeAdapters: 2,
2558
+ totalRequests: 24,
2559
+ successfulResponses: 21,
2560
+ acceptedResponses: 17,
2561
+ downgradedResponses: 4,
2562
+ failedResponses: 3,
2563
+ providerFallbackResponses: 12,
2564
+ providerFallbackRatioPct: 50,
2565
+ averageProviderAttemptCount: 1.9,
2566
+ averageConfidence: 0.71,
2567
+ lastRoutingStrategy: 'adaptive_health_routing',
2568
+ lastRoutingScore: 0.66,
2569
+ },
2570
+ },
2571
+ tutorTraceDiagnostics: {
2572
+ summary: {
2573
+ matchedTraces: 24,
2574
+ llmAdapterTraces: 24,
2575
+ fallbackTraces: 12,
2576
+ fallbackRatioPct: 50,
2577
+ averageProviderAttemptCount: 1.9,
2578
+ },
2579
+ providerBreakdown: [
2580
+ {
2581
+ providerName: 'LMStudio',
2582
+ traces: 14,
2583
+ fallbackTraces: 9,
2584
+ failedTraces: 2,
2585
+ },
2586
+ {
2587
+ providerName: 'DeepSeek',
2588
+ traces: 10,
2589
+ fallbackTraces: 3,
2590
+ failedTraces: 1,
2591
+ },
2592
+ ],
2593
+ },
2594
+ tutorProviderTrendDiagnostics: {
2595
+ summary: {
2596
+ totalProviders: 2,
2597
+ evaluatedProviders: 2,
2598
+ returnedProviders: 2,
2599
+ regressingProviders: 1,
2600
+ stableProviders: 1,
2601
+ improvingProviders: 0,
2602
+ insufficientDataProviders: 0,
2603
+ recommendedFocusProviderName: 'LMStudio',
2604
+ recommendedFocusReason: 'regressing_trend_score_36.50',
2605
+ },
2606
+ providers: [
2607
+ {
2608
+ providerName: 'LMStudio',
2609
+ trendStatus: 'regressing',
2610
+ trendScore: 36.5,
2611
+ trendConfidence: 78,
2612
+ fallbackRatioPct: 72,
2613
+ failedRatioPct: 28,
2614
+ },
2615
+ {
2616
+ providerName: 'DeepSeek',
2617
+ trendStatus: 'stable',
2618
+ trendScore: 6.2,
2619
+ trendConfidence: 52,
2620
+ fallbackRatioPct: 33,
2621
+ failedRatioPct: 10,
2622
+ },
2623
+ ],
2624
+ },
2625
+ tutorRoutingConfig: {
2626
+ enabled: true,
2627
+ minSamples: 6,
2628
+ maxFailedRatioPct: 30,
2629
+ maxDowngradedRatioPct: 40,
2630
+ minAverageConfidence: 0.7,
2631
+ preferredMode: 'auto',
2632
+ adapterTimeoutMs: 18000,
2633
+ },
2634
+ });
2635
+ const trendCheck = matrix.checks.find((check) => check.checkId === 'tutor_provider_trend_regression');
2636
+ expect(trendCheck?.status).toBe('fail');
2637
+ expect(String(trendCheck?.expected || '')).toContain('regressingProviders=0');
2638
+ expect(matrix.signals.tutorProviderTrendRegressingCount).toBe(1);
2639
+ expect(matrix.signals.tutorProviderTrendTopRegressingProvider).toBe('LMStudio');
2640
+ expect(matrix.signals.tutorProviderTrendTopRegressingScore).toBe(36.5);
2641
+ expect(matrix.signals.tutorProviderTrendTopRegressingConfidence).toBe(78);
2642
+ expect(matrix.signals.tutorProviderTrendRecommendedFocusProviderName).toBe('LMStudio');
2643
+ expect(matrix.overallStatus).toBe('blocked');
2644
+ });
2645
+ test('returns fail when tutor provider trend history shows persistent regression windows', () => {
2646
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2647
+ generatedAt: '2026-04-01T12:00:00.000Z',
2648
+ configuredStoreBackend: 'file',
2649
+ configuredQueryBackend: 'local_hybrid',
2650
+ store: createStoreDiagnostics(),
2651
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2652
+ queryCount: 24,
2653
+ tutorAdapterTelemetry: {
2654
+ summary: {
2655
+ totalAdapters: 2,
2656
+ activeAdapters: 2,
2657
+ totalRequests: 24,
2658
+ successfulResponses: 21,
2659
+ acceptedResponses: 18,
2660
+ downgradedResponses: 3,
2661
+ failedResponses: 3,
2662
+ providerFallbackResponses: 10,
2663
+ providerFallbackRatioPct: 41.67,
2664
+ averageProviderAttemptCount: 1.8,
2665
+ averageConfidence: 0.78,
2666
+ lastRoutingStrategy: 'adaptive_health_routing',
2667
+ lastRoutingScore: 0.7,
2668
+ },
2669
+ },
2670
+ tutorProviderTrendDiagnostics: {
2671
+ summary: {
2672
+ totalProviders: 2,
2673
+ evaluatedProviders: 2,
2674
+ returnedProviders: 2,
2675
+ regressingProviders: 0,
2676
+ stableProviders: 2,
2677
+ improvingProviders: 0,
2678
+ insufficientDataProviders: 0,
2679
+ recommendedFocusProviderName: 'LMStudio',
2680
+ },
2681
+ providers: [
2682
+ { providerName: 'LMStudio', trendStatus: 'stable', trendScore: 8, trendConfidence: 55 },
2683
+ { providerName: 'DeepSeek', trendStatus: 'stable', trendScore: 4, trendConfidence: 50 },
2684
+ ],
2685
+ },
2686
+ tutorProviderTrendHistory: {
2687
+ summary: {
2688
+ totalProviders: 2,
2689
+ evaluatedProviders: 2,
2690
+ totalRecords: 6,
2691
+ returnedRecords: 6,
2692
+ regressingRecords: 3,
2693
+ stableRecords: 2,
2694
+ improvingRecords: 1,
2695
+ insufficientDataRecords: 0,
2696
+ recommendedFocusProviderName: 'LMStudio',
2697
+ },
2698
+ records: [
2699
+ { providerName: 'LMStudio', windowIndex: 0, trendStatus: 'regressing', trendScore: 28, trendConfidence: 72 },
2700
+ { providerName: 'LMStudio', windowIndex: 1, trendStatus: 'regressing', trendScore: 22, trendConfidence: 68 },
2701
+ { providerName: 'LMStudio', windowIndex: 2, trendStatus: 'regressing', trendScore: 19, trendConfidence: 60 },
2702
+ { providerName: 'DeepSeek', windowIndex: 0, trendStatus: 'stable', trendScore: 7, trendConfidence: 49 },
2703
+ { providerName: 'DeepSeek', windowIndex: 1, trendStatus: 'stable', trendScore: 4, trendConfidence: 43 },
2704
+ { providerName: 'DeepSeek', windowIndex: 2, trendStatus: 'improving', trendScore: -15, trendConfidence: 61 },
2705
+ ],
2706
+ },
2707
+ tutorRoutingConfig: {
2708
+ enabled: true,
2709
+ minSamples: 6,
2710
+ maxFailedRatioPct: 30,
2711
+ maxDowngradedRatioPct: 40,
2712
+ minAverageConfidence: 0.7,
2713
+ preferredMode: 'auto',
2714
+ adapterTimeoutMs: 18000,
2715
+ },
2716
+ });
2717
+ const trendCheck = matrix.checks.find((check) => check.checkId === 'tutor_provider_trend_regression');
2718
+ expect(trendCheck?.status).toBe('fail');
2719
+ expect(String(trendCheck?.observed || '')).toContain('historyRegressing=3');
2720
+ expect(matrix.signals.tutorProviderTrendHistoryRecords).toBe(6);
2721
+ expect(matrix.signals.tutorProviderTrendHistoryRegressingRecords).toBe(3);
2722
+ expect(matrix.signals.tutorProviderTrendHistoryStableRecords).toBe(2);
2723
+ expect(matrix.signals.tutorProviderTrendHistoryImprovingRecords).toBe(1);
2724
+ expect(matrix.overallStatus).toBe('blocked');
2725
+ });
2726
+ test('returns warn when tutor provider fallback ratio stays high despite low hard-failure ratios', () => {
2727
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2728
+ generatedAt: '2026-04-01T12:00:00.000Z',
2729
+ configuredStoreBackend: 'file',
2730
+ configuredQueryBackend: 'local_hybrid',
2731
+ store: createStoreDiagnostics(),
2732
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2733
+ queryCount: 16,
2734
+ tutorAdapterTelemetry: {
2735
+ summary: {
2736
+ totalAdapters: 2,
2737
+ activeAdapters: 2,
2738
+ totalRequests: 20,
2739
+ successfulResponses: 19,
2740
+ acceptedResponses: 17,
2741
+ downgradedResponses: 2,
2742
+ failedResponses: 1,
2743
+ providerFallbackResponses: 15,
2744
+ providerFallbackRatioPct: 75,
2745
+ averageProviderAttemptCount: 2.3,
2746
+ averageConfidence: 0.85,
2747
+ lastRoutingStrategy: 'adaptive_health_routing',
2748
+ lastRoutingReason: 'Adaptive routing kept cloud-adapter primary; frequent provider fallback still observed.',
2749
+ lastRoutingScore: 0.82,
2750
+ },
2751
+ },
2752
+ tutorRoutingConfig: {
2753
+ enabled: true,
2754
+ minSamples: 6,
2755
+ maxFailedRatioPct: 30,
2756
+ maxDowngradedRatioPct: 40,
2757
+ minAverageConfidence: 0.7,
2758
+ preferredMode: 'auto',
2759
+ adapterTimeoutMs: 18000,
2760
+ },
2761
+ });
2762
+ const budgetCheck = matrix.checks.find((check) => check.checkId === 'tutor_routing_health_budget');
2763
+ expect(budgetCheck?.status).toBe('warn');
2764
+ expect(String(budgetCheck?.expected || '')).toContain('fallbackRatio<=60%');
2765
+ expect(String(budgetCheck?.expected || '')).toContain('avgProviderAttempts<2');
2766
+ expect(matrix.signals.tutorProviderFallbackResponses).toBe(15);
2767
+ expect(matrix.signals.tutorProviderFallbackRatioPct).toBe(75);
2768
+ expect(matrix.signals.tutorAverageProviderAttemptCount).toBe(2.3);
2769
+ expect(matrix.overallStatus).toBe('degraded');
2770
+ });
2771
+ test('normalizes tutor routing decision signals from telemetry summary', () => {
2772
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2773
+ generatedAt: '2026-04-01T12:00:00.000Z',
2774
+ configuredStoreBackend: 'file',
2775
+ configuredQueryBackend: 'local_hybrid',
2776
+ store: createStoreDiagnostics(),
2777
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2778
+ queryCount: 16,
2779
+ tutorAdapterTelemetry: {
2780
+ summary: {
2781
+ totalAdapters: 1,
2782
+ activeAdapters: 1,
2783
+ totalRequests: 1,
2784
+ successfulResponses: 1,
2785
+ acceptedResponses: 1,
2786
+ downgradedResponses: 0,
2787
+ failedResponses: 0,
2788
+ averageConfidence: 0.9,
2789
+ lastRoutingStrategy: 'unknown_strategy',
2790
+ lastRoutingReason: 'x'.repeat(320),
2791
+ lastRoutingScore: 2.4,
2792
+ },
2793
+ },
2794
+ tutorRoutingConfig: {
2795
+ enabled: true,
2796
+ minSamples: 1,
2797
+ maxFailedRatioPct: 30,
2798
+ maxDowngradedRatioPct: 40,
2799
+ minAverageConfidence: 0.6,
2800
+ preferredMode: 'auto',
2801
+ adapterTimeoutMs: 18000,
2802
+ },
2803
+ });
2804
+ expect(matrix.signals.tutorLastRoutingStrategy).toBe('unknown');
2805
+ expect(matrix.signals.tutorLastRoutingReason.length).toBeLessThanOrEqual(160);
2806
+ expect(matrix.signals.tutorLastRoutingScore).toBe(1);
2807
+ expect(matrix.signals.tutorRoutingDynamicPreferredMode).toBe('auto');
2808
+ expect(matrix.signals.tutorRoutingDynamicModeSuggestionActive).toBe(false);
2809
+ expect(matrix.signals.tutorRoutingDynamicModeReason).toBe('');
2810
+ const traceabilityCheck = matrix.checks.find((check) => check.checkId === 'tutor_routing_traceability');
2811
+ expect(traceabilityCheck?.status).toBe('warn');
2812
+ expect(String(traceabilityCheck?.expected || '')).toContain('strategy in');
2813
+ expect(traceabilityCheck?.recommendedActions).toEqual(expect.arrayContaining([
2814
+ expect.stringContaining('Last routing strategy=unknown'),
2815
+ ]));
2816
+ });
2817
+ test('extracts dynamic preferred mode from legacy routing reason payload when structured fields are missing', () => {
2818
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2819
+ generatedAt: '2026-04-01T12:00:00.000Z',
2820
+ configuredStoreBackend: 'file',
2821
+ configuredQueryBackend: 'local_hybrid',
2822
+ store: createStoreDiagnostics(),
2823
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2824
+ queryCount: 16,
2825
+ tutorAdapterTelemetry: {
2826
+ summary: {
2827
+ totalAdapters: 2,
2828
+ activeAdapters: 2,
2829
+ totalRequests: 10,
2830
+ successfulResponses: 9,
2831
+ acceptedResponses: 8,
2832
+ downgradedResponses: 1,
2833
+ failedResponses: 1,
2834
+ averageConfidence: 0.83,
2835
+ lastRoutingStrategy: 'adaptive_health_routing',
2836
+ lastRoutingReason: 'Adaptive routing selected cloud-adapter, score=0.8100, dynamicPreferredMode=cloud, dynamicModeReason=prefer cloud due to local trend penalty=0.200 and cloud penalty=0.000, modeTrend(local:regressing=2/2,penalty=0.200,top=LMStudio@25.00/55.00)',
2837
+ lastRoutingScore: 0.81,
2838
+ },
2839
+ },
2840
+ tutorRoutingConfig: {
2841
+ enabled: true,
2842
+ minSamples: 4,
2843
+ maxFailedRatioPct: 30,
2844
+ maxDowngradedRatioPct: 40,
2845
+ minAverageConfidence: 0.7,
2846
+ preferredMode: 'auto',
2847
+ adapterTimeoutMs: 18000,
2848
+ },
2849
+ });
2850
+ expect(matrix.signals.tutorRoutingDynamicPreferredMode).toBe('cloud');
2851
+ expect(matrix.signals.tutorRoutingDynamicModeSuggestionActive).toBe(true);
2852
+ expect(matrix.signals.tutorRoutingDynamicModeReason).toBe('prefer cloud due to local trend penalty=0.200 and cloud penalty=0.000');
2853
+ });
2854
+ test('warns when routing remains on fallback strategy under active adaptive routing', () => {
2855
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2856
+ generatedAt: '2026-04-01T12:00:00.000Z',
2857
+ configuredStoreBackend: 'file',
2858
+ configuredQueryBackend: 'local_hybrid',
2859
+ store: createStoreDiagnostics(),
2860
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2861
+ queryCount: 20,
2862
+ tutorAdapterTelemetry: {
2863
+ summary: {
2864
+ totalAdapters: 2,
2865
+ activeAdapters: 2,
2866
+ totalRequests: 18,
2867
+ successfulResponses: 17,
2868
+ acceptedResponses: 14,
2869
+ downgradedResponses: 3,
2870
+ failedResponses: 1,
2871
+ averageConfidence: 0.82,
2872
+ lastRoutingStrategy: 'fallback_default',
2873
+ lastRoutingReason: 'requested adapterId=missing-adapter was not found. Selected local-adapter as default fallback adapter.',
2874
+ lastRoutingScore: 0,
2875
+ },
2876
+ },
2877
+ tutorRoutingConfig: {
2878
+ enabled: true,
2879
+ minSamples: 6,
2880
+ maxFailedRatioPct: 30,
2881
+ maxDowngradedRatioPct: 40,
2882
+ minAverageConfidence: 0.7,
2883
+ preferredMode: 'auto',
2884
+ adapterTimeoutMs: 18000,
2885
+ },
2886
+ });
2887
+ const budgetCheck = matrix.checks.find((check) => check.checkId === 'tutor_routing_health_budget');
2888
+ const traceabilityCheck = matrix.checks.find((check) => check.checkId === 'tutor_routing_traceability');
2889
+ expect(budgetCheck?.status).toBe('pass');
2890
+ expect(traceabilityCheck?.status).toBe('warn');
2891
+ expect(String(traceabilityCheck?.expected || '')).toContain('strategy!=fallback_default');
2892
+ expect(matrix.overallStatus).toBe('degraded');
2893
+ });
2894
+ test('warns when tutor adapter timeout leaves recommended governance window', () => {
2895
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2896
+ generatedAt: '2026-04-01T12:00:00.000Z',
2897
+ configuredStoreBackend: 'file',
2898
+ configuredQueryBackend: 'local_hybrid',
2899
+ store: createStoreDiagnostics(),
2900
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2901
+ queryCount: 20,
2902
+ tutorAdapterTelemetry: {
2903
+ summary: {
2904
+ totalAdapters: 2,
2905
+ activeAdapters: 2,
2906
+ totalRequests: 16,
2907
+ successfulResponses: 15,
2908
+ acceptedResponses: 13,
2909
+ downgradedResponses: 2,
2910
+ failedResponses: 1,
2911
+ averageConfidence: 0.83,
2912
+ lastRoutingStrategy: 'adaptive_health_routing',
2913
+ lastRoutingScore: 0.88,
2914
+ },
2915
+ },
2916
+ tutorRoutingConfig: {
2917
+ enabled: true,
2918
+ minSamples: 6,
2919
+ maxFailedRatioPct: 30,
2920
+ maxDowngradedRatioPct: 40,
2921
+ minAverageConfidence: 0.7,
2922
+ preferredMode: 'auto',
2923
+ adapterTimeoutMs: 700,
2924
+ },
2925
+ });
2926
+ const timeoutBudgetCheck = matrix.checks.find((check) => check.checkId === 'tutor_adapter_timeout_budget');
2927
+ expect(timeoutBudgetCheck?.status).toBe('warn');
2928
+ expect(String(timeoutBudgetCheck?.expected || '')).toBe('1000<=adapterTimeoutMs<=30000');
2929
+ expect(matrix.signals.tutorRoutingAdapterTimeoutMs).toBe(700);
2930
+ expect(matrix.overallStatus).toBe('degraded');
2931
+ });
2932
+ test('fails when tutor adapter timeout breaches hard governance budget', () => {
2933
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2934
+ generatedAt: '2026-04-01T12:00:00.000Z',
2935
+ configuredStoreBackend: 'file',
2936
+ configuredQueryBackend: 'local_hybrid',
2937
+ store: createStoreDiagnostics(),
2938
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2939
+ queryCount: 20,
2940
+ tutorAdapterTelemetry: {
2941
+ summary: {
2942
+ totalAdapters: 2,
2943
+ activeAdapters: 2,
2944
+ totalRequests: 16,
2945
+ successfulResponses: 15,
2946
+ acceptedResponses: 13,
2947
+ downgradedResponses: 2,
2948
+ failedResponses: 1,
2949
+ averageConfidence: 0.83,
2950
+ lastRoutingStrategy: 'adaptive_health_routing',
2951
+ lastRoutingScore: 0.88,
2952
+ },
2953
+ },
2954
+ tutorRoutingConfig: {
2955
+ enabled: true,
2956
+ minSamples: 6,
2957
+ maxFailedRatioPct: 30,
2958
+ maxDowngradedRatioPct: 40,
2959
+ minAverageConfidence: 0.7,
2960
+ preferredMode: 'auto',
2961
+ adapterTimeoutMs: 70000,
2962
+ },
2963
+ });
2964
+ const timeoutBudgetCheck = matrix.checks.find((check) => check.checkId === 'tutor_adapter_timeout_budget');
2965
+ expect(timeoutBudgetCheck?.status).toBe('fail');
2966
+ expect(String(timeoutBudgetCheck?.expected || '')).toBe('300<=adapterTimeoutMs<=60000');
2967
+ expect(matrix.signals.tutorRoutingAdapterTimeoutMs).toBe(70000);
2968
+ expect(matrix.overallStatus).toBe('blocked');
2969
+ });
2970
+ test('passes when session memory promotion coverage is healthy', () => {
2971
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
2972
+ generatedAt: '2026-04-01T12:00:00.000Z',
2973
+ configuredStoreBackend: 'file',
2974
+ configuredQueryBackend: 'local_hybrid',
2975
+ store: createStoreDiagnostics(),
2976
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
2977
+ queryCount: 20,
2978
+ learningQualityTrend: {
2979
+ status: 'stable',
2980
+ score: 0.3,
2981
+ confidence: 0.7,
2982
+ },
2983
+ sessionPlanQualityHistory: {
2984
+ summary: {
2985
+ totalRecords: 5,
2986
+ overallPassRatePct: 80,
2987
+ consecutiveFailureCount: 0,
2988
+ commonFailedGates: [],
2989
+ },
2990
+ },
2991
+ sessionPlanQualityTrend: {
2992
+ status: 'stable',
2993
+ score: 0.2,
2994
+ confidence: 0.6,
2995
+ },
2996
+ memoryPolicyDiagnostics: {
2997
+ summary: {
2998
+ totalEntries: 20,
2999
+ expiredEntries: 1,
3000
+ staleEntries: 2,
3001
+ lowConfidenceEntries: 1,
3002
+ healthScore: 90,
3003
+ status: 'healthy',
3004
+ },
3005
+ },
3006
+ memoryPolicyTrend: {
3007
+ status: 'stable',
3008
+ score: 0.1,
3009
+ confidence: 0.55,
3010
+ },
3011
+ sessionActionTelemetry: {
3012
+ executionCount: 10,
3013
+ memoryPersistedCount: 8,
3014
+ memoryPromotionAppliedCount: 3,
3015
+ memoryPromotionCount: 11,
3016
+ },
3017
+ });
3018
+ const sessionPromotionCheck = matrix.checks.find((check) => check.checkId === 'session_memory_promotion_coverage');
3019
+ expect(sessionPromotionCheck?.status).toBe('pass');
3020
+ expect(matrix.signals.sessionActionExecutionCount).toBe(10);
3021
+ expect(matrix.signals.sessionMemoryPersistedCount).toBe(8);
3022
+ expect(matrix.signals.sessionMemoryPromotionAppliedCount).toBe(3);
3023
+ expect(matrix.signals.sessionMemoryPromotionCount).toBe(11);
3024
+ expect(matrix.signals.sessionMemoryPromotionCoveragePct).toBe(37.5);
3025
+ });
3026
+ test('warns when session memory promotion coverage has no promoted actions', () => {
3027
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3028
+ generatedAt: '2026-04-01T12:00:00.000Z',
3029
+ configuredStoreBackend: 'file',
3030
+ configuredQueryBackend: 'local_hybrid',
3031
+ store: createStoreDiagnostics(),
3032
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
3033
+ queryCount: 20,
3034
+ learningQualityTrend: {
3035
+ status: 'stable',
3036
+ score: 0.25,
3037
+ confidence: 0.66,
3038
+ },
3039
+ sessionPlanQualityHistory: {
3040
+ summary: {
3041
+ totalRecords: 5,
3042
+ overallPassRatePct: 80,
3043
+ consecutiveFailureCount: 0,
3044
+ commonFailedGates: [],
3045
+ },
3046
+ },
3047
+ sessionPlanQualityTrend: {
3048
+ status: 'stable',
3049
+ score: 0.2,
3050
+ confidence: 0.61,
3051
+ },
3052
+ memoryPolicyDiagnostics: {
3053
+ summary: {
3054
+ totalEntries: 20,
3055
+ expiredEntries: 1,
3056
+ staleEntries: 2,
3057
+ lowConfidenceEntries: 1,
3058
+ healthScore: 90,
3059
+ status: 'healthy',
3060
+ },
3061
+ },
3062
+ memoryPolicyTrend: {
3063
+ status: 'stable',
3064
+ score: 0.1,
3065
+ confidence: 0.55,
3066
+ },
3067
+ sessionActionTelemetry: {
3068
+ executionCount: 8,
3069
+ memoryPersistedCount: 6,
3070
+ memoryPromotionAppliedCount: 0,
3071
+ memoryPromotionCount: 0,
3072
+ },
3073
+ });
3074
+ const sessionPromotionCheck = matrix.checks.find((check) => check.checkId === 'session_memory_promotion_coverage');
3075
+ expect(sessionPromotionCheck?.status).toBe('warn');
3076
+ expect(String(sessionPromotionCheck?.expected || '')).toContain('promotedActions>=1');
3077
+ expect(sessionPromotionCheck?.recommendedActions).toEqual(expect.arrayContaining([
3078
+ expect.stringContaining('coverage is 0%'),
3079
+ ]));
3080
+ expect(matrix.signals.sessionMemoryPromotionCoveragePct).toBe(0);
3081
+ });
3082
+ test('builds runtime runbook for explicit check with trace filter and verification targets', () => {
3083
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3084
+ generatedAt: '2026-04-01T12:00:00.000Z',
3085
+ configuredStoreBackend: 'file',
3086
+ configuredQueryBackend: 'local_hybrid',
3087
+ store: createStoreDiagnostics(),
3088
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
3089
+ queryCount: 30,
3090
+ apiRequestErrorTelemetry: {
3091
+ totalRequests: 30,
3092
+ errorRequests: 5,
3093
+ invalidRequestErrors: 1,
3094
+ serverErrorRequests: 2,
3095
+ transientErrorRequests: 1,
3096
+ averageDurationMs: 780,
3097
+ p95DurationMs: 2900,
3098
+ scopePathPrefix: '/api/knowledge',
3099
+ scopeMethod: 'post',
3100
+ slowTopPaths: [
3101
+ { path: 'POST /api/knowledge/session/execute', count: 4, p95DurationMs: 3600 },
3102
+ ],
3103
+ },
3104
+ thresholds: {
3105
+ apiLatencyMinRequestSample: 10,
3106
+ apiLatencyP95WarnMs: 1000,
3107
+ apiLatencyP95FailMs: 2400,
3108
+ apiLatencyHotspotWarnMs: 1500,
3109
+ apiLatencyHotspotFailMs: 3200,
3110
+ },
3111
+ });
3112
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'api_latency_p95');
3113
+ expect(runbook.requestedCheckId).toBe('api_latency_p95');
3114
+ expect(runbook.selectionSource).toBe('requested');
3115
+ expect(runbook.selectedCheck?.checkId).toBe('api_latency_p95');
3116
+ expect(runbook.selectedCheck?.status).toBe('fail');
3117
+ expect(runbook.traceFilter.pathPrefix).toBe('/api/knowledge/session/execute');
3118
+ expect(runbook.traceFilter.statusAtLeast).toBe(0);
3119
+ expect(runbook.traceFilter.method).toBe('POST');
3120
+ expect(runbook.verificationTargets.length).toBeGreaterThan(0);
3121
+ expect(String(runbook.verificationTargets[0] || '')).toContain('Satisfy check expectation');
3122
+ });
3123
+ test('runtime runbook for vector index status includes diagnostics verification targets', () => {
3124
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3125
+ generatedAt: '2026-04-01T12:00:00.000Z',
3126
+ configuredStoreBackend: 'file',
3127
+ configuredQueryBackend: 'local_vector',
3128
+ store: createStoreDiagnostics(),
3129
+ queryDiagnostics: createQueryDiagnostics({
3130
+ backendId: 'local-vector-v1',
3131
+ runtime: {
3132
+ backendId: 'local-vector-v1',
3133
+ ready: true,
3134
+ vectorIndex: {
3135
+ enabled: true,
3136
+ status: 'stale',
3137
+ persisted: false,
3138
+ loadedFromDisk: false,
3139
+ },
3140
+ },
3141
+ }),
3142
+ queryCount: 12,
3143
+ });
3144
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'query_vector_index_status');
3145
+ expect(runbook.selectedCheck?.checkId).toBe('query_vector_index_status');
3146
+ expect(runbook.traceFilter.pathPrefix).toBe('/api/knowledge/query-backend-diagnostics');
3147
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('/api/knowledge/query-backend-diagnostics'))).toBe(true);
3148
+ });
3149
+ test('runtime runbook for vector acceleration mode includes acceleration verification target', () => {
3150
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3151
+ generatedAt: '2026-04-01T12:00:00.000Z',
3152
+ configuredStoreBackend: 'file',
3153
+ configuredQueryBackend: 'local_vector',
3154
+ store: createStoreDiagnostics(),
3155
+ queryDiagnostics: createQueryDiagnostics({
3156
+ backendId: 'local-vector-v1',
3157
+ runtime: {
3158
+ backendId: 'local-vector-v1',
3159
+ ready: true,
3160
+ vectorIndex: {
3161
+ enabled: true,
3162
+ status: 'ready',
3163
+ persisted: true,
3164
+ loadedFromDisk: true,
3165
+ acceleration: {
3166
+ enabled: false,
3167
+ mode: 'full_scan',
3168
+ adapterId: 'local-vector-acceleration-ann-v1',
3169
+ },
3170
+ },
3171
+ },
3172
+ }),
3173
+ queryCount: 20,
3174
+ });
3175
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'query_vector_acceleration_mode');
3176
+ expect(runbook.selectedCheck?.checkId).toBe('query_vector_acceleration_mode');
3177
+ expect(runbook.traceFilter.pathPrefix).toBe('/api/knowledge/query-backend-diagnostics');
3178
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('vectorIndex.acceleration'))).toBe(true);
3179
+ });
3180
+ test('runtime runbook for vector acceleration representation consistency includes metadata verification targets', () => {
3181
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3182
+ generatedAt: '2026-04-01T12:00:00.000Z',
3183
+ configuredStoreBackend: 'file',
3184
+ configuredQueryBackend: 'local_vector',
3185
+ store: createStoreDiagnostics(),
3186
+ queryDiagnostics: createQueryDiagnostics({
3187
+ backendId: 'local-vector-v1',
3188
+ runtime: {
3189
+ backendId: 'local-vector-v1',
3190
+ ready: true,
3191
+ vectorIndex: {
3192
+ enabled: true,
3193
+ status: 'ready',
3194
+ persisted: true,
3195
+ loadedFromDisk: true,
3196
+ atomCount: 128,
3197
+ acceleration: {
3198
+ enabled: true,
3199
+ mode: 'ann_prefilter',
3200
+ lastSelectionMode: 'token_prefilter',
3201
+ lastCandidateCount: 48,
3202
+ adapterId: 'external-http-vector-acceleration-v1',
3203
+ healthStatus: 'ready',
3204
+ representationVersion: 'remote-representation-v2',
3205
+ embeddingModelId: 'remote-embedding-v2',
3206
+ embeddingDimension: 64,
3207
+ indexSignature: 'remote_sig_v2',
3208
+ representationStatus: 'mismatch',
3209
+ representationStatusReason: 'embedding_model_id_mismatch',
3210
+ representationStrictMode: true,
3211
+ requestCount: 28,
3212
+ circuitState: 'closed',
3213
+ },
3214
+ },
3215
+ },
3216
+ }),
3217
+ queryCount: 28,
3218
+ });
3219
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'query_vector_acceleration_representation_consistency');
3220
+ expect(runbook.selectedCheck?.checkId).toBe('query_vector_acceleration_representation_consistency');
3221
+ expect(runbook.traceFilter.pathPrefix).toBe('/api/knowledge/query-backend-diagnostics');
3222
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('representationStatus is aligned'))).toBe(true);
3223
+ });
3224
+ test('runtime runbook for vector acceleration health includes health verification target', () => {
3225
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3226
+ generatedAt: '2026-04-01T12:00:00.000Z',
3227
+ configuredStoreBackend: 'file',
3228
+ configuredQueryBackend: 'local_vector',
3229
+ store: createStoreDiagnostics(),
3230
+ queryDiagnostics: createQueryDiagnostics({
3231
+ backendId: 'local-vector-v1',
3232
+ runtime: {
3233
+ backendId: 'local-vector-v1',
3234
+ ready: true,
3235
+ vectorIndex: {
3236
+ enabled: true,
3237
+ status: 'ready',
3238
+ persisted: true,
3239
+ loadedFromDisk: true,
3240
+ acceleration: {
3241
+ enabled: true,
3242
+ mode: 'ann_prefilter',
3243
+ adapterId: 'external-http-vector-acceleration-v1',
3244
+ healthStatus: 'degraded',
3245
+ healthMessage: 'external_http_status_503',
3246
+ },
3247
+ },
3248
+ },
3249
+ }),
3250
+ queryCount: 20,
3251
+ });
3252
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'query_vector_acceleration_health');
3253
+ expect(runbook.selectedCheck?.checkId).toBe('query_vector_acceleration_health');
3254
+ expect(runbook.traceFilter.pathPrefix).toBe('/api/knowledge/query-backend-diagnostics');
3255
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('acceleration.healthStatus'))).toBe(true);
3256
+ });
3257
+ test('runtime runbook for vector acceleration prefilter effectiveness includes selection telemetry target', () => {
3258
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3259
+ generatedAt: '2026-04-01T12:00:00.000Z',
3260
+ configuredStoreBackend: 'file',
3261
+ configuredQueryBackend: 'local_vector',
3262
+ store: createStoreDiagnostics(),
3263
+ queryDiagnostics: createQueryDiagnostics({
3264
+ backendId: 'local-vector-v1',
3265
+ runtime: {
3266
+ backendId: 'local-vector-v1',
3267
+ ready: true,
3268
+ vectorIndex: {
3269
+ enabled: true,
3270
+ status: 'ready',
3271
+ persisted: true,
3272
+ loadedFromDisk: true,
3273
+ atomCount: 256,
3274
+ acceleration: {
3275
+ enabled: true,
3276
+ mode: 'ann_prefilter',
3277
+ lastSelectionMode: 'full_scan',
3278
+ lastCandidateCount: 256,
3279
+ adapterId: 'external-http-vector-acceleration-v1',
3280
+ healthStatus: 'ready',
3281
+ circuitState: 'closed',
3282
+ requestCount: 20,
3283
+ },
3284
+ },
3285
+ },
3286
+ }),
3287
+ queryCount: 20,
3288
+ });
3289
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'query_vector_acceleration_prefilter_effectiveness');
3290
+ expect(runbook.selectedCheck?.checkId).toBe('query_vector_acceleration_prefilter_effectiveness');
3291
+ expect(runbook.traceFilter.pathPrefix).toBe('/api/knowledge/query-backend-diagnostics');
3292
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('lastSelectionMode'))).toBe(true);
3293
+ });
3294
+ test('runtime runbook for vector acceleration calibration readiness includes calibration verification targets', () => {
3295
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3296
+ generatedAt: '2026-04-01T12:00:00.000Z',
3297
+ configuredStoreBackend: 'file',
3298
+ configuredQueryBackend: 'local_vector',
3299
+ store: createStoreDiagnostics(),
3300
+ queryDiagnostics: createQueryDiagnostics({
3301
+ backendId: 'local-vector-v1',
3302
+ runtime: {
3303
+ backendId: 'local-vector-v1',
3304
+ ready: true,
3305
+ vectorIndex: {
3306
+ enabled: true,
3307
+ status: 'ready',
3308
+ persisted: true,
3309
+ loadedFromDisk: true,
3310
+ atomCount: 256,
3311
+ acceleration: {
3312
+ enabled: true,
3313
+ mode: 'ann_prefilter',
3314
+ lastSelectionMode: 'token_signature_prefilter',
3315
+ lastCandidateCount: 64,
3316
+ adapterId: 'external-http-vector-acceleration-v1',
3317
+ healthStatus: 'ready',
3318
+ circuitState: 'closed',
3319
+ requestCount: 20,
3320
+ syncRequestCount: 3,
3321
+ syncSuccessCount: 3,
3322
+ syncedIndexSignature: 'idx_sync_ok',
3323
+ syncedAtomCount: 128,
3324
+ lastRequestId: 'connector-req-42',
3325
+ },
3326
+ },
3327
+ },
3328
+ }),
3329
+ queryCount: 20,
3330
+ });
3331
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'query_vector_acceleration_calibration_readiness');
3332
+ expect(runbook.selectedCheck?.checkId).toBe('query_vector_acceleration_calibration_readiness');
3333
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('sync telemetry ready'))).toBe(true);
3334
+ });
3335
+ test('runtime runbook for vector acceleration circuit state includes circuit verification target', () => {
3336
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3337
+ generatedAt: '2026-04-01T12:00:00.000Z',
3338
+ configuredStoreBackend: 'file',
3339
+ configuredQueryBackend: 'local_vector',
3340
+ store: createStoreDiagnostics(),
3341
+ queryDiagnostics: createQueryDiagnostics({
3342
+ backendId: 'local-vector-v1',
3343
+ runtime: {
3344
+ backendId: 'local-vector-v1',
3345
+ ready: true,
3346
+ vectorIndex: {
3347
+ enabled: true,
3348
+ status: 'ready',
3349
+ persisted: true,
3350
+ loadedFromDisk: true,
3351
+ acceleration: {
3352
+ enabled: true,
3353
+ mode: 'ann_prefilter',
3354
+ adapterId: 'external-http-vector-acceleration-v1',
3355
+ healthStatus: 'degraded',
3356
+ healthMessage: 'external_http_circuit_open',
3357
+ circuitState: 'open',
3358
+ shortCircuitCount: 6,
3359
+ consecutiveFailures: 3,
3360
+ },
3361
+ },
3362
+ },
3363
+ }),
3364
+ queryCount: 20,
3365
+ });
3366
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'query_vector_acceleration_circuit_state');
3367
+ expect(runbook.selectedCheck?.checkId).toBe('query_vector_acceleration_circuit_state');
3368
+ expect(runbook.traceFilter.pathPrefix).toBe('/api/knowledge/query-backend-diagnostics');
3369
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('query-backend-diagnostics')
3370
+ && String(item || '').includes('vectorIndex'))).toBe(true);
3371
+ });
3372
+ test('runtime runbook for vector acceleration index sync health includes sync telemetry verification target', () => {
3373
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3374
+ generatedAt: '2026-04-01T12:00:00.000Z',
3375
+ configuredStoreBackend: 'file',
3376
+ configuredQueryBackend: 'local_vector',
3377
+ store: createStoreDiagnostics(),
3378
+ queryDiagnostics: createQueryDiagnostics({
3379
+ backendId: 'local-vector-v1',
3380
+ runtime: {
3381
+ backendId: 'local-vector-v1',
3382
+ ready: true,
3383
+ vectorIndex: {
3384
+ enabled: true,
3385
+ status: 'ready',
3386
+ persisted: true,
3387
+ loadedFromDisk: true,
3388
+ acceleration: {
3389
+ enabled: true,
3390
+ mode: 'ann_prefilter',
3391
+ adapterId: 'external-http-vector-acceleration-v1',
3392
+ healthStatus: 'ready',
3393
+ indexSyncStatus: 'ready',
3394
+ syncRequestCount: 3,
3395
+ syncSuccessCount: 3,
3396
+ syncFailureCount: 0,
3397
+ syncedIndexSignature: 'idx_sync_ok',
3398
+ syncedAtomCount: 128,
3399
+ lastSyncAt: '2026-04-01T12:00:00.000Z',
3400
+ circuitState: 'closed',
3401
+ requestCount: 12,
3402
+ successCount: 12,
3403
+ failureCount: 0,
3404
+ },
3405
+ },
3406
+ },
3407
+ }),
3408
+ queryCount: 20,
3409
+ });
3410
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'query_vector_acceleration_index_sync_health');
3411
+ expect(runbook.selectedCheck?.checkId).toBe('query_vector_acceleration_index_sync_health');
3412
+ expect(runbook.traceFilter.pathPrefix).toBe('/api/knowledge/query-backend-diagnostics');
3413
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('indexSyncStatus/indexSyncMessage/lastSyncAt'))).toBe(true);
3414
+ });
3415
+ test('runtime runbook for vector acceleration traceability includes connector correlation verification target', () => {
3416
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3417
+ generatedAt: '2026-04-01T12:00:00.000Z',
3418
+ configuredStoreBackend: 'file',
3419
+ configuredQueryBackend: 'local_vector',
3420
+ store: createStoreDiagnostics(),
3421
+ queryDiagnostics: createQueryDiagnostics({
3422
+ backendId: 'local-vector-v1',
3423
+ runtime: {
3424
+ backendId: 'local-vector-v1',
3425
+ ready: true,
3426
+ vectorIndex: {
3427
+ enabled: true,
3428
+ status: 'ready',
3429
+ persisted: true,
3430
+ loadedFromDisk: true,
3431
+ acceleration: {
3432
+ enabled: true,
3433
+ mode: 'ann_prefilter',
3434
+ adapterId: 'external-http-vector-acceleration-v1',
3435
+ healthStatus: 'degraded',
3436
+ healthMessage: 'external_http_status_503',
3437
+ },
3438
+ },
3439
+ },
3440
+ }),
3441
+ queryCount: 20,
3442
+ });
3443
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'query_vector_acceleration_traceability');
3444
+ expect(runbook.selectedCheck?.checkId).toBe('query_vector_acceleration_traceability');
3445
+ expect(runbook.traceFilter.pathPrefix).toBe('/api/knowledge/query-backend-diagnostics');
3446
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('diagnostics.runtime.vectorIndex.acceleration.healthStatus is ready|unknown'))).toBe(true);
3447
+ });
3448
+ test('runtime runbook for tutor provider trend regression includes provider diagnostics targets', () => {
3449
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3450
+ generatedAt: '2026-04-01T12:00:00.000Z',
3451
+ configuredStoreBackend: 'file',
3452
+ configuredQueryBackend: 'local_hybrid',
3453
+ store: createStoreDiagnostics(),
3454
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
3455
+ queryCount: 20,
3456
+ tutorAdapterTelemetry: {
3457
+ summary: {
3458
+ totalAdapters: 2,
3459
+ activeAdapters: 2,
3460
+ totalRequests: 20,
3461
+ successfulResponses: 18,
3462
+ acceptedResponses: 14,
3463
+ downgradedResponses: 4,
3464
+ failedResponses: 2,
3465
+ providerFallbackResponses: 8,
3466
+ providerFallbackRatioPct: 40,
3467
+ averageProviderAttemptCount: 1.8,
3468
+ averageConfidence: 0.76,
3469
+ lastRoutingStrategy: 'adaptive_health_routing',
3470
+ lastRoutingScore: 0.72,
3471
+ },
3472
+ },
3473
+ tutorProviderTrendDiagnostics: {
3474
+ summary: {
3475
+ totalProviders: 2,
3476
+ evaluatedProviders: 2,
3477
+ returnedProviders: 2,
3478
+ regressingProviders: 1,
3479
+ stableProviders: 1,
3480
+ improvingProviders: 0,
3481
+ insufficientDataProviders: 0,
3482
+ recommendedFocusProviderName: 'LMStudio',
3483
+ },
3484
+ providers: [
3485
+ {
3486
+ providerName: 'LMStudio',
3487
+ trendStatus: 'regressing',
3488
+ trendScore: 31,
3489
+ trendConfidence: 74,
3490
+ },
3491
+ {
3492
+ providerName: 'DeepSeek',
3493
+ trendStatus: 'stable',
3494
+ trendScore: 4,
3495
+ trendConfidence: 46,
3496
+ },
3497
+ ],
3498
+ },
3499
+ tutorRoutingConfig: {
3500
+ enabled: true,
3501
+ minSamples: 6,
3502
+ maxFailedRatioPct: 30,
3503
+ maxDowngradedRatioPct: 40,
3504
+ minAverageConfidence: 0.7,
3505
+ preferredMode: 'auto',
3506
+ adapterTimeoutMs: 18000,
3507
+ },
3508
+ });
3509
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'tutor_provider_trend_regression');
3510
+ expect(runbook.selectedCheck?.checkId).toBe('tutor_provider_trend_regression');
3511
+ expect(runbook.selectedCheck?.status).toBe('fail');
3512
+ expect(runbook.traceFilter.pathPrefix).toBe('/api/knowledge/tutor/trace-diagnostics/providers');
3513
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('/api/knowledge/tutor/trace-diagnostics/providers/history'))).toBe(true);
3514
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('/api/knowledge/tutor/trace-diagnostics/providers?source=llm-adapter'))).toBe(true);
3515
+ });
3516
+ test('runtime runbook for tutor routing dynamic mode alignment includes mode reconciliation targets', () => {
3517
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3518
+ generatedAt: '2026-04-01T12:00:00.000Z',
3519
+ configuredStoreBackend: 'file',
3520
+ configuredQueryBackend: 'local_hybrid',
3521
+ store: createStoreDiagnostics(),
3522
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
3523
+ queryCount: 20,
3524
+ tutorAdapterTelemetry: {
3525
+ summary: {
3526
+ totalAdapters: 2,
3527
+ activeAdapters: 2,
3528
+ totalRequests: 20,
3529
+ successfulResponses: 16,
3530
+ acceptedResponses: 12,
3531
+ downgradedResponses: 4,
3532
+ failedResponses: 4,
3533
+ providerFallbackResponses: 12,
3534
+ providerFallbackRatioPct: 60,
3535
+ averageProviderAttemptCount: 2.4,
3536
+ averageConfidence: 0.63,
3537
+ lastRoutingStrategy: 'adaptive_health_routing',
3538
+ lastRoutingScore: 0.55,
3539
+ lastRoutingDynamicPreferredMode: 'cloud',
3540
+ lastRoutingDynamicModeReason: 'prefer cloud due to local trend penalty=0.250 and cloud penalty=0.000',
3541
+ },
3542
+ },
3543
+ tutorRoutingConfig: {
3544
+ enabled: true,
3545
+ minSamples: 6,
3546
+ maxFailedRatioPct: 25,
3547
+ maxDowngradedRatioPct: 35,
3548
+ minAverageConfidence: 0.7,
3549
+ preferredMode: 'local',
3550
+ adapterTimeoutMs: 18000,
3551
+ },
3552
+ });
3553
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'tutor_routing_dynamic_mode_alignment');
3554
+ expect(runbook.selectedCheck?.checkId).toBe('tutor_routing_dynamic_mode_alignment');
3555
+ expect(['warn', 'fail']).toContain(String(runbook.selectedCheck?.status || ''));
3556
+ expect(runbook.traceFilter.pathPrefix).toBe('/api/knowledge/tutor/trace-diagnostics/providers/history');
3557
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('/api/knowledge/session/orchestration/config'))).toBe(true);
3558
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('/api/knowledge/tutor/trace-diagnostics/providers/history'))).toBe(true);
3559
+ });
3560
+ test('runtime runbook for orchestration path strategy alignment includes outcome verification targets', () => {
3561
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3562
+ generatedAt: '2026-04-01T12:00:00.000Z',
3563
+ configuredStoreBackend: 'file',
3564
+ configuredQueryBackend: 'local_hybrid',
3565
+ store: createStoreDiagnostics(),
3566
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 0 }),
3567
+ queryCount: 20,
3568
+ sessionStrategyTelemetry: {
3569
+ totalRecords: 9,
3570
+ strategyRecords: 9,
3571
+ trendAutoSelectionSharePct: 66.6667,
3572
+ trendAutoAverageMasteryDeltaPct: -4.2,
3573
+ trendAutoNegativeRatioPct: 66.6667,
3574
+ modeFallbackSelectionSharePct: 22.2222,
3575
+ selectionSourceCounts: {
3576
+ explicit_request: 1,
3577
+ strategy_trend: 6,
3578
+ mode_fallback: 2,
3579
+ unknown: 0,
3580
+ },
3581
+ strategyBreakdown: [
3582
+ {
3583
+ strategy: 'balanced',
3584
+ executions: 3,
3585
+ averageMasteryDeltaPct: -2.5,
3586
+ positiveRatioPct: 33.3333,
3587
+ negativeRatioPct: 66.6667,
3588
+ },
3589
+ {
3590
+ strategy: 'mastery_recovery',
3591
+ executions: 4,
3592
+ averageMasteryDeltaPct: -4.8,
3593
+ positiveRatioPct: 25,
3594
+ negativeRatioPct: 75,
3595
+ },
3596
+ {
3597
+ strategy: 'exploration_boost',
3598
+ executions: 2,
3599
+ averageMasteryDeltaPct: -1.4,
3600
+ positiveRatioPct: 0,
3601
+ negativeRatioPct: 100,
3602
+ },
3603
+ ],
3604
+ },
3605
+ });
3606
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'orchestration_path_strategy_alignment');
3607
+ expect(runbook.selectedCheck?.checkId).toBe('orchestration_path_strategy_alignment');
3608
+ expect(['warn', 'fail']).toContain(String(runbook.selectedCheck?.status || ''));
3609
+ expect(runbook.traceFilter.pathPrefix).toBe('/api/knowledge/session/history');
3610
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('/api/knowledge/session/history'))).toBe(true);
3611
+ expect(runbook.verificationTargets.some((item) => String(item || '').includes('/api/knowledge/quality/trend'))).toBe(true);
3612
+ });
3613
+ test('builds runtime runbook using top-risk fallback when requested check is unavailable', () => {
3614
+ const matrix = (0, runtimeCapability_1.buildRuntimeCapabilityMatrix)({
3615
+ generatedAt: '2026-04-01T12:00:00.000Z',
3616
+ configuredStoreBackend: 'file',
3617
+ configuredQueryBackend: 'local_hybrid',
3618
+ store: createStoreDiagnostics(),
3619
+ queryDiagnostics: createQueryDiagnostics({ fallbackCount: 9 }),
3620
+ queryCount: 20,
3621
+ thresholds: {
3622
+ minQuerySampleSize: 5,
3623
+ queryFallbackWarnRatioPct: 10,
3624
+ queryFallbackFailRatioPct: 30,
3625
+ },
3626
+ });
3627
+ const runbook = (0, runtimeCapability_1.buildRuntimeCapabilityRunbook)(matrix, 'missing_check_id');
3628
+ expect(runbook.requestedCheckId).toBe('missing_check_id');
3629
+ expect(runbook.selectionSource).toBe('top_risk_fallback');
3630
+ expect(runbook.selectedCheck).toBeDefined();
3631
+ expect(runbook.selectedCheck?.checkId).toBe('query_fallback_ratio');
3632
+ expect(['warn', 'fail']).toContain(String(runbook.selectedCheck?.status || ''));
3633
+ expect(runbook.topRiskCheck?.checkId).toBe('query_fallback_ratio');
3634
+ });
3635
+ });