@skill-harness/adapters 0.17.0 → 0.18.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 (118) hide show
  1. package/dist/index.d.ts +0 -30
  2. package/dist/index.js +0 -30
  3. package/dist/pi.js +21 -133
  4. package/package.json +2 -3
  5. package/dist/archive-access.d.ts +0 -58
  6. package/dist/archive-access.js +0 -61
  7. package/dist/archive-checkpoint.d.ts +0 -47
  8. package/dist/archive-checkpoint.js +0 -116
  9. package/dist/archive-facts.d.ts +0 -19
  10. package/dist/archive-facts.js +0 -20
  11. package/dist/archive-observer.d.ts +0 -21
  12. package/dist/archive-observer.js +0 -79
  13. package/dist/archive-policy.d.ts +0 -107
  14. package/dist/archive-policy.js +0 -135
  15. package/dist/archive-read-capability.d.ts +0 -49
  16. package/dist/archive-read-capability.js +0 -45
  17. package/dist/archive-retention-policy.d.ts +0 -52
  18. package/dist/archive-retention-policy.js +0 -49
  19. package/dist/archived-work.d.ts +0 -45
  20. package/dist/archived-work.js +0 -78
  21. package/dist/blind-intervention.d.ts +0 -35
  22. package/dist/blind-intervention.js +0 -218
  23. package/dist/codex-diagnostic-model.d.ts +0 -14
  24. package/dist/codex-diagnostic-model.js +0 -39
  25. package/dist/codex-host-observer.d.ts +0 -111
  26. package/dist/codex-host-observer.js +0 -309
  27. package/dist/codex-https.d.ts +0 -7
  28. package/dist/codex-https.js +0 -221
  29. package/dist/codex-model-profile.d.ts +0 -38
  30. package/dist/codex-model-profile.js +0 -54
  31. package/dist/codex-producer-ipc.d.ts +0 -55
  32. package/dist/codex-producer-ipc.js +0 -67
  33. package/dist/codex-sdk-transport.d.ts +0 -50
  34. package/dist/codex-sdk-transport.js +0 -294
  35. package/dist/codex-subscription.d.ts +0 -114
  36. package/dist/codex-subscription.js +0 -268
  37. package/dist/evidence-archive.d.ts +0 -65
  38. package/dist/evidence-archive.js +0 -225
  39. package/dist/execution-projection-schema.d.ts +0 -10
  40. package/dist/execution-projection-schema.js +0 -30
  41. package/dist/execution-retention-archive.d.ts +0 -69
  42. package/dist/execution-retention-archive.js +0 -154
  43. package/dist/generated/retention-v2-contract.d.ts +0 -72
  44. package/dist/generated/retention-v2-contract.js +0 -105
  45. package/dist/generated/retention-v2-json.d.ts +0 -24
  46. package/dist/generated/retention-v2-json.js +0 -268
  47. package/dist/generated/retention-v2-native-json.d.ts +0 -2
  48. package/dist/generated/retention-v2-native-json.js +0 -33
  49. package/dist/generated/retention-v2-native.d.ts +0 -58
  50. package/dist/generated/retention-v2-native.js +0 -155
  51. package/dist/generated/retention-v2-pin.d.ts +0 -2
  52. package/dist/generated/retention-v2-pin.js +0 -4
  53. package/dist/generated/retention-v2-types.d.ts +0 -49
  54. package/dist/generated/retention-v2-types.js +0 -2
  55. package/dist/generated/retention-v2-work-types.d.ts +0 -260
  56. package/dist/generated/retention-v2-work-types.js +0 -13
  57. package/dist/generated/work-v4/execution-id.d.ts +0 -5
  58. package/dist/generated/work-v4/execution-id.js +0 -14
  59. package/dist/generated/work-v4/json.d.ts +0 -24
  60. package/dist/generated/work-v4/json.js +0 -268
  61. package/dist/generated/work-v4/occurrences.d.ts +0 -226
  62. package/dist/generated/work-v4/occurrences.js +0 -116
  63. package/dist/generated/work-v4/pin.d.ts +0 -1
  64. package/dist/generated/work-v4/pin.js +0 -3
  65. package/dist/generated/work-v4/projection.d.ts +0 -294
  66. package/dist/generated/work-v4/projection.js +0 -238
  67. package/dist/generated/work-v4/reader.d.ts +0 -24
  68. package/dist/generated/work-v4/reader.js +0 -109
  69. package/dist/generated/work-v4/snapshot.d.ts +0 -28
  70. package/dist/generated/work-v4/snapshot.js +0 -268
  71. package/dist/generated/work-v4/types.d.ts +0 -260
  72. package/dist/generated/work-v4/types.js +0 -13
  73. package/dist/generated/work-v4/validation.d.ts +0 -13
  74. package/dist/generated/work-v4/validation.js +0 -227
  75. package/dist/installed-review-session.d.ts +0 -28
  76. package/dist/installed-review-session.js +0 -166
  77. package/dist/intervention-run.d.ts +0 -403
  78. package/dist/intervention-run.js +0 -169
  79. package/dist/learning-case.d.ts +0 -12
  80. package/dist/learning-case.js +0 -15
  81. package/dist/learning-journal.d.ts +0 -18
  82. package/dist/learning-journal.js +0 -256
  83. package/dist/learning-lifecycle.d.ts +0 -28
  84. package/dist/learning-lifecycle.js +0 -66
  85. package/dist/learning-trust-setup.d.ts +0 -64
  86. package/dist/learning-trust-setup.js +0 -55
  87. package/dist/learning-workspace.d.ts +0 -1084
  88. package/dist/learning-workspace.js +0 -705
  89. package/dist/principal-payload-port.d.ts +0 -25
  90. package/dist/principal-payload-port.js +0 -40
  91. package/dist/producer-product.d.ts +0 -70
  92. package/dist/producer-product.js +0 -186
  93. package/dist/producer-review.d.ts +0 -53
  94. package/dist/producer-review.js +0 -207
  95. package/dist/prompt-capture-extension.d.ts +0 -10
  96. package/dist/prompt-capture-extension.js +0 -26
  97. package/dist/prompt-provenance.d.ts +0 -22
  98. package/dist/prompt-provenance.js +0 -146
  99. package/dist/reviewed-archive-export.d.ts +0 -42
  100. package/dist/reviewed-archive-export.js +0 -78
  101. package/dist/session-observation.d.ts +0 -50
  102. package/dist/session-observation.js +0 -186
  103. package/dist/session-retention.d.ts +0 -48
  104. package/dist/session-retention.js +0 -121
  105. package/dist/trust-lifecycle.d.ts +0 -152
  106. package/dist/trust-lifecycle.js +0 -209
  107. package/dist/weekly-investigation.d.ts +0 -237
  108. package/dist/weekly-investigation.js +0 -330
  109. package/dist/work-candidates.d.ts +0 -29
  110. package/dist/work-candidates.js +0 -78
  111. package/dist/work-case-archive.d.ts +0 -25
  112. package/dist/work-case-archive.js +0 -63
  113. package/dist/work-case-review.d.ts +0 -45
  114. package/dist/work-case-review.js +0 -220
  115. package/dist/work-signal-cases.d.ts +0 -15
  116. package/dist/work-signal-cases.js +0 -54
  117. package/dist/work-signal-observation.d.ts +0 -23
  118. package/dist/work-signal-observation.js +0 -89
@@ -1,121 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import { resolve } from 'node:path';
3
- import { learningFile, learningHash, learningCopy } from './learning-journal.js';
4
- import { retainArchiveSource, readArchiveSource } from './evidence-archive.js';
5
- import { observePiSession, observeSessionLedger, sessionText } from './session-observation.js';
6
- const captured = new WeakMap();
7
- const sha = (bytes) => createHash('sha256').update(bytes).digest('hex');
8
- function checkedSelections(input) {
9
- if (!Array.isArray(input) || input.length < 1 || input.length > 16)
10
- throw Error('select 1–16 explicit session sources');
11
- const seen = new Set(), executions = new Set();
12
- let parents = 0, ledgers = 0;
13
- for (const s of input) {
14
- if (!s || typeof s !== 'object' || Object.keys(s).some(k => !['kind', 'path', 'executionId'].includes(k)))
15
- throw Error('closed source selection required');
16
- if (!['parent', 'child', 'ledger', 'feedback', 'artifact'].includes(s.kind) || typeof s.path !== 'string' || resolve(s.path) !== s.path)
17
- throw Error('explicit absolute source path required');
18
- if (seen.has(s.path))
19
- throw Error('duplicate session source');
20
- seen.add(s.path);
21
- if (s.kind === 'parent')
22
- parents++;
23
- if (s.kind === 'ledger')
24
- ledgers++;
25
- if (s.executionId !== undefined) {
26
- if (s.kind !== 'child' || !/^exec:[0-9a-f-]{36}$/i.test(s.executionId) || executions.has(s.executionId))
27
- throw Error('unique child execution id required');
28
- executions.add(s.executionId);
29
- }
30
- }
31
- if (parents !== 1 || ledgers > 1)
32
- throw Error('exactly one parent and at most one ledger required');
33
- }
34
- function projectSession(selections, buffers) {
35
- const parent = observePiSession(buffers[selections.findIndex(s => s.kind === 'parent')]);
36
- const children = selections.flatMap((s, i) => s.kind === 'child' ? [{ source: i, executionId: s.executionId ?? null, session: observePiSession(buffers[i]) }] : []);
37
- if (new Set([parent.sessionId, ...children.map(c => c.session.sessionId)]).size !== children.length + 1)
38
- throw Error('duplicate parent/child session id');
39
- const ledger = selections.findIndex(s => s.kind === 'ledger'), attempts = ledger < 0 ? [] : observeSessionLedger(buffers[ledger]);
40
- for (const child of children)
41
- if (child.executionId && !attempts.some(a => a.executionId === child.executionId))
42
- throw Error('selected child execution absent from ledger');
43
- const gaps = [...parent.gaps, 'No quality, acceptance, calibrated learning or adoption is inferred from this import.'];
44
- for (const child of children)
45
- gaps.push(...child.session.gaps.map(g => 'Child source ' + (child.source + 1) + ' (' + child.session.sessionId + '): ' + g));
46
- if (ledger < 0)
47
- gaps.push('No delegation ledger selected.');
48
- else
49
- gaps.push('Ledger/session association is operator-selected, not authenticated; ledger may include other sessions.');
50
- if (attempts.length > children.filter(c => c.executionId).length)
51
- gaps.push('Child transcript coverage incomplete; no combined token total is claimed.');
52
- if (children.length)
53
- gaps.push('Child execution mappings are explicit operator declarations, not proof of parentage. Each transcript has separate usage.');
54
- if (!selections.some(s => s.kind === 'feedback'))
55
- gaps.push('External feedback not supplied; user messages remain available for review.');
56
- if (!selections.some(s => s.kind === 'artifact'))
57
- gaps.push('No final artifact or source snapshot supplied.');
58
- return { parent, children, attempts, gaps };
59
- }
60
- /** Explicit local selection only. Does not scan session directories, follow links, or contact workers. */
61
- export function prepareSessionImport(selections) {
62
- checkedSelections(selections);
63
- const buffers = selections.map(s => learningFile(s.path, 8 * 1024 * 1024));
64
- if (buffers.reduce((n, b) => n + b.length, 0) > 32 * 1024 * 1024)
65
- throw Error('session selection exceeds 32 MiB');
66
- const sources = selections.map((s, i) => ({ ...s, executionId: s.executionId ?? null, sha256: sha(buffers[i]), bytes: buffers[i].length }));
67
- const { parent, children, attempts, gaps } = projectSession(selections, buffers);
68
- const digest = learningHash({ version: 'session-selection-v1', sources });
69
- const preview = { version: 'session-import-preview-v1', digest, sources, parent, children, attempts, gaps, acceptance: 'not-assessed' };
70
- captured.set(preview, { preview: learningCopy(preview), buffers });
71
- return preview;
72
- }
73
- export function retainSessionImport(root, preview, expectedDigest) {
74
- const c = captured.get(preview);
75
- if (!c || learningHash(c.preview) !== learningHash(preview) || expectedDigest !== c.preview.digest)
76
- throw Error('exact preview digest required; changed or forged session import');
77
- for (const s of c.preview.sources)
78
- if (sha(learningFile(s.path, 8 * 1024 * 1024)) !== s.sha256)
79
- throw Error('session source changed since preview; prepare again');
80
- const sources = c.preview.sources.map((s, i) => {
81
- const parser = s.kind === 'parent' || s.kind === 'child' ? 'pi-session-jsonl' : s.kind === 'ledger' ? 'pi-daddy-session-ledger' : 'session-evidence';
82
- const r = retainArchiveSource(root, { sourceId: 'session-' + s.sha256, parser: { id: parser, version: '1' }, retention: 'exact', bytes: c.buffers[i] });
83
- return { ...s, manifestId: r.manifestId };
84
- });
85
- const record = { version: 'retrospective-session-v1', selectionDigest: preview.digest, sources };
86
- return retainArchiveSource(root, { sourceId: 'retrospective-' + preview.digest, parser: { id: 'retrospective-session', version: '1' }, retention: 'exact', bytes: Buffer.from(JSON.stringify(record)) }).manifestId;
87
- }
88
- export function readRetainedSession(root, manifestId) {
89
- const selected = readArchiveSource(root, manifestId);
90
- if (selected.status !== 'available' || selected.reference.retention !== 'exact' || selected.reference.parser.id !== 'retrospective-session' || selected.reference.parser.version !== '1')
91
- throw Error('retained session unavailable or unsupported');
92
- const record = JSON.parse(sessionText(selected.bytes));
93
- if (!record || record.version !== 'retrospective-session-v1' || Object.keys(record).sort().join() !== 'selectionDigest,sources,version' || !Array.isArray(record.sources))
94
- throw Error('invalid retained session');
95
- checkedSelections(record.sources.map(s => ({ kind: s.kind, path: s.path, ...(s.executionId === null ? {} : { executionId: s.executionId }) })));
96
- const sources = record.sources.map(s => {
97
- if (Object.keys(s).sort().join() !== 'bytes,executionId,kind,manifestId,path,sha256')
98
- throw Error('invalid retained session source');
99
- const r = readArchiveSource(root, s.manifestId);
100
- if (r.status !== 'available' || r.reference.retention !== 'exact' || r.reference.sha256 !== s.sha256 || r.bytes.length !== s.bytes)
101
- throw Error('retained session source missing or changed');
102
- return { selection: s, bytes: r.bytes };
103
- });
104
- if (sources.reduce((n, s) => n + s.bytes.length, 0) > 32 * 1024 * 1024)
105
- throw Error('session selection exceeds 32 MiB');
106
- const plain = record.sources.map(({ manifestId, ...s }) => s);
107
- if (learningHash({ version: 'session-selection-v1', sources: plain }) !== record.selectionDigest)
108
- throw Error('retained session selection mismatch');
109
- const projection = projectSession(record.sources.map(s => ({ kind: s.kind, path: s.path, ...(s.executionId === null ? {} : { executionId: s.executionId }) })), sources.map(s => s.bytes));
110
- return { version: record.version, manifestId, selectionDigest: record.selectionDigest, sources: record.sources, ...projection, acceptance: 'not-assessed' };
111
- }
112
- export function readRetainedSessionSource(root, manifestId, index) {
113
- const session = readRetainedSession(root, manifestId), source = session.sources[index];
114
- if (!Number.isSafeInteger(index) || !source)
115
- throw Error('select a listed session source');
116
- const result = readArchiveSource(root, source.manifestId);
117
- if (result.status !== 'available')
118
- throw Error('session source unavailable');
119
- return result.bytes;
120
- }
121
- //# sourceMappingURL=session-retention.js.map
@@ -1,152 +0,0 @@
1
- import { type CalibrationComponent, type CalibrationPrediction, type ExposurePolicy } from '@skill-harness/core';
2
- import { type LearningCaseReference } from './learning-case.js';
3
- export interface TrustLifecycleInput {
4
- archiveRoot: string;
5
- component: CalibrationComponent;
6
- seed: string;
7
- maxUnflagged: number;
8
- cohort: {
9
- incidentId: string;
10
- manifestId: string;
11
- flagged: boolean;
12
- split: 'calibration' | 'heldout' | 'tuning';
13
- }[];
14
- exposure: ExposurePolicy | null;
15
- }
16
- export interface TrustReferenceOutcome {
17
- kind: 'prediction' | 'unflagged';
18
- targetId: string;
19
- value: boolean;
20
- evidenceManifestId: string;
21
- referenceId: string;
22
- }
23
- export declare const trustPolicyDigest: (input: TrustLifecycleInput) => string;
24
- export declare const trustOutcomeDigest: (outcome: TrustReferenceOutcome) => string;
25
- export declare function createTrustLifecycle(directory: string, input: TrustLifecycleInput, authorizedPolicyDigests: readonly string[]): {
26
- inspect: (now: number) => {
27
- policyId: string;
28
- component: CalibrationComponent;
29
- calibration: {
30
- version: "factory-calibration-v1";
31
- reports: import("@skill-harness/core").CalibrationReport[];
32
- excludedTuning: number;
33
- referenceBasis: "independently-supplied-host-context";
34
- advisoryOnly: true;
35
- };
36
- sampledIncidentIds: string[];
37
- unflagged: {
38
- sampled: number;
39
- resolved: number;
40
- misses: number;
41
- unresolved: number;
42
- conflicted: number;
43
- };
44
- attentionUsed: number;
45
- retired: boolean;
46
- exposures: {
47
- mode: "ask" | "silent" | "retire";
48
- reason: string;
49
- id: string;
50
- }[];
51
- tip: string;
52
- grantExpansion: false;
53
- };
54
- configuration: () => TrustLifecycleInput;
55
- previewExposure: (now: number) => {
56
- mode: "silent" | "ask" | "retire";
57
- reason: string;
58
- advisoryOnly: true;
59
- } | {
60
- mode: "retire";
61
- reason: string;
62
- } | {
63
- mode: "silent";
64
- reason: string;
65
- };
66
- history: () => import("./learning-journal.js").LearningEvent[];
67
- previewCaseOutcome: (predictionId: string, reference: LearningCaseReference) => {
68
- outcome: TrustReferenceOutcome;
69
- caseReference: LearningCaseReference;
70
- digest: string;
71
- tip: string;
72
- };
73
- linkCaseOutcome(predictionId: string, reference: LearningCaseReference, authorizedDigests: readonly string[], referenceAuthor?: string): void;
74
- predict(p: CalibrationPrediction): void;
75
- correct(prior: string, p: CalibrationPrediction, reason: string): void;
76
- outcome(value: TrustReferenceOutcome, authorizedReferenceDigests: readonly string[], referenceAuthor?: string): void;
77
- expose(id: string, now: number): {
78
- replayed: boolean;
79
- mode: "ask" | "silent" | "retire";
80
- reason: string;
81
- } | {
82
- replayed: boolean;
83
- mode: "silent" | "ask" | "retire";
84
- reason: string;
85
- advisoryOnly: true;
86
- };
87
- };
88
- /** Existing calibration is recomputed from durable scoped predictions and independently permitted
89
- * retained labels. Applied exposure is an attention reservation, not proof a human saw a question. */
90
- export declare function openTrustLifecycle(directory: string): {
91
- inspect: (now: number) => {
92
- policyId: string;
93
- component: CalibrationComponent;
94
- calibration: {
95
- version: "factory-calibration-v1";
96
- reports: import("@skill-harness/core").CalibrationReport[];
97
- excludedTuning: number;
98
- referenceBasis: "independently-supplied-host-context";
99
- advisoryOnly: true;
100
- };
101
- sampledIncidentIds: string[];
102
- unflagged: {
103
- sampled: number;
104
- resolved: number;
105
- misses: number;
106
- unresolved: number;
107
- conflicted: number;
108
- };
109
- attentionUsed: number;
110
- retired: boolean;
111
- exposures: {
112
- mode: "ask" | "silent" | "retire";
113
- reason: string;
114
- id: string;
115
- }[];
116
- tip: string;
117
- grantExpansion: false;
118
- };
119
- configuration: () => TrustLifecycleInput;
120
- previewExposure: (now: number) => {
121
- mode: "silent" | "ask" | "retire";
122
- reason: string;
123
- advisoryOnly: true;
124
- } | {
125
- mode: "retire";
126
- reason: string;
127
- } | {
128
- mode: "silent";
129
- reason: string;
130
- };
131
- history: () => import("./learning-journal.js").LearningEvent[];
132
- previewCaseOutcome: (predictionId: string, reference: LearningCaseReference) => {
133
- outcome: TrustReferenceOutcome;
134
- caseReference: LearningCaseReference;
135
- digest: string;
136
- tip: string;
137
- };
138
- linkCaseOutcome(predictionId: string, reference: LearningCaseReference, authorizedDigests: readonly string[], referenceAuthor?: string): void;
139
- predict(p: CalibrationPrediction): void;
140
- correct(prior: string, p: CalibrationPrediction, reason: string): void;
141
- outcome(value: TrustReferenceOutcome, authorizedReferenceDigests: readonly string[], referenceAuthor?: string): void;
142
- expose(id: string, now: number): {
143
- replayed: boolean;
144
- mode: "ask" | "silent" | "retire";
145
- reason: string;
146
- } | {
147
- replayed: boolean;
148
- mode: "silent" | "ask" | "retire";
149
- reason: string;
150
- advisoryOnly: true;
151
- };
152
- };
@@ -1,209 +0,0 @@
1
- import { calibratePredictions, recommendExposure } from '@skill-harness/core';
2
- import { isAbsolute } from 'node:path';
3
- import { readArchiveSource } from './evidence-archive.js';
4
- import { learningCopy, learningHash, learningJournal, registerLearningStore, verifyLearningStore } from './learning-journal.js';
5
- import { readLearningCase } from './learning-case.js';
6
- export const trustPolicyDigest = (input) => learningHash({ version: 'trust-lifecycle-v1', input });
7
- export const trustOutcomeDigest = (outcome) => learningHash({ version: 'trust-reference-v1', outcome });
8
- function evidence(root, id) { const result = readArchiveSource(root, id); if (result.status !== 'available' || !['exact', 'redacted'].includes(result.reference.retention))
9
- throw Error('independent retained evidence unavailable'); return result; }
10
- const text = (v) => typeof v === 'string' && v.length > 0 && v.length <= 512 && !/[\u0000-\u001f\u007f]/.test(v);
11
- function validate(input) {
12
- if (!isAbsolute(input.archiveRoot) || Object.keys(input).sort().join() !== 'archiveRoot,cohort,component,exposure,maxUnflagged,seed' || !/^([a-f0-9]{64})$/.test(input.seed) || !Number.isSafeInteger(input.maxUnflagged) || input.maxUnflagged < 0 || input.maxUnflagged > 32 || !Array.isArray(input.cohort) || !input.cohort.length || input.cohort.length > 1024 || new Set(input.cohort.map(c => c.incidentId)).size !== input.cohort.length)
13
- throw Error('invalid frozen trust cohort');
14
- for (const c of input.cohort) {
15
- if (Object.keys(c).sort().join() !== 'flagged,incidentId,manifestId,split' || !text(c.incidentId) || typeof c.flagged !== 'boolean' || !['calibration', 'heldout', 'tuning'].includes(c.split))
16
- throw Error('invalid cohort row');
17
- evidence(input.archiveRoot, c.manifestId);
18
- }
19
- const dummy = { id: 'validation', incidentId: 'validation', component: input.component, kind: input.component.kind === 'detector' ? 'positive' : 'approval', split: 'calibration' };
20
- calibratePredictions([dummy]);
21
- if (input.exposure) {
22
- if (learningHash(input.exposure.component) !== learningHash(input.component))
23
- throw Error('policy component scope mismatch');
24
- const report = calibratePredictions([{ ...dummy, kind: input.exposure.kind, split: input.exposure.split }]).reports[0];
25
- recommendExposure(report, input.exposure, 0);
26
- }
27
- }
28
- export function createTrustLifecycle(directory, input, authorizedPolicyDigests) {
29
- const safe = learningCopy(input);
30
- validate(safe);
31
- const policyId = trustPolicyDigest(safe);
32
- if (!authorizedPolicyDigests.includes(policyId))
33
- throw Error('independent predeclared policy authority required');
34
- const sampledIncidentIds = safe.cohort.filter(c => !c.flagged && c.split !== 'tuning').sort((a, b) => learningHash([safe.seed, a.incidentId]).localeCompare(learningHash([safe.seed, b.incidentId]))).slice(0, safe.maxUnflagged).map(c => c.incidentId);
35
- const initial = { type: 'initial', kind: 'trust-lifecycle-v1', input: safe, policyId, sampledIncidentIds };
36
- registerLearningStore(safe.archiveRoot, 'trust', policyId, directory, learningHash(initial));
37
- try {
38
- learningJournal(directory, initial);
39
- }
40
- catch (e) {
41
- if (e.code !== 'EEXIST')
42
- throw e;
43
- const old = learningJournal(directory).read()[0].value;
44
- if (learningHash(old) !== learningHash(initial))
45
- throw Error('trust policy already predeclared');
46
- }
47
- return openTrustLifecycle(directory);
48
- }
49
- /** Existing calibration is recomputed from durable scoped predictions and independently permitted
50
- * retained labels. Applied exposure is an attention reservation, not proof a human saw a question. */
51
- export function openTrustLifecycle(directory) {
52
- const journal = learningJournal(directory), initial = journal.read()[0].value;
53
- if (initial.kind !== 'trust-lifecycle-v1' || initial.type !== 'initial')
54
- throw Error('wrong trust journal');
55
- const input = initial.input, sampledIncidentIds = initial.sampledIncidentIds;
56
- validate(input);
57
- const replay = () => {
58
- verifyLearningStore(input.archiveRoot, 'trust', String(initial.policyId), directory, learningHash(initial));
59
- const history = journal.read(), predictions = new Map(), allIds = new Set(), outcomes = new Map(), caseLinks = new Map(), exposures = new Map();
60
- let retired = false, lastExposureAt = 0;
61
- for (const { value: v } of history.slice(1)) {
62
- if (v.type === 'prediction' || v.type === 'correction') {
63
- const p = v.prediction;
64
- calibratePredictions([p]);
65
- if (allIds.has(p.id))
66
- throw Error('duplicate prediction identity');
67
- const c = input.cohort.find(c => c.incidentId === p.incidentId);
68
- if (!c?.flagged || c.split !== p.split || learningHash(p.component) !== learningHash(input.component))
69
- throw Error('prediction scope mismatch');
70
- if (v.type === 'correction') {
71
- const old = predictions.get(String(v.prior));
72
- if (!old || old.incidentId !== p.incidentId)
73
- throw Error('stale prediction correction');
74
- predictions.delete(String(v.prior));
75
- }
76
- predictions.set(p.id, p);
77
- allIds.add(p.id);
78
- }
79
- else if (v.type === 'outcome') {
80
- const r = v.outcome;
81
- if (outcomes.has(r.referenceId))
82
- throw Error('duplicate reference identity');
83
- outcomes.set(r.referenceId, r);
84
- if (v.caseReference)
85
- caseLinks.set(r.referenceId, v.caseReference);
86
- }
87
- else if (v.type === 'exposure') {
88
- const id = String(v.id), result = v.result;
89
- if (typeof v.now !== 'number' || !Number.isFinite(v.now) || v.now < lastExposureAt || exposures.has(id) || !['ask', 'silent', 'retire'].includes(result.mode))
90
- throw Error('invalid exposure history');
91
- lastExposureAt = v.now;
92
- exposures.set(id, result);
93
- retired ||= result.mode === 'retire';
94
- }
95
- else
96
- throw Error('unknown trust history event');
97
- }
98
- return { history, predictions, allIds, outcomes, caseLinks, exposures, retired, lastExposureAt, tip: history.at(-1).id };
99
- };
100
- replay();
101
- const inspect = (now) => {
102
- if (!Number.isFinite(now) || now < 0)
103
- throw Error('valid policy clock required');
104
- const s = replay(), labels = [];
105
- for (const r of s.outcomes.values()) {
106
- evidence(input.archiveRoot, r.evidenceManifestId);
107
- const p = s.predictions.get(r.targetId), link = s.caseLinks.get(r.referenceId);
108
- if (link && !readLearningCase(input.archiveRoot, link).matched)
109
- continue;
110
- if (r.kind === 'prediction' && p)
111
- labels.push({ ...p, id: r.referenceId, correct: r.value });
112
- }
113
- for (const p of s.predictions.values())
114
- evidence(input.archiveRoot, input.cohort.find(c => c.incidentId === p.incidentId).manifestId);
115
- const calibration = calibratePredictions([...s.predictions.values()], { outcomes: labels });
116
- let misses = 0, resolved = 0, conflicted = 0;
117
- for (const id of sampledIncidentIds) {
118
- evidence(input.archiveRoot, input.cohort.find(c => c.incidentId === id).manifestId);
119
- const values = new Set([...s.outcomes.values()].filter(r => r.kind === 'unflagged' && r.targetId === id).map(r => r.value));
120
- if (values.size === 1) {
121
- resolved++;
122
- if (values.has(true))
123
- misses++;
124
- }
125
- else if (values.size > 1)
126
- conflicted++;
127
- }
128
- return { policyId: String(initial.policyId), component: learningCopy(input.component), calibration, sampledIncidentIds: [...sampledIncidentIds], unflagged: { sampled: sampledIncidentIds.length, resolved, misses, unresolved: sampledIncidentIds.length - resolved, conflicted }, attentionUsed: [...s.exposures.values()].filter(e => e.mode === 'ask').length, retired: s.retired, exposures: [...s.exposures].map(([id, result]) => ({ id, ...result })), tip: s.tip, grantExpansion: false };
129
- };
130
- const prediction = (p) => { const copy = learningCopy(p); calibratePredictions([copy]); const row = input.cohort.find(c => c.incidentId === copy.incidentId); if (!row?.flagged || row.split !== copy.split || learningHash(copy.component) !== learningHash(input.component))
131
- throw Error('prediction scope mismatch'); evidence(input.archiveRoot, row.manifestId); return copy; };
132
- const previewCaseOutcome = (predictionId, reference) => {
133
- const ref = learningCopy(reference), s = replay(), p = s.predictions.get(predictionId), row = p && input.cohort.find(c => c.incidentId === p.incidentId), resolved = readLearningCase(input.archiveRoot, ref);
134
- if (!p || p.kind !== 'positive' || row?.manifestId !== ref.manifestId || !resolved.matched || !['confirmed_defect', 'expected_behavior'].includes(resolved.current.disposition) || learningHash(resolved.candidate.detector) !== learningHash({ id: p.component.id, version: p.component.version, population: p.component.population }))
135
- throw Error('current independent case outcome scope required');
136
- const outcome = { kind: 'prediction', targetId: p.id, value: resolved.current.disposition === 'confirmed_defect', evidenceManifestId: ref.manifestId, referenceId: ref.decisionId };
137
- return { outcome, caseReference: ref, digest: learningHash({ outcome, caseReference: ref }), tip: s.tip };
138
- };
139
- const previewExposure = (now) => {
140
- const view = inspect(now), policy = input.exposure ? { ...input.exposure, attentionRemaining: Math.max(0, input.exposure.attentionRemaining - view.attentionUsed) } : null;
141
- const report = view.calibration.reports.find(r => policy && r.kind === policy.kind && r.split === policy.split);
142
- return view.retired ? { mode: 'retire', reason: 'previously-retired' } : report ? recommendExposure(report, policy, now) : { mode: 'silent', reason: policy ? 'insufficient-independent-evidence' : 'policy-unavailable' };
143
- };
144
- return { inspect, configuration: () => learningCopy(input), previewExposure, history: () => journal.read(), previewCaseOutcome,
145
- linkCaseOutcome(predictionId, reference, authorizedDigests, referenceAuthor) {
146
- if (referenceAuthor !== undefined && !text(referenceAuthor))
147
- throw Error('explicit reference author required');
148
- const preview = previewCaseOutcome(predictionId, reference);
149
- if (!authorizedDigests.includes(preview.digest))
150
- throw Error('independent exact reference authority required');
151
- const s = replay();
152
- if (s.tip !== preview.tip)
153
- throw Error('stale case outcome snapshot');
154
- const old = s.outcomes.get(preview.outcome.referenceId);
155
- if (old) {
156
- if (trustOutcomeDigest(old) !== trustOutcomeDigest(preview.outcome) || learningHash(s.caseLinks.get(old.referenceId) ?? null) !== learningHash(reference))
157
- throw Error('reference identity conflict');
158
- return;
159
- }
160
- journal.append(s.tip, { type: 'outcome', outcome: preview.outcome, caseReference: preview.caseReference, authorityDigest: preview.digest, ...(referenceAuthor === undefined ? {} : { referenceAuthor }) });
161
- },
162
- predict(p) { const safe = prediction(p), s = replay(); if (s.allIds.has(safe.id)) {
163
- if (learningHash(s.predictions.get(safe.id) ?? null) !== learningHash(safe))
164
- throw Error('prediction identity conflict');
165
- return;
166
- } journal.append(s.tip, { type: 'prediction', prediction: safe }); },
167
- correct(prior, p, reason) { const safe = prediction(p), s = replay(), old = s.predictions.get(prior); if (!old || old.incidentId !== safe.incidentId || s.allIds.has(safe.id) || !text(reason))
168
- throw Error('stale or invalid prediction correction'); journal.append(s.tip, { type: 'correction', prior, prediction: safe, reason }); },
169
- outcome(value, authorizedReferenceDigests, referenceAuthor) {
170
- if (referenceAuthor !== undefined && !text(referenceAuthor))
171
- throw Error('explicit reference author required');
172
- const r = learningCopy(value);
173
- if (Object.keys(r).sort().join() !== 'evidenceManifestId,kind,referenceId,targetId,value' || !['prediction', 'unflagged'].includes(r.kind) || !text(r.targetId) || !text(r.referenceId) || typeof r.value !== 'boolean')
174
- throw Error('invalid reference outcome');
175
- const digest = trustOutcomeDigest(r);
176
- if (!authorizedReferenceDigests.includes(digest))
177
- throw Error('independent exact reference authority required');
178
- evidence(input.archiveRoot, r.evidenceManifestId);
179
- const s = replay();
180
- if (r.kind === 'prediction' ? !s.predictions.has(r.targetId) : !sampledIncidentIds.includes(r.targetId))
181
- throw Error('outcome outside current prediction or frozen sample');
182
- const old = s.outcomes.get(r.referenceId);
183
- if (old) {
184
- if (trustOutcomeDigest(old) !== digest)
185
- throw Error('reference identity conflict');
186
- return;
187
- }
188
- journal.append(s.tip, { type: 'outcome', outcome: r, authorityDigest: digest, ...(referenceAuthor === undefined ? {} : { referenceAuthor }) });
189
- },
190
- expose(id, now) {
191
- if (!text(id))
192
- throw Error('exposure identity required');
193
- const s = replay(), existing = s.exposures.get(id);
194
- if (existing)
195
- return { ...learningCopy(existing), replayed: true };
196
- if (now < s.lastExposureAt)
197
- throw Error('policy clock moved backwards');
198
- const view = inspect(now);
199
- if (view.tip !== s.tip)
200
- throw Error('stale exposure snapshot');
201
- const policy = input.exposure ? { ...input.exposure, attentionRemaining: Math.max(0, input.exposure.attentionRemaining - view.attentionUsed) } : null;
202
- const report = view.calibration.reports.find(r => policy && r.kind === policy.kind && r.split === policy.split);
203
- const result = s.retired ? { mode: 'retire', reason: 'previously-retired' } : report ? recommendExposure(report, policy, now) : { mode: 'silent', reason: policy ? 'insufficient-independent-evidence' : 'policy-unavailable' };
204
- journal.append(s.tip, { type: 'exposure', id, now, result, policyId: initial.policyId, evidenceTip: s.tip });
205
- return { ...learningCopy(result), replayed: false };
206
- }
207
- };
208
- }
209
- //# sourceMappingURL=trust-lifecycle.js.map