@jigyasudham/veto 1.4.0 → 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.
Files changed (50) hide show
  1. package/README.md +218 -17
  2. package/dist/council/decision-engine.d.ts.map +1 -1
  3. package/dist/council/decision-engine.js +20 -0
  4. package/dist/council/decision-engine.js.map +1 -1
  5. package/dist/council/decision-extractor.d.ts +13 -0
  6. package/dist/council/decision-extractor.d.ts.map +1 -0
  7. package/dist/council/decision-extractor.js +66 -0
  8. package/dist/council/decision-extractor.js.map +1 -0
  9. package/dist/council/devil-advocate.d.ts.map +1 -1
  10. package/dist/council/devil-advocate.js +12 -1
  11. package/dist/council/devil-advocate.js.map +1 -1
  12. package/dist/council/lead-developer.d.ts.map +1 -1
  13. package/dist/council/lead-developer.js +34 -14
  14. package/dist/council/lead-developer.js.map +1 -1
  15. package/dist/council/legal-compliance.d.ts.map +1 -1
  16. package/dist/council/legal-compliance.js +44 -24
  17. package/dist/council/legal-compliance.js.map +1 -1
  18. package/dist/council/llm-council.d.ts +3 -0
  19. package/dist/council/llm-council.d.ts.map +1 -1
  20. package/dist/council/llm-council.js +127 -21
  21. package/dist/council/llm-council.js.map +1 -1
  22. package/dist/council/product-manager.d.ts.map +1 -1
  23. package/dist/council/product-manager.js +33 -13
  24. package/dist/council/product-manager.js.map +1 -1
  25. package/dist/council/security.d.ts.map +1 -1
  26. package/dist/council/security.js +44 -24
  27. package/dist/council/security.js.map +1 -1
  28. package/dist/council/session-summarizer.d.ts +25 -0
  29. package/dist/council/session-summarizer.d.ts.map +1 -0
  30. package/dist/council/session-summarizer.js +130 -0
  31. package/dist/council/session-summarizer.js.map +1 -0
  32. package/dist/council/system-architect.d.ts.map +1 -1
  33. package/dist/council/system-architect.js +33 -13
  34. package/dist/council/system-architect.js.map +1 -1
  35. package/dist/council/ux-designer.d.ts.map +1 -1
  36. package/dist/council/ux-designer.js +47 -26
  37. package/dist/council/ux-designer.js.map +1 -1
  38. package/dist/server.js +109 -13
  39. package/dist/server.js.map +1 -1
  40. package/dist/skills/memory/skill-session-restore.d.ts.map +1 -1
  41. package/dist/skills/memory/skill-session-restore.js +19 -24
  42. package/dist/skills/memory/skill-session-restore.js.map +1 -1
  43. package/dist/skills/memory/skill-session-save.d.ts.map +1 -1
  44. package/dist/skills/memory/skill-session-save.js +5 -9
  45. package/dist/skills/memory/skill-session-save.js.map +1 -1
  46. package/dist/tools/definitions.d.ts +164 -6
  47. package/dist/tools/definitions.d.ts.map +1 -1
  48. package/dist/tools/definitions.js +24 -6
  49. package/dist/tools/definitions.js.map +1 -1
  50. package/package.json +1 -1
@@ -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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"}
@@ -1 +1 @@
1
- {"version":3,"file":"system-architect.d.ts","sourceRoot":"","sources":["../../src/council/system-architect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAqI5C,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAmD/C"}
1
+ {"version":3,"file":"system-architect.d.ts","sourceRoot":"","sources":["../../src/council/system-architect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAsI5C,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAqD/C"}
@@ -1,3 +1,4 @@
1
+ import { extractDecision, pickSide, reframeVote } from './decision-extractor.js';
1
2
  const BLOCK_RULES = [
2
3
  {
3
4
  pattern: /\bdrop\s+table\b/i,
@@ -143,32 +144,51 @@ export function analyze(task) {
143
144
  recommendations.push(rule.recommendation);
144
145
  }
145
146
  }
147
+ let vote;
146
148
  if (blocks.length > 0) {
147
- return {
149
+ vote = {
148
150
  verdict: 'block',
149
151
  reason: blocks[0].reason,
150
152
  concerns: blocks.slice(1).map(b => b.reason),
151
153
  recommendation: blocks.map(b => b.recommendation).join(' | '),
152
154
  };
153
155
  }
154
- if (concerns.length > 0) {
155
- return {
156
+ else if (concerns.length > 0) {
157
+ vote = {
156
158
  verdict: 'warn',
157
159
  reason: `${concerns.length} structural concern${concerns.length > 1 ? 's' : ''} — review before building.`,
158
160
  concerns,
159
161
  recommendation: recommendations[0],
160
162
  };
161
163
  }
162
- const matched = TOPIC_INSIGHTS.filter(t => t.pattern.test(task));
163
- if (matched.length > 0) {
164
- const top = matched.slice(0, 2);
165
- return {
166
- verdict: 'warn',
167
- reason: top[0].concern,
168
- concerns: top.slice(1).map(t => t.concern),
169
- recommendation: top.map(t => t.recommendation).join(' | '),
170
- };
164
+ else {
165
+ const matched = TOPIC_INSIGHTS.filter(t => t.pattern.test(task));
166
+ if (matched.length > 0) {
167
+ const top = matched.slice(0, 2);
168
+ vote = {
169
+ verdict: 'warn',
170
+ reason: top[0].concern,
171
+ concerns: top.slice(1).map(t => t.concern),
172
+ recommendation: top.map(t => t.recommendation).join(' | '),
173
+ };
174
+ }
175
+ else {
176
+ vote = { verdict: 'approve', reason: 'Architecture looks sound. No structural concerns identified.', concerns: [] };
177
+ }
171
178
  }
172
- return { verdict: 'approve', reason: 'Architecture looks sound. No structural concerns identified.', concerns: [] };
179
+ return applyDecisionStance(vote, task);
180
+ }
181
+ // Architect risk: options that tighten coupling or introduce new architectural layers
182
+ const ARCH_RISK = /\b(bundl|integrat\s+into|embed|inline|http|express|new\s+(server|layer|transport|protocol)|microservice)\b/i;
183
+ function applyDecisionStance(vote, task) {
184
+ const ctx = extractDecision(task);
185
+ if (!ctx.isDecisionTask)
186
+ return vote;
187
+ const { optionA, optionB } = ctx;
188
+ const side = pickSide(optionA, optionB, ARCH_RISK);
189
+ const advice = side
190
+ ? `"${side.preferred}" preserves separation of concerns and keeps the boundary clean. "${side.avoided}" creates coupling that is difficult to undo later — the caller now depends on implementation details.`
191
+ : `Evaluate which option maintains the cleaner boundary. Prefer the path that adds no new coupling between existing components.`;
192
+ return reframeVote(vote, ctx, side?.preferred ?? null, advice);
173
193
  }
174
194
  //# sourceMappingURL=system-architect.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"system-architect.js","sourceRoot":"","sources":["../../src/council/system-architect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"system-architect.js","sourceRoot":"","sources":["../../src/council/system-architect.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ux-designer.d.ts","sourceRoot":"","sources":["../../src/council/ux-designer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAqE5C,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CA+F/C"}
1
+ {"version":3,"file":"ux-designer.d.ts","sourceRoot":"","sources":["../../src/council/ux-designer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAsE5C,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAkG/C"}
@@ -1,3 +1,4 @@
1
+ import { extractDecision, pickSide, reframeVote } from './decision-extractor.js';
1
2
  // Backend-only tasks: UX approves without friction
2
3
  const BACKEND_ONLY = /\b(api|backend|server|database|db|query|schema|migration|auth.*middleware|jwt|oauth|cron|cli|script|worker|queue|cache|redis|sql|index|trigger|webhook)\b/i;
3
4
  const FRONTEND_SIGNALS = /\b(ui|ux|form|button|modal|page|screen|component|view|layout|menu|nav|input|field|label|error.?message|loading|user.?interface|frontend|react|vue|svelte|html|css)\b/i;
@@ -65,14 +66,15 @@ export function analyze(task) {
65
66
  if (TRIVIAL.test(task.trim())) {
66
67
  return { verdict: 'approve', reason: 'Trivial change — no UX concerns.', concerns: [] };
67
68
  }
68
- // Pure backend tasks get a light pass
69
+ // Pure backend tasks get a light pass — but still apply decision stance
69
70
  const isBackend = BACKEND_ONLY.test(task) && !FRONTEND_SIGNALS.test(task);
70
71
  if (isBackend) {
71
- return {
72
+ const backendVote = {
72
73
  verdict: 'approve',
73
74
  reason: 'Backend task — no direct UX concerns. Ensure API errors surface clearly to users.',
74
75
  concerns: [],
75
76
  };
77
+ return applyDecisionStance(backendVote, task);
76
78
  }
77
79
  const blocks = [];
78
80
  const concerns = [];
@@ -88,22 +90,6 @@ export function analyze(task) {
88
90
  recommendations.push(rule.recommendation);
89
91
  }
90
92
  }
91
- if (blocks.length > 0) {
92
- return {
93
- verdict: 'block',
94
- reason: blocks[0].reason,
95
- concerns: blocks.slice(1).map(b => b.reason),
96
- recommendation: blocks.map(b => b.recommendation).join(' | '),
97
- };
98
- }
99
- if (concerns.length > 0) {
100
- return {
101
- verdict: 'warn',
102
- reason: `${concerns.length} UX concern${concerns.length > 1 ? 's' : ''} — real users will notice this.`,
103
- concerns,
104
- recommendation: recommendations[0],
105
- };
106
- }
107
93
  // Topic-based UX analysis for tasks with no direct frontend signals
108
94
  const TOPIC_INSIGHTS = [
109
95
  {
@@ -137,16 +123,51 @@ export function analyze(task) {
137
123
  recommendation: 'Show progress for any operation over 500ms. For long operations, stream partial results or show a "working..." status. Never leave the user in silence.',
138
124
  },
139
125
  ];
140
- const topicMatched = TOPIC_INSIGHTS.filter(t => t.pattern.test(task));
141
- if (topicMatched.length > 0) {
142
- const top = topicMatched.slice(0, 2);
143
- return {
126
+ let vote;
127
+ if (blocks.length > 0) {
128
+ vote = {
129
+ verdict: 'block',
130
+ reason: blocks[0].reason,
131
+ concerns: blocks.slice(1).map(b => b.reason),
132
+ recommendation: blocks.map(b => b.recommendation).join(' | '),
133
+ };
134
+ }
135
+ else if (concerns.length > 0) {
136
+ vote = {
144
137
  verdict: 'warn',
145
- reason: top[0].concern,
146
- concerns: top.slice(1).map(t => t.concern),
147
- recommendation: top.map(t => t.recommendation).join(' | '),
138
+ reason: `${concerns.length} UX concern${concerns.length > 1 ? 's' : ''} — real users will notice this.`,
139
+ concerns,
140
+ recommendation: recommendations[0],
148
141
  };
149
142
  }
150
- return { verdict: 'approve', reason: 'UX looks solid. No user experience concerns identified.', concerns: [] };
143
+ else {
144
+ const topicMatched = TOPIC_INSIGHTS.filter(t => t.pattern.test(task));
145
+ if (topicMatched.length > 0) {
146
+ const top = topicMatched.slice(0, 2);
147
+ vote = {
148
+ verdict: 'warn',
149
+ reason: top[0].concern,
150
+ concerns: top.slice(1).map(t => t.concern),
151
+ recommendation: top.map(t => t.recommendation).join(' | '),
152
+ };
153
+ }
154
+ else {
155
+ vote = { verdict: 'approve', reason: 'UX looks solid. No user experience concerns identified.', concerns: [] };
156
+ }
157
+ }
158
+ return applyDecisionStance(vote, task);
159
+ }
160
+ // UX risk: options that add setup friction, credentials, or configuration overhead
161
+ const UX_RISK = /\b(http|api.?key|auth|oauth|port|server\s+config|credentials|token|setup.{0,15}required|install.{0,15}extra)\b/i;
162
+ function applyDecisionStance(vote, task) {
163
+ const ctx = extractDecision(task);
164
+ if (!ctx.isDecisionTask)
165
+ return vote;
166
+ const { optionA, optionB } = ctx;
167
+ const side = pickSide(optionA, optionB, UX_RISK);
168
+ const advice = side
169
+ ? `"${side.preferred}" keeps the developer experience simpler — no extra setup or credentials. "${side.avoided}" adds friction that will silently reduce adoption.`
170
+ : `Evaluate which option requires fewer steps for a first-time user. The shorter happy path wins on developer experience.`;
171
+ return reframeVote(vote, ctx, side?.preferred ?? null, advice);
151
172
  }
152
173
  //# sourceMappingURL=ux-designer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ux-designer.js","sourceRoot":"","sources":["../../src/council/ux-designer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ux-designer.js","sourceRoot":"","sources":["../../src/council/ux-designer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEjF,mDAAmD;AACnD,MAAM,YAAY,GAAG,4JAA4J,CAAC;AAClL,MAAM,gBAAgB,GAAG,uKAAuK,CAAC;AAEjM,MAAM,WAAW,GAAuE;IACtF;QACE,OAAO,EAAE,0CAA0C;QACnD,MAAM,EAAE,2EAA2E;QACnF,cAAc,EAAE,uEAAuE;KACxF;IACD;QACE,OAAO,EAAE,0EAA0E;QACnF,MAAM,EAAE,8EAA8E;QACtF,cAAc,EAAE,+DAA+D;KAChF;IACD;QACE,OAAO,EAAE,wCAAwC;QACjD,MAAM,EAAE,oEAAoE;QAC5E,cAAc,EAAE,yDAAyD;KAC1E;CACF,CAAC;AAEF,MAAM,UAAU,GAAwE;IACtF;QACE,OAAO,EAAE,wCAAwC;QACjD,OAAO,EAAE,mEAAmE;QAC5E,cAAc,EAAE,2DAA2D;KAC5E;IACD;QACE,OAAO,EAAE,+CAA+C;QACxD,OAAO,EAAE,uEAAuE;QAChF,cAAc,EAAE,6DAA6D;KAC9E;IACD;QACE,OAAO,EAAE,iCAAiC;QAC1C,OAAO,EAAE,iEAAiE;QAC1E,cAAc,EAAE,oFAAoF;KACrG;IACD;QACE,OAAO,EAAE,qCAAqC;QAC9C,OAAO,EAAE,8DAA8D;QACvE,cAAc,EAAE,uEAAuE;KACxF;IACD;QACE,OAAO,EAAE,6CAA6C;QACtD,OAAO,EAAE,wEAAwE;QACjF,cAAc,EAAE,iEAAiE;KAClF;IACD;QACE,OAAO,EAAE,kDAAkD;QAC3D,OAAO,EAAE,yEAAyE;QAClF,cAAc,EAAE,mEAAmE;KACpF;IACD;QACE,OAAO,EAAE,kDAAkD;QAC3D,OAAO,EAAE,kEAAkE;QAC3E,cAAc,EAAE,+EAA+E;KAChG;IACD;QACE,OAAO,EAAE,2DAA2D;QACpE,OAAO,EAAE,0DAA0D;QACnE,cAAc,EAAE,kDAAkD;KACnE;CACF,CAAC;AAEF,MAAM,OAAO,GAAG,0EAA0E,CAAC;AAE3F,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,kCAAkC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC1F,CAAC;IAED,wEAAwE;IACxE,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1E,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,WAAW,GAAc;YAC7B,OAAO,EAAE,SAAS;YAClB,MAAM,EAAE,mFAAmF;YAC3F,QAAQ,EAAE,EAAE;SACb,CAAC;QACF,OAAO,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,MAAM,GAAsD,EAAE,CAAC;IACrE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,eAAe,GAAa,EAAE,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5B,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,oEAAoE;IACpE,MAAM,cAAc,GAAwE;QAC1F;YACE,OAAO,EAAE,2CAA2C;YACpD,OAAO,EAAE,kKAAkK;YAC3K,cAAc,EAAE,4JAA4J;SAC7K;QACD;YACE,OAAO,EAAE,yCAAyC;YAClD,OAAO,EAAE,oLAAoL;YAC7L,cAAc,EAAE,8IAA8I;SAC/J;QACD;YACE,OAAO,EAAE,wCAAwC;YACjD,OAAO,EAAE,yKAAyK;YAClL,cAAc,EAAE,6JAA6J;SAC9K;QACD;YACE,OAAO,EAAE,wCAAwC;YACjD,OAAO,EAAE,kJAAkJ;YAC3J,cAAc,EAAE,iKAAiK;SAClL;QACD;YACE,OAAO,EAAE,2CAA2C;YACpD,OAAO,EAAE,wIAAwI;YACjJ,cAAc,EAAE,2KAA2K;SAC5L;QACD;YACE,OAAO,EAAE,oCAAoC;YAC7C,OAAO,EAAE,2JAA2J;YACpK,cAAc,EAAE,yJAAyJ;SAC1K;KACF,CAAC;IAEF,IAAI,IAAe,CAAC;IAEpB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,IAAI,GAAG;YACL,OAAO,EAAE,OAAO;YAChB,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM;YACxB,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;YAC5C,cAAc,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;SAC9D,CAAC;IACJ,CAAC;SAAM,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,IAAI,GAAG;YACL,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,cAAc,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,iCAAiC;YACvG,QAAQ;YACR,cAAc,EAAE,eAAe,CAAC,CAAC,CAAC;SACnC,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,YAAY,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACtE,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACrC,IAAI,GAAG;gBACL,OAAO,EAAE,MAAM;gBACf,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO;gBACtB,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;gBAC1C,cAAc,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;aAC3D,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,yDAAyD,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACjH,CAAC;IACH,CAAC;IAED,OAAO,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,mFAAmF;AACnF,MAAM,OAAO,GAAG,iHAAiH,CAAC;AAElI,SAAS,mBAAmB,CAAC,IAAe,EAAE,IAAY;IACxD,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC;IACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI;QACjB,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,8EAA8E,IAAI,CAAC,OAAO,qDAAqD;QACnK,CAAC,CAAC,wHAAwH,CAAC;IAC7H,OAAO,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,IAAI,IAAI,EAAE,MAAM,CAAC,CAAC;AACjE,CAAC"}
package/dist/server.js CHANGED
@@ -9,7 +9,8 @@ import { buildContextString } from './context/reader.js';
9
9
  import { TOOL_DEFINITIONS } from './tools/definitions.js';
10
10
  import { saveSession, restoreSession, listSessions, closeSession, getDbPath, saveCouncilOutcome, storeKnowledge, searchKnowledge, deleteKnowledge, updateProjectMap, getProjectMap, upsertPattern, getPatterns, getContextStatus, fetchAndCacheDocs, saveTaskPlan, getTaskPlan, getUsageStatus, getAuditLog, getHealthStats, CONTEXT_WINDOWS, logUsage, getUsageLogs, getDb, storeScanDiagnostics, clearScanDiagnostics, updateSession, resolveContextWindow, getMetrics, } from './memory/local.js';
11
11
  import { exportMemory, importMemory } from './memory/sync.js';
12
- import { runLlmDebate } from './council/llm-council.js';
12
+ import { runLlmDebate, buildAgenticDebatePrompt, parseAgentResponses, runFromAgentResponses } from './council/llm-council.js';
13
+ import { autoSummarizeSession } from './council/session-summarizer.js';
13
14
  import { routeTask, getRateStatus, trackTokens, recordOutcome, getLearningStats, getLearnedThresholds, applyLearnedThresholds, getAgentPerformanceStats, getTaskTypeBreakdown, getCouncilInsights, getRecommendedAgent } from './router/index.js';
14
15
  import { getConfig, setConfig } from './memory/config.js';
15
16
  import { executeParallel, executeOne } from './agents/executor.js';
@@ -252,9 +253,47 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
252
253
  if (sessionProjectDir)
253
254
  activeProjectDir = sessionProjectDir;
254
255
  const savePlatform = args?.platform ? String(args.platform) : 'claude';
255
- const saveSummary = String(args?.summary ?? '');
256
- const saveContext = String(args?.context ?? '');
257
- const saveTaskState = args?.task_state ? String(args.task_state) : undefined;
256
+ const shouldAutoSummarize = args?.auto_summarize === true;
257
+ // Auto-summarize: try MCP Sampling first, fall back to agentic prompt for host AI
258
+ let autoSummaryResult = null;
259
+ if (shouldAutoSummarize) {
260
+ autoSummaryResult = await autoSummarizeSession(server, {
261
+ summary: args?.summary ? String(args.summary) : undefined,
262
+ context: args?.context ? String(args.context) : undefined,
263
+ task_state: args?.task_state ? String(args.task_state) : undefined,
264
+ });
265
+ // If agentic prompt returned, short-circuit — return it so the AI can fill it in
266
+ if (autoSummaryResult && 'mode' in autoSummaryResult && autoSummaryResult.mode === 'agentic') {
267
+ return {
268
+ content: [{
269
+ type: 'text',
270
+ text: JSON.stringify({
271
+ success: false,
272
+ auto_summarized: false,
273
+ ...autoSummaryResult,
274
+ }, null, 2),
275
+ }],
276
+ };
277
+ }
278
+ }
279
+ // Enforce size limits — unbounded strings exhaust SQLite page cache and memory
280
+ const SUMMARY_LIMIT = 2_000;
281
+ const CONTEXT_LIMIT = 50_000;
282
+ const TASK_STATE_LIMIT = 20_000;
283
+ const generatedSession = autoSummaryResult && 'auto_summarized' in autoSummaryResult ? autoSummaryResult : null;
284
+ const RAW_SUMMARY = generatedSession?.summary ?? String(args?.summary ?? '');
285
+ const RAW_CONTEXT = generatedSession?.context ?? String(args?.context ?? '');
286
+ const RAW_TASK_STATE = generatedSession?.task_state ?? (args?.task_state ? String(args.task_state) : undefined);
287
+ const saveSummary = RAW_SUMMARY.slice(0, SUMMARY_LIMIT);
288
+ const saveContext = RAW_CONTEXT.slice(0, CONTEXT_LIMIT);
289
+ const saveTaskState = RAW_TASK_STATE ? RAW_TASK_STATE.slice(0, TASK_STATE_LIMIT) : undefined;
290
+ const truncationWarnings = [];
291
+ if (RAW_SUMMARY.length > SUMMARY_LIMIT)
292
+ truncationWarnings.push(`summary truncated to ${SUMMARY_LIMIT} chars (was ${RAW_SUMMARY.length})`);
293
+ if (RAW_CONTEXT.length > CONTEXT_LIMIT)
294
+ truncationWarnings.push(`context truncated to ${CONTEXT_LIMIT} chars (was ${RAW_CONTEXT.length})`);
295
+ if (RAW_TASK_STATE && RAW_TASK_STATE.length > TASK_STATE_LIMIT)
296
+ truncationWarnings.push(`task_state truncated to ${TASK_STATE_LIMIT} chars (was ${RAW_TASK_STATE.length})`);
258
297
  const existingId = args?.session_id ? String(args.session_id) : undefined;
259
298
  const sessionInput = {
260
299
  summary: saveSummary,
@@ -287,6 +326,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
287
326
  autoSave.cached = { summary: saveSummary, context: saveContext, task_state: saveTaskState, platform: savePlatform, project_dir: sessionProjectDir, context_window: resolvedWindow };
288
327
  autoSave.last_save_at = result.saved_at;
289
328
  autoSave.last_session_id = result.session_id;
329
+ const autoSumFailed = shouldAutoSummarize && !autoSummaryResult;
290
330
  const responseObj = {
291
331
  success: true,
292
332
  message: wasUpdate
@@ -297,7 +337,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
297
337
  session_id: result.session_id,
298
338
  saved_at: result.saved_at,
299
339
  updated: wasUpdate,
340
+ auto_summarized: autoSummaryResult ? true : false,
341
+ ...(autoSumFailed ? { auto_summarize_warning: 'MCP Sampling unavailable — saved provided values instead. For best results use Claude Code or another host that supports sampling.' } : {}),
300
342
  ...(wasUpdate ? {} : { usage_pct: result.usage_pct, context_warning: result.context_warning }),
343
+ ...(truncationWarnings.length > 0 ? { truncation_warnings: truncationWarnings } : {}),
301
344
  };
302
345
  if (result.continuation_prompt)
303
346
  responseObj.continuation_prompt = result.continuation_prompt;
@@ -321,22 +364,41 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
321
364
  const s = result.session;
322
365
  if (s.project_dir)
323
366
  activeProjectDir = s.project_dir;
367
+ const parsedTaskState = s.task_state ? (() => { try {
368
+ return JSON.parse(s.task_state);
369
+ }
370
+ catch {
371
+ return s.task_state;
372
+ } })() : null;
373
+ const nextAction = (typeof parsedTaskState === 'object' && parsedTaskState !== null)
374
+ ? (parsedTaskState.nextAction ?? parsedTaskState.next_action ?? null)
375
+ : null;
376
+ const resumeInstructions = [
377
+ 'Context restored from previous session. Trust the summary, context, and task_state above — they were written by the AI that last worked on this.',
378
+ 'Do NOT re-read source files to orient yourself. That defeats the purpose of session restore and wastes tokens.',
379
+ 'Only open a file if you are about to EDIT it — not to "verify" or "familiarize yourself" with it.',
380
+ nextAction ? `Start immediately with: ${nextAction}` : 'Read task_state.nextAction (or context) for where to start.',
381
+ 'If context seems stale (e.g. you find a file has changed), read only that file, update the context, and continue.',
382
+ ].join(' ');
324
383
  return {
325
384
  content: [
326
385
  {
327
386
  type: 'text',
328
387
  text: JSON.stringify({
329
388
  success: true,
389
+ resume_instructions: resumeInstructions,
330
390
  session_id: s.id,
331
391
  created_by: s.platform,
332
- active_client: s.active_client ?? s.platform,
333
- last_resumed_at: s.last_resumed_at,
334
- started_at: s.started_at,
335
- ended_at: s.ended_at,
392
+ saved_at: s.started_at,
336
393
  project_dir: s.project_dir,
337
394
  summary: s.summary,
338
- context: s.context ? JSON.parse(s.context) : null,
339
- task_state: s.task_state ? JSON.parse(s.task_state) : null,
395
+ context: s.context ? (() => { try {
396
+ return JSON.parse(s.context);
397
+ }
398
+ catch {
399
+ return s.context;
400
+ } })() : null,
401
+ task_state: parsedTaskState,
340
402
  token_count: s.token_count,
341
403
  }, null, 2),
342
404
  },
@@ -409,13 +471,36 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
409
471
  const strictnessArg = (['fast', 'standard', 'strict'].includes(String(args?.strictness ?? '')))
410
472
  ? String(args.strictness)
411
473
  : 'standard';
412
- const debateStart = Date.now();
413
- const result = await runLlmDebate(server, {
474
+ const debateInput = {
414
475
  task,
415
476
  context: args?.context ? String(args.context) : undefined,
416
477
  project_dir: args?.project_dir ? String(args.project_dir) : undefined,
417
478
  strictness: strictnessArg,
418
- });
479
+ };
480
+ // Phase 2: agent_responses provided — run verdict engine on LLM-generated votes
481
+ const rawAgentResponses = args?.agent_responses;
482
+ if (rawAgentResponses && typeof rawAgentResponses === 'object') {
483
+ const parsed = parseAgentResponses(JSON.stringify(rawAgentResponses), task);
484
+ if (parsed) {
485
+ const debateStart = Date.now();
486
+ const result = runFromAgentResponses(debateInput, parsed);
487
+ const debateDuration = Date.now() - debateStart;
488
+ const sessionId = args?.session_id ? String(args.session_id) : undefined;
489
+ const outcomeId = saveCouncilOutcome({
490
+ session_id: sessionId, task, verdict: result.final_verdict,
491
+ lead_dev: JSON.stringify(result.votes.lead_dev), pm: JSON.stringify(result.votes.pm),
492
+ architect: JSON.stringify(result.votes.architect), ux: JSON.stringify(result.votes.ux),
493
+ devil: JSON.stringify(result.votes.devil), legal: JSON.stringify(result.votes.legal),
494
+ security: JSON.stringify(result.votes.security), recommended: result.recommended,
495
+ duration_ms: debateDuration,
496
+ });
497
+ const payload = { outcome_id: outcomeId, llm_backed: true, final_verdict: result.final_verdict, block_reasons: result.block_reasons, warnings: result.warnings, recommended: result.recommended, debated_at: result.debated_at, votes: result.votes };
498
+ return { content: [{ type: 'text', text: result.formatted_output + '\n\n' + JSON.stringify(payload, null, 2) }] };
499
+ }
500
+ }
501
+ // Phase 1: run deterministic debate + attach llm_upgrade prompt for host AI
502
+ const debateStart = Date.now();
503
+ const result = await runLlmDebate(server, debateInput);
419
504
  const debateDuration = Date.now() - debateStart;
420
505
  const sessionId = args?.session_id ? String(args.session_id) : undefined;
421
506
  const outcomeId = saveCouncilOutcome({
@@ -465,8 +550,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
465
550
  relevance: isRed ? 1.0 : 0.8,
466
551
  });
467
552
  }
553
+ // Build agentic upgrade prompt so host AI can provide real LLM reasoning on any platform
554
+ const enrichedCtx = buildContextString(debateInput.project_dir, debateInput.context);
555
+ const { optionA, optionB, isDecisionTask } = (await import('./council/decision-extractor.js')).extractDecision(task);
556
+ const decisionCtx = isDecisionTask ? `Option A: "${optionA}" vs Option B: "${optionB}"` : undefined;
557
+ const agenticPrompt = buildAgenticDebatePrompt(task, enrichedCtx, decisionCtx);
468
558
  const responsePayload = {
469
559
  outcome_id: outcomeId,
560
+ llm_backed: false,
470
561
  final_verdict: result.final_verdict,
471
562
  block_reasons: result.block_reasons,
472
563
  warnings: result.warnings,
@@ -481,6 +572,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
481
572
  legal: result.votes.legal,
482
573
  security: result.votes.security,
483
574
  },
575
+ llm_upgrade: {
576
+ available: true,
577
+ instruction: 'The verdict above is deterministic. For LLM-backed analysis: (1) read debate_prompt and reason as all 7 agents, generating the agent_responses JSON; (2) call veto_council_debate again with { task, agent_responses } to get the final LLM-backed verdict. Works on Claude Code, Gemini CLI, and Codex CLI with no API keys.',
578
+ debate_prompt: agenticPrompt,
579
+ },
484
580
  };
485
581
  const fullText = result.formatted_output + '\n\n' + JSON.stringify(responsePayload, null, 2);
486
582
  if (typeof args?.max_tokens === 'number') {