vibeostheog 0.23.55 → 0.23.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.23.56
2
+ - fix: softer dopamine-style communication layer with compact vector-change storytelling and calmer footer pulses
3
+
4
+
5
+ ## 0.23.55
6
+ - feat: add single-file bundle build (esbuild) + fix vibelitex schema deployment
7
+
8
+
1
9
  ## 0.23.54
2
10
  - test: make blackboxSelectMode test resilient to API response format
3
11
  - test: fix e2e tests for vibelitex mode (budget → vibelitex)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeostheog",
3
- "version": "0.23.55",
3
+ "version": "0.23.56",
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",
@@ -497,20 +497,19 @@ const C7_URGENCY = {
497
497
  function context7Directive(cv) {
498
498
  const urgency = cv?.context7_urgency || "preferred";
499
499
  return "[cost policy] If mcp__context7__resolve-library-id and mcp__context7__get-library-docs " +
500
- "tools are available in this session, ALWAYS use them instead of WebFetch or WebSearch " +
501
- "when looking up library or framework documentation " +
500
+ "are available, prefer them over WebFetch/WebSearch for library and framework docs " +
502
501
  "(docs.*, readthedocs.*, npmjs.com/package/*, pypi.org/project/*, pkg.go.dev, /api/reference/). " +
503
- "Do not fetch those URLs directly when context7 can serve the same content. " +
504
- "This saves ~$0.06/turn on average." +
502
+ "Use the cheapest accurate source first. " +
503
+ "This usually saves about $0.06/turn." +
505
504
  (C7_URGENCY[urgency] || "");
506
505
  }
507
506
  function thinkingDirective(level) {
508
507
  const credit = loadCredit();
509
508
  const creditNote = `credit ${credit}%`;
510
509
  if (level === "brief") {
511
- return `[thinking policy] Reasoning depth: BRIEF (manually set, ${creditNote}). Use extended thinking only for genuinely complex multi-step problems. Keep reasoning concise -- skip exploratory scratch work and restatement.`;
510
+ return `[thinking policy] Reasoning depth: BRIEF (manually set, ${creditNote}). Keep the answer crisp and only expand when the task truly needs it.`;
512
511
  }
513
- 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.`;
512
+ return `[thinking policy] Reasoning depth: OFF (manually set, ${creditNote}). Respond directly, avoid extra scratch work, and reserve extended thinking for when the user asks for it.`;
514
513
  }
515
514
  function orchestratorDirective(cv, sel) {
516
515
  const tierBias = cv?.tier_bias || "auto";
@@ -525,10 +524,10 @@ function orchestratorDirective(cv, sel) {
525
524
  const compatibilityMode = sel?.onboarding_mode === "assist";
526
525
  return `[AI ORCHESTRATOR AGENT] You are an AI orchestrator agent. ` +
527
526
  `Delegate heavy work to Task subagents (runs on ${targetModel}). ` +
528
- `Your role: verify, fill gaps, synthesize. ` +
527
+ `Your role is to verify, fill gaps, and synthesize cleanly. ` +
529
528
  (compatibilityMode
530
- ? "Compatibility mode is active: direct Write/Edit is allowed until the user enables strict guardrails."
531
- : "CRITICAL: Write/Edit tools are BLOCKED on this tier. You MUST delegate ALL implementation work to Task subagents.") +
529
+ ? "Compatibility mode is active, so direct Write/Edit stays available until strict guardrails are enabled."
530
+ : "Write/Edit tools are blocked on this tier; delegate implementation work to Task subagents.") +
532
531
  ` Always display the vibeOS cost footer.` +
533
532
  (tierBias !== "auto" ? ` [tier routing] This turn is biased toward ${tierBias} tier.` : "");
534
533
  }
@@ -541,8 +540,8 @@ function tddDirective(cv, sel) {
541
540
  const tddMode = cv?.tdd_mode || (sel.tdd_strict ? "strict" : "normal");
542
541
  const tddFocus = cv?.tdd_focus || [];
543
542
  const focusNote = tddFocus.length > 0 ? ` Focus: ${tddFocus.join(", ")}.` : "";
544
- return `[tdd enforcement: ${tddMode}] Auto-create skeleton tests for source files being written/edited.${TDD_NOTES[tddMode] || ""}${focusNote} ` +
545
- "When creating or modifying source files, ensure corresponding test files exist with proper assertions.";
543
+ return `[tdd enforcement: ${tddMode}] Auto-create skeleton tests for source files being written or edited.${TDD_NOTES[tddMode] || ""}${focusNote} ` +
544
+ "When the work changes code, keep the test path visible and make the next test step obvious.";
546
545
  }
547
546
  function flowDirective(cv, sel) {
548
547
  const flowMode = cv?.flow_mode || (sel.flow_enforce ? "normal" : "audit");
@@ -550,14 +549,14 @@ function flowDirective(cv, sel) {
550
549
  const enforceNote = sel.flow_enforce ? " TODO/FIXME extraction is active." : "";
551
550
  const focusNote = flowFocus.length > 0 ? ` Focus rules: ${flowFocus.join(", ")}.` : "";
552
551
  return `[flow enforcement: ${flowMode}] Development flow rules are active: write/edit operations are checked against project conventions.${enforceNote}${focusNote} ` +
553
- "Follow existing code patterns, naming conventions, and project structure.";
552
+ "Stay close to the existing code patterns, naming style, and project structure.";
554
553
  }
555
554
  function flowTodosDirective() {
556
555
  const pendingTodos = loadTodos().filter((t) => t.status === "pending").length;
557
556
  if (pendingTodos === 0)
558
557
  return null;
559
- return "[vibeOS] " + pendingTodos + " extracted TODO/FIXME items are pending. " +
560
- "Consider calling `todowrite` to add them to the native task list.";
558
+ return "[vibeOS] " + pendingTodos + " extracted TODO/FIXME items are waiting. " +
559
+ "If useful, call `todowrite` so they land in the native task list.";
561
560
  }
562
561
  function patternDirective(fp) {
563
562
  const patterns = promotedProjectPatterns(fp);
@@ -586,8 +585,8 @@ function welcomeDirective() {
586
585
  const active = sel.active_slot || "medium";
587
586
  const current = currentModel || "(unknown)";
588
587
  return "[vibeOS] Active plugin. Slot: " + active + " (" + current + "). " +
589
- "Use trinity command to switch slots, rebuild, or check status. " +
590
- "Run `trinity help` for all commands.";
588
+ "Use `trinity status` for a quick check, `trinity help` for the full command list, " +
589
+ "or `trinity set`, `trinity mode`, and `trinity rebuild` to move forward.";
591
590
  }
592
591
  function contextBudgetDirective(_input, output) {
593
592
  const ctxBudget = estimateContextBudget(_input, output);
@@ -595,7 +594,7 @@ function contextBudgetDirective(_input, output) {
595
594
  return null;
596
595
  const severity = ctxBudget.pct > 90 ? "CRITICAL" : "WARNING";
597
596
  return `[context budget: ${severity}] Context window is ${ctxBudget.pct}% full (~${ctxBudget.estimatedTokens} tokens). ` +
598
- "Consider using Task subagents for heavy work, compressing tool outputs, or starting a new session to avoid context overflow.";
597
+ "Use Task subagents for heavy work, compress tool output, or start a fresh session before context gets cramped.";
599
598
  }
600
599
  export const onSystemTransform = async (_input, output) => {
601
600
  if (!loadSelection().enabled)
@@ -720,12 +719,11 @@ export const onSystemTransform = async (_input, output) => {
720
719
  }
721
720
  const stressMitigationDirective = rawStress > 0.7
722
721
  ? "[stress mitigation: CRITICAL] The user's message shows very high stress indicators. " +
723
- "Stay calm, structured, and thorough. Use proper markdown formatting with code blocks, " +
724
- "lists, and organized structure. Do NOT mirror the user's tone or brevity. " +
725
- "This is the most important directive in your system prompt for this turn."
722
+ "Stay calm, structured, and thorough. Lead with the answer, keep steps explicit, and avoid playful language or overload. " +
723
+ "Do not mirror the user's urgency."
726
724
  : rawStress > 0.4
727
725
  ? "[stress mitigation: elevated] The user's message has elevated stress indicators. " +
728
- "Maintain structured, well-formatted responses with markdown and code blocks."
726
+ "Keep the response structured, readable, and lightly reassuring."
729
727
  : null;
730
728
  if (stressMitigationDirective) {
731
729
  pushSystem(output, stressMitigationDirective);
@@ -738,13 +736,13 @@ export const onSystemTransform = async (_input, output) => {
738
736
  const tpl = TEMPLATES[_currentTemplate] || TEMPLATES[DEFAULT_TEMPLATE];
739
737
  let fused = tpl.directive;
740
738
  if (sel.delegation_enforce && _controlVector?.enforcement_mode !== "relaxed") {
741
- fused += " CRITICAL: Write/Edit tools are BLOCKED on brain tier. Delegate ALL implementation to Task subagents. Use parallel invocation for independent tasks.";
739
+ fused += " Write/Edit stays blocked on brain tier. Delegate implementation to Task subagents and use parallel calls for independent work.";
742
740
  }
743
741
  if (sel.tdd_enforce && _controlVector?.tdd_mode !== "lazy") {
744
- fused += " Auto-create test skeletons for changed source files.";
742
+ fused += " Keep test skeletons ready for changed source files.";
745
743
  }
746
744
  if (sel.flow_enabled && _controlVector?.flow_mode !== "audit") {
747
- fused += " Follow existing code conventions and project patterns.";
745
+ fused += " Stay close to existing code conventions and project patterns.";
748
746
  }
749
747
  pushSystem(output, fused);
750
748
  }
@@ -768,7 +766,7 @@ export const onSystemTransform = async (_input, output) => {
768
766
  if (currentRegime !== prevRegime) {
769
767
  _prevBlackboxRegime = currentRegime;
770
768
  pushSystem(output, "[decision engine] Resolution: " + (res.resolution || "unresolved") + " " +
771
- "(" + currentRegime + "). Momentum: " + ((res.momentum || 0) > 0 ? "positive" : (res.momentum || 0) < 0 ? "negative" : "neutral") + ".");
769
+ "(" + currentRegime + "). Momentum: " + ((res.momentum || 0) > 0 ? "positive" : (res.momentum || 0) < 0 ? "negative" : "→ steady") + ".");
772
770
  if (res.is_looping && res.loop_intervention_level && res.loop_intervention_level !== "none") {
773
771
  const severity = res.loop_intervention_level === "escalated" ? "CRITICAL"
774
772
  : res.loop_intervention_level === "assertive" ? "WARNING" : "NOTICE";
@@ -832,18 +830,18 @@ export const onSystemTransform = async (_input, output) => {
832
830
  catch { }
833
831
  if (!oneShot("vibeos_dashboard_instruct")) {
834
832
  pushSystem(output, "[vibeOS dashboard display] When the trinity tool returns output starting with '[vibeOS-dashboard]', " +
835
- "you MUST use the question tool to display that data in a clean, human-readable format. " +
833
+ "use the question tool to display that data in a clean, human-readable format. " +
836
834
  "Use the question field (not the header) to show the dashboard data. " +
837
835
  "Format it with clear sections separated by blank lines, aligned columns with spaces, " +
838
- "and plain text only (no emojis, no markdown). " +
836
+ "and plain text only. " +
839
837
  "The header should be 'vibeOS Dashboard'. " +
840
838
  "Include only one option in options: {label: 'Dismiss', description: ''}. " +
841
839
  "Strip the '[vibeOS-dashboard]' marker line before displaying.");
842
840
  }
843
841
  if (!oneShot("vibeos_dopamine_style_" + fp)) {
844
- pushSystem(output, "[tool style: dopamine] When calling the bash tool, use a short, progress-focused description " +
842
+ pushSystem(output, "[tool style: dopamine] When calling the bash tool, use a short, calm, progress-focused description " +
845
843
  "that names the user-visible milestone being advanced. Combine independent bash commands into a single " +
846
- "call with && or ;. Never use raw technical labels as tool descriptions.");
844
+ "call with && or ;. Keep the wording human and avoid hype or raw technical labels.");
847
845
  }
848
846
  }
849
847
  catch (err) {
@@ -283,6 +283,7 @@ async function _appendFooter(input, output, directory) {
283
283
  providerLabel: execution.provider_label,
284
284
  modelName: modelDisplayName(execution.model),
285
285
  ltTotal,
286
+ ltTrend: sesTrend,
286
287
  vibeBrand,
287
288
  optMode: displayMode,
288
289
  flashIcon,
@@ -20,6 +20,20 @@ export function resolveBrand(optMode, activeSlot) {
20
20
  export function resolveTierIcon(slot) {
21
21
  return TIER_ICON[slot] || "\u26A1";
22
22
  }
23
+ export function trendGlyph(trend) {
24
+ if (trend === "up")
25
+ return "↗";
26
+ if (trend === "down")
27
+ return "↘";
28
+ return "→";
29
+ }
30
+ export function formatSavingsPulse(amountUsd, trend) {
31
+ const amount = Number(amountUsd || 0);
32
+ if (!Number.isFinite(amount) || amount <= 0)
33
+ return "";
34
+ const arrow = trendGlyph(trend);
35
+ return `$${amount.toFixed(2)} saved${arrow !== "→" ? ` ${arrow}` : ""}`;
36
+ }
23
37
  export function buildEnforcementTags(opts) {
24
38
  const tags = [];
25
39
  if (opts.bbMode === "relaxed") {
@@ -40,11 +54,13 @@ export function buildEnforcementTags(opts) {
40
54
  return tags;
41
55
  }
42
56
  export function buildFooterLine(input) {
43
- const { activeSlot, sessionSlot, providerLabel, modelName, ltTotal, vibeBrand, optMode, flashIcon, enfTags, vectorChangedSlot } = input;
57
+ const { activeSlot, sessionSlot, providerLabel, modelName, ltTotal, ltTrend, vibeBrand, optMode, flashIcon, enfTags, vectorChangedSlot } = input;
44
58
  const tierIcon = resolveTierIcon(activeSlot);
45
59
  let line = `\u2014 ${tierIcon} ${activeSlot} | ${providerLabel} | ${modelName}`;
46
60
  if (ltTotal > 0) {
47
- line += ` | $${ltTotal.toFixed(2)}`;
61
+ const savingsPulse = formatSavingsPulse(ltTotal, ltTrend);
62
+ if (savingsPulse)
63
+ line += ` | ${savingsPulse}`;
48
64
  }
49
65
  line += ` | ${vibeBrand}${flashIcon}`;
50
66
  if (optMode && optMode !== "auto") {
@@ -3,7 +3,7 @@ import { writeFileSync, appendFileSync, existsSync, mkdirSync } from "node:fs";
3
3
  import { join, dirname, basename } from "node:path";
4
4
  import { createHash } from "node:crypto";
5
5
  import { currentTier, currentModel, setCurrentModel, setCurrentTier, _OC_SID, _modelLocked, loadSelection, readLifetimeSavings, recordCacheSaving, recordMissedContext7, getScratchpadHit, recordScratchpadObservation, recordPrivacyTelemetry, updateState, getSessionScratchpadDir, ensureSessionScratchpadDirs, SAVINGS_LEDGER_FILE, CONTEXT7_INSTALL_FLAG, SOFT_QUOTA_LIMIT, upsertTodo, ML_ENABLED, _mlGraph, _cacheDb, _mlSavePending, ML_CONFIDENCE_THRESHOLD, setMlSavePending, saveMLState, SCRATCHPAD_TOOLS, SCRATCHPAD_GLOBAL_DIR, TOOL_NAME_NORMALIZE, stableJson, applyDecadence, } from "../state.js";
6
- import { classify, modelCostPerTurn, isModelFree, detectContext7, isDocsTarget, shortModelName, formatUsd, _refreshModel, readConfig, resolveDisplayModelId, TRINITY_CHEAP, TRINITY_MEDIUM, TRINITY_BRAIN, cacheSavePer1MInputTokens, trendDisplay, modelToSlotLabel, resolveExecutionIdentity, modelDisplayName, } from "../pricing.js";
6
+ import { classify, modelCostPerTurn, isModelFree, detectContext7, isDocsTarget, shortModelName, formatUsd, _refreshModel, readConfig, resolveDisplayModelId, TRINITY_CHEAP, TRINITY_MEDIUM, TRINITY_BRAIN, cacheSavePer1MInputTokens, modelToSlotLabel, resolveExecutionIdentity, modelDisplayName, } from "../pricing.js";
7
7
  import { latestUserIntent } from "./chat-transform.js";
8
8
  import { loadSessionOptMode } from "../selection-manager.js";
9
9
  import { loadOptimizationMode } from "../turn-classify.js";
@@ -530,7 +530,7 @@ export const onToolExecuteBefore = async (input, output) => {
530
530
  _mutateBlockedToolArgs(t, argSources, checkPath, output);
531
531
  if (shouldLogWarn(`${t}|protect|${checkPath}`))
532
532
  console.error(`[vibeOS] [protection] BLOCKED direct ${t} in self-protected directory: ${checkPath}`);
533
- pendingUiNote = `🛡 Self-modification blocked: ${basename(checkPath)} is in a protected project tree. Use manual git workflow.`;
533
+ pendingUiNote = `[LOCK] Self-modification paused: ${basename(checkPath)} is in a protected project tree. Use a manual git workflow.`;
534
534
  enforcementBlocked = true;
535
535
  return;
536
536
  }
@@ -544,11 +544,11 @@ export const onToolExecuteBefore = async (input, output) => {
544
544
  if (costDetector.checkAnomaly(fullModelName, modelCost)) {
545
545
  const avg = costDetector.currentAnomalyMean;
546
546
  const ratio = avg > 0 ? (modelCost / avg).toFixed(1) : "?";
547
- const msg = `Cost spike: ${shortModelName(fullModelName)} at $${modelCost.toFixed(4)}/turn — ${ratio}x higher than recent avg of $${avg.toFixed(4)}. Run \`trinity cheap\` or \`trinity medium\` to save.`;
547
+ const msg = `Cost spike: ${shortModelName(fullModelName)} at $${modelCost.toFixed(4)}/turn — ${ratio}x above the recent average of $${avg.toFixed(4)}. Switch to \`trinity medium\` or \`trinity cheap\` to keep momentum.`;
548
548
  if (shouldLogWarn(`${t}|cost-anomaly|${fullModelName}|${modelCost.toFixed(4)}`)) {
549
549
  console.error(`[vibeOS] [cost-anomaly] ${msg}`);
550
550
  }
551
- pendingUiNote = `🚨 ${msg}`;
551
+ pendingUiNote = `[SLOW DOWN] ${msg}`;
552
552
  enforcementBlocked = true;
553
553
  return;
554
554
  }
@@ -557,8 +557,7 @@ export const onToolExecuteBefore = async (input, output) => {
557
557
  // Credit < 40%: non-task tool — record and nudge to step aside.
558
558
  if (_credit < 40 && !compatibilityMode) {
559
559
  const total = recordSaving(t, "credit<40% high-tier", _estOpus, { firstWord: _firstWord });
560
- const trend = trendDisplay(readLifetimeSavings().sesTrend);
561
- const msg = `⚠ [vibeOS] Credit: ${_credit}% — switching to medium saves ~$${_estOpus.toFixed(3)}/turn. Run \`trinity medium\`.`;
560
+ const msg = `[vibeOS] Credit is at ${_credit}%. Quick win: switch to medium to save about ~$${_estOpus.toFixed(3)}/turn.`;
562
561
  if (shouldLogWarn(`${t}|credit|${_tierWord}`) && process.env.VIBEOS_DEBUG_DELEGATION === "1") {
563
562
  console.error(`[vibeOS] [delegation] ${msg}`);
564
563
  }
@@ -585,7 +584,7 @@ export const onToolExecuteBefore = async (input, output) => {
585
584
  if (isBlocked) {
586
585
  _mutateBlockedToolArgs(tLower, argSources, originalPath, output);
587
586
  const total = recordSaving(t, "delegation enforced", savings, { firstWord: _firstWord });
588
- pendingUiNote = `🚫 Brain tier direct ${t} blocked delegate via Task or run \`trinity medium\`.`;
587
+ pendingUiNote = `[ENF] Brain-tier direct ${t} paused. Delegate via Task or switch to \`trinity medium\`.`;
589
588
  enforcementBlocked = true;
590
589
  if (shouldLogWarn(`${t}|enforced|${_tierWord}`))
591
590
  console.error(`[vibeOS] [enforcement] BLOCKED direct ${t} on high tier → delegate via Task`);
@@ -594,7 +593,7 @@ export const onToolExecuteBefore = async (input, output) => {
594
593
  }
595
594
  const total = recordSaving(t, "direct edit", _estEdit, { firstWord: _firstWord });
596
595
  if (!compatibilityMode) {
597
- const msg = `[vibeOS] ${_tierWord} tier direct ${t} — save ~$${_estEdit.toFixed(3)} by delegating to Task. Run \`trinity medium\`.`;
596
+ const msg = `[vibeOS] ${_tierWord} tier direct ${t} — save about ~$${_estEdit.toFixed(3)} by delegating to Task. Try \`trinity medium\`.`;
598
597
  if (shouldLogWarn(`${t}|direct|${_tierWord}`) && process.env.VIBEOS_DEBUG_DELEGATION === "1") {
599
598
  console.error(`[vibeOS] [delegation] ${msg}`);
600
599
  }
@@ -623,11 +622,11 @@ export const onToolExecuteBefore = async (input, output) => {
623
622
  writeFileSync(CONTEXT7_INSTALL_FLAG, "");
624
623
  }
625
624
  catch { }
626
- console.error(`[vibeOS] 💡 Install context7 MCP to save ~$0.06/turn on docs: \`claude mcp add context7 npx @upstash/context7-mcp\``);
625
+ console.error(`[vibeOS] Small win: install context7 MCP to save about ~$0.06/turn on docs: \`claude mcp add context7 npx @upstash/context7-mcp\``);
627
626
  }
628
627
  else if (!context7AlertedThisSession) {
629
628
  context7AlertedThisSession = true;
630
- console.error(`[vibeOS] 💸 context7 not installedmissed ~$${(missed ?? 0).toFixed(2)} savings this session.`);
629
+ console.error(`[vibeOS] context7 is still off about ~$${(missed ?? 0).toFixed(2)} in savings slipped this session.`);
631
630
  }
632
631
  }
633
632
  }
@@ -637,7 +636,7 @@ export const onToolExecuteBefore = async (input, output) => {
637
636
  const n = softQuotaCounts[t];
638
637
  if (n === SOFT_QUOTA_LIMIT + 1) {
639
638
  const total = recordSaving(t, `soft quota exceeded (limit ${SOFT_QUOTA_LIMIT})`, SAVE_EST.SOFT_QUOTA);
640
- console.error(`[vibeOS] Bash usage high (${n}/${SOFT_QUOTA_LIMIT}) — delegate to Task subagent.`);
639
+ console.error(`[vibeOS] Bash usage is getting heavy (${n}/${SOFT_QUOTA_LIMIT}) — hand the next step to a Task subagent.`);
641
640
  }
642
641
  return;
643
642
  }
@@ -720,6 +719,7 @@ export const onToolExecuteAfter = async (input, output) => {
720
719
  providerLabel: execution.provider_label,
721
720
  modelName: modelDisplayName(execution.model),
722
721
  ltTotal,
722
+ ltTrend: sv.sesTrend,
723
723
  vibeBrand,
724
724
  optMode: optModeFooter,
725
725
  flashIcon,
@@ -16,25 +16,25 @@ const CREDIT_MIN_OK = 40;
16
16
  export function createTrinityTool(deps) {
17
17
  return {
18
18
  description: "Control the vibeOS plugin and active model slot. " +
19
- "Use action='status' to see current state. " +
20
- "Use action='enable' or 'disable' to toggle the plugin (takes effect immediately, no restart needed). " +
21
- "Use action='set' with slot='brain'|'medium'|'cheap' to switch model tiers " +
22
- "(writes opencode.json — active immediately). " +
19
+ "Use action='status' to see the current state. " +
20
+ "Use action='enable' or 'disable' to toggle the plugin immediately. " +
21
+ "Use action='set' with slot='brain'|'medium'|'cheap' to switch model tiers (writes opencode.json). " +
23
22
  "Use action='mode' with slot='vibeultrax'|'vibeqmax'|'vibemax'|'budget'|'quality'|'speed'|'longrun'|'auto'|'balanced'|'audit'|'forensic' to switch optimization mode. " +
24
23
  "Use action='thinking' with level='full'|'brief'|'off'. " +
25
- "Use action='rebuild' to auto-detect available models from all configured providers and reassign brain/medium/cheap slots. " +
24
+ "Use action='rebuild' to detect available models from configured providers and reassign brain/medium/cheap slots. " +
26
25
  "Use action='flow' with slot='on'|'off' to toggle flow enforcer, or action='flow' alone for audit. " +
27
26
  "Use action='flow' with slot='enforce' and level='on'|'off' to toggle auto-extract TODOs. " +
28
- "Use action='enforce' with slot='on'|'off' to toggle delegation enforcement (blocks direct writes/edits on brain tier). " +
27
+ "Use action='enforce' with slot='on'|'off' to toggle delegation enforcement. " +
29
28
  "Use action='tdd' with slot='on'|'off' to toggle auto-create test skeletons. " +
30
29
  "Use action='tdd' with slot='strict' and level='on'|'off' to toggle strict failing TODO test templates. " +
31
30
  "Use action='tdd' alone for audit. " +
32
31
  "Use action='setup' to create a compatibility profile for first-time users. " +
33
32
  "Use action='project' to show per-project analytics and optimization suggestions. " +
34
33
  "Use action='patterns' to inspect learned project patterns or slot='clear' to clear them. " +
35
- "Use action='guard' to ensure AGENTS.md and README.md exist and stay current. Use action='api-token' with token='<new_token>' to update the API token and re-enable remote control-vector, or token='invalidate' to disable the embedded alpha token " +
34
+ "Use action='guard' to keep AGENTS.md and README.md current. " +
35
+ "Use action='api-token' with token='<new_token>' to update the API token or token='invalidate' to disable the embedded alpha token. " +
36
36
  "Use action='api-bootstrap-token' with token='<new_token>' to store an alpha bootstrap token and exchange it for a normal API token on alpha builds. " +
37
- "Call this when the user says things like 'switch to medium', 'use cheap model', 'disable plugin', 'trinity status'.",
37
+ "Call this when the user says things like 'switch to medium', 'use cheap model', 'disable plugin', or 'trinity status'.",
38
38
  args: {
39
39
  action: deps.tool.schema.enum(["status", "enable", "disable", "set", "mode", "thinking", "flow", "tdd", "setup", "project", "patterns", "rebuild", "diagnose", "help", "enforce", "repair-state", "blackbox", "report", "target", "guard", "api-token", "api-bootstrap-token", "todo", "todo-done", "todo-sync"]).optional(),
40
40
  slot: deps.tool.schema.enum(["brain", "medium", "cheap", "budget", "quality", "speed", "longrun", "auto", "balanced", "audit", "forensic", "vibeultrax", "vibeqmax", "vibemax", "vibelitex", "on", "off", "enforce", "strict", "preview", "apply", "clear", "savings"]).optional(),
@@ -152,7 +152,7 @@ export function createTrinityTool(deps) {
152
152
  try {
153
153
  const res = deps._latestBlackboxState || deps.getBlackboxResolution();
154
154
  if (res && res.n_interactions > 3) {
155
- const momentumIcon = res.momentum > MOMENTUM_SIGNIFICANT_THRESHOLD ? "up up" : res.momentum > 0 ? "up" : res.momentum < -MOMENTUM_SIGNIFICANT_THRESHOLD ? "down down" : res.momentum < 0 ? "down" : "flat";
155
+ const momentumIcon = res.momentum > MOMENTUM_SIGNIFICANT_THRESHOLD ? "" : res.momentum > 0 ? "" : res.momentum < -MOMENTUM_SIGNIFICANT_THRESHOLD ? "" : res.momentum < 0 ? "" : "";
156
156
  const loopTag = res.is_looping ? " (loop)" : "";
157
157
  decisionLine = `${res.resolution} ${res.sub_regime} ${momentumIcon}${loopTag}`;
158
158
  }
@@ -177,7 +177,7 @@ export function createTrinityTool(deps) {
177
177
  ` Flow: ${sel.flow_enabled !== false ? "ON" : "OFF"}${sel.flow_enforce ? " (extract)" : ""}`,
178
178
  ` TDD: ${sel.tdd_enforce ? "ON" : "OFF"}${sel.tdd_strict !== false ? " strict" : ""}${sel.tdd_quality !== false ? " quality" : ""}`,
179
179
  ` Enforce: ${sel.delegation_enforce ? "ON" : "OFF"}${sel.onboarding_mode === "assist" ? " (compatibility)" : " (mandatory)"}`,
180
- ` Lock: ${deps._modelLocked ? `\u{1F512} ON${lockedSlot ? ` (${lockedSlot})` : ""}${lockedModel ? ` ${lockedModel}` : ""}` : "\u{1F513} OFF"}`,
180
+ ` Lock: ${deps._modelLocked ? `LOCK ON${lockedSlot ? ` (${lockedSlot})` : ""}${lockedModel ? ` ${lockedModel}` : ""}` : "LOCK OFF"}`,
181
181
  ` Compatibility: ${onboardingMode === "assist" ? "ASSIST (soft defaults, progressive activation)" : "STRICT (full guardrails)"}`,
182
182
  `|`,
183
183
  `All-time savings:`,
@@ -351,7 +351,7 @@ export function createTrinityTool(deps) {
351
351
  if (ok)
352
352
  deps.writeSelection("onboarding_mode", "strict");
353
353
  return ok
354
- ? `\u{1F6AB} Delegation enforcement ENABLED \u2014 direct writes/edits BLOCKED on brain tier`
354
+ ? `Delegation enforcement ENABLED \u2014 direct writes/edits are blocked on brain tier`
355
355
  : `\u274c Failed to write model-tiers.json`;
356
356
  }
357
357
  const sel = deps.loadSelection();
@@ -365,14 +365,14 @@ export function createTrinityTool(deps) {
365
365
  deps._lockedSlot = lockSlot;
366
366
  deps._lockedModel = lockModel;
367
367
  console.error(`[vibeOS] model LOCKED \u2014 ${lockModel} (${deps.currentTier}) will not auto-reconcile with config`);
368
- return `\u{1F512} Model LOCKED \u2014 ${lockModel} will not change unless you force with \`trinity set\` or \`trinity lock off\`.`;
368
+ return `LOCK ON \u2014 ${lockModel} will not change unless you force with \`trinity set\` or \`trinity lock off\`.`;
369
369
  }
370
370
  if (slot === "off") {
371
371
  deps._modelLocked = false;
372
372
  deps._lockedSlot = null;
373
373
  deps._lockedModel = null;
374
374
  console.error(`[vibeOS] model UNLOCKED \u2014 auto-reconcile re-enabled`);
375
- return `\u{1F513} Model UNLOCKED \u2014 will auto-follow OpenCode config changes.`;
375
+ return `LOCK OFF \u2014 will auto-follow OpenCode config changes.`;
376
376
  }
377
377
  return `\u{1F512} Model lock: ${deps._modelLocked ? "ON (fixed per session)" : "OFF (follows config)"}\nUse \`trinity lock on\` or \`trinity lock off\` to toggle.\nLock is per-session (resets on restart).`;
378
378
  }
@@ -587,12 +587,12 @@ export function createTrinityTool(deps) {
587
587
  suggestions.push(`\ud83d\udca1 Credit at ${credit}% \u2014 switch to medium/cheap slot with \`trinity medium\``);
588
588
  }
589
589
  if (suggestions.length > 0) {
590
- lines.push(`\n\ud83c\udfaf Optimization suggestions:`);
590
+ lines.push(`\nSmall wins:`);
591
591
  for (const s of suggestions)
592
592
  lines.push(` ${s}`);
593
593
  }
594
594
  else {
595
- lines.push(`\n\u2705 No optimization suggestions \u2014 looking good!`);
595
+ lines.push(`\n\u2705 No optimization suggestions \u2014 looking good.`);
596
596
  }
597
597
  lines.push(`\n${L.repeat(40)}`);
598
598
  lines.push(`Run \`trinity help\` for all commands | \`research-audit\` for deep fetch analysis`);