skalpel 4.0.55 → 4.0.57

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 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
- const variant = Math.random() < 0.5 ? "reveal" : "holdout";
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 off.
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
- return false; // 3) DEFAULT OFF
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skalpel",
3
- "version": "4.0.55",
3
+ "version": "4.0.57",
4
4
  "description": "Behavioral graph for AI-assisted coding — learns how you work and steers Claude Code + Codex in real time.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,22 +9,31 @@
9
9
  // that verifiably happened; else
10
10
  // • the current steer's plain-English label (what skalpel is doing now) — a description, not a number;
11
11
  // else
12
- // • the ALWAYS-ON presence line, "skalpel · N steers[ · <time clause>]".
13
- // N = steers ACTUALLY applied (fired + not suppressed), counted from the append-only
14
- // ~/.skalpel/steers.ndjsona fresh install reads "0 steers", present, never blank. The optional
15
- // TIME clause is chosen by BASELINE_TIME_MODE (Ryan flips one constant):
16
- // · <Xm> caught the CUMULATIVE LIFETIME sum of every real MEASURED red→green delta (each caught
17
- // false "done" and the moment that SAME proof, that SAME session, was later logged PASS — real
18
- // timestamps; reuses ledger.mjs's buildFixDeltas logic). ALWAYS-ON once real catches exist (it is
19
- // skalpel's terminal presence never gated/hidden). A measured total, NEVER an estimate; a catch
20
- // with no later PASS adds 0. Cumulative framing (not present-tense) keeps it honest for old data.
21
- // · ~Xm saved Raahil's #609 estimate: (applied steers) × (the user's OWN median loop cost from
22
- // their causal graph). A `~`-prefixed ESTIMATE grounded in their own data, shown only when
23
- // saved_min > 0. Never a server wall-clock number; never "skalpel saved you X" as a fact.
12
+ // • the ALWAYS-ON AMBIENT line: the `🔬 skalpel` wordmark, a dim em-dash, then a COMPOSED body of only
13
+ // the clauses that have real value (see THE INSTRUMENT LINE below). Nothing yet reads
14
+ // "🔬 skalpel — watching your agent's claims" present, quiet, never "0 steers".
15
+ //
16
+ // THE INSTRUMENT LINE (redesign, 2026-07-14 founder: "the bottom of my terminal is ugly, zero
17
+ // aesthetic, zero gratifying feeling" about `skalpel · 0 steers`). Typography + hierarchy, not
18
+ // decoration. The ambient body composes, in order, ONLY the clauses whose value exists:
19
+ // clean → "N claims verified[ · Xm caught][ · N steers]"
20
+ // caught → "N checked · M false[ · Xm caught][ · N steers]"
21
+ // nothing "watching your agent's claims" (dim quiet confidence, NOT a dead zero)
22
+ // · <Xm> caught the CUMULATIVE LIFETIME sum of every real MEASURED red→green delta (each caught
23
+ // false "done" and the moment that SAME proof, that SAME session, was later logged PASS — real
24
+ // timestamps; reuses ledger.mjs's buildFixDeltas logic). A measured total, NEVER an estimate; a
25
+ // catch with no later PASS adds 0. Cumulative framing (not present-tense) keeps it honest.
26
+ // · N steers — steers ACTUALLY applied (fired + not suppressed), counted from the append-only
27
+ // ~/.skalpel/steers.ndjson.
28
+ // IMMUTABLE ALWAYS-ON COUNTER (owner product decision — unchanged in substance): the counter surfaces
29
+ // (`N steers` when > 0, the measured `Xm caught` whenever it has a value) remain ALWAYS-ON on the
30
+ // ambient line — never gated, never hidden. This redesign only removes DEAD ZEROS: a zero-value clause
31
+ // is omitted, and the always-on presence is carried by the wordmark + the watching line instead of a
32
+ // literal "0 steers". "0 steers" never renders again.
33
+ // COLOR DISCIPLINE (Ive restraint): wordmark bold; live numbers cyan; chrome words dim. The skalpel red
34
+ // is ONE accent used ONCE — only on the `M false` clause when lies > 0. Semantic color only.
24
35
  // Every value here is a real count or a real measured timestamp delta (or a clearly `~`-marked estimate).
25
- // NOTE: this always-on presence line is a DELIBERATE new behavior origin/main's clean-idle bar emitted
26
- // ZERO bytes; this emits "skalpel · 0 steers" (Ryan: always-on presence, non-negotiable). Byte-identical
27
- // to origin/main is preserved ONLY for the untouched reveal / verdict / re-ask surfaces, not clean-idle.
36
+ // Byte-identical to origin/main is preserved for the untouched reveal / verdict surfaces.
28
37
  // Fail-open: any error → print nothing (or just the presence line), exit 0. Never blocks the bar.
29
38
  import { readFileSync, rmSync } from "node:fs";
30
39
  import { homedir } from "node:os";
@@ -37,14 +46,22 @@ const GREEN = "\x1b[32m";
37
46
  const BOLD = "\x1b[1m";
38
47
  const DIM = "\x1b[2m";
39
48
  const RESET = "\x1b[0m";
49
+ // The skalpel red — the ONE accent, used ONCE per line at most (only on `M false` when lies > 0).
50
+ const RED = "\x1b[38;2;233;38;31m";
51
+
52
+ // The composed wordmark + separators of the instrument line. Em-dash after the wordmark (it breathes);
53
+ // dim mid-dots between clauses. ANSI only, one line, no animation — the bar re-invokes this command.
54
+ const WORDMARK = `🔬 ${BOLD}skalpel${RESET}`;
55
+ const EMDASH = `${DIM} — ${RESET}`;
56
+ const MIDDOT = ` ${DIM}·${RESET} `;
40
57
 
41
- // ── RENDER MODE — the ONE constant Ryan flips. Governs the optional TIME clause on the always-on
42
- // `skalpel · N steers` baseline. The steers count + Raahil's #609 BOLD/CYAN styling are ALWAYS present,
43
- // unchanged, in every mode. Nothing else on the bar (reveal / verdict / re-ask / steer label) is affected.
44
- // "steers" → skalpel · N steers
45
- // "measured" → skalpel · N steers · 38m caught (DEFAULT — cumulative lifetime MEASURED red→green)
46
- // "saved" → skalpel · N steers · ~7m saved (Raahil's own-graph ESTIMATE, from steers.ndjson)
47
- // "both" → skalpel · N steers · 38m caught · ~7m saved
58
+ // ── RENDER MODE — the ONE constant Ryan flips. Governs the optional TIME clause(s) on the ambient
59
+ // instrument line. The heartbeat (claims verified / checked · false) and the `N steers` clause are
60
+ // mode-independent. Nothing else on the bar (reveal / verdict / re-ask / steer label) is affected.
61
+ // "steers" → no time clause
62
+ // "measured" → · 38m caught (DEFAULT — cumulative lifetime MEASURED red→green)
63
+ // "saved" → · ~7m saved (Raahil's own-graph ESTIMATE, from steers.ndjson)
64
+ // "both" → · 38m caught · ~7m saved
48
65
  const BASELINE_TIME_MODE = "measured";
49
66
  const SHOW_MEASURED = BASELINE_TIME_MODE === "measured" || BASELINE_TIME_MODE === "both";
50
67
  const SHOW_SAVED = BASELINE_TIME_MODE === "saved" || BASELINE_TIME_MODE === "both";
@@ -423,7 +440,7 @@ function main() {
423
440
  const n = reaskCount(payload.transcript_path);
424
441
  if (n >= 2) {
425
442
  process.stdout.write(
426
- `${BOLD}skalpel${RESET} · ${CYAN}${n} re-asks/interrupts this stretch${RESET} · ${DIM}run: skalpel autopsy${RESET}`,
443
+ `${WORDMARK}${EMDASH}${CYAN}${n}${RESET} ${DIM}re-asks/interrupts this stretch${RESET}${MIDDOT}${DIM}run: skalpel autopsy${RESET}`,
427
444
  );
428
445
  return;
429
446
  }
@@ -431,44 +448,49 @@ function main() {
431
448
  // Otherwise, if a steer is live, name what it's doing — a description, no number.
432
449
  const label = steerLabel();
433
450
  if (label) {
434
- process.stdout.write(`${BOLD}skalpel${RESET} · ${CYAN}${label}${RESET}`);
451
+ process.stdout.write(`${WORDMARK}${EMDASH}${CYAN}${label}${RESET}`);
435
452
  return;
436
453
  }
437
454
 
438
- // ALWAYS-ON baseline presence line — skalpel's terminal presence (owner product decision: never gated,
439
- // never hidden). `N steers` is ALWAYS shown (fresh install reads "0 steers" honest, present, never
440
- // blank; the user's own applied-steer count). Then the ONE optional time clause selected by
441
- // BASELINE_TIME_MODE, each an AGGREGATE number only (never per-catch claim text / proof those live in
442
- // the opt-in reveal + the TUI), shown only when its real value exists:
443
- // MEASUREDXm caught" the CUMULATIVE LIFETIME sum of every real measured red→green delta
444
- // (measuredCaughtTotalMs). Always-on once real catches exist; a MEASURED wall-clock, never an
445
- // estimate. Cumulative framing (not present-tense "just caught"), so it stays honest for old catches.
446
- // Raahil's `~`-prefixed saved ESTIMATE ("· ~7m saved") shown only when saved_min > 0 (its data is
447
- // the user's own steers.ndjson credit, not the shadow log, so it keeps his always-on #609 behavior).
455
+ // THE AMBIENT INSTRUMENT LINE — skalpel's always-on terminal presence (owner product decision: never
456
+ // gated, never hidden). The wordmark leads; the body composes ONLY the clauses with real value, each
457
+ // an AGGREGATE number (never per-catch claim text / proof — those live in the opt-in reveal + the TUI):
458
+ // THE HEARTBEAT (founder: "I only see 0 steers the product is invisible while it works"):
459
+ // clean so far "3 claims verified" (the earned-silence receipt real verdicts only)
460
+ // lies caught → "31 checked · 2 false" (the honest split; `M false` carries the one red accent)
461
+ // MEASURED "Xm caught" the CUMULATIVE LIFETIME sum of every real measured red→green delta
462
+ // (shadowTally). IMMUTABLE product surface: rendered whenever it has a value; a MEASURED
463
+ // wall-clock, never an estimate. Cumulative framing keeps it honest for old catches.
464
+ // • "N steers" — the user's own applied-steer count, whenever > 0 (always-on WHEN IT HAS VALUE;
465
+ // the redesign only removed the dead "0 steers" zero — presence is now the wordmark itself).
466
+ // • Raahil's `~`-prefixed saved ESTIMATE ("~7m saved") — mode-gated, shown only when saved_min > 0
467
+ // (its data is the user's own steers.ndjson credit, not the shadow log — #609 behavior preserved).
468
+ // Nothing yet (no verdicts, no steers, no measured) → the quiet watching line, never a dead zero.
448
469
  const { steers, savedMin } = readState();
449
- const tally = SHOW_MEASURED ? shadowTally() : { totalMs: 0, checked: 0, lies: 0 };
450
- let line = `${BOLD}skalpel${RESET} · ${CYAN}${steers} steers${RESET}`;
470
+ const tally = shadowTally();
471
+ const clauses = [];
472
+ if (tally.checked > 0) {
473
+ if (tally.lies > 0) {
474
+ clauses.push(`${CYAN}${tally.checked}${RESET} ${DIM}checked${RESET}`);
475
+ clauses.push(`${RED}${tally.lies} false${RESET}`); // the ONE red accent, used once
476
+ } else {
477
+ clauses.push(
478
+ `${CYAN}${tally.checked}${RESET} ${DIM}claim${tally.checked === 1 ? "" : "s"} verified${RESET}`,
479
+ );
480
+ }
481
+ }
451
482
  if (SHOW_MEASURED) {
452
483
  const caught = compactMeasured(tally.totalMs); // null when < 1s of real measured catches
453
- if (caught) line += ` · ${CYAN}${caught} caught${RESET}`;
454
- // THE HEARTBEAT (founder: "I only see 0 steers — the product is invisible while it works").
455
- // Once the armed shadow has genuinely CHECKED at least one claim, the line SHOWS the work:
456
- // clean so far → "· 3 claims verified" (the earned-silence receipt — real verdicts only)
457
- // lies caught → "· 31 checked · 2 false" (the honest split; the measured clause carries the time)
458
- // Real counts from the same single log pass. A fresh install (checked = 0) emits EXACTLY the
459
- // baseline line — byte-identical, nothing invented.
460
- if (tally.checked > 0) {
461
- line +=
462
- tally.lies > 0
463
- ? ` · ${CYAN}${tally.checked} checked · ${tally.lies} false${RESET}`
464
- : ` · ${CYAN}${tally.checked} claim${tally.checked === 1 ? "" : "s"} verified${RESET}`;
465
- }
484
+ if (caught) clauses.push(`${CYAN}${caught}${RESET} ${DIM}caught${RESET}`);
466
485
  }
486
+ if (steers > 0)
487
+ clauses.push(`${CYAN}${steers}${RESET} ${DIM}steer${steers === 1 ? "" : "s"}${RESET}`);
467
488
  if (SHOW_SAVED) {
468
489
  const phrase = savedPhrase(savedMin);
469
- if (phrase) line += ` · ${CYAN}${phrase}${RESET}`;
490
+ if (phrase) clauses.push(`${CYAN}${phrase}${RESET}`);
470
491
  }
471
- process.stdout.write(line);
492
+ const body = clauses.length ? clauses.join(MIDDOT) : `${DIM}watching your agent's claims${RESET}`;
493
+ process.stdout.write(`${WORDMARK}${EMDASH}${body}`);
472
494
  }
473
495
 
474
496
  // Fail-open: wrap the whole render so a thrown error can never spill a stack trace into the live status
@@ -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 > default off -------------------------------------
41
- test("arming — default OFF when config absent and env unset", () => {
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({}), false);
44
- assert.equal(verifySpawnArmed({}), false);
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 but NOT the reveal", () => {
63
- writeCfg({});
64
- assert.equal(verifySpawnArmed({ SKALPEL_VERIFY_SHADOW: "1" }), true);
65
- assert.equal(revealEnabled({ SKALPEL_VERIFY_SHADOW: "1" }), false);
66
- });
67
-
68
- test("arming — fail-open: a corrupt client.json never throws, resolves OFF", () => {
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
- assert.equal(revealEnabled({}), false);
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 ------------------------------------------