@lucern/graph-primitives 0.1.0-alpha.2

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 (224) hide show
  1. package/README.md +29 -0
  2. package/dist/beliefDecay-Q_26RTc-.d.ts +72 -0
  3. package/dist/beliefDecay.d.ts +2 -0
  4. package/dist/beliefDecay.js +1628 -0
  5. package/dist/beliefDecay.js.map +1 -0
  6. package/dist/beliefEvidenceLinks-42FlR48t.d.ts +77 -0
  7. package/dist/beliefEvidenceLinks.d.ts +1 -0
  8. package/dist/beliefEvidenceLinks.js +1978 -0
  9. package/dist/beliefEvidenceLinks.js.map +1 -0
  10. package/dist/beliefLifecycle-C-AehZgF.d.ts +43 -0
  11. package/dist/beliefLifecycle.d.ts +1 -0
  12. package/dist/beliefLifecycle.js +98 -0
  13. package/dist/beliefLifecycle.js.map +1 -0
  14. package/dist/confidencePropagationDispatch.d.ts +46 -0
  15. package/dist/confidencePropagationDispatch.js +744 -0
  16. package/dist/confidencePropagationDispatch.js.map +1 -0
  17. package/dist/contradictions-Hdwl7zid.d.ts +71 -0
  18. package/dist/contradictions.d.ts +1 -0
  19. package/dist/contradictions.js +1557 -0
  20. package/dist/contradictions.js.map +1 -0
  21. package/dist/convex.d.ts +23 -0
  22. package/dist/convex.js +17 -0
  23. package/dist/convex.js.map +1 -0
  24. package/dist/edgeValidation-CeI0wc0r.d.ts +35 -0
  25. package/dist/edgeValidation.d.ts +2 -0
  26. package/dist/edgeValidation.js +307 -0
  27. package/dist/edgeValidation.js.map +1 -0
  28. package/dist/edges/contains.d.ts +6 -0
  29. package/dist/edges/contains.js +14 -0
  30. package/dist/edges/contains.js.map +1 -0
  31. package/dist/edges/contradicts.d.ts +6 -0
  32. package/dist/edges/contradicts.js +183 -0
  33. package/dist/edges/contradicts.js.map +1 -0
  34. package/dist/edges/dependsOn.d.ts +6 -0
  35. package/dist/edges/dependsOn.js +240 -0
  36. package/dist/edges/dependsOn.js.map +1 -0
  37. package/dist/edges/derivedFrom.d.ts +6 -0
  38. package/dist/edges/derivedFrom.js +14 -0
  39. package/dist/edges/derivedFrom.js.map +1 -0
  40. package/dist/edges/elaborates.d.ts +6 -0
  41. package/dist/edges/elaborates.js +100 -0
  42. package/dist/edges/elaborates.js.map +1 -0
  43. package/dist/edges/index.d.ts +3 -0
  44. package/dist/edges/index.js +556 -0
  45. package/dist/edges/index.js.map +1 -0
  46. package/dist/edges/informs.d.ts +6 -0
  47. package/dist/edges/informs.js +112 -0
  48. package/dist/edges/informs.js.map +1 -0
  49. package/dist/edges/propagationTypes.d.ts +39 -0
  50. package/dist/edges/propagationTypes.js +17 -0
  51. package/dist/edges/propagationTypes.js.map +1 -0
  52. package/dist/edges/refutes.d.ts +6 -0
  53. package/dist/edges/refutes.js +108 -0
  54. package/dist/edges/refutes.js.map +1 -0
  55. package/dist/edges/supports.d.ts +6 -0
  56. package/dist/edges/supports.js +193 -0
  57. package/dist/edges/supports.js.map +1 -0
  58. package/dist/edges/tests.d.ts +6 -0
  59. package/dist/edges/tests.js +14 -0
  60. package/dist/edges/tests.js.map +1 -0
  61. package/dist/edges/utils.d.ts +12 -0
  62. package/dist/edges/utils.js +188 -0
  63. package/dist/edges/utils.js.map +1 -0
  64. package/dist/embeddingTrigger.d.ts +24 -0
  65. package/dist/embeddingTrigger.js +24 -0
  66. package/dist/embeddingTrigger.js.map +1 -0
  67. package/dist/entityBridge-DMaKooYn.d.ts +59 -0
  68. package/dist/entityBridge.d.ts +1 -0
  69. package/dist/entityBridge.js +663 -0
  70. package/dist/entityBridge.js.map +1 -0
  71. package/dist/entityLifecycle-BkhRJ-XI.d.ts +69 -0
  72. package/dist/entityLifecycle.d.ts +1 -0
  73. package/dist/entityLifecycle.js +2083 -0
  74. package/dist/entityLifecycle.js.map +1 -0
  75. package/dist/entityValidation-KLZ_Xl2D.d.ts +50 -0
  76. package/dist/entityValidation.d.ts +3 -0
  77. package/dist/entityValidation.js +71 -0
  78. package/dist/entityValidation.js.map +1 -0
  79. package/dist/epistemicAnswers-DSP1slZ9.d.ts +67 -0
  80. package/dist/epistemicAnswers.d.ts +1 -0
  81. package/dist/epistemicAnswers.js +1650 -0
  82. package/dist/epistemicAnswers.js.map +1 -0
  83. package/dist/epistemicBeliefs-DtFVTp-k.d.ts +377 -0
  84. package/dist/epistemicBeliefs.d.ts +5 -0
  85. package/dist/epistemicBeliefs.js +6386 -0
  86. package/dist/epistemicBeliefs.js.map +1 -0
  87. package/dist/epistemicContractHelpers.d.ts +1 -0
  88. package/dist/epistemicContractHelpers.js +320 -0
  89. package/dist/epistemicContractHelpers.js.map +1 -0
  90. package/dist/epistemicContracts.d.ts +77 -0
  91. package/dist/epistemicContracts.js +8436 -0
  92. package/dist/epistemicContracts.js.map +1 -0
  93. package/dist/epistemicEdges-DcA8ErUG.d.ts +191 -0
  94. package/dist/epistemicEdges.d.ts +2 -0
  95. package/dist/epistemicEdges.js +2749 -0
  96. package/dist/epistemicEdges.js.map +1 -0
  97. package/dist/epistemicEvidence-Bo638XDP.d.ts +128 -0
  98. package/dist/epistemicEvidence.d.ts +3 -0
  99. package/dist/epistemicEvidence.js +3282 -0
  100. package/dist/epistemicEvidence.js.map +1 -0
  101. package/dist/epistemicHelpers-Bd9xbaib.d.ts +329 -0
  102. package/dist/epistemicHelpers.d.ts +4 -0
  103. package/dist/epistemicHelpers.js +999 -0
  104. package/dist/epistemicHelpers.js.map +1 -0
  105. package/dist/epistemicLinking-CyeLOIzN.d.ts +35 -0
  106. package/dist/epistemicLinking.d.ts +1 -0
  107. package/dist/epistemicLinking.js +1391 -0
  108. package/dist/epistemicLinking.js.map +1 -0
  109. package/dist/epistemicNodes-BpD6Koud.d.ts +167 -0
  110. package/dist/epistemicNodes.d.ts +2 -0
  111. package/dist/epistemicNodes.js +2942 -0
  112. package/dist/epistemicNodes.js.map +1 -0
  113. package/dist/epistemicQuestions-CmEeY6zQ.d.ts +214 -0
  114. package/dist/epistemicQuestions.d.ts +3 -0
  115. package/dist/epistemicQuestions.js +4993 -0
  116. package/dist/epistemicQuestions.js.map +1 -0
  117. package/dist/epistemicSources-ZazxHOK1.d.ts +25 -0
  118. package/dist/epistemicSources.d.ts +1 -0
  119. package/dist/epistemicSources.js +2025 -0
  120. package/dist/epistemicSources.js.map +1 -0
  121. package/dist/evaluators/index.d.ts +9 -0
  122. package/dist/evaluators/index.js +8440 -0
  123. package/dist/evaluators/index.js.map +1 -0
  124. package/dist/evaluators/lintCheckerEvaluator.d.ts +11 -0
  125. package/dist/evaluators/lintCheckerEvaluator.js +155 -0
  126. package/dist/evaluators/lintCheckerEvaluator.js.map +1 -0
  127. package/dist/evaluators/sentryCheckerEvaluator.d.ts +11 -0
  128. package/dist/evaluators/sentryCheckerEvaluator.js +126 -0
  129. package/dist/evaluators/sentryCheckerEvaluator.js.map +1 -0
  130. package/dist/evaluators/shared.d.ts +27 -0
  131. package/dist/evaluators/shared.js +92 -0
  132. package/dist/evaluators/shared.js.map +1 -0
  133. package/dist/evaluators/testRunnerEvaluator.d.ts +17 -0
  134. package/dist/evaluators/testRunnerEvaluator.js +232 -0
  135. package/dist/evaluators/testRunnerEvaluator.js.map +1 -0
  136. package/dist/evaluators/tscCheckerEvaluator.d.ts +11 -0
  137. package/dist/evaluators/tscCheckerEvaluator.js +189 -0
  138. package/dist/evaluators/tscCheckerEvaluator.js.map +1 -0
  139. package/dist/globalId-DKh9d_uD.d.ts +20 -0
  140. package/dist/globalId.d.ts +1 -0
  141. package/dist/globalId.js +15 -0
  142. package/dist/globalId.js.map +1 -0
  143. package/dist/graphTypes-CpgIuCdo.d.ts +52 -0
  144. package/dist/graphTypes.d.ts +1 -0
  145. package/dist/graphTypes.js +120 -0
  146. package/dist/graphTypes.js.map +1 -0
  147. package/dist/helpers-BYHIk5vU.d.ts +27 -0
  148. package/dist/helpers.d.ts +4 -0
  149. package/dist/helpers.js +313 -0
  150. package/dist/helpers.js.map +1 -0
  151. package/dist/index-Dct1T70K.d.ts +25 -0
  152. package/dist/index-Dq-7R-gi.d.ts +31 -0
  153. package/dist/index.d.ts +45 -0
  154. package/dist/index.js +22294 -0
  155. package/dist/index.js.map +1 -0
  156. package/dist/invariantEnforcement.d.ts +52 -0
  157. package/dist/invariantEnforcement.js +231 -0
  158. package/dist/invariantEnforcement.js.map +1 -0
  159. package/dist/logicalRoleInference-CJxqWi3u.d.ts +16 -0
  160. package/dist/logicalRoleInference.d.ts +3 -0
  161. package/dist/logicalRoleInference.js +64 -0
  162. package/dist/logicalRoleInference.js.map +1 -0
  163. package/dist/matcherFeedbackUtils.d.ts +33 -0
  164. package/dist/matcherFeedbackUtils.js +95 -0
  165. package/dist/matcherFeedbackUtils.js.map +1 -0
  166. package/dist/ontology-matching-Buhu23ss.d.ts +48 -0
  167. package/dist/ontology-matching.d.ts +2 -0
  168. package/dist/ontology-matching.js +346 -0
  169. package/dist/ontology-matching.js.map +1 -0
  170. package/dist/ontologyApproval-Ba0Jjk1k.d.ts +26 -0
  171. package/dist/ontologyApproval.d.ts +1 -0
  172. package/dist/ontologyApproval.js +78 -0
  173. package/dist/ontologyApproval.js.map +1 -0
  174. package/dist/ontologyDefinitions.d.ts +72 -0
  175. package/dist/ontologyDefinitions.js +635 -0
  176. package/dist/ontologyDefinitions.js.map +1 -0
  177. package/dist/ontologyHelpers.d.ts +79 -0
  178. package/dist/ontologyHelpers.js +81 -0
  179. package/dist/ontologyHelpers.js.map +1 -0
  180. package/dist/ontologyRegistry-B67rPJ16.d.ts +31 -0
  181. package/dist/ontologyRegistry.d.ts +1 -0
  182. package/dist/ontologyRegistry.js +296 -0
  183. package/dist/ontologyRegistry.js.map +1 -0
  184. package/dist/projectionReconciliation-CxrXYGaB.d.ts +20 -0
  185. package/dist/projectionReconciliation.d.ts +1 -0
  186. package/dist/projectionReconciliation.js +261 -0
  187. package/dist/projectionReconciliation.js.map +1 -0
  188. package/dist/projectionStaleness-CAdpIsaW.d.ts +51 -0
  189. package/dist/projectionStaleness.d.ts +1 -0
  190. package/dist/projectionStaleness.js +57 -0
  191. package/dist/projectionStaleness.js.map +1 -0
  192. package/dist/questionEvidenceLinks-BdQD0TkM.d.ts +34 -0
  193. package/dist/questionEvidenceLinks.d.ts +1 -0
  194. package/dist/questionEvidenceLinks.js +1690 -0
  195. package/dist/questionEvidenceLinks.js.map +1 -0
  196. package/dist/resolverTypes-CC8Ea2E2.d.ts +20 -0
  197. package/dist/resolverTypes.d.ts +4 -0
  198. package/dist/resolverTypes.js +3 -0
  199. package/dist/resolverTypes.js.map +1 -0
  200. package/dist/resolvers-Br1a6eLV.d.ts +14 -0
  201. package/dist/resolvers.d.ts +5 -0
  202. package/dist/resolvers.js +308 -0
  203. package/dist/resolvers.js.map +1 -0
  204. package/dist/scopeResolverCompat.d.ts +26 -0
  205. package/dist/scopeResolverCompat.js +242 -0
  206. package/dist/scopeResolverCompat.js.map +1 -0
  207. package/dist/text-matching-CMn2WnVD.d.ts +40 -0
  208. package/dist/text-matching.d.ts +2 -0
  209. package/dist/text-matching.js +246 -0
  210. package/dist/text-matching.js.map +1 -0
  211. package/dist/topicOntologyResolver.d.ts +80 -0
  212. package/dist/topicOntologyResolver.js +67 -0
  213. package/dist/topicOntologyResolver.js.map +1 -0
  214. package/dist/topicProjectOverlay.d.ts +92 -0
  215. package/dist/topicProjectOverlay.js +249 -0
  216. package/dist/topicProjectOverlay.js.map +1 -0
  217. package/dist/topicScope-By_zp4tt.d.ts +34 -0
  218. package/dist/topicScope.d.ts +3 -0
  219. package/dist/topicScope.js +206 -0
  220. package/dist/topicScope.js.map +1 -0
  221. package/dist/workspaceIsolation.d.ts +44 -0
  222. package/dist/workspaceIsolation.js +950 -0
  223. package/dist/workspaceIsolation.js.map +1 -0
  224. package/package.json +46 -0
@@ -0,0 +1,11 @@
1
+ import { EngineeringEpistemicEvaluator } from './testRunnerEvaluator.js';
2
+ import '@lucern/confidence';
3
+ import '../epistemicContracts.js';
4
+ import '../convex.js';
5
+ import 'convex/values';
6
+
7
+ /** Lint-based engineering evaluator for epistemic contracts. */
8
+
9
+ declare const lintCheckerEvaluator: EngineeringEpistemicEvaluator;
10
+
11
+ export { lintCheckerEvaluator };
@@ -0,0 +1,155 @@
1
+ // src/evaluators/shared.ts
2
+ function asArray(value) {
3
+ return Array.isArray(value) ? value : [];
4
+ }
5
+ function asNumber(value) {
6
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
7
+ }
8
+ function asRecord(value) {
9
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
10
+ }
11
+ function asString(value) {
12
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
13
+ }
14
+ function deriveDirectionalResult(direction, conditionSatisfied) {
15
+ if (direction === "falsifies") {
16
+ return conditionSatisfied ? "disconfirmed" : "confirmed";
17
+ }
18
+ return conditionSatisfied ? "confirmed" : "disconfirmed";
19
+ }
20
+ function normalizeFilePath(value) {
21
+ return value.replace(/\\/g, "/").replace(/^\.\//, "");
22
+ }
23
+ function normalizeToolResultEnvelope(value) {
24
+ const record = asRecord(value);
25
+ if (!record) {
26
+ return {
27
+ output: asString(value) ?? void 0
28
+ };
29
+ }
30
+ const exitCode = asNumber(record.exitCode) ?? asNumber(record.code) ?? asNumber(record.status) ?? null;
31
+ return {
32
+ command: asString(record.command) ?? void 0,
33
+ data: record.data ?? record.payload,
34
+ exitCode,
35
+ output: asString(record.output) ?? void 0,
36
+ report: record.report ?? record.json ?? record.result ?? record.payload ?? void 0,
37
+ stderr: asString(record.stderr) ?? void 0,
38
+ stdout: asString(record.stdout) ?? void 0
39
+ };
40
+ }
41
+ function patternMatchesPath(filePath, pattern) {
42
+ const normalizedPath = normalizeFilePath(filePath);
43
+ const normalizedPattern = normalizeFilePath(pattern);
44
+ const escaped = normalizedPattern.replace(/[.+^${}()|[\]\\]/g, "\\$&");
45
+ const regexPattern = escaped.replace(/\\\*\\\*/g, ".*").replace(/\\\*/g, "[^/]*").replace(/\\\?/g, "[^/]");
46
+ return new RegExp(`^${regexPattern}$`).test(normalizedPath);
47
+ }
48
+ function somePatternMatches(filePath, patterns) {
49
+ if (!filePath) {
50
+ return false;
51
+ }
52
+ return patterns.some((pattern) => patternMatchesPath(filePath, pattern));
53
+ }
54
+
55
+ // src/evaluators/lintCheckerEvaluator.ts
56
+ function parseConfig(condition) {
57
+ const record = asRecord(condition.evaluatorConfig);
58
+ if (!record) {
59
+ throw new Error(
60
+ 'lint_checker requires evaluatorConfig with { filePatterns: string[], linter: "biome" }.'
61
+ );
62
+ }
63
+ const filePatterns = asArray(record.filePatterns).map(asString).filter((pattern) => Boolean(pattern));
64
+ if (filePatterns.length === 0) {
65
+ throw new Error("lint_checker requires at least one file pattern.");
66
+ }
67
+ const linter = asString(record.linter);
68
+ if (linter !== "biome") {
69
+ throw new Error(`Unsupported linter: ${String(record.linter)}`);
70
+ }
71
+ return {
72
+ filePatterns,
73
+ linter
74
+ };
75
+ }
76
+ function parseDiagnostics(resultData) {
77
+ const envelope = normalizeToolResultEnvelope(resultData);
78
+ const record = asRecord(envelope.report) ?? asRecord(envelope.data) ?? asRecord(resultData);
79
+ if (!record) {
80
+ return [];
81
+ }
82
+ return asArray(record.diagnostics).map((entry) => {
83
+ const diagnostic = asRecord(entry);
84
+ if (!diagnostic) {
85
+ return null;
86
+ }
87
+ const location = asRecord(diagnostic.location);
88
+ const pathRecord = asRecord(location?.path);
89
+ const filePath = asString(diagnostic.filePath) ?? asString(diagnostic.file) ?? asString(location?.filePath) ?? asString(pathRecord?.file);
90
+ const severity = asString(diagnostic.severity) ?? "error";
91
+ const message = asString(diagnostic.message) ?? asString(diagnostic.description) ?? "Lint issue";
92
+ return {
93
+ filePath: filePath ? normalizeFilePath(filePath) : null,
94
+ message,
95
+ severity
96
+ };
97
+ }).filter(
98
+ (diagnostic) => Boolean(diagnostic)
99
+ );
100
+ }
101
+ function getMatchedDiagnostics(contract, resultData) {
102
+ const config = parseConfig(contract.condition);
103
+ return parseDiagnostics(resultData).filter(
104
+ (diagnostic) => somePatternMatches(diagnostic.filePath, config.filePatterns)
105
+ );
106
+ }
107
+ var lintCheckerEvaluator = {
108
+ name: "lint_checker",
109
+ matches({ contract, resultData }) {
110
+ const envelope = normalizeToolResultEnvelope(resultData);
111
+ const exitCode = asNumber(envelope.exitCode);
112
+ if (exitCode === 0) {
113
+ return true;
114
+ }
115
+ return getMatchedDiagnostics(contract, resultData).length > 0;
116
+ },
117
+ evaluate(args) {
118
+ const config = parseConfig(args.contract.condition);
119
+ if (!args.resultData) {
120
+ return {
121
+ result: "error",
122
+ rationale: "lint_checker requires Biome lint resultData."
123
+ };
124
+ }
125
+ const envelope = normalizeToolResultEnvelope(args.resultData);
126
+ const exitCode = asNumber(envelope.exitCode);
127
+ const matchedDiagnostics = getMatchedDiagnostics(args.contract, args.resultData);
128
+ if (matchedDiagnostics.length === 0 && exitCode !== 0 && exitCode !== null) {
129
+ return {
130
+ result: "inconclusive",
131
+ rationale: "Biome reported issues, but none matched the configured file patterns."
132
+ };
133
+ }
134
+ const conditionSatisfied = exitCode === 0 || exitCode !== null && matchedDiagnostics.length === 0;
135
+ return {
136
+ result: deriveDirectionalResult(
137
+ args.contract.direction,
138
+ conditionSatisfied
139
+ ),
140
+ rationale: conditionSatisfied ? `Biome reported no matching lint diagnostics for ${config.filePatterns.join(", ")}.` : `Biome reported ${matchedDiagnostics.length} matching issue(s): ${matchedDiagnostics.map(
141
+ (diagnostic) => diagnostic.filePath ? `${diagnostic.filePath} (${diagnostic.severity})` : diagnostic.message
142
+ ).join(", ")}.`,
143
+ data: {
144
+ exitCode,
145
+ filePatterns: config.filePatterns,
146
+ linter: config.linter,
147
+ matchedDiagnostics
148
+ }
149
+ };
150
+ }
151
+ };
152
+
153
+ export { lintCheckerEvaluator };
154
+ //# sourceMappingURL=lintCheckerEvaluator.js.map
155
+ //# sourceMappingURL=lintCheckerEvaluator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/evaluators/shared.ts","../../src/evaluators/lintCheckerEvaluator.ts"],"names":[],"mappings":"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","file":"lintCheckerEvaluator.js","sourcesContent":["/** Shared evaluator helpers and result-normalization utilities. */\n\nimport type {\n EpistemicContractDirection,\n EpistemicContractEvaluationResult,\n} from \"../epistemicContractHelpers\";\n\nexport type ToolResultEnvelope = {\n command?: string;\n data?: unknown;\n exitCode?: number | null;\n output?: string;\n report?: unknown;\n stderr?: string;\n stdout?: string;\n};\n\ntype AnyRecord = Record<string, unknown>;\n\nexport function asArray(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nexport function asNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nexport function asRecord(value: unknown): AnyRecord | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as AnyRecord)\n : null;\n}\n\nexport function asString(value: unknown): string | null {\n return typeof value === \"string\" && value.trim().length > 0\n ? value.trim()\n : null;\n}\n\nexport function deriveDirectionalResult(\n direction: EpistemicContractDirection,\n conditionSatisfied: boolean\n): EpistemicContractEvaluationResult {\n if (direction === \"falsifies\") {\n return conditionSatisfied ? \"disconfirmed\" : \"confirmed\";\n }\n return conditionSatisfied ? \"confirmed\" : \"disconfirmed\";\n}\n\nexport function extractTextCandidates(value: unknown): string[] {\n const record = asRecord(value);\n if (!record) {\n const candidate = asString(value);\n return candidate ? [candidate] : [];\n }\n\n const candidates = [\n record.stdout,\n record.stderr,\n record.output,\n record.text,\n record.message,\n record.raw,\n ]\n .map(asString)\n .filter((candidate): candidate is string => Boolean(candidate));\n\n for (const nestedKey of [\"report\", \"result\", \"data\", \"payload\"]) {\n const nested = record[nestedKey];\n if (nested !== value) {\n candidates.push(...extractTextCandidates(nested));\n }\n }\n\n return Array.from(new Set(candidates));\n}\n\nexport function normalizeFilePath(value: string): string {\n return value.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n\nexport function normalizeToolResultEnvelope(value: unknown): ToolResultEnvelope {\n const record = asRecord(value);\n if (!record) {\n return {\n output: asString(value) ?? undefined,\n };\n }\n\n const exitCode =\n asNumber(record.exitCode) ??\n asNumber(record.code) ??\n asNumber(record.status) ??\n null;\n\n return {\n command: asString(record.command) ?? undefined,\n data: record.data ?? record.payload,\n exitCode,\n output: asString(record.output) ?? undefined,\n report:\n record.report ??\n record.json ??\n record.result ??\n record.payload ??\n undefined,\n stderr: asString(record.stderr) ?? undefined,\n stdout: asString(record.stdout) ?? undefined,\n };\n}\n\nexport function parseJsonCandidate<T = unknown>(value: unknown): T | null {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value !== \"string\") {\n return value as T;\n }\n\n try {\n return JSON.parse(value) as T;\n } catch {\n return null;\n }\n}\n\nexport function patternMatchesPath(\n filePath: string,\n pattern: string\n): boolean {\n const normalizedPath = normalizeFilePath(filePath);\n const normalizedPattern = normalizeFilePath(pattern);\n const escaped = normalizedPattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regexPattern = escaped\n .replace(/\\\\\\*\\\\\\*/g, \".*\")\n .replace(/\\\\\\*/g, \"[^/]*\")\n .replace(/\\\\\\?/g, \"[^/]\");\n return new RegExp(`^${regexPattern}$`).test(normalizedPath);\n}\n\nexport function somePatternMatches(\n filePath: string | null | undefined,\n patterns: string[]\n): boolean {\n if (!filePath) {\n return false;\n }\n return patterns.some((pattern) => patternMatchesPath(filePath, pattern));\n}\n","/** Lint-based engineering evaluator for epistemic contracts. */\n\nimport type {\n EpistemicContractCondition,\n EpistemicContractRecord,\n} from \"../epistemicContractHelpers\";\nimport type {\n EpistemicEvaluatorContext,\n EpistemicEvaluatorResult,\n} from \"../epistemicContracts\";\nimport {\n asArray,\n asNumber,\n asRecord,\n asString,\n deriveDirectionalResult,\n normalizeFilePath,\n normalizeToolResultEnvelope,\n somePatternMatches,\n} from \"./shared\";\nimport type { EngineeringEpistemicEvaluator } from \"./testRunnerEvaluator\";\n\ntype AnyContract = Pick<EpistemicContractRecord, \"condition\">;\n\ntype ParsedLintDiagnostic = {\n filePath: string | null;\n message: string;\n severity: string;\n};\n\ntype LintCheckerConfig = {\n filePatterns: string[];\n linter: \"biome\";\n};\n\nfunction parseConfig(condition: EpistemicContractCondition): LintCheckerConfig {\n const record = asRecord(condition.evaluatorConfig);\n if (!record) {\n throw new Error(\n \"lint_checker requires evaluatorConfig with { filePatterns: string[], linter: \\\"biome\\\" }.\"\n );\n }\n\n const filePatterns = asArray(record.filePatterns)\n .map(asString)\n .filter((pattern): pattern is string => Boolean(pattern));\n if (filePatterns.length === 0) {\n throw new Error(\"lint_checker requires at least one file pattern.\");\n }\n\n const linter = asString(record.linter);\n if (linter !== \"biome\") {\n throw new Error(`Unsupported linter: ${String(record.linter)}`);\n }\n\n return {\n filePatterns,\n linter,\n };\n}\n\nfunction parseDiagnostics(resultData: unknown): ParsedLintDiagnostic[] {\n const envelope = normalizeToolResultEnvelope(resultData);\n const record =\n asRecord(envelope.report) ?? asRecord(envelope.data) ?? asRecord(resultData);\n if (!record) {\n return [];\n }\n\n return asArray(record.diagnostics)\n .map((entry) => {\n const diagnostic = asRecord(entry);\n if (!diagnostic) {\n return null;\n }\n const location = asRecord(diagnostic.location);\n const pathRecord = asRecord(location?.path);\n const filePath =\n asString(diagnostic.filePath) ??\n asString(diagnostic.file) ??\n asString(location?.filePath) ??\n asString(pathRecord?.file);\n const severity = asString(diagnostic.severity) ?? \"error\";\n const message =\n asString(diagnostic.message) ??\n asString(diagnostic.description) ??\n \"Lint issue\";\n return {\n filePath: filePath ? normalizeFilePath(filePath) : null,\n message,\n severity,\n };\n })\n .filter(\n (diagnostic): diagnostic is ParsedLintDiagnostic => Boolean(diagnostic)\n );\n}\n\nfunction getMatchedDiagnostics(\n contract: AnyContract,\n resultData: unknown\n): ParsedLintDiagnostic[] {\n const config = parseConfig(contract.condition);\n return parseDiagnostics(resultData).filter((diagnostic) =>\n somePatternMatches(diagnostic.filePath, config.filePatterns)\n );\n}\n\nexport const lintCheckerEvaluator: EngineeringEpistemicEvaluator = {\n name: \"lint_checker\",\n matches({ contract, resultData }) {\n const envelope = normalizeToolResultEnvelope(resultData);\n const exitCode = asNumber(envelope.exitCode);\n if (exitCode === 0) {\n return true;\n }\n return getMatchedDiagnostics(contract, resultData).length > 0;\n },\n evaluate(args: EpistemicEvaluatorContext): EpistemicEvaluatorResult {\n const config = parseConfig(args.contract.condition);\n if (!args.resultData) {\n return {\n result: \"error\",\n rationale: \"lint_checker requires Biome lint resultData.\",\n };\n }\n\n const envelope = normalizeToolResultEnvelope(args.resultData);\n const exitCode = asNumber(envelope.exitCode);\n const matchedDiagnostics = getMatchedDiagnostics(args.contract, args.resultData);\n\n if (matchedDiagnostics.length === 0 && exitCode !== 0 && exitCode !== null) {\n return {\n result: \"inconclusive\",\n rationale:\n \"Biome reported issues, but none matched the configured file patterns.\",\n };\n }\n\n const conditionSatisfied =\n exitCode === 0 || (exitCode !== null && matchedDiagnostics.length === 0);\n\n return {\n result: deriveDirectionalResult(\n args.contract.direction,\n conditionSatisfied\n ),\n rationale: conditionSatisfied\n ? `Biome reported no matching lint diagnostics for ${config.filePatterns.join(\", \")}.`\n : `Biome reported ${matchedDiagnostics.length} matching issue(s): ${matchedDiagnostics\n .map((diagnostic) =>\n diagnostic.filePath\n ? `${diagnostic.filePath} (${diagnostic.severity})`\n : diagnostic.message\n )\n .join(\", \")}.`,\n data: {\n exitCode,\n filePatterns: config.filePatterns,\n linter: config.linter,\n matchedDiagnostics,\n },\n };\n },\n};\n"]}
@@ -0,0 +1,11 @@
1
+ import { EngineeringEpistemicEvaluator } from './testRunnerEvaluator.js';
2
+ import '@lucern/confidence';
3
+ import '../epistemicContracts.js';
4
+ import '../convex.js';
5
+ import 'convex/values';
6
+
7
+ /** Sentry-backed engineering evaluator for epistemic contracts. */
8
+
9
+ declare const sentryCheckerEvaluator: EngineeringEpistemicEvaluator;
10
+
11
+ export { sentryCheckerEvaluator };
@@ -0,0 +1,126 @@
1
+ // src/evaluators/shared.ts
2
+ function asArray(value) {
3
+ return Array.isArray(value) ? value : [];
4
+ }
5
+ function asNumber(value) {
6
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
7
+ }
8
+ function asRecord(value) {
9
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
10
+ }
11
+ function asString(value) {
12
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
13
+ }
14
+ function deriveDirectionalResult(direction, conditionSatisfied) {
15
+ if (direction === "falsifies") {
16
+ return conditionSatisfied ? "disconfirmed" : "confirmed";
17
+ }
18
+ return conditionSatisfied ? "confirmed" : "disconfirmed";
19
+ }
20
+ function normalizeToolResultEnvelope(value) {
21
+ const record = asRecord(value);
22
+ if (!record) {
23
+ return {
24
+ output: asString(value) ?? void 0
25
+ };
26
+ }
27
+ const exitCode = asNumber(record.exitCode) ?? asNumber(record.code) ?? asNumber(record.status) ?? null;
28
+ return {
29
+ command: asString(record.command) ?? void 0,
30
+ data: record.data ?? record.payload,
31
+ exitCode,
32
+ output: asString(record.output) ?? void 0,
33
+ report: record.report ?? record.json ?? record.result ?? record.payload ?? void 0,
34
+ stderr: asString(record.stderr) ?? void 0,
35
+ stdout: asString(record.stdout) ?? void 0
36
+ };
37
+ }
38
+
39
+ // src/evaluators/sentryCheckerEvaluator.ts
40
+ function parseConfig(condition) {
41
+ const record = asRecord(condition.evaluatorConfig);
42
+ if (!record) {
43
+ throw new Error(
44
+ "sentry_checker requires evaluatorConfig with { module, windowDays }."
45
+ );
46
+ }
47
+ const moduleName = asString(record.module);
48
+ const windowDays = asNumber(record.windowDays);
49
+ if (!moduleName || windowDays === null) {
50
+ throw new Error(
51
+ "sentry_checker requires a module name and numeric windowDays."
52
+ );
53
+ }
54
+ return {
55
+ module: moduleName,
56
+ windowDays
57
+ };
58
+ }
59
+ function parseIncidentCount(resultData) {
60
+ const envelope = normalizeToolResultEnvelope(resultData);
61
+ const record = asRecord(envelope.report) ?? asRecord(envelope.data) ?? asRecord(resultData);
62
+ if (!record) {
63
+ return {
64
+ incidentCount: null,
65
+ moduleName: null,
66
+ windowDays: null
67
+ };
68
+ }
69
+ const incidents = asArray(record.incidents);
70
+ const incidentCount = asNumber(record.incidentCount) ?? (incidents.length > 0 ? incidents.length : null);
71
+ return {
72
+ incidentCount,
73
+ moduleName: asString(record.module),
74
+ windowDays: asNumber(record.windowDays)
75
+ };
76
+ }
77
+ function matchesModule(contract, resultData) {
78
+ const config = parseConfig(contract.condition);
79
+ const payload = parseIncidentCount(resultData);
80
+ return !payload.moduleName || payload.moduleName === config.module;
81
+ }
82
+ var sentryCheckerEvaluator = {
83
+ name: "sentry_checker",
84
+ matches({ contract, resultData }) {
85
+ return matchesModule(contract, resultData);
86
+ },
87
+ evaluate(args) {
88
+ const config = parseConfig(args.contract.condition);
89
+ if (!args.resultData) {
90
+ return {
91
+ result: "error",
92
+ rationale: "sentry_checker requires incident count resultData."
93
+ };
94
+ }
95
+ const payload = parseIncidentCount(args.resultData);
96
+ if (payload.incidentCount === null) {
97
+ return {
98
+ result: "error",
99
+ rationale: "sentry_checker could not determine an incident count."
100
+ };
101
+ }
102
+ if (!matchesModule(args.contract, args.resultData)) {
103
+ return {
104
+ result: "inconclusive",
105
+ rationale: `Sentry result targeted ${payload.moduleName}, not ${config.module}.`
106
+ };
107
+ }
108
+ const conditionSatisfied = payload.incidentCount === 0;
109
+ return {
110
+ result: deriveDirectionalResult(
111
+ args.contract.direction,
112
+ conditionSatisfied
113
+ ),
114
+ rationale: conditionSatisfied ? `Sentry reported zero incidents for ${config.module} over ${config.windowDays} day(s).` : `Sentry reported ${payload.incidentCount} incident(s) for ${config.module} over ${config.windowDays} day(s).`,
115
+ data: {
116
+ incidentCount: payload.incidentCount,
117
+ module: config.module,
118
+ windowDays: config.windowDays
119
+ }
120
+ };
121
+ }
122
+ };
123
+
124
+ export { sentryCheckerEvaluator };
125
+ //# sourceMappingURL=sentryCheckerEvaluator.js.map
126
+ //# sourceMappingURL=sentryCheckerEvaluator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/evaluators/shared.ts","../../src/evaluators/sentryCheckerEvaluator.ts"],"names":[],"mappings":";AAmBO,SAAS,QAAQ,KAAA,EAA2B;AACjD,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,QAAQ,EAAC;AACzC;AAEO,SAAS,SAAS,KAAA,EAA+B;AACtD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,QAAA,CAAS,KAAK,IAAI,KAAA,GAAQ,IAAA;AACvE;AAEO,SAAS,SAAS,KAAA,EAAkC;AACzD,EAAA,OAAO,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAC5D,KAAA,GACD,IAAA;AACN;AAEO,SAAS,SAAS,KAAA,EAA+B;AACtD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,IAAA,GAAO,MAAA,GAAS,CAAA,GACtD,KAAA,CAAM,IAAA,EAAK,GACX,IAAA;AACN;AAEO,SAAS,uBAAA,CACd,WACA,kBAAA,EACmC;AACnC,EAAA,IAAI,cAAc,WAAA,EAAa;AAC7B,IAAA,OAAO,qBAAqB,cAAA,GAAiB,WAAA;AAAA,EAC/C;AACA,EAAA,OAAO,qBAAqB,WAAA,GAAc,cAAA;AAC5C;AAkCO,SAAS,4BAA4B,KAAA,EAAoC;AAC9E,EAAA,MAAM,MAAA,GAAS,SAAS,KAAK,CAAA;AAC7B,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ,QAAA,CAAS,KAAK,CAAA,IAAK;AAAA,KAC7B;AAAA,EACF;AAEA,EAAA,MAAM,QAAA,GACJ,QAAA,CAAS,MAAA,CAAO,QAAQ,CAAA,IACxB,QAAA,CAAS,MAAA,CAAO,IAAI,CAAA,IACpB,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA,IACtB,IAAA;AAEF,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,QAAA,CAAS,MAAA,CAAO,OAAO,CAAA,IAAK,MAAA;AAAA,IACrC,IAAA,EAAM,MAAA,CAAO,IAAA,IAAQ,MAAA,CAAO,OAAA;AAAA,IAC5B,QAAA;AAAA,IACA,MAAA,EAAQ,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA,IAAK,MAAA;AAAA,IACnC,MAAA,EACE,OAAO,MAAA,IACP,MAAA,CAAO,QACP,MAAA,CAAO,MAAA,IACP,OAAO,OAAA,IACP,MAAA;AAAA,IACF,MAAA,EAAQ,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA,IAAK,MAAA;AAAA,IACnC,MAAA,EAAQ,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA,IAAK;AAAA,GACrC;AACF;;;AClFA,SAAS,YAAY,SAAA,EAA4D;AAC/E,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,SAAA,CAAU,eAAe,CAAA;AACjD,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,UAAA,GAAa,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA;AACzC,EAAA,MAAM,UAAA,GAAa,QAAA,CAAS,MAAA,CAAO,UAAU,CAAA;AAC7C,EAAA,IAAI,CAAC,UAAA,IAAc,UAAA,KAAe,IAAA,EAAM;AACtC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,UAAA;AAAA,IACR;AAAA,GACF;AACF;AAEA,SAAS,mBAAmB,UAAA,EAI1B;AACA,EAAA,MAAM,QAAA,GAAW,4BAA4B,UAAU,CAAA;AACvD,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA,IAAK,SAAS,QAAA,CAAS,IAAI,CAAA,IAAK,QAAA,CAAS,UAAU,CAAA;AAC1F,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO;AAAA,MACL,aAAA,EAAe,IAAA;AAAA,MACf,UAAA,EAAY,IAAA;AAAA,MACZ,UAAA,EAAY;AAAA,KACd;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,MAAA,CAAO,SAAS,CAAA;AAC1C,EAAA,MAAM,aAAA,GACJ,SAAS,MAAA,CAAO,aAAa,MAC5B,SAAA,CAAU,MAAA,GAAS,CAAA,GAAI,SAAA,CAAU,MAAA,GAAS,IAAA,CAAA;AAE7C,EAAA,OAAO;AAAA,IACL,aAAA;AAAA,IACA,UAAA,EAAY,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA;AAAA,IAClC,UAAA,EAAY,QAAA,CAAS,MAAA,CAAO,UAAU;AAAA,GACxC;AACF;AAEA,SAAS,aAAA,CAAc,UAAuB,UAAA,EAA8B;AAC1E,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,QAAA,CAAS,SAAS,CAAA;AAC7C,EAAA,MAAM,OAAA,GAAU,mBAAmB,UAAU,CAAA;AAC7C,EAAA,OAAO,CAAC,OAAA,CAAQ,UAAA,IAAc,OAAA,CAAQ,eAAe,MAAA,CAAO,MAAA;AAC9D;AAEO,IAAM,sBAAA,GAAwD;AAAA,EACnE,IAAA,EAAM,gBAAA;AAAA,EACN,OAAA,CAAQ,EAAE,QAAA,EAAU,UAAA,EAAW,EAAG;AAChC,IAAA,OAAO,aAAA,CAAc,UAAU,UAAU,CAAA;AAAA,EAC3C,CAAA;AAAA,EACA,SAAS,IAAA,EAA2D;AAClE,IAAA,MAAM,MAAA,GAAS,WAAA,CAAY,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA;AAClD,IAAA,IAAI,CAAC,KAAK,UAAA,EAAY;AACpB,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,OAAA;AAAA,QACR,SAAA,EAAW;AAAA,OACb;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,kBAAA,CAAmB,IAAA,CAAK,UAAU,CAAA;AAClD,IAAA,IAAI,OAAA,CAAQ,kBAAkB,IAAA,EAAM;AAClC,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,OAAA;AAAA,QACR,SAAA,EAAW;AAAA,OACb;AAAA,IACF;AACA,IAAA,IAAI,CAAC,aAAA,CAAc,IAAA,CAAK,QAAA,EAAU,IAAA,CAAK,UAAU,CAAA,EAAG;AAClD,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,cAAA;AAAA,QACR,WAAW,CAAA,uBAAA,EAA0B,OAAA,CAAQ,UAAU,CAAA,MAAA,EAAS,OAAO,MAAM,CAAA,CAAA;AAAA,OAC/E;AAAA,IACF;AAEA,IAAA,MAAM,kBAAA,GAAqB,QAAQ,aAAA,KAAkB,CAAA;AAErD,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ,uBAAA;AAAA,QACN,KAAK,QAAA,CAAS,SAAA;AAAA,QACd;AAAA,OACF;AAAA,MACA,WAAW,kBAAA,GACP,CAAA,mCAAA,EAAsC,MAAA,CAAO,MAAM,SAAS,MAAA,CAAO,UAAU,CAAA,QAAA,CAAA,GAC7E,CAAA,gBAAA,EAAmB,QAAQ,aAAa,CAAA,iBAAA,EAAoB,OAAO,MAAM,CAAA,MAAA,EAAS,OAAO,UAAU,CAAA,QAAA,CAAA;AAAA,MACvG,IAAA,EAAM;AAAA,QACJ,eAAe,OAAA,CAAQ,aAAA;AAAA,QACvB,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,YAAY,MAAA,CAAO;AAAA;AACrB,KACF;AAAA,EACF;AACF","file":"sentryCheckerEvaluator.js","sourcesContent":["/** Shared evaluator helpers and result-normalization utilities. */\n\nimport type {\n EpistemicContractDirection,\n EpistemicContractEvaluationResult,\n} from \"../epistemicContractHelpers\";\n\nexport type ToolResultEnvelope = {\n command?: string;\n data?: unknown;\n exitCode?: number | null;\n output?: string;\n report?: unknown;\n stderr?: string;\n stdout?: string;\n};\n\ntype AnyRecord = Record<string, unknown>;\n\nexport function asArray(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nexport function asNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nexport function asRecord(value: unknown): AnyRecord | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as AnyRecord)\n : null;\n}\n\nexport function asString(value: unknown): string | null {\n return typeof value === \"string\" && value.trim().length > 0\n ? value.trim()\n : null;\n}\n\nexport function deriveDirectionalResult(\n direction: EpistemicContractDirection,\n conditionSatisfied: boolean\n): EpistemicContractEvaluationResult {\n if (direction === \"falsifies\") {\n return conditionSatisfied ? \"disconfirmed\" : \"confirmed\";\n }\n return conditionSatisfied ? \"confirmed\" : \"disconfirmed\";\n}\n\nexport function extractTextCandidates(value: unknown): string[] {\n const record = asRecord(value);\n if (!record) {\n const candidate = asString(value);\n return candidate ? [candidate] : [];\n }\n\n const candidates = [\n record.stdout,\n record.stderr,\n record.output,\n record.text,\n record.message,\n record.raw,\n ]\n .map(asString)\n .filter((candidate): candidate is string => Boolean(candidate));\n\n for (const nestedKey of [\"report\", \"result\", \"data\", \"payload\"]) {\n const nested = record[nestedKey];\n if (nested !== value) {\n candidates.push(...extractTextCandidates(nested));\n }\n }\n\n return Array.from(new Set(candidates));\n}\n\nexport function normalizeFilePath(value: string): string {\n return value.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n\nexport function normalizeToolResultEnvelope(value: unknown): ToolResultEnvelope {\n const record = asRecord(value);\n if (!record) {\n return {\n output: asString(value) ?? undefined,\n };\n }\n\n const exitCode =\n asNumber(record.exitCode) ??\n asNumber(record.code) ??\n asNumber(record.status) ??\n null;\n\n return {\n command: asString(record.command) ?? undefined,\n data: record.data ?? record.payload,\n exitCode,\n output: asString(record.output) ?? undefined,\n report:\n record.report ??\n record.json ??\n record.result ??\n record.payload ??\n undefined,\n stderr: asString(record.stderr) ?? undefined,\n stdout: asString(record.stdout) ?? undefined,\n };\n}\n\nexport function parseJsonCandidate<T = unknown>(value: unknown): T | null {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value !== \"string\") {\n return value as T;\n }\n\n try {\n return JSON.parse(value) as T;\n } catch {\n return null;\n }\n}\n\nexport function patternMatchesPath(\n filePath: string,\n pattern: string\n): boolean {\n const normalizedPath = normalizeFilePath(filePath);\n const normalizedPattern = normalizeFilePath(pattern);\n const escaped = normalizedPattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regexPattern = escaped\n .replace(/\\\\\\*\\\\\\*/g, \".*\")\n .replace(/\\\\\\*/g, \"[^/]*\")\n .replace(/\\\\\\?/g, \"[^/]\");\n return new RegExp(`^${regexPattern}$`).test(normalizedPath);\n}\n\nexport function somePatternMatches(\n filePath: string | null | undefined,\n patterns: string[]\n): boolean {\n if (!filePath) {\n return false;\n }\n return patterns.some((pattern) => patternMatchesPath(filePath, pattern));\n}\n","/** Sentry-backed engineering evaluator for epistemic contracts. */\n\nimport type {\n EpistemicContractCondition,\n EpistemicContractRecord,\n} from \"../epistemicContractHelpers\";\nimport type {\n EpistemicEvaluatorContext,\n EpistemicEvaluatorResult,\n} from \"../epistemicContracts\";\nimport {\n asArray,\n asNumber,\n asRecord,\n asString,\n deriveDirectionalResult,\n normalizeToolResultEnvelope,\n} from \"./shared\";\nimport type { EngineeringEpistemicEvaluator } from \"./testRunnerEvaluator\";\n\ntype AnyContract = Pick<EpistemicContractRecord, \"condition\">;\n\ntype SentryCheckerConfig = {\n module: string;\n windowDays: number;\n};\n\nfunction parseConfig(condition: EpistemicContractCondition): SentryCheckerConfig {\n const record = asRecord(condition.evaluatorConfig);\n if (!record) {\n throw new Error(\n \"sentry_checker requires evaluatorConfig with { module, windowDays }.\"\n );\n }\n\n const moduleName = asString(record.module);\n const windowDays = asNumber(record.windowDays);\n if (!moduleName || windowDays === null) {\n throw new Error(\n \"sentry_checker requires a module name and numeric windowDays.\"\n );\n }\n\n return {\n module: moduleName,\n windowDays,\n };\n}\n\nfunction parseIncidentCount(resultData: unknown): {\n incidentCount: number | null;\n moduleName: string | null;\n windowDays: number | null;\n} {\n const envelope = normalizeToolResultEnvelope(resultData);\n const record = asRecord(envelope.report) ?? asRecord(envelope.data) ?? asRecord(resultData);\n if (!record) {\n return {\n incidentCount: null,\n moduleName: null,\n windowDays: null,\n };\n }\n\n const incidents = asArray(record.incidents);\n const incidentCount =\n asNumber(record.incidentCount) ??\n (incidents.length > 0 ? incidents.length : null);\n\n return {\n incidentCount,\n moduleName: asString(record.module),\n windowDays: asNumber(record.windowDays),\n };\n}\n\nfunction matchesModule(contract: AnyContract, resultData: unknown): boolean {\n const config = parseConfig(contract.condition);\n const payload = parseIncidentCount(resultData);\n return !payload.moduleName || payload.moduleName === config.module;\n}\n\nexport const sentryCheckerEvaluator: EngineeringEpistemicEvaluator = {\n name: \"sentry_checker\",\n matches({ contract, resultData }) {\n return matchesModule(contract, resultData);\n },\n evaluate(args: EpistemicEvaluatorContext): EpistemicEvaluatorResult {\n const config = parseConfig(args.contract.condition);\n if (!args.resultData) {\n return {\n result: \"error\",\n rationale: \"sentry_checker requires incident count resultData.\",\n };\n }\n\n const payload = parseIncidentCount(args.resultData);\n if (payload.incidentCount === null) {\n return {\n result: \"error\",\n rationale: \"sentry_checker could not determine an incident count.\",\n };\n }\n if (!matchesModule(args.contract, args.resultData)) {\n return {\n result: \"inconclusive\",\n rationale: `Sentry result targeted ${payload.moduleName}, not ${config.module}.`,\n };\n }\n\n const conditionSatisfied = payload.incidentCount === 0;\n\n return {\n result: deriveDirectionalResult(\n args.contract.direction,\n conditionSatisfied\n ),\n rationale: conditionSatisfied\n ? `Sentry reported zero incidents for ${config.module} over ${config.windowDays} day(s).`\n : `Sentry reported ${payload.incidentCount} incident(s) for ${config.module} over ${config.windowDays} day(s).`,\n data: {\n incidentCount: payload.incidentCount,\n module: config.module,\n windowDays: config.windowDays,\n },\n };\n },\n};\n"]}
@@ -0,0 +1,27 @@
1
+ import { EpistemicContractDirection, EpistemicContractEvaluationResult } from '@lucern/confidence';
2
+
3
+ /** Shared evaluator helpers and result-normalization utilities. */
4
+
5
+ type ToolResultEnvelope = {
6
+ command?: string;
7
+ data?: unknown;
8
+ exitCode?: number | null;
9
+ output?: string;
10
+ report?: unknown;
11
+ stderr?: string;
12
+ stdout?: string;
13
+ };
14
+ type AnyRecord = Record<string, unknown>;
15
+ declare function asArray(value: unknown): unknown[];
16
+ declare function asNumber(value: unknown): number | null;
17
+ declare function asRecord(value: unknown): AnyRecord | null;
18
+ declare function asString(value: unknown): string | null;
19
+ declare function deriveDirectionalResult(direction: EpistemicContractDirection, conditionSatisfied: boolean): EpistemicContractEvaluationResult;
20
+ declare function extractTextCandidates(value: unknown): string[];
21
+ declare function normalizeFilePath(value: string): string;
22
+ declare function normalizeToolResultEnvelope(value: unknown): ToolResultEnvelope;
23
+ declare function parseJsonCandidate<T = unknown>(value: unknown): T | null;
24
+ declare function patternMatchesPath(filePath: string, pattern: string): boolean;
25
+ declare function somePatternMatches(filePath: string | null | undefined, patterns: string[]): boolean;
26
+
27
+ export { type ToolResultEnvelope, asArray, asNumber, asRecord, asString, deriveDirectionalResult, extractTextCandidates, normalizeFilePath, normalizeToolResultEnvelope, parseJsonCandidate, patternMatchesPath, somePatternMatches };
@@ -0,0 +1,92 @@
1
+ // src/evaluators/shared.ts
2
+ function asArray(value) {
3
+ return Array.isArray(value) ? value : [];
4
+ }
5
+ function asNumber(value) {
6
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
7
+ }
8
+ function asRecord(value) {
9
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
10
+ }
11
+ function asString(value) {
12
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
13
+ }
14
+ function deriveDirectionalResult(direction, conditionSatisfied) {
15
+ if (direction === "falsifies") {
16
+ return conditionSatisfied ? "disconfirmed" : "confirmed";
17
+ }
18
+ return conditionSatisfied ? "confirmed" : "disconfirmed";
19
+ }
20
+ function extractTextCandidates(value) {
21
+ const record = asRecord(value);
22
+ if (!record) {
23
+ const candidate = asString(value);
24
+ return candidate ? [candidate] : [];
25
+ }
26
+ const candidates = [
27
+ record.stdout,
28
+ record.stderr,
29
+ record.output,
30
+ record.text,
31
+ record.message,
32
+ record.raw
33
+ ].map(asString).filter((candidate) => Boolean(candidate));
34
+ for (const nestedKey of ["report", "result", "data", "payload"]) {
35
+ const nested = record[nestedKey];
36
+ if (nested !== value) {
37
+ candidates.push(...extractTextCandidates(nested));
38
+ }
39
+ }
40
+ return Array.from(new Set(candidates));
41
+ }
42
+ function normalizeFilePath(value) {
43
+ return value.replace(/\\/g, "/").replace(/^\.\//, "");
44
+ }
45
+ function normalizeToolResultEnvelope(value) {
46
+ const record = asRecord(value);
47
+ if (!record) {
48
+ return {
49
+ output: asString(value) ?? void 0
50
+ };
51
+ }
52
+ const exitCode = asNumber(record.exitCode) ?? asNumber(record.code) ?? asNumber(record.status) ?? null;
53
+ return {
54
+ command: asString(record.command) ?? void 0,
55
+ data: record.data ?? record.payload,
56
+ exitCode,
57
+ output: asString(record.output) ?? void 0,
58
+ report: record.report ?? record.json ?? record.result ?? record.payload ?? void 0,
59
+ stderr: asString(record.stderr) ?? void 0,
60
+ stdout: asString(record.stdout) ?? void 0
61
+ };
62
+ }
63
+ function parseJsonCandidate(value) {
64
+ if (value === null || value === void 0) {
65
+ return null;
66
+ }
67
+ if (typeof value !== "string") {
68
+ return value;
69
+ }
70
+ try {
71
+ return JSON.parse(value);
72
+ } catch {
73
+ return null;
74
+ }
75
+ }
76
+ function patternMatchesPath(filePath, pattern) {
77
+ const normalizedPath = normalizeFilePath(filePath);
78
+ const normalizedPattern = normalizeFilePath(pattern);
79
+ const escaped = normalizedPattern.replace(/[.+^${}()|[\]\\]/g, "\\$&");
80
+ const regexPattern = escaped.replace(/\\\*\\\*/g, ".*").replace(/\\\*/g, "[^/]*").replace(/\\\?/g, "[^/]");
81
+ return new RegExp(`^${regexPattern}$`).test(normalizedPath);
82
+ }
83
+ function somePatternMatches(filePath, patterns) {
84
+ if (!filePath) {
85
+ return false;
86
+ }
87
+ return patterns.some((pattern) => patternMatchesPath(filePath, pattern));
88
+ }
89
+
90
+ export { asArray, asNumber, asRecord, asString, deriveDirectionalResult, extractTextCandidates, normalizeFilePath, normalizeToolResultEnvelope, parseJsonCandidate, patternMatchesPath, somePatternMatches };
91
+ //# sourceMappingURL=shared.js.map
92
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/evaluators/shared.ts"],"names":[],"mappings":";AAmBO,SAAS,QAAQ,KAAA,EAA2B;AACjD,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,QAAQ,EAAC;AACzC;AAEO,SAAS,SAAS,KAAA,EAA+B;AACtD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,QAAA,CAAS,KAAK,IAAI,KAAA,GAAQ,IAAA;AACvE;AAEO,SAAS,SAAS,KAAA,EAAkC;AACzD,EAAA,OAAO,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAC5D,KAAA,GACD,IAAA;AACN;AAEO,SAAS,SAAS,KAAA,EAA+B;AACtD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,IAAA,GAAO,MAAA,GAAS,CAAA,GACtD,KAAA,CAAM,IAAA,EAAK,GACX,IAAA;AACN;AAEO,SAAS,uBAAA,CACd,WACA,kBAAA,EACmC;AACnC,EAAA,IAAI,cAAc,WAAA,EAAa;AAC7B,IAAA,OAAO,qBAAqB,cAAA,GAAiB,WAAA;AAAA,EAC/C;AACA,EAAA,OAAO,qBAAqB,WAAA,GAAc,cAAA;AAC5C;AAEO,SAAS,sBAAsB,KAAA,EAA0B;AAC9D,EAAA,MAAM,MAAA,GAAS,SAAS,KAAK,CAAA;AAC7B,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,SAAA,GAAY,SAAS,KAAK,CAAA;AAChC,IAAA,OAAO,SAAA,GAAY,CAAC,SAAS,CAAA,GAAI,EAAC;AAAA,EACpC;AAEA,EAAA,MAAM,UAAA,GAAa;AAAA,IACjB,MAAA,CAAO,MAAA;AAAA,IACP,MAAA,CAAO,MAAA;AAAA,IACP,MAAA,CAAO,MAAA;AAAA,IACP,MAAA,CAAO,IAAA;AAAA,IACP,MAAA,CAAO,OAAA;AAAA,IACP,MAAA,CAAO;AAAA,GACT,CACG,IAAI,QAAQ,CAAA,CACZ,OAAO,CAAC,SAAA,KAAmC,OAAA,CAAQ,SAAS,CAAC,CAAA;AAEhE,EAAA,KAAA,MAAW,aAAa,CAAC,QAAA,EAAU,QAAA,EAAU,MAAA,EAAQ,SAAS,CAAA,EAAG;AAC/D,IAAA,MAAM,MAAA,GAAS,OAAO,SAAS,CAAA;AAC/B,IAAA,IAAI,WAAW,KAAA,EAAO;AACpB,MAAA,UAAA,CAAW,IAAA,CAAK,GAAG,qBAAA,CAAsB,MAAM,CAAC,CAAA;AAAA,IAClD;AAAA,EACF;AAEA,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAI,GAAA,CAAI,UAAU,CAAC,CAAA;AACvC;AAEO,SAAS,kBAAkB,KAAA,EAAuB;AACvD,EAAA,OAAO,MAAM,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,SAAS,EAAE,CAAA;AACtD;AAEO,SAAS,4BAA4B,KAAA,EAAoC;AAC9E,EAAA,MAAM,MAAA,GAAS,SAAS,KAAK,CAAA;AAC7B,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ,QAAA,CAAS,KAAK,CAAA,IAAK;AAAA,KAC7B;AAAA,EACF;AAEA,EAAA,MAAM,QAAA,GACJ,QAAA,CAAS,MAAA,CAAO,QAAQ,CAAA,IACxB,QAAA,CAAS,MAAA,CAAO,IAAI,CAAA,IACpB,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA,IACtB,IAAA;AAEF,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,QAAA,CAAS,MAAA,CAAO,OAAO,CAAA,IAAK,MAAA;AAAA,IACrC,IAAA,EAAM,MAAA,CAAO,IAAA,IAAQ,MAAA,CAAO,OAAA;AAAA,IAC5B,QAAA;AAAA,IACA,MAAA,EAAQ,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA,IAAK,MAAA;AAAA,IACnC,MAAA,EACE,OAAO,MAAA,IACP,MAAA,CAAO,QACP,MAAA,CAAO,MAAA,IACP,OAAO,OAAA,IACP,MAAA;AAAA,IACF,MAAA,EAAQ,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA,IAAK,MAAA;AAAA,IACnC,MAAA,EAAQ,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA,IAAK;AAAA,GACrC;AACF;AAEO,SAAS,mBAAgC,KAAA,EAA0B;AACxE,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW;AACzC,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,MAAM,KAAK,CAAA;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,kBAAA,CACd,UACA,OAAA,EACS;AACT,EAAA,MAAM,cAAA,GAAiB,kBAAkB,QAAQ,CAAA;AACjD,EAAA,MAAM,iBAAA,GAAoB,kBAAkB,OAAO,CAAA;AACnD,EAAA,MAAM,OAAA,GAAU,iBAAA,CAAkB,OAAA,CAAQ,mBAAA,EAAqB,MAAM,CAAA;AACrE,EAAA,MAAM,YAAA,GAAe,OAAA,CAClB,OAAA,CAAQ,WAAA,EAAa,IAAI,CAAA,CACzB,OAAA,CAAQ,OAAA,EAAS,OAAO,CAAA,CACxB,OAAA,CAAQ,OAAA,EAAS,MAAM,CAAA;AAC1B,EAAA,OAAO,IAAI,MAAA,CAAO,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA,CAAG,CAAA,CAAE,KAAK,cAAc,CAAA;AAC5D;AAEO,SAAS,kBAAA,CACd,UACA,QAAA,EACS;AACT,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,SAAS,IAAA,CAAK,CAAC,YAAY,kBAAA,CAAmB,QAAA,EAAU,OAAO,CAAC,CAAA;AACzE","file":"shared.js","sourcesContent":["/** Shared evaluator helpers and result-normalization utilities. */\n\nimport type {\n EpistemicContractDirection,\n EpistemicContractEvaluationResult,\n} from \"../epistemicContractHelpers\";\n\nexport type ToolResultEnvelope = {\n command?: string;\n data?: unknown;\n exitCode?: number | null;\n output?: string;\n report?: unknown;\n stderr?: string;\n stdout?: string;\n};\n\ntype AnyRecord = Record<string, unknown>;\n\nexport function asArray(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nexport function asNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nexport function asRecord(value: unknown): AnyRecord | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as AnyRecord)\n : null;\n}\n\nexport function asString(value: unknown): string | null {\n return typeof value === \"string\" && value.trim().length > 0\n ? value.trim()\n : null;\n}\n\nexport function deriveDirectionalResult(\n direction: EpistemicContractDirection,\n conditionSatisfied: boolean\n): EpistemicContractEvaluationResult {\n if (direction === \"falsifies\") {\n return conditionSatisfied ? \"disconfirmed\" : \"confirmed\";\n }\n return conditionSatisfied ? \"confirmed\" : \"disconfirmed\";\n}\n\nexport function extractTextCandidates(value: unknown): string[] {\n const record = asRecord(value);\n if (!record) {\n const candidate = asString(value);\n return candidate ? [candidate] : [];\n }\n\n const candidates = [\n record.stdout,\n record.stderr,\n record.output,\n record.text,\n record.message,\n record.raw,\n ]\n .map(asString)\n .filter((candidate): candidate is string => Boolean(candidate));\n\n for (const nestedKey of [\"report\", \"result\", \"data\", \"payload\"]) {\n const nested = record[nestedKey];\n if (nested !== value) {\n candidates.push(...extractTextCandidates(nested));\n }\n }\n\n return Array.from(new Set(candidates));\n}\n\nexport function normalizeFilePath(value: string): string {\n return value.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n\nexport function normalizeToolResultEnvelope(value: unknown): ToolResultEnvelope {\n const record = asRecord(value);\n if (!record) {\n return {\n output: asString(value) ?? undefined,\n };\n }\n\n const exitCode =\n asNumber(record.exitCode) ??\n asNumber(record.code) ??\n asNumber(record.status) ??\n null;\n\n return {\n command: asString(record.command) ?? undefined,\n data: record.data ?? record.payload,\n exitCode,\n output: asString(record.output) ?? undefined,\n report:\n record.report ??\n record.json ??\n record.result ??\n record.payload ??\n undefined,\n stderr: asString(record.stderr) ?? undefined,\n stdout: asString(record.stdout) ?? undefined,\n };\n}\n\nexport function parseJsonCandidate<T = unknown>(value: unknown): T | null {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value !== \"string\") {\n return value as T;\n }\n\n try {\n return JSON.parse(value) as T;\n } catch {\n return null;\n }\n}\n\nexport function patternMatchesPath(\n filePath: string,\n pattern: string\n): boolean {\n const normalizedPath = normalizeFilePath(filePath);\n const normalizedPattern = normalizeFilePath(pattern);\n const escaped = normalizedPattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regexPattern = escaped\n .replace(/\\\\\\*\\\\\\*/g, \".*\")\n .replace(/\\\\\\*/g, \"[^/]*\")\n .replace(/\\\\\\?/g, \"[^/]\");\n return new RegExp(`^${regexPattern}$`).test(normalizedPath);\n}\n\nexport function somePatternMatches(\n filePath: string | null | undefined,\n patterns: string[]\n): boolean {\n if (!filePath) {\n return false;\n }\n return patterns.some((pattern) => patternMatchesPath(filePath, pattern));\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import { EpistemicContractRecord } from '@lucern/confidence';
2
+ import { EpistemicEvaluator } from '../epistemicContracts.js';
3
+ import '../convex.js';
4
+ import 'convex/values';
5
+
6
+ /** Test-runner engineering evaluator for epistemic contracts. */
7
+
8
+ type AnyContract = Pick<EpistemicContractRecord, "condition">;
9
+ type EngineeringEpistemicEvaluator = EpistemicEvaluator & {
10
+ matches(args: {
11
+ contract: AnyContract;
12
+ resultData: unknown;
13
+ }): boolean;
14
+ };
15
+ declare const testRunnerEvaluator: EngineeringEpistemicEvaluator;
16
+
17
+ export { type EngineeringEpistemicEvaluator, testRunnerEvaluator };