@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.
- package/README.md +3 -3
- package/package.json +3 -5
- package/src/activity-adapter.ts +23 -23
- package/src/activity-monitor.ts +39 -10
- package/src/adapters/index.ts +20 -20
- package/src/adapters/monitor-adapter.ts +100 -100
- package/src/adapters/tool-adapter.ts +90 -90
- package/src/executor/index.ts +22 -22
- package/src/executor/tool-executor.ts +148 -148
- package/src/hooks/config-watcher.ts +173 -173
- package/src/hooks/index.ts +23 -23
- package/src/hooks/mcp-hooks.ts +227 -227
- package/src/index.ts +5 -5
- package/src/logging/index.ts +15 -15
- package/src/logging/mcp-transport.ts +134 -134
- package/src/new-resources.ts +2 -2
- package/src/profiles.ts +25 -54
- package/src/prompts.ts +4 -4
- package/src/registry/index.ts +13 -13
- package/src/registry/mcp-tool-registry.ts +298 -298
- package/src/resources/generated-skills/catalog.ts +36 -0
- package/src/resources/generated-skills/mandu-agent-workflow/SKILL.md +48 -0
- package/src/resources/generated-skills/mandu-contract/SKILL.md +20 -0
- package/src/resources/generated-skills/mandu-fs-routes/SKILL.md +19 -0
- package/src/resources/generated-skills/mandu-guard/SKILL.md +20 -0
- package/src/resources/generated-skills/mandu-hydration/SKILL.md +19 -0
- package/src/resources/generated-skills/mandu-testing/SKILL.md +20 -0
- package/src/resources/handlers.ts +3 -3
- package/src/resources/skills/guides.ts +49 -49
- package/src/resources/skills/index.ts +12 -12
- package/src/resources/skills/loader.ts +8 -35
- package/src/resources/skills/recipes.ts +28 -28
- package/src/server.ts +1 -1
- package/src/tools/agent.ts +479 -409
- package/src/tools/ate-exemplar.ts +92 -92
- package/src/tools/ate-flakes.ts +90 -90
- package/src/tools/ate-mutate.ts +103 -103
- package/src/tools/ate-mutation-report.ts +64 -64
- package/src/tools/ate-oracle-pending.ts +49 -49
- package/src/tools/ate-oracle-replay.ts +44 -44
- package/src/tools/ate-oracle-verdict.ts +70 -70
- package/src/tools/ate-prompt.ts +146 -146
- package/src/tools/ate-run.ts +1 -1
- package/src/tools/ate.ts +38 -38
- package/src/tools/brain.ts +6 -6
- package/src/tools/composite.ts +19 -61
- package/src/tools/contract.ts +11 -9
- package/src/tools/deploy-plan.ts +2 -2
- package/src/tools/deploy-preview.ts +316 -316
- package/src/tools/design.ts +825 -825
- package/src/tools/docs.ts +350 -350
- package/src/tools/generate.ts +4 -3
- package/src/tools/guard.ts +1 -1
- package/src/tools/history.ts +1 -1
- package/src/tools/hydration.ts +64 -64
- package/src/tools/index.ts +0 -118
- package/src/tools/kitchen.ts +72 -72
- package/src/tools/lint.ts +226 -226
- package/src/tools/loop-close.ts +175 -175
- package/src/tools/negotiate.ts +263 -263
- package/src/tools/resource.ts +1 -1
- package/src/tools/run-tests.ts +424 -424
- package/src/tools/runtime.ts +1 -1
- package/src/tools/seo.ts +1 -1
- package/src/tools/slot-validation.ts +19 -19
- package/src/tools/spec.ts +201 -201
- package/src/tools/transaction.ts +1 -1
- package/src/tx-lock.ts +73 -73
- package/src/utils/runtime-control.ts +52 -52
- package/src/utils/withWarnings.ts +1 -1
- package/src/resources/skills/mandu-agent-workflow/SKILL.md +0 -124
- package/src/resources/skills/mandu-agent-workflow/metadata.json +0 -7
- package/src/resources/skills/mandu-composition/SKILL.md +0 -131
- package/src/resources/skills/mandu-composition/metadata.json +0 -13
- package/src/resources/skills/mandu-composition/rules/_sections.md +0 -26
- package/src/resources/skills/mandu-composition/rules/_template.md +0 -77
- package/src/resources/skills/mandu-composition/rules/comp-arch-avoid-boolean-props.md +0 -146
- package/src/resources/skills/mandu-composition/rules/comp-arch-compound-components.md +0 -164
- package/src/resources/skills/mandu-composition/rules/comp-island-event.md +0 -161
- package/src/resources/skills/mandu-composition/rules/comp-island-slot-split.md +0 -167
- package/src/resources/skills/mandu-composition/rules/comp-pattern-children.md +0 -149
- package/src/resources/skills/mandu-composition/rules/comp-state-context-interface.md +0 -148
- package/src/resources/skills/mandu-composition/rules/comp-state-lift-state.md +0 -150
- package/src/resources/skills/mandu-deployment/SKILL.md +0 -135
- package/src/resources/skills/mandu-deployment/_sections.md +0 -41
- package/src/resources/skills/mandu-deployment/_template.md +0 -38
- package/src/resources/skills/mandu-deployment/metadata.json +0 -13
- package/src/resources/skills/mandu-deployment/rules/db-provider-supabase.md +0 -300
- package/src/resources/skills/mandu-deployment/rules/deploy-build-bun.md +0 -109
- package/src/resources/skills/mandu-deployment/rules/deploy-build-output.md +0 -115
- package/src/resources/skills/mandu-deployment/rules/deploy-cicd-github.md +0 -219
- package/src/resources/skills/mandu-deployment/rules/deploy-docker-bun.md +0 -150
- package/src/resources/skills/mandu-deployment/rules/deploy-docker-compose.md +0 -223
- package/src/resources/skills/mandu-deployment/rules/deploy-platform-fly.md +0 -152
- package/src/resources/skills/mandu-deployment/rules/deploy-platform-render.md +0 -179
- package/src/resources/skills/mandu-deployment/rules/deploy-platform-vercel.md +0 -140
- package/src/resources/skills/mandu-fs-routes/SKILL.md +0 -122
- package/src/resources/skills/mandu-fs-routes/metadata.json +0 -12
- package/src/resources/skills/mandu-fs-routes/rules/_sections.md +0 -36
- package/src/resources/skills/mandu-fs-routes/rules/_template.md +0 -69
- package/src/resources/skills/mandu-fs-routes/rules/routes-api-methods.md +0 -65
- package/src/resources/skills/mandu-fs-routes/rules/routes-dynamic-param.md +0 -93
- package/src/resources/skills/mandu-fs-routes/rules/routes-naming-page.md +0 -55
- package/src/resources/skills/mandu-guard/SKILL.md +0 -162
- package/src/resources/skills/mandu-guard/metadata.json +0 -12
- package/src/resources/skills/mandu-guard/rules/_sections.md +0 -36
- package/src/resources/skills/mandu-guard/rules/_template.md +0 -82
- package/src/resources/skills/mandu-guard/rules/guard-config-rules.md +0 -100
- package/src/resources/skills/mandu-guard/rules/guard-layer-direction.md +0 -76
- package/src/resources/skills/mandu-guard/rules/guard-preset-mandu.md +0 -81
- package/src/resources/skills/mandu-guard/rules/guard-validate-import.md +0 -80
- package/src/resources/skills/mandu-hydration/SKILL.md +0 -139
- package/src/resources/skills/mandu-hydration/metadata.json +0 -12
- package/src/resources/skills/mandu-hydration/rules/_sections.md +0 -31
- package/src/resources/skills/mandu-hydration/rules/_template.md +0 -72
- package/src/resources/skills/mandu-hydration/rules/hydration-data-event.md +0 -109
- package/src/resources/skills/mandu-hydration/rules/hydration-directive-use-client.md +0 -55
- package/src/resources/skills/mandu-hydration/rules/hydration-island-setup.md +0 -160
- package/src/resources/skills/mandu-hydration/rules/hydration-priority-visible.md +0 -91
- package/src/resources/skills/mandu-performance/SKILL.md +0 -125
- package/src/resources/skills/mandu-performance/metadata.json +0 -14
- package/src/resources/skills/mandu-performance/rules/_sections.md +0 -31
- package/src/resources/skills/mandu-performance/rules/_template.md +0 -64
- package/src/resources/skills/mandu-performance/rules/perf-async-defer-await.md +0 -103
- package/src/resources/skills/mandu-performance/rules/perf-async-parallel.md +0 -95
- package/src/resources/skills/mandu-performance/rules/perf-bun-file.md +0 -124
- package/src/resources/skills/mandu-performance/rules/perf-bun-serve.md +0 -125
- package/src/resources/skills/mandu-performance/rules/perf-bundle-imports.md +0 -80
- package/src/resources/skills/mandu-performance/rules/perf-bundle-island-lazy.md +0 -145
- package/src/resources/skills/mandu-performance/rules/perf-cache-react.md +0 -98
- package/src/resources/skills/mandu-performance/rules/perf-render-transitions.md +0 -154
- package/src/resources/skills/mandu-security/SKILL.md +0 -127
- package/src/resources/skills/mandu-security/metadata.json +0 -13
- package/src/resources/skills/mandu-security/rules/_sections.md +0 -31
- package/src/resources/skills/mandu-security/rules/_template.md +0 -74
- package/src/resources/skills/mandu-security/rules/sec-auth-guard.md +0 -127
- package/src/resources/skills/mandu-security/rules/sec-env-management.md +0 -133
- package/src/resources/skills/mandu-security/rules/sec-input-validate.md +0 -148
- package/src/resources/skills/mandu-security/rules/sec-protect-csrf.md +0 -146
- package/src/resources/skills/mandu-security/rules/sec-protect-headers.md +0 -138
- package/src/resources/skills/mandu-slot/SKILL.md +0 -125
- package/src/resources/skills/mandu-slot/metadata.json +0 -12
- package/src/resources/skills/mandu-slot/rules/_sections.md +0 -36
- package/src/resources/skills/mandu-slot/rules/_template.md +0 -63
- package/src/resources/skills/mandu-slot/rules/slot-basic-structure.md +0 -38
- package/src/resources/skills/mandu-slot/rules/slot-ctx-response.md +0 -56
- package/src/resources/skills/mandu-slot/rules/slot-guard-auth.md +0 -59
- package/src/resources/skills/mandu-slot/rules/slot-http-methods.md +0 -64
- package/src/resources/skills/mandu-styling/SKILL.md +0 -196
- package/src/resources/skills/mandu-styling/_sections.md +0 -43
- package/src/resources/skills/mandu-styling/_template.md +0 -32
- package/src/resources/skills/mandu-styling/metadata.json +0 -15
- package/src/resources/skills/mandu-styling/rules/style-component-compound.md +0 -235
- package/src/resources/skills/mandu-styling/rules/style-component-slots.md +0 -255
- package/src/resources/skills/mandu-styling/rules/style-component-tokens.md +0 -205
- package/src/resources/skills/mandu-styling/rules/style-island-animations.md +0 -272
- package/src/resources/skills/mandu-styling/rules/style-island-scoping.md +0 -167
- package/src/resources/skills/mandu-styling/rules/style-island-variants.md +0 -221
- package/src/resources/skills/mandu-styling/rules/style-perf-critical.md +0 -209
- package/src/resources/skills/mandu-styling/rules/style-perf-purge.md +0 -192
- package/src/resources/skills/mandu-styling/rules/style-setup-modules.md +0 -162
- package/src/resources/skills/mandu-styling/rules/style-setup-panda.md +0 -164
- package/src/resources/skills/mandu-styling/rules/style-setup-tailwind.md +0 -170
- package/src/resources/skills/mandu-styling/rules/style-tailwind-v4-gotchas.md +0 -179
- package/src/resources/skills/mandu-styling/rules/style-theme-darkmode.md +0 -229
- package/src/resources/skills/mandu-testing/SKILL.md +0 -132
- package/src/resources/skills/mandu-testing/metadata.json +0 -13
- package/src/resources/skills/mandu-testing/rules/_sections.md +0 -26
- package/src/resources/skills/mandu-testing/rules/_template.md +0 -65
- package/src/resources/skills/mandu-testing/rules/test-component-island.md +0 -195
- package/src/resources/skills/mandu-testing/rules/test-e2e-playwright.md +0 -196
- package/src/resources/skills/mandu-testing/rules/test-mock-fetch.md +0 -219
- package/src/resources/skills/mandu-testing/rules/test-slot-unit.md +0 -192
- package/src/resources/skills/mandu-ui/SKILL.md +0 -159
- package/src/resources/skills/mandu-ui/_sections.md +0 -23
- package/src/resources/skills/mandu-ui/_template.md +0 -32
- package/src/resources/skills/mandu-ui/metadata.json +0 -13
- package/src/resources/skills/mandu-ui/rules/ui-accessibility-aria.md +0 -232
- package/src/resources/skills/mandu-ui/rules/ui-accessibility-focus.md +0 -238
- package/src/resources/skills/mandu-ui/rules/ui-composition-patterns.md +0 -259
- package/src/resources/skills/mandu-ui/rules/ui-island-integration.md +0 -258
- package/src/resources/skills/mandu-ui/rules/ui-radix-patterns.md +0 -213
- package/src/resources/skills/mandu-ui/rules/ui-shadcn-setup.md +0 -209
package/src/tx-lock.ts
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Transaction Lock — prevents concurrent project mutations from multiple AI agents.
|
|
3
|
-
*
|
|
4
|
-
* In-process singleton. If no lock exists, destructive tools work as before (backward compatible).
|
|
5
|
-
* When a lock is held, only the holder (matching lockId) may execute destructive operations.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export interface TxLock {
|
|
9
|
-
lockId: string;
|
|
10
|
-
sessionId: string;
|
|
11
|
-
acquiredAt: number;
|
|
12
|
-
timeoutMs: number;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
16
|
-
|
|
17
|
-
let activeLock: TxLock | null = null;
|
|
18
|
-
|
|
19
|
-
function isExpired(lock: TxLock): boolean {
|
|
20
|
-
return Date.now() - lock.acquiredAt > lock.timeoutMs;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function acquireLock(
|
|
24
|
-
sessionId: string,
|
|
25
|
-
timeoutMs: number = DEFAULT_TIMEOUT_MS,
|
|
26
|
-
): { success: boolean; lockId?: string; error?: string } {
|
|
27
|
-
if (activeLock) {
|
|
28
|
-
if (isExpired(activeLock)) {
|
|
29
|
-
activeLock = null; // auto-release stale lock
|
|
30
|
-
} else {
|
|
31
|
-
return {
|
|
32
|
-
success: false,
|
|
33
|
-
error: `Lock held by session "${activeLock.sessionId}" since ${new Date(activeLock.acquiredAt).toISOString()}`,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
const lockId = crypto.randomUUID();
|
|
38
|
-
activeLock = { lockId, sessionId, acquiredAt: Date.now(), timeoutMs };
|
|
39
|
-
return { success: true, lockId };
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function releaseLock(lockId: string): boolean {
|
|
43
|
-
if (!activeLock || activeLock.lockId !== lockId) return false;
|
|
44
|
-
activeLock = null;
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function checkLock(): {
|
|
49
|
-
locked: boolean;
|
|
50
|
-
lockId?: string;
|
|
51
|
-
sessionId?: string;
|
|
52
|
-
acquiredAt?: number;
|
|
53
|
-
} {
|
|
54
|
-
if (activeLock && isExpired(activeLock)) {
|
|
55
|
-
activeLock = null;
|
|
56
|
-
}
|
|
57
|
-
if (!activeLock) return { locked: false };
|
|
58
|
-
return {
|
|
59
|
-
locked: true,
|
|
60
|
-
lockId: activeLock.lockId,
|
|
61
|
-
sessionId: activeLock.sessionId,
|
|
62
|
-
acquiredAt: activeLock.acquiredAt,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function requireLock(lockId?: string): { allowed: boolean; error?: string } {
|
|
67
|
-
if (!activeLock || isExpired(activeLock)) return { allowed: true };
|
|
68
|
-
if (lockId === activeLock.lockId) return { allowed: true };
|
|
69
|
-
return {
|
|
70
|
-
allowed: false,
|
|
71
|
-
error: `Project is locked by session "${activeLock.sessionId}". Provide a matching lockId or wait for expiry.`,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Transaction Lock — prevents concurrent project mutations from multiple AI agents.
|
|
3
|
+
*
|
|
4
|
+
* In-process singleton. If no lock exists, destructive tools work as before (backward compatible).
|
|
5
|
+
* When a lock is held, only the holder (matching lockId) may execute destructive operations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface TxLock {
|
|
9
|
+
lockId: string;
|
|
10
|
+
sessionId: string;
|
|
11
|
+
acquiredAt: number;
|
|
12
|
+
timeoutMs: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
16
|
+
|
|
17
|
+
let activeLock: TxLock | null = null;
|
|
18
|
+
|
|
19
|
+
function isExpired(lock: TxLock): boolean {
|
|
20
|
+
return Date.now() - lock.acquiredAt > lock.timeoutMs;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function acquireLock(
|
|
24
|
+
sessionId: string,
|
|
25
|
+
timeoutMs: number = DEFAULT_TIMEOUT_MS,
|
|
26
|
+
): { success: boolean; lockId?: string; error?: string } {
|
|
27
|
+
if (activeLock) {
|
|
28
|
+
if (isExpired(activeLock)) {
|
|
29
|
+
activeLock = null; // auto-release stale lock
|
|
30
|
+
} else {
|
|
31
|
+
return {
|
|
32
|
+
success: false,
|
|
33
|
+
error: `Lock held by session "${activeLock.sessionId}" since ${new Date(activeLock.acquiredAt).toISOString()}`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const lockId = crypto.randomUUID();
|
|
38
|
+
activeLock = { lockId, sessionId, acquiredAt: Date.now(), timeoutMs };
|
|
39
|
+
return { success: true, lockId };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function releaseLock(lockId: string): boolean {
|
|
43
|
+
if (!activeLock || activeLock.lockId !== lockId) return false;
|
|
44
|
+
activeLock = null;
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function checkLock(): {
|
|
49
|
+
locked: boolean;
|
|
50
|
+
lockId?: string;
|
|
51
|
+
sessionId?: string;
|
|
52
|
+
acquiredAt?: number;
|
|
53
|
+
} {
|
|
54
|
+
if (activeLock && isExpired(activeLock)) {
|
|
55
|
+
activeLock = null;
|
|
56
|
+
}
|
|
57
|
+
if (!activeLock) return { locked: false };
|
|
58
|
+
return {
|
|
59
|
+
locked: true,
|
|
60
|
+
lockId: activeLock.lockId,
|
|
61
|
+
sessionId: activeLock.sessionId,
|
|
62
|
+
acquiredAt: activeLock.acquiredAt,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function requireLock(lockId?: string): { allowed: boolean; error?: string } {
|
|
67
|
+
if (!activeLock || isExpired(activeLock)) return { allowed: true };
|
|
68
|
+
if (lockId === activeLock.lockId) return { allowed: true };
|
|
69
|
+
return {
|
|
70
|
+
allowed: false,
|
|
71
|
+
error: `Project is locked by session "${activeLock.sessionId}". Provide a matching lockId or wait for expiry.`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
|
|
3
|
-
export interface RuntimeControlRecord {
|
|
4
|
-
mode: "dev" | "start";
|
|
5
|
-
port: number;
|
|
6
|
-
token: string;
|
|
7
|
-
baseUrl: string;
|
|
8
|
-
startedAt: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const RUNTIME_CONTROL_RELATIVE_PATH = path.join(".mandu", "runtime-control.json");
|
|
12
|
-
|
|
13
|
-
export async function readRuntimeControl(rootDir: string): Promise<RuntimeControlRecord | null> {
|
|
14
|
-
try {
|
|
15
|
-
const file = Bun.file(path.join(rootDir, RUNTIME_CONTROL_RELATIVE_PATH));
|
|
16
|
-
if (!(await file.exists())) {
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
return await file.json() as RuntimeControlRecord;
|
|
20
|
-
} catch {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export async function requestRuntimeCache(
|
|
26
|
-
rootDir: string,
|
|
27
|
-
action: "stats" | "clear",
|
|
28
|
-
payload: Record<string, unknown> = {}
|
|
29
|
-
): Promise<{ control: RuntimeControlRecord; response: Response; body: unknown } | null> {
|
|
30
|
-
const control = await readRuntimeControl(rootDir);
|
|
31
|
-
if (!control) {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const response = await fetch(`${control.baseUrl}/_mandu/cache`, {
|
|
36
|
-
method: action === "stats" ? "GET" : "POST",
|
|
37
|
-
headers: {
|
|
38
|
-
"Content-Type": "application/json",
|
|
39
|
-
"x-mandu-control-token": control.token,
|
|
40
|
-
},
|
|
41
|
-
...(action === "clear" ? { body: JSON.stringify(payload) } : {}),
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
let body: unknown = null;
|
|
45
|
-
try {
|
|
46
|
-
body = await response.json();
|
|
47
|
-
} catch {
|
|
48
|
-
// ignore invalid JSON
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return { control, response, body };
|
|
52
|
-
}
|
|
1
|
+
import path from "path";
|
|
2
|
+
|
|
3
|
+
export interface RuntimeControlRecord {
|
|
4
|
+
mode: "dev" | "start";
|
|
5
|
+
port: number;
|
|
6
|
+
token: string;
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
startedAt: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const RUNTIME_CONTROL_RELATIVE_PATH = path.join(".mandu", "runtime-control.json");
|
|
12
|
+
|
|
13
|
+
export async function readRuntimeControl(rootDir: string): Promise<RuntimeControlRecord | null> {
|
|
14
|
+
try {
|
|
15
|
+
const file = Bun.file(path.join(rootDir, RUNTIME_CONTROL_RELATIVE_PATH));
|
|
16
|
+
if (!(await file.exists())) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
return await file.json() as RuntimeControlRecord;
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function requestRuntimeCache(
|
|
26
|
+
rootDir: string,
|
|
27
|
+
action: "stats" | "clear",
|
|
28
|
+
payload: Record<string, unknown> = {}
|
|
29
|
+
): Promise<{ control: RuntimeControlRecord; response: Response; body: unknown } | null> {
|
|
30
|
+
const control = await readRuntimeControl(rootDir);
|
|
31
|
+
if (!control) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const response = await fetch(`${control.baseUrl}/_mandu/cache`, {
|
|
36
|
+
method: action === "stats" ? "GET" : "POST",
|
|
37
|
+
headers: {
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
"x-mandu-control-token": control.token,
|
|
40
|
+
},
|
|
41
|
+
...(action === "clear" ? { body: JSON.stringify(payload) } : {}),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
let body: unknown = null;
|
|
45
|
+
try {
|
|
46
|
+
body = await response.json();
|
|
47
|
+
} catch {
|
|
48
|
+
// ignore invalid JSON
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { control, response, body };
|
|
52
|
+
}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: mandu-agent-workflow
|
|
3
|
-
description: |
|
|
4
|
-
Canonical Mandu agent workflow. Use first in Mandu projects before direct
|
|
5
|
-
source edits so Codex, Claude Code, Gemini CLI, and other agents follow the
|
|
6
|
-
same context -> plan -> apply -> verify -> repair loop.
|
|
7
|
-
license: MIT
|
|
8
|
-
metadata:
|
|
9
|
-
author: mandu
|
|
10
|
-
version: "1.0.0"
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# Mandu Agent Workflow
|
|
14
|
-
|
|
15
|
-
Mandu is an agent-native fullstack framework. Agents should not begin by
|
|
16
|
-
guessing file structure or calling low-level tools directly. Start with the
|
|
17
|
-
official agent surface, then use domain tools only when the plan identifies a
|
|
18
|
-
specific domain.
|
|
19
|
-
|
|
20
|
-
## When to Use
|
|
21
|
-
|
|
22
|
-
Use this skill for every Mandu project task that may inspect, create, modify, or
|
|
23
|
-
verify application code, framework configuration, contracts, slots, islands, or
|
|
24
|
-
deployment artifacts.
|
|
25
|
-
|
|
26
|
-
## Canonical Workflow
|
|
27
|
-
|
|
28
|
-
Always follow this loop:
|
|
29
|
-
|
|
30
|
-
```text
|
|
31
|
-
context -> plan -> apply -> verify -> repair
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
1. `context`: read the project map.
|
|
35
|
-
2. `plan`: convert the user request into domains, files, risks, and checks.
|
|
36
|
-
3. `apply`: prefer intent-level MCP/domain tools; direct edits must be grounded
|
|
37
|
-
in the plan.
|
|
38
|
-
4. `verify`: run the single agent-facing verification report.
|
|
39
|
-
5. `repair`: convert failures into next actions, then verify again.
|
|
40
|
-
|
|
41
|
-
## Preferred MCP Tools
|
|
42
|
-
|
|
43
|
-
Use these first when MCP is available:
|
|
44
|
-
|
|
45
|
-
| Step | Tool | Purpose |
|
|
46
|
-
|------|------|---------|
|
|
47
|
-
| context | `mandu.agent.context` | Project map, routes, APIs, slots, contracts, guard, diagnostics. |
|
|
48
|
-
| plan | `mandu.agent.plan` | Deterministic task plan with domains, files, tools, risks. |
|
|
49
|
-
| apply | `mandu.agent.apply` | Ordered action preview from `.mandu/agent-plan.json`. |
|
|
50
|
-
| verify | `mandu.agent.verify` | Unified post-change guard/diagnose/contract report. |
|
|
51
|
-
| repair | `mandu.agent.repair` | Structured next actions from `.mandu/agent-verify.json`. |
|
|
52
|
-
|
|
53
|
-
If MCP is unavailable, use the CLI equivalents:
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
mandu agent context --json
|
|
57
|
-
mandu agent plan "<task>" --json --write
|
|
58
|
-
mandu agent apply --from .mandu/agent-plan.json --json
|
|
59
|
-
mandu agent verify --changed --json --write
|
|
60
|
-
mandu agent repair --from .mandu/agent-verify.json --json
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Allowed File Edits
|
|
64
|
-
|
|
65
|
-
Direct file edits are allowed only after `plan` identifies the relevant domain
|
|
66
|
-
and the agent has inspected the local pattern. Prefer MCP/domain generation for:
|
|
67
|
-
|
|
68
|
-
- pages, layouts, and API routes
|
|
69
|
-
- contracts and OpenAPI-related files
|
|
70
|
-
- slots and fillings
|
|
71
|
-
- islands, partials, and hydration boundaries
|
|
72
|
-
- deploy intent and provider artifacts
|
|
73
|
-
|
|
74
|
-
Do not use destructive cleanup, cache removal, deploy execution, or broad
|
|
75
|
-
refactors without an explicit plan and verification path.
|
|
76
|
-
|
|
77
|
-
## Domain Skill Escalation
|
|
78
|
-
|
|
79
|
-
Read the matching domain skill when `mandu.agent.plan` includes that domain:
|
|
80
|
-
|
|
81
|
-
| Domain | Skill |
|
|
82
|
-
|--------|-------|
|
|
83
|
-
| route/api | `mandu-fs-routes` |
|
|
84
|
-
| hydration/island/partial | `mandu-hydration` |
|
|
85
|
-
| slot/filling | `mandu-slot` |
|
|
86
|
-
| guard/import boundary | `mandu-guard` |
|
|
87
|
-
| test/e2e/ATE | `mandu-testing` |
|
|
88
|
-
| deploy | `mandu-deployment` |
|
|
89
|
-
| security/auth/session | `mandu-security` |
|
|
90
|
-
| styling/ui/design | `mandu-styling`, `mandu-ui`, `mandu-composition` |
|
|
91
|
-
| performance | `mandu-performance` |
|
|
92
|
-
|
|
93
|
-
Domain skills are addenda. They must not replace the canonical workflow.
|
|
94
|
-
|
|
95
|
-
## Verification Command
|
|
96
|
-
|
|
97
|
-
Every code-changing task should end with:
|
|
98
|
-
|
|
99
|
-
```bash
|
|
100
|
-
mandu agent verify --changed --json --write
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Run additional commands listed in the plan or verify report, usually
|
|
104
|
-
`bun run typecheck` and targeted `bun test` commands.
|
|
105
|
-
|
|
106
|
-
## Repair Path
|
|
107
|
-
|
|
108
|
-
When verify fails:
|
|
109
|
-
|
|
110
|
-
```bash
|
|
111
|
-
mandu agent repair --from .mandu/agent-verify.json --json
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
Apply only actions that are explicitly safe and scoped. After any repair, run
|
|
115
|
-
`mandu agent verify --changed --json --write` again.
|
|
116
|
-
|
|
117
|
-
## Common Failures
|
|
118
|
-
|
|
119
|
-
- Skipping context and editing the wrong route or contract path.
|
|
120
|
-
- Calling low-level Guard, Doctor, Fix, ATE, or deploy tools before a plan.
|
|
121
|
-
- Treating a domain skill as the full workflow.
|
|
122
|
-
- Ending a task after tests without writing or reading the agent verify report.
|
|
123
|
-
- Applying broad file changes when `agent.apply` only produced a dry-run action
|
|
124
|
-
report.
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": "1.0.0",
|
|
3
|
-
"organization": "Mandu Framework",
|
|
4
|
-
"date": "May 2026",
|
|
5
|
-
"abstract": "Canonical Mandu agent workflow for Codex, Claude Code, Gemini CLI, and other coding agents. Establishes context -> plan -> apply -> verify -> repair as the default loop and routes domain work through focused Mandu skills and MCP tools.",
|
|
6
|
-
"tags": ["agent", "workflow", "mcp", "skills", "mandu"]
|
|
7
|
-
}
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: mandu-composition
|
|
3
|
-
description: |
|
|
4
|
-
React composition patterns for Mandu applications. Use when designing
|
|
5
|
-
Island components, managing shared state, or building reusable component
|
|
6
|
-
APIs. Triggers on compound components, context providers, boolean props,
|
|
7
|
-
or component architecture tasks.
|
|
8
|
-
license: MIT
|
|
9
|
-
metadata:
|
|
10
|
-
author: mandu
|
|
11
|
-
version: "1.0.0"
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
# Mandu Composition
|
|
15
|
-
|
|
16
|
-
Mandu 애플리케이션을 위한 React 컴포지션 패턴 가이드. Island 컴파운드 컴포넌트, 상태 관리 인터페이스, Provider 패턴, slot-client 분리를 다룹니다. Vercel의 Composition Patterns를 Mandu 컨텍스트로 변환하여 적용합니다.
|
|
17
|
-
|
|
18
|
-
## Agent Workflow Contract
|
|
19
|
-
|
|
20
|
-
This skill is a Domain addendum. It must not replace `mandu-agent-workflow`.
|
|
21
|
-
Use it only after `mandu.agent.plan` selects composition, UI, hydration, slot, or component domains.
|
|
22
|
-
|
|
23
|
-
Canonical workflow step: `plan -> apply -> verify`.
|
|
24
|
-
|
|
25
|
-
Preferred MCP tools:
|
|
26
|
-
|
|
27
|
-
| Step | Tools |
|
|
28
|
-
|------|-------|
|
|
29
|
-
| plan | `mandu.agent.plan`, `mandu.design.get`, `mandu.island.list` |
|
|
30
|
-
| apply | `mandu.agent.apply` |
|
|
31
|
-
| verify | `mandu.agent.verify`, `mandu.design.check`, `mandu.slot.validate` |
|
|
32
|
-
| repair | `mandu.agent.repair` |
|
|
33
|
-
|
|
34
|
-
Allowed file edits:
|
|
35
|
-
|
|
36
|
-
- Island/client component files named in the plan
|
|
37
|
-
- Provider/state modules scoped to the target feature
|
|
38
|
-
- Slot-client boundaries only when the plan includes slot or hydration domains
|
|
39
|
-
|
|
40
|
-
Verification command:
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
mandu agent verify --changed --json --write
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Common failures:
|
|
47
|
-
|
|
48
|
-
- Refactoring component APIs without checking island/client boundaries
|
|
49
|
-
- Adding shared state providers broader than the planned feature
|
|
50
|
-
- Mixing slot server logic into client composition files
|
|
51
|
-
|
|
52
|
-
Repair path:
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
mandu agent repair --from .mandu/agent-verify.json --json
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## When to Apply
|
|
59
|
-
|
|
60
|
-
Reference these guidelines when:
|
|
61
|
-
- Designing Island component architecture
|
|
62
|
-
- Managing shared state between Islands
|
|
63
|
-
- Building reusable component APIs
|
|
64
|
-
- Refactoring components with boolean prop proliferation
|
|
65
|
-
- Working with compound components or context providers
|
|
66
|
-
|
|
67
|
-
## Rule Categories by Priority
|
|
68
|
-
|
|
69
|
-
| Priority | Category | Impact | Prefix |
|
|
70
|
-
|----------|----------|--------|--------|
|
|
71
|
-
| 1 | Component Architecture | HIGH | `comp-arch-` |
|
|
72
|
-
| 2 | State Management | HIGH | `comp-state-` |
|
|
73
|
-
| 3 | Island Patterns | MEDIUM | `comp-island-` |
|
|
74
|
-
| 4 | Implementation Patterns | MEDIUM | `comp-pattern-` |
|
|
75
|
-
|
|
76
|
-
## Quick Reference
|
|
77
|
-
|
|
78
|
-
### 1. Component Architecture (HIGH)
|
|
79
|
-
|
|
80
|
-
- `comp-arch-avoid-boolean-props` - Use composition instead of boolean customization
|
|
81
|
-
- `comp-arch-compound-components` - Structure Islands as compound components
|
|
82
|
-
- `comp-arch-explicit-variants` - Create explicit variant components
|
|
83
|
-
|
|
84
|
-
### 2. State Management (HIGH)
|
|
85
|
-
|
|
86
|
-
- `comp-state-context-interface` - Define generic state/actions/meta interface
|
|
87
|
-
- `comp-state-lift-state` - Move state into provider for sibling access
|
|
88
|
-
- `comp-state-decouple-impl` - Provider is the only place knowing implementation
|
|
89
|
-
|
|
90
|
-
### 3. Island Patterns (MEDIUM)
|
|
91
|
-
|
|
92
|
-
- `comp-island-compound` - Compose Islands with shared context
|
|
93
|
-
- `comp-island-event` - Communicate between Islands with useIslandEvent
|
|
94
|
-
- `comp-island-slot-split` - Separate server logic (slot) from client (Island)
|
|
95
|
-
|
|
96
|
-
### 4. Implementation Patterns (MEDIUM)
|
|
97
|
-
|
|
98
|
-
- `comp-pattern-children` - Use children for composition over render props
|
|
99
|
-
- `comp-pattern-provider-boundary` - Understand provider boundary vs visual nesting
|
|
100
|
-
|
|
101
|
-
## Core Principle
|
|
102
|
-
|
|
103
|
-
**Lift state, compose internals, make state dependency-injectable.**
|
|
104
|
-
|
|
105
|
-
```
|
|
106
|
-
┌─────────────────────────────────────────┐
|
|
107
|
-
│ Provider (state + actions + meta) │
|
|
108
|
-
│ ┌───────────────────────────────────┐ │
|
|
109
|
-
│ │ Composer.Frame │ │
|
|
110
|
-
│ │ ┌─────────┐ ┌─────────────────┐ │ │
|
|
111
|
-
│ │ │ Input │ │ Footer │ │ │
|
|
112
|
-
│ │ └─────────┘ │ ┌─────┐ ┌─────┐ │ │ │
|
|
113
|
-
│ │ │ │Emoji│ │Send │ │ │ │
|
|
114
|
-
│ │ │ └─────┘ └─────┘ │ │ │
|
|
115
|
-
│ │ └─────────────────┘ │ │
|
|
116
|
-
│ └───────────────────────────────────┘ │
|
|
117
|
-
│ ┌───────────────┐ ← Outside Frame │
|
|
118
|
-
│ │ Preview │ but inside │
|
|
119
|
-
│ └───────────────┘ Provider! │
|
|
120
|
-
└─────────────────────────────────────────┘
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## How to Use
|
|
124
|
-
|
|
125
|
-
Read individual rule files for detailed explanations:
|
|
126
|
-
|
|
127
|
-
```
|
|
128
|
-
rules/comp-arch-compound-components.md
|
|
129
|
-
rules/comp-state-context-interface.md
|
|
130
|
-
rules/comp-island-event.md
|
|
131
|
-
```
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": "1.0.0",
|
|
3
|
-
"organization": "Mandu Framework",
|
|
4
|
-
"date": "February 2026",
|
|
5
|
-
"abstract": "Mandu 애플리케이션을 위한 React 컴포지션 패턴 가이드. Island 컴파운드 컴포넌트, state/actions/meta 인터페이스, Provider 패턴, useIslandEvent를 통한 Island 간 통신, slot-client 분리 패턴을 다룹니다. Vercel Composition Patterns 기반으로 Mandu 컨텍스트에 맞게 변환되었습니다.",
|
|
6
|
-
"references": [
|
|
7
|
-
"https://react.dev/learn/passing-data-deeply-with-context",
|
|
8
|
-
"https://react.dev/learn/scaling-up-with-reducer-and-context",
|
|
9
|
-
"https://www.patterns.dev/react/compound-pattern",
|
|
10
|
-
"https://kentcdodds.com/blog/compound-components-with-react-hooks"
|
|
11
|
-
],
|
|
12
|
-
"tags": ["composition", "compound", "context", "state", "island", "mandu"]
|
|
13
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# Sections
|
|
2
|
-
|
|
3
|
-
This file defines all sections, their ordering, impact levels, and descriptions.
|
|
4
|
-
The section ID (in parentheses) is the filename prefix used to group rules.
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## 1. Component Architecture (comp-arch)
|
|
9
|
-
|
|
10
|
-
**Impact:** HIGH
|
|
11
|
-
**Description:** Boolean props 대신 컴포지션 사용, 컴파운드 컴포넌트 구조화. 코드베이스가 확장됨에 따라 유지보수성에 큰 영향을 미칩니다.
|
|
12
|
-
|
|
13
|
-
## 2. State Management (comp-state)
|
|
14
|
-
|
|
15
|
-
**Impact:** HIGH
|
|
16
|
-
**Description:** state/actions/meta 인터페이스 정의, Provider를 통한 의존성 주입. 같은 UI를 다양한 상태 구현과 함께 재사용할 수 있게 합니다.
|
|
17
|
-
|
|
18
|
-
## 3. Island Patterns (comp-island)
|
|
19
|
-
|
|
20
|
-
**Impact:** MEDIUM
|
|
21
|
-
**Description:** Mandu Island 특화 패턴. 컴파운드 Island, Island 간 이벤트 통신, slot-client 분리를 다룹니다.
|
|
22
|
-
|
|
23
|
-
## 4. Implementation Patterns (comp-pattern)
|
|
24
|
-
|
|
25
|
-
**Impact:** MEDIUM
|
|
26
|
-
**Description:** children 활용, Provider 경계 이해 등 구현 세부 사항. 올바른 패턴 적용으로 유연성을 확보합니다.
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# Rule Template
|
|
2
|
-
|
|
3
|
-
Use this template when creating new rules for mandu-composition.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
```markdown
|
|
8
|
-
---
|
|
9
|
-
title: Rule Title Here
|
|
10
|
-
impact: HIGH | MEDIUM | LOW
|
|
11
|
-
impactDescription: 영향 설명 (예: "enables flexible composition")
|
|
12
|
-
tags: composition, tag1, tag2
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## Rule Title Here
|
|
16
|
-
|
|
17
|
-
**Impact: {LEVEL} ({impactDescription})**
|
|
18
|
-
|
|
19
|
-
규칙의 목적과 아키텍처적 영향을 설명합니다.
|
|
20
|
-
|
|
21
|
-
**Incorrect (문제가 되는 패턴):**
|
|
22
|
-
|
|
23
|
-
\`\`\`tsx
|
|
24
|
-
// ❌ Boolean props로 기능 추가
|
|
25
|
-
function Composer({
|
|
26
|
-
showAttachments,
|
|
27
|
-
showFormatting,
|
|
28
|
-
showEmojis,
|
|
29
|
-
isCompact,
|
|
30
|
-
isReadOnly,
|
|
31
|
-
}: Props) {
|
|
32
|
-
return (
|
|
33
|
-
<form>
|
|
34
|
-
{!isReadOnly && <Input />}
|
|
35
|
-
{showAttachments && <Attachments />}
|
|
36
|
-
{showFormatting && <Formatting />}
|
|
37
|
-
{showEmojis && <Emojis />}
|
|
38
|
-
</form>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
**Correct (컴포지션 패턴):**
|
|
44
|
-
|
|
45
|
-
\`\`\`tsx
|
|
46
|
-
// ✅ 컴포지션으로 유연하게 구성
|
|
47
|
-
<Composer.Provider state={state} actions={actions}>
|
|
48
|
-
<Composer.Frame>
|
|
49
|
-
<Composer.Input />
|
|
50
|
-
<Composer.Footer>
|
|
51
|
-
<Composer.Emojis />
|
|
52
|
-
<Composer.Submit />
|
|
53
|
-
</Composer.Footer>
|
|
54
|
-
</Composer.Frame>
|
|
55
|
-
</Composer.Provider>
|
|
56
|
-
\`\`\`
|
|
57
|
-
|
|
58
|
-
## Mandu Context
|
|
59
|
-
|
|
60
|
-
Mandu Island에서 이 패턴을 적용하는 방법을 설명합니다.
|
|
61
|
-
|
|
62
|
-
Reference: [관련 문서 링크](https://example.com)
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
## Naming Convention
|
|
68
|
-
|
|
69
|
-
- 파일명: `comp-{category}-{rule-name}.md`
|
|
70
|
-
- 예시: `comp-arch-compound-components.md`, `comp-state-context-interface.md`
|
|
71
|
-
|
|
72
|
-
## Core Principle
|
|
73
|
-
|
|
74
|
-
**Lift state, compose internals, make state dependency-injectable.**
|
|
75
|
-
|
|
76
|
-
UI는 조합 가능한 조각들이고, 상태는 Provider가 주입합니다.
|
|
77
|
-
Provider를 바꾸면 UI는 그대로 유지됩니다.
|