@massu/core 0.1.1 → 0.4.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 (151) hide show
  1. package/commands/_shared-preamble.md +76 -0
  2. package/commands/massu-audit-deps.md +211 -0
  3. package/commands/massu-changelog.md +174 -0
  4. package/commands/massu-cleanup.md +315 -0
  5. package/commands/massu-commit.md +481 -0
  6. package/commands/massu-create-plan.md +752 -0
  7. package/commands/massu-dead-code.md +131 -0
  8. package/commands/massu-debug.md +484 -0
  9. package/commands/massu-deploy.md +91 -0
  10. package/commands/massu-deps.md +374 -0
  11. package/commands/massu-doc-gen.md +279 -0
  12. package/commands/massu-docs.md +364 -0
  13. package/commands/massu-estimate.md +313 -0
  14. package/commands/massu-golden-path.md +973 -0
  15. package/commands/massu-guide.md +167 -0
  16. package/commands/massu-hotfix.md +480 -0
  17. package/commands/massu-loop-playwright.md +837 -0
  18. package/commands/massu-loop.md +775 -0
  19. package/commands/massu-new-feature.md +511 -0
  20. package/commands/massu-parity.md +214 -0
  21. package/commands/massu-plan.md +456 -0
  22. package/commands/massu-push-light.md +207 -0
  23. package/commands/massu-push.md +434 -0
  24. package/commands/massu-refactor.md +410 -0
  25. package/commands/massu-release.md +363 -0
  26. package/commands/massu-review.md +238 -0
  27. package/commands/massu-simplify.md +281 -0
  28. package/commands/massu-status.md +278 -0
  29. package/commands/massu-tdd.md +201 -0
  30. package/commands/massu-test.md +516 -0
  31. package/commands/massu-verify-playwright.md +281 -0
  32. package/commands/massu-verify.md +667 -0
  33. package/dist/cli.js +7772 -3140
  34. package/dist/hooks/cost-tracker.js +103 -40
  35. package/dist/hooks/post-edit-context.js +74 -8
  36. package/dist/hooks/post-tool-use.js +268 -106
  37. package/dist/hooks/pre-compact.js +167 -43
  38. package/dist/hooks/pre-delete-check.js +159 -42
  39. package/dist/hooks/quality-event.js +103 -40
  40. package/dist/hooks/security-gate.js +29 -0
  41. package/dist/hooks/session-end.js +143 -84
  42. package/dist/hooks/session-start.js +186 -49
  43. package/dist/hooks/user-prompt.js +189 -43
  44. package/package.json +10 -15
  45. package/src/adr-generator.ts +9 -2
  46. package/src/analytics.ts +9 -3
  47. package/src/audit-trail.ts +10 -3
  48. package/src/backfill-sessions.ts +5 -4
  49. package/src/cli.ts +6 -0
  50. package/src/cloud-sync.ts +14 -18
  51. package/src/commands/doctor.ts +193 -6
  52. package/src/commands/init.ts +230 -5
  53. package/src/commands/install-commands.ts +137 -0
  54. package/src/config.ts +68 -2
  55. package/src/cost-tracker.ts +11 -6
  56. package/src/db.ts +115 -2
  57. package/src/dependency-scorer.ts +9 -2
  58. package/src/docs-tools.ts +21 -16
  59. package/src/hooks/post-edit-context.ts +4 -4
  60. package/src/hooks/post-tool-use.ts +130 -0
  61. package/src/hooks/pre-compact.ts +23 -1
  62. package/src/hooks/pre-delete-check.ts +92 -4
  63. package/src/hooks/security-gate.ts +32 -0
  64. package/src/hooks/session-end.ts +3 -3
  65. package/src/hooks/session-start.ts +99 -6
  66. package/src/hooks/user-prompt.ts +46 -1
  67. package/src/import-resolver.ts +2 -1
  68. package/src/knowledge-db.ts +169 -0
  69. package/src/knowledge-indexer.ts +704 -0
  70. package/src/knowledge-tools.ts +1413 -0
  71. package/src/license.ts +482 -0
  72. package/src/memory-db.ts +1364 -23
  73. package/src/memory-tools.ts +14 -15
  74. package/src/observability-tools.ts +13 -2
  75. package/src/observation-extractor.ts +11 -4
  76. package/src/page-deps.ts +3 -2
  77. package/src/prompt-analyzer.ts +9 -2
  78. package/src/python/coupling-detector.ts +124 -0
  79. package/src/python/domain-enforcer.ts +83 -0
  80. package/src/python/impact-analyzer.ts +95 -0
  81. package/src/python/import-parser.ts +244 -0
  82. package/src/python/import-resolver.ts +135 -0
  83. package/src/python/migration-indexer.ts +115 -0
  84. package/src/python/migration-parser.ts +332 -0
  85. package/src/python/model-indexer.ts +70 -0
  86. package/src/python/model-parser.ts +279 -0
  87. package/src/python/route-indexer.ts +58 -0
  88. package/src/python/route-parser.ts +317 -0
  89. package/src/python-tools.ts +629 -0
  90. package/src/regression-detector.ts +9 -3
  91. package/src/security-scorer.ts +9 -2
  92. package/src/sentinel-db.ts +45 -89
  93. package/src/sentinel-tools.ts +8 -11
  94. package/src/server.ts +29 -7
  95. package/src/session-archiver.ts +4 -5
  96. package/src/team-knowledge.ts +9 -2
  97. package/src/tools.ts +1032 -44
  98. package/src/validate-features-runner.ts +0 -1
  99. package/src/validation-engine.ts +9 -2
  100. package/README.md +0 -40
  101. package/dist/server.js +0 -7008
  102. package/src/__tests__/adr-generator.test.ts +0 -260
  103. package/src/__tests__/analytics.test.ts +0 -282
  104. package/src/__tests__/audit-trail.test.ts +0 -382
  105. package/src/__tests__/backfill-sessions.test.ts +0 -690
  106. package/src/__tests__/cli.test.ts +0 -290
  107. package/src/__tests__/cloud-sync.test.ts +0 -261
  108. package/src/__tests__/config-sections.test.ts +0 -359
  109. package/src/__tests__/config.test.ts +0 -732
  110. package/src/__tests__/cost-tracker.test.ts +0 -348
  111. package/src/__tests__/db.test.ts +0 -177
  112. package/src/__tests__/dependency-scorer.test.ts +0 -325
  113. package/src/__tests__/docs-integration.test.ts +0 -178
  114. package/src/__tests__/docs-tools.test.ts +0 -199
  115. package/src/__tests__/domains.test.ts +0 -236
  116. package/src/__tests__/hooks.test.ts +0 -221
  117. package/src/__tests__/import-resolver.test.ts +0 -95
  118. package/src/__tests__/integration/path-traversal.test.ts +0 -134
  119. package/src/__tests__/integration/pricing-consistency.test.ts +0 -88
  120. package/src/__tests__/integration/tool-registration.test.ts +0 -146
  121. package/src/__tests__/memory-db.test.ts +0 -404
  122. package/src/__tests__/memory-enhancements.test.ts +0 -316
  123. package/src/__tests__/memory-tools.test.ts +0 -199
  124. package/src/__tests__/middleware-tree.test.ts +0 -177
  125. package/src/__tests__/observability-tools.test.ts +0 -595
  126. package/src/__tests__/observability.test.ts +0 -437
  127. package/src/__tests__/observation-extractor.test.ts +0 -167
  128. package/src/__tests__/page-deps.test.ts +0 -60
  129. package/src/__tests__/prompt-analyzer.test.ts +0 -298
  130. package/src/__tests__/regression-detector.test.ts +0 -295
  131. package/src/__tests__/rules.test.ts +0 -87
  132. package/src/__tests__/schema-mapper.test.ts +0 -29
  133. package/src/__tests__/security-scorer.test.ts +0 -238
  134. package/src/__tests__/security-utils.test.ts +0 -175
  135. package/src/__tests__/sentinel-db.test.ts +0 -491
  136. package/src/__tests__/sentinel-scanner.test.ts +0 -750
  137. package/src/__tests__/sentinel-tools.test.ts +0 -324
  138. package/src/__tests__/sentinel-types.test.ts +0 -750
  139. package/src/__tests__/server.test.ts +0 -452
  140. package/src/__tests__/session-archiver.test.ts +0 -524
  141. package/src/__tests__/session-state-generator.test.ts +0 -900
  142. package/src/__tests__/team-knowledge.test.ts +0 -327
  143. package/src/__tests__/tools.test.ts +0 -340
  144. package/src/__tests__/transcript-parser.test.ts +0 -195
  145. package/src/__tests__/trpc-index.test.ts +0 -25
  146. package/src/__tests__/validate-features-runner.test.ts +0 -517
  147. package/src/__tests__/validation-engine.test.ts +0 -300
  148. package/src/core-tools.ts +0 -685
  149. package/src/memory-queries.ts +0 -804
  150. package/src/memory-schema.ts +0 -546
  151. package/src/tool-helpers.ts +0 -41
@@ -1,300 +0,0 @@
1
- // Copyright (c) 2026 Massu. All rights reserved.
2
- // Licensed under BSL 1.1 - see LICENSE file for details.
3
-
4
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
5
- import Database from 'better-sqlite3';
6
- import { mkdirSync, writeFileSync, rmSync } from 'fs';
7
- import { join } from 'path';
8
- import {
9
- getValidationToolDefinitions,
10
- isValidationTool,
11
- validateFile,
12
- storeValidationResult,
13
- handleValidationToolCall,
14
- type ValidationCheck,
15
- } from '../validation-engine.ts';
16
-
17
- function createTestDb(): Database.Database {
18
- const db = new Database(':memory:');
19
- db.pragma('journal_mode = WAL');
20
-
21
- db.exec(`
22
- CREATE TABLE sessions (
23
- id INTEGER PRIMARY KEY AUTOINCREMENT,
24
- session_id TEXT UNIQUE NOT NULL,
25
- started_at TEXT NOT NULL,
26
- started_at_epoch INTEGER NOT NULL
27
- );
28
-
29
- CREATE TABLE validation_results (
30
- id INTEGER PRIMARY KEY AUTOINCREMENT,
31
- session_id TEXT,
32
- file_path TEXT NOT NULL,
33
- validation_type TEXT NOT NULL,
34
- passed INTEGER NOT NULL DEFAULT 1,
35
- details TEXT,
36
- rules_violated TEXT,
37
- created_at TEXT DEFAULT (datetime('now'))
38
- );
39
- `);
40
-
41
- return db;
42
- }
43
-
44
- describe('validation-engine', () => {
45
- let db: Database.Database;
46
- let testDir: string;
47
-
48
- beforeEach(() => {
49
- db = createTestDb();
50
- testDir = join('/tmp', 'massu-test-' + Math.random().toString(36).slice(2));
51
- mkdirSync(testDir, { recursive: true });
52
- });
53
-
54
- afterEach(() => {
55
- db.close();
56
- try {
57
- rmSync(testDir, { recursive: true, force: true });
58
- } catch {
59
- // Ignore cleanup errors
60
- }
61
- });
62
-
63
- describe('getValidationToolDefinitions', () => {
64
- it('should return tool definitions for validation tools', () => {
65
- const defs = getValidationToolDefinitions();
66
- expect(defs.length).toBe(2);
67
-
68
- const names = defs.map(d => d.name);
69
- expect(names.some(n => n.includes('validation_check'))).toBe(true);
70
- expect(names.some(n => n.includes('validation_report'))).toBe(true);
71
-
72
- for (const def of defs) {
73
- expect(def.name).toBeTruthy();
74
- expect(def.description).toBeTruthy();
75
- expect(def.inputSchema).toBeTruthy();
76
- expect(def.inputSchema.type).toBe('object');
77
- }
78
- });
79
- });
80
-
81
- describe('isValidationTool', () => {
82
- it('should return true for validation tools', () => {
83
- expect(isValidationTool('massu_validation_check')).toBe(true);
84
- expect(isValidationTool('massu_validation_report')).toBe(true);
85
- });
86
-
87
- it('should return false for non-validation tools', () => {
88
- expect(isValidationTool('massu_cost_session')).toBe(false);
89
- expect(isValidationTool('massu_quality_score')).toBe(false);
90
- expect(isValidationTool('random_tool')).toBe(false);
91
- });
92
-
93
- it('should handle base names without prefix', () => {
94
- expect(isValidationTool('validation_check')).toBe(true);
95
- expect(isValidationTool('validation_report')).toBe(true);
96
- });
97
- });
98
-
99
- describe('validateFile', () => {
100
- it('should return error check for non-existent file', () => {
101
- const filePath = join(testDir, 'nonexistent.ts');
102
- const checks = validateFile(filePath, testDir);
103
-
104
- expect(checks.length).toBeGreaterThan(0);
105
- const fileCheck = checks.find(c => c.name === 'file_exists');
106
- expect(fileCheck).toBeDefined();
107
- expect(fileCheck?.severity).toBe('error');
108
- });
109
-
110
- it('should block path traversal attempts', () => {
111
- const filePath = '../../../etc/passwd';
112
- const checks = validateFile(filePath, testDir);
113
-
114
- expect(checks.length).toBeGreaterThan(0);
115
- const pathCheck = checks.find(c => c.name === 'path_traversal');
116
- expect(pathCheck).toBeDefined();
117
- expect(pathCheck?.severity).toBe('critical');
118
- });
119
-
120
- it('should validate existing file', () => {
121
- const filePath = join(testDir, 'test.ts');
122
- writeFileSync(filePath, `
123
- // Simple test file
124
- export function hello() {
125
- return "world";
126
- }
127
- `.trim());
128
-
129
- const checks = validateFile(filePath, testDir);
130
-
131
- // Should not have critical errors
132
- const criticalErrors = checks.filter(c => c.severity === 'critical' || c.severity === 'error');
133
- expect(criticalErrors.length).toBe(0);
134
- });
135
-
136
- it('should detect import hallucinations', () => {
137
- const filePath = join(testDir, 'imports.ts');
138
- writeFileSync(filePath, `
139
- import { something } from './nonexistent.ts';
140
- import { other } from '@/fake-module.ts';
141
- `.trim());
142
-
143
- const checks = validateFile(filePath, testDir);
144
-
145
- const importErrors = checks.filter(c => c.name === 'import_hallucination');
146
- expect(importErrors.length).toBeGreaterThan(0);
147
- expect(importErrors[0].severity).toBe('error');
148
- });
149
- });
150
-
151
- describe('storeValidationResult', () => {
152
- it('should store validation result in database', () => {
153
- const sessionId = 'test-session-1';
154
- db.prepare('INSERT INTO sessions (session_id, started_at, started_at_epoch) VALUES (?, ?, ?)').run(
155
- sessionId,
156
- new Date().toISOString(),
157
- Math.floor(Date.now() / 1000)
158
- );
159
-
160
- const checks: ValidationCheck[] = [
161
- {
162
- name: 'import_hallucination',
163
- severity: 'error',
164
- message: 'Import not found',
165
- line: 1,
166
- file: 'test.ts',
167
- },
168
- {
169
- name: 'rule_compliance',
170
- severity: 'warning',
171
- message: 'Rule violation',
172
- file: 'test.ts',
173
- },
174
- ];
175
-
176
- storeValidationResult(db, 'test.ts', checks, sessionId);
177
-
178
- const results = db.prepare('SELECT * FROM validation_results WHERE session_id = ?').all(sessionId) as Array<Record<string, unknown>>;
179
- expect(results.length).toBe(1);
180
- expect(results[0].file_path).toBe('test.ts');
181
- expect(results[0].passed).toBe(0); // Has errors
182
- expect(results[0].details).toBeTruthy();
183
-
184
- const details = JSON.parse(results[0].details as string);
185
- expect(details.length).toBe(2);
186
- });
187
-
188
- it('should mark as passed when no errors', () => {
189
- const sessionId = 'test-session-2';
190
- db.prepare('INSERT INTO sessions (session_id, started_at, started_at_epoch) VALUES (?, ?, ?)').run(
191
- sessionId,
192
- new Date().toISOString(),
193
- Math.floor(Date.now() / 1000)
194
- );
195
-
196
- const checks: ValidationCheck[] = [
197
- {
198
- name: 'rule_applicable',
199
- severity: 'info',
200
- message: 'Rule applies',
201
- file: 'test.ts',
202
- },
203
- ];
204
-
205
- storeValidationResult(db, 'test.ts', checks, sessionId);
206
-
207
- const results = db.prepare('SELECT * FROM validation_results WHERE session_id = ?').all(sessionId) as Array<Record<string, unknown>>;
208
- expect(results.length).toBe(1);
209
- expect(results[0].passed).toBe(1); // No errors
210
- });
211
-
212
- it('should record violated rules', () => {
213
- const sessionId = 'test-session-3';
214
- db.prepare('INSERT INTO sessions (session_id, started_at, started_at_epoch) VALUES (?, ?, ?)').run(
215
- sessionId,
216
- new Date().toISOString(),
217
- Math.floor(Date.now() / 1000)
218
- );
219
-
220
- const checks: ValidationCheck[] = [
221
- {
222
- name: 'import_hallucination',
223
- severity: 'error',
224
- message: 'Import not found',
225
- file: 'test.ts',
226
- },
227
- {
228
- name: 'db_access_pattern',
229
- severity: 'warning',
230
- message: 'Wrong pattern',
231
- file: 'test.ts',
232
- },
233
- ];
234
-
235
- storeValidationResult(db, 'test.ts', checks, sessionId);
236
-
237
- const results = db.prepare('SELECT * FROM validation_results WHERE session_id = ?').all(sessionId) as Array<Record<string, unknown>>;
238
- expect(results[0].rules_violated).toBeTruthy();
239
- expect((results[0].rules_violated as string).includes('import_hallucination')).toBe(true);
240
- expect((results[0].rules_violated as string).includes('db_access_pattern')).toBe(true);
241
- });
242
- });
243
-
244
- describe('handleValidationToolCall', () => {
245
- it('should handle validation_check tool call for non-existent file', () => {
246
- const filePath = join(testDir, 'nonexistent.ts');
247
- const result = handleValidationToolCall('massu_validation_check', { file: filePath }, db);
248
-
249
- expect(result.content).toBeDefined();
250
- expect(result.content.length).toBeGreaterThan(0);
251
- expect(result.content[0].type).toBe('text');
252
- const text = result.content[0].text;
253
- expect(text).toContain('Validation');
254
- expect(text).toContain('Errors');
255
- });
256
-
257
- it('should return error for missing file parameter', () => {
258
- const result = handleValidationToolCall('massu_validation_check', {}, db);
259
-
260
- expect(result.content).toBeDefined();
261
- expect(result.content[0].type).toBe('text');
262
- expect(result.content[0].text).toContain('Usage');
263
- });
264
-
265
- it('should handle validation_report tool call', () => {
266
- const sessionId = 'report-session';
267
- db.prepare('INSERT INTO sessions (session_id, started_at, started_at_epoch) VALUES (?, ?, ?)').run(
268
- sessionId,
269
- new Date().toISOString(),
270
- Math.floor(Date.now() / 1000)
271
- );
272
-
273
- const checks: ValidationCheck[] = [
274
- {
275
- name: 'test_error',
276
- severity: 'error',
277
- message: 'Test error',
278
- file: 'test.ts',
279
- },
280
- ];
281
-
282
- storeValidationResult(db, 'test.ts', checks, sessionId);
283
-
284
- const result = handleValidationToolCall('massu_validation_report', { days: 7 }, db);
285
-
286
- expect(result.content).toBeDefined();
287
- expect(result.content[0].type).toBe('text');
288
- const text = result.content[0].text;
289
- expect(text).toContain('Validation Report');
290
- });
291
-
292
- it('should handle unknown tool name', () => {
293
- const result = handleValidationToolCall('massu_unknown_validation_tool', {}, db);
294
-
295
- expect(result.content).toBeDefined();
296
- expect(result.content[0].type).toBe('text');
297
- expect(result.content[0].text).toContain('Unknown validation tool');
298
- });
299
- });
300
- });