vibeostheog 0.25.40 → 0.25.43
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 +19 -1
- package/dist/assets/dashboard/vibeos-dashboard-config.js +1 -1
- package/dist/vibeOS.js +311 -51
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
|
-
## 0.25.
|
|
1
|
+
## 0.25.43
|
|
2
|
+
- fix: restore general friction detection in semantic observer
|
|
3
|
+
- fix: no cascade override when prompt has media
|
|
4
|
+
- fix: remove vibelitex medium floor that overrides API target (#262)
|
|
5
|
+
- fix: structural claim grammar with auto-verify and auto-amend turn (#261)
|
|
6
|
+
- fix: cascade trigger and claim grammar auto-verify (#260)
|
|
7
|
+
- fix: cascade now fires regardless of API route target, graph prediction respects existing _target (#257)
|
|
8
|
+
- fix: ML trigger cascade now maps brain to TRINITY_BRAIN, lowers override threshold to 0.7, allows graph prediction override (#255)
|
|
9
|
+
- fix: proper env-isolated contract tests for setup.js bin (#254) (#254)
|
|
10
|
+
- fix: remove duplicate prompt - npx is the single permission gate (#253)
|
|
11
|
+
- fix: update usage line to recommend npx -y (#252) (#252)
|
|
12
|
+
- fix: add permission prompt to setup.js + contract tests for install flow (#251) (#251)
|
|
13
|
+
quality-first: default mode is quality, not budget
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## 0.25.42
|
|
17
|
+
- fix: structural claim grammar with auto-verify and auto-amend turn (#261)
|
|
18
|
+
- fix: cascade trigger and claim grammar auto-verify (#260)
|
|
19
|
+
- fix: cascade now fires regardless of API route target, graph prediction respects existing _target (#257)
|
|
2
20
|
- fix: ML trigger cascade now maps brain to TRINITY_BRAIN, lowers override threshold to 0.7, allows graph prediction override (#255)
|
|
3
21
|
- fix: proper env-isolated contract tests for setup.js bin (#254) (#254)
|
|
4
22
|
- fix: remove duplicate prompt - npx is the single permission gate (#253)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:
|
|
1
|
+
window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:58212";
|
package/dist/vibeOS.js
CHANGED
|
@@ -213,6 +213,15 @@ function commandFamily(command) {
|
|
|
213
213
|
const first = c.replace(/^[a-z_][a-z0-9_]*=\S+\s+/g, "").split(/\s+/)[0];
|
|
214
214
|
return /^[a-z0-9._/-]{1,30}$/.test(first) ? first : "command";
|
|
215
215
|
}
|
|
216
|
+
function commandFailed(output) {
|
|
217
|
+
const code = output?.exitCode ?? output?.statusCode ?? output?.code;
|
|
218
|
+
if (Number.isFinite(Number(code)) && Number(code) !== 0)
|
|
219
|
+
return true;
|
|
220
|
+
const raw = output?.result ?? output?.text ?? output?.content ?? output?.data ?? "";
|
|
221
|
+
if (typeof raw !== "string")
|
|
222
|
+
return false;
|
|
223
|
+
return /\b(exit code|exited with code)\s*[:=]?\s*[1-9]\b|\b(assertionerror|syntaxerror|typeerror|referenceerror)\b|\b(failed|error:|err!)\b/i.test(raw);
|
|
224
|
+
}
|
|
216
225
|
function mergeProjectBucket(dst, src) {
|
|
217
226
|
const a = dst || {};
|
|
218
227
|
const b = src || {};
|
|
@@ -5114,7 +5123,7 @@ var init_vibeultrax = __esm({
|
|
|
5114
5123
|
|
|
5115
5124
|
// src/index.ts
|
|
5116
5125
|
init_flow_enforcer();
|
|
5117
|
-
import { readFileSync as readFileSync18, writeFileSync as writeFileSync17, existsSync as
|
|
5126
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync17, existsSync as existsSync20, mkdirSync as mkdirSync15, copyFileSync as copyFileSync2, renameSync as renameSync6, statSync as statSync10 } from "node:fs";
|
|
5118
5127
|
import { join as join19, dirname as dirname13, basename as basename5 } from "node:path";
|
|
5119
5128
|
|
|
5120
5129
|
// src/vibeOS-lib/session-metrics.js
|
|
@@ -11236,7 +11245,7 @@ async function probeModel(modelId, auth, providers = null) {
|
|
|
11236
11245
|
}
|
|
11237
11246
|
|
|
11238
11247
|
// src/lib/hooks/footer.js
|
|
11239
|
-
import { readFileSync as readFileSync15, appendFileSync as appendFileSync5, mkdirSync as mkdirSync12 } from "node:fs";
|
|
11248
|
+
import { readFileSync as readFileSync15, appendFileSync as appendFileSync5, existsSync as existsSync16, mkdirSync as mkdirSync12, statSync as statSync8 } from "node:fs";
|
|
11240
11249
|
import { join as join16 } from "node:path";
|
|
11241
11250
|
|
|
11242
11251
|
// src/lib/hooks/chat-transform.js
|
|
@@ -11244,6 +11253,7 @@ init_state();
|
|
|
11244
11253
|
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";
|
|
11245
11254
|
import { join as join15, dirname as dirname10, basename as basename3 } from "node:path";
|
|
11246
11255
|
import { createHash as createHash3 } from "node:crypto";
|
|
11256
|
+
import { homedir as homedir6 } from "node:os";
|
|
11247
11257
|
|
|
11248
11258
|
// src/lib/mode-policy.js
|
|
11249
11259
|
init_state();
|
|
@@ -11470,7 +11480,8 @@ function deriveTags(input, output) {
|
|
|
11470
11480
|
isGuardBreach: deriveRole(input?.name || "", input, output) === "bypass",
|
|
11471
11481
|
isProtectedTarget: typeof cmd === "string" && targetsProtectedBranch(cmd),
|
|
11472
11482
|
exitCode: output?.exitCode ?? output?.statusCode ?? output?.code ?? null,
|
|
11473
|
-
family: commandFamily(cmd)
|
|
11483
|
+
family: commandFamily(cmd),
|
|
11484
|
+
isFailed: commandFailed(output)
|
|
11474
11485
|
};
|
|
11475
11486
|
}
|
|
11476
11487
|
function getSessionEventLogPath(sid) {
|
|
@@ -11581,6 +11592,43 @@ function detectPatterns(events, fingerprint) {
|
|
|
11581
11592
|
});
|
|
11582
11593
|
}
|
|
11583
11594
|
}
|
|
11595
|
+
const seen = {};
|
|
11596
|
+
for (let i = 0; i < events.length; i++) {
|
|
11597
|
+
const e = events[i];
|
|
11598
|
+
if (!e.isFailed || e.family === "unknown" || e.family === "command")
|
|
11599
|
+
continue;
|
|
11600
|
+
if (i > 0 && events[i - 1].family === e.family && events[i - 1].isFailed) {
|
|
11601
|
+
const key = "friction:repeat-fail:" + e.family;
|
|
11602
|
+
if (!seen[key]) {
|
|
11603
|
+
seen[key] = true;
|
|
11604
|
+
patterns.push({
|
|
11605
|
+
key,
|
|
11606
|
+
summary: e.family + " failed repeatedly \u2014 possible systematic issue.",
|
|
11607
|
+
kind: "friction"
|
|
11608
|
+
});
|
|
11609
|
+
}
|
|
11610
|
+
}
|
|
11611
|
+
}
|
|
11612
|
+
for (let i = 1; i < events.length; i++) {
|
|
11613
|
+
const ver = events[i];
|
|
11614
|
+
if (ver.role !== "verification" || !ver.isFailed)
|
|
11615
|
+
continue;
|
|
11616
|
+
const prev = events[i - 1];
|
|
11617
|
+
if (prev.role !== "mutation")
|
|
11618
|
+
continue;
|
|
11619
|
+
const diff = ver.at - prev.at;
|
|
11620
|
+
if (diff >= 0 && diff <= 3 * 60 * 1e3) {
|
|
11621
|
+
const key = "friction:post-edit-fail:" + ver.family;
|
|
11622
|
+
if (!seen[key]) {
|
|
11623
|
+
seen[key] = true;
|
|
11624
|
+
patterns.push({
|
|
11625
|
+
key,
|
|
11626
|
+
summary: "Edit followed by " + ver.family + " failure \u2014 check your changes.",
|
|
11627
|
+
kind: "friction"
|
|
11628
|
+
});
|
|
11629
|
+
}
|
|
11630
|
+
}
|
|
11631
|
+
}
|
|
11584
11632
|
return patterns;
|
|
11585
11633
|
}
|
|
11586
11634
|
function getCurrentSid() {
|
|
@@ -12616,6 +12664,90 @@ var onMessagesTransform = async (_input, output) => {
|
|
|
12616
12664
|
injectWBP(messages);
|
|
12617
12665
|
applyDecadence();
|
|
12618
12666
|
await trackBlackbox(messages);
|
|
12667
|
+
try {
|
|
12668
|
+
if (!Array.isArray(messages) || Object.isFrozen(messages))
|
|
12669
|
+
return;
|
|
12670
|
+
const vibeHome = process.env.VIBEOS_HOME || join15(process.env.HOME || homedir6(), ".claude");
|
|
12671
|
+
if (typeof vibeHome !== "string" || vibeHome.length === 0)
|
|
12672
|
+
return;
|
|
12673
|
+
const claimFile = join15(vibeHome, "cascade-audit", "claim-audit.jsonl");
|
|
12674
|
+
const cascadeFile = join15(vibeHome, "cascade-audit", "cascade-audit.jsonl");
|
|
12675
|
+
if (!existsSync15(claimFile))
|
|
12676
|
+
return;
|
|
12677
|
+
const st = statSync7(claimFile);
|
|
12678
|
+
if (!st || st.size <= 0)
|
|
12679
|
+
return;
|
|
12680
|
+
const claimRaw = readFileSync14(claimFile, "utf-8");
|
|
12681
|
+
if (!claimRaw || typeof claimRaw !== "string")
|
|
12682
|
+
return;
|
|
12683
|
+
const claimLines = claimRaw.trim().split("\n").filter(Boolean).slice(-5);
|
|
12684
|
+
if (claimLines.length === 0)
|
|
12685
|
+
return;
|
|
12686
|
+
const cascadeRaw = existsSync15(cascadeFile) ? readFileSync14(cascadeFile, "utf-8") : "";
|
|
12687
|
+
const cascadeLines = cascadeRaw && typeof cascadeRaw === "string" ? cascadeRaw.trim().split("\n").filter(Boolean).slice(-20) : [];
|
|
12688
|
+
const cascadeRuns = cascadeLines.map((l) => {
|
|
12689
|
+
try {
|
|
12690
|
+
return JSON.parse(l);
|
|
12691
|
+
} catch {
|
|
12692
|
+
return null;
|
|
12693
|
+
}
|
|
12694
|
+
}).filter(Boolean);
|
|
12695
|
+
const unsubClaims = [];
|
|
12696
|
+
let lastInjectTs = 0;
|
|
12697
|
+
for (let i = messages.length - 1; i >= Math.max(0, messages.length - 4); i--) {
|
|
12698
|
+
const m = messages[i];
|
|
12699
|
+
if (!m || typeof m !== "object")
|
|
12700
|
+
continue;
|
|
12701
|
+
if (m.role === "assistant" && Array.isArray(m.parts)) {
|
|
12702
|
+
for (const p of m.parts) {
|
|
12703
|
+
if (p && typeof p === "object" && p.type === "text" && typeof p.text === "string" && p.text.includes("[verify]")) {
|
|
12704
|
+
lastInjectTs = Date.now();
|
|
12705
|
+
}
|
|
12706
|
+
}
|
|
12707
|
+
}
|
|
12708
|
+
}
|
|
12709
|
+
if (Date.now() - lastInjectTs < 3e4)
|
|
12710
|
+
return;
|
|
12711
|
+
for (const cl of claimLines) {
|
|
12712
|
+
if (!cl.trim())
|
|
12713
|
+
continue;
|
|
12714
|
+
let entry;
|
|
12715
|
+
try {
|
|
12716
|
+
entry = JSON.parse(cl);
|
|
12717
|
+
} catch {
|
|
12718
|
+
continue;
|
|
12719
|
+
}
|
|
12720
|
+
if (!entry || typeof entry !== "object")
|
|
12721
|
+
continue;
|
|
12722
|
+
const claimTexts = (entry.claims || []).filter(Boolean).map((c) => typeof c === "object" && c.text ? c.text : "").filter(Boolean).join(" | ");
|
|
12723
|
+
if (!claimTexts)
|
|
12724
|
+
continue;
|
|
12725
|
+
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))
|
|
12726
|
+
continue;
|
|
12727
|
+
let cascadeMatch = false;
|
|
12728
|
+
for (const cr of cascadeRuns) {
|
|
12729
|
+
const cTs = typeof cr === "object" && cr ? cr._ts || "" : "";
|
|
12730
|
+
if (cTs && entry.ts && Math.abs(new Date(cTs).getTime() - new Date(entry.ts).getTime()) < 12e4) {
|
|
12731
|
+
cascadeMatch = true;
|
|
12732
|
+
break;
|
|
12733
|
+
}
|
|
12734
|
+
}
|
|
12735
|
+
if (!cascadeMatch) {
|
|
12736
|
+
for (const c of entry.claims || []) {
|
|
12737
|
+
if (c && typeof c === "object" && c.text)
|
|
12738
|
+
unsubClaims.push(c.text);
|
|
12739
|
+
}
|
|
12740
|
+
}
|
|
12741
|
+
}
|
|
12742
|
+
if (unsubClaims.length > 0 && !Object.isFrozen(messages)) {
|
|
12743
|
+
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.";
|
|
12744
|
+
try {
|
|
12745
|
+
messages.push({ role: "assistant", parts: [{ type: "text", text: verifyText, synthetic: true }] });
|
|
12746
|
+
} catch {
|
|
12747
|
+
}
|
|
12748
|
+
}
|
|
12749
|
+
} catch {
|
|
12750
|
+
}
|
|
12619
12751
|
} catch (err) {
|
|
12620
12752
|
console.error(`[vibeOS] messages.transform failed: ${err.message}`);
|
|
12621
12753
|
}
|
|
@@ -13429,15 +13561,51 @@ async function _appendFooter(input, output, directory3) {
|
|
|
13429
13561
|
const rawMode = (typeof loadSelection2 === "function" ? loadSelection2()?.requested_optimization_mode || loadSelection2()?.optimization_mode : null) || displayMode;
|
|
13430
13562
|
const cv = computeControlVector2({ sub_regime: currentSubRegime, latest_stress_multiplier: _footerStress, user_text: latestUserIntent || "" }, void 0, rawMode);
|
|
13431
13563
|
const vibeBrand = resolveBrand(loadOptimizationMode() || displayMode, activeSlot);
|
|
13432
|
-
const _cp = [/(?:\u005c|['"](?:done|fixed|validated|works|verified|solved|resolved)['"]|\d+%|score|passed)/i];
|
|
13433
13564
|
let _claimTag = "";
|
|
13434
|
-
|
|
13435
|
-
|
|
13436
|
-
|
|
13437
|
-
|
|
13438
|
-
|
|
13565
|
+
try {
|
|
13566
|
+
const claimAuditFile = join16(VIBEOS_HOME, "cascade-audit", "claim-audit.jsonl");
|
|
13567
|
+
const cascadeAuditFile = join16(VIBEOS_HOME, "cascade-audit", "cascade-audit.jsonl");
|
|
13568
|
+
if (existsSync16(claimAuditFile) && statSync8(claimAuditFile).size > 0) {
|
|
13569
|
+
const claimLines = readFileSync15(claimAuditFile, "utf-8").trim().split("\n").slice(-10);
|
|
13570
|
+
const cascadeLines = existsSync16(cascadeAuditFile) ? readFileSync15(cascadeAuditFile, "utf-8").trim().split("\n").slice(-30) : [];
|
|
13571
|
+
const cascadeRuns = cascadeLines.filter(Boolean).map(function(l) {
|
|
13572
|
+
try {
|
|
13573
|
+
return JSON.parse(l);
|
|
13574
|
+
} catch {
|
|
13575
|
+
}
|
|
13576
|
+
}).filter(Boolean);
|
|
13577
|
+
let unsub = 0;
|
|
13578
|
+
for (const cl of claimLines) {
|
|
13579
|
+
if (!cl.trim())
|
|
13580
|
+
continue;
|
|
13581
|
+
let entry;
|
|
13582
|
+
try {
|
|
13583
|
+
entry = JSON.parse(cl);
|
|
13584
|
+
} catch {
|
|
13585
|
+
continue;
|
|
13586
|
+
}
|
|
13587
|
+
if (!entry)
|
|
13588
|
+
continue;
|
|
13589
|
+
const claimTexts = (entry.claims || []).map(function(c) {
|
|
13590
|
+
return c.text;
|
|
13591
|
+
}).join(" | ");
|
|
13592
|
+
let cascadeMatch = false;
|
|
13593
|
+
for (const cr of cascadeRuns) {
|
|
13594
|
+
const cTs = cr._ts || "";
|
|
13595
|
+
if (cTs && entry.ts && Math.abs(new Date(cTs).getTime() - new Date(entry.ts).getTime()) < 12e4) {
|
|
13596
|
+
cascadeMatch = true;
|
|
13597
|
+
break;
|
|
13598
|
+
}
|
|
13599
|
+
}
|
|
13600
|
+
if (!cascadeMatch)
|
|
13601
|
+
unsub++;
|
|
13439
13602
|
}
|
|
13603
|
+
if (unsub > 0)
|
|
13604
|
+
_claimTag = "\u26A0" + unsub;
|
|
13605
|
+
else
|
|
13606
|
+
_claimTag = "\u2713";
|
|
13440
13607
|
}
|
|
13608
|
+
} catch {
|
|
13441
13609
|
}
|
|
13442
13610
|
const vibeLine = buildFooterLine({
|
|
13443
13611
|
activeSlot,
|
|
@@ -13513,7 +13681,7 @@ ${vibeLine} \u2014`);
|
|
|
13513
13681
|
|
|
13514
13682
|
// src/lib/hooks/tool-execute.js
|
|
13515
13683
|
init_state();
|
|
13516
|
-
import { writeFileSync as writeFileSync16, appendFileSync as appendFileSync7, existsSync as
|
|
13684
|
+
import { writeFileSync as writeFileSync16, appendFileSync as appendFileSync7, existsSync as existsSync18, mkdirSync as mkdirSync14 } from "node:fs";
|
|
13517
13685
|
import { join as join18, dirname as dirname12, basename as basename4 } from "node:path";
|
|
13518
13686
|
import { createHash as createHash5 } from "node:crypto";
|
|
13519
13687
|
init_selection_manager();
|
|
@@ -13583,7 +13751,7 @@ init_smart_cache();
|
|
|
13583
13751
|
|
|
13584
13752
|
// src/lib/tdd-enforcer.js
|
|
13585
13753
|
init_state();
|
|
13586
|
-
import { readFileSync as readFileSync16, writeFileSync as writeFileSync15, appendFileSync as appendFileSync6, existsSync as
|
|
13754
|
+
import { readFileSync as readFileSync16, writeFileSync as writeFileSync15, appendFileSync as appendFileSync6, existsSync as existsSync17, mkdirSync as mkdirSync13, statSync as statSync9, readdirSync as readdirSync4, rmSync as rmSync6, openSync as openSync3 } from "node:fs";
|
|
13587
13755
|
import { join as join17, dirname as dirname11 } from "node:path";
|
|
13588
13756
|
import { createHash as createHash4 } from "node:crypto";
|
|
13589
13757
|
|
|
@@ -14727,7 +14895,7 @@ function _detectTestFramework() {
|
|
|
14727
14895
|
try {
|
|
14728
14896
|
const root = directory || process.cwd();
|
|
14729
14897
|
const pkgPath = join17(root, "package.json");
|
|
14730
|
-
if (
|
|
14898
|
+
if (existsSync17(pkgPath)) {
|
|
14731
14899
|
const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
|
|
14732
14900
|
const testScript = String(pkg?.scripts?.test || "");
|
|
14733
14901
|
const deps = { ...pkg?.devDependencies, ...pkg?.dependencies };
|
|
@@ -14749,7 +14917,7 @@ function _detectTestFramework() {
|
|
|
14749
14917
|
const testDirs = ["src/tests", "tests", "test", "__tests__"];
|
|
14750
14918
|
for (const td of testDirs) {
|
|
14751
14919
|
const dirPath = join17(root, td);
|
|
14752
|
-
if (!
|
|
14920
|
+
if (!existsSync17(dirPath))
|
|
14753
14921
|
continue;
|
|
14754
14922
|
const files = readdirSync4(dirPath).filter((f) => /\.test\./.test(f) || /\.spec\./.test(f));
|
|
14755
14923
|
if (files.length > 0) {
|
|
@@ -14796,7 +14964,7 @@ function _acquireLock(testPath) {
|
|
|
14796
14964
|
if (err.code !== "EEXIST")
|
|
14797
14965
|
return false;
|
|
14798
14966
|
try {
|
|
14799
|
-
const st =
|
|
14967
|
+
const st = statSync9(lockPath);
|
|
14800
14968
|
if (Date.now() - st.mtimeMs >= LOCK_EXPIRE_MS) {
|
|
14801
14969
|
rmSync6(lockPath, { force: true });
|
|
14802
14970
|
try {
|
|
@@ -14823,7 +14991,7 @@ function _releaseLock(testPath) {
|
|
|
14823
14991
|
}
|
|
14824
14992
|
function _isInCooldown(testPath) {
|
|
14825
14993
|
try {
|
|
14826
|
-
if (!
|
|
14994
|
+
if (!existsSync17(ENFORCEMENT_COOLDOWN_FILE2))
|
|
14827
14995
|
return false;
|
|
14828
14996
|
const hash = createHash4("sha256").update(testPath).digest("hex").slice(0, 16);
|
|
14829
14997
|
const lines = readFileSync16(ENFORCEMENT_COOLDOWN_FILE2, "utf-8").trim().split("\n").filter(Boolean);
|
|
@@ -14917,7 +15085,7 @@ function enforceTestFile(filePath) {
|
|
|
14917
15085
|
console.error(`[vibeOS] [tdd-enforce] enforceTestFile called for ${filePath}`);
|
|
14918
15086
|
let sourceContent = "";
|
|
14919
15087
|
try {
|
|
14920
|
-
if (
|
|
15088
|
+
if (existsSync17(filePath)) {
|
|
14921
15089
|
sourceContent = readFileSync16(filePath, "utf-8");
|
|
14922
15090
|
}
|
|
14923
15091
|
} catch {
|
|
@@ -14926,7 +15094,7 @@ function enforceTestFile(filePath) {
|
|
|
14926
15094
|
const skeleton = buildTestSkeleton(filePath, sourceContent, { strict: sel.tdd_strict !== false, quality: sel.tdd_quality !== false });
|
|
14927
15095
|
if (!skeleton)
|
|
14928
15096
|
return null;
|
|
14929
|
-
if (
|
|
15097
|
+
if (existsSync17(skeleton.path))
|
|
14930
15098
|
return null;
|
|
14931
15099
|
if (_enforcementCooldown.has(skeleton.path))
|
|
14932
15100
|
return null;
|
|
@@ -15278,14 +15446,14 @@ ${argsJson}
|
|
|
15278
15446
|
const sessionDir = getSessionScratchpadDir();
|
|
15279
15447
|
const globalDir = SCRATCHPAD_GLOBAL_DIR;
|
|
15280
15448
|
const ptrPath = join18(sessionDir, `${curHash}.ptr`);
|
|
15281
|
-
if (!
|
|
15449
|
+
if (!existsSync18(ptrPath)) {
|
|
15282
15450
|
for (const similar of prediction.similarEntries) {
|
|
15283
15451
|
const targetHash = similar.entry.hash;
|
|
15284
15452
|
if (targetHash.length < 16)
|
|
15285
15453
|
continue;
|
|
15286
15454
|
const cachedFile = join18(sessionDir, `${targetHash}.txt`);
|
|
15287
15455
|
const globalFile = join18(globalDir, `${targetHash}.txt`);
|
|
15288
|
-
if (
|
|
15456
|
+
if (existsSync18(cachedFile) || existsSync18(globalFile)) {
|
|
15289
15457
|
ensureSessionScratchpadDirs();
|
|
15290
15458
|
writeFileSync16(ptrPath, JSON.stringify({
|
|
15291
15459
|
contentHash: targetHash,
|
|
@@ -15346,16 +15514,13 @@ ${argsJson}
|
|
|
15346
15514
|
const _exploratoryTarget = EXPLORATORY.has(_firstWord2) ? TRINITY_CHEAP : null;
|
|
15347
15515
|
const _tierTarget = currentTier === "high" && TRINITY_MEDIUM && TRINITY_MEDIUM !== currentModel ? TRINITY_MEDIUM : TRINITY_CHEAP && TRINITY_CHEAP !== currentModel ? TRINITY_CHEAP : null;
|
|
15348
15516
|
let _target = _exploratoryTarget ?? _tierTarget;
|
|
15517
|
+
const _hasMedia = /\.(png|jpg|jpeg|gif|webp|bmp|svg|mp4|webm|ogg|mp3|wav|avi|mov)/i.test(_prompt);
|
|
15349
15518
|
const stressScore = latestUserIntent ? scoreStress(latestUserIntent) : 0;
|
|
15350
15519
|
const apiRoute = await remoteCall("routeModel", [_prompt, currentTier, TRINITY_CHEAP, TRINITY_MEDIUM, LEARNED_EXPLORATORY, stressScore], null);
|
|
15351
15520
|
if (apiRoute?.target) {
|
|
15352
15521
|
_target = apiRoute.target;
|
|
15353
|
-
|
|
15354
|
-
|
|
15355
|
-
console.error(`[vibeOS] \u{1F500} Task floor: preserving medium tier for high-tier brain task`);
|
|
15356
|
-
}
|
|
15357
|
-
} else if (_target === TRINITY_CHEAP && TRINITY_MEDIUM) {
|
|
15358
|
-
if (stressScore > 0.5) {
|
|
15522
|
+
} else {
|
|
15523
|
+
if (_target === TRINITY_CHEAP && TRINITY_MEDIUM && stressScore > 0.5) {
|
|
15359
15524
|
_target = TRINITY_MEDIUM;
|
|
15360
15525
|
console.error(`[vibeOS] \u{1F9D8} Stress ${stressScore.toFixed(2)} \u2192 preserving medium tier for Task quality`);
|
|
15361
15526
|
}
|
|
@@ -15367,14 +15532,14 @@ ${argsJson}
|
|
|
15367
15532
|
const mlGraphPrediction = predictBestModel(_mlGraph, _firstWord2, currentTier);
|
|
15368
15533
|
if (mlDifficulty.confidence >= ML_CONFIDENCE_THRESHOLD && mlDifficulty.level !== "moderate") {
|
|
15369
15534
|
const mlTarget = mlDifficulty.suggestedTier === "cheap" ? TRINITY_CHEAP : mlDifficulty.suggestedTier === "medium" ? TRINITY_MEDIUM : mlDifficulty.suggestedTier === "brain" ? TRINITY_BRAIN : null;
|
|
15370
|
-
if (mlTarget && mlTarget !==
|
|
15535
|
+
if (mlTarget && mlTarget !== _target) {
|
|
15371
15536
|
const tierRank = { budget: 0, cheap: 1, mid: 2, medium: 2, high: 3, brain: 3 };
|
|
15372
15537
|
const mlRank = tierRank[mlDifficulty.suggestedTier] || 0;
|
|
15373
15538
|
const curRank = _target ? tierRank[classify(_target)] || 0 : 0;
|
|
15374
15539
|
if (!_target) {
|
|
15375
15540
|
_target = mlTarget;
|
|
15376
15541
|
console.error(`[vibeOS] \u{1F9E0} ML difficulty: ${mlDifficulty.level} (score ${mlDifficulty.score.toFixed(2)}, conf ${mlDifficulty.confidence.toFixed(2)}) \u2192 ${mlTarget}`);
|
|
15377
|
-
} else if (mlRank > curRank && mlDifficulty.confidence >= 0.7) {
|
|
15542
|
+
} else if (!_hasMedia && mlRank > curRank && mlDifficulty.confidence >= 0.7) {
|
|
15378
15543
|
_target = mlTarget;
|
|
15379
15544
|
console.error(`[vibeOS] \u{1F9E0} ML upgrade: ${mlDifficulty.level} (score ${mlDifficulty.score.toFixed(2)}, conf ${mlDifficulty.confidence.toFixed(2)}) \u2192 ${mlTarget}`);
|
|
15380
15545
|
}
|
|
@@ -15383,8 +15548,10 @@ ${argsJson}
|
|
|
15383
15548
|
if (mlGraphPrediction && mlGraphPrediction !== currentModel) {
|
|
15384
15549
|
const graphNode = _mlGraph.nodes[_firstWord2];
|
|
15385
15550
|
if (graphNode && graphNode.count >= 3) {
|
|
15386
|
-
_target
|
|
15387
|
-
|
|
15551
|
+
if (!_target) {
|
|
15552
|
+
_target = mlGraphPrediction;
|
|
15553
|
+
console.error(`[vibeOS] \u{1F578} ML graph: ${_firstWord2} \u2192 ${mlGraphPrediction} (${graphNode.count} samples)`);
|
|
15554
|
+
}
|
|
15388
15555
|
}
|
|
15389
15556
|
}
|
|
15390
15557
|
if (_target) {
|
|
@@ -15396,7 +15563,7 @@ ${argsJson}
|
|
|
15396
15563
|
}
|
|
15397
15564
|
}
|
|
15398
15565
|
const activePipeline = loadSelection().active_pipeline;
|
|
15399
|
-
if (
|
|
15566
|
+
if (activePipeline && Array.isArray(activePipeline) && activePipeline.length > 1 && TRINITY_CHEAP && TRINITY_MEDIUM) {
|
|
15400
15567
|
try {
|
|
15401
15568
|
const cheapCost = 1e-3;
|
|
15402
15569
|
const mediumCost = 5e-3;
|
|
@@ -15407,13 +15574,13 @@ ${argsJson}
|
|
|
15407
15574
|
if (cascadeResult.escalate && pipelineModels.length > 1) {
|
|
15408
15575
|
if (pipelineModels.length > 2 && cascadeResult.confidence >= 0.8) {
|
|
15409
15576
|
const escalated = pipelineModels[2];
|
|
15410
|
-
if (escalated && escalated !== currentModel && (!_target || escalated !== _target)) {
|
|
15577
|
+
if (escalated && escalated !== currentModel && !_hasMedia && (!_target || escalated !== _target)) {
|
|
15411
15578
|
_target = escalated;
|
|
15412
15579
|
console.error(`[vibeOS] \u{1F500} Cascade depth-3 escalate: ${cascadeResult.reason} \u2192 ${escalated}`);
|
|
15413
15580
|
}
|
|
15414
15581
|
} else {
|
|
15415
15582
|
const escalated = pipelineModels[1];
|
|
15416
|
-
if (escalated && escalated !== currentModel &&
|
|
15583
|
+
if (escalated && escalated !== currentModel && !_target) {
|
|
15417
15584
|
_target = escalated;
|
|
15418
15585
|
console.error(`[vibeOS] \u{1F500} Cascade escalate: ${cascadeResult.reason} \u2192 ${escalated}`);
|
|
15419
15586
|
}
|
|
@@ -15592,7 +15759,7 @@ ${argsJson}
|
|
|
15592
15759
|
}
|
|
15593
15760
|
} else {
|
|
15594
15761
|
const missed = recordMissedContext7(_estC7);
|
|
15595
|
-
if (!
|
|
15762
|
+
if (!existsSync18(CONTEXT7_INSTALL_FLAG)) {
|
|
15596
15763
|
try {
|
|
15597
15764
|
mkdirSync14(dirname12(CONTEXT7_INSTALL_FLAG), { recursive: true });
|
|
15598
15765
|
writeFileSync16(CONTEXT7_INSTALL_FLAG, "");
|
|
@@ -16035,7 +16202,7 @@ ${pendingUiNote}`;
|
|
|
16035
16202
|
|
|
16036
16203
|
// src/lib/hooks/session-compact.js
|
|
16037
16204
|
init_state();
|
|
16038
|
-
import { readFileSync as readFileSync17, existsSync as
|
|
16205
|
+
import { readFileSync as readFileSync17, existsSync as existsSync19 } from "node:fs";
|
|
16039
16206
|
var onSessionCompacting = async (_input, output) => {
|
|
16040
16207
|
if (!loadSelection().enabled)
|
|
16041
16208
|
return;
|
|
@@ -16044,7 +16211,7 @@ var onSessionCompacting = async (_input, output) => {
|
|
|
16044
16211
|
const needsCompact = turnCount >= 7;
|
|
16045
16212
|
const indexPath = getSessionIndexPath();
|
|
16046
16213
|
let recent = "";
|
|
16047
|
-
if (
|
|
16214
|
+
if (existsSync19(indexPath)) {
|
|
16048
16215
|
try {
|
|
16049
16216
|
const lines = readFileSync17(indexPath, "utf-8").trim().split("\n").slice(-30);
|
|
16050
16217
|
recent = lines.map((l) => {
|
|
@@ -16150,11 +16317,15 @@ function ensureDeferredBootstrap() {
|
|
|
16150
16317
|
}
|
|
16151
16318
|
}
|
|
16152
16319
|
var CLAIM_PATTERNS = [
|
|
16320
|
+
/(?:I|we|the)\s+(?:pushed|released|merged|deployed|fixed|wrote|implemented|completed|committed)\b/i,
|
|
16321
|
+
/(?:tests?|build|CI|checks?|suite|output|result)\s+(?:is\s+|are\s+)?(?:pass(?:ing|ed|es)?|green|clean|succeed|stable|positive)/i,
|
|
16322
|
+
/v\d+\.\d+\.\d+/,
|
|
16323
|
+
/\d+\s*(?:test|spec)s?\s*(?:pass|passing)/i,
|
|
16153
16324
|
/(?:done|finished|complete)/i,
|
|
16154
16325
|
/(?:fixed|resolved|solved)/i,
|
|
16155
|
-
/(?:working|
|
|
16156
|
-
/(?:
|
|
16157
|
-
/(
|
|
16326
|
+
/(?:works|working|validated|verified)/i,
|
|
16327
|
+
/(?:exit\s*code\s*0|0\s*errors|0\s*failures)/i,
|
|
16328
|
+
/(?:\d+%|score|scored|passing|passed)/i
|
|
16158
16329
|
];
|
|
16159
16330
|
function scanClaimsInOutput(output) {
|
|
16160
16331
|
if (!output || typeof output !== "string") return;
|
|
@@ -16175,7 +16346,6 @@ function scanClaimsInOutput(output) {
|
|
|
16175
16346
|
claims: claims.slice(0, 10),
|
|
16176
16347
|
totalClaims: claims.length,
|
|
16177
16348
|
responseHash: ""
|
|
16178
|
-
// crypto hash skipped for performance
|
|
16179
16349
|
});
|
|
16180
16350
|
appendFileSync(auditFile, entry + String.fromCharCode(10));
|
|
16181
16351
|
} catch {
|
|
@@ -16196,9 +16366,9 @@ var _runDeferredStartupBootstrap = null;
|
|
|
16196
16366
|
function _readOpenCodeConfigObject(dir) {
|
|
16197
16367
|
const jsonPath = join19(dir, "opencode.json");
|
|
16198
16368
|
const jsoncPath = join19(dir, "opencode.jsonc");
|
|
16199
|
-
if (
|
|
16369
|
+
if (existsSync20(jsonPath))
|
|
16200
16370
|
return safeJsonParse2(readFileSync18(jsonPath, "utf-8"));
|
|
16201
|
-
if (
|
|
16371
|
+
if (existsSync20(jsoncPath))
|
|
16202
16372
|
return _parseJsonc(readFileSync18(jsoncPath, "utf-8"));
|
|
16203
16373
|
return {};
|
|
16204
16374
|
}
|
|
@@ -16251,7 +16421,7 @@ function _loadActiveJobForProject(directory3, fp2 = "") {
|
|
|
16251
16421
|
for (const base of candidates) {
|
|
16252
16422
|
try {
|
|
16253
16423
|
const activeJobsPath = join19(String(base), "active-jobs.json");
|
|
16254
|
-
if (!
|
|
16424
|
+
if (!existsSync20(activeJobsPath))
|
|
16255
16425
|
continue;
|
|
16256
16426
|
const jobs = safeJsonParse2(readFileSync18(activeJobsPath, "utf-8")) || {};
|
|
16257
16427
|
const job = fp2 ? jobs?.[fp2] : null;
|
|
@@ -16273,9 +16443,9 @@ function _tiersNeedRepair(tiers) {
|
|
|
16273
16443
|
async function _seedOrRepairModelTiers(directory3) {
|
|
16274
16444
|
const TIERS_FILE3 = getTiersFile();
|
|
16275
16445
|
let existing = null;
|
|
16276
|
-
if (
|
|
16446
|
+
if (existsSync20(TIERS_FILE3)) {
|
|
16277
16447
|
try {
|
|
16278
|
-
const st =
|
|
16448
|
+
const st = statSync10(TIERS_FILE3);
|
|
16279
16449
|
if (st.size > 10485760) {
|
|
16280
16450
|
_handleStateCorruption(TIERS_FILE3);
|
|
16281
16451
|
return false;
|
|
@@ -16386,7 +16556,7 @@ function loadMcpPort() {
|
|
|
16386
16556
|
return n;
|
|
16387
16557
|
}
|
|
16388
16558
|
try {
|
|
16389
|
-
if (
|
|
16559
|
+
if (existsSync20(getTiersFile())) {
|
|
16390
16560
|
const tiers = safeJsonParse2(readFileSync18(getTiersFile(), "utf-8"));
|
|
16391
16561
|
const cfg = tiers?.selection?.mcp_port;
|
|
16392
16562
|
if (cfg === false || cfg === "disabled" || cfg === 0)
|
|
@@ -16401,7 +16571,7 @@ function loadMcpPort() {
|
|
|
16401
16571
|
}
|
|
16402
16572
|
function persistMcpPort(port) {
|
|
16403
16573
|
try {
|
|
16404
|
-
if (!
|
|
16574
|
+
if (!existsSync20(getTiersFile()))
|
|
16405
16575
|
return;
|
|
16406
16576
|
const tiers = safeJsonParse2(readFileSync18(getTiersFile(), "utf-8"));
|
|
16407
16577
|
tiers.selection ??= {};
|
|
@@ -16503,7 +16673,7 @@ async function ensureMcpServerRunning() {
|
|
|
16503
16673
|
getSessionMetrics: () => computeSessionMetrics(readFullState(), _OC_SID),
|
|
16504
16674
|
getTodos: () => loadTodos(),
|
|
16505
16675
|
listReports: (filter) => {
|
|
16506
|
-
if (!
|
|
16676
|
+
if (!existsSync20(getReportsDir2())) {
|
|
16507
16677
|
const e = new Error("reports dir not found");
|
|
16508
16678
|
e.status = 404;
|
|
16509
16679
|
throw e;
|
|
@@ -16716,9 +16886,9 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
16716
16886
|
}
|
|
16717
16887
|
} catch {
|
|
16718
16888
|
}
|
|
16719
|
-
console.error(`[vibeOS] auto-config guard: currentModel=${currentModel ? "SET" : "NONE"}, TIERS_FILE=${getTiersFile()}, exists=${
|
|
16889
|
+
console.error(`[vibeOS] auto-config guard: currentModel=${currentModel ? "SET" : "NONE"}, TIERS_FILE=${getTiersFile()}, exists=${existsSync20(getTiersFile())}`);
|
|
16720
16890
|
try {
|
|
16721
|
-
if (!
|
|
16891
|
+
if (!existsSync20(getTiersFile())) {
|
|
16722
16892
|
console.error(`[vibeOS] model-tiers.json missing at load; will seed on first hook`);
|
|
16723
16893
|
}
|
|
16724
16894
|
await _seedOrRepairModelTiers(directory3);
|
|
@@ -16778,7 +16948,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
16778
16948
|
};
|
|
16779
16949
|
const backupFileStable = (path, label) => {
|
|
16780
16950
|
try {
|
|
16781
|
-
if (!
|
|
16951
|
+
if (!existsSync20(path))
|
|
16782
16952
|
return null;
|
|
16783
16953
|
const bkDir = join19(hookVibeHome, ".backups");
|
|
16784
16954
|
mkdirSync15(bkDir, { recursive: true });
|
|
@@ -16818,7 +16988,7 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
16818
16988
|
safeJsonParse: safeJsonParse2,
|
|
16819
16989
|
readFileSync: readFileSync18,
|
|
16820
16990
|
writeFileSync: writeFileSync17,
|
|
16821
|
-
existsSync:
|
|
16991
|
+
existsSync: existsSync20,
|
|
16822
16992
|
renameSync: renameSync6,
|
|
16823
16993
|
mkdirSync: mkdirSync15,
|
|
16824
16994
|
get TIERS_FILE() {
|
|
@@ -16989,6 +17159,51 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
16989
17159
|
ensureDeferredBootstrap();
|
|
16990
17160
|
await _appendFooter(_input, output, directory3);
|
|
16991
17161
|
scanClaimsInOutput(output);
|
|
17162
|
+
try {
|
|
17163
|
+
const auditDir = join19(getVibeOSHome13(), "cascade-audit");
|
|
17164
|
+
const claimFile = join19(auditDir, "claim-audit.jsonl");
|
|
17165
|
+
const cascadeFile = join19(auditDir, "cascade-audit.jsonl");
|
|
17166
|
+
if (existsSync20(claimFile) && statSync10(claimFile).size > 0) {
|
|
17167
|
+
const claimLines = readFileSync18(claimFile, "utf-8").trim().split("\n").slice(-10);
|
|
17168
|
+
const cascadeLines = existsSync20(cascadeFile) ? readFileSync18(cascadeFile, "utf-8").trim().split("\n").slice(-30) : [];
|
|
17169
|
+
const cascadeRuns = cascadeLines.filter(Boolean).map((l) => {
|
|
17170
|
+
try {
|
|
17171
|
+
return JSON.parse(l);
|
|
17172
|
+
} catch {
|
|
17173
|
+
}
|
|
17174
|
+
}).filter(Boolean);
|
|
17175
|
+
let unsub = 0;
|
|
17176
|
+
for (const cl of claimLines) {
|
|
17177
|
+
if (!cl.trim()) continue;
|
|
17178
|
+
let entry;
|
|
17179
|
+
try {
|
|
17180
|
+
entry = JSON.parse(cl);
|
|
17181
|
+
} catch {
|
|
17182
|
+
continue;
|
|
17183
|
+
}
|
|
17184
|
+
if (!entry) continue;
|
|
17185
|
+
const claimTexts = (entry.claims || []).map(function(c) {
|
|
17186
|
+
return c.text;
|
|
17187
|
+
}).join(" | ");
|
|
17188
|
+
if (!CLAIM_PATTERNS.some(function(p) {
|
|
17189
|
+
return p.test(claimTexts);
|
|
17190
|
+
})) continue;
|
|
17191
|
+
let cascadeMatch = false;
|
|
17192
|
+
for (const cr of cascadeRuns) {
|
|
17193
|
+
const cTs = cr._ts || "";
|
|
17194
|
+
if (cTs && entry.ts) {
|
|
17195
|
+
if (Math.abs(new Date(cTs).getTime() - new Date(entry.ts).getTime()) < 12e4) {
|
|
17196
|
+
cascadeMatch = true;
|
|
17197
|
+
break;
|
|
17198
|
+
}
|
|
17199
|
+
}
|
|
17200
|
+
}
|
|
17201
|
+
if (!cascadeMatch) unsub++;
|
|
17202
|
+
}
|
|
17203
|
+
_unsubstantiatedClaims = unsub;
|
|
17204
|
+
}
|
|
17205
|
+
} catch {
|
|
17206
|
+
}
|
|
16992
17207
|
},
|
|
16993
17208
|
"message.updated": async (_input, output) => {
|
|
16994
17209
|
setVibeOSHomeContext(hookVibeHome);
|
|
@@ -16999,6 +17214,51 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
16999
17214
|
ensureDeferredBootstrap();
|
|
17000
17215
|
await _appendFooter(_input, output, directory3);
|
|
17001
17216
|
scanClaimsInOutput(output);
|
|
17217
|
+
try {
|
|
17218
|
+
const auditDir = join19(getVibeOSHome13(), "cascade-audit");
|
|
17219
|
+
const claimFile = join19(auditDir, "claim-audit.jsonl");
|
|
17220
|
+
const cascadeFile = join19(auditDir, "cascade-audit.jsonl");
|
|
17221
|
+
if (existsSync20(claimFile) && statSync10(claimFile).size > 0) {
|
|
17222
|
+
const claimLines = readFileSync18(claimFile, "utf-8").trim().split("\n").slice(-10);
|
|
17223
|
+
const cascadeLines = existsSync20(cascadeFile) ? readFileSync18(cascadeFile, "utf-8").trim().split("\n").slice(-30) : [];
|
|
17224
|
+
const cascadeRuns = cascadeLines.filter(Boolean).map((l) => {
|
|
17225
|
+
try {
|
|
17226
|
+
return JSON.parse(l);
|
|
17227
|
+
} catch {
|
|
17228
|
+
}
|
|
17229
|
+
}).filter(Boolean);
|
|
17230
|
+
let unsub = 0;
|
|
17231
|
+
for (const cl of claimLines) {
|
|
17232
|
+
if (!cl.trim()) continue;
|
|
17233
|
+
let entry;
|
|
17234
|
+
try {
|
|
17235
|
+
entry = JSON.parse(cl);
|
|
17236
|
+
} catch {
|
|
17237
|
+
continue;
|
|
17238
|
+
}
|
|
17239
|
+
if (!entry) continue;
|
|
17240
|
+
const claimTexts = (entry.claims || []).map(function(c) {
|
|
17241
|
+
return c.text;
|
|
17242
|
+
}).join(" | ");
|
|
17243
|
+
if (!CLAIM_PATTERNS.some(function(p) {
|
|
17244
|
+
return p.test(claimTexts);
|
|
17245
|
+
})) continue;
|
|
17246
|
+
let cascadeMatch = false;
|
|
17247
|
+
for (const cr of cascadeRuns) {
|
|
17248
|
+
const cTs = cr._ts || "";
|
|
17249
|
+
if (cTs && entry.ts) {
|
|
17250
|
+
if (Math.abs(new Date(cTs).getTime() - new Date(entry.ts).getTime()) < 12e4) {
|
|
17251
|
+
cascadeMatch = true;
|
|
17252
|
+
break;
|
|
17253
|
+
}
|
|
17254
|
+
}
|
|
17255
|
+
}
|
|
17256
|
+
if (!cascadeMatch) unsub++;
|
|
17257
|
+
}
|
|
17258
|
+
_unsubstantiatedClaims = unsub;
|
|
17259
|
+
}
|
|
17260
|
+
} catch {
|
|
17261
|
+
}
|
|
17002
17262
|
},
|
|
17003
17263
|
tool: {
|
|
17004
17264
|
trinity: tool(createTrinityTool(trinityDeps)),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.43",
|
|
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",
|