@mandujs/core 0.9.15 → 0.9.16
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/package.json +1 -1
- package/src/brain/types.ts +10 -0
- package/src/watcher/rules.ts +34 -27
package/package.json
CHANGED
package/src/brain/types.ts
CHANGED
|
@@ -146,6 +146,12 @@ export interface ArchRule {
|
|
|
146
146
|
forbiddenImports?: string[];
|
|
147
147
|
/** Optional: required patterns in content */
|
|
148
148
|
requiredPatterns?: RegExp[];
|
|
149
|
+
/** Optional: exclude paths matching this pattern */
|
|
150
|
+
excludePattern?: string;
|
|
151
|
+
/** Recommended action for the agent */
|
|
152
|
+
agentAction?: "regenerate" | "move" | "rename" | "remove_import" | "validate" | "none";
|
|
153
|
+
/** MCP tool to execute */
|
|
154
|
+
agentCommand?: string;
|
|
149
155
|
}
|
|
150
156
|
|
|
151
157
|
/**
|
|
@@ -164,6 +170,10 @@ export interface WatchWarning {
|
|
|
164
170
|
event: "create" | "modify" | "delete";
|
|
165
171
|
/** Warning level */
|
|
166
172
|
level?: "info" | "warn";
|
|
173
|
+
/** Recommended action for the agent */
|
|
174
|
+
agentAction?: string;
|
|
175
|
+
/** MCP tool to execute */
|
|
176
|
+
agentCommand?: string;
|
|
167
177
|
}
|
|
168
178
|
|
|
169
179
|
/**
|
package/src/watcher/rules.ts
CHANGED
|
@@ -27,14 +27,19 @@ export const MVP_RULES: ArchRule[] = [
|
|
|
27
27
|
pattern: "generated/**",
|
|
28
28
|
action: "warn",
|
|
29
29
|
message: "Generated 파일이 직접 수정되었습니다. 이 파일은 `mandu generate`로 재생성됩니다.",
|
|
30
|
+
agentAction: "regenerate",
|
|
31
|
+
agentCommand: "mandu_generate",
|
|
30
32
|
},
|
|
31
33
|
{
|
|
32
34
|
id: "WRONG_SLOT_LOCATION",
|
|
33
35
|
name: "Wrong Slot Location",
|
|
34
36
|
description: "Slot 파일은 spec/slots/ 디렉토리에 있어야 합니다",
|
|
35
|
-
pattern: "
|
|
37
|
+
pattern: "**/*.slot.ts",
|
|
36
38
|
action: "warn",
|
|
37
39
|
message: "Slot 파일이 잘못된 위치에 있습니다. spec/slots/ 디렉토리로 이동하세요.",
|
|
40
|
+
excludePattern: "spec/slots/**",
|
|
41
|
+
agentAction: "move",
|
|
42
|
+
agentCommand: "mandu_check_location",
|
|
38
43
|
},
|
|
39
44
|
{
|
|
40
45
|
id: "SLOT_NAMING",
|
|
@@ -44,6 +49,8 @@ export const MVP_RULES: ArchRule[] = [
|
|
|
44
49
|
action: "warn",
|
|
45
50
|
message: "Slot 파일명이 .slot.ts로 끝나야 합니다.",
|
|
46
51
|
mustEndWith: ".slot.ts",
|
|
52
|
+
agentAction: "rename",
|
|
53
|
+
agentCommand: "mandu_check_location",
|
|
47
54
|
},
|
|
48
55
|
{
|
|
49
56
|
id: "CONTRACT_NAMING",
|
|
@@ -53,6 +60,8 @@ export const MVP_RULES: ArchRule[] = [
|
|
|
53
60
|
action: "warn",
|
|
54
61
|
message: "Contract 파일명이 .contract.ts로 끝나야 합니다.",
|
|
55
62
|
mustEndWith: ".contract.ts",
|
|
63
|
+
agentAction: "rename",
|
|
64
|
+
agentCommand: "mandu_check_location",
|
|
56
65
|
},
|
|
57
66
|
{
|
|
58
67
|
id: "FORBIDDEN_IMPORT",
|
|
@@ -62,6 +71,8 @@ export const MVP_RULES: ArchRule[] = [
|
|
|
62
71
|
action: "warn",
|
|
63
72
|
message: "Generated 파일에서 금지된 모듈이 import되었습니다.",
|
|
64
73
|
forbiddenImports: ["fs", "child_process", "cluster", "worker_threads"],
|
|
74
|
+
agentAction: "remove_import",
|
|
75
|
+
agentCommand: "mandu_guard_check",
|
|
65
76
|
},
|
|
66
77
|
{
|
|
67
78
|
id: "SLOT_MODIFIED",
|
|
@@ -70,6 +81,8 @@ export const MVP_RULES: ArchRule[] = [
|
|
|
70
81
|
pattern: "spec/slots/*.slot.ts",
|
|
71
82
|
action: "warn",
|
|
72
83
|
message: "Slot 수정 감지. mandu_validate_slot 또는 mandu_guard_check로 검증하세요.",
|
|
84
|
+
agentAction: "validate",
|
|
85
|
+
agentCommand: "mandu_validate_slot",
|
|
73
86
|
},
|
|
74
87
|
{
|
|
75
88
|
id: "ISLAND_FIRST_MODIFIED",
|
|
@@ -78,6 +91,8 @@ export const MVP_RULES: ArchRule[] = [
|
|
|
78
91
|
pattern: "apps/web/generated/routes/**",
|
|
79
92
|
action: "warn",
|
|
80
93
|
message: "Island-First componentModule이 수동 수정되었습니다. mandu generate를 실행하세요.",
|
|
94
|
+
agentAction: "regenerate",
|
|
95
|
+
agentCommand: "mandu_generate",
|
|
81
96
|
},
|
|
82
97
|
];
|
|
83
98
|
|
|
@@ -123,6 +138,10 @@ export function matchRules(filePath: string): ArchRule[] {
|
|
|
123
138
|
|
|
124
139
|
for (const rule of MVP_RULES) {
|
|
125
140
|
if (matchGlob(rule.pattern, filePath)) {
|
|
141
|
+
// Skip if excluded
|
|
142
|
+
if (rule.excludePattern && matchGlob(rule.excludePattern, filePath)) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
126
145
|
matched.push(rule);
|
|
127
146
|
}
|
|
128
147
|
}
|
|
@@ -193,15 +212,19 @@ export async function validateFile(
|
|
|
193
212
|
continue;
|
|
194
213
|
}
|
|
195
214
|
|
|
215
|
+
// Base warning fields reused across all branches
|
|
216
|
+
const base = {
|
|
217
|
+
ruleId: rule.id,
|
|
218
|
+
file: relativePath,
|
|
219
|
+
timestamp: new Date(),
|
|
220
|
+
event,
|
|
221
|
+
agentAction: rule.agentAction,
|
|
222
|
+
agentCommand: rule.agentCommand,
|
|
223
|
+
} as const;
|
|
224
|
+
|
|
196
225
|
// Check naming convention
|
|
197
226
|
if (rule.mustEndWith && !checkNamingConvention(relativePath, rule)) {
|
|
198
|
-
warnings.push({
|
|
199
|
-
ruleId: rule.id,
|
|
200
|
-
file: relativePath,
|
|
201
|
-
message: rule.message,
|
|
202
|
-
timestamp: new Date(),
|
|
203
|
-
event,
|
|
204
|
-
});
|
|
227
|
+
warnings.push({ ...base, message: rule.message });
|
|
205
228
|
continue;
|
|
206
229
|
}
|
|
207
230
|
|
|
@@ -221,11 +244,8 @@ export async function validateFile(
|
|
|
221
244
|
|
|
222
245
|
if (forbidden.length > 0) {
|
|
223
246
|
warnings.push({
|
|
224
|
-
|
|
225
|
-
file: relativePath,
|
|
247
|
+
...base,
|
|
226
248
|
message: `${rule.message} (${forbidden.join(", ")})`,
|
|
227
|
-
timestamp: new Date(),
|
|
228
|
-
event,
|
|
229
249
|
});
|
|
230
250
|
}
|
|
231
251
|
} catch {
|
|
@@ -236,25 +256,12 @@ export async function validateFile(
|
|
|
236
256
|
|
|
237
257
|
// Default: generate warning for pattern match
|
|
238
258
|
if (rule.id === "GENERATED_DIRECT_EDIT" || rule.id === "WRONG_SLOT_LOCATION" || rule.id === "ISLAND_FIRST_MODIFIED") {
|
|
239
|
-
warnings.push({
|
|
240
|
-
ruleId: rule.id,
|
|
241
|
-
file: relativePath,
|
|
242
|
-
message: rule.message,
|
|
243
|
-
timestamp: new Date(),
|
|
244
|
-
event,
|
|
245
|
-
});
|
|
259
|
+
warnings.push({ ...base, message: rule.message });
|
|
246
260
|
}
|
|
247
261
|
|
|
248
262
|
// Slot modified: info level notification
|
|
249
263
|
if (rule.id === "SLOT_MODIFIED" && event !== "delete") {
|
|
250
|
-
warnings.push({
|
|
251
|
-
ruleId: rule.id,
|
|
252
|
-
file: relativePath,
|
|
253
|
-
message: rule.message,
|
|
254
|
-
timestamp: new Date(),
|
|
255
|
-
event,
|
|
256
|
-
level: "info",
|
|
257
|
-
});
|
|
264
|
+
warnings.push({ ...base, message: rule.message, level: "info" as const });
|
|
258
265
|
}
|
|
259
266
|
}
|
|
260
267
|
|