vibeostheog 0.24.19 → 0.24.22

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/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## 0.24.22
2
+ - fix: restore bootstrap token and install regression (#149)
3
+
4
+
5
+ ## 0.24.21
6
+ - feat: pass user_text to RF prediction engine via control-vector API (#146)
7
+ - feat: pass user_text to RF prediction engine via control-vector API
8
+ - fix: extend ci test timeout
9
+ - fix: use EMBEDDED_API_TOKEN as bootstrap token fallback instead of direct API token (#148)
10
+ - fix: repair reload recovery and fallback mode state (#147)
11
+ - test: cover cold start maintenance user flow (#144)
12
+ - chore: v0.24.20
13
+ - chore: v0.24.19 (#145)
14
+ Prune stale active jobs and stabilize report tests
15
+
16
+
1
17
  ## 0.24.19
2
18
  - test: cover cold start maintenance user flow (#144)
3
19
  Prune stale active jobs and stabilize report tests
package/dist/vibeOS.js CHANGED
@@ -1104,7 +1104,7 @@ var init_vibemax = __esm({
1104
1104
 
1105
1105
  // src/index.ts
1106
1106
  init_flow_enforcer();
1107
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync15, existsSync as existsSync18, mkdirSync as mkdirSync13, copyFileSync as copyFileSync2, renameSync as renameSync6 } from "node:fs";
1107
+ import { readFileSync as readFileSync17, writeFileSync as writeFileSync15, existsSync as existsSync18, mkdirSync as mkdirSync13, copyFileSync as copyFileSync2, renameSync as renameSync6, statSync as statSync9 } from "node:fs";
1108
1108
  import { join as join18, dirname as dirname13, basename as basename5 } from "node:path";
1109
1109
 
1110
1110
  // src/vibeOS-lib/session-metrics.js
@@ -1734,6 +1734,10 @@ function normalizeApiToken(token, fallback2 = "") {
1734
1734
  const clean = String(token || "").trim();
1735
1735
  return API_TOKEN_RE.test(clean) ? clean : fallback2;
1736
1736
  }
1737
+ function normalizeDirectApiToken(token) {
1738
+ const clean = normalizeApiToken(token, "");
1739
+ return clean && clean !== EMBEDDED_API_TOKEN ? clean : "";
1740
+ }
1737
1741
  function isTruthyFlag(value) {
1738
1742
  return API_DISABLED_RE.test(String(value || "").trim());
1739
1743
  }
@@ -2095,7 +2099,7 @@ function readTokenFromDisk() {
2095
2099
  const env = readFileSync2(dir + "/.env.production", "utf8");
2096
2100
  const m = env.match(/^VIBEOS_API_TOKEN=(.+)$/m);
2097
2101
  if (m) {
2098
- const clean = normalizeApiToken(m[1], "");
2102
+ const clean = normalizeDirectApiToken(m[1]);
2099
2103
  if (clean)
2100
2104
  return clean;
2101
2105
  }
@@ -2104,6 +2108,16 @@ function readTokenFromDisk() {
2104
2108
  }
2105
2109
  return "";
2106
2110
  }
2111
+ function hasPrimaryTokenOnDisk() {
2112
+ if (readApiDisabledFromDisk())
2113
+ return false;
2114
+ try {
2115
+ const env = readFileSync2(_envPaths[0] + "/.env.production", "utf8");
2116
+ return /^VIBEOS_API_TOKEN=/m.test(env);
2117
+ } catch {
2118
+ return false;
2119
+ }
2120
+ }
2107
2121
  function readBootstrapTokenFromDisk() {
2108
2122
  if (readApiDisabledFromDisk())
2109
2123
  return "";
@@ -2117,8 +2131,8 @@ function readBootstrapTokenFromDisk() {
2117
2131
  return "";
2118
2132
  }
2119
2133
  var VIBEOS_API_DISABLED = readApiDisabledFromDisk() || isTruthyFlag(process.env.VIBEOS_API_DISABLED);
2120
- var VIBEOS_API_TOKEN = VIBEOS_API_DISABLED ? "" : readTokenFromDisk() || normalizeApiToken(process.env.VIBEOS_API_TOKEN, "") || EMBEDDED_API_TOKEN;
2121
- var VIBEOS_API_BOOTSTRAP_TOKEN = VIBEOS_API_DISABLED ? "" : readBootstrapTokenFromDisk() || process.env.VIBEOS_API_BOOTSTRAP_TOKEN || "";
2134
+ var VIBEOS_API_TOKEN = VIBEOS_API_DISABLED ? "" : readTokenFromDisk() || normalizeDirectApiToken(process.env.VIBEOS_API_TOKEN) || (!hasPrimaryTokenOnDisk() ? EMBEDDED_API_TOKEN : "");
2135
+ var VIBEOS_API_BOOTSTRAP_TOKEN = VIBEOS_API_DISABLED ? "" : readBootstrapTokenFromDisk() || process.env.VIBEOS_API_BOOTSTRAP_TOKEN || EMBEDDED_API_TOKEN;
2122
2136
  var VIBEOS_API_ENABLED = !VIBEOS_API_DISABLED && process.env.VIBEOS_API_ENABLED !== "false" && (!!VIBEOS_API_TOKEN || !!VIBEOS_API_BOOTSTRAP_TOKEN);
2123
2137
  var _anomalyDetector = null;
2124
2138
  function getAnomalyDetector() {
@@ -2149,7 +2163,7 @@ function persistBootstrapToken(token) {
2149
2163
  function setApiToken(newToken) {
2150
2164
  try {
2151
2165
  VIBEOS_API_DISABLED = false;
2152
- VIBEOS_API_TOKEN = normalizeApiToken(newToken, EMBEDDED_API_TOKEN);
2166
+ VIBEOS_API_TOKEN = normalizeDirectApiToken(newToken);
2153
2167
  VIBEOS_API_BOOTSTRAP_TOKEN = readBootstrapTokenFromDisk() || VIBEOS_API_BOOTSTRAP_TOKEN;
2154
2168
  VIBEOS_API_ENABLED = process.env.VIBEOS_API_ENABLED !== "false" && (!!VIBEOS_API_TOKEN || !!VIBEOS_API_BOOTSTRAP_TOKEN);
2155
2169
  _apiClient = null;
@@ -2241,7 +2255,7 @@ function syncApiTokenFromDisk() {
2241
2255
  const diskDisabled = readApiDisabledFromDisk() || isTruthyFlag(process.env.VIBEOS_API_DISABLED);
2242
2256
  const diskToken = readTokenFromDisk() || "";
2243
2257
  const diskBootstrapToken = readBootstrapTokenFromDisk() || "";
2244
- const envToken = normalizeApiToken(process.env.VIBEOS_API_TOKEN, "");
2258
+ const envToken = normalizeDirectApiToken(process.env.VIBEOS_API_TOKEN);
2245
2259
  if (diskDisabled) {
2246
2260
  if (!VIBEOS_API_DISABLED || VIBEOS_API_TOKEN || VIBEOS_API_BOOTSTRAP_TOKEN || VIBEOS_API_ENABLED) {
2247
2261
  VIBEOS_API_DISABLED = true;
@@ -2284,7 +2298,10 @@ function syncApiTokenFromDisk() {
2284
2298
  console.error("[vibeOS] API token loaded from VIBEOS_API_TOKEN env var");
2285
2299
  } else {
2286
2300
  VIBEOS_API_DISABLED = false;
2287
- VIBEOS_API_TOKEN ||= EMBEDDED_API_TOKEN;
2301
+ if (!VIBEOS_API_TOKEN && !hasPrimaryTokenOnDisk()) {
2302
+ VIBEOS_API_TOKEN = EMBEDDED_API_TOKEN;
2303
+ }
2304
+ VIBEOS_API_BOOTSTRAP_TOKEN ||= EMBEDDED_API_TOKEN;
2288
2305
  VIBEOS_API_ENABLED = process.env.VIBEOS_API_ENABLED !== "false" && (!!VIBEOS_API_TOKEN || !!VIBEOS_API_BOOTSTRAP_TOKEN);
2289
2306
  }
2290
2307
  }
@@ -2299,7 +2316,7 @@ function getApiClient2() {
2299
2316
  }
2300
2317
  return _apiClient;
2301
2318
  }
2302
- function isApiFallback() {
2319
+ function isApiFallback2() {
2303
2320
  return _apiFallbackMode || !VIBEOS_API_ENABLED;
2304
2321
  }
2305
2322
  function isApiConnected2() {
@@ -2395,7 +2412,7 @@ function safeJsonParse2(raw) {
2395
2412
  throw e;
2396
2413
  }
2397
2414
  }
2398
- var DFLT_SEL = { enabled: true, active_slot: null, slot_locked: false, thinking_level: "off", flow_enabled: true, tdd_enforce: false, tdd_strict: false, tdd_quality: true, flow_enforce: true, delegation_enforce: true, onboarding_mode: null, selected_provider: null, selected_quality_tier: null, selected_model: null, executed_provider: null, executed_quality_tier: null, executed_model: null, previous_default_agent: null };
2415
+ var DFLT_SEL = { enabled: true, active_slot: null, slot_locked: false, thinking_level: "off", flow_enabled: true, tdd_enforce: false, tdd_strict: false, tdd_quality: true, flow_enforce: true, delegation_enforce: true, onboarding_mode: null, selected_provider: null, selected_quality_tier: null, selected_model: null, executed_provider: null, executed_quality_tier: null, executed_model: null, previous_default_agent: null, previous_optimization_mode: null };
2399
2416
  function loadSelection() {
2400
2417
  const TIERS_FILE3 = join3(getVibeOSHome2(), "model-tiers.json");
2401
2418
  try {
@@ -2403,7 +2420,7 @@ function loadSelection() {
2403
2420
  return DFLT_SEL;
2404
2421
  const st = statSync3(TIERS_FILE3);
2405
2422
  if (st.size > 10485760) {
2406
- _handleStateCorruption(TIERS_FILE3);
2423
+ _handleStateCorruption2(TIERS_FILE3);
2407
2424
  return DFLT_SEL;
2408
2425
  }
2409
2426
  const j = safeJsonParse2(readFileSync3(TIERS_FILE3, "utf-8"));
@@ -2427,14 +2444,15 @@ function loadSelection() {
2427
2444
  executed_provider: j?.selection?.executed_provider || null,
2428
2445
  executed_quality_tier: j?.selection?.executed_quality_tier || null,
2429
2446
  executed_model: j?.selection?.executed_model || null,
2430
- previous_default_agent: j?.selection?.previous_default_agent || null
2447
+ previous_default_agent: j?.selection?.previous_default_agent || null,
2448
+ previous_optimization_mode: j?.selection?.previous_optimization_mode || null
2431
2449
  };
2432
2450
  } catch {
2433
- _handleStateCorruption(TIERS_FILE3);
2451
+ _handleStateCorruption2(TIERS_FILE3);
2434
2452
  return DFLT_SEL;
2435
2453
  }
2436
2454
  }
2437
- function writeSelection(key, value) {
2455
+ function writeSelection2(key, value) {
2438
2456
  const TIERS_FILE3 = join3(getVibeOSHome2(), "model-tiers.json");
2439
2457
  try {
2440
2458
  return withFileLock(TIERS_FILE3, () => {
@@ -2501,9 +2519,9 @@ function loadGlobalOptMode() {
2501
2519
  }
2502
2520
  }
2503
2521
  function saveGlobalOptMode(mode) {
2504
- return writeSelection("optimization_mode", mode);
2522
+ return writeSelection2("optimization_mode", mode);
2505
2523
  }
2506
- function writeSessionOptMode(sid, mode) {
2524
+ function writeSessionOptMode2(sid, mode) {
2507
2525
  const BLACKBOX_FILE = join3(getVibeOSHome2(), "blackbox-state.json");
2508
2526
  try {
2509
2527
  const j = existsSync4(BLACKBOX_FILE) ? safeJsonParse2(readFileSync3(BLACKBOX_FILE, "utf-8")) : {};
@@ -3453,7 +3471,7 @@ function runStartupMaintenanceOnce() {
3453
3471
  } catch {
3454
3472
  }
3455
3473
  }
3456
- function _handleStateCorruption(path) {
3474
+ function _handleStateCorruption2(path) {
3457
3475
  const backupDir = join4(VIBEOS_HOME, ".backups");
3458
3476
  mkdirSync3(backupDir, { recursive: true });
3459
3477
  const backupPath = join4(backupDir, basename2(path) + ".corrupted." + Date.now());
@@ -3558,12 +3576,12 @@ function readJsonOrEmpty(filePath) {
3558
3576
  return {};
3559
3577
  const st = statSync4(filePath);
3560
3578
  if (st.size > 10485760) {
3561
- _handleStateCorruption(filePath);
3579
+ _handleStateCorruption2(filePath);
3562
3580
  return {};
3563
3581
  }
3564
3582
  return safeJsonParse3(readFileSync4(filePath, "utf-8"));
3565
3583
  } catch {
3566
- _handleStateCorruption(filePath);
3584
+ _handleStateCorruption2(filePath);
3567
3585
  return {};
3568
3586
  }
3569
3587
  }
@@ -3614,12 +3632,12 @@ function readFullState() {
3614
3632
  return {};
3615
3633
  const st = statSync4(delegationStateFile);
3616
3634
  if (st.size > 10485760) {
3617
- _handleStateCorruption(delegationStateFile);
3635
+ _handleStateCorruption2(delegationStateFile);
3618
3636
  return {};
3619
3637
  }
3620
3638
  return safeJsonParse3(readFileSync4(delegationStateFile, "utf-8"));
3621
3639
  } catch {
3622
- _handleStateCorruption(delegationStateFile);
3640
+ _handleStateCorruption2(delegationStateFile);
3623
3641
  return {};
3624
3642
  }
3625
3643
  }
@@ -3659,7 +3677,7 @@ function loadGlobalLearning() {
3659
3677
  return DFLT_GL;
3660
3678
  const st = statSync4(globalLearningFile);
3661
3679
  if (st.size > 10485760) {
3662
- _handleStateCorruption(globalLearningFile);
3680
+ _handleStateCorruption2(globalLearningFile);
3663
3681
  return DFLT_GL;
3664
3682
  }
3665
3683
  const j = safeJsonParse3(readFileSync4(globalLearningFile, "utf-8"));
@@ -3672,7 +3690,7 @@ function loadGlobalLearning() {
3672
3690
  j.context7_last_seen ??= null;
3673
3691
  return j;
3674
3692
  } catch {
3675
- _handleStateCorruption(globalLearningFile);
3693
+ _handleStateCorruption2(globalLearningFile);
3676
3694
  return DFLT_GL;
3677
3695
  }
3678
3696
  }
@@ -3734,7 +3752,7 @@ function loadBlackboxState() {
3734
3752
  return { enabled: true, sessions: {} };
3735
3753
  const st = statSync4(blackboxFile);
3736
3754
  if (st.size > 10485760) {
3737
- _handleStateCorruption(blackboxFile);
3755
+ _handleStateCorruption2(blackboxFile);
3738
3756
  return { enabled: false, sessions: {} };
3739
3757
  }
3740
3758
  const raw = safeJsonParse3(readFileSync4(blackboxFile, "utf-8")) || { enabled: false, sessions: {} };
@@ -3774,7 +3792,7 @@ function loadBlackboxState() {
3774
3792
  }
3775
3793
  return raw;
3776
3794
  } catch {
3777
- _handleStateCorruption(blackboxFile);
3795
+ _handleStateCorruption2(blackboxFile);
3778
3796
  return { enabled: false, sessions: {} };
3779
3797
  }
3780
3798
  }
@@ -4281,7 +4299,7 @@ function _readActiveJobsRaw() {
4281
4299
  const raw = safeJsonParse3(readFileSync4(ACTIVE_JOBS_FILE, "utf-8"));
4282
4300
  return raw && typeof raw === "object" ? raw : {};
4283
4301
  } catch {
4284
- _handleStateCorruption(ACTIVE_JOBS_FILE);
4302
+ _handleStateCorruption2(ACTIVE_JOBS_FILE);
4285
4303
  return {};
4286
4304
  }
4287
4305
  }
@@ -4350,7 +4368,7 @@ function loadActiveJobs() {
4350
4368
  return next;
4351
4369
  });
4352
4370
  } catch {
4353
- _handleStateCorruption(ACTIVE_JOBS_FILE);
4371
+ _handleStateCorruption2(ACTIVE_JOBS_FILE);
4354
4372
  return {};
4355
4373
  }
4356
4374
  }
@@ -5543,7 +5561,7 @@ function _loadDynamicPricingCache() {
5543
5561
  return {};
5544
5562
  const st = statSync5(PRICING_CACHE_FILE2);
5545
5563
  if (st.size > 10485760) {
5546
- _handleStateCorruption(PRICING_CACHE_FILE2);
5564
+ _handleStateCorruption2(PRICING_CACHE_FILE2);
5547
5565
  _dynamicPricingCache = {};
5548
5566
  return {};
5549
5567
  }
@@ -5551,7 +5569,7 @@ function _loadDynamicPricingCache() {
5551
5569
  const map = raw?.models && typeof raw.models === "object" ? raw.models : {};
5552
5570
  _dynamicPricingCache = map;
5553
5571
  } catch {
5554
- _handleStateCorruption(PRICING_CACHE_FILE2);
5572
+ _handleStateCorruption2(PRICING_CACHE_FILE2);
5555
5573
  _dynamicPricingCache = {};
5556
5574
  }
5557
5575
  return _dynamicPricingCache;
@@ -5646,7 +5664,7 @@ function _loadPricingOverrides() {
5646
5664
  return {};
5647
5665
  const st = statSync5(tiersFile);
5648
5666
  if (st.size > 10485760) {
5649
- _handleStateCorruption(tiersFile);
5667
+ _handleStateCorruption2(tiersFile);
5650
5668
  _pricingOverridesCache = {};
5651
5669
  return {};
5652
5670
  }
@@ -5677,7 +5695,7 @@ function _loadPricingOverrides() {
5677
5695
  }
5678
5696
  _pricingOverridesCache = out;
5679
5697
  } catch {
5680
- _handleStateCorruption(join5(home, "model-tiers.json"));
5698
+ _handleStateCorruption2(join5(home, "model-tiers.json"));
5681
5699
  _pricingOverridesCache = {};
5682
5700
  }
5683
5701
  return _pricingOverridesCache;
@@ -5813,7 +5831,7 @@ function loadSelection2() {
5813
5831
  return DFLT_SEL2;
5814
5832
  const st = statSync5(TIERS_FILE3);
5815
5833
  if (st.size > 10485760) {
5816
- _handleStateCorruption(TIERS_FILE3);
5834
+ _handleStateCorruption2(TIERS_FILE3);
5817
5835
  return DFLT_SEL2;
5818
5836
  }
5819
5837
  const j = safeJsonParse3(readFileSync5(TIERS_FILE3, "utf-8"));
@@ -5836,7 +5854,7 @@ function loadSelection2() {
5836
5854
  executed_model: j?.selection?.executed_model || null
5837
5855
  };
5838
5856
  } catch {
5839
- _handleStateCorruption(TIERS_FILE3);
5857
+ _handleStateCorruption2(TIERS_FILE3);
5840
5858
  return DFLT_SEL2;
5841
5859
  }
5842
5860
  }
@@ -6064,7 +6082,7 @@ function loadTrinitySlotsFromTiersFile() {
6064
6082
  return false;
6065
6083
  const st = statSync5(TIERS_FILE3);
6066
6084
  if (st.size > 10485760) {
6067
- _handleStateCorruption(TIERS_FILE3);
6085
+ _handleStateCorruption2(TIERS_FILE3);
6068
6086
  return false;
6069
6087
  }
6070
6088
  const tiersData = safeJsonParse3(readFileSync5(TIERS_FILE3, "utf-8")) || {};
@@ -6774,7 +6792,7 @@ function classifyTurnSimple2(userText) {
6774
6792
  async function classifyTurnRemote(text) {
6775
6793
  try {
6776
6794
  const client2 = getApiClient2();
6777
- if (!client2 || isApiFallback())
6795
+ if (!client2 || isApiFallback2())
6778
6796
  return classifyTurnSimple(text);
6779
6797
  const res = await client2.classifyQuery(text);
6780
6798
  if (res && typeof res === "object" && "sub_regime" in res) {
@@ -6805,7 +6823,7 @@ function resolveOptimizationMode(subRegime, stressMultiplier, optimizationMode)
6805
6823
  const normalized = String(optimizationMode || "auto").toLowerCase();
6806
6824
  if (normalized === "auto" || normalized === "")
6807
6825
  return autoSelectMode2(subRegime || "INIT", stressMultiplier);
6808
- if (isApiFallback())
6826
+ if (isApiFallback2())
6809
6827
  return "vibelitex";
6810
6828
  if (normalized === "balanced" || normalized === "budget" || normalized === "quality" || normalized === "speed" || normalized === "longrun" || normalized === "audit" || normalized === "forensic" || normalized === "vibeultrax" || normalized === "vibeqmax" || normalized === "vibemax" || normalized === "vibelitex") {
6811
6829
  return normalized;
@@ -6817,7 +6835,7 @@ async function selectOptimizationModeRemote(subRegime, stressMultiplier, fallbac
6817
6835
  const fallback2 = resolveOptimizationMode(subRegime, stressMultiplier, fallbackMode);
6818
6836
  if (normalizedRequestedMode !== "auto" && normalizedRequestedMode !== "")
6819
6837
  return fallback2;
6820
- if (isApiFallback())
6838
+ if (isApiFallback2())
6821
6839
  return fallback2;
6822
6840
  try {
6823
6841
  const client2 = getApiClient2();
@@ -7085,7 +7103,7 @@ function resolveEnforcementMode() {
7085
7103
  async function syncOutcomeToApi(outcome) {
7086
7104
  try {
7087
7105
  const client2 = getApiClient2();
7088
- if (!client2 || isApiFallback())
7106
+ if (!client2 || isApiFallback2())
7089
7107
  return;
7090
7108
  await client2.blackboxOutcome(_OC_SID, outcome);
7091
7109
  } catch {
@@ -7094,7 +7112,7 @@ async function syncOutcomeToApi(outcome) {
7094
7112
  async function fetchBlackboxEnrichment(sessionId, localState) {
7095
7113
  try {
7096
7114
  const client2 = getApiClient2();
7097
- if (!client2 || isApiFallback())
7115
+ if (!client2 || isApiFallback2())
7098
7116
  return null;
7099
7117
  const result = await client2.blackboxAnalyze(sessionId, {
7100
7118
  userText: "",
@@ -7248,6 +7266,27 @@ function setBlackboxEnabled2(val) {
7248
7266
  var DFLT_OPTIMIZATION_MODE = "budget";
7249
7267
  function loadOptimizationMode() {
7250
7268
  try {
7269
+ const sel = loadSelection();
7270
+ const persistedMode = sel.optimization_mode || null;
7271
+ if (persistedMode === "vibelitex" && !isApiFallback2()) {
7272
+ const prevKey = `${_OC_SID}_prev_opt`;
7273
+ const recoveryMode = sel.previous_optimization_mode || loadSessionOptMode(prevKey);
7274
+ if (recoveryMode && recoveryMode !== "vibelitex") {
7275
+ try {
7276
+ writeSelection("previous_optimization_mode", null);
7277
+ } catch {
7278
+ }
7279
+ try {
7280
+ writeSessionOptMode2(_OC_SID, recoveryMode);
7281
+ } catch {
7282
+ }
7283
+ try {
7284
+ writeSessionOptMode2(prevKey, "");
7285
+ } catch {
7286
+ }
7287
+ return recoveryMode;
7288
+ }
7289
+ }
7251
7290
  const mode = loadSessionOptMode(_OC_SID);
7252
7291
  if (mode && mode !== "auto")
7253
7292
  return mode;
@@ -7261,7 +7300,7 @@ function loadOptimizationMode() {
7261
7300
  }
7262
7301
  function saveOptimizationMode(mode) {
7263
7302
  try {
7264
- writeSessionOptMode(_OC_SID, mode);
7303
+ writeSessionOptMode2(_OC_SID, mode);
7265
7304
  } catch (e) {
7266
7305
  console.error("[vibeOS] saveOptimizationMode session write failed: " + e.message);
7267
7306
  }
@@ -7638,12 +7677,12 @@ function readJsonOrEmpty2(filePath) {
7638
7677
  return {};
7639
7678
  const st = statSync6(filePath);
7640
7679
  if (st.size > 10485760) {
7641
- _handleStateCorruption(filePath);
7680
+ _handleStateCorruption2(filePath);
7642
7681
  return {};
7643
7682
  }
7644
7683
  return safeJsonParse3(readFileSync10(filePath, "utf-8"));
7645
7684
  } catch {
7646
- _handleStateCorruption(filePath);
7685
+ _handleStateCorruption2(filePath);
7647
7686
  return {};
7648
7687
  }
7649
7688
  }
@@ -10565,7 +10604,11 @@ async function apiComputeControlVector(state, action, optimizationMode) {
10565
10604
  const res = await remoteCall("blackboxControlVector", [state, action, optimizationMode], null);
10566
10605
  if (res?.control_vector) {
10567
10606
  const local = computeControlVector2(state, action, optimizationMode);
10568
- return mergeRemoteControlVector(res.control_vector, local);
10607
+ const merged = mergeRemoteControlVector(res.control_vector, local);
10608
+ if (res.rf_prediction?.mode && res.rf_prediction.mode !== res.control_vector?.optimization_mode) {
10609
+ merged.optimization_mode = res.rf_prediction.mode;
10610
+ }
10611
+ return merged;
10569
10612
  }
10570
10613
  } catch {
10571
10614
  }
@@ -10708,7 +10751,7 @@ function syncControlSettings(cv, options = {}) {
10708
10751
  const writeIf = (key, val) => {
10709
10752
  const sel = loadSelection();
10710
10753
  if (sel[key] !== val)
10711
- writeSelection(key, val);
10754
+ writeSelection2(key, val);
10712
10755
  };
10713
10756
  if (isManualMode) {
10714
10757
  const allEntries = [...BRANDED_MODES, ...RUNTIME_MODES];
@@ -10749,8 +10792,26 @@ function syncControlSettings(cv, options = {}) {
10749
10792
  writeIf("thinking_level", nextThinking);
10750
10793
  }
10751
10794
  if (persistOptimizationMode && cv.optimization_mode && userOptMode !== "auto") {
10752
- if (userOptMode !== cv.optimization_mode) {
10795
+ const fallbackPinned = isApiFallback() && cv.optimization_mode === "vibelitex";
10796
+ const previousOptMode2 = typeof currentSel.previous_optimization_mode === "string" ? currentSel.previous_optimization_mode : null;
10797
+ const prevSessionKey2 = `${sid}_prev_opt`;
10798
+ const sessionPreviousOptMode = loadSessionOptMode(prevSessionKey2);
10799
+ const restoreMode = sessionPreviousOptMode || previousOptMode2;
10800
+ const canRestorePrevious = !isApiFallback() && !!restoreMode && cv.optimization_mode !== "vibelitex" && (previousOptMode2 !== null || sessionPreviousOptMode !== null);
10801
+ if (fallbackPinned) {
10802
+ if (currentSel.optimization_mode !== "vibelitex") {
10803
+ writeIf("previous_optimization_mode", currentSel.optimization_mode);
10804
+ writeSessionOptMode(prevSessionKey2, currentSel.optimization_mode || "");
10805
+ }
10806
+ } else if (canRestorePrevious) {
10807
+ writeIf("optimization_mode", restoreMode);
10808
+ writeIf("previous_optimization_mode", null);
10809
+ writeSessionOptMode(sid, restoreMode);
10810
+ writeSessionOptMode(prevSessionKey2, "");
10811
+ } else if (userOptMode !== cv.optimization_mode) {
10753
10812
  writeIf("optimization_mode", cv.optimization_mode);
10813
+ if (previousOptMode2)
10814
+ writeIf("previous_optimization_mode", null);
10754
10815
  }
10755
10816
  }
10756
10817
  const slot = cv.tier_bias;
@@ -10774,7 +10835,7 @@ function syncControlSettings(cv, options = {}) {
10774
10835
  const oc = safeJsonParse3(readFileSync13(OC_CONFIG, "utf-8"));
10775
10836
  if (oc.default_agent !== cv.agent_mode) {
10776
10837
  if (cv.agent_mode === "plan" && oc.default_agent && oc.default_agent !== "plan") {
10777
- writeSelection("previous_default_agent", oc.default_agent);
10838
+ writeSelection2("previous_default_agent", oc.default_agent);
10778
10839
  }
10779
10840
  oc.default_agent = cv.agent_mode;
10780
10841
  writeFileSync12(OC_CONFIG, JSON.stringify(oc, null, 2) + "\n");
@@ -10792,12 +10853,24 @@ function syncControlSettings(cv, options = {}) {
10792
10853
  oc.default_agent = restoreAgent;
10793
10854
  writeFileSync12(OC_CONFIG, JSON.stringify(oc, null, 2) + "\n");
10794
10855
  if (currentSel.previous_default_agent)
10795
- writeSelection("previous_default_agent", null);
10856
+ writeSelection2("previous_default_agent", null);
10796
10857
  }
10797
10858
  }
10798
10859
  } catch {
10799
10860
  }
10800
10861
  }
10862
+ if (!isApiFallback() && cv.optimization_mode && cv.optimization_mode !== "vibelitex") {
10863
+ const finalSel = loadSelection();
10864
+ if (finalSel.optimization_mode === "vibelitex") {
10865
+ const restoreCandidate = finalSel.previous_optimization_mode || loadSessionOptMode(prevSessionKey) || previousOptMode;
10866
+ if (restoreCandidate && restoreCandidate !== "vibelitex") {
10867
+ writeSelection2("optimization_mode", restoreCandidate);
10868
+ writeSelection2("previous_optimization_mode", null);
10869
+ writeSessionOptMode(sid, restoreCandidate);
10870
+ writeSessionOptMode(prevSessionKey, "");
10871
+ }
10872
+ }
10873
+ }
10801
10874
  } catch {
10802
10875
  }
10803
10876
  }
@@ -10929,6 +11002,7 @@ async function trackBlackbox(messages) {
10929
11002
  localState.latest_stress_multiplier = st;
10930
11003
  saveSessionStress(st, st > 1.5 ? "critical" : st > 0.7 ? "elevated" : st > 0.3 ? "moderate" : "none");
10931
11004
  }
11005
+ localState.user_text = latestUserIntent;
10932
11006
  const modePreview = peekBudgetFirstMode({
10933
11007
  requestedMode: loadOptimizationMode(),
10934
11008
  subRegime: localState.sub_regime || "INIT",
@@ -11083,13 +11157,15 @@ var onSystemTransform = async (_input, output) => {
11083
11157
  const st = scoreStress(latestUserIntent);
11084
11158
  _controlVector = await apiComputeControlVector({
11085
11159
  sub_regime: classifiedRegime,
11086
- latest_stress_multiplier: st || void 0
11160
+ latest_stress_multiplier: st || void 0,
11161
+ user_text: latestUserIntent
11087
11162
  }, void 0, optimizationMode);
11088
11163
  }
11089
11164
  if (!_controlVector) {
11090
11165
  _controlVector = await apiComputeControlVector({
11091
11166
  sub_regime: "INIT",
11092
- latest_stress_multiplier: latestUserIntent ? scoreStress(latestUserIntent) : void 0
11167
+ latest_stress_multiplier: latestUserIntent ? scoreStress(latestUserIntent) : void 0,
11168
+ user_text: latestUserIntent || void 0
11093
11169
  }, void 0, optimizationMode);
11094
11170
  }
11095
11171
  const system = output?.system;
@@ -13570,26 +13646,28 @@ ${argsJson}
13570
13646
  }
13571
13647
  costDetector.record(modelCost);
13572
13648
  }
13573
- if (_credit < 40 && !compatibilityMode) {
13574
- const total = recordSaving(t, "credit<40% high-tier", _estOpus, {
13649
+ const tLower = String(t || "").toLowerCase();
13650
+ const lowCreditNudge = _credit < 40 && !compatibilityMode;
13651
+ if (lowCreditNudge) {
13652
+ const total = recordSaving(t, "credit<40% high-tier", _estEdit, {
13575
13653
  firstWord: _firstWord,
13576
13654
  projectFingerprint: currentProjectFingerprint,
13577
13655
  projectName: currentProjectName || "",
13578
13656
  sessionId: getCurrentSessionId()
13579
13657
  });
13580
- const msg = `[vibeOS] Quick win: ${resolveTierIcon("cheap")} cheap lane open \xB7 switch to ${resolveTierIcon("medium")} medium to save about ~$${_estOpus.toFixed(3)}/turn.`;
13658
+ const msg = `[vibeOS] Quick win: ${resolveTierIcon("cheap")} cheap lane open \xB7 switch to ${resolveTierIcon("medium")} medium to save about ~$${_estEdit.toFixed(3)}/turn.`;
13581
13659
  if (shouldLogWarn(`${t}|credit|${_tierWord}`) && process.env.VIBEOS_DEBUG_DELEGATION === "1") {
13582
13660
  console.error(`[vibeOS] [delegation] ${msg}`);
13583
13661
  }
13584
13662
  pendingUiNote = msg;
13585
- return;
13663
+ if (!WARN_ON_DIRECT.has(tLower))
13664
+ return;
13586
13665
  }
13587
- if (WARN_ON_DIRECT.has(String(t || "").toLowerCase())) {
13666
+ if (WARN_ON_DIRECT.has(tLower)) {
13588
13667
  const argSources = _toolArgSources(input, output);
13589
13668
  if (process.env.VIBEOS_DEBUG_DELEGATION === "1")
13590
13669
  console.error(`[vibeOS] [enforce-debug] tool=${t} tier=${currentTier} enforce=${sel?.delegation_enforce} argsType=${typeof args} argsExists=${argSources.length > 0}`);
13591
- const tLower = String(t || "").toLowerCase();
13592
- if (!compatibilityMode && sel.delegation_enforce && currentTier === "high" && argSources.length > 0) {
13670
+ if (!compatibilityMode && sel.delegation_enforce && currentTier === "high") {
13593
13671
  const originalPath = argSources.flatMap((src) => [src?.filePath, src?.file_path, src?.path]).find((v) => typeof v === "string" && v.trim()) || "";
13594
13672
  const basename6 = originalPath.split("/").pop() || "blocked";
13595
13673
  const apiResult = await remoteCall("delegateCheck", [tLower, currentTier, currentModel, _prompt], () => ({
@@ -13599,32 +13677,36 @@ ${argsJson}
13599
13677
  const isBlocked = apiResult?.blocked !== false;
13600
13678
  const savings = apiResult?.savings ?? _estEdit;
13601
13679
  if (isBlocked) {
13602
- const total2 = recordSaving(t, "delegation enforced", savings, {
13603
- firstWord: _firstWord,
13604
- projectFingerprint: currentProjectFingerprint,
13605
- projectName: currentProjectName || "",
13606
- sessionId: getCurrentSessionId()
13607
- });
13680
+ if (!lowCreditNudge) {
13681
+ const total = recordSaving(t, "delegation enforced", savings, {
13682
+ firstWord: _firstWord,
13683
+ projectFingerprint: currentProjectFingerprint,
13684
+ projectName: currentProjectName || "",
13685
+ sessionId: getCurrentSessionId()
13686
+ });
13687
+ }
13608
13688
  pendingUiNote = `[delegation] This is a good candidate for a Task subagent \u2014 ${resolveTierIcon("brain")} brain handles orchestration, let cheaper tiers do the write/edit. Switch to ${resolveTierIcon("medium")} medium with \`trinity medium\` if you'd rather do it directly.`;
13609
13689
  enforcementBlocked = true;
13610
13690
  if (shouldLogWarn(`${t}|enforced|${_tierWord}`))
13611
13691
  console.error(`[vibeOS] [enforcement] BLOCKED direct ${t} on high tier \u2192 delegate via Task`);
13612
13692
  return;
13613
13693
  }
13614
- }
13615
- const total = recordSaving(t, "direct edit", _estEdit, {
13616
- firstWord: _firstWord,
13617
- projectFingerprint: currentProjectFingerprint,
13618
- projectName: currentProjectName || "",
13619
- sessionId: getCurrentSessionId()
13620
- });
13621
- if (!compatibilityMode) {
13622
- const msg = `[vibeOS] ${resolveTierIcon("cheap")} cheap lane \xB7 save about ~$${_estEdit.toFixed(3)} by delegating to Task. Try ${resolveTierIcon("medium")} medium.`;
13623
- if (shouldLogWarn(`${t}|direct|${_tierWord}`) && process.env.VIBEOS_DEBUG_DELEGATION === "1") {
13624
- console.error(`[vibeOS] [delegation] ${msg}`);
13694
+ if (!lowCreditNudge) {
13695
+ const total = recordSaving(t, "direct edit", _estEdit, {
13696
+ firstWord: _firstWord,
13697
+ projectFingerprint: currentProjectFingerprint,
13698
+ projectName: currentProjectName || "",
13699
+ sessionId: getCurrentSessionId()
13700
+ });
13701
+ }
13702
+ if (!compatibilityMode) {
13703
+ const msg = `[vibeOS] ${resolveTierIcon("cheap")} cheap lane \xB7 save about ~$${_estEdit.toFixed(3)} by delegating to Task. Try ${resolveTierIcon("medium")} medium.`;
13704
+ if (shouldLogWarn(`${t}|direct|${_tierWord}`) && process.env.VIBEOS_DEBUG_DELEGATION === "1") {
13705
+ console.error(`[vibeOS] [delegation] ${msg}`);
13706
+ }
13707
+ pendingUiNote = msg;
13708
+ return;
13625
13709
  }
13626
- pendingUiNote = msg;
13627
- return;
13628
13710
  }
13629
13711
  }
13630
13712
  if (SOFT_QUOTA.has(t)) {
@@ -14260,9 +14342,30 @@ function _loadActiveJobForProject(directory3, fp2 = "") {
14260
14342
  }
14261
14343
  return getActiveJobForProject(fp2);
14262
14344
  }
14263
- async function _seedModelTiersIfMissing(directory3) {
14345
+ function _tiersNeedRepair(tiers) {
14346
+ const slots = ["brain", "medium", "cheap"];
14347
+ if (!tiers || typeof tiers !== "object") return true;
14348
+ return slots.some((slot) => {
14349
+ const oc = String(tiers?.trinity?.[slot]?.oc || "").trim();
14350
+ return !oc || PLACEHOLDER_RE.test(oc);
14351
+ });
14352
+ }
14353
+ async function _seedOrRepairModelTiers(directory3) {
14264
14354
  const TIERS_FILE3 = getTiersFile();
14265
- if (existsSync18(TIERS_FILE3))
14355
+ let existing = null;
14356
+ if (existsSync18(TIERS_FILE3)) {
14357
+ try {
14358
+ const st = statSync9(TIERS_FILE3);
14359
+ if (st.size > 10485760) {
14360
+ _handleStateCorruption(TIERS_FILE3);
14361
+ return false;
14362
+ }
14363
+ existing = safeJsonParse3(readFileSync17(TIERS_FILE3, "utf-8")) || {};
14364
+ } catch {
14365
+ existing = null;
14366
+ }
14367
+ }
14368
+ if (existing && !_tiersNeedRepair(existing))
14266
14369
  return false;
14267
14370
  const providers = _loadOpenCodeProviders(directory3);
14268
14371
  const auth = typeof _readAuth === "function" ? _readAuth() : {};
@@ -14285,25 +14388,31 @@ async function _seedModelTiersIfMissing(directory3) {
14285
14388
  cheap = "deepseek/deepseek-chat";
14286
14389
  console.error("[vibeOS] no providers detected \u2014 using default model tiers (brain=v4-pro, medium=v4-flash, cheap=v4-chat)");
14287
14390
  }
14391
+ const existingSelection = existing?.selection && typeof existing.selection === "object" ? existing.selection : {};
14392
+ const existingTrinity = existing?.trinity && typeof existing.trinity === "object" ? existing.trinity : {};
14393
+ const nextTrinity = {
14394
+ brain: existingTrinity.brain?.manual === true && String(existingTrinity.brain?.oc || "").trim() && !PLACEHOLDER_RE.test(String(existingTrinity.brain?.oc || "")) ? { ...existingTrinity.brain, cc: existingTrinity.brain?.cc || modelToCcAlias(String(existingTrinity.brain?.oc || "")) } : { oc: brain, cc: modelToCcAlias(brain) },
14395
+ medium: existingTrinity.medium?.manual === true && String(existingTrinity.medium?.oc || "").trim() && !PLACEHOLDER_RE.test(String(existingTrinity.medium?.oc || "")) ? { ...existingTrinity.medium, cc: existingTrinity.medium?.cc || modelToCcAlias(String(existingTrinity.medium?.oc || "")) } : { oc: medium, cc: modelToCcAlias(medium) },
14396
+ cheap: existingTrinity.cheap?.manual === true && String(existingTrinity.cheap?.oc || "").trim() && !PLACEHOLDER_RE.test(String(existingTrinity.cheap?.oc || "")) ? { ...existingTrinity.cheap, cc: existingTrinity.cheap?.cc || modelToCcAlias(String(existingTrinity.cheap?.oc || "")) } : { oc: cheap, cc: modelToCcAlias(cheap) }
14397
+ };
14398
+ const activeSlot = ["brain", "medium", "cheap"].includes(String(existingSelection.active_slot || "").trim()) ? String(existingSelection.active_slot) : "brain";
14288
14399
  const tiers = {
14400
+ ...existing,
14289
14401
  selection: {
14290
- enabled: true,
14291
- active_slot: "brain",
14292
- thinking_level: "off",
14293
- flow_enabled: false,
14294
- flow_enforce: false,
14295
- tdd_enforce: false,
14296
- tdd_strict: false,
14297
- tdd_quality: false,
14298
- delegation_enforce: true,
14299
- onboarding_mode: "assist",
14300
- setup_completed_at: (/* @__PURE__ */ new Date()).toISOString()
14402
+ ...existingSelection,
14403
+ enabled: existingSelection.enabled !== false,
14404
+ active_slot: activeSlot,
14405
+ thinking_level: existingSelection.thinking_level || "off",
14406
+ delegation_enforce: existingSelection.delegation_enforce !== false,
14407
+ flow_enabled: existingSelection.flow_enabled === true,
14408
+ flow_enforce: existingSelection.flow_enforce === true,
14409
+ tdd_enforce: existingSelection.tdd_enforce === true,
14410
+ tdd_strict: existingSelection.tdd_strict === true,
14411
+ tdd_quality: existingSelection.tdd_quality !== false,
14412
+ onboarding_mode: existingSelection.onboarding_mode || "assist",
14413
+ setup_completed_at: existingSelection.setup_completed_at || (/* @__PURE__ */ new Date()).toISOString()
14301
14414
  },
14302
- trinity: {
14303
- brain: { oc: brain, cc: modelToCcAlias(brain) },
14304
- medium: { oc: medium, cc: modelToCcAlias(medium) },
14305
- cheap: { oc: cheap, cc: modelToCcAlias(cheap) }
14306
- }
14415
+ trinity: nextTrinity
14307
14416
  };
14308
14417
  mkdirSync13(dirname13(TIERS_FILE3), { recursive: true });
14309
14418
  writeFileSync15(TIERS_FILE3, JSON.stringify(tiers, null, 2) + "\n", "utf-8");
@@ -14435,7 +14544,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
14435
14544
  if (!existsSync18(getTiersFile())) {
14436
14545
  console.error(`[vibeOS] model-tiers.json missing at load; will seed on first hook`);
14437
14546
  }
14438
- await _seedModelTiersIfMissing(directory3);
14547
+ await _seedOrRepairModelTiers(directory3);
14439
14548
  loadTrinitySlotsFromTiersFile();
14440
14549
  } catch {
14441
14550
  }
@@ -14559,7 +14668,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
14559
14668
  return hookVibeHome;
14560
14669
  },
14561
14670
  loadSelection,
14562
- writeSelection,
14671
+ writeSelection: writeSelection2,
14563
14672
  loadCredit,
14564
14673
  thinkingLevel,
14565
14674
  readLifetimeSavings,
@@ -14589,7 +14698,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
14589
14698
  setBlackboxEnabled,
14590
14699
  loadBlackboxState,
14591
14700
  saveBlackboxState,
14592
- isApiFallback: () => isApiFallback(),
14701
+ isApiFallback: () => isApiFallback2(),
14593
14702
  get _apiFallbackSince() {
14594
14703
  return _apiFallbackSince2;
14595
14704
  },
@@ -14597,7 +14706,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
14597
14706
  saveReportsIndex: saveReportsIndexStable,
14598
14707
  backupFile: backupFileStable,
14599
14708
  writeSessionSlot: writeSessionSlot2,
14600
- writeSessionOptMode,
14709
+ writeSessionOptMode: writeSessionOptMode2,
14601
14710
  _refreshModel,
14602
14711
  setApiToken,
14603
14712
  setApiBootstrapToken,
@@ -14843,7 +14952,7 @@ ${report.narrative}`);
14843
14952
  fallbackThinking: thinkingLevel(loadCredit()),
14844
14953
  backendConnected: isApiConnected2(),
14845
14954
  backendHealthUrl: `${VIBEOS_API_URL}/health`,
14846
- apiFallbackMode: isApiFallback(),
14955
+ apiFallbackMode: isApiFallback2(),
14847
14956
  apiFallbackSince: _apiFallbackSince2,
14848
14957
  modelLocked: _modelLocked,
14849
14958
  lockedSlot: _lockedSlot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.24.19",
3
+ "version": "0.24.22",
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",