@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,96 @@
1
+ import { AgentPlan, AgentAnalysis, AgentFinding, WorkerAgentType } from '../types.js';
2
+
3
+ export function plan(task: string, context?: string): AgentPlan {
4
+ return {
5
+ agent: 'error-handling' as WorkerAgentType,
6
+ task,
7
+ tier: 2,
8
+ approach: 'Audit error handling for the three failure classes: expected failures (validation, not found, auth), unexpected failures (bugs, network failures, DB errors), and catastrophic failures (process crash, OOM). Each class needs a different treatment. Expected failures return structured error responses. Unexpected failures are logged with context and surfaced as generic errors to users. Catastrophic failures are captured by a top-level handler and alert.',
9
+ steps: [
10
+ 'Identify all async operations: DB calls, HTTP requests, file I/O, external APIs',
11
+ 'Verify every async call has a try/catch or .catch() — no floating promises',
12
+ 'Check that catch blocks do not silently swallow errors — log OR rethrow, never neither',
13
+ 'Verify error messages to users do not leak stack traces or internal details in production',
14
+ 'Check that typed errors are used — no throw new Error("raw string") for domain errors',
15
+ 'Verify HTTP error codes are semantically correct: 400 vs 422, 401 vs 403, 404 vs 410',
16
+ 'Check that errors include enough context to diagnose: which record, which operation, what input',
17
+ 'Verify the top-level process error handler is in place: uncaughtException, unhandledRejection',
18
+ 'Check that external API timeouts are configured — no indefinite hangs',
19
+ 'Test each error path: does the system recover gracefully or leave state corrupted?',
20
+ ],
21
+ checklist: [
22
+ '[ ] No floating promises — every async call awaited or .catch() chained',
23
+ '[ ] No empty or silent catch blocks',
24
+ '[ ] Stack traces never exposed to users in production',
25
+ '[ ] Typed domain errors — not raw Error strings',
26
+ '[ ] HTTP status codes semantically correct',
27
+ '[ ] Error log includes context (what failed, on what input)',
28
+ '[ ] process.on("uncaughtException") and ("unhandledRejection") registered',
29
+ '[ ] All external HTTP calls have a timeout configured',
30
+ '[ ] Error paths tested — system recovers without corrupting state',
31
+ ],
32
+ pitfalls: [
33
+ 'Catch-and-log without rethrowing — the caller assumes success when the operation failed',
34
+ 'Using the same error type for expected and unexpected failures — callers cannot distinguish',
35
+ 'Not including the original error in a re-thrown wrapper — stack trace lost',
36
+ 'Logging only the error message without the input that caused it — impossible to reproduce',
37
+ 'Catching Error but not checking error.name — all errors look the same',
38
+ ],
39
+ patterns: [
40
+ 'Error taxonomy: expected (return structured error) | unexpected (log + generic response) | catastrophic (alert)',
41
+ 'Context-rich errors: every thrown error includes the operation, input, and correlation ID',
42
+ 'Fail-fast on programming errors: throw immediately on invalid arguments — do not try to recover',
43
+ 'Structured error types: one class per error category with a code field for programmatic handling',
44
+ ],
45
+ duration_estimate: '2-4 hours',
46
+ };
47
+ }
48
+
49
+ export function analyze(code: string, context?: string): AgentAnalysis {
50
+ const findings: AgentFinding[] = [];
51
+
52
+ // Empty catch blocks
53
+ const emptyCatch = (code.match(/catch\s*\([^)]*\)\s*\{\s*\}/g) ?? []).length;
54
+ if (emptyCatch > 0) {
55
+ findings.push({ severity: 'critical', category: 'silent-failure', description: `${emptyCatch} empty catch block(s) — exceptions silently swallowed`, fix: 'Log the error and/or rethrow. Never swallow exceptions silently.' });
56
+ }
57
+
58
+ // Catch with only console.log (no rethrow)
59
+ const logOnlyCatch = (code.match(/catch\s*\([^)]*\)\s*\{[^}]*console\.[a-z]+[^}]*\}/g) ?? [])
60
+ .filter(block => !block.includes('throw')).length;
61
+ if (logOnlyCatch > 0) {
62
+ findings.push({ severity: 'high', category: 'swallowed-error', description: `${logOnlyCatch} catch block(s) log but do not rethrow — caller assumes success`, fix: 'After logging, either rethrow the error or return a typed error result to the caller.' });
63
+ }
64
+
65
+ // Floating promises
66
+ const floatingPromise = (code.match(/(?<!\bawait\s)(?<!\breturn\s)\b\w+\([^)]*\)\.then\(/g) ?? []).length;
67
+ if (floatingPromise > 1) {
68
+ findings.push({ severity: 'high', category: 'floating-promise', description: `Potential floating promise(s) detected`, fix: 'Ensure all Promise chains are awaited or have a .catch() handler.' });
69
+ }
70
+
71
+ // Raw Error strings
72
+ const rawThrows = (code.match(/throw new Error\(['"`][^'"`]{1,50}['"`]\)/g) ?? []).length;
73
+ if (rawThrows > 2) {
74
+ findings.push({ severity: 'medium', category: 'untyped-errors', description: `${rawThrows} raw Error string throws — callers cannot distinguish error types`, fix: 'Create typed error classes (class NotFoundError extends Error) for each distinct error category.' });
75
+ }
76
+
77
+ // No timeout on fetch/axios
78
+ if (/fetch\(|axios\.|got\(|request\(/.test(code) && !/timeout/.test(code)) {
79
+ findings.push({ severity: 'medium', category: 'missing-timeout', description: 'External HTTP call detected without apparent timeout configuration', fix: 'Add a timeout to all external HTTP calls. Unconfigured calls hang indefinitely on network issues.' });
80
+ }
81
+
82
+ const critCount = findings.filter(f => f.severity === 'critical').length;
83
+ const highCount = findings.filter(f => f.severity === 'high').length;
84
+ const score = Math.max(0, 100 - critCount * 30 - highCount * 20 - findings.filter(f => f.severity === 'medium').length * 10);
85
+
86
+ return {
87
+ agent: 'error-handling' as WorkerAgentType,
88
+ subject: context ?? 'code',
89
+ findings,
90
+ score,
91
+ verdict: score >= 85 ? 'approved' : score >= 65 ? 'approved_with_warnings' : score >= 40 ? 'needs_revision' : 'rejected',
92
+ summary: findings.length === 0 ? 'Error handling looks solid.' : `${findings.length} error handling issue(s). Top: ${findings[0].description}`,
93
+ critical_count: critCount,
94
+ high_count: highCount,
95
+ };
96
+ }
@@ -0,0 +1,45 @@
1
+ import { AgentPlan, WorkerAgentType } from '../types.js';
2
+
3
+ export function plan(task: string, context?: string): AgentPlan {
4
+ return {
5
+ agent: 'competitor-analyzer' as WorkerAgentType,
6
+ task,
7
+ tier: 2,
8
+ approach: 'Analyse competitors on three dimensions: feature gap (what they have that you don\'t), differentiation gap (what you have that they don\'t), and positioning gap (where they own user perception). The goal is not to copy — it is to identify where building a feature would be table-stakes vs. where it would be genuinely differentiating.',
9
+ steps: [
10
+ 'List the top 3–5 direct competitors and 2–3 indirect alternatives',
11
+ 'For each competitor: document their core value proposition in one sentence',
12
+ 'Build a feature matrix: rows = features, columns = products, cells = yes/no/partial',
13
+ 'Identify table-stakes features: present in all competitors (building these is hygiene, not differentiation)',
14
+ 'Identify differentiating features: present in 0–1 competitors (building these creates moat)',
15
+ 'Identify features your product has that no competitor has — this is your current moat',
16
+ 'Research competitor pricing to understand the value they signal for each tier',
17
+ 'Read user reviews of competitors to find the most common complaints (these are opportunities)',
18
+ 'Identify the positioning gaps: what perception do users have of each competitor?',
19
+ 'Recommend the top 3 features by differentiation potential × build cost',
20
+ 'Store analysis in veto_memory_store (type="reference", tags=["competitive", "strategy"])',
21
+ ],
22
+ checklist: [
23
+ '[ ] Top 5 direct competitors identified',
24
+ '[ ] Feature matrix built with table-stakes vs. differentiating features separated',
25
+ '[ ] Current moat (unique features) identified',
26
+ '[ ] User review analysis for top 2 complaints per competitor',
27
+ '[ ] Differentiation opportunities ranked by potential × cost',
28
+ '[ ] Analysis stored in veto_memory_store',
29
+ ],
30
+ pitfalls: [
31
+ 'Copying competitor features without understanding why they built them — builds technical debt, not differentiation',
32
+ 'Ignoring indirect alternatives — users often switch to a different category entirely, not a direct competitor',
33
+ 'Treating all feature gaps as problems — some are intentional product decisions',
34
+ 'Not reading user reviews — documentation says what a product does; reviews say what it fails to do',
35
+ 'Analysing features in isolation from pricing — a feature only matters if the target segment can afford it',
36
+ ],
37
+ patterns: [
38
+ 'Table-stakes separation: hygiene features vs. moat features require different prioritisation logic',
39
+ 'Complaint mining: competitor weaknesses in reviews are your clearest product opportunities',
40
+ 'Moat-first thinking: understand your current differentiation before adding more features',
41
+ 'Indirect competitor awareness: the biggest threat is often a product in a different category',
42
+ ],
43
+ duration_estimate: '2-4 hours',
44
+ };
45
+ }
@@ -0,0 +1,54 @@
1
+ import { AgentPlan, WorkerAgentType } from '../types.js';
2
+
3
+ export function plan(task: string, context?: string): AgentPlan {
4
+ const t = (task + ' ' + (context ?? '')).toLowerCase();
5
+ const isTokenCost = t.includes('token') || t.includes('ai cost') || t.includes('api cost') || t.includes('llm');
6
+ const isInfra = t.includes('hosting') || t.includes('server') || t.includes('cloud') || t.includes('infra');
7
+
8
+ const approach = isTokenCost
9
+ ? 'Analyse AI token costs across all three platforms. Track tokens-per-task, cost-per-tier, and cost trajectory over time. Identify the top 3 cost drivers and recommend routing adjustments. A 20% reduction in average tier without quality loss is typically achievable via better router threshold calibration.'
10
+ : isInfra
11
+ ? 'Analyse infrastructure costs by service. Identify idle resources, over-provisioned instances, and services that could be consolidated. Compare reserved vs. on-demand pricing for predictable workloads. Document the cost-per-feature to identify which features have disproportionate infrastructure cost.'
12
+ : 'Track the three cost categories in this project: AI token spend, infrastructure, and developer time. Developer time is almost always the largest cost and the most under-tracked. Quantify each category, identify the top driver, and recommend the highest-ROI reduction.';
13
+
14
+ return {
15
+ agent: 'cost-analyzer' as WorkerAgentType,
16
+ task,
17
+ tier: 1,
18
+ approach,
19
+ steps: [
20
+ 'Identify which cost category to analyse: AI tokens, infrastructure, or developer time',
21
+ 'For token costs: call veto_rate_status and veto_learning_stats to get tier distribution',
22
+ 'Calculate average cost per task by tier (Tier 1 ≈ $0.001, Tier 2 ≈ $0.01, Tier 3 ≈ $0.05)',
23
+ 'Identify tasks that are over-tiered: Tier 3 tasks with output quality achievable at Tier 2',
24
+ 'For infrastructure: list monthly costs per service and idle/utilisation %',
25
+ 'For developer time: estimate hours lost to context switches, re-explanation, and tool friction',
26
+ 'Rank cost drivers by monthly impact ($ or hours)',
27
+ 'Propose the top 3 changes with estimated savings and implementation cost',
28
+ 'Calculate ROI for each proposal: savings per month / implementation cost in days',
29
+ 'Store cost analysis in veto_memory_store (type="reference", tags=["cost", "performance"])',
30
+ ],
31
+ checklist: [
32
+ '[ ] Cost category identified and scoped',
33
+ '[ ] Current monthly cost baseline established',
34
+ '[ ] Top 3 cost drivers identified and ranked by impact',
35
+ '[ ] At least one reduction proposal with estimated ROI',
36
+ '[ ] Developer time cost estimated (not just infrastructure)',
37
+ '[ ] Cost reduction proposals ranked by ROI, not just absolute savings',
38
+ ],
39
+ pitfalls: [
40
+ 'Optimising infrastructure cost while ignoring developer time — wrong priority',
41
+ 'Treating all Tier 3 tasks as necessary — many can be downgraded with better descriptions',
42
+ 'Not establishing a baseline before optimising — you cannot measure improvement without it',
43
+ 'Optimising for the cheapest option instead of the best cost/quality ratio',
44
+ 'Ignoring the cost of the optimisation itself — a 5% savings that takes 2 weeks is not worth it',
45
+ ],
46
+ patterns: [
47
+ 'Baseline-first: measure before optimising',
48
+ 'ROI ranking: sort proposals by monthly savings / implementation cost, not just savings',
49
+ 'Developer time inclusion: add estimated developer friction hours to every cost analysis',
50
+ 'Tier distribution analysis: the ratio of T1/T2/T3 tasks directly predicts AI spend',
51
+ ],
52
+ duration_estimate: '1-2 hours',
53
+ };
54
+ }
@@ -0,0 +1,60 @@
1
+ import { AgentPlan, WorkerAgentType } from '../types.js';
2
+
3
+ export function plan(task: string, context?: string): AgentPlan {
4
+ const t = (task + ' ' + (context ?? '')).toLowerCase();
5
+ const isFeature = t.includes('feature') || t.includes('implement') || t.includes('build') || t.includes('add');
6
+ const isProject = t.includes('project') || t.includes('entire') || t.includes('full') || t.includes('phase');
7
+ const isRefactor = t.includes('refactor') || t.includes('migrat') || t.includes('rewrite') || t.includes('restructur');
8
+
9
+ const approach = isProject
10
+ ? 'Estimate the full project using bottom-up decomposition: break into phases, phases into milestones, milestones into tasks. Estimate each task independently, then add a calibration factor based on team history. Never estimate a project in one number — give P50 (likely), P80 (likely with normal friction), and P95 (likely with major unexpected issue).'
11
+ : isRefactor
12
+ ? 'Refactors and migrations consistently take 2–3x the original estimate because hidden coupling is discovered mid-work. Use a base estimate of "how long to implement from scratch" × 2, plus a separate estimate for integration testing and rollback preparation. Do not use the refactor estimate as a deadline — use it as a budget check.'
13
+ : isFeature
14
+ ? 'Estimate the feature in four parts: core implementation, edge cases and error handling, tests, and integration. Core implementation is what engineers quote; the other three are what makes estimates wrong. A realistic feature estimate is roughly: core × 2.5.'
15
+ : 'Break the work into tasks of 1–4 hours each. Anything larger than 4 hours contains hidden complexity that will surface mid-execution. Estimate each small task, sum them, add 30% for integration and unexpected issues.';
16
+
17
+ return {
18
+ agent: 'estimator' as WorkerAgentType,
19
+ task,
20
+ tier: 2,
21
+ approach,
22
+ steps: [
23
+ 'Decompose the work into tasks of 1–4 hours each — nothing larger',
24
+ 'Estimate each task independently (avoid anchoring on the total)',
25
+ 'For each estimate: document the main assumption that could make it wrong',
26
+ 'Identify which tasks have the highest uncertainty — these drive the range',
27
+ 'Sum the task estimates to get the P50 (50% chance of hitting)',
28
+ 'Add 30% to get P80 (accounting for normal integration friction)',
29
+ 'Add another 30% to P80 to get P95 (accounting for one major unexpected issue)',
30
+ 'Identify the critical path: which tasks block all other work?',
31
+ 'Identify tasks that can be parallelised if more people are added',
32
+ 'Check against historical estimates: what was the last similar task\'s actual vs. estimate ratio?',
33
+ 'Store the estimate in veto_memory_store (type="reference") with actual time tracked when complete',
34
+ ],
35
+ checklist: [
36
+ '[ ] Work decomposed into tasks ≤ 4 hours each',
37
+ '[ ] Each task estimated independently',
38
+ '[ ] Main assumption per task documented',
39
+ '[ ] P50, P80, P95 range calculated',
40
+ '[ ] Critical path identified',
41
+ '[ ] Historical ratio checked (if prior estimates exist)',
42
+ '[ ] Estimate stored for calibration tracking',
43
+ ],
44
+ pitfalls: [
45
+ 'Estimating top-down from a desired deadline — the estimate becomes a negotiation, not a forecast',
46
+ 'Not separating core implementation from edge cases, tests, and integration — this is where estimates consistently fail',
47
+ 'Giving a single number instead of a range — single-number estimates communicate false precision',
48
+ 'Not documenting the assumptions behind the estimate — when reality diverges, nobody knows why',
49
+ 'Forgetting that refactors and migrations have a 2–3x hidden complexity multiplier',
50
+ 'Not tracking actuals — without actuals, estimates never improve',
51
+ ],
52
+ patterns: [
53
+ 'Bottom-up decomposition: sum of small estimates beats one large estimate every time',
54
+ 'P50/P80/P95 range: communicates uncertainty honestly rather than false precision',
55
+ 'Assumption documentation: the assumption is the estimate — when it is wrong, the estimate is wrong',
56
+ 'Estimate-to-actual tracking: store both estimate and actual in veto_memory_store to calibrate future estimates',
57
+ ],
58
+ duration_estimate: '30-60 minutes',
59
+ };
60
+ }
@@ -0,0 +1,113 @@
1
+ import { AgentPlan, WorkerAgentType } from '../types.js';
2
+
3
+ type EthicsCategory = 'ai-ml' | 'dark-patterns' | 'fairness' | 'privacy' | 'general';
4
+
5
+ function detectCategory(task: string): EthicsCategory {
6
+ const t = task.toLowerCase();
7
+ if (t.includes('ai') || t.includes('ml') || t.includes('model') || t.includes('predict') || t.includes('recommend')) return 'ai-ml';
8
+ if (t.includes('dark pattern') || t.includes('ux') || t.includes('onboarding') || t.includes('notification') || t.includes('subscription')) return 'dark-patterns';
9
+ if (t.includes('fair') || t.includes('bias') || t.includes('demographic') || t.includes('discriminat') || t.includes('equit')) return 'fairness';
10
+ if (t.includes('privac') || t.includes('data') || t.includes('tracking') || t.includes('surveillance')) return 'privacy';
11
+ return 'general';
12
+ }
13
+
14
+ const categoryApproach: Record<EthicsCategory, string> = {
15
+ 'ai-ml': 'Audit the AI/ML system for bias in three places: training data (is it representative?), model outputs (does it perform differently across demographic groups?), and system design (does the framing of the problem embed assumptions that harm certain users?). Bias at the data level is fixable. Bias at the framing level may require rethinking the feature.',
16
+ 'dark-patterns': 'Review the UX flow for patterns that extract value from users through confusion or manipulation rather than genuine usefulness. Dark patterns degrade trust at a rate users cannot articulate — they just stop using the product. The test: would a user feel tricked if they understood exactly what the product was doing?',
17
+ 'fairness': 'Analyse whether the feature treats all user groups equitably. Start with the groups most likely to be harmed by the design assumptions. Document which groups benefit, which are neutral, and which may be disadvantaged. Disproportionate harm does not have to be intentional to be real.',
18
+ 'privacy': 'Evaluate the data collection and usage against the principle of data minimisation: collect only what is necessary, use only for the stated purpose, retain only as long as needed. Identify the worst-case use of each data point if it were leaked or misused. Privacy harms are irreversible — the standard should be higher than legal compliance.',
19
+ 'general': 'Evaluate the feature against three ethical dimensions: autonomy (does it respect user choice?), harm (could it cause disproportionate harm to specific groups?), and transparency (do users understand what the system is doing on their behalf?). A feature that scores poorly on all three should not ship as designed.',
20
+ };
21
+
22
+ const categorySteps: Record<EthicsCategory, string[]> = {
23
+ 'ai-ml': [
24
+ 'Identify all groups who will be affected by the AI/ML system\'s outputs',
25
+ 'Check training data: is it representative of all affected groups?',
26
+ 'Identify proxy variables: features that correlate with protected characteristics (zip code → race, etc.)',
27
+ 'Measure output quality separately for each demographic group — aggregate accuracy hides disparities',
28
+ 'Test edge cases for groups likely to be underrepresented in training data',
29
+ 'Evaluate the feedback loop: does poor performance for group X reduce their usage, which reduces training data for X, which worsens performance? (Feedback loop bias)',
30
+ 'Define the acceptable fairness metric: demographic parity, equalised odds, or calibration — and document the tradeoff',
31
+ 'Establish a bias monitoring plan for post-launch',
32
+ 'Document findings in veto_memory_store (type="decision", tags=["ethics", "ai-bias"])',
33
+ ],
34
+ 'dark-patterns': [
35
+ 'Map the full user flow from signup through cancellation — cancellation is where dark patterns concentrate',
36
+ 'Check for: confirmshaming (guilt-inducing opt-out language), hidden costs, roach motel (easy in, hard out), misdirection, disguised ads',
37
+ 'Apply the "would a user feel tricked" test to each step',
38
+ 'Check notification permission requests for false urgency or misleading framing',
39
+ 'Review subscription cancellation flow: how many steps, how many confirmation screens?',
40
+ 'Review default settings: are they set in the user\'s interest or the product\'s interest?',
41
+ 'Identify patterns that are legal but erode trust — these cause churn, not just complaints',
42
+ 'Recommend the honest alternative for each dark pattern found',
43
+ 'Store findings in veto_memory_store (type="decision", tags=["ethics", "ux"])',
44
+ ],
45
+ 'fairness': [
46
+ 'Identify which user groups are affected by this feature',
47
+ 'For each group: document the expected benefit and expected harm',
48
+ 'Identify the group most likely to be disadvantaged by the current design assumptions',
49
+ 'Check if the feature was designed with a default user in mind — who is that user, and who is excluded?',
50
+ 'Evaluate accessibility: does the feature work for users with disabilities?',
51
+ 'Evaluate language/literacy: does the feature assume a reading level or language that excludes users?',
52
+ 'Evaluate economic access: does the feature require hardware, bandwidth, or time that not all users have?',
53
+ 'Recommend design changes that reduce disproportionate harm without removing value for majority users',
54
+ 'Store fairness analysis in veto_memory_store (type="decision", tags=["ethics", "fairness"])',
55
+ ],
56
+ 'privacy': [
57
+ 'List all data points collected by this feature',
58
+ 'For each data point: is it strictly necessary for the stated purpose?',
59
+ 'Apply data minimisation: remove every data point that is not strictly necessary',
60
+ 'Identify retention: how long is each data point kept? Is there an automatic deletion policy?',
61
+ 'Identify worst-case misuse for each data point (leaked, sold, subpoenaed, used for a different purpose)',
62
+ 'Check if users can access, correct, and delete their data (GDPR Art. 15-17)',
63
+ 'Check if the privacy policy accurately describes this data collection',
64
+ 'Evaluate third-party data sharing: does each third-party SDK or API receive PII?',
65
+ 'Store findings in veto_memory_store (type="decision", tags=["ethics", "privacy"])',
66
+ ],
67
+ 'general': [
68
+ 'Identify all affected user groups — not just the primary user',
69
+ 'Evaluate autonomy: does the feature respect user choice, or does it nudge/coerce?',
70
+ 'Evaluate harm: which groups could be harmed, and is the harm proportionate to the benefit?',
71
+ 'Evaluate transparency: do users understand what the system is doing on their behalf?',
72
+ 'Apply the "front page test": would this design choice be described negatively in a tech journalism article?',
73
+ 'Apply the "worst user" test: what does the most vulnerable user experience when using this feature?',
74
+ 'Identify the single highest-risk ethical dimension and make a concrete recommendation',
75
+ 'Store findings in veto_memory_store (type="decision", tags=["ethics"])',
76
+ ],
77
+ };
78
+
79
+ export function plan(task: string, context?: string): AgentPlan {
80
+ const category = detectCategory(task + ' ' + (context ?? ''));
81
+ return {
82
+ agent: 'ethics-bias' as WorkerAgentType,
83
+ task,
84
+ tier: 3,
85
+ approach: categoryApproach[category],
86
+ steps: categorySteps[category],
87
+ checklist: [
88
+ '[ ] All affected user groups identified — not just the primary user',
89
+ '[ ] AI/ML systems: output quality measured separately per demographic group',
90
+ '[ ] Dark patterns: "would a user feel tricked" test applied',
91
+ '[ ] Fairness: group most likely to be disadvantaged explicitly identified',
92
+ '[ ] Privacy: data minimisation applied — unnecessary data points removed',
93
+ '[ ] Feedback loops identified for AI/ML features',
94
+ '[ ] Post-launch monitoring plan defined for AI/ML outputs',
95
+ '[ ] Findings stored in veto_memory_store with tags=["ethics"]',
96
+ ],
97
+ pitfalls: [
98
+ 'Treating legal compliance as an ethical ceiling — GDPR compliance is the floor, not the standard',
99
+ 'Evaluating bias only on aggregate accuracy — group-level disparities are invisible in aggregate metrics',
100
+ 'Assuming good intent eliminates harm — disproportionate harm is real regardless of intent',
101
+ 'Treating ethics as a one-time check — AI/ML bias drifts as usage patterns change',
102
+ 'Ignoring indirect harm — the people harmed most are often not the users in the room when the product is designed',
103
+ 'Conflating user preference with user interest — users may prefer a dark pattern in the moment but it harms them long-term',
104
+ ],
105
+ patterns: [
106
+ 'Affected-group enumeration: start every ethics analysis by listing all affected groups, especially non-users',
107
+ 'Worst-user test: evaluate through the lens of the most vulnerable person likely to use this feature',
108
+ 'Front-page test: would this design choice be described negatively in a tech journalism article?',
109
+ 'Disparity detection: always measure AI/ML performance per group, not just in aggregate',
110
+ ],
111
+ duration_estimate: '1-3 hours',
112
+ };
113
+ }
@@ -0,0 +1,114 @@
1
+ import { AgentPlan, WorkerAgentType } from '../types.js';
2
+
3
+ type ResearchCategory = 'technology' | 'approach' | 'library' | 'pattern' | 'general';
4
+
5
+ function detectCategory(task: string): ResearchCategory {
6
+ const t = task.toLowerCase();
7
+ if (t.includes('library') || t.includes('package') || t.includes('npm') || t.includes('dependency')) return 'library';
8
+ if (t.includes('how to') || t.includes('approach') || t.includes('best way') || t.includes('strategy')) return 'approach';
9
+ if (t.includes('tech') || t.includes('framework') || t.includes('language') || t.includes('tool')) return 'technology';
10
+ if (t.includes('pattern') || t.includes('design') || t.includes('architecture')) return 'pattern';
11
+ return 'general';
12
+ }
13
+
14
+ const categoryApproach: Record<ResearchCategory, string> = {
15
+ 'technology': 'Evaluate the technology against four criteria: maturity (production usage at scale), maintenance (commit activity, issue response time), ecosystem (plugins, integrations, community), and fit (does it solve the actual problem or require workarounds). Compare the top 3 options side-by-side. Recommend one with clear reasoning.',
16
+ 'approach': 'Research the dominant approaches to this problem. For each approach: document the tradeoffs, who uses it at scale, what problems it introduces, and when it is the wrong choice. Identify the approach that minimises future regret for this specific context.',
17
+ 'library': 'Audit the library before committing: weekly downloads, last publish date, open issues, license, bundle size, TypeScript support, and peer dependency conflicts. Check for known CVEs. Find the 2–3 best alternatives and compare. Recommend based on the actual requirements, not just stars.',
18
+ 'pattern': 'Research the established patterns for this problem domain. Identify which pattern major codebases (open source projects similar to this one) use. Document the tradeoffs and known failure modes of each. Recommend the pattern with the best track record for this scale and team size.',
19
+ 'general': 'Frame the research question precisely before searching. Identify: what is actually being asked, what evidence would constitute an answer, what sources are authoritative for this topic. Synthesise findings into a recommendation with clear reasoning.',
20
+ };
21
+
22
+ const categorySteps: Record<ResearchCategory, string[]> = {
23
+ 'technology': [
24
+ 'Define the evaluation criteria specific to this project (performance, bundle size, licensing, etc.)',
25
+ 'Identify the top 3–5 candidate technologies via npm/GitHub/documentation',
26
+ 'For each candidate: check production usage at scale (case studies, "used by" lists)',
27
+ 'Check maintenance: last commit, release cadence, open issues, response time',
28
+ 'Check ecosystem: number of plugins, integrations, community size',
29
+ 'Run a minimal proof-of-concept for the top 2 candidates',
30
+ 'Document the tradeoffs in a comparison table',
31
+ 'Identify deal-breakers for each option',
32
+ 'Make a recommendation with explicit reasoning and known risks',
33
+ 'Store the research outcome in veto_memory_store (type="reference") for future retrieval',
34
+ ],
35
+ 'approach': [
36
+ 'Define the problem precisely — what outcome are we optimising for?',
37
+ 'List the constraints that eliminate certain approaches immediately',
38
+ 'Research the 3–5 dominant approaches used in production',
39
+ 'For each approach: document implementation complexity, operational burden, and failure modes',
40
+ 'Find real-world examples of each approach at similar scale',
41
+ 'Identify which approach has the worst tail risks (what happens when it fails?)',
42
+ 'Test the recommended approach against the stated constraints',
43
+ 'Document the approach not chosen and why — prevents relitigating the decision',
44
+ 'Store the recommendation in veto_memory_store (type="decision")',
45
+ ],
46
+ 'library': [
47
+ 'Check npm: weekly downloads, version history, last publish date',
48
+ 'Check GitHub: star count is vanity; check commit frequency, issue close rate, PR merge speed',
49
+ 'Check the license: MIT/Apache/BSD = fine. GPL/AGPL = requires legal review.',
50
+ 'Run: npm audit on the package to check for known CVEs',
51
+ 'Check bundle size via bundlephobia.com (for frontend dependencies)',
52
+ 'Check TypeScript support: first-party types or @types/ package',
53
+ 'Check peer dependency compatibility with the current project',
54
+ 'Find the 2 best alternatives and compare on the same criteria',
55
+ 'Recommend with specific version to pin and known issues to watch',
56
+ 'Store decision in veto_memory_store with tags=["dependency", package name]',
57
+ ],
58
+ 'pattern': [
59
+ 'Name the problem domain clearly (e.g. "managing shared state in multi-step forms")',
60
+ 'Search for the canonical pattern name in this domain',
61
+ 'Find 3–5 well-regarded open-source implementations of each pattern',
62
+ 'Document: what the pattern solves, what it cannot solve, and its failure modes',
63
+ 'Identify the complexity cost: what does adopting this pattern require developers to understand?',
64
+ 'Check if this codebase already uses a related pattern — consistency matters more than perfection',
65
+ 'Recommend the pattern that fits the team\'s current knowledge and codebase conventions',
66
+ 'Store the pattern recommendation in veto_memory_store (type="reference")',
67
+ ],
68
+ 'general': [
69
+ 'Frame the research question: what specific information is needed?',
70
+ 'Identify authoritative sources for this topic',
71
+ 'Gather evidence from at least 3 independent sources',
72
+ 'Identify where sources disagree and why',
73
+ 'Synthesise findings: what is well-established vs. contested?',
74
+ 'Apply findings to the specific context of this project',
75
+ 'Make a recommendation with confidence level (high/medium/low)',
76
+ 'Document sources and store in veto_memory_store (type="reference")',
77
+ ],
78
+ };
79
+
80
+ export function plan(task: string, context?: string): AgentPlan {
81
+ const category = detectCategory(task + ' ' + (context ?? ''));
82
+ return {
83
+ agent: 'researcher' as WorkerAgentType,
84
+ task,
85
+ tier: 2,
86
+ approach: categoryApproach[category],
87
+ steps: categorySteps[category],
88
+ checklist: [
89
+ '[ ] Research question defined precisely before searching',
90
+ '[ ] At least 3 independent sources consulted',
91
+ '[ ] Top 2–3 options compared side-by-side',
92
+ '[ ] Tradeoffs and failure modes documented for each option',
93
+ '[ ] License, maintenance, and security checked (for libraries)',
94
+ '[ ] Recommendation made with clear reasoning',
95
+ '[ ] Decision stored in veto_memory_store for future retrieval',
96
+ '[ ] Sources documented',
97
+ ],
98
+ pitfalls: [
99
+ 'Researching without a precise question — "research authentication" is not researchable',
100
+ 'Using star count as a quality signal — stars measure marketing, not quality',
101
+ 'Not checking maintenance status — a popular abandoned library is worse than an obscure active one',
102
+ 'Recommending the newest option instead of the most proven one',
103
+ 'Not documenting the options that were rejected — the decision gets relitigated next month',
104
+ 'Forgetting to check license compatibility for commercial or open-source projects',
105
+ ],
106
+ patterns: [
107
+ 'Evidence-based recommendation: recommendation follows from documented evidence, not preference',
108
+ 'Rejection documentation: record what was rejected and why as strongly as what was chosen',
109
+ 'Source triangulation: any single source can be wrong — find 3 independent confirmations',
110
+ 'Fit-first evaluation: the best option for someone else\'s context may be wrong for yours',
111
+ ],
112
+ duration_estimate: '30-90 minutes',
113
+ };
114
+ }
@@ -0,0 +1,63 @@
1
+ import { AgentPlan, WorkerAgentType } from '../types.js';
2
+
3
+ type RiskCategory = 'technical' | 'security' | 'business' | 'general';
4
+
5
+ function detectCategory(task: string): RiskCategory {
6
+ const t = task.toLowerCase();
7
+ if (t.includes('security') || t.includes('vulnerability') || t.includes('attack') || t.includes('breach')) return 'security';
8
+ if (t.includes('business') || t.includes('market') || t.includes('revenue') || t.includes('legal') || t.includes('regulatory')) return 'business';
9
+ if (t.includes('technical') || t.includes('architecture') || t.includes('system') || t.includes('infra') || t.includes('deploy')) return 'technical';
10
+ return 'general';
11
+ }
12
+
13
+ const approaches: Record<RiskCategory, string> = {
14
+ 'technical': 'Assess technical risks using a failure mode analysis. For each component: what happens when it fails? What is the blast radius? What is the recovery path? Assign probability (1–5) and impact (1–5), sort by P×I score. Focus on the top 3 risks — those are the ones worth mitigating now.',
15
+ 'security': 'Perform a threat model using STRIDE: Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege. For each threat: document the attack vector, current controls, and residual risk. Prioritise by attacker motivation × exploitability × impact.',
16
+ 'business': 'Assess business risks across four categories: market (demand disappears), operational (team/tooling fails), financial (runway runs out), and regulatory (compliance changes). For each: what is the early warning signal? What is the mitigation before it becomes a crisis?',
17
+ 'general': 'Enumerate risks across technical, business, and operational dimensions. For each risk: probability (low/medium/high), impact (low/medium/high), detectability (would we know before it causes damage?), and mitigation. Prioritise by P×I with a tie-break on detectability.',
18
+ };
19
+
20
+ export function plan(task: string, context?: string): AgentPlan {
21
+ const category = detectCategory(task + ' ' + (context ?? ''));
22
+ return {
23
+ agent: 'risk-assessor' as WorkerAgentType,
24
+ task,
25
+ tier: 3,
26
+ approach: approaches[category],
27
+ steps: [
28
+ 'Define the scope: what system, feature, or decision is being assessed?',
29
+ 'Enumerate all risks — do not filter yet, just list everything that could go wrong',
30
+ 'For each risk: assign probability (1–5) and impact (1–5)',
31
+ 'Calculate risk score: P × I (max 25)',
32
+ 'Sort risks by score, descending',
33
+ 'For the top 5 risks: document the early warning signal and mitigation',
34
+ 'Identify which risks can be eliminated vs. mitigated vs. accepted',
35
+ 'For accepted risks: document the acceptance rationale and review date',
36
+ 'Assign ownership: who is responsible for monitoring each top-5 risk?',
37
+ 'Store risk register in veto_memory_store (type="reference", tags=["risk", domain])',
38
+ ],
39
+ checklist: [
40
+ '[ ] Scope defined clearly',
41
+ '[ ] At least 10 risks enumerated before filtering',
42
+ '[ ] All risks scored on P × I scale',
43
+ '[ ] Top 5 risks have early warning signals documented',
44
+ '[ ] Top 5 risks have mitigation steps documented',
45
+ '[ ] Accepted risks have rationale and review date',
46
+ '[ ] Risk register stored in veto_memory_store',
47
+ ],
48
+ pitfalls: [
49
+ 'Listing only obvious risks — the dangerous ones are the ones nobody thinks of',
50
+ 'Scoring risks on gut feel without separating probability from impact',
51
+ 'Documenting risks without assigning owners — nobody monitors an ownerless risk',
52
+ 'Treating mitigation as risk elimination — most mitigations only reduce probability or impact, not to zero',
53
+ 'Not setting a review date — risk registers become stale within 3 months',
54
+ ],
55
+ patterns: [
56
+ 'P × I scoring: separates probability from impact to avoid conflating "likely but minor" with "unlikely but catastrophic"',
57
+ 'Early warning signal: each top risk gets a concrete signal that would trigger the mitigation',
58
+ 'Accepted risk documentation: explicit acceptance is better than implicit ignorance',
59
+ 'Risk ownership: every top-5 risk has a named owner who is responsible for the early warning signal',
60
+ ],
61
+ duration_estimate: '1-3 hours',
62
+ };
63
+ }
@@ -0,0 +1,55 @@
1
+ import { AgentPlan, WorkerAgentType } from '../types.js';
2
+
3
+ export function plan(task: string, context?: string): AgentPlan {
4
+ const t = (task + ' ' + (context ?? '')).toLowerCase();
5
+ const isGreenfield = t.includes('new project') || t.includes('start') || t.includes('greenfield') || t.includes('choose');
6
+ const isMigration = t.includes('migrat') || t.includes('replac') || t.includes('switch from') || t.includes('move from');
7
+
8
+ const approach = isGreenfield
9
+ ? 'Evaluate the full stack for a greenfield project. Prioritise developer velocity, operational simplicity, and escape hatches. Recommend a stack with a 2-year horizon, not a 10-year one.'
10
+ : isMigration
11
+ ? 'Evaluate the migration path. A technology switch is only worth it if the current choice is actively blocking progress. Quantify: what does the current stack cost in monthly developer friction? What is the migration cost in weeks? Recommend migrate only if ROI is positive within 6 months.'
12
+ : 'The best technology is usually the one the team already knows, unless there is a specific capability gap. Document the gap first, then evaluate if a technology switch is the minimal solution.';
13
+
14
+ return {
15
+ agent: 'tech-advisor' as WorkerAgentType,
16
+ task,
17
+ tier: 3,
18
+ approach,
19
+ steps: [
20
+ 'Identify the actual problem: what specific capability is missing or causing friction?',
21
+ 'Check if the current stack solves it with a library/plugin before considering a switch',
22
+ 'If a new technology is needed: define evaluation criteria for this project specifically',
23
+ 'List the top 3 candidates that meet the baseline criteria',
24
+ 'Evaluate each: team learning curve, operational complexity, ecosystem maturity, licensing',
25
+ 'Identify hidden costs: CI/CD changes, deployment changes, team training, tooling updates',
26
+ 'Run a time-boxed spike (2–4 hours) with the top candidate to validate the fit',
27
+ 'Document the decision as an ADR with alternatives and rejection reasons',
28
+ 'Identify the first sign the chosen technology was wrong — what triggers re-evaluation?',
29
+ 'Store in veto_memory_store (type="decision", tags=["tech-stack"])',
30
+ ],
31
+ checklist: [
32
+ '[ ] Problem statement defined before evaluating solutions',
33
+ '[ ] Current stack\'s ability to solve the problem checked first',
34
+ '[ ] Top 3 candidates evaluated against project-specific criteria',
35
+ '[ ] Hidden migration costs estimated',
36
+ '[ ] Time-boxed spike completed for top candidate',
37
+ '[ ] ADR written with alternatives and rejection reasons',
38
+ '[ ] Re-evaluation trigger defined',
39
+ ],
40
+ pitfalls: [
41
+ 'Choosing a technology because it is popular industry-wide — the industry\'s context is not yours',
42
+ 'Underestimating hidden migration costs (CI/CD, docs, engineer onboarding)',
43
+ 'Skipping the spike — looks good in docs often fails on real requirements',
44
+ 'Not defining a re-evaluation trigger — you end up committed to a wrong choice indefinitely',
45
+ 'Recommending a full rewrite when an adapter would solve the problem',
46
+ ],
47
+ patterns: [
48
+ 'Capability-gap-first: identify the gap before evaluating technologies',
49
+ 'Time-boxed spike: validate with real code before committing',
50
+ 'ADR on adoption: document the decision the day it is made',
51
+ 'Re-evaluation trigger: define upfront what would make you revisit this decision',
52
+ ],
53
+ duration_estimate: '2-4 hours',
54
+ };
55
+ }