@skill-harness/adapters 0.15.0 → 0.16.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/dist/blind-intervention.d.ts +6 -0
- package/dist/blind-intervention.js +9 -2
- package/dist/evidence-archive.d.ts +8 -0
- package/dist/evidence-archive.js +21 -17
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/learning-journal.d.ts +2 -2
- package/dist/learning-journal.js +1 -1
- package/dist/learning-trust-setup.d.ts +64 -0
- package/dist/learning-trust-setup.js +55 -0
- package/dist/learning-workspace.d.ts +930 -0
- package/dist/learning-workspace.js +663 -0
- package/dist/trust-lifecycle.d.ts +28 -4
- package/dist/trust-lifecycle.js +14 -5
- package/package.json +2 -2
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { type BlindQualityChoice, type InterventionManifest, type InterventionEvidence, type InterventionQualification } from "@skill-harness/core";
|
|
2
2
|
/** Explicit private retention. Host role declarations are NOT authentication. No provider is called. */
|
|
3
3
|
export declare function retainBlindIntervention(root: string, manifest: InterventionManifest, evidence: InterventionEvidence[], qualification: InterventionQualification, author: string): string;
|
|
4
|
+
/** Opaque linkage metadata only; never exposes roles, arm identities or cost before choice. */
|
|
5
|
+
export declare function readBlindInterventionBinding(root: string, id: string, author: string): Readonly<{
|
|
6
|
+
experimentDigest: string;
|
|
7
|
+
investigationDigest: string;
|
|
8
|
+
}>;
|
|
4
9
|
/** One immutable quality choice per comparison. Reopening cannot reset the reveal gate. */
|
|
5
10
|
export declare function openBlindIntervention(root: string, id: string, author: string): Readonly<{
|
|
6
11
|
view: () => {
|
|
@@ -12,6 +17,7 @@ export declare function openBlindIntervention(root: string, id: string, author:
|
|
|
12
17
|
limitations: string[];
|
|
13
18
|
};
|
|
14
19
|
quality(): BlindQualityChoice | null;
|
|
20
|
+
previewChoice(input: BlindQualityChoice): BlindQualityChoice;
|
|
15
21
|
readArtifact: (label: string, hash: string) => Buffer<ArrayBuffer>;
|
|
16
22
|
choose(input: BlindQualityChoice): BlindQualityChoice;
|
|
17
23
|
reveal(): {
|
|
@@ -90,7 +90,13 @@ function load(root, id, author) {
|
|
|
90
90
|
throw new Error("blind artifact unavailable");
|
|
91
91
|
artifacts.set(ref.hash, artifact.bytes);
|
|
92
92
|
}
|
|
93
|
-
|
|
93
|
+
const assessment = assessIntervention(bundle.manifest, bundle.evidence, { ...bundle.qualification, artifacts });
|
|
94
|
+
return { blind: createBlindComparison(bundle.manifest, assessment, bundle.seed), manifest: bundle.manifest };
|
|
95
|
+
}
|
|
96
|
+
/** Opaque linkage metadata only; never exposes roles, arm identities or cost before choice. */
|
|
97
|
+
export function readBlindInterventionBinding(root, id, author) {
|
|
98
|
+
const { manifest } = load(root, id, author);
|
|
99
|
+
return Object.freeze({ experimentDigest: manifest.id, investigationDigest: manifest.investigationSha256 });
|
|
94
100
|
}
|
|
95
101
|
function directory(path) {
|
|
96
102
|
const s = lstatSync(path);
|
|
@@ -159,10 +165,11 @@ function readChoice(root, id) {
|
|
|
159
165
|
export function openBlindIntervention(root, id, author) {
|
|
160
166
|
if (!SHA.test(id))
|
|
161
167
|
throw new Error("invalid blind comparison identity");
|
|
162
|
-
const current = () => load(root, id, author);
|
|
168
|
+
const current = () => load(root, id, author).blind;
|
|
163
169
|
return Object.freeze({
|
|
164
170
|
view: () => current().view(),
|
|
165
171
|
quality() { const blind = current(), choice = readChoice(root, id); return choice ? blind.choose(choice) : null; },
|
|
172
|
+
previewChoice(input) { return current().choose(input); },
|
|
166
173
|
readArtifact: (label, hash) => current().readArtifact(label, hash),
|
|
167
174
|
choose(input) {
|
|
168
175
|
const blind = current(), choice = blind.choose(input);
|
|
@@ -36,6 +36,14 @@ export declare function retainArchiveSource(root: string, input: ArchiveSourceIn
|
|
|
36
36
|
manifestId: string;
|
|
37
37
|
reference: ArchiveSourceReference;
|
|
38
38
|
};
|
|
39
|
+
export type ArchiveReferenceRead = {
|
|
40
|
+
status: 'available';
|
|
41
|
+
reference: ArchiveSourceReference;
|
|
42
|
+
} | Exclude<ArchiveRead, {
|
|
43
|
+
status: 'available';
|
|
44
|
+
}>;
|
|
45
|
+
/** Metadata only for explicit archive inventory. Does not claim content availability. */
|
|
46
|
+
export declare function readArchiveSourceReference(root: string, manifestId: string): ArchiveReferenceRead;
|
|
39
47
|
export declare function readArchiveSource(root: string, manifestId: string, maxBytes?: number): ArchiveRead;
|
|
40
48
|
export interface ArchivedJsonl {
|
|
41
49
|
status: "complete" | "partial" | "error";
|
package/dist/evidence-archive.js
CHANGED
|
@@ -149,27 +149,31 @@ export function retainArchiveSource(root, input) {
|
|
|
149
149
|
syncDirectory(resolve(root));
|
|
150
150
|
return { manifestId, reference };
|
|
151
151
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return { status: "error", reason: "invalid read bound" };
|
|
152
|
+
/** Metadata only for explicit archive inventory. Does not claim content availability. */
|
|
153
|
+
export function readArchiveSourceReference(root, manifestId) {
|
|
155
154
|
if (!HASH.test(manifestId))
|
|
156
|
-
return { status:
|
|
155
|
+
return { status: 'error', reason: 'invalid manifest identity' };
|
|
157
156
|
try {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
directory(join(root, "manifests"), false);
|
|
162
|
-
manifest = readVerified(join(root, "manifests", manifestId), manifestId, 8192);
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
if (absent(error))
|
|
166
|
-
return { status: "missing", reason: "manifest" };
|
|
167
|
-
throw error;
|
|
168
|
-
}
|
|
169
|
-
const text = manifest.toString("utf8");
|
|
157
|
+
directory(root, false);
|
|
158
|
+
directory(join(root, 'manifests'), false);
|
|
159
|
+
const text = readVerified(join(root, 'manifests', manifestId), manifestId, 8192).toString('utf8');
|
|
170
160
|
const reference = JSON.parse(text);
|
|
171
161
|
if (!validReference(reference) || JSON.stringify(reference) !== text)
|
|
172
|
-
fail(
|
|
162
|
+
fail('invalid manifest');
|
|
163
|
+
return { status: 'available', reference };
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
return absent(error) ? { status: 'missing', reason: 'manifest' } : { status: 'error', reason: 'invalid or inaccessible retained evidence' };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
export function readArchiveSource(root, manifestId, maxBytes = LIMIT) {
|
|
170
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0 || maxBytes > LIMIT)
|
|
171
|
+
return { status: "error", reason: "invalid read bound" };
|
|
172
|
+
try {
|
|
173
|
+
const manifest = readArchiveSourceReference(root, manifestId);
|
|
174
|
+
if (manifest.status !== 'available')
|
|
175
|
+
return manifest;
|
|
176
|
+
const { reference } = manifest;
|
|
173
177
|
if (reference.retention === "reference-only")
|
|
174
178
|
return { status: "missing", reason: "not-retained" };
|
|
175
179
|
if (reference.bytes > maxBytes)
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,10 @@ export * from "./archive-read-capability.js";
|
|
|
19
19
|
export * from "./archived-work.js";
|
|
20
20
|
export * from "./blind-intervention.js";
|
|
21
21
|
export * from "./learning-lifecycle.js";
|
|
22
|
+
export * from "./learning-workspace.js";
|
|
23
|
+
export * from "./learning-trust-setup.js";
|
|
24
|
+
export { learningHash, learningFile } from "./learning-journal.js";
|
|
25
|
+
export * from "./learning-case.js";
|
|
22
26
|
export * from "./archive-observer.js";
|
|
23
27
|
export * from "./weekly-investigation.js";
|
|
24
28
|
export * from "./intervention-run.js";
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,10 @@ export * from "./archive-read-capability.js";
|
|
|
31
31
|
export * from "./archived-work.js";
|
|
32
32
|
export * from "./blind-intervention.js";
|
|
33
33
|
export * from "./learning-lifecycle.js";
|
|
34
|
+
export * from "./learning-workspace.js";
|
|
35
|
+
export * from "./learning-trust-setup.js";
|
|
36
|
+
export { learningHash, learningFile } from "./learning-journal.js";
|
|
37
|
+
export * from "./learning-case.js";
|
|
34
38
|
export * from "./archive-observer.js";
|
|
35
39
|
export * from "./weekly-investigation.js";
|
|
36
40
|
export * from "./intervention-run.js";
|
|
@@ -14,5 +14,5 @@ export declare function learningJournal(path: string, initial?: Record<string, u
|
|
|
14
14
|
append(prior: string, value: Record<string, unknown>): LearningEvent;
|
|
15
15
|
};
|
|
16
16
|
/** One authoritative store per weekly key/policy in this archive; a renamed directory cannot refill it. */
|
|
17
|
-
export declare function registerLearningStore(root: string, kind: 'weekly' | 'trust' | 'intervention' | 'access', key: string, target: string, binding: string): void;
|
|
18
|
-
export declare function verifyLearningStore(root: string, kind: 'weekly' | 'trust' | 'intervention' | 'access', key: string, target: string, binding: string): void;
|
|
17
|
+
export declare function registerLearningStore(root: string, kind: 'weekly' | 'trust' | 'intervention' | 'access' | 'workspace', key: string, target: string, binding: string): void;
|
|
18
|
+
export declare function verifyLearningStore(root: string, kind: 'weekly' | 'trust' | 'intervention' | 'access' | 'workspace', key: string, target: string, binding: string): void;
|
package/dist/learning-journal.js
CHANGED
|
@@ -214,7 +214,7 @@ export function learningJournal(path, initial) {
|
|
|
214
214
|
}
|
|
215
215
|
/** One authoritative store per weekly key/policy in this archive; a renamed directory cannot refill it. */
|
|
216
216
|
export function registerLearningStore(root, kind, key, target, binding) {
|
|
217
|
-
if (!/^[a-f0-9]{64}$/.test(key) || !isAbsolute(target) || !['weekly', 'trust', 'intervention', 'access'].includes(kind))
|
|
217
|
+
if (!/^[a-f0-9]{64}$/.test(key) || !isAbsolute(target) || !['weekly', 'trust', 'intervention', 'access', 'workspace'].includes(kind))
|
|
218
218
|
throw Error('invalid learning registration');
|
|
219
219
|
directory(root);
|
|
220
220
|
directory(dirname(target));
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { CalibrationPrediction, CalibrationSplit, ExposurePolicy } from '@skill-harness/core';
|
|
2
|
+
import type { LearningCaseReference } from './learning-case.js';
|
|
3
|
+
import { type TrustLifecycleInput } from './trust-lifecycle.js';
|
|
4
|
+
export interface LearningTrustSetup {
|
|
5
|
+
caseName: string;
|
|
6
|
+
detectorId: string;
|
|
7
|
+
split: CalibrationSplit;
|
|
8
|
+
maxUnflagged: number;
|
|
9
|
+
unflagged: {
|
|
10
|
+
incidentId: string;
|
|
11
|
+
manifestId: string;
|
|
12
|
+
split: CalibrationSplit;
|
|
13
|
+
}[];
|
|
14
|
+
exposure: Omit<ExposurePolicy, 'component' | 'kind' | 'split'> | null;
|
|
15
|
+
}
|
|
16
|
+
/** Forms construct a frozen cohort from actual selected cases. Repeated observations of the
|
|
17
|
+
* same target are ONE incident; a detector nomination never becomes its own reference label. */
|
|
18
|
+
export declare function previewLearningTrust(directory: string, raw: LearningTrustSetup): {
|
|
19
|
+
input: TrustLifecycleInput;
|
|
20
|
+
policyDigest: string;
|
|
21
|
+
predictions: CalibrationPrediction[];
|
|
22
|
+
nominationCount: number;
|
|
23
|
+
independentIncidentCount: number;
|
|
24
|
+
caseManifestIds: string[];
|
|
25
|
+
labelsCreated: 0;
|
|
26
|
+
excludedOtherDetectors: number;
|
|
27
|
+
};
|
|
28
|
+
export declare function configureLearningTrust(directory: string, options: LearningTrustSetup, authorizedPolicyDigests: readonly string[]): {
|
|
29
|
+
policyId: string;
|
|
30
|
+
component: import("@skill-harness/core").CalibrationComponent;
|
|
31
|
+
calibration: {
|
|
32
|
+
version: "factory-calibration-v1";
|
|
33
|
+
reports: import("@skill-harness/core").CalibrationReport[];
|
|
34
|
+
excludedTuning: number;
|
|
35
|
+
referenceBasis: "independently-supplied-host-context";
|
|
36
|
+
advisoryOnly: true;
|
|
37
|
+
};
|
|
38
|
+
sampledIncidentIds: string[];
|
|
39
|
+
unflagged: {
|
|
40
|
+
sampled: number;
|
|
41
|
+
resolved: number;
|
|
42
|
+
misses: number;
|
|
43
|
+
unresolved: number;
|
|
44
|
+
conflicted: number;
|
|
45
|
+
};
|
|
46
|
+
attentionUsed: number;
|
|
47
|
+
retired: boolean;
|
|
48
|
+
exposures: {
|
|
49
|
+
mode: "ask" | "silent" | "retire";
|
|
50
|
+
reason: string;
|
|
51
|
+
id: string;
|
|
52
|
+
}[];
|
|
53
|
+
tip: string;
|
|
54
|
+
grantExpansion: false;
|
|
55
|
+
};
|
|
56
|
+
/** Selected case reference, not a retyped verdict. Separate explicit reference authority is
|
|
57
|
+
* still required by linkCaseOutcome; this only supplies the exact preview to the operator. */
|
|
58
|
+
export declare function previewLearningCaseLabel(directory: string, reference: LearningCaseReference): {
|
|
59
|
+
outcome: import("./trust-lifecycle.js").TrustReferenceOutcome;
|
|
60
|
+
caseReference: LearningCaseReference;
|
|
61
|
+
digest: string;
|
|
62
|
+
tip: string;
|
|
63
|
+
predictionId: string;
|
|
64
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { learningCopy, learningHash } from './learning-journal.js';
|
|
2
|
+
import { openLearningWorkspace } from './learning-workspace.js';
|
|
3
|
+
import { trustPolicyDigest } from './trust-lifecycle.js';
|
|
4
|
+
/** Forms construct a frozen cohort from actual selected cases. Repeated observations of the
|
|
5
|
+
* same target are ONE incident; a detector nomination never becomes its own reference label. */
|
|
6
|
+
export function previewLearningTrust(directory, raw) {
|
|
7
|
+
const options = learningCopy(raw), workspace = openLearningWorkspace(directory), config = workspace.configuration();
|
|
8
|
+
if (Object.keys(options).sort().join() !== 'caseName,detectorId,exposure,maxUnflagged,split,unflagged' || !['calibration', 'heldout', 'tuning'].includes(options.split) || !Array.isArray(options.unflagged) || options.unflagged.length > 1024)
|
|
9
|
+
throw Error('closed trust setup required');
|
|
10
|
+
const page = workspace.cases(options.caseName), items = [...page.items];
|
|
11
|
+
for (let offset = 5; offset < page.total; offset += 5)
|
|
12
|
+
items.push(...workspace.cases(options.caseName, offset).items);
|
|
13
|
+
const chosen = items.filter(c => c.candidate.detector.id === options.detectorId);
|
|
14
|
+
if (!chosen.length)
|
|
15
|
+
throw Error('selected detector has no retained cases');
|
|
16
|
+
const component = { kind: 'detector', ...chosen[0].candidate.detector };
|
|
17
|
+
if (chosen.some(c => learningHash(c.candidate.detector) !== learningHash(chosen[0].candidate.detector)))
|
|
18
|
+
throw Error('detector versions/populations must be calibrated separately');
|
|
19
|
+
const binding = workspace.inspect(0).cases.find(b => b.name === options.caseName);
|
|
20
|
+
if (!binding || binding.state !== 'ready')
|
|
21
|
+
throw Error('case binding unavailable');
|
|
22
|
+
const incidents = new Map();
|
|
23
|
+
for (const c of chosen) {
|
|
24
|
+
const id = learningHash({ target: c.candidate.target, population: component.population });
|
|
25
|
+
if (!incidents.has(id))
|
|
26
|
+
incidents.set(id, c);
|
|
27
|
+
}
|
|
28
|
+
const cohort = [...[...incidents].map(([incidentId, c]) => ({ incidentId, manifestId: c.caseManifestId, flagged: true, split: options.split })), ...options.unflagged.map(c => ({ ...c, flagged: false }))];
|
|
29
|
+
const input = { archiveRoot: config.archiveRoot, component, seed: learningHash({ scope: config.scopeDigest, component, cohort }), maxUnflagged: options.maxUnflagged, cohort,
|
|
30
|
+
exposure: options.exposure ? { ...options.exposure, component, kind: 'positive', split: options.split === 'tuning' ? 'calibration' : options.split } : null };
|
|
31
|
+
const predictions = [...incidents].map(([incidentId]) => ({ id: learningHash({ incidentId, component, split: options.split }), incidentId, component, kind: 'positive', split: options.split }));
|
|
32
|
+
return { input, policyDigest: trustPolicyDigest(input), predictions, nominationCount: chosen.length, independentIncidentCount: incidents.size,
|
|
33
|
+
caseManifestIds: [...incidents.values()].map(c => c.caseManifestId), labelsCreated: 0, excludedOtherDetectors: items.length - chosen.length };
|
|
34
|
+
}
|
|
35
|
+
export function configureLearningTrust(directory, options, authorizedPolicyDigests) {
|
|
36
|
+
const preview = previewLearningTrust(directory, options), workspace = openLearningWorkspace(directory);
|
|
37
|
+
workspace.configureTrust(preview.input, authorizedPolicyDigests);
|
|
38
|
+
for (const p of preview.predictions)
|
|
39
|
+
workspace.trust().predict(p);
|
|
40
|
+
return workspace.trust().inspect(0);
|
|
41
|
+
}
|
|
42
|
+
/** Selected case reference, not a retyped verdict. Separate explicit reference authority is
|
|
43
|
+
* still required by linkCaseOutcome; this only supplies the exact preview to the operator. */
|
|
44
|
+
export function previewLearningCaseLabel(directory, reference) {
|
|
45
|
+
const trust = openLearningWorkspace(directory).trust(), config = trust.configuration();
|
|
46
|
+
const row = config.cohort.find(c => c.flagged && c.manifestId === reference.manifestId);
|
|
47
|
+
if (!row)
|
|
48
|
+
throw Error('case outside frozen calibration cohort');
|
|
49
|
+
const predictions = trust.history().filter(e => e.value.type === 'prediction' || e.value.type === 'correction').map(e => e.value.prediction);
|
|
50
|
+
const p = predictions.filter(p => p.incidentId === row.incidentId).at(-1);
|
|
51
|
+
if (!p)
|
|
52
|
+
throw Error('prediction missing');
|
|
53
|
+
return { predictionId: p.id, ...trust.previewCaseOutcome(p.id, reference) };
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=learning-trust-setup.js.map
|