@massu/core 1.10.5 → 1.10.7

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.
@@ -24,6 +24,7 @@ import type {
24
24
  } from './sentinel-types.ts';
25
25
  import { getProjectRoot } from './config.ts';
26
26
  import { sanitizeFts5Query } from './memory-db.ts';
27
+ import { t } from './lib/sql-table-names.ts';
27
28
 
28
29
  // ============================================================
29
30
  // Sentinel: Feature Registry Data Access Layer
@@ -63,11 +64,11 @@ function toFeature(row: Record<string, unknown>): Feature {
63
64
  // ============================================================
64
65
 
65
66
  export function upsertFeature(db: Database.Database, input: FeatureInput): number {
66
- const existing = db.prepare('SELECT id FROM massu_sentinel WHERE feature_key = ?').get(input.feature_key) as { id: number } | undefined;
67
+ const existing = db.prepare(`SELECT id FROM ${t('sentinel')} WHERE feature_key = ?`).get(input.feature_key) as { id: number } | undefined;
67
68
 
68
69
  if (existing) {
69
70
  db.prepare(`
70
- UPDATE massu_sentinel SET
71
+ UPDATE ${t('sentinel')} SET
71
72
  domain = ?, subdomain = ?, title = ?, description = ?,
72
73
  status = COALESCE(?, status), priority = COALESCE(?, priority),
73
74
  portal_scope = COALESCE(?, portal_scope),
@@ -87,7 +88,7 @@ export function upsertFeature(db: Database.Database, input: FeatureInput): numbe
87
88
  }
88
89
 
89
90
  const result = db.prepare(`
90
- INSERT INTO massu_sentinel (feature_key, domain, subdomain, title, description, status, priority, portal_scope)
91
+ INSERT INTO ${t('sentinel')} (feature_key, domain, subdomain, title, description, status, priority, portal_scope)
91
92
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
92
93
  `).run(
93
94
  input.feature_key,
@@ -104,12 +105,12 @@ export function upsertFeature(db: Database.Database, input: FeatureInput): numbe
104
105
  }
105
106
 
106
107
  export function getFeature(db: Database.Database, featureKey: string): Feature | null {
107
- const row = db.prepare('SELECT * FROM massu_sentinel WHERE feature_key = ?').get(featureKey) as Record<string, unknown> | undefined;
108
+ const row = db.prepare(`SELECT * FROM ${t('sentinel')} WHERE feature_key = ?`).get(featureKey) as Record<string, unknown> | undefined;
108
109
  return row ? toFeature(row) : null;
109
110
  }
110
111
 
111
112
  export function getFeatureById(db: Database.Database, id: number): Feature | null {
112
- const row = db.prepare('SELECT * FROM massu_sentinel WHERE id = ?').get(id) as Record<string, unknown> | undefined;
113
+ const row = db.prepare(`SELECT * FROM ${t('sentinel')} WHERE id = ?`).get(id) as Record<string, unknown> | undefined;
113
114
  return row ? toFeature(row) : null;
114
115
  }
115
116
 
@@ -129,21 +130,21 @@ export function searchFeatures(
129
130
  // FTS5 search
130
131
  sql = `
131
132
  SELECT s.*, fts.rank,
132
- (SELECT COUNT(*) FROM massu_sentinel_components WHERE feature_id = s.id) as component_count,
133
- (SELECT COUNT(*) FROM massu_sentinel_procedures WHERE feature_id = s.id) as procedure_count,
134
- (SELECT COUNT(*) FROM massu_sentinel_pages WHERE feature_id = s.id) as page_count
135
- FROM massu_sentinel s
136
- JOIN massu_sentinel_fts fts ON s.id = fts.rowid
137
- WHERE massu_sentinel_fts MATCH ?
133
+ (SELECT COUNT(*) FROM ${t('sentinel_components')} WHERE feature_id = s.id) as component_count,
134
+ (SELECT COUNT(*) FROM ${t('sentinel_procedures')} WHERE feature_id = s.id) as procedure_count,
135
+ (SELECT COUNT(*) FROM ${t('sentinel_pages')} WHERE feature_id = s.id) as page_count
136
+ FROM ${t('sentinel')} s
137
+ JOIN ${t('sentinel_fts')} fts ON s.id = fts.rowid
138
+ WHERE ${t('sentinel_fts')} MATCH ?
138
139
  `;
139
140
  params.push(sanitizeFts5Query(query));
140
141
  } else {
141
142
  sql = `
142
143
  SELECT s.*,
143
- (SELECT COUNT(*) FROM massu_sentinel_components WHERE feature_id = s.id) as component_count,
144
- (SELECT COUNT(*) FROM massu_sentinel_procedures WHERE feature_id = s.id) as procedure_count,
145
- (SELECT COUNT(*) FROM massu_sentinel_pages WHERE feature_id = s.id) as page_count
146
- FROM massu_sentinel s
144
+ (SELECT COUNT(*) FROM ${t('sentinel_components')} WHERE feature_id = s.id) as component_count,
145
+ (SELECT COUNT(*) FROM ${t('sentinel_procedures')} WHERE feature_id = s.id) as procedure_count,
146
+ (SELECT COUNT(*) FROM ${t('sentinel_pages')} WHERE feature_id = s.id) as page_count
147
+ FROM ${t('sentinel')} s
147
148
  WHERE 1=1
148
149
  `;
149
150
  }
@@ -166,7 +167,7 @@ export function searchFeatures(
166
167
  params.push(`%"${escapedPortal}"%`);
167
168
  }
168
169
  if (filters?.page_route) {
169
- sql += ' AND s.id IN (SELECT feature_id FROM massu_sentinel_pages WHERE page_route = ?)';
170
+ sql += ` AND s.id IN (SELECT feature_id FROM ${t('sentinel_pages')} WHERE page_route = ?)`;
170
171
  params.push(filters.page_route);
171
172
  }
172
173
 
@@ -182,14 +183,14 @@ export function searchFeatures(
182
183
  }
183
184
 
184
185
  export function getFeaturesByDomain(db: Database.Database, domain: string): Feature[] {
185
- const rows = db.prepare('SELECT * FROM massu_sentinel WHERE domain = ? ORDER BY subdomain, feature_key').all(domain) as Record<string, unknown>[];
186
+ const rows = db.prepare(`SELECT * FROM ${t('sentinel')} WHERE domain = ? ORDER BY subdomain, feature_key`).all(domain) as Record<string, unknown>[];
186
187
  return rows.map(toFeature);
187
188
  }
188
189
 
189
190
  export function getFeaturesByFile(db: Database.Database, filePath: string): Feature[] {
190
191
  const rows = db.prepare(`
191
- SELECT DISTINCT s.* FROM massu_sentinel s
192
- JOIN massu_sentinel_components c ON c.feature_id = s.id
192
+ SELECT DISTINCT s.* FROM ${t('sentinel')} s
193
+ JOIN ${t('sentinel_components')} c ON c.feature_id = s.id
193
194
  WHERE c.component_file = ?
194
195
  ORDER BY s.feature_key
195
196
  `).all(filePath) as Record<string, unknown>[];
@@ -198,8 +199,8 @@ export function getFeaturesByFile(db: Database.Database, filePath: string): Feat
198
199
 
199
200
  export function getFeaturesByRoute(db: Database.Database, route: string): Feature[] {
200
201
  const rows = db.prepare(`
201
- SELECT DISTINCT s.* FROM massu_sentinel s
202
- JOIN massu_sentinel_pages p ON p.feature_id = s.id
202
+ SELECT DISTINCT s.* FROM ${t('sentinel')} s
203
+ JOIN ${t('sentinel_pages')} p ON p.feature_id = s.id
203
204
  WHERE p.page_route = ?
204
205
  ORDER BY s.feature_key
205
206
  `).all(route) as Record<string, unknown>[];
@@ -219,11 +220,11 @@ export function getFeatureDetail(db: Database.Database, featureKeyOrId: string |
219
220
  }
220
221
  if (!feature) return null;
221
222
 
222
- const components = db.prepare('SELECT * FROM massu_sentinel_components WHERE feature_id = ?').all(feature.id) as FeatureComponent[];
223
- const procedures = db.prepare('SELECT * FROM massu_sentinel_procedures WHERE feature_id = ?').all(feature.id) as FeatureProcedure[];
224
- const pages = db.prepare('SELECT * FROM massu_sentinel_pages WHERE feature_id = ?').all(feature.id) as FeaturePage[];
225
- const dependencies = db.prepare('SELECT * FROM massu_sentinel_deps WHERE feature_id = ?').all(feature.id) as FeatureDep[];
226
- const changelog = db.prepare('SELECT * FROM massu_sentinel_changelog WHERE feature_id = ? ORDER BY created_at DESC LIMIT 50').all(feature.id) as FeatureChangeLog[];
223
+ const components = db.prepare(`SELECT * FROM ${t('sentinel_components')} WHERE feature_id = ?`).all(feature.id) as FeatureComponent[];
224
+ const procedures = db.prepare(`SELECT * FROM ${t('sentinel_procedures')} WHERE feature_id = ?`).all(feature.id) as FeatureProcedure[];
225
+ const pages = db.prepare(`SELECT * FROM ${t('sentinel_pages')} WHERE feature_id = ?`).all(feature.id) as FeaturePage[];
226
+ const dependencies = db.prepare(`SELECT * FROM ${t('sentinel_deps')} WHERE feature_id = ?`).all(feature.id) as FeatureDep[];
227
+ const changelog = db.prepare(`SELECT * FROM ${t('sentinel_changelog')} WHERE feature_id = ? ORDER BY created_at DESC LIMIT 50`).all(feature.id) as FeatureChangeLog[];
227
228
 
228
229
  return { ...feature, components, procedures, pages, dependencies, changelog };
229
230
  }
@@ -235,10 +236,10 @@ export function getFeatureDetail(db: Database.Database, featureKeyOrId: string |
235
236
  export function getOrphanedFeatures(db: Database.Database): Feature[] {
236
237
  // Active features with no living primary component files
237
238
  const features = db.prepare(`
238
- SELECT s.* FROM massu_sentinel s
239
+ SELECT s.* FROM ${t('sentinel')} s
239
240
  WHERE s.status = 'active'
240
241
  AND NOT EXISTS (
241
- SELECT 1 FROM massu_sentinel_components c
242
+ SELECT 1 FROM ${t('sentinel_components')} c
242
243
  WHERE c.feature_id = s.id AND c.is_primary = 1
243
244
  )
244
245
  ORDER BY s.domain, s.feature_key
@@ -253,7 +254,7 @@ export function getFeatureImpact(db: Database.Database, filePaths: string[]): Im
253
254
  // Find all features linked to these files
254
255
  for (const filePath of filePaths) {
255
256
  const links = db.prepare(
256
- 'SELECT feature_id FROM massu_sentinel_components WHERE component_file = ?'
257
+ `SELECT feature_id FROM ${t('sentinel_components')} WHERE component_file = ?`
257
258
  ).all(filePath) as { feature_id: number }[];
258
259
  for (const link of links) {
259
260
  affectedFeatureIds.add(link.feature_id);
@@ -269,7 +270,7 @@ export function getFeatureImpact(db: Database.Database, filePaths: string[]): Im
269
270
  if (!feature || feature.status !== 'active') continue;
270
271
 
271
272
  const allComponents = db.prepare(
272
- 'SELECT component_file, is_primary FROM massu_sentinel_components WHERE feature_id = ?'
273
+ `SELECT component_file, is_primary FROM ${t('sentinel_components')} WHERE feature_id = ?`
273
274
  ).all(featureId) as { component_file: string; is_primary: number }[];
274
275
 
275
276
  const affected = allComponents.filter(c => fileSet.has(c.component_file));
@@ -324,7 +325,7 @@ export function linkComponent(
324
325
  isPrimary: boolean = false
325
326
  ): void {
326
327
  db.prepare(`
327
- INSERT OR REPLACE INTO massu_sentinel_components (feature_id, component_file, component_name, role, is_primary)
328
+ INSERT OR REPLACE INTO ${t('sentinel_components')} (feature_id, component_file, component_name, role, is_primary)
328
329
  VALUES (?, ?, ?, ?, ?)
329
330
  `).run(featureId, filePath, componentName, role, isPrimary ? 1 : 0);
330
331
  }
@@ -337,7 +338,7 @@ export function linkProcedure(
337
338
  procedureType?: string
338
339
  ): void {
339
340
  db.prepare(`
340
- INSERT OR REPLACE INTO massu_sentinel_procedures (feature_id, router_name, procedure_name, procedure_type)
341
+ INSERT OR REPLACE INTO ${t('sentinel_procedures')} (feature_id, router_name, procedure_name, procedure_type)
341
342
  VALUES (?, ?, ?, ?)
342
343
  `).run(featureId, routerName, procedureName, procedureType || null);
343
344
  }
@@ -349,7 +350,7 @@ export function linkPage(
349
350
  portal?: string
350
351
  ): void {
351
352
  db.prepare(`
352
- INSERT OR REPLACE INTO massu_sentinel_pages (feature_id, page_route, portal)
353
+ INSERT OR REPLACE INTO ${t('sentinel_pages')} (feature_id, page_route, portal)
353
354
  VALUES (?, ?, ?)
354
355
  `).run(featureId, route, portal || null);
355
356
  }
@@ -367,7 +368,7 @@ export function logChange(
367
368
  changedBy: string = 'claude-code'
368
369
  ): void {
369
370
  db.prepare(`
370
- INSERT INTO massu_sentinel_changelog (feature_id, change_type, changed_by, change_detail, commit_hash)
371
+ INSERT INTO ${t('sentinel_changelog')} (feature_id, change_type, changed_by, change_detail, commit_hash)
371
372
  VALUES (?, ?, ?, ?, ?)
372
373
  `).run(featureId, changeType, changedBy, detail, commitHash || null);
373
374
  }
@@ -377,7 +378,7 @@ export function logChange(
377
378
  // ============================================================
378
379
 
379
380
  export function validateFeatures(db: Database.Database, domainFilter?: string): ValidationReport {
380
- let sql = `SELECT * FROM massu_sentinel WHERE status = 'active'`;
381
+ let sql = `SELECT * FROM ${t('sentinel')} WHERE status = 'active'`;
381
382
  const params: unknown[] = [];
382
383
  if (domainFilter) {
383
384
  sql += ' AND domain = ?';
@@ -393,9 +394,9 @@ export function validateFeatures(db: Database.Database, domainFilter?: string):
393
394
 
394
395
  for (const row of features) {
395
396
  const feature = toFeature(row);
396
- const components = db.prepare('SELECT * FROM massu_sentinel_components WHERE feature_id = ?').all(feature.id) as FeatureComponent[];
397
- const procedures = db.prepare('SELECT * FROM massu_sentinel_procedures WHERE feature_id = ?').all(feature.id) as FeatureProcedure[];
398
- const pages = db.prepare('SELECT * FROM massu_sentinel_pages WHERE feature_id = ?').all(feature.id) as FeaturePage[];
397
+ const components = db.prepare(`SELECT * FROM ${t('sentinel_components')} WHERE feature_id = ?`).all(feature.id) as FeatureComponent[];
398
+ const procedures = db.prepare(`SELECT * FROM ${t('sentinel_procedures')} WHERE feature_id = ?`).all(feature.id) as FeatureProcedure[];
399
+ const pages = db.prepare(`SELECT * FROM ${t('sentinel_pages')} WHERE feature_id = ?`).all(feature.id) as FeaturePage[];
399
400
 
400
401
  const missingComponents: string[] = [];
401
402
  const missingProcedures: { router: string; procedure: string }[] = [];
@@ -475,7 +476,7 @@ export function checkParity(db: Database.Database, oldFiles: string[], newFiles:
475
476
  // Find features linked to old files
476
477
  const oldFeatureIds = new Set<number>();
477
478
  for (const file of oldFiles) {
478
- const links = db.prepare('SELECT feature_id FROM massu_sentinel_components WHERE component_file = ?').all(file) as { feature_id: number }[];
479
+ const links = db.prepare(`SELECT feature_id FROM ${t('sentinel_components')} WHERE component_file = ?`).all(file) as { feature_id: number }[];
479
480
  for (const link of links) {
480
481
  oldFeatureIds.add(link.feature_id);
481
482
  }
@@ -484,7 +485,7 @@ export function checkParity(db: Database.Database, oldFiles: string[], newFiles:
484
485
  // Find features linked to new files
485
486
  const newFeatureIds = new Set<number>();
486
487
  for (const file of newFiles) {
487
- const links = db.prepare('SELECT feature_id FROM massu_sentinel_components WHERE component_file = ?').all(file) as { feature_id: number }[];
488
+ const links = db.prepare(`SELECT feature_id FROM ${t('sentinel_components')} WHERE component_file = ?`).all(file) as { feature_id: number }[];
488
489
  for (const link of links) {
489
490
  newFeatureIds.add(link.feature_id);
490
491
  }
@@ -500,8 +501,8 @@ export function checkParity(db: Database.Database, oldFiles: string[], newFiles:
500
501
  const feature = getFeatureById(db, fId);
501
502
  if (!feature) continue;
502
503
 
503
- const oldComps = db.prepare('SELECT component_file FROM massu_sentinel_components WHERE feature_id = ? AND component_file IN (' + oldFiles.map(() => '?').join(',') + ')').all(fId, ...oldFiles) as { component_file: string }[];
504
- const newComps = db.prepare('SELECT component_file FROM massu_sentinel_components WHERE feature_id = ? AND component_file IN (' + newFiles.map(() => '?').join(',') + ')').all(fId, ...newFiles) as { component_file: string }[];
504
+ const oldComps = db.prepare(`SELECT component_file FROM ${t('sentinel_components')} WHERE feature_id = ? AND component_file IN (` + oldFiles.map(() => '?').join(',') + ')').all(fId, ...oldFiles) as { component_file: string }[];
505
+ const newComps = db.prepare(`SELECT component_file FROM ${t('sentinel_components')} WHERE feature_id = ? AND component_file IN (` + newFiles.map(() => '?').join(',') + ')').all(fId, ...newFiles) as { component_file: string }[];
505
506
 
506
507
  const item: ParityItem = {
507
508
  feature_key: feature.feature_key,
@@ -524,7 +525,7 @@ export function checkParity(db: Database.Database, oldFiles: string[], newFiles:
524
525
  const feature = getFeatureById(db, fId);
525
526
  if (!feature) continue;
526
527
 
527
- const newComps = db.prepare('SELECT component_file FROM massu_sentinel_components WHERE feature_id = ? AND component_file IN (' + newFiles.map(() => '?').join(',') + ')').all(fId, ...newFiles) as { component_file: string }[];
528
+ const newComps = db.prepare(`SELECT component_file FROM ${t('sentinel_components')} WHERE feature_id = ? AND component_file IN (` + newFiles.map(() => '?').join(',') + ')').all(fId, ...newFiles) as { component_file: string }[];
528
529
 
529
530
  newFeatures.push({
530
531
  feature_key: feature.feature_key,
@@ -549,19 +550,19 @@ export function clearAutoDiscoveredFeatures(db: Database.Database): void {
549
550
  // Only clear features that were auto-discovered (not manually registered)
550
551
  // We use the changelog to distinguish: auto-discovered ones have changed_by = 'scanner'
551
552
  const autoIds = db.prepare(`
552
- SELECT DISTINCT feature_id FROM massu_sentinel_changelog
553
+ SELECT DISTINCT feature_id FROM ${t('sentinel_changelog')}
553
554
  WHERE changed_by = 'scanner' AND change_type = 'created'
554
555
  `).all() as { feature_id: number }[];
555
556
 
556
557
  // Don't delete features that also have manual changes
557
558
  for (const { feature_id } of autoIds) {
558
559
  const hasManualChanges = db.prepare(`
559
- SELECT 1 FROM massu_sentinel_changelog
560
+ SELECT 1 FROM ${t('sentinel_changelog')}
560
561
  WHERE feature_id = ? AND changed_by != 'scanner'
561
562
  `).get(feature_id);
562
563
 
563
564
  if (!hasManualChanges) {
564
- db.prepare('DELETE FROM massu_sentinel WHERE id = ?').run(feature_id);
565
+ db.prepare(`DELETE FROM ${t('sentinel')} WHERE id = ?`).run(feature_id);
565
566
  }
566
567
  }
567
568
  }
@@ -13,6 +13,7 @@ import {
13
13
  } from './sentinel-db.ts';
14
14
  import type { FeatureInput, FeaturePriority } from './sentinel-types.ts';
15
15
  import { getConfig, getProjectRoot } from './config.ts';
16
+ import { t } from './lib/sql-table-names.ts';
16
17
 
17
18
  // ============================================================
18
19
  // Sentinel: Feature Auto-Discovery Scanner
@@ -114,7 +115,7 @@ function scanTrpcProcedures(dataDb: Database.Database): DiscoveredFeature[] {
114
115
 
115
116
  const procedures = dataDb.prepare(`
116
117
  SELECT router_name, procedure_name, procedure_type, router_file
117
- FROM massu_trpc_procedures
118
+ FROM ${t('trpc_procedures')}
118
119
  ORDER BY router_name, procedure_name
119
120
  `).all() as { router_name: string; procedure_name: string; procedure_type: string; router_file: string }[];
120
121
 
@@ -171,7 +172,7 @@ function scanPageRoutes(dataDb: Database.Database): DiscoveredFeature[] {
171
172
 
172
173
  const pages = dataDb.prepare(`
173
174
  SELECT page_file, route, portal, components, hooks, routers
174
- FROM massu_page_deps
175
+ FROM ${t('page_deps')}
175
176
  ORDER BY route
176
177
  `).all() as { page_file: string; route: string; portal: string; components: string; hooks: string; routers: string }[];
177
178
 
@@ -17,6 +17,7 @@ import {
17
17
  } from './sentinel-db.ts';
18
18
  import type { ComponentRole, FeatureStatus, FeaturePriority } from './sentinel-types.ts';
19
19
  import { getConfig } from './config.ts';
20
+ import { t } from './lib/sql-table-names.ts';
20
21
 
21
22
  /** Prefix a base tool name with the configured tool prefix. */
22
23
  function p(baseName: string): string {
@@ -400,7 +401,7 @@ function handleValidate(args: Record<string, unknown>, db: Database.Database): T
400
401
  if (fix) {
401
402
  lines.push('### Auto-Fix Applied');
402
403
  for (const item of issues.filter(i => i.status === 'orphaned')) {
403
- db.prepare("UPDATE massu_sentinel SET status = 'deprecated', updated_at = datetime('now') WHERE id = ?").run(item.feature.id);
404
+ db.prepare(`UPDATE ${t('sentinel')} SET status = 'deprecated', updated_at = datetime('now') WHERE id = ?`).run(item.feature.id);
404
405
  logChange(db, item.feature.id, 'deprecated', 'Auto-deprecated: all primary components missing');
405
406
  lines.push(`- Deprecated: ${item.feature.feature_key}`);
406
407
  }
package/src/tools.ts CHANGED
@@ -39,6 +39,7 @@ import { getKnowledgeDb } from './knowledge-db.ts';
39
39
  import { getPythonToolDefinitions, isPythonTool, handlePythonToolCall } from './python-tools.ts';
40
40
  import { getConfig, getProjectRoot, getResolvedPaths } from './config.ts';
41
41
  import { getCurrentTier, getToolTier, isToolAllowed, annotateToolDefinitions, getLicenseToolDefinitions, isLicenseTool, handleLicenseToolCall, isCloudFeatureAvailable } from './license.ts';
42
+ import { t } from './lib/sql-table-names.ts';
42
43
 
43
44
  export interface ToolDefinition {
44
45
  name: string;
@@ -572,7 +573,7 @@ function handleContext(file: string, dataDb: Database.Database, codegraphDb: Dat
572
573
 
573
574
  // 5. Import edges
574
575
  const imports = dataDb.prepare(
575
- 'SELECT target_file, imported_names FROM massu_imports WHERE source_file = ? LIMIT 20'
576
+ `SELECT target_file, imported_names FROM ${t('imports')} WHERE source_file = ? LIMIT 20`
576
577
  ).all(file) as { target_file: string; imported_names: string }[];
577
578
 
578
579
  if (imports.length > 0) {
@@ -586,7 +587,7 @@ function handleContext(file: string, dataDb: Database.Database, codegraphDb: Dat
586
587
 
587
588
  // 6. Imported BY
588
589
  const importedBy = dataDb.prepare(
589
- 'SELECT source_file FROM massu_imports WHERE target_file = ? LIMIT 20'
590
+ `SELECT source_file FROM ${t('imports')} WHERE target_file = ? LIMIT 20`
590
591
  ).all(file) as { source_file: string }[];
591
592
 
592
593
  if (importedBy.length > 0) {
@@ -786,7 +787,7 @@ function handleTrpcMap(args: Record<string, unknown>, dataDb: Database.Database)
786
787
 
787
788
  if (args.uncoupled) {
788
789
  const uncoupled = dataDb.prepare(
789
- 'SELECT router_name, procedure_name, procedure_type, router_file FROM massu_trpc_procedures WHERE has_ui_caller = 0 ORDER BY router_name, procedure_name'
790
+ `SELECT router_name, procedure_name, procedure_type, router_file FROM ${t('trpc_procedures')} WHERE has_ui_caller = 0 ORDER BY router_name, procedure_name`
790
791
  ).all() as { router_name: string; procedure_name: string; procedure_type: string; router_file: string }[];
791
792
 
792
793
  lines.push(`## Uncoupled Procedures (${uncoupled.length} total)`);
@@ -803,7 +804,7 @@ function handleTrpcMap(args: Record<string, unknown>, dataDb: Database.Database)
803
804
  }
804
805
  } else if (args.router) {
805
806
  const procs = dataDb.prepare(
806
- 'SELECT id, procedure_name, procedure_type, has_ui_caller FROM massu_trpc_procedures WHERE router_name = ? ORDER BY procedure_name'
807
+ `SELECT id, procedure_name, procedure_type, has_ui_caller FROM ${t('trpc_procedures')} WHERE router_name = ? ORDER BY procedure_name`
807
808
  ).all(args.router as string) as { id: number; procedure_name: string; procedure_type: string; has_ui_caller: number }[];
808
809
 
809
810
  lines.push(`## Router: ${args.router} (${procs.length} procedures)`);
@@ -814,7 +815,7 @@ function handleTrpcMap(args: Record<string, unknown>, dataDb: Database.Database)
814
815
  lines.push(`### ${args.router}.${proc.procedure_name} (${proc.procedure_type})${status}`);
815
816
 
816
817
  const callSites = dataDb.prepare(
817
- 'SELECT file, line, call_pattern FROM massu_trpc_call_sites WHERE procedure_id = ?'
818
+ `SELECT file, line, call_pattern FROM ${t('trpc_call_sites')} WHERE procedure_id = ?`
818
819
  ).all(proc.id) as { file: string; line: number; call_pattern: string }[];
819
820
 
820
821
  if (callSites.length > 0) {
@@ -829,7 +830,7 @@ function handleTrpcMap(args: Record<string, unknown>, dataDb: Database.Database)
829
830
  }
830
831
  } else if (args.procedure) {
831
832
  const procs = dataDb.prepare(
832
- 'SELECT id, router_name, router_file, procedure_type, has_ui_caller FROM massu_trpc_procedures WHERE procedure_name = ? ORDER BY router_name'
833
+ `SELECT id, router_name, router_file, procedure_type, has_ui_caller FROM ${t('trpc_procedures')} WHERE procedure_name = ? ORDER BY router_name`
833
834
  ).all(args.procedure as string) as { id: number; router_name: string; router_file: string; procedure_type: string; has_ui_caller: number }[];
834
835
 
835
836
  lines.push(`## Procedure "${args.procedure}" found in ${procs.length} routers`);
@@ -840,7 +841,7 @@ function handleTrpcMap(args: Record<string, unknown>, dataDb: Database.Database)
840
841
  lines.push(`File: ${proc.router_file}`);
841
842
 
842
843
  const callSites = dataDb.prepare(
843
- 'SELECT file, line, call_pattern FROM massu_trpc_call_sites WHERE procedure_id = ?'
844
+ `SELECT file, line, call_pattern FROM ${t('trpc_call_sites')} WHERE procedure_id = ?`
844
845
  ).all(proc.id) as { file: string; line: number; call_pattern: string }[];
845
846
 
846
847
  if (callSites.length > 0) {
@@ -854,8 +855,8 @@ function handleTrpcMap(args: Record<string, unknown>, dataDb: Database.Database)
854
855
  lines.push('');
855
856
  }
856
857
  } else {
857
- const total = dataDb.prepare('SELECT COUNT(*) as count FROM massu_trpc_procedures').get() as { count: number };
858
- const coupled = dataDb.prepare('SELECT COUNT(*) as count FROM massu_trpc_procedures WHERE has_ui_caller = 1').get() as { count: number };
858
+ const total = dataDb.prepare(`SELECT COUNT(*) as count FROM ${t('trpc_procedures')}`).get() as { count: number };
859
+ const coupled = dataDb.prepare(`SELECT COUNT(*) as count FROM ${t('trpc_procedures')} WHERE has_ui_caller = 1`).get() as { count: number };
859
860
  const uncoupled = total.count - coupled.count;
860
861
 
861
862
  // P-H009 (plan-stage-c-high-batch): when the index is empty, return an
@@ -893,11 +894,11 @@ function handleCouplingCheck(args: Record<string, unknown>, dataDb: Database.Dat
893
894
  let uncoupledProcs;
894
895
  if (stagedFiles) {
895
896
  uncoupledProcs = dataDb.prepare(
896
- `SELECT router_name, procedure_name, procedure_type, router_file FROM massu_trpc_procedures WHERE has_ui_caller = 0 AND router_file IN (${stagedFiles.map(() => '?').join(',')})`
897
+ `SELECT router_name, procedure_name, procedure_type, router_file FROM ${t('trpc_procedures')} WHERE has_ui_caller = 0 AND router_file IN (${stagedFiles.map(() => '?').join(',')})`
897
898
  ).all(...stagedFiles) as { router_name: string; procedure_name: string; procedure_type: string; router_file: string }[];
898
899
  } else {
899
900
  uncoupledProcs = dataDb.prepare(
900
- 'SELECT router_name, procedure_name, procedure_type, router_file FROM massu_trpc_procedures WHERE has_ui_caller = 0'
901
+ `SELECT router_name, procedure_name, procedure_type, router_file FROM ${t('trpc_procedures')} WHERE has_ui_caller = 0`
901
902
  ).all() as { router_name: string; procedure_name: string; procedure_type: string; router_file: string }[];
902
903
  }
903
904
 
@@ -922,7 +923,7 @@ function handleCouplingCheck(args: Record<string, unknown>, dataDb: Database.Dat
922
923
  const pageImports = new Set<string>();
923
924
  for (const page of allPages) {
924
925
  const imports = dataDb.prepare(
925
- 'SELECT target_file FROM massu_imports WHERE source_file = ?'
926
+ `SELECT target_file FROM ${t('imports')} WHERE source_file = ?`
926
927
  ).all(page.path) as { target_file: string }[];
927
928
  for (const imp of imports) {
928
929
  pageImports.add(imp.target_file);
@@ -1009,7 +1010,7 @@ function handleImpact(file: string, dataDb: Database.Database, codegraphDb: Data
1009
1010
  lines.push(`### Domain: ${fileDomain}`);
1010
1011
 
1011
1012
  const imports = dataDb.prepare(
1012
- 'SELECT target_file FROM massu_imports WHERE source_file = ?'
1013
+ `SELECT target_file FROM ${t('imports')} WHERE source_file = ?`
1013
1014
  ).all(file) as { target_file: string }[];
1014
1015
 
1015
1016
  const crossings: string[] = [];
package/src/trpc-index.ts CHANGED
@@ -5,6 +5,7 @@ import { readFileSync, existsSync, readdirSync } from 'fs';
5
5
  import { resolve, join } from 'path';
6
6
  import type Database from 'better-sqlite3';
7
7
  import { getConfig, getResolvedPaths, getProjectRoot } from './config.ts';
8
+ import { t } from './lib/sql-table-names.ts';
8
9
 
9
10
  interface RouterMapping {
10
11
  key: string; // e.g., "orders" (used as api.orders.*)
@@ -170,16 +171,16 @@ function escapeRegex(str: string): string {
170
171
  */
171
172
  export function buildTrpcIndex(dataDb: Database.Database): { totalProcedures: number; withCallers: number; withoutCallers: number } {
172
173
  // Clear existing data
173
- dataDb.exec('DELETE FROM massu_trpc_call_sites');
174
- dataDb.exec('DELETE FROM massu_trpc_procedures');
174
+ dataDb.exec(`DELETE FROM ${t('trpc_call_sites')}`);
175
+ dataDb.exec(`DELETE FROM ${t('trpc_procedures')}`);
175
176
 
176
177
  const routerMappings = parseRootRouter();
177
178
 
178
179
  const insertProc = dataDb.prepare(
179
- 'INSERT INTO massu_trpc_procedures (router_file, router_name, procedure_name, procedure_type, has_ui_caller) VALUES (?, ?, ?, ?, ?)'
180
+ `INSERT INTO ${t('trpc_procedures')} (router_file, router_name, procedure_name, procedure_type, has_ui_caller) VALUES (?, ?, ?, ?, ?)`
180
181
  );
181
182
  const insertCallSite = dataDb.prepare(
182
- 'INSERT INTO massu_trpc_call_sites (procedure_id, file, line, call_pattern) VALUES (?, ?, ?, ?)'
183
+ `INSERT INTO ${t('trpc_call_sites')} (procedure_id, file, line, call_pattern) VALUES (?, ?, ?, ?)`
183
184
  );
184
185
 
185
186
  let totalProcedures = 0;
@@ -12,6 +12,7 @@ import Database from 'better-sqlite3';
12
12
  import { resolve } from 'path';
13
13
  import { existsSync } from 'fs';
14
14
  import { getProjectRoot, getResolvedPaths } from './config.ts';
15
+ import { t } from './lib/sql-table-names.ts';
15
16
 
16
17
  const PROJECT_ROOT = getProjectRoot();
17
18
 
@@ -35,7 +36,7 @@ function main(): void {
35
36
  try {
36
37
  // Check if sentinel tables exist
37
38
  const tableExists = db.prepare(
38
- "SELECT name FROM sqlite_master WHERE type='table' AND name='massu_sentinel'"
39
+ "SELECT name FROM sqlite_master WHERE type='table' AND name=`${t('sentinel')}`"
39
40
  ).get();
40
41
 
41
42
  if (!tableExists) {
@@ -45,7 +46,7 @@ function main(): void {
45
46
 
46
47
  // Count active features
47
48
  const totalActive = db.prepare(
48
- "SELECT COUNT(*) as count FROM massu_sentinel WHERE status = 'active'"
49
+ `SELECT COUNT(*) as count FROM ${t('sentinel')} WHERE status = 'active'`
49
50
  ).get() as { count: number };
50
51
 
51
52
  if (totalActive.count === 0) {
@@ -56,8 +57,8 @@ function main(): void {
56
57
  // Check for orphaned features (active features with missing primary component files)
57
58
  const orphaned = db.prepare(`
58
59
  SELECT s.feature_key, s.title, s.priority, c.component_file
59
- FROM massu_sentinel s
60
- JOIN massu_sentinel_components c ON c.feature_id = s.id AND c.is_primary = 1
60
+ FROM ${t('sentinel')} s
61
+ JOIN ${t('sentinel_components')} c ON c.feature_id = s.id AND c.is_primary = 1
61
62
  WHERE s.status = 'active'
62
63
  ORDER BY s.priority DESC, s.domain, s.feature_key
63
64
  `).all() as { feature_key: string; title: string; priority: string; component_file: string }[];