vibeostheog 0.25.48 → 0.25.49

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,10 @@
1
+ ## 0.25.49
2
+ - fix: keep scratchpad cache session-only (#271)
3
+ - test: cover empty reward input (#269)
4
+ Merge remote-tracking branch 'origin/release/v0.25.48'
5
+ Stabilize claim status footer (#270)
6
+
7
+
1
8
  ## 0.25.48
2
9
  - feat: reward engine — quality credits, saving bonus, lie/laziness penalties (#266)
3
10
  - fix: forward claim evidence into reward scoring (#268)
@@ -1 +1 @@
1
- window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:43861";
1
+ window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:41975";
package/dist/vibeOS.js CHANGED
@@ -1538,6 +1538,21 @@ function ensureSessionScratchpadDirs() {
1538
1538
  return false;
1539
1539
  }
1540
1540
  }
1541
+ function safeCopyIntoSession(hash, fromPath, targetScratchpadDir = getSessionScratchpadDir()) {
1542
+ try {
1543
+ mkdirSync(targetScratchpadDir, { recursive: true });
1544
+ const sessionPath = join2(targetScratchpadDir, `${hash}.txt`);
1545
+ if (!existsSync2(sessionPath)) {
1546
+ copyFileSync(fromPath, sessionPath);
1547
+ const globalSummary = join2(SCRATCHPAD_GLOBAL_DIR, `${hash}.summary.txt`);
1548
+ const sessionSummary = join2(targetScratchpadDir, `${hash}.summary.txt`);
1549
+ if (existsSync2(globalSummary) && !existsSync2(sessionSummary)) {
1550
+ copyFileSync(globalSummary, sessionSummary);
1551
+ }
1552
+ }
1553
+ } catch {
1554
+ }
1555
+ }
1541
1556
  function cleanupCurrentSessionScratchpad() {
1542
1557
  if (_sessionCacheCleaned)
1543
1558
  return;
@@ -1732,52 +1747,6 @@ function indexAppend(hash, tool2, size, extra) {
1732
1747
  console.error(`[vibeOS] index write failed: ${err.message}`);
1733
1748
  }
1734
1749
  }
1735
- function scanRecentScratchpad(dir, titleCase, maxScan = 2e3) {
1736
- try {
1737
- if (!existsSync2(dir))
1738
- return null;
1739
- const entries = readdirSync(dir);
1740
- const ptrFiles = entries.filter((e) => e.endsWith(".ptr"));
1741
- const ptrCandidates = [];
1742
- for (const pf of ptrFiles) {
1743
- if (ptrCandidates.length >= MAX_PTR_CANDIDATES)
1744
- break;
1745
- try {
1746
- const st = statSync2(join2(dir, pf));
1747
- ptrCandidates.push({ ptrPath: join2(dir, pf), mtimeMs: st.mtimeMs });
1748
- } catch {
1749
- }
1750
- }
1751
- ptrCandidates.sort((a, b) => b.mtimeMs - a.mtimeMs);
1752
- let scanned = 0;
1753
- for (const { ptrPath } of ptrCandidates) {
1754
- if (scanned++ >= maxScan)
1755
- break;
1756
- try {
1757
- const ptrData = safeJsonParse2(readFileSync2(ptrPath, "utf-8"));
1758
- if (!ptrData?.contentHash)
1759
- continue;
1760
- const ptrTool = typeof ptrData.tool === "string" ? TOOL_NAME_NORMALIZE[ptrData.tool] || ptrData.tool : null;
1761
- if (titleCase && ptrTool && ptrTool !== titleCase)
1762
- continue;
1763
- const contentHash = String(ptrData.contentHash);
1764
- const f = join2(dir, `${contentHash}.txt`);
1765
- if (!existsSync2(f))
1766
- continue;
1767
- const st = statSync2(f);
1768
- const ageSec = (Date.now() - st.mtimeMs) / 1e3;
1769
- if (ageSec > SCRATCHPAD_MAX_AGE_SEC)
1770
- continue;
1771
- const sumPath = join2(dir, `${contentHash}.summary.txt`);
1772
- return { hash: contentHash, fullPath: f, sizeBytes: st.size, ageSec: Math.round(ageSec), summaryPath: existsSync2(sumPath) ? sumPath : null };
1773
- } catch {
1774
- }
1775
- }
1776
- return null;
1777
- } catch {
1778
- return null;
1779
- }
1780
- }
1781
1750
  function getScratchpadHit(toolLower, args, baseDir = null) {
1782
1751
  if (!SCRATCHPAD_TOOLS.has(toolLower))
1783
1752
  return null;
@@ -1804,12 +1773,8 @@ ${inputJson}
1804
1773
  } catch {
1805
1774
  }
1806
1775
  }
1807
- if (!fullPath) {
1808
- const recent = scanRecentScratchpad(sessionDir, titleCase, 2e3);
1809
- if (recent)
1810
- return recent;
1776
+ if (!fullPath)
1811
1777
  return null;
1812
- }
1813
1778
  }
1814
1779
  try {
1815
1780
  const st = statSync2(fullPath);
@@ -2683,7 +2648,7 @@ function saveSessionCheckpoint() {
2683
2648
  } catch {
2684
2649
  }
2685
2650
  }
2686
- var USER_HOME2, VIBEOS_CONTEXT, VIBEOS_HOME, OPENCODE_HOME, FILE_LOCK_DIR, DELEGATION_STATE_FILE, SAVINGS_LEDGER_FILE, GLOBAL_LEARNING_FILE, PRICING_CACHE_FILE, BLACKBOX_STATE_FILE, PROJECT_STATE_FILE, TIERS_FILE, ACTIVE_JOBS_FILE, AUTH_F, CREDIT_CACHE_F, FLOW_TODO_QUEUE_FILE, FLOW_DEDUP_FILE, ENFORCEMENT_COOLDOWN_FILE, TODOS_FILE, REPORTS_DIR, CONTEXT7_INSTALL_FLAG, TRINITY_OPENCODE_CONFIG, TRINITY_OPENCODE_CONFIGC, SCRATCHPAD_ROOT, SCRATCHPAD_GLOBAL_DIR, SCRATCHPAD_SESSIONS_DIR, SCRATCHPAD_SESSION_TTL_MS, SCRATCHPAD_MAX_AGE_SEC, MAX_SCRATCHPAD_FILES, MAX_SCRATCHPAD_BYTES, MAX_SESSION_SCRATCHPAD_FILES, MAX_SESSION_SCRATCHPAD_BYTES, CORRUPTION_BACKUP_MAX, CORRUPTION_BACKUP_TTL_MS, LEDGER_ROTATE_MAX_BYTES, LEDGER_ROTATE_MAX_LINES, LEDGER_ROTATE_MAX_AGE_MS, ACTIVE_JOBS_STALE_MS, MAX_PTR_CANDIDATES, SUMMARY_HEAD_TRUNCATE, DECADENCE_FRESH_MS, DECADENCE_WARM_MS, DECADENCE_COLD_MS, DECADENCE_EXPIRE_MS, DECADENCE_THROTTLE_MS, DECADENCE_GLOBAL_THROTTLE_MS, TOOL_NAME_NORMALIZE, SCRATCHPAD_TOOLS, WARN_DEDUPE_WINDOW_MS, SOFT_QUOTA_LIMIT, _OC_SID, currentSessionId, _sessionStart, currentTier, currentModel, currentProjectFingerprint, currentProjectName, recentToolEvents, frictionSessionKeys, _savingsCache, _savingsCacheMtime, _ledgerReconciledMtime, _ledgerTotalsCache, _mlGraph, _cacheDb, ML_ENABLED, ML_CONFIDENCE_THRESHOLD, _mlSavePending, _blackboxEnabled, _latestBlackboxState, _latestBlackboxLoopMsg, _latestBlackboxPivotMsg, _modelLocked, _lockedSlot, _lockedModel, _sessionCleanupRegistered, _sessionCacheCleaned, prunedThisProcess, _lastDecadenceRun, briefedProjects, _ledgerBuffer, _ledgerBufferTimer, LEDGER_BUFFER_MAX, LEDGER_BUFFER_FLUSH_MS, testReminderSeen, DFLT_GL, tool, _startupMaintenanceHome, FALLBACK_HIGH, FALLBACK_MID, HIGH_TIER_RE, MID_TIER_RE, scratchpadHitsSeen;
2651
+ var USER_HOME2, VIBEOS_CONTEXT, VIBEOS_HOME, OPENCODE_HOME, FILE_LOCK_DIR, DELEGATION_STATE_FILE, SAVINGS_LEDGER_FILE, GLOBAL_LEARNING_FILE, PRICING_CACHE_FILE, BLACKBOX_STATE_FILE, PROJECT_STATE_FILE, TIERS_FILE, ACTIVE_JOBS_FILE, AUTH_F, CREDIT_CACHE_F, FLOW_TODO_QUEUE_FILE, FLOW_DEDUP_FILE, ENFORCEMENT_COOLDOWN_FILE, TODOS_FILE, REPORTS_DIR, CONTEXT7_INSTALL_FLAG, TRINITY_OPENCODE_CONFIG, TRINITY_OPENCODE_CONFIGC, SCRATCHPAD_ROOT, SCRATCHPAD_GLOBAL_DIR, SCRATCHPAD_SESSIONS_DIR, SCRATCHPAD_SESSION_TTL_MS, SCRATCHPAD_MAX_AGE_SEC, MAX_SCRATCHPAD_FILES, MAX_SCRATCHPAD_BYTES, MAX_SESSION_SCRATCHPAD_FILES, MAX_SESSION_SCRATCHPAD_BYTES, CORRUPTION_BACKUP_MAX, CORRUPTION_BACKUP_TTL_MS, LEDGER_ROTATE_MAX_BYTES, LEDGER_ROTATE_MAX_LINES, LEDGER_ROTATE_MAX_AGE_MS, ACTIVE_JOBS_STALE_MS, SUMMARY_HEAD_TRUNCATE, DECADENCE_FRESH_MS, DECADENCE_WARM_MS, DECADENCE_COLD_MS, DECADENCE_EXPIRE_MS, DECADENCE_THROTTLE_MS, DECADENCE_GLOBAL_THROTTLE_MS, TOOL_NAME_NORMALIZE, SCRATCHPAD_TOOLS, WARN_DEDUPE_WINDOW_MS, SOFT_QUOTA_LIMIT, _OC_SID, currentSessionId, _sessionStart, currentTier, currentModel, currentProjectFingerprint, currentProjectName, recentToolEvents, frictionSessionKeys, _savingsCache, _savingsCacheMtime, _ledgerReconciledMtime, _ledgerTotalsCache, _mlGraph, _cacheDb, ML_ENABLED, ML_CONFIDENCE_THRESHOLD, _mlSavePending, _blackboxEnabled, _latestBlackboxState, _latestBlackboxLoopMsg, _latestBlackboxPivotMsg, _modelLocked, _lockedSlot, _lockedModel, _sessionCleanupRegistered, _sessionCacheCleaned, prunedThisProcess, _lastDecadenceRun, briefedProjects, _ledgerBuffer, _ledgerBufferTimer, LEDGER_BUFFER_MAX, LEDGER_BUFFER_FLUSH_MS, testReminderSeen, DFLT_GL, tool, _startupMaintenanceHome, FALLBACK_HIGH, FALLBACK_MID, HIGH_TIER_RE, MID_TIER_RE, scratchpadHitsSeen;
2687
2652
  var init_state = __esm({
2688
2653
  "src/lib/state.js"() {
2689
2654
  "use strict";
@@ -2736,7 +2701,6 @@ var init_state = __esm({
2736
2701
  LEDGER_ROTATE_MAX_LINES = 1e4;
2737
2702
  LEDGER_ROTATE_MAX_AGE_MS = 48 * 60 * 60 * 1e3;
2738
2703
  ACTIVE_JOBS_STALE_MS = 72 * 60 * 60 * 1e3;
2739
- MAX_PTR_CANDIDATES = 50;
2740
2704
  SUMMARY_HEAD_TRUNCATE = 500;
2741
2705
  DECADENCE_FRESH_MS = 5 * 60 * 1e3;
2742
2706
  DECADENCE_WARM_MS = 60 * 60 * 1e3;
@@ -5126,8 +5090,8 @@ var init_vibeultrax = __esm({
5126
5090
 
5127
5091
  // src/index.ts
5128
5092
  init_flow_enforcer();
5129
- import { readFileSync as readFileSync18, writeFileSync as writeFileSync18, existsSync as existsSync20, mkdirSync as mkdirSync15, copyFileSync as copyFileSync2, renameSync as renameSync6, statSync as statSync10 } from "node:fs";
5130
- import { join as join19, dirname as dirname13, basename as basename5 } from "node:path";
5093
+ import { readFileSync as readFileSync19, writeFileSync as writeFileSync18, existsSync as existsSync20, mkdirSync as mkdirSync15, copyFileSync as copyFileSync2, renameSync as renameSync6, statSync as statSync9 } from "node:fs";
5094
+ import { join as join20, dirname as dirname13, basename as basename5 } from "node:path";
5131
5095
 
5132
5096
  // src/vibeOS-lib/session-metrics.js
5133
5097
  function formatDuration(totalSeconds) {
@@ -11248,16 +11212,76 @@ async function probeModel(modelId, auth, providers = null) {
11248
11212
  }
11249
11213
 
11250
11214
  // src/lib/hooks/footer.js
11251
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync15, appendFileSync as appendFileSync5, existsSync as existsSync16, mkdirSync as mkdirSync12, statSync as statSync8 } from "node:fs";
11252
- import { join as join16 } from "node:path";
11215
+ import { readFileSync as readFileSync16, writeFileSync as writeFileSync15, appendFileSync as appendFileSync5, mkdirSync as mkdirSync12 } from "node:fs";
11216
+ import { join as join17 } from "node:path";
11253
11217
 
11254
11218
  // src/lib/hooks/chat-transform.js
11255
11219
  init_state();
11256
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync14, appendFileSync as appendFileSync4, existsSync as existsSync15, mkdirSync as mkdirSync11, rmSync as rmSync5, readdirSync as readdirSync3, statSync as statSync7 } from "node:fs";
11257
- import { join as join15, dirname as dirname10, basename as basename3 } from "node:path";
11220
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync14, appendFileSync as appendFileSync4, existsSync as existsSync16, mkdirSync as mkdirSync11, rmSync as rmSync5, readdirSync as readdirSync3, statSync as statSync7 } from "node:fs";
11221
+ import { join as join16, dirname as dirname10, basename as basename3 } from "node:path";
11258
11222
  import { createHash as createHash3 } from "node:crypto";
11259
11223
  import { homedir as homedir6 } from "node:os";
11260
11224
 
11225
+ // src/lib/claim-verification.js
11226
+ import { existsSync as existsSync14, readFileSync as readFileSync13 } from "node:fs";
11227
+ import { join as join13 } from "node:path";
11228
+ var CLAIM_PATTERNS = [
11229
+ /(?:I|we|the)\s+(?:pushed|released|merged|deployed|fixed|wrote|implemented|completed|committed)\b/i,
11230
+ /(?:tests?|build|CI|checks?|suite|output|result)\s+(?:is\s+|are\s+)?(?:pass(?:ing|ed|es)?|green|clean|succeed|stable|positive)/i,
11231
+ /v\d+\.\d+\.\d+/,
11232
+ /\d+\s*(?:test|spec)s?\s*(?:pass|passing)/i,
11233
+ /(?:exit\s*code\s*0|0\s*errors|0\s*failures)/i
11234
+ ];
11235
+ function extractClaimMatches(text) {
11236
+ if (!text || typeof text !== "string")
11237
+ return [];
11238
+ const claims = [];
11239
+ const lines = String(text).split("\n");
11240
+ for (let i = 0; i < lines.length; i++) {
11241
+ for (const pat of CLAIM_PATTERNS) {
11242
+ if (pat.test(lines[i])) {
11243
+ claims.push({ line: i + 1, text: lines[i].trim().substring(0, 120), pattern: pat.source });
11244
+ break;
11245
+ }
11246
+ }
11247
+ }
11248
+ return claims;
11249
+ }
11250
+ function loadRecentCascadeRuns(vibeHome) {
11251
+ try {
11252
+ const cascadeFile = join13(vibeHome, "cascade-audit", "cascade-audit.jsonl");
11253
+ if (!existsSync14(cascadeFile))
11254
+ return [];
11255
+ const raw = readFileSync13(cascadeFile, "utf-8");
11256
+ if (!raw || typeof raw !== "string")
11257
+ return [];
11258
+ return raw.trim().split("\n").filter(Boolean).slice(-30).map((l) => {
11259
+ try {
11260
+ return JSON.parse(l);
11261
+ } catch {
11262
+ return null;
11263
+ }
11264
+ }).filter(Boolean);
11265
+ } catch {
11266
+ return [];
11267
+ }
11268
+ }
11269
+ function evaluateClaimVerification({ text, vibeHome = process.env.VIBEOS_HOME || join13(process.env.HOME || "", ".claude"), now = Date.now(), windowMs = 12e4 }) {
11270
+ const claims = extractClaimMatches(text);
11271
+ if (claims.length === 0)
11272
+ return { claims, unsubstantiatedCount: 0, claimTag: "" };
11273
+ const cascadeRuns = loadRecentCascadeRuns(vibeHome);
11274
+ const substantiated = cascadeRuns.some((cr) => {
11275
+ const cTs = typeof cr === "object" && cr ? cr._ts || "" : "";
11276
+ return Boolean(cTs) && Math.abs(new Date(cTs).getTime() - now) < windowMs;
11277
+ });
11278
+ return {
11279
+ claims,
11280
+ unsubstantiatedCount: substantiated ? 0 : claims.length,
11281
+ claimTag: substantiated ? "\u2713" : `\u26A0${claims.length}`
11282
+ };
11283
+ }
11284
+
11261
11285
  // src/lib/mode-policy.js
11262
11286
  init_state();
11263
11287
  var STRESS_QUALITY_THRESHOLD = 1.5;
@@ -11453,15 +11477,15 @@ init_api_client();
11453
11477
  init_selection_manager();
11454
11478
 
11455
11479
  // src/lib/index-helpers.js
11456
- import { join as join14 } from "node:path";
11480
+ import { join as join15 } from "node:path";
11457
11481
  import { writeFileSync as writeFileSync13 } from "node:fs";
11458
11482
 
11459
11483
  // src/vibeOS-lib/semantic-observer.js
11460
11484
  init_state();
11461
11485
  init_pattern_helpers();
11462
11486
  init_pattern_helpers();
11463
- import { join as join13 } from "node:path";
11464
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync12, readFileSync as readFileSync13, existsSync as existsSync14 } from "node:fs";
11487
+ import { join as join14 } from "node:path";
11488
+ import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync12, readFileSync as readFileSync14, existsSync as existsSync15 } from "node:fs";
11465
11489
  function deriveRole(toolName, input, output) {
11466
11490
  if (["write", "edit", "notebookedit", "multiedit"].includes(toolName))
11467
11491
  return "mutation";
@@ -11488,15 +11512,15 @@ function deriveTags(input, output) {
11488
11512
  };
11489
11513
  }
11490
11514
  function getSessionEventLogPath(sid) {
11491
- const dir = join13(VIBEOS_HOME, "session-events");
11515
+ const dir = join14(VIBEOS_HOME, "session-events");
11492
11516
  mkdirSync10(dir, { recursive: true });
11493
- return join13(dir, sid + ".jsonl");
11517
+ return join14(dir, sid + ".jsonl");
11494
11518
  }
11495
11519
  function writeEvent(sid, event) {
11496
11520
  const path = getSessionEventLogPath(sid);
11497
11521
  let lines = [];
11498
- if (existsSync14(path)) {
11499
- const raw = readFileSync13(path, "utf-8").trim();
11522
+ if (existsSync15(path)) {
11523
+ const raw = readFileSync14(path, "utf-8").trim();
11500
11524
  if (raw)
11501
11525
  lines = raw.split("\n");
11502
11526
  }
@@ -11507,9 +11531,9 @@ function writeEvent(sid, event) {
11507
11531
  }
11508
11532
  function readRecentEvents(sid, n) {
11509
11533
  const path = getSessionEventLogPath(sid);
11510
- if (!existsSync14(path))
11534
+ if (!existsSync15(path))
11511
11535
  return [];
11512
- const raw = readFileSync13(path, "utf-8").trim();
11536
+ const raw = readFileSync14(path, "utf-8").trim();
11513
11537
  if (!raw)
11514
11538
  return [];
11515
11539
  const lines = raw.split("\n");
@@ -11691,9 +11715,9 @@ function sessionCompact(sid, fingerprint) {
11691
11715
  for (const p of patterns) {
11692
11716
  recordFrictionPattern(p.key, p.summary, { kind: p.kind, sessions: [sid], fingerprint });
11693
11717
  }
11694
- const bbPath = join13(VIBEOS_HOME, "blackbox-state.json");
11695
- if (existsSync14(bbPath)) {
11696
- const raw = readFileSync13(bbPath, "utf-8");
11718
+ const bbPath = join14(VIBEOS_HOME, "blackbox-state.json");
11719
+ if (existsSync15(bbPath)) {
11720
+ const raw = readFileSync14(bbPath, "utf-8");
11697
11721
  if (raw) {
11698
11722
  const bb = JSON.parse(raw);
11699
11723
  const ses = bb?.sessions?.[sid];
@@ -11951,7 +11975,7 @@ function recordSaving(tool2, reason, saveEst, meta = {}) {
11951
11975
  try {
11952
11976
  const sd = getSessionScratchpadDir();
11953
11977
  if (sd) {
11954
- const sp = join14(sd, "delegation-state-hint.txt");
11978
+ const sp = join15(sd, "delegation-state-hint.txt");
11955
11979
  try {
11956
11980
  writeFileSync13(sp, JSON.stringify({ sid, total_savings: s.lifetime.total_savings_usd, last_reason: reason }), "utf8");
11957
11981
  } catch {
@@ -12116,7 +12140,7 @@ var ANTI_LOOP_DIRECTIVE = "[anti-loop cost guard] Token waste is real money: if
12116
12140
  var _cachedC7Full = null;
12117
12141
  var _cachedC7Urgency = null;
12118
12142
  function getVibeOSHome9() {
12119
- return process.env.VIBEOS_HOME || join15(process.env.HOME || "", ".claude");
12143
+ return process.env.VIBEOS_HOME || join16(process.env.HOME || "", ".claude");
12120
12144
  }
12121
12145
  function mergeRemoteControlVector(remoteControlVector, localControlVector) {
12122
12146
  return {
@@ -12135,14 +12159,14 @@ function resolveRestorableOpenCodeAgent(currentSel) {
12135
12159
  if (remembered && remembered !== "plan")
12136
12160
  return remembered;
12137
12161
  try {
12138
- const configDir = dirname10(TRINITY_OPENCODE_CONFIG || join15(getOpenCodeHome(), "opencode.json"));
12162
+ const configDir = dirname10(TRINITY_OPENCODE_CONFIG || join16(getOpenCodeHome(), "opencode.json"));
12139
12163
  const candidates = readdirSync3(configDir).filter((name) => /^opencode\.json\.bak/.test(name)).map((name) => {
12140
- const path = join15(configDir, name);
12164
+ const path = join16(configDir, name);
12141
12165
  return { path, mtime: statSync7(path).mtimeMs };
12142
12166
  }).sort((a, b) => b.mtime - a.mtime);
12143
12167
  for (const candidate of candidates) {
12144
12168
  try {
12145
- const snapshot = safeJsonParse2(readFileSync14(candidate.path, "utf-8"));
12169
+ const snapshot = safeJsonParse2(readFileSync15(candidate.path, "utf-8"));
12146
12170
  const agent = typeof snapshot?.default_agent === "string" ? snapshot.default_agent.trim() : "";
12147
12171
  if (agent && agent !== "plan")
12148
12172
  return agent;
@@ -12246,11 +12270,11 @@ function buildProjectBriefing(directory3) {
12246
12270
  return `[project memory] Active project: ${label}. Stay focused on the current repository and prefer the existing workflow.`;
12247
12271
  }
12248
12272
  function ensureProjectSkill(dir, fp2) {
12249
- const skillsDir = join15(dir, ".opencode", "skills");
12273
+ const skillsDir = join16(dir, ".opencode", "skills");
12250
12274
  const projectName = basename3(dir);
12251
- const skillDir = join15(skillsDir, projectName);
12252
- const skillPath = join15(skillDir, "SKILL.md");
12253
- if (existsSync15(skillPath)) {
12275
+ const skillDir = join16(skillsDir, projectName);
12276
+ const skillPath = join16(skillDir, "SKILL.md");
12277
+ if (existsSync16(skillPath)) {
12254
12278
  return { created: false, skipped: true, path: skillPath };
12255
12279
  }
12256
12280
  const promoted = promotedProjectPatterns(fp2);
@@ -12428,9 +12452,9 @@ function syncControlSettings(cv, options = {}) {
12428
12452
  }
12429
12453
  if (cv.agent_mode) {
12430
12454
  try {
12431
- const OC_CONFIG = TRINITY_OPENCODE_CONFIG || join15(getOpenCodeHome(), "opencode.json");
12432
- if (existsSync15(OC_CONFIG)) {
12433
- const oc = safeJsonParse2(readFileSync14(OC_CONFIG, "utf-8"));
12455
+ const OC_CONFIG = TRINITY_OPENCODE_CONFIG || join16(getOpenCodeHome(), "opencode.json");
12456
+ if (existsSync16(OC_CONFIG)) {
12457
+ const oc = safeJsonParse2(readFileSync15(OC_CONFIG, "utf-8"));
12434
12458
  if (!oc)
12435
12459
  return;
12436
12460
  if (oc.default_agent !== cv.agent_mode) {
@@ -12445,9 +12469,9 @@ function syncControlSettings(cv, options = {}) {
12445
12469
  }
12446
12470
  } else {
12447
12471
  try {
12448
- const OC_CONFIG = TRINITY_OPENCODE_CONFIG || join15(getOpenCodeHome(), "opencode.json");
12449
- if (existsSync15(OC_CONFIG)) {
12450
- const oc = safeJsonParse2(readFileSync14(OC_CONFIG, "utf-8"));
12472
+ const OC_CONFIG = TRINITY_OPENCODE_CONFIG || join16(getOpenCodeHome(), "opencode.json");
12473
+ if (existsSync16(OC_CONFIG)) {
12474
+ const oc = safeJsonParse2(readFileSync15(OC_CONFIG, "utf-8"));
12451
12475
  if (!oc)
12452
12476
  return;
12453
12477
  const restoreAgent = oc.default_agent === "plan" ? resolveRestorableOpenCodeAgent(currentSel) : null;
@@ -12514,25 +12538,26 @@ function compressToolOutputs(messages) {
12514
12538
  const hash = createHash3("sha256").update(`tool_result
12515
12539
  ${raw}
12516
12540
  `).digest("hex").slice(0, 16);
12517
- const globalDir = join15(SCRATCHPAD_ROOT, "by-hash");
12518
- const sessPath = join15(getSessionScratchpadDir(), `${hash}.txt`);
12519
- const globalPath = join15(globalDir, `${hash}.txt`);
12541
+ const globalDir = join16(SCRATCHPAD_ROOT, "by-hash");
12542
+ const sessPath = join16(getSessionScratchpadDir(), `${hash}.txt`);
12543
+ const globalPath = join16(globalDir, `${hash}.txt`);
12520
12544
  try {
12521
12545
  mkdirSync11(globalDir, { recursive: true });
12522
12546
  ensureSessionScratchpadDirs();
12523
- if (!existsSync15(globalPath)) {
12547
+ if (!existsSync16(globalPath)) {
12524
12548
  writeFileSync14(globalPath, raw);
12525
12549
  indexAppend(hash, part.tool, raw.length);
12526
- if (existsSync15(sessPath))
12550
+ if (existsSync16(sessPath))
12527
12551
  rmSync5(sessPath, { force: true });
12528
12552
  }
12553
+ safeCopyIntoSession(hash, globalPath);
12529
12554
  const invPart = parts.slice(0, parts.indexOf(part)).reverse().find((p) => p?.type === "tool" && p?.tool === part.tool && p?.state?.input && p?.state?.status !== "completed");
12530
12555
  if (invPart?.state?.input) {
12531
12556
  const toolKey2 = TOOL_NAME_NORMALIZE[part.tool] || part.tool;
12532
12557
  const inputHash = createHash3("sha256").update(`${toolKey2}
12533
12558
  ${stableJson(invPart.state.input)}
12534
12559
  `).digest("hex").slice(0, 16);
12535
- const ptrPath = join15(getSessionScratchpadDir(), `${inputHash}.ptr`);
12560
+ const ptrPath = join16(getSessionScratchpadDir(), `${inputHash}.ptr`);
12536
12561
  try {
12537
12562
  writeFileSync14(ptrPath, JSON.stringify({ contentHash: hash, tool: part.tool }));
12538
12563
  } catch {
@@ -12680,78 +12705,30 @@ var onMessagesTransform = async (_input, output) => {
12680
12705
  try {
12681
12706
  if (!Array.isArray(messages) || Object.isFrozen(messages))
12682
12707
  return;
12683
- const vibeHome = process.env.VIBEOS_HOME || join15(process.env.HOME || homedir6(), ".claude");
12708
+ const vibeHome = process.env.VIBEOS_HOME || join16(process.env.HOME || homedir6(), ".claude");
12684
12709
  if (typeof vibeHome !== "string" || vibeHome.length === 0)
12685
12710
  return;
12686
- const claimFile = join15(vibeHome, "cascade-audit", "claim-audit.jsonl");
12687
- const cascadeFile = join15(vibeHome, "cascade-audit", "cascade-audit.jsonl");
12688
- if (!existsSync15(claimFile))
12689
- return;
12690
- const st = statSync7(claimFile);
12691
- if (!st || st.size <= 0)
12692
- return;
12693
- const claimRaw = readFileSync14(claimFile, "utf-8");
12694
- if (!claimRaw || typeof claimRaw !== "string")
12695
- return;
12696
- const claimLines = claimRaw.trim().split("\n").filter(Boolean).slice(-5);
12697
- if (claimLines.length === 0)
12698
- return;
12699
- const cascadeRaw = existsSync15(cascadeFile) ? readFileSync14(cascadeFile, "utf-8") : "";
12700
- const cascadeLines = cascadeRaw && typeof cascadeRaw === "string" ? cascadeRaw.trim().split("\n").filter(Boolean).slice(-20) : [];
12701
- const cascadeRuns = cascadeLines.map((l) => {
12702
- try {
12703
- return JSON.parse(l);
12704
- } catch {
12705
- return null;
12706
- }
12707
- }).filter(Boolean);
12708
- const unsubClaims = [];
12711
+ let currentAssistantText = "";
12709
12712
  let lastInjectTs = 0;
12710
12713
  for (let i = messages.length - 1; i >= Math.max(0, messages.length - 4); i--) {
12711
12714
  const m = messages[i];
12712
12715
  if (!m || typeof m !== "object")
12713
12716
  continue;
12714
12717
  if (m.role === "assistant" && Array.isArray(m.parts)) {
12718
+ currentAssistantText = m.parts.filter((p) => p && typeof p === "object" && p.type === "text" && typeof p.text === "string").map((p) => p.text).join("\n");
12715
12719
  for (const p of m.parts) {
12716
12720
  if (p && typeof p === "object" && p.type === "text" && typeof p.text === "string" && p.text.includes("[verify]")) {
12717
12721
  lastInjectTs = Date.now();
12718
12722
  }
12719
12723
  }
12724
+ if (currentAssistantText)
12725
+ break;
12720
12726
  }
12721
12727
  }
12722
12728
  if (Date.now() - lastInjectTs < 3e4)
12723
12729
  return;
12724
- for (const cl of claimLines) {
12725
- if (!cl.trim())
12726
- continue;
12727
- let entry;
12728
- try {
12729
- entry = JSON.parse(cl);
12730
- } catch {
12731
- continue;
12732
- }
12733
- if (!entry || typeof entry !== "object")
12734
- continue;
12735
- const claimTexts = (entry.claims || []).filter(Boolean).map((c) => typeof c === "object" && c.text ? c.text : "").filter(Boolean).join(" | ");
12736
- if (!claimTexts)
12737
- continue;
12738
- if (!/(?:I|we|the)\s+(?:pushed|released|merged|deployed|fixed)\b|(?:tests?|build|CI|checks?)\s+(?:is\s+|are\s+)?(?:pass|green|clean)\b|v\d+\.\d+\.\d+|done|fixed|works|exit\s*code\s*0|\d+%|score|passed/i.test(claimTexts))
12739
- continue;
12740
- let cascadeMatch = false;
12741
- for (const cr of cascadeRuns) {
12742
- const cTs = typeof cr === "object" && cr ? cr._ts || "" : "";
12743
- if (cTs && entry.ts && Math.abs(new Date(cTs).getTime() - new Date(entry.ts).getTime()) < 12e4) {
12744
- cascadeMatch = true;
12745
- break;
12746
- }
12747
- }
12748
- if (!cascadeMatch) {
12749
- for (const c of entry.claims || []) {
12750
- if (c && typeof c === "object" && c.text)
12751
- unsubClaims.push(c.text);
12752
- }
12753
- }
12754
- }
12730
+ const claimStatus = evaluateClaimVerification({ text: currentAssistantText, vibeHome });
12731
+ const unsubClaims = claimStatus.unsubstantiatedCount > 0 ? claimStatus.claims.map((c) => c.text).filter(Boolean) : [];
12755
12732
  if (unsubClaims.length > 0 && !Object.isFrozen(messages)) {
12756
12733
  const verifyText = "\n[vibeOS verify]\nUnsubstantiated claims from previous turn:\n" + unsubClaims.slice(0, 5).map((t) => ' - "' + (typeof t === "string" ? t.substring(0, 80) : "") + '"').join("\n") + "\nPlease verify each claim and correct if inaccurate.";
12757
12734
  try {
@@ -12821,7 +12798,7 @@ function orchestratorDirective(cv, sel) {
12821
12798
  const tierBias = cv?.tier_bias || "auto";
12822
12799
  let brainModel = "(brain)";
12823
12800
  try {
12824
- brainModel = safeJsonParse2(readFileSync14(TIERS_FILE, "utf-8")).trinity?.brain?.oc || brainModel;
12801
+ brainModel = safeJsonParse2(readFileSync15(TIERS_FILE, "utf-8")).trinity?.brain?.oc || brainModel;
12825
12802
  } catch {
12826
12803
  }
12827
12804
  const cheapModel = TRINITY_CHEAP || "the cheaper model";
@@ -12869,7 +12846,7 @@ function welcomeDirective() {
12869
12846
  const sel = loadSelection();
12870
12847
  let tiers = {};
12871
12848
  try {
12872
- tiers = safeJsonParse2(readFileSync14(TIERS_FILE, "utf-8")).trinity || {};
12849
+ tiers = safeJsonParse2(readFileSync15(TIERS_FILE, "utf-8")).trinity || {};
12873
12850
  } catch {
12874
12851
  }
12875
12852
  const active = sel.active_slot || "medium";
@@ -13126,7 +13103,7 @@ var onSystemTransform = async (_input, output) => {
13126
13103
  }) + "\n");
13127
13104
  if (_turnCountInject % 10 === 0 && _calBuffer.length > 0) {
13128
13105
  try {
13129
- const calFile = join15(getVibeOSHome9(), "calibration-data.jsonl");
13106
+ const calFile = join16(getVibeOSHome9(), "calibration-data.jsonl");
13130
13107
  mkdirSync11(getVibeOSHome9(), { recursive: true });
13131
13108
  appendFileSync4(calFile, _calBuffer.join(""));
13132
13109
  _calBuffer.length = 0;
@@ -13398,7 +13375,7 @@ function detectLaziness(input) {
13398
13375
  }
13399
13376
 
13400
13377
  // src/vibeOS-lib/lie-detector.js
13401
- var CLAIM_PATTERNS = [
13378
+ var CLAIM_PATTERNS2 = [
13402
13379
  /(?:I|we|the)\s+(?:pushed|released|merged|deployed|fixed|wrote|implemented|completed|committed)\b/i,
13403
13380
  /(?:tests?|build|CI|checks?|suite|output|result)\s+(?:is\s+|are\s+)?(?:pass(?:ing|ed|es)?|green|clean|succeed|stable|positive)/i,
13404
13381
  /(?:done|finished|complete)/i,
@@ -13418,7 +13395,7 @@ function scanClaims(text) {
13418
13395
  const claims = [];
13419
13396
  const lines = text.split("\n");
13420
13397
  for (let i = 0; i < lines.length; i++) {
13421
- for (const pat of CLAIM_PATTERNS) {
13398
+ for (const pat of CLAIM_PATTERNS2) {
13422
13399
  if (pat.test(lines[i])) {
13423
13400
  claims.push({ line: i + 1, text: lines[i].trim().substring(0, 120) });
13424
13401
  break;
@@ -13463,17 +13440,17 @@ function footerDebug(...args) {
13463
13440
  console.error(...args);
13464
13441
  }
13465
13442
  function getVibeOSHome10() {
13466
- return process.env.VIBEOS_HOME || join16(process.env.HOME || "", ".claude");
13443
+ return process.env.VIBEOS_HOME || join17(process.env.HOME || "", ".claude");
13467
13444
  }
13468
- var STATE_FILE2 = join16(getVibeOSHome10(), "delegation-state.json");
13469
- var SAVINGS_LEDGER_FILE2 = join16(getVibeOSHome10(), "savings-ledger.jsonl");
13445
+ var STATE_FILE2 = join17(getVibeOSHome10(), "delegation-state.json");
13446
+ var SAVINGS_LEDGER_FILE2 = join17(getVibeOSHome10(), "savings-ledger.jsonl");
13470
13447
  var _prevOutputText = "";
13471
13448
  var _autoReportCount = 0;
13472
13449
  var textCompletePainted = /* @__PURE__ */ new Set();
13473
13450
  var _lastStrippedText = "";
13474
13451
  function loadSelection2() {
13475
13452
  try {
13476
- const raw = readFileSync15(join16(getVibeOSHome10(), "model-tiers.json"), "utf-8");
13453
+ const raw = readFileSync16(join17(getVibeOSHome10(), "model-tiers.json"), "utf-8");
13477
13454
  return safeJsonParse2(raw)?.selection || { active_slot: "medium", enabled: true, delegation_enforce: true, flow_enabled: true, flow_enforce: true, tdd_enforce: false, tdd_strict: false };
13478
13455
  } catch {
13479
13456
  return { active_slot: "medium", enabled: true, delegation_enforce: true, flow_enabled: true, flow_enforce: true, tdd_enforce: false, tdd_strict: false };
@@ -13486,7 +13463,7 @@ function isGreetingLike(text) {
13486
13463
  function readLifetimeSavings2() {
13487
13464
  try {
13488
13465
  reconcileStateFromLedger();
13489
- const raw = readFileSync15(STATE_FILE2, "utf-8");
13466
+ const raw = readFileSync16(STATE_FILE2, "utf-8");
13490
13467
  const state = safeJsonParse2(raw);
13491
13468
  const ses = state?.sessions?.[getSessionId()] || {};
13492
13469
  return {
@@ -13655,7 +13632,7 @@ async function _appendFooter(input, output, directory3) {
13655
13632
  } catch {
13656
13633
  }
13657
13634
  if (!liveModel) {
13658
- liveModel = readConfig(directory3) || readConfig(join16(process.env.HOME || "", ".config", "opencode")) || process?.env?.OPENCODE_MODEL || "";
13635
+ liveModel = readConfig(directory3) || readConfig(join17(process.env.HOME || "", ".config", "opencode")) || process?.env?.OPENCODE_MODEL || "";
13659
13636
  }
13660
13637
  const displayModel = resolveTrinityDisplayModel(directory3, slot, liveModel, currentModel) || brainModel || liveModel || currentModel;
13661
13638
  const resolvedModel = displayModel || liveModel || brainModel || currentModel || "";
@@ -13724,53 +13701,8 @@ async function _appendFooter(input, output, directory3) {
13724
13701
  const rawMode = (typeof loadSelection2 === "function" ? loadSelection2()?.requested_optimization_mode || loadSelection2()?.optimization_mode : null) || displayMode;
13725
13702
  const cv = computeControlVector2({ sub_regime: currentSubRegime, latest_stress_multiplier: _footerStress, user_text: latestUserIntent || "" }, void 0, rawMode);
13726
13703
  const vibeBrand = resolveBrand(loadOptimizationMode() || displayMode, activeSlot);
13727
- let _claimTag = "";
13704
+ const claimStatus = evaluateClaimVerification({ text, vibeHome: VIBEOS_HOME });
13728
13705
  let _rewardTag = "";
13729
- try {
13730
- const claimAuditFile = join16(VIBEOS_HOME, "cascade-audit", "claim-audit.jsonl");
13731
- const cascadeAuditFile = join16(VIBEOS_HOME, "cascade-audit", "cascade-audit.jsonl");
13732
- if (existsSync16(claimAuditFile) && statSync8(claimAuditFile).size > 0) {
13733
- const claimLines = readFileSync15(claimAuditFile, "utf-8").trim().split("\n").slice(-10);
13734
- const cascadeLines = existsSync16(cascadeAuditFile) ? readFileSync15(cascadeAuditFile, "utf-8").trim().split("\n").slice(-30) : [];
13735
- const cascadeRuns = cascadeLines.filter(Boolean).map(function(l) {
13736
- try {
13737
- return JSON.parse(l);
13738
- } catch {
13739
- }
13740
- }).filter(Boolean);
13741
- let unsub = 0;
13742
- for (const cl of claimLines) {
13743
- if (!cl.trim())
13744
- continue;
13745
- let entry;
13746
- try {
13747
- entry = JSON.parse(cl);
13748
- } catch {
13749
- continue;
13750
- }
13751
- if (!entry)
13752
- continue;
13753
- const claimTexts = (entry.claims || []).map(function(c) {
13754
- return c.text;
13755
- }).join(" | ");
13756
- let cascadeMatch = false;
13757
- for (const cr of cascadeRuns) {
13758
- const cTs = cr._ts || "";
13759
- if (cTs && entry.ts && Math.abs(new Date(cTs).getTime() - new Date(entry.ts).getTime()) < 12e4) {
13760
- cascadeMatch = true;
13761
- break;
13762
- }
13763
- }
13764
- if (!cascadeMatch)
13765
- unsub++;
13766
- }
13767
- if (unsub > 0)
13768
- _claimTag = "\u26A0" + unsub;
13769
- else
13770
- _claimTag = "\u2713";
13771
- }
13772
- } catch {
13773
- }
13774
13706
  const vibeLine = buildFooterLine({
13775
13707
  activeSlot,
13776
13708
  providerLabel: execution.provider_label,
@@ -13786,7 +13718,7 @@ async function _appendFooter(input, output, directory3) {
13786
13718
  subRegime: currentSubRegime,
13787
13719
  stressGauge: _footerStress > 0.85 ? "\u2588" : _footerStress > 0.7 ? "\u2586" : _footerStress > 0.5 ? "\u2585" : _footerStress > 0.3 ? "\u2583" : _footerStress > 0.1 ? "\u2582" : "\u2581",
13788
13720
  cascadeIcon: (cv?.cascade_depth || 1) >= 3 ? "\u25B8\u25B8\u25B8" : (cv?.cascade_depth || 1) >= 2 ? "\u25B8\u25B8" : "",
13789
- claimTag: _claimTag,
13721
+ claimTag: claimStatus.claimTag || void 0,
13790
13722
  rewardTag: _rewardTag || void 0
13791
13723
  });
13792
13724
  const footerText = stripped + `
@@ -13831,8 +13763,8 @@ ${vibeLine}`;
13831
13763
  if (rewardResult.credits !== 0) {
13832
13764
  _rewardTag = rewardResult.credits > 0 ? `+${rewardResult.credits} XP` : `${rewardResult.credits} XP`;
13833
13765
  try {
13834
- const statePath = join16(VIBEOS_HOME, "delegation-state.json");
13835
- const state = safeJsonParse2(readFileSync15(statePath, "utf-8"), {});
13766
+ const statePath = join17(VIBEOS_HOME, "delegation-state.json");
13767
+ const state = safeJsonParse2(readFileSync16(statePath, "utf-8"), {});
13836
13768
  const sid2 = getCurrentSessionId();
13837
13769
  if (!state.sessions)
13838
13770
  state.sessions = {};
@@ -13850,7 +13782,7 @@ ${vibeLine}`;
13850
13782
  }
13851
13783
  try {
13852
13784
  mkdirSync12(getVibeOSHome10(), { recursive: true });
13853
- appendFileSync5(join16(getVibeOSHome10(), "calibration-data.jsonl"), JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), event: "outcome", sid: getSessionId(), outcome: finalOutcome }) + "\n");
13785
+ appendFileSync5(join17(getVibeOSHome10(), "calibration-data.jsonl"), JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), event: "outcome", sid: getSessionId(), outcome: finalOutcome }) + "\n");
13854
13786
  } catch {
13855
13787
  }
13856
13788
  }
@@ -13878,7 +13810,7 @@ ${vibeLine} \u2014`);
13878
13810
  // src/lib/hooks/tool-execute.js
13879
13811
  init_state();
13880
13812
  import { writeFileSync as writeFileSync17, appendFileSync as appendFileSync7, existsSync as existsSync18, mkdirSync as mkdirSync14 } from "node:fs";
13881
- import { join as join18, dirname as dirname12, basename as basename4 } from "node:path";
13813
+ import { join as join19, dirname as dirname12, basename as basename4 } from "node:path";
13882
13814
  import { createHash as createHash5 } from "node:crypto";
13883
13815
  init_selection_manager();
13884
13816
  init_api_client();
@@ -13947,8 +13879,8 @@ init_smart_cache();
13947
13879
 
13948
13880
  // src/lib/tdd-enforcer.js
13949
13881
  init_state();
13950
- import { readFileSync as readFileSync16, writeFileSync as writeFileSync16, appendFileSync as appendFileSync6, existsSync as existsSync17, mkdirSync as mkdirSync13, statSync as statSync9, readdirSync as readdirSync4, rmSync as rmSync6, openSync as openSync3 } from "node:fs";
13951
- import { join as join17, dirname as dirname11 } from "node:path";
13882
+ import { readFileSync as readFileSync17, writeFileSync as writeFileSync16, appendFileSync as appendFileSync6, existsSync as existsSync17, mkdirSync as mkdirSync13, statSync as statSync8, readdirSync as readdirSync4, rmSync as rmSync6, openSync as openSync3 } from "node:fs";
13883
+ import { join as join18, dirname as dirname11 } from "node:path";
13952
13884
  import { createHash as createHash4 } from "node:crypto";
13953
13885
 
13954
13886
  // src/utils/tdd-helpers.js
@@ -15077,7 +15009,7 @@ var test_skeletons_default = TEST_SKELETONS;
15077
15009
 
15078
15010
  // src/lib/tdd-enforcer.js
15079
15011
  function getVibeOSHome11() {
15080
- return process.env.VIBEOS_HOME || join17(process.env.HOME || "", ".claude");
15012
+ return process.env.VIBEOS_HOME || join18(process.env.HOME || "", ".claude");
15081
15013
  }
15082
15014
  var _detectedFramework = null;
15083
15015
  var directory = void 0;
@@ -15090,9 +15022,9 @@ function _detectTestFramework() {
15090
15022
  let testExt = null;
15091
15023
  try {
15092
15024
  const root = directory || process.cwd();
15093
- const pkgPath = join17(root, "package.json");
15025
+ const pkgPath = join18(root, "package.json");
15094
15026
  if (existsSync17(pkgPath)) {
15095
- const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
15027
+ const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
15096
15028
  const testScript = String(pkg?.scripts?.test || "");
15097
15029
  const deps = { ...pkg?.devDependencies, ...pkg?.dependencies };
15098
15030
  if (testScript.includes("vitest") || deps["vitest"]) {
@@ -15112,12 +15044,12 @@ function _detectTestFramework() {
15112
15044
  if (!framework) {
15113
15045
  const testDirs = ["src/tests", "tests", "test", "__tests__"];
15114
15046
  for (const td of testDirs) {
15115
- const dirPath = join17(root, td);
15047
+ const dirPath = join18(root, td);
15116
15048
  if (!existsSync17(dirPath))
15117
15049
  continue;
15118
15050
  const files = readdirSync4(dirPath).filter((f) => /\.test\./.test(f) || /\.spec\./.test(f));
15119
15051
  if (files.length > 0) {
15120
- const content = readFileSync16(join17(dirPath, files[0]), "utf-8");
15052
+ const content = readFileSync17(join18(dirPath, files[0]), "utf-8");
15121
15053
  if (/from\s+['"]node:test['"]/.test(content)) {
15122
15054
  framework = "node-test";
15123
15055
  testExt = files[0].split(".").pop();
@@ -15143,16 +15075,16 @@ function _detectTestFramework() {
15143
15075
  console.error(`[vibeOS] [tdd] detected test framework: ${framework || "default"} (ext: ${testExt || "match source"})`);
15144
15076
  return _detectedFramework;
15145
15077
  }
15146
- var ENFORCEMENT_LOCK_DIR = join17(getVibeOSHome11(), ".enforcement-lock");
15078
+ var ENFORCEMENT_LOCK_DIR = join18(getVibeOSHome11(), ".enforcement-lock");
15147
15079
  var LOCK_EXPIRE_MS = 3e4;
15148
- var ENFORCEMENT_COOLDOWN_FILE2 = join17(getVibeOSHome11(), ".enforcement-cooldown.jsonl");
15080
+ var ENFORCEMENT_COOLDOWN_FILE2 = join18(getVibeOSHome11(), ".enforcement-cooldown.jsonl");
15149
15081
  var COOLDOWN_MS = 6e4;
15150
15082
  var _enforcementCooldown = /* @__PURE__ */ new Set();
15151
15083
  function _acquireLock(testPath) {
15152
15084
  try {
15153
15085
  mkdirSync13(ENFORCEMENT_LOCK_DIR, { recursive: true });
15154
15086
  const hash = createHash4("sha256").update(testPath).digest("hex").slice(0, 16);
15155
- const lockPath = join17(ENFORCEMENT_LOCK_DIR, `${hash}.lock`);
15087
+ const lockPath = join18(ENFORCEMENT_LOCK_DIR, `${hash}.lock`);
15156
15088
  try {
15157
15089
  openSync3(lockPath, "wx");
15158
15090
  return true;
@@ -15160,7 +15092,7 @@ function _acquireLock(testPath) {
15160
15092
  if (err.code !== "EEXIST")
15161
15093
  return false;
15162
15094
  try {
15163
- const st = statSync9(lockPath);
15095
+ const st = statSync8(lockPath);
15164
15096
  if (Date.now() - st.mtimeMs >= LOCK_EXPIRE_MS) {
15165
15097
  rmSync6(lockPath, { force: true });
15166
15098
  try {
@@ -15180,7 +15112,7 @@ function _acquireLock(testPath) {
15180
15112
  function _releaseLock(testPath) {
15181
15113
  try {
15182
15114
  const hash = createHash4("sha256").update(testPath).digest("hex").slice(0, 16);
15183
- const lockPath = join17(ENFORCEMENT_LOCK_DIR, `${hash}.lock`);
15115
+ const lockPath = join18(ENFORCEMENT_LOCK_DIR, `${hash}.lock`);
15184
15116
  rmSync6(lockPath);
15185
15117
  } catch {
15186
15118
  }
@@ -15190,7 +15122,7 @@ function _isInCooldown(testPath) {
15190
15122
  if (!existsSync17(ENFORCEMENT_COOLDOWN_FILE2))
15191
15123
  return false;
15192
15124
  const hash = createHash4("sha256").update(testPath).digest("hex").slice(0, 16);
15193
- const lines = readFileSync16(ENFORCEMENT_COOLDOWN_FILE2, "utf-8").trim().split("\n").filter(Boolean);
15125
+ const lines = readFileSync17(ENFORCEMENT_COOLDOWN_FILE2, "utf-8").trim().split("\n").filter(Boolean);
15194
15126
  const now = Date.now();
15195
15127
  for (const line of lines) {
15196
15128
  try {
@@ -15211,7 +15143,7 @@ function _recordCooldown(testPath) {
15211
15143
  const hash = createHash4("sha256").update(testPath).digest("hex").slice(0, 16);
15212
15144
  const entry = JSON.stringify({ h: hash, ts: Date.now() }) + "\n";
15213
15145
  appendFileSync6(ENFORCEMENT_COOLDOWN_FILE2, entry);
15214
- const lines = readFileSync16(ENFORCEMENT_COOLDOWN_FILE2, "utf-8").trim().split("\n").filter(Boolean);
15146
+ const lines = readFileSync17(ENFORCEMENT_COOLDOWN_FILE2, "utf-8").trim().split("\n").filter(Boolean);
15215
15147
  if (lines.length > 500) {
15216
15148
  writeFileSync16(ENFORCEMENT_COOLDOWN_FILE2, lines.slice(-200).join("\n") + "\n");
15217
15149
  }
@@ -15282,7 +15214,7 @@ function enforceTestFile(filePath) {
15282
15214
  let sourceContent = "";
15283
15215
  try {
15284
15216
  if (existsSync17(filePath)) {
15285
- sourceContent = readFileSync16(filePath, "utf-8");
15217
+ sourceContent = readFileSync17(filePath, "utf-8");
15286
15218
  }
15287
15219
  } catch {
15288
15220
  }
@@ -15386,7 +15318,7 @@ var BYTES_PER_TOKEN2 = 4;
15386
15318
  var DEBUG_INTERNALS2 = process.env.VIBEOS_DEBUG_INTERNALS === "1";
15387
15319
  var IS_CLI_RUNTIME2 = Boolean(process.stdout?.isTTY || process.stderr?.isTTY || process.stdin?.isTTY);
15388
15320
  function getVibeOSHome12() {
15389
- return process.env.VIBEOS_HOME || join18(process.env.HOME || "", ".claude");
15321
+ return process.env.VIBEOS_HOME || join19(process.env.HOME || "", ".claude");
15390
15322
  }
15391
15323
  var projectDirectory = "";
15392
15324
  var pendingUiNote = null;
@@ -15502,7 +15434,7 @@ function _resolveToolPath(pathValue) {
15502
15434
  return raw;
15503
15435
  if (raw.startsWith("/"))
15504
15436
  return raw;
15505
- return projectDirectory ? join18(projectDirectory, raw).replace(/\\/g, "/") : raw;
15437
+ return projectDirectory ? join19(projectDirectory, raw).replace(/\\/g, "/") : raw;
15506
15438
  }
15507
15439
  function _isProtectedToolPath(pathValue) {
15508
15440
  const raw = _normalizeToolPath(pathValue);
@@ -15641,14 +15573,14 @@ ${argsJson}
15641
15573
  `).digest("hex").slice(0, 16);
15642
15574
  const sessionDir = getSessionScratchpadDir();
15643
15575
  const globalDir = SCRATCHPAD_GLOBAL_DIR;
15644
- const ptrPath = join18(sessionDir, `${curHash}.ptr`);
15576
+ const ptrPath = join19(sessionDir, `${curHash}.ptr`);
15645
15577
  if (!existsSync18(ptrPath)) {
15646
15578
  for (const similar of prediction.similarEntries) {
15647
15579
  const targetHash = similar.entry.hash;
15648
15580
  if (targetHash.length < 16)
15649
15581
  continue;
15650
- const cachedFile = join18(sessionDir, `${targetHash}.txt`);
15651
- const globalFile = join18(globalDir, `${targetHash}.txt`);
15582
+ const cachedFile = join19(sessionDir, `${targetHash}.txt`);
15583
+ const globalFile = join19(globalDir, `${targetHash}.txt`);
15652
15584
  if (existsSync18(cachedFile) || existsSync18(globalFile)) {
15653
15585
  ensureSessionScratchpadDirs();
15654
15586
  writeFileSync17(ptrPath, JSON.stringify({
@@ -16025,7 +15957,7 @@ var onToolExecuteAfter = async (input, output) => {
16025
15957
  } catch {
16026
15958
  }
16027
15959
  if (!liveModel) {
16028
- liveModel = readConfig(projectDirectory) || readConfig(join18(process.env.HOME || "", ".config", "opencode")) || process?.env?.OPENCODE_MODEL || "";
15960
+ liveModel = readConfig(projectDirectory) || readConfig(join19(process.env.HOME || "", ".config", "opencode")) || process?.env?.OPENCODE_MODEL || "";
16029
15961
  }
16030
15962
  const displayModel = resolveTrinityDisplayModel(projectDirectory, selNow.active_slot || "", liveModel, currentModel) || liveModel || currentModel;
16031
15963
  const resolvedModel = displayModel || liveModel || currentModel || "";
@@ -16101,7 +16033,7 @@ var onToolExecuteAfter = async (input, output) => {
16101
16033
  const trinityAction = trinityArgs?.action || trinityArgs?.todo || "";
16102
16034
  if (trinityAction === "todo") {
16103
16035
  try {
16104
- const flowTodoFilePath = join18(getVibeOSHome12(), ".flow-todo-queue.jsonl");
16036
+ const flowTodoFilePath = join19(getVibeOSHome12(), ".flow-todo-queue.jsonl");
16105
16037
  let todoLines = [];
16106
16038
  if (__require("fs").existsSync(flowTodoFilePath)) {
16107
16039
  const raw2 = __require("fs").readFileSync(flowTodoFilePath, "utf-8").trim();
@@ -16398,7 +16330,7 @@ ${pendingUiNote}`;
16398
16330
 
16399
16331
  // src/lib/hooks/session-compact.js
16400
16332
  init_state();
16401
- import { readFileSync as readFileSync17, existsSync as existsSync19 } from "node:fs";
16333
+ import { readFileSync as readFileSync18, existsSync as existsSync19 } from "node:fs";
16402
16334
  var onSessionCompacting = async (_input, output) => {
16403
16335
  if (!loadSelection().enabled)
16404
16336
  return;
@@ -16409,7 +16341,7 @@ var onSessionCompacting = async (_input, output) => {
16409
16341
  let recent = "";
16410
16342
  if (existsSync19(indexPath)) {
16411
16343
  try {
16412
- const lines = readFileSync17(indexPath, "utf-8").trim().split("\n").slice(-30);
16344
+ const lines = readFileSync18(indexPath, "utf-8").trim().split("\n").slice(-30);
16413
16345
  recent = lines.map((l) => {
16414
16346
  try {
16415
16347
  return JSON.parse(l);
@@ -16495,13 +16427,13 @@ init_state();
16495
16427
  init_state();
16496
16428
  init_api_client();
16497
16429
  function getVibeOSHome13() {
16498
- return process.env.VIBEOS_HOME || join19(process.env.HOME || "", ".claude");
16430
+ return process.env.VIBEOS_HOME || join20(process.env.HOME || "", ".claude");
16499
16431
  }
16500
16432
  function getTiersFile() {
16501
- return join19(getVibeOSHome13(), "model-tiers.json");
16433
+ return join20(getVibeOSHome13(), "model-tiers.json");
16502
16434
  }
16503
16435
  function getReportsDir2() {
16504
- return join19(getVibeOSHome13(), "reports");
16436
+ return join20(getVibeOSHome13(), "reports");
16505
16437
  }
16506
16438
  function ensureDeferredBootstrap() {
16507
16439
  if (_deferredBootstrapDone || _modelLocked)
@@ -16512,7 +16444,7 @@ function ensureDeferredBootstrap() {
16512
16444
  } catch {
16513
16445
  }
16514
16446
  }
16515
- var CLAIM_PATTERNS2 = [
16447
+ var CLAIM_PATTERNS3 = [
16516
16448
  /(?:I|we|the)\s+(?:pushed|released|merged|deployed|fixed|wrote|implemented|completed|committed)\b/i,
16517
16449
  /(?:tests?|build|CI|checks?|suite|output|result)\s+(?:is\s+|are\s+)?(?:pass(?:ing|ed|es)?|green|clean|succeed|stable|positive)/i,
16518
16450
  /v\d+\.\d+\.\d+/,
@@ -16524,19 +16456,30 @@ var CLAIM_PATTERNS2 = [
16524
16456
  /(?:\d+%|score|scored|passing|passed)/i
16525
16457
  ];
16526
16458
  function scanClaimsInOutput(output) {
16527
- if (!output || typeof output !== "string") return;
16459
+ let text = "";
16460
+ if (typeof output === "string") {
16461
+ text = output;
16462
+ } else if (output && typeof output === "object") {
16463
+ const payload = typeof output.message === "object" && output.message ? output.message : output;
16464
+ if (typeof payload.text === "string") text = payload.text;
16465
+ else if (typeof payload.result === "string") text = payload.result;
16466
+ else if (typeof payload.content === "string") text = payload.content;
16467
+ else if (Array.isArray(payload.content)) text = payload.content.filter((p) => p?.type === "text").map((p) => p.text).filter(Boolean).join("\n");
16468
+ else if (Array.isArray(payload.parts)) text = payload.parts.filter((p) => p?.type === "text").map((p) => p.text).filter(Boolean).join("\n");
16469
+ }
16470
+ if (!text) return;
16528
16471
  try {
16529
16472
  const claims = [];
16530
- const lines = String(output).split(String.fromCharCode(10));
16473
+ const lines = String(text).split(String.fromCharCode(10));
16531
16474
  for (let i = 0; i < lines.length; i++) {
16532
- for (const pat of CLAIM_PATTERNS2) {
16475
+ for (const pat of CLAIM_PATTERNS3) {
16533
16476
  if (pat.test(lines[i])) claims.push({ line: i + 1, text: lines[i].trim().substring(0, 120), pattern: pat.source });
16534
16477
  }
16535
16478
  }
16536
16479
  if (claims.length === 0) return;
16537
- const auditDir = join19(getVibeOSHome13(), "cascade-audit");
16480
+ const auditDir = join20(getVibeOSHome13(), "cascade-audit");
16538
16481
  mkdirSync15(auditDir, { recursive: true });
16539
- const auditFile = join19(auditDir, "claim-audit.jsonl");
16482
+ const auditFile = join20(auditDir, "claim-audit.jsonl");
16540
16483
  const entry = JSON.stringify({
16541
16484
  ts: (/* @__PURE__ */ new Date()).toISOString(),
16542
16485
  claims: claims.slice(0, 10),
@@ -16560,18 +16503,18 @@ var _deferredBootstrapDone = false;
16560
16503
  var _skillsEnsured = /* @__PURE__ */ new Set();
16561
16504
  var _runDeferredStartupBootstrap = null;
16562
16505
  function _readOpenCodeConfigObject(dir) {
16563
- const jsonPath = join19(dir, "opencode.json");
16564
- const jsoncPath = join19(dir, "opencode.jsonc");
16506
+ const jsonPath = join20(dir, "opencode.json");
16507
+ const jsoncPath = join20(dir, "opencode.jsonc");
16565
16508
  if (existsSync20(jsonPath))
16566
- return safeJsonParse2(readFileSync18(jsonPath, "utf-8"));
16509
+ return safeJsonParse2(readFileSync19(jsonPath, "utf-8"));
16567
16510
  if (existsSync20(jsoncPath))
16568
- return _parseJsonc(readFileSync18(jsoncPath, "utf-8"));
16511
+ return _parseJsonc(readFileSync19(jsoncPath, "utf-8"));
16569
16512
  return {};
16570
16513
  }
16571
16514
  function _loadOpenCodeProviders(directory3) {
16572
16515
  try {
16573
16516
  const merged = {};
16574
- const dirs = [directory3 ? join19(directory3, ".") : null, getOpenCodeHome()].filter(Boolean);
16517
+ const dirs = [directory3 ? join20(directory3, ".") : null, getOpenCodeHome()].filter(Boolean);
16575
16518
  for (const dir of dirs) {
16576
16519
  const cfg = _readOpenCodeConfigObject(String(dir));
16577
16520
  const providers = cfg?.provider || {};
@@ -16613,13 +16556,13 @@ async function _resolveBootstrapModel(client2, directory3) {
16613
16556
  return { model: "", source: "" };
16614
16557
  }
16615
16558
  function _loadActiveJobForProject(directory3, fp2 = "") {
16616
- const candidates = [getVibeOSHome13(), directory3 ? join19(directory3, "..") : ""].filter(Boolean);
16559
+ const candidates = [getVibeOSHome13(), directory3 ? join20(directory3, "..") : ""].filter(Boolean);
16617
16560
  for (const base of candidates) {
16618
16561
  try {
16619
- const activeJobsPath = join19(String(base), "active-jobs.json");
16562
+ const activeJobsPath = join20(String(base), "active-jobs.json");
16620
16563
  if (!existsSync20(activeJobsPath))
16621
16564
  continue;
16622
- const jobs = safeJsonParse2(readFileSync18(activeJobsPath, "utf-8")) || {};
16565
+ const jobs = safeJsonParse2(readFileSync19(activeJobsPath, "utf-8")) || {};
16623
16566
  const job = fp2 ? jobs?.[fp2] : null;
16624
16567
  if (job && typeof job === "object")
16625
16568
  return job;
@@ -16641,12 +16584,12 @@ async function _seedOrRepairModelTiers(directory3) {
16641
16584
  let existing = null;
16642
16585
  if (existsSync20(TIERS_FILE3)) {
16643
16586
  try {
16644
- const st = statSync10(TIERS_FILE3);
16587
+ const st = statSync9(TIERS_FILE3);
16645
16588
  if (st.size > 10485760) {
16646
16589
  _handleStateCorruption(TIERS_FILE3);
16647
16590
  return false;
16648
16591
  }
16649
- existing = safeJsonParse2(readFileSync18(TIERS_FILE3, "utf-8")) || {};
16592
+ existing = safeJsonParse2(readFileSync19(TIERS_FILE3, "utf-8")) || {};
16650
16593
  } catch {
16651
16594
  existing = null;
16652
16595
  }
@@ -16737,7 +16680,7 @@ function _modelTier2(id2) {
16737
16680
  }
16738
16681
  function readPackageVersion() {
16739
16682
  try {
16740
- const pkg = safeJsonParse2(readFileSync18(join19(process.cwd(), "package.json"), "utf-8"));
16683
+ const pkg = safeJsonParse2(readFileSync19(join20(process.cwd(), "package.json"), "utf-8"));
16741
16684
  return String(pkg?.version || "");
16742
16685
  } catch {
16743
16686
  return "";
@@ -16753,7 +16696,7 @@ function loadMcpPort() {
16753
16696
  }
16754
16697
  try {
16755
16698
  if (existsSync20(getTiersFile())) {
16756
- const tiers = safeJsonParse2(readFileSync18(getTiersFile(), "utf-8"));
16699
+ const tiers = safeJsonParse2(readFileSync19(getTiersFile(), "utf-8"));
16757
16700
  const cfg = tiers?.selection?.mcp_port;
16758
16701
  if (cfg === false || cfg === "disabled" || cfg === 0)
16759
16702
  return 0;
@@ -16769,7 +16712,7 @@ function persistMcpPort(port) {
16769
16712
  try {
16770
16713
  if (!existsSync20(getTiersFile()))
16771
16714
  return;
16772
- const tiers = safeJsonParse2(readFileSync18(getTiersFile(), "utf-8"));
16715
+ const tiers = safeJsonParse2(readFileSync19(getTiersFile(), "utf-8"));
16773
16716
  tiers.selection ??= {};
16774
16717
  if (Number(tiers.selection.mcp_port) === Number(port) && !("mcp_port" in tiers))
16775
16718
  return;
@@ -16833,7 +16776,7 @@ async function ensureMcpServerRunning() {
16833
16776
  selection: loadSelection(),
16834
16777
  tiersData: (() => {
16835
16778
  try {
16836
- return safeJsonParse2(readFileSync18(getTiersFile(), "utf-8"));
16779
+ return safeJsonParse2(readFileSync19(getTiersFile(), "utf-8"));
16837
16780
  } catch {
16838
16781
  return {};
16839
16782
  }
@@ -16849,7 +16792,7 @@ async function ensureMcpServerRunning() {
16849
16792
  optimizationMode: loadSelection()?.optimization_mode || null,
16850
16793
  tiers: (() => {
16851
16794
  try {
16852
- return safeJsonParse2(readFileSync18(getTiersFile(), "utf-8"))?.trinity;
16795
+ return safeJsonParse2(readFileSync19(getTiersFile(), "utf-8"))?.trinity;
16853
16796
  } catch {
16854
16797
  return null;
16855
16798
  }
@@ -17041,7 +16984,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
17041
16984
  if (currentModel) {
17042
16985
  setCurrentTier(classify(currentModel));
17043
16986
  try {
17044
- const _tiersData2 = safeJsonParse2(readFileSync18(getTiersFile(), "utf-8"));
16987
+ const _tiersData2 = safeJsonParse2(readFileSync19(getTiersFile(), "utf-8"));
17045
16988
  const _slotOrder = getTrinitySlotOrder(_tiersData2);
17046
16989
  const _primarySlot = _slotOrder[0] || "brain";
17047
16990
  const _activeSlot = _tiersData2?.selection?.active_slot || _primarySlot;
@@ -17067,7 +17010,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
17067
17010
  const lockedSlot = ["brain", "medium", "cheap"].includes(String(startupSelection.active_slot || "").trim()) ? String(startupSelection.active_slot) : "brain";
17068
17011
  let lockedModel = currentModel || null;
17069
17012
  try {
17070
- const tiers = safeJsonParse2(readFileSync18(getTiersFile(), "utf-8"));
17013
+ const tiers = safeJsonParse2(readFileSync19(getTiersFile(), "utf-8"));
17071
17014
  lockedModel = tiers?.trinity?.[lockedSlot]?.oc || lockedModel || null;
17072
17015
  } catch {
17073
17016
  }
@@ -17100,14 +17043,14 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
17100
17043
  activeJob2 = _loadActiveJobForProject(directory3, fp);
17101
17044
  const systemBriefedProjects = /* @__PURE__ */ new Set();
17102
17045
  const hookVibeHome = getVibeOSHome13();
17103
- const hookStateFile = join19(hookVibeHome, "delegation-state.json");
17104
- const hookProjectStateFile = join19(hookVibeHome, "project-states.json");
17105
- const hookReportsDir = join19(hookVibeHome, "reports");
17106
- const hookReportsIndex = join19(hookReportsDir, "index.json");
17107
- const hookTiersFile = join19(hookVibeHome, "model-tiers.json");
17046
+ const hookStateFile = join20(hookVibeHome, "delegation-state.json");
17047
+ const hookProjectStateFile = join20(hookVibeHome, "project-states.json");
17048
+ const hookReportsDir = join20(hookVibeHome, "reports");
17049
+ const hookReportsIndex = join20(hookReportsDir, "index.json");
17050
+ const hookTiersFile = join20(hookVibeHome, "model-tiers.json");
17108
17051
  const loadProjectStateStable = () => {
17109
17052
  try {
17110
- const state = safeJsonParse2(readFileSync18(hookProjectStateFile, "utf-8"));
17053
+ const state = safeJsonParse2(readFileSync19(hookProjectStateFile, "utf-8"));
17111
17054
  if (state && typeof state === "object") {
17112
17055
  state.project_hashes ??= {};
17113
17056
  return state;
@@ -17127,7 +17070,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
17127
17070
  };
17128
17071
  const reportsIndexStable = () => {
17129
17072
  try {
17130
- const idx = safeJsonParse2(readFileSync18(hookReportsIndex, "utf-8"));
17073
+ const idx = safeJsonParse2(readFileSync19(hookReportsIndex, "utf-8"));
17131
17074
  if (!idx || !Array.isArray(idx.reports))
17132
17075
  return { reports: [] };
17133
17076
  return idx;
@@ -17146,9 +17089,9 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
17146
17089
  try {
17147
17090
  if (!existsSync20(path))
17148
17091
  return null;
17149
- const bkDir = join19(hookVibeHome, ".backups");
17092
+ const bkDir = join20(hookVibeHome, ".backups");
17150
17093
  mkdirSync15(bkDir, { recursive: true });
17151
- const bk = join19(bkDir, `${basename5(path)}.${label}.${Date.now()}.bak`);
17094
+ const bk = join20(bkDir, `${basename5(path)}.${label}.${Date.now()}.bak`);
17152
17095
  copyFileSync2(path, bk);
17153
17096
  return bk;
17154
17097
  } catch {
@@ -17159,7 +17102,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
17159
17102
  };
17160
17103
  const _tiersData = (() => {
17161
17104
  try {
17162
- return safeJsonParse2(readFileSync18(getTiersFile(), "utf-8"));
17105
+ return safeJsonParse2(readFileSync19(getTiersFile(), "utf-8"));
17163
17106
  } catch {
17164
17107
  return {};
17165
17108
  }
@@ -17182,7 +17125,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
17182
17125
  },
17183
17126
  directory: directory3,
17184
17127
  safeJsonParse: safeJsonParse2,
17185
- readFileSync: readFileSync18,
17128
+ readFileSync: readFileSync19,
17186
17129
  writeFileSync: writeFileSync18,
17187
17130
  existsSync: existsSync20,
17188
17131
  renameSync: renameSync6,
@@ -17353,15 +17296,15 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
17353
17296
  setCurrentProjectName(directory3 ? directory3.split("/").pop() : "unknown");
17354
17297
  }
17355
17298
  ensureDeferredBootstrap();
17356
- await _appendFooter(_input, output, directory3);
17357
17299
  scanClaimsInOutput(output);
17300
+ await _appendFooter(_input, output, directory3);
17358
17301
  try {
17359
- const auditDir = join19(getVibeOSHome13(), "cascade-audit");
17360
- const claimFile = join19(auditDir, "claim-audit.jsonl");
17361
- const cascadeFile = join19(auditDir, "cascade-audit.jsonl");
17362
- if (existsSync20(claimFile) && statSync10(claimFile).size > 0) {
17363
- const claimLines = readFileSync18(claimFile, "utf-8").trim().split("\n").slice(-10);
17364
- const cascadeLines = existsSync20(cascadeFile) ? readFileSync18(cascadeFile, "utf-8").trim().split("\n").slice(-30) : [];
17302
+ const auditDir = join20(getVibeOSHome13(), "cascade-audit");
17303
+ const claimFile = join20(auditDir, "claim-audit.jsonl");
17304
+ const cascadeFile = join20(auditDir, "cascade-audit.jsonl");
17305
+ if (existsSync20(claimFile) && statSync9(claimFile).size > 0) {
17306
+ const claimLines = readFileSync19(claimFile, "utf-8").trim().split("\n").slice(-10);
17307
+ const cascadeLines = existsSync20(cascadeFile) ? readFileSync19(cascadeFile, "utf-8").trim().split("\n").slice(-30) : [];
17365
17308
  const cascadeRuns = cascadeLines.filter(Boolean).map((l) => {
17366
17309
  try {
17367
17310
  return JSON.parse(l);
@@ -17381,7 +17324,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
17381
17324
  const claimTexts = (entry.claims || []).map(function(c) {
17382
17325
  return c.text;
17383
17326
  }).join(" | ");
17384
- if (!CLAIM_PATTERNS2.some(function(p) {
17327
+ if (!CLAIM_PATTERNS3.some(function(p) {
17385
17328
  return p.test(claimTexts);
17386
17329
  })) continue;
17387
17330
  let cascadeMatch = false;
@@ -17408,15 +17351,15 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
17408
17351
  setCurrentProjectName(directory3 ? directory3.split("/").pop() : "unknown");
17409
17352
  }
17410
17353
  ensureDeferredBootstrap();
17411
- await _appendFooter(_input, output, directory3);
17412
17354
  scanClaimsInOutput(output);
17355
+ await _appendFooter(_input, output, directory3);
17413
17356
  try {
17414
- const auditDir = join19(getVibeOSHome13(), "cascade-audit");
17415
- const claimFile = join19(auditDir, "claim-audit.jsonl");
17416
- const cascadeFile = join19(auditDir, "cascade-audit.jsonl");
17417
- if (existsSync20(claimFile) && statSync10(claimFile).size > 0) {
17418
- const claimLines = readFileSync18(claimFile, "utf-8").trim().split("\n").slice(-10);
17419
- const cascadeLines = existsSync20(cascadeFile) ? readFileSync18(cascadeFile, "utf-8").trim().split("\n").slice(-30) : [];
17357
+ const auditDir = join20(getVibeOSHome13(), "cascade-audit");
17358
+ const claimFile = join20(auditDir, "claim-audit.jsonl");
17359
+ const cascadeFile = join20(auditDir, "cascade-audit.jsonl");
17360
+ if (existsSync20(claimFile) && statSync9(claimFile).size > 0) {
17361
+ const claimLines = readFileSync19(claimFile, "utf-8").trim().split("\n").slice(-10);
17362
+ const cascadeLines = existsSync20(cascadeFile) ? readFileSync19(cascadeFile, "utf-8").trim().split("\n").slice(-30) : [];
17420
17363
  const cascadeRuns = cascadeLines.filter(Boolean).map((l) => {
17421
17364
  try {
17422
17365
  return JSON.parse(l);
@@ -17436,7 +17379,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
17436
17379
  const claimTexts = (entry.claims || []).map(function(c) {
17437
17380
  return c.text;
17438
17381
  }).join(" | ");
17439
- if (!CLAIM_PATTERNS2.some(function(p) {
17382
+ if (!CLAIM_PATTERNS3.some(function(p) {
17440
17383
  return p.test(claimTexts);
17441
17384
  })) continue;
17442
17385
  let cascadeMatch = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.25.48",
3
+ "version": "0.25.49",
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",