@dewtech/dare-cli 2.15.0 → 2.17.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 (101) hide show
  1. package/README.md +659 -561
  2. package/dist/__tests__/refine.test.d.ts +2 -0
  3. package/dist/__tests__/refine.test.d.ts.map +1 -0
  4. package/dist/__tests__/refine.test.js +186 -0
  5. package/dist/__tests__/refine.test.js.map +1 -0
  6. package/dist/__tests__/review.test.d.ts +2 -0
  7. package/dist/__tests__/review.test.d.ts.map +1 -0
  8. package/dist/__tests__/review.test.js +242 -0
  9. package/dist/__tests__/review.test.js.map +1 -0
  10. package/dist/__tests__/update.test.d.ts +2 -0
  11. package/dist/__tests__/update.test.d.ts.map +1 -0
  12. package/dist/__tests__/update.test.js +150 -0
  13. package/dist/__tests__/update.test.js.map +1 -0
  14. package/dist/bin/dare.js +6 -0
  15. package/dist/bin/dare.js.map +1 -1
  16. package/dist/commands/dag.d.ts.map +1 -1
  17. package/dist/commands/dag.js +27 -9
  18. package/dist/commands/dag.js.map +1 -1
  19. package/dist/commands/execute.d.ts.map +1 -1
  20. package/dist/commands/execute.js +76 -0
  21. package/dist/commands/execute.js.map +1 -1
  22. package/dist/commands/refine.d.ts +16 -0
  23. package/dist/commands/refine.d.ts.map +1 -0
  24. package/dist/commands/refine.js +167 -0
  25. package/dist/commands/refine.js.map +1 -0
  26. package/dist/commands/review.d.ts +16 -0
  27. package/dist/commands/review.d.ts.map +1 -0
  28. package/dist/commands/review.js +106 -0
  29. package/dist/commands/review.js.map +1 -0
  30. package/dist/commands/update.d.ts +13 -0
  31. package/dist/commands/update.d.ts.map +1 -0
  32. package/dist/commands/update.js +149 -0
  33. package/dist/commands/update.js.map +1 -0
  34. package/dist/types/Refine.types.d.ts +96 -0
  35. package/dist/types/Refine.types.d.ts.map +1 -0
  36. package/dist/types/Refine.types.js +19 -0
  37. package/dist/types/Refine.types.js.map +1 -0
  38. package/dist/types/Review.types.d.ts +86 -0
  39. package/dist/types/Review.types.d.ts.map +1 -0
  40. package/dist/types/Review.types.js +15 -0
  41. package/dist/types/Review.types.js.map +1 -0
  42. package/dist/types/UpdateManifest.types.d.ts +91 -0
  43. package/dist/types/UpdateManifest.types.d.ts.map +1 -0
  44. package/dist/types/UpdateManifest.types.js +13 -0
  45. package/dist/types/UpdateManifest.types.js.map +1 -0
  46. package/dist/utils/ReviewRunner.d.ts +42 -0
  47. package/dist/utils/ReviewRunner.d.ts.map +1 -0
  48. package/dist/utils/ReviewRunner.js +175 -0
  49. package/dist/utils/ReviewRunner.js.map +1 -0
  50. package/dist/utils/UpdateApplier.d.ts +42 -0
  51. package/dist/utils/UpdateApplier.d.ts.map +1 -0
  52. package/dist/utils/UpdateApplier.js +207 -0
  53. package/dist/utils/UpdateApplier.js.map +1 -0
  54. package/dist/utils/UpdateDetector.d.ts +56 -0
  55. package/dist/utils/UpdateDetector.d.ts.map +1 -0
  56. package/dist/utils/UpdateDetector.js +164 -0
  57. package/dist/utils/UpdateDetector.js.map +1 -0
  58. package/dist/utils/complexity-analyzer.d.ts +60 -0
  59. package/dist/utils/complexity-analyzer.d.ts.map +1 -0
  60. package/dist/utils/complexity-analyzer.js +292 -0
  61. package/dist/utils/complexity-analyzer.js.map +1 -0
  62. package/dist/utils/excalidraw-renderer.d.ts +79 -0
  63. package/dist/utils/excalidraw-renderer.d.ts.map +1 -0
  64. package/dist/utils/excalidraw-renderer.js +188 -0
  65. package/dist/utils/excalidraw-renderer.js.map +1 -0
  66. package/dist/utils/excalidraw-renderer.test.d.ts +2 -0
  67. package/dist/utils/excalidraw-renderer.test.d.ts.map +1 -0
  68. package/dist/utils/excalidraw-renderer.test.js +135 -0
  69. package/dist/utils/excalidraw-renderer.test.js.map +1 -0
  70. package/dist/utils/project-generator.d.ts.map +1 -1
  71. package/dist/utils/project-generator.js +21 -2
  72. package/dist/utils/project-generator.js.map +1 -1
  73. package/dist/utils/stack-bootstrap.js +3 -1
  74. package/dist/utils/stack-bootstrap.js.map +1 -1
  75. package/dist/utils/static-analyzer.d.ts +29 -0
  76. package/dist/utils/static-analyzer.d.ts.map +1 -0
  77. package/dist/utils/static-analyzer.js +390 -0
  78. package/dist/utils/static-analyzer.js.map +1 -0
  79. package/dist/utils/version-compare.d.ts +27 -0
  80. package/dist/utils/version-compare.d.ts.map +1 -0
  81. package/dist/utils/version-compare.js +47 -0
  82. package/dist/utils/version-compare.js.map +1 -0
  83. package/package.json +1 -1
  84. package/templates/DARE-dag-example.yaml +280 -0
  85. package/templates/UPDATE-MANIFEST.json +48 -0
  86. package/templates/ide/antigravity/.agents/skills/dare-blueprint/SKILL.md +180 -36
  87. package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +114 -0
  88. package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +111 -0
  89. package/templates/ide/antigravity/.agents/skills/dare-tasks/SKILL.md +41 -0
  90. package/templates/ide/antigravity/templates/TASK-SPEC-template.md +45 -4
  91. package/templates/ide/claude/.claude/commands/dare-blueprint.md +56 -0
  92. package/templates/ide/claude/.claude/commands/dare-dag-build.md +41 -0
  93. package/templates/ide/claude/.claude/commands/dare-dag-viz.md +197 -0
  94. package/templates/ide/claude/.claude/commands/dare-refine.md +145 -0
  95. package/templates/ide/claude/.claude/commands/dare-review.md +113 -0
  96. package/templates/ide/claude/templates/TASK-SPEC-template.md +45 -4
  97. package/templates/ide/cursor/.cursor/commands/generate-blueprint.md +45 -0
  98. package/templates/ide/cursor/.cursor/commands/generate-tasks.md +42 -0
  99. package/templates/ide/cursor/.cursor/commands/refine-task.md +107 -0
  100. package/templates/ide/cursor/.cursor/commands/review-task.md +91 -0
  101. package/templates/ide/cursor/templates/TASK-SPEC-template.md +45 -4
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=refine.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refine.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/refine.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,186 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import fs from 'fs-extra';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import { analyzeTaskComplexity, proposeSplit, levelFromScore, } from '../utils/complexity-analyzer.js';
6
+ async function makeTempDir() {
7
+ return fs.mkdtemp(path.join(os.tmpdir(), 'dare-refine-test-'));
8
+ }
9
+ async function writeFile(dir, rel, content) {
10
+ const abs = path.join(dir, rel);
11
+ await fs.ensureDir(path.dirname(abs));
12
+ await fs.writeFile(abs, content);
13
+ }
14
+ // ── levelFromScore ────────────────────────────────────────────────────────────
15
+ describe('levelFromScore', () => {
16
+ it('maps scores to default buckets', () => {
17
+ expect(levelFromScore(0)).toBe('LOW');
18
+ expect(levelFromScore(5)).toBe('LOW');
19
+ expect(levelFromScore(6)).toBe('MED');
20
+ expect(levelFromScore(12)).toBe('MED');
21
+ expect(levelFromScore(13)).toBe('HIGH');
22
+ expect(levelFromScore(20)).toBe('HIGH');
23
+ expect(levelFromScore(21)).toBe('CRITICAL');
24
+ expect(levelFromScore(50)).toBe('CRITICAL');
25
+ });
26
+ it('respects custom thresholds', () => {
27
+ const t = { low: 2, med: 4, high: 6 };
28
+ expect(levelFromScore(2, t)).toBe('LOW');
29
+ expect(levelFromScore(3, t)).toBe('MED');
30
+ expect(levelFromScore(4, t)).toBe('MED');
31
+ expect(levelFromScore(5, t)).toBe('HIGH');
32
+ expect(levelFromScore(6, t)).toBe('HIGH');
33
+ expect(levelFromScore(7, t)).toBe('CRITICAL');
34
+ });
35
+ });
36
+ // ── analyzeTaskComplexity ─────────────────────────────────────────────────────
37
+ describe('analyzeTaskComplexity', () => {
38
+ let tmp;
39
+ beforeEach(async () => {
40
+ tmp = await makeTempDir();
41
+ });
42
+ afterEach(async () => {
43
+ await fs.remove(tmp);
44
+ });
45
+ it('returns no-spec signal when spec is missing', async () => {
46
+ const r = await analyzeTaskComplexity('task-ghost', tmp);
47
+ expect(r).not.toBeNull();
48
+ expect(r?.specPath).toBeNull();
49
+ expect(r?.signals[0].kind).toBe('no-spec');
50
+ });
51
+ it('scores a tiny task as LOW', async () => {
52
+ await writeFile(tmp, 'DARE/EXECUTION/task-001.md', `
53
+ # Task 001
54
+
55
+ ## 3. Arquivos
56
+
57
+ | Ação | Caminho |
58
+ |------|---------|
59
+ | CRIAR | \`src/foo.ts\` |
60
+
61
+ ## 4. Implementação
62
+
63
+ - [ ] Teste do caminho feliz
64
+ `);
65
+ const r = await analyzeTaskComplexity('task-001', tmp);
66
+ expect(r?.level).toBe('LOW');
67
+ expect(r?.recommendsSplit).toBe(false);
68
+ });
69
+ it('scores a big task as HIGH/CRITICAL', async () => {
70
+ await writeFile(tmp, 'DARE/EXECUTION/task-002.md', `
71
+ # Task 002
72
+
73
+ > **Complexidade:** HIGH
74
+
75
+ ## 3. Arquivos
76
+
77
+ | Ação | Caminho |
78
+ |------|---------|
79
+ | CRIAR | \`src/a.ts\` |
80
+ | CRIAR | \`src/b.ts\` |
81
+ | CRIAR | \`src/c.ts\` |
82
+ | CRIAR | \`src/d.ts\` |
83
+ | CRIAR | \`src/e.ts\` |
84
+ | CRIAR | \`src/f.ts\` |
85
+ | CRIAR | \`src/g.ts\` |
86
+ | MODIFICAR | \`tests/a.test.ts\` |
87
+
88
+ ## 4. Implementação
89
+
90
+ Implementar:
91
+ - \`POST /auth/register\`
92
+ - \`POST /auth/login\`
93
+ - \`POST /auth/refresh\`
94
+ - \`POST /auth/logout\`
95
+ - \`GET /auth/me\`
96
+
97
+ Vamos refactor o UserService e migrate o schema para suportar profile_settings.
98
+ Precisamos integrate com o serviço externo de email também.
99
+
100
+ - [ ] Teste do happy path
101
+ - [ ] Teste de email inválido
102
+ - [ ] Teste de senha fraca
103
+ - [ ] Teste de email duplicado
104
+ - [ ] Teste de rate limit
105
+ - [ ] Teste de refresh expirado
106
+ - [ ] Teste de logout idempotente
107
+ `);
108
+ const r = await analyzeTaskComplexity('task-002', tmp);
109
+ expect(['HIGH', 'CRITICAL']).toContain(r?.level);
110
+ expect(r?.recommendsSplit).toBe(true);
111
+ // Should attribute weight to multiple signal kinds
112
+ const kinds = r?.signals.map((s) => s.kind) ?? [];
113
+ expect(kinds).toContain('files');
114
+ expect(kinds).toContain('functions');
115
+ expect(kinds).toContain('tests');
116
+ expect(kinds).toContain('keywords');
117
+ expect(kinds).toContain('author-high');
118
+ });
119
+ it('counts depends_on when caller provides it', async () => {
120
+ await writeFile(tmp, 'DARE/EXECUTION/task-003.md', `## 3. Arquivos\n| CRIAR | \`a.ts\` |`);
121
+ const r0 = await analyzeTaskComplexity('task-003', tmp, { dependsOnCount: 0 });
122
+ const r4 = await analyzeTaskComplexity('task-003', tmp, { dependsOnCount: 4 });
123
+ expect((r4?.score ?? 0)).toBeGreaterThan(r0?.score ?? 0);
124
+ expect(r4?.signals.some((s) => s.kind === 'dependencies')).toBe(true);
125
+ });
126
+ it('honors custom thresholds from options', async () => {
127
+ await writeFile(tmp, 'DARE/EXECUTION/task-004.md', `| CRIAR | \`a.ts\` |\n| CRIAR | \`b.ts\` |`);
128
+ const r = await analyzeTaskComplexity('task-004', tmp, {
129
+ thresholds: { low: 0.5, med: 1, high: 1.5 },
130
+ });
131
+ expect(r?.level).toBe('CRITICAL'); // tiny score still tripped by aggressive thresholds
132
+ });
133
+ });
134
+ // ── proposeSplit ──────────────────────────────────────────────────────────────
135
+ describe('proposeSplit', () => {
136
+ it('returns empty proposal when no files listed', () => {
137
+ const p = proposeSplit('task-001', []);
138
+ expect(p.subtasks).toHaveLength(0);
139
+ expect(p.notes).toContain('Nenhum arquivo listado');
140
+ });
141
+ it('groups by top-level directory', () => {
142
+ const p = proposeSplit('task-002', [
143
+ 'src/auth/login.ts',
144
+ 'src/auth/register.ts',
145
+ 'src/users/profile.ts',
146
+ 'tests/auth/login.test.ts',
147
+ ]);
148
+ // 3 groups: src/auth, src/users, tests/auth
149
+ expect(p.subtasks).toHaveLength(3);
150
+ expect(p.subtasks.map((s) => s.id)).toEqual([
151
+ 'task-002a',
152
+ 'task-002b',
153
+ 'task-002c',
154
+ ]);
155
+ });
156
+ it('splits overlarge groups by maxFilesPerSubtask', () => {
157
+ const files = Array.from({ length: 9 }, (_, i) => `src/auth/file${i}.ts`);
158
+ const p = proposeSplit('task-003', files, { maxFilesPerSubtask: 3 });
159
+ // 9 files / 3 per chunk = 3 chunks (all from same group)
160
+ expect(p.subtasks).toHaveLength(3);
161
+ expect(p.subtasks.every((s) => s.files.length <= 3)).toBe(true);
162
+ });
163
+ it('assigns sequential letter suffixes', () => {
164
+ const p = proposeSplit('task-004', [
165
+ 'a/one.ts',
166
+ 'b/one.ts',
167
+ 'c/one.ts',
168
+ 'd/one.ts',
169
+ ]);
170
+ const ids = p.subtasks.map((s) => s.id);
171
+ expect(ids[0]).toBe('task-004a');
172
+ expect(ids[1]).toBe('task-004b');
173
+ expect(ids[2]).toBe('task-004c');
174
+ expect(ids[3]).toBe('task-004d');
175
+ });
176
+ it('preserves files within each sub-task', () => {
177
+ const p = proposeSplit('task-005', [
178
+ 'src/auth/a.ts',
179
+ 'src/auth/b.ts',
180
+ 'src/users/c.ts',
181
+ ]);
182
+ const authSub = p.subtasks.find((s) => s.title.includes('src/auth'));
183
+ expect(authSub?.files).toEqual(['src/auth/a.ts', 'src/auth/b.ts']);
184
+ });
185
+ });
186
+ //# sourceMappingURL=refine.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refine.test.js","sourceRoot":"","sources":["../../src/__tests__/refine.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=review.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/review.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,242 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import fs from 'fs-extra';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import { analyzeFile, isTestFile, runStaticAnalysis, } from '../utils/static-analyzer.js';
6
+ import { parseFilesFromSpec, runReview, } from '../utils/ReviewRunner.js';
7
+ // Temp dir helper — each test gets its own sandbox.
8
+ async function makeTempDir() {
9
+ return fs.mkdtemp(path.join(os.tmpdir(), 'dare-review-test-'));
10
+ }
11
+ async function writeFile(dir, rel, content) {
12
+ const abs = path.join(dir, rel);
13
+ await fs.ensureDir(path.dirname(abs));
14
+ await fs.writeFile(abs, content);
15
+ }
16
+ // ── isTestFile ────────────────────────────────────────────────────────────────
17
+ describe('isTestFile', () => {
18
+ it('matches *.test.ts', () => {
19
+ expect(isTestFile('src/foo.test.ts')).toBe(true);
20
+ expect(isTestFile('src/foo.spec.ts')).toBe(true);
21
+ });
22
+ it('matches __tests__ directories', () => {
23
+ expect(isTestFile('src/__tests__/foo.ts')).toBe(true);
24
+ expect(isTestFile('src\\__tests__\\foo.ts')).toBe(true);
25
+ });
26
+ it('matches Go/Python test conventions', () => {
27
+ expect(isTestFile('pkg/auth/auth_test.go')).toBe(true);
28
+ expect(isTestFile('tests/test_auth.py')).toBe(true);
29
+ });
30
+ it('rejects production files', () => {
31
+ expect(isTestFile('src/auth/login.ts')).toBe(false);
32
+ expect(isTestFile('src/controllers/users.go')).toBe(false);
33
+ });
34
+ });
35
+ // ── parseFilesFromSpec ────────────────────────────────────────────────────────
36
+ describe('parseFilesFromSpec', () => {
37
+ it('extracts files from a CRIAR/MODIFICAR table', () => {
38
+ const md = `
39
+ ## 3. ARQUIVOS
40
+
41
+ | Ação | Caminho | Descrição |
42
+ |------|---------|-----------|
43
+ | CRIAR | \`src/auth/login.ts\` | Login handler |
44
+ | MODIFICAR | \`src/routes.ts\` | Wire route |
45
+ | CRIAR | \`tests/auth.test.ts\` | Tests |
46
+ `;
47
+ expect(parseFilesFromSpec(md)).toEqual([
48
+ 'src/auth/login.ts',
49
+ 'src/routes.ts',
50
+ 'tests/auth.test.ts',
51
+ ]);
52
+ });
53
+ it('accepts English actions too', () => {
54
+ const md = `
55
+ | Action | Path |
56
+ | CREATE | \`a.ts\` |
57
+ | MODIFY | \`b.ts\` |
58
+ | UPDATE | \`c.ts\` |
59
+ `;
60
+ expect(parseFilesFromSpec(md)).toEqual(['a.ts', 'b.ts', 'c.ts']);
61
+ });
62
+ it('de-duplicates paths', () => {
63
+ const md = `
64
+ | MODIFICAR | \`src/a.ts\` |
65
+ | MODIFICAR | \`src/a.ts\` |
66
+ `;
67
+ expect(parseFilesFromSpec(md)).toEqual(['src/a.ts']);
68
+ });
69
+ it('ignores rows without a backtick path', () => {
70
+ const md = `
71
+ | CRIAR | descrição sem path | x |
72
+ | MODIFICAR | \`src/real.ts\` | x |
73
+ `;
74
+ expect(parseFilesFromSpec(md)).toEqual(['src/real.ts']);
75
+ });
76
+ });
77
+ // ── Static analyzer detectors ─────────────────────────────────────────────────
78
+ describe('static-analyzer: detectors', () => {
79
+ let tmp;
80
+ beforeEach(async () => {
81
+ tmp = await makeTempDir();
82
+ });
83
+ afterEach(async () => {
84
+ await fs.remove(tmp);
85
+ });
86
+ async function analyze(rel, content) {
87
+ await writeFile(tmp, rel, content);
88
+ return analyzeFile(path.join(tmp, rel), rel);
89
+ }
90
+ function kinds(report) {
91
+ return report.violations.map((v) => v.kind);
92
+ }
93
+ it('detects TODO/FIXME/XXX/HACK in comments', async () => {
94
+ const r = await analyze('src/a.ts', `// TODO: implement\nconst x = 1; // FIXME later\n// XXX broken\n/* HACK */`);
95
+ const found = kinds(r);
96
+ expect(found.filter((k) => k === 'todo-marker').length).toBeGreaterThanOrEqual(4);
97
+ });
98
+ it('ignores TODO inside string literals', async () => {
99
+ const r = await analyze('src/a.ts', `const msg = "TODO: not a real comment";\nconst real = 1;`);
100
+ expect(kinds(r)).not.toContain('todo-marker');
101
+ });
102
+ it('detects throw new Error("not implemented") and friends', async () => {
103
+ const r = await analyze('src/b.ts', `function x() { throw new Error('not implemented'); }\nfunction y() { throw new Error('todo'); }`);
104
+ const stubs = r.violations.filter((v) => v.kind === 'not-implemented-stub');
105
+ expect(stubs.length).toBeGreaterThanOrEqual(2);
106
+ });
107
+ it('detects Rust unimplemented!() and todo!()', async () => {
108
+ const r = await analyze('src/lib.rs', `fn a() { unimplemented!() }\nfn b() { todo!() }`);
109
+ expect(kinds(r)).toContain('not-implemented-stub');
110
+ });
111
+ it('detects Python raise NotImplementedError', async () => {
112
+ const r = await analyze('src/x.py', `def foo():\n raise NotImplementedError\n`);
113
+ expect(kinds(r)).toContain('not-implemented-stub');
114
+ });
115
+ it('detects empty function single-line (TS)', async () => {
116
+ const r = await analyze('src/c.ts', `function foo() {}\nconst bar = () => {};\nfunction baz() { /* real */ return 1; }`);
117
+ const empties = r.violations.filter((v) => v.kind === 'empty-function');
118
+ expect(empties.length).toBeGreaterThanOrEqual(1);
119
+ });
120
+ it('detects empty multi-line function (TS)', async () => {
121
+ const r = await analyze('src/d.ts', `function alpha() {\n}\nfunction beta() {\n const x = 1;\n return x;\n}`);
122
+ const empties = r.violations.filter((v) => v.kind === 'empty-function');
123
+ expect(empties.length).toBe(1);
124
+ });
125
+ it('detects Python def x(): pass', async () => {
126
+ const r = await analyze('src/e.py', `def foo():\n pass\n`);
127
+ expect(kinds(r)).toContain('empty-function');
128
+ });
129
+ it('detects phantom returns (only stmt is return null)', async () => {
130
+ const r = await analyze('src/f.ts', `function getUser(id: string) {\n return null;\n}\nfunction getOther() {\n const x = compute();\n return x;\n}`);
131
+ const phantoms = r.violations.filter((v) => v.kind === 'phantom-return');
132
+ expect(phantoms.length).toBe(1);
133
+ });
134
+ it('detects placeholder comments', async () => {
135
+ const r = await analyze('src/g.ts', `// implement later\n// stub\n# placeholder\n// fixme implement\nconst real = 1;`);
136
+ const placeholders = r.violations.filter((v) => v.kind === 'placeholder-comment');
137
+ expect(placeholders.length).toBeGreaterThanOrEqual(3);
138
+ });
139
+ it('detects production mocks (jest.fn, sinon.stub, vi.mock)', async () => {
140
+ const r = await analyze('src/h.ts', `const x = jest.fn();\nconst y = sinon.stub();\nvi.mock('foo');`);
141
+ const mocks = r.violations.filter((v) => v.kind === 'production-mock');
142
+ expect(mocks.length).toBeGreaterThanOrEqual(3);
143
+ });
144
+ it('does NOT flag mocks in test files', async () => {
145
+ const r = await analyze('src/h.test.ts', `const x = jest.fn();\nvi.mock('foo');`);
146
+ expect(r.isTestFile).toBe(true);
147
+ expect(kinds(r)).not.toContain('production-mock');
148
+ });
149
+ it('runs clean on a real-looking implementation', async () => {
150
+ const r = await analyze('src/auth/login.ts', `
151
+ import { hash } from 'crypto';
152
+
153
+ export async function login(email: string, password: string) {
154
+ if (!email || !password) {
155
+ throw new Error('email and password are required');
156
+ }
157
+ const user = await db.users.findOne({ email });
158
+ if (!user) return { ok: false, code: 401 };
159
+ const ok = await verify(user.passwordHash, password);
160
+ if (!ok) return { ok: false, code: 401 };
161
+ return { ok: true, token: signToken(user.id) };
162
+ }
163
+ `.trim());
164
+ expect(r.violations).toEqual([]);
165
+ });
166
+ });
167
+ // ── runStaticAnalysis + runReview end-to-end ──────────────────────────────────
168
+ describe('runStaticAnalysis', () => {
169
+ let tmp;
170
+ beforeEach(async () => {
171
+ tmp = await makeTempDir();
172
+ });
173
+ afterEach(async () => {
174
+ await fs.remove(tmp);
175
+ });
176
+ it('scans multiple files in parallel', async () => {
177
+ await writeFile(tmp, 'src/a.ts', `function x() {} // empty`);
178
+ await writeFile(tmp, 'src/b.ts', `// TODO\nconst y = 1;`);
179
+ await writeFile(tmp, 'src/c.ts', `export const PI = 3.14;`);
180
+ const reports = await runStaticAnalysis(tmp, ['src/a.ts', 'src/b.ts', 'src/c.ts']);
181
+ expect(reports).toHaveLength(3);
182
+ expect(reports[0].violations.length).toBeGreaterThan(0);
183
+ expect(reports[1].violations.length).toBeGreaterThan(0);
184
+ expect(reports[2].violations).toEqual([]);
185
+ });
186
+ it('returns clean report for missing files', async () => {
187
+ const reports = await runStaticAnalysis(tmp, ['does/not/exist.ts']);
188
+ expect(reports[0].violations).toEqual([]);
189
+ });
190
+ });
191
+ describe('runReview end-to-end', () => {
192
+ let tmp;
193
+ beforeEach(async () => {
194
+ tmp = await makeTempDir();
195
+ });
196
+ afterEach(async () => {
197
+ await fs.remove(tmp);
198
+ });
199
+ it('parses spec, scans listed files, fails on errors', async () => {
200
+ await writeFile(tmp, 'DARE/EXECUTION/task-001.md', `
201
+ ## 3. ARQUIVOS
202
+
203
+ | Ação | Caminho | Descrição |
204
+ |------|---------|-----------|
205
+ | CRIAR | \`src/foo.ts\` | Foo handler |
206
+ `);
207
+ await writeFile(tmp, 'src/foo.ts', `function foo() { throw new Error('not implemented'); }`);
208
+ const report = await runReview('task-001', { projectRoot: tmp });
209
+ expect(report.taskId).toBe('task-001');
210
+ expect(report.filesScanned).toEqual(['src/foo.ts']);
211
+ expect(report.failed).toBe(true);
212
+ expect(report.totals.errors).toBeGreaterThan(0);
213
+ });
214
+ it('passes when nothing is found', async () => {
215
+ await writeFile(tmp, 'DARE/EXECUTION/task-002.md', `| MODIFICAR | \`src/clean.ts\` | x |`);
216
+ await writeFile(tmp, 'src/clean.ts', `export const X = 1;`);
217
+ const report = await runReview('task-002', { projectRoot: tmp });
218
+ expect(report.failed).toBe(false);
219
+ expect(report.totals.errors).toBe(0);
220
+ });
221
+ it('merges --from-agent semantic verdict', async () => {
222
+ await writeFile(tmp, 'DARE/EXECUTION/task-003.md', `| MODIFICAR | \`src/clean.ts\` | x |`);
223
+ await writeFile(tmp, 'src/clean.ts', `export const X = 1;`);
224
+ await writeFile(tmp, 'verdict.json', JSON.stringify({
225
+ passed: false,
226
+ unmetCriteria: ['Missing password regex'],
227
+ notes: 'Stub-free but spec not satisfied',
228
+ }));
229
+ const report = await runReview('task-003', {
230
+ projectRoot: tmp,
231
+ fromAgent: path.join(tmp, 'verdict.json'),
232
+ });
233
+ expect(report.semantic?.passed).toBe(false);
234
+ expect(report.failed).toBe(true); // semantic failure flips it
235
+ });
236
+ it('returns empty report when no files can be resolved', async () => {
237
+ const report = await runReview('task-ghost', { projectRoot: tmp });
238
+ expect(report.filesScanned).toHaveLength(0);
239
+ expect(report.failed).toBe(false);
240
+ });
241
+ });
242
+ //# sourceMappingURL=review.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.test.js","sourceRoot":"","sources":["../../src/__tests__/review.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EACL,WAAW,EACX,UAAU,EACV,iBAAiB,GAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,kBAAkB,EAClB,SAAS,GACV,MAAM,0BAA0B,CAAC;AAGlC,oDAAoD;AACpD,KAAK,UAAU,WAAW;IACxB,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,GAAW,EAAE,OAAe;IAChE,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAChC,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACtC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACnC,CAAC;AAED,iFAAiF;AAEjF,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtD,MAAM,CAAC,UAAU,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,CAAC,UAAU,CAAC,uBAAuB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,CAAC,UAAU,CAAC,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,iFAAiF;AAEjF,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,EAAE,GAAG;;;;;;;;CAQd,CAAC;QACE,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YACrC,mBAAmB;YACnB,eAAe;YACf,oBAAoB;SACrB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,EAAE,GAAG;;;;;CAKd,CAAC;QACE,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,EAAE,GAAG;;;CAGd,CAAC;QACE,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,EAAE,GAAG;;;CAGd,CAAC;QACE,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,iFAAiF;AAEjF,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,IAAI,GAAW,CAAC;IAChB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,GAAG,GAAG,MAAM,WAAW,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,KAAK,UAAU,OAAO,CAAC,GAAW,EAAE,OAAe;QACjD,MAAM,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QACnC,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAC/C,CAAC;IAED,SAAS,KAAK,CAAC,MAAiD;QAC9D,OAAO,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IAED,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB,UAAU,EACV,4EAA4E,CAC7E,CAAC;QACF,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACvB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB,UAAU,EACV,0DAA0D,CAC3D,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB,UAAU,EACV,iGAAiG,CAClG,CAAC;QACF,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,sBAAsB,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB,YAAY,EACZ,iDAAiD,CAClD,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,6CAA6C,CAAC,CAAC;QACnF,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB,UAAU,EACV,mFAAmF,CACpF,CAAC;QACF,MAAM,OAAO,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QACxE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB,UAAU,EACV,0EAA0E,CAC3E,CAAC;QACF,MAAM,OAAO,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QACxE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,wBAAwB,CAAC,CAAC;QAC9D,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB,UAAU,EACV,kHAAkH,CACnH,CAAC;QACF,MAAM,QAAQ,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QACzE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB,UAAU,EACV,iFAAiF,CAClF,CAAC;QACF,MAAM,YAAY,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,CACtC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,qBAAqB,CACxC,CAAC;QACF,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB,UAAU,EACV,gEAAgE,CACjE,CAAC;QACF,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB,eAAe,EACf,uCAAuC,CACxC,CAAC;QACF,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB,mBAAmB,EACnB;;;;;;;;;;;;;OAaC,CAAC,IAAI,EAAE,CACT,CAAC;QACF,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,iFAAiF;AAEjF,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,IAAI,GAAW,CAAC;IAChB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,GAAG,GAAG,MAAM,WAAW,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,0BAA0B,CAAC,CAAC;QAC7D,MAAM,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,uBAAuB,CAAC,CAAC;QAC1D,MAAM,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,yBAAyB,CAAC,CAAC;QAE5D,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;QACnF,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAI,GAAW,CAAC;IAChB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,GAAG,GAAG,MAAM,WAAW,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,SAAS,CACb,GAAG,EACH,4BAA4B,EAC5B;;;;;;CAML,CACI,CAAC;QACF,MAAM,SAAS,CAAC,GAAG,EAAE,YAAY,EAAE,wDAAwD,CAAC,CAAC;QAE7F,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;QACjE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,SAAS,CACb,GAAG,EACH,4BAA4B,EAC5B,sCAAsC,CACvC,CAAC;QACF,MAAM,SAAS,CAAC,GAAG,EAAE,cAAc,EAAE,qBAAqB,CAAC,CAAC;QAE5D,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;QACjE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,SAAS,CACb,GAAG,EACH,4BAA4B,EAC5B,sCAAsC,CACvC,CAAC;QACF,MAAM,SAAS,CAAC,GAAG,EAAE,cAAc,EAAE,qBAAqB,CAAC,CAAC;QAC5D,MAAM,SAAS,CACb,GAAG,EACH,cAAc,EACd,IAAI,CAAC,SAAS,CAAC;YACb,MAAM,EAAE,KAAK;YACb,aAAa,EAAE,CAAC,wBAAwB,CAAC;YACzC,KAAK,EAAE,kCAAkC;SAC1C,CAAC,CACH,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE;YACzC,WAAW,EAAE,GAAG;YAChB,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC;SAC1C,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,4BAA4B;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,YAAY,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;QACnE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=update.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/update.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,150 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { compareVersions, isNewerThan, parseVersion, sortVersionsAscending, } from '../utils/version-compare.js';
3
+ import { buildUpdatePlan, changeAppliesToIde, LEGACY_BASELINE_VERSION, resolveProjectVersion, } from '../utils/UpdateDetector.js';
4
+ describe('version-compare', () => {
5
+ it('parses semver strings', () => {
6
+ expect(parseVersion('2.17.0')).toEqual({ major: 2, minor: 17, patch: 0 });
7
+ expect(parseVersion('10.0.42')).toEqual({ major: 10, minor: 0, patch: 42 });
8
+ });
9
+ it('rejects invalid versions', () => {
10
+ expect(() => parseVersion('abc')).toThrow();
11
+ expect(() => parseVersion('1.2')).toThrow();
12
+ });
13
+ it('compares versions', () => {
14
+ expect(compareVersions('1.0.0', '1.0.0')).toBe(0);
15
+ expect(compareVersions('1.0.0', '1.0.1')).toBe(-1);
16
+ expect(compareVersions('2.0.0', '1.99.99')).toBe(1);
17
+ expect(compareVersions('2.17.0', '2.16.0')).toBe(1);
18
+ });
19
+ it('isNewerThan is strict', () => {
20
+ expect(isNewerThan('2.17.0', '2.16.0')).toBe(true);
21
+ expect(isNewerThan('2.16.0', '2.16.0')).toBe(false);
22
+ expect(isNewerThan('2.15.0', '2.16.0')).toBe(false);
23
+ });
24
+ it('sorts versions ascending', () => {
25
+ expect(sortVersionsAscending(['2.17.0', '2.16.0', '3.0.0', '2.16.1'])).toEqual([
26
+ '2.16.0',
27
+ '2.16.1',
28
+ '2.17.0',
29
+ '3.0.0',
30
+ ]);
31
+ });
32
+ });
33
+ describe('resolveProjectVersion', () => {
34
+ it('returns the version as-is for real DARE versions', () => {
35
+ expect(resolveProjectVersion({ version: '2.17.0' })).toEqual({
36
+ version: '2.17.0',
37
+ isLegacy: false,
38
+ });
39
+ });
40
+ it('treats hardcoded placeholder "0.1.0" as legacy', () => {
41
+ expect(resolveProjectVersion({ version: '0.1.0' })).toEqual({
42
+ version: LEGACY_BASELINE_VERSION,
43
+ isLegacy: true,
44
+ });
45
+ });
46
+ it('treats missing version as legacy', () => {
47
+ expect(resolveProjectVersion({})).toEqual({
48
+ version: LEGACY_BASELINE_VERSION,
49
+ isLegacy: true,
50
+ });
51
+ });
52
+ });
53
+ describe('changeAppliesToIde', () => {
54
+ const baseChange = {
55
+ type: 'modified',
56
+ path: 'x',
57
+ description: '',
58
+ };
59
+ it("wildcard '*' applies to every IDE", () => {
60
+ expect(changeAppliesToIde({ ...baseChange, appliesTo: ['*'] }, 'cursor')).toBe(true);
61
+ expect(changeAppliesToIde({ ...baseChange }, 'antigravity')).toBe(true); // default
62
+ });
63
+ it('exact ide match', () => {
64
+ expect(changeAppliesToIde({ ...baseChange, appliesTo: ['cursor'] }, 'cursor')).toBe(true);
65
+ expect(changeAppliesToIde({ ...baseChange, appliesTo: ['cursor'] }, 'antigravity')).toBe(false);
66
+ });
67
+ it("'hybrid' inherits cursor + antigravity", () => {
68
+ expect(changeAppliesToIde({ ...baseChange, appliesTo: ['cursor'] }, 'hybrid')).toBe(true);
69
+ expect(changeAppliesToIde({ ...baseChange, appliesTo: ['antigravity'] }, 'hybrid')).toBe(true);
70
+ expect(changeAppliesToIde({ ...baseChange, appliesTo: ['claude-code'] }, 'hybrid')).toBe(false);
71
+ });
72
+ it("'claude-hybrid' inherits claude-code + cursor", () => {
73
+ expect(changeAppliesToIde({ ...baseChange, appliesTo: ['claude-code'] }, 'claude-hybrid')).toBe(true);
74
+ expect(changeAppliesToIde({ ...baseChange, appliesTo: ['cursor'] }, 'claude-hybrid')).toBe(true);
75
+ expect(changeAppliesToIde({ ...baseChange, appliesTo: ['antigravity'] }, 'claude-hybrid')).toBe(false);
76
+ });
77
+ });
78
+ describe('buildUpdatePlan', () => {
79
+ const manifest = {
80
+ schemaVersion: 1,
81
+ releases: {
82
+ '2.16.0': {
83
+ releasedAt: '2026-05-10',
84
+ summary: 'A',
85
+ changelog: 'A',
86
+ changes: [],
87
+ },
88
+ '2.17.0': {
89
+ releasedAt: '2026-05-15',
90
+ summary: 'B',
91
+ changelog: 'B',
92
+ changes: [
93
+ {
94
+ type: 'modified',
95
+ path: 'shared.md',
96
+ description: '',
97
+ appliesTo: ['*'],
98
+ },
99
+ {
100
+ type: 'added',
101
+ path: '.cursor/commands/x.md',
102
+ description: '',
103
+ appliesTo: ['cursor'],
104
+ },
105
+ {
106
+ type: 'added',
107
+ path: '.agents/skills/y.md',
108
+ description: '',
109
+ appliesTo: ['antigravity'],
110
+ },
111
+ ],
112
+ },
113
+ '2.18.0': {
114
+ releasedAt: '2026-06-01',
115
+ summary: 'C',
116
+ changelog: 'C',
117
+ changes: [
118
+ {
119
+ type: 'modified',
120
+ path: 'other.md',
121
+ description: '',
122
+ },
123
+ ],
124
+ },
125
+ },
126
+ };
127
+ it('includes only versions strictly newer than fromVersion', () => {
128
+ const plan = buildUpdatePlan(manifest, '2.16.0', '2.18.0', 'cursor');
129
+ const versions = plan.pendingReleases.map((r) => r.version);
130
+ expect(versions).toEqual(['2.17.0', '2.18.0']);
131
+ });
132
+ it('excludes versions newer than toVersion', () => {
133
+ const plan = buildUpdatePlan(manifest, '2.16.0', '2.17.0', 'cursor');
134
+ const versions = plan.pendingReleases.map((r) => r.version);
135
+ expect(versions).toEqual(['2.17.0']);
136
+ });
137
+ it('filters changes by IDE', () => {
138
+ const plan = buildUpdatePlan(manifest, '2.16.0', '2.17.0', 'cursor');
139
+ const paths = plan.applicableChanges.map((c) => c.path);
140
+ expect(paths).toContain('shared.md');
141
+ expect(paths).toContain('.cursor/commands/x.md');
142
+ expect(paths).not.toContain('.agents/skills/y.md');
143
+ });
144
+ it('returns empty plan when up to date', () => {
145
+ const plan = buildUpdatePlan(manifest, '2.18.0', '2.18.0', 'cursor');
146
+ expect(plan.pendingReleases).toHaveLength(0);
147
+ expect(plan.applicableChanges).toHaveLength(0);
148
+ });
149
+ });
150
+ //# sourceMappingURL=update.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.test.js","sourceRoot":"","sources":["../../src/__tests__/update.test.ts"],"names":[],"mappings":"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"}