@metaharness/flywheel 0.1.0 → 0.1.7
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/analyze.d.ts +39 -0
- package/dist/analyze.d.ts.map +1 -0
- package/dist/analyze.js +68 -0
- package/dist/analyze.js.map +1 -0
- package/dist/cjs/analyze.js +72 -0
- package/dist/cjs/analyze.js.map +1 -0
- package/dist/cjs/cli.js +139 -0
- package/dist/cjs/cli.js.map +1 -0
- package/dist/cjs/gate.js +43 -0
- package/dist/cjs/gate.js.map +1 -0
- package/dist/cjs/index.js +28 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/lineage.js +52 -0
- package/dist/cjs/lineage.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/receipts.js +44 -0
- package/dist/cjs/receipts.js.map +1 -0
- package/dist/cjs/replay.js +81 -0
- package/dist/cjs/replay.js.map +1 -0
- package/dist/cjs/run.js +147 -0
- package/dist/cjs/run.js.map +1 -0
- package/dist/cjs/types.js +10 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +103 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/replay.d.ts +3 -1
- package/dist/replay.d.ts.map +1 -1
- package/dist/replay.js +43 -4
- package/dist/replay.js.map +1 -1
- package/dist/run.d.ts +11 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +78 -28
- package/dist/run.js.map +1 -1
- package/dist/types.d.ts +40 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +28 -7
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ReplayBundle } from './types.js';
|
|
2
|
+
/** Per-lever effectiveness over a run. */
|
|
3
|
+
export interface TargetStat {
|
|
4
|
+
target: string;
|
|
5
|
+
attempts: number;
|
|
6
|
+
promotions: number;
|
|
7
|
+
rejections: number;
|
|
8
|
+
/** promotions / attempts. */
|
|
9
|
+
promoteRate: number;
|
|
10
|
+
/** mean primaryDelta over this lever's PROMOTED candidates (0 if none promoted). */
|
|
11
|
+
avgDeltaPromoted: number;
|
|
12
|
+
/** mean primaryDelta over ALL of this lever's candidates (promoted + rejected). */
|
|
13
|
+
avgDeltaAll: number;
|
|
14
|
+
/** the single best primaryDelta this lever produced. */
|
|
15
|
+
bestDelta: number;
|
|
16
|
+
/** mean sealed candidateScore.costPerWin over this lever's PROMOTED candidates — the cost-per-accepted-
|
|
17
|
+
* task for wins this lever bought (lower is better). 0 when none promoted or cost not sealed. */
|
|
18
|
+
avgCostPerWinPromoted: number;
|
|
19
|
+
/** the lowest (cheapest) sealed costPerWin among this lever's PROMOTED candidates. */
|
|
20
|
+
bestCostPerWin: number;
|
|
21
|
+
}
|
|
22
|
+
export interface BundleAnalysis {
|
|
23
|
+
generations: number;
|
|
24
|
+
candidates: number;
|
|
25
|
+
promotions: number;
|
|
26
|
+
rejections: number;
|
|
27
|
+
/** rejections specifically caused by regressing the frozen anchor (Goodhart guard fired). */
|
|
28
|
+
anchorRegressed: number;
|
|
29
|
+
/** per-lever stats, ranked most-effective first (promotions, then avg promoted lift, then avg lift). */
|
|
30
|
+
byTarget: TargetStat[];
|
|
31
|
+
/** sealed costPerWin along the PROMOTED chain (root→current) — the cost-per-accepted-task trajectory.
|
|
32
|
+
* A DOWNWARD trend means the flywheel is buying wins more cheaply over generations. Empty if unsealed. */
|
|
33
|
+
costPerWinTrend: number[];
|
|
34
|
+
}
|
|
35
|
+
/** Compute the mutation-effectiveness report from a bundle's candidate ledger. */
|
|
36
|
+
export declare function analyzeBundle(bundle: ReplayBundle): BundleAnalysis;
|
|
37
|
+
/** Human-readable lines for the `analyze` CLI verb. */
|
|
38
|
+
export declare function formatAnalysis(a: BundleAnalysis, label: string): string[];
|
|
39
|
+
//# sourceMappingURL=analyze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../src/analyze.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,YAAY,CAAC;AAE9D,0CAA0C;AAC1C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,gBAAgB,EAAE,MAAM,CAAC;IACzB,mFAAmF;IACnF,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB;sGACkG;IAClG,qBAAqB,EAAE,MAAM,CAAC;IAC9B,sFAAsF;IACtF,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,6FAA6F;IAC7F,eAAe,EAAE,MAAM,CAAC;IACxB,wGAAwG;IACxG,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB;+GAC2G;IAC3G,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAID,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAyClE;AAED,uDAAuD;AACvD,wBAAgB,cAAc,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAyBzE"}
|
package/dist/analyze.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const mean = (xs) => (xs.length ? xs.reduce((a, b) => a + b, 0) / xs.length : 0);
|
|
2
|
+
/** Compute the mutation-effectiveness report from a bundle's candidate ledger. */
|
|
3
|
+
export function analyzeBundle(bundle) {
|
|
4
|
+
const commits = (bundle.all_commits ?? []).filter((c) => c.verdict !== 'ROOT');
|
|
5
|
+
const groups = new Map();
|
|
6
|
+
for (const c of commits) {
|
|
7
|
+
const t = c.mutation?.target ?? '(none)';
|
|
8
|
+
(groups.get(t) ?? groups.set(t, []).get(t)).push(c);
|
|
9
|
+
}
|
|
10
|
+
const costOf = (c) => c.candidateScore?.costPerWin;
|
|
11
|
+
const byTarget = [...groups.entries()].map(([target, cs]) => {
|
|
12
|
+
const promoted = cs.filter((c) => c.verdict === 'PROMOTED');
|
|
13
|
+
const rejected = cs.filter((c) => c.verdict === 'REJECTED');
|
|
14
|
+
const promotedCosts = promoted.map(costOf).filter((x) => typeof x === 'number');
|
|
15
|
+
return {
|
|
16
|
+
target,
|
|
17
|
+
attempts: cs.length,
|
|
18
|
+
promotions: promoted.length,
|
|
19
|
+
rejections: rejected.length,
|
|
20
|
+
promoteRate: cs.length ? promoted.length / cs.length : 0,
|
|
21
|
+
avgDeltaPromoted: mean(promoted.map((c) => c.primaryDelta)),
|
|
22
|
+
avgDeltaAll: mean(cs.map((c) => c.primaryDelta)),
|
|
23
|
+
bestDelta: cs.length ? Math.max(...cs.map((c) => c.primaryDelta)) : 0,
|
|
24
|
+
avgCostPerWinPromoted: mean(promotedCosts),
|
|
25
|
+
bestCostPerWin: promotedCosts.length ? Math.min(...promotedCosts) : 0,
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
// Rank: most promotions first, then biggest average promoted lift, then biggest average lift overall.
|
|
29
|
+
byTarget.sort((a, b) => b.promotions - a.promotions || b.avgDeltaPromoted - a.avgDeltaPromoted || b.avgDeltaAll - a.avgDeltaAll);
|
|
30
|
+
return {
|
|
31
|
+
generations: new Set(commits.map((c) => c.generation)).size,
|
|
32
|
+
candidates: commits.length,
|
|
33
|
+
promotions: commits.filter((c) => c.verdict === 'PROMOTED').length,
|
|
34
|
+
rejections: commits.filter((c) => c.verdict === 'REJECTED').length,
|
|
35
|
+
anchorRegressed: commits.filter((c) => (c.failureReasons ?? []).includes('anchor_regressed')).length,
|
|
36
|
+
byTarget,
|
|
37
|
+
// Promoted chain is stored current→root; reverse to root→current for the trajectory.
|
|
38
|
+
costPerWinTrend: [...(bundle.chain ?? []).filter((c) => c.verdict === 'PROMOTED')].reverse()
|
|
39
|
+
.map(costOf).filter((x) => typeof x === 'number'),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** Human-readable lines for the `analyze` CLI verb. */
|
|
43
|
+
export function formatAnalysis(a, label) {
|
|
44
|
+
const lines = [
|
|
45
|
+
`Mutation-effectiveness — ${label}`,
|
|
46
|
+
` generations=${a.generations} candidates=${a.candidates} promotions=${a.promotions} rejections=${a.rejections} anchor-regressed=${a.anchorRegressed}`,
|
|
47
|
+
'',
|
|
48
|
+
` ${'lever'.padEnd(22)} ${'att'.padStart(4)} ${'prom'.padStart(5)} ${'rate'.padStart(6)} ${'avgΔ(prom)'.padStart(11)} ${'avgΔ(all)'.padStart(10)} ${'best'.padStart(6)} ${'cpw(prom)'.padStart(10)} ${'cpw(best)'.padStart(10)}`,
|
|
49
|
+
];
|
|
50
|
+
if (!a.byTarget.length) {
|
|
51
|
+
lines.push(' (no candidates in this bundle — an honest-null / root-only run)');
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
for (const t of a.byTarget) {
|
|
55
|
+
lines.push(` ${t.target.padEnd(22)} ${String(t.attempts).padStart(4)} ${String(t.promotions).padStart(5)} ${(t.promoteRate * 100).toFixed(0).padStart(5)}% ` +
|
|
56
|
+
`${t.avgDeltaPromoted.toFixed(2).padStart(11)} ${t.avgDeltaAll.toFixed(2).padStart(10)} ${t.bestDelta.toFixed(0).padStart(6)} ` +
|
|
57
|
+
`${(t.promotions ? t.avgCostPerWinPromoted.toFixed(2) : '—').padStart(10)} ${(t.promotions ? t.bestCostPerWin.toFixed(2) : '—').padStart(10)}`);
|
|
58
|
+
}
|
|
59
|
+
lines.push('', ` → most effective lever: ${a.byTarget[0].promotions > 0 ? a.byTarget[0].target : '(none promoted — widen the proposer or targets)'}`);
|
|
60
|
+
}
|
|
61
|
+
if (a.costPerWinTrend.length > 1) {
|
|
62
|
+
const [first, last] = [a.costPerWinTrend[0], a.costPerWinTrend[a.costPerWinTrend.length - 1]];
|
|
63
|
+
const dir = last < first ? 'cheaper ↓' : last > first ? 'costlier ↑' : 'flat →';
|
|
64
|
+
lines.push(` → cost-per-win trajectory (root→current): ${a.costPerWinTrend.map((c) => c.toFixed(2)).join(' → ')} [${dir}]`);
|
|
65
|
+
}
|
|
66
|
+
return lines;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=analyze.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../src/analyze.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.analyzeBundle = analyzeBundle;
|
|
4
|
+
exports.formatAnalysis = formatAnalysis;
|
|
5
|
+
const mean = (xs) => (xs.length ? xs.reduce((a, b) => a + b, 0) / xs.length : 0);
|
|
6
|
+
/** Compute the mutation-effectiveness report from a bundle's candidate ledger. */
|
|
7
|
+
function analyzeBundle(bundle) {
|
|
8
|
+
const commits = (bundle.all_commits ?? []).filter((c) => c.verdict !== 'ROOT');
|
|
9
|
+
const groups = new Map();
|
|
10
|
+
for (const c of commits) {
|
|
11
|
+
const t = c.mutation?.target ?? '(none)';
|
|
12
|
+
(groups.get(t) ?? groups.set(t, []).get(t)).push(c);
|
|
13
|
+
}
|
|
14
|
+
const costOf = (c) => c.candidateScore?.costPerWin;
|
|
15
|
+
const byTarget = [...groups.entries()].map(([target, cs]) => {
|
|
16
|
+
const promoted = cs.filter((c) => c.verdict === 'PROMOTED');
|
|
17
|
+
const rejected = cs.filter((c) => c.verdict === 'REJECTED');
|
|
18
|
+
const promotedCosts = promoted.map(costOf).filter((x) => typeof x === 'number');
|
|
19
|
+
return {
|
|
20
|
+
target,
|
|
21
|
+
attempts: cs.length,
|
|
22
|
+
promotions: promoted.length,
|
|
23
|
+
rejections: rejected.length,
|
|
24
|
+
promoteRate: cs.length ? promoted.length / cs.length : 0,
|
|
25
|
+
avgDeltaPromoted: mean(promoted.map((c) => c.primaryDelta)),
|
|
26
|
+
avgDeltaAll: mean(cs.map((c) => c.primaryDelta)),
|
|
27
|
+
bestDelta: cs.length ? Math.max(...cs.map((c) => c.primaryDelta)) : 0,
|
|
28
|
+
avgCostPerWinPromoted: mean(promotedCosts),
|
|
29
|
+
bestCostPerWin: promotedCosts.length ? Math.min(...promotedCosts) : 0,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
// Rank: most promotions first, then biggest average promoted lift, then biggest average lift overall.
|
|
33
|
+
byTarget.sort((a, b) => b.promotions - a.promotions || b.avgDeltaPromoted - a.avgDeltaPromoted || b.avgDeltaAll - a.avgDeltaAll);
|
|
34
|
+
return {
|
|
35
|
+
generations: new Set(commits.map((c) => c.generation)).size,
|
|
36
|
+
candidates: commits.length,
|
|
37
|
+
promotions: commits.filter((c) => c.verdict === 'PROMOTED').length,
|
|
38
|
+
rejections: commits.filter((c) => c.verdict === 'REJECTED').length,
|
|
39
|
+
anchorRegressed: commits.filter((c) => (c.failureReasons ?? []).includes('anchor_regressed')).length,
|
|
40
|
+
byTarget,
|
|
41
|
+
// Promoted chain is stored current→root; reverse to root→current for the trajectory.
|
|
42
|
+
costPerWinTrend: [...(bundle.chain ?? []).filter((c) => c.verdict === 'PROMOTED')].reverse()
|
|
43
|
+
.map(costOf).filter((x) => typeof x === 'number'),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** Human-readable lines for the `analyze` CLI verb. */
|
|
47
|
+
function formatAnalysis(a, label) {
|
|
48
|
+
const lines = [
|
|
49
|
+
`Mutation-effectiveness — ${label}`,
|
|
50
|
+
` generations=${a.generations} candidates=${a.candidates} promotions=${a.promotions} rejections=${a.rejections} anchor-regressed=${a.anchorRegressed}`,
|
|
51
|
+
'',
|
|
52
|
+
` ${'lever'.padEnd(22)} ${'att'.padStart(4)} ${'prom'.padStart(5)} ${'rate'.padStart(6)} ${'avgΔ(prom)'.padStart(11)} ${'avgΔ(all)'.padStart(10)} ${'best'.padStart(6)} ${'cpw(prom)'.padStart(10)} ${'cpw(best)'.padStart(10)}`,
|
|
53
|
+
];
|
|
54
|
+
if (!a.byTarget.length) {
|
|
55
|
+
lines.push(' (no candidates in this bundle — an honest-null / root-only run)');
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
for (const t of a.byTarget) {
|
|
59
|
+
lines.push(` ${t.target.padEnd(22)} ${String(t.attempts).padStart(4)} ${String(t.promotions).padStart(5)} ${(t.promoteRate * 100).toFixed(0).padStart(5)}% ` +
|
|
60
|
+
`${t.avgDeltaPromoted.toFixed(2).padStart(11)} ${t.avgDeltaAll.toFixed(2).padStart(10)} ${t.bestDelta.toFixed(0).padStart(6)} ` +
|
|
61
|
+
`${(t.promotions ? t.avgCostPerWinPromoted.toFixed(2) : '—').padStart(10)} ${(t.promotions ? t.bestCostPerWin.toFixed(2) : '—').padStart(10)}`);
|
|
62
|
+
}
|
|
63
|
+
lines.push('', ` → most effective lever: ${a.byTarget[0].promotions > 0 ? a.byTarget[0].target : '(none promoted — widen the proposer or targets)'}`);
|
|
64
|
+
}
|
|
65
|
+
if (a.costPerWinTrend.length > 1) {
|
|
66
|
+
const [first, last] = [a.costPerWinTrend[0], a.costPerWinTrend[a.costPerWinTrend.length - 1]];
|
|
67
|
+
const dir = last < first ? 'cheaper ↓' : last > first ? 'costlier ↑' : 'flat →';
|
|
68
|
+
lines.push(` → cost-per-win trajectory (root→current): ${a.costPerWinTrend.map((c) => c.toFixed(2)).join(' → ')} [${dir}]`);
|
|
69
|
+
}
|
|
70
|
+
return lines;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=analyze.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/analyze.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/cli.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.dispatch = dispatch;
|
|
37
|
+
// @metaharness/flywheel — CLI dispatch (consumed by `metaharness flywheel <sub>`). Returns
|
|
38
|
+
// { code, lines } to match the sibling package convention (weight-eft / redblue). Three verbs:
|
|
39
|
+
// run <config.mjs> — run the loop from a user config module (its own proposer/evaluator/suites)
|
|
40
|
+
// replay <bundle> — independently verify a proof bundle (receipts + lineage + frozen gate)
|
|
41
|
+
// graph <bundle> — print the lineage chain + the compounding lift curve
|
|
42
|
+
const node_fs_1 = require("node:fs");
|
|
43
|
+
const node_path_1 = require("node:path");
|
|
44
|
+
const node_url_1 = require("node:url");
|
|
45
|
+
const run_js_1 = require("./run.js");
|
|
46
|
+
const replay_js_1 = require("./replay.js");
|
|
47
|
+
const receipts_js_1 = require("./receipts.js");
|
|
48
|
+
const analyze_js_1 = require("./analyze.js");
|
|
49
|
+
const USAGE = [
|
|
50
|
+
'metaharness flywheel — a verifiable self-improvement loop for agent harnesses.',
|
|
51
|
+
'',
|
|
52
|
+
' metaharness flywheel run <config.mjs> [--out bundle.json] [--generations N]',
|
|
53
|
+
' Run the loop. <config.mjs> default-exports a FlywheelConfig (your proposer/evaluator/suites).',
|
|
54
|
+
' metaharness flywheel replay <proof-bundle.json> [--gate-fingerprint <hex>]',
|
|
55
|
+
' Independently verify a bundle: receipts + lineage-to-root + (optional) frozen-gate fingerprint.',
|
|
56
|
+
' metaharness flywheel graph <proof-bundle.json>',
|
|
57
|
+
' Print the promoted lineage chain and the compounding lift curve.',
|
|
58
|
+
' metaharness flywheel analyze <proof-bundle.json>',
|
|
59
|
+
' F-P2 mutation-effectiveness: which policy levers earn promotions and how much lift each produces.',
|
|
60
|
+
];
|
|
61
|
+
function loadBundle(path) {
|
|
62
|
+
if (!path)
|
|
63
|
+
throw new Error('a proof-bundle.json path is required');
|
|
64
|
+
return JSON.parse((0, node_fs_1.readFileSync)(path, 'utf-8'));
|
|
65
|
+
}
|
|
66
|
+
function flag(args, name) {
|
|
67
|
+
const i = args.indexOf(name);
|
|
68
|
+
return i >= 0 ? args[i + 1] : undefined;
|
|
69
|
+
}
|
|
70
|
+
async function replay(args) {
|
|
71
|
+
const bundle = loadBundle(args[0]);
|
|
72
|
+
const v = (0, replay_js_1.verifyReplayBundle)(bundle, { pinnedGateFingerprint: flag(args, '--gate-fingerprint') });
|
|
73
|
+
const lines = [
|
|
74
|
+
`Replaying ${args[0]} [data_source=${bundle.data_source}]`,
|
|
75
|
+
` chain: ${v.chainSummary}`,
|
|
76
|
+
` receipts verify (Ed25519, embedded key): ${v.checks.receipts ? 'PASS' : 'FAIL'}`,
|
|
77
|
+
` reconstructs to gen-0 root: ${v.checks.reachesRoot ? 'PASS' : 'FAIL'}`,
|
|
78
|
+
` each generation re-bases on the winner: ${v.checks.contiguousParents ? 'PASS' : 'FAIL'}`,
|
|
79
|
+
` every chain node is a promotion: ${v.checks.allPromoted ? 'PASS' : 'FAIL'}`,
|
|
80
|
+
` gate UNCHANGED (fingerprint): ${flag(args, '--gate-fingerprint') ? (v.checks.gateUnchanged ? 'PASS' : 'FAIL') : 'skipped (no --gate-fingerprint)'}`,
|
|
81
|
+
` verified improvements: ${bundle.verified_improvements} | anchor-surviving: ${bundle.anchor_surviving_improvements} | milestone: ${bundle.milestone_reached}`,
|
|
82
|
+
'',
|
|
83
|
+
`ACCEPTANCE: ${v.pass ? 'PASS' : 'FAIL (' + v.failures.join(', ') + ')'}`,
|
|
84
|
+
];
|
|
85
|
+
return { code: v.pass ? 0 : 1, lines };
|
|
86
|
+
}
|
|
87
|
+
function analyze(args) {
|
|
88
|
+
const bundle = loadBundle(args[0]);
|
|
89
|
+
return { code: 0, lines: (0, analyze_js_1.formatAnalysis)((0, analyze_js_1.analyzeBundle)(bundle), `${args[0]} [data_source=${bundle.data_source}]`) };
|
|
90
|
+
}
|
|
91
|
+
function graph(args) {
|
|
92
|
+
const bundle = loadBundle(args[0]);
|
|
93
|
+
const max = Math.max(1, ...bundle.lift_curve.map((p) => p.primary));
|
|
94
|
+
const lines = [`Lineage + lift curve — ${args[0]} [root=${bundle.root_id}]`, ''];
|
|
95
|
+
for (const p of bundle.lift_curve) {
|
|
96
|
+
const bar = '█'.repeat(Math.round((p.primary / max) * 32));
|
|
97
|
+
lines.push(` gen${String(p.generation).padStart(2)} ${String(p.primary).padStart(4)} ${bar} ${p.delta > 0 ? `(+${p.delta})` : ''}${p.anchor !== null ? ` anchor=${p.anchor}` : ''}`);
|
|
98
|
+
}
|
|
99
|
+
lines.push('', ` promoted chain: ${bundle.chain.map((c) => `gen${c.generation}${c.mutation ? `(${c.mutation.target})` : '(root)'}`).join(' → ')}`);
|
|
100
|
+
return { code: 0, lines };
|
|
101
|
+
}
|
|
102
|
+
async function run(args) {
|
|
103
|
+
const cfgPath = args[0];
|
|
104
|
+
if (!cfgPath)
|
|
105
|
+
return { code: 2, lines: ['Usage: metaharness flywheel run <config.mjs> [--out bundle.json] [--generations N]'] };
|
|
106
|
+
const abs = (0, node_path_1.isAbsolute)(cfgPath) ? cfgPath : (0, node_path_1.resolve)(process.cwd(), cfgPath);
|
|
107
|
+
const mod = (await Promise.resolve(`${(0, node_url_1.pathToFileURL)(abs).href}`).then(s => __importStar(require(s))));
|
|
108
|
+
const partial = mod.default ?? mod.flywheelConfig;
|
|
109
|
+
if (!partial || !partial.rootPolicy || !partial.proposer || !partial.evaluator || !partial.holdout) {
|
|
110
|
+
return { code: 2, lines: [`${cfgPath} must default-export a FlywheelConfig with at least { rootPolicy, proposer, evaluator, holdout }.`] };
|
|
111
|
+
}
|
|
112
|
+
const gens = Number(flag(args, '--generations')) || partial.maxGenerations || 10;
|
|
113
|
+
const result = await (0, run_js_1.runFlywheelGenerations)({ maxGenerations: gens, signer: partial.signer ?? (0, receipts_js_1.makeSigner)(), dataSource: partial.dataSource ?? 'LIVE', ...partial });
|
|
114
|
+
const out = flag(args, '--out');
|
|
115
|
+
const lines = [`Ran ${result.generationsRun} generations.`];
|
|
116
|
+
for (const p of result.liftCurve)
|
|
117
|
+
lines.push(` gen${p.generation}: primary=${p.primary} ${p.delta > 0 ? `(+${p.delta})` : ''}`);
|
|
118
|
+
lines.push(`verified improvements: ${result.replayBundle.verified_improvements} | anchor-surviving: ${result.replayBundle.anchor_surviving_improvements} | milestone: ${result.milestoneReached}`);
|
|
119
|
+
if (out) {
|
|
120
|
+
(0, node_fs_1.writeFileSync)(out, JSON.stringify(result.replayBundle, null, 2));
|
|
121
|
+
lines.push(`replay bundle written: ${out}`);
|
|
122
|
+
}
|
|
123
|
+
return { code: 0, lines };
|
|
124
|
+
}
|
|
125
|
+
async function dispatch(sub, args) {
|
|
126
|
+
switch (sub) {
|
|
127
|
+
case 'replay': return replay(args);
|
|
128
|
+
case 'graph': return graph(args);
|
|
129
|
+
case 'analyze': return analyze(args);
|
|
130
|
+
case 'run': return run(args);
|
|
131
|
+
case undefined:
|
|
132
|
+
case 'help':
|
|
133
|
+
case '--help':
|
|
134
|
+
return { code: 0, lines: USAGE };
|
|
135
|
+
default:
|
|
136
|
+
return { code: 2, lines: [`Unknown flywheel subcommand: ${sub}`, '', ...USAGE] };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/gate.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.meetsPromotionRule = meetsPromotionRule;
|
|
4
|
+
exports.gateFingerprint = gateFingerprint;
|
|
5
|
+
// @metaharness/flywheel — the DEFAULT promotion gate + its fingerprint.
|
|
6
|
+
//
|
|
7
|
+
// "The gate is the product." A promotion is only as trustworthy as the rule that admitted it, and that
|
|
8
|
+
// rule must be FROZEN for a deployment and VERIFIABLY unchanged. This is the default conjunctive rule
|
|
9
|
+
// (every clause load-bearing; ALL must hold) — but it is just a `PromotionRule`, so a caller may inject
|
|
10
|
+
// its own (stricter compliance gate, cost policy, etc.) and fingerprint that instead.
|
|
11
|
+
const node_crypto_1 = require("node:crypto");
|
|
12
|
+
/**
|
|
13
|
+
* The default frozen gate. Conjunctive — a candidate is promoted iff EVERY clause holds:
|
|
14
|
+
* 1. primary does not regress (candidate.primary ≥ baseline.primary)
|
|
15
|
+
* 2. no-op rate strictly improves (candidate.noopRate < baseline.noopRate) — the load-bearing signal;
|
|
16
|
+
* a policy earns a promotion by making the executor COMMIT more, not just score higher
|
|
17
|
+
* 3. cost/win does not worsen (candidate.costPerWin ≤ baseline.costPerWin)
|
|
18
|
+
* 4. no hard safety/security regression
|
|
19
|
+
* 5. if an anchor is supplied, it must not regress (candidate ≥ baseline) — the anti-Goodhart guard
|
|
20
|
+
*/
|
|
21
|
+
function meetsPromotionRule(e) {
|
|
22
|
+
const reasons = [];
|
|
23
|
+
if (e.candidate.primary < e.baseline.primary)
|
|
24
|
+
reasons.push('primary_regressed');
|
|
25
|
+
if (!(e.candidate.noopRate < e.baseline.noopRate))
|
|
26
|
+
reasons.push('noop_rate_not_improved');
|
|
27
|
+
if (e.candidate.costPerWin > e.baseline.costPerWin)
|
|
28
|
+
reasons.push('cost_per_win_worsened');
|
|
29
|
+
if (e.candidate.regressed)
|
|
30
|
+
reasons.push('safety_regressed');
|
|
31
|
+
if (e.anchor && e.anchor.candidate < e.anchor.baseline)
|
|
32
|
+
reasons.push('anchor_regressed');
|
|
33
|
+
return { promote: reasons.length === 0, reasons };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A fingerprint of a promotion rule's source — an external reviewer recomputes this and compares it to a
|
|
37
|
+
* pinned value to prove the gate was UNCHANGED between runs. `Function.prototype.toString` is stable for
|
|
38
|
+
* a given source; for a build-artifact-level guarantee, hash the rule's source file instead and pass it.
|
|
39
|
+
*/
|
|
40
|
+
function gateFingerprint(rule) {
|
|
41
|
+
return (0, node_crypto_1.createHash)('sha256').update(rule.toString()).digest('hex');
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../../src/gate.ts"],"names":[],"mappings":";;AAkBA,gDAQC;AAOD,0CAEC;AAnCD,wEAAwE;AACxE,EAAE;AACF,uGAAuG;AACvG,sGAAsG;AACtG,wGAAwG;AACxG,sFAAsF;AACtF,6CAAyC;AAGzC;;;;;;;;GAQG;AACH,SAAgB,kBAAkB,CAAC,CAAoB;IACrD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,CAAC,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO;QAAE,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAChF,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IAC1F,IAAI,CAAC,CAAC,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,QAAQ,CAAC,UAAU;QAAE,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAC1F,IAAI,CAAC,CAAC,SAAS,CAAC,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC5D,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,QAAQ;QAAE,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACzF,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,SAAgB,eAAe,CAAC,IAAmB;IACjD,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACpE,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatAnalysis = exports.analyzeBundle = exports.verifyReplayBundle = exports.liftPoint = exports.computeLiftCurve = exports.InMemoryLineageStore = exports.canon = exports.verifyReceipt = exports.makeSigner = exports.gateFingerprint = exports.meetsPromotionRule = exports.runFlywheelGenerations = void 0;
|
|
4
|
+
// @metaharness/flywheel — a verifiable self-improvement loop for agent harnesses.
|
|
5
|
+
// Freeze the model. Evolve the harness. Promote only what proves lift.
|
|
6
|
+
//
|
|
7
|
+
// The reusable engine for run → measure → mutate → verify → promote. It knows only candidates, scores,
|
|
8
|
+
// gates, receipts, and promotion lineage — never a host, model, or benchmark. Plug in your own proposer,
|
|
9
|
+
// evaluator, gate, holdouts, and cost/security rules; get the same auditable, replayable improvement loop.
|
|
10
|
+
var run_js_1 = require("./run.js");
|
|
11
|
+
Object.defineProperty(exports, "runFlywheelGenerations", { enumerable: true, get: function () { return run_js_1.runFlywheelGenerations; } });
|
|
12
|
+
var gate_js_1 = require("./gate.js");
|
|
13
|
+
Object.defineProperty(exports, "meetsPromotionRule", { enumerable: true, get: function () { return gate_js_1.meetsPromotionRule; } });
|
|
14
|
+
Object.defineProperty(exports, "gateFingerprint", { enumerable: true, get: function () { return gate_js_1.gateFingerprint; } });
|
|
15
|
+
var receipts_js_1 = require("./receipts.js");
|
|
16
|
+
Object.defineProperty(exports, "makeSigner", { enumerable: true, get: function () { return receipts_js_1.makeSigner; } });
|
|
17
|
+
Object.defineProperty(exports, "verifyReceipt", { enumerable: true, get: function () { return receipts_js_1.verifyReceipt; } });
|
|
18
|
+
Object.defineProperty(exports, "canon", { enumerable: true, get: function () { return receipts_js_1.canon; } });
|
|
19
|
+
var lineage_js_1 = require("./lineage.js");
|
|
20
|
+
Object.defineProperty(exports, "InMemoryLineageStore", { enumerable: true, get: function () { return lineage_js_1.InMemoryLineageStore; } });
|
|
21
|
+
Object.defineProperty(exports, "computeLiftCurve", { enumerable: true, get: function () { return lineage_js_1.computeLiftCurve; } });
|
|
22
|
+
Object.defineProperty(exports, "liftPoint", { enumerable: true, get: function () { return lineage_js_1.liftPoint; } });
|
|
23
|
+
var replay_js_1 = require("./replay.js");
|
|
24
|
+
Object.defineProperty(exports, "verifyReplayBundle", { enumerable: true, get: function () { return replay_js_1.verifyReplayBundle; } });
|
|
25
|
+
var analyze_js_1 = require("./analyze.js");
|
|
26
|
+
Object.defineProperty(exports, "analyzeBundle", { enumerable: true, get: function () { return analyze_js_1.analyzeBundle; } });
|
|
27
|
+
Object.defineProperty(exports, "formatAnalysis", { enumerable: true, get: function () { return analyze_js_1.formatAnalysis; } });
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,kFAAkF;AAClF,uEAAuE;AACvE,EAAE;AACF,uGAAuG;AACvG,yGAAyG;AACzG,2GAA2G;AAC3G,mCAAkD;AAAzC,gHAAA,sBAAsB,OAAA;AAG/B,qCAAgE;AAAvD,6GAAA,kBAAkB,OAAA;AAAE,0GAAA,eAAe,OAAA;AAC5C,6CAAiE;AAAxD,yGAAA,UAAU,OAAA;AAAE,4GAAA,aAAa,OAAA;AAAE,oGAAA,KAAK,OAAA;AACzC,2CAAiF;AAAxE,kHAAA,oBAAoB,OAAA;AAAE,8GAAA,gBAAgB,OAAA;AAAE,uGAAA,SAAS,OAAA;AAC1D,yCAAiD;AAAxC,+GAAA,kBAAkB,OAAA;AAE3B,2CAA6D;AAApD,2GAAA,aAAa,OAAA;AAAE,4GAAA,cAAc,OAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InMemoryLineageStore = void 0;
|
|
4
|
+
exports.computeLiftCurve = computeLiftCurve;
|
|
5
|
+
exports.liftPoint = liftPoint;
|
|
6
|
+
class InMemoryLineageStore {
|
|
7
|
+
commits = new Map();
|
|
8
|
+
async append(commit) {
|
|
9
|
+
this.commits.set(commit.id, { ...commit });
|
|
10
|
+
}
|
|
11
|
+
async get(id) {
|
|
12
|
+
const c = this.commits.get(id);
|
|
13
|
+
return c ? { ...c } : null;
|
|
14
|
+
}
|
|
15
|
+
async walkToRoot(id) {
|
|
16
|
+
const chain = [];
|
|
17
|
+
const seen = new Set();
|
|
18
|
+
let cur = this.commits.get(id) ?? null;
|
|
19
|
+
while (cur && !seen.has(cur.id)) {
|
|
20
|
+
seen.add(cur.id);
|
|
21
|
+
chain.push({ ...cur });
|
|
22
|
+
cur = cur.parents[0] ? this.commits.get(cur.parents[0]) ?? null : null;
|
|
23
|
+
}
|
|
24
|
+
return chain;
|
|
25
|
+
}
|
|
26
|
+
async list() {
|
|
27
|
+
return [...this.commits.values()].map((c) => ({ ...c }));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.InMemoryLineageStore = InMemoryLineageStore;
|
|
31
|
+
/** The compounding lift curve: root primary, then each promoted generation's primary + delta + anchor.
|
|
32
|
+
* `chain` is current→root (as returned by walkToRoot); we reverse to read root→current. */
|
|
33
|
+
function computeLiftCurve(chain, rootPrimary) {
|
|
34
|
+
const rootFirst = [...chain].reverse();
|
|
35
|
+
const curve = [];
|
|
36
|
+
let running = rootPrimary;
|
|
37
|
+
for (const c of rootFirst) {
|
|
38
|
+
if (c.verdict === 'ROOT') {
|
|
39
|
+
curve.push({ generation: c.generation, primary: rootPrimary, delta: 0, anchor: c.anchorScore });
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
running += c.primaryDelta;
|
|
43
|
+
curve.push({ generation: c.generation, primary: running, delta: c.primaryDelta, anchor: c.anchorScore });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return curve;
|
|
47
|
+
}
|
|
48
|
+
/** Convenience: a single point (used when composing a curve incrementally). */
|
|
49
|
+
function liftPoint(generation, primary, delta, anchor) {
|
|
50
|
+
return { generation, primary, delta, anchor };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=lineage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lineage.js","sourceRoot":"","sources":["../../src/lineage.ts"],"names":[],"mappings":";;;AAkCA,4CAaC;AAGD,8BAEC;AA9CD,MAAa,oBAAoB;IACd,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IAE5D,KAAK,CAAC,MAAM,CAAC,MAAqB;QAChC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,EAAU;QAClB,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/B,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7B,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,EAAU;QACzB,MAAM,KAAK,GAAoB,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;QACvC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;YACvB,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QACzE,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,KAAK,CAAC,IAAI;QACR,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF;AAxBD,oDAwBC;AAED;4FAC4F;AAC5F,SAAgB,gBAAgB,CAAC,KAAsB,EAAE,WAAmB;IAC1E,MAAM,SAAS,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;IACvC,MAAM,KAAK,GAAc,EAAE,CAAC;IAC5B,IAAI,OAAO,GAAG,WAAW,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAClG,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,CAAC,CAAC,YAAY,CAAC;YAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAC3G,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,+EAA+E;AAC/E,SAAgB,SAAS,CAAC,UAAkB,EAAE,OAAe,EAAE,KAAa,EAAE,MAAqB;IACjG,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.canon = canon;
|
|
4
|
+
exports.makeSigner = makeSigner;
|
|
5
|
+
exports.verifyReceipt = verifyReceipt;
|
|
6
|
+
// @metaharness/flywheel — Ed25519 receipts. Every promotion is signed; a receiver VERIFIES the
|
|
7
|
+
// signature with the embedded public key. Trust comes from the verifiable signature, not from the
|
|
8
|
+
// producer — so a lineage can be replayed and audited with no access to the machine that made it.
|
|
9
|
+
const node_crypto_1 = require("node:crypto");
|
|
10
|
+
/** Deterministic, sorted-key JSON canonicalization — the exact bytes that get signed. */
|
|
11
|
+
function canon(v) {
|
|
12
|
+
if (v === null || typeof v !== 'object')
|
|
13
|
+
return JSON.stringify(v);
|
|
14
|
+
if (Array.isArray(v))
|
|
15
|
+
return `[${v.map(canon).join(',')}]`;
|
|
16
|
+
const o = v;
|
|
17
|
+
return `{${Object.keys(o).sort().map((k) => `${JSON.stringify(k)}:${canon(o[k])}`).join(',')}}`;
|
|
18
|
+
}
|
|
19
|
+
/** A per-process Ed25519 signer. For production, wrap a secret-backed or HSM key behind the same
|
|
20
|
+
* {@link Signer} interface — the flywheel core never sees the private key. */
|
|
21
|
+
function makeSigner() {
|
|
22
|
+
const kp = (0, node_crypto_1.generateKeyPairSync)('ed25519');
|
|
23
|
+
const pub = kp.publicKey.export({ type: 'spki', format: 'der' }).toString('base64');
|
|
24
|
+
return {
|
|
25
|
+
publicKey: () => pub,
|
|
26
|
+
sign: (payload) => ({
|
|
27
|
+
payload,
|
|
28
|
+
signature: (0, node_crypto_1.sign)(null, Buffer.from(canon(payload)), kp.privateKey).toString('base64'),
|
|
29
|
+
publicKey: pub,
|
|
30
|
+
alg: 'ed25519',
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Independently verify a receipt — recompute canon, check the signature against the EMBEDDED key. */
|
|
35
|
+
function verifyReceipt(r) {
|
|
36
|
+
try {
|
|
37
|
+
const pub = (0, node_crypto_1.createPublicKey)({ key: Buffer.from(r.publicKey, 'base64'), format: 'der', type: 'spki' });
|
|
38
|
+
return (0, node_crypto_1.verify)(null, Buffer.from(canon(r.payload)), pub, Buffer.from(r.signature, 'base64'));
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=receipts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipts.js","sourceRoot":"","sources":["../../src/receipts.ts"],"names":[],"mappings":";;AAOA,sBAKC;AAID,gCAYC;AAGD,sCAOC;AAtCD,+FAA+F;AAC/F,kGAAkG;AAClG,kGAAkG;AAClG,6CAAuH;AAGvH,yFAAyF;AACzF,SAAgB,KAAK,CAAC,CAAU;IAC9B,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAClE,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAC3D,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAClG,CAAC;AAED;+EAC+E;AAC/E,SAAgB,UAAU;IACxB,MAAM,EAAE,GAAG,IAAA,iCAAmB,EAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAI,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAChG,OAAO;QACL,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG;QACpB,IAAI,EAAE,CAAC,OAAgC,EAAoB,EAAE,CAAC,CAAC;YAC7D,OAAO;YACP,SAAS,EAAE,IAAA,kBAAM,EAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;YACtF,SAAS,EAAE,GAAG;YACd,GAAG,EAAE,SAAS;SACf,CAAC;KACH,CAAC;AACJ,CAAC;AAED,sGAAsG;AACtG,SAAgB,aAAa,CAAC,CAAmB;IAC/C,IAAI,CAAC;QACH,MAAM,GAAG,GAAc,IAAA,6BAAe,EAAC,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QACjH,OAAO,IAAA,oBAAQ,EAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|