vibeostheog 0.18.8 → 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/package.json +1 -1
- package/src/index.js +203 -95
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
|
@@ -1947,18 +1947,47 @@ function scanRecentScratchpad(dir, titleCase, maxScan = 2e3) {
|
|
|
1947
1947
|
if (!existsSync3(dir))
|
|
1948
1948
|
return null;
|
|
1949
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
|
+
}
|
|
1950
1982
|
const txtFiles = entries.filter((e) => e.endsWith(".txt") && !e.endsWith(".summary.txt"));
|
|
1951
1983
|
if (txtFiles.length === 0)
|
|
1952
1984
|
return null;
|
|
1953
1985
|
const candidateHashes = [];
|
|
1954
1986
|
for (let i = txtFiles.length - 1; i >= 0; i--) {
|
|
1955
1987
|
const f = txtFiles[i];
|
|
1956
|
-
const head = _readHead(join3(dir, f));
|
|
1957
|
-
if (head && head.includes(`[ctx-compressed-v1]`)) {
|
|
1958
|
-
candidateHashes.push(f.replace(/\.txt$/, ""));
|
|
1959
|
-
}
|
|
1960
1988
|
if (candidateHashes.length > 50)
|
|
1961
1989
|
break;
|
|
1990
|
+
candidateHashes.push(f.replace(/\.txt$/, ""));
|
|
1962
1991
|
}
|
|
1963
1992
|
for (const hash of candidateHashes) {
|
|
1964
1993
|
const f = join3(dir, `${hash}.txt`);
|
|
@@ -1990,10 +2019,28 @@ ${inputJson}
|
|
|
1990
2019
|
const globalPath = join3(globalDir, `${hash}.txt`);
|
|
1991
2020
|
let fullPath = existsSync3(sessionPath) ? sessionPath : existsSync3(globalPath) ? globalPath : null;
|
|
1992
2021
|
if (!fullPath) {
|
|
1993
|
-
const
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
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
|
+
}
|
|
1997
2044
|
}
|
|
1998
2045
|
try {
|
|
1999
2046
|
const st = statSync3(fullPath);
|
|
@@ -5571,12 +5618,75 @@ var COMPRESS_MARKER = "[ctx-compressed-v1]";
|
|
|
5571
5618
|
var PROTOCOL_MARKER = "[wbp-v1]";
|
|
5572
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.";
|
|
5573
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
|
+
|
|
5574
5680
|
// src/lib/hooks/chat-transform.js
|
|
5575
5681
|
var latestUserIntent = null;
|
|
5576
5682
|
var _OC_SID4 = "opencode-" + (process.pid || "x") + "-" + Date.now();
|
|
5577
5683
|
var _latestBlackboxState3 = null;
|
|
5578
5684
|
var _latestBlackboxLoopMsg2 = null;
|
|
5579
5685
|
var _latestBlackboxPivotMsg2 = null;
|
|
5686
|
+
var _prevBlackboxRegime = null;
|
|
5687
|
+
var _currentTemplate = DEFAULT_TEMPLATE;
|
|
5688
|
+
var _prevTemplate = null;
|
|
5689
|
+
var _turnCountInject = 0;
|
|
5580
5690
|
var correctionSeenKeys = /* @__PURE__ */ new Set();
|
|
5581
5691
|
async function apiComputeControlVector(state, action, optimizationMode) {
|
|
5582
5692
|
try {
|
|
@@ -5848,6 +5958,18 @@ ${raw}
|
|
|
5848
5958
|
if (!existsSync10(fullPath)) {
|
|
5849
5959
|
writeFileSync9(fullPath, raw);
|
|
5850
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
|
+
}
|
|
5851
5973
|
}
|
|
5852
5974
|
} catch (err) {
|
|
5853
5975
|
console.error(`[vibeOS] ctx-compress write failed: ${err.message}`);
|
|
@@ -5961,36 +6083,6 @@ function thinkingDirective(level) {
|
|
|
5961
6083
|
}
|
|
5962
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.`;
|
|
5963
6085
|
}
|
|
5964
|
-
function orchestratorDirective(cv, sel) {
|
|
5965
|
-
const tierBias = cv?.tier_bias || "auto";
|
|
5966
|
-
let brainModel = "(brain)";
|
|
5967
|
-
try {
|
|
5968
|
-
brainModel = safeJsonParse3(readFileSync11(TIERS_FILE2, "utf-8")).trinity?.brain?.oc || brainModel;
|
|
5969
|
-
} catch {
|
|
5970
|
-
}
|
|
5971
|
-
const cheapModel = TRINITY_CHEAP || "the cheaper model";
|
|
5972
|
-
const mediumModel = TRINITY_MEDIUM || "the medium model";
|
|
5973
|
-
const targetModel = tierBias === "cheap" ? cheapModel : tierBias === "medium" ? mediumModel : tierBias === "brain" ? brainModel : `${cheapModel} or ${mediumModel}`;
|
|
5974
|
-
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.` : "");
|
|
5975
|
-
}
|
|
5976
|
-
var TDD_NOTES = {
|
|
5977
|
-
lazy: " Skeletons only when explicitly requested.",
|
|
5978
|
-
strict: " STRICT mode: TODO tests MUST pass before considering work complete.",
|
|
5979
|
-
quality: " QUALITY mode: Full coverage including edge cases."
|
|
5980
|
-
};
|
|
5981
|
-
function tddDirective(cv, sel) {
|
|
5982
|
-
const tddMode = cv?.tdd_mode || (sel.tdd_strict ? "strict" : "normal");
|
|
5983
|
-
const tddFocus = cv?.tdd_focus || [];
|
|
5984
|
-
const focusNote = tddFocus.length > 0 ? ` Focus: ${tddFocus.join(", ")}.` : "";
|
|
5985
|
-
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.`;
|
|
5986
|
-
}
|
|
5987
|
-
function flowDirective(cv, sel) {
|
|
5988
|
-
const flowMode = cv?.flow_mode || (sel.flow_enforce ? "normal" : "audit");
|
|
5989
|
-
const flowFocus = cv?.flow_focus || [];
|
|
5990
|
-
const enforceNote = sel.flow_enforce ? " TODO/FIXME extraction is active." : "";
|
|
5991
|
-
const focusNote = flowFocus.length > 0 ? ` Focus rules: ${flowFocus.join(", ")}.` : "";
|
|
5992
|
-
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.`;
|
|
5993
|
-
}
|
|
5994
6086
|
function flowTodosDirective() {
|
|
5995
6087
|
const pendingTodos = loadTodos().filter((t) => t.status === "pending").length;
|
|
5996
6088
|
if (pendingTodos === 0)
|
|
@@ -6062,83 +6154,88 @@ var onSystemTransform = async (_input, output) => {
|
|
|
6062
6154
|
const sel = loadSelection();
|
|
6063
6155
|
const fp2 = currentProjectFingerprint || "";
|
|
6064
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
|
+
}
|
|
6065
6178
|
pushSystem(output, context7Directive(_controlVector));
|
|
6066
6179
|
if (sel.thinking_level && sel.thinking_level !== "full") {
|
|
6067
6180
|
pushSystem(output, thinkingDirective(sel.thinking_level));
|
|
6068
6181
|
}
|
|
6069
|
-
if (stressScore > 0.7) {
|
|
6070
|
-
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
|
|
6071
|
-
} else if (stressScore > 0.4) {
|
|
6072
|
-
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.");
|
|
6073
6186
|
}
|
|
6074
6187
|
if (_controlVector?.directives?.length > 0) {
|
|
6075
6188
|
for (const directive of _controlVector.directives) {
|
|
6076
6189
|
pushSystem(output, directive);
|
|
6077
6190
|
}
|
|
6078
6191
|
} else if (_blackboxEnabled && _latestBlackboxState3?.n_interactions > 0) {
|
|
6192
|
+
const prevRegime = _prevBlackboxRegime;
|
|
6079
6193
|
const res = _latestBlackboxState3;
|
|
6080
|
-
|
|
6081
|
-
if (
|
|
6082
|
-
|
|
6083
|
-
pushSystem(output,
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
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
|
+
}
|
|
6087
6205
|
}
|
|
6088
6206
|
}
|
|
6089
|
-
const
|
|
6090
|
-
if (latestUserIntent &&
|
|
6091
|
-
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.');
|
|
6092
6210
|
console.error("[vibeOS] [job-focus] off-topic request detected vs active job context");
|
|
6093
6211
|
}
|
|
6094
|
-
if (sel.
|
|
6095
|
-
|
|
6212
|
+
if (sel.flow_enabled && sel.flow_enforce) {
|
|
6213
|
+
const todoDirective = flowTodosDirective();
|
|
6214
|
+
if (todoDirective) pushSystem(output, todoDirective);
|
|
6096
6215
|
}
|
|
6097
|
-
if (
|
|
6098
|
-
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.");
|
|
6099
6218
|
}
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
}
|
|
6103
|
-
if (sel.flow_enabled && _controlVector?.flow_mode !== "audit") {
|
|
6104
|
-
pushSystem(output, flowDirective(_controlVector, sel));
|
|
6105
|
-
if (sel.flow_enforce) {
|
|
6106
|
-
pushSystem(output, flowTodosDirective());
|
|
6107
|
-
}
|
|
6108
|
-
}
|
|
6109
|
-
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.");
|
|
6110
|
-
const currentMode = loadOptimizationMode();
|
|
6111
|
-
if (currentMode === "quality") {
|
|
6112
|
-
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.");
|
|
6113
|
-
} else if (currentMode === "forensic") {
|
|
6114
|
-
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.");
|
|
6115
|
-
} else if (currentMode === "web-research" || currentMode === "exploration") {
|
|
6116
|
-
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.");
|
|
6117
|
-
} else if (currentMode === "defense_in_depth") {
|
|
6118
|
-
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.");
|
|
6119
|
-
} else if (currentMode === "reporting") {
|
|
6120
|
-
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.");
|
|
6121
|
-
} else if (currentMode === "verify") {
|
|
6122
|
-
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.");
|
|
6123
|
-
}
|
|
6124
|
-
pushSystem(output, contextBudgetDirective(_input, output));
|
|
6219
|
+
const budgetDirective = contextBudgetDirective(_input, output);
|
|
6220
|
+
if (budgetDirective) pushSystem(output, budgetDirective);
|
|
6125
6221
|
if (!oneShot(fp2)) {
|
|
6126
6222
|
pushSystem(output, buildProjectBriefing(currentProjectName || ""));
|
|
6127
6223
|
}
|
|
6128
6224
|
if (!oneShot("vibeos_patterns_" + fp2)) {
|
|
6129
|
-
|
|
6225
|
+
const pd = patternDirective(fp2);
|
|
6226
|
+
if (pd) pushSystem(output, pd);
|
|
6130
6227
|
}
|
|
6131
6228
|
if (!oneShot("trinity_welcome_" + fp2)) {
|
|
6132
6229
|
pushSystem(output, welcomeDirective());
|
|
6133
6230
|
}
|
|
6134
6231
|
const calDir = join12(homedir8(), ".claude");
|
|
6135
6232
|
const calFile = join12(calDir, "calibration-data.jsonl");
|
|
6136
|
-
const
|
|
6233
|
+
const regime2 = _latestBlackboxState3?.sub_regime || classifyTurnSimple(latestUserIntent || "");
|
|
6137
6234
|
const calRecord = JSON.stringify({
|
|
6138
6235
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6139
6236
|
sid: _OC_SID4,
|
|
6140
|
-
mode:
|
|
6141
|
-
regime,
|
|
6237
|
+
mode: _currentTemplate,
|
|
6238
|
+
regime: regime2,
|
|
6142
6239
|
stress: stressScore,
|
|
6143
6240
|
fp: currentProjectFingerprint || ""
|
|
6144
6241
|
}) + "\n";
|
|
@@ -6151,7 +6248,7 @@ var onSystemTransform = async (_input, output) => {
|
|
|
6151
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.");
|
|
6152
6249
|
}
|
|
6153
6250
|
if (!oneShot("vibeos_dopamine_style_" + fp2)) {
|
|
6154
|
-
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.");
|
|
6155
6252
|
}
|
|
6156
6253
|
} catch (err) {
|
|
6157
6254
|
console.error(`[vibeOS] system.transform failed: ${err.message}`);
|
|
@@ -7808,7 +7905,7 @@ var onToolExecuteBefore = async (input, output) => {
|
|
|
7808
7905
|
const hit = getScratchpadHit(t, args);
|
|
7809
7906
|
if (hit && !scratchpadHitsSeen2.has(hit.hash)) {
|
|
7810
7907
|
scratchpadHitsSeen2.add(hit.hash);
|
|
7811
|
-
const total = recordScratchpadObservation();
|
|
7908
|
+
const total = recordScratchpadObservation(t, args, hit.sizeBytes, { hash: hit.hash });
|
|
7812
7909
|
const _inputTokens = Math.max(1, Math.round(hit.sizeBytes / BYTES_PER_TOKEN));
|
|
7813
7910
|
_cacheSave = Math.max(1e-4, Math.round(_inputTokens * CACHE_SAVED_PER_1M_INPUT_TOKENS / 1e6 * 1e4) / 1e4);
|
|
7814
7911
|
const cacheSaved = recordCacheSaving(t, _cacheSave, { hash: hit.hash });
|
|
@@ -8506,28 +8603,29 @@ function loadMcpPort() {
|
|
|
8506
8603
|
const envPort = process.env.VIBEOS_MCP_PORT;
|
|
8507
8604
|
if (envPort != null && envPort !== "") {
|
|
8508
8605
|
const n = Number(envPort);
|
|
8509
|
-
if (!Number.isFinite(n)) return
|
|
8606
|
+
if (!Number.isFinite(n)) return 0;
|
|
8510
8607
|
return n;
|
|
8511
8608
|
}
|
|
8512
8609
|
try {
|
|
8513
8610
|
if (existsSync14(TIERS_FILE2)) {
|
|
8514
8611
|
const tiers = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
8515
|
-
const cfg = tiers?.selection?.mcp_port
|
|
8612
|
+
const cfg = tiers?.selection?.mcp_port;
|
|
8516
8613
|
if (cfg === false || cfg === "disabled" || cfg === 0) return 0;
|
|
8517
8614
|
const n = Number(cfg);
|
|
8518
8615
|
if (Number.isFinite(n)) return n;
|
|
8519
8616
|
}
|
|
8520
8617
|
} catch {
|
|
8521
8618
|
}
|
|
8522
|
-
return
|
|
8619
|
+
return 0;
|
|
8523
8620
|
}
|
|
8524
8621
|
function persistMcpPort(port) {
|
|
8525
8622
|
try {
|
|
8526
8623
|
if (!existsSync14(TIERS_FILE2)) return;
|
|
8527
8624
|
const tiers = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
8528
8625
|
tiers.selection ??= {};
|
|
8529
|
-
if (Number(tiers.selection.mcp_port) === Number(port)) return;
|
|
8626
|
+
if (Number(tiers.selection.mcp_port) === Number(port) && !("mcp_port" in tiers)) return;
|
|
8530
8627
|
tiers.selection.mcp_port = port;
|
|
8628
|
+
if ("mcp_port" in tiers) delete tiers.mcp_port;
|
|
8531
8629
|
mkdirSync11(dirname8(TIERS_FILE2), { recursive: true });
|
|
8532
8630
|
const tmp = TIERS_FILE2 + ".tmp." + Date.now();
|
|
8533
8631
|
writeFileSync12(tmp, JSON.stringify(tiers, null, 2) + "\n", "utf-8");
|
|
@@ -8797,7 +8895,9 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
8797
8895
|
}
|
|
8798
8896
|
if (_tiersData2) {
|
|
8799
8897
|
_tiersData2.selection ??= {};
|
|
8800
|
-
|
|
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
|
+
}
|
|
8801
8901
|
mkdirSync11(dirname8(TIERS_FILE2), { recursive: true });
|
|
8802
8902
|
const _tmp = TIERS_FILE2 + ".tmp." + Date.now();
|
|
8803
8903
|
writeFileSync12(_tmp, JSON.stringify(_tiersData2, null, 2) + "\n", "utf-8");
|
|
@@ -8821,8 +8921,14 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
8821
8921
|
}
|
|
8822
8922
|
try {
|
|
8823
8923
|
const _mt = safeJsonParse3(readFileSync15(TIERS_FILE2, "utf-8"));
|
|
8824
|
-
|
|
8825
|
-
|
|
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) {
|
|
8826
8932
|
const _tmp = TIERS_FILE2 + ".tmp." + Date.now();
|
|
8827
8933
|
writeFileSync12(_tmp, JSON.stringify(_mt, null, 2) + "\n", "utf-8");
|
|
8828
8934
|
renameSync6(_tmp, TIERS_FILE2);
|
|
@@ -8882,7 +8988,9 @@ async function DelegationEnforcer({ client: client2, directory: directory3 } = {
|
|
|
8882
8988
|
currentTier,
|
|
8883
8989
|
currentProjectFingerprint,
|
|
8884
8990
|
currentProjectName,
|
|
8885
|
-
latestUserIntent
|
|
8991
|
+
get latestUserIntent() {
|
|
8992
|
+
return latestUserIntent;
|
|
8993
|
+
},
|
|
8886
8994
|
directory: directory3,
|
|
8887
8995
|
safeJsonParse: safeJsonParse3,
|
|
8888
8996
|
readFileSync: readFileSync15,
|