@jinn-network/jinn-layer 0.1.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/adapters/contribution-adapter.d.ts +18 -0
- package/dist/adapters/contribution-adapter.js +134 -0
- package/dist/adapters/corpus-adapter.d.ts +12 -0
- package/dist/adapters/corpus-adapter.js +212 -0
- package/dist/adapters/index.d.ts +17 -0
- package/dist/adapters/index.js +17 -0
- package/dist/adapters/json-map-store.d.ts +4 -0
- package/dist/adapters/json-map-store.js +31 -0
- package/dist/adapters/local-learning-adapter.d.ts +25 -0
- package/dist/adapters/local-learning-adapter.js +49 -0
- package/dist/adapters/skills-adapter.d.ts +8 -0
- package/dist/adapters/skills-adapter.js +55 -0
- package/dist/admission-policy.d.ts +38 -0
- package/dist/admission-policy.js +17 -0
- package/dist/bin/jinn-distill-mcp.d.ts +2 -0
- package/dist/bin/jinn-distill-mcp.js +10 -0
- package/dist/bin/jinn-layer.d.ts +7 -0
- package/dist/bin/jinn-layer.js +15 -0
- package/dist/bridge-fetch-evidence.d.ts +102 -0
- package/dist/bridge-fetch-evidence.js +677 -0
- package/dist/bridge-verdict-source.d.ts +47 -0
- package/dist/bridge-verdict-source.js +216 -0
- package/dist/bridge.d.ts +247 -0
- package/dist/bridge.js +439 -0
- package/dist/capture.d.ts +98 -0
- package/dist/capture.js +617 -0
- package/dist/cli.d.ts +148 -0
- package/dist/cli.js +2221 -0
- package/dist/cluster-selection.d.ts +34 -0
- package/dist/cluster-selection.js +135 -0
- package/dist/cluster.d.ts +89 -0
- package/dist/cluster.js +142 -0
- package/dist/consume.d.ts +139 -0
- package/dist/consume.js +280 -0
- package/dist/corpus-probes.d.ts +61 -0
- package/dist/corpus-probes.js +120 -0
- package/dist/corpus-store.d.ts +16 -0
- package/dist/corpus-store.js +101 -0
- package/dist/distill-captures.d.ts +56 -0
- package/dist/distill-captures.js +283 -0
- package/dist/distill-feedback.d.ts +20 -0
- package/dist/distill-feedback.js +30 -0
- package/dist/distill-llm.d.ts +138 -0
- package/dist/distill-llm.js +438 -0
- package/dist/distill-mcp-server.d.ts +30 -0
- package/dist/distill-mcp-server.js +281 -0
- package/dist/distill-mode.d.ts +62 -0
- package/dist/distill-mode.js +107 -0
- package/dist/distill-progress.d.ts +78 -0
- package/dist/distill-progress.js +69 -0
- package/dist/distill-prompt.d.ts +34 -0
- package/dist/distill-prompt.js +85 -0
- package/dist/distill-render.d.ts +123 -0
- package/dist/distill-render.js +303 -0
- package/dist/distill-runs.d.ts +28 -0
- package/dist/distill-runs.js +39 -0
- package/dist/distill-traces.d.ts +67 -0
- package/dist/distill-traces.js +211 -0
- package/dist/distill.d.ts +180 -0
- package/dist/distill.js +337 -0
- package/dist/distiller.d.ts +118 -0
- package/dist/distiller.js +142 -0
- package/dist/envelope.d.ts +9 -0
- package/dist/envelope.js +9 -0
- package/dist/eval-prep.d.ts +129 -0
- package/dist/eval-prep.js +523 -0
- package/dist/execution-publish.d.ts +62 -0
- package/dist/execution-publish.js +72 -0
- package/dist/gate.d.ts +39 -0
- package/dist/gate.js +106 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.js +50 -0
- package/dist/ipfs-cid.d.ts +18 -0
- package/dist/ipfs-cid.js +149 -0
- package/dist/layer-default.d.ts +3 -0
- package/dist/layer-default.js +10 -0
- package/dist/ledger.d.ts +62 -0
- package/dist/ledger.js +104 -0
- package/dist/measurement.d.ts +90 -0
- package/dist/measurement.js +134 -0
- package/dist/path-safety.d.ts +19 -0
- package/dist/path-safety.js +303 -0
- package/dist/pipeline.d.ts +94 -0
- package/dist/pipeline.js +124 -0
- package/dist/plugin-wiring.d.ts +4 -0
- package/dist/plugin-wiring.js +54 -0
- package/dist/preview.d.ts +31 -0
- package/dist/preview.js +28 -0
- package/dist/process-contract.d.ts +303 -0
- package/dist/process-contract.js +118 -0
- package/dist/publish-skill.d.ts +86 -0
- package/dist/publish-skill.js +116 -0
- package/dist/publish.d.ts +294 -0
- package/dist/publish.js +1090 -0
- package/dist/scripts/scan-skills-registry.d.ts +24 -0
- package/dist/scripts/scan-skills-registry.js +207 -0
- package/dist/seed-import/curated-batch.d.ts +36 -0
- package/dist/seed-import/curated-batch.js +103 -0
- package/dist/seed-import/episode-execute.d.ts +50 -0
- package/dist/seed-import/episode-execute.js +235 -0
- package/dist/seed-import/episode-fetch.d.ts +119 -0
- package/dist/seed-import/episode-fetch.js +137 -0
- package/dist/seed-import/episode-plan.d.ts +11 -0
- package/dist/seed-import/episode-plan.js +27 -0
- package/dist/seed-import/episode-report.d.ts +39 -0
- package/dist/seed-import/episode-report.js +36 -0
- package/dist/seed-import/execute.d.ts +61 -0
- package/dist/seed-import/execute.js +245 -0
- package/dist/seed-import/fetch.d.ts +62 -0
- package/dist/seed-import/fetch.js +82 -0
- package/dist/seed-import/licence.d.ts +17 -0
- package/dist/seed-import/licence.js +36 -0
- package/dist/seed-import/plan.d.ts +10 -0
- package/dist/seed-import/plan.js +21 -0
- package/dist/seed-import/report.d.ts +34 -0
- package/dist/seed-import/report.js +31 -0
- package/dist/seed-import/state.d.ts +72 -0
- package/dist/seed-import/state.js +120 -0
- package/dist/signal.d.ts +36 -0
- package/dist/signal.js +48 -0
- package/dist/signing.d.ts +8 -0
- package/dist/signing.js +21 -0
- package/dist/skill-package.d.ts +70 -0
- package/dist/skill-package.js +141 -0
- package/dist/skill.d.ts +21 -0
- package/dist/skill.js +77 -0
- package/dist/snapshot-transcript.d.ts +54 -0
- package/dist/snapshot-transcript.js +117 -0
- package/dist/three-arm-run.d.ts +27 -0
- package/dist/three-arm-run.js +41 -0
- package/package.json +60 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Distillation pipeline orchestrator (spec/2026-07-06-distillation-v1.md §6–§8).
|
|
3
|
+
*
|
|
4
|
+
* Composes the run-time loop end to end: verdict source → **bridge** (ledger →
|
|
5
|
+
* layer-1 evidence, both polarities, exclusion + dedup) → **gate + cluster**
|
|
6
|
+
* (eligible evidence grouped by distinct instance/tier) → **distill** (patterns
|
|
7
|
+
* + lessons → layer-2 skills). Every I/O boundary is an injected port, so the
|
|
8
|
+
* whole loop runs green under stubs (the Tier-0 dry-run) and swaps to the real
|
|
9
|
+
* adapters (verdict-source / fetchEvidence / claude distiller / publishSkill) +
|
|
10
|
+
* `ANTHROPIC_API_KEY` for a Tier-1 run with no code change.
|
|
11
|
+
*
|
|
12
|
+
* The bridge and distiller are decoupled in production through the corpus; here
|
|
13
|
+
* the pipeline captures each bridged envelope via the `publishEvidence` port and
|
|
14
|
+
* hands the same envelopes to clustering, so it reuses the tested `bridgeAttempts`
|
|
15
|
+
* (exclusion/dedup) without a corpus round-trip or a double fetch.
|
|
16
|
+
*/
|
|
17
|
+
import { type AttemptRef, type BridgeEvidence, type BridgeResult } from './bridge.js';
|
|
18
|
+
import { type HarnessPublishDeps } from './publish.js';
|
|
19
|
+
import { type TraceEnvelopeV0 } from './envelope.js';
|
|
20
|
+
import { type MetaCluster } from './cluster.js';
|
|
21
|
+
import { type DistillCluster, type DistillLLMOutput, type DistillResult, type MetaDistillLLMOutput, type MetaDistillResult } from './distill.js';
|
|
22
|
+
import type { SkillPackage } from './skill-package.js';
|
|
23
|
+
export interface PipelineDeps {
|
|
24
|
+
/** Ledger verdict-row source (both polarities). */
|
|
25
|
+
verdictSource: {
|
|
26
|
+
list: (args?: {
|
|
27
|
+
limit?: number;
|
|
28
|
+
}) => Promise<AttemptRef[]>;
|
|
29
|
+
};
|
|
30
|
+
/** Fetch the patch + task descriptor for an attempt. */
|
|
31
|
+
fetchEvidence: (ref: AttemptRef) => Promise<BridgeEvidence>;
|
|
32
|
+
/** Deps for the layer-1 publish (capture→publish). */
|
|
33
|
+
publishDeps: HarnessPublishDeps;
|
|
34
|
+
/** Bulk bridge records opt into a single manifest anchor; default stays per-record. */
|
|
35
|
+
anchorMode?: 'per-record' | 'manifest';
|
|
36
|
+
/** Add one explicit per-record control tx to a live manifest measurement run. */
|
|
37
|
+
measurePerRecordControl?: boolean;
|
|
38
|
+
/** The LLM distill port (jinn-skill-distill-prompt-v1 over a cluster). */
|
|
39
|
+
distill: (cluster: DistillCluster) => Promise<DistillLLMOutput>;
|
|
40
|
+
/** Publish a layer-2 skill package (Plan A publishSkill). */
|
|
41
|
+
publishSkill: (pkg: SkillPackage) => Promise<{
|
|
42
|
+
envelopeRef: string;
|
|
43
|
+
anchorTx: string | null;
|
|
44
|
+
}>;
|
|
45
|
+
/** Held-out slate (§12): excluded from the bridge AND the gate/cluster. */
|
|
46
|
+
slate: {
|
|
47
|
+
instanceIds: Set<string>;
|
|
48
|
+
repos?: Set<string>;
|
|
49
|
+
};
|
|
50
|
+
distribution?: string;
|
|
51
|
+
/** The distilling model, recorded in each skill's provenance (§5 auditability). */
|
|
52
|
+
distillModel?: string;
|
|
53
|
+
/** Enable stage-2 cross-instance meta-distill (issue #1463). Default off (opt-in). */
|
|
54
|
+
meta?: boolean;
|
|
55
|
+
/** The stage-2 meta LLM port. Required when `meta` is true. */
|
|
56
|
+
metaDistill?: (cluster: MetaCluster) => Promise<MetaDistillLLMOutput>;
|
|
57
|
+
/**
|
|
58
|
+
* Attempts retained per `(instance_id, polarity)` — the per-instance attempt
|
|
59
|
+
* group the distiller reasons over for group-relative distillation (#1478).
|
|
60
|
+
* Default 8. NOTE: for a group to be complete, `verdictSource.list` must
|
|
61
|
+
* return every attempt of the instance. Its no-limit default walks the full
|
|
62
|
+
* paged corpus; an explicit tight `limit` truncates in enrichment order and
|
|
63
|
+
* can split a group.
|
|
64
|
+
*/
|
|
65
|
+
groupCap?: number;
|
|
66
|
+
limit?: number;
|
|
67
|
+
now?: () => Date;
|
|
68
|
+
}
|
|
69
|
+
export interface PipelineResult {
|
|
70
|
+
bridge: BridgeResult;
|
|
71
|
+
clusterCount: number;
|
|
72
|
+
distilled: DistillResult;
|
|
73
|
+
/**
|
|
74
|
+
* True when the verdict fetch returned exactly `limit` rows — a truncation
|
|
75
|
+
* signal. Under group retention (#1478) a truncated fetch means attempt groups
|
|
76
|
+
* may be PARTIAL (the source pages by enrichment order, not by instance), so
|
|
77
|
+
* `groupSize`/`nPass`/`nFail` understate the real group. The CLI surfaces this.
|
|
78
|
+
*/
|
|
79
|
+
verdictsTruncated: boolean;
|
|
80
|
+
/** Stage-2 result — present only when `meta` was enabled. */
|
|
81
|
+
metaDistilled?: MetaDistillResult;
|
|
82
|
+
}
|
|
83
|
+
export interface PreparedDistillationEvidence {
|
|
84
|
+
bridge: BridgeResult;
|
|
85
|
+
collected: Array<{
|
|
86
|
+
ref: string;
|
|
87
|
+
instanceId: string;
|
|
88
|
+
env: TraceEnvelopeV0;
|
|
89
|
+
}>;
|
|
90
|
+
clusters: DistillCluster[];
|
|
91
|
+
verdictsTruncated: boolean;
|
|
92
|
+
}
|
|
93
|
+
export declare function prepareDistillationEvidence(deps: Pick<PipelineDeps, 'verdictSource' | 'fetchEvidence' | 'publishDeps' | 'anchorMode' | 'measurePerRecordControl' | 'slate' | 'groupCap' | 'limit' | 'now'>): Promise<PreparedDistillationEvidence>;
|
|
94
|
+
export declare function runDistillationPipeline(deps: PipelineDeps): Promise<PipelineResult>;
|
package/dist/pipeline.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Distillation pipeline orchestrator (spec/2026-07-06-distillation-v1.md §6–§8).
|
|
3
|
+
*
|
|
4
|
+
* Composes the run-time loop end to end: verdict source → **bridge** (ledger →
|
|
5
|
+
* layer-1 evidence, both polarities, exclusion + dedup) → **gate + cluster**
|
|
6
|
+
* (eligible evidence grouped by distinct instance/tier) → **distill** (patterns
|
|
7
|
+
* + lessons → layer-2 skills). Every I/O boundary is an injected port, so the
|
|
8
|
+
* whole loop runs green under stubs (the Tier-0 dry-run) and swaps to the real
|
|
9
|
+
* adapters (verdict-source / fetchEvidence / claude distiller / publishSkill) +
|
|
10
|
+
* `ANTHROPIC_API_KEY` for a Tier-1 run with no code change.
|
|
11
|
+
*
|
|
12
|
+
* The bridge and distiller are decoupled in production through the corpus; here
|
|
13
|
+
* the pipeline captures each bridged envelope via the `publishEvidence` port and
|
|
14
|
+
* hands the same envelopes to clustering, so it reuses the tested `bridgeAttempts`
|
|
15
|
+
* (exclusion/dedup) without a corpus round-trip or a double fetch.
|
|
16
|
+
*/
|
|
17
|
+
import { buildBridgeManifestPublisher, bridgeAttempts, } from './bridge.js';
|
|
18
|
+
import { capture } from './capture.js';
|
|
19
|
+
import { publish, } from './publish.js';
|
|
20
|
+
import { buildLayer2ScrubPipeline } from '@jinn-network/core/scrub';
|
|
21
|
+
import { parseTraceEnvelopeV0 } from './envelope.js';
|
|
22
|
+
import { clusterEvidence, buildMetaClusters } from './cluster.js';
|
|
23
|
+
import { distillClusters, metaDistill } from './distill.js';
|
|
24
|
+
export async function prepareDistillationEvidence(deps) {
|
|
25
|
+
const layer2 = buildLayer2ScrubPipeline();
|
|
26
|
+
const slateIds = deps.slate.instanceIds;
|
|
27
|
+
const collected = [];
|
|
28
|
+
// The bridge's publish port: capture at layer-2 altitude, publish layer-1
|
|
29
|
+
// evidence, and collect the envelope for the gate/cluster stage.
|
|
30
|
+
const publishEvidence = async (task, ref) => {
|
|
31
|
+
const pending = await capture(task, { pipeline: layer2 });
|
|
32
|
+
const env = parseTraceEnvelopeV0({
|
|
33
|
+
...pending.draft,
|
|
34
|
+
consent: { contributionConsent: true, scrubCompleted: true },
|
|
35
|
+
});
|
|
36
|
+
const published = await publish(pending, deps.publishDeps);
|
|
37
|
+
if (published.vetoed)
|
|
38
|
+
throw new Error('unexpected veto bridging evidence');
|
|
39
|
+
collected.push({ ref: published.envelopeRef, instanceId: ref.instanceId, env });
|
|
40
|
+
return { envelopeRef: published.envelopeRef, anchorTx: published.anchorTx };
|
|
41
|
+
};
|
|
42
|
+
let publishManifestBatch;
|
|
43
|
+
if (deps.anchorMode === 'manifest') {
|
|
44
|
+
if (!('publishManifestBody' in deps.publishDeps) ||
|
|
45
|
+
!('anchorManifest' in deps.publishDeps) ||
|
|
46
|
+
!('recordManifestAnchor' in deps.publishDeps)) {
|
|
47
|
+
throw new Error('manifest anchor mode requires manifest-capable publish deps');
|
|
48
|
+
}
|
|
49
|
+
const manifestDeps = deps.publishDeps;
|
|
50
|
+
const publisher = buildBridgeManifestPublisher(manifestDeps, {
|
|
51
|
+
pipeline: layer2,
|
|
52
|
+
...(deps.measurePerRecordControl ? { measurePerRecordControl: true } : {}),
|
|
53
|
+
});
|
|
54
|
+
publishManifestBatch = async (candidates) => {
|
|
55
|
+
const result = await publisher(candidates);
|
|
56
|
+
if (result.publishedMembers.length !== result.memberRefs.length) {
|
|
57
|
+
throw new Error(`manifest publisher returned ${result.publishedMembers.length} envelopes for ${result.memberRefs.length} refs`);
|
|
58
|
+
}
|
|
59
|
+
for (let index = 0; index < result.publishedMembers.length; index += 1) {
|
|
60
|
+
const member = result.publishedMembers[index];
|
|
61
|
+
const candidate = candidates[index];
|
|
62
|
+
collected.push({
|
|
63
|
+
ref: result.memberRefs[index],
|
|
64
|
+
instanceId: candidate.ref.instanceId,
|
|
65
|
+
env: member.trace,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// 1. Bridge — ledger → layer-1 evidence (exclusion + dedup live in bridgeAttempts).
|
|
72
|
+
const refs = await deps.verdictSource.list({ ...(deps.limit !== undefined ? { limit: deps.limit } : {}) });
|
|
73
|
+
const verdictsTruncated = deps.limit !== undefined && refs.length >= deps.limit;
|
|
74
|
+
const bridge = await bridgeAttempts(refs, {
|
|
75
|
+
slateInstanceIds: slateIds,
|
|
76
|
+
fetchEvidence: deps.fetchEvidence,
|
|
77
|
+
publishEvidence,
|
|
78
|
+
anchorMode: deps.anchorMode ?? 'per-record',
|
|
79
|
+
...(publishManifestBatch ? { publishManifestBatch } : {}),
|
|
80
|
+
groupCap: deps.groupCap ?? 8,
|
|
81
|
+
...(deps.now ? { now: deps.now } : {}),
|
|
82
|
+
});
|
|
83
|
+
// 2. Gate + cluster — eligible evidence grouped by distinct (instance, tier).
|
|
84
|
+
// heldOut is defence-in-depth over the bridge's own exclusion.
|
|
85
|
+
const clusters = clusterEvidence(collected, { heldOut: (id) => slateIds.has(id) });
|
|
86
|
+
return { bridge, collected, clusters, verdictsTruncated };
|
|
87
|
+
}
|
|
88
|
+
export async function runDistillationPipeline(deps) {
|
|
89
|
+
const prepared = await prepareDistillationEvidence(deps);
|
|
90
|
+
const { bridge, clusters, verdictsTruncated } = prepared;
|
|
91
|
+
// 3. Distill — patterns + lessons → layer-2 skills (output scrub + contamination scan inside).
|
|
92
|
+
const distilled = await distillClusters(clusters, {
|
|
93
|
+
distill: deps.distill,
|
|
94
|
+
publishSkill: deps.publishSkill,
|
|
95
|
+
slate: deps.slate,
|
|
96
|
+
...(deps.distribution ? { distribution: deps.distribution } : {}),
|
|
97
|
+
...(deps.distillModel ? { distillModel: deps.distillModel } : {}),
|
|
98
|
+
...(deps.now ? { now: deps.now } : {}),
|
|
99
|
+
});
|
|
100
|
+
// 4. Stage-2 (opt-in) — cross-instance meta-distill over the stage-1 skills
|
|
101
|
+
// this run just published. Reads only in-memory results (no corpus round-trip).
|
|
102
|
+
let metaDistilled;
|
|
103
|
+
if (deps.meta) {
|
|
104
|
+
if (!deps.metaDistill) {
|
|
105
|
+
throw new Error('runDistillationPipeline: meta is enabled but no metaDistill port was provided');
|
|
106
|
+
}
|
|
107
|
+
const clusterById = new Map(clusters.map((c) => [c.clusterId, c]));
|
|
108
|
+
const stage1 = distilled.published.map((p) => {
|
|
109
|
+
const cl = clusterById.get(p.clusterId);
|
|
110
|
+
if (!cl)
|
|
111
|
+
throw new Error(`meta: no originating cluster for ${p.clusterId}`);
|
|
112
|
+
return { clusterId: p.clusterId, skillKind: p.skillKind, pkg: p.pkg, evidenceRefs: cl.evidenceRefs, instanceIds: cl.instanceIds };
|
|
113
|
+
});
|
|
114
|
+
metaDistilled = await metaDistill(buildMetaClusters(stage1), {
|
|
115
|
+
metaDistill: deps.metaDistill,
|
|
116
|
+
publishSkill: deps.publishSkill,
|
|
117
|
+
slate: deps.slate,
|
|
118
|
+
...(deps.distribution ? { distribution: deps.distribution } : {}),
|
|
119
|
+
...(deps.distillModel ? { distillModel: deps.distillModel } : {}),
|
|
120
|
+
...(deps.now ? { now: deps.now } : {}),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return { bridge, clusterCount: clusters.length, distilled, verdictsTruncated, ...(metaDistilled ? { metaDistilled } : {}) };
|
|
124
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type JinnPlugin, type JinnPluginDeps } from '@jinn-network/plugin';
|
|
2
|
+
/** Assemble the real port set used by versioned process hosts. */
|
|
3
|
+
export declare function buildPluginDepsFromEnv(overrides?: Partial<JinnPluginDeps>): JinnPluginDeps;
|
|
4
|
+
export declare function buildPluginFromEnv(overrides?: Partial<JinnPluginDeps>): JinnPlugin;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { createJinnPlugin } from '@jinn-network/plugin';
|
|
2
|
+
import { createContributionAdapter, createCorpusAdapter, createEvidenceAdapter, createLocalLearningAdapter, createSkillsAdapter, } from './adapters/index.js';
|
|
3
|
+
import { ContributionStore, defaultEvidenceIndexPath, reindexEvidenceStore, resolveContributionStateDir, } from '@jinn-network/core';
|
|
4
|
+
import { DEFAULT_EPISODES_DIR, DEFAULT_SKILLS_INSTALL_DIR, localSkillProvenance, stagingDirFor, } from './distill-captures.js';
|
|
5
|
+
import { buildDefaultLayer } from './layer-default.js';
|
|
6
|
+
function episodesDir() {
|
|
7
|
+
return process.env['JINN_LAYER_EPISODES_DIR'] ?? DEFAULT_EPISODES_DIR;
|
|
8
|
+
}
|
|
9
|
+
function skillsInstallDir() {
|
|
10
|
+
return process.env['JINN_LAYER_SKILLS_INSTALL_DIR'] ?? DEFAULT_SKILLS_INSTALL_DIR;
|
|
11
|
+
}
|
|
12
|
+
/** Assemble the real port set used by versioned process hosts. */
|
|
13
|
+
export function buildPluginDepsFromEnv(overrides = {}) {
|
|
14
|
+
const corpus = overrides.corpus ?? createCorpusAdapter({ layer: buildDefaultLayer() });
|
|
15
|
+
const evidenceDir = episodesDir();
|
|
16
|
+
const evidenceIndexPath = process.env['JINN_LAYER_EVIDENCE_INDEX_PATH']
|
|
17
|
+
?? defaultEvidenceIndexPath(evidenceDir);
|
|
18
|
+
let refreshIndex = Promise.resolve();
|
|
19
|
+
const evidence = overrides.evidence ?? createEvidenceAdapter({
|
|
20
|
+
capturesDir: evidenceDir,
|
|
21
|
+
onStoreChanged: () => {
|
|
22
|
+
const refresh = () => {
|
|
23
|
+
const report = reindexEvidenceStore({
|
|
24
|
+
episodesDir: evidenceDir,
|
|
25
|
+
indexPath: evidenceIndexPath,
|
|
26
|
+
});
|
|
27
|
+
if (!report.indexUpdated) {
|
|
28
|
+
throw new Error(report.indexError ?? 'derived evidence index was not updated');
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
refreshIndex = refreshIndex.then(refresh, refresh);
|
|
32
|
+
return refreshIndex;
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
const contribution = overrides.contribution ?? createContributionAdapter({
|
|
36
|
+
statusStore: new ContributionStore({ stateDir: resolveContributionStateDir() }),
|
|
37
|
+
evidence,
|
|
38
|
+
});
|
|
39
|
+
const skills = overrides.skills ?? createSkillsAdapter({ installDir: skillsInstallDir() });
|
|
40
|
+
const localLearning = overrides.localLearning ?? createLocalLearningAdapter({
|
|
41
|
+
distiller: {
|
|
42
|
+
distill: async () => ({
|
|
43
|
+
clusterCount: 0,
|
|
44
|
+
distilled: { published: [], rejected: [], errors: [] },
|
|
45
|
+
}),
|
|
46
|
+
},
|
|
47
|
+
loadCaptures: async () => [],
|
|
48
|
+
listSkills: async () => localSkillProvenance(skillsInstallDir(), stagingDirFor(skillsInstallDir())),
|
|
49
|
+
});
|
|
50
|
+
return { corpus, evidence, contribution, localLearning, skills };
|
|
51
|
+
}
|
|
52
|
+
export function buildPluginFromEnv(overrides = {}) {
|
|
53
|
+
return createJinnPlugin(buildPluginDepsFromEnv(overrides));
|
|
54
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness-layer scrub preview — "see exactly what would leave your machine".
|
|
3
|
+
*
|
|
4
|
+
* `preview(pending)` renders a `PendingEnvelope` as a `ScrubReport`: the
|
|
5
|
+
* canonical EpisodeV1 payload exactly as it would publish, plus the redaction
|
|
6
|
+
* diff. Consent is the publish action; it is not duplicated inside the shared
|
|
7
|
+
* local/public evidence payload.
|
|
8
|
+
*
|
|
9
|
+
* `redactions[].before` values are the original (sensitive) content: local
|
|
10
|
+
* display only, NEVER persisted — anything that serialises a report for
|
|
11
|
+
* storage or transport must strip them (`stripBeforeValues`).
|
|
12
|
+
*
|
|
13
|
+
* Plan: docs/superpowers/plans/2026-07-02-jinn-harness-network-v0-plan.md
|
|
14
|
+
* Task 3 (issue #1310).
|
|
15
|
+
*/
|
|
16
|
+
import type { EpisodeV1Write } from '@jinn-network/plugin';
|
|
17
|
+
import type { PendingEnvelope, ScrubRedaction } from './capture.js';
|
|
18
|
+
export interface ScrubReport {
|
|
19
|
+
/** The envelope exactly as it would publish (consent flags asserted). */
|
|
20
|
+
envelope: EpisodeV1Write;
|
|
21
|
+
/** The redaction diff. `before` is local-display-only, never persisted. */
|
|
22
|
+
redactions: ScrubRedaction[];
|
|
23
|
+
}
|
|
24
|
+
/** Render the pending envelope's scrub report. Pure and local — no I/O. */
|
|
25
|
+
export declare function preview(pending: PendingEnvelope): ScrubReport;
|
|
26
|
+
/**
|
|
27
|
+
* The persistence-safe projection of a redaction list: identical minus every
|
|
28
|
+
* `before` value. Use this for ANY serialised output (e.g. `--json`) — the
|
|
29
|
+
* originals exist for the operator's eyes on their own terminal, nothing else.
|
|
30
|
+
*/
|
|
31
|
+
export declare function stripBeforeValues(redactions: ScrubRedaction[]): Array<Omit<ScrubRedaction, 'before'>>;
|
package/dist/preview.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness-layer scrub preview — "see exactly what would leave your machine".
|
|
3
|
+
*
|
|
4
|
+
* `preview(pending)` renders a `PendingEnvelope` as a `ScrubReport`: the
|
|
5
|
+
* canonical EpisodeV1 payload exactly as it would publish, plus the redaction
|
|
6
|
+
* diff. Consent is the publish action; it is not duplicated inside the shared
|
|
7
|
+
* local/public evidence payload.
|
|
8
|
+
*
|
|
9
|
+
* `redactions[].before` values are the original (sensitive) content: local
|
|
10
|
+
* display only, NEVER persisted — anything that serialises a report for
|
|
11
|
+
* storage or transport must strip them (`stripBeforeValues`).
|
|
12
|
+
*
|
|
13
|
+
* Plan: docs/superpowers/plans/2026-07-02-jinn-harness-network-v0-plan.md
|
|
14
|
+
* Task 3 (issue #1310).
|
|
15
|
+
*/
|
|
16
|
+
import { toPublishedEpisode } from './publish.js';
|
|
17
|
+
/** Render the pending envelope's scrub report. Pure and local — no I/O. */
|
|
18
|
+
export function preview(pending) {
|
|
19
|
+
return { envelope: toPublishedEpisode(pending), redactions: pending.redactions };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The persistence-safe projection of a redaction list: identical minus every
|
|
23
|
+
* `before` value. Use this for ANY serialised output (e.g. `--json`) — the
|
|
24
|
+
* originals exist for the operator's eyes on their own terminal, nothing else.
|
|
25
|
+
*/
|
|
26
|
+
export function stripBeforeValues(redactions) {
|
|
27
|
+
return redactions.map(({ before: _before, ...rest }) => rest);
|
|
28
|
+
}
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type FirstTurnPickupResult, type ContributionLedgerEntry, type JinnPluginDeps, type SessionEndResult } from '@jinn-network/plugin';
|
|
3
|
+
export declare const PROCESS_CONTRACT_VERSION: 1;
|
|
4
|
+
export declare const PROCESS_STATUSES: readonly ["ok", "degraded", "unavailable"];
|
|
5
|
+
export type ProcessStatus = (typeof PROCESS_STATUSES)[number];
|
|
6
|
+
export interface ProcessEnvelope<T> {
|
|
7
|
+
contractVersion: typeof PROCESS_CONTRACT_VERSION;
|
|
8
|
+
status: ProcessStatus;
|
|
9
|
+
value?: T;
|
|
10
|
+
reason?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const SessionPickupRequestV1Schema: z.ZodObject<{
|
|
13
|
+
contractVersion: z.ZodLiteral<1>;
|
|
14
|
+
meta: z.ZodObject<{
|
|
15
|
+
sessionId: z.ZodString;
|
|
16
|
+
taskSummary: z.ZodString;
|
|
17
|
+
distributionTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
18
|
+
harness: z.ZodObject<{
|
|
19
|
+
name: z.ZodString;
|
|
20
|
+
version: z.ZodString;
|
|
21
|
+
}, z.core.$strict>;
|
|
22
|
+
model: z.ZodString;
|
|
23
|
+
tools: z.ZodArray<z.ZodString>;
|
|
24
|
+
skillsLoadout: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
25
|
+
pickup: z.ZodOptional<z.ZodObject<{
|
|
26
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
27
|
+
autoAdopt: z.ZodDefault<z.ZodBoolean>;
|
|
28
|
+
autoAdoptTier: z.ZodDefault<z.ZodEnum<{
|
|
29
|
+
"user-accepted": "user-accepted";
|
|
30
|
+
"tests-passed": "tests-passed";
|
|
31
|
+
"evaluator-verified": "evaluator-verified";
|
|
32
|
+
}>>;
|
|
33
|
+
maxCandidates: z.ZodDefault<z.ZodNumber>;
|
|
34
|
+
}, z.core.$strict>>;
|
|
35
|
+
repositorySlug: z.ZodOptional<z.ZodString>;
|
|
36
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
37
|
+
user: "user";
|
|
38
|
+
"host-internal": "host-internal";
|
|
39
|
+
}>>;
|
|
40
|
+
parentSessionId: z.ZodOptional<z.ZodString>;
|
|
41
|
+
}, z.core.$strict>;
|
|
42
|
+
firstMessage: z.ZodString;
|
|
43
|
+
}, z.core.$strict>;
|
|
44
|
+
export declare const SessionEndRequestV1Schema: z.ZodObject<{
|
|
45
|
+
contractVersion: z.ZodLiteral<1>;
|
|
46
|
+
episode: z.ZodObject<{
|
|
47
|
+
schemaVersion: z.ZodLiteral<"jinn.episode.v1">;
|
|
48
|
+
episodeId: z.ZodString;
|
|
49
|
+
retrievalVisible: z.ZodDefault<z.ZodBoolean>;
|
|
50
|
+
session: z.ZodObject<{
|
|
51
|
+
sessionId: z.ZodString;
|
|
52
|
+
capturedAt: z.ZodISODateTime;
|
|
53
|
+
kind: z.ZodEnum<{
|
|
54
|
+
user: "user";
|
|
55
|
+
"host-internal": "host-internal";
|
|
56
|
+
}>;
|
|
57
|
+
parentSessionId: z.ZodOptional<z.ZodString>;
|
|
58
|
+
}, z.core.$strict>;
|
|
59
|
+
origin: z.ZodObject<{
|
|
60
|
+
writer: z.ZodString;
|
|
61
|
+
build: z.ZodString;
|
|
62
|
+
}, z.core.$strict>;
|
|
63
|
+
task: z.ZodObject<{
|
|
64
|
+
summary: z.ZodString;
|
|
65
|
+
distributionTags: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
66
|
+
repositorySlug: z.ZodOptional<z.ZodString>;
|
|
67
|
+
baseCommit: z.ZodOptional<z.ZodString>;
|
|
68
|
+
createdAt: z.ZodOptional<z.ZodNumber>;
|
|
69
|
+
instanceId: z.ZodOptional<z.ZodString>;
|
|
70
|
+
}, z.core.$strict>;
|
|
71
|
+
trajectory: z.ZodArray<z.ZodObject<{
|
|
72
|
+
spanId: z.ZodString;
|
|
73
|
+
parentSpanId: z.ZodNullable<z.ZodString>;
|
|
74
|
+
kind: z.ZodEnum<{
|
|
75
|
+
"jinn.agent_turn": "jinn.agent_turn";
|
|
76
|
+
"jinn.tool_call": "jinn.tool_call";
|
|
77
|
+
}>;
|
|
78
|
+
name: z.ZodString;
|
|
79
|
+
startTimeUnixNano: z.ZodString;
|
|
80
|
+
endTimeUnixNano: z.ZodString;
|
|
81
|
+
attributes: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
82
|
+
redactedKeys: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
83
|
+
truncatedKeys: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
84
|
+
events: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
85
|
+
timeUnixNano: z.ZodString;
|
|
86
|
+
name: z.ZodString;
|
|
87
|
+
attributes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
88
|
+
}, z.core.$strict>>>;
|
|
89
|
+
status: z.ZodOptional<z.ZodObject<{
|
|
90
|
+
code: z.ZodEnum<{
|
|
91
|
+
UNSET: "UNSET";
|
|
92
|
+
OK: "OK";
|
|
93
|
+
ERROR: "ERROR";
|
|
94
|
+
}>;
|
|
95
|
+
message: z.ZodOptional<z.ZodString>;
|
|
96
|
+
}, z.core.$strict>>;
|
|
97
|
+
}, z.core.$strict>>;
|
|
98
|
+
environment: z.ZodObject<{
|
|
99
|
+
harness: z.ZodObject<{
|
|
100
|
+
name: z.ZodString;
|
|
101
|
+
version: z.ZodString;
|
|
102
|
+
}, z.core.$strict>;
|
|
103
|
+
model: z.ZodString;
|
|
104
|
+
tools: z.ZodArray<z.ZodString>;
|
|
105
|
+
skillsLoadout: z.ZodArray<z.ZodString>;
|
|
106
|
+
generatorModel: z.ZodOptional<z.ZodObject<{
|
|
107
|
+
id: z.ZodString;
|
|
108
|
+
provider: z.ZodOptional<z.ZodString>;
|
|
109
|
+
openWeights: z.ZodOptional<z.ZodBoolean>;
|
|
110
|
+
source: z.ZodEnum<{
|
|
111
|
+
stream: "stream";
|
|
112
|
+
config: "config";
|
|
113
|
+
}>;
|
|
114
|
+
}, z.core.$strict>>;
|
|
115
|
+
distributionClass: z.ZodOptional<z.ZodEnum<{
|
|
116
|
+
unknown: "unknown";
|
|
117
|
+
open: "open";
|
|
118
|
+
"restricted-tos": "restricted-tos";
|
|
119
|
+
}>>;
|
|
120
|
+
verifier: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
121
|
+
type: z.ZodLiteral<"f2p-p2p">;
|
|
122
|
+
failToPass: z.ZodArray<z.ZodString>;
|
|
123
|
+
passToPass: z.ZodArray<z.ZodString>;
|
|
124
|
+
evalSemanticsVersion: z.ZodString;
|
|
125
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
126
|
+
type: z.ZodEnum<{
|
|
127
|
+
command: "command";
|
|
128
|
+
none: "none";
|
|
129
|
+
}>;
|
|
130
|
+
failToPass: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
131
|
+
passToPass: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
132
|
+
evalSemanticsVersion: z.ZodOptional<z.ZodString>;
|
|
133
|
+
}, z.core.$strict>], "type">>;
|
|
134
|
+
}, z.core.$strict>;
|
|
135
|
+
outcome: z.ZodPreprocess<z.ZodObject<{
|
|
136
|
+
status: z.ZodEnum<{
|
|
137
|
+
completed: "completed";
|
|
138
|
+
failed: "failed";
|
|
139
|
+
abandoned: "abandoned";
|
|
140
|
+
}>;
|
|
141
|
+
verificationStrength: z.ZodEnum<{
|
|
142
|
+
"user-accepted": "user-accepted";
|
|
143
|
+
"tests-passed": "tests-passed";
|
|
144
|
+
"evaluator-verified": "evaluator-verified";
|
|
145
|
+
}>;
|
|
146
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
147
|
+
acceptedDiff: z.ZodOptional<z.ZodBoolean>;
|
|
148
|
+
testRuns: z.ZodOptional<z.ZodObject<{
|
|
149
|
+
passed: z.ZodNumber;
|
|
150
|
+
failed: z.ZodNumber;
|
|
151
|
+
}, z.core.$strict>>;
|
|
152
|
+
}, z.core.$strict>>;
|
|
153
|
+
cost: z.ZodObject<{
|
|
154
|
+
durationMs: z.ZodNumber;
|
|
155
|
+
tokens: z.ZodOptional<z.ZodObject<{
|
|
156
|
+
input: z.ZodNumber;
|
|
157
|
+
output: z.ZodNumber;
|
|
158
|
+
}, z.core.$strict>>;
|
|
159
|
+
usdEstimate: z.ZodOptional<z.ZodString>;
|
|
160
|
+
}, z.core.$strict>;
|
|
161
|
+
retention: z.ZodObject<{
|
|
162
|
+
policy: z.ZodEnum<{
|
|
163
|
+
"local-private": "local-private";
|
|
164
|
+
"contribution-eligible": "contribution-eligible";
|
|
165
|
+
}>;
|
|
166
|
+
}, z.core.$strict>;
|
|
167
|
+
provenance: z.ZodDefault<z.ZodEnum<{
|
|
168
|
+
contributed: "contributed";
|
|
169
|
+
imported: "imported";
|
|
170
|
+
"derived-from-history": "derived-from-history";
|
|
171
|
+
}>>;
|
|
172
|
+
lineage: z.ZodOptional<z.ZodObject<{
|
|
173
|
+
episodeId: z.ZodString;
|
|
174
|
+
mintRef: z.ZodOptional<z.ZodString>;
|
|
175
|
+
}, z.core.$strict>>;
|
|
176
|
+
attemptGroup: z.ZodOptional<z.ZodObject<{
|
|
177
|
+
groupId: z.ZodString;
|
|
178
|
+
attemptId: z.ZodString;
|
|
179
|
+
relatedAttemptRefs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
180
|
+
groupSize: z.ZodOptional<z.ZodNumber>;
|
|
181
|
+
nPass: z.ZodOptional<z.ZodNumber>;
|
|
182
|
+
nFail: z.ZodOptional<z.ZodNumber>;
|
|
183
|
+
}, z.core.$strict>>;
|
|
184
|
+
activity: z.ZodOptional<z.ZodObject<{
|
|
185
|
+
retrievalFired: z.ZodBoolean;
|
|
186
|
+
eligibleRefs: z.ZodArray<z.ZodString>;
|
|
187
|
+
deliveredRefs: z.ZodArray<z.ZodString>;
|
|
188
|
+
deliveryMode: z.ZodEnum<{
|
|
189
|
+
degraded: "degraded";
|
|
190
|
+
disabled: "disabled";
|
|
191
|
+
delivered: "delivered";
|
|
192
|
+
withheld: "withheld";
|
|
193
|
+
}>;
|
|
194
|
+
deliveredContentHash: z.ZodOptional<z.ZodString>;
|
|
195
|
+
searchedTerms: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
196
|
+
providedRefs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
197
|
+
surfacedRefs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
198
|
+
fetchedRefs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
199
|
+
installedSkillRefs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
200
|
+
}, z.core.$strict>>;
|
|
201
|
+
eligibility: z.ZodOptional<z.ZodObject<{
|
|
202
|
+
eligible: z.ZodBoolean;
|
|
203
|
+
reason: z.ZodString;
|
|
204
|
+
checkedAt: z.ZodISODateTime;
|
|
205
|
+
}, z.core.$strict>>;
|
|
206
|
+
contributionCandidate: z.ZodOptional<z.ZodObject<{
|
|
207
|
+
testRuns: z.ZodArray<z.ZodObject<{
|
|
208
|
+
command: z.ZodString;
|
|
209
|
+
exitCode: z.ZodNumber;
|
|
210
|
+
at: z.ZodISODateTime;
|
|
211
|
+
}, z.core.$strict>>;
|
|
212
|
+
skillEvents: z.ZodArray<z.ZodObject<{
|
|
213
|
+
skillRef: z.ZodString;
|
|
214
|
+
action: z.ZodEnum<{
|
|
215
|
+
loaded: "loaded";
|
|
216
|
+
invoked: "invoked";
|
|
217
|
+
}>;
|
|
218
|
+
}, z.core.$strict>>;
|
|
219
|
+
schemaVersion: z.ZodLiteral<"jinn.contribution-candidate.v1">;
|
|
220
|
+
sourceId: z.ZodString;
|
|
221
|
+
repositorySlug: z.ZodString;
|
|
222
|
+
baseCommit: z.ZodString;
|
|
223
|
+
acceptedDiff: z.ZodString;
|
|
224
|
+
intermediateFailureDiffs: z.ZodArray<z.ZodString>;
|
|
225
|
+
publishMinedTasksConsent: z.ZodBoolean;
|
|
226
|
+
createdAt: z.ZodISODateTime;
|
|
227
|
+
}, z.core.$strict>>;
|
|
228
|
+
}, z.core.$strict>;
|
|
229
|
+
activity: z.ZodObject<{
|
|
230
|
+
retrievalFired: z.ZodBoolean;
|
|
231
|
+
eligibleRefs: z.ZodArray<z.ZodString>;
|
|
232
|
+
deliveredRefs: z.ZodArray<z.ZodString>;
|
|
233
|
+
deliveryMode: z.ZodEnum<{
|
|
234
|
+
degraded: "degraded";
|
|
235
|
+
disabled: "disabled";
|
|
236
|
+
delivered: "delivered";
|
|
237
|
+
withheld: "withheld";
|
|
238
|
+
}>;
|
|
239
|
+
deliveredContentHash: z.ZodOptional<z.ZodString>;
|
|
240
|
+
searchedTerms: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
241
|
+
providedRefs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
242
|
+
surfacedRefs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
243
|
+
fetchedRefs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
244
|
+
installedSkillRefs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
245
|
+
}, z.core.$strict>;
|
|
246
|
+
eligibilityInputs: z.ZodObject<{
|
|
247
|
+
publicRepo: z.ZodOptional<z.ZodBoolean>;
|
|
248
|
+
acceptedDiff: z.ZodOptional<z.ZodBoolean>;
|
|
249
|
+
}, z.core.$strict>;
|
|
250
|
+
contributionCandidate: z.ZodOptional<z.ZodObject<{
|
|
251
|
+
testRuns: z.ZodArray<z.ZodObject<{
|
|
252
|
+
command: z.ZodString;
|
|
253
|
+
exitCode: z.ZodNumber;
|
|
254
|
+
at: z.ZodISODateTime;
|
|
255
|
+
}, z.core.$strict>>;
|
|
256
|
+
skillEvents: z.ZodArray<z.ZodObject<{
|
|
257
|
+
skillRef: z.ZodString;
|
|
258
|
+
action: z.ZodEnum<{
|
|
259
|
+
loaded: "loaded";
|
|
260
|
+
invoked: "invoked";
|
|
261
|
+
}>;
|
|
262
|
+
}, z.core.$strict>>;
|
|
263
|
+
schemaVersion: z.ZodLiteral<"jinn.contribution-candidate.v1">;
|
|
264
|
+
sourceId: z.ZodString;
|
|
265
|
+
repositorySlug: z.ZodString;
|
|
266
|
+
baseCommit: z.ZodString;
|
|
267
|
+
acceptedDiff: z.ZodString;
|
|
268
|
+
intermediateFailureDiffs: z.ZodArray<z.ZodString>;
|
|
269
|
+
publishMinedTasksConsent: z.ZodBoolean;
|
|
270
|
+
createdAt: z.ZodISODateTime;
|
|
271
|
+
}, z.core.$strict>>;
|
|
272
|
+
contributionVetoed: z.ZodOptional<z.ZodBoolean>;
|
|
273
|
+
}, z.core.$strict>;
|
|
274
|
+
export type SessionPickupRequestV1 = z.infer<typeof SessionPickupRequestV1Schema>;
|
|
275
|
+
export type SessionEndRequestV1 = z.infer<typeof SessionEndRequestV1Schema>;
|
|
276
|
+
export declare function envelope<T>(status: ProcessStatus, value?: T, reason?: string): ProcessEnvelope<T>;
|
|
277
|
+
export declare function sessionEndEnvelope(result: SessionEndResult): ProcessEnvelope<SessionEndResult>;
|
|
278
|
+
/** Track pickup port health without repeating requests merely to classify output. */
|
|
279
|
+
export declare function trackingCorpus(deps: JinnPluginDeps): {
|
|
280
|
+
deps: JinnPluginDeps;
|
|
281
|
+
status: () => ProcessStatus;
|
|
282
|
+
reason: () => string | undefined;
|
|
283
|
+
};
|
|
284
|
+
export type SessionPickupEnvelope = ProcessEnvelope<FirstTurnPickupResult>;
|
|
285
|
+
/**
|
|
286
|
+
* Preserve useful pickup evidence when one candidate-local corpus read is
|
|
287
|
+
* unavailable. A wholly unavailable corpus with no packets remains
|
|
288
|
+
* `unavailable`; partial success is `degraded` so hosts still consume the
|
|
289
|
+
* returned packets. Core-caught promise rejections also surface through the
|
|
290
|
+
* result's degraded reason even when the tracking wrapper observed no
|
|
291
|
+
* PortResult.
|
|
292
|
+
*/
|
|
293
|
+
export declare function sessionPickupEnvelope(result: FirstTurnPickupResult, observedStatus: ProcessStatus, observedReason?: string): SessionPickupEnvelope;
|
|
294
|
+
export interface ContributionLedgerRowV1 {
|
|
295
|
+
time: string | null;
|
|
296
|
+
task: string;
|
|
297
|
+
env: string | null;
|
|
298
|
+
anchor: string | null;
|
|
299
|
+
tier: 'user-accepted' | 'tests-passed' | null;
|
|
300
|
+
state: ContributionLedgerEntry['status'];
|
|
301
|
+
}
|
|
302
|
+
/** Persistence-safe terminal projection. Local IDs and candidate evidence do not cross it. */
|
|
303
|
+
export declare function contributionLedgerRow(entry: ContributionLedgerEntry): ContributionLedgerRowV1;
|