@mandujs/mcp 0.38.12 → 0.39.0-beta.1

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 (183) hide show
  1. package/README.md +3 -3
  2. package/package.json +3 -5
  3. package/src/activity-adapter.ts +23 -23
  4. package/src/activity-monitor.ts +39 -10
  5. package/src/adapters/index.ts +20 -20
  6. package/src/adapters/monitor-adapter.ts +100 -100
  7. package/src/adapters/tool-adapter.ts +90 -90
  8. package/src/executor/index.ts +22 -22
  9. package/src/executor/tool-executor.ts +148 -148
  10. package/src/hooks/config-watcher.ts +173 -173
  11. package/src/hooks/index.ts +23 -23
  12. package/src/hooks/mcp-hooks.ts +227 -227
  13. package/src/index.ts +5 -5
  14. package/src/logging/index.ts +15 -15
  15. package/src/logging/mcp-transport.ts +134 -134
  16. package/src/new-resources.ts +2 -2
  17. package/src/profiles.ts +25 -54
  18. package/src/prompts.ts +4 -4
  19. package/src/registry/index.ts +13 -13
  20. package/src/registry/mcp-tool-registry.ts +298 -298
  21. package/src/resources/generated-skills/catalog.ts +36 -0
  22. package/src/resources/generated-skills/mandu-agent-workflow/SKILL.md +48 -0
  23. package/src/resources/generated-skills/mandu-contract/SKILL.md +20 -0
  24. package/src/resources/generated-skills/mandu-fs-routes/SKILL.md +19 -0
  25. package/src/resources/generated-skills/mandu-guard/SKILL.md +20 -0
  26. package/src/resources/generated-skills/mandu-hydration/SKILL.md +19 -0
  27. package/src/resources/generated-skills/mandu-testing/SKILL.md +20 -0
  28. package/src/resources/handlers.ts +3 -3
  29. package/src/resources/skills/guides.ts +49 -49
  30. package/src/resources/skills/index.ts +12 -12
  31. package/src/resources/skills/loader.ts +8 -35
  32. package/src/resources/skills/recipes.ts +28 -28
  33. package/src/server.ts +1 -1
  34. package/src/tools/agent.ts +479 -409
  35. package/src/tools/ate-exemplar.ts +92 -92
  36. package/src/tools/ate-flakes.ts +90 -90
  37. package/src/tools/ate-mutate.ts +103 -103
  38. package/src/tools/ate-mutation-report.ts +64 -64
  39. package/src/tools/ate-oracle-pending.ts +49 -49
  40. package/src/tools/ate-oracle-replay.ts +44 -44
  41. package/src/tools/ate-oracle-verdict.ts +70 -70
  42. package/src/tools/ate-prompt.ts +146 -146
  43. package/src/tools/ate-run.ts +1 -1
  44. package/src/tools/ate.ts +38 -38
  45. package/src/tools/brain.ts +6 -6
  46. package/src/tools/composite.ts +19 -61
  47. package/src/tools/contract.ts +11 -9
  48. package/src/tools/deploy-plan.ts +2 -2
  49. package/src/tools/deploy-preview.ts +316 -316
  50. package/src/tools/design.ts +825 -825
  51. package/src/tools/docs.ts +350 -350
  52. package/src/tools/generate.ts +4 -3
  53. package/src/tools/guard.ts +1 -1
  54. package/src/tools/history.ts +1 -1
  55. package/src/tools/hydration.ts +64 -64
  56. package/src/tools/index.ts +0 -118
  57. package/src/tools/kitchen.ts +72 -72
  58. package/src/tools/lint.ts +226 -226
  59. package/src/tools/loop-close.ts +175 -175
  60. package/src/tools/negotiate.ts +263 -263
  61. package/src/tools/resource.ts +1 -1
  62. package/src/tools/run-tests.ts +424 -424
  63. package/src/tools/runtime.ts +1 -1
  64. package/src/tools/seo.ts +1 -1
  65. package/src/tools/slot-validation.ts +19 -19
  66. package/src/tools/spec.ts +201 -201
  67. package/src/tools/transaction.ts +1 -1
  68. package/src/tx-lock.ts +73 -73
  69. package/src/utils/runtime-control.ts +52 -52
  70. package/src/utils/withWarnings.ts +1 -1
  71. package/src/resources/skills/mandu-agent-workflow/SKILL.md +0 -124
  72. package/src/resources/skills/mandu-agent-workflow/metadata.json +0 -7
  73. package/src/resources/skills/mandu-composition/SKILL.md +0 -131
  74. package/src/resources/skills/mandu-composition/metadata.json +0 -13
  75. package/src/resources/skills/mandu-composition/rules/_sections.md +0 -26
  76. package/src/resources/skills/mandu-composition/rules/_template.md +0 -77
  77. package/src/resources/skills/mandu-composition/rules/comp-arch-avoid-boolean-props.md +0 -146
  78. package/src/resources/skills/mandu-composition/rules/comp-arch-compound-components.md +0 -164
  79. package/src/resources/skills/mandu-composition/rules/comp-island-event.md +0 -161
  80. package/src/resources/skills/mandu-composition/rules/comp-island-slot-split.md +0 -167
  81. package/src/resources/skills/mandu-composition/rules/comp-pattern-children.md +0 -149
  82. package/src/resources/skills/mandu-composition/rules/comp-state-context-interface.md +0 -148
  83. package/src/resources/skills/mandu-composition/rules/comp-state-lift-state.md +0 -150
  84. package/src/resources/skills/mandu-deployment/SKILL.md +0 -135
  85. package/src/resources/skills/mandu-deployment/_sections.md +0 -41
  86. package/src/resources/skills/mandu-deployment/_template.md +0 -38
  87. package/src/resources/skills/mandu-deployment/metadata.json +0 -13
  88. package/src/resources/skills/mandu-deployment/rules/db-provider-supabase.md +0 -300
  89. package/src/resources/skills/mandu-deployment/rules/deploy-build-bun.md +0 -109
  90. package/src/resources/skills/mandu-deployment/rules/deploy-build-output.md +0 -115
  91. package/src/resources/skills/mandu-deployment/rules/deploy-cicd-github.md +0 -219
  92. package/src/resources/skills/mandu-deployment/rules/deploy-docker-bun.md +0 -150
  93. package/src/resources/skills/mandu-deployment/rules/deploy-docker-compose.md +0 -223
  94. package/src/resources/skills/mandu-deployment/rules/deploy-platform-fly.md +0 -152
  95. package/src/resources/skills/mandu-deployment/rules/deploy-platform-render.md +0 -179
  96. package/src/resources/skills/mandu-deployment/rules/deploy-platform-vercel.md +0 -140
  97. package/src/resources/skills/mandu-fs-routes/SKILL.md +0 -122
  98. package/src/resources/skills/mandu-fs-routes/metadata.json +0 -12
  99. package/src/resources/skills/mandu-fs-routes/rules/_sections.md +0 -36
  100. package/src/resources/skills/mandu-fs-routes/rules/_template.md +0 -69
  101. package/src/resources/skills/mandu-fs-routes/rules/routes-api-methods.md +0 -65
  102. package/src/resources/skills/mandu-fs-routes/rules/routes-dynamic-param.md +0 -93
  103. package/src/resources/skills/mandu-fs-routes/rules/routes-naming-page.md +0 -55
  104. package/src/resources/skills/mandu-guard/SKILL.md +0 -162
  105. package/src/resources/skills/mandu-guard/metadata.json +0 -12
  106. package/src/resources/skills/mandu-guard/rules/_sections.md +0 -36
  107. package/src/resources/skills/mandu-guard/rules/_template.md +0 -82
  108. package/src/resources/skills/mandu-guard/rules/guard-config-rules.md +0 -100
  109. package/src/resources/skills/mandu-guard/rules/guard-layer-direction.md +0 -76
  110. package/src/resources/skills/mandu-guard/rules/guard-preset-mandu.md +0 -81
  111. package/src/resources/skills/mandu-guard/rules/guard-validate-import.md +0 -80
  112. package/src/resources/skills/mandu-hydration/SKILL.md +0 -139
  113. package/src/resources/skills/mandu-hydration/metadata.json +0 -12
  114. package/src/resources/skills/mandu-hydration/rules/_sections.md +0 -31
  115. package/src/resources/skills/mandu-hydration/rules/_template.md +0 -72
  116. package/src/resources/skills/mandu-hydration/rules/hydration-data-event.md +0 -109
  117. package/src/resources/skills/mandu-hydration/rules/hydration-directive-use-client.md +0 -55
  118. package/src/resources/skills/mandu-hydration/rules/hydration-island-setup.md +0 -160
  119. package/src/resources/skills/mandu-hydration/rules/hydration-priority-visible.md +0 -91
  120. package/src/resources/skills/mandu-performance/SKILL.md +0 -125
  121. package/src/resources/skills/mandu-performance/metadata.json +0 -14
  122. package/src/resources/skills/mandu-performance/rules/_sections.md +0 -31
  123. package/src/resources/skills/mandu-performance/rules/_template.md +0 -64
  124. package/src/resources/skills/mandu-performance/rules/perf-async-defer-await.md +0 -103
  125. package/src/resources/skills/mandu-performance/rules/perf-async-parallel.md +0 -95
  126. package/src/resources/skills/mandu-performance/rules/perf-bun-file.md +0 -124
  127. package/src/resources/skills/mandu-performance/rules/perf-bun-serve.md +0 -125
  128. package/src/resources/skills/mandu-performance/rules/perf-bundle-imports.md +0 -80
  129. package/src/resources/skills/mandu-performance/rules/perf-bundle-island-lazy.md +0 -145
  130. package/src/resources/skills/mandu-performance/rules/perf-cache-react.md +0 -98
  131. package/src/resources/skills/mandu-performance/rules/perf-render-transitions.md +0 -154
  132. package/src/resources/skills/mandu-security/SKILL.md +0 -127
  133. package/src/resources/skills/mandu-security/metadata.json +0 -13
  134. package/src/resources/skills/mandu-security/rules/_sections.md +0 -31
  135. package/src/resources/skills/mandu-security/rules/_template.md +0 -74
  136. package/src/resources/skills/mandu-security/rules/sec-auth-guard.md +0 -127
  137. package/src/resources/skills/mandu-security/rules/sec-env-management.md +0 -133
  138. package/src/resources/skills/mandu-security/rules/sec-input-validate.md +0 -148
  139. package/src/resources/skills/mandu-security/rules/sec-protect-csrf.md +0 -146
  140. package/src/resources/skills/mandu-security/rules/sec-protect-headers.md +0 -138
  141. package/src/resources/skills/mandu-slot/SKILL.md +0 -125
  142. package/src/resources/skills/mandu-slot/metadata.json +0 -12
  143. package/src/resources/skills/mandu-slot/rules/_sections.md +0 -36
  144. package/src/resources/skills/mandu-slot/rules/_template.md +0 -63
  145. package/src/resources/skills/mandu-slot/rules/slot-basic-structure.md +0 -38
  146. package/src/resources/skills/mandu-slot/rules/slot-ctx-response.md +0 -56
  147. package/src/resources/skills/mandu-slot/rules/slot-guard-auth.md +0 -59
  148. package/src/resources/skills/mandu-slot/rules/slot-http-methods.md +0 -64
  149. package/src/resources/skills/mandu-styling/SKILL.md +0 -196
  150. package/src/resources/skills/mandu-styling/_sections.md +0 -43
  151. package/src/resources/skills/mandu-styling/_template.md +0 -32
  152. package/src/resources/skills/mandu-styling/metadata.json +0 -15
  153. package/src/resources/skills/mandu-styling/rules/style-component-compound.md +0 -235
  154. package/src/resources/skills/mandu-styling/rules/style-component-slots.md +0 -255
  155. package/src/resources/skills/mandu-styling/rules/style-component-tokens.md +0 -205
  156. package/src/resources/skills/mandu-styling/rules/style-island-animations.md +0 -272
  157. package/src/resources/skills/mandu-styling/rules/style-island-scoping.md +0 -167
  158. package/src/resources/skills/mandu-styling/rules/style-island-variants.md +0 -221
  159. package/src/resources/skills/mandu-styling/rules/style-perf-critical.md +0 -209
  160. package/src/resources/skills/mandu-styling/rules/style-perf-purge.md +0 -192
  161. package/src/resources/skills/mandu-styling/rules/style-setup-modules.md +0 -162
  162. package/src/resources/skills/mandu-styling/rules/style-setup-panda.md +0 -164
  163. package/src/resources/skills/mandu-styling/rules/style-setup-tailwind.md +0 -170
  164. package/src/resources/skills/mandu-styling/rules/style-tailwind-v4-gotchas.md +0 -179
  165. package/src/resources/skills/mandu-styling/rules/style-theme-darkmode.md +0 -229
  166. package/src/resources/skills/mandu-testing/SKILL.md +0 -132
  167. package/src/resources/skills/mandu-testing/metadata.json +0 -13
  168. package/src/resources/skills/mandu-testing/rules/_sections.md +0 -26
  169. package/src/resources/skills/mandu-testing/rules/_template.md +0 -65
  170. package/src/resources/skills/mandu-testing/rules/test-component-island.md +0 -195
  171. package/src/resources/skills/mandu-testing/rules/test-e2e-playwright.md +0 -196
  172. package/src/resources/skills/mandu-testing/rules/test-mock-fetch.md +0 -219
  173. package/src/resources/skills/mandu-testing/rules/test-slot-unit.md +0 -192
  174. package/src/resources/skills/mandu-ui/SKILL.md +0 -159
  175. package/src/resources/skills/mandu-ui/_sections.md +0 -23
  176. package/src/resources/skills/mandu-ui/_template.md +0 -32
  177. package/src/resources/skills/mandu-ui/metadata.json +0 -13
  178. package/src/resources/skills/mandu-ui/rules/ui-accessibility-aria.md +0 -232
  179. package/src/resources/skills/mandu-ui/rules/ui-accessibility-focus.md +0 -238
  180. package/src/resources/skills/mandu-ui/rules/ui-composition-patterns.md +0 -259
  181. package/src/resources/skills/mandu-ui/rules/ui-island-integration.md +0 -258
  182. package/src/resources/skills/mandu-ui/rules/ui-radix-patterns.md +0 -213
  183. package/src/resources/skills/mandu-ui/rules/ui-shadcn-setup.md +0 -209
@@ -1,146 +1,146 @@
1
- /**
2
- * `mandu_ate_prompt` — Phase A.3 prompt catalog tool.
3
- *
4
- * See `docs/ate/roadmap-v2-agent-native.md` §4.2 and §7 (A.3 extension
5
- * "Pre-composed prompts") for the design.
6
- *
7
- * Semantics:
8
- * - If `context` is provided, the handler composes the full prompt
9
- * (template + matched exemplars + serialized context) and returns
10
- * a single ready-to-send-to-LLM string.
11
- * - If `context` is omitted, the handler returns the raw template body +
12
- * sha256 + a peek at available exemplars — the agent composes.
13
- *
14
- * Snake_case tool name (§11 decision #4). Read-only.
15
- */
16
-
17
- import type { Tool } from "@modelcontextprotocol/sdk/types.js";
18
- import {
19
- loadPrompt,
20
- scanExemplars,
21
- composePrompt,
22
- type Exemplar,
23
- } from "@mandujs/ate";
24
-
25
- export const atePromptToolDefinitions: Tool[] = [
26
- {
27
- name: "mandu_ate_prompt",
28
- annotations: {
29
- readOnlyHint: true,
30
- },
31
- description:
32
- "Phase A.3 agent-native prompt catalog. Returns the system prompt for a " +
33
- "given test kind, with Mandu-specific primitives, anti-patterns, and the " +
34
- "selector convention baked in. When `context` is passed, the handler " +
35
- "also injects up-to-3 matching exemplars (tagged with @ate-exemplar:) " +
36
- "plus the JSON context block and returns a fully composed, ready-to-" +
37
- "send-to-LLM string. When `context` is omitted, the handler returns the " +
38
- "raw template + the separate exemplar list so the agent can compose. " +
39
- "Kinds available in v1: filling_unit, filling_integration, e2e_playwright. " +
40
- "The returned sha256 is stable per-version and safe as a cache key.",
41
- inputSchema: {
42
- type: "object",
43
- properties: {
44
- repoRoot: {
45
- type: "string",
46
- description:
47
- "Absolute path to the Mandu project root. Required when context is " +
48
- "omitted so we can scan exemplars from the repo.",
49
- },
50
- kind: {
51
- type: "string",
52
- description:
53
- "Prompt kind. v1 catalog: filling_unit | filling_integration | e2e_playwright.",
54
- },
55
- version: {
56
- type: "number",
57
- description:
58
- "Pin to a specific template version. Defaults to the highest available.",
59
- },
60
- context: {
61
- type: "object",
62
- description:
63
- "Optional semantic context (usually the output of mandu_ate_context). " +
64
- "When present, the returned `prompt` is pre-composed.",
65
- additionalProperties: true,
66
- },
67
- maxPositive: {
68
- type: "number",
69
- description: "Max positive exemplars to inject. Default 3.",
70
- },
71
- maxAnti: {
72
- type: "number",
73
- description: "Max anti-exemplars to inject. Default 1.",
74
- },
75
- },
76
- required: ["kind"],
77
- },
78
- },
79
- ];
80
-
81
- export function atePromptTools(_projectRoot: string) {
82
- return {
83
- mandu_ate_prompt: async (args: Record<string, unknown>) => {
84
- const kind = args.kind as string | undefined;
85
- if (!kind || typeof kind !== "string") {
86
- return { ok: false, error: "'kind' is required and must be a string" };
87
- }
88
-
89
- const version = typeof args.version === "number" ? args.version : undefined;
90
- const repoRoot = typeof args.repoRoot === "string" ? args.repoRoot : undefined;
91
- const context = args.context;
92
- const maxPositive = typeof args.maxPositive === "number" ? args.maxPositive : undefined;
93
- const maxAnti = typeof args.maxAnti === "number" ? args.maxAnti : undefined;
94
-
95
- try {
96
- // When context is given, return a pre-composed prompt.
97
- if (context !== undefined) {
98
- const composed = await composePrompt({
99
- kind,
100
- version,
101
- context,
102
- repoRoot,
103
- ...(maxPositive !== undefined ? { maxPositive } : {}),
104
- ...(maxAnti !== undefined ? { maxAnti } : {}),
105
- });
106
- return {
107
- ok: true,
108
- prompt: composed.prompt,
109
- sha256: composed.sha256,
110
- version: composed.version,
111
- kind: composed.kind,
112
- exemplarCount: composed.exemplarCount,
113
- antiCount: composed.antiCount,
114
- tokenEstimate: composed.tokenEstimate,
115
- };
116
- }
117
-
118
- // Otherwise: raw template + exemplar peek so the agent composes.
119
- const loaded = loadPrompt(kind, version);
120
- let exemplars: Exemplar[] = [];
121
- if (repoRoot) {
122
- try {
123
- const all = await scanExemplars(repoRoot);
124
- exemplars = all.filter((e) => e.kind === kind).slice(0, 5);
125
- } catch {
126
- // non-fatal — caller may invoke without a repoRoot
127
- }
128
- }
129
- return {
130
- ok: true,
131
- prompt: loaded.raw,
132
- sha256: loaded.sha256,
133
- version: loaded.frontmatter.version,
134
- kind: loaded.frontmatter.kind,
135
- exemplars,
136
- exemplarCount: exemplars.filter((e) => !e.anti).length,
137
- antiCount: exemplars.filter((e) => e.anti).length,
138
- tokenEstimate: Math.ceil(loaded.raw.length / 4),
139
- };
140
- } catch (err) {
141
- const msg = err instanceof Error ? err.message : String(err);
142
- return { ok: false, error: msg };
143
- }
144
- },
145
- };
146
- }
1
+ /**
2
+ * `mandu_ate_prompt` — Phase A.3 prompt catalog tool.
3
+ *
4
+ * See `docs/ate/roadmap-v2-agent-native.md` §4.2 and §7 (A.3 extension
5
+ * "Pre-composed prompts") for the design.
6
+ *
7
+ * Semantics:
8
+ * - If `context` is provided, the handler composes the full prompt
9
+ * (template + matched exemplars + serialized context) and returns
10
+ * a single ready-to-send-to-LLM string.
11
+ * - If `context` is omitted, the handler returns the raw template body +
12
+ * sha256 + a peek at available exemplars — the agent composes.
13
+ *
14
+ * Snake_case tool name (§11 decision #4). Read-only.
15
+ */
16
+
17
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
18
+ import {
19
+ loadPrompt,
20
+ scanExemplars,
21
+ composePrompt,
22
+ type Exemplar,
23
+ } from "@mandujs/ate";
24
+
25
+ export const atePromptToolDefinitions: Tool[] = [
26
+ {
27
+ name: "mandu_ate_prompt",
28
+ annotations: {
29
+ readOnlyHint: true,
30
+ },
31
+ description:
32
+ "Phase A.3 agent-native prompt catalog. Returns the system prompt for a " +
33
+ "given test kind, with Mandu-specific primitives, anti-patterns, and the " +
34
+ "selector convention baked in. When `context` is passed, the handler " +
35
+ "also injects up-to-3 matching exemplars (tagged with @ate-exemplar:) " +
36
+ "plus the JSON context block and returns a fully composed, ready-to-" +
37
+ "send-to-LLM string. When `context` is omitted, the handler returns the " +
38
+ "raw template + the separate exemplar list so the agent can compose. " +
39
+ "Kinds available in v1: filling_unit, filling_integration, e2e_playwright. " +
40
+ "The returned sha256 is stable per-version and safe as a cache key.",
41
+ inputSchema: {
42
+ type: "object",
43
+ properties: {
44
+ repoRoot: {
45
+ type: "string",
46
+ description:
47
+ "Absolute path to the Mandu project root. Required when context is " +
48
+ "omitted so we can scan exemplars from the repo.",
49
+ },
50
+ kind: {
51
+ type: "string",
52
+ description:
53
+ "Prompt kind. v1 catalog: filling_unit | filling_integration | e2e_playwright.",
54
+ },
55
+ version: {
56
+ type: "number",
57
+ description:
58
+ "Pin to a specific template version. Defaults to the highest available.",
59
+ },
60
+ context: {
61
+ type: "object",
62
+ description:
63
+ "Optional semantic context (usually the output of mandu_ate_context). " +
64
+ "When present, the returned `prompt` is pre-composed.",
65
+ additionalProperties: true,
66
+ },
67
+ maxPositive: {
68
+ type: "number",
69
+ description: "Max positive exemplars to inject. Default 3.",
70
+ },
71
+ maxAnti: {
72
+ type: "number",
73
+ description: "Max anti-exemplars to inject. Default 1.",
74
+ },
75
+ },
76
+ required: ["kind"],
77
+ },
78
+ },
79
+ ];
80
+
81
+ export function atePromptTools(_projectRoot: string) {
82
+ return {
83
+ mandu_ate_prompt: async (args: Record<string, unknown>) => {
84
+ const kind = args.kind as string | undefined;
85
+ if (!kind || typeof kind !== "string") {
86
+ return { ok: false, error: "'kind' is required and must be a string" };
87
+ }
88
+
89
+ const version = typeof args.version === "number" ? args.version : undefined;
90
+ const repoRoot = typeof args.repoRoot === "string" ? args.repoRoot : undefined;
91
+ const context = args.context;
92
+ const maxPositive = typeof args.maxPositive === "number" ? args.maxPositive : undefined;
93
+ const maxAnti = typeof args.maxAnti === "number" ? args.maxAnti : undefined;
94
+
95
+ try {
96
+ // When context is given, return a pre-composed prompt.
97
+ if (context !== undefined) {
98
+ const composed = await composePrompt({
99
+ kind,
100
+ version,
101
+ context,
102
+ repoRoot,
103
+ ...(maxPositive !== undefined ? { maxPositive } : {}),
104
+ ...(maxAnti !== undefined ? { maxAnti } : {}),
105
+ });
106
+ return {
107
+ ok: true,
108
+ prompt: composed.prompt,
109
+ sha256: composed.sha256,
110
+ version: composed.version,
111
+ kind: composed.kind,
112
+ exemplarCount: composed.exemplarCount,
113
+ antiCount: composed.antiCount,
114
+ tokenEstimate: composed.tokenEstimate,
115
+ };
116
+ }
117
+
118
+ // Otherwise: raw template + exemplar peek so the agent composes.
119
+ const loaded = loadPrompt(kind, version);
120
+ let exemplars: Exemplar[] = [];
121
+ if (repoRoot) {
122
+ try {
123
+ const all = await scanExemplars(repoRoot);
124
+ exemplars = all.filter((e) => e.kind === kind).slice(0, 5);
125
+ } catch {
126
+ // non-fatal — caller may invoke without a repoRoot
127
+ }
128
+ }
129
+ return {
130
+ ok: true,
131
+ prompt: loaded.raw,
132
+ sha256: loaded.sha256,
133
+ version: loaded.frontmatter.version,
134
+ kind: loaded.frontmatter.kind,
135
+ exemplars,
136
+ exemplarCount: exemplars.filter((e) => !e.anti).length,
137
+ antiCount: exemplars.filter((e) => e.anti).length,
138
+ tokenEstimate: Math.ceil(loaded.raw.length / 4),
139
+ };
140
+ } catch (err) {
141
+ const msg = err instanceof Error ? err.message : String(err);
142
+ return { ok: false, error: msg };
143
+ }
144
+ },
145
+ };
146
+ }
@@ -37,7 +37,7 @@ import {
37
37
  type AteMonitorEvent,
38
38
  type FailureV1,
39
39
  } from "@mandujs/ate";
40
- import { eventBus } from "@mandujs/core/observability";
40
+ import { eventBus } from "@mandujs/core/compat/observability/index";
41
41
 
42
42
  export const ateRunToolDefinitions: Tool[] = [
43
43
  {
package/src/tools/ate.ts CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  precommitCheck,
16
16
  } from "@mandujs/ate";
17
17
  import type { OracleLevel, AteMonitorEvent } from "@mandujs/ate";
18
- import { eventBus } from "@mandujs/core/observability";
18
+ import { eventBus } from "@mandujs/core/compat/observability/index";
19
19
  import {
20
20
  writePartialResults,
21
21
  createAteProgressTracker,
@@ -105,11 +105,11 @@ export const ateToolDefinitions: Tool[] = [
105
105
  type: "string",
106
106
  description: "Dev server URL (default: http://localhost:3333). Must match the running mandu dev server.",
107
107
  },
108
- ci: { type: "boolean", description: "CI mode: stricter timeouts, no interactive prompts" },
109
- timeoutMs: {
110
- type: "number",
111
- description: "Hard timeout for the whole Playwright process in milliseconds (default: 600000).",
112
- },
108
+ ci: { type: "boolean", description: "CI mode: stricter timeouts, no interactive prompts" },
109
+ timeoutMs: {
110
+ type: "number",
111
+ description: "Hard timeout for the whole Playwright process in milliseconds (default: 600000).",
112
+ },
113
113
  headless: { type: "boolean", description: "Run browsers headlessly (default: true)" },
114
114
  browsers: {
115
115
  type: "array",
@@ -264,11 +264,11 @@ export const ateToolDefinitions: Tool[] = [
264
264
  enum: ["L0", "L1", "L2", "L3"],
265
265
  description: "Assertion depth: L0=smoke, L1=HTTP status, L2=contract schema, L3=full behavioral",
266
266
  },
267
- ci: { type: "boolean", description: "CI mode: stricter timeouts" },
268
- timeoutMs: {
269
- type: "number",
270
- description: "Hard timeout for the whole Playwright process in milliseconds (default: 600000).",
271
- },
267
+ ci: { type: "boolean", description: "CI mode: stricter timeouts" },
268
+ timeoutMs: {
269
+ type: "number",
270
+ description: "Hard timeout for the whole Playwright process in milliseconds (default: 600000).",
271
+ },
272
272
  useImpactAnalysis: {
273
273
  type: "boolean",
274
274
  description: "Run impact analysis first and only test changed routes (faster in CI)",
@@ -386,7 +386,7 @@ export function ateTools(projectRoot: string, server?: Server) {
386
386
  return await ateRun(input);
387
387
  } catch (err) {
388
388
  const message = err instanceof Error ? err.message : String(err);
389
- const isTimeout = /timeout|timed out|타임아웃/i.test(message);
389
+ const isTimeout = /timeout|timed out|타임아웃/i.test(message);
390
390
  const snap = tracker.snapshot();
391
391
  const partial: PartialRunResults = {
392
392
  runId: snap.runId ?? `unknown-${Date.now()}`,
@@ -447,21 +447,21 @@ export function ateTools(projectRoot: string, server?: Server) {
447
447
  browsers,
448
448
  onlyFiles,
449
449
  onlyRoutes,
450
- grep,
451
- timeoutMs,
452
- progressToken,
453
- } = args as {
450
+ grep,
451
+ timeoutMs,
452
+ progressToken,
453
+ } = args as {
454
454
  repoRoot: string;
455
455
  baseURL?: string;
456
456
  ci?: boolean;
457
457
  headless?: boolean;
458
458
  browsers?: ("chromium" | "firefox" | "webkit")[];
459
459
  onlyFiles?: string[];
460
- onlyRoutes?: string[];
461
- grep?: string;
462
- timeoutMs?: number;
463
- progressToken?: string | number;
464
- };
460
+ onlyRoutes?: string[];
461
+ grep?: string;
462
+ timeoutMs?: number;
463
+ progressToken?: string | number;
464
+ };
465
465
  return await runWithObservability(
466
466
  {
467
467
  repoRoot,
@@ -469,11 +469,11 @@ export function ateTools(projectRoot: string, server?: Server) {
469
469
  ci,
470
470
  headless,
471
471
  browsers,
472
- onlyFiles,
473
- onlyRoutes,
474
- grep,
475
- timeoutMs,
476
- },
472
+ onlyFiles,
473
+ onlyRoutes,
474
+ grep,
475
+ timeoutMs,
476
+ },
477
477
  { progressToken },
478
478
  );
479
479
  },
@@ -529,10 +529,10 @@ export function ateTools(projectRoot: string, server?: Server) {
529
529
  },
530
530
  "mandu.ate.auto_pipeline": async (args: Record<string, unknown>) => {
531
531
  const {
532
- repoRoot, baseURL, oracleLevel, ci, useImpactAnalysis,
533
- base, head, autoHeal, tsconfigPath, routeGlobs, buildSalt,
534
- timeoutMs,
535
- } = args as {
532
+ repoRoot, baseURL, oracleLevel, ci, useImpactAnalysis,
533
+ base, head, autoHeal, tsconfigPath, routeGlobs, buildSalt,
534
+ timeoutMs,
535
+ } = args as {
536
536
  repoRoot: string;
537
537
  baseURL?: string;
538
538
  oracleLevel?: OracleLevel;
@@ -542,14 +542,14 @@ export function ateTools(projectRoot: string, server?: Server) {
542
542
  head?: string;
543
543
  autoHeal?: boolean;
544
544
  tsconfigPath?: string;
545
- routeGlobs?: string[];
546
- buildSalt?: string;
547
- timeoutMs?: number;
548
- };
549
- return await runFullPipeline({
550
- repoRoot, baseURL, oracleLevel, ci, useImpactAnalysis,
551
- base, head, autoHeal, tsconfigPath, routeGlobs, buildSalt, timeoutMs,
552
- });
545
+ routeGlobs?: string[];
546
+ buildSalt?: string;
547
+ timeoutMs?: number;
548
+ };
549
+ return await runFullPipeline({
550
+ repoRoot, baseURL, oracleLevel, ci, useImpactAnalysis,
551
+ base, head, autoHeal, tsconfigPath, routeGlobs, buildSalt, timeoutMs,
552
+ });
553
553
  },
554
554
  "mandu.ate.feedback": async (args: Record<string, unknown>) => {
555
555
  const { repoRoot, runId, autoApply } = args as {
@@ -20,13 +20,13 @@ import {
20
20
  getBrain,
21
21
  initializeArchitectureAnalyzer,
22
22
  getArchitectureAnalyzer,
23
- } from "@mandujs/core/brain";
23
+ } from "@mandujs/core/compat/brain/index";
24
24
  import {
25
25
  generateJsonStatus,
26
26
  getWatcher,
27
27
  startWatcher,
28
28
  stopWatcher,
29
- } from "@mandujs/core/watcher";
29
+ } from "@mandujs/core/compat/watcher/index";
30
30
  import { getProjectPaths } from "../utils/project.js";
31
31
 
32
32
  export const brainToolDefinitions: Tool[] = [
@@ -665,7 +665,7 @@ export function brainTools(projectRoot: string, server?: Server, monitor?: Activ
665
665
 
666
666
  // #235 followup — brain auth tools (status / login / logout).
667
667
  handlers["mandu.brain.status"] = async () => {
668
- const core = await import("@mandujs/core/brain");
668
+ const core = await import("@mandujs/core/compat/brain/index");
669
669
  assertBrainAuthSurface(core);
670
670
  const store = core.getCredentialStore();
671
671
  const resolution = await core.resolveBrainAdapter({
@@ -745,7 +745,7 @@ export function brainTools(projectRoot: string, server?: Server, monitor?: Activ
745
745
  };
746
746
 
747
747
  if (provider === "openai") {
748
- const core = await import("@mandujs/core/brain");
748
+ const core = await import("@mandujs/core/compat/brain/index");
749
749
  assertBrainAuthSurface(core);
750
750
  const auth = new core.ChatGPTAuth();
751
751
  const existing = auth.locateAuthFile();
@@ -836,7 +836,7 @@ export function brainTools(projectRoot: string, server?: Server, monitor?: Activ
836
836
  }
837
837
 
838
838
  // Anthropic — Mandu-managed OAuth loopback flow.
839
- const core = await import("@mandujs/core/brain");
839
+ const core = await import("@mandujs/core/compat/brain/index");
840
840
  assertBrainAuthSurface(core);
841
841
  try {
842
842
  const adapter = new core.AnthropicOAuthAdapter({
@@ -889,7 +889,7 @@ export function brainTools(projectRoot: string, server?: Server, monitor?: Activ
889
889
  const { provider = "all" } = args as {
890
890
  provider?: "openai" | "anthropic" | "all";
891
891
  };
892
- const core = await import("@mandujs/core/brain");
892
+ const core = await import("@mandujs/core/compat/brain/index");
893
893
  assertBrainAuthSurface(core);
894
894
  const store = core.getCredentialStore();
895
895
  const targets =
@@ -8,12 +8,11 @@ import { specTools } from "./spec.js";
8
8
  import { guardTools } from "./guard.js";
9
9
  import { negotiateTools } from "./negotiate.js";
10
10
  import { contractTools } from "./contract.js";
11
- import { generateTools } from "./generate.js";
12
- import { kitchenTools } from "./kitchen.js";
13
- import { ateTools } from "./ate.js";
11
+ import { generateTools } from "./generate.js";
12
+ import { kitchenTools } from "./kitchen.js";
14
13
  import { requestRuntimeCache } from "../utils/runtime-control.js";
15
14
  import { requireLock } from "../tx-lock.js";
16
- import { runExtendedDiagnose, buildReport, type DiagnoseCheckResult } from "@mandujs/core/diagnose";
15
+ import { runExtendedDiagnose, buildReport, type DiagnoseCheckResult } from "@mandujs/core/compat/diagnose/index";
17
16
  import path from "path";
18
17
  import fs from "fs/promises";
19
18
 
@@ -60,10 +59,10 @@ export const compositeToolDefinitions: Tool[] = [
60
59
  },
61
60
  },
62
61
  {
63
- name: "mandu.island.add",
64
- description:
65
- "Create an island component with correct @mandujs/core/client imports and hydration strategy. " +
66
- "Generates a .island.tsx file in app/{route}/ with the wrapComponent() island definition.",
62
+ name: "mandu.island.add",
63
+ description:
64
+ "Create an island component with correct @mandujs/core/client imports and hydration strategy. " +
65
+ "Generates a .island.tsx file in app/{route}/ with the wrapComponent() island definition.",
67
66
  annotations: {
68
67
  destructiveHint: true,
69
68
  readOnlyHint: false,
@@ -96,23 +95,6 @@ export const compositeToolDefinitions: Tool[] = [
96
95
  required: ["preset"],
97
96
  },
98
97
  },
99
- {
100
- name: "mandu.test.route",
101
- description:
102
- "Run the ATE test pipeline on a single route: extract -> generate -> run -> report. " +
103
- "Set quick=true to skip extraction and use cached data.",
104
- annotations: {
105
- readOnlyHint: false,
106
- },
107
- inputSchema: {
108
- type: "object",
109
- properties: {
110
- routeId: { type: "string", description: "Route ID to test (e.g. 'api-users', 'blog-slug')" },
111
- quick: { type: "boolean", description: "Skip extraction, reuse cached graph (default: false)" },
112
- },
113
- required: ["routeId"],
114
- },
115
- },
116
98
  {
117
99
  name: "mandu.deploy.check",
118
100
  description:
@@ -164,10 +146,9 @@ export function compositeTools(projectRoot: string) {
164
146
  const spec = specTools(projectRoot);
165
147
  const guard = guardTools(projectRoot);
166
148
  const neg = negotiateTools(projectRoot);
167
- const contract = contractTools(projectRoot);
168
- const generate = generateTools(projectRoot);
169
- const kitchen = kitchenTools(projectRoot);
170
- const ate = ateTools(projectRoot);
149
+ const contract = contractTools(projectRoot);
150
+ const generate = generateTools(projectRoot);
151
+ const kitchen = kitchenTools(projectRoot);
171
152
 
172
153
  return {
173
154
  "mandu.feature.create": async (args: Record<string, unknown>) => {
@@ -362,29 +343,6 @@ export function compositeTools(projectRoot: string) {
362
343
  return { created: true, path: "app/middleware.ts", preset };
363
344
  },
364
345
 
365
- "mandu.test.route": async (args: Record<string, unknown>) => {
366
- const { routeId, quick = false } = args as { routeId: string; quick?: boolean };
367
- const steps: { step: string; result: unknown }[] = [];
368
- if (!quick) {
369
- steps.push({ step: "extract", result: await ate["mandu.ate.extract"]({ repoRoot: projectRoot, routeGlobs: [`app/${routeId.replace(/-/g, "/")}/**`] }) });
370
- }
371
- steps.push({ step: "generate", result: await ate["mandu.ate.generate"]({ repoRoot: projectRoot, oracleLevel: "L1", onlyRoutes: [routeId] }) });
372
- const runResult = await ate["mandu.ate.run"]({ repoRoot: projectRoot }) as { runId?: string; startedAt?: string; finishedAt?: string; exitCode?: number };
373
- steps.push({ step: "run", result: runResult });
374
- const report = await ate["mandu.ate.report"]({
375
- repoRoot: projectRoot, runId: runResult.runId ?? "unknown",
376
- startedAt: runResult.startedAt ?? new Date().toISOString(), finishedAt: runResult.finishedAt ?? new Date().toISOString(),
377
- exitCode: runResult.exitCode ?? 1,
378
- });
379
- steps.push({ step: "report", result: report });
380
- const passed = runResult.exitCode === 0;
381
- let healSuggestions: unknown | undefined;
382
- if (!passed && runResult.runId) {
383
- healSuggestions = await ate["mandu.ate.heal"]({ repoRoot: projectRoot, runId: runResult.runId }).catch(() => undefined);
384
- }
385
- return { passed, routeId, results: steps, ...(healSuggestions ? { healSuggestions } : {}) };
386
- },
387
-
388
346
  "mandu.deploy.check": async (args: Record<string, unknown>) => {
389
347
  const { target = "bun" } = args as { target?: "bun" | "docker" | "node" };
390
348
  const [guardResult, contractResult, manifestResult] = await Promise.all([
@@ -474,10 +432,10 @@ function generateMiddlewareSource(preset: string, options: Record<string, string
474
432
  return templates[preset] ?? templates.default;
475
433
  }
476
434
 
477
- function generateIslandSource(name: string, strategy: string): string {
478
- return `"use client";
479
- import { wrapComponent } from "@mandujs/core/client";
480
- import { useState } from "react";
435
+ function generateIslandSource(name: string, strategy: string): string {
436
+ return `"use client";
437
+ import { wrapComponent } from "@mandujs/core/client";
438
+ import { useState } from "react";
481
439
 
482
440
  interface ${name}Props {
483
441
  [key: string]: unknown;
@@ -493,8 +451,8 @@ function ${name}Inner(props: ${name}Props) {
493
451
  );
494
452
  }
495
453
 
496
- // Route hydration priority should be set on the page/manifest route.
497
- // Suggested priority for this island: "${strategy}".
498
- export default wrapComponent(${name}Inner);
499
- `;
500
- }
454
+ // Route hydration priority should be set on the page/manifest route.
455
+ // Suggested priority for this island: "${strategy}".
456
+ export default wrapComponent(${name}Inner);
457
+ `;
458
+ }
@@ -1,13 +1,15 @@
1
1
  import type { Tool } from "@modelcontextprotocol/sdk/types.js";
2
- import {
3
- loadManifest,
4
- runContractGuardCheck,
5
- generateOpenAPIDocument,
6
- openAPIToJSON,
7
- type RouteSpec,
8
- type SpecHttpMethod,
9
- } from "@mandujs/core";
10
- import { generateContractTemplate } from "@mandujs/core/generator";
2
+ import {
3
+ loadManifest,
4
+ runContractGuardCheck,
5
+ type RouteSpec,
6
+ type SpecHttpMethod,
7
+ } from "@mandujs/core";
8
+ import {
9
+ generateOpenAPIDocument,
10
+ openAPIToJSON,
11
+ } from "@mandujs/core/compat/openapi/index";
12
+ import { generateContractTemplate } from "@mandujs/core/compat/generator/index";
11
13
  import { getProjectPaths, writeJsonFile } from "../utils/project.js";
12
14
  import path from "path";
13
15
  import fs from "fs/promises";
@@ -39,13 +39,13 @@ import {
39
39
  type DeployIntentCache,
40
40
  type PlanDiffEntry,
41
41
  type VercelCompileResult,
42
- } from "@mandujs/core/deploy";
42
+ } from "@mandujs/core/compat/deploy/index";
43
43
  import {
44
44
  generateManifest,
45
45
  loadManifest,
46
46
  type RoutesManifest,
47
47
  } from "@mandujs/core";
48
- import { resolveBrainAdapter } from "@mandujs/core/brain";
48
+ import { resolveBrainAdapter } from "@mandujs/core/compat/brain/index";
49
49
  import path from "node:path";
50
50
 
51
51
  /**