@krtclcdy/tersio 2.0.0 → 2.0.1

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/README.md CHANGED
@@ -61,16 +61,18 @@ User-level installs also register the package in `~/.omp/plugins` (visible in OM
61
61
 
62
62
  ## Benchmarks
63
63
 
64
- Measured before/after — real `o200k_base` token counts, samples and run protocol in [BENCHMARK.md](./BENCHMARK.md). Overhead is paid once per session; savings accumulate per reply, command, or task.
64
+ Measured savings against the same workload without the modes. Token counts are real `o200k_base` BPE tokens (js-tiktoken), not chars÷4 estimates. Sample protocol, per-sample data, and caveats in [BENCHMARK.md](./BENCHMARK.md).
65
65
 
66
- | Mode | Overhead (once) | Before | After | Saving | Pays off after |
67
- |---|---:|---:|---:|---:|---|
68
- | `/caveman lite` | 46 tok | 146 tok/reply | 67 | −55% | 1 reply |
69
- | `/caveman full` | 172 tok | 146 tok/reply | 61 | −58% | ~2 replies |
70
- | `/caveman ultra` | 68 tok | 146 tok/reply | 34 | −77% | 1 reply |
71
- | `/rtk on` | 165 tok | 537 tok (grep) | 469 | −13% (−34% on `git status`) | varies |
72
- | `/ponytail full` | 76 tok | 261–481 tok/task | 108–143 | −59 to −70% | first task |
73
- | `/combo balanced` | 480 tok | 944 tok mixed turn | 638 | −32%/turn | first turn |
66
+ | Measured surface (n) | Baseline → Tersio | Δ |
67
+ |---|---|---|
68
+ | Terse reply, caveman lite — BPE tok (3 samples, p50) | 146 → 73 tok | **−52.6%** |
69
+ | Terse reply, caveman full — BPE tok (3 samples, p50) | 154 → 58 tok | **−62.3%** |
70
+ | Terse reply, caveman ultra — BPE tok (3 samples, p50) | 146 → 33 tok | **−78.6%** |
71
+ | Code diff, ponytail minimal-ladder — BPE tok (2 tasks) | 261–481 → 108–143 tok | **−58.6…−70.3%** |
72
+ | Shell output, rtk — `git status` — BPE tok | 32 → 21 tok | **−34.4%** |
73
+ | Shell output, rtk — repo `grep` — BPE tok | 537 → 469 tok | **−12.7%** |
74
+
75
+ Break-even math, balanced preset (caveman full + rtk + ponytail): `⌈overhead ÷ saving-per-turn⌉ = ⌈480 ÷ 306⌉ = 2 turns`, where a mixed turn (reply + `git status`-class command + code task) costs 944 tok baseline vs 638 tok with Tersio — a 0.68× ratio. Every turn after turn 2 nets ≈ −32%. RTK keeps diffs and failing-test output exact by design (−0.4% and −1.5% there), concentrating savings where noise lives.
74
76
 
75
77
  ## CLI
76
78
 
@@ -80,7 +82,7 @@ Measured before/after — real `o200k_base` token counts, samples and run protoc
80
82
  | `tersio update` | Refresh from the latest release |
81
83
  | `tersio reinstall` | Fresh install, preserving the Ponytail package |
82
84
  | `tersio doctor` | Check OMP, extension, Ponytail, and RTK health |
83
- | `tersio uninstall` | Remove extensions and registration (`--remove-rtk`, `--remove-ponytail` for more) |
85
+ | `tersio uninstall` | Remove extensions, registration, and the Ponytail plugin (`--keep-ponytail` keeps Ponytail; `--remove-rtk` also removes the RTK binary) |
84
86
  | `tersio version` | Print version |
85
87
 
86
88
  Flags: `--dry-run`, `--yes`/`-y`, `--verbose`, `--scope`, `--combo-default`/`--caveman-default`/`--rtk-default`/`--ponytail-default`. Legacy `--doctor` / `--uninstall` forms still work.
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { fileURLToPath } from 'node:url';
3
3
  import { dirname, join } from 'node:path';
4
- import { asPromptArray, getSharedComboState, isComboPresetActive, isOmpSubagentPrompt, lastCustomValue, normalizeInputCommand, normalizeMode, paintStatusBar, sessionEntries, setSharedComboMode } from '../shared/session-state.js';
4
+ import { asPromptArray, getSharedComboState, isComboPresetActive, isOmpSubagentPrompt, lastCustomValue, normalizeInputCommand, normalizeMode, paintStatusBar, reconcileSharedComboEntries, sessionEntries, setSharedComboMode } from '../shared/session-state.js';
5
5
  import { readCavemanDefault } from '../shared/plugin-settings.js';
6
6
  const CAVERN_DIR = dirname(fileURLToPath(import.meta.url));
7
7
  const RULE_PATH = join(CAVERN_DIR, 'rule.md');
@@ -96,6 +96,11 @@ export default function cavemanSessionExtension(pi) {
96
96
  });
97
97
  function restoreMode(ctx) {
98
98
  const entries = sessionEntries(ctx);
99
+ // Publish the persisted combo state (incl. combo-level) before painting:
100
+ // bar suppression reads the in-process bridge, which is empty in a fresh
101
+ // host until the combo extension reconciles — and its reconcile is
102
+ // UI-gated. Deriving it here makes suppression independent of load order.
103
+ reconcileSharedComboEntries(entries);
99
104
  // Persisted session state wins; a fresh session falls back to the
100
105
  // installer/user-configured default (off unless configured).
101
106
  const persisted = resolveMode(entries, '');
@@ -29,7 +29,6 @@ function loadPonytailInstructions(mode) {
29
29
  }
30
30
  export default function comboToggleExtension(pi) {
31
31
  pi.setLabel?.('Combo session toggle (all 3 add-ons)');
32
- let currentState = getSharedComboState();
33
32
  let lastCtx = undefined;
34
33
  function syncStatus(ctx) {
35
34
  if (ctx)
@@ -43,11 +42,14 @@ export default function comboToggleExtension(pi) {
43
42
  c.ui.setStatus('combo', undefined);
44
43
  return;
45
44
  }
45
+ // Read the live bridge, not cached extension state: sibling extensions
46
+ // reconcile it from persisted entries before this one runs.
47
+ const state = getSharedComboState();
46
48
  const theme = c.ui.theme;
47
- const c0 = currentState.caveman.toUpperCase();
48
- const r = currentState.rtk.toUpperCase();
49
- const p = currentState.ponytail.toUpperCase();
50
- const lvl = currentState.level.toUpperCase();
49
+ const c0 = state.caveman.toUpperCase();
50
+ const r = state.rtk.toUpperCase();
51
+ const p = state.ponytail.toUpperCase();
52
+ const lvl = state.level.toUpperCase();
51
53
  const label = `combo ${lvl}: 🪨caveman=${c0} ⚡rtk=${r} 🦥ponytail=${p}`;
52
54
  c.ui.setStatus('combo', theme?.fg ? `${theme.fg('accent', '🧩')} ${theme.fg('muted', label)}` : `🧩 ${label}`);
53
55
  // Clobber any sibling bars another extension may have painted in a race
@@ -67,13 +69,12 @@ export default function comboToggleExtension(pi) {
67
69
  pi.appendEntry?.('combo-level', { level });
68
70
  }
69
71
  function useState(state, ctx) {
70
- currentState = state;
71
72
  syncStatus(ctx);
72
73
  return state;
73
74
  }
74
75
  function reconcile(ctx) {
75
76
  if (!ctx?.hasUI)
76
- return currentState;
77
+ return getSharedComboState();
77
78
  return useState(reconcileSharedComboEntries(sessionEntries(ctx)), ctx);
78
79
  }
79
80
  function listen(ctx) {
@@ -109,7 +110,7 @@ export default function comboToggleExtension(pi) {
109
110
  }
110
111
  persistPreset(level);
111
112
  useState(setSharedComboLevel(level), ctx);
112
- ctx?.ui?.notify?.(`Combo ${level} applied: ${levelSummary(currentState)}`, 'info');
113
+ ctx?.ui?.notify?.(`Combo ${level} applied: ${levelSummary(getSharedComboState())}`, 'info');
113
114
  if (ctx?.reload)
114
115
  await ctx.reload();
115
116
  },
@@ -1,6 +1,6 @@
1
1
  import os from 'node:os';
2
2
  import path from 'node:path';
3
- import { asPromptArray, getSharedComboState, isComboPresetActive, isOmpSubagentPrompt, lastCustomValue, normalizeInputCommand, paintStatusBar, sessionEntries, setSharedComboMode } from '../shared/session-state.js';
3
+ import { asPromptArray, getSharedComboState, isComboPresetActive, isOmpSubagentPrompt, lastCustomValue, normalizeInputCommand, paintStatusBar, reconcileSharedComboEntries, sessionEntries, setSharedComboMode } from '../shared/session-state.js';
4
4
  import { readRtkDefault } from '../shared/plugin-settings.js';
5
5
  const DEFAULT_ENABLED = false;
6
6
  function asBoolean(value) {
@@ -102,6 +102,11 @@ export default function rtkSessionExtension(pi) {
102
102
  });
103
103
  function restoreEnabled(ctx) {
104
104
  const entries = sessionEntries(ctx);
105
+ // Publish the persisted combo state (incl. combo-level) before painting:
106
+ // bar suppression reads the in-process bridge, which is empty in a fresh
107
+ // host until the combo extension reconciles — and its reconcile is
108
+ // UI-gated. Deriving it here makes suppression independent of load order.
109
+ reconcileSharedComboEntries(entries);
105
110
  // Persisted session state wins; a fresh session falls back to the
106
111
  // installer/user-configured default (off unless configured).
107
112
  const persisted = resolveEnabled(entries);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krtclcdy/tersio",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "✂️ Token-saving OMP add-ons: terse Caveman replies, compact RTK shell output, lean Ponytail code calls — one-command combo presets.",
5
5
  "keywords": [
6
6
  "omp",
package/tersio.js CHANGED
@@ -69,6 +69,7 @@ const verbose = args.includes('--verbose');
69
69
  const doctor = command === 'doctor' || args.includes('--doctor');
70
70
  const uninstall = command === 'uninstall' || args.includes('--uninstall');
71
71
  const removePonytail = args.includes('--remove-ponytail');
72
+ const keepPonytail = args.includes('--keep-ponytail');
72
73
  const removeRtk = args.includes('--remove-rtk');
73
74
  const scopeFlag = flagValue('--scope')?.toLowerCase() ?? null;
74
75
  // --- Profile selection (session-start mode defaults) ---
@@ -92,7 +93,7 @@ Commands:
92
93
 
93
94
  Options:
94
95
  --scope user|project|both
95
- --remove-ponytail (uninstall: also remove the Ponytail plugin)
96
+ --keep-ponytail (uninstall: keep the Ponytail plugin — removed by default)
96
97
  --remove-rtk (uninstall: also remove the RTK binary)
97
98
  --combo-default off|medium|balanced|max (implies caveman, rtk, ponytail)
98
99
  --caveman-default off|lite|full|ultra|wenyan (override; default follows combo)
@@ -800,7 +801,9 @@ async function removeUninstallTarget(target, shouldDryRun, recursive = true) {
800
801
  async function runUninstall(options = {}) {
801
802
  const shouldDryRun = options.dryRun ?? dryRun;
802
803
  const confirmed = (options.yes ?? yes) || shouldDryRun;
803
- const shouldRemovePonytail = options.removePonytail ?? removePonytail;
804
+ // Ponytail ships with Tersio's presets, so a full uninstall removes it too;
805
+ // --keep-ponytail opts out and reinstall always preserves it.
806
+ const shouldRemovePonytail = options.removePonytail ?? (removePonytail || !keepPonytail);
804
807
  const shouldRemoveRtk = options.removeRtk ?? removeRtk;
805
808
  console.log('\n=== Tersio Uninstall ===\n');
806
809
  const extDir = path.join(OMP_AGENT_DIR, 'extensions');