@jigyasudham/veto 1.4.1 → 1.4.3
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 +148 -19
- package/dist/council/llm-council.d.ts +3 -0
- package/dist/council/llm-council.d.ts.map +1 -1
- package/dist/council/llm-council.js +86 -3
- package/dist/council/llm-council.js.map +1 -1
- package/dist/council/session-summarizer.d.ts +25 -0
- package/dist/council/session-summarizer.d.ts.map +1 -0
- package/dist/council/session-summarizer.js +130 -0
- package/dist/council/session-summarizer.js.map +1 -0
- package/dist/server.js +69 -7
- package/dist/server.js.map +1 -1
- package/dist/skills/memory/skill-session-save.d.ts.map +1 -1
- package/dist/skills/memory/skill-session-save.js +5 -9
- package/dist/skills/memory/skill-session-save.js.map +1 -1
- package/dist/tools/definitions.d.ts +164 -6
- package/dist/tools/definitions.d.ts.map +1 -1
- package/dist/tools/definitions.js +24 -6
- package/dist/tools/definitions.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,9 +12,9 @@ An MCP server that runs locally on your machine, plugs into Claude Code, Codex C
|
|
|
12
12
|
|
|
13
13
|
Veto has two fundamentally different types of agents:
|
|
14
14
|
|
|
15
|
-
### Council agents — real LLM reasoning (7 agents)
|
|
15
|
+
### Council agents — real LLM reasoning via agentic loop (7 agents)
|
|
16
16
|
|
|
17
|
-
The 7 council agents
|
|
17
|
+
The 7 council agents use the **agentic loop pattern** — no API key, no extra cost, works on Claude Code, Gemini CLI, and Codex CLI identically. The tool returns an instant deterministic result plus a `debate_prompt`. You (the host AI) read it, reason as all 7 specialists, and pass the responses back. Veto runs the verdict engine on your real LLM output.
|
|
18
18
|
|
|
19
19
|
| Agent | Role |
|
|
20
20
|
|---|---|
|
|
@@ -31,7 +31,7 @@ Use `strictness` to control depth:
|
|
|
31
31
|
- `standard` — all 7 agents, default
|
|
32
32
|
- `strict` — all 7 agents + Devil's Advocate rebuttal round on the most critical blocker
|
|
33
33
|
|
|
34
|
-
`veto_benchmark` also runs
|
|
34
|
+
`veto_benchmark` also runs council — two debates in parallel for side-by-side approach comparison.
|
|
35
35
|
|
|
36
36
|
### Expert modules — deterministic, instant, zero tokens (42+ agents)
|
|
37
37
|
|
|
@@ -41,10 +41,10 @@ Every other agent in Veto — coder, reviewer, tester, debugger, security scanne
|
|
|
41
41
|
veto_agent_plan { agent: "coder", task: "..." } ← deterministic plan, instant
|
|
42
42
|
veto_code_review { code: "..." } ← regex + heuristic scanner, instant
|
|
43
43
|
veto_secrets_scan{ text: "..." } ← pattern matching, instant
|
|
44
|
-
veto_council_debate { task: "..." } ←
|
|
44
|
+
veto_council_debate { task: "..." } ← agentic loop: host AI reasons as 7 specialists
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
**Why this split?** LLM reasoning
|
|
47
|
+
**Why this split?** LLM reasoning is only worth it for high-stakes architecture/security/migration decisions. Pattern-matching is MORE reliable than LLMs for secrets detection and OWASP scanning (no hallucinations). The deterministic agents are the workhorses; the council is the gatekeeper.
|
|
48
48
|
|
|
49
49
|
---
|
|
50
50
|
|
|
@@ -104,7 +104,7 @@ All config files are home-directory relative — they apply globally across all
|
|
|
104
104
|
|
|
105
105
|
## What Veto Does
|
|
106
106
|
|
|
107
|
-
**Council** — Before any significant task, 7 specialist agents
|
|
107
|
+
**Council** — Before any significant task, 7 specialist agents debate it using the agentic loop and return a GREEN / YELLOW / RED / DEADLOCK verdict. Works on Claude Code, Gemini CLI, and Codex CLI — no API keys needed. Bad decisions get blocked before any code is written.
|
|
108
108
|
|
|
109
109
|
**Metrics** — `veto_metrics` gives you a live usage dashboard: sessions saved, council verdict breakdown, top agents by call count, 7-day quality trend, and knowledge base stats. Zero cost, pure SQLite.
|
|
110
110
|
|
|
@@ -140,9 +140,9 @@ All config files are home-directory relative — they apply globally across all
|
|
|
140
140
|
|
|
141
141
|
## The 50 Agents
|
|
142
142
|
|
|
143
|
-
### Council Layer — LLM
|
|
143
|
+
### Council Layer — LLM reasoning via agentic loop (8)
|
|
144
144
|
|
|
145
|
-
>
|
|
145
|
+
> Real LLM reasoning, zero extra cost, works on all 3 platforms. The host AI reasons as all 7 specialists and passes structured responses back to Veto's verdict engine. Used by `veto_council_debate` and `veto_benchmark`.
|
|
146
146
|
|
|
147
147
|
`Lead Developer` · `Product Manager` · `System Architect` · `UX Designer` · `Devil's Advocate` · `Legal & Compliance` · `Security` · `Decision Engine`
|
|
148
148
|
|
|
@@ -256,27 +256,49 @@ veto doctor
|
|
|
256
256
|
|
|
257
257
|
## Council Debate
|
|
258
258
|
|
|
259
|
+
Two-phase flow — works on Claude Code, Gemini CLI, and Codex CLI with no API keys:
|
|
260
|
+
|
|
259
261
|
```
|
|
262
|
+
# Phase 1 — call with task, get instant deterministic result + LLM upgrade prompt
|
|
260
263
|
veto_council_debate {
|
|
261
264
|
task: "migrate auth from sessions to JWTs",
|
|
262
265
|
project_dir: "/your/project",
|
|
263
|
-
strictness: "standard"
|
|
266
|
+
strictness: "standard"
|
|
264
267
|
}
|
|
265
268
|
→ {
|
|
269
|
+
llm_backed: false,
|
|
270
|
+
final_verdict: "YELLOW",
|
|
271
|
+
votes: { lead_dev: {...}, architect: {...}, security: {...}, ... },
|
|
272
|
+
llm_upgrade: {
|
|
273
|
+
available: true,
|
|
274
|
+
instruction: "Read debate_prompt, reason as all 7 agents, call again with agent_responses",
|
|
275
|
+
debate_prompt: "You are running a Veto Council debate. Analyze the task as each specialist..."
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
# Phase 2 — reason as all 7 agents, pass responses back → get LLM-backed verdict
|
|
280
|
+
veto_council_debate {
|
|
281
|
+
task: "migrate auth from sessions to JWTs",
|
|
282
|
+
agent_responses: {
|
|
283
|
+
lead_dev: { verdict: "warn", reason: "Stateless JWTs complicate logout — need blocklist", concerns: ["Refresh token rotation must be atomic"], recommendation: "Use short-lived access tokens (15m) + httpOnly refresh tokens" },
|
|
284
|
+
pm: { verdict: "approve", reason: "JWT migration unblocks mobile clients", concerns: [], recommendation: "Ship behind a feature flag, roll back if logout issues" },
|
|
285
|
+
architect: { verdict: "approve", reason: "Good fit for stateless microservice boundary", concerns: ["Clock skew can break expiry across services"], recommendation: "Add NTP sync check; use relative expiry not absolute timestamps" },
|
|
286
|
+
ux: { verdict: "approve", reason: "No user-visible change if migration is seamless", concerns: [], recommendation: "Silent migration — no logout required for existing sessions" },
|
|
287
|
+
devil: { verdict: "warn", reason: "What if the refresh token store goes down at 2AM?", concerns: ["Redis outage = all users logged out", "Token replay attack window between rotation and invalidation"], recommendation: "Fallback to session auth if Redis is down; use short rotation window" },
|
|
288
|
+
legal: { verdict: "approve", reason: "JWTs are industry standard, no new compliance risk", concerns: [], recommendation: "Document token storage in privacy policy" },
|
|
289
|
+
security: { verdict: "warn", reason: "Refresh token rotation must be atomic — TOCTOU risk", concerns: ["localStorage storage of access token is XSS-vulnerable"], recommendation: "Store access token in memory only; refresh token in httpOnly Secure SameSite=Strict cookie" }
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
→ {
|
|
293
|
+
llm_backed: true,
|
|
266
294
|
final_verdict: "YELLOW",
|
|
267
295
|
block_reasons: [],
|
|
268
|
-
warnings: ["
|
|
269
|
-
|
|
270
|
-
lead_dev: { verdict: "warn", reason: "Stateless JWTs complicate logout flows...", concerns: [...] },
|
|
271
|
-
architect: { verdict: "approve", reason: "Good fit for microservices...", concerns: [...] },
|
|
272
|
-
security: { verdict: "warn", reason: "Refresh token rotation must be atomic...", concerns: [...] },
|
|
273
|
-
...
|
|
274
|
-
},
|
|
275
|
-
recommended: "Proceed with JWT migration. Implement a Redis blocklist for logout..."
|
|
296
|
+
warnings: ["Refresh token rotation must be atomic...", "What if the refresh token store goes down..."],
|
|
297
|
+
recommended: "Proceed with JWT. Use httpOnly cookies for refresh tokens, memory-only for access tokens..."
|
|
276
298
|
}
|
|
277
299
|
```
|
|
278
300
|
|
|
279
|
-
When the task presents a binary choice, agents name the option they prefer:
|
|
301
|
+
When the task presents a binary choice, agents name the option they prefer and the output includes a `🎯 Council leans toward:` line:
|
|
280
302
|
|
|
281
303
|
```
|
|
282
304
|
veto_council_debate {
|
|
@@ -297,6 +319,13 @@ veto_council_debate {
|
|
|
297
319
|
Tag sessions when saving to make them findable later:
|
|
298
320
|
|
|
299
321
|
```
|
|
322
|
+
# Let Veto generate the summary from conversation context
|
|
323
|
+
veto_session_save {
|
|
324
|
+
auto_summarize: true,
|
|
325
|
+
tags: ["auth", "jwt", "middleware"]
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
# Or write it manually
|
|
300
329
|
veto_session_save {
|
|
301
330
|
summary: "Implemented JWT auth middleware",
|
|
302
331
|
context: "...",
|
|
@@ -310,6 +339,106 @@ veto_sessions_list { query: "auth" }
|
|
|
310
339
|
|
|
311
340
|
---
|
|
312
341
|
|
|
342
|
+
## New in v1.4.3
|
|
343
|
+
|
|
344
|
+
### Council debate + session save — work on Gemini CLI and Codex CLI
|
|
345
|
+
|
|
346
|
+
MCP Sampling (`server.createMessage`) is not yet implemented by any of the three CLI hosts. Previously this meant the council always used deterministic fallbacks and `auto_summarize` never ran on any platform.
|
|
347
|
+
|
|
348
|
+
**v1.4.3 introduces the agentic loop pattern** — no API keys, no sampling dependency, works on all three platforms identically.
|
|
349
|
+
|
|
350
|
+
#### Council debate — two-phase LLM upgrade
|
|
351
|
+
|
|
352
|
+
```
|
|
353
|
+
# Phase 1 — always returns an instant deterministic result
|
|
354
|
+
veto_council_debate { task: "migrate auth to JWT" }
|
|
355
|
+
→ {
|
|
356
|
+
llm_backed: false,
|
|
357
|
+
final_verdict: "YELLOW",
|
|
358
|
+
votes: { ... }, ← deterministic agent analysis
|
|
359
|
+
llm_upgrade: {
|
|
360
|
+
available: true,
|
|
361
|
+
instruction: "Read debate_prompt, reason as all 7 agents, call again with agent_responses",
|
|
362
|
+
debate_prompt: "You are running a Veto Council debate. Analyze the task as each specialist..."
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
# Phase 2 — call again with your agent_responses → get the LLM-backed verdict
|
|
367
|
+
veto_council_debate {
|
|
368
|
+
task: "migrate auth to JWT",
|
|
369
|
+
agent_responses: {
|
|
370
|
+
lead_dev: { verdict: "warn", reason: "...", concerns: [], recommendation: "..." },
|
|
371
|
+
pm: { verdict: "approve", ... },
|
|
372
|
+
architect: { verdict: "warn", ... },
|
|
373
|
+
ux: { verdict: "approve", ... },
|
|
374
|
+
devil: { verdict: "warn", ... },
|
|
375
|
+
legal: { verdict: "warn", ... },
|
|
376
|
+
security: { verdict: "warn", ... }
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
→ { llm_backed: true, final_verdict: "YELLOW", votes: { ... } }
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
The host AI (Claude, Gemini, or Codex) reads the `debate_prompt`, reasons as all 7 specialists, and passes the structured JSON back. Veto runs the verdict engine on the real LLM output.
|
|
383
|
+
|
|
384
|
+
#### Session save — agentic fallback
|
|
385
|
+
|
|
386
|
+
When `auto_summarize: true` and MCP Sampling is unavailable, `veto_session_save` now returns a structured template and instructions for the calling AI to fill in and call again — instead of silently saving nothing:
|
|
387
|
+
|
|
388
|
+
```
|
|
389
|
+
veto_session_save { auto_summarize: true }
|
|
390
|
+
→ {
|
|
391
|
+
mode: "agentic",
|
|
392
|
+
instruction: "Generate the session summary yourself from the conversation above, then call veto_session_save again with the filled-in fields.",
|
|
393
|
+
summarize_prompt: "Review the conversation above and produce a session checkpoint...",
|
|
394
|
+
template: {
|
|
395
|
+
auto_summarize: false,
|
|
396
|
+
summary: "<one sentence describing what was accomplished>",
|
|
397
|
+
context: "{ task, decisions[], findings[] with file:line }",
|
|
398
|
+
task_state: "{ completed[], remaining[], nextAction: 'Edit src/X.ts line N — ...' }"
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## New in v1.4.2
|
|
406
|
+
|
|
407
|
+
### `veto_session_save` — LLM auto-summarization
|
|
408
|
+
|
|
409
|
+
Pass `auto_summarize: true` and Veto reads the full conversation via MCP Sampling, then generates an accurate, structured session checkpoint itself — you don't write summary, context, or task_state manually.
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
# Simplest possible save — Veto does the work
|
|
413
|
+
veto_session_save {
|
|
414
|
+
auto_summarize: true,
|
|
415
|
+
project_dir: "/your/project",
|
|
416
|
+
tags: ["auth", "migration"]
|
|
417
|
+
}
|
|
418
|
+
→ {
|
|
419
|
+
success: true,
|
|
420
|
+
auto_summarized: true,
|
|
421
|
+
session_id: "abc-123",
|
|
422
|
+
summary: "Implemented JWT auth middleware with refresh token rotation",
|
|
423
|
+
context: {
|
|
424
|
+
task: "migrate session auth to JWT",
|
|
425
|
+
decisions: [{ decision: "store refresh token in httpOnly cookie", rationale: "XSS protection" }],
|
|
426
|
+
findings: ["src/auth.ts:142 — refreshToken handler, needs rotation logic next"]
|
|
427
|
+
},
|
|
428
|
+
task_state: {
|
|
429
|
+
completed: ["access token generation", "middleware wiring"],
|
|
430
|
+
remaining: ["refresh token rotation", "logout blocklist"],
|
|
431
|
+
nextAction: "Edit src/auth.ts line 142 — implement rotation: invalidate old refresh token, issue new one, update DB row"
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Veto generates `nextAction` as a **concrete, file+line instruction** the next AI can execute without re-reading any source files. On restore, the `resume_instructions` field tells the AI to trust this and start immediately.
|
|
437
|
+
|
|
438
|
+
When MCP Sampling is unavailable (all platforms currently), returns an agentic template asking the host AI to generate the summary from the conversation and call back with filled-in fields — see v1.4.3.
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
313
442
|
## New in v1.4.1
|
|
314
443
|
|
|
315
444
|
### Council debate — decision-aware verdicts
|
|
@@ -329,7 +458,7 @@ Lead Dev: [Express-bundled vs external-adapter] reason [WARN]
|
|
|
329
458
|
🎯 Council leans toward: "external adapter pattern" (4 agents prefer it)
|
|
330
459
|
```
|
|
331
460
|
|
|
332
|
-
|
|
461
|
+
In the agentic loop (phase 2), the host AI is explicitly instructed to name the preferred option in its recommendation for each agent role.
|
|
333
462
|
|
|
334
463
|
### `veto_session_restore` — resume instructions
|
|
335
464
|
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
2
|
import type { DebateInput, DebateResult } from './types.js';
|
|
3
|
+
export declare function buildAgenticDebatePrompt(task: string, enrichedContext: string, decisionContext?: string): string;
|
|
4
|
+
export declare function parseAgentResponses(raw: string, task: string): DebateResult['votes'] | null;
|
|
5
|
+
export declare function runFromAgentResponses(input: DebateInput, votes: DebateResult['votes']): DebateResult;
|
|
3
6
|
export declare function runLlmDebate(server: Server, input: DebateInput): Promise<DebateResult>;
|
|
4
7
|
//# sourceMappingURL=llm-council.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-council.d.ts","sourceRoot":"","sources":["../../src/council/llm-council.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"llm-council.d.ts","sourceRoot":"","sources":["../../src/council/llm-council.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,KAAK,EAAa,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAuJvE,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAoChH;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,IAAI,CA8B3F;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,YAAY,CAKpG;AAID,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAqC5F"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
// LLM-backed council —
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// LLM-backed council — three tiers:
|
|
2
|
+
// 1. MCP Sampling (server.createMessage) — if host implements it
|
|
3
|
+
// 2. Agentic loop — host AI reasons as all 7 agents, passes responses back
|
|
4
|
+
// 3. Deterministic fallback — always available, zero tokens
|
|
4
5
|
import { decide, formatDebate } from './decision-engine.js';
|
|
5
6
|
import { buildContextString } from '../context/reader.js';
|
|
6
7
|
import { searchKnowledge } from '../memory/local.js';
|
|
@@ -122,6 +123,88 @@ async function callAgentLlm(server, agentKey, task, memoryContext, decisionConte
|
|
|
122
123
|
return FALLBACKS[agentKey](task);
|
|
123
124
|
}
|
|
124
125
|
}
|
|
126
|
+
// ─── Agentic loop: host AI reasons as all 7 agents ───────────────────────────
|
|
127
|
+
const AGENT_ROLE_DESCRIPTIONS = {
|
|
128
|
+
lead_dev: 'Lead Developer — technical feasibility, code quality, implementation risk, engineering best practices. Block when something is technically broken or creates severe debt.',
|
|
129
|
+
pm: 'Product Manager — user value, business alignment, scope clarity, product-market fit. Block when something contradicts core product goals.',
|
|
130
|
+
architect: 'System Architect — scalability, maintainability, coupling, architectural integrity. Block breaking changes that violate architectural principles.',
|
|
131
|
+
ux: 'UX Designer — usability, accessibility, user flow, experience quality. Block changes that harm users or violate accessibility standards.',
|
|
132
|
+
devil: "Devil's Advocate — find failure modes, edge cases, hidden dependencies, flawed assumptions. Challenge the most attractive option. Block on fatal flaws.",
|
|
133
|
+
legal: 'Legal & Compliance — GDPR, CCPA, licensing, data privacy, regulatory exposure. Block anything creating clear legal liability.',
|
|
134
|
+
security: 'Security Engineer — OWASP Top 10, auth, injection, data leakage, threat model. Block anything introducing clear security risks.',
|
|
135
|
+
};
|
|
136
|
+
export function buildAgenticDebatePrompt(task, enrichedContext, decisionContext) {
|
|
137
|
+
const agentEntries = Object.entries(AGENT_ROLE_DESCRIPTIONS)
|
|
138
|
+
.map(([key, desc]) => ` "${key}": ${desc}`)
|
|
139
|
+
.join('\n');
|
|
140
|
+
const decisionNote = decisionContext
|
|
141
|
+
? `\n\nARCHITECTURAL CHOICE IN TASK: ${decisionContext}\nEach agent MUST name which option they prefer in their recommendation.`
|
|
142
|
+
: '';
|
|
143
|
+
const schema = `{
|
|
144
|
+
"lead_dev": { "verdict": "approve|warn|block", "reason": "one sentence", "concerns": ["concern"], "recommendation": "actionable advice" },
|
|
145
|
+
"pm": { "verdict": "approve|warn|block", "reason": "one sentence", "concerns": ["concern"], "recommendation": "actionable advice" },
|
|
146
|
+
"architect": { "verdict": "approve|warn|block", "reason": "one sentence", "concerns": ["concern"], "recommendation": "actionable advice" },
|
|
147
|
+
"ux": { "verdict": "approve|warn|block", "reason": "one sentence", "concerns": ["concern"], "recommendation": "actionable advice" },
|
|
148
|
+
"devil": { "verdict": "warn|block", "reason": "one sentence", "concerns": ["failure mode"], "recommendation": "mitigation" },
|
|
149
|
+
"legal": { "verdict": "approve|warn|block", "reason": "one sentence", "concerns": ["concern"], "recommendation": "actionable advice" },
|
|
150
|
+
"security": { "verdict": "approve|warn|block", "reason": "one sentence", "concerns": ["vulnerability"], "recommendation": "actionable advice" }
|
|
151
|
+
}`;
|
|
152
|
+
return `You are running a Veto Council debate. Analyze the following task as each of the 7 specialists below. Each specialist evaluates independently from their own domain perspective.
|
|
153
|
+
|
|
154
|
+
SPECIALIST ROLES:
|
|
155
|
+
${agentEntries}${decisionNote}
|
|
156
|
+
|
|
157
|
+
TASK:
|
|
158
|
+
${task}
|
|
159
|
+
${enrichedContext ? `\nCONTEXT:\n${enrichedContext}` : ''}
|
|
160
|
+
|
|
161
|
+
RULES:
|
|
162
|
+
- Each specialist speaks only from their domain — Lead Dev does NOT comment on business value, PM does NOT comment on code quality, etc.
|
|
163
|
+
- devil always warns or blocks, never approves non-trivial tasks
|
|
164
|
+
- If the task presents two options (A vs B), each specialist MUST name which they prefer in their recommendation
|
|
165
|
+
- Keep each reason to one sentence. Concerns are brief phrases.
|
|
166
|
+
|
|
167
|
+
Return ONLY this JSON (no markdown, no prose before or after):
|
|
168
|
+
${schema}`;
|
|
169
|
+
}
|
|
170
|
+
export function parseAgentResponses(raw, task) {
|
|
171
|
+
try {
|
|
172
|
+
const match = raw.match(/\{[\s\S]*\}/);
|
|
173
|
+
if (!match)
|
|
174
|
+
return null;
|
|
175
|
+
const parsed = JSON.parse(match[0]);
|
|
176
|
+
const agents = ['lead_dev', 'pm', 'architect', 'ux', 'devil', 'legal', 'security'];
|
|
177
|
+
const votes = {};
|
|
178
|
+
for (const key of agents) {
|
|
179
|
+
const raw_vote = parsed[key];
|
|
180
|
+
if (!raw_vote || typeof raw_vote !== 'object') {
|
|
181
|
+
votes[key] = FALLBACKS[key](task);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const verdict = ['approve', 'warn', 'block'].includes(raw_vote.verdict)
|
|
185
|
+
? raw_vote.verdict
|
|
186
|
+
: 'warn';
|
|
187
|
+
votes[key] = {
|
|
188
|
+
verdict,
|
|
189
|
+
reason: typeof raw_vote.reason === 'string' ? raw_vote.reason : 'No reason provided.',
|
|
190
|
+
concerns: Array.isArray(raw_vote.concerns)
|
|
191
|
+
? raw_vote.concerns.filter((c) => typeof c === 'string')
|
|
192
|
+
: [],
|
|
193
|
+
recommendation: typeof raw_vote.recommendation === 'string' ? raw_vote.recommendation : undefined,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
return votes;
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
export function runFromAgentResponses(input, votes) {
|
|
203
|
+
const { final_verdict, block_reasons, warnings, recommended } = decide(votes);
|
|
204
|
+
const debated_at = new Date().toISOString();
|
|
205
|
+
const formatted_output = formatDebate(input.task, votes, final_verdict, block_reasons, warnings, recommended);
|
|
206
|
+
return { task: input.task, final_verdict, votes, recommended, block_reasons, warnings, debated_at, formatted_output };
|
|
207
|
+
}
|
|
125
208
|
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
126
209
|
export async function runLlmDebate(server, input) {
|
|
127
210
|
const enrichedContext = buildContextString(input.project_dir, input.context);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-council.js","sourceRoot":"","sources":["../../src/council/llm-council.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"llm-council.js","sourceRoot":"","sources":["../../src/council/llm-council.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,mEAAmE;AACnE,6EAA6E;AAC7E,8DAA8D;AAI9D,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,0CAA0C;AAC1C,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAO,qBAAqB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAY,sBAAsB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAY,kBAAkB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAS,qBAAqB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAS,uBAAuB,CAAC;AACpE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE5D,iFAAiF;AAEjF,MAAM,cAAc,GAA2B;IAC7C,QAAQ,EAAE;;;;;oMAKwL;IAElM,EAAE,EAAE;;;;;oMAK8L;IAElM,SAAS,EAAE;;;;;oMAKuL;IAElM,EAAE,EAAE;;;;;oMAK8L;IAElM,KAAK,EAAE;;;;;mNAK0M;IAEjN,KAAK,EAAE;;;;;0MAKiM;IAExM,QAAQ,EAAE;;;;;0MAK8L;CACzM,CAAC;AAEF,MAAM,SAAS,GAAgD;IAC7D,QAAQ,EAAG,eAAe;IAC1B,EAAE,EAAS,UAAU;IACrB,SAAS,EAAE,iBAAiB;IAC5B,EAAE,EAAS,UAAU;IACrB,KAAK,EAAM,aAAa;IACxB,KAAK,EAAM,aAAa;IACxB,QAAQ,EAAG,gBAAgB;CAC5B,CAAC;AAEF,iFAAiF;AAEjF,SAAS,cAAc,CAAC,IAAY,EAAE,QAAgB,EAAE,YAAoB;IAC1E,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,OAAO,GAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QACrG,OAAO;YACL,OAAO;YACP,MAAM,EAAE,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,qBAAqB;YACzF,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;YACvG,cAAc,EAAE,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS;SACxF,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY,EAAE,WAAoB;IAC5D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;QAC3F,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACrC,OAAO,QAAQ;aACZ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;aACpD,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF,KAAK,UAAU,YAAY,CACzB,MAAc,EACd,QAAgB,EAChB,IAAY,EACZ,aAAqB,EACrB,eAAwB;IAExB,MAAM,KAAK,GAAa,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;IACvD,IAAI,eAAe;QAAE,KAAK,CAAC,IAAI,CAAC,qCAAqC,eAAe,wGAAwG,CAAC,CAAC;IAC9L,IAAI,aAAa;QAAE,KAAK,CAAC,IAAI,CAAC,uCAAuC,aAAa,EAAE,CAAC,CAAC;IACtF,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAElC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC;YACxC,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC;YACvE,YAAY,EAAE,cAAc,CAAC,QAAQ,CAAC;YACtC,SAAS,EAAE,GAAG;YACd,cAAc,EAAE,MAAM;SACvB,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,OAAO,cAAc,CAAC,YAAY,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,6EAA6E;QAC7E,OAAO,SAAS,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;AACH,CAAC;AAED,gFAAgF;AAEhF,MAAM,uBAAuB,GAA2B;IACtD,QAAQ,EAAG,2KAA2K;IACtL,EAAE,EAAS,2IAA2I;IACtJ,SAAS,EAAE,mJAAmJ;IAC9J,EAAE,EAAS,0IAA0I;IACrJ,KAAK,EAAM,yJAAyJ;IACpK,KAAK,EAAM,+HAA+H;IAC1I,QAAQ,EAAG,iIAAiI;CAC7I,CAAC;AAEF,MAAM,UAAU,wBAAwB,CAAC,IAAY,EAAE,eAAuB,EAAE,eAAwB;IACtG,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC;SACzD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;SAC3C,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,YAAY,GAAG,eAAe;QAClC,CAAC,CAAC,qCAAqC,eAAe,0EAA0E;QAChI,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,MAAM,GAAG;;;;;;;;EAQf,CAAC;IAED,OAAO;;;EAGP,YAAY,GAAG,YAAY;;;EAG3B,IAAI;EACJ,eAAe,CAAC,CAAC,CAAC,eAAe,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE;;;;;;;;;EASvD,MAAM,EAAE,CAAC;AACX,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAW,EAAE,IAAY;IAC3D,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,CAAU,CAAC;QAE5F,MAAM,KAAK,GAAG,EAA2B,CAAC;QAC1C,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7B,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC9C,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;gBAClC,SAAS;YACX,CAAC;YACD,MAAM,OAAO,GAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAChF,CAAC,CAAC,QAAQ,CAAC,OAAuC;gBAClD,CAAC,CAAC,MAAM,CAAC;YACX,KAAK,CAAC,GAAG,CAAC,GAAG;gBACX,OAAO;gBACP,MAAM,EAAE,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,qBAAqB;gBACrF,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;oBACxC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;oBACjE,CAAC,CAAC,EAAE;gBACN,cAAc,EAAE,OAAO,QAAQ,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS;aAClG,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAkB,EAAE,KAA4B;IACpF,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,gBAAgB,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC9G,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC;AACxH,CAAC;AAED,iFAAiF;AAEjF,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAc,EAAE,KAAkB;IACnE,MAAM,eAAe,GAAG,kBAAkB,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7E,MAAM,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,OAAO,eAAe,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;IACtF,MAAM,aAAa,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAExE,uEAAuE;IACvE,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,eAAe,GAAG,QAAQ,CAAC,cAAc;QAC7C,CAAC,CAAC,cAAc,QAAQ,CAAC,OAAO,mBAAmB,QAAQ,CAAC,OAAO,GAAG;QACtE,CAAC,CAAC,SAAS,CAAC;IAEd,kFAAkF;IAClF,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC9E,YAAY,CAAC,MAAM,EAAE,UAAU,EAAG,QAAQ,EAAE,aAAa,EAAE,eAAe,CAAC;QAC3E,YAAY,CAAC,MAAM,EAAE,IAAI,EAAS,QAAQ,EAAE,aAAa,EAAE,eAAe,CAAC;QAC3E,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,CAAC;QAC3E,YAAY,CAAC,MAAM,EAAE,IAAI,EAAS,QAAQ,EAAE,aAAa,EAAE,eAAe,CAAC;QAC3E,YAAY,CAAC,MAAM,EAAE,OAAO,EAAM,QAAQ,EAAE,aAAa,EAAE,eAAe,CAAC;QAC3E,YAAY,CAAC,MAAM,EAAE,OAAO,EAAM,QAAQ,EAAE,aAAa,EAAE,eAAe,CAAC;QAC3E,YAAY,CAAC,MAAM,EAAE,UAAU,EAAG,QAAQ,EAAE,aAAa,EAAE,eAAe,CAAC;KAC5E,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IACtE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,gBAAgB,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IAE9G,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,aAAa;QACb,KAAK;QACL,WAAW;QACX,aAAa;QACb,QAAQ;QACR,UAAU;QACV,gBAAgB;KACjB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
export interface GeneratedSession {
|
|
3
|
+
summary: string;
|
|
4
|
+
context: string;
|
|
5
|
+
task_state: string;
|
|
6
|
+
auto_summarized: true;
|
|
7
|
+
}
|
|
8
|
+
export interface AgenticSummarizePrompt {
|
|
9
|
+
mode: 'agentic';
|
|
10
|
+
instruction: string;
|
|
11
|
+
summarize_prompt: string;
|
|
12
|
+
template: {
|
|
13
|
+
auto_summarize: false;
|
|
14
|
+
summary: string;
|
|
15
|
+
context: string;
|
|
16
|
+
task_state: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export declare function buildAgenticSummarizePrompt(): AgenticSummarizePrompt;
|
|
20
|
+
export declare function autoSummarizeSession(server: Server, hints: {
|
|
21
|
+
summary?: string;
|
|
22
|
+
context?: string;
|
|
23
|
+
task_state?: string;
|
|
24
|
+
}): Promise<GeneratedSession | AgenticSummarizePrompt | null>;
|
|
25
|
+
//# sourceMappingURL=session-summarizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-summarizer.d.ts","sourceRoot":"","sources":["../../src/council/session-summarizer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAExE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,IAAI,CAAC;CACvB;AA+ED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE;QACR,cAAc,EAAE,KAAK,CAAC;QACtB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAmBD,wBAAgB,2BAA2B,IAAI,sBAAsB,CAapE;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GACjE,OAAO,CAAC,gBAAgB,GAAG,sBAAsB,GAAG,IAAI,CAAC,CAoB3D"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// LLM-backed session summarizer — uses MCP Sampling with full conversation context
|
|
2
|
+
// to generate a structured, accurate session checkpoint without the calling AI
|
|
3
|
+
// having to manually write summary/context/task_state.
|
|
4
|
+
const SYSTEM_PROMPT = `You are a session archivist for a software development AI assistant.
|
|
5
|
+
Your job: read the conversation above and produce a precise, compact session checkpoint
|
|
6
|
+
that lets a DIFFERENT AI resume this exact work in a new session — without re-reading any source files.
|
|
7
|
+
|
|
8
|
+
Return ONLY valid JSON with exactly this shape (no markdown, no prose):
|
|
9
|
+
{
|
|
10
|
+
"summary": "one sentence: what was accomplished or attempted",
|
|
11
|
+
"phase": "planning|implementing|reviewing|blocked|complete",
|
|
12
|
+
"context": {
|
|
13
|
+
"task": "original task description verbatim",
|
|
14
|
+
"decisions": [
|
|
15
|
+
{ "decision": "what was decided", "rationale": "why" }
|
|
16
|
+
],
|
|
17
|
+
"findings": [
|
|
18
|
+
"specific file path + what matters about it (e.g. src/server.ts:302 — veto_session_save handler, add validation here)"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"task_state": {
|
|
22
|
+
"completed": ["list of finished subtasks, specific"],
|
|
23
|
+
"inProgress": ["current subtask being worked on"],
|
|
24
|
+
"remaining": ["subtasks still to do"],
|
|
25
|
+
"blockers": ["anything requiring human input before continuing"],
|
|
26
|
+
"nextAction": "concrete, file-specific instruction: e.g. Edit src/server.ts line 302 — add zod .max(2000) on summary field"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
Rules:
|
|
31
|
+
- nextAction MUST be actionable without opening any file — include filename, line number, and exact change
|
|
32
|
+
- findings MUST name specific files and what is relevant about them, not generic descriptions
|
|
33
|
+
- Keep total JSON under 1500 tokens
|
|
34
|
+
- Do not include large code blocks — reference file+line instead`;
|
|
35
|
+
function buildUserMessage(hints) {
|
|
36
|
+
const parts = [
|
|
37
|
+
'The conversation context above is the full work session to checkpoint.',
|
|
38
|
+
'Extract a session save from it. Focus on: which specific files were touched (with line numbers), what decisions were made and why, and make nextAction a concrete file+line instruction.',
|
|
39
|
+
];
|
|
40
|
+
if (hints.summary)
|
|
41
|
+
parts.push(`\nHint from calling AI (summary): ${hints.summary}`);
|
|
42
|
+
if (hints.context)
|
|
43
|
+
parts.push(`\nHint from calling AI (context): ${hints.context}`);
|
|
44
|
+
if (hints.task_state)
|
|
45
|
+
parts.push(`\nHint from calling AI (task_state): ${hints.task_state}`);
|
|
46
|
+
if (hints.summary || hints.context || hints.task_state) {
|
|
47
|
+
parts.push('\nUse these hints as supplementary input. The conversation is the primary source — improve on the hints where the conversation provides more detail.');
|
|
48
|
+
}
|
|
49
|
+
return parts.join('\n');
|
|
50
|
+
}
|
|
51
|
+
function parseGeneratedSession(raw) {
|
|
52
|
+
try {
|
|
53
|
+
const match = raw.match(/\{[\s\S]*\}/);
|
|
54
|
+
if (!match)
|
|
55
|
+
return null;
|
|
56
|
+
const parsed = JSON.parse(match[0]);
|
|
57
|
+
if (typeof parsed.summary !== 'string')
|
|
58
|
+
return null;
|
|
59
|
+
const summary = String(parsed.summary).slice(0, 2000);
|
|
60
|
+
const context = JSON.stringify({
|
|
61
|
+
task: parsed.context?.task ?? '',
|
|
62
|
+
phase: parsed.phase ?? 'implementing',
|
|
63
|
+
decisions: Array.isArray(parsed.context?.decisions) ? parsed.context.decisions : [],
|
|
64
|
+
findings: Array.isArray(parsed.context?.findings) ? parsed.context.findings : [],
|
|
65
|
+
}).slice(0, 50_000);
|
|
66
|
+
const task_state = JSON.stringify({
|
|
67
|
+
completed: Array.isArray(parsed.task_state?.completed) ? parsed.task_state.completed : [],
|
|
68
|
+
inProgress: Array.isArray(parsed.task_state?.inProgress) ? parsed.task_state.inProgress : [],
|
|
69
|
+
remaining: Array.isArray(parsed.task_state?.remaining) ? parsed.task_state.remaining : [],
|
|
70
|
+
blockers: Array.isArray(parsed.task_state?.blockers) ? parsed.task_state.blockers : [],
|
|
71
|
+
nextAction: typeof parsed.task_state?.nextAction === 'string' ? parsed.task_state.nextAction : '',
|
|
72
|
+
}).slice(0, 20_000);
|
|
73
|
+
return { summary, context, task_state };
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const AGENTIC_TEMPLATE = {
|
|
80
|
+
auto_summarize: false,
|
|
81
|
+
summary: '<one sentence: what was accomplished or is in progress>',
|
|
82
|
+
context: JSON.stringify({
|
|
83
|
+
task: '<original task description verbatim>',
|
|
84
|
+
decisions: [{ decision: '<what was decided>', rationale: '<why>' }],
|
|
85
|
+
findings: ['<src/file.ts:N — what matters about this file>'],
|
|
86
|
+
}),
|
|
87
|
+
task_state: JSON.stringify({
|
|
88
|
+
completed: ['<finished subtask>'],
|
|
89
|
+
inProgress: ['<current subtask>'],
|
|
90
|
+
remaining: ['<subtask still to do>'],
|
|
91
|
+
blockers: [],
|
|
92
|
+
nextAction: '<concrete file+line instruction: Edit src/X.ts line N — do Y>',
|
|
93
|
+
}),
|
|
94
|
+
};
|
|
95
|
+
export function buildAgenticSummarizePrompt() {
|
|
96
|
+
return {
|
|
97
|
+
mode: 'agentic',
|
|
98
|
+
instruction: 'MCP Sampling is unavailable on this platform. Generate the session summary yourself from the conversation above, then call veto_session_save again with the filled-in fields. Use the template below — replace every <placeholder> with real content from the conversation.',
|
|
99
|
+
summarize_prompt: `Review the conversation above and produce a session checkpoint. Requirements:
|
|
100
|
+
- summary: one sentence describing what was accomplished
|
|
101
|
+
- context.task: the original task verbatim
|
|
102
|
+
- context.decisions: decisions made and why (only non-obvious ones)
|
|
103
|
+
- context.findings: specific file paths with line numbers and what matters there
|
|
104
|
+
- task_state.nextAction: MUST be a concrete file+line instruction — e.g. "Edit src/server.ts line 302 — add zod .max(2000) on summary field". NOT vague like "add validation".
|
|
105
|
+
- Keep total JSON under 1500 tokens`,
|
|
106
|
+
template: AGENTIC_TEMPLATE,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export async function autoSummarizeSession(server, hints) {
|
|
110
|
+
try {
|
|
111
|
+
const result = await server.createMessage({
|
|
112
|
+
messages: [{ role: 'user', content: { type: 'text', text: buildUserMessage(hints) } }],
|
|
113
|
+
systemPrompt: SYSTEM_PROMPT,
|
|
114
|
+
maxTokens: 800,
|
|
115
|
+
includeContext: 'allServers',
|
|
116
|
+
});
|
|
117
|
+
const raw = result.content.type === 'text' ? result.content.text : '';
|
|
118
|
+
if (!raw)
|
|
119
|
+
return buildAgenticSummarizePrompt();
|
|
120
|
+
const parsed = parseGeneratedSession(raw);
|
|
121
|
+
if (!parsed)
|
|
122
|
+
return buildAgenticSummarizePrompt();
|
|
123
|
+
return { ...parsed, auto_summarized: true };
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// MCP Sampling unavailable — return agentic prompt so the calling AI can do it
|
|
127
|
+
return buildAgenticSummarizePrompt();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=session-summarizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-summarizer.js","sourceRoot":"","sources":["../../src/council/session-summarizer.ts"],"names":[],"mappings":"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"}
|