@unson/brainbase-mcp 0.7.0 → 0.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.
- package/README.md +1 -1
- package/contracts/foundation/graph-history.sql +634 -0
- package/contracts/judgment-dag/digest.json +2 -2
- package/contracts/judgment-value-proof/schema.json +43 -1
- package/dist/canonical-task-service.js +16 -5
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +107 -0
- package/dist/company-os-objectives.d.ts +11 -0
- package/dist/company-os-objectives.js +84 -47
- package/dist/foundation-authenticated-tools.d.ts +56 -0
- package/dist/foundation-authenticated-tools.js +347 -0
- package/dist/foundation-graph-http.d.ts +43 -0
- package/dist/foundation-graph-http.js +243 -0
- package/dist/foundation-graph-write.d.ts +90 -0
- package/dist/foundation-graph-write.js +447 -0
- package/dist/foundation-public-provider.d.ts +140 -0
- package/dist/foundation-public-provider.js +192 -0
- package/dist/graph-corrections.d.ts +157 -0
- package/dist/graph-corrections.js +620 -0
- package/dist/graph-foundation-reader.d.ts +60 -0
- package/dist/graph-foundation-reader.js +494 -0
- package/dist/graph-retrieval.d.ts +6 -1
- package/dist/graph-revision-reader.d.ts +80 -0
- package/dist/graph-revision-reader.js +246 -0
- package/dist/graph-web-http.d.ts +26 -0
- package/dist/graph-web-http.js +215 -0
- package/dist/graph-web.d.ts +364 -0
- package/dist/graph-web.js +639 -0
- package/dist/judgment-problem-snapshot.d.ts +30 -2
- package/dist/judgment-problem-snapshot.js +302 -6
- package/dist/judgment-value-proof-review.d.ts +166 -0
- package/dist/judgment-value-proof-review.js +437 -0
- package/dist/judgment-value-proof.d.ts +28 -1
- package/dist/judgment-value-proof.js +53 -8
- package/dist/knowledge-continuation.d.ts +127 -0
- package/dist/knowledge-continuation.js +446 -0
- package/dist/knowledge-lookup.d.ts +178 -0
- package/dist/knowledge-lookup.js +758 -0
- package/dist/local-web-fetch-bridge.d.ts +5 -0
- package/dist/local-web-fetch-bridge.js +37 -0
- package/dist/local-web-host.d.ts +109 -0
- package/dist/local-web-host.js +688 -0
- package/dist/local-web-security.d.ts +25 -0
- package/dist/local-web-security.js +95 -0
- package/dist/organization-graph.d.ts +15 -0
- package/dist/organization-graph.js +24 -4
- package/dist/personal-knowledge.d.ts +12 -0
- package/dist/personal-knowledge.js +29 -0
- package/dist/personal-memory-handover.d.ts +108 -0
- package/dist/personal-memory-handover.js +369 -0
- package/dist/philosophy-revision-reader.d.ts +85 -0
- package/dist/philosophy-revision-reader.js +241 -0
- package/dist/portable-graph.d.ts +24 -0
- package/dist/portable-graph.js +77 -0
- package/dist/server.d.ts +7 -2
- package/dist/server.js +9 -6
- package/dist/value-proof-review-http.d.ts +25 -0
- package/dist/value-proof-review-http.js +185 -0
- package/dist/world-model.d.ts +21 -3
- package/dist/world-model.js +94 -12
- package/package.json +94 -6
- package/ui/brainbase-tokens.css +56 -0
- package/ui/graph-own-share.js +367 -0
- package/ui/graph-projects-view.css +23 -0
- package/ui/graph-projects-view.js +730 -0
- package/ui/graph-registry-view.css +101 -0
- package/ui/graph-registry-view.js +804 -0
- package/ui/graph-view-shared.css +522 -0
- package/ui/graph-view-shared.js +1227 -0
- package/ui/judgment-view.css +119 -45
- package/ui/local-web-shell.css +396 -0
- package/ui/local-web-shell.js +378 -0
- package/ui/objective-editor-http-port.js +154 -0
- package/ui/objective-editor.css +180 -74
- package/ui/objective-editor.js +490 -43
- package/ui/outcome-knowledge.css +50 -14
- package/ui/outcome-knowledge.js +15 -1
- package/ui/value-proof-review.css +504 -0
- package/ui/value-proof-review.js +1104 -0
- package/ui/workspace-kit.css +485 -0
- package/ui/workspace-kit.js +229 -0
- package/ui/world-model-view.css +188 -0
- package/ui/world-model-view.js +486 -0
- package/ui/icons/mana/LICENSE.tabler.txt +0 -21
- package/ui/icons/mana/affiliate.svg +0 -20
- package/ui/icons/mana/brand-github.svg +0 -15
- package/ui/icons/mana/brand-google-drive.svg +0 -17
- package/ui/icons/mana/brand-slack.svg +0 -18
- package/ui/icons/mana/cpu.svg +0 -24
- package/ui/outcome-mana.css +0 -255
- package/ui/outcome-mana.js +0 -2325
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type FoundationDefinition, type FoundationAcl, type FoundationRevision } from './ontology-foundation.js';
|
|
1
|
+
import { type FoundationDefinition, type FoundationAcl, type FoundationEvaluationDescriptor, type FoundationRevision } from './ontology-foundation.js';
|
|
2
2
|
/**
|
|
3
3
|
* An immutable input bundle for one judgment.
|
|
4
4
|
*
|
|
@@ -8,7 +8,7 @@ import { type FoundationDefinition, type FoundationAcl, type FoundationRevision
|
|
|
8
8
|
*/
|
|
9
9
|
export declare const JUDGMENT_PROBLEM_SNAPSHOT_VERSION: "judgment-problem-snapshot.v1";
|
|
10
10
|
export type JudgmentProblemSnapshotId = `sha256:${string}`;
|
|
11
|
-
export type JudgmentProblemReferenceKind = 'objective' | 'criterion' | 'variable' | 'observation' | 'model' | 'constraint' | 'authority' | 'resource' | 'deadline' | 'dag' | 'evidence';
|
|
11
|
+
export type JudgmentProblemReferenceKind = 'entity' | 'edge' | 'objective' | 'criterion' | 'variable' | 'observation' | 'model' | 'constraint' | 'philosophy' | 'authority' | 'resource' | 'deadline' | 'dag' | 'evidence';
|
|
12
12
|
export type JudgmentProblemScopeType = 'personal' | 'project' | 'organization';
|
|
13
13
|
export interface JudgmentProblemScope {
|
|
14
14
|
readonly type: JudgmentProblemScopeType;
|
|
@@ -35,8 +35,15 @@ export interface JudgmentProblemReference {
|
|
|
35
35
|
readonly scope: JudgmentProblemScope;
|
|
36
36
|
readonly valid_from: string;
|
|
37
37
|
readonly valid_to?: string | null;
|
|
38
|
+
/**
|
|
39
|
+
* Source-owned measurement conditions for an Observation reference. The
|
|
40
|
+
* descriptor is checked against the canonical Variable and Objective
|
|
41
|
+
* before a current judgment can use the observation.
|
|
42
|
+
*/
|
|
43
|
+
readonly measurement?: JudgmentProblemObservationMeasurementDescriptor;
|
|
38
44
|
readonly evidence?: JudgmentProblemEvidenceBinding;
|
|
39
45
|
}
|
|
46
|
+
export type JudgmentProblemObservationMeasurementDescriptor = FoundationEvaluationDescriptor;
|
|
40
47
|
/**
|
|
41
48
|
* Stable name shared by sub-DAG and reservation consumers. A ProblemRef is
|
|
42
49
|
* intentionally only a versioned, scoped reference; it never carries an
|
|
@@ -90,6 +97,10 @@ export interface JudgmentProblemReferenceResolution {
|
|
|
90
97
|
/** The provider must return the digest of the exact revision it resolved. */
|
|
91
98
|
readonly digest?: JudgmentProblemSnapshotId;
|
|
92
99
|
readonly message?: string;
|
|
100
|
+
/** Canonical Observation metadata returned by the source-owned resolver. */
|
|
101
|
+
readonly canonical?: {
|
|
102
|
+
readonly measurement?: JudgmentProblemObservationMeasurementDescriptor;
|
|
103
|
+
};
|
|
93
104
|
}
|
|
94
105
|
/**
|
|
95
106
|
* A provider is the only place that knows how an Observation, authority,
|
|
@@ -104,6 +115,8 @@ export interface JudgmentProblemReferenceProvider {
|
|
|
104
115
|
readonly reference: JudgmentProblemReference;
|
|
105
116
|
readonly phase: JudgmentProblemReferenceResolutionPhase;
|
|
106
117
|
readonly context: JudgmentProblemSnapshotAccessContext;
|
|
118
|
+
/** The full bundle enables cross-reference coherence checks. */
|
|
119
|
+
readonly snapshot?: JudgmentProblemSnapshot;
|
|
107
120
|
}): JudgmentProblemReferenceResolution | Promise<JudgmentProblemReferenceResolution>;
|
|
108
121
|
}
|
|
109
122
|
export interface SaveJudgmentProblemSnapshotRequest {
|
|
@@ -124,6 +137,19 @@ export interface LoadJudgmentProblemSnapshotRequest {
|
|
|
124
137
|
readonly reference_resolution?: JudgmentProblemReferenceResolutionMode;
|
|
125
138
|
readonly referenceProvider?: JudgmentProblemReferenceProvider;
|
|
126
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Validate a not-yet-persisted snapshot through the same read and reference
|
|
142
|
+
* boundaries used by load. This is intentionally read-only: callers cannot
|
|
143
|
+
* turn validation into publication by passing an artifact root.
|
|
144
|
+
*/
|
|
145
|
+
export interface ValidateJudgmentProblemSnapshotRequest {
|
|
146
|
+
readonly snapshot: JudgmentProblemSnapshot;
|
|
147
|
+
readonly access: JudgmentProblemSnapshotAccessContext;
|
|
148
|
+
readonly accessProvider?: JudgmentProblemSnapshotAccessProvider;
|
|
149
|
+
/** Defaults to `current`; historical validation only rechecks ACL/digest. */
|
|
150
|
+
readonly reference_resolution?: JudgmentProblemReferenceResolutionMode;
|
|
151
|
+
readonly referenceProvider: JudgmentProblemReferenceProvider;
|
|
152
|
+
}
|
|
127
153
|
export interface JudgmentProblemSnapshotReceipt {
|
|
128
154
|
readonly snapshot_id: JudgmentProblemSnapshotId;
|
|
129
155
|
readonly snapshot_version: typeof JUDGMENT_PROBLEM_SNAPSHOT_VERSION;
|
|
@@ -147,6 +173,7 @@ export declare const defaultJudgmentProblemSnapshotAccessProvider: JudgmentProbl
|
|
|
147
173
|
export declare function computeJudgmentProblemSnapshotId(value: JudgmentProblemSnapshot): JudgmentProblemSnapshotId;
|
|
148
174
|
export declare function saveJudgmentProblemSnapshot(request: SaveJudgmentProblemSnapshotRequest): Promise<JudgmentProblemSnapshotReceipt>;
|
|
149
175
|
export declare function loadJudgmentProblemSnapshot(request: LoadJudgmentProblemSnapshotRequest): Promise<JudgmentProblemSnapshot>;
|
|
176
|
+
export declare function validateJudgmentProblemSnapshot(request: ValidateJudgmentProblemSnapshotRequest): Promise<void>;
|
|
150
177
|
/** Structural adapter for FoundationRevisionStore-like readers. */
|
|
151
178
|
export interface JudgmentProblemFoundationReferenceReader {
|
|
152
179
|
read(reference: FoundationRevision, context: {
|
|
@@ -181,5 +208,6 @@ export declare function createJudgmentProblemFoundationReferenceProvider(options
|
|
|
181
208
|
readonly reference: JudgmentProblemReference;
|
|
182
209
|
readonly phase: JudgmentProblemReferenceResolutionPhase;
|
|
183
210
|
readonly context: JudgmentProblemSnapshotAccessContext;
|
|
211
|
+
readonly snapshot?: JudgmentProblemSnapshot;
|
|
184
212
|
}) => JudgmentProblemReferenceResolution | Promise<JudgmentProblemReferenceResolution>;
|
|
185
213
|
}): JudgmentProblemReferenceProvider;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createHash, randomUUID } from 'node:crypto';
|
|
2
2
|
import { link, open, lstat, mkdir, readdir, readFile, unlink } from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import { validateFoundationDefinition } from './ontology-foundation.js';
|
|
4
|
+
import { validateFoundationDefinition, validateEvaluationCompatibility } from './ontology-foundation.js';
|
|
5
|
+
import { checkObjectiveReadiness } from './company-os-objectives.js';
|
|
5
6
|
/**
|
|
6
7
|
* An immutable input bundle for one judgment.
|
|
7
8
|
*
|
|
@@ -24,12 +25,15 @@ const SNAPSHOT_ID_PATTERN = /^sha256:([0-9a-f]{64})$/u;
|
|
|
24
25
|
const POSITIVE_REVISION_PATTERN = /^[1-9]\d*$/u;
|
|
25
26
|
const SCOPE_TYPES = ['personal', 'project', 'organization'];
|
|
26
27
|
const REFERENCE_KINDS = [
|
|
28
|
+
'entity',
|
|
29
|
+
'edge',
|
|
27
30
|
'objective',
|
|
28
31
|
'criterion',
|
|
29
32
|
'variable',
|
|
30
33
|
'observation',
|
|
31
34
|
'model',
|
|
32
35
|
'constraint',
|
|
36
|
+
'philosophy',
|
|
33
37
|
'authority',
|
|
34
38
|
'resource',
|
|
35
39
|
'deadline',
|
|
@@ -48,7 +52,7 @@ const SNAPSHOT_KEYS = [
|
|
|
48
52
|
'snapshot_version'
|
|
49
53
|
];
|
|
50
54
|
const ENVELOPE_KEYS = ['snapshot', 'snapshot_id', 'snapshot_version'];
|
|
51
|
-
const REFERENCE_KEYS = ['digest', 'evidence', 'id', 'kind', 'revision', 'scope', 'valid_from', 'valid_to'];
|
|
55
|
+
const REFERENCE_KEYS = ['digest', 'evidence', 'id', 'kind', 'measurement', 'revision', 'scope', 'valid_from', 'valid_to'];
|
|
52
56
|
const EVIDENCE_KEYS = ['access', 'content', 'digest', 'mode', 'reference_id', 'reference_revision'];
|
|
53
57
|
const SCOPE_KEYS = ['id', 'type'];
|
|
54
58
|
const ACL_KEYS = ['ownerId', 'readerIds', 'visibility', 'writerIds'];
|
|
@@ -254,6 +258,9 @@ function validateReference(value, index) {
|
|
|
254
258
|
if (validTo !== undefined && Date.parse(validTo) < Date.parse(validFrom)) {
|
|
255
259
|
fail('invalid_request', `${label}.valid_to precedes valid_from`);
|
|
256
260
|
}
|
|
261
|
+
const measurement = value.measurement === undefined
|
|
262
|
+
? undefined
|
|
263
|
+
: validateMeasurementDescriptor(value.measurement, `${label}.measurement`);
|
|
257
264
|
const evidence = value.evidence === undefined ? undefined : validateEvidence(value.evidence, `${label}.evidence`);
|
|
258
265
|
return deepFreeze({
|
|
259
266
|
kind: value.kind,
|
|
@@ -263,9 +270,73 @@ function validateReference(value, index) {
|
|
|
263
270
|
scope: { type: value.scope.type, id: value.scope.id },
|
|
264
271
|
valid_from: validFrom,
|
|
265
272
|
...(validTo === undefined ? {} : { valid_to: validTo }),
|
|
273
|
+
...(measurement === undefined ? {} : { measurement }),
|
|
266
274
|
...(evidence === undefined ? {} : { evidence })
|
|
267
275
|
});
|
|
268
276
|
}
|
|
277
|
+
function validateMeasurementDescriptor(value, label) {
|
|
278
|
+
const aggregations = [
|
|
279
|
+
'none',
|
|
280
|
+
'sum',
|
|
281
|
+
'average',
|
|
282
|
+
'count',
|
|
283
|
+
'min',
|
|
284
|
+
'max',
|
|
285
|
+
'last',
|
|
286
|
+
'custom'
|
|
287
|
+
];
|
|
288
|
+
const keys = ['aggregation', 'granularity', 'period', 'scope', 'unit', 'variableRef'];
|
|
289
|
+
if (!isPlainRecord(value) || !hasOnlyKeys(value, keys)
|
|
290
|
+
|| !Object.prototype.hasOwnProperty.call(value, 'variableRef')
|
|
291
|
+
|| !Object.prototype.hasOwnProperty.call(value, 'aggregation')
|
|
292
|
+
|| !Object.prototype.hasOwnProperty.call(value, 'granularity')
|
|
293
|
+
|| !Object.prototype.hasOwnProperty.call(value, 'scope')
|
|
294
|
+
|| !Object.prototype.hasOwnProperty.call(value, 'period')) {
|
|
295
|
+
fail('invalid_request', `${label} is invalid`);
|
|
296
|
+
}
|
|
297
|
+
if (!isPlainRecord(value.variableRef)
|
|
298
|
+
|| !hasExactKeys(value.variableRef, ['id', 'revision', 'type'])
|
|
299
|
+
|| value.variableRef.type !== 'variable') {
|
|
300
|
+
fail('invalid_request', `${label}.variableRef must reference a Variable revision`);
|
|
301
|
+
}
|
|
302
|
+
const variableId = requireString(value.variableRef.id, `${label}.variableRef.id`);
|
|
303
|
+
const variableRevision = requireRevision(value.variableRef.revision, `${label}.variableRef.revision`);
|
|
304
|
+
if (typeof value.aggregation !== 'string' || !aggregations.includes(value.aggregation)) {
|
|
305
|
+
fail('invalid_request', `${label}.aggregation is invalid`);
|
|
306
|
+
}
|
|
307
|
+
const granularity = requireString(value.granularity, `${label}.granularity`);
|
|
308
|
+
if (value.unit !== undefined && typeof value.unit !== 'string') {
|
|
309
|
+
fail('invalid_request', `${label}.unit must be a string when provided`);
|
|
310
|
+
}
|
|
311
|
+
if (!isPlainRecord(value.scope)
|
|
312
|
+
|| !Array.isArray(value.scope.subjectIds)
|
|
313
|
+
|| value.scope.subjectIds.some((subjectId) => typeof subjectId !== 'string' || subjectId.trim().length === 0)
|
|
314
|
+
|| typeof value.scope.validFrom !== 'string'
|
|
315
|
+
|| Number.isNaN(Date.parse(value.scope.validFrom))
|
|
316
|
+
|| (value.scope.validUntil !== undefined && (typeof value.scope.validUntil !== 'string' || Number.isNaN(Date.parse(value.scope.validUntil))))) {
|
|
317
|
+
fail('invalid_request', `${label}.scope is invalid`);
|
|
318
|
+
}
|
|
319
|
+
if (!isPlainRecord(value.period)
|
|
320
|
+
|| typeof value.period.from !== 'string'
|
|
321
|
+
|| typeof value.period.until !== 'string'
|
|
322
|
+
|| Number.isNaN(Date.parse(value.period.from))
|
|
323
|
+
|| Number.isNaN(Date.parse(value.period.until))
|
|
324
|
+
|| Date.parse(value.period.until) < Date.parse(value.period.from)) {
|
|
325
|
+
fail('invalid_request', `${label}.period is invalid`);
|
|
326
|
+
}
|
|
327
|
+
return deepFreeze({
|
|
328
|
+
variableRef: { id: variableId, type: 'variable', revision: variableRevision },
|
|
329
|
+
...(value.unit === undefined ? {} : { unit: value.unit }),
|
|
330
|
+
aggregation: value.aggregation,
|
|
331
|
+
granularity,
|
|
332
|
+
scope: {
|
|
333
|
+
subjectIds: [...value.scope.subjectIds],
|
|
334
|
+
validFrom: value.scope.validFrom,
|
|
335
|
+
...(value.scope.validUntil === undefined ? {} : { validUntil: value.scope.validUntil })
|
|
336
|
+
},
|
|
337
|
+
period: { from: value.period.from, until: value.period.until }
|
|
338
|
+
});
|
|
339
|
+
}
|
|
269
340
|
function validateSnapshot(value) {
|
|
270
341
|
if (!isPlainRecord(value) || !hasExactKeys(value, SNAPSHOT_KEYS) ||
|
|
271
342
|
value.snapshot_version !== JUDGMENT_PROBLEM_SNAPSHOT_VERSION ||
|
|
@@ -299,6 +370,10 @@ function requiredKinds(references) {
|
|
|
299
370
|
}
|
|
300
371
|
function validateRequiredReferences(snapshot) {
|
|
301
372
|
const kinds = requiredKinds(snapshot.references);
|
|
373
|
+
const objectiveCount = snapshot.references.filter((reference) => reference.kind === 'objective').length;
|
|
374
|
+
if (objectiveCount !== 1) {
|
|
375
|
+
fail('invalid_request', `snapshot must contain exactly one objective reference; found ${objectiveCount}`);
|
|
376
|
+
}
|
|
302
377
|
const required = [
|
|
303
378
|
'objective',
|
|
304
379
|
'criterion',
|
|
@@ -353,10 +428,10 @@ function evidenceReference(owner, evidence) {
|
|
|
353
428
|
...(owner.valid_to === undefined ? {} : { valid_to: owner.valid_to })
|
|
354
429
|
};
|
|
355
430
|
}
|
|
356
|
-
async function resolveOneReference(reference, phase, context, provider, errorReference = reference) {
|
|
431
|
+
async function resolveOneReference(reference, phase, context, provider, snapshot, errorReference = reference) {
|
|
357
432
|
let result;
|
|
358
433
|
try {
|
|
359
|
-
result = await provider.resolve({ reference, phase, context });
|
|
434
|
+
result = await provider.resolve({ reference, phase, context, snapshot });
|
|
360
435
|
}
|
|
361
436
|
catch (error) {
|
|
362
437
|
if (error instanceof JudgmentProblemSnapshotError)
|
|
@@ -383,9 +458,9 @@ async function resolveOneReference(reference, phase, context, provider, errorRef
|
|
|
383
458
|
}
|
|
384
459
|
async function resolveReferences(snapshot, phase, context, provider) {
|
|
385
460
|
for (const reference of snapshot.references) {
|
|
386
|
-
await resolveOneReference(reference, phase, context, provider);
|
|
461
|
+
await resolveOneReference(reference, phase, context, provider, snapshot);
|
|
387
462
|
if (reference.evidence?.mode === 'immutable_reference') {
|
|
388
|
-
await resolveOneReference(evidenceReference(reference, reference.evidence), phase, context, provider, reference);
|
|
463
|
+
await resolveOneReference(evidenceReference(reference, reference.evidence), phase, context, provider, snapshot, reference);
|
|
389
464
|
}
|
|
390
465
|
}
|
|
391
466
|
}
|
|
@@ -682,6 +757,43 @@ export async function loadJudgmentProblemSnapshot(request) {
|
|
|
682
757
|
await resolveReferences(envelope.snapshot, referenceResolution === 'current' ? 'read' : 'historical_read', context, request.referenceProvider);
|
|
683
758
|
return envelope.snapshot;
|
|
684
759
|
}
|
|
760
|
+
export async function validateJudgmentProblemSnapshot(request) {
|
|
761
|
+
if (!isPlainRecord(request))
|
|
762
|
+
fail('invalid_request', 'validation request must be a plain object');
|
|
763
|
+
const snapshot = validateSnapshot(request.snapshot);
|
|
764
|
+
validateRequiredReferences(snapshot);
|
|
765
|
+
const context = validateAccessContext(request.access);
|
|
766
|
+
const referenceResolution = request.reference_resolution ?? 'current';
|
|
767
|
+
if (referenceResolution !== 'current' && referenceResolution !== 'historical') {
|
|
768
|
+
fail('invalid_request', 'reference_resolution must be current or historical');
|
|
769
|
+
}
|
|
770
|
+
if (!request.referenceProvider || typeof request.referenceProvider.resolve !== 'function') {
|
|
771
|
+
fail('invalid_request', `referenceProvider.resolve is required for ${referenceResolution} reference resolution`);
|
|
772
|
+
}
|
|
773
|
+
const accessProvider = request.accessProvider ?? defaultJudgmentProblemSnapshotAccessProvider;
|
|
774
|
+
await authorize('read', snapshot, context, accessProvider);
|
|
775
|
+
for (const reference of snapshot.references) {
|
|
776
|
+
if (reference.evidence === undefined)
|
|
777
|
+
continue;
|
|
778
|
+
try {
|
|
779
|
+
const allowed = await accessProvider.authorize({
|
|
780
|
+
action: 'read',
|
|
781
|
+
context,
|
|
782
|
+
acl: reference.evidence.access,
|
|
783
|
+
snapshot,
|
|
784
|
+
reference
|
|
785
|
+
});
|
|
786
|
+
if (allowed === false)
|
|
787
|
+
fail('unauthorized', `evidence access was denied for ${reference.kind}/${reference.id}@${reference.revision}`, reference);
|
|
788
|
+
}
|
|
789
|
+
catch (error) {
|
|
790
|
+
if (error instanceof JudgmentProblemSnapshotError)
|
|
791
|
+
throw error;
|
|
792
|
+
fail('unauthorized', `evidence access was denied for ${reference.kind}/${reference.id}@${reference.revision}`, reference);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
await resolveReferences(snapshot, referenceResolution === 'current' ? 'read' : 'historical_read', context, request.referenceProvider);
|
|
796
|
+
}
|
|
685
797
|
function validateAccessContext(value) {
|
|
686
798
|
if (!isPlainRecord(value) || typeof value.principal !== 'string' || value.principal.trim().length === 0 || value.principal.includes('\0')) {
|
|
687
799
|
fail('unauthorized', 'a trusted principal is required');
|
|
@@ -699,8 +811,16 @@ function validateAccessContext(value) {
|
|
|
699
811
|
* bypass the canonical store or digest check.
|
|
700
812
|
*/
|
|
701
813
|
export function createJudgmentProblemFoundationReferenceProvider(options) {
|
|
814
|
+
const objectiveReader = {
|
|
815
|
+
async read(reference, context) {
|
|
816
|
+
return await options.store.read(reference, { principal: context.principal });
|
|
817
|
+
}
|
|
818
|
+
};
|
|
702
819
|
return {
|
|
703
820
|
async resolve(input) {
|
|
821
|
+
if (input.reference.kind === 'observation') {
|
|
822
|
+
return resolveObservationReference(input, options, objectiveReader);
|
|
823
|
+
}
|
|
704
824
|
if (!['objective', 'variable', 'model', 'constraint'].includes(input.reference.kind)) {
|
|
705
825
|
if (options.resolveOther)
|
|
706
826
|
return options.resolveOther(input);
|
|
@@ -733,6 +853,26 @@ export function createJudgmentProblemFoundationReferenceProvider(options) {
|
|
|
733
853
|
return { status: 'not_applicable', message: applicability.message };
|
|
734
854
|
}
|
|
735
855
|
}
|
|
856
|
+
if (definition.type === 'objective') {
|
|
857
|
+
if (input.phase === 'historical_read') {
|
|
858
|
+
const dependencyResult = await validateObjectiveDependencies(definition, input, options);
|
|
859
|
+
if (dependencyResult)
|
|
860
|
+
return dependencyResult;
|
|
861
|
+
}
|
|
862
|
+
else {
|
|
863
|
+
const readiness = await checkObjectiveReadiness(objectiveReader, input.reference.id, { principal: input.context.principal }, input.reference.revision);
|
|
864
|
+
if (!readiness.ready)
|
|
865
|
+
return objectiveReadinessResult(readiness.issues);
|
|
866
|
+
const dependencyResult = await validateObjectiveDependencies(definition, input, options);
|
|
867
|
+
if (dependencyResult)
|
|
868
|
+
return dependencyResult;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
if (definition.type === 'model') {
|
|
872
|
+
const dependencyResult = await validateModelDependencies(definition, input, options);
|
|
873
|
+
if (dependencyResult)
|
|
874
|
+
return dependencyResult;
|
|
875
|
+
}
|
|
736
876
|
if (options.validate) {
|
|
737
877
|
return options.validate({
|
|
738
878
|
...input,
|
|
@@ -743,6 +883,162 @@ export function createJudgmentProblemFoundationReferenceProvider(options) {
|
|
|
743
883
|
}
|
|
744
884
|
};
|
|
745
885
|
}
|
|
886
|
+
function objectiveReadinessResult(issues) {
|
|
887
|
+
const notApplicable = issues.some((issue) => (issue.code === 'UNAUTHORIZED_USE' || issue.code === 'CRITERION_PERIOD_MISMATCH'));
|
|
888
|
+
return {
|
|
889
|
+
status: notApplicable ? 'not_applicable' : 'unresolved',
|
|
890
|
+
message: issues.map((issue) => issue.message).join('; ')
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
async function validateObjectiveDependencies(definition, input, options) {
|
|
894
|
+
for (const criterion of definition.criteria) {
|
|
895
|
+
const dependency = criterion?.variableRef;
|
|
896
|
+
if (!isVariableRevision(dependency)) {
|
|
897
|
+
return { status: 'unresolved', message: 'Objective criterion does not reference a valid Variable revision' };
|
|
898
|
+
}
|
|
899
|
+
const resolved = await options.store.read(dependency, { principal: input.context.principal });
|
|
900
|
+
if (!resolved)
|
|
901
|
+
return { status: 'missing', message: `Objective Variable ${dependency.id}@${dependency.revision} was not found` };
|
|
902
|
+
if (!matchingFoundationRecord(resolved, dependency, 'variable')) {
|
|
903
|
+
return { status: 'unresolved', message: `Objective Variable ${dependency.id}@${dependency.revision} is not the requested revision` };
|
|
904
|
+
}
|
|
905
|
+
const pinned = findSnapshotReference(input.snapshot, dependency);
|
|
906
|
+
if (pinned && pinned.digest !== resolved.digest) {
|
|
907
|
+
return { status: 'unresolved', message: `Objective Variable ${dependency.id}@${dependency.revision} digest changed` };
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
return undefined;
|
|
911
|
+
}
|
|
912
|
+
async function validateModelDependencies(definition, input, options) {
|
|
913
|
+
const dependencies = [...definition.inputVariableRefs, ...definition.outputVariableRefs];
|
|
914
|
+
const seen = new Set();
|
|
915
|
+
for (const dependency of dependencies) {
|
|
916
|
+
if (!isVariableRevision(dependency)) {
|
|
917
|
+
return { status: 'unresolved', message: 'Model input/output must reference a valid Variable revision' };
|
|
918
|
+
}
|
|
919
|
+
const key = `${dependency.id}@${dependency.revision}`;
|
|
920
|
+
if (seen.has(key))
|
|
921
|
+
continue;
|
|
922
|
+
seen.add(key);
|
|
923
|
+
const resolved = await options.store.read(dependency, { principal: input.context.principal });
|
|
924
|
+
if (!resolved)
|
|
925
|
+
return { status: 'missing', message: `Model Variable ${dependency.id}@${dependency.revision} was not found` };
|
|
926
|
+
if (!matchingFoundationRecord(resolved, dependency, 'variable')) {
|
|
927
|
+
return { status: 'unresolved', message: `Model Variable ${dependency.id}@${dependency.revision} is not the requested revision` };
|
|
928
|
+
}
|
|
929
|
+
const pinned = findSnapshotReference(input.snapshot, dependency);
|
|
930
|
+
if (pinned && pinned.digest !== resolved.digest) {
|
|
931
|
+
return { status: 'unresolved', message: `Model Variable ${dependency.id}@${dependency.revision} digest changed` };
|
|
932
|
+
}
|
|
933
|
+
if (input.phase === 'historical_read')
|
|
934
|
+
continue;
|
|
935
|
+
const definitionResult = validateFoundationDefinition(resolved.definition, { use: 'judgment' });
|
|
936
|
+
if (!definitionResult.valid) {
|
|
937
|
+
const notApplicable = definitionResult.issues.some((issue) => issue.code === 'UNAUTHORIZED_USE');
|
|
938
|
+
return {
|
|
939
|
+
status: notApplicable ? 'not_applicable' : 'unresolved',
|
|
940
|
+
message: definitionResult.issues.map((issue) => issue.message).join('; ')
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
const applicability = validateFoundationReferenceApplicability(input.reference, resolved.definition);
|
|
944
|
+
if (!applicability.valid)
|
|
945
|
+
return { status: 'not_applicable', message: applicability.message };
|
|
946
|
+
}
|
|
947
|
+
return undefined;
|
|
948
|
+
}
|
|
949
|
+
function isVariableRevision(value) {
|
|
950
|
+
return isPlainRecord(value)
|
|
951
|
+
&& value.type === 'variable'
|
|
952
|
+
&& typeof value.id === 'string'
|
|
953
|
+
&& value.id.length > 0
|
|
954
|
+
&& typeof value.revision === 'string'
|
|
955
|
+
&& /^[1-9]\d*$/u.test(value.revision);
|
|
956
|
+
}
|
|
957
|
+
function matchingFoundationRecord(record, reference, type) {
|
|
958
|
+
return typeof record.digest === 'string'
|
|
959
|
+
&& isPlainRecord(record.definition)
|
|
960
|
+
&& record.definition.type === type
|
|
961
|
+
&& record.definition.id === reference.id
|
|
962
|
+
&& record.definition.revision === reference.revision;
|
|
963
|
+
}
|
|
964
|
+
function findSnapshotReference(snapshot, reference) {
|
|
965
|
+
return snapshot?.references.find((candidate) => (candidate.kind === reference.type
|
|
966
|
+
&& candidate.id === reference.id
|
|
967
|
+
&& candidate.revision === reference.revision));
|
|
968
|
+
}
|
|
969
|
+
async function resolveObservationReference(input, options, objectiveReader) {
|
|
970
|
+
if (!options.resolveOther)
|
|
971
|
+
return { status: 'unresolved', message: 'No canonical Observation provider is registered' };
|
|
972
|
+
const resolved = await options.resolveOther(input);
|
|
973
|
+
if (resolved.status !== 'resolved')
|
|
974
|
+
return resolved;
|
|
975
|
+
const descriptor = input.reference.measurement;
|
|
976
|
+
const canonical = resolved.canonical?.measurement;
|
|
977
|
+
if (input.phase === 'historical_read') {
|
|
978
|
+
if (descriptor !== undefined && canonical !== undefined && !sameMeasurementDescriptor(descriptor, canonical)) {
|
|
979
|
+
return { status: 'unresolved', message: 'Historical Observation measurement metadata changed' };
|
|
980
|
+
}
|
|
981
|
+
return resolved;
|
|
982
|
+
}
|
|
983
|
+
if (descriptor === undefined || canonical === undefined) {
|
|
984
|
+
return { status: 'unresolved', message: 'Current Observation requires canonical measurement metadata and a pinned descriptor' };
|
|
985
|
+
}
|
|
986
|
+
if (!sameMeasurementDescriptor(descriptor, canonical)) {
|
|
987
|
+
return { status: 'unresolved', message: 'Observation measurement descriptor does not match canonical metadata' };
|
|
988
|
+
}
|
|
989
|
+
const snapshot = input.snapshot;
|
|
990
|
+
if (!snapshot)
|
|
991
|
+
return { status: 'unresolved', message: 'Current Observation validation requires the complete snapshot bundle' };
|
|
992
|
+
const objectiveReference = snapshot.references.find((candidate) => candidate.kind === 'objective');
|
|
993
|
+
if (!objectiveReference)
|
|
994
|
+
return { status: 'unresolved', message: 'Current Observation requires an Objective reference' };
|
|
995
|
+
const objectiveRecord = await options.store.read({ id: objectiveReference.id, type: 'objective', revision: objectiveReference.revision }, { principal: input.context.principal });
|
|
996
|
+
if (!objectiveRecord)
|
|
997
|
+
return { status: 'missing', message: 'Objective for Observation measurement was not found' };
|
|
998
|
+
const objectiveRevision = {
|
|
999
|
+
id: objectiveReference.id,
|
|
1000
|
+
type: 'objective',
|
|
1001
|
+
revision: objectiveReference.revision
|
|
1002
|
+
};
|
|
1003
|
+
if (!matchingFoundationRecord(objectiveRecord, objectiveRevision, 'objective')) {
|
|
1004
|
+
return { status: 'unresolved', message: 'Objective for Observation measurement is not the requested revision' };
|
|
1005
|
+
}
|
|
1006
|
+
if (objectiveRecord.digest !== objectiveReference.digest) {
|
|
1007
|
+
return { status: 'unresolved', message: 'Objective for Observation measurement digest changed' };
|
|
1008
|
+
}
|
|
1009
|
+
const objectiveDefinition = objectiveRecord.definition;
|
|
1010
|
+
const objectiveApplicability = validateFoundationReferenceApplicability(objectiveReference, objectiveDefinition);
|
|
1011
|
+
if (!objectiveApplicability.valid)
|
|
1012
|
+
return { status: 'not_applicable', message: objectiveApplicability.message };
|
|
1013
|
+
const readiness = await checkObjectiveReadiness(objectiveReader, objectiveReference.id, { principal: input.context.principal }, objectiveReference.revision);
|
|
1014
|
+
if (!readiness.ready)
|
|
1015
|
+
return objectiveReadinessResult(readiness.issues);
|
|
1016
|
+
const variableRecord = await options.store.read(descriptor.variableRef, { principal: input.context.principal });
|
|
1017
|
+
if (!variableRecord)
|
|
1018
|
+
return { status: 'missing', message: 'Observation measurement Variable was not found' };
|
|
1019
|
+
if (!matchingFoundationRecord(variableRecord, descriptor.variableRef, 'variable')) {
|
|
1020
|
+
return { status: 'unresolved', message: 'Observation measurement Variable is not the requested revision' };
|
|
1021
|
+
}
|
|
1022
|
+
const pinnedVariable = findSnapshotReference(snapshot, descriptor.variableRef);
|
|
1023
|
+
if (pinnedVariable && pinnedVariable.digest !== variableRecord.digest) {
|
|
1024
|
+
return { status: 'unresolved', message: 'Observation measurement Variable digest changed' };
|
|
1025
|
+
}
|
|
1026
|
+
const compatibility = validateEvaluationCompatibility(variableRecord.definition, descriptor, { period: objectiveDefinition.evaluationPeriod });
|
|
1027
|
+
if (!compatibility.valid) {
|
|
1028
|
+
const notApplicable = compatibility.issues.some((issue) => issue.code === 'UNAUTHORIZED_USE');
|
|
1029
|
+
return {
|
|
1030
|
+
status: notApplicable ? 'not_applicable' : 'unresolved',
|
|
1031
|
+
message: compatibility.issues.map((issue) => issue.message).join('; ')
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
if (!scopeContainsReference(descriptor.scope, input.reference)) {
|
|
1035
|
+
return { status: 'not_applicable', message: 'Observation measurement scope does not cover the Observation reference' };
|
|
1036
|
+
}
|
|
1037
|
+
return resolved;
|
|
1038
|
+
}
|
|
1039
|
+
function sameMeasurementDescriptor(left, right) {
|
|
1040
|
+
return canonicalJson(left) === canonicalJson(right);
|
|
1041
|
+
}
|
|
746
1042
|
function validateFoundationReferenceApplicability(reference, definition) {
|
|
747
1043
|
const scopes = definition.type === 'model'
|
|
748
1044
|
? [definition.scope, definition.applicability]
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { type JudgmentValueProof } from './judgment-value-proof.js';
|
|
2
|
+
export declare const JUDGMENT_VALUE_PROOF_FILE_SUFFIX = ".value-proof.json";
|
|
3
|
+
export declare const JUDGMENT_VALUE_PROOF_FEEDBACK_SCHEMA = "brainbase-judgment-value-proof-feedback-v1";
|
|
4
|
+
export declare const JUDGMENT_VALUE_PROOF_FEEDBACK_FILE = "judgment-value-proof-feedback.jsonl";
|
|
5
|
+
export type JudgmentValueProofReviewSection = 'needs_human' | 'blocked' | 'continued' | 'other';
|
|
6
|
+
export type JudgmentValueProofFeedbackStatus = 'accepted' | 'corrected' | 'next_time_ask' | 'reverted';
|
|
7
|
+
/** What the owner's feedback asks to change. `delegation` is the ask/continue boundary. */
|
|
8
|
+
export type JudgmentValueProofFeedbackLayer = 'delegation' | 'method' | 'objective' | 'world_model' | 'philosophy' | 'other';
|
|
9
|
+
export declare const JUDGMENT_VALUE_PROOF_FEEDBACK_LAYERS: readonly JudgmentValueProofFeedbackLayer[];
|
|
10
|
+
export interface JudgmentValueProofJournalEntry {
|
|
11
|
+
readonly file: string;
|
|
12
|
+
readonly proof: JudgmentValueProof;
|
|
13
|
+
}
|
|
14
|
+
export interface JudgmentValueProofJournalRejection {
|
|
15
|
+
readonly file: string;
|
|
16
|
+
readonly reason: string;
|
|
17
|
+
}
|
|
18
|
+
export type JudgmentValueProofJournalRead = {
|
|
19
|
+
readonly status: 'unavailable';
|
|
20
|
+
readonly root: string;
|
|
21
|
+
readonly reason: string;
|
|
22
|
+
} | {
|
|
23
|
+
readonly status: 'available';
|
|
24
|
+
readonly root: string;
|
|
25
|
+
readonly entries: readonly JudgmentValueProofJournalEntry[];
|
|
26
|
+
readonly rejected: readonly JudgmentValueProofJournalRejection[];
|
|
27
|
+
readonly latest_recorded_at: string | null;
|
|
28
|
+
};
|
|
29
|
+
export interface JudgmentValueProofFeedbackRecord {
|
|
30
|
+
readonly schema_version: typeof JUDGMENT_VALUE_PROOF_FEEDBACK_SCHEMA;
|
|
31
|
+
readonly feedback_id: string;
|
|
32
|
+
readonly intent_id: string;
|
|
33
|
+
readonly decision_attempt_id: string;
|
|
34
|
+
readonly status: JudgmentValueProofFeedbackStatus;
|
|
35
|
+
readonly summary: string | null;
|
|
36
|
+
/** Absent on records written before the layer was introduced. */
|
|
37
|
+
readonly target_layer?: JudgmentValueProofFeedbackLayer | null;
|
|
38
|
+
readonly recorded_at: string;
|
|
39
|
+
}
|
|
40
|
+
export interface JudgmentValueProofFeedbackInput {
|
|
41
|
+
readonly dataDir?: string;
|
|
42
|
+
readonly intent_id: string;
|
|
43
|
+
readonly decision_attempt_id: string;
|
|
44
|
+
readonly status: JudgmentValueProofFeedbackStatus;
|
|
45
|
+
readonly summary?: string | null;
|
|
46
|
+
readonly target_layer?: JudgmentValueProofFeedbackLayer | null;
|
|
47
|
+
readonly now?: Date;
|
|
48
|
+
}
|
|
49
|
+
export interface JudgmentValueProofReviewItem {
|
|
50
|
+
readonly file: string;
|
|
51
|
+
readonly section: JudgmentValueProofReviewSection;
|
|
52
|
+
readonly proof: JudgmentValueProof;
|
|
53
|
+
readonly feedback_history: readonly JudgmentValueProofFeedbackRecord[];
|
|
54
|
+
}
|
|
55
|
+
export type JudgmentValueProofReviewHome = {
|
|
56
|
+
readonly status: 'unavailable';
|
|
57
|
+
readonly root: string;
|
|
58
|
+
readonly reason: string;
|
|
59
|
+
} | {
|
|
60
|
+
readonly status: 'available';
|
|
61
|
+
readonly root: string;
|
|
62
|
+
readonly coverage: {
|
|
63
|
+
readonly saved: number;
|
|
64
|
+
readonly rejected: number;
|
|
65
|
+
readonly latest_recorded_at: string | null;
|
|
66
|
+
readonly possibly_stalled: boolean;
|
|
67
|
+
};
|
|
68
|
+
readonly sections: Readonly<Record<JudgmentValueProofReviewSection, readonly JudgmentValueProofReviewItem[]>>;
|
|
69
|
+
readonly delegation_map: JudgmentDelegationMap;
|
|
70
|
+
readonly rejected: readonly JudgmentValueProofJournalRejection[];
|
|
71
|
+
};
|
|
72
|
+
/** Whether Brainbase currently proceeds on a kind of judgment, is being checked, or asks the owner. */
|
|
73
|
+
export type JudgmentDelegationState = 'delegated' | 'verifying' | 'returned';
|
|
74
|
+
/** Rows are kinds when recorded; otherwise the reason code, which is not a kind and is shown apart. */
|
|
75
|
+
export type JudgmentDelegationRowSource = 'judgment_kind' | 'reason_code' | 'unrecorded';
|
|
76
|
+
export type JudgmentDelegationStateBasis = {
|
|
77
|
+
readonly reason: 'latest_judgment_returned';
|
|
78
|
+
readonly at: string;
|
|
79
|
+
} | {
|
|
80
|
+
readonly reason: 'latest_feedback';
|
|
81
|
+
readonly status: JudgmentValueProofFeedbackStatus;
|
|
82
|
+
readonly target_layer: JudgmentValueProofFeedbackLayer | null;
|
|
83
|
+
readonly at: string;
|
|
84
|
+
} | {
|
|
85
|
+
readonly reason: 'no_feedback';
|
|
86
|
+
};
|
|
87
|
+
export interface JudgmentDelegationItemRef {
|
|
88
|
+
readonly intent_id: string;
|
|
89
|
+
readonly decision_attempt_id: string;
|
|
90
|
+
readonly row_key: string;
|
|
91
|
+
}
|
|
92
|
+
export interface JudgmentDelegationRow {
|
|
93
|
+
readonly key: string;
|
|
94
|
+
readonly source: JudgmentDelegationRowSource;
|
|
95
|
+
/** Kind label or reason code; null for judgments that recorded neither. */
|
|
96
|
+
readonly label: string | null;
|
|
97
|
+
readonly state: JudgmentDelegationState;
|
|
98
|
+
readonly state_basis: JudgmentDelegationStateBasis;
|
|
99
|
+
readonly counts: {
|
|
100
|
+
readonly continued: number;
|
|
101
|
+
readonly returned: number;
|
|
102
|
+
readonly rated: number;
|
|
103
|
+
readonly by_feedback: Readonly<Record<JudgmentValueProofFeedbackStatus, number>>;
|
|
104
|
+
readonly corrected_or_reverted: number;
|
|
105
|
+
readonly inherited: number;
|
|
106
|
+
};
|
|
107
|
+
readonly latest_recorded_at: string;
|
|
108
|
+
/** Newest first. */
|
|
109
|
+
readonly items: readonly JudgmentDelegationItemRef[];
|
|
110
|
+
}
|
|
111
|
+
export interface JudgmentDelegationMap {
|
|
112
|
+
readonly judged: number;
|
|
113
|
+
readonly kind_recorded: number;
|
|
114
|
+
readonly rated: number;
|
|
115
|
+
/** Kind rows first, then reason-code rows, then the unrecorded row. */
|
|
116
|
+
readonly rows: readonly JudgmentDelegationRow[];
|
|
117
|
+
/** Continued without asking, then corrected or reverted by the owner (P14). */
|
|
118
|
+
readonly corrected_after_continue: readonly JudgmentDelegationItemRef[];
|
|
119
|
+
/** Continued without asking after the owner asked to be asked for that row. */
|
|
120
|
+
readonly continued_after_ask: readonly JudgmentDelegationItemRef[];
|
|
121
|
+
}
|
|
122
|
+
export declare function defaultJudgmentJournalRoot(dataDir?: string): string;
|
|
123
|
+
/**
|
|
124
|
+
* Reads saved judgment value proofs from `<root>/*.value-proof.json` and
|
|
125
|
+
* `<root>/<session>/*.value-proof.json`. The journal is read-only here.
|
|
126
|
+
*/
|
|
127
|
+
export declare function readJudgmentValueProofJournal(options?: {
|
|
128
|
+
readonly root?: string;
|
|
129
|
+
}): Promise<JudgmentValueProofJournalRead>;
|
|
130
|
+
export declare function classifyJudgmentValueProof(proof: JudgmentValueProof): JudgmentValueProofReviewSection;
|
|
131
|
+
/** Reads all recorded feedback in append order. A missing file means no feedback has been recorded. */
|
|
132
|
+
export declare function readJudgmentValueProofFeedback(options?: {
|
|
133
|
+
readonly dataDir?: string;
|
|
134
|
+
}): Promise<readonly JudgmentValueProofFeedbackRecord[]>;
|
|
135
|
+
/**
|
|
136
|
+
* Appends one owner feedback record without touching the judgment journal.
|
|
137
|
+
* Re-sending the same attempt, status and summary returns the existing record.
|
|
138
|
+
*/
|
|
139
|
+
export declare function recordJudgmentValueProofFeedback(input: JudgmentValueProofFeedbackInput): Promise<{
|
|
140
|
+
readonly record: JudgmentValueProofFeedbackRecord;
|
|
141
|
+
readonly created: boolean;
|
|
142
|
+
}>;
|
|
143
|
+
/** Returns the proof with its latest owner feedback applied, plus the feedback history for that attempt. */
|
|
144
|
+
export declare function applyJudgmentValueProofFeedback(proof: JudgmentValueProof, records: readonly JudgmentValueProofFeedbackRecord[]): {
|
|
145
|
+
readonly proof: JudgmentValueProof;
|
|
146
|
+
readonly history: readonly JudgmentValueProofFeedbackRecord[];
|
|
147
|
+
};
|
|
148
|
+
export declare function buildJudgmentValueProofReviewHome(journal: JudgmentValueProofJournalRead, feedback: readonly JudgmentValueProofFeedbackRecord[], options?: {
|
|
149
|
+
readonly now?: Date;
|
|
150
|
+
readonly staleAfterMs?: number;
|
|
151
|
+
}): JudgmentValueProofReviewHome;
|
|
152
|
+
/**
|
|
153
|
+
* Groups reviewable judgments by kind and decides, per kind, whether Brainbase is trusted to
|
|
154
|
+
* proceed, is still being checked, or returns the judgment to the owner. Deterministic: the state
|
|
155
|
+
* follows only the newest judgment and the newest owner feedback in the row.
|
|
156
|
+
*/
|
|
157
|
+
export declare function buildJudgmentDelegationMap(items: readonly JudgmentValueProofReviewItem[], feedback: readonly JudgmentValueProofFeedbackRecord[]): JudgmentDelegationMap;
|
|
158
|
+
export interface JudgmentValueProofFeedbackSummary {
|
|
159
|
+
/** Decisions with at least one feedback record; each counts once, by its latest feedback. */
|
|
160
|
+
readonly rated: number;
|
|
161
|
+
readonly by_status: Readonly<Record<JudgmentValueProofFeedbackStatus, number>>;
|
|
162
|
+
/** Latest `corrected` and `next_time_ask` feedback by the layer they ask to change. */
|
|
163
|
+
readonly by_layer: Readonly<Record<JudgmentValueProofFeedbackLayer | 'unrecorded', number>>;
|
|
164
|
+
}
|
|
165
|
+
/** Counts the latest feedback per decision, for deciding where revisions should live. */
|
|
166
|
+
export declare function summarizeJudgmentValueProofFeedback(records: readonly JudgmentValueProofFeedbackRecord[]): JudgmentValueProofFeedbackSummary;
|