vibeostheog 0.18.7 → 0.18.11
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 +3 -0
- package/package.json +1 -1
- package/src/index.js +216 -95
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.11",
|
|
4
4
|
"description": "Cost-aware delegation enforcer for OpenCode. Tracks model usage, routes Task subagents to cheaper tiers, surfaces cumulative savings in chat. Includes research audit, reporting framework, project memory, progressive scratchpad decadence, and trinity CLI for brain/medium/cheap slot switching.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"release": "node scripts/release.mjs",
|
package/src/index.js
CHANGED
|
@@ -385,6 +385,8 @@ var init_flow_enforcer = __esm({
|
|
|
385
385
|
init_flow_enforcer();
|
|
386
386
|
import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, existsSync as existsSync14, mkdirSync as mkdirSync11, copyFileSync as copyFileSync5, renameSync as renameSync6 } from "node:fs";
|
|
387
387
|
import { join as join15, dirname as dirname8, basename as basename8 } from "node:path";
|
|
388
|
+
import { homedir as homedir10 } from "node:os";
|
|
389
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
388
390
|
|
|
389
391
|
// src/vibeOS-lib/session-metrics.js
|
|
390
392
|
function formatDuration(totalSeconds) {
|
|
@@ -1945,18 +1947,47 @@ function scanRecentScratchpad(dir, titleCase, maxScan = 2e3) {
|
|
|
1945
1947
|
if (!existsSync3(dir))
|
|
1946
1948
|
return null;
|
|
1947
1949
|
const entries = readdirSync(dir);
|
|
1950
|
+
const ptrFiles = entries.filter((e) => e.endsWith(".ptr"));
|
|
1951
|
+
const ptrCandidates = [];
|
|
1952
|
+
for (const pf of ptrFiles) {
|
|
1953
|
+
if (ptrCandidates.length >= 50)
|
|
1954
|
+
break;
|
|
1955
|
+
try {
|
|
1956
|
+
const st = statSync3(join3(dir, pf));
|
|
1957
|
+
ptrCandidates.push({ ptrPath: join3(dir, pf), mtimeMs: st.mtimeMs });
|
|
1958
|
+
} catch {
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
ptrCandidates.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
1962
|
+
for (const { ptrPath } of ptrCandidates) {
|
|
1963
|
+
try {
|
|
1964
|
+
const ptrData = safeJsonParse3(readFileSync4(ptrPath, "utf-8"));
|
|
1965
|
+
if (!ptrData?.contentHash)
|
|
1966
|
+
continue;
|
|
1967
|
+
if (titleCase && ptrData.tool && TOOL_NAME_NORMALIZE[ptrData.tool] !== titleCase)
|
|
1968
|
+
continue;
|
|
1969
|
+
const contentHash = ptrData.contentHash;
|
|
1970
|
+
const f = join3(dir, `${contentHash}.txt`);
|
|
1971
|
+
if (!existsSync3(f))
|
|
1972
|
+
continue;
|
|
1973
|
+
const st = statSync3(f);
|
|
1974
|
+
const ageSec = (Date.now() - st.mtimeMs) / 1e3;
|
|
1975
|
+
if (ageSec > SCRATCHPAD_MAX_AGE_SEC)
|
|
1976
|
+
continue;
|
|
1977
|
+
const sumPath = join3(dir, `${contentHash}.summary.txt`);
|
|
1978
|
+
return { hash: contentHash, fullPath: f, sizeBytes: st.size, ageSec: Math.round(ageSec), summaryPath: existsSync3(sumPath) ? sumPath : null };
|
|
1979
|
+
} catch {
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1948
1982
|
const txtFiles = entries.filter((e) => e.endsWith(".txt") && !e.endsWith(".summary.txt"));
|
|
1949
1983
|
if (txtFiles.length === 0)
|
|
1950
1984
|
return null;
|
|
1951
1985
|
const candidateHashes = [];
|
|
1952
1986
|
for (let i = txtFiles.length - 1; i >= 0; i--) {
|
|
1953
1987
|
const f = txtFiles[i];
|
|
1954
|
-
const head = _readHead(join3(dir, f));
|
|
1955
|
-
if (head && head.includes(`[ctx-compressed-v1]`)) {
|
|
1956
|
-
candidateHashes.push(f.replace(/\.txt$/, ""));
|
|
1957
|
-
}
|
|
1958
1988
|
if (candidateHashes.length > 50)
|
|
1959
1989
|
break;
|
|
1990
|
+
candidateHashes.push(f.replace(/\.txt$/, ""));
|
|
1960
1991
|
}
|
|
1961
1992
|
for (const hash of candidateHashes) {
|
|
1962
1993
|
const f = join3(dir, `${hash}.txt`);
|
|
@@ -1988,10 +2019,28 @@ ${inputJson}
|
|
|
1988
2019
|
const globalPath = join3(globalDir, `${hash}.txt`);
|
|
1989
2020
|
let fullPath = existsSync3(sessionPath) ? sessionPath : existsSync3(globalPath) ? globalPath : null;
|
|
1990
2021
|
if (!fullPath) {
|
|
1991
|
-
const
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
2022
|
+
const ptrSessionPath = join3(sessionDir, `${hash}.ptr`);
|
|
2023
|
+
const ptrGlobalPath = join3(globalDir, `${hash}.ptr`);
|
|
2024
|
+
const ptrPath = existsSync3(ptrSessionPath) ? ptrSessionPath : existsSync3(ptrGlobalPath) ? ptrGlobalPath : null;
|
|
2025
|
+
let resolvedHash = hash;
|
|
2026
|
+
if (ptrPath) {
|
|
2027
|
+
try {
|
|
2028
|
+
const ptrData = safeJsonParse3(readFileSync4(ptrPath, "utf-8"));
|
|
2029
|
+
if (ptrData?.contentHash) {
|
|
2030
|
+
resolvedHash = ptrData.contentHash;
|
|
2031
|
+
const rSessionPath = join3(sessionDir, `${resolvedHash}.txt`);
|
|
2032
|
+
const rGlobalPath = join3(globalDir, `${resolvedHash}.txt`);
|
|
2033
|
+
fullPath = existsSync3(rSessionPath) ? rSessionPath : existsSync3(rGlobalPath) ? rGlobalPath : null;
|
|
2034
|
+
}
|
|
2035
|
+
} catch {
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
if (!fullPath) {
|
|
2039
|
+
const recent = scanRecentScratchpad(sessionDir, titleCase, 2e3) || scanRecentScratchpad(globalDir, titleCase, 2e3);
|
|
2040
|
+
if (recent)
|
|
2041
|
+
return recent;
|
|
2042
|
+
return null;
|
|
2043
|
+
}
|
|
1995
2044
|
}
|
|
1996
2045
|
try {
|
|
1997
2046
|
const st = statSync3(fullPath);
|
|
@@ -5569,12 +5618,75 @@ var COMPRESS_MARKER = "[ctx-compressed-v1]";
|
|
|
5569
5618
|
var PROTOCOL_MARKER = "[wbp-v1]";
|
|
5570
5619
|
var PROTOCOL_TEXT = PROTOCOL_MARKER + " [Worker-to-Brain Report Protocol] When synthesizing the preceding Task output: 1) EXTRACT core findings/data. 2) REFORMAT into bullet points. 3) VERIFY against the original ask. 4) SYNTHESIZE into final response.";
|
|
5571
5620
|
|
|
5621
|
+
// src/lib/templates.js
|
|
5622
|
+
var TEMPLATES = {
|
|
5623
|
+
save: {
|
|
5624
|
+
tier_bias: "cheap",
|
|
5625
|
+
thinking_mode: "off",
|
|
5626
|
+
enforcement_mode: "relaxed",
|
|
5627
|
+
flow_mode: "audit",
|
|
5628
|
+
tdd_mode: "lazy",
|
|
5629
|
+
context7_urgency: "required",
|
|
5630
|
+
wbp_verbosity: "minimal",
|
|
5631
|
+
agent_mode: "auto",
|
|
5632
|
+
directive: "[SAVE mode] Cost efficiency. Minimize token usage. Combine independent tool calls with && or ;. Prefer context7 over WebSearch/WebFetch for docs. Skip unnecessary verification. Batch parallel Task subagents."
|
|
5633
|
+
},
|
|
5634
|
+
quality: {
|
|
5635
|
+
tier_bias: "brain",
|
|
5636
|
+
thinking_mode: "full",
|
|
5637
|
+
enforcement_mode: "strict",
|
|
5638
|
+
flow_mode: "strict",
|
|
5639
|
+
tdd_mode: "save",
|
|
5640
|
+
context7_urgency: "preferred",
|
|
5641
|
+
wbp_verbosity: "verbose",
|
|
5642
|
+
agent_mode: "plan",
|
|
5643
|
+
directive: "[QUALITY mode] High quality output. Full verification of all results. Production-grade code. Write tests covering all paths and edge cases. Validate outputs before presenting. Do not cut corners."
|
|
5644
|
+
},
|
|
5645
|
+
security: {
|
|
5646
|
+
tier_bias: "brain",
|
|
5647
|
+
thinking_mode: "brief",
|
|
5648
|
+
enforcement_mode: "strict",
|
|
5649
|
+
flow_mode: "strict",
|
|
5650
|
+
tdd_mode: "quality",
|
|
5651
|
+
context7_urgency: "preferred",
|
|
5652
|
+
wbp_verbosity: "normal",
|
|
5653
|
+
agent_mode: "plan",
|
|
5654
|
+
directive: "[SECURITY mode] Defense-in-depth. Define the threat model before writing code. Validate all inputs. Never expose secrets or credentials. Verify each defense handles its threat. Consider: injection, broken auth, data exposure, logic errors, race conditions."
|
|
5655
|
+
}
|
|
5656
|
+
};
|
|
5657
|
+
var DEFAULT_TEMPLATE = "quality";
|
|
5658
|
+
function detectBudgetSignal(creditPercent) {
|
|
5659
|
+
return creditPercent < 40;
|
|
5660
|
+
}
|
|
5661
|
+
var _prevStress = 0;
|
|
5662
|
+
function detectStressSpike(stressScore) {
|
|
5663
|
+
var delta = stressScore - _prevStress;
|
|
5664
|
+
_prevStress = stressScore;
|
|
5665
|
+
return delta > 0.3 && stressScore > 0.5;
|
|
5666
|
+
}
|
|
5667
|
+
function resolveTemplate(prevTemplate, stressScore, userText, creditPercent) {
|
|
5668
|
+
if (detectBudgetSignal(creditPercent)) return "save";
|
|
5669
|
+
if (detectStressSpike(stressScore)) return "quality";
|
|
5670
|
+
return prevTemplate || DEFAULT_TEMPLATE;
|
|
5671
|
+
}
|
|
5672
|
+
var _turnCount = 0;
|
|
5673
|
+
function shouldInjectTemplate(template, prevTemplate) {
|
|
5674
|
+
_turnCount++;
|
|
5675
|
+
if (template !== prevTemplate) return true;
|
|
5676
|
+
if (_turnCount % 10 === 0) return true;
|
|
5677
|
+
return false;
|
|
5678
|
+
}
|
|
5679
|
+
|
|
5572
5680
|
// src/lib/hooks/chat-transform.js
|
|
5573
5681
|
var latestUserIntent = null;
|
|
5574
5682
|
var _OC_SID4 = "opencode-" + (process.pid || "x") + "-" + Date.now();
|
|
5575
5683
|
var _latestBlackboxState3 = null;
|
|
5576
5684
|
var _latestBlackboxLoopMsg2 = null;
|
|
5577
5685
|
var _latestBlackboxPivotMsg2 = null;
|
|
5686
|
+
var _prevBlackboxRegime = null;
|
|
5687
|
+
var _currentTemplate = DEFAULT_TEMPLATE;
|
|
5688
|
+
var _prevTemplate = null;
|
|
5689
|
+
var _turnCountInject = 0;
|
|
5578
5690
|
var correctionSeenKeys = /* @__PURE__ */ new Set();
|
|
5579
5691
|
async function apiComputeControlVector(state, action, optimizationMode) {
|
|
5580
5692
|
try {
|
|
@@ -5846,6 +5958,18 @@ ${raw}
|
|
|
5846
5958
|
if (!existsSync10(fullPath)) {
|
|
5847
5959
|
writeFileSync9(fullPath, raw);
|
|
5848
5960
|
indexAppend(hash, part.tool, raw.length);
|
|
5961
|
+
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");
|
|
5962
|
+
if (invPart?.state?.input) {
|
|
5963
|
+
const toolKey = TOOL_NAME_NORMALIZE[part.tool] || part.tool;
|
|
5964
|
+
const inputHash = createHash3("sha256").update(`${toolKey}
|
|
5965
|
+
${stableJson(invPart.state.input)}
|
|
5966
|
+
`).digest("hex").slice(0, 16);
|
|
5967
|
+
const ptrPath = join12(getSessionScratchpadDir(), `${inputHash}.ptr`);
|
|
5968
|
+
try {
|
|
5969
|
+
writeFileSync9(ptrPath, JSON.stringify({ contentHash: hash, tool: part.tool }));
|
|
5970
|
+
} catch {
|
|
5971
|
+
}
|
|
5972
|
+
}
|
|
5849
5973
|
}
|
|
5850
5974
|
} catch (err) {
|
|
5851
5975
|
console.error(`[vibeOS] ctx-compress write failed: ${err.message}`);
|
|
@@ -5959,36 +6083,6 @@ function thinkingDirective(level) {
|
|
|
5959
6083
|
}
|
|
5960
6084
|
return `[thinking policy] Reasoning depth: OFF (manually set, ${creditNote}). Skip extended thinking entirely. Respond directly and concisely. Every thinking token costs money -- save it for when the user explicitly asks.`;
|
|
5961
6085
|
}
|
|
5962
|
-
function orchestratorDirective(cv, sel) {
|
|
5963
|
-
const tierBias = cv?.tier_bias || "auto";
|
|
5964
|
-
let brainModel = "(brain)";
|
|
5965
|
-
try {
|
|
5966
|
-
brainModel = safeJsonParse3(readFileSync11(TIERS_FILE2, "utf-8")).trinity?.brain?.oc || brainModel;
|
|
5967
|
-
} catch {
|
|
5968
|
-
}
|
|
5969
|
-
const cheapModel = TRINITY_CHEAP || "the cheaper model";
|
|
5970
|
-
const mediumModel = TRINITY_MEDIUM || "the medium model";
|
|
5971
|
-
const targetModel = tierBias === "cheap" ? cheapModel : tierBias === "medium" ? mediumModel : tierBias === "brain" ? brainModel : `${cheapModel} or ${mediumModel}`;
|
|
5972
|
-
return `[AI ORCHESTRATOR AGENT] You are an AI orchestrator agent. Delegate heavy work to Task subagents (runs on ${targetModel}). Your role: verify, fill gaps, synthesize. CRITICAL: Write/Edit tools are BLOCKED on this tier. You MUST delegate ALL implementation work to Task subagents. Always display the vibeOS cost footer.` + (tierBias !== "auto" ? ` [tier routing] This turn is biased toward ${tierBias} tier.` : "");
|
|
5973
|
-
}
|
|
5974
|
-
var TDD_NOTES = {
|
|
5975
|
-
lazy: " Skeletons only when explicitly requested.",
|
|
5976
|
-
strict: " STRICT mode: TODO tests MUST pass before considering work complete.",
|
|
5977
|
-
quality: " QUALITY mode: Full coverage including edge cases."
|
|
5978
|
-
};
|
|
5979
|
-
function tddDirective(cv, sel) {
|
|
5980
|
-
const tddMode = cv?.tdd_mode || (sel.tdd_strict ? "strict" : "normal");
|
|
5981
|
-
const tddFocus = cv?.tdd_focus || [];
|
|
5982
|
-
const focusNote = tddFocus.length > 0 ? ` Focus: ${tddFocus.join(", ")}.` : "";
|
|
5983
|
-
return `[tdd enforcement: ${tddMode}] Auto-create skeleton tests for source files being written/edited.${TDD_NOTES[tddMode] || ""}${focusNote} When creating or modifying source files, ensure corresponding test files exist with proper assertions.`;
|
|
5984
|
-
}
|
|
5985
|
-
function flowDirective(cv, sel) {
|
|
5986
|
-
const flowMode = cv?.flow_mode || (sel.flow_enforce ? "normal" : "audit");
|
|
5987
|
-
const flowFocus = cv?.flow_focus || [];
|
|
5988
|
-
const enforceNote = sel.flow_enforce ? " TODO/FIXME extraction is active." : "";
|
|
5989
|
-
const focusNote = flowFocus.length > 0 ? ` Focus rules: ${flowFocus.join(", ")}.` : "";
|
|
5990
|
-
return `[flow enforcement: ${flowMode}] Development flow rules are active: write/edit operations are checked against project conventions.${enforceNote}${focusNote} Follow existing code patterns, naming conventions, and project structure.`;
|
|
5991
|
-
}
|
|
5992
6086
|
function flowTodosDirective() {
|
|
5993
6087
|
const pendingTodos = loadTodos().filter((t) => t.status === "pending").length;
|
|
5994
6088
|
if (pendingTodos === 0)
|
|
@@ -6060,83 +6154,88 @@ var onSystemTransform = async (_input, output) => {
|
|
|
6060
6154
|
const sel = loadSelection();
|
|
6061
6155
|
const fp2 = currentProjectFingerprint || "";
|
|
6062
6156
|
const stressScore = latestUserIntent ? scoreStress(latestUserIntent) * (_controlVector?.stress_multiplier ?? 1) : 0;
|
|
6157
|
+
const credit = loadCredit();
|
|
6158
|
+
_turnCountInject++;
|
|
6159
|
+
_prevTemplate = _currentTemplate;
|
|
6160
|
+
_currentTemplate = resolveTemplate(_prevTemplate, stressScore, latestUserIntent, credit);
|
|
6161
|
+
if (_currentTemplate !== loadOptimizationMode()) {
|
|
6162
|
+
saveOptimizationMode(_currentTemplate);
|
|
6163
|
+
}
|
|
6164
|
+
if (shouldInjectTemplate(_currentTemplate, _prevTemplate)) {
|
|
6165
|
+
const tpl = TEMPLATES[_currentTemplate] || TEMPLATES[DEFAULT_TEMPLATE];
|
|
6166
|
+
let fused = tpl.directive;
|
|
6167
|
+
if (sel.delegation_enforce && _controlVector?.enforcement_mode !== "relaxed") {
|
|
6168
|
+
fused += " CRITICAL: Write/Edit tools are BLOCKED on brain tier. Delegate ALL implementation to Task subagents. Use parallel invocation for independent tasks.";
|
|
6169
|
+
}
|
|
6170
|
+
if (sel.tdd_enforce && _controlVector?.tdd_mode !== "lazy") {
|
|
6171
|
+
fused += " Auto-create test skeletons for changed source files.";
|
|
6172
|
+
}
|
|
6173
|
+
if (sel.flow_enabled && _controlVector?.flow_mode !== "audit") {
|
|
6174
|
+
fused += " Follow existing code conventions and project patterns.";
|
|
6175
|
+
}
|
|
6176
|
+
pushSystem(output, fused);
|
|
6177
|
+
}
|
|
6063
6178
|
pushSystem(output, context7Directive(_controlVector));
|
|
6064
6179
|
if (sel.thinking_level && sel.thinking_level !== "full") {
|
|
6065
6180
|
pushSystem(output, thinkingDirective(sel.thinking_level));
|
|
6066
6181
|
}
|
|
6067
|
-
if (stressScore > 0.7) {
|
|
6068
|
-
pushSystem(output, "[stress mitigation: CRITICAL] The user's message shows very high stress indicators. Stay calm, structured, and thorough. Use proper markdown formatting with code blocks, lists, and organized structure
|
|
6069
|
-
} else if (stressScore > 0.4) {
|
|
6070
|
-
pushSystem(output, "[stress mitigation: elevated] The user's message has elevated stress indicators. Maintain structured, well-formatted responses with markdown and code blocks
|
|
6182
|
+
if (stressScore > 0.7 && detectStressSpike(stressScore)) {
|
|
6183
|
+
pushSystem(output, "[stress mitigation: CRITICAL] The user's message shows very high stress indicators. Stay calm, structured, and thorough. Use proper markdown formatting with code blocks, lists, and organized structure. Do NOT mirror the user's tone or brevity. This is the most important directive in your system prompt for this turn.");
|
|
6184
|
+
} else if (stressScore > 0.4 && detectStressSpike(stressScore)) {
|
|
6185
|
+
pushSystem(output, "[stress mitigation: elevated] The user's message has elevated stress indicators. Maintain structured, well-formatted responses with markdown and code blocks.");
|
|
6071
6186
|
}
|
|
6072
6187
|
if (_controlVector?.directives?.length > 0) {
|
|
6073
6188
|
for (const directive of _controlVector.directives) {
|
|
6074
6189
|
pushSystem(output, directive);
|
|
6075
6190
|
}
|
|
6076
6191
|
} else if (_blackboxEnabled && _latestBlackboxState3?.n_interactions > 0) {
|
|
6192
|
+
const prevRegime = _prevBlackboxRegime;
|
|
6077
6193
|
const res = _latestBlackboxState3;
|
|
6078
|
-
|
|
6079
|
-
if (
|
|
6080
|
-
|
|
6081
|
-
pushSystem(output,
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6194
|
+
const currentRegime = res.sub_regime || "EXPLORING";
|
|
6195
|
+
if (currentRegime !== prevRegime) {
|
|
6196
|
+
_prevBlackboxRegime = currentRegime;
|
|
6197
|
+
pushSystem(output, "[decision engine] Resolution: " + (res.resolution || "unresolved") + " (" + currentRegime + "). Momentum: " + ((res.momentum || 0) > 0 ? "positive" : (res.momentum || 0) < 0 ? "negative" : "neutral") + ".");
|
|
6198
|
+
if (res.is_looping && res.loop_intervention_level && res.loop_intervention_level !== "none") {
|
|
6199
|
+
const severity = res.loop_intervention_level === "escalated" ? "CRITICAL" : res.loop_intervention_level === "assertive" ? "WARNING" : "NOTICE";
|
|
6200
|
+
pushSystem(output, "[loop prevention: " + severity + "] " + (_latestBlackboxLoopMsg2 || "The conversation may be looping \u2014 try a different approach.") + " (level: " + res.loop_intervention_level + ")");
|
|
6201
|
+
}
|
|
6202
|
+
if (res.pivot_detected && _latestBlackboxPivotMsg2) {
|
|
6203
|
+
pushSystem(output, "[context switch: PIVOT] " + _latestBlackboxPivotMsg2);
|
|
6204
|
+
}
|
|
6085
6205
|
}
|
|
6086
6206
|
}
|
|
6087
|
-
const
|
|
6088
|
-
if (latestUserIntent &&
|
|
6089
|
-
pushSystem(output,
|
|
6207
|
+
const projectJob2 = getActiveJobForProject();
|
|
6208
|
+
if (latestUserIntent && projectJob2 && isLikelyOffTopic(latestUserIntent, projectJob2)) {
|
|
6209
|
+
pushSystem(output, '[job-focus] Active job context exists: "' + (projectJob2.prompt || "").slice(0, 140) + '...". The latest user request appears off-topic relative to this running job. Before taking write/edit/task actions, ask one concise confirmation question to validate switching scope.');
|
|
6090
6210
|
console.error("[vibeOS] [job-focus] off-topic request detected vs active job context");
|
|
6091
6211
|
}
|
|
6092
|
-
if (sel.
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
if (_controlVector?.enforcement_mode !== "relaxed" && _controlVector?.agent_mode !== "plan") {
|
|
6096
|
-
pushSystem(output, "[batch execution] When you need to run multiple independent Task subagent calls, invoke them ALL in parallel rather than sequentially. Parallel tasks complete faster and reduce total session cost. Only sequence tasks when one depends on the output of another.");
|
|
6212
|
+
if (sel.flow_enabled && sel.flow_enforce) {
|
|
6213
|
+
const todoDirective = flowTodosDirective();
|
|
6214
|
+
if (todoDirective) pushSystem(output, todoDirective);
|
|
6097
6215
|
}
|
|
6098
|
-
if (
|
|
6099
|
-
pushSystem(output,
|
|
6216
|
+
if (_turnCountInject % 5 === 0) {
|
|
6217
|
+
pushSystem(output, "[project guard: CRITICAL] AGENTS.md and README.md are protected by vibeOS. Do NOT modify either file without explicit user permission. AGENTS.md defines that AI agents must ask before changing code.");
|
|
6100
6218
|
}
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
if (sel.flow_enforce) {
|
|
6104
|
-
pushSystem(output, flowTodosDirective());
|
|
6105
|
-
}
|
|
6106
|
-
}
|
|
6107
|
-
pushSystem(output, "[project guard: CRITICAL] AGENTS.md and README.md are protected by vibeOS. Do NOT modify either file without explicit user permission. When implementing new features, update README.md to document them. AGENTS.md defines that AI agents must ask before changing code -- respect this rule.");
|
|
6108
|
-
const currentMode = loadOptimizationMode();
|
|
6109
|
-
if (currentMode === "quality") {
|
|
6110
|
-
pushSystem(output, "[mode: quality] Prioritize quality and thoroughness. Provide complete edge case coverage, comprehensive error handling, full type annotations, production-grade code with tests. Do not cut corners for brevity.");
|
|
6111
|
-
} else if (currentMode === "forensic") {
|
|
6112
|
-
pushSystem(output, "[mode: forensic] Use forensic analysis depth: evidence-based reasoning tracing each claim to source; multi-hypothesis evaluation considering competing explanations; explicit uncertainty flags for assumptions and trade-offs; structured output with clear reasoning traces; thorough verification of all edge cases and failure modes.");
|
|
6113
|
-
} else if (currentMode === "web-research" || currentMode === "exploration") {
|
|
6114
|
-
pushSystem(output, "[mode: exploration] Use a research-oriented approach: gather information from multiple perspectives before converging; document alternative approaches; flag confidence levels for each finding; synthesize into actionable recommendations.");
|
|
6115
|
-
} else if (currentMode === "defense_in_depth") {
|
|
6116
|
-
pushSystem(output, "[mode: defense in depth] For every component: define the threat model, implement with defenses, then verify the defense handles the threat. Never write code without specifying what it defends against. Consider: injection, broken auth, data exposure, logic errors, race conditions.");
|
|
6117
|
-
} else if (currentMode === "reporting") {
|
|
6118
|
-
pushSystem(output, "[mode: formal report] Structure output as a formal engineering report with: executive summary, methodology, detailed findings with evidence, trade-offs documented, conclusions with confidence levels, and recommendations.");
|
|
6119
|
-
} else if (currentMode === "verify") {
|
|
6120
|
-
pushSystem(output, "[mode: verification-first] Before writing code, declare verification criteria: which edge cases must pass, what invariants must hold. After each code block, include a verification section showing how correctness is established against each criterion.");
|
|
6121
|
-
}
|
|
6122
|
-
pushSystem(output, contextBudgetDirective(_input, output));
|
|
6219
|
+
const budgetDirective = contextBudgetDirective(_input, output);
|
|
6220
|
+
if (budgetDirective) pushSystem(output, budgetDirective);
|
|
6123
6221
|
if (!oneShot(fp2)) {
|
|
6124
6222
|
pushSystem(output, buildProjectBriefing(currentProjectName || ""));
|
|
6125
6223
|
}
|
|
6126
6224
|
if (!oneShot("vibeos_patterns_" + fp2)) {
|
|
6127
|
-
|
|
6225
|
+
const pd = patternDirective(fp2);
|
|
6226
|
+
if (pd) pushSystem(output, pd);
|
|
6128
6227
|
}
|
|
6129
6228
|
if (!oneShot("trinity_welcome_" + fp2)) {
|
|
6130
6229
|
pushSystem(output, welcomeDirective());
|
|
6131
6230
|
}
|
|
6132
6231
|
const calDir = join12(homedir8(), ".claude");
|
|
6133
6232
|
const calFile = join12(calDir, "calibration-data.jsonl");
|
|
6134
|
-
const
|
|
6233
|
+
const regime2 = _latestBlackboxState3?.sub_regime || classifyTurnSimple(latestUserIntent || "");
|
|
6135
6234
|
const calRecord = JSON.stringify({
|
|
6136
6235
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6137
6236
|
sid: _OC_SID4,
|
|
6138
|
-
mode:
|
|
6139
|
-
regime,
|
|
6237
|
+
mode: _currentTemplate,
|
|
6238
|
+
regime: regime2,
|
|
6140
6239
|
stress: stressScore,
|
|
6141
6240
|
fp: currentProjectFingerprint || ""
|
|
6142
6241
|
}) + "\n";
|
|
@@ -6149,7 +6248,7 @@ var onSystemTransform = async (_input, output) => {
|
|
|
6149
6248
|
pushSystem(output, "[vibeOS dashboard display] When the trinity tool returns output starting with '[vibeOS-dashboard]', you MUST use the question tool to display that data in a clean, human-readable format. Use the question field (not the header) to show the dashboard data. Format it with clear sections separated by blank lines, aligned columns with spaces, and plain text only (no emojis, no markdown). The header should be 'vibeOS Dashboard'. Include only one option in options: {label: 'Dismiss', description: ''}. Strip the '[vibeOS-dashboard]' marker line before displaying.");
|
|
6150
6249
|
}
|
|
6151
6250
|
if (!oneShot("vibeos_dopamine_style_" + fp2)) {
|
|
6152
|
-
pushSystem(output, "[tool style: dopamine] When calling the bash tool, use an emoji-prefixed, progress-focused description
|
|
6251
|
+
pushSystem(output, "[tool style: dopamine] When calling the bash tool, use an emoji-prefixed, progress-focused description. Combine independent bash commands into a single call with && or ;. Never use raw technical labels as tool descriptions.");
|
|
6153
6252
|
}
|
|
6154
6253
|
} catch (err) {
|
|
6155
6254
|
console.error(`[vibeOS] system.transform failed: ${err.message}`);
|
|
@@ -7806,7 +7905,7 @@ var onToolExecuteBefore = async (input, output) => {
|
|
|
7806
7905
|
const hit = getScratchpadHit(t, args);
|
|
7807
7906
|
if (hit && !scratchpadHitsSeen2.has(hit.hash)) {
|
|
7808
7907
|
scratchpadHitsSeen2.add(hit.hash);
|
|
7809
|
-
const total = recordScratchpadObservation();
|
|
7908
|
+
const total = recordScratchpadObservation(t, args, hit.sizeBytes, { hash: hit.hash });
|
|
7810
7909
|
const _inputTokens = Math.max(1, Math.round(hit.sizeBytes / BYTES_PER_TOKEN));
|
|
7811
7910
|
_cacheSave = Math.max(1e-4, Math.round(_inputTokens * CACHE_SAVED_PER_1M_INPUT_TOKENS / 1e6 * 1e4) / 1e4);
|
|
7812
7911
|
const cacheSaved = recordCacheSaving(t, _cacheSave, { hash: hit.hash });
|
|
@@ -8504,28 +8603,29 @@ function loadMcpPort() {
|
|
|
8504
8603
|
const envPort = process.env.VIBEOS_MCP_PORT;
|
|
8505
8604
|
if (envPort != null && envPort !== "") {
|
|
8506
8605
|
const n = Number(envPort);
|
|
8507
|
-
if (!Number.isFinite(n)) return
|
|
8606
|
+
if (!Number.isFinite(n)) return 0;
|
|
8508
8607
|
return n;
|
|
8509
8608
|
}
|
|
8510
8609
|
try {
|
|
8511
8610
|
if (existsSync14(TIERS_FILE2)) {
|
|
8512
8611
|
const tiers = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
8513
|
-
const cfg = tiers?.selection?.mcp_port
|
|
8612
|
+
const cfg = tiers?.selection?.mcp_port;
|
|
8514
8613
|
if (cfg === false || cfg === "disabled" || cfg === 0) return 0;
|
|
8515
8614
|
const n = Number(cfg);
|
|
8516
8615
|
if (Number.isFinite(n)) return n;
|
|
8517
8616
|
}
|
|
8518
8617
|
} catch {
|
|
8519
8618
|
}
|
|
8520
|
-
return
|
|
8619
|
+
return 0;
|
|
8521
8620
|
}
|
|
8522
8621
|
function persistMcpPort(port) {
|
|
8523
8622
|
try {
|
|
8524
8623
|
if (!existsSync14(TIERS_FILE2)) return;
|
|
8525
8624
|
const tiers = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
8526
8625
|
tiers.selection ??= {};
|
|
8527
|
-
if (Number(tiers.selection.mcp_port) === Number(port)) return;
|
|
8626
|
+
if (Number(tiers.selection.mcp_port) === Number(port) && !("mcp_port" in tiers)) return;
|
|
8528
8627
|
tiers.selection.mcp_port = port;
|
|
8628
|
+
if ("mcp_port" in tiers) delete tiers.mcp_port;
|
|
8529
8629
|
mkdirSync11(dirname8(TIERS_FILE2), { recursive: true });
|
|
8530
8630
|
const tmp = TIERS_FILE2 + ".tmp." + Date.now();
|
|
8531
8631
|
writeFileSync12(tmp, JSON.stringify(tiers, null, 2) + "\n", "utf-8");
|
|
@@ -8795,7 +8895,9 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
8795
8895
|
}
|
|
8796
8896
|
if (_tiersData2) {
|
|
8797
8897
|
_tiersData2.selection ??= {};
|
|
8798
|
-
|
|
8898
|
+
for (const _sk of ["mcp_port", "optimization_mode", "enforcement_enabled", "flow_enforce_level", "tdd_quality", "thinking_mode", "blackbox_regime", "_mode_changed_at", "_mode_source"]) {
|
|
8899
|
+
if (_sk in _tiersData2) delete _tiersData2[_sk];
|
|
8900
|
+
}
|
|
8799
8901
|
mkdirSync11(dirname8(TIERS_FILE2), { recursive: true });
|
|
8800
8902
|
const _tmp = TIERS_FILE2 + ".tmp." + Date.now();
|
|
8801
8903
|
writeFileSync12(_tmp, JSON.stringify(_tiersData2, null, 2) + "\n", "utf-8");
|
|
@@ -8819,8 +8921,14 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
8819
8921
|
}
|
|
8820
8922
|
try {
|
|
8821
8923
|
const _mt = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
8822
|
-
|
|
8823
|
-
|
|
8924
|
+
let _dirty = false;
|
|
8925
|
+
for (const _sk of ["mcp_port", "optimization_mode", "enforcement_enabled", "flow_enforce_level", "tdd_quality", "thinking_mode", "blackbox_regime", "_mode_changed_at", "_mode_source"]) {
|
|
8926
|
+
if (_sk in _mt) {
|
|
8927
|
+
delete _mt[_sk];
|
|
8928
|
+
_dirty = true;
|
|
8929
|
+
}
|
|
8930
|
+
}
|
|
8931
|
+
if (_dirty) {
|
|
8824
8932
|
const _tmp = TIERS_FILE2 + ".tmp." + Date.now();
|
|
8825
8933
|
writeFileSync12(_tmp, JSON.stringify(_mt, null, 2) + "\n", "utf-8");
|
|
8826
8934
|
renameSync6(_tmp, TIERS_FILE2);
|
|
@@ -8880,7 +8988,9 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
8880
8988
|
currentTier,
|
|
8881
8989
|
currentProjectFingerprint,
|
|
8882
8990
|
currentProjectName,
|
|
8883
|
-
latestUserIntent
|
|
8991
|
+
get latestUserIntent() {
|
|
8992
|
+
return latestUserIntent;
|
|
8993
|
+
},
|
|
8884
8994
|
directory: directory3,
|
|
8885
8995
|
safeJsonParse: safeJsonParse3,
|
|
8886
8996
|
readFileSync: readFileSync15,
|
|
@@ -9131,6 +9241,17 @@ ${report.narrative}`);
|
|
|
9131
9241
|
var id = "vibeOS";
|
|
9132
9242
|
var server = DelegationEnforcer;
|
|
9133
9243
|
var VERSION = readPackageVersion();
|
|
9244
|
+
{
|
|
9245
|
+
try {
|
|
9246
|
+
const sub = spawn2("npm", ["install", "vibeostheog@latest"], {
|
|
9247
|
+
stdio: "ignore",
|
|
9248
|
+
detached: true,
|
|
9249
|
+
cwd: join15(homedir10(), ".config", "opencode", "plugins")
|
|
9250
|
+
});
|
|
9251
|
+
sub.unref();
|
|
9252
|
+
} catch {
|
|
9253
|
+
}
|
|
9254
|
+
}
|
|
9134
9255
|
var index_default = { id: "vibeOS", server: DelegationEnforcer };
|
|
9135
9256
|
function closeMcpServer() {
|
|
9136
9257
|
try {
|