noteconnection 1.8.0 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/README.md +257 -1803
  2. package/dist/src/agent_workspace.contract.parity.test.js +105 -421
  3. package/dist/src/agent_workspace.frontend.test.js +410 -11
  4. package/dist/src/android.knowledgebase.picker.contract.test.js +102 -0
  5. package/dist/src/appimage.patchelf.test.js +113 -0
  6. package/dist/src/appimage.portability.test.js +156 -0
  7. package/dist/src/appimage.update.test.js +127 -0
  8. package/dist/src/backend/FileLoader.js +18 -4
  9. package/dist/src/backend/FileLoader.test.js +125 -0
  10. package/dist/src/backend/GraphBuilder.identity.test.js +86 -0
  11. package/dist/src/backend/GraphBuilder.js +66 -18
  12. package/dist/src/backend/GraphBuilder.matching.test.js +127 -0
  13. package/dist/src/backend/GraphMetrics.js +0 -3
  14. package/dist/src/backend/ResourceIdentity.js +155 -0
  15. package/dist/src/backend/ResourceIdentity.test.js +113 -0
  16. package/dist/src/backend/algorithms/CycleDetection.js +0 -1
  17. package/dist/src/backend/algorithms/HybridEngine.js +0 -3
  18. package/dist/src/backend/algorithms/LayoutEngine.js +0 -1
  19. package/dist/src/backend/algorithms/StatisticalAnalyzer.js +0 -4
  20. package/dist/src/backend/algorithms/TopologicalSort.js +0 -2
  21. package/dist/src/backend/build_dag.js +0 -1
  22. package/dist/src/capacitor.bridge.serialization.contract.test.js +3 -0
  23. package/dist/src/capacitor.runtime.contract.test.js +11 -2
  24. package/dist/src/core/Graph.js +138 -42
  25. package/dist/src/core/Graph.test.js +74 -0
  26. package/dist/src/core/NoteConnection.js +2 -2
  27. package/dist/src/core/PathBridge.js +265 -2
  28. package/dist/src/core/ResourceReference.js +17 -0
  29. package/dist/src/desktop.godot.pack.test.js +142 -0
  30. package/dist/src/desktop.runtime.graph.test.js +66 -0
  31. package/dist/src/export/WorkspaceExportBundle.js +44 -0
  32. package/dist/src/export/WorkspaceExportBundle.test.js +61 -0
  33. package/dist/src/foundation.release.evidence.contract.test.js +127 -9
  34. package/dist/src/foundation.sqlite.runtime.contract.test.js +6 -0
  35. package/dist/src/frontend/README.md +257 -1803
  36. package/dist/src/frontend/agent_workspace.js +665 -7
  37. package/dist/src/frontend/index.html +31 -2
  38. package/dist/src/frontend/knowledge_projection_contract.js +230 -0
  39. package/dist/src/frontend/knowledge_projection_store.js +214 -0
  40. package/dist/src/frontend/libs/path_core.js +158 -42
  41. package/dist/src/frontend/locales/en.json +32 -0
  42. package/dist/src/frontend/locales/zh.json +32 -0
  43. package/dist/src/frontend/mobile_budget_runtime.js +33 -0
  44. package/dist/src/frontend/mobile_exact_analyzer.js +393 -0
  45. package/dist/src/frontend/mobile_identity_contract.js +221 -0
  46. package/dist/src/frontend/mobile_semantic_comparator.js +264 -0
  47. package/dist/src/frontend/path.html +6 -2
  48. package/dist/src/frontend/simulationWorker.js +1 -1
  49. package/dist/src/frontend/source_manager.js +110 -4
  50. package/dist/src/frontend/storage_provider.js +661 -71
  51. package/dist/src/frontend/styles.css +107 -13
  52. package/dist/src/frontend/workspace_panes.js +111 -7
  53. package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
  54. package/dist/src/graph.answer.operator.contract.test.js +72 -0
  55. package/dist/src/index.js +6 -2
  56. package/dist/src/index.knowledge-root.test.js +118 -0
  57. package/dist/src/indexing/IndexLifecycle.js +22 -0
  58. package/dist/src/indexing/IndexLifecycle.test.js +24 -0
  59. package/dist/src/knowledge.api.contract.test.js +4 -2
  60. package/dist/src/knowledge_projection.contract.test.js +134 -0
  61. package/dist/src/knowledge_projection_store.test.js +200 -0
  62. package/dist/src/learning/AnswerQualityEvaluation.js +153 -0
  63. package/dist/src/learning/AnswerQualityEvaluation.test.js +118 -0
  64. package/dist/src/learning/KnowledgeLearningPlatform.js +4687 -3892
  65. package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +418 -0
  66. package/dist/src/learning/KnowledgeLearningPlatform.test.js +243 -6
  67. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +25 -1
  68. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +13 -5
  69. package/dist/src/learning/MeasurementEvidenceConflicts.test.js +78 -0
  70. package/dist/src/learning/PublicAnswerContract.test.js +85 -0
  71. package/dist/src/learning/PublicEvidenceSelection.test.js +94 -0
  72. package/dist/src/learning/PublicMeasurementDisclosure.test.js +54 -0
  73. package/dist/src/learning/agentConversationExecution.js +211 -0
  74. package/dist/src/learning/agentConversationExecution.test.js +209 -0
  75. package/dist/src/learning/agentConversationSerialization.js +266 -0
  76. package/dist/src/learning/agentConversationSerialization.test.js +165 -0
  77. package/dist/src/learning/agentResponseBudget.js +179 -0
  78. package/dist/src/learning/agentResponseBudget.test.js +97 -0
  79. package/dist/src/learning/agentWorkspaceCapabilityContracts.js +65 -0
  80. package/dist/src/learning/answerReleaseReview.js +1191 -250
  81. package/dist/src/learning/answerReleaseReview.test.js +1293 -7
  82. package/dist/src/learning/answerTaskPlan.js +473 -0
  83. package/dist/src/learning/conversationComposer.js +627 -386
  84. package/dist/src/learning/conversationComposer.test.js +1403 -0
  85. package/dist/src/learning/evidenceContextAssembler.js +312 -120
  86. package/dist/src/learning/graphAnswerCoverage.js +37 -0
  87. package/dist/src/learning/graphAnswerCoverage.test.js +93 -0
  88. package/dist/src/learning/graphAnswerCoverageCalibration.js +59 -0
  89. package/dist/src/learning/graphAnswerCoverageCalibration.test.js +46 -0
  90. package/dist/src/learning/graphAnswerFacts.js +94 -0
  91. package/dist/src/learning/graphAnswerFacts.test.js +39 -0
  92. package/dist/src/learning/graphAnswerPlan.js +908 -0
  93. package/dist/src/learning/graphAnswerPlan.test.js +907 -0
  94. package/dist/src/learning/graphAnswerQualityCalibration.js +255 -0
  95. package/dist/src/learning/graphAnswerQualityCalibration.test.js +72 -0
  96. package/dist/src/learning/graphAnswerQualityPolicy.js +30 -0
  97. package/dist/src/learning/graphClaimMatcher.js +104 -0
  98. package/dist/src/learning/graphConditionedContext.js +109 -0
  99. package/dist/src/learning/graphConditionedContext.test.js +99 -0
  100. package/dist/src/learning/graphContextAssembler.js +3 -13
  101. package/dist/src/learning/graphContextAssembler.test.js +2 -2
  102. package/dist/src/learning/graphExpansionPolicy.js +22 -0
  103. package/dist/src/learning/graphExpansionPolicy.test.js +33 -0
  104. package/dist/src/learning/identityMetadata.test.js +26 -0
  105. package/dist/src/learning/index.js +1 -0
  106. package/dist/src/learning/mobileAnswerProjection.js +104 -0
  107. package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
  108. package/dist/src/learning/queryBackend.js +34 -10
  109. package/dist/src/learning/queryBackend.test.js +21 -0
  110. package/dist/src/learning/ragContextPack.js +115 -16
  111. package/dist/src/learning/ragContextPack.test.js +151 -0
  112. package/dist/src/learning/ragEvidenceQuality.js +96 -0
  113. package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
  114. package/dist/src/learning/ragPublicText.js +67 -4
  115. package/dist/src/learning/ragPublicText.test.js +57 -0
  116. package/dist/src/learning/ragSufficiencyJudge.js +11 -1
  117. package/dist/src/learning/ragSufficiencyProviderJudge.js +16 -26
  118. package/dist/src/learning/ragSufficiencyProviderJudge.test.js +51 -0
  119. package/dist/src/learning/requestNormalization.js +106 -0
  120. package/dist/src/learning/requestNormalization.test.js +101 -0
  121. package/dist/src/learning/store.js +116 -12
  122. package/dist/src/learning/store.test.js +299 -0
  123. package/dist/src/learning/vectorAccelerationAdapter.js +22 -6
  124. package/dist/src/learning/vectorAccelerationAdapter.test.js +30 -0
  125. package/dist/src/learning/workspaceHydration.js +168 -0
  126. package/dist/src/learning/workspaceHydration.test.js +30 -0
  127. package/dist/src/license.policy.contract.test.js +9 -4
  128. package/dist/src/markdown/MarkdownGateway.js +4 -0
  129. package/dist/src/markdown/MarkdownGateway.test.js +59 -0
  130. package/dist/src/middleware/SseResponseWriter.js +122 -0
  131. package/dist/src/middleware/SseResponseWriter.test.js +54 -0
  132. package/dist/src/middleware/auth.js +28 -7
  133. package/dist/src/middleware/auth.test.js +33 -0
  134. package/dist/src/middleware/index.js +2 -1
  135. package/dist/src/mobile.android.evidence.contract.test.js +146 -0
  136. package/dist/src/mobile.android.signing.contract.test.js +66 -0
  137. package/dist/src/mobile.artifact.contract.test.js +144 -0
  138. package/dist/src/mobile.budget.contract.test.js +90 -0
  139. package/dist/src/mobile.canonical-id.readiness.test.js +54 -0
  140. package/dist/src/mobile.graph.parity.contract.test.js +207 -0
  141. package/dist/src/mobile.identity.contract.test.js +66 -0
  142. package/dist/src/mobile.identity.corpus.manifest.test.js +72 -0
  143. package/dist/src/mobile.identity.corpus.test.js +40 -0
  144. package/dist/src/mobile.native.recovery.contract.test.js +64 -0
  145. package/dist/src/mobile.pipeline.test.js +11 -1
  146. package/dist/src/mobile.profile.contract.test.js +225 -0
  147. package/dist/src/mobile.semantic.parity.test.js +92 -0
  148. package/dist/src/mobile_exact_analyzer.test.js +113 -0
  149. package/dist/src/notemd/ContentGenerator.js +4 -9
  150. package/dist/src/notemd/FileProcessor.js +4 -9
  151. package/dist/src/notemd/NotemdService.js +12 -17
  152. package/dist/src/notemd/Translator.js +4 -9
  153. package/dist/src/notemd/progressReporter.js +9 -0
  154. package/dist/src/notemd.server.integration.test.js +119 -4
  155. package/dist/src/notemd.workflow.pipeline.test.js +1 -1
  156. package/dist/src/pathbridge.handshake.contract.test.js +29 -0
  157. package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
  158. package/dist/src/pathcore.bundle.contract.test.js +8 -0
  159. package/dist/src/platform/ExportProfile.js +28 -0
  160. package/dist/src/platform/MobileBudget.js +11 -0
  161. package/dist/src/platform/PlatformCapabilities.js +14 -0
  162. package/dist/src/platform/PlatformCapabilities.test.js +6 -0
  163. package/dist/src/query_backend.external_http.integration.test.js +2 -2
  164. package/dist/src/release.godot.mirror.contract.test.js +28 -4
  165. package/dist/src/resources/ResourceRegistry.js +40 -0
  166. package/dist/src/resources/ResourceRegistry.test.js +36 -0
  167. package/dist/src/routes/index.js +0 -4
  168. package/dist/src/routes/knowledge.js +46 -33
  169. package/dist/src/routes/knowledgePayload.js +185 -0
  170. package/dist/src/routes/knowledgePayload.test.js +53 -0
  171. package/dist/src/routes/markdown.js +8 -0
  172. package/dist/src/routes/notemd.js +990 -234
  173. package/dist/src/routes/registry.contract.test.js +5 -2
  174. package/dist/src/routes/registry.shadow.contract.test.js +22 -0
  175. package/dist/src/routes/render.js +14 -51
  176. package/dist/src/runtime.capabilities.test.js +18 -2
  177. package/dist/src/server.js +566 -1090
  178. package/dist/src/server.migration.test.js +417 -15
  179. package/dist/src/sidecar.build.lock.contract.test.js +201 -0
  180. package/dist/src/sidecar.freshness.contract.test.js +184 -0
  181. package/dist/src/sidecar.replacement.boundary.contract.test.js +6 -3
  182. package/dist/src/sidecar.supply.readiness.contract.test.js +11 -0
  183. package/dist/src/simulation.worker.offline.test.js +104 -0
  184. package/dist/src/storage.provider.capacitor.content.contract.test.js +4 -1
  185. package/dist/src/storage.provider.contract.test.js +152 -1
  186. package/dist/src/tauri.frontend.build.contract.test.js +8 -0
  187. package/dist/src/tauri.window.evidence.execution.test.js +68 -0
  188. package/dist/src/utils/RuntimePaths.js +6 -0
  189. package/dist/src/utils/RuntimePaths.test.js +27 -0
  190. package/dist/src/windows.installer.build.test.js +109 -0
  191. package/dist/src/windows.installer.payload.test.js +76 -0
  192. package/dist/src/windows.installer.runtime.test.js +69 -0
  193. package/dist/src/workspace/WorkspaceRegistry.js +13 -0
  194. package/package.json +32 -10
  195. package/dist/src/routes/data.js +0 -267
  196. package/dist/src/routes/diagnostics.js +0 -51
@@ -35,441 +35,125 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const fs = __importStar(require("fs"));
37
37
  const path = __importStar(require("path"));
38
- function extractUnionLiterals(source, typeName) {
39
- const pattern = new RegExp(`export type\\s+${typeName}\\s*=([\\s\\S]*?);`);
40
- const match = source.match(pattern);
41
- if (!match) {
42
- throw new Error(`Unable to locate type definition for ${typeName}`);
43
- }
44
- return Array.from(match[1].matchAll(/'([^']+)'/g)).map((item) => item[1]);
45
- }
46
- function extractObjectLiteralKeys(source, constName) {
47
- const objectLiteral = extractObjectLiteralSource(source, constName);
48
- const keys = [];
49
- let objectDepth = 0;
50
- let lineStart = true;
51
- for (let index = 0; index < objectLiteral.length; index += 1) {
52
- const character = objectLiteral[index];
53
- if (character === '{') {
54
- objectDepth += 1;
55
- lineStart = false;
56
- continue;
57
- }
58
- if (character === '}') {
59
- objectDepth -= 1;
60
- lineStart = false;
61
- continue;
62
- }
63
- if (character === '\n') {
64
- lineStart = true;
65
- continue;
66
- }
67
- if (objectDepth === 1 && lineStart) {
68
- if (/\s/.test(character)) {
69
- continue;
70
- }
71
- if (/[a-zA-Z0-9_]/.test(character)) {
72
- let cursor = index;
73
- while (cursor < objectLiteral.length && /[a-zA-Z0-9_]/.test(objectLiteral[cursor])) {
74
- cursor += 1;
75
- }
76
- const key = objectLiteral.slice(index, cursor);
77
- let separator = cursor;
78
- while (separator < objectLiteral.length && /\s/.test(objectLiteral[separator])) {
79
- separator += 1;
80
- }
81
- if (objectLiteral[separator] === ':') {
82
- keys.push(key);
83
- }
84
- }
85
- lineStart = false;
86
- continue;
87
- }
88
- if (!/\s/.test(character)) {
89
- lineStart = false;
90
- }
91
- }
92
- return Array.from(new Set(keys));
93
- }
94
- function extractObjectLiteralSource(source, constName) {
95
- const constStart = source.indexOf(`const ${constName} = {`);
96
- if (constStart < 0) {
97
- throw new Error(`Unable to locate constant ${constName}`);
98
- }
99
- const openBraceIndex = source.indexOf('{', constStart);
100
- let depth = 0;
101
- let endIndex = -1;
102
- for (let index = openBraceIndex; index < source.length; index += 1) {
103
- const character = source[index];
104
- if (character === '{') {
105
- depth += 1;
106
- }
107
- else if (character === '}') {
108
- depth -= 1;
109
- if (depth === 0) {
110
- endIndex = index;
111
- break;
112
- }
113
- }
114
- }
115
- if (endIndex < 0) {
116
- throw new Error(`Unable to parse object literal for ${constName}`);
117
- }
118
- return source.slice(openBraceIndex, endIndex + 1);
119
- }
120
- function extractArrayLiteralAfterMarker(source, marker) {
121
- const markerIndex = source.indexOf(marker);
122
- if (markerIndex < 0) {
123
- throw new Error(`Unable to locate marker: ${marker}`);
124
- }
125
- const openBracketIndex = source.indexOf('[', markerIndex + marker.length);
126
- if (openBracketIndex < 0) {
127
- throw new Error(`Unable to locate opening array bracket for marker: ${marker}`);
128
- }
129
- let depth = 0;
130
- let endIndex = -1;
131
- for (let index = openBracketIndex; index < source.length; index += 1) {
132
- const character = source[index];
133
- if (character === '[') {
134
- depth += 1;
135
- continue;
136
- }
137
- if (character === ']') {
138
- depth -= 1;
139
- if (depth === 0) {
140
- endIndex = index;
141
- break;
142
- }
143
- }
144
- }
145
- if (endIndex < 0) {
146
- throw new Error(`Unable to resolve closing array bracket for marker: ${marker}`);
147
- }
148
- return source.slice(openBracketIndex, endIndex + 1);
149
- }
150
- function extractObjectFieldStringLiterals(source, fieldName) {
151
- const pattern = new RegExp(`${fieldName}\\s*:\\s*'([^']+)'`, 'g');
152
- return Array.from(source.matchAll(pattern)).map((match) => match[1]);
153
- }
154
- function extractOperationDefaultResultPresentationsFromFrontend(source) {
155
- const registryLiteral = extractObjectLiteralSource(source, 'KNOWLEDGE_OPERATION_TRANSPORT_REGISTRY');
156
- const entries = Array.from(registryLiteral.matchAll(/([a-zA-Z0-9_]+)\s*:\s*{[\s\S]*?defaultResultPresentation\s*:\s*'([^']+)'/g));
157
- const mapping = {};
158
- entries.forEach((entry) => {
159
- const operationId = String(entry[1] || '').trim();
160
- const resultPresentation = String(entry[2] || '').trim();
161
- if (!operationId || !resultPresentation) {
162
- return;
38
+ const vm = __importStar(require("vm"));
39
+ const KnowledgeLearningPlatform_1 = require("./learning/KnowledgeLearningPlatform");
40
+ const agentWorkspaceCapabilityContracts_1 = require("./learning/agentWorkspaceCapabilityContracts");
41
+ describe('agent workspace capability runtime parity', () => {
42
+ let diagnostics;
43
+ let capabilities;
44
+ let workspace;
45
+ let fetch;
46
+ beforeAll(async () => {
47
+ const window = {};
48
+ fetch = jest.fn();
49
+ vm.runInNewContext(fs.readFileSync(path.join(__dirname, 'frontend', 'agent_workspace.js'), 'utf8'), {
50
+ window, document: { readyState: 'loading', addEventListener() { }, getElementById() { return null; } },
51
+ console, Set, Map, fetch,
52
+ });
53
+ workspace = window.NoteConnectionAgentWorkspace;
54
+ diagnostics = workspace.getCapabilityRegistryDiagnostics();
55
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ autoPersist: false });
56
+ await platform.ingestKnowledge({ documents: [{ documentId: 'contract', sourcePath: 'contracts/graph.md', content: '# Graph\n\nGraph theory studies nodes and edges.' }] });
57
+ const response = await platform.agentConversation({ message: 'Graph theory', persistMemory: false });
58
+ expect(response.knowledgePoints.length).toBeGreaterThan(0);
59
+ capabilities = response.knowledgePoints.flatMap(point => point.capabilities);
60
+ expect(capabilities.length).toBeGreaterThan(0);
61
+ });
62
+ test('transport registry covers the exported operation contract', () => {
63
+ expect(new Set(diagnostics.operationTransports)).toEqual(new Set(agentWorkspaceCapabilityContracts_1.AGENT_WORKSPACE_OPERATION_IDS));
64
+ });
65
+ test('request builders cover the exported operation contract', () => {
66
+ expect(new Set(diagnostics.operationRequestBuilders)).toEqual(new Set(agentWorkspaceCapabilityContracts_1.AGENT_WORKSPACE_OPERATION_IDS));
67
+ });
68
+ test('transports and request builders agree at runtime', () => {
69
+ expect(new Set(diagnostics.operationTransports)).toEqual(new Set(diagnostics.operationRequestBuilders));
70
+ });
71
+ test('override operation keys exist in the exported contract', () => {
72
+ for (const operation of Object.keys(diagnostics.operationResultPresentationOverrideMap))
73
+ expect(agentWorkspaceCapabilityContracts_1.AGENT_WORKSPACE_OPERATION_IDS).toContain(operation);
74
+ });
75
+ test('override presentations exist in the exported contract', () => {
76
+ for (const presentations of Object.values(diagnostics.operationResultPresentationOverrideMap)) {
77
+ expect(presentations.length).toBeGreaterThan(0);
78
+ for (const presentation of presentations)
79
+ expect(agentWorkspaceCapabilityContracts_1.AGENT_WORKSPACE_RESULT_PRESENTATIONS).toContain(presentation);
163
80
  }
164
- mapping[operationId] = resultPresentation;
165
81
  });
166
- return mapping;
167
- }
168
- function extractOperationResultPresentationOverridesFromFrontend(source) {
169
- const overridesLiteral = extractObjectLiteralSource(source, 'KNOWLEDGE_OPERATION_RESULT_PRESENTATION_OVERRIDES');
170
- const entries = Array.from(overridesLiteral.matchAll(/([a-zA-Z0-9_]+)\s*:\s*\[([^\]]*)\]/g));
171
- const mapping = {};
172
- entries.forEach((entry) => {
173
- const operationId = String(entry[1] || '').trim();
174
- if (!operationId) {
175
- return;
82
+ test('every operation has a nonempty unique allowlist containing its default', () => {
83
+ for (const operation of agentWorkspaceCapabilityContracts_1.AGENT_WORKSPACE_OPERATION_IDS) {
84
+ const allowed = diagnostics.operationAllowedResultPresentations[operation];
85
+ expect(allowed).toContain(diagnostics.operationDefaultResultPresentations[operation]);
86
+ expect(new Set(allowed).size).toBe(allowed.length);
176
87
  }
177
- const rawArrayLiteral = String(entry[2] || '');
178
- const values = Array.from(rawArrayLiteral.matchAll(/'([^']+)'/g))
179
- .map((valueMatch) => String(valueMatch[1] || '').trim())
180
- .filter(Boolean);
181
- mapping[operationId] = Array.from(new Set(values));
182
88
  });
183
- return mapping;
184
- }
185
- function extractOperationAllowedResultPresentationsFromFrontend(source) {
186
- const defaultMapping = extractOperationDefaultResultPresentationsFromFrontend(source);
187
- const overrideMapping = extractOperationResultPresentationOverridesFromFrontend(source);
188
- const allOperationIds = new Set([
189
- ...Object.keys(defaultMapping),
190
- ...Object.keys(overrideMapping),
191
- ]);
192
- const allowedMapping = {};
193
- allOperationIds.forEach((operationId) => {
194
- const values = [
195
- String(defaultMapping[operationId] || '').trim(),
196
- ...(overrideMapping[operationId] || []),
197
- ].filter(Boolean);
198
- allowedMapping[operationId] = Array.from(new Set(values));
199
- });
200
- return allowedMapping;
201
- }
202
- function extractBackendKnowledgeOperationPairs(conversationCapabilityLiteral) {
203
- const entries = Array.from(String(conversationCapabilityLiteral || '').matchAll(/execution\s*:\s*{[\s\S]*?kind\s*:\s*'knowledge_operation'[\s\S]*?operationId\s*:\s*'([^']+)'[\s\S]*?resultPresentation\s*:\s*'([^']+)'/g));
204
- return entries.map((entry) => ({
205
- operationId: String(entry[1] || '').trim(),
206
- resultPresentation: String(entry[2] || '').trim(),
207
- })).filter((entry) => entry.operationId.length > 0 && entry.resultPresentation.length > 0);
208
- }
209
- function extractTopLevelObjectLiteralsFromArrayLiteral(arrayLiteralSource) {
210
- const source = String(arrayLiteralSource || '');
211
- const objectLiterals = [];
212
- let inString = null;
213
- let isEscaped = false;
214
- let objectDepth = 0;
215
- let objectStartIndex = -1;
216
- for (let index = 0; index < source.length; index += 1) {
217
- const character = source[index];
218
- if (inString) {
219
- if (isEscaped) {
220
- isEscaped = false;
221
- continue;
222
- }
223
- if (character === '\\') {
224
- isEscaped = true;
225
- continue;
226
- }
227
- if (character === inString) {
228
- inString = null;
229
- }
230
- continue;
231
- }
232
- if (character === '\'' || character === '"' || character === '`') {
233
- inString = character;
234
- continue;
235
- }
236
- if (character === '{') {
237
- if (objectDepth === 0) {
238
- objectStartIndex = index;
239
- }
240
- objectDepth += 1;
241
- continue;
89
+ test('overrides declare only non-default presentations', () => {
90
+ for (const [operation, presentations] of Object.entries(diagnostics.operationResultPresentationOverrideMap)) {
91
+ expect(presentations).not.toContain(diagnostics.operationDefaultResultPresentations[operation]);
242
92
  }
243
- if (character === '}') {
244
- if (objectDepth <= 0) {
245
- continue;
246
- }
247
- objectDepth -= 1;
248
- if (objectDepth === 0 && objectStartIndex >= 0) {
249
- objectLiterals.push(source.slice(objectStartIndex, index + 1));
250
- objectStartIndex = -1;
251
- }
252
- }
253
- }
254
- return objectLiterals;
255
- }
256
- describe('agent workspace capability registry parity', () => {
257
- const repoRoot = path.resolve(__dirname, '..');
258
- const typesSource = fs.readFileSync(path.join(repoRoot, 'src', 'learning', 'types.ts'), 'utf8');
259
- const frontendSource = fs.readFileSync(path.join(repoRoot, 'src', 'frontend', 'agent_workspace.js'), 'utf8');
260
- const knowledgePlatformSource = fs.readFileSync(path.join(repoRoot, 'src', 'learning', 'KnowledgeLearningPlatform.ts'), 'utf8');
261
- const BACKEND_CONTRACT_MARKER = "const capabilities: AgentConversationResponse['knowledgePoints'][number]['capabilities'] =";
262
- const backendContractAvailable = knowledgePlatformSource.indexOf(BACKEND_CONTRACT_MARKER) >= 0;
263
- const backendTest = backendContractAvailable ? test : test.skip;
264
- let conversationCapabilityLiteral;
265
- try {
266
- conversationCapabilityLiteral = extractArrayLiteralAfterMarker(knowledgePlatformSource, BACKEND_CONTRACT_MARKER);
267
- }
268
- catch {
269
- conversationCapabilityLiteral = '';
270
- }
271
- test.skip('frontend operation transport registry covers AgentConversationCapabilityOperationId union', () => {
272
- const operationIds = extractUnionLiterals(typesSource, 'AgentConversationCapabilityOperationId');
273
- const frontendOperationIds = extractObjectLiteralKeys(frontendSource, 'KNOWLEDGE_OPERATION_TRANSPORT_REGISTRY');
274
- expect(new Set(frontendOperationIds)).toEqual(new Set(operationIds));
275
- });
276
- test.skip('frontend operation request builder registry covers AgentConversationCapabilityOperationId union', () => {
277
- const operationIds = extractUnionLiterals(typesSource, 'AgentConversationCapabilityOperationId');
278
- const frontendOperationIds = extractObjectLiteralKeys(frontendSource, 'KNOWLEDGE_OPERATION_REQUEST_BUILDERS');
279
- expect(new Set(frontendOperationIds)).toEqual(new Set(operationIds));
280
- });
281
- test('frontend operation transport and request builder registries stay aligned', () => {
282
- const transportOperationIds = extractObjectLiteralKeys(frontendSource, 'KNOWLEDGE_OPERATION_TRANSPORT_REGISTRY');
283
- const requestBuilderOperationIds = extractObjectLiteralKeys(frontendSource, 'KNOWLEDGE_OPERATION_REQUEST_BUILDERS');
284
- expect(new Set(transportOperationIds)).toEqual(new Set(requestBuilderOperationIds));
285
- });
286
- test.skip('frontend operation result-presentation override keys stay within operation union', () => {
287
- const operationIds = new Set(extractUnionLiterals(typesSource, 'AgentConversationCapabilityOperationId'));
288
- const overrideMapping = extractOperationResultPresentationOverridesFromFrontend(frontendSource);
289
- Object.keys(overrideMapping).forEach((operationId) => {
290
- expect(operationIds.has(operationId)).toBe(true);
291
- expect(overrideMapping[operationId].length).toBeGreaterThan(0);
292
- });
293
- });
294
- test.skip('frontend operation result-presentation overrides stay within result-presentation union', () => {
295
- const resultPresentationIds = new Set(extractUnionLiterals(typesSource, 'AgentConversationCapabilityResultPresentation'));
296
- const overrideMapping = extractOperationResultPresentationOverridesFromFrontend(frontendSource);
297
- Object.entries(overrideMapping).forEach(([operationId, presentations]) => {
298
- expect(operationId).toBeTruthy();
299
- expect(presentations.length).toBeGreaterThan(0);
300
- presentations.forEach((presentation) => {
301
- expect(resultPresentationIds.has(presentation)).toBe(true);
302
- });
303
- });
304
- });
305
- test('frontend operation allowlists include transport defaults and stay non-empty', () => {
306
- const defaultMapping = extractOperationDefaultResultPresentationsFromFrontend(frontendSource);
307
- const allowlistMapping = extractOperationAllowedResultPresentationsFromFrontend(frontendSource);
308
- const overrideMapping = extractOperationResultPresentationOverridesFromFrontend(frontendSource);
309
- Object.entries(defaultMapping).forEach(([operationId, defaultPresentation]) => {
310
- expect(defaultPresentation).toBeTruthy();
311
- const allowlist = allowlistMapping[operationId] || [];
312
- expect(allowlist.length).toBeGreaterThan(0);
313
- expect(allowlist).toContain(defaultPresentation);
314
- expect(new Set(allowlist).size).toBe(allowlist.length);
315
- });
316
- Object.keys(overrideMapping).forEach((operationId) => {
317
- expect(defaultMapping[operationId]).toBeDefined();
318
- });
319
- });
320
- test('frontend operation result-presentation overrides only declare non-default presentations', () => {
321
- const defaultMapping = extractOperationDefaultResultPresentationsFromFrontend(frontendSource);
322
- const overrideMapping = extractOperationResultPresentationOverridesFromFrontend(frontendSource);
323
- Object.entries(overrideMapping).forEach(([operationId, overridePresentations]) => {
324
- const defaultPresentation = String(defaultMapping[operationId] || '').trim();
325
- expect(defaultPresentation).toBeTruthy();
326
- overridePresentations.forEach((presentation) => {
327
- expect(presentation).not.toBe(defaultPresentation);
328
- });
329
- });
330
- });
331
- test('frontend registry diagnostics expose operation presentation maps', () => {
332
- expect(frontendSource).toMatch(/operationResultPresentationOverrideMap\s*:\s*resolveOperationResultPresentationOverrideMap\(\)/);
333
- expect(frontendSource).toMatch(/operationInvalidResultPresentationOverrideMap\s*:\s*(resolveOperationInvalidResultPresentationOverrideMap\(\)|invalidOverrideMap)/);
334
- expect(frontendSource).toMatch(/operationUnknownResultPresentationOverrideMap\s*:\s*(resolveOperationUnknownResultPresentationOverrideMap\(\)|unknownOverrideMap)/);
335
- expect(frontendSource).toMatch(/operationDefaultResultPresentations\s*:\s*resolveOperationDefaultResultPresentationMap\(\)/);
336
- expect(frontendSource).toMatch(/operationAllowedResultPresentations\s*:\s*resolveOperationAllowedResultPresentationMap\(\)/);
337
- expect(frontendSource).toMatch(/operationResultPresentationOverrideDriftDetected\s*:\s*\(/);
338
- expect(frontendSource).toMatch(/operationResultPresentationInvalidOverrideTokenCount\s*:\s*invalidOverrideTokenCount/);
339
- expect(frontendSource).toMatch(/operationResultPresentationUnknownOverrideTokenCount\s*:\s*unknownOverrideTokenCount/);
340
93
  });
341
- test.skip('frontend result presentation registries cover AgentConversationCapabilityResultPresentation union', () => {
342
- const presentationIds = extractUnionLiterals(typesSource, 'AgentConversationCapabilityResultPresentation');
343
- const customPresentationIds = extractObjectLiteralKeys(frontendSource, 'CUSTOM_RESULT_PRESENTERS');
344
- const cardPresentationIds = extractObjectLiteralKeys(frontendSource, 'CARD_RESULT_PRESENTATION_REGISTRY');
345
- expect(new Set([...customPresentationIds, ...cardPresentationIds])).toEqual(new Set(presentationIds));
94
+ test('diagnostics report no invalid or unknown presentation drift', () => {
95
+ expect(diagnostics.operationResultPresentationOverrideDriftDetected).toBe(false);
96
+ expect(diagnostics.operationResultPresentationInvalidOverrideTokenCount).toBe(0);
97
+ expect(diagnostics.operationResultPresentationUnknownOverrideTokenCount).toBe(0);
346
98
  });
347
- test('frontend card result presentation registry and payload builders stay aligned', () => {
348
- const cardPresentationIds = extractObjectLiteralKeys(frontendSource, 'CARD_RESULT_PRESENTATION_REGISTRY');
349
- const payloadBuilderPresentationIds = extractObjectLiteralKeys(frontendSource, 'RESULT_PRESENTATION_PAYLOAD_BUILDERS');
350
- expect(new Set(cardPresentationIds)).toEqual(new Set(payloadBuilderPresentationIds));
99
+ test('presenters cover the exported presentation contract', () => {
100
+ expect(new Set(diagnostics.resultPresentations)).toEqual(new Set(agentWorkspaceCapabilityContracts_1.AGENT_WORKSPACE_RESULT_PRESENTATIONS));
351
101
  });
352
- test.skip('frontend execution kind handlers cover AgentConversationCapabilityExecutionKind union', () => {
353
- const executionKinds = extractUnionLiterals(typesSource, 'AgentConversationCapabilityExecutionKind');
354
- const frontendExecutionKinds = extractObjectLiteralKeys(frontendSource, 'CAPABILITY_EXECUTION_KIND_HANDLERS');
355
- expect(new Set(frontendExecutionKinds)).toEqual(new Set(executionKinds));
102
+ test('card presenters and payload builders agree', () => {
103
+ expect(new Set(diagnostics.cardResultPresentations)).toEqual(new Set(diagnostics.resultPresentationPayloadBuilders));
356
104
  });
357
- backendTest('backend conversation emitter action set stays governed and union-compatible', () => {
358
- const backendActionIds = Array.from(new Set(extractObjectFieldStringLiterals(conversationCapabilityLiteral, 'actionId')));
359
- const explicitActionIds = extractUnionLiterals(typesSource, 'AgentConversationActionId');
360
- const tutorActionIds = extractUnionLiterals(typesSource, 'TutorActionKind');
361
- const governedActionIds = [
362
- 'open_focus_mode',
363
- 'open_learning_path',
364
- 'generate_quiz',
365
- 'recap',
366
- 'generate_transfer',
367
- 'generate_counterexample',
368
- 'follow_up',
369
- 'compare_query_backends',
370
- 'inspect_conversation_turn_cache_diagnostics',
371
- 'inspect_conversation_turn_cache_alert_trend',
372
- 'inspect_conversation_turn_cache_alert_trend_index',
373
- 'inspect_conversation_turn_cache_alert_trend_export',
374
- 'inspect_query_backend_diagnostics',
375
- 'inspect_query_backend_comparison_history',
376
- 'inspect_query_backend_comparison_trend',
377
- 'inspect_tutor_adapter_telemetry',
378
- 'inspect_tutor_trace_diagnostics',
379
- 'inspect_learning_quality_trend',
380
- 'inspect_learning_quality_history',
381
- 'inspect_session_plan_quality_trend',
382
- 'inspect_session_plan_quality_history',
383
- 'inspect_runtime_capability_runbook_verify',
384
- 'inspect_runtime_capability_runbook_history',
385
- 'inspect_runtime_capability_runbook_checks',
386
- 'inspect_runtime_capability_runbook_action_queue',
387
- 'inspect_session_history',
388
- 'build_study_session',
389
- 'inspect_conversation_memory',
390
- ];
391
- const fullActionUnionSet = new Set([...explicitActionIds, ...tutorActionIds]);
392
- backendActionIds.forEach((actionId) => {
393
- expect(fullActionUnionSet.has(actionId)).toBe(true);
394
- });
395
- expect(new Set(backendActionIds)).toEqual(new Set(governedActionIds));
396
- expect(backendActionIds).not.toContain('analyze_answer');
397
- });
398
- backendTest('backend conversation emitter operation ids stay in parity with frontend transport and request registries', () => {
399
- const backendOperationIds = Array.from(new Set(extractObjectFieldStringLiterals(conversationCapabilityLiteral, 'operationId')));
400
- const frontendTransportOperationIds = extractObjectLiteralKeys(frontendSource, 'KNOWLEDGE_OPERATION_TRANSPORT_REGISTRY');
401
- const frontendRequestBuilderOperationIds = extractObjectLiteralKeys(frontendSource, 'KNOWLEDGE_OPERATION_REQUEST_BUILDERS');
402
- expect(new Set(backendOperationIds)).toEqual(new Set(frontendTransportOperationIds));
403
- expect(new Set(backendOperationIds)).toEqual(new Set(frontendRequestBuilderOperationIds));
105
+ test('execution handlers cover the exported execution contract', () => {
106
+ expect(new Set(diagnostics.executionKinds)).toEqual(new Set(agentWorkspaceCapabilityContracts_1.AGENT_WORKSPACE_EXECUTION_KINDS));
404
107
  });
405
- backendTest('backend conversation emitter result presentations stay in parity with frontend presenters', () => {
406
- const backendResultPresentations = Array.from(new Set(extractObjectFieldStringLiterals(conversationCapabilityLiteral, 'resultPresentation')));
407
- const customPresentationIds = extractObjectLiteralKeys(frontendSource, 'CUSTOM_RESULT_PRESENTERS');
408
- const cardPresentationIds = extractObjectLiteralKeys(frontendSource, 'CARD_RESULT_PRESENTATION_REGISTRY');
409
- const frontendResultPresentations = new Set([...customPresentationIds, ...cardPresentationIds]);
410
- expect(new Set(backendResultPresentations)).toEqual(frontendResultPresentations);
108
+ test('real conversation capabilities expose stable unique actions and core operations', () => {
109
+ const oneAtom = capabilities.filter(capability => capability.targetAtomId === capabilities[0].targetAtomId);
110
+ expect(new Set(oneAtom.map(capability => capability.capabilityId)).size).toBe(oneAtom.length);
111
+ expect(oneAtom.map(capability => capability.actionId)).toEqual(expect.arrayContaining(['open_focus_mode', 'open_learning_path', 'build_study_session', 'generate_quiz', 'recap']));
112
+ expect(oneAtom.map(capability => capability.actionId)).not.toContain('analyze_answer');
411
113
  });
412
- backendTest('backend knowledge-operation execution presentations stay within frontend operation allowlist', () => {
413
- const frontendOperationAllowedPresentations = extractOperationAllowedResultPresentationsFromFrontend(frontendSource);
414
- const backendOperationPairs = extractBackendKnowledgeOperationPairs(conversationCapabilityLiteral);
415
- expect(backendOperationPairs.length).toBeGreaterThan(0);
416
- const backendOperationPresentationSetByOperationId = new Map();
417
- backendOperationPairs.forEach((entry) => {
418
- expect(frontendOperationAllowedPresentations[entry.operationId]).toBeDefined();
419
- expect(frontendOperationAllowedPresentations[entry.operationId]).toContain(entry.resultPresentation);
420
- const knownPresentations = backendOperationPresentationSetByOperationId.get(entry.operationId) || new Set();
421
- knownPresentations.add(entry.resultPresentation);
422
- backendOperationPresentationSetByOperationId.set(entry.operationId, knownPresentations);
423
- });
424
- backendOperationPresentationSetByOperationId.forEach((presentations) => {
425
- expect(presentations.size).toBe(1);
426
- });
114
+ test('all emitted operations are executable through both frontend registries', () => {
115
+ for (const capability of capabilities)
116
+ if (capability.execution.kind === 'knowledge_operation') {
117
+ expect(diagnostics.operationTransports).toContain(capability.execution.operationId);
118
+ expect(diagnostics.operationRequestBuilders).toContain(capability.execution.operationId);
119
+ }
427
120
  });
428
- backendTest('backend non-default operation presentations require explicit frontend overrides', () => {
429
- const defaultMapping = extractOperationDefaultResultPresentationsFromFrontend(frontendSource);
430
- const overrideMapping = extractOperationResultPresentationOverridesFromFrontend(frontendSource);
431
- const backendOperationPairs = extractBackendKnowledgeOperationPairs(conversationCapabilityLiteral);
432
- expect(backendOperationPairs.length).toBeGreaterThan(0);
433
- backendOperationPairs.forEach(({ operationId, resultPresentation }) => {
434
- const defaultPresentation = String(defaultMapping[operationId] || '').trim();
435
- expect(defaultPresentation).toBeTruthy();
436
- if (resultPresentation !== defaultPresentation) {
437
- const operationOverrides = overrideMapping[operationId] || [];
438
- expect(operationOverrides).toContain(resultPresentation);
121
+ test('every emitted result presentation has a frontend presenter', () => {
122
+ for (const capability of capabilities)
123
+ if (capability.execution.kind === 'knowledge_operation')
124
+ expect(diagnostics.resultPresentations).toContain(capability.execution.resultPresentation);
125
+ });
126
+ test('emitted operation presentations respect each operation allowlist', () => {
127
+ for (const capability of capabilities)
128
+ if (capability.execution.kind === 'knowledge_operation')
129
+ expect(diagnostics.operationAllowedResultPresentations[capability.execution.operationId]).toContain(capability.execution.resultPresentation);
130
+ });
131
+ test('emitted non-default presentations require an explicit override', () => {
132
+ for (const capability of capabilities)
133
+ if (capability.execution.kind === 'knowledge_operation') {
134
+ const { operationId, resultPresentation } = capability.execution;
135
+ if (resultPresentation !== diagnostics.operationDefaultResultPresentations[operationId])
136
+ expect(diagnostics.operationResultPresentationOverrideMap[operationId]).toContain(resultPresentation);
439
137
  }
440
- });
441
138
  });
442
- backendTest('frontend override presentations must be exercised by backend capability emission', () => {
443
- const overrideMapping = extractOperationResultPresentationOverridesFromFrontend(frontendSource);
444
- const backendOperationPairs = extractBackendKnowledgeOperationPairs(conversationCapabilityLiteral);
445
- const backendOperationPresentations = new Map();
446
- backendOperationPairs.forEach(({ operationId, resultPresentation }) => {
447
- const knownPresentations = backendOperationPresentations.get(operationId) || new Set();
448
- knownPresentations.add(resultPresentation);
449
- backendOperationPresentations.set(operationId, knownPresentations);
450
- });
451
- Object.entries(overrideMapping).forEach(([operationId, overridePresentations]) => {
452
- const backendPresentations = backendOperationPresentations.get(operationId) || new Set();
453
- overridePresentations.forEach((presentation) => {
454
- expect(backendPresentations.has(presentation)).toBe(true);
455
- });
456
- });
139
+ test('tutor override is exercised by actual capability emission', () => {
140
+ expect(capabilities.some(capability => capability.execution.kind === 'knowledge_operation' && capability.execution.resultPresentation === 'tutor_action_card')).toBe(true);
141
+ // Workflow-history cards are emitted by artifact workflows, not every conversation.
142
+ expect(diagnostics.operationAllowedResultPresentations.fetch_workflow_artifacts).toEqual(expect.arrayContaining(['knowledge_run_card', 'knowledge_run_history_card']));
143
+ });
144
+ test('every emitted capability has a complete executable identity and label', () => {
145
+ for (const capability of capabilities) {
146
+ expect(capability.capabilityId).toBeTruthy();
147
+ expect(capability.actionId).toBeTruthy();
148
+ expect(capability.targetAtomId).toBeTruthy();
149
+ expect(capability.label).toBeTruthy();
150
+ expect(capability.labelKey).toMatch(/^agentWorkspace\.actions\./);
151
+ expect(diagnostics.executionKinds).toContain(capability.execution.kind);
152
+ }
457
153
  });
458
- backendTest('backend conversation emitter capabilities keep executable contract completeness', () => {
459
- const capabilityObjectLiterals = extractTopLevelObjectLiteralsFromArrayLiteral(conversationCapabilityLiteral);
460
- expect(capabilityObjectLiterals.length).toBeGreaterThan(0);
461
- capabilityObjectLiterals.forEach((capabilityLiteral) => {
462
- expect(capabilityLiteral).toMatch(/capabilityId\s*:\s*`[^`]+`|capabilityId\s*:\s*'[^']+'/);
463
- expect(capabilityLiteral).toMatch(/actionId\s*:\s*'[^']+'/);
464
- expect(capabilityLiteral).toMatch(/labelKey\s*:\s*'agentWorkspace\.actions\.[^']+'/);
465
- expect(capabilityLiteral).toMatch(/failure\s*:\s*{[\s\S]*?messageKey\s*:\s*'agentWorkspace\.messages\.[^']+'/);
466
- expect(capabilityLiteral).toMatch(/failure\s*:\s*{[\s\S]*?fallbackMessage\s*:\s*'[^']+'/);
467
- expect(capabilityLiteral).toMatch(/execution\s*:\s*{[\s\S]*?kind\s*:\s*'[^']+'/);
468
- const isKnowledgeOperation = /execution\s*:\s*{[\s\S]*?kind\s*:\s*'knowledge_operation'/.test(capabilityLiteral);
469
- if (isKnowledgeOperation) {
470
- expect(capabilityLiteral).toMatch(/execution\s*:\s*{[\s\S]*?operationId\s*:\s*'[^']+'/);
471
- expect(capabilityLiteral).toMatch(/execution\s*:\s*{[\s\S]*?resultPresentation\s*:\s*'[^']+'/);
472
- }
473
- });
154
+ test.each([{ execution: { kind: 'unsupported' } }, { actionId: 'open_learning_path' }])('rejects unsupported/missing execution without implicit legacy I/O: %p', async (capability) => {
155
+ await workspace.executeCapability({}, capability, {});
156
+ expect(fetch).not.toHaveBeenCalled();
157
+ expect(diagnostics.legacyActionFallbacks).toEqual([]);
474
158
  });
475
159
  });