vibeostheog 0.25.20 → 0.25.21

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,7 @@
1
+ ## 0.25.21
2
+ - fix: stabilize OpenCode install resolution
3
+
4
+
1
5
  ## 0.25.19
2
6
  - fix: harden loop detection and behavioral stress
3
7
 
package/bin/setup.js CHANGED
@@ -4,18 +4,7 @@ import { execSync } from "node:child_process";
4
4
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
5
5
  import { dirname, resolve } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
- import { homedir } from "node:os";
8
-
9
- function resolveOpenCodeHomes() {
10
- const override = process.env.VIBEOS_OPENCODE_HOME;
11
- if (override) return [override];
12
- const base = homedir();
13
- const desktopHome = process.env.VIBEOS_OPENCODE_DESKTOP_HOME
14
- || (process.platform === "darwin" ? resolve(base, "Library", "Application Support", "ai.opencode.desktop") : null);
15
- const configHome = resolve(base, ".config", "opencode");
16
- const dotHome = resolve(base, ".opencode");
17
- return [desktopHome, configHome, dotHome].filter(Boolean);
18
- }
7
+ import { resolveOpenCodeHome } from "../scripts/lib/opencode-homes.mjs";
19
8
 
20
9
  const __dirname = dirname(fileURLToPath(import.meta.url));
21
10
  const root = resolve(__dirname, "..");
@@ -35,7 +24,7 @@ if (!existsSync(deployScript)) {
35
24
  console.error("Fatal: scripts/deploy.mjs not found at", deployScript);
36
25
  process.exit(1);
37
26
  }
38
- execSync(`node "${deployScript}"`, { stdio: "inherit", cwd: root });
27
+ execSync(`node "${deployScript}"`, { stdio: "inherit", cwd: process.cwd() });
39
28
 
40
29
  // For per-project setup, also register in project-level opencode.json
41
30
  if (isProject) {
@@ -51,8 +40,9 @@ if (isProject) {
51
40
  if (!config || typeof config !== "object" || Array.isArray(config)) config = {};
52
41
  if (!config.$schema) config.$schema = "https://opencode.ai/config.json";
53
42
  if (!Array.isArray(config.plugin)) config.plugin = [];
54
- const [installHome] = resolveOpenCodeHomes();
55
- const pluginRef = resolve(installHome || resolve(homedir(), ".config", "opencode"), "plugins", "vibeOS.js");
43
+ const installHome = resolveOpenCodeHome({ cwd: process.cwd() });
44
+ const pluginRef = resolve(installHome, "plugins", "vibeOS.js");
45
+ config.plugin = config.plugin.filter((p) => !(typeof p === "string" && p.includes("vibeOS")));
56
46
  if (!config.plugin.includes(pluginRef)) {
57
47
  config.plugin.push(pluginRef);
58
48
  mkdirSync(dirname(configPath), { recursive: true });
@@ -1 +1 @@
1
- window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:62952";
1
+ window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:49879";
package/dist/vibeOS.js CHANGED
@@ -978,22 +978,30 @@ function getVibeOSHome2() {
978
978
  function hasOpenCodeConfig(dir) {
979
979
  return existsSync2(join2(dir, "opencode.json")) || existsSync2(join2(dir, "opencode.jsonc"));
980
980
  }
981
- function getOpenCodeHome() {
981
+ function resolveOpenCodeHomes() {
982
982
  const override = process.env.VIBEOS_OPENCODE_HOME;
983
983
  if (override)
984
- return override;
984
+ return [override];
985
985
  const base = process.env.HOME || USER_HOME2;
986
+ const desktopHome = process.env.VIBEOS_OPENCODE_DESKTOP_HOME || (process.platform === "darwin" ? join2(base, "Library", "Application Support", "ai.opencode.desktop") : null);
986
987
  const configHome = join2(base, ".config", "opencode");
987
988
  const dotHome = join2(base, ".opencode");
988
- if (hasOpenCodeConfig(configHome))
989
- return configHome;
990
- if (hasOpenCodeConfig(dotHome))
991
- return dotHome;
992
- if (existsSync2(configHome))
993
- return configHome;
994
- if (existsSync2(dotHome))
995
- return dotHome;
996
- return configHome;
989
+ return [desktopHome, configHome, dotHome].filter(Boolean);
990
+ }
991
+ function resolveOpenCodeHome() {
992
+ const homes = resolveOpenCodeHomes();
993
+ for (const home of homes) {
994
+ if (hasOpenCodeConfig(home))
995
+ return home;
996
+ }
997
+ for (const home of homes) {
998
+ if (existsSync2(home))
999
+ return home;
1000
+ }
1001
+ return homes[0] || join2(process.env.HOME || USER_HOME2, ".config", "opencode");
1002
+ }
1003
+ function getOpenCodeHome() {
1004
+ return resolveOpenCodeHome();
997
1005
  }
998
1006
  function setVibeOSHomeContext(home) {
999
1007
  VIBEOS_CONTEXT.enterWith({ home: String(home || "") });
@@ -2690,7 +2698,7 @@ var init_state = __esm({
2690
2698
  })();
2691
2699
  VIBEOS_CONTEXT = new AsyncLocalStorage();
2692
2700
  VIBEOS_HOME = process.env.VIBEOS_HOME || join2(USER_HOME2, ".claude");
2693
- OPENCODE_HOME = process.env.VIBEOS_OPENCODE_HOME || join2(USER_HOME2, ".config", "opencode");
2701
+ OPENCODE_HOME = resolveOpenCodeHome();
2694
2702
  FILE_LOCK_DIR = join2(VIBEOS_HOME, ".vibeOS-locks");
2695
2703
  DELEGATION_STATE_FILE = join2(VIBEOS_HOME, "delegation-state.json");
2696
2704
  SAVINGS_LEDGER_FILE = join2(VIBEOS_HOME, "savings-ledger.jsonl");
@@ -2858,6 +2866,9 @@ function safeJsonParse3(raw) {
2858
2866
  return null;
2859
2867
  }
2860
2868
  }
2869
+ function getRealityCheckSettingsFile() {
2870
+ return join3(getVibeOSHome3(), "reality-check-settings.json");
2871
+ }
2861
2872
  function resolveRulesPath() {
2862
2873
  if (process.env.VIBEOS_FLOW_RULES_PATH && existsSync3(process.env.VIBEOS_FLOW_RULES_PATH)) {
2863
2874
  return process.env.VIBEOS_FLOW_RULES_PATH;
@@ -2995,14 +3006,15 @@ function defaultRealityCheckRules() {
2995
3006
  ];
2996
3007
  }
2997
3008
  function readRealityCheckSettings() {
2998
- const settingsMtime = existsSync3(REALITY_CHECK_SETTINGS_FILE) ? statSync3(REALITY_CHECK_SETTINGS_FILE).mtimeMs : 0;
3009
+ const settingsFile = getRealityCheckSettingsFile();
3010
+ const settingsMtime = existsSync3(settingsFile) ? statSync3(settingsFile).mtimeMs : 0;
2999
3011
  if (_cachedRealityCheck && settingsMtime === _realityCheckMtime) {
3000
3012
  return _cachedRealityCheck;
3001
3013
  }
3002
3014
  let parsed = {};
3003
3015
  try {
3004
- if (existsSync3(REALITY_CHECK_SETTINGS_FILE)) {
3005
- const raw = readFileSync3(REALITY_CHECK_SETTINGS_FILE, "utf-8");
3016
+ if (existsSync3(settingsFile)) {
3017
+ const raw = readFileSync3(settingsFile, "utf-8");
3006
3018
  const json2 = safeJsonParse3(raw);
3007
3019
  if (json2 && typeof json2 === "object")
3008
3020
  parsed = json2;
@@ -3085,7 +3097,8 @@ function loadRules() {
3085
3097
  const rulesPath = resolveRulesPath();
3086
3098
  try {
3087
3099
  const rulesMtime = existsSync3(rulesPath) ? statSync3(rulesPath).mtimeMs : 0;
3088
- const realityMtime = existsSync3(REALITY_CHECK_SETTINGS_FILE) ? statSync3(REALITY_CHECK_SETTINGS_FILE).mtimeMs : 0;
3100
+ const realityFile = getRealityCheckSettingsFile();
3101
+ const realityMtime = existsSync3(realityFile) ? statSync3(realityFile).mtimeMs : 0;
3089
3102
  const scopeKey = String(currentProjectFingerprint || "");
3090
3103
  const cacheKey = `${rulesMtime}:${realityMtime}:${scopeKey}`;
3091
3104
  if (_cachedRules && _realityCheckCacheKey === "__test__")
@@ -3311,7 +3324,7 @@ function syncFlowTodosToNative(upsertFn) {
3311
3324
  }
3312
3325
  return count;
3313
3326
  }
3314
- var VIBEOS_STDERR_DEBUG, VIBEOS_CONSOLE_ERROR_GUARD, globalConsoleState, __dirname2, REALITY_CHECK_SETTINGS_FILE, REALITY_CHECK_RULE_IDS, RULES_PATH_CANDIDATES, GUARD_AGENTS_TEMPLATE, GUARD_README_TEMPLATE, FLOW_DEDUP_FILE2, MAX_FLOW_TODOS, _flowWarnsSeen, _stateWriter, _cachedRules, _rulesMtime, _cachedRealityCheck, _realityCheckMtime, _realityCheckCacheKey;
3327
+ var VIBEOS_STDERR_DEBUG, VIBEOS_CONSOLE_ERROR_GUARD, globalConsoleState, __dirname2, REALITY_CHECK_RULE_IDS, RULES_PATH_CANDIDATES, GUARD_AGENTS_TEMPLATE, GUARD_README_TEMPLATE, FLOW_DEDUP_FILE2, MAX_FLOW_TODOS, _flowWarnsSeen, _stateWriter, _cachedRules, _rulesMtime, _cachedRealityCheck, _realityCheckMtime, _realityCheckCacheKey;
3315
3328
  var init_flow_enforcer = __esm({
3316
3329
  "src/vibeOS-lib/flow-enforcer.js"() {
3317
3330
  "use strict";
@@ -3346,7 +3359,6 @@ var init_flow_enforcer = __esm({
3346
3359
  globalConsoleState[VIBEOS_CONSOLE_ERROR_GUARD] = true;
3347
3360
  }
3348
3361
  __dirname2 = dirname2(fileURLToPath(import.meta.url));
3349
- REALITY_CHECK_SETTINGS_FILE = join3(getVibeOSHome3(), "reality-check-settings.json");
3350
3362
  REALITY_CHECK_RULE_IDS = /* @__PURE__ */ new Set([
3351
3363
  "require-read-before-claim",
3352
3364
  "verify-state-on-disk",
@@ -7158,7 +7170,8 @@ var ResolutionTracker = class _ResolutionTracker {
7158
7170
  return 1 - cosineSimilarity2(a, b);
7159
7171
  }
7160
7172
  detectLoop() {
7161
- return this.loopCount >= 2 || this.getRepeatStreak() >= 2 || this.getActivityRepeatStreak() >= 2 || this.getTargetRepeatStreak() >= 2;
7173
+ const repeatSignal = Math.max(this.getRepeatStreak(), this.getActivityRepeatStreak(), this.getTargetRepeatStreak());
7174
+ return this.loopCount >= 2 || repeatSignal >= 2;
7162
7175
  }
7163
7176
  computeIntentState() {
7164
7177
  const last = this.history[this.history.length - 1];
@@ -7418,8 +7431,16 @@ function detectOutcomeSignal(text) {
7418
7431
  return "negative";
7419
7432
  return null;
7420
7433
  }
7421
- function countTrailingRepeat(items, signatureOf) {
7422
- if (!Array.isArray(items) || items.length === 0)
7434
+ function normalizeActivitySignature(event) {
7435
+ if (!event || typeof event !== "object")
7436
+ return "";
7437
+ const tool2 = String(event.tool || "").trim().toLowerCase();
7438
+ const target = String(event.target || "").trim().toLowerCase();
7439
+ const action = String(event.action || event.kind || "").trim().toLowerCase();
7440
+ return [tool2, target, action].filter(Boolean).join(":");
7441
+ }
7442
+ function countBehavioralRepeat(items, signatureOf, minLength = 2) {
7443
+ if (!Array.isArray(items) || items.length < minLength)
7423
7444
  return 0;
7424
7445
  const last = signatureOf(items[items.length - 1]);
7425
7446
  if (!last)
@@ -7432,13 +7453,26 @@ function countTrailingRepeat(items, signatureOf) {
7432
7453
  }
7433
7454
  return streak;
7434
7455
  }
7435
- function normalizeActivitySignature(event) {
7436
- if (!event || typeof event !== "object")
7437
- return "";
7438
- const tool2 = String(event.tool || "").trim().toLowerCase();
7439
- const target = String(event.target || "").trim().toLowerCase();
7440
- const action = String(event.action || event.kind || "").trim().toLowerCase();
7441
- return [tool2, target, action].filter(Boolean).join(":");
7456
+ function getBehavioralStressSignals(context, blackboxState) {
7457
+ const recentEvents = Array.isArray(context?.recentToolEvents) ? context.recentToolEvents : Array.isArray(recentToolEvents) ? recentToolEvents : [];
7458
+ const recentWindow = recentEvents.slice(-8);
7459
+ const toolRepeatStreak = countBehavioralRepeat(recentWindow, normalizeActivitySignature);
7460
+ const targetRepeatStreak = countBehavioralRepeat(recentWindow, (event) => String(event?.target || "").trim().toLowerCase());
7461
+ const outcomeHistory = Array.isArray(context?.outcomeHistory) ? context.outcomeHistory : Array.isArray(blackboxState?.outcomeHistory) ? blackboxState.outcomeHistory : [];
7462
+ const negativeOutcomes = outcomeHistory.slice(-5).filter((o) => /negative|failed|unresolved|loop_detected/i.test(String(o?.outcome || ""))).length;
7463
+ const loopCount = Number(blackboxState?.loop_count ?? blackboxState?.loopConsecutive ?? blackboxState?.loop_consecutive ?? 0);
7464
+ const repeatStreak = Number(blackboxState?.repeat_streak ?? 0);
7465
+ const activityRepeatStreak = Number(blackboxState?.activity_repeat_streak ?? 0);
7466
+ const targetRepeatStateStreak = Number(blackboxState?.target_repeat_streak ?? 0);
7467
+ return {
7468
+ toolRepeatStreak,
7469
+ targetRepeatStreak,
7470
+ negativeOutcomes,
7471
+ loopCount,
7472
+ repeatStreak,
7473
+ activityRepeatStreak,
7474
+ targetRepeatStateStreak
7475
+ };
7442
7476
  }
7443
7477
  function scoreStress(text, context = {}) {
7444
7478
  if (!text || typeof text !== "string")
@@ -7497,29 +7531,27 @@ function scoreStress(text, context = {}) {
7497
7531
  } catch {
7498
7532
  }
7499
7533
  }
7500
- const recentEvents = Array.isArray(context?.recentToolEvents) ? context.recentToolEvents : Array.isArray(recentToolEvents) ? recentToolEvents : [];
7501
- const recentWindow = recentEvents.slice(-8);
7502
- const toolRepeatStreak = countTrailingRepeat(recentWindow, normalizeActivitySignature);
7534
+ const { toolRepeatStreak, targetRepeatStreak, negativeOutcomes, loopCount, repeatStreak, activityRepeatStreak, targetRepeatStateStreak } = getBehavioralStressSignals(context, blackboxState);
7503
7535
  if (toolRepeatStreak >= 2) {
7504
- score += 0.05 + Math.min(0.2, (toolRepeatStreak - 1) * 0.04);
7536
+ score += 0.08 + Math.min(0.24, (toolRepeatStreak - 1) * 0.05);
7505
7537
  }
7506
- const repeatedTargets = countTrailingRepeat(recentWindow, (event) => String(event?.target || "").trim().toLowerCase());
7507
- if (repeatedTargets >= 2) {
7508
- score += 0.04 + Math.min(0.12, (repeatedTargets - 1) * 0.03);
7538
+ if (targetRepeatStreak >= 2) {
7539
+ score += 0.05 + Math.min(0.16, (targetRepeatStreak - 1) * 0.035);
7509
7540
  }
7510
- const outcomeHistory = Array.isArray(context?.outcomeHistory) ? context.outcomeHistory : Array.isArray(blackboxState?.outcomeHistory) ? blackboxState.outcomeHistory : [];
7511
- const recentOutcomes = outcomeHistory.slice(-5);
7512
- const negativeOutcomes = recentOutcomes.filter((o) => /negative|failed|unresolved|loop_detected/i.test(String(o?.outcome || ""))).length;
7513
7541
  if (negativeOutcomes >= 1) {
7514
- score += 0.03 * negativeOutcomes + Math.min(0.12, negativeOutcomes * 0.02);
7542
+ score += 0.05 * negativeOutcomes + Math.min(0.18, negativeOutcomes * 0.03);
7515
7543
  }
7516
- const loopCount = Number(blackboxState?.loop_count ?? blackboxState?.loopConsecutive ?? blackboxState?.loop_consecutive ?? 0);
7517
7544
  if (blackboxState?.is_looping || loopCount >= 2) {
7518
- score += 0.08 + Math.min(0.15, loopCount * 0.02);
7545
+ score += 0.1 + Math.min(0.18, loopCount * 0.03);
7519
7546
  }
7520
- const repeatStreak = Number(blackboxState?.repeat_streak ?? 0);
7521
7547
  if (repeatStreak >= 2) {
7522
- score += 0.05 + Math.min(0.08, repeatStreak * 0.02);
7548
+ score += 0.06 + Math.min(0.12, repeatStreak * 0.025);
7549
+ }
7550
+ if (activityRepeatStreak >= 2) {
7551
+ score += 0.05 + Math.min(0.1, activityRepeatStreak * 0.02);
7552
+ }
7553
+ if (targetRepeatStateStreak >= 2) {
7554
+ score += 0.04 + Math.min(0.08, targetRepeatStateStreak * 0.015);
7523
7555
  }
7524
7556
  if (text.length < 30)
7525
7557
  score += 0.06;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.25.20",
3
+ "version": "0.25.21",
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",
@@ -4,6 +4,7 @@ import { cpSync, readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync
4
4
  import { join, dirname } from "node:path"
5
5
  import { fileURLToPath } from "node:url"
6
6
  import { homedir } from "node:os"
7
+ import { resolveOpenCodeHomes } from "./lib/opencode-homes.mjs"
7
8
 
8
9
  const __dirname = dirname(fileURLToPath(import.meta.url))
9
10
  const ROOT = join(__dirname, "..")
@@ -11,17 +12,6 @@ const ROOT = join(__dirname, "..")
11
12
  const bundlePath = join(ROOT, "dist", "vibeOS.js")
12
13
  const assetsPath = join(ROOT, "dist", "assets")
13
14
 
14
- function resolveOpenCodeHomes() {
15
- const override = process.env.VIBEOS_OPENCODE_HOME
16
- if (override) return [override]
17
- const base = homedir()
18
- const desktopHome = process.env.VIBEOS_OPENCODE_DESKTOP_HOME
19
- || (process.platform === "darwin" ? join(base, "Library", "Application Support", "ai.opencode.desktop") : null)
20
- const configHome = join(base, ".config", "opencode")
21
- const dotHome = join(base, ".opencode")
22
- return [desktopHome, configHome, dotHome].filter(Boolean)
23
- }
24
-
25
15
  if (!existsSync(bundlePath)) {
26
16
  process.stderr.write("[vibeOS deploy] ERROR: dist/vibeOS.js not found\n")
27
17
  process.exit(1)