@jigyasudham/veto 1.2.1 → 1.2.5

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 (320) hide show
  1. package/README.md +29 -6
  2. package/dist/adapters/index.d.ts +46 -0
  3. package/dist/adapters/index.d.ts.map +1 -0
  4. package/dist/adapters/index.js +47 -8
  5. package/dist/adapters/index.js.map +1 -0
  6. package/dist/agents/development/api.d.ts +3 -0
  7. package/dist/agents/development/api.d.ts.map +1 -0
  8. package/dist/agents/development/api.js.map +1 -0
  9. package/dist/agents/development/backend.d.ts +3 -0
  10. package/dist/agents/development/backend.d.ts.map +1 -0
  11. package/dist/agents/development/backend.js.map +1 -0
  12. package/dist/agents/development/coder.d.ts +3 -0
  13. package/dist/agents/development/coder.d.ts.map +1 -0
  14. package/dist/agents/development/coder.js.map +1 -0
  15. package/dist/agents/development/database.d.ts +3 -0
  16. package/dist/agents/development/database.d.ts.map +1 -0
  17. package/dist/agents/development/database.js +175 -52
  18. package/dist/agents/development/database.js.map +1 -0
  19. package/dist/agents/development/debugger.d.ts +3 -0
  20. package/dist/agents/development/debugger.d.ts.map +1 -0
  21. package/dist/agents/development/debugger.js.map +1 -0
  22. package/dist/agents/development/devops.d.ts +3 -0
  23. package/dist/agents/development/devops.d.ts.map +1 -0
  24. package/dist/agents/development/devops.js +190 -55
  25. package/dist/agents/development/devops.js.map +1 -0
  26. package/dist/agents/development/frontend.d.ts +3 -0
  27. package/dist/agents/development/frontend.d.ts.map +1 -0
  28. package/dist/agents/development/frontend.js.map +1 -0
  29. package/dist/agents/development/migration.d.ts +3 -0
  30. package/dist/agents/development/migration.d.ts.map +1 -0
  31. package/dist/agents/development/migration.js.map +1 -0
  32. package/dist/agents/development/performance.d.ts +3 -0
  33. package/dist/agents/development/performance.d.ts.map +1 -0
  34. package/dist/agents/development/performance.js.map +1 -0
  35. package/dist/agents/development/refactor.d.ts +3 -0
  36. package/dist/agents/development/refactor.d.ts.map +1 -0
  37. package/dist/agents/development/refactor.js.map +1 -0
  38. package/dist/agents/development/reviewer.d.ts +4 -0
  39. package/dist/agents/development/reviewer.d.ts.map +1 -0
  40. package/dist/agents/development/reviewer.js +34 -17
  41. package/dist/agents/development/reviewer.js.map +1 -0
  42. package/dist/agents/development/tester.d.ts +3 -0
  43. package/dist/agents/development/tester.d.ts.map +1 -0
  44. package/dist/agents/development/tester.js.map +1 -0
  45. package/dist/agents/executor.d.ts +4 -0
  46. package/dist/agents/executor.d.ts.map +1 -0
  47. package/dist/agents/executor.js +10 -1
  48. package/dist/agents/executor.js.map +1 -0
  49. package/dist/agents/memory/context-manager.d.ts +3 -0
  50. package/dist/agents/memory/context-manager.d.ts.map +1 -0
  51. package/dist/agents/memory/context-manager.js.map +1 -0
  52. package/dist/agents/memory/decision-logger.d.ts +3 -0
  53. package/dist/agents/memory/decision-logger.d.ts.map +1 -0
  54. package/dist/agents/memory/decision-logger.js.map +1 -0
  55. package/dist/agents/memory/knowledge-base.d.ts +3 -0
  56. package/dist/agents/memory/knowledge-base.d.ts.map +1 -0
  57. package/dist/agents/memory/knowledge-base.js.map +1 -0
  58. package/dist/agents/memory/pattern-learner.d.ts +3 -0
  59. package/dist/agents/memory/pattern-learner.d.ts.map +1 -0
  60. package/dist/agents/memory/pattern-learner.js.map +1 -0
  61. package/dist/agents/memory/project-mapper.d.ts +3 -0
  62. package/dist/agents/memory/project-mapper.d.ts.map +1 -0
  63. package/dist/agents/memory/project-mapper.js.map +1 -0
  64. package/dist/agents/quality/accessibility.d.ts +4 -0
  65. package/dist/agents/quality/accessibility.d.ts.map +1 -0
  66. package/dist/agents/quality/accessibility.js.map +1 -0
  67. package/dist/agents/quality/code-quality.d.ts +4 -0
  68. package/dist/agents/quality/code-quality.d.ts.map +1 -0
  69. package/dist/agents/quality/code-quality.js.map +1 -0
  70. package/dist/agents/quality/compatibility.d.ts +3 -0
  71. package/dist/agents/quality/compatibility.d.ts.map +1 -0
  72. package/dist/agents/quality/compatibility.js.map +1 -0
  73. package/dist/agents/quality/documentation.d.ts +4 -0
  74. package/dist/agents/quality/documentation.d.ts.map +1 -0
  75. package/dist/agents/quality/documentation.js.map +1 -0
  76. package/dist/agents/quality/error-handling.d.ts +4 -0
  77. package/dist/agents/quality/error-handling.d.ts.map +1 -0
  78. package/dist/agents/quality/error-handling.js.map +1 -0
  79. package/dist/agents/research/competitor-analyzer.d.ts +3 -0
  80. package/dist/agents/research/competitor-analyzer.d.ts.map +1 -0
  81. package/dist/agents/research/competitor-analyzer.js.map +1 -0
  82. package/dist/agents/research/cost-analyzer.d.ts +3 -0
  83. package/dist/agents/research/cost-analyzer.d.ts.map +1 -0
  84. package/dist/agents/research/cost-analyzer.js.map +1 -0
  85. package/dist/agents/research/estimator.d.ts +3 -0
  86. package/dist/agents/research/estimator.d.ts.map +1 -0
  87. package/dist/agents/research/estimator.js.map +1 -0
  88. package/dist/agents/research/ethics-bias.d.ts +3 -0
  89. package/dist/agents/research/ethics-bias.d.ts.map +1 -0
  90. package/dist/agents/research/ethics-bias.js.map +1 -0
  91. package/dist/agents/research/researcher.d.ts +3 -0
  92. package/dist/agents/research/researcher.d.ts.map +1 -0
  93. package/dist/agents/research/researcher.js.map +1 -0
  94. package/dist/agents/research/risk-assessor.d.ts +3 -0
  95. package/dist/agents/research/risk-assessor.d.ts.map +1 -0
  96. package/dist/agents/research/risk-assessor.js.map +1 -0
  97. package/dist/agents/research/tech-advisor.d.ts +3 -0
  98. package/dist/agents/research/tech-advisor.d.ts.map +1 -0
  99. package/dist/agents/research/tech-advisor.js.map +1 -0
  100. package/dist/agents/security/auth.d.ts +3 -0
  101. package/dist/agents/security/auth.d.ts.map +1 -0
  102. package/dist/agents/security/auth.js.map +1 -0
  103. package/dist/agents/security/dependency-audit.d.ts +19 -0
  104. package/dist/agents/security/dependency-audit.d.ts.map +1 -0
  105. package/dist/agents/security/dependency-audit.js.map +1 -0
  106. package/dist/agents/security/penetration.d.ts +3 -0
  107. package/dist/agents/security/penetration.d.ts.map +1 -0
  108. package/dist/agents/security/penetration.js.map +1 -0
  109. package/dist/agents/security/privacy.d.ts +3 -0
  110. package/dist/agents/security/privacy.d.ts.map +1 -0
  111. package/dist/agents/security/privacy.js.map +1 -0
  112. package/dist/agents/security/scanner.d.ts +4 -0
  113. package/dist/agents/security/scanner.d.ts.map +1 -0
  114. package/dist/agents/security/scanner.js.map +1 -0
  115. package/dist/agents/security/secrets.d.ts +12 -0
  116. package/dist/agents/security/secrets.d.ts.map +1 -0
  117. package/dist/agents/security/secrets.js.map +1 -0
  118. package/dist/agents/types.d.ts +62 -0
  119. package/dist/agents/types.d.ts.map +1 -0
  120. package/dist/agents/types.js.map +1 -0
  121. package/dist/agents/workflow/automation.d.ts +3 -0
  122. package/dist/agents/workflow/automation.d.ts.map +1 -0
  123. package/dist/agents/workflow/automation.js.map +1 -0
  124. package/dist/agents/workflow/file-manager.d.ts +3 -0
  125. package/dist/agents/workflow/file-manager.d.ts.map +1 -0
  126. package/dist/agents/workflow/file-manager.js.map +1 -0
  127. package/dist/agents/workflow/git-agent.d.ts +3 -0
  128. package/dist/agents/workflow/git-agent.d.ts.map +1 -0
  129. package/dist/agents/workflow/git-agent.js.map +1 -0
  130. package/dist/agents/workflow/reporter.d.ts +3 -0
  131. package/dist/agents/workflow/reporter.d.ts.map +1 -0
  132. package/dist/agents/workflow/reporter.js.map +1 -0
  133. package/dist/agents/workflow/search-agent.d.ts +3 -0
  134. package/dist/agents/workflow/search-agent.d.ts.map +1 -0
  135. package/dist/agents/workflow/search-agent.js.map +1 -0
  136. package/dist/agents/workflow/task-coordinator.d.ts +3 -0
  137. package/dist/agents/workflow/task-coordinator.d.ts.map +1 -0
  138. package/dist/agents/workflow/task-coordinator.js.map +1 -0
  139. package/dist/agents/workflow/task-planner.d.ts +3 -0
  140. package/dist/agents/workflow/task-planner.d.ts.map +1 -0
  141. package/dist/agents/workflow/task-planner.js.map +1 -0
  142. package/dist/cli.d.ts +3 -0
  143. package/dist/cli.d.ts.map +1 -0
  144. package/dist/cli.js +65 -4
  145. package/dist/cli.js.map +1 -0
  146. package/dist/context/reader.d.ts +12 -0
  147. package/dist/context/reader.d.ts.map +1 -0
  148. package/dist/context/reader.js.map +1 -0
  149. package/dist/council/decision-engine.d.ts +11 -0
  150. package/dist/council/decision-engine.d.ts.map +1 -0
  151. package/dist/council/decision-engine.js.map +1 -0
  152. package/dist/council/devil-advocate.d.ts +3 -0
  153. package/dist/council/devil-advocate.d.ts.map +1 -0
  154. package/dist/council/devil-advocate.js +46 -0
  155. package/dist/council/devil-advocate.js.map +1 -0
  156. package/dist/council/index.d.ts +4 -0
  157. package/dist/council/index.d.ts.map +1 -0
  158. package/dist/council/index.js +9 -11
  159. package/dist/council/index.js.map +1 -0
  160. package/dist/council/lead-developer.d.ts +3 -0
  161. package/dist/council/lead-developer.d.ts.map +1 -0
  162. package/dist/council/lead-developer.js +65 -1
  163. package/dist/council/lead-developer.js.map +1 -0
  164. package/dist/council/legal-compliance.d.ts +3 -0
  165. package/dist/council/legal-compliance.d.ts.map +1 -0
  166. package/dist/council/legal-compliance.js +43 -0
  167. package/dist/council/legal-compliance.js.map +1 -0
  168. package/dist/council/product-manager.d.ts +3 -0
  169. package/dist/council/product-manager.d.ts.map +1 -0
  170. package/dist/council/product-manager.js +47 -0
  171. package/dist/council/product-manager.js.map +1 -0
  172. package/dist/council/security.d.ts +3 -0
  173. package/dist/council/security.d.ts.map +1 -0
  174. package/dist/council/security.js +48 -0
  175. package/dist/council/security.js.map +1 -0
  176. package/dist/council/system-architect.d.ts +3 -0
  177. package/dist/council/system-architect.d.ts.map +1 -0
  178. package/dist/council/system-architect.js +53 -1
  179. package/dist/council/system-architect.js.map +1 -0
  180. package/dist/council/types.d.ts +32 -0
  181. package/dist/council/types.d.ts.map +1 -0
  182. package/dist/council/types.js.map +1 -0
  183. package/dist/council/ux-designer.d.ts +3 -0
  184. package/dist/council/ux-designer.d.ts.map +1 -0
  185. package/dist/council/ux-designer.js +44 -1
  186. package/dist/council/ux-designer.js.map +1 -0
  187. package/dist/github/pr-fetcher.d.ts +25 -0
  188. package/dist/github/pr-fetcher.d.ts.map +1 -0
  189. package/dist/github/pr-fetcher.js +60 -0
  190. package/dist/github/pr-fetcher.js.map +1 -0
  191. package/dist/memory/local.d.ts +144 -0
  192. package/dist/memory/local.d.ts.map +1 -0
  193. package/dist/memory/local.js +34 -24
  194. package/dist/memory/local.js.map +1 -0
  195. package/dist/memory/schema.d.ts +81 -0
  196. package/dist/memory/schema.d.ts.map +1 -0
  197. package/dist/memory/schema.js +2 -1
  198. package/dist/memory/schema.js.map +1 -0
  199. package/dist/memory/sync.d.ts +24 -0
  200. package/dist/memory/sync.d.ts.map +1 -0
  201. package/dist/memory/sync.js.map +1 -0
  202. package/dist/plugins/loader.d.ts +13 -0
  203. package/dist/plugins/loader.d.ts.map +1 -0
  204. package/dist/plugins/loader.js.map +1 -0
  205. package/dist/router/complexity-scorer.d.ts +18 -0
  206. package/dist/router/complexity-scorer.d.ts.map +1 -0
  207. package/dist/router/complexity-scorer.js.map +1 -0
  208. package/dist/router/context-compressor.d.ts +11 -0
  209. package/dist/router/context-compressor.d.ts.map +1 -0
  210. package/dist/router/context-compressor.js.map +1 -0
  211. package/dist/router/index.d.ts +27 -0
  212. package/dist/router/index.d.ts.map +1 -0
  213. package/dist/router/index.js.map +1 -0
  214. package/dist/router/learning-updater.d.ts +61 -0
  215. package/dist/router/learning-updater.d.ts.map +1 -0
  216. package/dist/router/learning-updater.js.map +1 -0
  217. package/dist/router/model-selector.d.ts +14 -0
  218. package/dist/router/model-selector.d.ts.map +1 -0
  219. package/dist/router/model-selector.js.map +1 -0
  220. package/dist/router/rate-monitor.d.ts +19 -0
  221. package/dist/router/rate-monitor.d.ts.map +1 -0
  222. package/dist/router/rate-monitor.js.map +1 -0
  223. package/dist/server.d.ts +3 -0
  224. package/dist/server.d.ts.map +1 -0
  225. package/dist/server.js +297 -73
  226. package/dist/server.js.map +1 -0
  227. package/dist/skills/development/skill-api-design.d.ts +15 -0
  228. package/dist/skills/development/skill-api-design.d.ts.map +1 -0
  229. package/dist/skills/development/skill-api-design.js.map +1 -0
  230. package/dist/skills/development/skill-auth.d.ts +15 -0
  231. package/dist/skills/development/skill-auth.d.ts.map +1 -0
  232. package/dist/skills/development/skill-auth.js.map +1 -0
  233. package/dist/skills/development/skill-ci-cd.d.ts +2 -0
  234. package/dist/skills/development/skill-ci-cd.d.ts.map +1 -0
  235. package/dist/skills/development/skill-ci-cd.js.map +1 -0
  236. package/dist/skills/development/skill-crud.d.ts +15 -0
  237. package/dist/skills/development/skill-crud.d.ts.map +1 -0
  238. package/dist/skills/development/skill-crud.js.map +1 -0
  239. package/dist/skills/development/skill-db-schema.d.ts +2 -0
  240. package/dist/skills/development/skill-db-schema.d.ts.map +1 -0
  241. package/dist/skills/development/skill-db-schema.js.map +1 -0
  242. package/dist/skills/development/skill-docker.d.ts +2 -0
  243. package/dist/skills/development/skill-docker.d.ts.map +1 -0
  244. package/dist/skills/development/skill-docker.js.map +1 -0
  245. package/dist/skills/development/skill-env-setup.d.ts +2 -0
  246. package/dist/skills/development/skill-env-setup.d.ts.map +1 -0
  247. package/dist/skills/development/skill-env-setup.js.map +1 -0
  248. package/dist/skills/development/skill-scaffold.d.ts +15 -0
  249. package/dist/skills/development/skill-scaffold.d.ts.map +1 -0
  250. package/dist/skills/development/skill-scaffold.js.map +1 -0
  251. package/dist/skills/intelligence/skill-complexity-score.d.ts +15 -0
  252. package/dist/skills/intelligence/skill-complexity-score.d.ts.map +1 -0
  253. package/dist/skills/intelligence/skill-complexity-score.js.map +1 -0
  254. package/dist/skills/intelligence/skill-cost-track.d.ts +14 -0
  255. package/dist/skills/intelligence/skill-cost-track.d.ts.map +1 -0
  256. package/dist/skills/intelligence/skill-cost-track.js.map +1 -0
  257. package/dist/skills/intelligence/skill-learning-loop.d.ts +15 -0
  258. package/dist/skills/intelligence/skill-learning-loop.d.ts.map +1 -0
  259. package/dist/skills/intelligence/skill-learning-loop.js.map +1 -0
  260. package/dist/skills/intelligence/skill-pattern-detect.d.ts +14 -0
  261. package/dist/skills/intelligence/skill-pattern-detect.d.ts.map +1 -0
  262. package/dist/skills/intelligence/skill-pattern-detect.js.map +1 -0
  263. package/dist/skills/intelligence/skill-rate-watch.d.ts +15 -0
  264. package/dist/skills/intelligence/skill-rate-watch.d.ts.map +1 -0
  265. package/dist/skills/intelligence/skill-rate-watch.js.map +1 -0
  266. package/dist/skills/memory/skill-context-compress.d.ts +15 -0
  267. package/dist/skills/memory/skill-context-compress.d.ts.map +1 -0
  268. package/dist/skills/memory/skill-context-compress.js.map +1 -0
  269. package/dist/skills/memory/skill-cross-sync.d.ts +15 -0
  270. package/dist/skills/memory/skill-cross-sync.d.ts.map +1 -0
  271. package/dist/skills/memory/skill-cross-sync.js.map +1 -0
  272. package/dist/skills/memory/skill-decision-log.d.ts +15 -0
  273. package/dist/skills/memory/skill-decision-log.d.ts.map +1 -0
  274. package/dist/skills/memory/skill-decision-log.js.map +1 -0
  275. package/dist/skills/memory/skill-session-restore.d.ts +15 -0
  276. package/dist/skills/memory/skill-session-restore.d.ts.map +1 -0
  277. package/dist/skills/memory/skill-session-restore.js.map +1 -0
  278. package/dist/skills/memory/skill-session-save.d.ts +15 -0
  279. package/dist/skills/memory/skill-session-save.d.ts.map +1 -0
  280. package/dist/skills/memory/skill-session-save.js.map +1 -0
  281. package/dist/skills/quality/skill-accessibility.d.ts +2 -0
  282. package/dist/skills/quality/skill-accessibility.d.ts.map +1 -0
  283. package/dist/skills/quality/skill-accessibility.js.map +1 -0
  284. package/dist/skills/quality/skill-code-review.d.ts +15 -0
  285. package/dist/skills/quality/skill-code-review.d.ts.map +1 -0
  286. package/dist/skills/quality/skill-code-review.js.map +1 -0
  287. package/dist/skills/quality/skill-docs-gen.d.ts +2 -0
  288. package/dist/skills/quality/skill-docs-gen.d.ts.map +1 -0
  289. package/dist/skills/quality/skill-docs-gen.js.map +1 -0
  290. package/dist/skills/quality/skill-perf-audit.d.ts +2 -0
  291. package/dist/skills/quality/skill-perf-audit.d.ts.map +1 -0
  292. package/dist/skills/quality/skill-perf-audit.js.map +1 -0
  293. package/dist/skills/quality/skill-security-scan.d.ts +15 -0
  294. package/dist/skills/quality/skill-security-scan.d.ts.map +1 -0
  295. package/dist/skills/quality/skill-security-scan.js.map +1 -0
  296. package/dist/skills/quality/skill-test-suite.d.ts +15 -0
  297. package/dist/skills/quality/skill-test-suite.d.ts.map +1 -0
  298. package/dist/skills/quality/skill-test-suite.js.map +1 -0
  299. package/dist/skills/workflow/skill-deploy.d.ts +2 -0
  300. package/dist/skills/workflow/skill-deploy.d.ts.map +1 -0
  301. package/dist/skills/workflow/skill-deploy.js.map +1 -0
  302. package/dist/skills/workflow/skill-git-workflow.d.ts +2 -0
  303. package/dist/skills/workflow/skill-git-workflow.d.ts.map +1 -0
  304. package/dist/skills/workflow/skill-git-workflow.js.map +1 -0
  305. package/dist/skills/workflow/skill-rollback.d.ts +2 -0
  306. package/dist/skills/workflow/skill-rollback.d.ts.map +1 -0
  307. package/dist/skills/workflow/skill-rollback.js.map +1 -0
  308. package/dist/skills/workflow/skill-task-breakdown.d.ts +2 -0
  309. package/dist/skills/workflow/skill-task-breakdown.d.ts.map +1 -0
  310. package/dist/skills/workflow/skill-task-breakdown.js.map +1 -0
  311. package/dist/watcher/index.d.ts +23 -0
  312. package/dist/watcher/index.d.ts.map +1 -0
  313. package/dist/watcher/index.js.map +1 -0
  314. package/dist/workflow/pipeline.d.ts +35 -0
  315. package/dist/workflow/pipeline.d.ts.map +1 -0
  316. package/dist/workflow/pipeline.js.map +1 -0
  317. package/package.json +8 -4
  318. package/dist/adapters/claude.js +0 -57
  319. package/dist/adapters/codex.js +0 -58
  320. package/dist/adapters/gemini.js +0 -58
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":""}
package/dist/server.js CHANGED
@@ -1,25 +1,28 @@
1
1
  #!/usr/bin/env node
2
- // Veto MCP Server — Phase 1 skeleton
3
- // Exposes: veto_status, veto_session_save, veto_session_restore, veto_sessions_list
2
+ // Veto MCP Server — 41 tools, 15 phases, self-learning router
4
3
  // Suppress node:sqlite experimental warning — it would corrupt the MCP stdio protocol
5
4
  process.removeAllListeners('warning');
6
5
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
7
6
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
8
7
  import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
9
8
  import { buildContextString } from './context/reader.js';
10
- import { saveSession, restoreSession, listSessions, getDbPath, saveCouncilOutcome, storeKnowledge, searchKnowledge, deleteKnowledge, updateProjectMap, getProjectMap, upsertPattern, getPatterns, getContextStatus, fetchAndCacheDocs, saveTaskPlan, getUsageStatus, getAuditLog, getHealthStats, CONTEXT_WINDOWS, } from './memory/local.js';
9
+ import { saveSession, restoreSession, listSessions, closeSession, getDbPath, saveCouncilOutcome, storeKnowledge, searchKnowledge, deleteKnowledge, updateProjectMap, getProjectMap, upsertPattern, getPatterns, getContextStatus, fetchAndCacheDocs, saveTaskPlan, getUsageStatus, getAuditLog, getHealthStats, CONTEXT_WINDOWS, } from './memory/local.js';
11
10
  import { exportMemory, importMemory } from './memory/sync.js';
12
11
  import { runDebate } from './council/index.js';
13
- import { routeTask, getRateStatus, recordOutcome, getLearningStats, applyLearnedThresholds, getAgentPerformanceStats, getTaskTypeBreakdown, getCouncilInsights, getRecommendedAgent } from './router/index.js';
12
+ import { routeTask, getRateStatus, recordOutcome, getLearningStats, getLearnedThresholds, applyLearnedThresholds, getAgentPerformanceStats, getTaskTypeBreakdown, getCouncilInsights, getRecommendedAgent } from './router/index.js';
14
13
  import { executeParallel, executeOne } from './agents/executor.js';
15
14
  import { handoff, continueSession, getPlatformSetup } from './adapters/index.js';
16
15
  import { startWatch, pollWatch, stopWatch } from './watcher/index.js';
17
16
  import { runPipeline } from './workflow/pipeline.js';
18
17
  import { loadPlugins, listPlugins } from './plugins/loader.js';
18
+ import { fetchPrDiff } from './github/pr-fetcher.js';
19
19
  import { readFileSync, statSync } from 'node:fs';
20
- import { extname, basename } from 'node:path';
20
+ import { extname, basename, join, dirname } from 'node:path';
21
21
  import { createHash } from 'node:crypto';
22
- const VERSION = '1.2.0';
22
+ import { fileURLToPath } from 'node:url';
23
+ import { execSync as execSyncTop } from 'node:child_process';
24
+ const __dirname = dirname(fileURLToPath(import.meta.url));
25
+ const { version: VERSION } = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf8'));
23
26
  // Tracks the project_dir of the most recently active session in this process.
24
27
  // Used as a fallback when memory_store/memory_search are called without an explicit project_dir,
25
28
  // so memories are automatically scoped to the current project.
@@ -28,6 +31,30 @@ let activeProjectDir = null;
28
31
  const SERVER_START_TIME = Date.now();
29
32
  let serverErrorCount = 0;
30
33
  let lastServerError = null;
34
+ const autoSave = {
35
+ threshold_pct: 70,
36
+ cooldown_ms: 5 * 60 * 1000, // 5 min between auto-saves
37
+ last_save_at: null,
38
+ last_session_id: null,
39
+ cached: null,
40
+ };
41
+ function maybeAutoSave(token_count, platform) {
42
+ if (!autoSave.cached)
43
+ return { triggered: false };
44
+ const window_size = CONTEXT_WINDOWS[platform] ?? 200_000;
45
+ const usage_pct = Math.round((token_count / window_size) * 100);
46
+ if (usage_pct < autoSave.threshold_pct)
47
+ return { triggered: false };
48
+ if (autoSave.last_save_at) {
49
+ const elapsed = Date.now() - new Date(autoSave.last_save_at).getTime();
50
+ if (elapsed < autoSave.cooldown_ms)
51
+ return { triggered: false };
52
+ }
53
+ const result = saveSession({ ...autoSave.cached, token_count, platform });
54
+ autoSave.last_save_at = result.saved_at;
55
+ autoSave.last_session_id = result.session_id;
56
+ return { triggered: true, session_id: result.session_id, usage_pct };
57
+ }
31
58
  const server = new Server({ name: 'veto', version: VERSION }, {
32
59
  capabilities: {
33
60
  tools: {},
@@ -40,7 +67,26 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
40
67
  tools: [
41
68
  {
42
69
  name: 'veto_status',
43
- description: 'Returns Veto server status, version, and database info.',
70
+ description: 'Returns Veto server status, version, and database info. Pass token_count to trigger auto-save if context usage crosses 70%.',
71
+ inputSchema: {
72
+ type: 'object',
73
+ properties: {
74
+ token_count: {
75
+ type: 'number',
76
+ description: 'Current session token count. If provided and context usage ≥ 70%, Veto auto-saves the last known session context in the background.',
77
+ },
78
+ platform: {
79
+ type: 'string',
80
+ description: 'AI platform (claude, gemini, codex). Used to select the correct context window for threshold calculation. Defaults to "claude".',
81
+ enum: ['claude', 'gemini', 'codex'],
82
+ },
83
+ },
84
+ required: [],
85
+ },
86
+ },
87
+ {
88
+ name: 'veto_autosave_status',
89
+ description: 'Returns the current auto-save state: whether a context is cached, the threshold, the last auto-save time, and the session ID.',
44
90
  inputSchema: {
45
91
  type: 'object',
46
92
  properties: {},
@@ -675,13 +721,44 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
675
721
  required: ['project_dir'],
676
722
  },
677
723
  },
724
+ {
725
+ name: 'veto_pr_review',
726
+ description: 'Fetches a GitHub PR diff and runs the full Veto triple-scan (code review + security + secrets). Returns a structured verdict and ready-to-post GitHub review comments. Set GITHUB_TOKEN env var for private repos.',
727
+ inputSchema: {
728
+ type: 'object',
729
+ properties: {
730
+ pr_url: { type: 'string', description: 'Full GitHub PR URL. e.g. https://github.com/owner/repo/pull/123' },
731
+ context: { type: 'string', description: 'Optional: PR description or ticket number for extra context.' },
732
+ fail_on: { type: 'string', enum: ['warn', 'fail'], description: 'Whether WARN counts as a failure. Default: "fail".' },
733
+ },
734
+ required: ['pr_url'],
735
+ },
736
+ },
678
737
  ],
679
738
  }));
739
+ // ─── Shared Scan Utility ──────────────────────────────────────────────────────
740
+ async function runTripleScan(diff, context) {
741
+ const [reviewResult, secResult, secretsResult] = await Promise.all([
742
+ executeOne({ id: 'scan-review', agent: 'reviewer', task: 'Review this git diff for code quality issues', code: diff, context }),
743
+ executeOne({ id: 'scan-sec', agent: 'security-scanner', task: 'Scan this git diff for security vulnerabilities', code: diff, context }),
744
+ executeOne({ id: 'scan-secrets', agent: 'secrets', task: 'Scan this git diff for exposed secrets or credentials', code: diff }),
745
+ ]);
746
+ const hasBlocking = (reviewResult.analysis?.critical_count ?? 0) > 0
747
+ || (secResult.analysis?.critical_count ?? 0) > 0
748
+ || (secretsResult.analysis?.critical_count ?? 0) > 0;
749
+ const hasWarnings = (reviewResult.analysis?.high_count ?? 0) > 0
750
+ || (secResult.analysis?.high_count ?? 0) > 0;
751
+ const verdict = hasBlocking ? 'fail' : hasWarnings ? 'warn' : 'pass';
752
+ return { reviewResult, secResult, secretsResult, verdict };
753
+ }
680
754
  // ─── Tool Handlers ────────────────────────────────────────────────────────────
681
755
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
682
756
  const { name, arguments: args } = request.params;
683
757
  switch (name) {
684
758
  case 'veto_status': {
759
+ const statusTokenCount = typeof args?.token_count === 'number' ? args.token_count : null;
760
+ const statusPlatform = args?.platform ? String(args.platform) : 'claude';
761
+ const autoSaveResult = statusTokenCount !== null ? maybeAutoSave(statusTokenCount, statusPlatform) : null;
685
762
  return {
686
763
  content: [
687
764
  {
@@ -690,29 +767,70 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
690
767
  status: 'running',
691
768
  version: VERSION,
692
769
  server: 'veto',
693
- phase: 8,
694
- capabilities: ['session_save', 'session_restore', 'router', 'rate_monitor', 'council_debate', 'agent_plan', 'code_review', 'security_scan', 'secrets_scan', 'parallel_exec', 'memory_store', 'memory_search', 'project_map', 'pattern_store', 'memory_export', 'memory_import', 'learning_stats', 'learning_apply', 'record_outcome', 'handoff', 'continue', 'platform_setup'],
770
+ phase: 16,
771
+ capabilities: [
772
+ 'session_save', 'session_restore', 'sessions_list',
773
+ 'router', 'rate_monitor',
774
+ 'council_debate',
775
+ 'agent_plan', 'parallel_exec',
776
+ 'code_review', 'diff_review', 'security_scan', 'secrets_scan', 'ci_gate',
777
+ 'workflow', 'watch',
778
+ 'explain',
779
+ 'memory_store', 'memory_search', 'memory_delete', 'memory_export', 'memory_import',
780
+ 'project_map', 'pattern_store',
781
+ 'learning_stats', 'learning_apply', 'record_outcome',
782
+ 'handoff', 'continue', 'platform_setup',
783
+ 'plugins',
784
+ 'docs_fetch', 'context_status', 'task_parse',
785
+ 'usage_status', 'audit_log', 'health',
786
+ 'auto_save',
787
+ ],
695
788
  db_path: getDbPath(),
696
789
  uptime_ms: process.uptime() * 1000,
697
790
  timestamp: new Date().toISOString(),
791
+ ...(autoSaveResult?.triggered ? { auto_save: { triggered: true, session_id: autoSaveResult.session_id, usage_pct: autoSaveResult.usage_pct } } : {}),
698
792
  }, null, 2),
699
793
  },
700
794
  ],
701
795
  };
702
796
  }
797
+ case 'veto_autosave_status': {
798
+ return {
799
+ content: [{
800
+ type: 'text',
801
+ text: JSON.stringify({
802
+ threshold_pct: autoSave.threshold_pct,
803
+ cooldown_ms: autoSave.cooldown_ms,
804
+ context_cached: autoSave.cached !== null,
805
+ cached_summary: autoSave.cached?.summary ?? null,
806
+ last_save_at: autoSave.last_save_at,
807
+ last_session_id: autoSave.last_session_id,
808
+ note: 'Auto-save fires when veto_status is called with token_count ≥ threshold_pct% of context window.',
809
+ }, null, 2),
810
+ }],
811
+ };
812
+ }
703
813
  case 'veto_session_save': {
704
814
  const sessionProjectDir = args?.project_dir ? String(args.project_dir) : undefined;
705
815
  if (sessionProjectDir)
706
816
  activeProjectDir = sessionProjectDir;
817
+ const savePlatform = args?.platform ? String(args.platform) : 'claude';
818
+ const saveSummary = String(args?.summary ?? '');
819
+ const saveContext = String(args?.context ?? '');
820
+ const saveTaskState = args?.task_state ? String(args.task_state) : undefined;
707
821
  const result = saveSession({
708
- summary: String(args?.summary ?? ''),
709
- context: String(args?.context ?? ''),
710
- task_state: args?.task_state ? String(args.task_state) : undefined,
711
- platform: args?.platform ? String(args.platform) : 'claude',
822
+ summary: saveSummary,
823
+ context: saveContext,
824
+ task_state: saveTaskState,
825
+ platform: savePlatform,
712
826
  connection_type: args?.connection_type ? String(args.connection_type) : 'subscription',
713
827
  project_dir: sessionProjectDir,
714
828
  token_count: typeof args?.token_count === 'number' ? args.token_count : 0,
715
829
  });
830
+ // Cache for auto-save: future veto_status calls with high token_count will re-save this context
831
+ autoSave.cached = { summary: saveSummary, context: saveContext, task_state: saveTaskState, platform: savePlatform, project_dir: sessionProjectDir };
832
+ autoSave.last_save_at = result.saved_at;
833
+ autoSave.last_session_id = result.session_id;
716
834
  const responseObj = {
717
835
  success: true,
718
836
  message: result.context_warning
@@ -826,11 +944,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
826
944
  isError: true,
827
945
  };
828
946
  }
829
- const result = await runDebate({
947
+ const debateStart = Date.now();
948
+ const result = runDebate({
830
949
  task,
831
950
  context: args?.context ? String(args.context) : undefined,
832
951
  project_dir: args?.project_dir ? String(args.project_dir) : undefined,
833
952
  });
953
+ const debateDuration = Date.now() - debateStart;
834
954
  const outcomeId = saveCouncilOutcome({
835
955
  session_id: args?.session_id ? String(args.session_id) : undefined,
836
956
  task,
@@ -843,6 +963,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
843
963
  legal: JSON.stringify(result.votes.legal),
844
964
  security: JSON.stringify(result.votes.security),
845
965
  recommended: result.recommended,
966
+ duration_ms: debateDuration,
846
967
  });
847
968
  return {
848
969
  content: [
@@ -904,13 +1025,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
904
1025
  // Resolve diff — use provided or read from git
905
1026
  let diff = args?.diff ? String(args.diff).trim() : '';
906
1027
  if (!diff && projectDir) {
907
- const { execSync: execSyncDiff } = await import('node:child_process');
908
1028
  try {
909
- diff = execSyncDiff('git diff HEAD --no-color', {
1029
+ diff = execSyncTop('git diff HEAD --no-color', {
910
1030
  cwd: projectDir, timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'],
911
1031
  }).toString().trim();
912
1032
  if (!diff) {
913
- diff = execSyncDiff('git diff --cached --no-color', {
1033
+ diff = execSyncTop('git diff --cached --no-color', {
914
1034
  cwd: projectDir, timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'],
915
1035
  }).toString().trim();
916
1036
  }
@@ -923,20 +1043,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
923
1043
  // Parse changed files from diff header lines
924
1044
  const changedFiles = [...diff.matchAll(/^diff --git a\/.+ b\/(.+)$/gm)].map(m => m[1]);
925
1045
  const diffChunks = diff.split(/^diff --git /m).filter(Boolean);
926
- // Run code-review, security-scan, secrets-scan in parallel across the full diff
927
1046
  const context = buildContextString(projectDir, userContext);
928
- const [reviewResult, secResult, secretsResult] = await Promise.all([
929
- executeOne({ id: 'diff-review', agent: 'reviewer', task: 'Review this git diff for code quality issues', code: diff, context }),
930
- executeOne({ id: 'diff-sec', agent: 'security-scanner', task: 'Scan this git diff for security vulnerabilities', code: diff, context }),
931
- executeOne({ id: 'diff-secrets', agent: 'secrets', task: 'Scan this git diff for exposed secrets or credentials', code: diff }),
932
- ]);
933
- // Derive overall verdict
934
- const hasBlocking = (reviewResult.analysis?.critical_count ?? 0) > 0
935
- || (secResult.analysis?.critical_count ?? 0) > 0
936
- || (secretsResult.analysis?.critical_count ?? 0) > 0;
937
- const hasWarnings = (reviewResult.analysis?.high_count ?? 0) > 0
938
- || (secResult.analysis?.high_count ?? 0) > 0;
939
- const verdict = hasBlocking ? 'fail' : hasWarnings ? 'warn' : 'pass';
1047
+ const { reviewResult, secResult, secretsResult, verdict } = await runTripleScan(diff, context);
940
1048
  const verdictEmoji = verdict === 'pass' ? '✅ PASS' : verdict === 'warn' ? '⚠️ WARN' : '❌ FAIL';
941
1049
  // Per-file finding counts (approximate from line refs)
942
1050
  const fileFindings = {};
@@ -1166,15 +1274,28 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1166
1274
  if (!summary || !context) {
1167
1275
  return { content: [{ type: 'text', text: JSON.stringify({ success: false, message: 'summary and context are required.' }) }], isError: true };
1168
1276
  }
1277
+ const handoffPlatform = args?.from_platform ? String(args.from_platform) : 'claude';
1278
+ const handoffTaskState = args?.task_state ? String(args.task_state) : undefined;
1279
+ const handoffProjectDir = args?.project_dir ? String(args.project_dir) : undefined;
1169
1280
  const result = handoff({
1170
1281
  summary,
1171
1282
  context,
1172
- task_state: args?.task_state ? String(args.task_state) : undefined,
1173
- from_platform: args?.from_platform ? String(args.from_platform) : 'claude',
1283
+ task_state: handoffTaskState,
1284
+ from_platform: handoffPlatform,
1174
1285
  to_platform: args?.to_platform ? String(args.to_platform) : undefined,
1175
- project_dir: args?.project_dir ? String(args.project_dir) : undefined,
1286
+ project_dir: handoffProjectDir,
1176
1287
  token_count: typeof args?.token_count === 'number' ? args.token_count : 0,
1177
1288
  });
1289
+ // Cache for auto-save
1290
+ autoSave.cached = { summary, context, task_state: handoffTaskState, platform: handoffPlatform, project_dir: handoffProjectDir };
1291
+ autoSave.last_save_at = result.saved_at;
1292
+ autoSave.last_session_id = result.session_id;
1293
+ // Close the current session so ended_at is recorded
1294
+ if (activeProjectDir) {
1295
+ const sessions = listSessions(1);
1296
+ if (sessions[0] && sessions[0].id !== result.session_id)
1297
+ closeSession(sessions[0].id);
1298
+ }
1178
1299
  return { content: [{ type: 'text', text: result.instructions + '\n\n' + JSON.stringify({ session_id: result.session_id, to_platform: result.to_platform, saved_at: result.saved_at, reason: result.reason }, null, 2) }] };
1179
1300
  }
1180
1301
  case 'veto_continue': {
@@ -1229,10 +1350,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1229
1350
  const includeTaskTypes = args?.include_task_types === true;
1230
1351
  const includeCouncil = args?.include_council_insights === true;
1231
1352
  const stats = getLearningStats();
1353
+ const learned = getLearnedThresholds();
1232
1354
  const result = {
1233
1355
  total_outcomes: stats.total_tasks,
1234
1356
  tier_breakdown: stats.tier_breakdown,
1235
- current_thresholds: { tier1_max: 30, tier2_max: 70, note: 'defaults — call veto_learning_apply to update from data' },
1357
+ current_thresholds: {
1358
+ tier1_max: learned.tier1_max,
1359
+ tier2_max: learned.tier2_max,
1360
+ source: learned.source,
1361
+ data_points: learned.data_points,
1362
+ note: learned.source === 'learned'
1363
+ ? `Learned from ${learned.data_points} outcomes.`
1364
+ : 'Using defaults — call veto_learning_apply after 20+ outcomes to update from data.',
1365
+ },
1236
1366
  suggested_thresholds: stats.suggested_thresholds,
1237
1367
  ready_to_apply: stats.total_tasks >= 20,
1238
1368
  };
@@ -1350,7 +1480,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1350
1480
  if (!package_name) {
1351
1481
  return { content: [{ type: 'text', text: JSON.stringify({ success: false, message: 'package_name is required.' }) }], isError: true };
1352
1482
  }
1353
- const result = await fetchAndCacheDocs(package_name, ecosystem, version, max_chars);
1483
+ const result = await fetchAndCacheDocs(package_name, ecosystem, version, max_chars, VERSION);
1354
1484
  if (!result) {
1355
1485
  return { content: [{ type: 'text', text: JSON.stringify({ success: false, message: `Could not fetch docs for ${package_name} (${ecosystem}). Source may be offline — try again.` }) }], isError: true };
1356
1486
  }
@@ -1378,15 +1508,54 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1378
1508
  const planResult = await executeOne({ id: 'task-parse-1', agent: 'task-planner', task: `Parse this project description into a structured task breakdown with dependencies and complexity scores (max ${max_tasks} tasks):\n\n${description}`, context: ctx || undefined, project_dir });
1379
1509
  // Build structured task DAG from planner output
1380
1510
  const steps = planResult.plan?.steps ?? [];
1381
- const tasks = steps.slice(0, max_tasks).map((step, i) => ({
1382
- id: `task-${i + 1}`,
1383
- title: step,
1384
- complexity: Math.min(10, Math.max(1, Math.round((i / steps.length) * 10) + 3)),
1385
- priority: i === 0 ? 'critical' : i < 3 ? 'high' : i < steps.length - 2 ? 'medium' : 'low',
1386
- depends_on: i > 0 ? [`task-${i}`] : [],
1387
- suggested_agent: 'coder',
1388
- estimated_hours: 2,
1389
- }));
1511
+ // Agent keyword map pick the most relevant agent based on step keywords
1512
+ const agentKeywords = [
1513
+ { keywords: /test|spec|coverage|assert|unit|integration/i, agent: 'tester' },
1514
+ { keywords: /secur|auth|jwt|oauth|permission|role|encrypt|hash/i, agent: 'auth' },
1515
+ { keywords: /database|schema|migrat|sql|query|index|table/i, agent: 'database' },
1516
+ { keywords: /api|endpoint|rest|graphql|route|openapi/i, agent: 'api' },
1517
+ { keywords: /ui|component|frontend|react|vue|svelte|html|css|style/i, agent: 'frontend' },
1518
+ { keywords: /docker|deploy|ci|cd|pipeline|container|k8s|infra/i, agent: 'devops' },
1519
+ { keywords: /refactor|clean|restructure|rename|extract/i, agent: 'refactor' },
1520
+ { keywords: /review|audit|quality|lint|check/i, agent: 'reviewer' },
1521
+ { keywords: /debug|fix|bug|error|crash|trace|diagnos/i, agent: 'debugger' },
1522
+ { keywords: /document|readme|comment|jsdoc|wiki/i, agent: 'documentation' },
1523
+ { keywords: /perform|optim|speed|cache|profil|latency/i, agent: 'performance' },
1524
+ { keywords: /migrat|upgrade|version|port|convert/i, agent: 'migration' },
1525
+ ];
1526
+ function pickAgent(step) {
1527
+ for (const { keywords, agent } of agentKeywords) {
1528
+ if (keywords.test(step))
1529
+ return agent;
1530
+ }
1531
+ return 'coder';
1532
+ }
1533
+ // Complexity scoring: longer, more-keyword-dense steps = higher complexity
1534
+ function scoreStep(step) {
1535
+ const words = step.split(/\s+/).length;
1536
+ const hasComplexWords = /integrat|architect|design|implement|optim|migrat|refactor/i.test(step);
1537
+ const base = Math.min(7, Math.max(2, Math.round(words / 3)));
1538
+ return hasComplexWords ? Math.min(10, base + 2) : base;
1539
+ }
1540
+ // Dependency inference: look for explicit "after", "before", "requires", "depends" keywords
1541
+ function inferDeps(step, allSteps, idx) {
1542
+ const lower = step.toLowerCase();
1543
+ if (/^(deploy|test|release|publish|document)/i.test(step.trim()) && idx > 0) {
1544
+ return [`task-${idx}`];
1545
+ }
1546
+ if (/after.{0,30}(setup|init|instal|creat|build)/i.test(lower) && idx > 0) {
1547
+ return [`task-${idx}`];
1548
+ }
1549
+ return idx > 0 && /integrat|connect|wire|link/i.test(lower) ? [`task-${idx}`] : [];
1550
+ }
1551
+ const tasks = steps.slice(0, max_tasks).map((step, i) => {
1552
+ const complexity = scoreStep(step);
1553
+ const agent = pickAgent(step);
1554
+ const deps = inferDeps(step, steps, i);
1555
+ const priority = i === 0 ? 'critical' : complexity >= 7 ? 'high' : complexity >= 5 ? 'medium' : 'low';
1556
+ const estimated_hours = complexity <= 3 ? 1 : complexity <= 6 ? 2 : complexity <= 8 ? 4 : 8;
1557
+ return { id: `task-${i + 1}`, title: step, complexity, priority, depends_on: deps, suggested_agent: agent, estimated_hours };
1558
+ });
1390
1559
  const plan = {
1391
1560
  summary: description.slice(0, 100),
1392
1561
  total_tasks: tasks.length,
@@ -1456,9 +1625,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1456
1625
  // Read diff if not provided
1457
1626
  let diff = diff_input;
1458
1627
  if (!diff) {
1459
- const { execSync } = await import('node:child_process');
1460
1628
  try {
1461
- diff = execSync('git diff HEAD', { cwd: project_dir, encoding: 'utf8', timeout: 15000 });
1629
+ diff = execSyncTop('git diff HEAD', { cwd: project_dir, encoding: 'utf8', timeout: 15000 });
1462
1630
  }
1463
1631
  catch {
1464
1632
  diff = '';
@@ -1467,7 +1635,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1467
1635
  if (!diff?.trim()) {
1468
1636
  return { content: [{ type: 'text', text: JSON.stringify({ verdict: 'pass', exit_code: 0, message: 'No changes detected.', duration_ms: Date.now() - start }) }] };
1469
1637
  }
1470
- // Run all three checks in parallel
1471
1638
  const projectCtx = (() => { try {
1472
1639
  return buildContextString(project_dir);
1473
1640
  }
@@ -1475,36 +1642,27 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1475
1642
  return '';
1476
1643
  } })();
1477
1644
  const fullContext = [context, projectCtx].filter(Boolean).join('\n\n');
1478
- const [codeResult, secResult, secretsResult] = await Promise.all([
1479
- executeOne({ id: 'ci-code', agent: 'reviewer', task: `CI code review of this diff:\n\n${diff}`, context: fullContext }),
1480
- executeOne({ id: 'ci-sec', agent: 'security-scanner', task: `CI security scan of this diff:\n\n${diff}`, context: fullContext }),
1481
- executeOne({ id: 'ci-secrets', agent: 'secrets', task: `CI secrets scan — check for exposed credentials in this diff:\n\n${diff}`, context: fullContext }),
1482
- ]);
1483
- const codeConf = codeResult.output?.confidence ?? 0.8;
1484
- const secConf = secResult.output?.confidence ?? 0.8;
1485
- const secretsConf = secretsResult.output?.confidence ?? 1.0;
1486
- // Determine verdict
1487
- const hasCritical = codeConf < 0.4 || secConf < 0.4 || secretsConf < 0.5;
1488
- const hasWarn = codeConf < 0.7 || secConf < 0.6;
1489
- const rawVerdict = hasCritical ? 'fail' : hasWarn ? 'warn' : 'pass';
1490
- const verdict = rawVerdict;
1491
- const exit_code = rawVerdict === 'fail' || (rawVerdict === 'warn' && fail_on === 'warn') ? 1 : 0;
1645
+ const { reviewResult: codeResult, secResult, secretsResult, verdict } = await runTripleScan(diff, fullContext);
1646
+ const exit_code = verdict === 'fail' || (verdict === 'warn' && fail_on === 'warn') ? 1 : 0;
1647
+ const codeScore = codeResult.analysis?.score ?? Math.round((codeResult.output?.confidence ?? 0.8) * 100);
1648
+ const secScore = secResult.analysis?.score ?? Math.round((secResult.output?.confidence ?? 0.8) * 100);
1649
+ const secretsClean = (secretsResult.analysis?.findings?.length ?? 0) === 0;
1492
1650
  const blocking_issues = [];
1493
- if (codeConf < 0.7)
1494
- blocking_issues.push(`Code review: ${codeResult.output?.recommendation ?? 'issues found'}`);
1495
- if (secConf < 0.6)
1496
- blocking_issues.push(`Security: ${secResult.output?.recommendation ?? 'vulnerabilities detected'}`);
1497
- if (secretsConf < 0.5)
1498
- blocking_issues.push(`Secrets: ${secretsResult.output?.recommendation ?? 'potential secrets exposed'}`);
1651
+ if ((codeResult.analysis?.critical_count ?? 0) > 0)
1652
+ blocking_issues.push(`Code review: ${codeResult.analysis?.summary ?? 'critical issues found'}`);
1653
+ if ((secResult.analysis?.critical_count ?? 0) > 0)
1654
+ blocking_issues.push(`Security: ${secResult.analysis?.summary ?? 'vulnerabilities detected'}`);
1655
+ if (!secretsClean)
1656
+ blocking_issues.push(`Secrets: ${secretsResult.analysis?.summary ?? 'exposed credentials detected'}`);
1499
1657
  const icon = verdict === 'pass' ? '✅' : verdict === 'warn' ? '⚠️' : '❌';
1500
1658
  const ci_summary = [
1501
1659
  `${icon} **Veto CI Gate: ${verdict.toUpperCase()}**`,
1502
1660
  ``,
1503
1661
  `| Check | Score | Status |`,
1504
1662
  `|---|---|---|`,
1505
- `| Code Review | ${Math.round(codeConf * 100)}% | ${codeConf >= 0.7 ? '✅' : '❌'} |`,
1506
- `| Security Scan | ${Math.round(secConf * 100)}% | ${secConf >= 0.6 ? '✅' : '❌'} |`,
1507
- `| Secrets Scan | ${Math.round(secretsConf * 100)}% | ${secretsConf >= 0.5 ? '✅' : '❌'} |`,
1663
+ `| Code Review | ${codeScore}% | ${(codeResult.analysis?.critical_count ?? 0) === 0 ? '✅' : '❌'} |`,
1664
+ `| Security Scan | ${secScore}% | ${(secResult.analysis?.critical_count ?? 0) === 0 ? '✅' : '❌'} |`,
1665
+ `| Secrets Scan | | ${secretsClean ? '✅ Clean' : '❌ Found'} |`,
1508
1666
  blocking_issues.length > 0 ? `\n**Blocking issues:**\n${blocking_issues.map(i => `- ${i}`).join('\n')}` : '',
1509
1667
  ].filter(Boolean).join('\n');
1510
1668
  return {
@@ -1513,9 +1671,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1513
1671
  text: JSON.stringify({
1514
1672
  verdict, exit_code,
1515
1673
  checks: {
1516
- code_review: { score: Math.round(codeConf * 100) },
1517
- security: { score: Math.round(secConf * 100) },
1518
- secrets: { score: Math.round(secretsConf * 100) },
1674
+ code_review: { score: codeScore, critical: codeResult.analysis?.critical_count ?? 0, high: codeResult.analysis?.high_count ?? 0 },
1675
+ security: { score: secScore, critical: secResult.analysis?.critical_count ?? 0, high: secResult.analysis?.high_count ?? 0 },
1676
+ secrets: { clean: secretsClean, findings: secretsResult.analysis?.findings ?? [] },
1519
1677
  },
1520
1678
  blocking_issues,
1521
1679
  ci_summary,
@@ -1524,6 +1682,72 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1524
1682
  }],
1525
1683
  };
1526
1684
  }
1685
+ case 'veto_pr_review': {
1686
+ const pr_url = String(args?.pr_url ?? '').trim();
1687
+ const context = args?.context ? String(args.context) : '';
1688
+ const fail_on = args?.fail_on === 'warn' ? 'warn' : 'fail';
1689
+ if (!pr_url) {
1690
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, message: 'pr_url is required.' }) }], isError: true };
1691
+ }
1692
+ const start = Date.now();
1693
+ const fetched = await fetchPrDiff(pr_url);
1694
+ if (!fetched.ok) {
1695
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, message: fetched.error }) }], isError: true };
1696
+ }
1697
+ const { diff, meta } = fetched;
1698
+ const prContext = [
1699
+ `PR: ${meta.title} (${meta.html_url})`,
1700
+ `Author: ${meta.author} · ${meta.head_branch} → ${meta.base_branch}`,
1701
+ `Changes: +${meta.additions} -${meta.deletions} across ${meta.changed_files} files`,
1702
+ context,
1703
+ ].filter(Boolean).join('\n');
1704
+ const { reviewResult, secResult, secretsResult, verdict } = await runTripleScan(diff, prContext);
1705
+ const exit_code = verdict === 'fail' || (verdict === 'warn' && fail_on === 'warn') ? 1 : 0;
1706
+ const codeScore = reviewResult.analysis?.score ?? Math.round((reviewResult.output?.confidence ?? 0.8) * 100);
1707
+ const secScore = secResult.analysis?.score ?? Math.round((secResult.output?.confidence ?? 0.8) * 100);
1708
+ const secretsClean = (secretsResult.analysis?.findings?.length ?? 0) === 0;
1709
+ const blocking_issues = [];
1710
+ if ((reviewResult.analysis?.critical_count ?? 0) > 0)
1711
+ blocking_issues.push(`Code review: ${reviewResult.analysis?.summary ?? 'critical issues found'}`);
1712
+ if ((secResult.analysis?.critical_count ?? 0) > 0)
1713
+ blocking_issues.push(`Security: ${secResult.analysis?.summary ?? 'vulnerabilities detected'}`);
1714
+ if (!secretsClean)
1715
+ blocking_issues.push(`Secrets: ${secretsResult.analysis?.summary ?? 'exposed credentials detected'}`);
1716
+ // Build ready-to-post GitHub review comment (Markdown)
1717
+ const icon = verdict === 'pass' ? '✅' : verdict === 'warn' ? '⚠️' : '❌';
1718
+ const review_comment = [
1719
+ `## ${icon} Veto Review — ${verdict.toUpperCase()}`,
1720
+ ``,
1721
+ `| Check | Score | Status |`,
1722
+ `|---|---|---|`,
1723
+ `| Code Review | ${codeScore}% | ${(reviewResult.analysis?.critical_count ?? 0) === 0 ? '✅' : '❌'} |`,
1724
+ `| Security Scan | ${secScore}% | ${(secResult.analysis?.critical_count ?? 0) === 0 ? '✅' : '❌'} |`,
1725
+ `| Secrets Scan | — | ${secretsClean ? '✅ Clean' : '❌ Found'} |`,
1726
+ ``,
1727
+ blocking_issues.length > 0
1728
+ ? `**Blocking issues:**\n${blocking_issues.map(i => `- ${i}`).join('\n')}`
1729
+ : `No blocking issues found.`,
1730
+ ``,
1731
+ `> Reviewed by [Veto](https://github.com/jigyasudham/veto) · ${meta.changed_files} files · +${meta.additions}/-${meta.deletions} · ${Date.now() - start}ms`,
1732
+ ].join('\n');
1733
+ return {
1734
+ content: [{
1735
+ type: 'text',
1736
+ text: JSON.stringify({
1737
+ verdict, exit_code,
1738
+ pr: { title: meta.title, author: meta.author, url: meta.html_url, base: meta.base_branch, head: meta.head_branch, additions: meta.additions, deletions: meta.deletions, changed_files: meta.changed_files },
1739
+ checks: {
1740
+ code_review: { score: codeScore, critical: reviewResult.analysis?.critical_count ?? 0, high: reviewResult.analysis?.high_count ?? 0 },
1741
+ security: { score: secScore, critical: secResult.analysis?.critical_count ?? 0, high: secResult.analysis?.high_count ?? 0 },
1742
+ secrets: { clean: secretsClean, findings: secretsResult.analysis?.findings ?? [] },
1743
+ },
1744
+ blocking_issues,
1745
+ review_comment,
1746
+ duration_ms: Date.now() - start,
1747
+ }, null, 2),
1748
+ }],
1749
+ };
1750
+ }
1527
1751
  default:
1528
1752
  throw new Error(`Unknown tool: ${name}`);
1529
1753
  }