@jigyasudham/veto 0.8.3 → 1.1.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 (114) hide show
  1. package/README.md +217 -54
  2. package/dist/adapters/index.js +4 -3
  3. package/dist/agents/executor.js +36 -3
  4. package/dist/cli.js +246 -7
  5. package/dist/context/reader.js +113 -0
  6. package/dist/council/index.js +3 -1
  7. package/dist/memory/local.js +18 -1
  8. package/dist/memory/schema.js +12 -10
  9. package/dist/plugins/loader.js +49 -0
  10. package/dist/router/index.js +2 -2
  11. package/dist/router/learning-updater.js +45 -1
  12. package/dist/server.js +507 -21
  13. package/dist/watcher/index.js +77 -0
  14. package/dist/workflow/pipeline.js +64 -0
  15. package/package.json +12 -3
  16. package/.claude/settings.local.json +0 -9
  17. package/src/adapters/claude.ts +0 -70
  18. package/src/adapters/codex.ts +0 -71
  19. package/src/adapters/gemini.ts +0 -71
  20. package/src/adapters/index.ts +0 -217
  21. package/src/agents/development/api.ts +0 -120
  22. package/src/agents/development/backend.ts +0 -85
  23. package/src/agents/development/coder.ts +0 -213
  24. package/src/agents/development/database.ts +0 -83
  25. package/src/agents/development/debugger.ts +0 -238
  26. package/src/agents/development/devops.ts +0 -86
  27. package/src/agents/development/frontend.ts +0 -85
  28. package/src/agents/development/migration.ts +0 -144
  29. package/src/agents/development/performance.ts +0 -144
  30. package/src/agents/development/refactor.ts +0 -86
  31. package/src/agents/development/reviewer.ts +0 -268
  32. package/src/agents/development/tester.ts +0 -151
  33. package/src/agents/executor.ts +0 -158
  34. package/src/agents/memory/context-manager.ts +0 -171
  35. package/src/agents/memory/decision-logger.ts +0 -160
  36. package/src/agents/memory/knowledge-base.ts +0 -124
  37. package/src/agents/memory/pattern-learner.ts +0 -143
  38. package/src/agents/memory/project-mapper.ts +0 -118
  39. package/src/agents/quality/accessibility.ts +0 -99
  40. package/src/agents/quality/code-quality.ts +0 -115
  41. package/src/agents/quality/compatibility.ts +0 -58
  42. package/src/agents/quality/documentation.ts +0 -105
  43. package/src/agents/quality/error-handling.ts +0 -96
  44. package/src/agents/research/competitor-analyzer.ts +0 -45
  45. package/src/agents/research/cost-analyzer.ts +0 -54
  46. package/src/agents/research/estimator.ts +0 -60
  47. package/src/agents/research/ethics-bias.ts +0 -113
  48. package/src/agents/research/researcher.ts +0 -114
  49. package/src/agents/research/risk-assessor.ts +0 -63
  50. package/src/agents/research/tech-advisor.ts +0 -55
  51. package/src/agents/security/auth.ts +0 -287
  52. package/src/agents/security/dependency-audit.ts +0 -337
  53. package/src/agents/security/penetration.ts +0 -262
  54. package/src/agents/security/privacy.ts +0 -285
  55. package/src/agents/security/scanner.ts +0 -322
  56. package/src/agents/security/secrets.ts +0 -249
  57. package/src/agents/types.ts +0 -66
  58. package/src/agents/workflow/automation.ts +0 -59
  59. package/src/agents/workflow/file-manager.ts +0 -52
  60. package/src/agents/workflow/git-agent.ts +0 -55
  61. package/src/agents/workflow/reporter.ts +0 -51
  62. package/src/agents/workflow/search-agent.ts +0 -40
  63. package/src/agents/workflow/task-coordinator.ts +0 -41
  64. package/src/agents/workflow/task-planner.ts +0 -47
  65. package/src/cli.ts +0 -204
  66. package/src/council/decision-engine.ts +0 -171
  67. package/src/council/devil-advocate.ts +0 -116
  68. package/src/council/index.ts +0 -44
  69. package/src/council/lead-developer.ts +0 -118
  70. package/src/council/legal-compliance.ts +0 -152
  71. package/src/council/product-manager.ts +0 -102
  72. package/src/council/security.ts +0 -172
  73. package/src/council/system-architect.ts +0 -132
  74. package/src/council/types.ts +0 -33
  75. package/src/council/ux-designer.ts +0 -121
  76. package/src/memory/local.ts +0 -305
  77. package/src/memory/schema.ts +0 -174
  78. package/src/memory/sync.ts +0 -274
  79. package/src/router/complexity-scorer.ts +0 -96
  80. package/src/router/context-compressor.ts +0 -74
  81. package/src/router/index.ts +0 -60
  82. package/src/router/learning-updater.ts +0 -271
  83. package/src/router/model-selector.ts +0 -83
  84. package/src/router/rate-monitor.ts +0 -103
  85. package/src/server.ts +0 -1038
  86. package/src/skills/development/skill-api-design.ts +0 -329
  87. package/src/skills/development/skill-auth.ts +0 -271
  88. package/src/skills/development/skill-ci-cd.ts +0 -0
  89. package/src/skills/development/skill-crud.ts +0 -209
  90. package/src/skills/development/skill-db-schema.ts +0 -0
  91. package/src/skills/development/skill-docker.ts +0 -0
  92. package/src/skills/development/skill-env-setup.ts +0 -0
  93. package/src/skills/development/skill-scaffold.ts +0 -323
  94. package/src/skills/intelligence/skill-complexity-score.ts +0 -69
  95. package/src/skills/intelligence/skill-cost-track.ts +0 -39
  96. package/src/skills/intelligence/skill-learning-loop.ts +0 -69
  97. package/src/skills/intelligence/skill-pattern-detect.ts +0 -38
  98. package/src/skills/intelligence/skill-rate-watch.ts +0 -61
  99. package/src/skills/memory/skill-context-compress.ts +0 -98
  100. package/src/skills/memory/skill-cross-sync.ts +0 -104
  101. package/src/skills/memory/skill-decision-log.ts +0 -119
  102. package/src/skills/memory/skill-session-restore.ts +0 -59
  103. package/src/skills/memory/skill-session-save.ts +0 -94
  104. package/src/skills/quality/skill-accessibility.ts +0 -0
  105. package/src/skills/quality/skill-code-review.ts +0 -84
  106. package/src/skills/quality/skill-docs-gen.ts +0 -0
  107. package/src/skills/quality/skill-perf-audit.ts +0 -0
  108. package/src/skills/quality/skill-security-scan.ts +0 -91
  109. package/src/skills/quality/skill-test-suite.ts +0 -290
  110. package/src/skills/workflow/skill-deploy.ts +0 -0
  111. package/src/skills/workflow/skill-git-workflow.ts +0 -0
  112. package/src/skills/workflow/skill-rollback.ts +0 -0
  113. package/src/skills/workflow/skill-task-breakdown.ts +0 -0
  114. package/tsconfig.json +0 -20
@@ -1,84 +0,0 @@
1
- // Skill: code-review — 20-point code review checklist
2
-
3
- export interface SkillInput {
4
- task: string;
5
- context?: string;
6
- options?: Record<string, unknown>;
7
- }
8
-
9
- export interface SkillOutput {
10
- skill: string;
11
- template?: string;
12
- checklist: string[];
13
- patterns: string[];
14
- gotchas: string[];
15
- resources: string[];
16
- }
17
-
18
- export function run(input: SkillInput): SkillOutput {
19
- return {
20
- skill: 'code-review',
21
- template: undefined,
22
- checklist: [
23
- // Correctness (1-4)
24
- '1. CORRECTNESS — Does the code do what the PR description says? Walk through the logic manually with a concrete example.',
25
- '2. EDGE CASES — Does it handle null/undefined, empty collections, zero, negative numbers, very large inputs, and concurrent calls correctly?',
26
- '3. ERROR HANDLING — Are all errors caught, typed, and handled? No silent swallowed errors, no bare catch blocks that discard the error.',
27
- '4. CONCURRENCY — Does shared mutable state have proper synchronisation? Are async operations correctly awaited? No floating promises.',
28
-
29
- // Security (5-7)
30
- '5. INPUT VALIDATION — Is all user-supplied input validated with a schema library (zod/joi) before use? No raw string concatenation into queries.',
31
- '6. AUTHENTICATION & AUTHORISATION — Does every data-access path check that the requesting user owns the resource? Is auth middleware applied?',
32
- '7. SECRETS — No hardcoded credentials, API keys, or tokens in the diff. No sensitive values logged or included in error responses.',
33
-
34
- // Performance (8-9)
35
- '8. N+1 QUERIES — Are list endpoints fetching related records in a loop? Use batch/include/join instead.',
36
- '9. COMPLEXITY — Are there any O(n²) or worse algorithms on large datasets? Is database access inside a loop?',
37
-
38
- // Types and naming (10-12)
39
- '10. TYPES — Is TypeScript used strictly (no `any`, no type assertions without comment)? Are interfaces and return types explicit on public functions?',
40
- '11. NAMING — Are variables, functions, and classes named clearly and consistently? Do boolean variables use is/has/should prefixes?',
41
- '12. MAGIC VALUES — Are all magic numbers and magic strings replaced with named constants or enums?',
42
-
43
- // Style and complexity (13-14)
44
- '13. COMPLEXITY — Are functions short (< 30 lines) and single-purpose? If a function requires a long comment to explain it, refactor instead.',
45
- '14. DUPLICATION — Is the same logic copy-pasted from elsewhere? Extract a shared utility or extend an existing one.',
46
-
47
- // Tests (15-16)
48
- '15. TEST COVERAGE — Are there tests for the new code? Do they cover the happy path, error paths, and at least one edge case?',
49
- '16. TEST QUALITY — Do the tests assert on the right things? Are mocks minimal and purposeful? Tests should not duplicate implementation logic.',
50
-
51
- // Documentation (17)
52
- '17. DOCUMENTATION — Do complex functions have a JSDoc comment explaining the why (not just the what)? Are public API changes reflected in the OpenAPI spec?',
53
-
54
- // Dependencies and build (18)
55
- '18. DEPENDENCIES — Are new npm packages justified? Check for license compatibility, maintenance status, and security advisories (npm audit).',
56
-
57
- // Observability (19)
58
- '19. OBSERVABILITY — Are significant operations logged at the appropriate level? Are errors logged with enough context to diagnose? No passwords in logs.',
59
-
60
- // Review hygiene (20)
61
- '20. BREAKING CHANGES — Does the change break any existing API contracts, DB schemas, or public interfaces? If so, is it properly versioned or migrated?',
62
- ],
63
- patterns: [
64
- 'Review the diff, not the file — focus on what changed and why',
65
- 'Ask questions instead of issuing commands: "Could this be null here?" vs "Fix this"',
66
- 'Distinguish blocking issues (must fix) from suggestions (nice to have) in comments',
67
- 'Approve with comments for minor non-blocking issues rather than blocking for style',
68
- 'Check the tests before the implementation — tests reveal the intended behaviour',
69
- ],
70
- gotchas: [
71
- 'Approving without running or reading the tests — tests are part of the code',
72
- 'Nitpicking style when an auto-formatter (Prettier/ESLint) should enforce it',
73
- 'Missing the forest for the trees: reviewing individual lines but missing a design flaw',
74
- 'Not reviewing DB migrations for data safety (missing IF NOT EXISTS, backfill plan)',
75
- 'Forgetting to check error message text — "null pointer exception" leaking to the user',
76
- ],
77
- resources: [
78
- 'https://google.github.io/eng-practices/review/reviewer/',
79
- 'https://mtlynch.io/code-review-love/',
80
- 'https://www.conventionalcommits.org/ (PR title / commit message style)',
81
- 'https://cheatsheetseries.owasp.org/cheatsheets/Code_Review_Guide_Introduction_Cheat_Sheet.html',
82
- ],
83
- };
84
- }
File without changes
File without changes
@@ -1,91 +0,0 @@
1
- // Skill: security-scan — OWASP Top 10 scan process with tool commands
2
-
3
- export interface SkillInput {
4
- task: string;
5
- context?: string;
6
- options?: Record<string, unknown>;
7
- }
8
-
9
- export interface SkillOutput {
10
- skill: string;
11
- template?: string;
12
- checklist: string[];
13
- patterns: string[];
14
- gotchas: string[];
15
- resources: string[];
16
- }
17
-
18
- export function run(input: SkillInput): SkillOutput {
19
- return {
20
- skill: 'security-scan',
21
- template: undefined,
22
- checklist: [
23
- // Dependency scanning
24
- '1. Run npm audit: npx npm audit --audit-level=high (fail CI if high/critical found)',
25
- '2. Run Snyk for deeper CVE analysis: npx snyk test --severity-threshold=high',
26
- '3. Check for outdated packages: npx npm-check-updates (review before upgrading)',
27
- '4. Verify lockfile integrity: npm ci (uses lockfile exactly; fails if lockfile is dirty)',
28
-
29
- // Secrets scanning
30
- '5. Scan for hardcoded secrets: npx gitleaks detect --source . --verbose',
31
- '6. Run trufflehog on git history: trufflehog git file://. --since-commit HEAD~20',
32
- '7. Verify .gitignore covers .env, *.key, *.pem, secrets.json, credentials.json',
33
-
34
- // Static analysis
35
- '8. Run ESLint security plugin: eslint --plugin security --rule "security/detect-eval-with-expression: error"',
36
- '9. Run Semgrep OWASP ruleset: semgrep --config=p/owasp-top-ten --error .',
37
- '10. Run CodeQL (GitHub Actions): use codeql-action/analyze with javascript/typescript queries',
38
-
39
- // A01 – Broken Access Control
40
- '11. A01 – Review every route handler: confirm auth middleware precedes data access',
41
- '12. A01 – Search for direct object references: grep -r "req.params.id" src/ — verify ownership check in each',
42
-
43
- // A02 – Cryptographic Failures
44
- '13. A02 – Search for weak hashes: grep -r "md5\\|sha1\\|DES\\|RC4" src/ (flag any match)',
45
- '14. A02 – Verify HTTPS enforcement: check for HSTS header and HTTP→HTTPS redirect in server config',
46
-
47
- // A03 – Injection
48
- '15. A03 – Search for SQL concatenation: grep -r "SELECT.*+" src/ — all DB calls should use parameterised queries',
49
- '16. A03 – Search for eval: grep -rn "eval(" src/ — no eval() in production code',
50
-
51
- // A05 – Misconfiguration
52
- '17. A05 – Run security headers check: curl -I https://your-domain.com | grep -E "Content-Security|X-Frame|Strict-Transport|X-Content"',
53
- '18. A05 – Verify no debug routes in production: grep -r "/debug\\|/__admin" src/routes/',
54
-
55
- // A07 – Auth failures
56
- '19. A07 – Confirm rate limiting on auth endpoints: grep -r "rateLimit" src/routes/auth',
57
- '20. A07 – Verify account lockout logic exists: grep -r "lockedUntil\\|failedAttempts" src/services/auth',
58
-
59
- // DAST
60
- '21. Run OWASP ZAP baseline scan: docker run -t owasp/zap2docker-stable zap-baseline.py -t https://staging.example.com',
61
- '22. Check Content-Security-Policy with observatory: npx observatory-cli your-domain.com --format report',
62
-
63
- // Final gate
64
- '23. Review all HIGH/CRITICAL findings; create tickets for each; do not ship with open criticals',
65
- '24. Add security scan steps to CI pipeline so every PR is checked automatically',
66
- ],
67
- patterns: [
68
- 'Shift-left security: scan in CI on every PR, not only before release',
69
- 'Defence in depth: layered scanning (dependency + static + dynamic)',
70
- 'Fail-fast: non-zero CI exit code on any high/critical finding',
71
- 'Security-as-code: Semgrep rules and ZAP configs version-controlled alongside application',
72
- ],
73
- gotchas: [
74
- 'npm audit reports transitive dependency vulnerabilities — check if exploitable in your code path before panicking',
75
- 'Semgrep false positives on test files — add --exclude "tests/" to production scans',
76
- 'ZAP baseline scan covers only unauthenticated paths — run a full scan with an auth script for coverage',
77
- 'Gitleaks detects secrets committed at any point in history, not just HEAD — clean git history with git-filter-repo if needed',
78
- 'Snyk requires authentication for full CVE database access — set SNYK_TOKEN in CI secrets',
79
- ],
80
- resources: [
81
- 'https://owasp.org/www-project-top-ten/',
82
- 'https://owasp.org/www-project-zap/',
83
- 'https://semgrep.dev/p/owasp-top-ten',
84
- 'https://github.com/gitleaks/gitleaks',
85
- 'https://snyk.io/docs/snyk-cli/',
86
- 'https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html',
87
- 'https://docs.npmjs.com/cli/v10/commands/npm-audit',
88
- 'https://observatory.mozilla.org/',
89
- ],
90
- };
91
- }
@@ -1,290 +0,0 @@
1
- // Skill: test-suite — complete test suite structure guide
2
-
3
- export interface SkillInput {
4
- task: string;
5
- context?: string;
6
- options?: Record<string, unknown>;
7
- }
8
-
9
- export interface SkillOutput {
10
- skill: string;
11
- template?: string;
12
- checklist: string[];
13
- patterns: string[];
14
- gotchas: string[];
15
- resources: string[];
16
- }
17
-
18
- const TEMPLATE = `
19
- // ── Unit test: ItemService (tests/unit/item.service.test.ts) ──────────────
20
- import { describe, it, expect, beforeEach, vi } from 'vitest';
21
- import { ItemService } from '../../src/services/item.service';
22
- import type { ItemRepository } from '../../src/repositories/item.repository';
23
-
24
- // Test fixture factory — create minimal valid objects
25
- function makeItem(overrides: Partial<Item> = {}): Item {
26
- return {
27
- id: 'item-1',
28
- name: 'Test Item',
29
- userId: 'user-1',
30
- createdAt: new Date('2024-01-01'),
31
- updatedAt: new Date('2024-01-01'),
32
- ...overrides,
33
- };
34
- }
35
-
36
- describe('ItemService', () => {
37
- let service: ItemService;
38
- let repo: ItemRepository;
39
-
40
- beforeEach(() => {
41
- repo = {
42
- findById: vi.fn(),
43
- findAllByUser: vi.fn(),
44
- create: vi.fn(),
45
- update: vi.fn(),
46
- delete: vi.fn(),
47
- };
48
- service = new ItemService(repo);
49
- });
50
-
51
- // ── Happy path ──────────────────────────────────────────────────────────
52
- describe('getItem', () => {
53
- it('returns the item when found and owned by the requesting user', async () => {
54
- const item = makeItem({ userId: 'user-1' });
55
- vi.mocked(repo.findById).mockResolvedValue(item);
56
-
57
- const result = await service.getItem('item-1', 'user-1');
58
- expect(result).toEqual(item);
59
- });
60
-
61
- // ── Error cases ───────────────────────────────────────────────────────
62
- it('throws NotFoundError when item does not exist', async () => {
63
- vi.mocked(repo.findById).mockResolvedValue(null);
64
- await expect(service.getItem('missing', 'user-1')).rejects.toThrow(NotFoundError);
65
- });
66
-
67
- it('throws ForbiddenError when item belongs to a different user', async () => {
68
- const item = makeItem({ userId: 'user-2' });
69
- vi.mocked(repo.findById).mockResolvedValue(item);
70
- await expect(service.getItem('item-1', 'user-1')).rejects.toThrow(ForbiddenError);
71
- });
72
- });
73
-
74
- // ── Edge cases ─────────────────────────────────────────────────────────
75
- describe('createItem', () => {
76
- it('trims whitespace from name before storing', async () => {
77
- const item = makeItem({ name: 'Trimmed' });
78
- vi.mocked(repo.create).mockResolvedValue(item);
79
-
80
- await service.createItem('user-1', { name: ' Trimmed ' });
81
- expect(repo.create).toHaveBeenCalledWith('user-1', { name: 'Trimmed' });
82
- });
83
-
84
- it('propagates repository errors', async () => {
85
- vi.mocked(repo.create).mockRejectedValue(new Error('DB connection failed'));
86
- await expect(service.createItem('user-1', { name: 'x' })).rejects.toThrow('DB connection failed');
87
- });
88
- });
89
- });
90
-
91
- // ── Integration test: Items API (tests/integration/items.test.ts) ─────────
92
- import request from 'supertest';
93
- import { createApp } from '../../src/app';
94
- import { signAccessToken } from '../../src/utils/tokens';
95
-
96
- describe('Items API', () => {
97
- let app: Express.Application;
98
- let authToken: string;
99
-
100
- beforeAll(async () => {
101
- app = await createApp({ db: testDb });
102
- authToken = signAccessToken('user-1', 'user');
103
- await testDb.user.create({ data: { id: 'user-1', email: 'test@example.com', passwordHash: 'x' } });
104
- });
105
-
106
- afterEach(async () => {
107
- await testDb.item.deleteMany();
108
- });
109
-
110
- describe('GET /v1/items', () => {
111
- it('returns empty list when no items exist', async () => {
112
- const res = await request(app)
113
- .get('/v1/items')
114
- .set('Authorization', \`Bearer \${authToken}\`);
115
-
116
- expect(res.status).toBe(200);
117
- expect(res.body.data).toEqual([]);
118
- });
119
-
120
- it('returns only items belonging to the authenticated user', async () => {
121
- await testDb.item.createMany({
122
- data: [
123
- { name: 'My Item', userId: 'user-1' },
124
- { name: 'Other Item', userId: 'user-2' },
125
- ],
126
- });
127
-
128
- const res = await request(app)
129
- .get('/v1/items')
130
- .set('Authorization', \`Bearer \${authToken}\`);
131
-
132
- expect(res.status).toBe(200);
133
- expect(res.body.data).toHaveLength(1);
134
- expect(res.body.data[0].name).toBe('My Item');
135
- });
136
-
137
- it('returns 401 when no token provided', async () => {
138
- const res = await request(app).get('/v1/items');
139
- expect(res.status).toBe(401);
140
- });
141
- });
142
-
143
- describe('POST /v1/items', () => {
144
- it('creates an item and returns 201 with Location header', async () => {
145
- const res = await request(app)
146
- .post('/v1/items')
147
- .set('Authorization', \`Bearer \${authToken}\`)
148
- .send({ name: 'New Item', description: 'A test item' });
149
-
150
- expect(res.status).toBe(201);
151
- expect(res.headers['location']).toMatch(/\\/v1\\/items\\//);
152
- expect(res.body.data.name).toBe('New Item');
153
- });
154
-
155
- it('returns 422 when name is missing', async () => {
156
- const res = await request(app)
157
- .post('/v1/items')
158
- .set('Authorization', \`Bearer \${authToken}\`)
159
- .send({ description: 'No name' });
160
-
161
- expect(res.status).toBe(422);
162
- expect(res.body.error.code).toBe('VALIDATION_ERROR');
163
- });
164
- });
165
-
166
- describe('GET /v1/items/:id', () => {
167
- it('returns 403 when requesting another user\\'s item', async () => {
168
- const item = await testDb.item.create({ data: { name: 'Other', userId: 'user-2' } });
169
-
170
- const res = await request(app)
171
- .get(\`/v1/items/\${item.id}\`)
172
- .set('Authorization', \`Bearer \${authToken}\`);
173
-
174
- expect(res.status).toBe(403);
175
- });
176
-
177
- it('returns 404 when item does not exist', async () => {
178
- const res = await request(app)
179
- .get('/v1/items/00000000-0000-0000-0000-000000000000')
180
- .set('Authorization', \`Bearer \${authToken}\`);
181
-
182
- expect(res.status).toBe(404);
183
- });
184
- });
185
- });
186
-
187
- // ── E2E test: full user journey (tests/e2e/user-journey.test.ts) ──────────
188
- describe('User journey: register → create item → retrieve → delete', () => {
189
- let accessToken: string;
190
- let itemId: string;
191
-
192
- it('registers a new user', async () => {
193
- const res = await request(app)
194
- .post('/v1/auth/register')
195
- .send({ email: 'journey@example.com', password: 'SecurePass123!' });
196
- expect(res.status).toBe(201);
197
- });
198
-
199
- it('logs in and receives an access token', async () => {
200
- const res = await request(app)
201
- .post('/v1/auth/login')
202
- .send({ email: 'journey@example.com', password: 'SecurePass123!' });
203
- expect(res.status).toBe(200);
204
- accessToken = res.body.data.accessToken;
205
- });
206
-
207
- it('creates an item', async () => {
208
- const res = await request(app)
209
- .post('/v1/items')
210
- .set('Authorization', \`Bearer \${accessToken}\`)
211
- .send({ name: 'Journey Item' });
212
- expect(res.status).toBe(201);
213
- itemId = res.body.data.id;
214
- });
215
-
216
- it('retrieves the created item', async () => {
217
- const res = await request(app)
218
- .get(\`/v1/items/\${itemId}\`)
219
- .set('Authorization', \`Bearer \${accessToken}\`);
220
- expect(res.status).toBe(200);
221
- expect(res.body.data.name).toBe('Journey Item');
222
- });
223
-
224
- it('deletes the item', async () => {
225
- const res = await request(app)
226
- .delete(\`/v1/items/\${itemId}\`)
227
- .set('Authorization', \`Bearer \${accessToken}\`);
228
- expect(res.status).toBe(204);
229
- });
230
-
231
- it('confirms item is gone after deletion', async () => {
232
- const res = await request(app)
233
- .get(\`/v1/items/\${itemId}\`)
234
- .set('Authorization', \`Bearer \${accessToken}\`);
235
- expect(res.status).toBe(404);
236
- });
237
- });
238
- `.trim();
239
-
240
- export function run(input: SkillInput): SkillOutput {
241
- return {
242
- skill: 'test-suite',
243
- template: TEMPLATE,
244
- checklist: [
245
- 'Install vitest (or jest) and supertest: npm install -D vitest supertest @types/supertest',
246
- 'Configure vitest.config.ts: coverage provider v8, include src/**/*.ts, threshold 80%',
247
- 'Create tests/ directory with unit/, integration/, and e2e/ subdirectories',
248
- 'Write test fixture factories that create minimal valid objects with optional overrides',
249
- 'Unit tests: test each service method in isolation — mock all dependencies with vi.fn()',
250
- 'Unit test happy path: expected input produces expected output',
251
- 'Unit test error cases: not found, forbidden, validation errors, repository failures',
252
- 'Unit test edge cases: empty strings, boundary values, null/undefined, concurrent calls',
253
- 'Integration tests: use supertest to send HTTP requests to the real Express app',
254
- 'Integration test auth: verify 401 without token, 401 with expired token, 200 with valid token',
255
- 'Integration test authorisation: verify 403 when accessing another user\'s resource',
256
- 'Integration test validation: verify 422 with missing required fields, invalid types, out-of-range values',
257
- 'Integration test pagination: verify page=1&pageSize=2 returns 2 items, meta.total is correct',
258
- 'E2E tests: simulate a complete user journey from registration through full workflow to deletion',
259
- 'Run coverage report: npx vitest run --coverage; verify no critical paths are uncovered',
260
- 'Add CI step: vitest run --coverage --reporter=verbose fails the build if coverage < 80%',
261
- 'Use afterEach to clean up test data; never rely on test execution order',
262
- 'Separate test database or use transactions that are rolled back after each test',
263
- 'Snapshot tests for complex output shapes (e.g., generated reports, API response structure)',
264
- 'Add test for rate-limiting endpoint: 11th request in window should return 429',
265
- ],
266
- patterns: [
267
- 'AAA pattern: Arrange → Act → Assert in every test case',
268
- 'Test fixture factory: makeUser(), makeItem() functions with optional overrides',
269
- 'Mock at the boundary: mock repositories in unit tests, use real DB in integration tests',
270
- 'Test pyramid: many unit tests, fewer integration tests, few E2E tests',
271
- 'Describe → nested describe → it hierarchy mirrors the module structure',
272
- ],
273
- gotchas: [
274
- 'Testing implementation details instead of behaviour — tests break on every refactor',
275
- 'Sharing mutable state between tests without cleanup — flaky test ordering dependency',
276
- 'Mocking too deep: mocking the DB client instead of the repository causes brittle tests',
277
- 'Not testing error paths — happy-path-only coverage misses the most bug-prone code',
278
- 'Writing assertions on the wrong field — test passes but is not actually verifying the behaviour',
279
- 'Not testing auth in integration tests — security bugs not caught until production',
280
- 'Using setTimeout in tests without fake timers — slow and non-deterministic',
281
- ],
282
- resources: [
283
- 'https://vitest.dev/guide/',
284
- 'https://github.com/ladjs/supertest',
285
- 'https://martinfowler.com/articles/practical-test-pyramid.html',
286
- 'https://testing-library.com/docs/ (for React component tests)',
287
- 'https://jestjs.io/docs/expect (matcher reference, compatible with vitest)',
288
- ],
289
- };
290
- }
File without changes
File without changes
File without changes
File without changes
package/tsconfig.json DELETED
@@ -1,20 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "lib": ["ES2022"],
7
- "outDir": "./dist",
8
- "rootDir": "./src",
9
- "strict": true,
10
- "esModuleInterop": true,
11
- "skipLibCheck": true,
12
- "forceConsistentCasingInFileNames": true,
13
- "resolveJsonModule": true,
14
- "declaration": true,
15
- "declarationMap": true,
16
- "sourceMap": true
17
- },
18
- "include": ["src/**/*"],
19
- "exclude": ["node_modules", "dist"]
20
- }