@jigyasudham/veto 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/README.md +190 -0
  3. package/dist/adapters/claude.js +57 -0
  4. package/dist/adapters/codex.js +58 -0
  5. package/dist/adapters/gemini.js +58 -0
  6. package/dist/adapters/index.js +156 -0
  7. package/dist/agents/development/api.js +116 -0
  8. package/dist/agents/development/backend.js +82 -0
  9. package/dist/agents/development/coder.js +207 -0
  10. package/dist/agents/development/database.js +81 -0
  11. package/dist/agents/development/debugger.js +234 -0
  12. package/dist/agents/development/devops.js +84 -0
  13. package/dist/agents/development/frontend.js +83 -0
  14. package/dist/agents/development/migration.js +141 -0
  15. package/dist/agents/development/performance.js +142 -0
  16. package/dist/agents/development/refactor.js +85 -0
  17. package/dist/agents/development/reviewer.js +260 -0
  18. package/dist/agents/development/tester.js +143 -0
  19. package/dist/agents/executor.js +144 -0
  20. package/dist/agents/memory/context-manager.js +167 -0
  21. package/dist/agents/memory/decision-logger.js +157 -0
  22. package/dist/agents/memory/knowledge-base.js +120 -0
  23. package/dist/agents/memory/pattern-learner.js +140 -0
  24. package/dist/agents/memory/project-mapper.js +114 -0
  25. package/dist/agents/quality/accessibility.js +89 -0
  26. package/dist/agents/quality/code-quality.js +109 -0
  27. package/dist/agents/quality/compatibility.js +55 -0
  28. package/dist/agents/quality/documentation.js +95 -0
  29. package/dist/agents/quality/error-handling.js +87 -0
  30. package/dist/agents/research/competitor-analyzer.js +44 -0
  31. package/dist/agents/research/cost-analyzer.js +51 -0
  32. package/dist/agents/research/estimator.js +57 -0
  33. package/dist/agents/research/ethics-bias.js +111 -0
  34. package/dist/agents/research/researcher.js +112 -0
  35. package/dist/agents/research/risk-assessor.js +61 -0
  36. package/dist/agents/research/tech-advisor.js +52 -0
  37. package/dist/agents/security/auth.js +269 -0
  38. package/dist/agents/security/dependency-audit.js +273 -0
  39. package/dist/agents/security/penetration.js +245 -0
  40. package/dist/agents/security/privacy.js +259 -0
  41. package/dist/agents/security/scanner.js +288 -0
  42. package/dist/agents/security/secrets.js +212 -0
  43. package/dist/agents/types.js +2 -0
  44. package/dist/agents/workflow/automation.js +56 -0
  45. package/dist/agents/workflow/file-manager.js +49 -0
  46. package/dist/agents/workflow/git-agent.js +52 -0
  47. package/dist/agents/workflow/reporter.js +48 -0
  48. package/dist/agents/workflow/search-agent.js +39 -0
  49. package/dist/agents/workflow/task-coordinator.js +40 -0
  50. package/dist/agents/workflow/task-planner.js +46 -0
  51. package/dist/cli.js +132 -0
  52. package/dist/council/decision-engine.js +136 -0
  53. package/dist/council/devil-advocate.js +106 -0
  54. package/dist/council/index.js +37 -0
  55. package/dist/council/lead-developer.js +108 -0
  56. package/dist/council/legal-compliance.js +142 -0
  57. package/dist/council/product-manager.js +92 -0
  58. package/dist/council/security.js +162 -0
  59. package/dist/council/system-architect.js +122 -0
  60. package/dist/council/types.js +2 -0
  61. package/dist/council/ux-designer.js +109 -0
  62. package/dist/memory/local.js +182 -0
  63. package/dist/memory/schema.js +116 -0
  64. package/dist/memory/sync.js +199 -0
  65. package/dist/router/complexity-scorer.js +78 -0
  66. package/dist/router/context-compressor.js +58 -0
  67. package/dist/router/index.js +29 -0
  68. package/dist/router/learning-updater.js +186 -0
  69. package/dist/router/model-selector.js +51 -0
  70. package/dist/router/rate-monitor.js +73 -0
  71. package/dist/server.js +949 -0
  72. package/dist/skills/development/skill-api-design.js +313 -0
  73. package/dist/skills/development/skill-auth.js +255 -0
  74. package/dist/skills/development/skill-ci-cd.js +2 -0
  75. package/dist/skills/development/skill-crud.js +193 -0
  76. package/dist/skills/development/skill-db-schema.js +2 -0
  77. package/dist/skills/development/skill-docker.js +2 -0
  78. package/dist/skills/development/skill-env-setup.js +2 -0
  79. package/dist/skills/development/skill-scaffold.js +299 -0
  80. package/dist/skills/intelligence/skill-complexity-score.js +66 -0
  81. package/dist/skills/intelligence/skill-cost-track.js +36 -0
  82. package/dist/skills/intelligence/skill-learning-loop.js +66 -0
  83. package/dist/skills/intelligence/skill-pattern-detect.js +35 -0
  84. package/dist/skills/intelligence/skill-rate-watch.js +58 -0
  85. package/dist/skills/memory/skill-context-compress.js +82 -0
  86. package/dist/skills/memory/skill-cross-sync.js +88 -0
  87. package/dist/skills/memory/skill-decision-log.js +103 -0
  88. package/dist/skills/memory/skill-session-restore.js +44 -0
  89. package/dist/skills/memory/skill-session-save.js +78 -0
  90. package/dist/skills/quality/skill-accessibility.js +2 -0
  91. package/dist/skills/quality/skill-code-review.js +60 -0
  92. package/dist/skills/quality/skill-docs-gen.js +2 -0
  93. package/dist/skills/quality/skill-perf-audit.js +2 -0
  94. package/dist/skills/quality/skill-security-scan.js +67 -0
  95. package/dist/skills/quality/skill-test-suite.js +274 -0
  96. package/dist/skills/workflow/skill-deploy.js +2 -0
  97. package/dist/skills/workflow/skill-git-workflow.js +2 -0
  98. package/dist/skills/workflow/skill-rollback.js +2 -0
  99. package/dist/skills/workflow/skill-task-breakdown.js +2 -0
  100. package/package.json +30 -0
  101. package/src/adapters/claude.ts +70 -0
  102. package/src/adapters/codex.ts +71 -0
  103. package/src/adapters/gemini.ts +71 -0
  104. package/src/adapters/index.ts +217 -0
  105. package/src/agents/development/api.ts +120 -0
  106. package/src/agents/development/backend.ts +85 -0
  107. package/src/agents/development/coder.ts +213 -0
  108. package/src/agents/development/database.ts +83 -0
  109. package/src/agents/development/debugger.ts +238 -0
  110. package/src/agents/development/devops.ts +86 -0
  111. package/src/agents/development/frontend.ts +85 -0
  112. package/src/agents/development/migration.ts +144 -0
  113. package/src/agents/development/performance.ts +144 -0
  114. package/src/agents/development/refactor.ts +86 -0
  115. package/src/agents/development/reviewer.ts +268 -0
  116. package/src/agents/development/tester.ts +151 -0
  117. package/src/agents/executor.ts +158 -0
  118. package/src/agents/memory/context-manager.ts +171 -0
  119. package/src/agents/memory/decision-logger.ts +160 -0
  120. package/src/agents/memory/knowledge-base.ts +124 -0
  121. package/src/agents/memory/pattern-learner.ts +143 -0
  122. package/src/agents/memory/project-mapper.ts +118 -0
  123. package/src/agents/quality/accessibility.ts +99 -0
  124. package/src/agents/quality/code-quality.ts +115 -0
  125. package/src/agents/quality/compatibility.ts +58 -0
  126. package/src/agents/quality/documentation.ts +105 -0
  127. package/src/agents/quality/error-handling.ts +96 -0
  128. package/src/agents/research/competitor-analyzer.ts +45 -0
  129. package/src/agents/research/cost-analyzer.ts +54 -0
  130. package/src/agents/research/estimator.ts +60 -0
  131. package/src/agents/research/ethics-bias.ts +113 -0
  132. package/src/agents/research/researcher.ts +114 -0
  133. package/src/agents/research/risk-assessor.ts +63 -0
  134. package/src/agents/research/tech-advisor.ts +55 -0
  135. package/src/agents/security/auth.ts +287 -0
  136. package/src/agents/security/dependency-audit.ts +337 -0
  137. package/src/agents/security/penetration.ts +262 -0
  138. package/src/agents/security/privacy.ts +285 -0
  139. package/src/agents/security/scanner.ts +322 -0
  140. package/src/agents/security/secrets.ts +249 -0
  141. package/src/agents/types.ts +66 -0
  142. package/src/agents/workflow/automation.ts +59 -0
  143. package/src/agents/workflow/file-manager.ts +52 -0
  144. package/src/agents/workflow/git-agent.ts +55 -0
  145. package/src/agents/workflow/reporter.ts +51 -0
  146. package/src/agents/workflow/search-agent.ts +40 -0
  147. package/src/agents/workflow/task-coordinator.ts +41 -0
  148. package/src/agents/workflow/task-planner.ts +47 -0
  149. package/src/cli.ts +143 -0
  150. package/src/council/decision-engine.ts +171 -0
  151. package/src/council/devil-advocate.ts +116 -0
  152. package/src/council/index.ts +44 -0
  153. package/src/council/lead-developer.ts +118 -0
  154. package/src/council/legal-compliance.ts +152 -0
  155. package/src/council/product-manager.ts +102 -0
  156. package/src/council/security.ts +172 -0
  157. package/src/council/system-architect.ts +132 -0
  158. package/src/council/types.ts +33 -0
  159. package/src/council/ux-designer.ts +121 -0
  160. package/src/memory/local.ts +305 -0
  161. package/src/memory/schema.ts +174 -0
  162. package/src/memory/sync.ts +274 -0
  163. package/src/router/complexity-scorer.ts +96 -0
  164. package/src/router/context-compressor.ts +74 -0
  165. package/src/router/index.ts +60 -0
  166. package/src/router/learning-updater.ts +271 -0
  167. package/src/router/model-selector.ts +83 -0
  168. package/src/router/rate-monitor.ts +103 -0
  169. package/src/server.ts +1038 -0
  170. package/src/skills/development/skill-api-design.ts +329 -0
  171. package/src/skills/development/skill-auth.ts +271 -0
  172. package/src/skills/development/skill-ci-cd.ts +0 -0
  173. package/src/skills/development/skill-crud.ts +209 -0
  174. package/src/skills/development/skill-db-schema.ts +0 -0
  175. package/src/skills/development/skill-docker.ts +0 -0
  176. package/src/skills/development/skill-env-setup.ts +0 -0
  177. package/src/skills/development/skill-scaffold.ts +323 -0
  178. package/src/skills/intelligence/skill-complexity-score.ts +69 -0
  179. package/src/skills/intelligence/skill-cost-track.ts +39 -0
  180. package/src/skills/intelligence/skill-learning-loop.ts +69 -0
  181. package/src/skills/intelligence/skill-pattern-detect.ts +38 -0
  182. package/src/skills/intelligence/skill-rate-watch.ts +61 -0
  183. package/src/skills/memory/skill-context-compress.ts +98 -0
  184. package/src/skills/memory/skill-cross-sync.ts +104 -0
  185. package/src/skills/memory/skill-decision-log.ts +119 -0
  186. package/src/skills/memory/skill-session-restore.ts +59 -0
  187. package/src/skills/memory/skill-session-save.ts +94 -0
  188. package/src/skills/quality/skill-accessibility.ts +0 -0
  189. package/src/skills/quality/skill-code-review.ts +84 -0
  190. package/src/skills/quality/skill-docs-gen.ts +0 -0
  191. package/src/skills/quality/skill-perf-audit.ts +0 -0
  192. package/src/skills/quality/skill-security-scan.ts +91 -0
  193. package/src/skills/quality/skill-test-suite.ts +290 -0
  194. package/src/skills/workflow/skill-deploy.ts +0 -0
  195. package/src/skills/workflow/skill-git-workflow.ts +0 -0
  196. package/src/skills/workflow/skill-rollback.ts +0 -0
  197. package/src/skills/workflow/skill-task-breakdown.ts +0 -0
  198. package/tsconfig.json +20 -0
@@ -0,0 +1,52 @@
1
+ export function plan(task, context) {
2
+ const t = (task + ' ' + (context ?? '')).toLowerCase();
3
+ const isMerge = t.includes('merge') || t.includes('conflict') || t.includes('rebase');
4
+ const isPR = t.includes('pull request') || t.includes('pr') || t.includes('review');
5
+ const isCommit = t.includes('commit') || t.includes('stage') || t.includes('message');
6
+ const approach = isMerge
7
+ ? 'Resolve merge conflicts by understanding what both sides intended, not just what they changed. Read both versions, understand the goal of each change, then write a resolution that preserves both intentions. Never resolve a conflict by picking one side blindly.'
8
+ : isPR
9
+ ? 'Structure the PR to make review fast: one clear title (what changed), a summary paragraph (why), a numbered list of changes (what files/functions), and a test plan. Small PRs merge faster than large ones — if the PR touches more than 10 files, split it.'
10
+ : isCommit
11
+ ? 'Write commit messages that explain WHY, not what. The diff shows what changed. The commit message tells future maintainers why. Format: imperative verb subject (50 chars), blank line, body if needed (72 chars per line).'
12
+ : 'Execute the git operation safely. For destructive operations (reset --hard, force push, branch delete): state the exact command and its consequences before running. Never force-push a shared branch without explicit instruction.';
13
+ return {
14
+ agent: 'git-agent',
15
+ task,
16
+ tier: 1,
17
+ approach,
18
+ steps: [
19
+ 'Identify the git operation needed: commit, branch, merge, rebase, tag, PR',
20
+ 'For destructive operations: state what will be lost and confirm before running',
21
+ 'For commits: stage only the relevant files — never git add -A blindly',
22
+ 'Write a commit message: imperative verb, 50 char subject, body if needed',
23
+ 'For merges: read both sides of each conflict before resolving',
24
+ 'For PRs: title (what), summary (why), change list (how), test plan',
25
+ 'For branch cleanup: verify the branch is fully merged before deleting',
26
+ 'For rebases: ensure the branch is not shared with others before rewriting history',
27
+ ],
28
+ checklist: [
29
+ '[ ] No accidental files staged (check git diff --staged before committing)',
30
+ '[ ] Commit message is imperative and explains WHY',
31
+ '[ ] No force-push to shared branches without explicit instruction',
32
+ '[ ] Merge conflicts resolved by understanding intent, not picking one side',
33
+ '[ ] Branch verified as merged before deletion',
34
+ '[ ] .env, credentials, and secrets not included in staged files',
35
+ ],
36
+ pitfalls: [
37
+ 'git add -A without reviewing what is staged — accidentally commits secrets or build artifacts',
38
+ 'Commit messages that describe what the diff shows — useless to future maintainers',
39
+ 'Force-pushing a branch others have cloned — rewrites their history',
40
+ 'Resolving merge conflicts by always taking "ours" — loses the other branch\'s intent',
41
+ 'Deleting a branch before verifying it is merged — loses work',
42
+ ],
43
+ patterns: [
44
+ 'Why-first commit messages: the diff shows what; the message explains why',
45
+ 'Surgical staging: add specific files, not directories, to keep commits atomic',
46
+ 'Pre-commit diff review: git diff --staged before every commit to catch surprises',
47
+ 'Branch lifecycle: feature → PR → merge → delete (never skip the verify-merged step)',
48
+ ],
49
+ duration_estimate: '15-45 minutes',
50
+ };
51
+ }
52
+ //# sourceMappingURL=git-agent.js.map
@@ -0,0 +1,48 @@
1
+ export function plan(task, context) {
2
+ const t = (task + ' ' + (context ?? '')).toLowerCase();
3
+ const isSession = t.includes('session') || t.includes('summary') || t.includes('what was done');
4
+ const isStatus = t.includes('status') || t.includes('progress') || t.includes('where are we');
5
+ const approach = isSession
6
+ ? 'Produce a session summary: what was accomplished, what decisions were made, what is next. Structure: one-sentence headline, bullet list of completed work, bullet list of open items, single next action. Optimised for someone picking up this work cold — they should need to read nothing else.'
7
+ : isStatus
8
+ ? 'Produce a status report: current phase, percent complete, what is blocking progress, and the next milestone. Include a risk flag if any blocker has been open for more than one session.'
9
+ : 'Produce the appropriate report for this context. Default to the session summary format: headline, completed, open, next action.';
10
+ return {
11
+ agent: 'reporter',
12
+ task,
13
+ tier: 1,
14
+ approach,
15
+ steps: [
16
+ 'Identify what type of report is needed: session summary, status report, or decision log',
17
+ 'Collect the facts: what was completed, what decisions were made, what is open',
18
+ 'Write the headline: one sentence that captures the most important thing',
19
+ 'List completed work as bullet points — specific, verifiable ("Auth middleware passing all tests")',
20
+ 'List open items with priority order',
21
+ 'Identify blockers: anything that prevents progress without human input',
22
+ 'State the single next action as a concrete step',
23
+ 'Save to session via veto_session_save if this report closes a work session',
24
+ ],
25
+ checklist: [
26
+ '[ ] Headline captures the most important single thing',
27
+ '[ ] Completed items are specific and verifiable',
28
+ '[ ] Open items are prioritised',
29
+ '[ ] Blockers are explicitly named',
30
+ '[ ] Next action is a single concrete step',
31
+ '[ ] Report saved if it closes a session',
32
+ ],
33
+ pitfalls: [
34
+ 'Vague completed items ("worked on auth") — not verifiable, not useful',
35
+ 'Listing everything instead of prioritising — buries the important items',
36
+ 'No next action — the person reading the report cannot resume without re-reading everything',
37
+ 'Including implementation details the reader does not need — reports should be scannable in 30 seconds',
38
+ ],
39
+ patterns: [
40
+ 'Headline-first: the most important thing should be visible without scrolling',
41
+ 'Scannable structure: headline → done → open → blockers → next — in that order',
42
+ 'One next action: multiple next actions means no prioritisation has happened',
43
+ 'Cold-start test: can someone who has not seen this work pick up where you left off from this report alone?',
44
+ ],
45
+ duration_estimate: '10-20 minutes',
46
+ };
47
+ }
48
+ //# sourceMappingURL=reporter.js.map
@@ -0,0 +1,39 @@
1
+ export function plan(task, context) {
2
+ return {
3
+ agent: 'search-agent',
4
+ task,
5
+ tier: 1,
6
+ approach: 'Search the codebase efficiently by starting with the most specific query and widening only if needed. Check veto_project_map_get first — if the answer is in the project map, no filesystem scan is needed. For symbol search: grep for the exact name. For concept search: grep for 2-3 keywords likely to co-occur. For file discovery: use glob patterns. Never read entire files when a targeted search suffices.',
7
+ steps: [
8
+ 'Call veto_project_map_get — check if the answer is already in the project map',
9
+ 'If the query is a symbol (function name, class, variable): grep for the exact name',
10
+ 'If the query is a concept: identify 2–3 keywords likely to co-occur in the relevant code',
11
+ 'Grep for keywords with file type filter (e.g. *.ts) to reduce noise',
12
+ 'Read only the matching sections, not entire files',
13
+ 'If nothing found: try synonyms or broader terms',
14
+ 'If still nothing: scan the directory structure for a likely home',
15
+ 'Update veto_project_map_update if the search revealed a gap in the map',
16
+ ],
17
+ checklist: [
18
+ '[ ] Project map checked before any filesystem scan',
19
+ '[ ] Exact symbol name tried before broad keyword search',
20
+ '[ ] File type filter applied to grep to reduce noise',
21
+ '[ ] Only matching sections read, not whole files',
22
+ '[ ] Project map updated if a previously unknown file was found',
23
+ ],
24
+ pitfalls: [
25
+ 'Reading entire files to find one function — wastes context tokens',
26
+ 'Searching without a file type filter — finds matches in node_modules and dist',
27
+ 'Using a broad term as the first query — too many false positives',
28
+ 'Not checking the project map first — may already have the answer',
29
+ ],
30
+ patterns: [
31
+ 'Specific-first search: exact symbol → keywords → directory scan',
32
+ 'Context-budgeted reading: read the matching section plus 10 lines of context, not the whole file',
33
+ 'Map-first navigation: the project map is faster than a filesystem scan for known files',
34
+ 'Synonym expansion: if the first query returns nothing, try 2-3 synonyms before giving up',
35
+ ],
36
+ duration_estimate: '5-20 minutes',
37
+ };
38
+ }
39
+ //# sourceMappingURL=search-agent.js.map
@@ -0,0 +1,40 @@
1
+ export function plan(task, context) {
2
+ return {
3
+ agent: 'task-coordinator',
4
+ task,
5
+ tier: 2,
6
+ approach: 'Coordinate multi-agent execution: assign tasks to the right worker agents, run independent tasks in parallel via veto_execute_parallel, collect results, reconcile conflicts, and assemble the final output. The coordinator does not do the work — it routes, monitors, and assembles.',
7
+ steps: [
8
+ 'Receive the task plan from task-planner (or build one if not provided)',
9
+ 'For each task: identify the best worker agent (coder, tester, security-scanner, etc.)',
10
+ 'Group independent tasks that can run in parallel',
11
+ 'Submit parallel group via veto_execute_parallel',
12
+ 'Wait for results — check each result for errors before proceeding',
13
+ 'If a parallel task fails: decide whether to retry, skip, or block the dependent tasks',
14
+ 'Submit the next sequential task or parallel group based on dependency order',
15
+ 'Collect all results and check for conflicts (two agents modify the same file)',
16
+ 'Resolve conflicts: the higher-priority agent wins, or escalate to the human',
17
+ 'Assemble the final output and save the session checkpoint',
18
+ ],
19
+ checklist: [
20
+ '[ ] Each task assigned to the correct worker agent',
21
+ '[ ] Independent tasks submitted to veto_execute_parallel',
22
+ '[ ] Each result checked for errors before triggering dependents',
23
+ '[ ] Conflicts identified and resolved',
24
+ '[ ] Final session saved via veto_session_save',
25
+ ],
26
+ pitfalls: [
27
+ 'Running all tasks sequentially when most could be parallel — wastes time',
28
+ 'Ignoring errors in parallel results and proceeding to dependent tasks — cascading failures',
29
+ 'Assigning the wrong agent type — a coder reviewing security is worse than no review',
30
+ 'Not saving progress after each parallel batch — a failure loses all intermediate work',
31
+ ],
32
+ patterns: [
33
+ 'Batch-and-wait: submit all independent tasks in one veto_execute_parallel call, then process results before the next batch',
34
+ 'Fail-fast on blockers: if a critical task fails, stop and report rather than continuing with invalid state',
35
+ 'Agent specialisation: always use the most specific agent available for each task type',
36
+ ],
37
+ duration_estimate: '30-90 minutes',
38
+ };
39
+ }
40
+ //# sourceMappingURL=task-coordinator.js.map
@@ -0,0 +1,46 @@
1
+ export function plan(task, context) {
2
+ return {
3
+ agent: 'task-planner',
4
+ task,
5
+ tier: 2,
6
+ approach: 'Decompose the goal into a concrete, ordered task list where each task is independently completable in 1–4 hours. The output is not a project plan — it is the immediate next N tasks in execution order, each with a clear acceptance criterion. Identify which tasks can run in parallel and which are sequential dependencies.',
7
+ steps: [
8
+ 'State the goal in one sentence — if you cannot, the goal needs clarifying first',
9
+ 'Identify all constraints: blocked by X, requires Y to exist first, cannot touch Z',
10
+ 'List all deliverables: what files, APIs, tests, or docs must exist when done?',
11
+ 'Break deliverables into tasks of 1–4 hours each — nothing larger',
12
+ 'For each task: write one acceptance criterion ("done when X passes" or "done when Y returns Z")',
13
+ 'Identify dependencies: which tasks must complete before others can start?',
14
+ 'Group independent tasks — these can run in parallel via veto_execute_parallel',
15
+ 'Order the dependent tasks: what is the critical path?',
16
+ 'Identify the single highest-risk task and put it first — fail fast',
17
+ 'Save the task plan via veto_session_save so it survives context switches',
18
+ ],
19
+ checklist: [
20
+ '[ ] Goal stated in one sentence',
21
+ '[ ] All constraints identified',
22
+ '[ ] Tasks are 1–4 hours each',
23
+ '[ ] Every task has an acceptance criterion',
24
+ '[ ] Dependencies mapped — no implicit ordering',
25
+ '[ ] Parallel tasks identified',
26
+ '[ ] Critical path identified',
27
+ '[ ] Highest-risk task is first',
28
+ '[ ] Plan saved via veto_session_save',
29
+ ],
30
+ pitfalls: [
31
+ 'Tasks too large ("implement auth") — cannot track progress or parallelize',
32
+ 'Tasks too small ("add semicolon") — overhead exceeds value',
33
+ 'Missing acceptance criteria — "done" is subjective without them',
34
+ 'Not identifying blockers upfront — a hidden blocker discovered mid-task stops everything',
35
+ 'Putting the risky unknown task last — you should fail fast, not late',
36
+ ],
37
+ patterns: [
38
+ 'Risk-first ordering: the most uncertain task goes first so you discover problems early',
39
+ 'Acceptance-criteria-first: write the criterion before the task to clarify what done means',
40
+ 'Parallel identification: tasks with no shared outputs can always run concurrently',
41
+ 'Four-hour rule: if a task cannot be completed in 4 hours, it contains hidden complexity — split it',
42
+ ],
43
+ duration_estimate: '30-60 minutes',
44
+ };
45
+ }
46
+ //# sourceMappingURL=task-planner.js.map
package/dist/cli.js ADDED
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env node
2
+ // Veto CLI — entry point for `npx veto init`
3
+ // Suppress Node experimental warnings (node:sqlite) for clean UX
4
+ process.removeAllListeners('warning');
5
+ import { mkdirSync, existsSync } from 'node:fs';
6
+ import { join, dirname } from 'node:path';
7
+ import { homedir } from 'node:os';
8
+ import { fileURLToPath } from 'node:url';
9
+ const VERSION = '0.8.0';
10
+ const VETO_DIR = join(homedir(), '.veto');
11
+ // Simple inline colors (no chalk needed for the init wizard to avoid ESM issues)
12
+ const c = {
13
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
14
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
15
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
16
+ cyan: (s) => `\x1b[36m${s}\x1b[0m`,
17
+ dim: (s) => `\x1b[2m${s}\x1b[0m`,
18
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
19
+ };
20
+ function printBanner() {
21
+ console.log('');
22
+ console.log(c.bold(c.cyan(' ██╗ ██╗███████╗████████╗ ██████╗')));
23
+ console.log(c.bold(c.cyan(' ██║ ██║██╔════╝╚══██╔══╝██╔═══██╗')));
24
+ console.log(c.bold(c.cyan(' ██║ ██║█████╗ ██║ ██║ ██║')));
25
+ console.log(c.bold(c.cyan(' ╚██╗ ██╔╝██╔══╝ ██║ ██║ ██║')));
26
+ console.log(c.bold(c.cyan(' ╚████╔╝ ███████╗ ██║ ╚██████╔╝')));
27
+ console.log(c.bold(c.cyan(' ╚═══╝ ╚══════╝ ╚═╝ ╚═════╝')));
28
+ console.log('');
29
+ console.log(c.dim(` 50 agents. 28 skills. 3 AIs. Self-learning. Zero extra cost.`));
30
+ console.log(c.dim(` v${VERSION}`));
31
+ console.log('');
32
+ }
33
+ async function initCommand() {
34
+ printBanner();
35
+ // 1. Create ~/.veto directory
36
+ if (!existsSync(VETO_DIR)) {
37
+ mkdirSync(VETO_DIR, { recursive: true });
38
+ console.log(c.green(' ✓') + ` Created ${VETO_DIR}`);
39
+ }
40
+ else {
41
+ console.log(c.dim(' · ') + `Found existing ${VETO_DIR}`);
42
+ }
43
+ // 2. Initialize SQLite database (imports local.ts which auto-creates tables)
44
+ process.stdout.write(' · Initializing SQLite database...');
45
+ const { getDb, getDbPath, saveSession } = await import('./memory/local.js');
46
+ try {
47
+ const db = getDb();
48
+ const dbPath = getDbPath();
49
+ // Smoke test: save + retrieve a test session
50
+ const { session_id } = saveSession({
51
+ platform: 'claude',
52
+ summary: 'Veto initialized',
53
+ context: 'Initial setup via npx veto init',
54
+ });
55
+ const row = db.prepare('SELECT id FROM sessions WHERE id = ?').get(session_id);
56
+ if (!row)
57
+ throw new Error('DB smoke test failed');
58
+ // Clean up test row
59
+ db.prepare('DELETE FROM sessions WHERE id = ?').run(session_id);
60
+ console.log(c.green(' ✓'));
61
+ console.log(c.green(' ✓') + ` Database ready at ${dbPath}`);
62
+ }
63
+ catch (err) {
64
+ console.log(c.red(' ✗'));
65
+ const msg = err instanceof Error ? err.message : String(err);
66
+ console.error(c.red(` Error initializing database: ${msg}`));
67
+ process.exit(1);
68
+ }
69
+ // 3. Print Claude Code config snippet
70
+ // Point to server.js (the MCP server), not cli.js (the init wizard)
71
+ const cliFile = fileURLToPath(import.meta.url);
72
+ const distDir = dirname(cliFile);
73
+ const serverPath = join(distDir, 'server.js').replace(/\\/g, '/');
74
+ console.log('');
75
+ console.log(c.bold(' ┌─ Add Veto to your AI CLI or IDE ───────────────────────────────┐'));
76
+ console.log(c.bold(' │') + ' ' + c.bold('│'));
77
+ console.log(c.bold(' │') + ' Config file locations: ' + c.bold('│'));
78
+ console.log(c.bold(' │') + ' ' + c.bold('│'));
79
+ console.log(c.bold(' │') + c.dim(' Claude Code → ~/.claude/mcp_servers.json') + ' ' + c.bold('│'));
80
+ console.log(c.bold(' │') + c.dim(' Gemini CLI → ~/.gemini/settings.json') + ' ' + c.bold('│'));
81
+ console.log(c.bold(' │') + c.dim(' Codex CLI → ~/.codex/config.json') + ' ' + c.bold('│'));
82
+ console.log(c.bold(' │') + c.dim(' Cursor → ~/.cursor/mcp.json') + ' ' + c.bold('│'));
83
+ console.log(c.bold(' │') + c.dim(' Windsurf → ~/.codeium/windsurf/mcp_config.json') + ' ' + c.bold('│'));
84
+ console.log(c.bold(' │') + ' ' + c.bold('│'));
85
+ console.log(c.bold(' │') + ' Claude / Gemini / Codex / Cursor / Windsurf: ' + c.bold('│'));
86
+ console.log(c.bold(' │') + ' ' + c.bold('│'));
87
+ console.log(c.bold(' │') + c.cyan(' {') + ' ' + c.bold('│'));
88
+ console.log(c.bold(' │') + c.cyan(' "mcpServers": {') + ' ' + c.bold('│'));
89
+ console.log(c.bold(' │') + c.cyan(' "veto": {') + ' ' + c.bold('│'));
90
+ console.log(c.bold(' │') + c.cyan(' "command": "node",') + ' ' + c.bold('│'));
91
+ console.log(c.bold(' │') + c.cyan(` "args": ["${serverPath}"]`) + ' ' + c.bold('│'));
92
+ console.log(c.bold(' │') + c.cyan(' }') + ' ' + c.bold('│'));
93
+ console.log(c.bold(' │') + c.cyan(' }') + ' ' + c.bold('│'));
94
+ console.log(c.bold(' │') + c.cyan(' }') + ' ' + c.bold('│'));
95
+ console.log(c.bold(' │') + ' ' + c.bold('│'));
96
+ console.log(c.bold(' │') + ' VS Code → .vscode/mcp.json: ' + c.bold('│'));
97
+ console.log(c.bold(' │') + ' ' + c.bold('│'));
98
+ console.log(c.bold(' │') + c.cyan(' {') + ' ' + c.bold('│'));
99
+ console.log(c.bold(' │') + c.cyan(' "servers": {') + ' ' + c.bold('│'));
100
+ console.log(c.bold(' │') + c.cyan(' "veto": {') + ' ' + c.bold('│'));
101
+ console.log(c.bold(' │') + c.cyan(' "type": "stdio",') + ' ' + c.bold('│'));
102
+ console.log(c.bold(' │') + c.cyan(' "command": "node",') + ' ' + c.bold('│'));
103
+ console.log(c.bold(' │') + c.cyan(` "args": ["${serverPath}"]`) + ' ' + c.bold('│'));
104
+ console.log(c.bold(' │') + c.cyan(' }') + ' ' + c.bold('│'));
105
+ console.log(c.bold(' │') + c.cyan(' }') + ' ' + c.bold('│'));
106
+ console.log(c.bold(' │') + c.cyan(' }') + ' ' + c.bold('│'));
107
+ console.log(c.bold(' │') + ' ' + c.bold('│'));
108
+ console.log(c.bold(' └────────────────────────────────────────────────────────────────┘'));
109
+ console.log('');
110
+ console.log(c.green(' ✓ Veto is ready!'));
111
+ console.log('');
112
+ console.log(' Next steps:');
113
+ console.log(c.dim(' 1.') + ' Add the config above to your AI CLI or IDE config file');
114
+ console.log(c.dim(' 2.') + ' Restart the CLI or IDE');
115
+ console.log(c.dim(' 3.') + ' Run: veto_status — should return { "status": "running", "version": "0.8.0" }');
116
+ console.log('');
117
+ }
118
+ // ─── Router ────────────────────────────────────────────────────────────────────
119
+ const command = process.argv[2] ?? 'init';
120
+ switch (command) {
121
+ case 'init':
122
+ initCommand().catch((err) => {
123
+ console.error(c.red(`Error: ${err.message}`));
124
+ process.exit(1);
125
+ });
126
+ break;
127
+ default:
128
+ console.error(`Unknown command: ${command}`);
129
+ console.log('Usage: veto init');
130
+ process.exit(1);
131
+ }
132
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1,136 @@
1
+ export function decide(votes) {
2
+ const entries = [
3
+ ['Lead Developer', votes.lead_dev],
4
+ ['Product Manager', votes.pm],
5
+ ['System Architect', votes.architect],
6
+ ['UX Designer', votes.ux],
7
+ ["Devil's Advocate", votes.devil],
8
+ ['Legal & Compliance', votes.legal],
9
+ ['Security', votes.security],
10
+ ];
11
+ // Expert agents — their block is always RED regardless of other votes
12
+ const CRITICAL = new Set(['Lead Developer', 'System Architect', 'Legal & Compliance', 'Security']);
13
+ const blockers = entries.filter(([, v]) => v.verdict === 'block');
14
+ const warners = entries.filter(([, v]) => v.verdict === 'warn');
15
+ const approvers = entries.filter(([, v]) => v.verdict === 'approve');
16
+ const criticalBlockers = blockers.filter(([name]) => CRITICAL.has(name));
17
+ const secondaryBlockers = blockers.filter(([name]) => !CRITICAL.has(name));
18
+ const criticalApprovers = approvers.filter(([name]) => CRITICAL.has(name));
19
+ const block_reasons = blockers.map(([, v]) => v.reason);
20
+ const warnings = [
21
+ ...blockers.flatMap(([, v]) => v.concerns),
22
+ ...warners.map(([, v]) => v.reason),
23
+ ...warners.flatMap(([, v]) => v.concerns),
24
+ ].filter((w) => typeof w === 'string' && w.length > 0);
25
+ let final_verdict;
26
+ if (criticalBlockers.length >= 1) {
27
+ // Any expert domain agent blocks → RED, no debate
28
+ final_verdict = 'RED';
29
+ }
30
+ else if (secondaryBlockers.length >= 2 && criticalApprovers.length >= 2) {
31
+ // Business/UX objections vs technical approval — genuine split
32
+ final_verdict = 'DEADLOCK';
33
+ }
34
+ else if (secondaryBlockers.length >= 1 || warners.length >= 1) {
35
+ // At least one concern but no hard expert block
36
+ final_verdict = 'YELLOW';
37
+ }
38
+ else {
39
+ final_verdict = 'GREEN';
40
+ }
41
+ const recommendations = [
42
+ ...blockers.map(([, v]) => v.recommendation).filter(Boolean),
43
+ ...warners.map(([, v]) => v.recommendation).filter(Boolean),
44
+ ];
45
+ const recommended = recommendations.length > 0
46
+ ? recommendations[0]
47
+ : 'Proceed with standard implementation best practices.';
48
+ return { final_verdict, block_reasons, warnings, recommended };
49
+ }
50
+ export function formatDebate(task, votes, verdict, block_reasons, warnings, recommended) {
51
+ const AGENT_ICONS = {
52
+ lead_dev: '🔵',
53
+ pm: '🟢',
54
+ architect: '🏛️ ',
55
+ ux: '🎨',
56
+ devil: '😈',
57
+ legal: '⚖️ ',
58
+ security: '🔒',
59
+ };
60
+ const AGENT_LABELS = {
61
+ lead_dev: 'Lead Dev: ',
62
+ pm: 'PM: ',
63
+ architect: 'Architect: ',
64
+ ux: 'UX: ',
65
+ devil: 'Devil: ',
66
+ legal: 'Legal: ',
67
+ security: 'Security: ',
68
+ };
69
+ const VERDICT_BADGE = {
70
+ block: '[BLOCKING]',
71
+ warn: '[WARN]',
72
+ approve: '[APPROVE]',
73
+ };
74
+ const VERDICT_LINE = {
75
+ GREEN: '✅ VERDICT: GREEN — All clear. Proceed.',
76
+ YELLOW: '⚠️ VERDICT: YELLOW — Proceed with caution.',
77
+ RED: '🚫 VERDICT: RED — BLOCKED.',
78
+ DEADLOCK: '⚖️ VERDICT: DEADLOCK — Council is split. You decide.',
79
+ };
80
+ const divider = '─'.repeat(54);
81
+ const lines = [
82
+ '',
83
+ '⚠️ VETO COUNCIL INITIATED',
84
+ divider,
85
+ '',
86
+ ];
87
+ const keys = ['lead_dev', 'pm', 'architect', 'ux', 'devil', 'legal', 'security'];
88
+ for (const key of keys) {
89
+ const vote = votes[key];
90
+ const icon = AGENT_ICONS[key];
91
+ const label = AGENT_LABELS[key];
92
+ const badge = VERDICT_BADGE[vote.verdict];
93
+ const prefix = `${icon} ${label}`;
94
+ const indent = ' ';
95
+ const shortReason = vote.reason.length > 46 ? vote.reason.slice(0, 43) + '...' : vote.reason;
96
+ lines.push(`${prefix}${shortReason} ${badge}`);
97
+ for (const concern of vote.concerns.slice(0, 2)) {
98
+ const short = concern.length > 46 ? concern.slice(0, 43) + '...' : concern;
99
+ lines.push(`${indent}↳ ${short}`);
100
+ }
101
+ }
102
+ lines.push('');
103
+ lines.push(divider);
104
+ lines.push(VERDICT_LINE[verdict]);
105
+ lines.push('');
106
+ if (block_reasons.length > 0) {
107
+ lines.push('🚫 Blocked because:');
108
+ for (const r of block_reasons) {
109
+ lines.push(` • ${r}`);
110
+ }
111
+ lines.push('');
112
+ }
113
+ if (warnings.length > 0) {
114
+ const shown = warnings.slice(0, 4);
115
+ const extra = warnings.length - shown.length;
116
+ lines.push(`⚠️ Warning${warnings.length > 1 ? 's' : ''}:`);
117
+ for (const w of shown) {
118
+ lines.push(` • ${w}`);
119
+ }
120
+ if (extra > 0)
121
+ lines.push(` • ...and ${extra} more`);
122
+ lines.push('');
123
+ }
124
+ lines.push(`✅ Recommended: ${recommended}`);
125
+ if (verdict === 'RED') {
126
+ lines.push('');
127
+ lines.push('Override with: proceed anyway [not recommended]');
128
+ }
129
+ else if (verdict === 'DEADLOCK') {
130
+ lines.push('');
131
+ lines.push('Council is split. Your call: [proceed / abort]');
132
+ }
133
+ lines.push('');
134
+ return lines.join('\n');
135
+ }
136
+ //# sourceMappingURL=decision-engine.js.map
@@ -0,0 +1,106 @@
1
+ // Devil always warns — never alone blocks, never approves non-trivial tasks
2
+ const PROBES = [
3
+ {
4
+ pattern: /auth|login|password|session|jwt|oauth/i,
5
+ concern: "What happens when auth fails at 2AM? Lockout policy? Account recovery flow?",
6
+ recommendation: 'Rate-limit auth endpoints. Lock after N failures. Build recovery email flow.',
7
+ },
8
+ {
9
+ pattern: /payment|charge|billing|stripe|invoice|subscription/i,
10
+ concern: "Idempotency keys? Double-charge prevention? What happens when payment webhook retries?",
11
+ recommendation: 'Idempotency keys on all payment mutations. Handle webhook duplicates explicitly.',
12
+ },
13
+ {
14
+ pattern: /deploy|release|rollout|push.{0,15}(prod|main|master)/i,
15
+ concern: "Rollback procedure if this deploy breaks production? How fast can you revert?",
16
+ recommendation: 'Document rollback runbook before deploying. Consider feature flag as kill switch.',
17
+ },
18
+ {
19
+ pattern: /migrat|schema.?change|alter.?table|add.{0,10}column/i,
20
+ concern: "Tested down-migration exists? What if this runs mid-traffic on prod?",
21
+ recommendation: 'Test down-migration on a copy. Use zero-downtime migration patterns (expand/contract).',
22
+ },
23
+ {
24
+ pattern: /\bcache\b|\bredis\b/i,
25
+ concern: "Cache stampede on cold start? Cache poisoning from bad writes? Invalidation race?",
26
+ recommendation: 'Probabilistic early expiry prevents stampede. Lock on cache miss for hot keys.',
27
+ },
28
+ {
29
+ pattern: /email|notification|sms|push.?notif/i,
30
+ concern: "Delivery failure handled? Retry queue? Duplicate notification prevention?",
31
+ recommendation: 'Add retry queue with exponential backoff. Idempotency key per notification.',
32
+ },
33
+ {
34
+ pattern: /webhook|callback.?url/i,
35
+ concern: "Webhook replay attacks? Signature verification? What if your handler is slow?",
36
+ recommendation: 'Verify webhook signatures. Respond 200 immediately, process async.',
37
+ },
38
+ {
39
+ pattern: /\bapi\b|endpoint|http.?client|fetch|axios/i,
40
+ concern: "External API goes down? Timeout set? Circuit breaker? Fallback behavior?",
41
+ recommendation: 'Set explicit timeout (3-5s). Circuit breaker for critical external deps.',
42
+ },
43
+ {
44
+ pattern: /file|upload|s3|blob|storage|bucket/i,
45
+ concern: "Partial upload failure? Storage quota? File type validation before processing?",
46
+ recommendation: 'Handle partial failures. Alert at 80% storage. Validate file type + scan for malware.',
47
+ },
48
+ {
49
+ pattern: /cron|schedule|job|queue|worker/i,
50
+ concern: "Job fails silently? Duplicate concurrent runs? Stuck job detection?",
51
+ recommendation: 'Log all job outcomes. Prevent concurrent runs with distributed lock. Set max duration.',
52
+ },
53
+ {
54
+ pattern: /third.?party|external.{0,15}service|vendor|sdk/i,
55
+ concern: "Vendor going down? SDK breaking changes? Data you do not control changing format?",
56
+ recommendation: 'Wrap in adapter layer. Monitor third-party SLA separately. Pin SDK version.',
57
+ },
58
+ {
59
+ pattern: /delete|remove|drop|destroy|purge/i,
60
+ concern: "Is this reversible? Backup before? What if it runs against wrong environment?",
61
+ recommendation: 'Soft-delete first (add deleted_at). Hard-delete only after confirmed safe.',
62
+ },
63
+ {
64
+ pattern: /rate.?limit|throttle/i,
65
+ concern: "What happens when the rate limit is hit? User notified clearly? Retry-After header?",
66
+ recommendation: 'Return 429 with Retry-After. Show clear user message. Log for monitoring.',
67
+ },
68
+ {
69
+ pattern: /concurren|parallel|race.?condition|mutex|lock/i,
70
+ concern: "Race condition under concurrent requests? Lock contention under load?",
71
+ recommendation: 'Test with concurrent load. Use optimistic locking or distributed mutex.',
72
+ },
73
+ {
74
+ pattern: /secret|key|token|credential|api.?key/i,
75
+ concern: "Rotation strategy? What if this key leaks? Who has access and is it logged?",
76
+ recommendation: 'Rotate keys on schedule. Audit access logs. Use short-lived tokens where possible.',
77
+ },
78
+ ];
79
+ const GENERIC = {
80
+ concern: "What is the failure mode here? What breaks at 2AM on a Sunday with no one watching?",
81
+ recommendation: 'Add monitoring, alerting, and a runbook for when this breaks.',
82
+ };
83
+ const TRIVIAL = /^(rename|fix typo|reorder|reformat|format code|update comment|add comment)\b/i;
84
+ export function analyze(task) {
85
+ if (TRIVIAL.test(task.trim())) {
86
+ return { verdict: 'approve', reason: 'Trivial change — no failure modes to probe.', concerns: [] };
87
+ }
88
+ const matched = [];
89
+ for (const probe of PROBES) {
90
+ if (probe.pattern.test(task)) {
91
+ matched.push({ concern: probe.concern, recommendation: probe.recommendation });
92
+ }
93
+ }
94
+ // Devil always raises at least one concern for non-trivial tasks
95
+ if (matched.length === 0) {
96
+ matched.push(GENERIC);
97
+ }
98
+ const top = matched.slice(0, 3); // cap at 3 concerns to avoid flooding
99
+ return {
100
+ verdict: 'warn',
101
+ reason: top[0].concern,
102
+ concerns: top.slice(1).map(m => m.concern),
103
+ recommendation: top.map(m => m.recommendation).join(' | '),
104
+ };
105
+ }
106
+ //# sourceMappingURL=devil-advocate.js.map
@@ -0,0 +1,37 @@
1
+ // Council orchestrator — runs all 7 agents in parallel, returns debate result
2
+ import { analyze as leadDevAnalyze } from './lead-developer.js';
3
+ import { analyze as pmAnalyze } from './product-manager.js';
4
+ import { analyze as architectAnalyze } from './system-architect.js';
5
+ import { analyze as uxAnalyze } from './ux-designer.js';
6
+ import { analyze as devilAnalyze } from './devil-advocate.js';
7
+ import { analyze as legalAnalyze } from './legal-compliance.js';
8
+ import { analyze as securityAnalyze } from './security.js';
9
+ import { decide, formatDebate } from './decision-engine.js';
10
+ export async function runDebate(input) {
11
+ const fullText = input.context ? `${input.task}\n${input.context}` : input.task;
12
+ // All 7 agents run in parallel — none depend on each other
13
+ const [lead_dev, pm, architect, ux, devil, legal, security] = await Promise.all([
14
+ Promise.resolve(leadDevAnalyze(fullText)),
15
+ Promise.resolve(pmAnalyze(fullText)),
16
+ Promise.resolve(architectAnalyze(fullText)),
17
+ Promise.resolve(uxAnalyze(fullText)),
18
+ Promise.resolve(devilAnalyze(fullText)),
19
+ Promise.resolve(legalAnalyze(fullText)),
20
+ Promise.resolve(securityAnalyze(fullText)),
21
+ ]);
22
+ const votes = { lead_dev, pm, architect, ux, devil, legal, security };
23
+ const { final_verdict, block_reasons, warnings, recommended } = decide(votes);
24
+ const debated_at = new Date().toISOString();
25
+ const formatted_output = formatDebate(input.task, votes, final_verdict, block_reasons, warnings, recommended);
26
+ return {
27
+ task: input.task,
28
+ final_verdict,
29
+ votes,
30
+ recommended,
31
+ block_reasons,
32
+ warnings,
33
+ debated_at,
34
+ formatted_output,
35
+ };
36
+ }
37
+ //# sourceMappingURL=index.js.map