vibeostheog 0.24.25 → 0.24.27

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.
Files changed (2) hide show
  1. package/dist/vibeOS.js +122 -61
  2. package/package.json +1 -1
package/dist/vibeOS.js CHANGED
@@ -3489,9 +3489,30 @@ function runStartupMaintenanceOnce() {
3489
3489
  } catch {
3490
3490
  }
3491
3491
  }
3492
+ function _ensureVibeOSHomeDir() {
3493
+ try {
3494
+ if (!existsSync5(VIBEOS_HOME)) {
3495
+ mkdirSync3(VIBEOS_HOME, { recursive: true });
3496
+ return VIBEOS_HOME;
3497
+ }
3498
+ const st = statSync4(VIBEOS_HOME);
3499
+ if (!st.isDirectory()) {
3500
+ const backup = VIBEOS_HOME + ".backup." + Date.now();
3501
+ renameSync3(VIBEOS_HOME, backup);
3502
+ mkdirSync3(VIBEOS_HOME, { recursive: true });
3503
+ }
3504
+ return VIBEOS_HOME;
3505
+ } catch {
3506
+ return VIBEOS_HOME;
3507
+ }
3508
+ }
3492
3509
  function _handleStateCorruption2(path) {
3510
+ _ensureVibeOSHomeDir();
3493
3511
  const backupDir = join4(VIBEOS_HOME, ".backups");
3494
- mkdirSync3(backupDir, { recursive: true });
3512
+ try {
3513
+ mkdirSync3(backupDir, { recursive: true });
3514
+ } catch {
3515
+ }
3495
3516
  const backupPath = join4(backupDir, basename2(path) + ".corrupted." + Date.now());
3496
3517
  try {
3497
3518
  copyFileSync(path, backupPath);
@@ -3781,26 +3802,10 @@ function loadBlackboxState() {
3781
3802
  for (const [sid, session] of Object.entries(raw.sessions)) {
3782
3803
  if (!session || typeof session !== "object")
3783
3804
  continue;
3784
- const next = { ...session };
3785
- const createdAtRaw = typeof next.createdAt === "string" ? next.createdAt : "";
3786
- const updatedAtRaw = typeof next.updatedAt === "string" ? next.updatedAt : "";
3787
- const startedRaw = typeof next.started === "string" ? next.started : "";
3788
- const sessionStartedRaw = typeof next.session_started_at === "string" ? next.session_started_at : "";
3789
- const anchorRaw = [createdAtRaw, updatedAtRaw, startedRaw, sessionStartedRaw].find((v) => v && !Number.isNaN(Date.parse(v)));
3790
- const anchorMs = anchorRaw ? Date.parse(anchorRaw) : NaN;
3791
- if (!Number.isFinite(Date.parse(createdAtRaw))) {
3792
- next.createdAt = Number.isFinite(anchorMs) ? new Date(anchorMs).toISOString() : new Date(now).toISOString();
3793
- changed = true;
3794
- }
3795
- if (!Number.isFinite(Date.parse(updatedAtRaw))) {
3796
- next.updatedAt = next.createdAt || new Date(now).toISOString();
3797
- changed = true;
3798
- }
3799
- if (typeof next.sessionId !== "string" || !next.sessionId.trim()) {
3800
- next.sessionId = String(sid || "");
3801
- changed = true;
3802
- }
3805
+ const { record: next, changed: recordChanged } = normalizeBlackboxRecord(session, sid, now);
3803
3806
  raw.sessions[sid] = next;
3807
+ if (recordChanged)
3808
+ changed = true;
3804
3809
  }
3805
3810
  if (changed) {
3806
3811
  try {
@@ -3823,22 +3828,7 @@ function saveBlackboxState(state) {
3823
3828
  for (const [sid, session] of Object.entries(next.sessions)) {
3824
3829
  if (!session || typeof session !== "object")
3825
3830
  continue;
3826
- const record = session;
3827
- const createdAtRaw = typeof record.createdAt === "string" ? record.createdAt : "";
3828
- const updatedAtRaw = typeof record.updatedAt === "string" ? record.updatedAt : "";
3829
- const startedRaw = typeof record.started === "string" ? record.started : "";
3830
- const sessionStartedRaw = typeof record.session_started_at === "string" ? record.session_started_at : "";
3831
- const anchorRaw = [createdAtRaw, updatedAtRaw, startedRaw, sessionStartedRaw].find((v) => v && !Number.isNaN(Date.parse(v)));
3832
- const anchorMs = anchorRaw ? Date.parse(anchorRaw) : NaN;
3833
- if (!Number.isFinite(Date.parse(createdAtRaw))) {
3834
- record.createdAt = Number.isFinite(anchorMs) ? new Date(anchorMs).toISOString() : new Date(now).toISOString();
3835
- }
3836
- if (!Number.isFinite(Date.parse(updatedAtRaw))) {
3837
- record.updatedAt = record.createdAt || new Date(now).toISOString();
3838
- }
3839
- if (typeof record.sessionId !== "string" || !record.sessionId.trim()) {
3840
- record.sessionId = String(sid || "");
3841
- }
3831
+ next.sessions[sid] = normalizeBlackboxRecord(session, sid, now).record;
3842
3832
  }
3843
3833
  mkdirSync3(dirname4(blackboxFile), { recursive: true });
3844
3834
  const tmp = blackboxFile + ".tmp";
@@ -3848,6 +3838,81 @@ function saveBlackboxState(state) {
3848
3838
  console.error(`[vibeOS] saveBlackboxState failed: ${err.message}`);
3849
3839
  }
3850
3840
  }
3841
+ function normalizeBlackboxRecord(record, sid, now) {
3842
+ const next = { ...record || {} };
3843
+ let changed = false;
3844
+ const createdAtRaw = typeof next.createdAt === "string" ? next.createdAt : "";
3845
+ const updatedAtRaw = typeof next.updatedAt === "string" ? next.updatedAt : "";
3846
+ const startedRaw = typeof next.started === "string" ? next.started : "";
3847
+ const sessionStartedRaw = typeof next.session_started_at === "string" ? next.session_started_at : "";
3848
+ const anchorRaw = [createdAtRaw, updatedAtRaw, startedRaw, sessionStartedRaw].find((v) => v && !Number.isNaN(Date.parse(v)));
3849
+ const anchorMs = anchorRaw ? Date.parse(anchorRaw) : NaN;
3850
+ if (!Number.isFinite(Date.parse(createdAtRaw))) {
3851
+ next.createdAt = Number.isFinite(anchorMs) ? new Date(anchorMs).toISOString() : new Date(now).toISOString();
3852
+ changed = true;
3853
+ }
3854
+ if (!Number.isFinite(Date.parse(updatedAtRaw))) {
3855
+ next.updatedAt = next.createdAt || new Date(now).toISOString();
3856
+ changed = true;
3857
+ }
3858
+ if (typeof next.sessionId !== "string" || !next.sessionId.trim()) {
3859
+ next.sessionId = String(sid || "");
3860
+ changed = true;
3861
+ }
3862
+ if (typeof next.project_fingerprint !== "string" || !next.project_fingerprint.trim()) {
3863
+ if (typeof currentProjectFingerprint === "string" && currentProjectFingerprint.trim()) {
3864
+ next.project_fingerprint = currentProjectFingerprint.trim();
3865
+ changed = true;
3866
+ }
3867
+ }
3868
+ if (typeof next.project_name !== "string" || !next.project_name.trim()) {
3869
+ if (typeof currentProjectName === "string" && currentProjectName.trim()) {
3870
+ next.project_name = currentProjectName.trim();
3871
+ changed = true;
3872
+ }
3873
+ }
3874
+ if (typeof next.regime !== "string" || !next.regime.trim()) {
3875
+ next.regime = typeof next.sub_regime === "string" && next.sub_regime.trim() ? next.sub_regime.trim() : "INIT";
3876
+ changed = true;
3877
+ }
3878
+ if (typeof next.sub_regime !== "string" || !next.sub_regime.trim()) {
3879
+ next.sub_regime = "INIT";
3880
+ changed = true;
3881
+ }
3882
+ if (typeof next.resolution !== "string" || !next.resolution.trim()) {
3883
+ next.resolution = "unresolved";
3884
+ changed = true;
3885
+ }
3886
+ if (!Number.isFinite(Number(next.momentum))) {
3887
+ next.momentum = 0;
3888
+ changed = true;
3889
+ }
3890
+ if (!Number.isFinite(Number(next.turn_counter))) {
3891
+ next.turn_counter = 0;
3892
+ changed = true;
3893
+ }
3894
+ if (!Number.isFinite(Number(next.loopCount))) {
3895
+ next.loopCount = 0;
3896
+ changed = true;
3897
+ }
3898
+ if (!Number.isFinite(Number(next.loop_consecutive))) {
3899
+ next.loop_consecutive = Number(next.loopCount || 0);
3900
+ changed = true;
3901
+ }
3902
+ if (!Array.isArray(next.history)) {
3903
+ next.history = [];
3904
+ changed = true;
3905
+ }
3906
+ if (!Array.isArray(next.pivotHistory)) {
3907
+ next.pivotHistory = [];
3908
+ changed = true;
3909
+ }
3910
+ if (!Array.isArray(next.outcomeHistory)) {
3911
+ next.outcomeHistory = [];
3912
+ changed = true;
3913
+ }
3914
+ return { record: next, changed };
3915
+ }
3851
3916
  function getSessionRoot() {
3852
3917
  return join4(SCRATCHPAD_SESSIONS_DIR, _OC_SID);
3853
3918
  }
@@ -4478,8 +4543,9 @@ function touchProjectBucket(state, fp2, meta = {}) {
4478
4543
  if (!bucket.sessions.includes(meta.sessionId)) {
4479
4544
  bucket.sessions.push(meta.sessionId);
4480
4545
  bucket.sessions = bucket.sessions.slice(-30);
4546
+ bucket.totalSessions = Number(bucket.totalSessions || 0) + 1;
4481
4547
  }
4482
- bucket.totalSessions = Math.max(Number(bucket.totalSessions || 0), bucket.sessions.length);
4548
+ bucket.totalSessions = Math.max(Number(bucket.totalSessions || 0), bucket.sessions.length, 1);
4483
4549
  }
4484
4550
  if (typeof meta.reportId === "string" && meta.reportId.trim()) {
4485
4551
  bucket.reports ??= [];
@@ -7763,10 +7829,10 @@ function generateReportId(type, fp2) {
7763
7829
  return `${ts}-${(fp2 || "unknown").slice(0, 6)}-${type}-${rnd}`;
7764
7830
  }
7765
7831
  var _reportDedupWindow = /* @__PURE__ */ new Map();
7766
- function _wouldBeDuplicate(type, summary) {
7832
+ function _wouldBeDuplicate(type, summary, scope) {
7767
7833
  if (typeof summary !== "string")
7768
7834
  return false;
7769
- const key = `${getVibeOSHome7()}::${type || ""}::${summary}`;
7835
+ const key = `${getVibeOSHome7()}::${type || ""}::${String(scope || "unknown")}::${summary}`;
7770
7836
  const last = _reportDedupWindow.get(key);
7771
7837
  if (last && Date.now() - last < 5 * 60 * 1e3)
7772
7838
  return true;
@@ -7849,7 +7915,8 @@ function saveReport({ type = "manual", summary = "", findings = null, metrics =
7849
7915
  const metricsSessionId = typeof metricsObject.sessionId === "string" && metricsObject.sessionId.trim() ? metricsObject.sessionId.trim() : "";
7850
7916
  const metricsProjectName = typeof metricsObject.projectName === "string" && metricsObject.projectName.trim() ? metricsObject.projectName.trim() : "";
7851
7917
  const metricsProjectFingerprint = typeof metricsObject.projectFingerprint === "string" && metricsObject.projectFingerprint.trim() ? metricsObject.projectFingerprint.trim() : "";
7852
- if (_wouldBeDuplicate(type, summary))
7918
+ const dedupScope = fingerprint || metricsProjectFingerprint || currentProjectFingerprint || currentProjectFingerprint2 || metricsProjectName || currentProjectName || currentProjectName2 || "unknown";
7919
+ if (_wouldBeDuplicate(type, summary, dedupScope))
7853
7920
  return null;
7854
7921
  if (!currentProjectFingerprint2 && metricsProjectFingerprint)
7855
7922
  currentProjectFingerprint2 = metricsProjectFingerprint;
@@ -11738,8 +11805,9 @@ async function _appendFooter(input, output, directory3) {
11738
11805
  }
11739
11806
  }
11740
11807
  const selNowFooter = loadSelection3();
11808
+ const normalizedIntent = classifyTurnSimple2(latestUserIntent || "");
11809
+ const currentSubRegime = _latestBlackboxState?.sub_regime || normalizedIntent;
11741
11810
  const bbMode = resolveEnforcementMode();
11742
- const optModeFooter = loadOptimizationMode();
11743
11811
  const enfTags = buildEnforcementTags({
11744
11812
  delegationEnforce: selNowFooter.delegation_enforce,
11745
11813
  flowEnforce: selNowFooter.flow_enforce,
@@ -11747,11 +11815,6 @@ async function _appendFooter(input, output, directory3) {
11747
11815
  bbMode,
11748
11816
  modelLocked: _modelLocked
11749
11817
  });
11750
- const resolvedMode = peekBudgetFirstMode({
11751
- requestedMode: optModeFooter,
11752
- subRegime: _latestBlackboxState?.sub_regime || classifyTurnSimple2(latestUserIntent || ""),
11753
- stress: _footerStress
11754
- }).mode;
11755
11818
  const stripped = text.replace(/\u2014 [^\u2014]+ \u2014\s*/g, "").trimEnd();
11756
11819
  if (stripped !== text)
11757
11820
  return;
@@ -11759,11 +11822,9 @@ async function _appendFooter(input, output, directory3) {
11759
11822
  return;
11760
11823
  const ltTotal = ltTasks + ltCache;
11761
11824
  const activeSlot = selNowFooter.active_slot || "brain";
11762
- const optMode = (resolvedMode || "budget").toLowerCase();
11763
11825
  const flashIcon = isApiConnected2() ? " \u26A1" : "";
11764
- const displayMode = resolvedMode || optModeFooter || optMode || selNowFooter?.optimization_mode || "auto";
11826
+ const displayMode = autoSelectMode2(currentSubRegime, _footerStress);
11765
11827
  const vibeBrand = resolveBrand(displayMode, activeSlot);
11766
- const currentSubRegime = _latestBlackboxState?.sub_regime || classifyTurnSimple2(latestUserIntent || "");
11767
11828
  const vibeLine = buildFooterLine({
11768
11829
  activeSlot,
11769
11830
  providerLabel: execution.provider_label,
@@ -13745,6 +13806,7 @@ ${argsJson}
13745
13806
  }
13746
13807
  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.`;
13747
13808
  enforcementBlocked = true;
13809
+ _mutateBlockedToolArgs(t, argSources, originalPath, output);
13748
13810
  if (shouldLogWarn(`${t}|enforced|${_tierWord}`))
13749
13811
  console.error(`[vibeOS] [enforcement] BLOCKED direct ${t} on high tier \u2192 delegate via Task`);
13750
13812
  return;
@@ -13841,14 +13903,6 @@ var onToolExecuteAfter = async (input, output) => {
13841
13903
  const { ltTasks, ltCache, ltCost, sesTrend } = readLifetimeSavings();
13842
13904
  const ltTotal = ltTasks + ltCache;
13843
13905
  const selNow = loadSelection();
13844
- const bbMode = resolveEnforcementMode();
13845
- const enfTags = buildEnforcementTags({
13846
- delegationEnforce: selNow.delegation_enforce,
13847
- flowEnforce: selNow.flow_enforce,
13848
- tddEnforce: selNow.tdd_enforce,
13849
- bbMode,
13850
- modelLocked: _modelLocked
13851
- });
13852
13906
  let liveModel = "";
13853
13907
  try {
13854
13908
  const cfg = await client.config.get("model");
@@ -13867,12 +13921,19 @@ var onToolExecuteAfter = async (input, output) => {
13867
13921
  }
13868
13922
  const execution = resolveExecutionIdentity(input?.args?.model || resolvedModel || "", projectDirectory);
13869
13923
  const currentSid = _OC_SID;
13870
- const optModeFooter = loadSessionOptMode(currentSid + "_opt") || loadOptimizationMode() || "budget";
13924
+ const currentSubRegime = loadBlackboxState()?.sessions?.[currentSid]?.sub_regime || classifyTurnSimple2(latestUserIntent || "");
13925
+ const bbMode = resolveEnforcementMode();
13926
+ const enfTags = buildEnforcementTags({
13927
+ delegationEnforce: selNow.delegation_enforce,
13928
+ flowEnforce: selNow.flow_enforce,
13929
+ tddEnforce: selNow.tdd_enforce,
13930
+ bbMode,
13931
+ modelLocked: _modelLocked
13932
+ });
13871
13933
  const activeSlot = selNow.active_slot || (execution.quality === "brain" ? "brain" : execution.quality === "medium" ? "medium" : "cheap");
13872
- const vibeBrand = resolveBrand(optModeFooter, activeSlot);
13934
+ const displayMode = autoSelectMode2(currentSubRegime, latestUserIntent ? scoreStress(latestUserIntent) : 0);
13935
+ const vibeBrand = resolveBrand(displayMode, activeSlot);
13873
13936
  const sessionSlot = loadSessionSlot(currentSid);
13874
- const displayMode = selNow.optimization_mode || optModeFooter || "auto";
13875
- const currentSubRegime = loadBlackboxState()?.sessions?.[currentSid]?.sub_regime || classifyTurnSimple2(latestUserIntent || "");
13876
13937
  const flashIcon = isApiConnected2() ? " \u26A1" : "";
13877
13938
  _footerText = buildFooterLine({
13878
13939
  activeSlot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.24.25",
3
+ "version": "0.24.27",
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",