@massu/core 1.10.7 → 1.10.8

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.
package/dist/cli.js CHANGED
@@ -27717,6 +27717,44 @@ var init_python_tools = __esm({
27717
27717
  }
27718
27718
  });
27719
27719
 
27720
+ // src/lib/framework-supports.ts
27721
+ function getAllRouterValues() {
27722
+ const config = getConfig();
27723
+ const values = [];
27724
+ if (config.framework.router) values.push(config.framework.router);
27725
+ const langs = config.framework.languages;
27726
+ if (langs) {
27727
+ for (const entry of Object.values(langs)) {
27728
+ if (entry?.router) values.push(entry.router);
27729
+ }
27730
+ }
27731
+ return values;
27732
+ }
27733
+ function getAllOrmValues() {
27734
+ const config = getConfig();
27735
+ const values = [];
27736
+ if (config.framework.orm) values.push(config.framework.orm);
27737
+ const langs = config.framework.languages;
27738
+ if (langs) {
27739
+ for (const entry of Object.values(langs)) {
27740
+ if (entry?.orm) values.push(entry.orm);
27741
+ }
27742
+ }
27743
+ return values;
27744
+ }
27745
+ function supportsRouter(name) {
27746
+ return getAllRouterValues().includes(name);
27747
+ }
27748
+ function supportsOrm(name) {
27749
+ return getAllOrmValues().includes(name);
27750
+ }
27751
+ var init_framework_supports = __esm({
27752
+ "src/lib/framework-supports.ts"() {
27753
+ "use strict";
27754
+ init_config();
27755
+ }
27756
+ });
27757
+
27720
27758
  // src/tools.ts
27721
27759
  import { readFileSync as readFileSync41, existsSync as existsSync42 } from "fs";
27722
27760
  import { resolve as resolve36, basename as basename10 } from "path";
@@ -27739,7 +27777,7 @@ function ensureIndexes(dataDb, codegraphDb, force = false) {
27739
27777
  if (codegraphDb !== void 0 && (force || isDataStale(dataDb, codegraphDb))) {
27740
27778
  const importCount = buildImportIndex(dataDb, codegraphDb);
27741
27779
  results.push(`Import edges: ${importCount}`);
27742
- if (config.framework.router === "trpc") {
27780
+ if (supportsRouter("trpc")) {
27743
27781
  const trpcStats = buildTrpcIndex(dataDb);
27744
27782
  results.push(`tRPC procedures: ${trpcStats.totalProcedures} (${trpcStats.withCallers} with UI, ${trpcStats.withoutCallers} without)`);
27745
27783
  }
@@ -27827,7 +27865,7 @@ function getToolDefinitions() {
27827
27865
  required: ["file"]
27828
27866
  }
27829
27867
  },
27830
- ...config.framework.router === "trpc" ? [
27868
+ ...supportsRouter("trpc") ? [
27831
27869
  {
27832
27870
  name: p18("trpc_map"),
27833
27871
  description: "Map tRPC procedures to their UI call sites. Find which components call a router, which procedures have no UI callers, or list all procedures for a router.",
@@ -27881,7 +27919,7 @@ function getToolDefinitions() {
27881
27919
  required: []
27882
27920
  }
27883
27921
  }] : [],
27884
- ...config.framework.orm === "prisma" ? [{
27922
+ ...supportsOrm("prisma") ? [{
27885
27923
  name: p18("schema"),
27886
27924
  description: "Prisma schema cross-reference. Show columns for a table, detect mismatches between code and schema, or verify column references in a file.",
27887
27925
  inputSchema: {
@@ -28704,6 +28742,7 @@ var init_tools = __esm({
28704
28742
  init_knowledge_db();
28705
28743
  init_python_tools();
28706
28744
  init_config();
28745
+ init_framework_supports();
28707
28746
  init_license();
28708
28747
  init_sql_table_names();
28709
28748
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massu/core",
3
- "version": "1.10.7",
3
+ "version": "1.10.8",
4
4
  "type": "module",
5
5
  "description": "AI Engineering Governance MCP Server - Session memory, knowledge system, feature registry, code intelligence, rule enforcement, tiered tooling (12 free / 73 total), 59 workflow commands, 11 agents, 20+ patterns",
6
6
  "main": "src/server.ts",
@@ -0,0 +1,85 @@
1
+ // Copyright (c) 2026 Massu. All rights reserved.
2
+ // Licensed under BSL 1.1 - see LICENSE file for details.
3
+
4
+ /**
5
+ * P-H033 (plan-stage-c-high-batch / 1.10.8): adapter-pattern tool gating.
6
+ *
7
+ * **Bug class closed**: `tools.ts:102,206,260` (pre-1.10.8) did direct
8
+ * `config.framework.router === 'trpc'` / `config.framework.orm === 'prisma'`
9
+ * comparisons. The adapter pattern exists for repo-detection (Plan 3c —
10
+ * `@massu/adapter-*` packages provide `matches(signals)` + `introspect()`)
11
+ * but does NOT extend to tool-definition gating. Result: adding a new
12
+ * adapter (e.g. `@massu/adapter-fastify`) can't activate or de-activate
13
+ * tools — its tool surface is invisible to the dispatcher until tools.ts
14
+ * is hand-edited.
15
+ *
16
+ * **Structural fix**: every tool-gating decision now goes through this
17
+ * module's `supportsRouter(name)` / `supportsOrm(name)` helpers. The
18
+ * helpers consult BOTH the legacy top-level `framework.router/.orm`
19
+ * field AND the per-language v2 schema `framework.languages.<lang>.router/.orm`
20
+ * entries. Future framework adapters can register support via the
21
+ * registration hooks (deferred to plan-adapter-tool-registration when
22
+ * the first cross-adapter tool ships).
23
+ *
24
+ * **Drift-guard**: `__tests__/framework-supports-no-direct-comparison.test.ts`
25
+ * scans `packages/core/src/**` and asserts zero `config.framework.router ===`
26
+ * or `config.framework.orm ===` literal comparisons outside this module
27
+ * itself.
28
+ *
29
+ * For default installs:
30
+ * - tRPC repo (router='trpc'): supportsRouter('trpc') → true (preserves
31
+ * current behavior — trpc_map tool gated on)
32
+ * - Prisma repo (orm='prisma'): supportsOrm('prisma') → true (schema tool on)
33
+ * - Custom adapter with router='fastify': supportsRouter('fastify') → true
34
+ * once the adapter's per-language entry sets framework.languages.typescript.router
35
+ * OR the legacy field — single check at the gate.
36
+ */
37
+
38
+ import { getConfig } from '../config.ts';
39
+
40
+ interface LanguageEntry {
41
+ router?: string;
42
+ orm?: string;
43
+ }
44
+
45
+ function getAllRouterValues(): string[] {
46
+ const config = getConfig();
47
+ const values: string[] = [];
48
+ if (config.framework.router) values.push(config.framework.router);
49
+ const langs = config.framework.languages as Record<string, LanguageEntry> | undefined;
50
+ if (langs) {
51
+ for (const entry of Object.values(langs)) {
52
+ if (entry?.router) values.push(entry.router);
53
+ }
54
+ }
55
+ return values;
56
+ }
57
+
58
+ function getAllOrmValues(): string[] {
59
+ const config = getConfig();
60
+ const values: string[] = [];
61
+ if (config.framework.orm) values.push(config.framework.orm);
62
+ const langs = config.framework.languages as Record<string, LanguageEntry> | undefined;
63
+ if (langs) {
64
+ for (const entry of Object.values(langs)) {
65
+ if (entry?.orm) values.push(entry.orm);
66
+ }
67
+ }
68
+ return values;
69
+ }
70
+
71
+ /**
72
+ * Returns true if any detected language in the config declares this router.
73
+ * Used to gate tool definitions (e.g. trpc_map only when supportsRouter('trpc')).
74
+ */
75
+ export function supportsRouter(name: string): boolean {
76
+ return getAllRouterValues().includes(name);
77
+ }
78
+
79
+ /**
80
+ * Returns true if any detected language in the config declares this ORM.
81
+ * Used to gate tool definitions (e.g. schema only when supportsOrm('prisma')).
82
+ */
83
+ export function supportsOrm(name: string): boolean {
84
+ return getAllOrmValues().includes(name);
85
+ }
@@ -1,4 +1,4 @@
1
- // AUTO-GENERATED by scripts/bundle-license-pubkey.mjs at 2026-05-17T15:51:32.373Z.
1
+ // AUTO-GENERATED by scripts/bundle-license-pubkey.mjs at 2026-05-17T16:00:08.526Z.
2
2
  // Source pem: packages/core/security/license-pubkey.pem
3
3
  // RAW-bytes sha256: 18a63d64fdec9e5a368fc45feaa49bed6ced815967e582bc7b8af534f22a9475
4
4
  // DO NOT EDIT — regenerate via `node scripts/bundle-license-pubkey.mjs` or
@@ -1,4 +1,4 @@
1
- // AUTO-GENERATED by scripts/bundle-pubkey.mjs at 2026-05-17T15:51:32.309Z.
1
+ // AUTO-GENERATED by scripts/bundle-pubkey.mjs at 2026-05-17T16:00:08.460Z.
2
2
  // Source pem: packages/core/security/registry-pubkey.pem
3
3
  // RAW-bytes sha256: 3b6226d036c472e533110d11a7d0cd2773ce1d7d4f1003517d5bd69c5418ed4c
4
4
  // DO NOT EDIT — regenerate via `node scripts/bundle-pubkey.mjs` or
package/src/tools.ts CHANGED
@@ -38,6 +38,7 @@ import { getKnowledgeToolDefinitions, isKnowledgeTool, handleKnowledgeToolCall }
38
38
  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
+ import { supportsRouter, supportsOrm } from './lib/framework-supports.ts';
41
42
  import { getCurrentTier, getToolTier, isToolAllowed, annotateToolDefinitions, getLicenseToolDefinitions, isLicenseTool, handleLicenseToolCall, isCloudFeatureAvailable } from './license.ts';
42
43
  import { t } from './lib/sql-table-names.ts';
43
44
 
@@ -99,7 +100,7 @@ function ensureIndexes(dataDb: Database.Database, codegraphDb?: Database.Databas
99
100
  const importCount = buildImportIndex(dataDb, codegraphDb);
100
101
  results.push(`Import edges: ${importCount}`);
101
102
 
102
- if (config.framework.router === 'trpc') {
103
+ if (supportsRouter('trpc')) {
103
104
  const trpcStats = buildTrpcIndex(dataDb);
104
105
  results.push(`tRPC procedures: ${trpcStats.totalProcedures} (${trpcStats.withCallers} with UI, ${trpcStats.withoutCallers} without)`);
105
106
  }
@@ -203,7 +204,7 @@ export function getToolDefinitions(): ToolDefinition[] {
203
204
  required: ['file'],
204
205
  },
205
206
  },
206
- ...(config.framework.router === 'trpc' ? [
207
+ ...(supportsRouter('trpc') ? [
207
208
  {
208
209
  name: p('trpc_map'),
209
210
  description: 'Map tRPC procedures to their UI call sites. Find which components call a router, which procedures have no UI callers, or list all procedures for a router.',
@@ -257,7 +258,7 @@ export function getToolDefinitions(): ToolDefinition[] {
257
258
  required: [],
258
259
  },
259
260
  }] : []),
260
- ...(config.framework.orm === 'prisma' ? [{
261
+ ...(supportsOrm('prisma') ? [{
261
262
  name: p('schema'),
262
263
  description: 'Prisma schema cross-reference. Show columns for a table, detect mismatches between code and schema, or verify column references in a file.',
263
264
  inputSchema: {