noteconnection 1.7.0 → 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.
- package/LICENSE +674 -21
- package/README.md +242 -62
- package/dist/src/agent_workspace.contract.parity.test.js +475 -0
- package/dist/src/agent_workspace.frontend.test.js +9989 -0
- package/dist/src/agent_workspace.locale.contract.test.js +95 -0
- package/dist/src/agent_workspace.runtime.behavior.test.js +5072 -0
- package/dist/src/copy.assets.contract.test.js +130 -0
- package/dist/src/core/PathBridge.js +28 -3
- package/dist/src/export/WorkspaceExportBundle.js +1130 -0
- package/dist/src/export/WorkspaceExportBundle.test.js +1480 -0
- package/dist/src/export/index.js +18 -0
- package/dist/src/export/types.js +2 -0
- package/dist/src/fixrisk.issue.verifier.contract.test.js +3 -1
- package/dist/src/foundation.ann.runtime.contract.test.js +81 -0
- package/dist/src/foundation.release.evidence.contract.test.js +406 -0
- package/dist/src/foundation.sqlite.runtime.contract.test.js +82 -0
- package/dist/src/frontend/README.md +242 -62
- package/dist/src/frontend/agent_workspace.js +5353 -0
- package/dist/src/frontend/agent_workspace_runtime.js +4434 -0
- package/dist/src/frontend/analysis.js +31 -4
- package/dist/src/frontend/app.js +2178 -62
- package/dist/src/frontend/focus_mode_interactions.js +33 -0
- package/dist/src/frontend/godot_future_path_renderer.js +540 -0
- package/dist/src/frontend/godot_tree_interactions.js +178 -0
- package/dist/src/frontend/graph_state.mjs +105 -0
- package/dist/src/frontend/hosted_future_path_runtime.js +157 -0
- package/dist/src/frontend/i18n.mjs +186 -0
- package/dist/src/frontend/index.html +641 -266
- package/dist/src/frontend/layout_gpu.js +12 -4
- package/dist/src/frontend/locales/en.json +721 -5
- package/dist/src/frontend/locales/zh.json +721 -5
- package/dist/src/frontend/main.mjs +60 -0
- package/dist/src/frontend/markdown_runtime.js +827 -0
- package/dist/src/frontend/notemd.css +49 -0
- package/dist/src/frontend/notemd.html +7 -1
- package/dist/src/frontend/notemd.js +64 -0
- package/dist/src/frontend/path.html +107 -0
- package/dist/src/frontend/path_app.js +2108 -130
- package/dist/src/frontend/path_layout.mjs +143 -0
- package/dist/src/frontend/path_mermaid_utils.mjs +108 -0
- package/dist/src/frontend/path_modules_bridge.js +486 -0
- package/dist/src/frontend/path_state.mjs +118 -0
- package/dist/src/frontend/path_styles.css +146 -0
- package/dist/src/frontend/path_worker_bridge.mjs +85 -0
- package/dist/src/frontend/reader.js +393 -33
- package/dist/src/frontend/runtime_bridge.js +67 -54
- package/dist/src/frontend/runtime_bridge.mjs +279 -0
- package/dist/src/frontend/settings.js +130 -12
- package/dist/src/frontend/source_manager.js +190 -21
- package/dist/src/frontend/styles.css +2720 -72
- package/dist/src/frontend/workbench_state.mjs +101 -0
- package/dist/src/frontend/workspace_panes.js +10168 -0
- package/dist/src/frontend.locale.contract.test.js +62 -0
- package/dist/src/godot.sidecar.bootstrap.contract.test.js +244 -0
- package/dist/src/indexing/IndexLifecycle.js +195 -0
- package/dist/src/indexing/IndexLifecycle.test.js +49 -0
- package/dist/src/indexing/SegmentBuilder.js +64 -0
- package/dist/src/indexing/UnitBuilder.js +48 -0
- package/dist/src/indexing/types.js +2 -0
- package/dist/src/knowledge.api.contract.test.js +170 -0
- package/dist/src/learning/KnowledgeLearningPlatform.js +10386 -0
- package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +327 -0
- package/dist/src/learning/KnowledgeLearningPlatform.program-f.test.js +99 -0
- package/dist/src/learning/KnowledgeLearningPlatform.test.js +2971 -0
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +2974 -0
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +3928 -0
- package/dist/src/learning/answerReleaseReview.js +4319 -0
- package/dist/src/learning/answerReleaseReview.test.js +2888 -0
- package/dist/src/learning/api.js +2 -0
- package/dist/src/learning/conversationComposer.js +1480 -0
- package/dist/src/learning/conversationComposer.test.js +1817 -0
- package/dist/src/learning/domains/ConversationManager.js +53 -0
- package/dist/src/learning/domains/KnowledgeIngestor.js +238 -0
- package/dist/src/learning/domains/KnowledgeQuerier.js +187 -0
- package/dist/src/learning/domains/MasteryEngine.js +387 -0
- package/dist/src/learning/domains/MemoryPolicyManager.js +408 -0
- package/dist/src/learning/domains/QualityEvaluator.js +307 -0
- package/dist/src/learning/domains/TutorRouter.js +313 -0
- package/dist/src/learning/domains/index.js +33 -0
- package/dist/src/learning/domains/types.js +7 -0
- package/dist/src/learning/errors.js +29 -0
- package/dist/src/learning/evidenceContextAssembler.js +1176 -0
- package/dist/src/learning/evidenceContextAssembler.test.js +6332 -0
- package/dist/src/learning/graphContextAssembler.js +870 -0
- package/dist/src/learning/graphContextAssembler.test.js +1033 -0
- package/dist/src/learning/index.js +28 -0
- package/dist/src/learning/queryBackend.js +1898 -0
- package/dist/src/learning/queryBackend.test.js +955 -0
- package/dist/src/learning/ragContextPack.js +257 -0
- package/dist/src/learning/ragContextPack.test.js +160 -0
- package/dist/src/learning/ragPublicText.js +38 -0
- package/dist/src/learning/ragSufficiencyJudge.js +161 -0
- package/dist/src/learning/ragSufficiencyJudge.test.js +177 -0
- package/dist/src/learning/ragSufficiencyProviderJudge.js +227 -0
- package/dist/src/learning/ragSufficiencyProviderJudge.test.js +156 -0
- package/dist/src/learning/requestNormalization.js +198 -0
- package/dist/src/learning/runtimeCapability.js +4677 -0
- package/dist/src/learning/runtimeCapability.test.js +3635 -0
- package/dist/src/learning/store.js +1240 -0
- package/dist/src/learning/store.test.js +1126 -0
- package/dist/src/learning/tutorAdapter.js +2 -0
- package/dist/src/learning/types.js +2 -0
- package/dist/src/learning/vectorAccelerationAdapter.js +942 -0
- package/dist/src/learning/vectorAccelerationAdapter.test.js +382 -0
- package/dist/src/lfs.asset.policy.contract.test.js +153 -0
- package/dist/src/license.policy.contract.test.js +66 -0
- package/dist/src/memory/MemoryGovernance.js +74 -0
- package/dist/src/memory/MemoryGovernance.test.js +46 -0
- package/dist/src/memory/types.js +2 -0
- package/dist/src/mermaid.frontend.guard.contract.test.js +77 -0
- package/dist/src/middleware/auth.js +17 -0
- package/dist/src/middleware/body-parser.js +45 -0
- package/dist/src/middleware/cors.js +44 -0
- package/dist/src/middleware/index.js +21 -0
- package/dist/src/middleware/request-trace.js +96 -0
- package/dist/src/notemd/AppConfigToml.js +6 -4
- package/dist/src/notemd/MermaidProcessor.js +400 -50
- package/dist/src/notemd/NotemdService.js +498 -13
- package/dist/src/notemd/PromptManager.js +15 -0
- package/dist/src/notemd/cli/commands.js +357 -0
- package/dist/src/notemd/cli/dispatcher.js +225 -0
- package/dist/src/notemd/cli/index.js +169 -0
- package/dist/src/notemd/cli/parser.js +68 -0
- package/dist/src/notemd/cli/types.js +2 -0
- package/dist/src/notemd/constants.js +43 -0
- package/dist/src/notemd/diagram/diagramGenerationService.js +78 -0
- package/dist/src/notemd/diagram/diagramSpec.js +79 -0
- package/dist/src/notemd/diagram/diagramSpecResponseParser.js +131 -0
- package/dist/src/notemd/diagram/intent.js +95 -0
- package/dist/src/notemd/diagram/planner.js +71 -0
- package/dist/src/notemd/diagram/prompts/diagramSpecPrompt.js +42 -0
- package/dist/src/notemd/diagram/types.js +18 -0
- package/dist/src/notemd/index.js +26 -0
- package/dist/src/notemd/operations/capabilityManifest.js +23 -0
- package/dist/src/notemd/operations/cliContracts.js +17 -0
- package/dist/src/notemd/operations/configProfileCommands.js +85 -0
- package/dist/src/notemd/operations/registry.contract.test.js +95 -0
- package/dist/src/notemd/operations/registry.js +991 -0
- package/dist/src/notemd/operations/types.js +2 -0
- package/dist/src/notemd/providerDiagnostics.js +220 -0
- package/dist/src/notemd/providerProfiles.js +42 -0
- package/dist/src/notemd/providerTemplates.js +231 -0
- package/dist/src/notemd/search/DuckDuckGoProvider.js +39 -0
- package/dist/src/notemd/search/SearchManager.js +13 -0
- package/dist/src/notemd/search/SearchProvider.js +2 -0
- package/dist/src/notemd/search/TavilyProvider.js +44 -0
- package/dist/src/notemd.agent.manifest.test.js +85 -0
- package/dist/src/notemd.api.contract.test.js +14 -1
- package/dist/src/notemd.app_config_toml.test.js +2 -1
- package/dist/src/notemd.batch.workflow.test.js +117 -0
- package/dist/src/notemd.cli.e2e.test.js +136 -0
- package/dist/src/notemd.core.test.js +51 -0
- package/dist/src/notemd.diagram.pipeline.test.js +233 -0
- package/dist/src/notemd.providerTemplates.test.js +34 -0
- package/dist/src/notemd.server.integration.test.js +143 -35
- package/dist/src/notemd.workflow.pipeline.test.js +162 -0
- package/dist/src/pathbridge.handshake.contract.test.js +16 -2
- package/dist/src/pathmode.background.contract.test.js +69 -0
- package/dist/src/pathmode.settings.api.contract.test.js +9 -0
- package/dist/src/pkg.sidecar.contract.test.js +9 -3
- package/dist/src/platform/ExportProfile.js +58 -0
- package/dist/src/platform/PlatformCapabilities.js +45 -0
- package/dist/src/platform/PlatformCapabilities.test.js +30 -0
- package/dist/src/platform/RenderMaterializer.js +33 -0
- package/dist/src/platform/RenderMaterializer.test.js +32 -0
- package/dist/src/query_backend.external_http.integration.test.js +410 -0
- package/dist/src/reader_renderer.js +404 -3
- package/dist/src/reader_renderer.test.js +87 -0
- package/dist/src/release.godot.mirror.contract.test.js +73 -0
- package/dist/src/resources/ResourceRegistry.js +223 -0
- package/dist/src/resources/ResourceRegistry.test.js +61 -0
- package/dist/src/resources/types.js +2 -0
- package/dist/src/routes/agentWorkspaceDiagnostics.js +173 -0
- package/dist/src/routes/data.js +267 -0
- package/dist/src/routes/diagnostics.js +51 -0
- package/dist/src/routes/index.js +23 -0
- package/dist/src/routes/knowledge.js +968 -0
- package/dist/src/routes/markdown.js +287 -0
- package/dist/src/routes/notemd.js +565 -0
- package/dist/src/routes/registry.contract.test.js +130 -0
- package/dist/src/routes/render.js +285 -0
- package/dist/src/routes/runtimeRunbookRouteOps.js +149 -0
- package/dist/src/routes/runtimeRunbookRouteOps.test.js +194 -0
- package/dist/src/routes/settings.js +6 -0
- package/dist/src/routes/staticFiles.js +94 -0
- package/dist/src/routes/types.js +2 -0
- package/dist/src/runtime.transport.adapter.contract.test.js +81 -0
- package/dist/src/server.js +11090 -1549
- package/dist/src/server.migration.test.js +193 -21
- package/dist/src/server.port.fallback.contract.test.js +63 -0
- package/dist/src/session/SessionStateStore.js +81 -0
- package/dist/src/session/SessionStateStore.test.js +58 -0
- package/dist/src/session/types.js +2 -0
- package/dist/src/settings.runtime.contract.test.js +50 -0
- package/dist/src/shared/types.contract.test.js +107 -0
- package/dist/src/shared/types.js +22 -0
- package/dist/src/sidecar.replacement.boundary.contract.test.js +128 -0
- package/dist/src/sidecar.supply.readiness.contract.test.js +144 -0
- package/dist/src/source_manager.loadflow.test.js +46 -0
- package/dist/src/startup.layout.snapshot.contract.test.js +57 -0
- package/dist/src/tauri.frontend.build.contract.test.js +60 -0
- package/dist/src/tauri.sidecar.cleanup.contract.test.js +21 -0
- package/dist/src/utils/RuntimePaths.js +4 -13
- package/dist/src/utils/platform.js +153 -0
- package/dist/src/workflows/WorkflowArtifactStore.js +96 -0
- package/dist/src/workflows/WorkflowArtifactStore.test.js +80 -0
- package/dist/src/workflows/types.js +2 -0
- package/dist/src/workspace/WorkspaceRegistry.js +122 -0
- package/dist/src/workspace/WorkspaceRegistry.test.js +29 -0
- package/dist/src/workspace/types.js +2 -0
- package/package.json +53 -10
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QualityEvaluator = void 0;
|
|
4
|
+
class QualityEvaluator {
|
|
5
|
+
constructor(platform, defaultThresholds = {}) {
|
|
6
|
+
this.platform = platform;
|
|
7
|
+
this.defaultThresholds = defaultThresholds;
|
|
8
|
+
this.evaluationCount = 0;
|
|
9
|
+
this.snapshotCount = 0;
|
|
10
|
+
this.planEvaluationCount = 0;
|
|
11
|
+
this.lastEvaluationAt = null;
|
|
12
|
+
this.evaluationPassRateHistory = [];
|
|
13
|
+
// Domain-level analysis state
|
|
14
|
+
this.evaluationHistory = [];
|
|
15
|
+
this.lastSnapshot = null;
|
|
16
|
+
this.regressionCount = 0;
|
|
17
|
+
this.lastRegressionAt = null;
|
|
18
|
+
// Domain health scoring weights for composite metric
|
|
19
|
+
this.healthWeights = {
|
|
20
|
+
retestPassRateUplift: 0.25,
|
|
21
|
+
misconceptionReduction: 0.25,
|
|
22
|
+
evidenceRatio: 0.20,
|
|
23
|
+
pathEffectiveness: 0.20,
|
|
24
|
+
queryP95: 0.10,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// ─── Public API ─────────────────────────────────────────────────
|
|
28
|
+
async evaluate(r) {
|
|
29
|
+
this.validateEvaluationRequest(r);
|
|
30
|
+
this.evaluationCount++;
|
|
31
|
+
this.lastEvaluationAt = new Date().toISOString();
|
|
32
|
+
// Domain-level baseline enrichment: auto-fill baseline from last snapshot
|
|
33
|
+
const enriched = this.enrichWithLastSnapshot(r);
|
|
34
|
+
const result = await this.platform.evaluateLearningQuality(enriched);
|
|
35
|
+
// Domain-level analysis
|
|
36
|
+
const healthScore = this.computeHealthScore(result);
|
|
37
|
+
const driftedMetrics = this.detectMetricDrift(result);
|
|
38
|
+
const regressed = this.detectRegression(result);
|
|
39
|
+
this.evaluationPassRateHistory.push(result.overallPassed);
|
|
40
|
+
if (this.evaluationPassRateHistory.length > 200)
|
|
41
|
+
this.evaluationPassRateHistory.shift();
|
|
42
|
+
// Record evaluation for trend analysis
|
|
43
|
+
this.recordEvaluation(result, healthScore);
|
|
44
|
+
if (regressed) {
|
|
45
|
+
this.regressionCount++;
|
|
46
|
+
this.lastRegressionAt = new Date().toISOString();
|
|
47
|
+
}
|
|
48
|
+
return this.augmentEvaluationResponse(result, healthScore, driftedMetrics, regressed);
|
|
49
|
+
}
|
|
50
|
+
async captureSnapshot(r) {
|
|
51
|
+
this.snapshotCount++;
|
|
52
|
+
const response = await this.platform.captureLearningQualitySnapshot(r);
|
|
53
|
+
// Cache the latest snapshot for auto-baseline in evaluate()
|
|
54
|
+
if (response?.snapshot) {
|
|
55
|
+
this.lastSnapshot = {
|
|
56
|
+
snapshot: response.snapshot,
|
|
57
|
+
sampledAt: response.sampledAt || new Date().toISOString(),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// Domain-level snapshot metadata
|
|
61
|
+
return {
|
|
62
|
+
...response,
|
|
63
|
+
_domain: {
|
|
64
|
+
snapshotNumber: this.snapshotCount,
|
|
65
|
+
isReference: this.lastSnapshot === null,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
async queryHistory(r) {
|
|
70
|
+
const response = await this.platform.queryLearningQualityHistory(r);
|
|
71
|
+
return {
|
|
72
|
+
...response,
|
|
73
|
+
_domain: {
|
|
74
|
+
evaluationCount: this.evaluationCount,
|
|
75
|
+
regressionCount: this.regressionCount,
|
|
76
|
+
recentHealthScore: this.evaluationHistory.length > 0
|
|
77
|
+
? this.evaluationHistory[this.evaluationHistory.length - 1].healthScore
|
|
78
|
+
: null,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async queryTrend(r) {
|
|
83
|
+
const response = await this.platform.queryLearningQualityTrend(r);
|
|
84
|
+
const domainTrend = this.computeDomainTrend(10);
|
|
85
|
+
return { ...response, _domain: { domainTrend } };
|
|
86
|
+
}
|
|
87
|
+
getThresholds() {
|
|
88
|
+
return this.platform.getLearningQualityThresholds();
|
|
89
|
+
}
|
|
90
|
+
async evaluatePlanQuality(r) {
|
|
91
|
+
this.planEvaluationCount++;
|
|
92
|
+
const response = await this.platform.evaluateStudySessionPlanQuality(r);
|
|
93
|
+
// Domain-level plan quality analysis
|
|
94
|
+
const planAnalysis = this.analyzePlanQuality(r, response);
|
|
95
|
+
return {
|
|
96
|
+
...response,
|
|
97
|
+
_domain: {
|
|
98
|
+
planEvaluationNumber: this.planEvaluationCount,
|
|
99
|
+
planAnalysis,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
async queryPlanQualityHistory(r) {
|
|
104
|
+
return this.platform.queryStudySessionPlanQualityHistory(r);
|
|
105
|
+
}
|
|
106
|
+
async queryPlanQualityTrend(r) {
|
|
107
|
+
return this.platform.queryStudySessionPlanQualityTrend(r);
|
|
108
|
+
}
|
|
109
|
+
async queryPlanQualityRuntimeThresholds(r) {
|
|
110
|
+
return this.platform.queryStudySessionPlanQualityRuntimeThresholds(r);
|
|
111
|
+
}
|
|
112
|
+
// ─── Public accessors ───────────────────────────────────────────
|
|
113
|
+
getEvaluationCount() { return this.evaluationCount; }
|
|
114
|
+
recentPassRate(n = 50) {
|
|
115
|
+
const w = this.evaluationPassRateHistory.slice(-n);
|
|
116
|
+
return w.length === 0 ? 1 : w.filter(Boolean).length / w.length;
|
|
117
|
+
}
|
|
118
|
+
getRegressionCount() { return this.regressionCount; }
|
|
119
|
+
getEvaluationHistory() { return [...this.evaluationHistory]; }
|
|
120
|
+
getDiagnosticsSummary() {
|
|
121
|
+
const trend = this.computeDomainTrend(5);
|
|
122
|
+
return {
|
|
123
|
+
evaluationCount: this.evaluationCount,
|
|
124
|
+
snapshotCount: this.snapshotCount,
|
|
125
|
+
planEvaluationCount: this.planEvaluationCount,
|
|
126
|
+
lastEvaluationAt: this.lastEvaluationAt,
|
|
127
|
+
recentPassRate: Number((this.recentPassRate(50) * 100).toFixed(1)),
|
|
128
|
+
regressionCount: this.regressionCount,
|
|
129
|
+
lastRegressionAt: this.lastRegressionAt,
|
|
130
|
+
currentHealthScore: this.evaluationHistory.length > 0
|
|
131
|
+
? this.evaluationHistory[this.evaluationHistory.length - 1].healthScore
|
|
132
|
+
: null,
|
|
133
|
+
healthTrend: trend,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// ─── Private: validation ────────────────────────────────────────
|
|
137
|
+
validateEvaluationRequest(r) {
|
|
138
|
+
if (!r)
|
|
139
|
+
throw new Error('Quality evaluation request is required.');
|
|
140
|
+
if (!r?.userId)
|
|
141
|
+
throw new Error('userId is required for quality evaluation.');
|
|
142
|
+
}
|
|
143
|
+
// ─── Private: augmentation ──────────────────────────────────────
|
|
144
|
+
augmentEvaluationResponse(response, healthScore, driftedMetrics, regressed) {
|
|
145
|
+
return {
|
|
146
|
+
...response,
|
|
147
|
+
_domain: {
|
|
148
|
+
evaluationNumber: this.evaluationCount,
|
|
149
|
+
snapshotCount: this.snapshotCount,
|
|
150
|
+
recentPassRate: this.recentPassRate(20),
|
|
151
|
+
evaluatedAt: this.lastEvaluationAt,
|
|
152
|
+
healthScore,
|
|
153
|
+
driftedMetrics,
|
|
154
|
+
regressed,
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
// ─── Private: health scoring ────────────────────────────────────
|
|
159
|
+
/**
|
|
160
|
+
* Compute a composite health score (0-100) from gate deltas.
|
|
161
|
+
* Weights: retest uplift 25%, misconception reduction 25%,
|
|
162
|
+
* evidence ratio 20%, path effectiveness 20%, query P95 10%.
|
|
163
|
+
*/
|
|
164
|
+
computeHealthScore(result) {
|
|
165
|
+
const deltas = result?.deltas || {};
|
|
166
|
+
const gates = Array.isArray(result?.gates) ? result.gates : [];
|
|
167
|
+
const gateMap = new Map();
|
|
168
|
+
for (const gate of gates) {
|
|
169
|
+
gateMap.set(gate.gateId, gate.passed);
|
|
170
|
+
}
|
|
171
|
+
let score = 0;
|
|
172
|
+
// Retest uplift: normalize to 0-1 range (expected 0-20% uplift)
|
|
173
|
+
const uplift = Number(deltas.retestPassRateUpliftPct || 0);
|
|
174
|
+
const upliftScore = clamp(uplift / 20, 0, 1);
|
|
175
|
+
score += upliftScore * this.healthWeights.retestPassRateUplift;
|
|
176
|
+
// Misconception reduction: normalize to 0-1 range (expected 0-15% reduction)
|
|
177
|
+
const reduction = Number(deltas.misconceptionRecurrenceReductionPct || 0);
|
|
178
|
+
const reductionScore = clamp(reduction / 15, 0, 1);
|
|
179
|
+
score += reductionScore * this.healthWeights.misconceptionReduction;
|
|
180
|
+
// Evidence ratio: binary gate contributes, plus bonus for high ratio
|
|
181
|
+
const evidencePassed = gateMap.get('evidence_ratio') === true;
|
|
182
|
+
const evidenceScore = evidencePassed ? 0.8 : 0.3;
|
|
183
|
+
score += evidenceScore * this.healthWeights.evidenceRatio;
|
|
184
|
+
// Path effectiveness: normalize to 0-1 range (expected 5-30% lift)
|
|
185
|
+
const pathLift = Number(deltas.pathEffectivenessLiftPct || 0);
|
|
186
|
+
const pathScore = clamp(pathLift / 30, 0, 1);
|
|
187
|
+
score += pathScore * this.healthWeights.pathEffectiveness;
|
|
188
|
+
// Query P95: passed gate = full, otherwise scale by proximity
|
|
189
|
+
const queryPassed = gateMap.get('query_p95') === true;
|
|
190
|
+
const queryScore = queryPassed ? 1.0 : 0.3;
|
|
191
|
+
score += queryScore * this.healthWeights.queryP95;
|
|
192
|
+
return Number((score * 100).toFixed(1));
|
|
193
|
+
}
|
|
194
|
+
// ─── Private: metric drift detection ────────────────────────────
|
|
195
|
+
/**
|
|
196
|
+
* Detect significant metric drift between baseline and current.
|
|
197
|
+
* Flags any metric whose absolute change exceeds reasonable thresholds.
|
|
198
|
+
*/
|
|
199
|
+
detectMetricDrift(result) {
|
|
200
|
+
const drifted = [];
|
|
201
|
+
const baseline = result?.baseline || {};
|
|
202
|
+
const current = result?.current || {};
|
|
203
|
+
const driftThresholds = {
|
|
204
|
+
retestPassRatePct: 15,
|
|
205
|
+
misconceptionRecurrenceRatePct: 10,
|
|
206
|
+
evidenceBackedSuggestionRatioPct: 15,
|
|
207
|
+
averagePathMasteryGainPct: 12,
|
|
208
|
+
randomPathMasteryGainPct: 12,
|
|
209
|
+
queryP95Ms: 2000,
|
|
210
|
+
};
|
|
211
|
+
for (const [key, threshold] of Object.entries(driftThresholds)) {
|
|
212
|
+
const delta = Number((current[key] || 0) - (baseline[key] || 0));
|
|
213
|
+
if (Math.abs(delta) > threshold) {
|
|
214
|
+
const direction = delta > 0 ? '+' : '';
|
|
215
|
+
drifted.push(`${key}: ${direction}${Number(delta).toFixed(1)} (threshold: ${threshold})`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return drifted;
|
|
219
|
+
}
|
|
220
|
+
// ─── Private: regression detection ──────────────────────────────
|
|
221
|
+
/**
|
|
222
|
+
* Detect quality regression by comparing current gates against
|
|
223
|
+
* the previous evaluation. Regression = previously-passing gate now fails.
|
|
224
|
+
*/
|
|
225
|
+
detectRegression(result) {
|
|
226
|
+
if (this.evaluationHistory.length === 0)
|
|
227
|
+
return false;
|
|
228
|
+
const prev = this.evaluationHistory[this.evaluationHistory.length - 1];
|
|
229
|
+
const currentGates = Array.isArray(result?.gates) ? result.gates : [];
|
|
230
|
+
const currentGateMap = new Map();
|
|
231
|
+
for (const gate of currentGates) {
|
|
232
|
+
currentGateMap.set(gate.gateId, gate.passed);
|
|
233
|
+
}
|
|
234
|
+
// Check if any previously-passing gate now fails
|
|
235
|
+
for (const [gateId, wasPassed] of Object.entries(prev.gateResults)) {
|
|
236
|
+
if (wasPassed && currentGateMap.get(gateId) === false) {
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
// ─── Private: evaluation history ────────────────────────────────
|
|
243
|
+
recordEvaluation(result, healthScore) {
|
|
244
|
+
const gates = Array.isArray(result?.gates) ? result.gates : [];
|
|
245
|
+
const gateResults = {};
|
|
246
|
+
for (const gate of gates) {
|
|
247
|
+
gateResults[gate.gateId] = gate.passed;
|
|
248
|
+
}
|
|
249
|
+
this.evaluationHistory.push({
|
|
250
|
+
evaluatedAt: result?.evaluatedAt || new Date().toISOString(),
|
|
251
|
+
overallPassed: result?.overallPassed ?? false,
|
|
252
|
+
healthScore,
|
|
253
|
+
gateResults,
|
|
254
|
+
deltas: { ...(result?.deltas || {}) },
|
|
255
|
+
});
|
|
256
|
+
if (this.evaluationHistory.length > 100)
|
|
257
|
+
this.evaluationHistory.shift();
|
|
258
|
+
}
|
|
259
|
+
// ─── Private: auto-baseline from last snapshot ──────────────────
|
|
260
|
+
/**
|
|
261
|
+
* If no baseline is explicitly provided, use the last captured snapshot
|
|
262
|
+
* as an implicit baseline, enabling trend analysis without manual setup.
|
|
263
|
+
*/
|
|
264
|
+
enrichWithLastSnapshot(r) {
|
|
265
|
+
if (r?.baseline || !this.lastSnapshot)
|
|
266
|
+
return r;
|
|
267
|
+
return { ...r, baseline: this.lastSnapshot.snapshot };
|
|
268
|
+
}
|
|
269
|
+
// ─── Private: domain trend computation ──────────────────────────
|
|
270
|
+
computeDomainTrend(n) {
|
|
271
|
+
const window = this.evaluationHistory.slice(-n);
|
|
272
|
+
if (window.length < 2) {
|
|
273
|
+
return {
|
|
274
|
+
direction: 'insufficient_data',
|
|
275
|
+
recentHealthScore: window[0]?.healthScore ?? 0,
|
|
276
|
+
windowAvgHealthScore: window[0]?.healthScore ?? 0,
|
|
277
|
+
healthScoreDelta: 0,
|
|
278
|
+
snapshotCount: window.length,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
const mid = Math.floor(window.length / 2);
|
|
282
|
+
const recentAvg = window.slice(-mid).reduce((s, e) => s + e.healthScore, 0) / mid;
|
|
283
|
+
const earlierAvg = window.slice(0, mid).reduce((s, e) => s + e.healthScore, 0) / mid;
|
|
284
|
+
const delta = recentAvg - earlierAvg;
|
|
285
|
+
return {
|
|
286
|
+
direction: delta > 5 ? 'improving' : delta < -5 ? 'degrading' : 'stable',
|
|
287
|
+
recentHealthScore: window[window.length - 1].healthScore,
|
|
288
|
+
windowAvgHealthScore: Number((window.reduce((s, e) => s + e.healthScore, 0) / window.length).toFixed(1)),
|
|
289
|
+
healthScoreDelta: Number(delta.toFixed(1)),
|
|
290
|
+
snapshotCount: window.length,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
// ─── Private: plan quality analysis ─────────────────────────────
|
|
294
|
+
analyzePlanQuality(request, _response) {
|
|
295
|
+
return {
|
|
296
|
+
actionCount: Array.isArray(request?.actions) ? request.actions.length : 0,
|
|
297
|
+
hasExplicitFocus: Array.isArray(request?.focusAtomIds) && request.focusAtomIds.length > 0,
|
|
298
|
+
hasPathStrategy: typeof request?.pathStrategy === 'string' && request.pathStrategy.length > 0,
|
|
299
|
+
hasAutoPromote: request?.autoPromoteMemory === true,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
exports.QualityEvaluator = QualityEvaluator;
|
|
304
|
+
/** Clamp a value to [min, max]. */
|
|
305
|
+
function clamp(value, min, max) {
|
|
306
|
+
return value < min ? min : value > max ? max : value;
|
|
307
|
+
}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TutorRouter = void 0;
|
|
4
|
+
class TutorRouter {
|
|
5
|
+
constructor(platform) {
|
|
6
|
+
this.platform = platform;
|
|
7
|
+
this.actionExecutionCount = 0;
|
|
8
|
+
this.catalogFetchCount = 0;
|
|
9
|
+
this.telemetryFetchCount = 0;
|
|
10
|
+
this.actionKindCounts = {};
|
|
11
|
+
// Domain-level analysis state
|
|
12
|
+
this.confidenceHistory = [];
|
|
13
|
+
this.sourceEffectiveness = {
|
|
14
|
+
ruleEngine: { count: 0, avgConfidence: 0, avgEvidenceCount: 0 },
|
|
15
|
+
llmAdapter: { count: 0, avgConfidence: 0, avgEvidenceCount: 0, downgradeCount: 0, errorCount: 0 },
|
|
16
|
+
};
|
|
17
|
+
this.downgradeEvents = [];
|
|
18
|
+
this.actionKindEffectiveness = new Map();
|
|
19
|
+
// Domain budgets
|
|
20
|
+
this.budgets = {
|
|
21
|
+
minConfidenceForAcceptance: 0.5,
|
|
22
|
+
downgradeAlertThreshold: 10, // alert when downgrade rate exceeds 10% in window
|
|
23
|
+
minEvidenceBindingRatio: 0.3, // minimum acceptable evidence-backed trace ratio
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
// ─── Public API ─────────────────────────────────────────────────
|
|
27
|
+
async getCatalog() {
|
|
28
|
+
this.catalogFetchCount++;
|
|
29
|
+
const catalog = await this.platform.getTutorAdapterCatalog();
|
|
30
|
+
// Domain-level catalog augmentation
|
|
31
|
+
const adapterCount = Array.isArray(catalog?.adapters) ? catalog.adapters.length : 0;
|
|
32
|
+
return {
|
|
33
|
+
...catalog,
|
|
34
|
+
_domain: {
|
|
35
|
+
catalogFetchNumber: this.catalogFetchCount,
|
|
36
|
+
adapterCount,
|
|
37
|
+
hasFallbackRuleEngine: true,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async getTelemetry() {
|
|
42
|
+
this.telemetryFetchCount++;
|
|
43
|
+
const telemetry = await this.platform.getTutorAdapterTelemetry();
|
|
44
|
+
// Domain-level source effectiveness summary
|
|
45
|
+
return {
|
|
46
|
+
...telemetry,
|
|
47
|
+
_domain: {
|
|
48
|
+
telemetryFetchNumber: this.telemetryFetchCount,
|
|
49
|
+
sourceEffectiveness: this.getSourceEffectiveness(),
|
|
50
|
+
downgradeRate: this.getDowngradeRate(50),
|
|
51
|
+
topActionKinds: this.getTopActionKinds(5),
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
async queryTraceDiagnostics(r) {
|
|
56
|
+
const response = await this.platform.queryTutorTraceDiagnostics(r);
|
|
57
|
+
// Domain-level trace quality analysis
|
|
58
|
+
const traceQuality = this.analyzeTraceQuality(response);
|
|
59
|
+
return { ...response, _domain: { traceQuality } };
|
|
60
|
+
}
|
|
61
|
+
async queryProviderTrendDiagnostics(r) {
|
|
62
|
+
const response = await this.platform.queryTutorProviderTrendDiagnostics(r);
|
|
63
|
+
// Domain-level provider preference analysis
|
|
64
|
+
const providerAnalysis = this.analyzeProviderTrend(response);
|
|
65
|
+
return { ...response, _domain: { providerAnalysis } };
|
|
66
|
+
}
|
|
67
|
+
async queryProviderTrendHistory(r) {
|
|
68
|
+
return this.platform.queryTutorProviderTrendHistory(r);
|
|
69
|
+
}
|
|
70
|
+
async executeAction(r) {
|
|
71
|
+
this.validateActionRequest(r);
|
|
72
|
+
this.actionExecutionCount++;
|
|
73
|
+
const kind = String(r?.actionKind ?? 'unknown');
|
|
74
|
+
this.actionKindCounts[kind] = (this.actionKindCounts[kind] || 0) + 1;
|
|
75
|
+
const response = await this.platform.executeTutorAction(r);
|
|
76
|
+
// Domain-level post-execution analysis
|
|
77
|
+
const trace = response?.trace;
|
|
78
|
+
if (trace) {
|
|
79
|
+
this.recordConfidence(trace, kind);
|
|
80
|
+
this.trackSourceEffectiveness(trace);
|
|
81
|
+
this.trackActionKindEffectiveness(kind, trace);
|
|
82
|
+
this.detectDowngrade(trace, kind);
|
|
83
|
+
}
|
|
84
|
+
return this.augmentActionResponse(response, kind);
|
|
85
|
+
}
|
|
86
|
+
// ─── Public accessors ───────────────────────────────────────────
|
|
87
|
+
getActionExecutionCount() { return this.actionExecutionCount; }
|
|
88
|
+
getSourceEffectiveness() {
|
|
89
|
+
return {
|
|
90
|
+
ruleEngine: { ...this.sourceEffectiveness.ruleEngine },
|
|
91
|
+
llmAdapter: { ...this.sourceEffectiveness.llmAdapter },
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
getDowngradeRate(windowSize = 50) {
|
|
95
|
+
const totalLlm = this.sourceEffectiveness.llmAdapter.count;
|
|
96
|
+
if (totalLlm === 0)
|
|
97
|
+
return 0;
|
|
98
|
+
const downgraded = this.sourceEffectiveness.llmAdapter.downgradeCount;
|
|
99
|
+
return Number(((downgraded / totalLlm) * 100).toFixed(1));
|
|
100
|
+
}
|
|
101
|
+
getConfidenceHistory() { return [...this.confidenceHistory]; }
|
|
102
|
+
getDowngradeEvents() { return [...this.downgradeEvents]; }
|
|
103
|
+
getDiagnosticsSummary() {
|
|
104
|
+
return {
|
|
105
|
+
actionExecutionCount: this.actionExecutionCount,
|
|
106
|
+
catalogFetchCount: this.catalogFetchCount,
|
|
107
|
+
telemetryFetchCount: this.telemetryFetchCount,
|
|
108
|
+
actionKindDistribution: { ...this.actionKindCounts },
|
|
109
|
+
sourceEffectiveness: this.getSourceEffectiveness(),
|
|
110
|
+
downgradeRate: this.getDowngradeRate(50),
|
|
111
|
+
downgradeEventCount: this.downgradeEvents.length,
|
|
112
|
+
recentDowngrades: this.downgradeEvents.slice(-5),
|
|
113
|
+
confidenceTrend: this.computeConfidenceTrend(20),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// ─── Private: validation ────────────────────────────────────────
|
|
117
|
+
validateActionRequest(r) {
|
|
118
|
+
if (!r)
|
|
119
|
+
throw new Error('Tutor action request is required.');
|
|
120
|
+
if (!r?.userId)
|
|
121
|
+
throw new Error('userId is required for tutor actions.');
|
|
122
|
+
if (!r?.actionKind)
|
|
123
|
+
throw new Error('actionKind is required for tutor actions.');
|
|
124
|
+
}
|
|
125
|
+
// ─── Private: augmentation ──────────────────────────────────────
|
|
126
|
+
augmentActionResponse(response, kind) {
|
|
127
|
+
const trace = response?.trace;
|
|
128
|
+
const evidenceCount = Array.isArray(trace?.evidenceSpanIds) ? trace.evidenceSpanIds.length : 0;
|
|
129
|
+
const source = trace?.source ?? 'unknown';
|
|
130
|
+
return {
|
|
131
|
+
...response,
|
|
132
|
+
_domain: {
|
|
133
|
+
actionKind: kind,
|
|
134
|
+
executionNumber: this.actionExecutionCount,
|
|
135
|
+
kindCount: this.actionKindCounts[kind] || 1,
|
|
136
|
+
source,
|
|
137
|
+
confidence: trace?.confidence ?? null,
|
|
138
|
+
evidenceBindingCount: evidenceCount,
|
|
139
|
+
evidenceBindingScore: this.scoreEvidenceBinding(evidenceCount, kind),
|
|
140
|
+
qualityFlag: this.flagTraceQuality(trace),
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// ─── Private: confidence tracking ───────────────────────────────
|
|
145
|
+
recordConfidence(trace, actionKind) {
|
|
146
|
+
const evidenceCount = Array.isArray(trace?.evidenceSpanIds) ? trace.evidenceSpanIds.length : 0;
|
|
147
|
+
this.confidenceHistory.push({
|
|
148
|
+
timestamp: trace?.createdAt || new Date().toISOString(),
|
|
149
|
+
actionKind,
|
|
150
|
+
source: trace?.source ?? 'unknown',
|
|
151
|
+
confidence: Number(trace?.confidence ?? 0),
|
|
152
|
+
evidenceCount,
|
|
153
|
+
});
|
|
154
|
+
if (this.confidenceHistory.length > 200)
|
|
155
|
+
this.confidenceHistory.shift();
|
|
156
|
+
}
|
|
157
|
+
computeConfidenceTrend(n) {
|
|
158
|
+
const window = this.confidenceHistory.slice(-n);
|
|
159
|
+
if (window.length < 2) {
|
|
160
|
+
return {
|
|
161
|
+
direction: 'insufficient_data',
|
|
162
|
+
recentAvg: window[0]?.confidence ?? 0,
|
|
163
|
+
windowAvg: window[0]?.confidence ?? 0,
|
|
164
|
+
snapshotCount: window.length,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
const mid = Math.floor(window.length / 2);
|
|
168
|
+
const recentAvg = window.slice(-mid).reduce((s, e) => s + e.confidence, 0) / mid;
|
|
169
|
+
const earlierAvg = window.slice(0, mid).reduce((s, e) => s + e.confidence, 0) / mid;
|
|
170
|
+
const delta = recentAvg - earlierAvg;
|
|
171
|
+
return {
|
|
172
|
+
direction: delta > 0.1 ? 'improving' : delta < -0.1 ? 'declining' : 'stable',
|
|
173
|
+
recentAvg: Number(recentAvg.toFixed(4)),
|
|
174
|
+
windowAvg: Number((window.reduce((s, e) => s + e.confidence, 0) / window.length).toFixed(4)),
|
|
175
|
+
snapshotCount: window.length,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
// ─── Private: source effectiveness ──────────────────────────────
|
|
179
|
+
trackSourceEffectiveness(trace) {
|
|
180
|
+
const source = trace?.source;
|
|
181
|
+
const evidenceCount = Array.isArray(trace?.evidenceSpanIds) ? trace.evidenceSpanIds.length : 0;
|
|
182
|
+
if (source === 'rule-engine') {
|
|
183
|
+
const re = this.sourceEffectiveness.ruleEngine;
|
|
184
|
+
re.count++;
|
|
185
|
+
re.avgConfidence = Number(((re.avgConfidence * (re.count - 1) + (trace?.confidence || 0)) / re.count).toFixed(4));
|
|
186
|
+
re.avgEvidenceCount = Number(((re.avgEvidenceCount * (re.count - 1) + evidenceCount) / re.count).toFixed(2));
|
|
187
|
+
}
|
|
188
|
+
else if (source === 'llm-adapter') {
|
|
189
|
+
const la = this.sourceEffectiveness.llmAdapter;
|
|
190
|
+
la.count++;
|
|
191
|
+
la.avgConfidence = Number(((la.avgConfidence * (la.count - 1) + (trace?.confidence || 0)) / la.count).toFixed(4));
|
|
192
|
+
la.avgEvidenceCount = Number(((la.avgEvidenceCount * (la.count - 1) + evidenceCount) / la.count).toFixed(2));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// ─── Private: action kind effectiveness ─────────────────────────
|
|
196
|
+
trackActionKindEffectiveness(kind, trace) {
|
|
197
|
+
let entry = this.actionKindEffectiveness.get(kind);
|
|
198
|
+
if (!entry) {
|
|
199
|
+
entry = { count: 0, totalConfidence: 0, evidenceBackedCount: 0 };
|
|
200
|
+
this.actionKindEffectiveness.set(kind, entry);
|
|
201
|
+
}
|
|
202
|
+
entry.count++;
|
|
203
|
+
entry.totalConfidence += Number(trace?.confidence || 0);
|
|
204
|
+
const evidenceCount = Array.isArray(trace?.evidenceSpanIds) ? trace.evidenceSpanIds.length : 0;
|
|
205
|
+
if (evidenceCount > 0)
|
|
206
|
+
entry.evidenceBackedCount++;
|
|
207
|
+
}
|
|
208
|
+
getTopActionKinds(n) {
|
|
209
|
+
return [...this.actionKindEffectiveness.entries()]
|
|
210
|
+
.sort((a, b) => b[1].count - a[1].count)
|
|
211
|
+
.slice(0, n)
|
|
212
|
+
.map(([kind, stats]) => ({
|
|
213
|
+
kind,
|
|
214
|
+
count: stats.count,
|
|
215
|
+
avgConfidence: Number((stats.totalConfidence / stats.count).toFixed(4)),
|
|
216
|
+
evidenceRatio: Number(((stats.evidenceBackedCount / stats.count) * 100).toFixed(1)),
|
|
217
|
+
}));
|
|
218
|
+
}
|
|
219
|
+
// ─── Private: downgrade detection ───────────────────────────────
|
|
220
|
+
detectDowngrade(trace, actionKind) {
|
|
221
|
+
const source = trace?.source;
|
|
222
|
+
const confidence = Number(trace?.confidence || 0);
|
|
223
|
+
const notes = String(trace?.notes || '');
|
|
224
|
+
// Track LLM adapter downgrades (responses rejected due to low confidence)
|
|
225
|
+
if (source === 'llm-adapter' && notes.includes('downgraded')) {
|
|
226
|
+
this.sourceEffectiveness.llmAdapter.downgradeCount++;
|
|
227
|
+
this.downgradeEvents.push({
|
|
228
|
+
timestamp: trace?.createdAt || new Date().toISOString(),
|
|
229
|
+
actionKind,
|
|
230
|
+
reason: notes,
|
|
231
|
+
confidence,
|
|
232
|
+
});
|
|
233
|
+
if (this.downgradeEvents.length > 100)
|
|
234
|
+
this.downgradeEvents.shift();
|
|
235
|
+
}
|
|
236
|
+
// Track LLM adapter errors (fallback used)
|
|
237
|
+
if (source === 'llm-adapter' && (notes.includes('failed') || notes.includes('fallback'))) {
|
|
238
|
+
this.sourceEffectiveness.llmAdapter.errorCount++;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// ─── Private: evidence binding scoring ──────────────────────────
|
|
242
|
+
scoreEvidenceBinding(evidenceCount, actionKind) {
|
|
243
|
+
// Different action kinds have different evidence expectations
|
|
244
|
+
const expectedEvidence = {
|
|
245
|
+
explain: 2,
|
|
246
|
+
quiz: 1,
|
|
247
|
+
review: 2,
|
|
248
|
+
analyze_answer: 1,
|
|
249
|
+
summarize: 1,
|
|
250
|
+
};
|
|
251
|
+
const expected = expectedEvidence[actionKind] ?? 1;
|
|
252
|
+
const score = evidenceCount >= expected ? 1 : evidenceCount / Math.max(1, expected);
|
|
253
|
+
return {
|
|
254
|
+
score: Number(score.toFixed(2)),
|
|
255
|
+
level: score >= 1 ? 'full' : score >= 0.5 ? 'partial' : 'insufficient',
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
// ─── Private: trace quality flagging ────────────────────────────
|
|
259
|
+
flagTraceQuality(trace) {
|
|
260
|
+
if (!trace)
|
|
261
|
+
return 'unknown';
|
|
262
|
+
const confidence = Number(trace?.confidence || 0);
|
|
263
|
+
const evidenceCount = Array.isArray(trace?.evidenceSpanIds) ? trace.evidenceSpanIds.length : 0;
|
|
264
|
+
const source = trace?.source;
|
|
265
|
+
if (source === 'llm-adapter' && confidence < this.budgets.minConfidenceForAcceptance) {
|
|
266
|
+
return 'unreliable';
|
|
267
|
+
}
|
|
268
|
+
if (evidenceCount === 0 && source === 'llm-adapter') {
|
|
269
|
+
return 'unverified';
|
|
270
|
+
}
|
|
271
|
+
if (confidence >= 0.8 && evidenceCount >= 2) {
|
|
272
|
+
return 'high_quality';
|
|
273
|
+
}
|
|
274
|
+
if (confidence >= 0.6 && evidenceCount >= 1) {
|
|
275
|
+
return 'acceptable';
|
|
276
|
+
}
|
|
277
|
+
return 'needs_review';
|
|
278
|
+
}
|
|
279
|
+
// ─── Private: trace quality analysis ────────────────────────────
|
|
280
|
+
analyzeTraceQuality(response) {
|
|
281
|
+
const items = Array.isArray(response?.items) ? response.items : [];
|
|
282
|
+
const dist = {};
|
|
283
|
+
let totalConfidence = 0;
|
|
284
|
+
let evidenceBound = 0;
|
|
285
|
+
for (const item of items) {
|
|
286
|
+
const flag = this.flagTraceQuality(item?.trace);
|
|
287
|
+
dist[flag] = (dist[flag] || 0) + 1;
|
|
288
|
+
totalConfidence += Number(item?.trace?.confidence || 0);
|
|
289
|
+
const evidenceCount = Array.isArray(item?.trace?.evidenceSpanIds) ? item.trace.evidenceSpanIds.length : 0;
|
|
290
|
+
if (evidenceCount > 0)
|
|
291
|
+
evidenceBound++;
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
qualityDistribution: dist,
|
|
295
|
+
evidenceBindingRate: items.length > 0
|
|
296
|
+
? Number(((evidenceBound / items.length) * 100).toFixed(1))
|
|
297
|
+
: 0,
|
|
298
|
+
averageConfidence: items.length > 0
|
|
299
|
+
? Number((totalConfidence / items.length).toFixed(4))
|
|
300
|
+
: 0,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
// ─── Private: provider trend analysis ───────────────────────────
|
|
304
|
+
analyzeProviderTrend(response) {
|
|
305
|
+
const providers = Array.isArray(response?.providers) ? response.providers : [];
|
|
306
|
+
return {
|
|
307
|
+
providerCount: providers.length,
|
|
308
|
+
hasActiveAdapter: this.sourceEffectiveness.llmAdapter.count > 0,
|
|
309
|
+
ruleEngineFallbackActive: true,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
exports.TutorRouter = TutorRouter;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Domain classes extracted from KnowledgeLearningPlatform.
|
|
4
|
+
*
|
|
5
|
+
* Each domain class wraps the platform behind a clean interface.
|
|
6
|
+
* Implementations are gradually migrated from the monolithic
|
|
7
|
+
* KnowledgeLearningPlatform into these domain classes.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* const ingestor = new KnowledgeIngestor(platform);
|
|
11
|
+
* const querier = new KnowledgeQuerier(platform);
|
|
12
|
+
* const conv = new ConversationManager(platform);
|
|
13
|
+
* const mastery = new MasteryEngine(platform);
|
|
14
|
+
* const quality = new QualityEvaluator(platform, thresholds);
|
|
15
|
+
* const tutor = new TutorRouter(platform);
|
|
16
|
+
* const memory = new MemoryPolicyManager(platform);
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.MemoryPolicyManager = exports.TutorRouter = exports.QualityEvaluator = exports.MasteryEngine = exports.ConversationManager = exports.KnowledgeQuerier = exports.KnowledgeIngestor = void 0;
|
|
20
|
+
var KnowledgeIngestor_1 = require("./KnowledgeIngestor");
|
|
21
|
+
Object.defineProperty(exports, "KnowledgeIngestor", { enumerable: true, get: function () { return KnowledgeIngestor_1.KnowledgeIngestor; } });
|
|
22
|
+
var KnowledgeQuerier_1 = require("./KnowledgeQuerier");
|
|
23
|
+
Object.defineProperty(exports, "KnowledgeQuerier", { enumerable: true, get: function () { return KnowledgeQuerier_1.KnowledgeQuerier; } });
|
|
24
|
+
var ConversationManager_1 = require("./ConversationManager");
|
|
25
|
+
Object.defineProperty(exports, "ConversationManager", { enumerable: true, get: function () { return ConversationManager_1.ConversationManager; } });
|
|
26
|
+
var MasteryEngine_1 = require("./MasteryEngine");
|
|
27
|
+
Object.defineProperty(exports, "MasteryEngine", { enumerable: true, get: function () { return MasteryEngine_1.MasteryEngine; } });
|
|
28
|
+
var QualityEvaluator_1 = require("./QualityEvaluator");
|
|
29
|
+
Object.defineProperty(exports, "QualityEvaluator", { enumerable: true, get: function () { return QualityEvaluator_1.QualityEvaluator; } });
|
|
30
|
+
var TutorRouter_1 = require("./TutorRouter");
|
|
31
|
+
Object.defineProperty(exports, "TutorRouter", { enumerable: true, get: function () { return TutorRouter_1.TutorRouter; } });
|
|
32
|
+
var MemoryPolicyManager_1 = require("./MemoryPolicyManager");
|
|
33
|
+
Object.defineProperty(exports, "MemoryPolicyManager", { enumerable: true, get: function () { return MemoryPolicyManager_1.MemoryPolicyManager; } });
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Domain base types for the KnowledgeLearningPlatform decomposition.
|
|
4
|
+
* Uses types from the public API surface (../types) and defines
|
|
5
|
+
* local interfaces for internal types not in the public contract.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|