@massu/core 0.1.1 → 0.1.2

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 (87) hide show
  1. package/README.md +2 -2
  2. package/dist/hooks/cost-tracker.js +23 -35
  3. package/dist/hooks/post-edit-context.js +2 -2
  4. package/dist/hooks/post-tool-use.js +43 -58
  5. package/dist/hooks/pre-compact.js +23 -38
  6. package/dist/hooks/pre-delete-check.js +18 -31
  7. package/dist/hooks/quality-event.js +23 -35
  8. package/dist/hooks/session-end.js +62 -78
  9. package/dist/hooks/session-start.js +33 -42
  10. package/dist/hooks/user-prompt.js +23 -38
  11. package/package.json +8 -14
  12. package/src/adr-generator.ts +9 -2
  13. package/src/analytics.ts +9 -3
  14. package/src/audit-trail.ts +10 -3
  15. package/src/cloud-sync.ts +14 -18
  16. package/src/commands/init.ts +1 -5
  17. package/src/cost-tracker.ts +11 -6
  18. package/src/dependency-scorer.ts +9 -2
  19. package/src/docs-tools.ts +13 -10
  20. package/src/hooks/post-edit-context.ts +3 -3
  21. package/src/hooks/session-end.ts +3 -3
  22. package/src/hooks/session-start.ts +2 -2
  23. package/src/memory-db.ts +1351 -23
  24. package/src/memory-tools.ts +14 -15
  25. package/src/observability-tools.ts +13 -2
  26. package/src/prompt-analyzer.ts +9 -2
  27. package/src/regression-detector.ts +9 -3
  28. package/src/security-scorer.ts +9 -2
  29. package/src/sentinel-db.ts +43 -88
  30. package/src/sentinel-tools.ts +8 -11
  31. package/src/server.ts +1 -2
  32. package/src/team-knowledge.ts +9 -2
  33. package/src/tools.ts +771 -35
  34. package/src/validate-features-runner.ts +0 -1
  35. package/src/validation-engine.ts +9 -2
  36. package/dist/cli.js +0 -7890
  37. package/dist/server.js +0 -7008
  38. package/src/__tests__/adr-generator.test.ts +0 -260
  39. package/src/__tests__/analytics.test.ts +0 -282
  40. package/src/__tests__/audit-trail.test.ts +0 -382
  41. package/src/__tests__/backfill-sessions.test.ts +0 -690
  42. package/src/__tests__/cli.test.ts +0 -290
  43. package/src/__tests__/cloud-sync.test.ts +0 -261
  44. package/src/__tests__/config-sections.test.ts +0 -359
  45. package/src/__tests__/config.test.ts +0 -732
  46. package/src/__tests__/cost-tracker.test.ts +0 -348
  47. package/src/__tests__/db.test.ts +0 -177
  48. package/src/__tests__/dependency-scorer.test.ts +0 -325
  49. package/src/__tests__/docs-integration.test.ts +0 -178
  50. package/src/__tests__/docs-tools.test.ts +0 -199
  51. package/src/__tests__/domains.test.ts +0 -236
  52. package/src/__tests__/hooks.test.ts +0 -221
  53. package/src/__tests__/import-resolver.test.ts +0 -95
  54. package/src/__tests__/integration/path-traversal.test.ts +0 -134
  55. package/src/__tests__/integration/pricing-consistency.test.ts +0 -88
  56. package/src/__tests__/integration/tool-registration.test.ts +0 -146
  57. package/src/__tests__/memory-db.test.ts +0 -404
  58. package/src/__tests__/memory-enhancements.test.ts +0 -316
  59. package/src/__tests__/memory-tools.test.ts +0 -199
  60. package/src/__tests__/middleware-tree.test.ts +0 -177
  61. package/src/__tests__/observability-tools.test.ts +0 -595
  62. package/src/__tests__/observability.test.ts +0 -437
  63. package/src/__tests__/observation-extractor.test.ts +0 -167
  64. package/src/__tests__/page-deps.test.ts +0 -60
  65. package/src/__tests__/prompt-analyzer.test.ts +0 -298
  66. package/src/__tests__/regression-detector.test.ts +0 -295
  67. package/src/__tests__/rules.test.ts +0 -87
  68. package/src/__tests__/schema-mapper.test.ts +0 -29
  69. package/src/__tests__/security-scorer.test.ts +0 -238
  70. package/src/__tests__/security-utils.test.ts +0 -175
  71. package/src/__tests__/sentinel-db.test.ts +0 -491
  72. package/src/__tests__/sentinel-scanner.test.ts +0 -750
  73. package/src/__tests__/sentinel-tools.test.ts +0 -324
  74. package/src/__tests__/sentinel-types.test.ts +0 -750
  75. package/src/__tests__/server.test.ts +0 -452
  76. package/src/__tests__/session-archiver.test.ts +0 -524
  77. package/src/__tests__/session-state-generator.test.ts +0 -900
  78. package/src/__tests__/team-knowledge.test.ts +0 -327
  79. package/src/__tests__/tools.test.ts +0 -340
  80. package/src/__tests__/transcript-parser.test.ts +0 -195
  81. package/src/__tests__/trpc-index.test.ts +0 -25
  82. package/src/__tests__/validate-features-runner.test.ts +0 -517
  83. package/src/__tests__/validation-engine.test.ts +0 -300
  84. package/src/core-tools.ts +0 -685
  85. package/src/memory-queries.ts +0 -804
  86. package/src/memory-schema.ts +0 -546
  87. package/src/tool-helpers.ts +0 -41
@@ -3,7 +3,7 @@ import{createRequire as __cr}from"module";const require=__cr(import.meta.url);
3
3
 
4
4
  // src/memory-db.ts
5
5
  import Database from "better-sqlite3";
6
- import { dirname as dirname2 } from "path";
6
+ import { dirname as dirname2, basename } from "path";
7
7
  import { existsSync as existsSync2, mkdirSync } from "fs";
8
8
 
9
9
  // src/config.ts
@@ -268,14 +268,26 @@ function getResolvedPaths() {
268
268
  };
269
269
  }
270
270
 
271
- // src/memory-schema.ts
271
+ // src/memory-db.ts
272
+ function getMemoryDb() {
273
+ const dbPath = getResolvedPaths().memoryDbPath;
274
+ const dir = dirname2(dbPath);
275
+ if (!existsSync2(dir)) {
276
+ mkdirSync(dir, { recursive: true });
277
+ }
278
+ const db = new Database(dbPath);
279
+ db.pragma("journal_mode = WAL");
280
+ db.pragma("foreign_keys = ON");
281
+ initMemorySchema(db);
282
+ return db;
283
+ }
272
284
  function initMemorySchema(db) {
273
285
  db.exec(`
274
286
  -- Sessions table (linked to Claude Code session IDs)
275
287
  CREATE TABLE IF NOT EXISTS sessions (
276
288
  id INTEGER PRIMARY KEY AUTOINCREMENT,
277
289
  session_id TEXT UNIQUE NOT NULL,
278
- project TEXT NOT NULL DEFAULT 'unknown',
290
+ project TEXT NOT NULL DEFAULT 'my-project',
279
291
  git_branch TEXT,
280
292
  started_at TEXT NOT NULL,
281
293
  started_at_epoch INTEGER NOT NULL,
@@ -330,9 +342,7 @@ function initMemorySchema(db) {
330
342
  content_rowid='id'
331
343
  );
332
344
  `);
333
- } catch (e) {
334
- process.stderr.write(`FTS5 setup warning: ${e instanceof Error ? e.message : String(e)}
335
- `);
345
+ } catch (_e) {
336
346
  }
337
347
  db.exec(`
338
348
  CREATE TRIGGER IF NOT EXISTS observations_ai AFTER INSERT ON observations BEGIN
@@ -392,9 +402,7 @@ function initMemorySchema(db) {
392
402
  content_rowid='id'
393
403
  );
394
404
  `);
395
- } catch (e) {
396
- process.stderr.write(`FTS5 setup warning: ${e instanceof Error ? e.message : String(e)}
397
- `);
405
+ } catch (_e) {
398
406
  }
399
407
  db.exec(`
400
408
  CREATE TRIGGER IF NOT EXISTS prompts_ai AFTER INSERT ON user_prompts BEGIN
@@ -464,9 +472,7 @@ function initMemorySchema(db) {
464
472
  content_rowid=id
465
473
  );
466
474
  `);
467
- } catch (e) {
468
- process.stderr.write(`FTS5 setup warning: ${e instanceof Error ? e.message : String(e)}
469
- `);
475
+ } catch (_e) {
470
476
  }
471
477
  db.exec(`
472
478
  CREATE TRIGGER IF NOT EXISTS ct_fts_insert AFTER INSERT ON conversation_turns BEGIN
@@ -490,7 +496,7 @@ function initMemorySchema(db) {
490
496
  CREATE TABLE IF NOT EXISTS session_quality_scores (
491
497
  id INTEGER PRIMARY KEY AUTOINCREMENT,
492
498
  session_id TEXT NOT NULL UNIQUE,
493
- project TEXT NOT NULL DEFAULT 'unknown',
499
+ project TEXT NOT NULL DEFAULT 'my-project',
494
500
  score INTEGER NOT NULL DEFAULT 100,
495
501
  security_score INTEGER NOT NULL DEFAULT 100,
496
502
  architecture_score INTEGER NOT NULL DEFAULT 100,
@@ -513,7 +519,7 @@ function initMemorySchema(db) {
513
519
  CREATE TABLE IF NOT EXISTS session_costs (
514
520
  id INTEGER PRIMARY KEY AUTOINCREMENT,
515
521
  session_id TEXT NOT NULL UNIQUE,
516
- project TEXT NOT NULL DEFAULT 'unknown',
522
+ project TEXT NOT NULL DEFAULT 'my-project',
517
523
  input_tokens INTEGER NOT NULL DEFAULT 0,
518
524
  output_tokens INTEGER NOT NULL DEFAULT 0,
519
525
  cache_read_tokens INTEGER NOT NULL DEFAULT 0,
@@ -741,9 +747,6 @@ function initMemorySchema(db) {
741
747
  CREATE INDEX IF NOT EXISTS idx_pending_sync_created ON pending_sync(created_at ASC);
742
748
  `);
743
749
  }
744
-
745
- // src/memory-queries.ts
746
- import { basename } from "path";
747
750
  function autoDetectTaskId(planFile) {
748
751
  if (!planFile) return null;
749
752
  const base = basename(planFile);
@@ -768,24 +771,6 @@ function linkSessionToTask(db, sessionId, taskId) {
768
771
  db.prepare("UPDATE sessions SET task_id = ? WHERE session_id = ?").run(taskId, sessionId);
769
772
  }
770
773
 
771
- // src/memory-db.ts
772
- var initializedPaths = /* @__PURE__ */ new Set();
773
- function getMemoryDb() {
774
- const dbPath = getResolvedPaths().memoryDbPath;
775
- const dir = dirname2(dbPath);
776
- if (!existsSync2(dir)) {
777
- mkdirSync(dir, { recursive: true });
778
- }
779
- const db = new Database(dbPath);
780
- db.pragma("journal_mode = WAL");
781
- db.pragma("foreign_keys = ON");
782
- if (!initializedPaths.has(dbPath)) {
783
- initMemorySchema(db);
784
- initializedPaths.add(dbPath);
785
- }
786
- return db;
787
- }
788
-
789
774
  // src/hooks/user-prompt.ts
790
775
  async function main() {
791
776
  try {
@@ -835,14 +820,14 @@ async function getGitBranch() {
835
820
  }
836
821
  }
837
822
  function readStdin() {
838
- return new Promise((resolve2) => {
823
+ return new Promise((resolve3) => {
839
824
  let data = "";
840
825
  process.stdin.setEncoding("utf-8");
841
826
  process.stdin.on("data", (chunk) => {
842
827
  data += chunk;
843
828
  });
844
- process.stdin.on("end", () => resolve2(data));
845
- setTimeout(() => resolve2(data), 3e3);
829
+ process.stdin.on("end", () => resolve3(data));
830
+ setTimeout(() => resolve3(data), 3e3);
846
831
  });
847
832
  }
848
833
  main();
package/package.json CHANGED
@@ -1,28 +1,21 @@
1
1
  {
2
2
  "name": "@massu/core",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "description": "AI Engineering Governance MCP Server - Session memory, feature registry, code intelligence, and rule enforcement",
6
- "license": "BSL-1.1",
7
- "author": "Massu AI <hello@massu.ai>",
8
- "main": "dist/server.js",
9
- "exports": {
10
- ".": "./dist/server.js",
11
- "./cli": "./dist/cli.js"
12
- },
6
+ "main": "src/server.ts",
13
7
  "bin": {
14
- "massu": "dist/cli.js"
8
+ "massu": "./src/cli.ts"
15
9
  },
16
10
  "scripts": {
17
11
  "start": "npx tsx src/server.ts",
18
12
  "test": "vitest run",
19
- "build": "tsc --noEmit && npm run build:server && npm run build:hooks",
20
- "build:server": "esbuild --bundle --platform=node --format=esm --outdir=dist --entry-names=[name] src/server.ts src/cli.ts --external:better-sqlite3 --external:yaml --external:zod --banner:js='import{createRequire as __cr}from\"module\";const require=__cr(import.meta.url);'",
13
+ "build": "tsc --noEmit && npm run build:hooks",
21
14
  "build:hooks": "esbuild --bundle --platform=node --format=esm --outdir=dist/hooks src/hooks/*.ts --external:better-sqlite3 --external:yaml --external:zod --banner:js='import{createRequire as __cr}from\"module\";const require=__cr(import.meta.url);'",
22
- "test:integration": "vitest run src/__tests__/integration/",
23
15
  "prepublishOnly": "bash ../../scripts/prepublish-check.sh && npm run build"
24
16
  },
25
17
  "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.0.0",
26
19
  "better-sqlite3": "^12.6.2",
27
20
  "yaml": "^2.4.0",
28
21
  "zod": "^3.23.0"
@@ -36,6 +29,7 @@
36
29
  },
37
30
  "files": [
38
31
  "src/**/*",
32
+ "!src/__tests__/**",
39
33
  "dist/**/*",
40
34
  "LICENSE"
41
35
  ],
@@ -52,11 +46,11 @@
52
46
  },
53
47
  "repository": {
54
48
  "type": "git",
55
- "url": "git+https://github.com/massu-ai/massu.git",
49
+ "url": "https://github.com/massu-ai/massu.git",
56
50
  "directory": "packages/core"
57
51
  },
58
52
  "bugs": {
59
53
  "url": "https://github.com/massu-ai/massu/issues"
60
54
  },
61
- "homepage": "https://massu.ai"
55
+ "homepage": "https://github.com/massu-ai/massu#readme"
62
56
  }
@@ -2,14 +2,18 @@
2
2
  // Licensed under BSL 1.1 - see LICENSE file for details.
3
3
 
4
4
  import type Database from 'better-sqlite3';
5
- import type { ToolDefinition, ToolResult } from './tool-helpers.ts';
6
- import { p, text } from './tool-helpers.ts';
5
+ import type { ToolDefinition, ToolResult } from './tools.ts';
7
6
  import { getConfig } from './config.ts';
8
7
 
9
8
  // ============================================================
10
9
  // ADR (Architecture Decision Record) Auto-Generation
11
10
  // ============================================================
12
11
 
12
+ /** Prefix a base tool name with the configured tool prefix. */
13
+ function p(baseName: string): string {
14
+ return `${getConfig().toolPrefix}_${baseName}`;
15
+ }
16
+
13
17
  /** Default decision detection phrases. Configurable via governance.adr.detection_phrases */
14
18
  const DEFAULT_DETECTION_PHRASES = ['chose', 'decided', 'switching to', 'moving from', 'going with'];
15
19
 
@@ -283,3 +287,6 @@ function handleAdrGenerate(args: Record<string, unknown>, db: Database.Database)
283
287
  return text(lines.filter(Boolean).join('\n'));
284
288
  }
285
289
 
290
+ function text(content: string): ToolResult {
291
+ return { content: [{ type: 'text', text: content }] };
292
+ }
package/src/analytics.ts CHANGED
@@ -2,14 +2,18 @@
2
2
  // Licensed under BSL 1.1 - see LICENSE file for details.
3
3
 
4
4
  import type Database from 'better-sqlite3';
5
- import type { ToolDefinition, ToolResult } from './tool-helpers.ts';
6
- import { p, text } from './tool-helpers.ts';
5
+ import type { ToolDefinition, ToolResult } from './tools.ts';
7
6
  import { getConfig } from './config.ts';
8
7
 
9
8
  // ============================================================
10
9
  // Quality Trend Analytics
11
10
  // ============================================================
12
11
 
12
+ /** Prefix a base tool name with the configured tool prefix. */
13
+ function p(baseName: string): string {
14
+ return `${getConfig().toolPrefix}_${baseName}`;
15
+ }
16
+
13
17
  export interface QualityBreakdown {
14
18
  security: number;
15
19
  architecture: number;
@@ -118,7 +122,6 @@ export function backfillQualityScores(db: Database.Database): number {
118
122
  FROM sessions s
119
123
  LEFT JOIN session_quality_scores q ON s.session_id = q.session_id
120
124
  WHERE q.session_id IS NULL
121
- LIMIT 1000
122
125
  `).all() as Array<{ session_id: string }>;
123
126
 
124
127
  let backfilled = 0;
@@ -365,3 +368,6 @@ function handleQualityReport(args: Record<string, unknown>, db: Database.Databas
365
368
  return text(lines.join('\n'));
366
369
  }
367
370
 
371
+ function text(content: string): ToolResult {
372
+ return { content: [{ type: 'text', text: content }] };
373
+ }
@@ -2,14 +2,18 @@
2
2
  // Licensed under BSL 1.1 - see LICENSE file for details.
3
3
 
4
4
  import type Database from 'better-sqlite3';
5
- import type { ToolDefinition, ToolResult } from './tool-helpers.ts';
6
- import { p, text } from './tool-helpers.ts';
5
+ import type { ToolDefinition, ToolResult } from './tools.ts';
7
6
  import { getConfig } from './config.ts';
8
7
 
9
8
  // ============================================================
10
9
  // Compliance Audit Trail
11
10
  // ============================================================
12
11
 
12
+ /** Prefix a base tool name with the configured tool prefix. */
13
+ function p(baseName: string): string {
14
+ return `${getConfig().toolPrefix}_${baseName}`;
15
+ }
16
+
13
17
  export interface AuditEntry {
14
18
  eventType: 'code_change' | 'rule_enforced' | 'approval' | 'review' | 'commit' | 'compaction';
15
19
  actor: 'ai' | 'human' | 'hook' | 'agent';
@@ -129,7 +133,7 @@ export function backfillAuditLog(db: Database.Database): number {
129
133
  FROM observations o
130
134
  LEFT JOIN audit_log a ON a.evidence = o.detail AND a.session_id = o.session_id
131
135
  WHERE a.id IS NULL
132
- AND o.type IN ('bugfix', 'cr_violation', 'vr_check', 'incident_near_miss', 'decision')
136
+ AND o.type IN ('bugfix', 'cr_violation', 'vr_check', 'incident', 'decision')
133
137
  ORDER BY o.created_at ASC
134
138
  LIMIT 1000
135
139
  `).all() as Array<Record<string, unknown>>;
@@ -441,3 +445,6 @@ function handleAuditChain(args: Record<string, unknown>, db: Database.Database):
441
445
  return text(lines.join('\n'));
442
446
  }
443
447
 
448
+ function text(content: string): ToolResult {
449
+ return { content: [{ type: 'text', text: content }] };
450
+ }
package/src/cloud-sync.ts CHANGED
@@ -166,26 +166,22 @@ export async function syncToCloud(
166
166
  * Successfully synced items are removed; failed items get their retry count incremented.
167
167
  */
168
168
  export async function drainSyncQueue(db: Database.Database): Promise<void> {
169
- try {
170
- const config = getConfig();
171
- if (!config.cloud?.enabled || !config.cloud?.apiKey) return;
172
-
173
- const pending = dequeuePendingSync(db, 10);
174
- for (const item of pending) {
175
- try {
176
- const payload = JSON.parse(item.payload) as SyncPayload;
177
- const result = await syncToCloud(db, payload);
178
- if (result.success) {
179
- removePendingSync(db, item.id);
180
- } else {
181
- incrementRetryCount(db, item.id, result.error ?? 'Unknown error');
182
- }
183
- } catch (err) {
184
- incrementRetryCount(db, item.id, err instanceof Error ? err.message : String(err));
169
+ const config = getConfig();
170
+ if (!config.cloud?.enabled || !config.cloud?.apiKey) return;
171
+
172
+ const pending = dequeuePendingSync(db, 10);
173
+ for (const item of pending) {
174
+ try {
175
+ const payload = JSON.parse(item.payload) as SyncPayload;
176
+ const result = await syncToCloud(db, payload);
177
+ if (result.success) {
178
+ removePendingSync(db, item.id);
179
+ } else {
180
+ incrementRetryCount(db, item.id, result.error ?? 'Unknown error');
185
181
  }
182
+ } catch (err) {
183
+ incrementRetryCount(db, item.id, err instanceof Error ? err.message : String(err));
186
184
  }
187
- } catch (err) {
188
- process.stderr.write(`massu: drainSyncQueue failed: ${err instanceof Error ? err.message : String(err)}\n`);
189
185
  }
190
186
  }
191
187
 
@@ -12,11 +12,7 @@
12
12
  */
13
13
 
14
14
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
15
- import { resolve, basename, dirname } from 'path';
16
- import { fileURLToPath } from 'url';
17
-
18
- const __filename = fileURLToPath(import.meta.url);
19
- const __dirname = dirname(__filename);
15
+ import { resolve, basename } from 'path';
20
16
  import { stringify as yamlStringify } from 'yaml';
21
17
 
22
18
  // ============================================================
@@ -2,8 +2,7 @@
2
2
  // Licensed under BSL 1.1 - see LICENSE file for details.
3
3
 
4
4
  import type Database from 'better-sqlite3';
5
- import type { ToolDefinition, ToolResult } from './tool-helpers.ts';
6
- import { p, text } from './tool-helpers.ts';
5
+ import type { ToolDefinition, ToolResult } from './tools.ts';
7
6
  import type { TranscriptEntry } from './transcript-parser.ts';
8
7
  import { getConfig } from './config.ts';
9
8
 
@@ -11,13 +10,17 @@ import { getConfig } from './config.ts';
11
10
  // Cost Attribution Tracking
12
11
  // ============================================================
13
12
 
13
+ /** Prefix a base tool name with the configured tool prefix. */
14
+ function p(baseName: string): string {
15
+ return `${getConfig().toolPrefix}_${baseName}`;
16
+ }
17
+
14
18
  /** Default model pricing (Claude models). Can be overridden via config.analytics.cost.models */
15
19
  const DEFAULT_MODEL_PRICING: Record<string, { input_per_million: number; output_per_million: number; cache_read_per_million?: number; cache_write_per_million?: number }> = {
16
- 'claude-opus-4-6': { input_per_million: 5.00, output_per_million: 25.00, cache_read_per_million: 0.50, cache_write_per_million: 6.25 },
20
+ 'claude-opus-4-6': { input_per_million: 15.00, output_per_million: 75.00, cache_read_per_million: 1.50, cache_write_per_million: 18.75 },
17
21
  'claude-sonnet-4-6': { input_per_million: 3.00, output_per_million: 15.00, cache_read_per_million: 0.30, cache_write_per_million: 3.75 },
18
22
  'claude-sonnet-4-5': { input_per_million: 3.00, output_per_million: 15.00, cache_read_per_million: 0.30, cache_write_per_million: 3.75 },
19
- 'claude-3-5-haiku-20241022': { input_per_million: 0.80, output_per_million: 4.00, cache_read_per_million: 0.08, cache_write_per_million: 1.00 },
20
- 'claude-haiku-4-5-20251001': { input_per_million: 1.00, output_per_million: 5.00, cache_read_per_million: 0.10, cache_write_per_million: 1.25 },
23
+ 'claude-haiku-4-5-20251001': { input_per_million: 0.80, output_per_million: 4.00, cache_read_per_million: 0.08, cache_write_per_million: 1.00 },
21
24
  'default': { input_per_million: 3.00, output_per_million: 15.00, cache_read_per_million: 0.30, cache_write_per_million: 3.75 },
22
25
  };
23
26
 
@@ -134,7 +137,6 @@ export function backfillSessionCosts(db: Database.Database): number {
134
137
  FROM sessions s
135
138
  LEFT JOIN session_costs c ON s.session_id = c.session_id
136
139
  WHERE c.session_id IS NULL
137
- LIMIT 1000
138
140
  `).all() as Array<{ session_id: string }>;
139
141
 
140
142
  // Backfilling requires transcript data which may not be available
@@ -348,3 +350,6 @@ function handleCostFeature(args: Record<string, unknown>, db: Database.Database)
348
350
  return text(lines.join('\n'));
349
351
  }
350
352
 
353
+ function text(content: string): ToolResult {
354
+ return { content: [{ type: 'text', text: content }] };
355
+ }
@@ -2,8 +2,7 @@
2
2
  // Licensed under BSL 1.1 - see LICENSE file for details.
3
3
 
4
4
  import type Database from 'better-sqlite3';
5
- import type { ToolDefinition, ToolResult } from './tool-helpers.ts';
6
- import { p, text } from './tool-helpers.ts';
5
+ import type { ToolDefinition, ToolResult } from './tools.ts';
7
6
  import { getConfig } from './config.ts';
8
7
  import { existsSync, readFileSync } from 'fs';
9
8
  import { resolve } from 'path';
@@ -12,6 +11,11 @@ import { resolve } from 'path';
12
11
  // Dependency Risk Scoring
13
12
  // ============================================================
14
13
 
14
+ /** Prefix a base tool name with the configured tool prefix. */
15
+ function p(baseName: string): string {
16
+ return `${getConfig().toolPrefix}_${baseName}`;
17
+ }
18
+
15
19
  export interface DepRiskFactors {
16
20
  vulnerabilities: number;
17
21
  lastPublishDays: number | null;
@@ -328,3 +332,6 @@ function handleDepAlternatives(args: Record<string, unknown>, db: Database.Datab
328
332
  return text(lines.filter(Boolean).join('\n'));
329
333
  }
330
334
 
335
+ function text(content: string): ToolResult {
336
+ return { content: [{ type: 'text', text: content }] };
337
+ }
package/src/docs-tools.ts CHANGED
@@ -4,22 +4,18 @@
4
4
  import { readFileSync, existsSync } from 'fs';
5
5
  import { resolve, basename } from 'path';
6
6
  import { getConfig, getResolvedPaths } from './config.ts';
7
- import type { ToolDefinition, ToolResult } from './tool-helpers.ts';
8
- import { p, text } from './tool-helpers.ts';
7
+ import type { ToolDefinition, ToolResult } from './tools.ts';
8
+
9
+ /** Prefix a base tool name with the configured tool prefix. */
10
+ function p(baseName: string): string {
11
+ return `${getConfig().toolPrefix}_${baseName}`;
12
+ }
9
13
 
10
14
  // ============================================================
11
15
  // Help Site Auto-Sync: MCP Docs Tools
12
16
  // docs_audit + docs_coverage
13
17
  // ============================================================
14
18
 
15
- const DOCS_BASE_NAMES = new Set(['docs_audit', 'docs_coverage']);
16
-
17
- export function isDocsTool(name: string): boolean {
18
- const pfx = getConfig().toolPrefix + '_';
19
- const baseName = name.startsWith(pfx) ? name.slice(pfx.length) : name;
20
- return DOCS_BASE_NAMES.has(baseName);
21
- }
22
-
23
19
  interface DocsMapping {
24
20
  id: string;
25
21
  helpPage: string;
@@ -512,3 +508,10 @@ function handleDocsCoverage(args: Record<string, unknown>): ToolResult {
512
508
  return text(lines.join('\n'));
513
509
  }
514
510
 
511
+ // ============================================================
512
+ // Utilities
513
+ // ============================================================
514
+
515
+ function text(content: string): ToolResult {
516
+ return { content: [{ type: 'text', text: content }] };
517
+ }
@@ -54,12 +54,12 @@ async function main(): Promise<void> {
54
54
  }
55
55
  }
56
56
 
57
- // 2. Check middleware tree membership (CR-16)
57
+ // 2. Check middleware tree membership
58
58
  try {
59
59
  const dataDb = new Database(getResolvedPaths().dataDbPath, { readonly: true });
60
60
  try {
61
61
  if (isInMiddlewareTree(dataDb, rel)) {
62
- warnings.push('[CRITICAL] CR-16: This file is in the middleware import tree. No Node.js deps allowed.');
62
+ warnings.push('[CRITICAL] This file is in the middleware import tree. No Node.js deps allowed.');
63
63
  }
64
64
  } finally {
65
65
  dataDb.close();
@@ -70,7 +70,7 @@ async function main(): Promise<void> {
70
70
 
71
71
  // 3. Output warnings if any
72
72
  if (warnings.length > 0) {
73
- console.log(`[CS CONTEXT] ${warnings.join(' | ')}`);
73
+ console.log(`[Massu] ${warnings.join(' | ')}`);
74
74
  }
75
75
  } catch (_e) {
76
76
  // Best-effort: never block Claude Code
@@ -8,10 +8,10 @@
8
8
  // Dependencies: P1-002, P5-001, P5-002
9
9
  // ============================================================
10
10
 
11
- import { getMemoryDb, endSession, addSummary, getRecentObservations, createSession, addConversationTurn, addToolCallDetail, getLastProcessedLine, setLastProcessedLine } from '../memory-db.ts';
11
+ import { getMemoryDb, endSession, addSummary, createSession, addConversationTurn, addToolCallDetail, getLastProcessedLine, setLastProcessedLine } from '../memory-db.ts';
12
12
  import { generateCurrentMd } from '../session-state-generator.ts';
13
13
  import { archiveAndRegenerate } from '../session-archiver.ts';
14
- import { parseTranscriptFrom, extractUserMessages, extractAssistantMessages, extractToolCalls, estimateTokens } from '../transcript-parser.ts';
14
+ import { parseTranscriptFrom, estimateTokens } from '../transcript-parser.ts';
15
15
  import { syncToCloud, drainSyncQueue } from '../cloud-sync.ts';
16
16
  import { calculateQualityScore, storeQualityScore, backfillQualityScores } from '../analytics.ts';
17
17
  import { extractTokenUsage, calculateCost, storeSessionCost } from '../cost-tracker.ts';
@@ -64,7 +64,7 @@ async function main(): Promise<void> {
64
64
  // 4.6. Calculate and store quality score
65
65
  try {
66
66
  const { score, breakdown } = calculateQualityScore(db, session_id);
67
- if (score > 0) {
67
+ if (score !== 50) {
68
68
  storeQualityScore(db, session_id, score, breakdown);
69
69
  }
70
70
  backfillQualityScores(db);
@@ -153,7 +153,7 @@ function buildContext(db: Database.Database, sessionId: string, source: string,
153
153
  sections.sort((a, b) => b.importance - a.importance);
154
154
 
155
155
  let usedTokens = 0;
156
- const headerTokens = estimateTokens('=== CS MEMORY: Previous Session Context ===\n\n=== END CS MEMORY ===\n');
156
+ const headerTokens = estimateTokens('=== Massu Memory: Previous Session Context ===\n\n=== END Massu Memory ===\n');
157
157
  usedTokens += headerTokens;
158
158
 
159
159
  const includedSections: string[] = [];
@@ -167,7 +167,7 @@ function buildContext(db: Database.Database, sessionId: string, source: string,
167
167
 
168
168
  if (includedSections.length === 0) return '';
169
169
 
170
- return `=== CS MEMORY: Previous Session Context ===\n\n${includedSections.join('\n')}\n=== END CS MEMORY ===\n`;
170
+ return `=== Massu Memory: Previous Session Context ===\n\n${includedSections.join('\n')}\n=== END Massu Memory ===\n`;
171
171
  }
172
172
 
173
173
  function estimateTokens(text: string): number {