vibeostheog 0.25.31 → 0.25.33

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.
@@ -1 +1 @@
1
- window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:44909";
1
+ window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:57270";
package/dist/vibeOS.js CHANGED
@@ -979,7 +979,7 @@ var init_smart_cache = __esm({
979
979
  });
980
980
 
981
981
  // src/lib/state.js
982
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, appendFileSync, existsSync as existsSync2, mkdirSync, statSync as statSync2, readdirSync, openSync, readSync, closeSync, rmSync, copyFileSync, renameSync as renameSync2 } from "node:fs";
982
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, appendFileSync as appendFileSync2, existsSync as existsSync2, mkdirSync, statSync as statSync2, readdirSync, openSync, readSync, closeSync, rmSync, copyFileSync, renameSync as renameSync2 } from "node:fs";
983
983
  import { join as join2, dirname, basename as basename2 } from "node:path";
984
984
  import { spawn } from "node:child_process";
985
985
  import { homedir as homedir2, tmpdir as tmpdir2 } from "node:os";
@@ -1139,7 +1139,7 @@ function _handleStateCorruption2(path) {
1139
1139
  }
1140
1140
  const logPath = join2(VIBEOS_HOME, ".state-corruption-log.jsonl");
1141
1141
  try {
1142
- appendFileSync(logPath, JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), path, backup: backupPath }) + "\n");
1142
+ appendFileSync2(logPath, JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), path, backup: backupPath }) + "\n");
1143
1143
  } catch {
1144
1144
  }
1145
1145
  _pruneCorruptionBackups(backupDir);
@@ -1586,7 +1586,7 @@ function _flushLedgerBuffer() {
1586
1586
  const lines = batch.map((e) => typeof e === "string" ? e.trimEnd() : String(e).trimEnd());
1587
1587
  const joined = lines.filter(Boolean).map((l) => l + "\n").join("");
1588
1588
  try {
1589
- appendFileSync(SAVINGS_LEDGER_FILE, joined);
1589
+ appendFileSync2(SAVINGS_LEDGER_FILE, joined);
1590
1590
  _compactSavingsLedgerIfNeeded();
1591
1591
  } catch {
1592
1592
  }
@@ -1736,8 +1736,8 @@ function indexAppend(hash, tool2, size, extra) {
1736
1736
  const sessionIndex = getSessionIndexPath();
1737
1737
  mkdirSync(dirname(globalIndex), { recursive: true });
1738
1738
  mkdirSync(dirname(sessionIndex), { recursive: true });
1739
- appendFileSync(globalIndex, entry);
1740
- appendFileSync(sessionIndex, entry);
1739
+ appendFileSync2(globalIndex, entry);
1740
+ appendFileSync2(sessionIndex, entry);
1741
1741
  } catch (err) {
1742
1742
  console.error(`[vibeOS] index write failed: ${err.message}`);
1743
1743
  }
@@ -2859,7 +2859,7 @@ __export(flow_enforcer_exports, {
2859
2859
  setFlowStateWriter: () => setFlowStateWriter,
2860
2860
  syncFlowTodosToNative: () => syncFlowTodosToNative
2861
2861
  });
2862
- import { readFileSync as readFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3, statSync as statSync3, appendFileSync as appendFileSync2, renameSync as renameSync3 } from "node:fs";
2862
+ import { readFileSync as readFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3, statSync as statSync3, appendFileSync as appendFileSync3, renameSync as renameSync3 } from "node:fs";
2863
2863
  import { join as join3, dirname as dirname2 } from "node:path";
2864
2864
  import { fileURLToPath } from "node:url";
2865
2865
  function getVibeOSHome3() {
@@ -3291,7 +3291,7 @@ function recordFlowTodo({ filePath, content }) {
3291
3291
  filePath,
3292
3292
  todos
3293
3293
  }) + "\n";
3294
- appendFileSync2(flowTodoFile, entry);
3294
+ appendFileSync3(flowTodoFile, entry);
3295
3295
  try {
3296
3296
  const lines = readFileSync3(flowTodoFile, "utf-8").trim().split("\n").filter(Boolean);
3297
3297
  if (lines.length > MAX_FLOW_TODOS) {
@@ -9466,7 +9466,7 @@ function createTrinityTool(deps) {
9466
9466
  return {
9467
9467
  description: "Control the vibeOS plugin and active model slot. Use action='status' to see the current state. Use action='enable' or 'disable' to toggle the plugin immediately. Use action='set' with slot='brain'|'medium'|'cheap' to switch model tiers (writes opencode.json). Optionally pass model='<model_id>' to set a custom model for that slot. Use action='mode' with slot='vibeultrax'|'vibeqmax'|'vibemax'|'budget'|'quality'|'speed'|'longrun'|'auto'|'balanced'|'audit'|'forensic' to switch optimization mode. Use action='thinking' with level='full'|'brief'|'off'. Use action='rebuild' to detect available models from configured providers and reassign brain/medium/cheap slots. Use action='flow' with slot='on'|'off' to toggle flow enforcer, or action='flow' alone for audit. Use action='flow' with slot='enforce' and level='on'|'off' to toggle auto-extract TODOs. Use action='enforce' with slot='on'|'off' to toggle delegation enforcement. Use action='tdd' with slot='on'|'off' to toggle auto-create test skeletons. Use action='tdd' with slot='strict' and level='on'|'off' to toggle strict failing TODO test templates. Use action='tdd' alone for audit. Use action='setup' to create a compatibility profile for first-time users. Use action='project' to show per-project analytics and optimization suggestions. Use action='patterns' to inspect learned project patterns or slot='clear' to clear them. Use action='guard' to keep AGENTS.md and README.md current. Use action='reality-check' to read verified live state and report only evidence-backed facts. Use action='api-token' with token='<new_token>' to update the API token or token='invalidate' to disable the embedded alpha token. Use action='api-bootstrap-token' with token='<new_token>' to store an alpha bootstrap token and exchange it for a normal API token on alpha builds. Call this when the user says things like 'switch to medium', 'use cheap model', 'disable plugin', 'vibe status' (or the legacy 'trinity status').",
9468
9468
  args: {
9469
- action: deps.tool.schema.enum(["status", "enable", "disable", "set", "mode", "thinking", "flow", "tdd", "setup", "project", "patterns", "rebuild", "diagnose", "help", "enforce", "repair-state", "blackbox", "report", "target", "guard", "reality-check", "api-token", "api-bootstrap-token", "todo", "todo-done", "todo-sync"]).optional(),
9469
+ action: deps.tool.schema.enum(["status", "enable", "disable", "set", "mode", "thinking", "flow", "tdd", "setup", "project", "patterns", "rebuild", "diagnose", "help", "enforce", "repair-state", "blackbox", "report", "target", "guard", "reality-check", "api-token", "api-bootstrap-token", "verify-claims", "todo", "todo-done", "todo-sync"]).optional(),
9470
9470
  slot: deps.tool.schema.enum(["brain", "medium", "cheap", "budget", "quality", "speed", "longrun", "auto", "balanced", "audit", "forensic", "vibeultrax", "vibeqmax", "vibemax", "vibelitex", "on", "off", "enforce", "strict", "preview", "apply", "clear", "savings"]).optional(),
9471
9471
  level: deps.tool.schema.enum(["full", "brief", "off", "on"]).optional(),
9472
9472
  model: deps.tool.schema.string().optional(),
@@ -10333,6 +10333,125 @@ ${L.repeat(40)}`);
10333
10333
  return "[vibeOS] Alpha bootstrap token exchanged successfully. Remote API re-enabled.";
10334
10334
  return "[vibeOS] Alpha bootstrap token saved. Remote API will retry the exchange on the next call.";
10335
10335
  }
10336
+ if (action === "verify-claims") {
10337
+ const VIBEOS_HOME2 = join11(process.env.HOME || "", ".claude");
10338
+ const AUDIT_DIR = join11(VIBEOS_HOME2, "cascade-audit");
10339
+ const claimFile = join11(AUDIT_DIR, "claim-audit.jsonl");
10340
+ const cascadeFile = join11(AUDIT_DIR, "cascade-audit.jsonl");
10341
+ const lines = ["[vibeOS] Claim verification report"];
10342
+ lines.push("=".repeat(50));
10343
+ let claimCount = 0, unsubstantiatedCount = 0, verifiedCount = 0;
10344
+ const CLAIM_RE = /(?:done|fixed|validated|works|score|%|passed|verified|solved|resolved)/i;
10345
+ const claims = [];
10346
+ if (deps.existsSync(claimFile)) {
10347
+ try {
10348
+ const raw = deps.readFileSync(claimFile, "utf-8");
10349
+ for (const ln of raw.trim().split(String.fromCharCode(10))) {
10350
+ if (!ln.trim())
10351
+ continue;
10352
+ try {
10353
+ claims.push(JSON.parse(ln));
10354
+ } catch {
10355
+ }
10356
+ }
10357
+ } catch {
10358
+ }
10359
+ }
10360
+ const cascadeRuns = [];
10361
+ if (deps.existsSync(cascadeFile)) {
10362
+ try {
10363
+ const raw = deps.readFileSync(cascadeFile, "utf-8");
10364
+ for (const ln of raw.trim().split(String.fromCharCode(10))) {
10365
+ if (!ln.trim())
10366
+ continue;
10367
+ try {
10368
+ cascadeRuns.push(JSON.parse(ln));
10369
+ } catch {
10370
+ }
10371
+ }
10372
+ } catch {
10373
+ }
10374
+ }
10375
+ const recentClaims = claims.slice(-20);
10376
+ const recentCascade = cascadeRuns.slice(-50);
10377
+ lines.push("Claims detected (last 20): " + recentClaims.length);
10378
+ lines.push("Cascade runs available: " + recentCascade.length);
10379
+ lines.push("");
10380
+ if (recentClaims.length === 0) {
10381
+ lines.push(" No claims detected in recent responses.");
10382
+ }
10383
+ for (const cl of recentClaims) {
10384
+ claimCount++;
10385
+ const claimTexts = (cl.claims || []).map(function(c) {
10386
+ return c.text;
10387
+ }).join(" | ");
10388
+ const ts = (cl.ts || "").slice(0, 19);
10389
+ let cascadeMatch = false;
10390
+ let emptyAnswers = 0;
10391
+ for (const cr of recentCascade) {
10392
+ const cTs = cr._ts || "";
10393
+ if (cTs && cl.ts) {
10394
+ const diffMs = Math.abs(new Date(cTs).getTime() - new Date(cl.ts).getTime());
10395
+ if (diffMs < 12e4) {
10396
+ cascadeMatch = true;
10397
+ if (cr.answer_empty)
10398
+ emptyAnswers++;
10399
+ }
10400
+ }
10401
+ }
10402
+ const hasScore = CLAIM_RE.test(claimTexts);
10403
+ let substantiated = true;
10404
+ let notes = [];
10405
+ if (hasScore && recentCascade.length === 0) {
10406
+ substantiated = false;
10407
+ notes.push("no cascade run data available");
10408
+ } else if (hasScore && !cascadeMatch) {
10409
+ substantiated = false;
10410
+ notes.push("no cascade run within 2min of claim");
10411
+ }
10412
+ if (emptyAnswers > 0) {
10413
+ notes.push("cascade returned empty answers");
10414
+ }
10415
+ if (substantiated) {
10416
+ verifiedCount++;
10417
+ lines.push(" [VERIFIED] " + ts + ": " + claimTexts.substring(0, 80));
10418
+ } else {
10419
+ unsubstantiatedCount++;
10420
+ lines.push(" [UNSUBSTANTIATED] " + ts + ": " + claimTexts.substring(0, 80));
10421
+ if (notes.length > 0)
10422
+ lines.push(" Reasons: " + notes.join("; "));
10423
+ }
10424
+ }
10425
+ lines.push("");
10426
+ lines.push("Summary: " + verifiedCount + " verified, " + unsubstantiatedCount + " unsubstantiated, " + (claimCount - verifiedCount - unsubstantiatedCount) + " pending");
10427
+ lines.push("Claim audit: " + claimFile);
10428
+ lines.push("Cascade audit: " + cascadeFile);
10429
+ const { execSync } = __require("child_process");
10430
+ let gitDiffLines = "";
10431
+ try {
10432
+ gitDiffLines = execSync("git diff --stat", { encoding: "utf-8", timeout: 5e3 }).trim();
10433
+ } catch {
10434
+ }
10435
+ if (gitDiffLines) {
10436
+ lines.push("");
10437
+ lines.push("Git working tree has uncommitted changes:");
10438
+ for (const dl of gitDiffLines.split(String.fromCharCode(10))) {
10439
+ lines.push(" " + dl);
10440
+ }
10441
+ } else {
10442
+ for (const cl of recentClaims) {
10443
+ const claimTexts = (cl.claims || []).map(function(c) {
10444
+ return c.text;
10445
+ }).join(" | ");
10446
+ if (/fixed|done|solved|resolved|validated/i.test(claimTexts)) {
10447
+ if (!gitDiffLines) {
10448
+ lines.push(" WARNING: '" + claimTexts.substring(0, 50) + "' claim but no uncommitted changes in working tree");
10449
+ }
10450
+ }
10451
+ }
10452
+ }
10453
+ return lines.join(String.fromCharCode(10));
10454
+ }
10336
10455
  if (action === "rebuild") {
10337
10456
  const providers = typeof deps._loadOpenCodeProviders === "function" ? deps._loadOpenCodeProviders(deps.directory) : {};
10338
10457
  const auth = deps._readAuth();
@@ -11122,12 +11241,12 @@ async function probeModel(modelId, auth, providers = null) {
11122
11241
  }
11123
11242
 
11124
11243
  // src/lib/hooks/footer.js
11125
- import { readFileSync as readFileSync14, appendFileSync as appendFileSync4, mkdirSync as mkdirSync11 } from "node:fs";
11244
+ import { readFileSync as readFileSync14, appendFileSync as appendFileSync5, mkdirSync as mkdirSync11 } from "node:fs";
11126
11245
  import { join as join15 } from "node:path";
11127
11246
 
11128
11247
  // src/lib/hooks/chat-transform.js
11129
11248
  init_state();
11130
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync13, appendFileSync as appendFileSync3, existsSync as existsSync14, mkdirSync as mkdirSync10, rmSync as rmSync5, readdirSync as readdirSync3, statSync as statSync7 } from "node:fs";
11249
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync13, appendFileSync as appendFileSync4, existsSync as existsSync14, mkdirSync as mkdirSync10, rmSync as rmSync5, readdirSync as readdirSync3, statSync as statSync7 } from "node:fs";
11131
11250
  import { join as join14, dirname as dirname10, basename as basename3 } from "node:path";
11132
11251
  import { createHash as createHash3 } from "node:crypto";
11133
11252
 
@@ -12084,6 +12203,11 @@ function syncControlSettings(cv, options = {}) {
12084
12203
  writeIf("active_pipeline", JSON.stringify(modeEntry.pipeline));
12085
12204
  }
12086
12205
  }
12206
+ if (cv?.pipeline_root && Array.isArray(cv.pipeline_root)) {
12207
+ writeIf("active_pipeline", JSON.stringify(cv.pipeline_root));
12208
+ } else if (cv?.cascade_depth && cv.cascade_depth >= 3) {
12209
+ writeIf("active_pipeline", JSON.stringify(["local", "medium", "brain"]));
12210
+ }
12087
12211
  writeIf("enabled", true);
12088
12212
  const compatibilityMode = currentSel.onboarding_mode === "assist";
12089
12213
  const flowManuallyDisabled = currentSel.flow_enabled === false && currentSel.flow_enforce === false;
@@ -12524,6 +12648,14 @@ var onSystemTransform = async (_input, output) => {
12524
12648
  if (!loadSelection().enabled)
12525
12649
  return;
12526
12650
  try {
12651
+ const bbOnDisk = loadBlackboxState();
12652
+ if (_latestBlackboxState3 && bbOnDisk) {
12653
+ const diskHasSessions = Object.keys(bbOnDisk.sessions || {}).length > 0;
12654
+ const stateHasRegime = !!_latestBlackboxState3.sub_regime;
12655
+ if (diskHasSessions && !stateHasRegime) {
12656
+ _latestBlackboxState3 = bbOnDisk;
12657
+ }
12658
+ }
12527
12659
  const hookDirectory = String(onSystemTransform._directory || "");
12528
12660
  const userText = extractLastUserText(_input) || extractLastUserText(output);
12529
12661
  if (typeof userText === "string" && userText.trim())
@@ -12549,6 +12681,25 @@ var onSystemTransform = async (_input, output) => {
12549
12681
  if (st)
12550
12682
  _latestBlackboxState3.latest_stress_multiplier = st;
12551
12683
  _controlVector = await apiComputeControlVector(_latestBlackboxState3, void 0, optimizationMode);
12684
+ if (_controlVector) {
12685
+ const fullState = loadBlackboxState() || { sessions: {}, enabled: true };
12686
+ fullState.cv = _controlVector;
12687
+ if (_latestBlackboxState3) {
12688
+ if (_latestBlackboxState3.sub_regime)
12689
+ fullState.sub_regime = _latestBlackboxState3.sub_regime;
12690
+ if (_latestBlackboxState3.latest_stress_multiplier)
12691
+ fullState.latest_stress_multiplier = _latestBlackboxState3.latest_stress_multiplier;
12692
+ if (_latestBlackboxState3.n_interactions)
12693
+ fullState.n_interactions = _latestBlackboxState3.n_interactions;
12694
+ if (_latestBlackboxState3.resolution)
12695
+ fullState.resolution = _latestBlackboxState3.resolution;
12696
+ if (_latestBlackboxState3.momentum)
12697
+ fullState.momentum = _latestBlackboxState3.momentum;
12698
+ fullState.latest_control_vector_ts = Date.now();
12699
+ }
12700
+ fullState.sessions ??= {};
12701
+ saveBlackboxState(fullState);
12702
+ }
12552
12703
  } else if (latestUserIntent) {
12553
12704
  const st = scoreStress(latestUserIntent);
12554
12705
  _controlVector = await apiComputeControlVector({
@@ -12737,7 +12888,7 @@ var onSystemTransform = async (_input, output) => {
12737
12888
  try {
12738
12889
  const calFile = join14(getVibeOSHome9(), "calibration-data.jsonl");
12739
12890
  mkdirSync10(getVibeOSHome9(), { recursive: true });
12740
- appendFileSync3(calFile, _calBuffer.join(""));
12891
+ appendFileSync4(calFile, _calBuffer.join(""));
12741
12892
  _calBuffer.length = 0;
12742
12893
  } catch {
12743
12894
  }
@@ -12921,6 +13072,9 @@ function buildFooterLine(input) {
12921
13072
  if (input.stressGauge) {
12922
13073
  line += ` | ${input.stressGauge}`;
12923
13074
  }
13075
+ if (input.claimTag) {
13076
+ line += ` | ${input.claimTag}`;
13077
+ }
12924
13078
  if (sessionSlot && sessionSlot !== activeSlot) {
12925
13079
  line += ` | session:${sessionSlot}`;
12926
13080
  }
@@ -13179,6 +13333,16 @@ async function _appendFooter(input, output, directory3) {
13179
13333
  const rawMode = (typeof loadSelection3 === "function" ? loadSelection3()?.requested_optimization_mode || loadSelection3()?.optimization_mode : null) || displayMode;
13180
13334
  const cv = computeControlVector2({ sub_regime: currentSubRegime, latest_stress_multiplier: _footerStress, user_text: latestUserIntent || "" }, void 0, rawMode);
13181
13335
  const vibeBrand = resolveBrand(loadOptimizationMode() || displayMode, activeSlot);
13336
+ const _cp = [/(?:\u005c|['"](?:done|fixed|validated|works|verified|solved|resolved)['"]|\d+%|score|passed)/i];
13337
+ let _claimTag = "";
13338
+ if (text) {
13339
+ for (const _p of _cp) {
13340
+ if (_p.test(text)) {
13341
+ _claimTag = "[CLAIMS]";
13342
+ break;
13343
+ }
13344
+ }
13345
+ }
13182
13346
  const vibeLine = buildFooterLine({
13183
13347
  activeSlot,
13184
13348
  providerLabel: execution.provider_label,
@@ -13193,7 +13357,8 @@ async function _appendFooter(input, output, directory3) {
13193
13357
  vectorChangedSlot: selNowFooter?.vector_changed_slot,
13194
13358
  subRegime: currentSubRegime,
13195
13359
  stressGauge: _footerStress > 0.85 ? "\u2588" : _footerStress > 0.7 ? "\u2586" : _footerStress > 0.5 ? "\u2585" : _footerStress > 0.3 ? "\u2583" : _footerStress > 0.1 ? "\u2582" : "\u2581",
13196
- cascadeIcon: (cv?.cascade_depth || 1) >= 3 ? "\u25B8\u25B8\u25B8" : (cv?.cascade_depth || 1) >= 2 ? "\u25B8\u25B8" : ""
13360
+ cascadeIcon: (cv?.cascade_depth || 1) >= 3 ? "\u25B8\u25B8\u25B8" : (cv?.cascade_depth || 1) >= 2 ? "\u25B8\u25B8" : "",
13361
+ claimTag: _claimTag
13197
13362
  });
13198
13363
  const footerText = stripped + `
13199
13364
 
@@ -13225,7 +13390,7 @@ ${vibeLine}`;
13225
13390
  syncOutcomeToApi(finalOutcome);
13226
13391
  try {
13227
13392
  mkdirSync11(getVibeOSHome10(), { recursive: true });
13228
- appendFileSync4(join15(getVibeOSHome10(), "calibration-data.jsonl"), JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), event: "outcome", sid: getSessionId(), outcome: finalOutcome }) + "\n");
13393
+ appendFileSync5(join15(getVibeOSHome10(), "calibration-data.jsonl"), JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), event: "outcome", sid: getSessionId(), outcome: finalOutcome }) + "\n");
13229
13394
  } catch {
13230
13395
  }
13231
13396
  }
@@ -13252,7 +13417,7 @@ ${vibeLine} \u2014`);
13252
13417
 
13253
13418
  // src/lib/hooks/tool-execute.js
13254
13419
  init_state();
13255
- import { writeFileSync as writeFileSync15, appendFileSync as appendFileSync6, existsSync as existsSync16, mkdirSync as mkdirSync13 } from "node:fs";
13420
+ import { writeFileSync as writeFileSync15, appendFileSync as appendFileSync7, existsSync as existsSync16, mkdirSync as mkdirSync13 } from "node:fs";
13256
13421
  import { join as join17, dirname as dirname12, basename as basename4 } from "node:path";
13257
13422
  import { createHash as createHash5 } from "node:crypto";
13258
13423
  init_selection_manager();
@@ -13321,7 +13486,7 @@ init_smart_cache();
13321
13486
 
13322
13487
  // src/lib/tdd-enforcer.js
13323
13488
  init_state();
13324
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync14, appendFileSync as appendFileSync5, existsSync as existsSync15, mkdirSync as mkdirSync12, statSync as statSync8, readdirSync as readdirSync4, rmSync as rmSync6, openSync as openSync3 } from "node:fs";
13489
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync14, appendFileSync as appendFileSync6, existsSync as existsSync15, mkdirSync as mkdirSync12, statSync as statSync8, readdirSync as readdirSync4, rmSync as rmSync6, openSync as openSync3 } from "node:fs";
13325
13490
  import { join as join16, dirname as dirname11 } from "node:path";
13326
13491
  import { createHash as createHash4 } from "node:crypto";
13327
13492
 
@@ -14584,7 +14749,7 @@ function _recordCooldown(testPath) {
14584
14749
  mkdirSync12(dirname11(ENFORCEMENT_COOLDOWN_FILE2), { recursive: true });
14585
14750
  const hash = createHash4("sha256").update(testPath).digest("hex").slice(0, 16);
14586
14751
  const entry = JSON.stringify({ h: hash, ts: Date.now() }) + "\n";
14587
- appendFileSync5(ENFORCEMENT_COOLDOWN_FILE2, entry);
14752
+ appendFileSync6(ENFORCEMENT_COOLDOWN_FILE2, entry);
14588
14753
  const lines = readFileSync15(ENFORCEMENT_COOLDOWN_FILE2, "utf-8").trim().split("\n").filter(Boolean);
14589
14754
  if (lines.length > 500) {
14590
14755
  writeFileSync14(ENFORCEMENT_COOLDOWN_FILE2, lines.slice(-200).join("\n") + "\n");
@@ -15142,13 +15307,21 @@ ${argsJson}
15142
15307
  const mediumCost = 5e-3;
15143
15308
  const brainCost = 0.02;
15144
15309
  const cascadeResult = cascadeDecide(_prompt, cheapCost, mediumCost, brainCost, 0.85);
15145
- const tierMap = { cheap: TRINITY_CHEAP, medium: TRINITY_MEDIUM, brain: TRINITY_BRAIN || TRINITY_MEDIUM, local: TRINITY_CHEAP };
15310
+ const tierMap = { cheap: TRINITY_CHEAP, medium: TRINITY_MEDIUM, brain: TRINITY_BRAIN, local: TRINITY_CHEAP };
15146
15311
  const pipelineModels = activePipeline.map((t2) => tierMap[t2] || TRINITY_CHEAP);
15147
15312
  if (cascadeResult.escalate && pipelineModels.length > 1) {
15148
- const escalated = pipelineModels[1];
15149
- if (escalated && escalated !== currentModel && (!_target || escalated !== _target)) {
15150
- _target = escalated;
15151
- console.error(`[vibeOS] \u{1F500} Cascade escalate: ${cascadeResult.reason} \u2192 ${escalated}`);
15313
+ if (pipelineModels.length > 2 && cascadeResult.confidence >= 0.8) {
15314
+ const escalated = pipelineModels[2];
15315
+ if (escalated && escalated !== currentModel && (!_target || escalated !== _target)) {
15316
+ _target = escalated;
15317
+ console.error(`[vibeOS] \u{1F500} Cascade depth-3 escalate: ${cascadeResult.reason} \u2192 ${escalated}`);
15318
+ }
15319
+ } else {
15320
+ const escalated = pipelineModels[1];
15321
+ if (escalated && escalated !== currentModel && (!_target || escalated !== _target)) {
15322
+ _target = escalated;
15323
+ console.error(`[vibeOS] \u{1F500} Cascade escalate: ${cascadeResult.reason} \u2192 ${escalated}`);
15324
+ }
15152
15325
  }
15153
15326
  } else if (cascadeResult.useCheap && !_target) {
15154
15327
  _target = pipelineModels[0];
@@ -15176,7 +15349,7 @@ ${argsJson}
15176
15349
  _setModel(inArgs);
15177
15350
  try {
15178
15351
  const selNow = loadSelection();
15179
- const desiredSlot = _target === TRINITY_CHEAP ? "cheap" : _target === TRINITY_MEDIUM ? "medium" : null;
15352
+ const desiredSlot = _target === TRINITY_CHEAP ? "cheap" : _target === TRINITY_MEDIUM ? "medium" : _target === TRINITY_BRAIN ? "brain" : null;
15180
15353
  if (selNow.delegation_enforce && currentTier === "high" && desiredSlot && selNow.active_slot !== desiredSlot) {
15181
15354
  taskSlotRestore = selNow.active_slot || "brain";
15182
15355
  const switched = applySlot(desiredSlot);
@@ -15516,7 +15689,7 @@ var onToolExecuteAfter = async (input, output) => {
15516
15689
  const taskPrompt = input?.args?.prompt || input?.args?.description || "";
15517
15690
  const quality = scoreTaskQuality(taskOutput, taskPrompt);
15518
15691
  try {
15519
- appendFileSync6(SAVINGS_LEDGER_FILE, JSON.stringify({
15692
+ appendFileSync7(SAVINGS_LEDGER_FILE, JSON.stringify({
15520
15693
  at: (/* @__PURE__ */ new Date()).toISOString(),
15521
15694
  kind: "quality",
15522
15695
  score: quality,
@@ -15874,6 +16047,38 @@ function ensureDeferredBootstrap() {
15874
16047
  } catch {
15875
16048
  }
15876
16049
  }
16050
+ var CLAIM_PATTERNS = [
16051
+ /(?:done|finished|complete)/i,
16052
+ /(?:fixed|resolved|solved)/i,
16053
+ /(?:working|works|validated|verified)/i,
16054
+ /(?:[0-9]+\.[0-9]?%|\d+%)/,
16055
+ /(?:score|scored|passing|passed)/i
16056
+ ];
16057
+ function scanClaimsInOutput(output) {
16058
+ if (!output || typeof output !== "string") return;
16059
+ try {
16060
+ const claims = [];
16061
+ const lines = String(output).split(String.fromCharCode(10));
16062
+ for (let i = 0; i < lines.length; i++) {
16063
+ for (const pat of CLAIM_PATTERNS) {
16064
+ if (pat.test(lines[i])) claims.push({ line: i + 1, text: lines[i].trim().substring(0, 120), pattern: pat.source });
16065
+ }
16066
+ }
16067
+ if (claims.length === 0) return;
16068
+ const auditDir = join18(getVibeOSHome13(), "cascade-audit");
16069
+ mkdirSync14(auditDir, { recursive: true });
16070
+ const auditFile = join18(auditDir, "claim-audit.jsonl");
16071
+ const entry = JSON.stringify({
16072
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
16073
+ claims: claims.slice(0, 10),
16074
+ totalClaims: claims.length,
16075
+ responseHash: ""
16076
+ // crypto hash skipped for performance
16077
+ });
16078
+ appendFileSync(auditFile, entry + String.fromCharCode(10));
16079
+ } catch {
16080
+ }
16081
+ }
15877
16082
  var activeJob2 = null;
15878
16083
  var fp = "";
15879
16084
  var _mcpServerRuntime = null;
@@ -16681,6 +16886,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
16681
16886
  }
16682
16887
  ensureDeferredBootstrap();
16683
16888
  await _appendFooter(_input, output, directory3);
16889
+ scanClaimsInOutput(output);
16684
16890
  },
16685
16891
  "message.updated": async (_input, output) => {
16686
16892
  setVibeOSHomeContext(hookVibeHome);
@@ -16690,6 +16896,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
16690
16896
  }
16691
16897
  ensureDeferredBootstrap();
16692
16898
  await _appendFooter(_input, output, directory3);
16899
+ scanClaimsInOutput(output);
16693
16900
  },
16694
16901
  tool: {
16695
16902
  trinity: tool(createTrinityTool(trinityDeps)),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.25.31",
3
+ "version": "0.25.33",
4
4
  "description": "Cost-aware delegation enforcer for OpenCode. Tracks model usage, routes Task subagents to cheaper tiers, surfaces cumulative savings in chat. Includes research audit, reporting framework, project memory, progressive scratchpad decadence, and trinity CLI for brain/medium/cheap slot switching.",
5
5
  "scripts": {
6
6
  "release": "node scripts/release.mjs",