@jigyasudham/veto 1.2.2 → 1.2.6
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 +29 -6
- package/dist/adapters/index.d.ts +46 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +47 -8
- package/dist/adapters/index.js.map +1 -0
- package/dist/agents/development/api.d.ts +3 -0
- package/dist/agents/development/api.d.ts.map +1 -0
- package/dist/agents/development/api.js.map +1 -0
- package/dist/agents/development/backend.d.ts +3 -0
- package/dist/agents/development/backend.d.ts.map +1 -0
- package/dist/agents/development/backend.js.map +1 -0
- package/dist/agents/development/coder.d.ts +3 -0
- package/dist/agents/development/coder.d.ts.map +1 -0
- package/dist/agents/development/coder.js.map +1 -0
- package/dist/agents/development/database.d.ts +3 -0
- package/dist/agents/development/database.d.ts.map +1 -0
- package/dist/agents/development/database.js +175 -52
- package/dist/agents/development/database.js.map +1 -0
- package/dist/agents/development/debugger.d.ts +3 -0
- package/dist/agents/development/debugger.d.ts.map +1 -0
- package/dist/agents/development/debugger.js.map +1 -0
- package/dist/agents/development/devops.d.ts +3 -0
- package/dist/agents/development/devops.d.ts.map +1 -0
- package/dist/agents/development/devops.js +190 -55
- package/dist/agents/development/devops.js.map +1 -0
- package/dist/agents/development/frontend.d.ts +3 -0
- package/dist/agents/development/frontend.d.ts.map +1 -0
- package/dist/agents/development/frontend.js.map +1 -0
- package/dist/agents/development/migration.d.ts +3 -0
- package/dist/agents/development/migration.d.ts.map +1 -0
- package/dist/agents/development/migration.js.map +1 -0
- package/dist/agents/development/performance.d.ts +3 -0
- package/dist/agents/development/performance.d.ts.map +1 -0
- package/dist/agents/development/performance.js.map +1 -0
- package/dist/agents/development/refactor.d.ts +3 -0
- package/dist/agents/development/refactor.d.ts.map +1 -0
- package/dist/agents/development/refactor.js.map +1 -0
- package/dist/agents/development/reviewer.d.ts +4 -0
- package/dist/agents/development/reviewer.d.ts.map +1 -0
- package/dist/agents/development/reviewer.js +34 -17
- package/dist/agents/development/reviewer.js.map +1 -0
- package/dist/agents/development/tester.d.ts +3 -0
- package/dist/agents/development/tester.d.ts.map +1 -0
- package/dist/agents/development/tester.js.map +1 -0
- package/dist/agents/executor.d.ts +4 -0
- package/dist/agents/executor.d.ts.map +1 -0
- package/dist/agents/executor.js +10 -1
- package/dist/agents/executor.js.map +1 -0
- package/dist/agents/memory/context-manager.d.ts +3 -0
- package/dist/agents/memory/context-manager.d.ts.map +1 -0
- package/dist/agents/memory/context-manager.js.map +1 -0
- package/dist/agents/memory/decision-logger.d.ts +3 -0
- package/dist/agents/memory/decision-logger.d.ts.map +1 -0
- package/dist/agents/memory/decision-logger.js.map +1 -0
- package/dist/agents/memory/knowledge-base.d.ts +3 -0
- package/dist/agents/memory/knowledge-base.d.ts.map +1 -0
- package/dist/agents/memory/knowledge-base.js.map +1 -0
- package/dist/agents/memory/pattern-learner.d.ts +3 -0
- package/dist/agents/memory/pattern-learner.d.ts.map +1 -0
- package/dist/agents/memory/pattern-learner.js.map +1 -0
- package/dist/agents/memory/project-mapper.d.ts +3 -0
- package/dist/agents/memory/project-mapper.d.ts.map +1 -0
- package/dist/agents/memory/project-mapper.js.map +1 -0
- package/dist/agents/quality/accessibility.d.ts +4 -0
- package/dist/agents/quality/accessibility.d.ts.map +1 -0
- package/dist/agents/quality/accessibility.js.map +1 -0
- package/dist/agents/quality/code-quality.d.ts +4 -0
- package/dist/agents/quality/code-quality.d.ts.map +1 -0
- package/dist/agents/quality/code-quality.js.map +1 -0
- package/dist/agents/quality/compatibility.d.ts +3 -0
- package/dist/agents/quality/compatibility.d.ts.map +1 -0
- package/dist/agents/quality/compatibility.js.map +1 -0
- package/dist/agents/quality/documentation.d.ts +4 -0
- package/dist/agents/quality/documentation.d.ts.map +1 -0
- package/dist/agents/quality/documentation.js.map +1 -0
- package/dist/agents/quality/error-handling.d.ts +4 -0
- package/dist/agents/quality/error-handling.d.ts.map +1 -0
- package/dist/agents/quality/error-handling.js.map +1 -0
- package/dist/agents/research/competitor-analyzer.d.ts +3 -0
- package/dist/agents/research/competitor-analyzer.d.ts.map +1 -0
- package/dist/agents/research/competitor-analyzer.js.map +1 -0
- package/dist/agents/research/cost-analyzer.d.ts +3 -0
- package/dist/agents/research/cost-analyzer.d.ts.map +1 -0
- package/dist/agents/research/cost-analyzer.js.map +1 -0
- package/dist/agents/research/estimator.d.ts +3 -0
- package/dist/agents/research/estimator.d.ts.map +1 -0
- package/dist/agents/research/estimator.js.map +1 -0
- package/dist/agents/research/ethics-bias.d.ts +3 -0
- package/dist/agents/research/ethics-bias.d.ts.map +1 -0
- package/dist/agents/research/ethics-bias.js.map +1 -0
- package/dist/agents/research/researcher.d.ts +3 -0
- package/dist/agents/research/researcher.d.ts.map +1 -0
- package/dist/agents/research/researcher.js.map +1 -0
- package/dist/agents/research/risk-assessor.d.ts +3 -0
- package/dist/agents/research/risk-assessor.d.ts.map +1 -0
- package/dist/agents/research/risk-assessor.js.map +1 -0
- package/dist/agents/research/tech-advisor.d.ts +3 -0
- package/dist/agents/research/tech-advisor.d.ts.map +1 -0
- package/dist/agents/research/tech-advisor.js.map +1 -0
- package/dist/agents/security/auth.d.ts +3 -0
- package/dist/agents/security/auth.d.ts.map +1 -0
- package/dist/agents/security/auth.js.map +1 -0
- package/dist/agents/security/dependency-audit.d.ts +19 -0
- package/dist/agents/security/dependency-audit.d.ts.map +1 -0
- package/dist/agents/security/dependency-audit.js.map +1 -0
- package/dist/agents/security/penetration.d.ts +3 -0
- package/dist/agents/security/penetration.d.ts.map +1 -0
- package/dist/agents/security/penetration.js.map +1 -0
- package/dist/agents/security/privacy.d.ts +3 -0
- package/dist/agents/security/privacy.d.ts.map +1 -0
- package/dist/agents/security/privacy.js.map +1 -0
- package/dist/agents/security/scanner.d.ts +4 -0
- package/dist/agents/security/scanner.d.ts.map +1 -0
- package/dist/agents/security/scanner.js.map +1 -0
- package/dist/agents/security/secrets.d.ts +12 -0
- package/dist/agents/security/secrets.d.ts.map +1 -0
- package/dist/agents/security/secrets.js.map +1 -0
- package/dist/agents/types.d.ts +62 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/agents/workflow/automation.d.ts +3 -0
- package/dist/agents/workflow/automation.d.ts.map +1 -0
- package/dist/agents/workflow/automation.js.map +1 -0
- package/dist/agents/workflow/file-manager.d.ts +3 -0
- package/dist/agents/workflow/file-manager.d.ts.map +1 -0
- package/dist/agents/workflow/file-manager.js.map +1 -0
- package/dist/agents/workflow/git-agent.d.ts +3 -0
- package/dist/agents/workflow/git-agent.d.ts.map +1 -0
- package/dist/agents/workflow/git-agent.js.map +1 -0
- package/dist/agents/workflow/reporter.d.ts +3 -0
- package/dist/agents/workflow/reporter.d.ts.map +1 -0
- package/dist/agents/workflow/reporter.js.map +1 -0
- package/dist/agents/workflow/search-agent.d.ts +3 -0
- package/dist/agents/workflow/search-agent.d.ts.map +1 -0
- package/dist/agents/workflow/search-agent.js.map +1 -0
- package/dist/agents/workflow/task-coordinator.d.ts +3 -0
- package/dist/agents/workflow/task-coordinator.d.ts.map +1 -0
- package/dist/agents/workflow/task-coordinator.js.map +1 -0
- package/dist/agents/workflow/task-planner.d.ts +3 -0
- package/dist/agents/workflow/task-planner.d.ts.map +1 -0
- package/dist/agents/workflow/task-planner.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +5 -3
- package/dist/cli.js.map +1 -0
- package/dist/context/reader.d.ts +12 -0
- package/dist/context/reader.d.ts.map +1 -0
- package/dist/context/reader.js.map +1 -0
- package/dist/council/decision-engine.d.ts +11 -0
- package/dist/council/decision-engine.d.ts.map +1 -0
- package/dist/council/decision-engine.js.map +1 -0
- package/dist/council/devil-advocate.d.ts +3 -0
- package/dist/council/devil-advocate.d.ts.map +1 -0
- package/dist/council/devil-advocate.js +46 -0
- package/dist/council/devil-advocate.js.map +1 -0
- package/dist/council/index.d.ts +4 -0
- package/dist/council/index.d.ts.map +1 -0
- package/dist/council/index.js +9 -11
- package/dist/council/index.js.map +1 -0
- package/dist/council/lead-developer.d.ts +3 -0
- package/dist/council/lead-developer.d.ts.map +1 -0
- package/dist/council/lead-developer.js +65 -1
- package/dist/council/lead-developer.js.map +1 -0
- package/dist/council/legal-compliance.d.ts +3 -0
- package/dist/council/legal-compliance.d.ts.map +1 -0
- package/dist/council/legal-compliance.js +43 -0
- package/dist/council/legal-compliance.js.map +1 -0
- package/dist/council/product-manager.d.ts +3 -0
- package/dist/council/product-manager.d.ts.map +1 -0
- package/dist/council/product-manager.js +47 -0
- package/dist/council/product-manager.js.map +1 -0
- package/dist/council/security.d.ts +3 -0
- package/dist/council/security.d.ts.map +1 -0
- package/dist/council/security.js +48 -0
- package/dist/council/security.js.map +1 -0
- package/dist/council/system-architect.d.ts +3 -0
- package/dist/council/system-architect.d.ts.map +1 -0
- package/dist/council/system-architect.js +53 -1
- package/dist/council/system-architect.js.map +1 -0
- package/dist/council/types.d.ts +32 -0
- package/dist/council/types.d.ts.map +1 -0
- package/dist/council/types.js.map +1 -0
- package/dist/council/ux-designer.d.ts +3 -0
- package/dist/council/ux-designer.d.ts.map +1 -0
- package/dist/council/ux-designer.js +44 -1
- package/dist/council/ux-designer.js.map +1 -0
- package/dist/github/pr-fetcher.d.ts +25 -0
- package/dist/github/pr-fetcher.d.ts.map +1 -0
- package/dist/github/pr-fetcher.js +60 -0
- package/dist/github/pr-fetcher.js.map +1 -0
- package/dist/memory/local.d.ts +144 -0
- package/dist/memory/local.d.ts.map +1 -0
- package/dist/memory/local.js +19 -19
- package/dist/memory/local.js.map +1 -0
- package/dist/memory/schema.d.ts +81 -0
- package/dist/memory/schema.d.ts.map +1 -0
- package/dist/memory/schema.js +2 -1
- package/dist/memory/schema.js.map +1 -0
- package/dist/memory/sync.d.ts +24 -0
- package/dist/memory/sync.d.ts.map +1 -0
- package/dist/memory/sync.js.map +1 -0
- package/dist/plugins/loader.d.ts +13 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/router/complexity-scorer.d.ts +18 -0
- package/dist/router/complexity-scorer.d.ts.map +1 -0
- package/dist/router/complexity-scorer.js.map +1 -0
- package/dist/router/context-compressor.d.ts +11 -0
- package/dist/router/context-compressor.d.ts.map +1 -0
- package/dist/router/context-compressor.js.map +1 -0
- package/dist/router/index.d.ts +27 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/learning-updater.d.ts +61 -0
- package/dist/router/learning-updater.d.ts.map +1 -0
- package/dist/router/learning-updater.js.map +1 -0
- package/dist/router/model-selector.d.ts +14 -0
- package/dist/router/model-selector.d.ts.map +1 -0
- package/dist/router/model-selector.js.map +1 -0
- package/dist/router/rate-monitor.d.ts +19 -0
- package/dist/router/rate-monitor.d.ts.map +1 -0
- package/dist/router/rate-monitor.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +297 -73
- package/dist/server.js.map +1 -0
- package/dist/skills/development/skill-api-design.d.ts +15 -0
- package/dist/skills/development/skill-api-design.d.ts.map +1 -0
- package/dist/skills/development/skill-api-design.js.map +1 -0
- package/dist/skills/development/skill-auth.d.ts +15 -0
- package/dist/skills/development/skill-auth.d.ts.map +1 -0
- package/dist/skills/development/skill-auth.js.map +1 -0
- package/dist/skills/development/skill-ci-cd.d.ts +2 -0
- package/dist/skills/development/skill-ci-cd.d.ts.map +1 -0
- package/dist/skills/development/skill-ci-cd.js.map +1 -0
- package/dist/skills/development/skill-crud.d.ts +15 -0
- package/dist/skills/development/skill-crud.d.ts.map +1 -0
- package/dist/skills/development/skill-crud.js.map +1 -0
- package/dist/skills/development/skill-db-schema.d.ts +2 -0
- package/dist/skills/development/skill-db-schema.d.ts.map +1 -0
- package/dist/skills/development/skill-db-schema.js.map +1 -0
- package/dist/skills/development/skill-docker.d.ts +2 -0
- package/dist/skills/development/skill-docker.d.ts.map +1 -0
- package/dist/skills/development/skill-docker.js.map +1 -0
- package/dist/skills/development/skill-env-setup.d.ts +2 -0
- package/dist/skills/development/skill-env-setup.d.ts.map +1 -0
- package/dist/skills/development/skill-env-setup.js.map +1 -0
- package/dist/skills/development/skill-scaffold.d.ts +15 -0
- package/dist/skills/development/skill-scaffold.d.ts.map +1 -0
- package/dist/skills/development/skill-scaffold.js.map +1 -0
- package/dist/skills/intelligence/skill-complexity-score.d.ts +15 -0
- package/dist/skills/intelligence/skill-complexity-score.d.ts.map +1 -0
- package/dist/skills/intelligence/skill-complexity-score.js.map +1 -0
- package/dist/skills/intelligence/skill-cost-track.d.ts +14 -0
- package/dist/skills/intelligence/skill-cost-track.d.ts.map +1 -0
- package/dist/skills/intelligence/skill-cost-track.js.map +1 -0
- package/dist/skills/intelligence/skill-learning-loop.d.ts +15 -0
- package/dist/skills/intelligence/skill-learning-loop.d.ts.map +1 -0
- package/dist/skills/intelligence/skill-learning-loop.js.map +1 -0
- package/dist/skills/intelligence/skill-pattern-detect.d.ts +14 -0
- package/dist/skills/intelligence/skill-pattern-detect.d.ts.map +1 -0
- package/dist/skills/intelligence/skill-pattern-detect.js.map +1 -0
- package/dist/skills/intelligence/skill-rate-watch.d.ts +15 -0
- package/dist/skills/intelligence/skill-rate-watch.d.ts.map +1 -0
- package/dist/skills/intelligence/skill-rate-watch.js.map +1 -0
- package/dist/skills/memory/skill-context-compress.d.ts +15 -0
- package/dist/skills/memory/skill-context-compress.d.ts.map +1 -0
- package/dist/skills/memory/skill-context-compress.js.map +1 -0
- package/dist/skills/memory/skill-cross-sync.d.ts +15 -0
- package/dist/skills/memory/skill-cross-sync.d.ts.map +1 -0
- package/dist/skills/memory/skill-cross-sync.js.map +1 -0
- package/dist/skills/memory/skill-decision-log.d.ts +15 -0
- package/dist/skills/memory/skill-decision-log.d.ts.map +1 -0
- package/dist/skills/memory/skill-decision-log.js.map +1 -0
- package/dist/skills/memory/skill-session-restore.d.ts +15 -0
- package/dist/skills/memory/skill-session-restore.d.ts.map +1 -0
- package/dist/skills/memory/skill-session-restore.js.map +1 -0
- package/dist/skills/memory/skill-session-save.d.ts +15 -0
- package/dist/skills/memory/skill-session-save.d.ts.map +1 -0
- package/dist/skills/memory/skill-session-save.js.map +1 -0
- package/dist/skills/quality/skill-accessibility.d.ts +2 -0
- package/dist/skills/quality/skill-accessibility.d.ts.map +1 -0
- package/dist/skills/quality/skill-accessibility.js.map +1 -0
- package/dist/skills/quality/skill-code-review.d.ts +15 -0
- package/dist/skills/quality/skill-code-review.d.ts.map +1 -0
- package/dist/skills/quality/skill-code-review.js.map +1 -0
- package/dist/skills/quality/skill-docs-gen.d.ts +2 -0
- package/dist/skills/quality/skill-docs-gen.d.ts.map +1 -0
- package/dist/skills/quality/skill-docs-gen.js.map +1 -0
- package/dist/skills/quality/skill-perf-audit.d.ts +2 -0
- package/dist/skills/quality/skill-perf-audit.d.ts.map +1 -0
- package/dist/skills/quality/skill-perf-audit.js.map +1 -0
- package/dist/skills/quality/skill-security-scan.d.ts +15 -0
- package/dist/skills/quality/skill-security-scan.d.ts.map +1 -0
- package/dist/skills/quality/skill-security-scan.js.map +1 -0
- package/dist/skills/quality/skill-test-suite.d.ts +15 -0
- package/dist/skills/quality/skill-test-suite.d.ts.map +1 -0
- package/dist/skills/quality/skill-test-suite.js.map +1 -0
- package/dist/skills/workflow/skill-deploy.d.ts +2 -0
- package/dist/skills/workflow/skill-deploy.d.ts.map +1 -0
- package/dist/skills/workflow/skill-deploy.js.map +1 -0
- package/dist/skills/workflow/skill-git-workflow.d.ts +2 -0
- package/dist/skills/workflow/skill-git-workflow.d.ts.map +1 -0
- package/dist/skills/workflow/skill-git-workflow.js.map +1 -0
- package/dist/skills/workflow/skill-rollback.d.ts +2 -0
- package/dist/skills/workflow/skill-rollback.d.ts.map +1 -0
- package/dist/skills/workflow/skill-rollback.js.map +1 -0
- package/dist/skills/workflow/skill-task-breakdown.d.ts +2 -0
- package/dist/skills/workflow/skill-task-breakdown.d.ts.map +1 -0
- package/dist/skills/workflow/skill-task-breakdown.js.map +1 -0
- package/dist/watcher/index.d.ts +23 -0
- package/dist/watcher/index.d.ts.map +1 -0
- package/dist/watcher/index.js.map +1 -0
- package/dist/workflow/pipeline.d.ts +35 -0
- package/dist/workflow/pipeline.d.ts.map +1 -0
- package/dist/workflow/pipeline.js.map +1 -0
- package/package.json +2 -2
- package/dist/adapters/claude.js +0 -57
- package/dist/adapters/codex.js +0 -58
- package/dist/adapters/gemini.js +0 -58
- package/vitest.config.ts +0 -11
package/dist/server.js
CHANGED
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// Veto MCP Server —
|
|
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
|
-
|
|
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:
|
|
694
|
-
capabilities: [
|
|
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:
|
|
709
|
-
context:
|
|
710
|
-
task_state:
|
|
711
|
-
platform:
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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:
|
|
1173
|
-
from_platform:
|
|
1283
|
+
task_state: handoffTaskState,
|
|
1284
|
+
from_platform: handoffPlatform,
|
|
1174
1285
|
to_platform: args?.to_platform ? String(args.to_platform) : undefined,
|
|
1175
|
-
project_dir:
|
|
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: {
|
|
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
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
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 =
|
|
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
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
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 (
|
|
1494
|
-
blocking_issues.push(`Code review: ${codeResult.
|
|
1495
|
-
if (
|
|
1496
|
-
blocking_issues.push(`Security: ${secResult.
|
|
1497
|
-
if (
|
|
1498
|
-
blocking_issues.push(`Secrets: ${secretsResult.
|
|
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 | ${
|
|
1506
|
-
`| Security Scan | ${
|
|
1507
|
-
`| Secrets Scan |
|
|
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:
|
|
1517
|
-
security: { score:
|
|
1518
|
-
secrets: {
|
|
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
|
}
|