@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.
Files changed (131) hide show
  1. package/dist/adapters/contribution-adapter.d.ts +18 -0
  2. package/dist/adapters/contribution-adapter.js +134 -0
  3. package/dist/adapters/corpus-adapter.d.ts +12 -0
  4. package/dist/adapters/corpus-adapter.js +212 -0
  5. package/dist/adapters/index.d.ts +17 -0
  6. package/dist/adapters/index.js +17 -0
  7. package/dist/adapters/json-map-store.d.ts +4 -0
  8. package/dist/adapters/json-map-store.js +31 -0
  9. package/dist/adapters/local-learning-adapter.d.ts +25 -0
  10. package/dist/adapters/local-learning-adapter.js +49 -0
  11. package/dist/adapters/skills-adapter.d.ts +8 -0
  12. package/dist/adapters/skills-adapter.js +55 -0
  13. package/dist/admission-policy.d.ts +38 -0
  14. package/dist/admission-policy.js +17 -0
  15. package/dist/bin/jinn-distill-mcp.d.ts +2 -0
  16. package/dist/bin/jinn-distill-mcp.js +10 -0
  17. package/dist/bin/jinn-layer.d.ts +7 -0
  18. package/dist/bin/jinn-layer.js +15 -0
  19. package/dist/bridge-fetch-evidence.d.ts +102 -0
  20. package/dist/bridge-fetch-evidence.js +677 -0
  21. package/dist/bridge-verdict-source.d.ts +47 -0
  22. package/dist/bridge-verdict-source.js +216 -0
  23. package/dist/bridge.d.ts +247 -0
  24. package/dist/bridge.js +439 -0
  25. package/dist/capture.d.ts +98 -0
  26. package/dist/capture.js +617 -0
  27. package/dist/cli.d.ts +148 -0
  28. package/dist/cli.js +2221 -0
  29. package/dist/cluster-selection.d.ts +34 -0
  30. package/dist/cluster-selection.js +135 -0
  31. package/dist/cluster.d.ts +89 -0
  32. package/dist/cluster.js +142 -0
  33. package/dist/consume.d.ts +139 -0
  34. package/dist/consume.js +280 -0
  35. package/dist/corpus-probes.d.ts +61 -0
  36. package/dist/corpus-probes.js +120 -0
  37. package/dist/corpus-store.d.ts +16 -0
  38. package/dist/corpus-store.js +101 -0
  39. package/dist/distill-captures.d.ts +56 -0
  40. package/dist/distill-captures.js +283 -0
  41. package/dist/distill-feedback.d.ts +20 -0
  42. package/dist/distill-feedback.js +30 -0
  43. package/dist/distill-llm.d.ts +138 -0
  44. package/dist/distill-llm.js +438 -0
  45. package/dist/distill-mcp-server.d.ts +30 -0
  46. package/dist/distill-mcp-server.js +281 -0
  47. package/dist/distill-mode.d.ts +62 -0
  48. package/dist/distill-mode.js +107 -0
  49. package/dist/distill-progress.d.ts +78 -0
  50. package/dist/distill-progress.js +69 -0
  51. package/dist/distill-prompt.d.ts +34 -0
  52. package/dist/distill-prompt.js +85 -0
  53. package/dist/distill-render.d.ts +123 -0
  54. package/dist/distill-render.js +303 -0
  55. package/dist/distill-runs.d.ts +28 -0
  56. package/dist/distill-runs.js +39 -0
  57. package/dist/distill-traces.d.ts +67 -0
  58. package/dist/distill-traces.js +211 -0
  59. package/dist/distill.d.ts +180 -0
  60. package/dist/distill.js +337 -0
  61. package/dist/distiller.d.ts +118 -0
  62. package/dist/distiller.js +142 -0
  63. package/dist/envelope.d.ts +9 -0
  64. package/dist/envelope.js +9 -0
  65. package/dist/eval-prep.d.ts +129 -0
  66. package/dist/eval-prep.js +523 -0
  67. package/dist/execution-publish.d.ts +62 -0
  68. package/dist/execution-publish.js +72 -0
  69. package/dist/gate.d.ts +39 -0
  70. package/dist/gate.js +106 -0
  71. package/dist/index.d.ts +49 -0
  72. package/dist/index.js +50 -0
  73. package/dist/ipfs-cid.d.ts +18 -0
  74. package/dist/ipfs-cid.js +149 -0
  75. package/dist/layer-default.d.ts +3 -0
  76. package/dist/layer-default.js +10 -0
  77. package/dist/ledger.d.ts +62 -0
  78. package/dist/ledger.js +104 -0
  79. package/dist/measurement.d.ts +90 -0
  80. package/dist/measurement.js +134 -0
  81. package/dist/path-safety.d.ts +19 -0
  82. package/dist/path-safety.js +303 -0
  83. package/dist/pipeline.d.ts +94 -0
  84. package/dist/pipeline.js +124 -0
  85. package/dist/plugin-wiring.d.ts +4 -0
  86. package/dist/plugin-wiring.js +54 -0
  87. package/dist/preview.d.ts +31 -0
  88. package/dist/preview.js +28 -0
  89. package/dist/process-contract.d.ts +303 -0
  90. package/dist/process-contract.js +118 -0
  91. package/dist/publish-skill.d.ts +86 -0
  92. package/dist/publish-skill.js +116 -0
  93. package/dist/publish.d.ts +294 -0
  94. package/dist/publish.js +1090 -0
  95. package/dist/scripts/scan-skills-registry.d.ts +24 -0
  96. package/dist/scripts/scan-skills-registry.js +207 -0
  97. package/dist/seed-import/curated-batch.d.ts +36 -0
  98. package/dist/seed-import/curated-batch.js +103 -0
  99. package/dist/seed-import/episode-execute.d.ts +50 -0
  100. package/dist/seed-import/episode-execute.js +235 -0
  101. package/dist/seed-import/episode-fetch.d.ts +119 -0
  102. package/dist/seed-import/episode-fetch.js +137 -0
  103. package/dist/seed-import/episode-plan.d.ts +11 -0
  104. package/dist/seed-import/episode-plan.js +27 -0
  105. package/dist/seed-import/episode-report.d.ts +39 -0
  106. package/dist/seed-import/episode-report.js +36 -0
  107. package/dist/seed-import/execute.d.ts +61 -0
  108. package/dist/seed-import/execute.js +245 -0
  109. package/dist/seed-import/fetch.d.ts +62 -0
  110. package/dist/seed-import/fetch.js +82 -0
  111. package/dist/seed-import/licence.d.ts +17 -0
  112. package/dist/seed-import/licence.js +36 -0
  113. package/dist/seed-import/plan.d.ts +10 -0
  114. package/dist/seed-import/plan.js +21 -0
  115. package/dist/seed-import/report.d.ts +34 -0
  116. package/dist/seed-import/report.js +31 -0
  117. package/dist/seed-import/state.d.ts +72 -0
  118. package/dist/seed-import/state.js +120 -0
  119. package/dist/signal.d.ts +36 -0
  120. package/dist/signal.js +48 -0
  121. package/dist/signing.d.ts +8 -0
  122. package/dist/signing.js +21 -0
  123. package/dist/skill-package.d.ts +70 -0
  124. package/dist/skill-package.js +141 -0
  125. package/dist/skill.d.ts +21 -0
  126. package/dist/skill.js +77 -0
  127. package/dist/snapshot-transcript.d.ts +54 -0
  128. package/dist/snapshot-transcript.js +117 -0
  129. package/dist/three-arm-run.d.ts +27 -0
  130. package/dist/three-arm-run.js +41 -0
  131. package/package.json +60 -0
@@ -0,0 +1,117 @@
1
+ /**
2
+ * system_snapshot extraction — donation unwrap + ustar read + transcript
3
+ * lookup (issue #1472, spec §8).
4
+ *
5
+ * The engine tars each solve's working dir into a `system_snapshot` artifact
6
+ * (hand-rolled POSIX ustar + gzip, `client/src/harnesses/engine/packaging.ts`
7
+ * `createWorkdirTarball`) and publishes it donation-wrapped
8
+ * (`jinn.artifact.donation.v1`: JSON with base64 `data`). Inside is the
9
+ * harness's raw stdout transcript (`.claude-code/stdout.jsonl`,
10
+ * `.codex-code/stdout.jsonl`) — the solve's actual reasoning, which
11
+ * `jinn.trajectory.v1` does NOT carry (2 artifact.emit spans only; #1473
12
+ * tracks fixing that at solve time).
13
+ *
14
+ * `unwrapDonation` mirrors the module-private `decodeDonationArtifact`
15
+ * (`@jinn-network/core/corpus-read`) and additionally verifies the decoded
16
+ * bytes hash to the declared sha256 (tamper check). The ustar reader mirrors
17
+ * the writer: regular files only, names ≤100 chars, no PAX/GNU extensions —
18
+ * a malformed header ends iteration rather than throwing. Decompression is
19
+ * bomb-guarded via zlib's `maxOutputLength`.
20
+ */
21
+ import { createHash } from 'node:crypto';
22
+ import { gunzipSync } from 'node:zlib';
23
+ import { ClaudeCodeStreamJsonParser, CodexExecJsonParser, } from '@jinn-network/core/trajectory';
24
+ const DONATION_ENCODING = 'jinn.artifact.donation.v1';
25
+ /** Gzip-bomb guard: snapshots observed live are ≤ ~300 KB compressed. */
26
+ export const MAX_SNAPSHOT_DECOMPRESSED_BYTES = 32 * 1024 * 1024;
27
+ /** Transcript locations the learner adapters write under the workingDir. */
28
+ const TRANSCRIPT_PATHS = [
29
+ { suffix: '.claude-code/stdout.jsonl', harness: 'claude-code' },
30
+ { suffix: '.codex-code/stdout.jsonl', harness: 'codex' },
31
+ // .hermes-agent/stdout.log is a ~1KB plain-text log — no decision path; skipped.
32
+ ];
33
+ /**
34
+ * Decode a `jinn.artifact.donation.v1` wrapper to its raw bytes. Throws on a
35
+ * non-donation shape, a declared-sha mismatch against `expectedSha256`, or
36
+ * decoded bytes that do not hash to the declared sha (tamper check — parity
37
+ * plus-one with corpus/acquire.ts `decodeDonationArtifact`).
38
+ */
39
+ export function unwrapDonation(raw, expectedSha256) {
40
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
41
+ throw new Error('donation artifact payload is not an object');
42
+ }
43
+ const record = raw;
44
+ if (record['schemaVersion'] !== DONATION_ENCODING || record['encoding'] !== DONATION_ENCODING) {
45
+ throw new Error('donation artifact payload has unexpected encoding');
46
+ }
47
+ if (record['sha256'] !== expectedSha256) {
48
+ throw new Error('donation artifact sha256 does not match requested artifact');
49
+ }
50
+ if (typeof record['data'] !== 'string') {
51
+ throw new Error('donation artifact payload is missing base64 data');
52
+ }
53
+ const bytes = Buffer.from(record['data'], 'base64');
54
+ const computed = createHash('sha256').update(bytes).digest('hex');
55
+ if (computed !== expectedSha256) {
56
+ throw new Error('donation artifact bytes do not hash to the declared sha256');
57
+ }
58
+ return bytes;
59
+ }
60
+ /**
61
+ * Gunzip (bomb-guarded) + read a POSIX ustar archive into entries. Regular
62
+ * files only; a malformed/truncated header or size field ends iteration
63
+ * (best-effort read of what is intact, never an infinite loop).
64
+ */
65
+ export function untarGz(tarGz) {
66
+ const tar = gunzipSync(tarGz, { maxOutputLength: MAX_SNAPSHOT_DECOMPRESSED_BYTES });
67
+ const entries = [];
68
+ let off = 0;
69
+ while (off + 512 <= tar.length) {
70
+ const name = tar.subarray(off, off + 100).toString('utf8').replace(/\0.*$/, '');
71
+ if (!name)
72
+ break; // end-of-archive zero block
73
+ const sizeField = tar
74
+ .subarray(off + 124, off + 136)
75
+ .toString('utf8')
76
+ .replace(/\0.*$/, '')
77
+ .trim();
78
+ const size = parseInt(sizeField, 8);
79
+ if (!Number.isFinite(size) || size < 0)
80
+ break; // malformed header — stop
81
+ const typeflag = String.fromCharCode(tar[off + 156] ?? 48);
82
+ const bodyStart = off + 512;
83
+ const bodyEnd = bodyStart + size;
84
+ if (bodyEnd > tar.length)
85
+ break; // truncated body — stop
86
+ if (typeflag === '0' || typeflag === '\0') {
87
+ entries.push({ name, bytes: tar.subarray(bodyStart, bodyEnd) });
88
+ }
89
+ off = bodyStart + Math.ceil(size / 512) * 512;
90
+ }
91
+ return entries;
92
+ }
93
+ /** Locate the solve transcript among snapshot entries, or null if absent. */
94
+ export function findSolveTranscript(entries) {
95
+ for (const { suffix, harness } of TRANSCRIPT_PATHS) {
96
+ const entry = entries.find((e) => e.name === suffix || e.name.endsWith(`/${suffix}`));
97
+ if (entry)
98
+ return { harness, jsonl: entry.bytes.toString('utf8') };
99
+ }
100
+ return null;
101
+ }
102
+ /**
103
+ * End-to-end: donation wrapper JSON → the solve transcript, or null when the
104
+ * snapshot carries none (hermes, or transcript-less). Throws on unwrap /
105
+ * decompression failures — the caller treats any throw as "no enrichment".
106
+ */
107
+ export function extractSnapshotTranscript(wrapper, expectedSha256) {
108
+ const bytes = unwrapDonation(wrapper, expectedSha256);
109
+ return findSolveTranscript(untarGz(bytes));
110
+ }
111
+ /** Parse snapshot stdout with the same canonical typed-span parser as the live path. */
112
+ export function parseSolveTranscript(transcript) {
113
+ const parser = transcript.harness === 'claude-code'
114
+ ? new ClaudeCodeStreamJsonParser()
115
+ : new CodexExecJsonParser();
116
+ return parser.parseText(transcript.jsonl);
117
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Three-arm measurement runner (spec/2026-07-06-distillation-v1.md §11).
3
+ *
4
+ * Orchestrates the §11 run: for each arm — seeds-only (control), raw-evidence
5
+ * (the D11 product baseline), distilled — run the held-out slate under that
6
+ * arm's pre-installed corpus snapshot, collect per-instance pass/fail + cost,
7
+ * then hand all three to `threeArmMeasurement` for the gate + pilot verdict.
8
+ *
9
+ * The per-arm RUN is an injected port (`runArm`). Its production implementation
10
+ * is the **capability-eval rig (#1416)** — pre-install a content-addressed corpus
11
+ * snapshot, run the swe-rebench-v2 slate under it, grade in Docker. That rig is a
12
+ * follow-on; keeping it a port means this orchestration is correct and tested now
13
+ * and the real runner drops in unchanged. Arms run **sequentially by default** to
14
+ * bound disk/inference; each is expensive.
15
+ */
16
+ import { type ArmResult, type ThreeArmResult } from './measurement.js';
17
+ export type ArmName = 'seedsOnly' | 'rawEvidence' | 'distilled';
18
+ export interface ThreeArmRunDeps {
19
+ /** Run the held-out slate under an arm's pre-installed loadout → per-instance results. */
20
+ runArm: (arm: ArmName) => Promise<ArmResult[]>;
21
+ alpha?: number;
22
+ costMargin?: number;
23
+ /** Run arms concurrently (default false — arms are disk/inference-heavy, so serialize). */
24
+ parallel?: boolean;
25
+ log?: (msg: string) => void;
26
+ }
27
+ export declare function runThreeArm(deps: ThreeArmRunDeps): Promise<ThreeArmResult>;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Three-arm measurement runner (spec/2026-07-06-distillation-v1.md §11).
3
+ *
4
+ * Orchestrates the §11 run: for each arm — seeds-only (control), raw-evidence
5
+ * (the D11 product baseline), distilled — run the held-out slate under that
6
+ * arm's pre-installed corpus snapshot, collect per-instance pass/fail + cost,
7
+ * then hand all three to `threeArmMeasurement` for the gate + pilot verdict.
8
+ *
9
+ * The per-arm RUN is an injected port (`runArm`). Its production implementation
10
+ * is the **capability-eval rig (#1416)** — pre-install a content-addressed corpus
11
+ * snapshot, run the swe-rebench-v2 slate under it, grade in Docker. That rig is a
12
+ * follow-on; keeping it a port means this orchestration is correct and tested now
13
+ * and the real runner drops in unchanged. Arms run **sequentially by default** to
14
+ * bound disk/inference; each is expensive.
15
+ */
16
+ import { threeArmMeasurement } from './measurement.js';
17
+ const ARMS = ['seedsOnly', 'rawEvidence', 'distilled'];
18
+ export async function runThreeArm(deps) {
19
+ const log = deps.log ?? (() => { });
20
+ let seedsOnly;
21
+ let rawEvidence;
22
+ let distilled;
23
+ if (deps.parallel) {
24
+ log('running three arms concurrently');
25
+ [seedsOnly, rawEvidence, distilled] = await Promise.all(ARMS.map((a) => deps.runArm(a)));
26
+ }
27
+ else {
28
+ const out = {};
29
+ for (const arm of ARMS) {
30
+ log(`running arm: ${arm}`);
31
+ out[arm] = await deps.runArm(arm);
32
+ }
33
+ seedsOnly = out.seedsOnly;
34
+ rawEvidence = out.rawEvidence;
35
+ distilled = out.distilled;
36
+ }
37
+ return threeArmMeasurement({ seedsOnly, rawEvidence, distilled }, {
38
+ ...(deps.alpha !== undefined ? { alpha: deps.alpha } : {}),
39
+ ...(deps.costMargin !== undefined ? { costMargin: deps.costMargin } : {}),
40
+ });
41
+ }
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@jinn-network/jinn-layer",
3
+ "version": "0.1.0",
4
+ "description": "Standalone Jinn plugin process layer: host contract, local evidence, corpus reads, distillation, and seed import.",
5
+ "type": "module",
6
+ "packageManager": "yarn@4.13.0",
7
+ "license": "MIT",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/Jinn-Network/mono.git",
11
+ "directory": "packages/layer"
12
+ },
13
+ "engines": {
14
+ "node": ">=22"
15
+ },
16
+ "bin": {
17
+ "jinn-distill-mcp": "./dist/bin/jinn-distill-mcp.js",
18
+ "jinn-layer": "./dist/bin/jinn-layer.js"
19
+ },
20
+ "main": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "files": [
23
+ "dist/"
24
+ ],
25
+ "exports": {
26
+ ".": {
27
+ "import": "./dist/index.js",
28
+ "types": "./dist/index.d.ts"
29
+ }
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "scripts": {
35
+ "build": "tsc -p tsconfig.json",
36
+ "pack:smoke": "node scripts/pack-smoke.mjs",
37
+ "typecheck": "tsc --noEmit -p tsconfig.json",
38
+ "test": "vitest run"
39
+ },
40
+ "dependencies": {
41
+ "@jinn-network/core": "0.1.0",
42
+ "@jinn-network/plugin": "0.1.0",
43
+ "@modelcontextprotocol/sdk": "^1.27.1",
44
+ "better-sqlite3": "^12.10.0",
45
+ "canonicalize": "^3.0.0",
46
+ "viem": "^2.0.0",
47
+ "yaml": "^2.8.4",
48
+ "zod": "^4.4.3"
49
+ },
50
+ "devDependencies": {
51
+ "@types/better-sqlite3": "^7.6.0",
52
+ "@types/node": "^26.1.0",
53
+ "typescript": "^5.4.0",
54
+ "vitest": "^4.1.8"
55
+ },
56
+ "resolutions": {
57
+ "@jinn-network/core": "portal:../core",
58
+ "@jinn-network/plugin": "portal:../plugin"
59
+ }
60
+ }