@unson/brainbase-mcp 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/contracts/foundation/graph-history.sql +634 -0
  2. package/contracts/judgment-value-proof/schema.json +43 -1
  3. package/dist/canonical-task-contract.d.ts +9 -0
  4. package/dist/canonical-task-contract.js +39 -0
  5. package/dist/canonical-task-principal.d.ts +16 -0
  6. package/dist/canonical-task-principal.js +36 -0
  7. package/dist/canonical-task-service.d.ts +251 -0
  8. package/dist/canonical-task-service.js +820 -0
  9. package/dist/cli.d.ts +2 -0
  10. package/dist/cli.js +107 -0
  11. package/dist/company-os-evaluation.d.ts +193 -0
  12. package/dist/company-os-evaluation.js +1150 -0
  13. package/dist/company-os-impact-review.d.ts +248 -0
  14. package/dist/company-os-impact-review.js +663 -0
  15. package/dist/company-os-learning-adoption.d.ts +288 -0
  16. package/dist/company-os-learning-adoption.js +944 -0
  17. package/dist/company-os-objectives.d.ts +63 -0
  18. package/dist/company-os-objectives.js +234 -0
  19. package/dist/company-os-receipt-adapter.d.ts +109 -0
  20. package/dist/company-os-receipt-adapter.js +636 -0
  21. package/dist/constraint-exception-store.d.ts +23 -0
  22. package/dist/constraint-exception-store.js +108 -0
  23. package/dist/constraint-resolution.d.ts +175 -0
  24. package/dist/constraint-resolution.js +922 -0
  25. package/dist/decision-adapter.d.ts +145 -0
  26. package/dist/decision-adapter.js +586 -0
  27. package/dist/durable-wait-http.d.ts +51 -0
  28. package/dist/durable-wait-http.js +497 -0
  29. package/dist/durable-waits.d.ts +234 -0
  30. package/dist/durable-waits.js +944 -0
  31. package/dist/execution-authority-http.d.ts +28 -0
  32. package/dist/execution-authority-http.js +359 -0
  33. package/dist/execution-authority.d.ts +201 -0
  34. package/dist/execution-authority.js +634 -0
  35. package/dist/foundation-authenticated-tools.d.ts +56 -0
  36. package/dist/foundation-authenticated-tools.js +347 -0
  37. package/dist/foundation-catalog.d.ts +26 -0
  38. package/dist/foundation-catalog.js +206 -0
  39. package/dist/foundation-constraint-store.d.ts +50 -0
  40. package/dist/foundation-constraint-store.js +215 -0
  41. package/dist/foundation-graph-http.d.ts +43 -0
  42. package/dist/foundation-graph-http.js +243 -0
  43. package/dist/foundation-graph-write.d.ts +90 -0
  44. package/dist/foundation-graph-write.js +447 -0
  45. package/dist/foundation-http.d.ts +90 -0
  46. package/dist/foundation-http.js +439 -0
  47. package/dist/foundation-public-provider.d.ts +140 -0
  48. package/dist/foundation-public-provider.js +192 -0
  49. package/dist/foundation-store.d.ts +132 -0
  50. package/dist/foundation-store.js +654 -0
  51. package/dist/graph-corrections.d.ts +157 -0
  52. package/dist/graph-corrections.js +620 -0
  53. package/dist/graph-foundation-reader.d.ts +60 -0
  54. package/dist/graph-foundation-reader.js +494 -0
  55. package/dist/graph-retrieval.d.ts +6 -1
  56. package/dist/graph-revision-reader.d.ts +80 -0
  57. package/dist/graph-revision-reader.js +246 -0
  58. package/dist/graph-web-http.d.ts +26 -0
  59. package/dist/graph-web-http.js +215 -0
  60. package/dist/graph-web.d.ts +364 -0
  61. package/dist/graph-web.js +639 -0
  62. package/dist/judgment-dag-composition.d.ts +224 -0
  63. package/dist/judgment-dag-composition.js +731 -0
  64. package/dist/judgment-dag.d.ts +2 -0
  65. package/dist/judgment-dag.js +1 -0
  66. package/dist/judgment-problem-snapshot.d.ts +213 -0
  67. package/dist/judgment-problem-snapshot.js +1073 -0
  68. package/dist/judgment-value-proof-review.d.ts +166 -0
  69. package/dist/judgment-value-proof-review.js +437 -0
  70. package/dist/judgment-value-proof.d.ts +28 -1
  71. package/dist/judgment-value-proof.js +53 -8
  72. package/dist/judgment-view-http.d.ts +22 -0
  73. package/dist/judgment-view-http.js +128 -0
  74. package/dist/judgment-view.d.ts +222 -0
  75. package/dist/judgment-view.js +627 -0
  76. package/dist/knowledge-adapter.d.ts +112 -0
  77. package/dist/knowledge-adapter.js +691 -0
  78. package/dist/knowledge-continuation.d.ts +127 -0
  79. package/dist/knowledge-continuation.js +446 -0
  80. package/dist/knowledge-lookup.d.ts +178 -0
  81. package/dist/knowledge-lookup.js +758 -0
  82. package/dist/local-web-fetch-bridge.d.ts +5 -0
  83. package/dist/local-web-fetch-bridge.js +37 -0
  84. package/dist/local-web-host.d.ts +109 -0
  85. package/dist/local-web-host.js +688 -0
  86. package/dist/local-web-security.d.ts +25 -0
  87. package/dist/local-web-security.js +95 -0
  88. package/dist/ontology-foundation.d.ts +209 -0
  89. package/dist/ontology-foundation.js +1000 -0
  90. package/dist/ontology.d.ts +13 -0
  91. package/dist/ontology.js +14 -0
  92. package/dist/organization-connection.d.ts +164 -0
  93. package/dist/organization-connection.js +428 -0
  94. package/dist/organization-graph.d.ts +15 -0
  95. package/dist/organization-graph.js +24 -4
  96. package/dist/personal-knowledge.d.ts +132 -0
  97. package/dist/personal-knowledge.js +779 -0
  98. package/dist/personal-memory-handover.d.ts +108 -0
  99. package/dist/personal-memory-handover.js +369 -0
  100. package/dist/philosophy-revision-reader.d.ts +85 -0
  101. package/dist/philosophy-revision-reader.js +241 -0
  102. package/dist/portable-graph.d.ts +24 -0
  103. package/dist/portable-graph.js +77 -0
  104. package/dist/problem-candidates.d.ts +149 -0
  105. package/dist/problem-candidates.js +898 -0
  106. package/dist/problem-selection.d.ts +238 -0
  107. package/dist/problem-selection.js +995 -0
  108. package/dist/resource-reservation-http.d.ts +31 -0
  109. package/dist/resource-reservation-http.js +371 -0
  110. package/dist/resource-reservations.d.ts +221 -0
  111. package/dist/resource-reservations.js +577 -0
  112. package/dist/server.d.ts +104 -2
  113. package/dist/server.js +186 -4
  114. package/dist/ssot.d.ts +6 -1
  115. package/dist/ssot.js +63 -5
  116. package/dist/streamable-http.d.ts +42 -0
  117. package/dist/streamable-http.js +288 -0
  118. package/dist/types.d.ts +20 -0
  119. package/dist/value-proof-review-http.d.ts +25 -0
  120. package/dist/value-proof-review-http.js +185 -0
  121. package/dist/world-model.d.ts +199 -0
  122. package/dist/world-model.js +955 -0
  123. package/package.json +230 -3
  124. package/ui/brainbase-tokens.css +56 -0
  125. package/ui/graph-own-share.js +367 -0
  126. package/ui/graph-projects-view.css +23 -0
  127. package/ui/graph-projects-view.js +730 -0
  128. package/ui/graph-registry-view.css +101 -0
  129. package/ui/graph-registry-view.js +804 -0
  130. package/ui/graph-view-shared.css +522 -0
  131. package/ui/graph-view-shared.js +1227 -0
  132. package/ui/judgment-view.css +312 -0
  133. package/ui/judgment-view.js +508 -0
  134. package/ui/local-web-shell.css +396 -0
  135. package/ui/local-web-shell.js +378 -0
  136. package/ui/objective-editor-http-port.js +154 -0
  137. package/ui/objective-editor.css +286 -0
  138. package/ui/objective-editor.js +1586 -0
  139. package/ui/outcome-knowledge.css +50 -14
  140. package/ui/outcome-knowledge.js +15 -1
  141. package/ui/outcome-mana.css +91 -14
  142. package/ui/outcome-mana.js +958 -61
  143. package/ui/value-proof-review.css +504 -0
  144. package/ui/value-proof-review.js +1104 -0
  145. package/ui/workspace-kit.css +485 -0
  146. package/ui/workspace-kit.js +229 -0
  147. package/ui/world-model-view.css +188 -0
  148. package/ui/world-model-view.js +486 -0
@@ -0,0 +1,627 @@
1
+ /**
2
+ * Read-only projection contract for following one judgment from its
3
+ * conclusion back to the exact Problem, Objective, evidence, child runs, and
4
+ * evaluation that were used at the time.
5
+ *
6
+ * This module deliberately owns neither a store nor an authorization policy.
7
+ * A host supplies a port after authenticating the request and binding its
8
+ * tenant/scope. Every reference read is explicitly historical so the view
9
+ * cannot silently replace a past definition with its latest revision.
10
+ */
11
+ export const JUDGMENT_VIEW_CONTRACT_VERSION = 'judgment-view.v1';
12
+ export const JUDGMENT_VIEW_STATUSES = Object.freeze([
13
+ 'resolved',
14
+ 'unknown',
15
+ 'permission_denied',
16
+ 'unavailable',
17
+ 'undecidable',
18
+ 'invalid',
19
+ ]);
20
+ function isRecord(value) {
21
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
22
+ }
23
+ function nonEmptyString(value) {
24
+ return typeof value === 'string' && value.trim().length > 0;
25
+ }
26
+ function hasOwn(value, key) {
27
+ return Object.prototype.hasOwnProperty.call(value, key);
28
+ }
29
+ function isStatus(value) {
30
+ return typeof value === 'string' && JUDGMENT_VIEW_STATUSES.includes(value);
31
+ }
32
+ function failure(status, reason) {
33
+ return { status, reason };
34
+ }
35
+ function sectionFailure(result) {
36
+ return { status: result.status, reason: result.reason };
37
+ }
38
+ function collectionFailure(result) {
39
+ return { status: result.status, items: null, absence_confirmed: false, reason: result.reason };
40
+ }
41
+ function resolvedSection(value) {
42
+ return { status: 'resolved', value };
43
+ }
44
+ function resolvedCollection(items) {
45
+ return { status: 'resolved', items, absence_confirmed: items.length === 0 };
46
+ }
47
+ function unknownCollection(reason) {
48
+ return { status: 'unknown', items: null, absence_confirmed: false, reason };
49
+ }
50
+ function statusFromResult(result) {
51
+ return result.status;
52
+ }
53
+ function safeReason(error) {
54
+ return error instanceof Error && error.message.trim().length > 0 ? error.message : 'read failed';
55
+ }
56
+ async function safeRead(reader) {
57
+ try {
58
+ const result = await reader();
59
+ if (!isRecord(result) || result.status === 'resolved' && !hasOwn(result, 'value')) {
60
+ return failure('unknown', 'read port returned an invalid result');
61
+ }
62
+ if (result.status !== 'resolved') {
63
+ if (!isStatus(result.status) || !nonEmptyString(result.reason)) {
64
+ return failure('unknown', 'read port returned an invalid failure');
65
+ }
66
+ return { status: result.status, reason: result.reason };
67
+ }
68
+ return { status: 'resolved', value: result.value };
69
+ }
70
+ catch (error) {
71
+ return failure('unavailable', safeReason(error));
72
+ }
73
+ }
74
+ function validDAGReference(value) {
75
+ return isRecord(value) && nonEmptyString(value.id) && nonEmptyString(value.version);
76
+ }
77
+ function validProblemReference(value) {
78
+ return isRecord(value)
79
+ && nonEmptyString(value.snapshot_id)
80
+ && nonEmptyString(value.problem_id)
81
+ && nonEmptyString(value.revision);
82
+ }
83
+ function sameProblemReference(left, right) {
84
+ return left.snapshot_id === right.snapshot_id
85
+ && left.problem_id === right.problem_id
86
+ && left.revision === right.revision;
87
+ }
88
+ function validEvidenceReference(value) {
89
+ return isRecord(value)
90
+ && nonEmptyString(value.kind)
91
+ && nonEmptyString(value.id)
92
+ && (value.revision === undefined || nonEmptyString(value.revision));
93
+ }
94
+ function validHistoricalEvidenceReference(value) {
95
+ return validEvidenceReference(value) && nonEmptyString(value.revision);
96
+ }
97
+ function validEvidenceRecord(value, reference) {
98
+ return isRecord(value)
99
+ && nonEmptyString(value.kind)
100
+ && value.kind === reference.kind
101
+ && nonEmptyString(value.id)
102
+ && value.id === reference.id
103
+ && nonEmptyString(value.revision)
104
+ && value.revision === reference.revision
105
+ && (value.digest === undefined || nonEmptyString(value.digest));
106
+ }
107
+ function validSubdagResult(value) {
108
+ if (!isRecord(value)
109
+ || !['completed', 'failed', 'held'].includes(String(value.status))
110
+ || !nonEmptyString(value.input_contract)
111
+ || !nonEmptyString(value.output_contract)
112
+ || !Array.isArray(value.evidence)) {
113
+ return false;
114
+ }
115
+ if (value.run_reference !== null && value.run_reference !== undefined) {
116
+ if (!isRecord(value.run_reference) || !nonEmptyString(value.run_reference.run_id) || !validDAGReference(value.run_reference.dag))
117
+ return false;
118
+ }
119
+ if (!Array.isArray(value.evidence) || value.evidence.some((item) => !validEvidenceReference(item)))
120
+ return false;
121
+ if (value.reason !== undefined && typeof value.reason !== 'string')
122
+ return false;
123
+ return true;
124
+ }
125
+ function validateCompositionRun(value, expectedRunId) {
126
+ if (!isRecord(value)
127
+ || value.run_id !== expectedRunId
128
+ || !validDAGReference(value.composition)
129
+ || !validDAGReference(value.parent_dag)
130
+ || !nonEmptyString(value.question)
131
+ || !validProblemReference(value.problem_snapshot)
132
+ || !['completed', 'failed', 'held'].includes(String(value.status))
133
+ || !Array.isArray(value.execution_order)
134
+ || value.execution_order.some((item) => !nonEmptyString(item))
135
+ || !Array.isArray(value.children)) {
136
+ return false;
137
+ }
138
+ return value.children.every((child) => {
139
+ if (!isRecord(child)
140
+ || !nonEmptyString(child.invocation_id)
141
+ || !validDAGReference(child.dag)
142
+ || !nonEmptyString(child.question)
143
+ || !nonEmptyString(child.input_contract)
144
+ || !nonEmptyString(child.output_contract)
145
+ || !validProblemReference(child.problem_snapshot)
146
+ || !Array.isArray(child.dependency_invocation_ids)
147
+ || child.dependency_invocation_ids.some((item) => !nonEmptyString(item))
148
+ || !Array.isArray(child.dependency_results)
149
+ || !validSubdagResult(child.result)) {
150
+ return false;
151
+ }
152
+ if (!sameProblemReference(child.problem_snapshot, value.problem_snapshot))
153
+ return false;
154
+ return true;
155
+ });
156
+ }
157
+ function validateSnapshot(value, expected) {
158
+ if (!isRecord(value)
159
+ || value.snapshot_version !== 'judgment-problem-snapshot.v1'
160
+ || value.problem_id !== expected.problem_id
161
+ || value.revision !== expected.revision
162
+ || !nonEmptyString(value.question)
163
+ || !Array.isArray(value.references)) {
164
+ return false;
165
+ }
166
+ return value.references.every((reference) => (isRecord(reference)
167
+ && nonEmptyString(reference.kind)
168
+ && nonEmptyString(reference.id)
169
+ && nonEmptyString(reference.revision)
170
+ && nonEmptyString(reference.digest)));
171
+ }
172
+ function validFoundationRef(value, type) {
173
+ return isRecord(value)
174
+ && nonEmptyString(value.id)
175
+ && nonEmptyString(value.revision)
176
+ && nonEmptyString(value.digest)
177
+ && (type === undefined || value.type === type);
178
+ }
179
+ function validFoundationRecord(value, reference) {
180
+ if (!isRecord(value) || !nonEmptyString(value.digest) || value.digest !== reference.digest || !isRecord(value.definition))
181
+ return false;
182
+ const definition = value.definition;
183
+ return definition.id === reference.id && definition.type === reference.type && definition.revision === reference.revision;
184
+ }
185
+ function sameFoundationRef(left, right) {
186
+ return left.id === right.id && left.type === right.type && left.revision === right.revision && left.digest === right.digest;
187
+ }
188
+ function asFoundationRef(reference) {
189
+ return {
190
+ id: reference.id,
191
+ type: reference.type,
192
+ revision: reference.revision,
193
+ digest: reference.digest,
194
+ };
195
+ }
196
+ function isObjectiveDefinition(value) {
197
+ return value.type === 'objective';
198
+ }
199
+ function isVariableDefinition(value) {
200
+ return value.type === 'variable';
201
+ }
202
+ function validObjectiveCriterion(value) {
203
+ return isRecord(value)
204
+ && isRecord(value.variableRef)
205
+ && value.variableRef.type === 'variable'
206
+ && nonEmptyString(value.variableRef.id)
207
+ && nonEmptyString(value.variableRef.revision)
208
+ && ['at_least', 'at_most', 'equals'].includes(String(value.operator))
209
+ && (value.target === undefined || typeof value.target === 'string' || typeof value.target === 'number' || typeof value.target === 'boolean');
210
+ }
211
+ function extractConclusion(artifact, runId, dag) {
212
+ if (!isRecord(artifact)
213
+ || artifact.run_id !== runId
214
+ || !validDAGReference(artifact.dag)
215
+ || artifact.dag.id !== dag.id
216
+ || artifact.dag.version !== dag.version
217
+ || !Array.isArray(artifact.execution_order)
218
+ || !Array.isArray(artifact.nodes)
219
+ || artifact.execution_order.length === 0) {
220
+ return null;
221
+ }
222
+ const finalNodeId = artifact.execution_order[artifact.execution_order.length - 1];
223
+ if (!nonEmptyString(finalNodeId))
224
+ return null;
225
+ const finalNode = artifact.nodes.find((node) => isRecord(node) && node.node_id === finalNodeId);
226
+ if (!finalNode || !hasOwn(finalNode, 'output'))
227
+ return null;
228
+ return {
229
+ source: 'parent-run-artifact',
230
+ runId,
231
+ dag,
232
+ value: finalNode.output,
233
+ };
234
+ }
235
+ function sectionStatus(section) {
236
+ return section.status;
237
+ }
238
+ function collectionStatus(collection) {
239
+ return collection.status;
240
+ }
241
+ function aggregateStatus(sections) {
242
+ const statuses = sections.map((section) => sectionStatus(section) ?? collectionStatus(section));
243
+ if (statuses.includes('invalid'))
244
+ return 'invalid';
245
+ if (statuses.includes('permission_denied'))
246
+ return 'permission_denied';
247
+ if (statuses.includes('unavailable'))
248
+ return 'unavailable';
249
+ if (statuses.includes('unknown'))
250
+ return 'unknown';
251
+ if (statuses.includes('undecidable'))
252
+ return 'undecidable';
253
+ return 'resolved';
254
+ }
255
+ function baseDocument(status, reason) {
256
+ return {
257
+ contract_version: JUDGMENT_VIEW_CONTRACT_VERSION,
258
+ mode: 'historical',
259
+ status,
260
+ ...(reason ? { reason } : {}),
261
+ run: { status, reason },
262
+ conclusion: { status, reason },
263
+ problem: { status, reason },
264
+ objective: { status, reason },
265
+ evidence: { status, items: null, absence_confirmed: false, reason },
266
+ childRuns: { status, items: null, absence_confirmed: false, reason },
267
+ resultEvaluation: { status, reason },
268
+ judgmentValidity: { status, reason },
269
+ };
270
+ }
271
+ function buildRunView(run) {
272
+ return {
273
+ runId: run.run_id,
274
+ status: run.status,
275
+ question: run.question,
276
+ composition: run.composition,
277
+ parentDag: run.parent_dag,
278
+ problemSnapshot: run.problem_snapshot,
279
+ };
280
+ }
281
+ function buildProblemView(snapshot, reference) {
282
+ return {
283
+ snapshotId: reference.snapshot_id,
284
+ problemId: snapshot.problem_id,
285
+ revision: snapshot.revision,
286
+ question: snapshot.question,
287
+ references: snapshot.references.map((item) => ({
288
+ kind: item.kind,
289
+ id: item.id,
290
+ revision: item.revision,
291
+ digest: item.digest,
292
+ })),
293
+ };
294
+ }
295
+ function buildChildView(child) {
296
+ return {
297
+ invocationId: child.invocation_id,
298
+ dag: child.dag,
299
+ status: child.result.status,
300
+ question: child.question,
301
+ ...(child.result.run_reference?.run_id ? { runId: child.result.run_reference.run_id } : {}),
302
+ conclusion: child.result.conclusion,
303
+ uncertainty: child.result.uncertainty,
304
+ applicability: child.result.applicability,
305
+ ...(child.result.reason ? { reason: child.result.reason } : {}),
306
+ };
307
+ }
308
+ async function buildObjectiveView(snapshot, access, port) {
309
+ const objectiveReferences = snapshot.references.filter((reference) => reference.kind === 'objective');
310
+ if (objectiveReferences.length === 0)
311
+ return { status: 'unknown', reason: 'objective reference is absent from the historical snapshot' };
312
+ if (objectiveReferences.length !== 1)
313
+ return { status: 'invalid', reason: 'historical snapshot must contain exactly one objective reference' };
314
+ const objectiveReference = objectiveReferences[0];
315
+ const foundationReference = {
316
+ id: objectiveReference.id,
317
+ type: 'objective',
318
+ revision: objectiveReference.revision,
319
+ digest: objectiveReference.digest,
320
+ };
321
+ const objectiveResult = await safeRead(() => port.readFoundationReference({
322
+ reference: foundationReference,
323
+ access,
324
+ resolution: 'historical',
325
+ }));
326
+ if (objectiveResult.status !== 'resolved')
327
+ return sectionFailure(objectiveResult);
328
+ if (!validFoundationRecord(objectiveResult.value, foundationReference) || !isObjectiveDefinition(objectiveResult.value.definition)) {
329
+ return { status: 'invalid', reason: 'historical objective reference readback does not match the requested objective' };
330
+ }
331
+ const objective = objectiveResult.value.definition;
332
+ if (!Array.isArray(objective.criteria) || objective.criteria.some((criterion) => !validObjectiveCriterion(criterion))) {
333
+ return { status: 'invalid', reason: 'objective criteria are malformed' };
334
+ }
335
+ const variableReferences = snapshot.references.filter((reference) => reference.kind === 'variable');
336
+ const criteria = [];
337
+ for (const criterion of objective.criteria) {
338
+ const variableReference = criterion.variableRef;
339
+ const matches = variableReferences.filter((reference) => (reference.id === variableReference.id && reference.revision === variableReference.revision));
340
+ if (matches.length !== 1)
341
+ return { status: 'unknown', reason: 'a criterion variable is not pinned in the historical snapshot' };
342
+ const requestedVariable = {
343
+ id: matches[0].id,
344
+ type: 'variable',
345
+ revision: matches[0].revision,
346
+ digest: matches[0].digest,
347
+ };
348
+ const variableResult = await safeRead(() => port.readFoundationReference({
349
+ reference: requestedVariable,
350
+ access,
351
+ resolution: 'historical',
352
+ }));
353
+ if (variableResult.status !== 'resolved')
354
+ return sectionFailure(variableResult);
355
+ if (!validFoundationRecord(variableResult.value, requestedVariable) || !isVariableDefinition(variableResult.value.definition)) {
356
+ return { status: 'invalid', reason: 'historical criterion variable readback does not match the requested variable' };
357
+ }
358
+ const variable = variableResult.value.definition;
359
+ criteria.push({
360
+ variableRef: requestedVariable,
361
+ operator: criterion.operator,
362
+ ...(criterion.target === undefined ? {} : { target: criterion.target }),
363
+ variable: {
364
+ meaning: variable.meaning,
365
+ subject: variable.subject,
366
+ valueKind: variable.valueKind,
367
+ ...(variable.unit === undefined ? {} : { unit: variable.unit }),
368
+ aggregation: variable.aggregation,
369
+ granularity: variable.granularity,
370
+ },
371
+ });
372
+ }
373
+ return resolvedSection({
374
+ ref: foundationReference,
375
+ meaning: objective.meaning,
376
+ desiredState: objective.desiredState,
377
+ adoptionState: objective.adoptionState,
378
+ ...(objective.epistemicState === undefined ? {} : { epistemicState: objective.epistemicState }),
379
+ beneficiaryIds: objective.beneficiaryIds,
380
+ criteria: resolvedCollection(criteria),
381
+ });
382
+ }
383
+ function highestFailure(results) {
384
+ const priority = [
385
+ 'invalid',
386
+ 'permission_denied',
387
+ 'unavailable',
388
+ 'unknown',
389
+ 'undecidable',
390
+ ];
391
+ return [...results].sort((left, right) => priority.indexOf(left.status) - priority.indexOf(right.status))[0]
392
+ ?? failure('unknown', 'historical evidence could not be resolved');
393
+ }
394
+ async function buildEvidenceCollection(run, access, port) {
395
+ const evidence = [];
396
+ const failures = [];
397
+ for (const child of run.children) {
398
+ for (const reference of child.result.evidence) {
399
+ if (!validHistoricalEvidenceReference(reference)) {
400
+ failures.push(failure('invalid', 'historical evidence reference must include a revision'));
401
+ continue;
402
+ }
403
+ const evidenceResult = await safeRead(() => port.readEvidence({
404
+ invocationId: child.invocation_id,
405
+ ...(child.result.run_reference?.run_id ? { runId: child.result.run_reference.run_id } : {}),
406
+ reference,
407
+ access,
408
+ resolution: 'historical',
409
+ }));
410
+ if (evidenceResult.status !== 'resolved') {
411
+ failures.push(evidenceResult);
412
+ continue;
413
+ }
414
+ if (!validEvidenceRecord(evidenceResult.value, reference)) {
415
+ failures.push(failure('invalid', 'historical evidence readback does not match the requested reference'));
416
+ continue;
417
+ }
418
+ evidence.push({
419
+ source: 'subdag',
420
+ invocationId: child.invocation_id,
421
+ ...(child.result.run_reference?.run_id ? { runId: child.result.run_reference.run_id } : {}),
422
+ kind: evidenceResult.value.kind,
423
+ id: evidenceResult.value.id,
424
+ revision: evidenceResult.value.revision,
425
+ ...(evidenceResult.value.digest === undefined ? {} : { digest: evidenceResult.value.digest }),
426
+ });
427
+ }
428
+ }
429
+ if (failures.length > 0)
430
+ return collectionFailure(highestFailure(failures));
431
+ return resolvedCollection(evidence);
432
+ }
433
+ function validEvaluationRecord(value) {
434
+ if (!isRecord(value)
435
+ || value.version !== 1
436
+ || !nonEmptyString(value.id)
437
+ || !isRecord(value.snapshot)
438
+ || !isRecord(value.objectiveRef)
439
+ || !isRecord(value.outcomeCaseRef)
440
+ || !Array.isArray(value.predictions)
441
+ || !Array.isArray(value.actuals)
442
+ || !Array.isArray(value.criteria)
443
+ || !Array.isArray(value.predictionComparisons)
444
+ || !['achieved', 'not_achieved', 'indeterminate'].includes(String(value.achievement))
445
+ || !isRecord(value.judgmentAtTimeValidity)
446
+ || !['valid', 'invalid', 'indeterminate'].includes(String(value.judgmentAtTimeValidity.status))
447
+ || !nonEmptyString(value.judgmentAtTimeValidity.basis)
448
+ || !nonEmptyString(value.evaluatedAt))
449
+ return false;
450
+ if (!nonEmptyString(value.snapshot.snapshotId) || !nonEmptyString(value.snapshot.problemId) || !nonEmptyString(value.snapshot.revision))
451
+ return false;
452
+ if (!validFoundationRef(value.objectiveRef, 'objective'))
453
+ return false;
454
+ if (!nonEmptyString(value.outcomeCaseRef.id) || !nonEmptyString(value.outcomeCaseRef.revision) || !nonEmptyString(value.outcomeCaseRef.digest))
455
+ return false;
456
+ if (value.judgmentAtTimeValidity.evidenceRefs !== undefined
457
+ && (!Array.isArray(value.judgmentAtTimeValidity.evidenceRefs)
458
+ || value.judgmentAtTimeValidity.evidenceRefs.some((item) => !nonEmptyString(item))))
459
+ return false;
460
+ return true;
461
+ }
462
+ function sameEvaluationSnapshot(evaluation, snapshot) {
463
+ return evaluation.snapshot.snapshotId === snapshot.snapshot_id
464
+ && evaluation.snapshot.problemId === snapshot.problem_id
465
+ && evaluation.snapshot.revision === snapshot.revision
466
+ // snapshot_id is the canonical immutable Problem snapshot digest. The
467
+ // evaluation must carry the same digest; matching locator fields alone is
468
+ // insufficient because a tampered evaluation could otherwise look
469
+ // historical while pointing at a different snapshot body.
470
+ && evaluation.snapshot.digest === snapshot.snapshot_id;
471
+ }
472
+ function buildEvaluationSections(evaluation, objective) {
473
+ if (!sameFoundationRef(evaluation.objectiveRef, objective)) {
474
+ return {
475
+ resultEvaluation: { status: 'invalid', reason: 'evaluation objective reference differs from the historical objective' },
476
+ judgmentValidity: { status: 'invalid', reason: 'evaluation objective reference differs from the historical objective' },
477
+ };
478
+ }
479
+ if (!Array.isArray(evaluation.criteria)
480
+ || !Array.isArray(evaluation.predictionComparisons)
481
+ || evaluation.criteria.some((item) => !isRecord(item))
482
+ || evaluation.predictionComparisons.some((item) => !isRecord(item))) {
483
+ return {
484
+ resultEvaluation: { status: 'invalid', reason: 'evaluation arrays are malformed' },
485
+ judgmentValidity: { status: 'invalid', reason: 'evaluation arrays are malformed' },
486
+ };
487
+ }
488
+ return {
489
+ resultEvaluation: resolvedSection({
490
+ evaluationId: evaluation.id,
491
+ achievement: evaluation.achievement,
492
+ criteria: evaluation.criteria,
493
+ predictionComparisons: evaluation.predictionComparisons,
494
+ evaluatedAt: evaluation.evaluatedAt,
495
+ outcomeCaseRef: evaluation.outcomeCaseRef,
496
+ }),
497
+ judgmentValidity: resolvedSection({
498
+ status: evaluation.judgmentAtTimeValidity.status,
499
+ basis: evaluation.judgmentAtTimeValidity.basis,
500
+ evidenceRefs: evaluation.judgmentAtTimeValidity.evidenceRefs ?? [],
501
+ }),
502
+ };
503
+ }
504
+ function requestIsValid(request) {
505
+ return isRecord(request)
506
+ && nonEmptyString(request.runId)
507
+ && isRecord(request.access)
508
+ && nonEmptyString(request.access.tenantId)
509
+ && nonEmptyString(request.access.principal)
510
+ && nonEmptyString(request.access.scopeId)
511
+ && (request.evaluationId === undefined || nonEmptyString(request.evaluationId));
512
+ }
513
+ export function createJudgmentViewService(port) {
514
+ if (!port || typeof port !== 'object')
515
+ throw new TypeError('A judgment view read port is required');
516
+ for (const method of ['readCompositionRun', 'readProblemSnapshot', 'readFoundationReference', 'readRunArtifact', 'readEvidence']) {
517
+ if (typeof port[method] !== 'function') {
518
+ throw new TypeError(`${method} is required`);
519
+ }
520
+ }
521
+ return {
522
+ async read(request) {
523
+ if (!requestIsValid(request))
524
+ return baseDocument('invalid', 'runId and trusted access context are required');
525
+ const runResult = await safeRead(() => port.readCompositionRun({ runId: request.runId, access: request.access }));
526
+ if (runResult.status !== 'resolved')
527
+ return baseDocument(runResult.status, runResult.reason);
528
+ if (!validateCompositionRun(runResult.value, request.runId))
529
+ return baseDocument('invalid', 'composition run record is malformed');
530
+ const run = runResult.value;
531
+ const runSection = resolvedSection(buildRunView(run));
532
+ const childRuns = resolvedCollection(run.children.map(buildChildView));
533
+ const evidence = await buildEvidenceCollection(run, request.access, port);
534
+ const problemResult = await safeRead(() => port.readProblemSnapshot({
535
+ reference: run.problem_snapshot,
536
+ access: request.access,
537
+ resolution: 'historical',
538
+ }));
539
+ const document = {
540
+ contract_version: JUDGMENT_VIEW_CONTRACT_VERSION,
541
+ mode: 'historical',
542
+ status: 'unknown',
543
+ run: runSection,
544
+ conclusion: { status: 'unknown', reason: 'parent run artifact is not available' },
545
+ problem: problemResult.status === 'resolved'
546
+ && validateSnapshot(problemResult.value, run.problem_snapshot)
547
+ ? resolvedSection(buildProblemView(problemResult.value, run.problem_snapshot))
548
+ : problemResult.status === 'resolved'
549
+ ? { status: 'invalid', reason: 'problem snapshot readback does not match the composition run' }
550
+ : sectionFailure(problemResult),
551
+ objective: { status: 'unknown', reason: 'historical Problem snapshot is unavailable' },
552
+ evidence,
553
+ childRuns,
554
+ resultEvaluation: { status: 'unknown', reason: 'evaluation is not available' },
555
+ judgmentValidity: { status: 'unknown', reason: 'evaluation is not available' },
556
+ };
557
+ const artifactResult = await safeRead(() => port.readRunArtifact({
558
+ runId: run.run_id,
559
+ dag: run.parent_dag,
560
+ access: request.access,
561
+ resolution: 'historical',
562
+ }));
563
+ if (artifactResult.status === 'resolved') {
564
+ const conclusion = extractConclusion(artifactResult.value, run.run_id, run.parent_dag);
565
+ document.conclusion = conclusion ? resolvedSection(conclusion) : { status: 'invalid', reason: 'parent run artifact does not match the historical run' };
566
+ }
567
+ else {
568
+ document.conclusion = sectionFailure(artifactResult);
569
+ }
570
+ if (document.problem.status === 'resolved' && problemResult.status === 'resolved' && validateSnapshot(problemResult.value, run.problem_snapshot)) {
571
+ document.objective = await buildObjectiveView(problemResult.value, request.access, port);
572
+ }
573
+ if (port.readEvaluation && document.problem.status === 'resolved' && document.objective.status === 'resolved') {
574
+ const objective = document.objective.value?.ref;
575
+ if (objective) {
576
+ const evaluationResult = await safeRead(() => port.readEvaluation({
577
+ runId: run.run_id,
578
+ snapshot: run.problem_snapshot,
579
+ objective,
580
+ ...(request.evaluationId ? { evaluationId: request.evaluationId } : {}),
581
+ access: request.access,
582
+ resolution: 'historical',
583
+ }));
584
+ if (evaluationResult.status === 'resolved') {
585
+ if (!validEvaluationRecord(evaluationResult.value) || !sameEvaluationSnapshot(evaluationResult.value, run.problem_snapshot)) {
586
+ document.resultEvaluation = { status: 'invalid', reason: 'evaluation readback does not match the historical Problem snapshot' };
587
+ document.judgmentValidity = { status: 'invalid', reason: 'evaluation readback does not match the historical Problem snapshot' };
588
+ }
589
+ else {
590
+ const sections = buildEvaluationSections(evaluationResult.value, objective);
591
+ document.resultEvaluation = sections.resultEvaluation;
592
+ document.judgmentValidity = sections.judgmentValidity;
593
+ }
594
+ }
595
+ else {
596
+ document.resultEvaluation = sectionFailure(evaluationResult);
597
+ document.judgmentValidity = sectionFailure(evaluationResult);
598
+ }
599
+ }
600
+ }
601
+ const status = aggregateStatus([
602
+ document.run,
603
+ document.conclusion,
604
+ document.problem,
605
+ document.objective,
606
+ document.evidence,
607
+ document.childRuns,
608
+ document.resultEvaluation,
609
+ document.judgmentValidity,
610
+ ]);
611
+ const reasons = [
612
+ document.conclusion.reason,
613
+ document.problem.reason,
614
+ document.objective.reason,
615
+ document.resultEvaluation.reason,
616
+ document.judgmentValidity.reason,
617
+ ].filter((reason) => nonEmptyString(reason));
618
+ document.status = status;
619
+ if (reasons.length > 0)
620
+ document.reason = reasons[0];
621
+ return document;
622
+ },
623
+ };
624
+ }
625
+ export async function readJudgmentView(port, request) {
626
+ return createJudgmentViewService(port).read(request);
627
+ }