noteconnection 1.8.0 → 1.9.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 (195) 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/backend/FileLoader.js +18 -4
  8. package/dist/src/backend/FileLoader.test.js +125 -0
  9. package/dist/src/backend/GraphBuilder.identity.test.js +86 -0
  10. package/dist/src/backend/GraphBuilder.js +66 -18
  11. package/dist/src/backend/GraphBuilder.matching.test.js +127 -0
  12. package/dist/src/backend/GraphMetrics.js +0 -3
  13. package/dist/src/backend/ResourceIdentity.js +155 -0
  14. package/dist/src/backend/ResourceIdentity.test.js +113 -0
  15. package/dist/src/backend/algorithms/CycleDetection.js +0 -1
  16. package/dist/src/backend/algorithms/HybridEngine.js +0 -3
  17. package/dist/src/backend/algorithms/LayoutEngine.js +0 -1
  18. package/dist/src/backend/algorithms/StatisticalAnalyzer.js +0 -4
  19. package/dist/src/backend/algorithms/TopologicalSort.js +0 -2
  20. package/dist/src/backend/build_dag.js +0 -1
  21. package/dist/src/capacitor.bridge.serialization.contract.test.js +3 -0
  22. package/dist/src/capacitor.runtime.contract.test.js +11 -2
  23. package/dist/src/core/Graph.js +138 -42
  24. package/dist/src/core/Graph.test.js +74 -0
  25. package/dist/src/core/NoteConnection.js +2 -2
  26. package/dist/src/core/PathBridge.js +265 -2
  27. package/dist/src/core/ResourceReference.js +17 -0
  28. package/dist/src/desktop.godot.pack.test.js +142 -0
  29. package/dist/src/desktop.runtime.graph.test.js +66 -0
  30. package/dist/src/export/WorkspaceExportBundle.js +44 -0
  31. package/dist/src/export/WorkspaceExportBundle.test.js +61 -0
  32. package/dist/src/foundation.release.evidence.contract.test.js +127 -9
  33. package/dist/src/foundation.sqlite.runtime.contract.test.js +6 -0
  34. package/dist/src/frontend/README.md +257 -1803
  35. package/dist/src/frontend/agent_workspace.js +665 -7
  36. package/dist/src/frontend/index.html +31 -2
  37. package/dist/src/frontend/knowledge_projection_contract.js +230 -0
  38. package/dist/src/frontend/knowledge_projection_store.js +214 -0
  39. package/dist/src/frontend/libs/path_core.js +158 -42
  40. package/dist/src/frontend/locales/en.json +32 -0
  41. package/dist/src/frontend/locales/zh.json +32 -0
  42. package/dist/src/frontend/mobile_budget_runtime.js +33 -0
  43. package/dist/src/frontend/mobile_exact_analyzer.js +393 -0
  44. package/dist/src/frontend/mobile_identity_contract.js +221 -0
  45. package/dist/src/frontend/mobile_semantic_comparator.js +264 -0
  46. package/dist/src/frontend/path.html +6 -2
  47. package/dist/src/frontend/simulationWorker.js +1 -1
  48. package/dist/src/frontend/source_manager.js +110 -4
  49. package/dist/src/frontend/storage_provider.js +661 -71
  50. package/dist/src/frontend/styles.css +107 -13
  51. package/dist/src/frontend/workspace_panes.js +111 -7
  52. package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
  53. package/dist/src/graph.answer.operator.contract.test.js +72 -0
  54. package/dist/src/index.js +6 -2
  55. package/dist/src/index.knowledge-root.test.js +118 -0
  56. package/dist/src/indexing/IndexLifecycle.js +22 -0
  57. package/dist/src/indexing/IndexLifecycle.test.js +24 -0
  58. package/dist/src/knowledge.api.contract.test.js +4 -2
  59. package/dist/src/knowledge_projection.contract.test.js +134 -0
  60. package/dist/src/knowledge_projection_store.test.js +200 -0
  61. package/dist/src/learning/AnswerQualityEvaluation.js +153 -0
  62. package/dist/src/learning/AnswerQualityEvaluation.test.js +118 -0
  63. package/dist/src/learning/KnowledgeLearningPlatform.js +4687 -3892
  64. package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +418 -0
  65. package/dist/src/learning/KnowledgeLearningPlatform.test.js +243 -6
  66. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +25 -1
  67. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +13 -5
  68. package/dist/src/learning/MeasurementEvidenceConflicts.test.js +78 -0
  69. package/dist/src/learning/PublicAnswerContract.test.js +85 -0
  70. package/dist/src/learning/PublicEvidenceSelection.test.js +94 -0
  71. package/dist/src/learning/PublicMeasurementDisclosure.test.js +54 -0
  72. package/dist/src/learning/agentConversationExecution.js +211 -0
  73. package/dist/src/learning/agentConversationExecution.test.js +209 -0
  74. package/dist/src/learning/agentConversationSerialization.js +266 -0
  75. package/dist/src/learning/agentConversationSerialization.test.js +165 -0
  76. package/dist/src/learning/agentResponseBudget.js +179 -0
  77. package/dist/src/learning/agentResponseBudget.test.js +97 -0
  78. package/dist/src/learning/agentWorkspaceCapabilityContracts.js +65 -0
  79. package/dist/src/learning/answerReleaseReview.js +1191 -250
  80. package/dist/src/learning/answerReleaseReview.test.js +1293 -7
  81. package/dist/src/learning/answerTaskPlan.js +473 -0
  82. package/dist/src/learning/conversationComposer.js +627 -386
  83. package/dist/src/learning/conversationComposer.test.js +1403 -0
  84. package/dist/src/learning/evidenceContextAssembler.js +312 -120
  85. package/dist/src/learning/graphAnswerCoverage.js +37 -0
  86. package/dist/src/learning/graphAnswerCoverage.test.js +93 -0
  87. package/dist/src/learning/graphAnswerCoverageCalibration.js +59 -0
  88. package/dist/src/learning/graphAnswerCoverageCalibration.test.js +46 -0
  89. package/dist/src/learning/graphAnswerFacts.js +94 -0
  90. package/dist/src/learning/graphAnswerFacts.test.js +39 -0
  91. package/dist/src/learning/graphAnswerPlan.js +908 -0
  92. package/dist/src/learning/graphAnswerPlan.test.js +907 -0
  93. package/dist/src/learning/graphAnswerQualityCalibration.js +255 -0
  94. package/dist/src/learning/graphAnswerQualityCalibration.test.js +72 -0
  95. package/dist/src/learning/graphAnswerQualityPolicy.js +30 -0
  96. package/dist/src/learning/graphClaimMatcher.js +104 -0
  97. package/dist/src/learning/graphConditionedContext.js +109 -0
  98. package/dist/src/learning/graphConditionedContext.test.js +99 -0
  99. package/dist/src/learning/graphContextAssembler.js +3 -13
  100. package/dist/src/learning/graphContextAssembler.test.js +2 -2
  101. package/dist/src/learning/graphExpansionPolicy.js +22 -0
  102. package/dist/src/learning/graphExpansionPolicy.test.js +33 -0
  103. package/dist/src/learning/identityMetadata.test.js +26 -0
  104. package/dist/src/learning/index.js +1 -0
  105. package/dist/src/learning/mobileAnswerProjection.js +104 -0
  106. package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
  107. package/dist/src/learning/queryBackend.js +34 -10
  108. package/dist/src/learning/queryBackend.test.js +21 -0
  109. package/dist/src/learning/ragContextPack.js +115 -16
  110. package/dist/src/learning/ragContextPack.test.js +151 -0
  111. package/dist/src/learning/ragEvidenceQuality.js +96 -0
  112. package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
  113. package/dist/src/learning/ragPublicText.js +67 -4
  114. package/dist/src/learning/ragPublicText.test.js +57 -0
  115. package/dist/src/learning/ragSufficiencyJudge.js +11 -1
  116. package/dist/src/learning/ragSufficiencyProviderJudge.js +16 -26
  117. package/dist/src/learning/ragSufficiencyProviderJudge.test.js +51 -0
  118. package/dist/src/learning/requestNormalization.js +106 -0
  119. package/dist/src/learning/requestNormalization.test.js +101 -0
  120. package/dist/src/learning/store.js +116 -12
  121. package/dist/src/learning/store.test.js +299 -0
  122. package/dist/src/learning/vectorAccelerationAdapter.js +22 -6
  123. package/dist/src/learning/vectorAccelerationAdapter.test.js +30 -0
  124. package/dist/src/learning/workspaceHydration.js +168 -0
  125. package/dist/src/learning/workspaceHydration.test.js +30 -0
  126. package/dist/src/license.policy.contract.test.js +9 -4
  127. package/dist/src/markdown/MarkdownGateway.js +4 -0
  128. package/dist/src/markdown/MarkdownGateway.test.js +59 -0
  129. package/dist/src/middleware/SseResponseWriter.js +122 -0
  130. package/dist/src/middleware/SseResponseWriter.test.js +54 -0
  131. package/dist/src/middleware/auth.js +28 -7
  132. package/dist/src/middleware/auth.test.js +33 -0
  133. package/dist/src/middleware/index.js +2 -1
  134. package/dist/src/mobile.android.evidence.contract.test.js +146 -0
  135. package/dist/src/mobile.android.signing.contract.test.js +66 -0
  136. package/dist/src/mobile.artifact.contract.test.js +144 -0
  137. package/dist/src/mobile.budget.contract.test.js +90 -0
  138. package/dist/src/mobile.canonical-id.readiness.test.js +54 -0
  139. package/dist/src/mobile.graph.parity.contract.test.js +207 -0
  140. package/dist/src/mobile.identity.contract.test.js +66 -0
  141. package/dist/src/mobile.identity.corpus.manifest.test.js +72 -0
  142. package/dist/src/mobile.identity.corpus.test.js +40 -0
  143. package/dist/src/mobile.native.recovery.contract.test.js +64 -0
  144. package/dist/src/mobile.pipeline.test.js +11 -1
  145. package/dist/src/mobile.profile.contract.test.js +225 -0
  146. package/dist/src/mobile.semantic.parity.test.js +92 -0
  147. package/dist/src/mobile_exact_analyzer.test.js +113 -0
  148. package/dist/src/notemd/ContentGenerator.js +4 -9
  149. package/dist/src/notemd/FileProcessor.js +4 -9
  150. package/dist/src/notemd/NotemdService.js +12 -17
  151. package/dist/src/notemd/Translator.js +4 -9
  152. package/dist/src/notemd/progressReporter.js +9 -0
  153. package/dist/src/notemd.server.integration.test.js +119 -4
  154. package/dist/src/notemd.workflow.pipeline.test.js +1 -1
  155. package/dist/src/pathbridge.handshake.contract.test.js +29 -0
  156. package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
  157. package/dist/src/pathcore.bundle.contract.test.js +8 -0
  158. package/dist/src/platform/ExportProfile.js +28 -0
  159. package/dist/src/platform/MobileBudget.js +11 -0
  160. package/dist/src/platform/PlatformCapabilities.js +14 -0
  161. package/dist/src/platform/PlatformCapabilities.test.js +6 -0
  162. package/dist/src/query_backend.external_http.integration.test.js +2 -2
  163. package/dist/src/release.godot.mirror.contract.test.js +28 -4
  164. package/dist/src/resources/ResourceRegistry.js +40 -0
  165. package/dist/src/resources/ResourceRegistry.test.js +36 -0
  166. package/dist/src/routes/index.js +0 -4
  167. package/dist/src/routes/knowledge.js +46 -33
  168. package/dist/src/routes/knowledgePayload.js +185 -0
  169. package/dist/src/routes/knowledgePayload.test.js +53 -0
  170. package/dist/src/routes/markdown.js +8 -0
  171. package/dist/src/routes/notemd.js +990 -234
  172. package/dist/src/routes/registry.contract.test.js +5 -2
  173. package/dist/src/routes/registry.shadow.contract.test.js +22 -0
  174. package/dist/src/routes/render.js +14 -51
  175. package/dist/src/runtime.capabilities.test.js +18 -2
  176. package/dist/src/server.js +566 -1090
  177. package/dist/src/server.migration.test.js +417 -15
  178. package/dist/src/sidecar.build.lock.contract.test.js +201 -0
  179. package/dist/src/sidecar.freshness.contract.test.js +184 -0
  180. package/dist/src/sidecar.replacement.boundary.contract.test.js +6 -3
  181. package/dist/src/sidecar.supply.readiness.contract.test.js +11 -0
  182. package/dist/src/simulation.worker.offline.test.js +104 -0
  183. package/dist/src/storage.provider.capacitor.content.contract.test.js +4 -1
  184. package/dist/src/storage.provider.contract.test.js +152 -1
  185. package/dist/src/tauri.frontend.build.contract.test.js +8 -0
  186. package/dist/src/tauri.window.evidence.execution.test.js +68 -0
  187. package/dist/src/utils/RuntimePaths.js +6 -0
  188. package/dist/src/utils/RuntimePaths.test.js +27 -0
  189. package/dist/src/windows.installer.build.test.js +109 -0
  190. package/dist/src/windows.installer.payload.test.js +76 -0
  191. package/dist/src/windows.installer.runtime.test.js +69 -0
  192. package/dist/src/workspace/WorkspaceRegistry.js +13 -0
  193. package/package.json +32 -10
  194. package/dist/src/routes/data.js +0 -267
  195. package/dist/src/routes/diagnostics.js +0 -51
@@ -834,6 +834,49 @@ describe('WorkspaceExportBundle', () => {
834
834
  leakedInternalFragments: [],
835
835
  gates: [],
836
836
  },
837
+ graphAnswerPlan: {
838
+ intent: 'definition',
839
+ depth: 'standard',
840
+ anchorAtomId: 'atom_reflection',
841
+ leadClaimId: 'claim_reflection',
842
+ requiredRoles: ['definition', 'mechanism'],
843
+ omittedCandidates: [],
844
+ answerTaskPlan: {
845
+ schemaVersion: '1',
846
+ primarySubject: 'Reflection',
847
+ requestedDepth: 'standard',
848
+ subtasks: [
849
+ { subtaskId: 'definition', kind: 'definition', subject: 'Reflection', required: true, expectedOutput: 'direct_answer' },
850
+ { subtaskId: 'learning_route', kind: 'learning_route', subject: 'Reflection', required: true, expectedOutput: 'ordered_nodes' },
851
+ ],
852
+ learningRoute: [
853
+ { nodeId: 'atom_foundation', title: 'Foundation', role: 'prerequisite', order: 1, orderingBasis: 'explicit_prerequisite', evidenceRefs: ['edge_1'], reason: 'foundation' },
854
+ { nodeId: 'atom_reflection', title: 'Reflection', role: 'core', order: 2, orderingBasis: 'explicit_prerequisite', evidenceRefs: ['claim_reflection'], reason: 'core' },
855
+ { nodeId: 'atom_measurement', title: 'Measurement', role: 'application', order: 3, orderingBasis: 'source_order', evidenceRefs: ['claim_measurement'], reason: 'application' },
856
+ ],
857
+ },
858
+ claims: [
859
+ { claimId: 'claim_reflection', required: true },
860
+ { claimId: 'claim_mechanism', required: true },
861
+ ],
862
+ },
863
+ graphAnswerCoverage: {
864
+ passed: true,
865
+ applicable: true,
866
+ requiredClaimIds: ['claim_reflection', 'claim_mechanism'],
867
+ coveredClaimIds: ['claim_reflection', 'claim_mechanism'],
868
+ missingRequiredClaimIds: [],
869
+ coverageScore: 1,
870
+ },
871
+ answerTaskCoverage: {
872
+ passed: true,
873
+ applicable: true,
874
+ coveredSubtaskIds: ['definition', 'learning_route'],
875
+ missingRequiredSubtaskIds: [],
876
+ subtaskCoverage: [],
877
+ learningRouteNodeCount: 3,
878
+ coverageScore: 1,
879
+ },
837
880
  },
838
881
  graphContext: {
839
882
  anchorAtomId: 'atom_reflection',
@@ -914,6 +957,24 @@ describe('WorkspaceExportBundle', () => {
914
957
  temporalWarningCount: 0,
915
958
  missingLookupCount: 0,
916
959
  }),
960
+ graphAnswerPlan: {
961
+ intent: 'definition',
962
+ depth: 'standard',
963
+ anchorAtomId: 'atom_reflection',
964
+ claimCount: 2,
965
+ requiredClaimCount: 2,
966
+ requiredRoles: ['definition', 'mechanism'],
967
+ coverageScore: 1,
968
+ missingRequiredClaimIds: [],
969
+ },
970
+ answerTask: {
971
+ primarySubject: 'Reflection',
972
+ subtaskCount: 2,
973
+ requiredSubtaskCount: 2,
974
+ missingRequiredSubtaskIds: [],
975
+ learningRouteNodeCount: 3,
976
+ coverageScore: 1,
977
+ },
917
978
  }),
918
979
  expect.objectContaining({
919
980
  artifactId: 'workflow_artifact_knowledge_run_2',
@@ -40,16 +40,51 @@ describe('foundation release evidence freshness contract', () => {
40
40
  const repoRoot = path.resolve(__dirname, '..');
41
41
  const packageJsonPath = path.join(repoRoot, 'package.json');
42
42
  const scriptPath = path.join(repoRoot, 'scripts', 'verify-foundation-release-evidence.js');
43
+ const provenance = require('../scripts/foundation-evidence-provenance');
44
+ const fingerprints = require('../scripts/sidecar-build-fingerprint');
45
+ let fixtureIdentity;
43
46
  function readJson(filePath) {
44
47
  const raw = fs.readFileSync(filePath, 'utf8');
45
48
  return JSON.parse(raw);
46
49
  }
47
50
  function createTempReportRoot() {
48
- return fs.mkdtempSync(path.join(os.tmpdir(), 'noteconnection-foundation-release-evidence-'));
51
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'noteconnection-foundation-release-evidence-'));
52
+ fs.mkdirSync(path.join(root, 'dist', 'src'), { recursive: true });
53
+ fs.mkdirSync(path.join(root, 'src-tauri', 'bin'), { recursive: true });
54
+ fs.writeFileSync(path.join(root, 'dist', 'src', 'server.js'), 'fixture runtime');
55
+ const sidecar = path.join(root, 'src-tauri', 'bin', 'fixture-sidecar');
56
+ fs.writeFileSync(sidecar, 'fixture packaged runtime');
57
+ fixtureIdentity = { ...provenance.readFoundationRuntimeIdentity(root, sidecar), sourceTreeHash: fingerprints.computeSidecarSourceFingerprint(repoRoot).digest };
58
+ return root;
49
59
  }
50
60
  function writeJson(filePath, value) {
51
61
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
52
- fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
62
+ const report = structuredClone(value);
63
+ if (report.profileRuns) {
64
+ report.host = { nodeVersion: process.version, ...report.host };
65
+ report.provenance = {
66
+ schemaVersion: 1, runId: `${report.host.evidenceHostId}-${report.verifiedAt}`,
67
+ sourceRevision: 'a'.repeat(40), ...fixtureIdentity, workloadHash: provenance.foundationWorkloadHash(report),
68
+ };
69
+ for (const profile of report.profileRuns)
70
+ for (const mode of profile.modes) {
71
+ mode.runtime = { ...report.host };
72
+ if (mode.soak) {
73
+ const provided = new Map(mode.soak.gates.map((gate) => [gate.gateId, gate]));
74
+ mode.soak.gates = ['startup_p95', 'startup_max', 'ingest_p95', 'ingest_max', 'readiness_p95', 'diagnostics_p95', 'query_p95', 'query_max'].map(gateId => ({
75
+ observedMs: 100, maxAllowedMs: 2500, sampleCount: 8, passed: true, gateId, ...provided.get(gateId),
76
+ }));
77
+ }
78
+ if (mode.releaseGates) {
79
+ const provided = new Map(mode.releaseGates.gates.map((gate) => [gate.gateId, gate]));
80
+ mode.releaseGates.gates = ['startup_p95', 'ingest_p95', 'diagnostics_p95', 'query_p95', 'query_max', 'expected_recall'].map(gateId => ({
81
+ observed: gateId === 'expected_recall' ? 1 : 100, required: gateId === 'expected_recall' ? 1 : 2500,
82
+ comparison: gateId === 'expected_recall' ? 'gte' : 'lte', sampleCount: 8, passed: true, gateId, ...provided.get(gateId),
83
+ }));
84
+ }
85
+ }
86
+ }
87
+ fs.writeFileSync(filePath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
53
88
  }
54
89
  function buildPassingSqliteReport(verifiedAt, host = { platform: 'win32', arch: 'x64', evidenceHostId: 'windows-ci-a' }) {
55
90
  return {
@@ -203,7 +238,7 @@ describe('foundation release evidence freshness contract', () => {
203
238
  try {
204
239
  writeJson(sqliteReportPath, buildPassingSqliteReport('2026-06-05T23:00:00.000Z'));
205
240
  writeJson(annReportPath, buildPassingAnnReport('2026-06-05T22:00:00.000Z'));
206
- const result = verifier.verifyFoundationReleaseEvidence({
241
+ const result = verifier.verifyFoundationReleaseEvidence({ artifactRoot: tempRoot,
207
242
  sqliteReportPath,
208
243
  annReportPath,
209
244
  now,
@@ -233,7 +268,7 @@ describe('foundation release evidence freshness contract', () => {
233
268
  try {
234
269
  writeJson(sqliteReportPath, buildPassingSqliteReport('2026-06-01T00:00:00.000Z'));
235
270
  writeJson(annReportPath, buildPassingAnnReport('2026-06-05T22:00:00.000Z'));
236
- const result = verifier.verifyFoundationReleaseEvidence({
271
+ const result = verifier.verifyFoundationReleaseEvidence({ artifactRoot: tempRoot,
237
272
  sqliteReportPath,
238
273
  annReportPath,
239
274
  now,
@@ -246,6 +281,89 @@ describe('foundation release evidence freshness contract', () => {
246
281
  fs.rmSync(tempRoot, { recursive: true, force: true });
247
282
  }
248
283
  });
284
+ test('a later matrix run does not hide a fresh dated SQLite soak', () => {
285
+ const verifier = require(scriptPath);
286
+ const tempRoot = createTempReportRoot();
287
+ const sqliteReportPath = path.join(tempRoot, 'foundation-sqlite-runtime-report-latest.json');
288
+ const annReportPath = path.join(tempRoot, 'foundation-ann-runtime-report-latest.json');
289
+ try {
290
+ writeJson(sqliteReportPath, { ...buildPassingSqliteReport('2026-06-05T23:30:00.000Z'), suiteKind: 'matrix' });
291
+ writeJson(path.join(tempRoot, 'foundation-sqlite-runtime-report-2026-06-05T23-00-00.json'), buildPassingSqliteReport('2026-06-05T23:00:00.000Z'));
292
+ writeJson(annReportPath, buildPassingAnnReport('2026-06-05T23:00:00.000Z'));
293
+ const result = verifier.verifyFoundationReleaseEvidence({ artifactRoot: tempRoot, sqliteReportPath, annReportPath, now: new Date('2026-06-06T00:00:00Z') });
294
+ expect(result.ok).toBe(true);
295
+ expect(result.summary.sqlite.reportPath).toContain('2026-06-05T23-00-00');
296
+ }
297
+ finally {
298
+ fs.rmSync(tempRoot, { recursive: true, force: true });
299
+ }
300
+ });
301
+ test('latest and dated copies of one run do not count as repeated evidence', () => {
302
+ const verifier = require(scriptPath);
303
+ const tempRoot = createTempReportRoot();
304
+ const sqliteReportPath = path.join(tempRoot, 'foundation-sqlite-runtime-report-latest.json');
305
+ const annReportPath = path.join(tempRoot, 'foundation-ann-runtime-report-latest.json');
306
+ try {
307
+ const sqlite = buildPassingSqliteReport('2026-06-05T23:00:00.000Z');
308
+ const ann = buildPassingAnnReport('2026-06-05T23:00:00.000Z');
309
+ writeJson(sqliteReportPath, sqlite);
310
+ writeJson(annReportPath, ann);
311
+ writeJson(path.join(tempRoot, 'foundation-sqlite-runtime-report-copy.json'), sqlite);
312
+ writeJson(path.join(tempRoot, 'foundation-ann-runtime-report-copy.json'), ann);
313
+ const result = verifier.verifyFoundationReleaseEvidence({ artifactRoot: tempRoot, sqliteReportPath, annReportPath, minReportCount: 2, now: new Date('2026-06-06T00:00:00Z') });
314
+ expect(result.ok).toBe(false);
315
+ expect(result.summary.sqlite.reportCount).toBe(1);
316
+ expect(result.summary.ann.reportCount).toBe(1);
317
+ }
318
+ finally {
319
+ fs.rmSync(tempRoot, { recursive: true, force: true });
320
+ }
321
+ });
322
+ test.each([
323
+ ['missing provenance', (report) => { delete report.provenance; }],
324
+ ['wrong source', (report) => { report.provenance.sourceTreeHash = 'f'.repeat(64); }],
325
+ ['wrong artifact', (report) => { report.provenance.artifacts.packaged_sidecar.sha256 = 'f'.repeat(64); }],
326
+ ['changed workload', (report) => { report.profileRuns[0].workloadProfile.documentCount++; }],
327
+ ['unsupported runtime', (report) => { report.profileRuns[0].modes[0].runtime.nodeVersion = 'v20.19.0'; }],
328
+ ['future report', (report) => { report.verifiedAt = '2026-06-07T00:00:00Z'; }],
329
+ ['missing gate', (report) => { report.profileRuns[0].modes[0].soak.gates.pop(); }],
330
+ ['unsubstantiated pass', (report) => { report.profileRuns[0].modes[0].soak.gates[0].observedMs = 999999; }],
331
+ ])('rejects %s even if the report declares passing gates', (_name, mutate) => {
332
+ const verifier = require(scriptPath);
333
+ const tempRoot = createTempReportRoot();
334
+ const sqliteReportPath = path.join(tempRoot, 'foundation-sqlite-runtime-report-latest.json');
335
+ const annReportPath = path.join(tempRoot, 'foundation-ann-runtime-report-latest.json');
336
+ try {
337
+ writeJson(sqliteReportPath, buildPassingSqliteReport('2026-06-05T23:00:00Z'));
338
+ writeJson(annReportPath, buildPassingAnnReport('2026-06-05T23:00:00Z'));
339
+ const report = readJson(sqliteReportPath);
340
+ mutate(report);
341
+ fs.writeFileSync(sqliteReportPath, JSON.stringify(report));
342
+ const result = verifier.verifyFoundationReleaseEvidence({ artifactRoot: tempRoot, sqliteReportPath, annReportPath, now: new Date('2026-06-06T00:00:00Z') });
343
+ expect(result.ok).toBe(false);
344
+ expect(result.errors.length).toBeGreaterThan(0);
345
+ }
346
+ finally {
347
+ fs.rmSync(tempRoot, { recursive: true, force: true });
348
+ }
349
+ });
350
+ test('an eligible recent failure is not masked by an older passing soak', () => {
351
+ const verifier = require(scriptPath);
352
+ const tempRoot = createTempReportRoot();
353
+ const sqliteReportPath = path.join(tempRoot, 'foundation-sqlite-runtime-report-latest.json');
354
+ const annReportPath = path.join(tempRoot, 'foundation-ann-runtime-report-latest.json');
355
+ try {
356
+ const failed = buildPassingSqliteReport('2026-06-05T23:30:00.000Z');
357
+ failed.profileRuns[0].modes[0].soak.pass = false;
358
+ writeJson(sqliteReportPath, failed);
359
+ writeJson(path.join(tempRoot, 'foundation-sqlite-runtime-report-earlier.json'), buildPassingSqliteReport('2026-06-05T23:00:00.000Z'));
360
+ writeJson(annReportPath, buildPassingAnnReport('2026-06-05T23:00:00.000Z'));
361
+ expect(verifier.verifyFoundationReleaseEvidence({ artifactRoot: tempRoot, sqliteReportPath, annReportPath, now: new Date('2026-06-06T00:00:00Z') }).ok).toBe(false);
362
+ }
363
+ finally {
364
+ fs.rmSync(tempRoot, { recursive: true, force: true });
365
+ }
366
+ });
249
367
  test('accepts repeated sqlite and ANN release evidence when enough fresh history reports exist', () => {
250
368
  const verifier = require(scriptPath);
251
369
  const tempRoot = createTempReportRoot();
@@ -257,7 +375,7 @@ describe('foundation release evidence freshness contract', () => {
257
375
  writeJson(path.join(tempRoot, 'sqlite', 'foundation-sqlite-runtime-report-2026-06-05T22-30-00-000Z.json'), buildPassingSqliteReport('2026-06-05T22:30:00.000Z'));
258
376
  writeJson(annReportPath, buildPassingAnnReport('2026-06-05T22:00:00.000Z'));
259
377
  writeJson(path.join(tempRoot, 'ann', 'foundation-ann-runtime-report-2026-06-05T21-30-00-000Z.json'), buildPassingAnnReport('2026-06-05T21:30:00.000Z'));
260
- const result = verifier.verifyFoundationReleaseEvidence({
378
+ const result = verifier.verifyFoundationReleaseEvidence({ artifactRoot: tempRoot,
261
379
  sqliteReportPath,
262
380
  annReportPath,
263
381
  now,
@@ -292,7 +410,7 @@ describe('foundation release evidence freshness contract', () => {
292
410
  writeJson(path.join(tempRoot, 'sqlite', 'foundation-sqlite-runtime-report-2026-06-05T22-30-00-000Z.json'), buildPassingSqliteReport('2026-06-05T22:30:00.000Z', linuxHost));
293
411
  writeJson(annReportPath, buildPassingAnnReport('2026-06-05T22:00:00.000Z', windowsHost));
294
412
  writeJson(path.join(tempRoot, 'ann', 'foundation-ann-runtime-report-2026-06-05T21-30-00-000Z.json'), buildPassingAnnReport('2026-06-05T21:30:00.000Z', linuxHost));
295
- const result = verifier.verifyFoundationReleaseEvidence({
413
+ const result = verifier.verifyFoundationReleaseEvidence({ artifactRoot: tempRoot,
296
414
  sqliteReportPath,
297
415
  annReportPath,
298
416
  now,
@@ -331,7 +449,7 @@ describe('foundation release evidence freshness contract', () => {
331
449
  writeJson(path.join(tempRoot, 'sqlite', 'foundation-sqlite-runtime-report-2026-06-05T22-30-00-000Z.json'), buildPassingSqliteReport('2026-06-05T22:30:00.000Z', windowsHost));
332
450
  writeJson(annReportPath, buildPassingAnnReport('2026-06-05T22:00:00.000Z', windowsHost));
333
451
  writeJson(path.join(tempRoot, 'ann', 'foundation-ann-runtime-report-2026-06-05T21-30-00-000Z.json'), buildPassingAnnReport('2026-06-05T21:30:00.000Z', windowsHost));
334
- const result = verifier.verifyFoundationReleaseEvidence({
452
+ const result = verifier.verifyFoundationReleaseEvidence({ artifactRoot: tempRoot,
335
453
  sqliteReportPath,
336
454
  annReportPath,
337
455
  now,
@@ -356,7 +474,7 @@ describe('foundation release evidence freshness contract', () => {
356
474
  try {
357
475
  writeJson(sqliteReportPath, buildPassingSqliteReport('2026-06-05T23:00:00.000Z'));
358
476
  writeJson(annReportPath, buildPassingAnnReport('2026-06-05T22:00:00.000Z'));
359
- const result = verifier.verifyFoundationReleaseEvidence({
477
+ const result = verifier.verifyFoundationReleaseEvidence({ artifactRoot: tempRoot,
360
478
  sqliteReportPath,
361
479
  annReportPath,
362
480
  now,
@@ -382,7 +500,7 @@ describe('foundation release evidence freshness contract', () => {
382
500
  writeJson(path.join(tempRoot, 'sqlite', 'foundation-sqlite-runtime-report-2026-05-30T00-00-00-000Z.json'), buildPassingSqliteReport('2026-05-30T00:00:00.000Z'));
383
501
  writeJson(annReportPath, buildPassingAnnReport('2026-06-05T22:00:00.000Z'));
384
502
  writeJson(path.join(tempRoot, 'ann', 'foundation-ann-runtime-report-2026-06-05T21-00-00-000Z.json'), buildNonReleaseAnnReport('2026-06-05T21:00:00.000Z'));
385
- const result = verifier.verifyFoundationReleaseEvidence({
503
+ const result = verifier.verifyFoundationReleaseEvidence({ artifactRoot: tempRoot,
386
504
  sqliteReportPath,
387
505
  annReportPath,
388
506
  now,
@@ -68,6 +68,12 @@ describe('foundation sqlite runtime verification contract', () => {
68
68
  expect(source).toContain('/api/knowledge/query');
69
69
  expect(source).toContain("graphBackendSignalKind === 'embedded_graphdb'");
70
70
  expect(source).toContain("storageEngine === 'sqlite'");
71
+ expect(source).toContain("requestedProvider === 'sqlite'");
72
+ expect(source).toContain("resolvedProvider === 'sqlite'");
73
+ expect(source).toContain('fallbackReason');
74
+ expect(source).toContain("storageRequestedProvider === 'sqlite'");
75
+ expect(source).toContain("storageResolvedProvider === 'sqlite'");
76
+ expect(source).toContain('storageSupportsSqlite === true');
71
77
  expect(source).toContain("usingFallback !== true");
72
78
  expect(source).toContain("genericQuery: 'persist graph content restart sqlite proof'");
73
79
  expect(source).toContain('graphDbLastSnapshotMetadata');