@jigyasudham/veto 0.8.3 → 1.0.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/README.md +209 -52
- package/dist/agents/executor.js +36 -3
- package/dist/cli.js +246 -7
- package/dist/context/reader.js +113 -0
- package/dist/council/index.js +3 -1
- package/dist/plugins/loader.js +49 -0
- package/dist/router/index.js +2 -2
- package/dist/router/learning-updater.js +45 -1
- package/dist/server.js +478 -14
- package/dist/watcher/index.js +77 -0
- package/dist/workflow/pipeline.js +64 -0
- package/package.json +12 -3
- package/.claude/settings.local.json +0 -9
- package/src/adapters/claude.ts +0 -70
- package/src/adapters/codex.ts +0 -71
- package/src/adapters/gemini.ts +0 -71
- package/src/adapters/index.ts +0 -217
- package/src/agents/development/api.ts +0 -120
- package/src/agents/development/backend.ts +0 -85
- package/src/agents/development/coder.ts +0 -213
- package/src/agents/development/database.ts +0 -83
- package/src/agents/development/debugger.ts +0 -238
- package/src/agents/development/devops.ts +0 -86
- package/src/agents/development/frontend.ts +0 -85
- package/src/agents/development/migration.ts +0 -144
- package/src/agents/development/performance.ts +0 -144
- package/src/agents/development/refactor.ts +0 -86
- package/src/agents/development/reviewer.ts +0 -268
- package/src/agents/development/tester.ts +0 -151
- package/src/agents/executor.ts +0 -158
- package/src/agents/memory/context-manager.ts +0 -171
- package/src/agents/memory/decision-logger.ts +0 -160
- package/src/agents/memory/knowledge-base.ts +0 -124
- package/src/agents/memory/pattern-learner.ts +0 -143
- package/src/agents/memory/project-mapper.ts +0 -118
- package/src/agents/quality/accessibility.ts +0 -99
- package/src/agents/quality/code-quality.ts +0 -115
- package/src/agents/quality/compatibility.ts +0 -58
- package/src/agents/quality/documentation.ts +0 -105
- package/src/agents/quality/error-handling.ts +0 -96
- package/src/agents/research/competitor-analyzer.ts +0 -45
- package/src/agents/research/cost-analyzer.ts +0 -54
- package/src/agents/research/estimator.ts +0 -60
- package/src/agents/research/ethics-bias.ts +0 -113
- package/src/agents/research/researcher.ts +0 -114
- package/src/agents/research/risk-assessor.ts +0 -63
- package/src/agents/research/tech-advisor.ts +0 -55
- package/src/agents/security/auth.ts +0 -287
- package/src/agents/security/dependency-audit.ts +0 -337
- package/src/agents/security/penetration.ts +0 -262
- package/src/agents/security/privacy.ts +0 -285
- package/src/agents/security/scanner.ts +0 -322
- package/src/agents/security/secrets.ts +0 -249
- package/src/agents/types.ts +0 -66
- package/src/agents/workflow/automation.ts +0 -59
- package/src/agents/workflow/file-manager.ts +0 -52
- package/src/agents/workflow/git-agent.ts +0 -55
- package/src/agents/workflow/reporter.ts +0 -51
- package/src/agents/workflow/search-agent.ts +0 -40
- package/src/agents/workflow/task-coordinator.ts +0 -41
- package/src/agents/workflow/task-planner.ts +0 -47
- package/src/cli.ts +0 -204
- package/src/council/decision-engine.ts +0 -171
- package/src/council/devil-advocate.ts +0 -116
- package/src/council/index.ts +0 -44
- package/src/council/lead-developer.ts +0 -118
- package/src/council/legal-compliance.ts +0 -152
- package/src/council/product-manager.ts +0 -102
- package/src/council/security.ts +0 -172
- package/src/council/system-architect.ts +0 -132
- package/src/council/types.ts +0 -33
- package/src/council/ux-designer.ts +0 -121
- package/src/memory/local.ts +0 -305
- package/src/memory/schema.ts +0 -174
- package/src/memory/sync.ts +0 -274
- package/src/router/complexity-scorer.ts +0 -96
- package/src/router/context-compressor.ts +0 -74
- package/src/router/index.ts +0 -60
- package/src/router/learning-updater.ts +0 -271
- package/src/router/model-selector.ts +0 -83
- package/src/router/rate-monitor.ts +0 -103
- package/src/server.ts +0 -1038
- package/src/skills/development/skill-api-design.ts +0 -329
- package/src/skills/development/skill-auth.ts +0 -271
- package/src/skills/development/skill-ci-cd.ts +0 -0
- package/src/skills/development/skill-crud.ts +0 -209
- 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 +0 -323
- package/src/skills/intelligence/skill-complexity-score.ts +0 -69
- package/src/skills/intelligence/skill-cost-track.ts +0 -39
- package/src/skills/intelligence/skill-learning-loop.ts +0 -69
- package/src/skills/intelligence/skill-pattern-detect.ts +0 -38
- package/src/skills/intelligence/skill-rate-watch.ts +0 -61
- package/src/skills/memory/skill-context-compress.ts +0 -98
- package/src/skills/memory/skill-cross-sync.ts +0 -104
- package/src/skills/memory/skill-decision-log.ts +0 -119
- package/src/skills/memory/skill-session-restore.ts +0 -59
- package/src/skills/memory/skill-session-save.ts +0 -94
- package/src/skills/quality/skill-accessibility.ts +0 -0
- package/src/skills/quality/skill-code-review.ts +0 -84
- 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 +0 -91
- package/src/skills/quality/skill-test-suite.ts +0 -290
- 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 +0 -20
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
// Product Manager — ship value fast, cut scope ruthlessly
|
|
2
|
-
import type { AgentVote } from './types.js';
|
|
3
|
-
|
|
4
|
-
const BLOCK_RULES: Array<{ pattern: RegExp; reason: string; recommendation: string }> = [
|
|
5
|
-
{
|
|
6
|
-
pattern: /rewrite.{0,20}from.{0,10}scratch/i,
|
|
7
|
-
reason: 'Rewriting from scratch abandons working code and delays users by months.',
|
|
8
|
-
recommendation: 'Incremental refactor using Strangler Fig. Split only when bottleneck is proven.',
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
pattern: /build.{0,20}(our own|custom).{0,20}(framework|orm|database|auth.?system|message.?queue)/i,
|
|
12
|
-
reason: 'Building custom infrastructure has a 12+ month cost before it provides value.',
|
|
13
|
-
recommendation: 'Use battle-tested existing solutions. Build what differentiates you, not plumbing.',
|
|
14
|
-
},
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
const WARN_RULES: Array<{ pattern: RegExp; concern: string; recommendation: string }> = [
|
|
18
|
-
{
|
|
19
|
-
pattern: /\bmicroservice/i,
|
|
20
|
-
concern: 'Microservices add 10x operational complexity. Justified only at Netflix/Amazon scale.',
|
|
21
|
-
recommendation: 'Start modular monolith. Extract services only when a specific bottleneck demands it.',
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
pattern: /enterprise.{0,20}(grade|pattern|architecture|solution)/i,
|
|
25
|
-
concern: 'Enterprise patterns optimize for 10,000-person orgs, not fast-moving products.',
|
|
26
|
-
recommendation: 'Ship the simple version. Add enterprise complexity when customers pay for it.',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
pattern: /future.{0,20}proof|build.{0,20}for.{0,20}(scale|growth|million)/i,
|
|
30
|
-
concern: 'Optimizing for imaginary future scale delays value to users you have today.',
|
|
31
|
-
recommendation: "YAGNI. Build for 10x current scale, not 1000x. You'll know when you need more.",
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
pattern: /\bperfect\b|\bflawless\b|fully.{0,10}generic|completely.{0,10}flexible/i,
|
|
35
|
-
concern: 'Perfect is the enemy of shipped. What is the minimum version that solves the problem?',
|
|
36
|
-
recommendation: 'Define a specific "done" criterion. Timebox perfection work to 20% of total.',
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
pattern: /build.{0,20}(framework|platform|engine|layer|system)\b.{0,20}first/i,
|
|
40
|
-
concern: 'Building infrastructure before product delays user value. Products fund platforms.',
|
|
41
|
-
recommendation: 'Build product features. Extract the framework only when the pattern is proven.',
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
pattern: /abstrac|generic.{0,20}(solution|framework|wrapper|handler)/i,
|
|
45
|
-
concern: 'Premature abstraction bets on requirements that may never come.',
|
|
46
|
-
recommendation: 'Three concrete implementations before extracting an abstraction.',
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
pattern: /add.{0,20}feature.{0,30}(not.{0,10}ask|nobody.{0,10}request|just.{0,10}in.{0,10}case)/i,
|
|
50
|
-
concern: 'Building unrequested features is scope creep. Validate demand first.',
|
|
51
|
-
recommendation: 'Ship what was asked. Add features after user feedback confirms demand.',
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
pattern: /v2|v3|version\s+[23]/i,
|
|
55
|
-
concern: 'Designing v2/v3 before v1 ships is a classic focus trap.',
|
|
56
|
-
recommendation: 'Ship v1. Learn from real users. Then plan v2 with real data.',
|
|
57
|
-
},
|
|
58
|
-
];
|
|
59
|
-
|
|
60
|
-
const TRIVIAL = /^(rename|fix typo|reorder|reformat|format|update comment|add comment)\b/i;
|
|
61
|
-
|
|
62
|
-
export function analyze(task: string): AgentVote {
|
|
63
|
-
if (TRIVIAL.test(task.trim())) {
|
|
64
|
-
return { verdict: 'approve', reason: 'Trivial change — no product concerns.', concerns: [] };
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const blocks: Array<{ reason: string; recommendation: string }> = [];
|
|
68
|
-
const concerns: string[] = [];
|
|
69
|
-
const recommendations: string[] = [];
|
|
70
|
-
|
|
71
|
-
for (const rule of BLOCK_RULES) {
|
|
72
|
-
if (rule.pattern.test(task)) {
|
|
73
|
-
blocks.push({ reason: rule.reason, recommendation: rule.recommendation });
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
for (const rule of WARN_RULES) {
|
|
77
|
-
if (rule.pattern.test(task)) {
|
|
78
|
-
concerns.push(rule.concern);
|
|
79
|
-
recommendations.push(rule.recommendation);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (blocks.length > 0) {
|
|
84
|
-
return {
|
|
85
|
-
verdict: 'block',
|
|
86
|
-
reason: blocks[0].reason,
|
|
87
|
-
concerns: blocks.slice(1).map(b => b.reason),
|
|
88
|
-
recommendation: blocks.map(b => b.recommendation).join(' | '),
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (concerns.length > 0) {
|
|
93
|
-
return {
|
|
94
|
-
verdict: 'warn',
|
|
95
|
-
reason: `${concerns.length} product risk${concerns.length > 1 ? 's' : ''} — scope or complexity concern.`,
|
|
96
|
-
concerns,
|
|
97
|
-
recommendation: recommendations[0],
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return { verdict: 'approve', reason: 'Reasonable scope. Ship it.', concerns: [] };
|
|
102
|
-
}
|
package/src/council/security.ts
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
// Security — threat modeling, attack surface analysis, auth weaknesses, CVE patterns
|
|
2
|
-
import type { AgentVote } from './types.js';
|
|
3
|
-
|
|
4
|
-
const BLOCK_RULES: Array<{ pattern: RegExp; reason: string; recommendation: string }> = [
|
|
5
|
-
{
|
|
6
|
-
pattern: /(no.{0,25}rate.?limit|(auth|login|password|signin|otp|2fa|token|reset).{0,50}no.{0,20}rate.?limit|no.{0,25}rate.?limit.{0,50}(auth|login|password|signin|otp|2fa))/i,
|
|
7
|
-
reason: 'Auth endpoint without rate limiting is wide open to brute-force and credential stuffing.',
|
|
8
|
-
recommendation: 'Rate limit: 5 attempts / 15 min / IP. Exponential backoff. Lock account after 10 failures.',
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
pattern: /jwt.{0,35}(no|without|missing).{0,20}expir|token.{0,20}never.{0,15}expir/i,
|
|
12
|
-
reason: 'JWTs without expiry are permanent access tokens — a stolen token never becomes invalid.',
|
|
13
|
-
recommendation: 'Set JWT exp to 15 min. Issue refresh tokens in httpOnly, Secure, SameSite=Strict cookies.',
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
pattern: /localStorage.{0,30}(token|jwt|session|auth|secret)|(token|jwt|session|auth|secret).{0,30}localStorage/i,
|
|
17
|
-
reason: 'Tokens in localStorage are readable by any script — XSS vulnerability gives full account takeover.',
|
|
18
|
-
recommendation: 'Store tokens only in httpOnly Secure SameSite=Strict cookies. Never localStorage.',
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
pattern: /no.{0,20}csrf|skip.{0,20}csrf|disable.{0,20}csrf|without.{0,20}csrf/i,
|
|
22
|
-
reason: 'Missing CSRF protection enables cross-site request forgery — attackers can act as authenticated users.',
|
|
23
|
-
recommendation: 'Use CSRF tokens for form submissions. Set SameSite=Strict on session cookies as baseline.',
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
pattern: /run.{0,20}(as\s+)?root|user\s+root.{0,20}(docker|container|image)/i,
|
|
27
|
-
reason: 'Running containers as root means any exploit has full host access.',
|
|
28
|
-
recommendation: 'Add `USER 1001` in Dockerfile. Use rootless containers. Drop all capabilities.',
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
pattern: /admin.{0,35}(route|endpoint|panel|api).{0,35}(no|without|skip|missing).{0,20}auth/i,
|
|
32
|
-
reason: 'Admin routes without authentication check expose privileged operations to any unauthenticated caller.',
|
|
33
|
-
recommendation: 'Guard all admin routes with both authentication AND role/permission authorization check.',
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
pattern: /\b(mass.?assign|accept.{0,20}(all|any).{0,20}(field|body|param|input))\b/i,
|
|
37
|
-
reason: 'Mass assignment lets attackers inject internal fields (isAdmin: true) through the request body.',
|
|
38
|
-
recommendation: 'Whitelist allowed fields explicitly. Never spread req.body into DB operations.',
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
pattern: /\.\.\/|\.\.\\|path.{0,20}traversal|(file|path).{0,20}(user|input|param).{0,20}(read|open|access)/i,
|
|
42
|
-
reason: 'Path traversal vulnerability — attacker can read arbitrary server files by manipulating path input.',
|
|
43
|
-
recommendation: 'Use path.resolve() and verify result starts with your allowed base directory.',
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
pattern: /deserializ.{0,30}(user|external|untrusted|input)/i,
|
|
47
|
-
reason: 'Deserializing untrusted data enables remote code execution via gadget chains.',
|
|
48
|
-
recommendation: 'Never deserialize untrusted data. Use JSON.parse() with schema validation (zod).',
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
pattern: /xml.{0,30}(user|input|external).{0,30}(parse|process)/i,
|
|
52
|
-
reason: 'Parsing user-supplied XML without XXE protection enables XML External Entity injection.',
|
|
53
|
-
recommendation: 'Disable external entity processing in your XML parser. Prefer JSON over XML for APIs.',
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
pattern: /\bshell\b.{0,30}(user|input|param)|exec\s*\(.{0,30}(req\.|input|param)/i,
|
|
57
|
-
reason: 'Passing user input to shell commands enables OS command injection — full server compromise.',
|
|
58
|
-
recommendation: 'Use execFile() with args as array. Never concatenate user input into shell commands.',
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
pattern: /no.{0,20}(auth|authentication|authorization).{0,30}(internal|service.?to.?service|microservice)/i,
|
|
62
|
-
reason: 'Service-to-service calls without auth allows any internal service to impersonate another.',
|
|
63
|
-
recommendation: 'Use mutual TLS or service tokens for internal API calls. Never trust internal network alone.',
|
|
64
|
-
},
|
|
65
|
-
];
|
|
66
|
-
|
|
67
|
-
const WARN_RULES: Array<{ pattern: RegExp; concern: string; recommendation: string }> = [
|
|
68
|
-
{
|
|
69
|
-
pattern: /no.{0,25}(content.?security.?policy|\bcsp\b)/i,
|
|
70
|
-
concern: 'Missing Content-Security-Policy header — no browser-level XSS mitigation.',
|
|
71
|
-
recommendation: "Set CSP: default-src 'self'; script-src 'self'. Use helmet.js for Express.",
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
pattern: /verbose.{0,20}error|stack.?trace.{0,25}(user|client|return|response|send)/i,
|
|
75
|
-
concern: 'Verbose error messages expose file paths, library versions, and stack traces to attackers.',
|
|
76
|
-
recommendation: 'Log full errors server-side only. Return generic messages to clients.',
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
pattern: /no.{0,20}(audit|security).{0,15}log/i,
|
|
80
|
-
concern: 'No security audit log — impossible to detect or investigate breaches after the fact.',
|
|
81
|
-
recommendation: 'Log: auth events, admin actions, data exports, permission denials, with IP + user + timestamp.',
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
pattern: /no.{0,20}(dependency|package|npm|pip).{0,20}(audit|scan|update)/i,
|
|
85
|
-
concern: 'Unaudited dependencies may contain known CVEs actively exploited in the wild.',
|
|
86
|
-
recommendation: 'Run npm audit / snyk in CI pipeline. Block builds with critical severity CVEs.',
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
pattern: /no.{0,20}(payload|body|request).{0,20}(size|limit|max)/i,
|
|
90
|
-
concern: 'No payload size limit — attackers can exhaust server memory with large request bodies.',
|
|
91
|
-
recommendation: 'Set body size limit (1MB JSON, 10MB uploads). Return 413 on excess. Use streaming for large files.',
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
pattern: /\bregex\b.{0,30}(user|input|param|untrusted)/i,
|
|
95
|
-
concern: 'Complex regex on user input can cause ReDoS — catastrophic backtracking is a DoS vector.',
|
|
96
|
-
recommendation: 'Test regex with ReDoS checker (vuln-regex-detector). Set match timeout for user input.',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
pattern: /server.?version|x-powered-by|expose.{0,20}(version|framework)/i,
|
|
100
|
-
concern: 'Disclosing server/framework version in headers helps attackers target known CVEs.',
|
|
101
|
-
recommendation: 'Remove X-Powered-By. Set Server: header to empty string. Use helmet.js.',
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
pattern: /upload.{0,30}(any|all|every).{0,20}(type|extension|format|file)/i,
|
|
105
|
-
concern: 'Accepting any file type enables upload of malicious executables or web shells.',
|
|
106
|
-
recommendation: 'Whitelist allowed MIME types. Validate magic bytes (not extension). Scan with ClamAV.',
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
pattern: /\bidor\b|direct.{0,20}object.{0,20}ref|user.?id.{0,20}(param|query|url|path)/i,
|
|
110
|
-
concern: 'Potential IDOR — user can access other users\' resources by changing an ID in the request.',
|
|
111
|
-
recommendation: 'Always verify ownership: resource.userId === req.user.id before returning/mutating.',
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
pattern: /compare.{0,20}(secret|token|hash|hmac|signature|password).{0,20}===|===.{0,20}(secret|token|hmac)/i,
|
|
115
|
-
concern: 'String === comparison of secrets is vulnerable to timing attacks.',
|
|
116
|
-
recommendation: 'Use crypto.timingSafeEqual() for all secret and HMAC comparisons.',
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
pattern: /no.{0,20}hsts|http.{0,20}(only|no.?https)/i,
|
|
120
|
-
concern: 'Without HSTS, browsers may connect over HTTP — credentials can be intercepted.',
|
|
121
|
-
recommendation: 'Set HSTS: max-age=31536000; includeSubDomains; preload. Redirect all HTTP to HTTPS.',
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
pattern: /secret.{0,20}(env|environment|config).{0,20}(log|print|console|output)/i,
|
|
125
|
-
concern: 'Logging secrets or config values leaks credentials to anyone with log access.',
|
|
126
|
-
recommendation: 'Never log secrets. Redact sensitive fields in structured logs. Audit log pipelines.',
|
|
127
|
-
},
|
|
128
|
-
];
|
|
129
|
-
|
|
130
|
-
const TRIVIAL = /^(rename|fix typo|reorder|reformat|format|update comment|add comment)\b/i;
|
|
131
|
-
|
|
132
|
-
export function analyze(task: string): AgentVote {
|
|
133
|
-
if (TRIVIAL.test(task.trim())) {
|
|
134
|
-
return { verdict: 'approve', reason: 'Trivial change — no security concerns.', concerns: [] };
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const blocks: Array<{ reason: string; recommendation: string }> = [];
|
|
138
|
-
const concerns: string[] = [];
|
|
139
|
-
const recommendations: string[] = [];
|
|
140
|
-
|
|
141
|
-
for (const rule of BLOCK_RULES) {
|
|
142
|
-
if (rule.pattern.test(task)) {
|
|
143
|
-
blocks.push({ reason: rule.reason, recommendation: rule.recommendation });
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
for (const rule of WARN_RULES) {
|
|
147
|
-
if (rule.pattern.test(task)) {
|
|
148
|
-
concerns.push(rule.concern);
|
|
149
|
-
recommendations.push(rule.recommendation);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (blocks.length > 0) {
|
|
154
|
-
return {
|
|
155
|
-
verdict: 'block',
|
|
156
|
-
reason: blocks[0].reason,
|
|
157
|
-
concerns: blocks.slice(1).map(b => b.reason),
|
|
158
|
-
recommendation: blocks.map(b => b.recommendation).join(' | '),
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (concerns.length > 0) {
|
|
163
|
-
return {
|
|
164
|
-
verdict: 'warn',
|
|
165
|
-
reason: `${concerns.length} security concern${concerns.length > 1 ? 's' : ''} — threat model flagged issues.`,
|
|
166
|
-
concerns,
|
|
167
|
-
recommendation: recommendations[0],
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return { verdict: 'approve', reason: 'No security threats identified in threat model.', concerns: [] };
|
|
172
|
-
}
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
// System Architect — scalability, failure modes, structural integrity
|
|
2
|
-
import type { AgentVote } from './types.js';
|
|
3
|
-
|
|
4
|
-
const BLOCK_RULES: Array<{ pattern: RegExp; reason: string; recommendation: string }> = [
|
|
5
|
-
{
|
|
6
|
-
pattern: /\bdrop\s+table\b/i,
|
|
7
|
-
reason: 'DROP TABLE is irreversible. No rollback possible after execution.',
|
|
8
|
-
recommendation: 'Write a down-migration. Verify backup. Test on staging. Run in maintenance window.',
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
pattern: /\btruncate\b/i,
|
|
12
|
-
reason: 'TRUNCATE deletes all rows instantly — no transaction, no rollback.',
|
|
13
|
-
recommendation: 'Use DELETE with WHERE in a transaction. Backup first. Verify on staging.',
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
pattern: /\bdelete\s+from\b(?!.*where)/i,
|
|
17
|
-
reason: 'DELETE without WHERE clause wipes the entire table.',
|
|
18
|
-
recommendation: 'Always add a WHERE clause. Wrap in transaction. Test on staging.',
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
pattern: /sqlite.{0,50}(concurrent|multi.?user|high.?traffic|production|scale)/i,
|
|
22
|
-
reason: 'SQLite serializes writes — breaks at >10 concurrent writers.',
|
|
23
|
-
recommendation: 'Use PostgreSQL for multi-user or high-traffic applications.',
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
pattern: /(payment|billing|charge|transfer|transaction).{0,40}no.{0,15}(transaction|rollback|atomic)/i,
|
|
27
|
-
reason: 'Financial operations without database transactions risk data inconsistency.',
|
|
28
|
-
recommendation: 'Wrap all financial mutations in explicit BEGIN/COMMIT/ROLLBACK transactions.',
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
pattern: /store.{0,20}(password|credit.?card|ssn|social.?security).{0,20}plain/i,
|
|
32
|
-
reason: 'Storing sensitive data in plaintext is a catastrophic data breach risk.',
|
|
33
|
-
recommendation: 'Hash passwords (bcrypt). Encrypt PII at rest (AES-256). Never store raw card data.',
|
|
34
|
-
},
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
const WARN_RULES: Array<{ pattern: RegExp; concern: string; recommendation: string }> = [
|
|
38
|
-
{
|
|
39
|
-
pattern: /select\s+\*/i,
|
|
40
|
-
concern: 'SELECT * fetches all columns — wasted memory and network on large tables.',
|
|
41
|
-
recommendation: 'Select only needed columns explicitly.',
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
pattern: /\bfor\b.{0,80}(query|select|db\.|\.find|\.get|fetch)/i,
|
|
45
|
-
concern: 'Query inside a loop creates N+1 problem — DB gets hammered at scale.',
|
|
46
|
-
recommendation: 'Batch the query outside the loop using IN clause or JOIN.',
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
pattern: /no.{0,15}index\b/i,
|
|
50
|
-
concern: 'Missing index on search/filter columns causes full table scans.',
|
|
51
|
-
recommendation: 'Add indexes on FK columns and any WHERE/ORDER BY columns.',
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
pattern: /synchronous|blocking.{0,20}(i\/o|read|write|call)/i,
|
|
55
|
-
concern: 'Synchronous I/O blocks the Node.js event loop under concurrent load.',
|
|
56
|
-
recommendation: 'Use async/await with fs.promises, not fs.readFileSync.',
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
pattern: /no.{0,15}cache\b/i,
|
|
60
|
-
concern: 'No caching on repeated reads hammers the database unnecessarily.',
|
|
61
|
-
recommendation: 'Cache hot read paths with Redis or in-memory TTL cache.',
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
pattern: /no.{0,15}(timeout|time.?out)\b/i,
|
|
65
|
-
concern: 'External calls without timeout hang indefinitely when the dependency fails.',
|
|
66
|
-
recommendation: 'Set explicit timeouts (3-5s for APIs). Add retry with exponential backoff.',
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
pattern: /single.{0,25}(point|server|node|instance).{0,25}(fail|crash|down)/i,
|
|
70
|
-
concern: 'Single point of failure with no redundancy — one crash = full outage.',
|
|
71
|
-
recommendation: 'Add health checks. Consider redundancy or graceful degradation.',
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
pattern: /no.{0,15}(migration|schema.?version)/i,
|
|
75
|
-
concern: 'Database changes without versioned migrations cannot be safely rolled back.',
|
|
76
|
-
recommendation: 'Use a migration tool (Knex, Prisma migrate, Flyway).',
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
pattern: /global\s+(state|variable|singleton)/i,
|
|
80
|
-
concern: 'Global mutable state causes unpredictable behavior under concurrent requests.',
|
|
81
|
-
recommendation: 'Scope state to request context. Use dependency injection.',
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
pattern: /\bregex\b.{0,30}(user.?input|unvalidated|untrusted)/i,
|
|
85
|
-
concern: 'Complex regex on untrusted input can cause ReDoS (catastrophic backtracking).',
|
|
86
|
-
recommendation: 'Use simple regex patterns. Set timeout on regex evaluation for user input.',
|
|
87
|
-
},
|
|
88
|
-
];
|
|
89
|
-
|
|
90
|
-
const TRIVIAL = /^(rename|fix typo|reorder|reformat|format|update comment|add comment)\b/i;
|
|
91
|
-
|
|
92
|
-
export function analyze(task: string): AgentVote {
|
|
93
|
-
if (TRIVIAL.test(task.trim())) {
|
|
94
|
-
return { verdict: 'approve', reason: 'Trivial change — no architectural concerns.', concerns: [] };
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const blocks: Array<{ reason: string; recommendation: string }> = [];
|
|
98
|
-
const concerns: string[] = [];
|
|
99
|
-
const recommendations: string[] = [];
|
|
100
|
-
|
|
101
|
-
for (const rule of BLOCK_RULES) {
|
|
102
|
-
if (rule.pattern.test(task)) {
|
|
103
|
-
blocks.push({ reason: rule.reason, recommendation: rule.recommendation });
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
for (const rule of WARN_RULES) {
|
|
107
|
-
if (rule.pattern.test(task)) {
|
|
108
|
-
concerns.push(rule.concern);
|
|
109
|
-
recommendations.push(rule.recommendation);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (blocks.length > 0) {
|
|
114
|
-
return {
|
|
115
|
-
verdict: 'block',
|
|
116
|
-
reason: blocks[0].reason,
|
|
117
|
-
concerns: blocks.slice(1).map(b => b.reason),
|
|
118
|
-
recommendation: blocks.map(b => b.recommendation).join(' | '),
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (concerns.length > 0) {
|
|
123
|
-
return {
|
|
124
|
-
verdict: 'warn',
|
|
125
|
-
reason: `${concerns.length} structural concern${concerns.length > 1 ? 's' : ''} — review before building.`,
|
|
126
|
-
concerns,
|
|
127
|
-
recommendation: recommendations[0],
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return { verdict: 'approve', reason: 'Architecture looks sound. No structural concerns.', concerns: [] };
|
|
132
|
-
}
|
package/src/council/types.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export type AgentVerdict = 'approve' | 'warn' | 'block';
|
|
2
|
-
export type CouncilVerdict = 'GREEN' | 'YELLOW' | 'RED' | 'DEADLOCK';
|
|
3
|
-
|
|
4
|
-
export interface AgentVote {
|
|
5
|
-
verdict: AgentVerdict;
|
|
6
|
-
reason: string;
|
|
7
|
-
concerns: string[];
|
|
8
|
-
recommendation?: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface DebateInput {
|
|
12
|
-
task: string;
|
|
13
|
-
context?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface DebateResult {
|
|
17
|
-
task: string;
|
|
18
|
-
final_verdict: CouncilVerdict;
|
|
19
|
-
votes: {
|
|
20
|
-
lead_dev: AgentVote;
|
|
21
|
-
pm: AgentVote;
|
|
22
|
-
architect: AgentVote;
|
|
23
|
-
ux: AgentVote;
|
|
24
|
-
devil: AgentVote;
|
|
25
|
-
legal: AgentVote;
|
|
26
|
-
security: AgentVote;
|
|
27
|
-
};
|
|
28
|
-
recommended: string;
|
|
29
|
-
block_reasons: string[];
|
|
30
|
-
warnings: string[];
|
|
31
|
-
debated_at: string;
|
|
32
|
-
formatted_output: string;
|
|
33
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
// UX Designer — user flows, simplicity, real-user experience
|
|
2
|
-
import type { AgentVote } from './types.js';
|
|
3
|
-
|
|
4
|
-
// Backend-only tasks: UX approves without friction
|
|
5
|
-
const BACKEND_ONLY = /\b(api|backend|server|database|db|query|schema|migration|auth.*middleware|jwt|oauth|cron|cli|script|worker|queue|cache|redis|sql|index|trigger|webhook)\b/i;
|
|
6
|
-
const FRONTEND_SIGNALS = /\b(ui|ux|form|button|modal|page|screen|component|view|layout|menu|nav|input|field|label|error.?message|loading|user.?interface|frontend|react|vue|svelte|html|css)\b/i;
|
|
7
|
-
|
|
8
|
-
const BLOCK_RULES: Array<{ pattern: RegExp; reason: string; recommendation: string }> = [
|
|
9
|
-
{
|
|
10
|
-
pattern: /window\.alert\s*\(|window\.confirm\s*\(/i,
|
|
11
|
-
reason: 'window.alert/confirm blocks the page and cannot be styled. Users hate it.',
|
|
12
|
-
recommendation: 'Replace with toast notifications (react-hot-toast) or inline dialogs.',
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
pattern: /no.{0,20}error.{0,20}(message|state|feedback).{0,30}(form|submit|input)/i,
|
|
16
|
-
reason: 'Forms without error feedback leave users confused and drive support tickets.',
|
|
17
|
-
recommendation: 'Add inline validation messages for every field that can fail.',
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
pattern: /(?:7|8|9|10|eleven|twelve).{0,15}step/i,
|
|
21
|
-
reason: 'More than 6 steps in a flow loses 70%+ of users before completion.',
|
|
22
|
-
recommendation: 'Break into smaller flows or use progressive disclosure.',
|
|
23
|
-
},
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
const WARN_RULES: Array<{ pattern: RegExp; concern: string; recommendation: string }> = [
|
|
27
|
-
{
|
|
28
|
-
pattern: /no.{0,15}(mobile|responsive|viewport)/i,
|
|
29
|
-
concern: '60%+ of users are on mobile. Responsive is baseline, not a bonus.',
|
|
30
|
-
recommendation: 'Mobile-first CSS. Test breakpoints: 375px, 768px, 1280px.',
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
pattern: /no.{0,15}(loading|spinner|progress|skeleton)/i,
|
|
34
|
-
concern: 'Missing loading state — users cannot tell if their action registered.',
|
|
35
|
-
recommendation: 'Show loading indicator for any operation that takes >300ms.',
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
pattern: /\bmodal\b|\bpopup\b|\bdialog\b/i,
|
|
39
|
-
concern: 'Modals interrupt flow and fail on small screens. Use sparingly.',
|
|
40
|
-
recommendation: 'Reserve modals for destructive confirmations only. Use inline for everything else.',
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
pattern: /no.{0,15}(accessib|aria|a11y|wcag)/i,
|
|
44
|
-
concern: 'Missing accessibility — 15% of users cannot use the product.',
|
|
45
|
-
recommendation: 'Add aria-labels, keyboard nav, focus management. Test with VoiceOver.',
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
pattern: /color.{0,20}only|rely.{0,15}on.{0,15}color/i,
|
|
49
|
-
concern: '8% of users are colorblind — color-only signals are invisible to them.',
|
|
50
|
-
recommendation: 'Add icons, patterns, or text alongside color to convey meaning.',
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
pattern: /no.{0,15}(empty.?state|zero.?state|first.?time)/i,
|
|
54
|
-
concern: 'No empty state — first-time users see a blank screen that looks broken.',
|
|
55
|
-
recommendation: 'Design empty state that explains what goes here and how to start.',
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
pattern: /no.{0,15}(confirm|confirmation|undo|undo.?redo)/i,
|
|
59
|
-
concern: 'Destructive action without confirmation leads to user data loss.',
|
|
60
|
-
recommendation: 'Add confirmation dialog for destructive actions. Provide undo where possible.',
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
pattern: /auto.?submit|submit.{0,10}without.{0,10}(confirm|review)/i,
|
|
64
|
-
concern: 'Auto-submitting without user review removes user agency.',
|
|
65
|
-
recommendation: 'Always let users review before final submission.',
|
|
66
|
-
},
|
|
67
|
-
];
|
|
68
|
-
|
|
69
|
-
const TRIVIAL = /^(rename|fix typo|reorder|reformat|format|update comment|add comment)\b/i;
|
|
70
|
-
|
|
71
|
-
export function analyze(task: string): AgentVote {
|
|
72
|
-
if (TRIVIAL.test(task.trim())) {
|
|
73
|
-
return { verdict: 'approve', reason: 'Trivial change — no UX concerns.', concerns: [] };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Pure backend tasks get a light pass
|
|
77
|
-
const isBackend = BACKEND_ONLY.test(task) && !FRONTEND_SIGNALS.test(task);
|
|
78
|
-
if (isBackend) {
|
|
79
|
-
return {
|
|
80
|
-
verdict: 'approve',
|
|
81
|
-
reason: 'Backend task — no direct UX concerns. Ensure API errors surface clearly to users.',
|
|
82
|
-
concerns: [],
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const blocks: Array<{ reason: string; recommendation: string }> = [];
|
|
87
|
-
const concerns: string[] = [];
|
|
88
|
-
const recommendations: string[] = [];
|
|
89
|
-
|
|
90
|
-
for (const rule of BLOCK_RULES) {
|
|
91
|
-
if (rule.pattern.test(task)) {
|
|
92
|
-
blocks.push({ reason: rule.reason, recommendation: rule.recommendation });
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
for (const rule of WARN_RULES) {
|
|
96
|
-
if (rule.pattern.test(task)) {
|
|
97
|
-
concerns.push(rule.concern);
|
|
98
|
-
recommendations.push(rule.recommendation);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (blocks.length > 0) {
|
|
103
|
-
return {
|
|
104
|
-
verdict: 'block',
|
|
105
|
-
reason: blocks[0].reason,
|
|
106
|
-
concerns: blocks.slice(1).map(b => b.reason),
|
|
107
|
-
recommendation: blocks.map(b => b.recommendation).join(' | '),
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (concerns.length > 0) {
|
|
112
|
-
return {
|
|
113
|
-
verdict: 'warn',
|
|
114
|
-
reason: `${concerns.length} UX concern${concerns.length > 1 ? 's' : ''} — real users will notice this.`,
|
|
115
|
-
concerns,
|
|
116
|
-
recommendation: recommendations[0],
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return { verdict: 'approve', reason: 'UX looks solid. No user experience concerns.', concerns: [] };
|
|
121
|
-
}
|