@jigyasudham/veto 2.5.0 → 2.6.0
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/LAUNCH-KIT.md +37 -22
- package/README.md +10 -5
- package/dist/cli/statusline.d.ts +31 -0
- package/dist/cli/statusline.d.ts.map +1 -0
- package/dist/cli/statusline.js +307 -0
- package/dist/cli/statusline.js.map +1 -0
- package/dist/cli.js +63 -5
- package/dist/cli.js.map +1 -1
- package/dist/memory/local.d.ts +7 -0
- package/dist/memory/local.d.ts.map +1 -1
- package/dist/memory/local.js +9 -1
- package/dist/memory/local.js.map +1 -1
- package/dist/memory/schema.d.ts +1 -0
- package/dist/memory/schema.d.ts.map +1 -1
- package/dist/memory/schema.js +16 -0
- package/dist/memory/schema.js.map +1 -1
- package/dist/server/handlers/observability.d.ts.map +1 -1
- package/dist/server/handlers/observability.js +60 -1
- package/dist/server/handlers/observability.js.map +1 -1
- package/dist/tools/definitions.d.ts +13 -0
- package/dist/tools/definitions.d.ts.map +1 -1
- package/dist/tools/definitions.js +14 -0
- package/dist/tools/definitions.js.map +1 -1
- package/package.json +2 -2
- package/server.json +3 -3
package/LAUNCH-KIT.md
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
# Veto Launch Kit
|
|
2
2
|
|
|
3
|
-
Ready-to-paste copy for distribution. Facts current as of v2.
|
|
4
|
-
Core hook: **
|
|
3
|
+
Ready-to-paste copy for distribution. Facts current as of v2.5.0 (npm latest + official MCP Registry).
|
|
4
|
+
Core hook: **93 agentic tools + a 49-specialist agent council for every major AI CLI, at zero extra
|
|
5
5
|
token cost on subscription plans.**
|
|
6
6
|
|
|
7
|
+
> **New in v2.2–2.5 (lead with these — they're the cleanest expression of the "Veto" name):**
|
|
8
|
+
> a guardrail layer that catches AI mistakes before they ship —
|
|
9
|
+
> `veto_dep_verify` (dependency-hallucination guard: flags packages the AI invented),
|
|
10
|
+
> `veto_decisions` (decision-drift enforcement: stops the AI quietly reversing an agreed choice), and
|
|
11
|
+
> `veto_drift_check` (compounding-error circuit breaker). This is the launch's strongest story.
|
|
12
|
+
|
|
7
13
|
Canonical links:
|
|
8
14
|
- npm: https://www.npmjs.com/package/@jigyasudham/veto
|
|
9
15
|
- GitHub: https://github.com/jigyasudham/veto
|
|
@@ -24,7 +30,7 @@ Canonical links:
|
|
|
24
30
|
**Entry line (alphabetical by `owner/name` within the section):**
|
|
25
31
|
|
|
26
32
|
```
|
|
27
|
-
- [jigyasudham/veto](https://github.com/jigyasudham/veto) 📇 🏠 🍎 🪟 🐧 -
|
|
33
|
+
- [jigyasudham/veto](https://github.com/jigyasudham/veto) 📇 🏠 🍎 🪟 🐧 - 93 agentic tools and a 49-specialist agent council (Lead Dev, Architect, Security…) for every major AI CLI — Claude Code, Codex, Gemini, Cursor, Windsurf. Self-learning router, cross-platform memory, dependency-hallucination + decision-drift guards, deterministic agents that optionally upgrade to LLM. Zero extra token cost on subscriptions.
|
|
28
34
|
```
|
|
29
35
|
|
|
30
36
|
**Submit steps:**
|
|
@@ -32,9 +38,9 @@ Canonical links:
|
|
|
32
38
|
gh repo fork punkpeye/awesome-mcp-servers --clone
|
|
33
39
|
# add the line under the Coding Agents section, keeping alphabetical order
|
|
34
40
|
git checkout -b add-veto
|
|
35
|
-
git commit -am "Add Veto —
|
|
41
|
+
git commit -am "Add Veto — 93 MCP tools + 49-agent council for every AI CLI"
|
|
36
42
|
git push -u origin add-veto
|
|
37
|
-
gh pr create --repo punkpeye/awesome-mcp-servers --title "Add Veto" --body "Adds Veto: an MCP server giving every major AI CLI a 49-specialist agent council +
|
|
43
|
+
gh pr create --repo punkpeye/awesome-mcp-servers --title "Add Veto" --body "Adds Veto: an MCP server giving every major AI CLI a 49-specialist agent council + 93 tools, using existing subscriptions (no API keys). MIT, on the official MCP registry as io.github.jigyasudham/veto."
|
|
38
44
|
```
|
|
39
45
|
|
|
40
46
|
---
|
|
@@ -43,16 +49,16 @@ gh pr create --repo punkpeye/awesome-mcp-servers --title "Add Veto" --body "Adds
|
|
|
43
49
|
|
|
44
50
|
**Title (submit the GitHub URL as the link):**
|
|
45
51
|
```
|
|
46
|
-
Show HN: Veto –
|
|
52
|
+
Show HN: Veto – 93 MCP tools and a 49-agent council for every AI CLI
|
|
47
53
|
```
|
|
48
54
|
|
|
49
55
|
**First comment (post immediately after submitting):**
|
|
50
56
|
```
|
|
51
57
|
Hi HN — I built Veto, a single MCP server that plugs into whatever AI CLI you already
|
|
52
|
-
use (Claude Code, Codex, Gemini, Cursor, Windsurf, Zed, JetBrains) and gives it
|
|
58
|
+
use (Claude Code, Codex, Gemini, Cursor, Windsurf, Zed, JetBrains) and gives it 93 tools
|
|
53
59
|
and a council of 49 specialist agents — code review, security/secrets scanning, a 7-agent
|
|
54
|
-
"should we build this" debate, CI gates, SDD agents,
|
|
55
|
-
across CLIs.
|
|
60
|
+
"should we build this" debate, CI gates, SDD agents, guards that catch dependency
|
|
61
|
+
hallucinations and decision drift, and persistent memory that follows you across CLIs.
|
|
56
62
|
|
|
57
63
|
The design decision I'd most like feedback on: the 42 worker agents are *deterministic
|
|
58
64
|
expert modules by default* (regex/AST secret detection, OWASP/CWE rules, complexity metrics)
|
|
@@ -75,7 +81,7 @@ or the cross-CLI memory/handoff. What would you want a tool like this to NOT do?
|
|
|
75
81
|
```
|
|
76
82
|
|
|
77
83
|
> HN tips: post Tue–Thu ~8–10am ET. Don't ask for upvotes. Reply fast and non-defensively;
|
|
78
|
-
> the skeptical "isn't
|
|
84
|
+
> the skeptical "isn't 93 tools bloat?" question is your best moment — answer it with the
|
|
79
85
|
> deterministic-vs-LLM architecture above.
|
|
80
86
|
|
|
81
87
|
---
|
|
@@ -86,7 +92,7 @@ or the cross-CLI memory/handoff. What would you want a tool like this to NOT do?
|
|
|
86
92
|
**Title:** I gave Claude Code a 49-agent council + persistent memory across CLIs — open source, no API keys
|
|
87
93
|
**Body:**
|
|
88
94
|
```
|
|
89
|
-
Veto is an MCP server I've been building that adds
|
|
95
|
+
Veto is an MCP server I've been building that adds 93 tools + 49 specialist agents to Claude
|
|
90
96
|
Code using your existing Claude subscription (no separate API key, no extra token bill on
|
|
91
97
|
Max/Pro).
|
|
92
98
|
|
|
@@ -96,6 +102,9 @@ What it actually does day to day:
|
|
|
96
102
|
debates a plan before you build it
|
|
97
103
|
- memory that saves your session and restores it in Gemini CLI or Codex if you switch — the
|
|
98
104
|
handoff carries full context
|
|
105
|
+
- guards that catch the AI's own mistakes: dependency-hallucination detection (flags packages
|
|
106
|
+
it invented), decision-drift enforcement (stops it reversing a choice you already made), and a
|
|
107
|
+
compounding-error circuit breaker
|
|
99
108
|
- a self-learning router that re-tunes which model tier handles which task
|
|
100
109
|
|
|
101
110
|
Most worker agents are deterministic (real OWASP/CWE/secret-detection code), and upgrade to
|
|
@@ -125,11 +134,11 @@ Repo: https://github.com/jigyasudham/veto — keen on feedback re: wiring it to
|
|
|
125
134
|
```
|
|
126
135
|
|
|
127
136
|
### r/ChatGPTCoding
|
|
128
|
-
**Title:** Open-source MCP server:
|
|
137
|
+
**Title:** Open-source MCP server: 93 tools + 49-agent council that works across Codex, Claude, Gemini & Cursor
|
|
129
138
|
**Body:**
|
|
130
139
|
```
|
|
131
140
|
Veto is an MCP server that gives whatever AI coding CLI you use (Codex, Claude Code, Gemini,
|
|
132
|
-
Cursor, Windsurf) a shared layer:
|
|
141
|
+
Cursor, Windsurf) a shared layer: 93 tools, a 49-specialist agent council, code review +
|
|
133
142
|
security scanning, CI gates, and memory that follows you when you switch tools.
|
|
134
143
|
|
|
135
144
|
The agents are deterministic by default and upgrade to LLM reasoning only when your client
|
|
@@ -150,7 +159,7 @@ https://github.com/jigyasudham/veto
|
|
|
150
159
|
|
|
151
160
|
```
|
|
152
161
|
1/ I shipped Veto — one MCP server that gives every major AI CLI a council of 49 specialist
|
|
153
|
-
agents +
|
|
162
|
+
agents + 93 tools, using your existing subscription. No API keys. No extra token bill.
|
|
154
163
|
|
|
155
164
|
Claude Code, Codex, Gemini, Cursor, Windsurf, Zed, JetBrains — same superpowers everywhere.
|
|
156
165
|
[attach veto.gif]
|
|
@@ -166,7 +175,11 @@ actual trade-offs. It's saved me from a few bad calls already.
|
|
|
166
175
|
4/ And it remembers. Save a session in Claude Code, restore it in Gemini CLI mid-task — the
|
|
167
176
|
handoff carries full context. Plus a router that re-tunes itself every 20 outcomes.
|
|
168
177
|
|
|
169
|
-
5/
|
|
178
|
+
5/ The newest part lives up to the name: a guardrail layer that vetoes the AI's own mistakes —
|
|
179
|
+
catches packages it hallucinated, blocks it from quietly reversing a decision you already made,
|
|
180
|
+
and trips a circuit breaker on compounding errors.
|
|
181
|
+
|
|
182
|
+
6/ MIT. On npm and the official MCP registry.
|
|
170
183
|
|
|
171
184
|
One command: npx @jigyasudham/veto init
|
|
172
185
|
|
|
@@ -189,23 +202,25 @@ self-learning, multi-agent, developer-tools
|
|
|
189
202
|
|
|
190
203
|
**Short description (<=100 chars — matches server.json):**
|
|
191
204
|
```
|
|
192
|
-
|
|
205
|
+
93 agentic MCP tools, 49 specialist agents for every major AI CLI. Self-learning, zero API cost.
|
|
193
206
|
```
|
|
194
207
|
|
|
195
208
|
**One-liner:**
|
|
196
209
|
```
|
|
197
|
-
A council of 49 specialist agents +
|
|
210
|
+
A council of 49 specialist agents + 93 tools for every AI CLI, using your existing subscription.
|
|
198
211
|
```
|
|
199
212
|
|
|
200
213
|
**Long description:**
|
|
201
214
|
```
|
|
202
215
|
Veto is a local MCP server that gives every major AI CLI — Claude Code, Codex, Gemini,
|
|
203
|
-
Antigravity, Cursor, Windsurf, Zed, JetBrains — a shared layer of
|
|
216
|
+
Antigravity, Cursor, Windsurf, Zed, JetBrains — a shared layer of 93 agentic tools and 49
|
|
204
217
|
specialist agents. 42 worker agents (across dev, security, memory, research, quality, and
|
|
205
218
|
workflow domains) run as deterministic expert modules by default and optionally upgrade to LLM
|
|
206
219
|
reasoning via MCP Sampling; a 7-agent Council debates trade-offs before you build. It adds code
|
|
207
|
-
review, security and secrets scanning, CI gates, SDD agents, Playwright automation, a
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
220
|
+
review, security and secrets scanning, CI gates, SDD agents, Playwright automation, a guardrail
|
|
221
|
+
layer that catches the AI's own mistakes (dependency-hallucination detection, decision-drift
|
|
222
|
+
enforcement, and a compounding-error circuit breaker), a self-learning router that re-tunes its
|
|
223
|
+
thresholds every 20 outcomes, and persistent memory that hands off your session across CLIs. On
|
|
224
|
+
a subscription it costs nothing extra; on API billing, Sampling calls count and it warns you.
|
|
225
|
+
MIT licensed.
|
|
211
226
|
```
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# veto
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **93 agentic tools. 49 specialists. Every major AI CLI. Self-learning. Zero extra cost on subscriptions.**
|
|
4
4
|
|
|
5
5
|
An MCP server that runs locally on your machine, plugs into Claude Code, Codex CLI, Gemini CLI, Antigravity CLI, Cursor, Windsurf, Zed, and JetBrains using your existing subscriptions — giving every AI a council of specialist agents, local LLM support, SDD agents, playwright automation, persistent cross-platform memory, a self-learning router that re-tunes its tier thresholds automatically every 20 recorded task outcomes (reviews record outcomes for you; configurable via `auto_apply_learning`), CI/CD gates, workspace discovery, and bidirectional IDE communication.
|
|
6
6
|
|
|
@@ -69,12 +69,12 @@ The 7-agent **Council** is LLM-first — its value is the multi-agent debate —
|
|
|
69
69
|
| **Memory** | `veto_memory_store` · `veto_memory_search` · `veto_memory_delete` · `veto_project_map_update` · `veto_project_map_get` · `veto_pattern_store` · `veto_patterns_list` · `veto_memory_export` · `veto_memory_import` |
|
|
70
70
|
| **Learning** | `veto_record_outcome` · `veto_learning_stats` · `veto_learning_apply` |
|
|
71
71
|
| **Handoff** | `veto_handoff` · `veto_continue` · `veto_platform_setup` |
|
|
72
|
-
| **Observability** | `veto_usage_status` · `veto_audit_log` · `veto_health` · `veto_metrics` |
|
|
72
|
+
| **Observability** | `veto_usage_status` · `veto_audit_log` · `veto_health` · `veto_metrics` · `veto_snapshot` |
|
|
73
73
|
| **Discover** | `veto_discover` · `veto_summarize` · `veto_git_blame` · `veto_changelog` · `veto_onboard` · `veto_debt_register` |
|
|
74
74
|
| **DevTools** | `veto_docs_fetch` · `veto_context_status` · `veto_openapi_gen` · `veto_flag_auditor` · `veto_env_setup` · `veto_commit_message` · `veto_pr_description` · `veto_pr_post` · `veto_prompt_optimizer` · `veto_sre_advisor` · `veto_diagram` · `veto_rca` · `veto_doc_gen` · `veto_postmortem` · `veto_release_notes` · `veto_translate` · `veto_merge_conflict` |
|
|
75
75
|
| **Plugins** | `veto_plugins` |
|
|
76
76
|
|
|
77
|
-
## Compact Mode —
|
|
77
|
+
## Compact Mode — 93 tools without the context tax
|
|
78
78
|
|
|
79
79
|
92 tool schemas cost a client ~16K context tokens before the user types a word. Compact mode advertises a surface that is **5–6× smaller**: seven core tools (`veto_status`, `veto_session_save`, `veto_session_restore`, `veto_route_task`, `veto_council_debate`, `veto_memory_search`, `veto_record_outcome`) plus two meta-tools — `veto_find_tools` searches the full catalog by keyword and returns matching schemas on demand; `veto_call` invokes any catalog tool by name. Every tool remains directly callable in both modes; compact only changes what is advertised up front.
|
|
80
80
|
|
|
@@ -209,7 +209,7 @@ veto sessions # List last 20 saved sessions ([auto] badge on
|
|
|
209
209
|
veto sessions --clean # Remove auto-saves older than 7 days
|
|
210
210
|
veto memory [query] # Search knowledge base (blank = all entries)
|
|
211
211
|
veto patterns [prefix] # List learned agent/routing patterns
|
|
212
|
-
veto tools [filter] # List all
|
|
212
|
+
veto tools [filter] # List all 93 MCP tools (--json for machine output)
|
|
213
213
|
veto agents [filter] # List all 49 specialists — workers + council (--json)
|
|
214
214
|
veto routing [status|log|reset] # Inspect the opt-in routing feedback loop
|
|
215
215
|
veto hook install # Install pre-commit secrets scan hook
|
|
@@ -417,6 +417,11 @@ Platform switching is manual — Veto surfaces which platform has budget remaini
|
|
|
417
417
|
|
|
418
418
|
## Release Notes
|
|
419
419
|
|
|
420
|
+
### 2.6.0
|
|
421
|
+
- **`veto statusline` — a compact Veto line under any AI CLI prompt.** `veto statusline install` wires a `statusLine` command into Claude Code's settings.json (backed up; `uninstall` restores it byte-for-byte). The `print` hot path is read-only, fast, and crash-proof — it renders e.g. `⬡ veto GREEN · router 94% · claude 42% · mem 15` and degrades to a neutral `⬡ veto` if the DB is missing or locked. Lives in the CLI so every Veto user gets it in any terminal, not just the VS Code HUD.
|
|
422
|
+
- **`veto_snapshot` — one-call editor/HUD aggregate.** Returns `{ session, council, routerTop, rate, memoryCount, health }` in a single read-only call, so editor integrations (veto-vscode) can stop reading internal tables directly. Tool count is now **93**.
|
|
423
|
+
- **Stable read-contract versioning.** `veto.db` now stamps `PRAGMA user_version` (`VETO_DB_SCHEMA_VERSION`) on every open, so external readers can detect schema drift and degrade gracefully instead of silently blanking.
|
|
424
|
+
|
|
420
425
|
### 2.5.0
|
|
421
426
|
- **`veto_drift_check` — compounding-error circuit breaker.** Scans the recent tool-call trace for consecutive failures, repeated error messages, and single-tool thrashing, then runs the `debugger` agent for a concrete recovery step. See [Compounding-Error Circuit Breaker](#compounding-error-circuit-breaker).
|
|
422
427
|
- **Council calibration fixes.** Tightened the deterministic council's pattern triggers so they no longer false-fire on generic words (e.g. "server", "transport") or semver strings like `v2.5.0`, and removed stale hardcoded tool counts from agent reasoning.
|
|
@@ -438,7 +443,7 @@ Platform switching is manual — Veto surfaces which platform has budget remaini
|
|
|
438
443
|
|
|
439
444
|
## Project Structure
|
|
440
445
|
|
|
441
|
-
Veto is a single MCP server (`src/server.ts`) that registers
|
|
446
|
+
Veto is a single MCP server (`src/server.ts`) that registers 93 tools, MCP Resources, and Prompts, then dispatches every tool call through a per-domain **handler registry** — there is no monolithic switch. Each domain owns a `HandlerMap` module under `src/server/handlers/`:
|
|
442
447
|
|
|
443
448
|
| Module | Tools | Domain |
|
|
444
449
|
|---|---|---|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface StatuslineData {
|
|
2
|
+
verdict: 'GREEN' | 'YELLOW' | 'RED' | null;
|
|
3
|
+
routerPct: number | null;
|
|
4
|
+
platform: string | null;
|
|
5
|
+
ratePct: number | null;
|
|
6
|
+
memCount: number | null;
|
|
7
|
+
}
|
|
8
|
+
export declare function readStatuslineData(): StatuslineData;
|
|
9
|
+
export interface ComposeOptions {
|
|
10
|
+
color?: boolean;
|
|
11
|
+
ascii?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function composeStatusline(data: StatuslineData, opts?: ComposeOptions): string;
|
|
14
|
+
export declare function printStatusline(opts?: ComposeOptions): void;
|
|
15
|
+
export interface InstallResult {
|
|
16
|
+
ok: boolean;
|
|
17
|
+
message: string;
|
|
18
|
+
changed?: boolean;
|
|
19
|
+
backupPath?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function installStatusline(client?: string, opts?: {
|
|
22
|
+
force?: boolean;
|
|
23
|
+
dryRun?: boolean;
|
|
24
|
+
}): InstallResult;
|
|
25
|
+
export declare function uninstallStatusline(client?: string): InstallResult;
|
|
26
|
+
export declare function statuslineStatusInfo(client?: string): {
|
|
27
|
+
installed: boolean;
|
|
28
|
+
settingsPath: string | null;
|
|
29
|
+
sample: string;
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=statusline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statusline.d.ts","sourceRoot":"","sources":["../../src/cli/statusline.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,IAAI,CAAC;IAC3C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAqBD,wBAAgB,kBAAkB,IAAI,cAAc,CAuBnD;AA8DD,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAUD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,GAAE,cAAmB,GAAG,MAAM,CAgCzF;AAGD,wBAAgB,eAAe,CAAC,IAAI,GAAE,cAAmB,GAAG,IAAI,CAQ/D;AAkCD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,SAAW,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,aAAa,CA0DpH;AAED,wBAAgB,mBAAmB,CAAC,MAAM,SAAW,GAAG,aAAa,CA4CpE;AAED,wBAAgB,oBAAoB,CAAC,MAAM,SAAW,GAAG;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAY3H"}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
// veto statusline — a compact, always-on Veto line beneath the AI CLI prompt.
|
|
2
|
+
//
|
|
3
|
+
// Lives in the CLI (not the VS Code extension) so EVERY Veto user gets it in any
|
|
4
|
+
// terminal. Claude Code natively supports a custom `statusLine` command in
|
|
5
|
+
// settings.json; `veto statusline install` wires this command in.
|
|
6
|
+
//
|
|
7
|
+
// The `print` subcommand is a HOT PATH: it runs on every prompt render, so it
|
|
8
|
+
// must be read-only, fast (<50ms), and crash-proof. It opens a dedicated
|
|
9
|
+
// read-only DB connection (no migrations, no table creation, no writes) and on
|
|
10
|
+
// ANY problem — missing DB, locked DB (WAL / SQLITE_BUSY), bad row — it prints a
|
|
11
|
+
// neutral `⬡ veto` and exits 0. It never throws and never blocks the prompt.
|
|
12
|
+
import { createRequire } from 'node:module';
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from 'node:fs';
|
|
14
|
+
import { join, dirname } from 'node:path';
|
|
15
|
+
import { homedir } from 'node:os';
|
|
16
|
+
import { getDbPath, getDb } from '../memory/local.js';
|
|
17
|
+
import { getConfig } from '../memory/config.js';
|
|
18
|
+
// node:sqlite is a Node 22.5+ built-in — use createRequire so bundlers skip it.
|
|
19
|
+
const _require = createRequire(import.meta.url);
|
|
20
|
+
const DbSync = _require('node:sqlite').DatabaseSync;
|
|
21
|
+
const EMPTY = {
|
|
22
|
+
verdict: null, routerPct: null, platform: null, ratePct: null, memCount: null,
|
|
23
|
+
};
|
|
24
|
+
// Open the veto DB read-only. Returns null if it can't (missing/locked/corrupt).
|
|
25
|
+
function openReadOnly(path) {
|
|
26
|
+
try {
|
|
27
|
+
const db = new DbSync(path, { readOnly: true });
|
|
28
|
+
// query_only is belt-and-suspenders; busy_timeout keeps us from blocking the
|
|
29
|
+
// prompt if a writer holds the WAL lock — fail fast to the neutral fallback.
|
|
30
|
+
db.exec('PRAGMA query_only = ON');
|
|
31
|
+
db.exec('PRAGMA busy_timeout = 50');
|
|
32
|
+
return db;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Crash-proof read of everything the statusline shows. Never throws.
|
|
39
|
+
export function readStatuslineData() {
|
|
40
|
+
let db = null;
|
|
41
|
+
let closeAfter = false;
|
|
42
|
+
try {
|
|
43
|
+
const path = getDbPath();
|
|
44
|
+
if (path === ':memory:') {
|
|
45
|
+
// In-memory (tests / special cases): a fresh read-only handle would be a
|
|
46
|
+
// different empty DB, so reuse the shared reader.
|
|
47
|
+
db = getDb();
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
if (!existsSync(path))
|
|
51
|
+
return EMPTY;
|
|
52
|
+
db = openReadOnly(path);
|
|
53
|
+
closeAfter = true;
|
|
54
|
+
if (!db)
|
|
55
|
+
return EMPTY;
|
|
56
|
+
}
|
|
57
|
+
return queryStatusline(db);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return EMPTY;
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
if (closeAfter && db) {
|
|
64
|
+
try {
|
|
65
|
+
db.close();
|
|
66
|
+
}
|
|
67
|
+
catch { /* ignore */ }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function queryStatusline(db) {
|
|
72
|
+
const data = { ...EMPTY };
|
|
73
|
+
// Each block is independently guarded: a missing/older table degrades that one
|
|
74
|
+
// segment to null rather than blanking the whole line.
|
|
75
|
+
try {
|
|
76
|
+
const row = db.prepare('SELECT verdict FROM council_outcomes ORDER BY debated_at DESC LIMIT 1').get();
|
|
77
|
+
const v = (row?.verdict ?? '').toUpperCase();
|
|
78
|
+
if (v === 'GREEN' || v === 'YELLOW' || v === 'RED')
|
|
79
|
+
data.verdict = v;
|
|
80
|
+
}
|
|
81
|
+
catch { /* segment off */ }
|
|
82
|
+
try {
|
|
83
|
+
// Top confidence among learned patterns. Exclude router.* threshold rows and
|
|
84
|
+
// composed_agent:* definitions — those carry config/JSON, not a learning score.
|
|
85
|
+
const row = db.prepare(`SELECT confidence FROM patterns
|
|
86
|
+
WHERE pattern_key NOT LIKE 'router.%' AND pattern_key NOT LIKE 'composed_agent:%'
|
|
87
|
+
ORDER BY confidence DESC, seen_count DESC LIMIT 1`).get();
|
|
88
|
+
if (typeof row?.confidence === 'number') {
|
|
89
|
+
data.routerPct = Math.max(0, Math.min(100, Math.round(row.confidence * 100)));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch { /* segment off */ }
|
|
93
|
+
try {
|
|
94
|
+
const row = db.prepare('SELECT platform FROM sessions ORDER BY created_at DESC LIMIT 1').get();
|
|
95
|
+
if (row?.platform)
|
|
96
|
+
data.platform = row.platform;
|
|
97
|
+
}
|
|
98
|
+
catch { /* segment off */ }
|
|
99
|
+
// Rate % for the active platform today — mirrors router/rate-monitor semantics
|
|
100
|
+
// (min(100, round(tokens / dailyBudget * 100))).
|
|
101
|
+
if (data.platform) {
|
|
102
|
+
try {
|
|
103
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
104
|
+
const row = db.prepare('SELECT token_count FROM rate_usage WHERE platform = ? AND date_key = ?').get(data.platform, today);
|
|
105
|
+
const tokens = row?.token_count ?? 0;
|
|
106
|
+
const budgets = getConfig().dailyTokenBudget;
|
|
107
|
+
const budget = budgets[data.platform];
|
|
108
|
+
if (budget && budget > 0) {
|
|
109
|
+
data.ratePct = Math.min(100, Math.round((tokens / budget) * 100));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch { /* segment off */ }
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
const row = db.prepare('SELECT COUNT(*) AS n FROM knowledge_base').get();
|
|
116
|
+
if (typeof row?.n === 'number')
|
|
117
|
+
data.memCount = row.n;
|
|
118
|
+
}
|
|
119
|
+
catch { /* segment off */ }
|
|
120
|
+
return data;
|
|
121
|
+
}
|
|
122
|
+
const ANSI = {
|
|
123
|
+
reset: '\x1b[0m',
|
|
124
|
+
dim: '\x1b[2m',
|
|
125
|
+
green: '\x1b[32m',
|
|
126
|
+
yellow: '\x1b[33m',
|
|
127
|
+
red: '\x1b[31m',
|
|
128
|
+
};
|
|
129
|
+
export function composeStatusline(data, opts = {}) {
|
|
130
|
+
const color = opts.color ?? !process.env.NO_COLOR;
|
|
131
|
+
const ascii = opts.ascii ?? Boolean(process.env.VETO_STATUSLINE_ASCII);
|
|
132
|
+
const paint = (s, code) => (color ? `${code}${s}${ANSI.reset}` : s);
|
|
133
|
+
const head = `${ascii ? '#' : '⬡'} veto`;
|
|
134
|
+
const segments = [];
|
|
135
|
+
if (data.verdict) {
|
|
136
|
+
const code = data.verdict === 'GREEN' ? ANSI.green
|
|
137
|
+
: data.verdict === 'YELLOW' ? ANSI.yellow
|
|
138
|
+
: ANSI.red;
|
|
139
|
+
segments.push(paint(data.verdict, code));
|
|
140
|
+
}
|
|
141
|
+
if (data.routerPct !== null) {
|
|
142
|
+
segments.push(`router ${data.routerPct}%`);
|
|
143
|
+
}
|
|
144
|
+
if (data.platform && data.ratePct !== null) {
|
|
145
|
+
// Color the rate % using the same thresholds as rate-monitor (warn ≥70, crit ≥90).
|
|
146
|
+
const label = `${data.platform} ${data.ratePct}%`;
|
|
147
|
+
const code = data.ratePct >= 90 ? ANSI.red : data.ratePct >= 70 ? ANSI.yellow : '';
|
|
148
|
+
segments.push(code ? paint(label, code) : label);
|
|
149
|
+
}
|
|
150
|
+
if (data.memCount !== null) {
|
|
151
|
+
segments.push(`mem ${data.memCount}`);
|
|
152
|
+
}
|
|
153
|
+
if (segments.length === 0)
|
|
154
|
+
return head; // neutral fallback
|
|
155
|
+
return `${head} ${segments.join(' · ')}`;
|
|
156
|
+
}
|
|
157
|
+
// The hot path: read + render + print. Never throws, always exits 0.
|
|
158
|
+
export function printStatusline(opts = {}) {
|
|
159
|
+
let line;
|
|
160
|
+
try {
|
|
161
|
+
line = composeStatusline(readStatuslineData(), opts);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
line = composeStatusline(EMPTY, opts);
|
|
165
|
+
}
|
|
166
|
+
process.stdout.write(line + '\n');
|
|
167
|
+
}
|
|
168
|
+
// Resolve the settings.json for a client. Only Claude Code exposes a documented
|
|
169
|
+
// `statusLine` command hook today; others are gated behind --client as a stretch.
|
|
170
|
+
function resolveClient(client) {
|
|
171
|
+
const HOME = homedir();
|
|
172
|
+
switch (client) {
|
|
173
|
+
case 'claude':
|
|
174
|
+
// VETO_STATUSLINE_SETTINGS overrides the path (used by tests).
|
|
175
|
+
return {
|
|
176
|
+
name: 'Claude Code',
|
|
177
|
+
settingsPath: process.env.VETO_STATUSLINE_SETTINGS ?? join(HOME, '.claude', 'settings.json'),
|
|
178
|
+
};
|
|
179
|
+
default:
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const STATUSLINE_VALUE = { type: 'command', command: 'veto statusline print' };
|
|
184
|
+
const BACKUP_SUFFIX = '.veto-statusline-backup';
|
|
185
|
+
const NO_ORIGINAL = '__VETO_NO_ORIGINAL_FILE__';
|
|
186
|
+
function isOurStatusLine(v) {
|
|
187
|
+
return Boolean(v) && typeof v === 'object'
|
|
188
|
+
&& v.command === STATUSLINE_VALUE.command;
|
|
189
|
+
}
|
|
190
|
+
export function installStatusline(client = 'claude', opts = {}) {
|
|
191
|
+
const target = resolveClient(client);
|
|
192
|
+
if (!target) {
|
|
193
|
+
return { ok: false, message: `Unknown client "${client}". Supported: claude.` };
|
|
194
|
+
}
|
|
195
|
+
const { settingsPath } = target;
|
|
196
|
+
const existed = existsSync(settingsPath);
|
|
197
|
+
let settings = {};
|
|
198
|
+
let rawOriginal = '';
|
|
199
|
+
if (existed) {
|
|
200
|
+
try {
|
|
201
|
+
rawOriginal = readFileSync(settingsPath, 'utf8');
|
|
202
|
+
settings = JSON.parse(rawOriginal);
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return { ok: false, message: `Refusing to touch ${settingsPath}: it is not valid JSON.` };
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const current = settings.statusLine;
|
|
209
|
+
if (isOurStatusLine(current)) {
|
|
210
|
+
return { ok: true, changed: false, message: `Already installed for ${target.name} (${settingsPath}).` };
|
|
211
|
+
}
|
|
212
|
+
if (current !== undefined && !opts.force) {
|
|
213
|
+
return {
|
|
214
|
+
ok: false,
|
|
215
|
+
message: `${target.name} already has a custom statusLine. Re-run with --force to replace it `
|
|
216
|
+
+ `(your original is backed up and restored on uninstall).`,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
if (opts.dryRun) {
|
|
220
|
+
return {
|
|
221
|
+
ok: true,
|
|
222
|
+
changed: false,
|
|
223
|
+
message: `[dry-run] Would set statusLine → ${JSON.stringify(STATUSLINE_VALUE)} in ${settingsPath}`
|
|
224
|
+
+ (current !== undefined ? ` (replacing existing statusLine).` : `.`),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
// Back up byte-for-byte so uninstall can restore exactly. Only create the
|
|
228
|
+
// backup once (a re-install must not overwrite the true original).
|
|
229
|
+
const backupPath = settingsPath + BACKUP_SUFFIX;
|
|
230
|
+
if (!existsSync(backupPath)) {
|
|
231
|
+
writeFileSync(backupPath, existed ? rawOriginal : NO_ORIGINAL, 'utf8');
|
|
232
|
+
}
|
|
233
|
+
settings.statusLine = { ...STATUSLINE_VALUE };
|
|
234
|
+
if (!existed)
|
|
235
|
+
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
236
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
|
|
237
|
+
return {
|
|
238
|
+
ok: true,
|
|
239
|
+
changed: true,
|
|
240
|
+
backupPath,
|
|
241
|
+
message: `Installed Veto statusline for ${target.name}.\n ${settingsPath}\n backup: ${backupPath}`
|
|
242
|
+
+ (current !== undefined ? `\n (replaced your previous statusLine — restored on uninstall)` : ``),
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
export function uninstallStatusline(client = 'claude') {
|
|
246
|
+
const target = resolveClient(client);
|
|
247
|
+
if (!target) {
|
|
248
|
+
return { ok: false, message: `Unknown client "${client}". Supported: claude.` };
|
|
249
|
+
}
|
|
250
|
+
const { settingsPath } = target;
|
|
251
|
+
const backupPath = settingsPath + BACKUP_SUFFIX;
|
|
252
|
+
if (existsSync(backupPath)) {
|
|
253
|
+
const backup = readFileSync(backupPath, 'utf8');
|
|
254
|
+
if (backup === NO_ORIGINAL) {
|
|
255
|
+
// There was no settings file before us — remove our key; delete the file if
|
|
256
|
+
// it now holds nothing else.
|
|
257
|
+
if (existsSync(settingsPath)) {
|
|
258
|
+
try {
|
|
259
|
+
const settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
260
|
+
delete settings.statusLine;
|
|
261
|
+
if (Object.keys(settings).length === 0) {
|
|
262
|
+
unlinkSync(settingsPath);
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
catch { /* leave as-is if unreadable */ }
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
// Restore the original file byte-for-byte.
|
|
273
|
+
writeFileSync(settingsPath, backup, 'utf8');
|
|
274
|
+
}
|
|
275
|
+
unlinkSync(backupPath);
|
|
276
|
+
return { ok: true, changed: true, message: `Uninstalled Veto statusline for ${target.name} (restored ${settingsPath}).` };
|
|
277
|
+
}
|
|
278
|
+
// No backup — best-effort removal of our key only.
|
|
279
|
+
if (existsSync(settingsPath)) {
|
|
280
|
+
try {
|
|
281
|
+
const settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
282
|
+
if (isOurStatusLine(settings.statusLine)) {
|
|
283
|
+
delete settings.statusLine;
|
|
284
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
|
|
285
|
+
return { ok: true, changed: true, message: `Removed Veto statusline from ${settingsPath}.` };
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch { /* fall through */ }
|
|
289
|
+
}
|
|
290
|
+
return { ok: true, changed: false, message: `Veto statusline was not installed for ${target.name}.` };
|
|
291
|
+
}
|
|
292
|
+
export function statuslineStatusInfo(client = 'claude') {
|
|
293
|
+
const target = resolveClient(client);
|
|
294
|
+
const sample = composeStatusline(readStatuslineData());
|
|
295
|
+
if (!target)
|
|
296
|
+
return { installed: false, settingsPath: null, sample };
|
|
297
|
+
let installed = false;
|
|
298
|
+
if (existsSync(target.settingsPath)) {
|
|
299
|
+
try {
|
|
300
|
+
const settings = JSON.parse(readFileSync(target.settingsPath, 'utf8'));
|
|
301
|
+
installed = isOurStatusLine(settings.statusLine);
|
|
302
|
+
}
|
|
303
|
+
catch { /* installed stays false */ }
|
|
304
|
+
}
|
|
305
|
+
return { installed, settingsPath: target.settingsPath, sample };
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=statusline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statusline.js","sourceRoot":"","sources":["../../src/cli/statusline.ts"],"names":[],"mappings":"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"}
|