vibeostheog 0.18.3 → 0.18.5

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,14 @@
1
+ ## 0.18.5
2
+ - fix: trinity slots now authoritative over opencode.json model
3
+
4
+
5
+ ## 0.18.4
6
+ - fix: quality tracking now computes avg from lifetime score/count instead of hardcoding 0
7
+ - fix: savings rate shown with 4 decimal precision (was rounding to $0.00/hr)
8
+ - fix: cache savings minimum enforced at $0.0001 per scratchpad hit (was rounding to $0)
9
+ - fix: ledger reconciliation flushes buffer before reading + uses Math.max() to prevent state drops
10
+ - fix: model lock no longer overridden by bogus opencode.json model
11
+
1
12
  ## 0.18.3
2
13
  - feat: dynamic mode injection + footer hooks fix
3
14
  - fix: auto-enable plugin on load + always show footer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.18.3",
3
+ "version": "0.18.5",
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",
package/src/index.js CHANGED
@@ -2516,6 +2516,7 @@ function reconcileStateFromLedger() {
2516
2516
  if (ledgerMtime === _ledgerReconciledMtime)
2517
2517
  return;
2518
2518
  _ledgerReconciledMtime = ledgerMtime;
2519
+ _flushLedgerBuffer();
2519
2520
  const l = readLedgerTotals();
2520
2521
  if (l.total <= 0)
2521
2522
  return;
@@ -2527,8 +2528,8 @@ function reconcileStateFromLedger() {
2527
2528
  return;
2528
2529
  updateState((s) => {
2529
2530
  s.lifetime ??= { warn_count: 0, total_savings_usd: 0, last_updated: "" };
2530
- s.lifetime.total_savings_usd = l.delegation;
2531
- s.lifetime.cache_savings_usd = l.cache;
2531
+ s.lifetime.total_savings_usd = Math.max(l.delegation, stDelegation);
2532
+ s.lifetime.cache_savings_usd = Math.max(l.cache, stCache);
2532
2533
  s.lifetime.last_updated = (/* @__PURE__ */ new Date()).toISOString();
2533
2534
  s.lifetime.rebuilt_from_ledger = true;
2534
2535
  s.lifetime.ledger_entries_reconciled = l.entries;
@@ -3036,7 +3037,7 @@ function _refreshModel(directory3) {
3036
3037
  console.error(`[vibeOS] auto-detected model: ${currentModel} (tier=${currentTier})`);
3037
3038
  }
3038
3039
  }
3039
- if (!_modelLocked2) {
3040
+ if (!_modelLocked2 && !slotOcModel) {
3040
3041
  const cfgModel = readConfig(directory3) || readConfig(join4(USER_HOME3, ".config/opencode")) || "";
3041
3042
  if (cfgModel && cfgModel !== currentModel) {
3042
3043
  const oldModel = currentModel;
@@ -6227,11 +6228,19 @@ function readLifetimeSavings2() {
6227
6228
  sesCache: roundUsd2(ses?.cache_savings_usd || 0),
6228
6229
  sesTaskDelegations: ses?.task_delegations_count || 0,
6229
6230
  sesDuration: ses?.duration_seconds || 0,
6230
- sesRatePerHour: ses?.rate_per_hour || 0,
6231
+ sesRatePerHour: (() => {
6232
+ const sesTotal = Number(ses?.total_savings_usd || 0) + Number(ses?.cache_savings_usd || 0);
6233
+ if (!sesTotal)
6234
+ return 0;
6235
+ const dur = Number(ses?.duration_seconds || 0);
6236
+ if (dur <= 0)
6237
+ return 0;
6238
+ return Number((sesTotal / (dur / 3600)).toFixed(4));
6239
+ })(),
6231
6240
  sesTrend: ses?.trend || "",
6232
6241
  sesToolBreakdown: ses?.tool_breakdown || {},
6233
6242
  sesModelTurns: ses?.model_turns || {},
6234
- quality_avg: ses?.quality_avg || 0
6243
+ quality_avg: state?.lifetime?.quality_total_count > 0 ? Math.round((state?.lifetime?.quality_total_score || 0) / state?.lifetime?.quality_total_count) : 0
6235
6244
  };
6236
6245
  } catch {
6237
6246
  return { ltTasks: 0, ltCache: 0, ltCost: 0, count: 0, sesTasks: 0, sesCache: 0, sesTaskDelegations: 0, sesDuration: 0, sesRatePerHour: 0, sesTrend: "", sesToolBreakdown: {}, sesModelTurns: {}, quality_avg: 0 };
@@ -7799,7 +7808,7 @@ var onToolExecuteBefore = async (input, output) => {
7799
7808
  scratchpadHitsSeen2.add(hit.hash);
7800
7809
  const total = recordScratchpadObservation();
7801
7810
  const _inputTokens = Math.max(1, Math.round(hit.sizeBytes / BYTES_PER_TOKEN));
7802
- _cacheSave = Math.round(_inputTokens * CACHE_SAVED_PER_1M_INPUT_TOKENS / 1e6 * 1e3) / 1e3;
7811
+ _cacheSave = Math.max(1e-4, Math.round(_inputTokens * CACHE_SAVED_PER_1M_INPUT_TOKENS / 1e6 * 1e4) / 1e4);
7803
7812
  const cacheSaved = recordCacheSaving(t, _cacheSave, { hash: hit.hash });
7804
7813
  const sumNote = hit.summaryPath ? ` (summary: ${hit.summaryPath})` : "";
7805
7814
  const cacheNote = cacheSaved ? `, cache+$${(cacheSaved.lifetime || 0).toFixed(3)} lt` : "";