@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.
- package/.claude/settings.local.json +9 -0
- package/README.md +190 -0
- package/dist/adapters/claude.js +57 -0
- package/dist/adapters/codex.js +58 -0
- package/dist/adapters/gemini.js +58 -0
- package/dist/adapters/index.js +156 -0
- package/dist/agents/development/api.js +116 -0
- package/dist/agents/development/backend.js +82 -0
- package/dist/agents/development/coder.js +207 -0
- package/dist/agents/development/database.js +81 -0
- package/dist/agents/development/debugger.js +234 -0
- package/dist/agents/development/devops.js +84 -0
- package/dist/agents/development/frontend.js +83 -0
- package/dist/agents/development/migration.js +141 -0
- package/dist/agents/development/performance.js +142 -0
- package/dist/agents/development/refactor.js +85 -0
- package/dist/agents/development/reviewer.js +260 -0
- package/dist/agents/development/tester.js +143 -0
- package/dist/agents/executor.js +144 -0
- package/dist/agents/memory/context-manager.js +167 -0
- package/dist/agents/memory/decision-logger.js +157 -0
- package/dist/agents/memory/knowledge-base.js +120 -0
- package/dist/agents/memory/pattern-learner.js +140 -0
- package/dist/agents/memory/project-mapper.js +114 -0
- package/dist/agents/quality/accessibility.js +89 -0
- package/dist/agents/quality/code-quality.js +109 -0
- package/dist/agents/quality/compatibility.js +55 -0
- package/dist/agents/quality/documentation.js +95 -0
- package/dist/agents/quality/error-handling.js +87 -0
- package/dist/agents/research/competitor-analyzer.js +44 -0
- package/dist/agents/research/cost-analyzer.js +51 -0
- package/dist/agents/research/estimator.js +57 -0
- package/dist/agents/research/ethics-bias.js +111 -0
- package/dist/agents/research/researcher.js +112 -0
- package/dist/agents/research/risk-assessor.js +61 -0
- package/dist/agents/research/tech-advisor.js +52 -0
- package/dist/agents/security/auth.js +269 -0
- package/dist/agents/security/dependency-audit.js +273 -0
- package/dist/agents/security/penetration.js +245 -0
- package/dist/agents/security/privacy.js +259 -0
- package/dist/agents/security/scanner.js +288 -0
- package/dist/agents/security/secrets.js +212 -0
- package/dist/agents/types.js +2 -0
- package/dist/agents/workflow/automation.js +56 -0
- package/dist/agents/workflow/file-manager.js +49 -0
- package/dist/agents/workflow/git-agent.js +52 -0
- package/dist/agents/workflow/reporter.js +48 -0
- package/dist/agents/workflow/search-agent.js +39 -0
- package/dist/agents/workflow/task-coordinator.js +40 -0
- package/dist/agents/workflow/task-planner.js +46 -0
- package/dist/cli.js +132 -0
- package/dist/council/decision-engine.js +136 -0
- package/dist/council/devil-advocate.js +106 -0
- package/dist/council/index.js +37 -0
- package/dist/council/lead-developer.js +108 -0
- package/dist/council/legal-compliance.js +142 -0
- package/dist/council/product-manager.js +92 -0
- package/dist/council/security.js +162 -0
- package/dist/council/system-architect.js +122 -0
- package/dist/council/types.js +2 -0
- package/dist/council/ux-designer.js +109 -0
- package/dist/memory/local.js +182 -0
- package/dist/memory/schema.js +116 -0
- package/dist/memory/sync.js +199 -0
- package/dist/router/complexity-scorer.js +78 -0
- package/dist/router/context-compressor.js +58 -0
- package/dist/router/index.js +29 -0
- package/dist/router/learning-updater.js +186 -0
- package/dist/router/model-selector.js +51 -0
- package/dist/router/rate-monitor.js +73 -0
- package/dist/server.js +949 -0
- package/dist/skills/development/skill-api-design.js +313 -0
- package/dist/skills/development/skill-auth.js +255 -0
- package/dist/skills/development/skill-ci-cd.js +2 -0
- package/dist/skills/development/skill-crud.js +193 -0
- package/dist/skills/development/skill-db-schema.js +2 -0
- package/dist/skills/development/skill-docker.js +2 -0
- package/dist/skills/development/skill-env-setup.js +2 -0
- package/dist/skills/development/skill-scaffold.js +299 -0
- package/dist/skills/intelligence/skill-complexity-score.js +66 -0
- package/dist/skills/intelligence/skill-cost-track.js +36 -0
- package/dist/skills/intelligence/skill-learning-loop.js +66 -0
- package/dist/skills/intelligence/skill-pattern-detect.js +35 -0
- package/dist/skills/intelligence/skill-rate-watch.js +58 -0
- package/dist/skills/memory/skill-context-compress.js +82 -0
- package/dist/skills/memory/skill-cross-sync.js +88 -0
- package/dist/skills/memory/skill-decision-log.js +103 -0
- package/dist/skills/memory/skill-session-restore.js +44 -0
- package/dist/skills/memory/skill-session-save.js +78 -0
- package/dist/skills/quality/skill-accessibility.js +2 -0
- package/dist/skills/quality/skill-code-review.js +60 -0
- package/dist/skills/quality/skill-docs-gen.js +2 -0
- package/dist/skills/quality/skill-perf-audit.js +2 -0
- package/dist/skills/quality/skill-security-scan.js +67 -0
- package/dist/skills/quality/skill-test-suite.js +274 -0
- package/dist/skills/workflow/skill-deploy.js +2 -0
- package/dist/skills/workflow/skill-git-workflow.js +2 -0
- package/dist/skills/workflow/skill-rollback.js +2 -0
- package/dist/skills/workflow/skill-task-breakdown.js +2 -0
- package/package.json +30 -0
- package/src/adapters/claude.ts +70 -0
- package/src/adapters/codex.ts +71 -0
- package/src/adapters/gemini.ts +71 -0
- package/src/adapters/index.ts +217 -0
- package/src/agents/development/api.ts +120 -0
- package/src/agents/development/backend.ts +85 -0
- package/src/agents/development/coder.ts +213 -0
- package/src/agents/development/database.ts +83 -0
- package/src/agents/development/debugger.ts +238 -0
- package/src/agents/development/devops.ts +86 -0
- package/src/agents/development/frontend.ts +85 -0
- package/src/agents/development/migration.ts +144 -0
- package/src/agents/development/performance.ts +144 -0
- package/src/agents/development/refactor.ts +86 -0
- package/src/agents/development/reviewer.ts +268 -0
- package/src/agents/development/tester.ts +151 -0
- package/src/agents/executor.ts +158 -0
- package/src/agents/memory/context-manager.ts +171 -0
- package/src/agents/memory/decision-logger.ts +160 -0
- package/src/agents/memory/knowledge-base.ts +124 -0
- package/src/agents/memory/pattern-learner.ts +143 -0
- package/src/agents/memory/project-mapper.ts +118 -0
- package/src/agents/quality/accessibility.ts +99 -0
- package/src/agents/quality/code-quality.ts +115 -0
- package/src/agents/quality/compatibility.ts +58 -0
- package/src/agents/quality/documentation.ts +105 -0
- package/src/agents/quality/error-handling.ts +96 -0
- package/src/agents/research/competitor-analyzer.ts +45 -0
- package/src/agents/research/cost-analyzer.ts +54 -0
- package/src/agents/research/estimator.ts +60 -0
- package/src/agents/research/ethics-bias.ts +113 -0
- package/src/agents/research/researcher.ts +114 -0
- package/src/agents/research/risk-assessor.ts +63 -0
- package/src/agents/research/tech-advisor.ts +55 -0
- package/src/agents/security/auth.ts +287 -0
- package/src/agents/security/dependency-audit.ts +337 -0
- package/src/agents/security/penetration.ts +262 -0
- package/src/agents/security/privacy.ts +285 -0
- package/src/agents/security/scanner.ts +322 -0
- package/src/agents/security/secrets.ts +249 -0
- package/src/agents/types.ts +66 -0
- package/src/agents/workflow/automation.ts +59 -0
- package/src/agents/workflow/file-manager.ts +52 -0
- package/src/agents/workflow/git-agent.ts +55 -0
- package/src/agents/workflow/reporter.ts +51 -0
- package/src/agents/workflow/search-agent.ts +40 -0
- package/src/agents/workflow/task-coordinator.ts +41 -0
- package/src/agents/workflow/task-planner.ts +47 -0
- package/src/cli.ts +143 -0
- package/src/council/decision-engine.ts +171 -0
- package/src/council/devil-advocate.ts +116 -0
- package/src/council/index.ts +44 -0
- package/src/council/lead-developer.ts +118 -0
- package/src/council/legal-compliance.ts +152 -0
- package/src/council/product-manager.ts +102 -0
- package/src/council/security.ts +172 -0
- package/src/council/system-architect.ts +132 -0
- package/src/council/types.ts +33 -0
- package/src/council/ux-designer.ts +121 -0
- package/src/memory/local.ts +305 -0
- package/src/memory/schema.ts +174 -0
- package/src/memory/sync.ts +274 -0
- package/src/router/complexity-scorer.ts +96 -0
- package/src/router/context-compressor.ts +74 -0
- package/src/router/index.ts +60 -0
- package/src/router/learning-updater.ts +271 -0
- package/src/router/model-selector.ts +83 -0
- package/src/router/rate-monitor.ts +103 -0
- package/src/server.ts +1038 -0
- package/src/skills/development/skill-api-design.ts +329 -0
- package/src/skills/development/skill-auth.ts +271 -0
- package/src/skills/development/skill-ci-cd.ts +0 -0
- package/src/skills/development/skill-crud.ts +209 -0
- package/src/skills/development/skill-db-schema.ts +0 -0
- package/src/skills/development/skill-docker.ts +0 -0
- package/src/skills/development/skill-env-setup.ts +0 -0
- package/src/skills/development/skill-scaffold.ts +323 -0
- package/src/skills/intelligence/skill-complexity-score.ts +69 -0
- package/src/skills/intelligence/skill-cost-track.ts +39 -0
- package/src/skills/intelligence/skill-learning-loop.ts +69 -0
- package/src/skills/intelligence/skill-pattern-detect.ts +38 -0
- package/src/skills/intelligence/skill-rate-watch.ts +61 -0
- package/src/skills/memory/skill-context-compress.ts +98 -0
- package/src/skills/memory/skill-cross-sync.ts +104 -0
- package/src/skills/memory/skill-decision-log.ts +119 -0
- package/src/skills/memory/skill-session-restore.ts +59 -0
- package/src/skills/memory/skill-session-save.ts +94 -0
- package/src/skills/quality/skill-accessibility.ts +0 -0
- package/src/skills/quality/skill-code-review.ts +84 -0
- package/src/skills/quality/skill-docs-gen.ts +0 -0
- package/src/skills/quality/skill-perf-audit.ts +0 -0
- package/src/skills/quality/skill-security-scan.ts +91 -0
- package/src/skills/quality/skill-test-suite.ts +290 -0
- package/src/skills/workflow/skill-deploy.ts +0 -0
- package/src/skills/workflow/skill-git-workflow.ts +0 -0
- package/src/skills/workflow/skill-rollback.ts +0 -0
- package/src/skills/workflow/skill-task-breakdown.ts +0 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { AgentPlan, WorkerAgentType } from '../types.js';
|
|
2
|
+
|
|
3
|
+
type DbType = 'rdbms' | 'nosql' | 'timeseries' | 'graph' | 'general';
|
|
4
|
+
|
|
5
|
+
function detectDbType(task: string, context?: string): DbType {
|
|
6
|
+
const combined = (task + ' ' + (context ?? '')).toLowerCase();
|
|
7
|
+
if (combined.includes('mongo') || combined.includes('document') || combined.includes('dynamodb') || combined.includes('firestore') || combined.includes('nosql')) return 'nosql';
|
|
8
|
+
if (combined.includes('timeseries') || combined.includes('influx') || combined.includes('prometheus') || combined.includes('clickhouse') || combined.includes('time series')) return 'timeseries';
|
|
9
|
+
if (combined.includes('graph') || combined.includes('neo4j') || combined.includes('relationship')) return 'graph';
|
|
10
|
+
if (combined.includes('postgres') || combined.includes('mysql') || combined.includes('sqlite') || combined.includes('sql') || combined.includes('relational')) return 'rdbms';
|
|
11
|
+
return 'general';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const dbApproach: Record<DbType, string> = {
|
|
15
|
+
rdbms: 'Design a normalised schema first (3NF), add indexes for every foreign key and frequent filter column, use transactions for multi-table mutations, plan migration scripts with backward compatibility.',
|
|
16
|
+
nosql: 'Design around access patterns — denormalise to serve queries in one round trip. Choose partition keys that distribute load evenly. Model for reads, use references sparingly for writes.',
|
|
17
|
+
timeseries: 'Optimise for append-heavy write patterns. Use time-bucketed partitioning. Compress old data with downsampling. Design queries around time ranges, not individual rows.',
|
|
18
|
+
graph: 'Model entities as nodes and relationships as edges with properties. Index node labels and edge types. Design traversal patterns and bound depth of recursive queries.',
|
|
19
|
+
general: 'Evaluate RDBMS vs NoSQL based on data structure, access patterns, and consistency requirements. Design schema to serve the most frequent query without joins if possible.',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function plan(task: string, context?: string): AgentPlan {
|
|
23
|
+
const dbType = detectDbType(task, context);
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
agent: 'database' as WorkerAgentType,
|
|
27
|
+
task,
|
|
28
|
+
tier: 3,
|
|
29
|
+
approach: dbApproach[dbType],
|
|
30
|
+
steps: [
|
|
31
|
+
'List all entities and their relationships — draw an ER diagram',
|
|
32
|
+
'Identify the top 5 most frequent query patterns (what will be read most?)',
|
|
33
|
+
'Design the schema to serve those queries with minimal joins/lookups',
|
|
34
|
+
'Add primary keys and unique constraints first',
|
|
35
|
+
'Add foreign key constraints for relational integrity',
|
|
36
|
+
'Identify every column used in WHERE, ORDER BY, or JOIN — add indexes',
|
|
37
|
+
'Choose composite index column order by selectivity (most selective first)',
|
|
38
|
+
'Design the migration script: additive changes first (new tables, new nullable columns)',
|
|
39
|
+
'Write seed / fixture data for the development environment',
|
|
40
|
+
'Write query tests that assert on execution plan (EXPLAIN ANALYZE)',
|
|
41
|
+
'Set up connection pooling with appropriate pool size for the workload',
|
|
42
|
+
'Configure statement_timeout and lock_timeout to prevent runaway queries',
|
|
43
|
+
'Plan archival strategy for old data — partitioning or archival table',
|
|
44
|
+
'Document the schema with comments on each table and non-obvious column',
|
|
45
|
+
],
|
|
46
|
+
checklist: [
|
|
47
|
+
'[ ] Every table has a primary key',
|
|
48
|
+
'[ ] Foreign keys are declared and indexed',
|
|
49
|
+
'[ ] Every JOIN column on the many-side has an index',
|
|
50
|
+
'[ ] Every column used in frequent WHERE clauses has an index',
|
|
51
|
+
'[ ] No SELECT * in production queries — enumerate columns',
|
|
52
|
+
'[ ] Multi-table mutations wrapped in transactions',
|
|
53
|
+
'[ ] Migrations are reversible (down migration written)',
|
|
54
|
+
'[ ] Migration tested on a copy of production data volume',
|
|
55
|
+
'[ ] Connection pool size calculated: connections = (core_count * 2) + effective_spindle_count',
|
|
56
|
+
'[ ] statement_timeout configured to prevent runaway queries',
|
|
57
|
+
'[ ] EXPLAIN ANALYZE run on all slow query candidates',
|
|
58
|
+
'[ ] Sensitive columns (PII, passwords) identified and encrypted at rest',
|
|
59
|
+
'[ ] Backup and point-in-time recovery tested',
|
|
60
|
+
'[ ] Schema documented with table and column comments',
|
|
61
|
+
],
|
|
62
|
+
pitfalls: [
|
|
63
|
+
'Using SELECT * in application queries — sends unnecessary data over the wire and breaks when columns are added/removed',
|
|
64
|
+
'Forgetting to index foreign keys — causes full table scans on every JOIN',
|
|
65
|
+
'Storing JSON blobs in relational databases to avoid schema work — kills query performance and integrity',
|
|
66
|
+
'Not wrapping multi-step mutations in a transaction — leaves the database in a partially updated state on failure',
|
|
67
|
+
'Using ORM-generated schemas without reviewing the SQL — ORMs frequently generate non-optimal index choices',
|
|
68
|
+
'Choosing UUID as a clustered primary key in PostgreSQL without understanding write amplification from random page splits',
|
|
69
|
+
'Ignoring VACUUM in PostgreSQL — table bloat degrades read performance over time',
|
|
70
|
+
'Testing migrations only on an empty database — schema changes that work on empty DBs may lock production tables for minutes',
|
|
71
|
+
],
|
|
72
|
+
patterns: [
|
|
73
|
+
'Repository pattern (abstract DB access behind an interface)',
|
|
74
|
+
'Unit of Work pattern (group related DB operations into a transaction)',
|
|
75
|
+
'CQRS (separate read and write models for high-throughput systems)',
|
|
76
|
+
'Event Sourcing (store events, derive state — for audit-heavy domains)',
|
|
77
|
+
'Optimistic locking (version column for concurrent update detection)',
|
|
78
|
+
'Soft delete pattern (deleted_at timestamp instead of hard DELETE)',
|
|
79
|
+
'Temporal tables (track history of row changes)',
|
|
80
|
+
],
|
|
81
|
+
duration_estimate: '1-2 days',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { AgentPlan, WorkerAgentType } from '../types.js';
|
|
2
|
+
|
|
3
|
+
type ErrorCategory = 'runtime' | 'type' | 'async' | 'performance' | 'network' | 'memory' | 'logic';
|
|
4
|
+
|
|
5
|
+
function detectErrorCategory(task: string, context?: string): ErrorCategory {
|
|
6
|
+
const combined = (task + ' ' + (context ?? '')).toLowerCase();
|
|
7
|
+
if (combined.includes('memory') || combined.includes('leak') || combined.includes('heap') || combined.includes('oom')) return 'memory';
|
|
8
|
+
if (combined.includes('slow') || combined.includes('latency') || combined.includes('timeout') || combined.includes('performance')) return 'performance';
|
|
9
|
+
if (combined.includes('network') || combined.includes('fetch') || combined.includes('http') || combined.includes('cors') || combined.includes('socket')) return 'network';
|
|
10
|
+
if (combined.includes('promise') || combined.includes('async') || combined.includes('await') || combined.includes('callback') || combined.includes('race')) return 'async';
|
|
11
|
+
if (combined.includes('type') || combined.includes('undefined') || combined.includes('null') || combined.includes('cannot read')) return 'type';
|
|
12
|
+
if (combined.includes('wrong') || combined.includes('incorrect') || combined.includes('unexpected') || combined.includes('logic')) return 'logic';
|
|
13
|
+
return 'runtime';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const categoryApproach: Record<ErrorCategory, string> = {
|
|
17
|
+
runtime: 'Reproduce reliably → isolate to smallest failing case → read the full stack trace → form one hypothesis → add targeted logging → verify fix does not break other paths.',
|
|
18
|
+
type: 'Trace the data flow from origin to crash site — find where the wrong type enters. Use TypeScript strict mode findings as a guide. Fix the source, not the symptom.',
|
|
19
|
+
async: 'Map the Promise chain or async call graph. Look for missing awaits, race conditions, unhandled rejections, and event-loop blocking. Add sequential logging to trace execution order.',
|
|
20
|
+
performance: 'Measure first — use profiling tools to identify the actual bottleneck before touching code. Focus on the 80/20 hotspot. Validate improvement with benchmarks before and after.',
|
|
21
|
+
network: 'Inspect actual requests in browser DevTools or a proxy (Wireshark/mitmproxy). Verify headers, CORS policy, TLS, DNS, and connection reuse. Distinguish client bugs from server bugs.',
|
|
22
|
+
memory: 'Take heap snapshots before and after suspected operations. Compare retained objects. Look for closures holding large references, event listener accumulation, and growing caches without eviction.',
|
|
23
|
+
logic: 'Write a minimal reproducing test. Step through with a debugger or add assertion-style logging at each decision point. State the expected vs actual output explicitly before investigating.',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const categorySteps: Record<ErrorCategory, string[]> = {
|
|
27
|
+
runtime: [
|
|
28
|
+
'Read the full stack trace — note the exact file, line number, and error message',
|
|
29
|
+
'Reproduce the error in isolation — create the smallest possible reproduction',
|
|
30
|
+
'Check if the error is deterministic or intermittent',
|
|
31
|
+
'Identify the last working state using git bisect or recent commits',
|
|
32
|
+
'Form a single specific hypothesis about the root cause',
|
|
33
|
+
'Add targeted logging around the hypothesis — do NOT log everything',
|
|
34
|
+
'Verify the hypothesis by temporarily modifying the suspected code',
|
|
35
|
+
'Fix at the root cause, not at the point where the error surfaces',
|
|
36
|
+
'Write a regression test that would have caught this bug',
|
|
37
|
+
'Review related code paths that could have the same defect',
|
|
38
|
+
'Document the root cause in the fix commit message',
|
|
39
|
+
],
|
|
40
|
+
type: [
|
|
41
|
+
'Find the exact line where the TypeError / undefined access occurs',
|
|
42
|
+
'Trace the variable backwards to where it is assigned',
|
|
43
|
+
'Check if the data source (API, DB, config) can return null/undefined',
|
|
44
|
+
'Enable TypeScript strict mode and check for new red squiggles',
|
|
45
|
+
'Fix the type at the origin — add correct types or validation at the boundary',
|
|
46
|
+
'Add runtime validation (zod, guard function) at the data entry point',
|
|
47
|
+
'Remove any type assertions (as Type, as any) that hide the real type',
|
|
48
|
+
'Test with null, undefined, empty string, and unexpected types',
|
|
49
|
+
'Add null checks or optional chaining where appropriate',
|
|
50
|
+
'Write a unit test that exercises the null/undefined path',
|
|
51
|
+
],
|
|
52
|
+
async: [
|
|
53
|
+
'Map the full async call graph for the failing operation',
|
|
54
|
+
'Check every await — ensure no async function is called without await',
|
|
55
|
+
'Look for missing error propagation — catch blocks that do not rethrow',
|
|
56
|
+
'Check for race conditions — operations that depend on execution order',
|
|
57
|
+
'Look for event-loop blocking (synchronous heavy computation in an async context)',
|
|
58
|
+
'Verify Promise.all vs Promise.allSettled — unhandled rejection vs partial failure',
|
|
59
|
+
'Add sequential timestamps to log statements to trace actual execution order',
|
|
60
|
+
'Use AsyncLocalStorage or correlation IDs to trace concurrent requests',
|
|
61
|
+
'Check for multiple competing setInterval/setTimeout that interfere',
|
|
62
|
+
'Write a test that exercises the async failure path explicitly',
|
|
63
|
+
],
|
|
64
|
+
performance: [
|
|
65
|
+
'Establish a baseline measurement — latency p50/p95/p99, throughput, CPU, memory',
|
|
66
|
+
'Use a profiler (clinic.js, Chrome DevTools, py-spy) — identify the top hotspot',
|
|
67
|
+
'Check for N+1 query patterns — count DB queries per request',
|
|
68
|
+
'Check for synchronous blocking operations in async code',
|
|
69
|
+
'Review algorithm complexity — O(n²) loops over large datasets',
|
|
70
|
+
'Check caching — are expensive results being recomputed unnecessarily?',
|
|
71
|
+
'Profile memory — look for unnecessary object allocation in hot paths',
|
|
72
|
+
'Fix the single biggest bottleneck and measure again before moving on',
|
|
73
|
+
'Add performance regression tests (benchmarks) to CI',
|
|
74
|
+
'Document the performance improvement with before/after numbers',
|
|
75
|
+
],
|
|
76
|
+
network: [
|
|
77
|
+
'Capture the raw request and response with browser DevTools or curl',
|
|
78
|
+
'Check CORS headers — Access-Control-Allow-Origin must match the origin',
|
|
79
|
+
'Verify the TLS certificate is valid and not expired',
|
|
80
|
+
'Check DNS resolution — nslookup or dig the hostname',
|
|
81
|
+
'Verify the correct HTTP method and Content-Type are being sent',
|
|
82
|
+
'Look for redirect loops (301/302 cycles)',
|
|
83
|
+
'Check keep-alive and connection pool settings on the client',
|
|
84
|
+
'Test from multiple networks to distinguish ISP / firewall issues',
|
|
85
|
+
'Inspect retry logic — are retries causing duplicate side effects?',
|
|
86
|
+
'Add request/response logging middleware to trace the full exchange',
|
|
87
|
+
],
|
|
88
|
+
memory: [
|
|
89
|
+
'Take a heap snapshot before the suspected operation',
|
|
90
|
+
'Perform the operation that causes the leak',
|
|
91
|
+
'Take a second heap snapshot and compare with the first',
|
|
92
|
+
'Identify the object type and retention path in the diff',
|
|
93
|
+
'Look for event listeners added without removeEventListener',
|
|
94
|
+
'Check for closures that hold references to large objects',
|
|
95
|
+
'Review caches and collections that grow without eviction',
|
|
96
|
+
'Look for circular references that prevent garbage collection',
|
|
97
|
+
'Fix the retention path and verify with a third heap snapshot',
|
|
98
|
+
'Add a memory usage metric to monitoring to detect future regressions',
|
|
99
|
+
],
|
|
100
|
+
logic: [
|
|
101
|
+
'Write down the exact expected output and the actual output',
|
|
102
|
+
'Identify the decision points (conditionals, loops, function calls) on the code path',
|
|
103
|
+
'Write a minimal unit test that reproduces the wrong output',
|
|
104
|
+
'Step through the code with a debugger, verifying state at each step',
|
|
105
|
+
'Check boundary conditions: off-by-one errors, inclusive vs exclusive ranges',
|
|
106
|
+
'Check date/time logic: timezone assumptions, DST transitions, epoch offsets',
|
|
107
|
+
'Verify sort/comparison functions return correct negative/zero/positive values',
|
|
108
|
+
'Trace the state mutation — check for accidental shared mutable state',
|
|
109
|
+
'Fix the logic and run all related tests',
|
|
110
|
+
'Add an assertion comment explaining the invariant being enforced',
|
|
111
|
+
],
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const categoryChecklist: Record<ErrorCategory, string[]> = {
|
|
115
|
+
runtime: [
|
|
116
|
+
'[ ] Full stack trace captured and read carefully',
|
|
117
|
+
'[ ] Minimal reproduction created',
|
|
118
|
+
'[ ] Root cause identified (not just symptom fixed)',
|
|
119
|
+
'[ ] Fix applied at root cause location',
|
|
120
|
+
'[ ] Regression test written',
|
|
121
|
+
'[ ] Related code paths reviewed for same defect',
|
|
122
|
+
'[ ] Fix verified in the same environment where the bug occurred',
|
|
123
|
+
],
|
|
124
|
+
type: [
|
|
125
|
+
'[ ] TypeScript strict mode enabled',
|
|
126
|
+
'[ ] No type assertions (as Type) hiding the bug',
|
|
127
|
+
'[ ] Runtime validation added at data boundary',
|
|
128
|
+
'[ ] Null/undefined paths tested explicitly',
|
|
129
|
+
'[ ] No any types introduced to silence the compiler',
|
|
130
|
+
],
|
|
131
|
+
async: [
|
|
132
|
+
'[ ] Every async call is properly awaited',
|
|
133
|
+
'[ ] Unhandled rejection handler in place',
|
|
134
|
+
'[ ] Race conditions analysed and eliminated',
|
|
135
|
+
'[ ] Error propagation tested in failure paths',
|
|
136
|
+
'[ ] Async test uses proper done/async-await, not callbacks',
|
|
137
|
+
],
|
|
138
|
+
performance: [
|
|
139
|
+
'[ ] Baseline benchmark recorded before fix',
|
|
140
|
+
'[ ] Fix targets the profiled hotspot, not guesswork',
|
|
141
|
+
'[ ] No N+1 query patterns remain',
|
|
142
|
+
'[ ] Improvement verified with post-fix benchmark',
|
|
143
|
+
'[ ] Performance regression test added to CI',
|
|
144
|
+
],
|
|
145
|
+
network: [
|
|
146
|
+
'[ ] Raw request/response captured and inspected',
|
|
147
|
+
'[ ] CORS headers correct',
|
|
148
|
+
'[ ] TLS certificate valid',
|
|
149
|
+
'[ ] Retry logic does not cause duplicate side effects',
|
|
150
|
+
'[ ] Error handling for network timeouts in place',
|
|
151
|
+
],
|
|
152
|
+
memory: [
|
|
153
|
+
'[ ] Heap snapshots taken before and after fix',
|
|
154
|
+
'[ ] All event listeners have corresponding removeEventListener',
|
|
155
|
+
'[ ] Caches have maximum size and eviction policy',
|
|
156
|
+
'[ ] No circular references between large objects',
|
|
157
|
+
'[ ] Memory metric added to monitoring dashboard',
|
|
158
|
+
],
|
|
159
|
+
logic: [
|
|
160
|
+
'[ ] Expected vs actual output documented',
|
|
161
|
+
'[ ] Minimal reproducing test written before fix',
|
|
162
|
+
'[ ] All boundary conditions tested',
|
|
163
|
+
'[ ] Off-by-one conditions verified',
|
|
164
|
+
'[ ] Shared mutable state eliminated from the bug path',
|
|
165
|
+
],
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const categoryPitfalls: Record<ErrorCategory, string[]> = {
|
|
169
|
+
runtime: [
|
|
170
|
+
'Fixing the symptom (adding a null check at the crash site) without fixing the root cause (why null got there)',
|
|
171
|
+
'Changing multiple things at once — makes it impossible to know which change fixed the bug',
|
|
172
|
+
'Not writing a regression test — the bug will return',
|
|
173
|
+
'Ignoring the stack trace and guessing at the cause',
|
|
174
|
+
],
|
|
175
|
+
type: [
|
|
176
|
+
'Using "as any" or "as Type" to silence TypeScript — masks the real bug',
|
|
177
|
+
'Checking for null in the wrong place — check where the data enters, not where it crashes',
|
|
178
|
+
'Conflating undefined (not set) with null (intentionally empty)',
|
|
179
|
+
],
|
|
180
|
+
async: [
|
|
181
|
+
'Adding await to a non-Promise — causes subtle bugs when the value becomes a resolved Promise accidentally',
|
|
182
|
+
'Using Promise.all when one rejection should not cancel the others — use Promise.allSettled',
|
|
183
|
+
'Catching errors in middleware and not rethrowing — downstream code sees undefined instead of an error',
|
|
184
|
+
],
|
|
185
|
+
performance: [
|
|
186
|
+
'Optimising without measuring first — wastes time on non-bottlenecks',
|
|
187
|
+
'Caching without an eviction strategy — trades performance for a memory leak',
|
|
188
|
+
'Parallelising I/O without limiting concurrency — causes resource exhaustion',
|
|
189
|
+
],
|
|
190
|
+
network: [
|
|
191
|
+
'Debugging CORS on the client — CORS is a server-side configuration problem',
|
|
192
|
+
'Trusting browser error messages for network issues — use curl/mitmproxy for ground truth',
|
|
193
|
+
'Ignoring timeout configuration — 30-second default timeouts hide slow endpoint bugs',
|
|
194
|
+
],
|
|
195
|
+
memory: [
|
|
196
|
+
'Using WeakMap/WeakRef without understanding the GC implications — not a guaranteed fix',
|
|
197
|
+
'Adding .off() listeners in cleanup without matching the exact listener reference — listener remains attached',
|
|
198
|
+
'Assuming garbage collection will clean up large arrays that are still reachable via closure',
|
|
199
|
+
],
|
|
200
|
+
logic: [
|
|
201
|
+
'Fixing the wrong layer — UI shows wrong data because the API returns wrong data, not because the UI is broken',
|
|
202
|
+
'Not isolating the bug with a test before fixing — leads to over-engineering the fix',
|
|
203
|
+
'Trusting console.log output order in async code — use timestamps',
|
|
204
|
+
],
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const categoryRootCauses: Record<ErrorCategory, string[]> = {
|
|
208
|
+
runtime: ['Null/undefined dereference', 'Index out of bounds', 'Missing module export', 'Incorrect function signature', 'Environment variable not set'],
|
|
209
|
+
type: ['API returning different shape than expected', 'Optional field treated as required', 'Union type not narrowed before use', 'JSON.parse result not validated'],
|
|
210
|
+
async: ['Missing await on async function', 'Unhandled Promise rejection', 'Race condition between concurrent operations', 'Event listener attached multiple times'],
|
|
211
|
+
performance: ['N+1 database query', 'Unbounded loop over large dataset', 'Synchronous blocking in event loop', 'Missing index on queried column', 'Large objects allocated in hot path'],
|
|
212
|
+
network: ['CORS misconfiguration', 'Expired TLS certificate', 'DNS resolution failure', 'Firewall blocking the port', 'Incorrect Content-Type header'],
|
|
213
|
+
memory: ['Event listeners not removed on component unmount', 'Closure retaining large object', 'Unbounded cache', 'Circular reference in object graph'],
|
|
214
|
+
logic: ['Off-by-one error in loop bounds', 'Timezone-naive date comparison', 'Wrong operator precedence', 'Mutating shared state across requests', 'Short-circuit evaluation misunderstood'],
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export function plan(task: string, context?: string): AgentPlan {
|
|
218
|
+
const category = detectErrorCategory(task, context);
|
|
219
|
+
const rootCauses = categoryRootCauses[category];
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
agent: 'debugger' as WorkerAgentType,
|
|
223
|
+
task,
|
|
224
|
+
tier: 2,
|
|
225
|
+
approach: categoryApproach[category],
|
|
226
|
+
steps: categorySteps[category],
|
|
227
|
+
checklist: categoryChecklist[category],
|
|
228
|
+
pitfalls: categoryPitfalls[category],
|
|
229
|
+
patterns: [
|
|
230
|
+
'Reproduce-Isolate-Fix loop',
|
|
231
|
+
'Scientific method (hypothesis → test → conclusion)',
|
|
232
|
+
'Rubber duck debugging',
|
|
233
|
+
'Binary search debugging (git bisect)',
|
|
234
|
+
...rootCauses.map(c => `Root cause: ${c}`),
|
|
235
|
+
],
|
|
236
|
+
duration_estimate: category === 'performance' || category === 'memory' ? '2-6 hours' : '30 minutes - 3 hours',
|
|
237
|
+
};
|
|
238
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { AgentPlan, WorkerAgentType } from '../types.js';
|
|
2
|
+
|
|
3
|
+
type DeployTarget = 'docker' | 'kubernetes' | 'serverless' | 'paas' | 'general';
|
|
4
|
+
|
|
5
|
+
function detectTarget(task: string, context?: string): DeployTarget {
|
|
6
|
+
const combined = (task + ' ' + (context ?? '')).toLowerCase();
|
|
7
|
+
if (combined.includes('kubernetes') || combined.includes('k8s') || combined.includes('helm') || combined.includes('pod')) return 'kubernetes';
|
|
8
|
+
if (combined.includes('lambda') || combined.includes('serverless') || combined.includes('cloud function') || combined.includes('faas')) return 'serverless';
|
|
9
|
+
if (combined.includes('heroku') || combined.includes('render') || combined.includes('railway') || combined.includes('fly.io') || combined.includes('paas')) return 'paas';
|
|
10
|
+
if (combined.includes('docker') || combined.includes('container') || combined.includes('compose')) return 'docker';
|
|
11
|
+
return 'general';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const targetApproach: Record<DeployTarget, string> = {
|
|
15
|
+
docker: 'Multi-stage Dockerfile to minimise image size, docker-compose for local development with dependent services, GitHub Actions for build-push-deploy pipeline.',
|
|
16
|
+
kubernetes: 'Helm chart per service, resource requests/limits, liveness/readiness probes, HorizontalPodAutoscaler, ConfigMap and Secret management, Ingress with TLS.',
|
|
17
|
+
serverless: 'Serverless Framework or AWS SAM for IaC, per-function IAM roles with least privilege, environment-specific stages, DLQ for failed invocations.',
|
|
18
|
+
paas: 'Environment variables in the platform console (never committed), Procfile or start command, health check route, deployment hooks for migrations.',
|
|
19
|
+
general: 'Containerise with Docker for environment parity. Use a CI/CD pipeline for automated testing and deployment. Manage secrets with a vault, not environment files.',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function plan(task: string, context?: string): AgentPlan {
|
|
23
|
+
const target = detectTarget(task, context);
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
agent: 'devops' as WorkerAgentType,
|
|
27
|
+
task,
|
|
28
|
+
tier: 3,
|
|
29
|
+
approach: targetApproach[target],
|
|
30
|
+
steps: [
|
|
31
|
+
'Write a multi-stage Dockerfile: stage 1 (builder) installs deps and compiles, stage 2 (runtime) copies only the built artefact',
|
|
32
|
+
'Set a non-root USER in the Dockerfile runtime stage',
|
|
33
|
+
'Pin the base image to a specific digest, not :latest',
|
|
34
|
+
'Add .dockerignore to exclude node_modules, .git, and secrets',
|
|
35
|
+
'Write docker-compose.yml for local development with all dependent services (DB, Redis, etc.)',
|
|
36
|
+
'Add health checks to compose services so the app only starts when dependencies are ready',
|
|
37
|
+
'Write the CI pipeline: lint → test → build image → push to registry → deploy',
|
|
38
|
+
'Use separate environment stages: development, staging, production',
|
|
39
|
+
'Store secrets in a vault (AWS Secrets Manager, HashiCorp Vault, GitHub Actions secrets) — never in the repo',
|
|
40
|
+
'Configure rolling deployment or blue/green to achieve zero-downtime deploys',
|
|
41
|
+
'Add liveness probe (is the process alive?) and readiness probe (can it serve traffic?) to the container',
|
|
42
|
+
'Set CPU and memory resource requests and limits',
|
|
43
|
+
'Configure structured logging to stdout — let the orchestrator collect it',
|
|
44
|
+
'Add a /health endpoint that checks DB connectivity and returns 200 or 503',
|
|
45
|
+
'Set up alerting on error rate, latency p95, and pod restart count',
|
|
46
|
+
],
|
|
47
|
+
checklist: [
|
|
48
|
+
'[ ] Dockerfile is multi-stage — runtime image contains no build tools or source code',
|
|
49
|
+
'[ ] Base image pinned to a specific SHA or version tag, not :latest',
|
|
50
|
+
'[ ] Container runs as a non-root user',
|
|
51
|
+
'[ ] .dockerignore excludes node_modules, .git, .env, and secrets',
|
|
52
|
+
'[ ] All secrets loaded from environment variables or a vault — never baked into the image',
|
|
53
|
+
'[ ] CI pipeline runs lint and tests before building the image',
|
|
54
|
+
'[ ] CI pipeline fails the deploy if tests fail',
|
|
55
|
+
'[ ] Docker image scanned for vulnerabilities (trivy or snyk) in CI',
|
|
56
|
+
'[ ] Deployment uses rolling update or blue/green — no downtime on deploy',
|
|
57
|
+
'[ ] Liveness and readiness probes configured',
|
|
58
|
+
'[ ] Resource requests and limits set on all containers',
|
|
59
|
+
'[ ] Structured JSON logging to stdout',
|
|
60
|
+
'[ ] Log retention policy set (no unlimited growth)',
|
|
61
|
+
'[ ] Health check endpoint returns 503 when dependencies are unhealthy',
|
|
62
|
+
'[ ] Alerts configured for error rate > 1% and p95 latency > SLO',
|
|
63
|
+
'[ ] Runbook written for on-call responders',
|
|
64
|
+
],
|
|
65
|
+
pitfalls: [
|
|
66
|
+
'Using :latest as the base image tag — breaks reproducibility when the upstream image changes',
|
|
67
|
+
'Running the container as root — a container escape becomes a root host compromise',
|
|
68
|
+
'Baking secrets into the image via ENV or COPY — secrets are visible in docker history',
|
|
69
|
+
'Not adding health checks to compose — the app starts before the database is ready, crashes on first query',
|
|
70
|
+
'Building the full Docker image in CI without layer caching — 10-minute builds for a one-line change',
|
|
71
|
+
'Deploying directly to production without a staging environment test — no safety net',
|
|
72
|
+
'Not setting resource limits — a memory leak can starve all other pods on the node',
|
|
73
|
+
'Using docker-compose in production — lacks self-healing, scheduling, and scaling capabilities',
|
|
74
|
+
],
|
|
75
|
+
patterns: [
|
|
76
|
+
'Multi-stage Docker build (minimise image size)',
|
|
77
|
+
'Blue/Green deployment (zero-downtime swap)',
|
|
78
|
+
'Canary release (route small percentage to new version)',
|
|
79
|
+
'GitOps (declarative infra state tracked in git, applied by Flux/ArgoCD)',
|
|
80
|
+
'Infrastructure as Code (Terraform, Pulumi, CDK)',
|
|
81
|
+
'Immutable infrastructure (replace, never patch in place)',
|
|
82
|
+
'Twelve-Factor App methodology',
|
|
83
|
+
],
|
|
84
|
+
duration_estimate: '1-2 days',
|
|
85
|
+
};
|
|
86
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { AgentPlan, WorkerAgentType } from '../types.js';
|
|
2
|
+
|
|
3
|
+
type FrontendType = 'component' | 'page' | 'form' | 'data-display' | 'general';
|
|
4
|
+
|
|
5
|
+
function detectFrontendType(task: string, context?: string): FrontendType {
|
|
6
|
+
const combined = (task + ' ' + (context ?? '')).toLowerCase();
|
|
7
|
+
if (combined.includes('form') || combined.includes('input') || combined.includes('submit') || combined.includes('validation')) return 'form';
|
|
8
|
+
if (combined.includes('table') || combined.includes('list') || combined.includes('chart') || combined.includes('dashboard') || combined.includes('grid')) return 'data-display';
|
|
9
|
+
if (combined.includes('page') || combined.includes('route') || combined.includes('view') || combined.includes('screen')) return 'page';
|
|
10
|
+
if (combined.includes('component') || combined.includes('button') || combined.includes('modal') || combined.includes('dialog') || combined.includes('dropdown')) return 'component';
|
|
11
|
+
return 'general';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const typeApproach: Record<FrontendType, string> = {
|
|
15
|
+
component: 'Define the Props interface first. Implement the static presentational render before adding state. Extract sub-components when the render method exceeds 50 JSX lines. Test each state independently.',
|
|
16
|
+
page: 'Design the page data requirements (what APIs to call), implement data fetching with loading/error/empty states, compose from smaller components. Handle navigation state and deep linking.',
|
|
17
|
+
form: 'Use a form library (react-hook-form or Formik). Define the schema with Zod or Yup. Show inline validation errors. Handle submission loading state and server errors. Ensure keyboard-accessible.',
|
|
18
|
+
'data-display': 'Fetch data with pagination or virtual scrolling for large datasets. Show skeleton loaders. Handle empty state with a clear call-to-action. Make columns resizable and sortable if applicable.',
|
|
19
|
+
general: 'Design the component tree top-down. Define props interfaces before writing JSX. Add loading, error, and empty states to every data-dependent component.',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function plan(task: string, context?: string): AgentPlan {
|
|
23
|
+
const frontendType = detectFrontendType(task, context);
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
agent: 'frontend' as WorkerAgentType,
|
|
27
|
+
task,
|
|
28
|
+
tier: 2,
|
|
29
|
+
approach: typeApproach[frontendType],
|
|
30
|
+
steps: [
|
|
31
|
+
'Define the Props interface with JSDoc on every prop, including optional vs required',
|
|
32
|
+
'Identify and define any local state the component manages',
|
|
33
|
+
'Sketch the component tree — identify which parts should be extracted as sub-components',
|
|
34
|
+
'Implement the static happy-path render with hardcoded sample data',
|
|
35
|
+
'Replace sample data with props and verify TypeScript types',
|
|
36
|
+
'Add loading state — use a skeleton loader, not a spinner for layout-heavy content',
|
|
37
|
+
'Add error state — show a user-friendly message with a retry action',
|
|
38
|
+
'Add empty state — show a meaningful prompt when there is no data',
|
|
39
|
+
'Add useEffect for data fetching or subscriptions, with proper dependency array',
|
|
40
|
+
'Implement event handlers and form submission logic',
|
|
41
|
+
'Add ARIA roles, labels, and keyboard navigation for interactive elements',
|
|
42
|
+
'Test with keyboard only — tab order must be logical',
|
|
43
|
+
'Apply responsive CSS: mobile-first, then tablet (768px), then desktop (1280px) breakpoints',
|
|
44
|
+
'Write render tests covering loading, error, empty, and data states',
|
|
45
|
+
'Profile with React DevTools and memo/useMemo only where profiling shows a real regression',
|
|
46
|
+
],
|
|
47
|
+
checklist: [
|
|
48
|
+
'[ ] Props interface fully typed and exported',
|
|
49
|
+
'[ ] Default props specified for optional props with sensible defaults',
|
|
50
|
+
'[ ] Loading state uses skeleton loader matching the content layout',
|
|
51
|
+
'[ ] Error state shows user-friendly message with retry button',
|
|
52
|
+
'[ ] Empty state shows message and call-to-action',
|
|
53
|
+
'[ ] No useEffect with stale closure (dependency array complete)',
|
|
54
|
+
'[ ] No state for derived data — compute it from props/state on render',
|
|
55
|
+
'[ ] Interactive elements are keyboard operable',
|
|
56
|
+
'[ ] All images have alt text',
|
|
57
|
+
'[ ] Form inputs have associated <label> elements',
|
|
58
|
+
'[ ] Color is not the only means of conveying information',
|
|
59
|
+
'[ ] Focus is managed correctly when modals open/close',
|
|
60
|
+
'[ ] Component works at 320px mobile width',
|
|
61
|
+
'[ ] Component works at 1440px desktop width',
|
|
62
|
+
'[ ] No inline styles — use CSS modules or styled-components',
|
|
63
|
+
'[ ] Render tests written for all significant states',
|
|
64
|
+
],
|
|
65
|
+
pitfalls: [
|
|
66
|
+
'Calling setState inside useEffect with the setState function in the dependency array — infinite re-render loop',
|
|
67
|
+
'Forgetting the key prop on list items — React silently mismatches DOM elements during reconciliation',
|
|
68
|
+
'Storing derived data (e.g., filtered list) in state instead of computing it on each render',
|
|
69
|
+
'Using array index as key when the list can be reordered — causes incorrect component reuse',
|
|
70
|
+
'Making components too generic too early — premature abstraction adds props nobody uses',
|
|
71
|
+
'Not handling the loading state — a blank flash before data arrives breaks perceived performance',
|
|
72
|
+
'useCallback / useMemo without profiling first — adds overhead for no measurable gain',
|
|
73
|
+
'Forgetting to clean up event listeners, timers, and subscriptions in useEffect return function',
|
|
74
|
+
],
|
|
75
|
+
patterns: [
|
|
76
|
+
'Compound component pattern (parent shares state with slotted children)',
|
|
77
|
+
'Controlled component pattern (props drive state, events propagate up)',
|
|
78
|
+
'Render props pattern (for cross-cutting component logic)',
|
|
79
|
+
'Custom hook extraction (move complex effect logic out of the component)',
|
|
80
|
+
'Container / Presenter split (data fetching vs rendering separation)',
|
|
81
|
+
'Skeleton loader pattern (avoid layout shift on load)',
|
|
82
|
+
],
|
|
83
|
+
duration_estimate: frontendType === 'page' ? '4-8 hours' : '2-4 hours',
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { AgentPlan, WorkerAgentType } from '../types.js';
|
|
2
|
+
|
|
3
|
+
type MigrationType = 'schema' | 'data' | 'platform' | 'zero-downtime' | 'general';
|
|
4
|
+
|
|
5
|
+
function detectMigrationType(task: string, context?: string): MigrationType {
|
|
6
|
+
const combined = (task + ' ' + (context ?? '')).toLowerCase();
|
|
7
|
+
if (combined.includes('zero downtime') || combined.includes('blue-green') || combined.includes('rolling') || combined.includes('live migration')) return 'zero-downtime';
|
|
8
|
+
if (combined.includes('data migration') || combined.includes('backfill') || combined.includes('etl') || combined.includes('transform data')) return 'data';
|
|
9
|
+
if (combined.includes('platform') || combined.includes('cloud') || combined.includes('aws') || combined.includes('gcp') || combined.includes('azure') || combined.includes('move')) return 'platform';
|
|
10
|
+
if (combined.includes('schema') || combined.includes('column') || combined.includes('table') || combined.includes('database') || combined.includes('alter')) return 'schema';
|
|
11
|
+
return 'general';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const typeApproach: Record<MigrationType, string> = {
|
|
15
|
+
schema: 'Expand-Migrate-Contract pattern: first add new columns as nullable (backward compatible), then backfill, then add constraints, then remove old columns. Each phase is a separate deployment.',
|
|
16
|
+
data: 'Write idempotent backfill scripts that can be re-run safely. Process in batches of 1000-10000 rows to avoid locking. Verify row counts before and after. Keep the original data until verified.',
|
|
17
|
+
platform: 'Run old and new platforms in parallel. Migrate traffic gradually (10% → 50% → 100%). Maintain rollback capability at each step. Verify data consistency between platforms before cutover.',
|
|
18
|
+
'zero-downtime': 'Decouple schema changes from code changes. Make schema additive first. Deploy code that supports both old and new schema. Then migrate schema. Then deploy code that requires new schema only.',
|
|
19
|
+
general: 'Always take a backup before migrating. Test the migration on a staging environment with production-volume data. Plan and rehearse the rollback procedure before starting.',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const typeSteps: Record<MigrationType, string[]> = {
|
|
23
|
+
schema: [
|
|
24
|
+
'Take a full database backup and verify it is restorable',
|
|
25
|
+
'Analyse the table size — migrations on large tables require extra care',
|
|
26
|
+
'Write the expansion migration: add new nullable columns or tables (no data changes)',
|
|
27
|
+
'Deploy the expansion migration to staging and verify with EXPLAIN on common queries',
|
|
28
|
+
'Deploy the expansion migration to production — additive changes are safe and fast',
|
|
29
|
+
'Write the application code that writes to both old and new columns simultaneously',
|
|
30
|
+
'Deploy the dual-write code to production',
|
|
31
|
+
'Write the backfill script: UPDATE new_column = derive(old_column) WHERE new_column IS NULL LIMIT 10000',
|
|
32
|
+
'Run the backfill in batches during low-traffic hours, monitoring DB load',
|
|
33
|
+
'Verify: SELECT COUNT(*) WHERE new_column IS NULL — should return 0',
|
|
34
|
+
'Deploy code that reads from new columns only',
|
|
35
|
+
'Write the contract migration: add NOT NULL constraint, create indexes, drop old columns',
|
|
36
|
+
'Deploy the contract migration to production during a maintenance window',
|
|
37
|
+
'Verify application health and run smoke tests',
|
|
38
|
+
],
|
|
39
|
+
data: [
|
|
40
|
+
'Define the transformation logic and document the expected output for a sample of rows',
|
|
41
|
+
'Write the backfill script as an idempotent operation (re-running it produces the same result)',
|
|
42
|
+
'Test the script on 100 rows in staging and manually verify the output',
|
|
43
|
+
'Measure the script execution time on staging at full data volume',
|
|
44
|
+
'Schedule the production backfill during the lowest-traffic window',
|
|
45
|
+
'Process in batches: use LIMIT + WHERE id > last_processed_id to paginate',
|
|
46
|
+
'Add a progress counter — log every N rows processed',
|
|
47
|
+
'Monitor DB CPU, lock waits, and replication lag during the backfill',
|
|
48
|
+
'Pause the script automatically if replication lag exceeds a threshold',
|
|
49
|
+
'Verify row counts: SELECT COUNT(*) before and after should balance',
|
|
50
|
+
'Spot-check 10-20 randomly selected rows — manual verification of the transformation',
|
|
51
|
+
'Keep the original data in the source columns or a backup table until fully verified',
|
|
52
|
+
'Archive or drop the source data only after a defined hold period (e.g., 30 days)',
|
|
53
|
+
],
|
|
54
|
+
platform: [
|
|
55
|
+
'Document all dependencies of the current platform (databases, queues, external services)',
|
|
56
|
+
'Set up the new platform environment with identical configuration',
|
|
57
|
+
'Migrate all secrets and configuration to the new platform\'s secrets manager',
|
|
58
|
+
'Deploy the application to the new platform and run full integration tests',
|
|
59
|
+
'Set up a data sync from old to new platform (replication or CDC with Debezium)',
|
|
60
|
+
'Route 5% of production traffic to the new platform and monitor error rates',
|
|
61
|
+
'Compare metrics between old and new platform over 24 hours',
|
|
62
|
+
'Increase traffic to 25%, 50%, 75%, 100% with monitoring gates at each step',
|
|
63
|
+
'When at 100%, stop new writes to the old platform and verify replication caught up',
|
|
64
|
+
'Run a final data consistency check between old and new platform',
|
|
65
|
+
'Update DNS/load balancer to point exclusively to new platform',
|
|
66
|
+
'Keep the old platform running for 7 days as a rollback option',
|
|
67
|
+
'Decommission the old platform after the hold period',
|
|
68
|
+
],
|
|
69
|
+
'zero-downtime': [
|
|
70
|
+
'Identify all schema changes needed and classify each as additive (safe) or destructive (requires care)',
|
|
71
|
+
'Phase 1 — Expansion: add new tables and nullable columns without removing anything',
|
|
72
|
+
'Deploy Phase 1 migration — no code change needed, old code still works',
|
|
73
|
+
'Phase 2 — Compatibility code: deploy app code that writes to old and new columns, reads from new if available',
|
|
74
|
+
'Verify Phase 2 is working correctly in staging for 24+ hours',
|
|
75
|
+
'Phase 3 — Backfill: run idempotent backfill to populate new columns from old data',
|
|
76
|
+
'Verify backfill completeness: zero rows with NULL in new columns',
|
|
77
|
+
'Phase 4 — New code: deploy app code that reads exclusively from new columns',
|
|
78
|
+
'Monitor for 24 hours — check error rates and data correctness',
|
|
79
|
+
'Phase 5 — Contract: add NOT NULL constraints, create indexes, drop old columns',
|
|
80
|
+
'Verify final state with integration tests and manual spot-checks',
|
|
81
|
+
'Document the completed migration and update the schema documentation',
|
|
82
|
+
],
|
|
83
|
+
general: [
|
|
84
|
+
'Take a full backup of all data involved in the migration',
|
|
85
|
+
'Verify the backup is restorable by doing a test restore on a separate instance',
|
|
86
|
+
'Write the migration script and test it thoroughly on staging',
|
|
87
|
+
'Test the rollback procedure on staging — confirm you can undo the migration',
|
|
88
|
+
'Calculate the expected execution time at production data volume',
|
|
89
|
+
'Plan the maintenance window if downtime is required',
|
|
90
|
+
'Communicate the migration plan and timeline to stakeholders',
|
|
91
|
+
'Execute the migration and monitor closely',
|
|
92
|
+
'Run smoke tests immediately after migration',
|
|
93
|
+
'Monitor for 24-48 hours before declaring success',
|
|
94
|
+
'Document lessons learned',
|
|
95
|
+
],
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export function plan(task: string, context?: string): AgentPlan {
|
|
99
|
+
const migrationType = detectMigrationType(task, context);
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
agent: 'migration' as WorkerAgentType,
|
|
103
|
+
task,
|
|
104
|
+
tier: 3,
|
|
105
|
+
approach: typeApproach[migrationType],
|
|
106
|
+
steps: typeSteps[migrationType],
|
|
107
|
+
checklist: [
|
|
108
|
+
'[ ] Full backup taken and restore tested before starting',
|
|
109
|
+
'[ ] Migration tested on staging with production data volume',
|
|
110
|
+
'[ ] Rollback procedure written, tested, and rehearsed',
|
|
111
|
+
'[ ] Execution time estimated at production scale',
|
|
112
|
+
'[ ] Stakeholders notified of migration plan and timeline',
|
|
113
|
+
'[ ] Backfill script is idempotent — safe to re-run on failure',
|
|
114
|
+
'[ ] Backfill processes in batches — no single query that locks the whole table',
|
|
115
|
+
'[ ] Replication lag monitored during migration',
|
|
116
|
+
'[ ] Row counts verified before and after migration',
|
|
117
|
+
'[ ] Smoke tests pass immediately after migration',
|
|
118
|
+
'[ ] Application metrics (error rate, latency) normal after migration',
|
|
119
|
+
'[ ] Old data retained for a defined hold period before deletion',
|
|
120
|
+
'[ ] Schema documentation updated',
|
|
121
|
+
'[ ] Post-migration review scheduled for 48 hours after cutover',
|
|
122
|
+
],
|
|
123
|
+
pitfalls: [
|
|
124
|
+
'Running ALTER TABLE on a large table without ALGORITHM=INPLACE or pg_rewrite — locks the table for minutes and causes downtime',
|
|
125
|
+
'Not testing the rollback — every migration plan needs a verified rollback procedure',
|
|
126
|
+
'Backfilling without batching — a single UPDATE affecting millions of rows holds a table lock for minutes',
|
|
127
|
+
'Migrating production without staging validation — staging exists for this purpose',
|
|
128
|
+
'Not monitoring replication lag during the migration — a lagging replica causes stale reads',
|
|
129
|
+
'Removing the old columns before the application is fully migrated to the new columns',
|
|
130
|
+
'Skipping the data verification step — corrupted data may not surface for days',
|
|
131
|
+
'Under-estimating the time at production data volume — test with realistic row counts',
|
|
132
|
+
],
|
|
133
|
+
patterns: [
|
|
134
|
+
'Expand-Migrate-Contract pattern (safe schema evolution)',
|
|
135
|
+
'Dual-write pattern (write to old and new during transition)',
|
|
136
|
+
'Strangler Fig pattern (gradually replace old system with new)',
|
|
137
|
+
'Blue/Green deployment (parallel environments for zero-downtime cutover)',
|
|
138
|
+
'Change Data Capture (CDC) for live platform migrations',
|
|
139
|
+
'Idempotent migration scripts (safe to re-run)',
|
|
140
|
+
'Feature flag gating (roll out new schema reading gradually)',
|
|
141
|
+
],
|
|
142
|
+
duration_estimate: '2-5 days',
|
|
143
|
+
};
|
|
144
|
+
}
|