skalpel 4.0.55 → 4.0.56
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/first-run.mjs +5 -1
- package/insights.mjs +8 -3
- package/package.json +1 -1
- package/verify-safeguards.test.mjs +24 -12
package/first-run.mjs
CHANGED
|
@@ -586,7 +586,11 @@ export function assignVariant(home, env = process.env) {
|
|
|
586
586
|
return forced;
|
|
587
587
|
}
|
|
588
588
|
if (state.variant === "reveal" || state.variant === "holdout") return state.variant;
|
|
589
|
-
|
|
589
|
+
// DEFAULT: everyone gets the reveal (founder decision 2026-07-14 — "everything off dark, to prod").
|
|
590
|
+
// The 50/50 holdout A/B is retired for new installs; the SKALPEL_FIRST_RUN_VARIANT override above
|
|
591
|
+
// still forces either arm (tests / a future re-run of the experiment), and previously-assigned
|
|
592
|
+
// holdout users keep their recorded arm (the persisted-state branch above) so old data stays clean.
|
|
593
|
+
const variant = "reveal";
|
|
590
594
|
state.variant = variant;
|
|
591
595
|
state.assigned_at = new Date().toISOString();
|
|
592
596
|
writeState(home, state);
|
package/insights.mjs
CHANGED
|
@@ -59,7 +59,7 @@ export function verifyConfigArmed() {
|
|
|
59
59
|
return null;
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
// revealEnabled(env) — is the USER-VISIBLE reveal armed? env override > consented config > default
|
|
62
|
+
// revealEnabled(env) — is the USER-VISIBLE reveal armed? env override > consented config > default ON.
|
|
63
63
|
// SKALPEL_VERIFY_SHADOW is deliberately NOT consulted here: it arms only the DARK log-only shadow (no
|
|
64
64
|
// reveal); the spawn gate ORs it in separately (verifySpawnArmed). Wrapped so it can never throw.
|
|
65
65
|
export function revealEnabled(env) {
|
|
@@ -67,11 +67,16 @@ export function revealEnabled(env) {
|
|
|
67
67
|
const envOverride = parseArmToken((env || {}).SKALPEL_VERIFY_REVEAL);
|
|
68
68
|
if (envOverride !== null) return envOverride; // 1) dev/CI env override wins
|
|
69
69
|
const cfg = verifyConfigArmed();
|
|
70
|
-
if (cfg !== null) return cfg; // 2) consented config
|
|
70
|
+
if (cfg !== null) return cfg; // 2) consented config (skalpel verify on|off still rules)
|
|
71
71
|
} catch {
|
|
72
72
|
/* fall through to default */
|
|
73
73
|
}
|
|
74
|
-
|
|
74
|
+
// 3) DEFAULT ON — founder decision 2026-07-14 ("everything off dark, to prod"): the live catch +
|
|
75
|
+
// reveal ship ARMED out of the box. The safeguards that make this sane are unchanged and still
|
|
76
|
+
// override this default: `skalpel verify off` (consented config, step 2), the env kill (step 1),
|
|
77
|
+
// the flake double-confirm before any red, recorded-failure corroboration on Codex, and the
|
|
78
|
+
// adjudicated auto-darken (precision < 90% over ≥ 10 verdicts silently re-darkens the reveal).
|
|
79
|
+
return true;
|
|
75
80
|
}
|
|
76
81
|
// verifySpawnArmed(env) — should the per-turn hook SPAWN the detached shadow worker at all? True when the
|
|
77
82
|
// reveal is armed OR the dev log-only shadow (SKALPEL_VERIFY_SHADOW=1) is set. This is the single gate the
|
package/package.json
CHANGED
|
@@ -37,11 +37,11 @@ beforeEach(() => {
|
|
|
37
37
|
});
|
|
38
38
|
const writeCfg = (o) => writeFileSync(CLIENT_JSON_PATH, JSON.stringify(o));
|
|
39
39
|
|
|
40
|
-
// ---- arming resolver precedence: env > config >
|
|
41
|
-
test("arming —
|
|
40
|
+
// ---- arming resolver precedence: env > config > DEFAULT ON (founder 2026-07-14, off-dark) -------
|
|
41
|
+
test("arming — DEFAULT ON when config absent and env unset (ships armed)", () => {
|
|
42
42
|
assert.equal(verifyConfigArmed(), null);
|
|
43
|
-
assert.equal(revealEnabled({}),
|
|
44
|
-
assert.equal(verifySpawnArmed({}),
|
|
43
|
+
assert.equal(revealEnabled({}), true);
|
|
44
|
+
assert.equal(verifySpawnArmed({}), true);
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
test("arming — consented config on/off", () => {
|
|
@@ -59,17 +59,29 @@ test("arming — env override BEATS config in both directions", () => {
|
|
|
59
59
|
assert.equal(revealEnabled({ SKALPEL_VERIFY_REVEAL: "1" }), true, "env on beats config off");
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
-
test("arming — SKALPEL_VERIFY_SHADOW arms the spawn
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
test("arming — SKALPEL_VERIFY_SHADOW arms the spawn even when the user turned the reveal OFF", () => {
|
|
63
|
+
// The meaningful spawn-vs-reveal split now lives on the DECLINED path: with config verify:"off",
|
|
64
|
+
// the reveal stays dark but the dev/CI log-only shadow env can still arm the spawn.
|
|
65
|
+
writeCfg({ verify: "off" });
|
|
66
|
+
assert.equal(
|
|
67
|
+
revealEnabled({ SKALPEL_VERIFY_SHADOW: "1" }),
|
|
68
|
+
false,
|
|
69
|
+
"user's off still rules the reveal",
|
|
70
|
+
);
|
|
71
|
+
assert.equal(
|
|
72
|
+
verifySpawnArmed({ SKALPEL_VERIFY_SHADOW: "1" }),
|
|
73
|
+
true,
|
|
74
|
+
"log-only shadow still spawns",
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("arming — fail-open: a corrupt client.json never throws, resolves to the DEFAULT (on)", () => {
|
|
69
79
|
writeFileSync(CLIENT_JSON_PATH, "{ this is not json");
|
|
70
80
|
assert.doesNotThrow(() => revealEnabled({}));
|
|
71
81
|
assert.equal(verifyConfigArmed(), null);
|
|
72
|
-
|
|
82
|
+
// Unreadable config falls through to the ships-armed default. A user who declined keeps OFF via a
|
|
83
|
+
// VALID config (previous test); the corrupt-file edge resolves like a fresh install.
|
|
84
|
+
assert.equal(revealEnabled({}), true);
|
|
73
85
|
});
|
|
74
86
|
|
|
75
87
|
// ---- adjudication ledger + <90% auto-darken derivation ------------------------------------------
|