@rotifer/playground 0.23.2 → 0.25.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.
@@ -0,0 +1,205 @@
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.autoPublishGate = autoPublishGate;
37
+ exports.needsCompileBeforePublish = needsCompileBeforePublish;
38
+ exports.needsNetworkConfigBeforePublish = needsNetworkConfigBeforePublish;
39
+ exports.resolveWrapFidelity = resolveWrapFidelity;
40
+ exports.skipHintFor = skipHintFor;
41
+ exports.offerAutoPublish = offerAutoPublish;
42
+ const node_fs_1 = require("node:fs");
43
+ const node_path_1 = require("node:path");
44
+ const node_readline_1 = require("node:readline");
45
+ const display = __importStar(require("../utils/display.js"));
46
+ const palette_js_1 = require("../utils/palette.js");
47
+ const user_config_js_1 = require("../utils/user-config.js");
48
+ const auth_js_1 = require("../cloud/auth.js");
49
+ const publish_js_1 = require("../commands/publish.js");
50
+ /**
51
+ * Pure decision: should `wrap` ask about publishing?
52
+ *
53
+ * Ordered so the reported reason is the one the user can act on first. An
54
+ * explicit opt-out wins over everything (never second-guess it); a build
55
+ * environment is next because nothing else matters when nobody is watching;
56
+ * a Gene that cannot be published as-is (missing WASM, missing network
57
+ * config) outranks being signed out, because logging in would not fix either.
58
+ */
59
+ function autoPublishGate(input) {
60
+ if (!input.enabled)
61
+ return { offer: false, reason: "disabled-by-config" };
62
+ if (!input.interactive)
63
+ return { offer: false, reason: "non-interactive" };
64
+ if (input.needsWasm)
65
+ return { offer: false, reason: "needs-compile" };
66
+ if (input.needsNetworkConfig)
67
+ return { offer: false, reason: "needs-network-config" };
68
+ if (!input.loggedIn)
69
+ return { offer: false, reason: "not-logged-in" };
70
+ return { offer: true };
71
+ }
72
+ /** True when publishing this Gene would be rejected for a missing WASM artifact. */
73
+ function needsCompileBeforePublish(geneDir, fidelity) {
74
+ if (fidelity !== "Native")
75
+ return false;
76
+ return !(0, node_fs_1.existsSync)((0, node_path_1.join)(geneDir, "gene.ir.wasm"));
77
+ }
78
+ /**
79
+ * True when publishing this Gene would be rejected for an empty (or absent)
80
+ * `network.allowedDomains` — the exact check in publish.ts's
81
+ * publishSingleGene, duplicated here rather than imported because that
82
+ * function only reports the failure after asking the user to confirm; this
83
+ * runs before the question is asked at all.
84
+ *
85
+ * A missing or unparseable phenotype.json is not this function's problem to
86
+ * report — `false` here just means "don't block on network config", and
87
+ * whatever is actually wrong with the file surfaces from publishSingleGene
88
+ * itself if the user says yes.
89
+ */
90
+ function needsNetworkConfigBeforePublish(geneDir, fidelity) {
91
+ if (fidelity !== "Hybrid")
92
+ return false;
93
+ try {
94
+ const phenotype = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(geneDir, "phenotype.json"), "utf-8"));
95
+ const domains = phenotype?.network?.allowedDomains;
96
+ return !Array.isArray(domains) || domains.length === 0;
97
+ }
98
+ catch {
99
+ return false;
100
+ }
101
+ }
102
+ /**
103
+ * Which fidelity the auto-publish gate should judge a wrap by.
104
+ *
105
+ * `wrap`'s plain path (no --from-skill/--from-clawhub) loads an existing
106
+ * phenotype.json when re-wrapping a gene — e.g. to change --domain — and
107
+ * leaves its `fidelity` untouched. The CLI's `--fidelity` flag still defaults
108
+ * to "Wrapped" regardless. Passing that default straight to the gate made an
109
+ * existing Native gene with no compiled gene.ir.wasm show the publish prompt,
110
+ * accept a "yes", and only then fail inside publishSingleGene — found by an
111
+ * independent cursor-agent pyramid test run, 2026-08-31, which is also why
112
+ * this is a pure function rather than a PTY-driven E2E test: reproducing it
113
+ * needs a real TTY, and this repo's CI matrix runs both ubuntu-latest and
114
+ * macos-14, whose `script` binaries take incompatible arguments — a
115
+ * behavioural test for a one-line data-selection bug was the wrong layer.
116
+ *
117
+ * The on-disk phenotype wins whenever one was actually loaded; the CLI flag
118
+ * is truth only when there was nothing on disk to read.
119
+ */
120
+ function resolveWrapFidelity(phenotype, cliFidelity) {
121
+ return typeof phenotype.fidelity === "string" && phenotype.fidelity.length > 0
122
+ ? phenotype.fidelity
123
+ : cliFidelity;
124
+ }
125
+ /**
126
+ * The next step a skipped offer points at.
127
+ *
128
+ * Exported as a pure function because most skip reasons are unreachable from a
129
+ * spawned-CLI test: a child process never has a TTY, so `non-interactive`
130
+ * shadows every reason below it. Testing the message through the gate would
131
+ * quietly cover one branch and leave three unexercised.
132
+ */
133
+ function skipHintFor(reason, geneName, geneDir) {
134
+ if (reason === "needs-compile") {
135
+ return ` rotifer compile ${geneName} # required before publishing a Native gene`;
136
+ }
137
+ if (reason === "needs-network-config") {
138
+ const phenotypePath = geneDir ? (0, node_path_1.join)(geneDir, "phenotype.json") : `${geneName}/phenotype.json`;
139
+ return ` Add network.allowedDomains to ${phenotypePath}, then: rotifer publish ${geneName}`;
140
+ }
141
+ if (reason === "not-logged-in") {
142
+ return ` rotifer login # then: rotifer publish ${geneName}`;
143
+ }
144
+ return ` rotifer publish ${geneName} # upload to Rotifer Cloud`;
145
+ }
146
+ /**
147
+ * Ask, defaulting to yes. Empty input (a bare Enter) is the default — that is
148
+ * what makes it a default rather than a question with a suggested answer.
149
+ */
150
+ async function confirmPublish(geneName) {
151
+ console.log();
152
+ display.hint(palette_js_1.c.dim(`Publishing is on by default — turn it off with 'rotifer config set default-publish false'`));
153
+ const rl = (0, node_readline_1.createInterface)({ input: process.stdin, output: process.stdout });
154
+ const answer = await new Promise((resolve) => {
155
+ rl.question(`Publish '${geneName}' to Rotifer Cloud? [Y/n] `, (ans) => {
156
+ rl.close();
157
+ resolve(ans.trim().toLowerCase());
158
+ });
159
+ });
160
+ return answer === "" || answer === "y" || answer === "yes";
161
+ }
162
+ /**
163
+ * Run the offer. Returns whether the Gene was actually published, so callers
164
+ * can decide what to print next. Never throws: a wrap that succeeded must not
165
+ * be reported as failed because the optional upload afterwards did not work.
166
+ */
167
+ async function offerAutoPublish(opts) {
168
+ const { geneName, geneDir, fidelity } = opts;
169
+ const gate = autoPublishGate({
170
+ enabled: (0, user_config_js_1.shouldAutoPublish)(),
171
+ interactive: Boolean(process.stdin.isTTY) && !display.isJsonMode(),
172
+ loggedIn: (0, auth_js_1.isLoggedIn)(),
173
+ needsWasm: needsCompileBeforePublish(geneDir, fidelity),
174
+ needsNetworkConfig: needsNetworkConfigBeforePublish(geneDir, fidelity),
175
+ });
176
+ // Printed for every skip, opt-out included: turning off the *prompt* is not
177
+ // a request to hide that publishing exists, and this line is what `wrap`
178
+ // already printed before the offer was wired in.
179
+ if (!gate.offer) {
180
+ display.hint(skipHintFor(gate.reason, geneName, geneDir));
181
+ return false;
182
+ }
183
+ if (!(await confirmPublish(geneName))) {
184
+ console.log();
185
+ display.hint(` rotifer publish ${geneName} # upload later`);
186
+ return false;
187
+ }
188
+ console.log();
189
+ try {
190
+ const creds = await (0, auth_js_1.requireAuth)();
191
+ const result = await (0, publish_js_1.publishSingleGene)(geneName, geneDir, creds, {});
192
+ if (result.status === "failed") {
193
+ display.warn(`Publish failed: ${result.error ?? "unknown error"}`);
194
+ display.hint(` rotifer publish ${geneName} # retry`);
195
+ return false;
196
+ }
197
+ return true;
198
+ }
199
+ catch (e) {
200
+ display.warn(`Publish failed: ${e instanceof Error ? e.message : String(e)}`);
201
+ display.hint(` rotifer publish ${geneName} # retry`);
202
+ return false;
203
+ }
204
+ }
205
+ //# sourceMappingURL=auto-publish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-publish.js","sourceRoot":"","sources":["../../src/publish/auto-publish.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The §5.1 fitness formula, in one place.
3
+ *
4
+ * F(g) = [S_r · ln(1 + C_util) · (1 + R_rob)] / [L · Resource_Cost]
5
+ *
6
+ * `L` and `Resource_Cost` in the spec are the *raw* latency and cost, so both
7
+ * sit in the denominator and a slower, costlier gene scores lower. The
8
+ * implementation does not divide by raw values — an unbounded denominator
9
+ * drives F(g) to zero for any gene with a realistic latency, which is what
10
+ * ADR-215 P1 set out to avoid. It normalizes each into a (0, 1] score first:
11
+ *
12
+ * L_score = 1 / (1 + avg_latency_ms / LATENCY_SCALE_MS)
13
+ * Cost_score = 1 / (1 + avg_cost / RESOURCE_SCALE_UNITS)
14
+ *
15
+ * Those scores are already *inverted* — lower latency means a score nearer 1 —
16
+ * so they belong in the numerator. Dividing by them, as this code did until
17
+ * this module existed, flips the penalty into a reward: F(g) rose with latency
18
+ * and every gene slower than a second pinned at the 1.0 cap. The regression
19
+ * tests in `tests/unit/fitness-formula.test.ts` hold the direction.
20
+ */
21
+ /**
22
+ * Latency at which L_score halves. `[N]` — provisional, uncalibrated.
23
+ *
24
+ * ADR-318 D2 replaces both constants with `L_ref` / `Cost_ref` — the season
25
+ * median for the gene's own domain and fidelity, which is what makes F(g)
26
+ * dimensionless and comparable across bindings — and marks their values `[N]`
27
+ * pending ABM / measured calibration under RFC-001 §0. That reference scale
28
+ * needs a season-median pipeline that does not exist yet (v0.9.3 #6); these two
29
+ * fixed constants are the stand-ins until it does.
30
+ */
31
+ export declare const LATENCY_SCALE_MS = 1000;
32
+ /**
33
+ * Resource cost (fuel units) at which Cost_score halves. `[N]` — provisional.
34
+ *
35
+ * Badly out of scale, and known to be: ADR-318 recorded both constants as
36
+ * guesses, and measured 7.7e9 fuel on a leaderboard gene from its reported
37
+ * efficiency score. Locally, three
38
+ * sandbox runs each over the bundled Native corpus burn 1.2M–83M fuel
39
+ * (url-extractor 1.22M, debugger 1.44M, citation-manager 1.80M,
40
+ * particle-spatial 83.3M), so at a 10k scale every real gene lands at a
41
+ * Cost_score of 0.008 or below and F(g) collapses to ~0.003 — far under
42
+ * τ = 0.3. While it divided, the same mismatch was invisible: it inflated F(g)
43
+ * past the 1.0 cap instead. This is why `arena submit` does not gate on F(g)
44
+ * while `hasCompleteFitnessInputs` is false: a threshold comparison against a
45
+ * provisional scale is not an admission decision. Picking new values is a
46
+ * protocol-parameter change under RFC-001 §0, not a code cleanup.
47
+ */
48
+ export declare const RESOURCE_SCALE_UNITS = 10000;
49
+ export interface FitnessInputs {
50
+ /** S_r — fraction of evaluation runs that passed, in [0, 1]. */
51
+ successRate: number;
52
+ /** Mean wall-clock latency across the evaluation runs, in milliseconds. */
53
+ avgLatencyMs: number;
54
+ /** Mean fuel consumed across the evaluation runs. */
55
+ avgResourceCost: number;
56
+ /** C_util — input-space coverage in [0, 1]. */
57
+ coverage: number;
58
+ /** R_rob — adversarial robustness in [0, 1]. */
59
+ robustness: number;
60
+ }
61
+ export interface FitnessBreakdown {
62
+ /**
63
+ * F(g), in (0, 2·ln 2] ≈ (0, 1.386].
64
+ *
65
+ * Not capped. The old `min(1.0)` was there because dividing by the
66
+ * efficiency scores made the value unbounded — with them multiplied the
67
+ * formula is bounded by its own factors, and ADR-318 D2 drops the cap for
68
+ * exactly that reason: a cap erases the difference between everything above
69
+ * it, which is what made six leaderboard genes tie at a perfect 1.000.
70
+ */
71
+ value: number;
72
+ /** L_score — 1 at zero latency, falling monotonically as latency rises. */
73
+ latencyScore: number;
74
+ /** Cost_score — 1 at zero cost, falling monotonically as cost rises. */
75
+ resourceEfficiency: number;
76
+ }
77
+ /** L_score: 1 at zero latency, strictly decreasing, never zero. */
78
+ export declare function latencyScoreFor(avgLatencyMs: number): number;
79
+ /** Cost_score: 1 at zero cost, strictly decreasing, never zero. */
80
+ export declare function resourceEfficiencyFor(avgResourceCost: number): number;
81
+ /**
82
+ * F(g) from one batch of evaluation measurements.
83
+ *
84
+ * Multiplicative throughout: a zero in any factor collapses the score, with no
85
+ * mutual compensation between a gene's strengths and its weaknesses.
86
+ */
87
+ export declare function computeBaseFitness(inputs: FitnessInputs): FitnessBreakdown;
88
+ //# sourceMappingURL=fitness-formula.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fitness-formula.d.ts","sourceRoot":"","sources":["../../src/utils/fitness-formula.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAE3C,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,eAAe,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;OAQG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,mEAAmE;AACnE,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,gBAAgB,CAU1E"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ /**
3
+ * The §5.1 fitness formula, in one place.
4
+ *
5
+ * F(g) = [S_r · ln(1 + C_util) · (1 + R_rob)] / [L · Resource_Cost]
6
+ *
7
+ * `L` and `Resource_Cost` in the spec are the *raw* latency and cost, so both
8
+ * sit in the denominator and a slower, costlier gene scores lower. The
9
+ * implementation does not divide by raw values — an unbounded denominator
10
+ * drives F(g) to zero for any gene with a realistic latency, which is what
11
+ * ADR-215 P1 set out to avoid. It normalizes each into a (0, 1] score first:
12
+ *
13
+ * L_score = 1 / (1 + avg_latency_ms / LATENCY_SCALE_MS)
14
+ * Cost_score = 1 / (1 + avg_cost / RESOURCE_SCALE_UNITS)
15
+ *
16
+ * Those scores are already *inverted* — lower latency means a score nearer 1 —
17
+ * so they belong in the numerator. Dividing by them, as this code did until
18
+ * this module existed, flips the penalty into a reward: F(g) rose with latency
19
+ * and every gene slower than a second pinned at the 1.0 cap. The regression
20
+ * tests in `tests/unit/fitness-formula.test.ts` hold the direction.
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.RESOURCE_SCALE_UNITS = exports.LATENCY_SCALE_MS = void 0;
24
+ exports.latencyScoreFor = latencyScoreFor;
25
+ exports.resourceEfficiencyFor = resourceEfficiencyFor;
26
+ exports.computeBaseFitness = computeBaseFitness;
27
+ /**
28
+ * Latency at which L_score halves. `[N]` — provisional, uncalibrated.
29
+ *
30
+ * ADR-318 D2 replaces both constants with `L_ref` / `Cost_ref` — the season
31
+ * median for the gene's own domain and fidelity, which is what makes F(g)
32
+ * dimensionless and comparable across bindings — and marks their values `[N]`
33
+ * pending ABM / measured calibration under RFC-001 §0. That reference scale
34
+ * needs a season-median pipeline that does not exist yet (v0.9.3 #6); these two
35
+ * fixed constants are the stand-ins until it does.
36
+ */
37
+ exports.LATENCY_SCALE_MS = 1000;
38
+ /**
39
+ * Resource cost (fuel units) at which Cost_score halves. `[N]` — provisional.
40
+ *
41
+ * Badly out of scale, and known to be: ADR-318 recorded both constants as
42
+ * guesses, and measured 7.7e9 fuel on a leaderboard gene from its reported
43
+ * efficiency score. Locally, three
44
+ * sandbox runs each over the bundled Native corpus burn 1.2M–83M fuel
45
+ * (url-extractor 1.22M, debugger 1.44M, citation-manager 1.80M,
46
+ * particle-spatial 83.3M), so at a 10k scale every real gene lands at a
47
+ * Cost_score of 0.008 or below and F(g) collapses to ~0.003 — far under
48
+ * τ = 0.3. While it divided, the same mismatch was invisible: it inflated F(g)
49
+ * past the 1.0 cap instead. This is why `arena submit` does not gate on F(g)
50
+ * while `hasCompleteFitnessInputs` is false: a threshold comparison against a
51
+ * provisional scale is not an admission decision. Picking new values is a
52
+ * protocol-parameter change under RFC-001 §0, not a code cleanup.
53
+ */
54
+ exports.RESOURCE_SCALE_UNITS = 10_000;
55
+ /** L_score: 1 at zero latency, strictly decreasing, never zero. */
56
+ function latencyScoreFor(avgLatencyMs) {
57
+ return 1.0 / (1.0 + Math.max(avgLatencyMs, 0) / exports.LATENCY_SCALE_MS);
58
+ }
59
+ /** Cost_score: 1 at zero cost, strictly decreasing, never zero. */
60
+ function resourceEfficiencyFor(avgResourceCost) {
61
+ return 1.0 / (1.0 + Math.max(avgResourceCost, 0) / exports.RESOURCE_SCALE_UNITS);
62
+ }
63
+ /**
64
+ * F(g) from one batch of evaluation measurements.
65
+ *
66
+ * Multiplicative throughout: a zero in any factor collapses the score, with no
67
+ * mutual compensation between a gene's strengths and its weaknesses.
68
+ */
69
+ function computeBaseFitness(inputs) {
70
+ const latencyScore = latencyScoreFor(inputs.avgLatencyMs);
71
+ const resourceEfficiency = resourceEfficiencyFor(inputs.avgResourceCost);
72
+ const quality = inputs.successRate * Math.log1p(inputs.coverage) * (1 + inputs.robustness);
73
+ // Multiplied, not divided: L_score and Cost_score are already inverted, so
74
+ // multiplying by them is what makes slower and costlier score lower. No cap —
75
+ // every factor is bounded, so the product is too.
76
+ const value = quality * latencyScore * resourceEfficiency;
77
+ return { value, latencyScore, resourceEfficiency };
78
+ }
79
+ //# sourceMappingURL=fitness-formula.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fitness-formula.js","sourceRoot":"","sources":["../../src/utils/fitness-formula.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;;;AA8DH,0CAEC;AAGD,sDAEC;AAQD,gDAUC;AArFD;;;;;;;;;GASG;AACU,QAAA,gBAAgB,GAAG,IAAI,CAAC;AACrC;;;;;;;;;;;;;;;GAeG;AACU,QAAA,oBAAoB,GAAG,MAAM,CAAC;AAgC3C,mEAAmE;AACnE,SAAgB,eAAe,CAAC,YAAoB;IAClD,OAAO,GAAG,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,GAAG,wBAAgB,CAAC,CAAC;AACpE,CAAC;AAED,mEAAmE;AACnE,SAAgB,qBAAqB,CAAC,eAAuB;IAC3D,OAAO,GAAG,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,GAAG,4BAAoB,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,MAAqB;IACtD,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC1D,MAAM,kBAAkB,GAAG,qBAAqB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IACzE,MAAM,OAAO,GACX,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7E,2EAA2E;IAC3E,8EAA8E;IAC9E,kDAAkD;IAClD,MAAM,KAAK,GAAG,OAAO,GAAG,YAAY,GAAG,kBAAkB,CAAC;IAC1D,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,CAAC;AACrD,CAAC"}
@@ -1,6 +1,10 @@
1
1
  export interface UserConfig {
2
2
  "update-check"?: boolean;
3
+ /** Pre-multi-package rollback target; still written for @rotifer/playground
4
+ * so an older CLI and `rotifer config get last-version` keep working. */
3
5
  "last-version"?: string;
6
+ /** Per-package rollback targets, written by `rotifer self-update`. */
7
+ "last-versions"?: Record<string, string>;
4
8
  "default-publish"?: boolean;
5
9
  }
6
10
  export declare function isValidKey(key: string): key is keyof UserConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"user-config.d.ts","sourceRoot":"","sources":["../../src/utils/user-config.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,UAAU;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAUD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,MAAM,UAAU,CAE/D;AAED,wBAAgB,cAAc,IAAI,UAAU,CAQ3C;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAGvD;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,UAAU,GAAG,MAAM,CAIhE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAQ7E;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAO3C"}
1
+ {"version":3,"file":"user-config.d.ts","sourceRoot":"","sources":["../../src/utils/user-config.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,UAAU;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;8EAC0E;IAC1E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAYD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,MAAM,UAAU,CAE/D;AAED,wBAAgB,cAAc,IAAI,UAAU,CAQ3C;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAGvD;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,UAAU,GAAG,MAAM,CAIhE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAQ7E;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAO3C"}
@@ -18,6 +18,8 @@ function getUserConfigFile() {
18
18
  const DEFAULTS = {
19
19
  "update-check": true,
20
20
  "last-version": "",
21
+ // Not exposed through `rotifer config` (see VALID_KEYS) — self-update owns it.
22
+ "last-versions": {},
21
23
  "default-publish": true,
22
24
  };
23
25
  const VALID_KEYS = new Set(["update-check", "last-version", "default-publish"]);
@@ -1 +1 @@
1
- {"version":3,"file":"user-config.js","sourceRoot":"","sources":["../../src/utils/user-config.ts"],"names":[],"mappings":";;AA0BA,gCAEC;AAED,wCAQC;AAED,wCAGC;AAED,gDAIC;AAED,gDAQC;AAED,8CAOC;AApED,qCAA6E;AAC7E,yCAAiC;AACjC,qCAAkC;AAElC,SAAS,YAAY;IACnB,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAA,gBAAI,EAAC,IAAA,iBAAO,GAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,IAAA,gBAAI,EAAC,YAAY,EAAE,EAAE,aAAa,CAAC,CAAC;AAC7C,CAAC;AAQD,MAAM,QAAQ,GAAyB;IACrC,cAAc,EAAE,IAAI;IACpB,cAAc,EAAE,EAAE;IAClB,iBAAiB,EAAE,IAAI;CACxB,CAAC;AAEF,MAAM,UAAU,GAAG,IAAI,GAAG,CAAmB,CAAC,cAAc,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAElG,SAAgB,UAAU,CAAC,GAAW;IACpC,OAAO,UAAU,CAAC,GAAG,CAAC,GAAuB,CAAC,CAAC;AACjD,CAAC;AAED,SAAgB,cAAc;IAC5B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,iBAAiB,EAAE,CAAC;QAC9B,IAAI,IAAA,oBAAU,EAAC,CAAC,CAAC,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,kCAAkC,CAAC,CAAC;IAC9C,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAgB,cAAc,CAAC,MAAkB;IAC/C,IAAA,mBAAS,EAAC,YAAY,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,IAAA,uBAAa,EAAC,iBAAiB,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC7E,CAAC;AAED,SAAgB,kBAAkB,CAAC,GAAqB;IACtD,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED,SAAgB,kBAAkB,CAAC,GAAqB,EAAE,KAAa;IACrE,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,IAAI,GAAG,KAAK,cAAc,IAAI,GAAG,KAAK,iBAAiB,EAAE,CAAC;QACxD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,GAAG,CAAC;IAClD,CAAC;SAAM,CAAC;QACL,MAAkC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnD,CAAC;IACD,cAAc,CAAC,MAAM,CAAC,CAAC;AACzB,CAAC;AAED,SAAgB,iBAAiB;IAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IACrD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,WAAW,KAAK,OAAO,IAAI,WAAW,KAAK,GAAG,CAAC;IACxD,CAAC;IACD,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,OAAO,MAAM,CAAC,iBAAiB,CAAC,IAAI,QAAQ,CAAC,iBAAiB,CAAC,CAAC;AAClE,CAAC"}
1
+ {"version":3,"file":"user-config.js","sourceRoot":"","sources":["../../src/utils/user-config.ts"],"names":[],"mappings":";;AAgCA,gCAEC;AAED,wCAQC;AAED,wCAGC;AAED,gDAIC;AAED,gDAQC;AAED,8CAOC;AA1ED,qCAA6E;AAC7E,yCAAiC;AACjC,qCAAkC;AAElC,SAAS,YAAY;IACnB,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAA,gBAAI,EAAC,IAAA,iBAAO,GAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,IAAA,gBAAI,EAAC,YAAY,EAAE,EAAE,aAAa,CAAC,CAAC;AAC7C,CAAC;AAYD,MAAM,QAAQ,GAAyB;IACrC,cAAc,EAAE,IAAI;IACpB,cAAc,EAAE,EAAE;IAClB,+EAA+E;IAC/E,eAAe,EAAE,EAAE;IACnB,iBAAiB,EAAE,IAAI;CACxB,CAAC;AAEF,MAAM,UAAU,GAAG,IAAI,GAAG,CAAmB,CAAC,cAAc,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAElG,SAAgB,UAAU,CAAC,GAAW;IACpC,OAAO,UAAU,CAAC,GAAG,CAAC,GAAuB,CAAC,CAAC;AACjD,CAAC;AAED,SAAgB,cAAc;IAC5B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,iBAAiB,EAAE,CAAC;QAC9B,IAAI,IAAA,oBAAU,EAAC,CAAC,CAAC,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,kCAAkC,CAAC,CAAC;IAC9C,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAgB,cAAc,CAAC,MAAkB;IAC/C,IAAA,mBAAS,EAAC,YAAY,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,IAAA,uBAAa,EAAC,iBAAiB,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC7E,CAAC;AAED,SAAgB,kBAAkB,CAAC,GAAqB;IACtD,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED,SAAgB,kBAAkB,CAAC,GAAqB,EAAE,KAAa;IACrE,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,IAAI,GAAG,KAAK,cAAc,IAAI,GAAG,KAAK,iBAAiB,EAAE,CAAC;QACxD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,GAAG,CAAC;IAClD,CAAC;SAAM,CAAC;QACL,MAAkC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnD,CAAC;IACD,cAAc,CAAC,MAAM,CAAC,CAAC;AACzB,CAAC;AAED,SAAgB,iBAAiB;IAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IACrD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,WAAW,KAAK,OAAO,IAAI,WAAW,KAAK,GAAG,CAAC;IACxD,CAAC;IACD,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,OAAO,MAAM,CAAC,iBAAiB,CAAC,IAAI,QAAQ,CAAC,iBAAiB,CAAC,CAAC;AAClE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rotifer/playground",
3
- "version": "0.23.2",
3
+ "version": "0.25.0",
4
4
  "description": "Rotifer Protocol Playground — local development environment for gene development, Arena competition, and protocol simulation",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Rotifer Protocol Contributors",
@@ -87,10 +87,10 @@
87
87
  },
88
88
  "optionalDependencies": {
89
89
  "@rolldown/binding-linux-x64-gnu": "1.1.1",
90
- "@rotifer/playground-darwin-arm64": "0.23.2",
91
- "@rotifer/playground-darwin-x64": "0.23.2",
92
- "@rotifer/playground-linux-x64-gnu": "0.23.2",
93
- "@rotifer/playground-win32-x64-msvc": "0.23.2"
90
+ "@rotifer/playground-darwin-arm64": "0.25.0",
91
+ "@rotifer/playground-darwin-x64": "0.25.0",
92
+ "@rotifer/playground-linux-x64-gnu": "0.25.0",
93
+ "@rotifer/playground-win32-x64-msvc": "0.25.0"
94
94
  },
95
95
  "engines": {
96
96
  "node": ">=22.18.0"