vibeostheog 0.24.26 → 0.24.29

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,20 @@
1
+ ## 0.24.29
2
+ - feat: promote data-backed experimental regimes (#158)
3
+ - feat: promote data-backed experimental regimes
4
+ - test: add live lifecycle regression
5
+ - chore: v0.24.28
6
+ Merge pull request #160 from DrunkkToys/codex/release-patch-0.24.28
7
+ Fix clean CI sync for generated modules
8
+ Fix CI sync for generated modules
9
+ Fix CI artifact sync
10
+ Sync generated flow rules
11
+ Merge remote-tracking branch 'origin/master' into codex/release-patch-0.24.28
12
+ Fix release CI regressions
13
+ Merge pull request #159 from DrunkkToys/codex/release-patch-0.24.28
14
+ Strengthen cascade lifecycle coverage
15
+ Merge branch 'master' of https://github.com/DrunkkToys/vibeOS into codex/release-patch-0.24.28
16
+
17
+
1
18
  ## 0.24.25
2
19
  - fix: heal stale vibelitex recovery across cascade
3
20
 
package/dist/vibeOS.js CHANGED
@@ -454,6 +454,12 @@ function autoSelectMode(subRegime, stressMultiplier) {
454
454
  return "speed";
455
455
  if (regime === "CONVERGING" || regime === "CLOSED")
456
456
  return "quality";
457
+ if (regime === "IMPLEMENTING")
458
+ return "quality";
459
+ if (regime === "RESEARCH" || regime === "DESIGNING")
460
+ return "longrun";
461
+ if (regime === "REVIEWING")
462
+ return "audit";
457
463
  if (stressMultiplier && stressMultiplier > QUALITY_STRESS_THRESHOLD)
458
464
  return "quality";
459
465
  return "litex";
@@ -515,6 +521,58 @@ var init_meta_controller = __esm({
515
521
  context7_urgency: "preferred",
516
522
  wbp_verbosity: "normal"
517
523
  },
524
+ IMPLEMENTING: {
525
+ enforcement_mode: "strict",
526
+ enforcement_reason: "implementation work \u2014 validate code changes and keep tests on",
527
+ flow_mode: "strict",
528
+ flow_focus: ["write-edit-check", "no-untouched-files"],
529
+ tdd_mode: "strict",
530
+ tdd_focus: ["skeleton-on-write", "assertion-check"],
531
+ tier_bias: "brain",
532
+ thinking_mode: "brief",
533
+ stress_multiplier: 1.3,
534
+ context7_urgency: "required",
535
+ wbp_verbosity: "normal"
536
+ },
537
+ RESEARCH: {
538
+ enforcement_mode: "normal",
539
+ enforcement_reason: "research mode \u2014 collect evidence before changing anything",
540
+ flow_mode: "audit",
541
+ flow_focus: ["trace-audit"],
542
+ tdd_mode: "lazy",
543
+ tdd_focus: [],
544
+ tier_bias: "brain",
545
+ thinking_mode: "full",
546
+ stress_multiplier: 1.2,
547
+ context7_urgency: "required",
548
+ wbp_verbosity: "detailed"
549
+ },
550
+ REVIEWING: {
551
+ enforcement_mode: "strict",
552
+ enforcement_reason: "review mode \u2014 validate diffs and surface risks",
553
+ flow_mode: "strict",
554
+ flow_focus: ["write-edit-check", "no-untouched-files", "no-lgtm"],
555
+ tdd_mode: "quality",
556
+ tdd_focus: ["full-coverage", "edge-cases"],
557
+ tier_bias: "brain",
558
+ thinking_mode: "brief",
559
+ stress_multiplier: 1.1,
560
+ context7_urgency: "required",
561
+ wbp_verbosity: "normal"
562
+ },
563
+ DESIGNING: {
564
+ enforcement_mode: "normal",
565
+ enforcement_reason: "design mode \u2014 explore architecture and tradeoffs",
566
+ flow_mode: "audit",
567
+ flow_focus: ["trace-audit"],
568
+ tdd_mode: "normal",
569
+ tdd_focus: [],
570
+ tier_bias: "brain",
571
+ thinking_mode: "full",
572
+ stress_multiplier: 1.1,
573
+ context7_urgency: "required",
574
+ wbp_verbosity: "detailed"
575
+ },
518
576
  CONVERGING: {
519
577
  enforcement_mode: "strict",
520
578
  enforcement_reason: "user about to commit \u2014 full enforcement, catch violations",
@@ -3802,26 +3860,10 @@ function loadBlackboxState() {
3802
3860
  for (const [sid, session] of Object.entries(raw.sessions)) {
3803
3861
  if (!session || typeof session !== "object")
3804
3862
  continue;
3805
- const next = { ...session };
3806
- const createdAtRaw = typeof next.createdAt === "string" ? next.createdAt : "";
3807
- const updatedAtRaw = typeof next.updatedAt === "string" ? next.updatedAt : "";
3808
- const startedRaw = typeof next.started === "string" ? next.started : "";
3809
- const sessionStartedRaw = typeof next.session_started_at === "string" ? next.session_started_at : "";
3810
- const anchorRaw = [createdAtRaw, updatedAtRaw, startedRaw, sessionStartedRaw].find((v) => v && !Number.isNaN(Date.parse(v)));
3811
- const anchorMs = anchorRaw ? Date.parse(anchorRaw) : NaN;
3812
- if (!Number.isFinite(Date.parse(createdAtRaw))) {
3813
- next.createdAt = Number.isFinite(anchorMs) ? new Date(anchorMs).toISOString() : new Date(now).toISOString();
3814
- changed = true;
3815
- }
3816
- if (!Number.isFinite(Date.parse(updatedAtRaw))) {
3817
- next.updatedAt = next.createdAt || new Date(now).toISOString();
3818
- changed = true;
3819
- }
3820
- if (typeof next.sessionId !== "string" || !next.sessionId.trim()) {
3821
- next.sessionId = String(sid || "");
3822
- changed = true;
3823
- }
3863
+ const { record: next, changed: recordChanged } = normalizeBlackboxRecord(session, sid, now);
3824
3864
  raw.sessions[sid] = next;
3865
+ if (recordChanged)
3866
+ changed = true;
3825
3867
  }
3826
3868
  if (changed) {
3827
3869
  try {
@@ -3844,22 +3886,7 @@ function saveBlackboxState(state) {
3844
3886
  for (const [sid, session] of Object.entries(next.sessions)) {
3845
3887
  if (!session || typeof session !== "object")
3846
3888
  continue;
3847
- const record = session;
3848
- const createdAtRaw = typeof record.createdAt === "string" ? record.createdAt : "";
3849
- const updatedAtRaw = typeof record.updatedAt === "string" ? record.updatedAt : "";
3850
- const startedRaw = typeof record.started === "string" ? record.started : "";
3851
- const sessionStartedRaw = typeof record.session_started_at === "string" ? record.session_started_at : "";
3852
- const anchorRaw = [createdAtRaw, updatedAtRaw, startedRaw, sessionStartedRaw].find((v) => v && !Number.isNaN(Date.parse(v)));
3853
- const anchorMs = anchorRaw ? Date.parse(anchorRaw) : NaN;
3854
- if (!Number.isFinite(Date.parse(createdAtRaw))) {
3855
- record.createdAt = Number.isFinite(anchorMs) ? new Date(anchorMs).toISOString() : new Date(now).toISOString();
3856
- }
3857
- if (!Number.isFinite(Date.parse(updatedAtRaw))) {
3858
- record.updatedAt = record.createdAt || new Date(now).toISOString();
3859
- }
3860
- if (typeof record.sessionId !== "string" || !record.sessionId.trim()) {
3861
- record.sessionId = String(sid || "");
3862
- }
3889
+ next.sessions[sid] = normalizeBlackboxRecord(session, sid, now).record;
3863
3890
  }
3864
3891
  mkdirSync3(dirname4(blackboxFile), { recursive: true });
3865
3892
  const tmp = blackboxFile + ".tmp";
@@ -3869,6 +3896,81 @@ function saveBlackboxState(state) {
3869
3896
  console.error(`[vibeOS] saveBlackboxState failed: ${err.message}`);
3870
3897
  }
3871
3898
  }
3899
+ function normalizeBlackboxRecord(record, sid, now) {
3900
+ const next = { ...record || {} };
3901
+ let changed = false;
3902
+ const createdAtRaw = typeof next.createdAt === "string" ? next.createdAt : "";
3903
+ const updatedAtRaw = typeof next.updatedAt === "string" ? next.updatedAt : "";
3904
+ const startedRaw = typeof next.started === "string" ? next.started : "";
3905
+ const sessionStartedRaw = typeof next.session_started_at === "string" ? next.session_started_at : "";
3906
+ const anchorRaw = [createdAtRaw, updatedAtRaw, startedRaw, sessionStartedRaw].find((v) => v && !Number.isNaN(Date.parse(v)));
3907
+ const anchorMs = anchorRaw ? Date.parse(anchorRaw) : NaN;
3908
+ if (!Number.isFinite(Date.parse(createdAtRaw))) {
3909
+ next.createdAt = Number.isFinite(anchorMs) ? new Date(anchorMs).toISOString() : new Date(now).toISOString();
3910
+ changed = true;
3911
+ }
3912
+ if (!Number.isFinite(Date.parse(updatedAtRaw))) {
3913
+ next.updatedAt = next.createdAt || new Date(now).toISOString();
3914
+ changed = true;
3915
+ }
3916
+ if (typeof next.sessionId !== "string" || !next.sessionId.trim()) {
3917
+ next.sessionId = String(sid || "");
3918
+ changed = true;
3919
+ }
3920
+ if (typeof next.project_fingerprint !== "string" || !next.project_fingerprint.trim()) {
3921
+ if (typeof currentProjectFingerprint === "string" && currentProjectFingerprint.trim()) {
3922
+ next.project_fingerprint = currentProjectFingerprint.trim();
3923
+ changed = true;
3924
+ }
3925
+ }
3926
+ if (typeof next.project_name !== "string" || !next.project_name.trim()) {
3927
+ if (typeof currentProjectName === "string" && currentProjectName.trim()) {
3928
+ next.project_name = currentProjectName.trim();
3929
+ changed = true;
3930
+ }
3931
+ }
3932
+ if (typeof next.regime !== "string" || !next.regime.trim()) {
3933
+ next.regime = typeof next.sub_regime === "string" && next.sub_regime.trim() ? next.sub_regime.trim() : "INIT";
3934
+ changed = true;
3935
+ }
3936
+ if (typeof next.sub_regime !== "string" || !next.sub_regime.trim()) {
3937
+ next.sub_regime = "INIT";
3938
+ changed = true;
3939
+ }
3940
+ if (typeof next.resolution !== "string" || !next.resolution.trim()) {
3941
+ next.resolution = "unresolved";
3942
+ changed = true;
3943
+ }
3944
+ if (!Number.isFinite(Number(next.momentum))) {
3945
+ next.momentum = 0;
3946
+ changed = true;
3947
+ }
3948
+ if (!Number.isFinite(Number(next.turn_counter))) {
3949
+ next.turn_counter = 0;
3950
+ changed = true;
3951
+ }
3952
+ if (!Number.isFinite(Number(next.loopCount))) {
3953
+ next.loopCount = 0;
3954
+ changed = true;
3955
+ }
3956
+ if (!Number.isFinite(Number(next.loop_consecutive))) {
3957
+ next.loop_consecutive = Number(next.loopCount || 0);
3958
+ changed = true;
3959
+ }
3960
+ if (!Array.isArray(next.history)) {
3961
+ next.history = [];
3962
+ changed = true;
3963
+ }
3964
+ if (!Array.isArray(next.pivotHistory)) {
3965
+ next.pivotHistory = [];
3966
+ changed = true;
3967
+ }
3968
+ if (!Array.isArray(next.outcomeHistory)) {
3969
+ next.outcomeHistory = [];
3970
+ changed = true;
3971
+ }
3972
+ return { record: next, changed };
3973
+ }
3872
3974
  function getSessionRoot() {
3873
3975
  return join4(SCRATCHPAD_SESSIONS_DIR, _OC_SID);
3874
3976
  }
@@ -6248,7 +6350,7 @@ import { join as join7, dirname as dirname8 } from "node:path";
6248
6350
 
6249
6351
  // src/vibeOS-lib/blackbox/resolution-tracker.js
6250
6352
  var ResolutionTracker = class _ResolutionTracker {
6251
- static SUB_REGIMES = ["INIT", "DIVERGENT", "EXPLORING", "REFINING", "CONVERGING", "CLOSED", "LOOPING"];
6353
+ static SUB_REGIMES = ["INIT", "DIVERGENT", "EXPLORING", "REFINING", "IMPLEMENTING", "RESEARCH", "REVIEWING", "DESIGNING", "CONVERGING", "CLOSED", "LOOPING"];
6252
6354
  sessionId;
6253
6355
  maxHistory;
6254
6356
  history;
@@ -6858,6 +6960,12 @@ function autoSelectMode2(subRegime, stressMultiplier) {
6858
6960
  return "speed";
6859
6961
  if (regime === "CONVERGING" || regime === "CLOSED")
6860
6962
  return "quality";
6963
+ if (regime === "IMPLEMENTING")
6964
+ return "quality";
6965
+ if (regime === "RESEARCH" || regime === "DESIGNING")
6966
+ return "longrun";
6967
+ if (regime === "REVIEWING")
6968
+ return "audit";
6861
6969
  if (stress > QUALITY_STRESS_THRESHOLD2)
6862
6970
  return "quality";
6863
6971
  return "vibelitex";
@@ -10417,6 +10525,10 @@ function recordSaving(tool2, reason, saveEst, meta = {}) {
10417
10525
  const w = ses.warns[i];
10418
10526
  if (w?.key === warnKey && now - w.ts < WARN_DEDUPE_WINDOW_MS) {
10419
10527
  w.count = (w.count || 1) + 1;
10528
+ w.est_savings_usd = roundUsd(Number(w.est_savings_usd || 0) + saveEst);
10529
+ w.saveEst = roundUsd(Number(w.saveEst || 0) + saveEst);
10530
+ ses.total_savings_usd = roundUsd(Number(ses.total_savings_usd || 0) + saveEst);
10531
+ s.lifetime.total_savings_usd = roundUsd(Number(s.lifetime.total_savings_usd || 0) + saveEst);
10420
10532
  deduped = true;
10421
10533
  }
10422
10534
  }
@@ -11430,6 +11542,10 @@ var REGIME_TAG = {
11430
11542
  DIVERGENT: "DVRG",
11431
11543
  EXPLORING: "XPLR",
11432
11544
  REFINING: "RFNE",
11545
+ IMPLEMENTING: "IMPL",
11546
+ RESEARCH: "RSCH",
11547
+ REVIEWING: "RVW",
11548
+ DESIGNING: "DSGN",
11433
11549
  CONVERGING: "CVGE",
11434
11550
  CLOSED: "CLSD",
11435
11551
  LOOPING: "LOOP",
@@ -11457,6 +11573,28 @@ function resolveBrand(optMode, activeSlot) {
11457
11573
  function resolveTierIcon(slot) {
11458
11574
  return TIER_ICON[slot] || "\u26A1";
11459
11575
  }
11576
+ function formatModeLabel(optMode) {
11577
+ const normalized = String(optMode || "").toLowerCase();
11578
+ if (!normalized)
11579
+ return "";
11580
+ if (normalized === "vibemax" || normalized === "vibelitex" || normalized === "budget")
11581
+ return "Budget";
11582
+ if (normalized === "vibeqmax" || normalized === "quality")
11583
+ return "Quality";
11584
+ if (normalized === "vibeultrax")
11585
+ return "VibeUltraX";
11586
+ if (normalized === "speed")
11587
+ return "Speed";
11588
+ if (normalized === "longrun")
11589
+ return "Longrun";
11590
+ if (normalized === "audit")
11591
+ return "Audit";
11592
+ if (normalized === "forensic")
11593
+ return "Forensic";
11594
+ if (normalized === "balanced")
11595
+ return "Balanced";
11596
+ return normalized.charAt(0).toUpperCase() + normalized.slice(1);
11597
+ }
11460
11598
  function formatVectorPulse(vectorChangedSlot) {
11461
11599
  if (!vectorChangedSlot)
11462
11600
  return "";
@@ -11515,6 +11653,7 @@ function buildFooterLine(input) {
11515
11653
  const { activeSlot, sessionSlot, providerLabel, modelName, ltTotal, ltTrend, vibeBrand, optMode, flashIcon, enfTags, vectorChangedSlot, subRegime } = input;
11516
11654
  const tierIcon = resolveTierIcon(activeSlot);
11517
11655
  const regimeTag = subRegime ? REGIME_TAG[subRegime] || subRegime.slice(0, 4) : null;
11656
+ const modeLabel = formatModeLabel(optMode);
11518
11657
  let line = `\u2014 ${tierIcon} ${activeSlot} | ${providerLabel} | ${modelName}${regimeTag ? ` \u25B6 ${regimeTag}` : ""}`;
11519
11658
  if (ltTotal > 0) {
11520
11659
  const savingsPulse = formatSavingsPulse(ltTotal, ltTrend);
@@ -11523,7 +11662,7 @@ function buildFooterLine(input) {
11523
11662
  }
11524
11663
  line += ` | ${vibeBrand}${flashIcon}`;
11525
11664
  if (optMode && optMode !== "auto") {
11526
- line += ` ${optMode}`;
11665
+ line += ` ${modeLabel}`;
11527
11666
  }
11528
11667
  if (vectorChangedSlot && vectorChangedSlot !== activeSlot) {
11529
11668
  line += ` | ${formatVectorPulse(vectorChangedSlot)}`;
@@ -11761,8 +11900,9 @@ async function _appendFooter(input, output, directory3) {
11761
11900
  }
11762
11901
  }
11763
11902
  const selNowFooter = loadSelection3();
11903
+ const normalizedIntent = classifyTurnSimple2(latestUserIntent || "");
11904
+ const currentSubRegime = _latestBlackboxState?.sub_regime || normalizedIntent;
11764
11905
  const bbMode = resolveEnforcementMode();
11765
- const optModeFooter = loadOptimizationMode();
11766
11906
  const enfTags = buildEnforcementTags({
11767
11907
  delegationEnforce: selNowFooter.delegation_enforce,
11768
11908
  flowEnforce: selNowFooter.flow_enforce,
@@ -11770,11 +11910,6 @@ async function _appendFooter(input, output, directory3) {
11770
11910
  bbMode,
11771
11911
  modelLocked: _modelLocked
11772
11912
  });
11773
- const resolvedMode = peekBudgetFirstMode({
11774
- requestedMode: optModeFooter,
11775
- subRegime: _latestBlackboxState?.sub_regime || classifyTurnSimple2(latestUserIntent || ""),
11776
- stress: _footerStress
11777
- }).mode;
11778
11913
  const stripped = text.replace(/\u2014 [^\u2014]+ \u2014\s*/g, "").trimEnd();
11779
11914
  if (stripped !== text)
11780
11915
  return;
@@ -11782,11 +11917,9 @@ async function _appendFooter(input, output, directory3) {
11782
11917
  return;
11783
11918
  const ltTotal = ltTasks + ltCache;
11784
11919
  const activeSlot = selNowFooter.active_slot || "brain";
11785
- const optMode = (resolvedMode || "budget").toLowerCase();
11786
11920
  const flashIcon = isApiConnected2() ? " \u26A1" : "";
11787
- const displayMode = resolvedMode || optModeFooter || optMode || selNowFooter?.optimization_mode || "auto";
11788
- const vibeBrand = resolveBrand(displayMode, activeSlot);
11789
- const currentSubRegime = _latestBlackboxState?.sub_regime || classifyTurnSimple2(latestUserIntent || "");
11921
+ const displayMode = autoSelectMode2(currentSubRegime, _footerStress);
11922
+ const vibeBrand = resolveBrand(loadOptimizationMode() || displayMode, activeSlot);
11790
11923
  const vibeLine = buildFooterLine({
11791
11924
  activeSlot,
11792
11925
  providerLabel: execution.provider_label,
@@ -11857,7 +11990,7 @@ import { writeFileSync as writeFileSync14, appendFileSync as appendFileSync6, ex
11857
11990
  import { join as join17, dirname as dirname12, basename as basename4 } from "node:path";
11858
11991
  import { createHash as createHash5 } from "node:crypto";
11859
11992
 
11860
- // src/lib/cost-anomaly.js
11993
+ // src/lib/cost-anomaly.ts
11861
11994
  var COST_WINDOW_SIZE = 20;
11862
11995
  var COST_ANOMALY_THRESHOLD = 3;
11863
11996
  var COST_WARMUP_SAMPLES = 5;
@@ -11868,26 +12001,21 @@ var CostAnomalyDetector = class {
11868
12001
  currentAnomalyCost = 0;
11869
12002
  currentAnomalyMean = 0;
11870
12003
  record(cost) {
11871
- if (this.disabled)
11872
- return;
12004
+ if (this.disabled) return;
11873
12005
  this.costHistory.push(cost);
11874
12006
  if (this.costHistory.length > COST_WINDOW_SIZE) {
11875
12007
  this.costHistory.shift();
11876
12008
  }
11877
12009
  }
11878
12010
  get mean() {
11879
- if (this.costHistory.length === 0)
11880
- return 0;
12011
+ if (this.costHistory.length === 0) return 0;
11881
12012
  return this.costHistory.reduce((a, b) => a + b, 0) / this.costHistory.length;
11882
12013
  }
11883
12014
  checkAnomaly(model, cost) {
11884
- if (this.disabled)
11885
- return false;
11886
- if (this.costHistory.length < COST_WARMUP_SAMPLES)
11887
- return false;
12015
+ if (this.disabled) return false;
12016
+ if (this.costHistory.length < COST_WARMUP_SAMPLES) return false;
11888
12017
  const avg = this.mean;
11889
- if (avg <= 0 || cost <= avg)
11890
- return false;
12018
+ if (avg <= 0 || cost <= avg) return false;
11891
12019
  const ratio = cost / avg;
11892
12020
  if (ratio > COST_ANOMALY_THRESHOLD) {
11893
12021
  this.currentAnomalyModel = model;
@@ -11909,8 +12037,7 @@ var CostAnomalyDetector = class {
11909
12037
  };
11910
12038
  var _costDetector = null;
11911
12039
  function getCostAnomalyDetector() {
11912
- if (!_costDetector)
11913
- _costDetector = new CostAnomalyDetector();
12040
+ if (!_costDetector) _costDetector = new CostAnomalyDetector();
11914
12041
  return _costDetector;
11915
12042
  }
11916
12043
 
@@ -13865,14 +13992,6 @@ var onToolExecuteAfter = async (input, output) => {
13865
13992
  const { ltTasks, ltCache, ltCost, sesTrend } = readLifetimeSavings();
13866
13993
  const ltTotal = ltTasks + ltCache;
13867
13994
  const selNow = loadSelection();
13868
- const bbMode = resolveEnforcementMode();
13869
- const enfTags = buildEnforcementTags({
13870
- delegationEnforce: selNow.delegation_enforce,
13871
- flowEnforce: selNow.flow_enforce,
13872
- tddEnforce: selNow.tdd_enforce,
13873
- bbMode,
13874
- modelLocked: _modelLocked
13875
- });
13876
13995
  let liveModel = "";
13877
13996
  try {
13878
13997
  const cfg = await client.config.get("model");
@@ -13891,12 +14010,19 @@ var onToolExecuteAfter = async (input, output) => {
13891
14010
  }
13892
14011
  const execution = resolveExecutionIdentity(input?.args?.model || resolvedModel || "", projectDirectory);
13893
14012
  const currentSid = _OC_SID;
13894
- const optModeFooter = loadSessionOptMode(currentSid + "_opt") || loadOptimizationMode() || "budget";
14013
+ const currentSubRegime = loadBlackboxState()?.sessions?.[currentSid]?.sub_regime || classifyTurnSimple2(latestUserIntent || "");
14014
+ const bbMode = resolveEnforcementMode();
14015
+ const enfTags = buildEnforcementTags({
14016
+ delegationEnforce: selNow.delegation_enforce,
14017
+ flowEnforce: selNow.flow_enforce,
14018
+ tddEnforce: selNow.tdd_enforce,
14019
+ bbMode,
14020
+ modelLocked: _modelLocked
14021
+ });
13895
14022
  const activeSlot = selNow.active_slot || (execution.quality === "brain" ? "brain" : execution.quality === "medium" ? "medium" : "cheap");
13896
- const vibeBrand = resolveBrand(optModeFooter, activeSlot);
14023
+ const displayMode = autoSelectMode2(currentSubRegime, latestUserIntent ? scoreStress(latestUserIntent) : 0);
14024
+ const vibeBrand = resolveBrand(displayMode, activeSlot);
13897
14025
  const sessionSlot = loadSessionSlot(currentSid);
13898
- const displayMode = selNow.optimization_mode || optModeFooter || "auto";
13899
- const currentSubRegime = loadBlackboxState()?.sessions?.[currentSid]?.sub_regime || classifyTurnSimple2(latestUserIntent || "");
13900
14026
  const flashIcon = isApiConnected2() ? " \u26A1" : "";
13901
14027
  _footerText = buildFooterLine({
13902
14028
  activeSlot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.24.26",
3
+ "version": "0.24.29",
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",