@massu/core 0.6.3 → 0.7.0
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 +29 -2
- package/dist/hooks/auto-learning-pipeline.js +469 -0
- package/dist/hooks/cost-tracker.js +28 -1
- package/dist/hooks/fix-detector.js +462 -0
- package/dist/hooks/incident-pipeline.js +426 -0
- package/dist/hooks/post-edit-context.js +28 -1
- package/dist/hooks/post-tool-use.js +28 -1
- package/dist/hooks/pre-compact.js +28 -1
- package/dist/hooks/pre-delete-check.js +28 -1
- package/dist/hooks/quality-event.js +28 -1
- package/dist/hooks/rule-enforcement-pipeline.js +440 -0
- package/dist/hooks/session-end.js +28 -1
- package/dist/hooks/session-start.js +28 -1
- package/dist/hooks/user-prompt.js +28 -1
- package/package.json +2 -2
- package/src/config.ts +31 -0
- package/src/hooks/auto-learning-pipeline.ts +195 -0
- package/src/hooks/fix-detector.ts +186 -0
- package/src/hooks/incident-pipeline.ts +148 -0
- package/src/hooks/rule-enforcement-pipeline.ts +158 -0
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{createRequire as __cr}from"module";const require=__cr(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// src/hooks/incident-pipeline.ts
|
|
5
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync } from "fs";
|
|
6
|
+
import { basename, resolve as resolve2 } from "path";
|
|
7
|
+
|
|
8
|
+
// src/config.ts
|
|
9
|
+
import { resolve, dirname } from "path";
|
|
10
|
+
import { existsSync, readFileSync } from "fs";
|
|
11
|
+
import { parse as parseYaml } from "yaml";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
var DomainConfigSchema = z.object({
|
|
14
|
+
name: z.string().default("Unknown"),
|
|
15
|
+
routers: z.array(z.string()).default([]),
|
|
16
|
+
pages: z.array(z.string()).default([]),
|
|
17
|
+
tables: z.array(z.string()).default([]),
|
|
18
|
+
allowedImportsFrom: z.array(z.string()).default([])
|
|
19
|
+
});
|
|
20
|
+
var PatternRuleConfigSchema = z.object({
|
|
21
|
+
pattern: z.string().default("**"),
|
|
22
|
+
rules: z.array(z.string()).default([])
|
|
23
|
+
});
|
|
24
|
+
var CostModelSchema = z.object({
|
|
25
|
+
input_per_million: z.number(),
|
|
26
|
+
output_per_million: z.number(),
|
|
27
|
+
cache_read_per_million: z.number().optional(),
|
|
28
|
+
cache_write_per_million: z.number().optional()
|
|
29
|
+
});
|
|
30
|
+
var AnalyticsConfigSchema = z.object({
|
|
31
|
+
quality: z.object({
|
|
32
|
+
weights: z.record(z.string(), z.number()).default({
|
|
33
|
+
bug_found: -5,
|
|
34
|
+
vr_failure: -10,
|
|
35
|
+
incident: -20,
|
|
36
|
+
cr_violation: -3,
|
|
37
|
+
vr_pass: 2,
|
|
38
|
+
clean_commit: 5,
|
|
39
|
+
successful_verification: 3
|
|
40
|
+
}),
|
|
41
|
+
categories: z.array(z.string()).default(["security", "architecture", "coupling", "tests", "rule_compliance"])
|
|
42
|
+
}).optional(),
|
|
43
|
+
cost: z.object({
|
|
44
|
+
models: z.record(z.string(), CostModelSchema).default({}),
|
|
45
|
+
currency: z.string().default("USD")
|
|
46
|
+
}).optional(),
|
|
47
|
+
prompts: z.object({
|
|
48
|
+
success_indicators: z.array(z.string()).default(["committed", "approved", "looks good", "perfect", "great", "thanks"]),
|
|
49
|
+
failure_indicators: z.array(z.string()).default(["revert", "wrong", "that's not", "undo", "incorrect"]),
|
|
50
|
+
max_turns_for_success: z.number().default(2)
|
|
51
|
+
}).optional()
|
|
52
|
+
}).optional();
|
|
53
|
+
var CustomPatternSchema = z.object({
|
|
54
|
+
pattern: z.string(),
|
|
55
|
+
severity: z.string(),
|
|
56
|
+
message: z.string()
|
|
57
|
+
});
|
|
58
|
+
var GovernanceConfigSchema = z.object({
|
|
59
|
+
audit: z.object({
|
|
60
|
+
formats: z.array(z.string()).default(["summary", "detailed", "soc2"]),
|
|
61
|
+
retention_days: z.number().default(365),
|
|
62
|
+
auto_log: z.record(z.string(), z.boolean()).default({
|
|
63
|
+
code_changes: true,
|
|
64
|
+
rule_enforcement: true,
|
|
65
|
+
approvals: true,
|
|
66
|
+
commits: true
|
|
67
|
+
})
|
|
68
|
+
}).optional(),
|
|
69
|
+
validation: z.object({
|
|
70
|
+
realtime: z.boolean().default(true),
|
|
71
|
+
checks: z.record(z.string(), z.boolean()).default({
|
|
72
|
+
rule_compliance: true,
|
|
73
|
+
import_existence: true,
|
|
74
|
+
naming_conventions: true
|
|
75
|
+
}),
|
|
76
|
+
custom_patterns: z.array(CustomPatternSchema).default([])
|
|
77
|
+
}).optional(),
|
|
78
|
+
adr: z.object({
|
|
79
|
+
detection_phrases: z.array(z.string()).default(["chose", "decided", "switching to", "moving from", "going with"]),
|
|
80
|
+
template: z.string().default("default"),
|
|
81
|
+
storage: z.string().default("database"),
|
|
82
|
+
output_dir: z.string().default("docs/adr")
|
|
83
|
+
}).optional()
|
|
84
|
+
}).optional();
|
|
85
|
+
var SecurityPatternSchema = z.object({
|
|
86
|
+
pattern: z.string(),
|
|
87
|
+
severity: z.string(),
|
|
88
|
+
category: z.string(),
|
|
89
|
+
description: z.string()
|
|
90
|
+
});
|
|
91
|
+
var SecurityConfigSchema = z.object({
|
|
92
|
+
patterns: z.array(SecurityPatternSchema).default([]),
|
|
93
|
+
auto_score_on_edit: z.boolean().default(true),
|
|
94
|
+
score_threshold_alert: z.number().default(50),
|
|
95
|
+
severity_weights: z.record(z.string(), z.number()).optional(),
|
|
96
|
+
restrictive_licenses: z.array(z.string()).optional(),
|
|
97
|
+
dep_alternatives: z.record(z.string(), z.array(z.string())).optional(),
|
|
98
|
+
dependencies: z.object({
|
|
99
|
+
package_manager: z.string().default("npm"),
|
|
100
|
+
blocked_packages: z.array(z.string()).default([]),
|
|
101
|
+
preferred_packages: z.record(z.string(), z.string()).default({}),
|
|
102
|
+
max_bundle_size_kb: z.number().default(500)
|
|
103
|
+
}).optional()
|
|
104
|
+
}).optional();
|
|
105
|
+
var TeamConfigSchema = z.object({
|
|
106
|
+
enabled: z.boolean().default(false),
|
|
107
|
+
sync_backend: z.string().default("local"),
|
|
108
|
+
developer_id: z.string().default("auto"),
|
|
109
|
+
share_by_default: z.boolean().default(false),
|
|
110
|
+
expertise_weights: z.object({
|
|
111
|
+
session: z.number().default(20),
|
|
112
|
+
observation: z.number().default(10)
|
|
113
|
+
}).optional(),
|
|
114
|
+
privacy: z.object({
|
|
115
|
+
share_file_paths: z.boolean().default(true),
|
|
116
|
+
share_code_snippets: z.boolean().default(false),
|
|
117
|
+
share_observations: z.boolean().default(true)
|
|
118
|
+
}).optional()
|
|
119
|
+
}).optional();
|
|
120
|
+
var RegressionConfigSchema = z.object({
|
|
121
|
+
test_patterns: z.array(z.string()).default([
|
|
122
|
+
"{dir}/__tests__/{name}.test.{ext}",
|
|
123
|
+
"{dir}/{name}.spec.{ext}",
|
|
124
|
+
"tests/{path}.test.{ext}"
|
|
125
|
+
]),
|
|
126
|
+
test_runner: z.string().default("npm test"),
|
|
127
|
+
health_thresholds: z.object({
|
|
128
|
+
healthy: z.number().default(80),
|
|
129
|
+
warning: z.number().default(50)
|
|
130
|
+
}).optional()
|
|
131
|
+
}).optional();
|
|
132
|
+
var AutoLearningConfigSchema = z.object({
|
|
133
|
+
enabled: z.boolean().default(true),
|
|
134
|
+
incidentDir: z.string().default("docs/incidents"),
|
|
135
|
+
memoryDir: z.string().default("memory"),
|
|
136
|
+
memoryIndexFile: z.string().default("MEMORY.md"),
|
|
137
|
+
enforcementHooksDir: z.string().default("scripts/hooks"),
|
|
138
|
+
fixDetection: z.object({
|
|
139
|
+
enabled: z.boolean().default(true),
|
|
140
|
+
lookbackDays: z.number().default(7),
|
|
141
|
+
signals: z.array(z.string()).default([
|
|
142
|
+
"removed_broken_code",
|
|
143
|
+
"added_error_handling",
|
|
144
|
+
"method_name_correction",
|
|
145
|
+
"auth_fix",
|
|
146
|
+
"nil_handling_fix",
|
|
147
|
+
"concurrency_fix",
|
|
148
|
+
"async_pattern_fix",
|
|
149
|
+
"added_missing_import"
|
|
150
|
+
])
|
|
151
|
+
}).default({}),
|
|
152
|
+
pipeline: z.object({
|
|
153
|
+
requireIncidentReport: z.boolean().default(true),
|
|
154
|
+
requirePreventionRule: z.boolean().default(true),
|
|
155
|
+
requireEnforcement: z.boolean().default(true)
|
|
156
|
+
}).default({})
|
|
157
|
+
}).optional();
|
|
158
|
+
var CloudConfigSchema = z.object({
|
|
159
|
+
enabled: z.boolean().default(false),
|
|
160
|
+
apiKey: z.string().optional(),
|
|
161
|
+
endpoint: z.string().optional(),
|
|
162
|
+
sync: z.object({
|
|
163
|
+
memory: z.boolean().default(true),
|
|
164
|
+
analytics: z.boolean().default(true),
|
|
165
|
+
audit: z.boolean().default(true)
|
|
166
|
+
}).default({ memory: true, analytics: true, audit: true })
|
|
167
|
+
}).optional();
|
|
168
|
+
var ConventionsConfigSchema = z.object({
|
|
169
|
+
claudeDirName: z.string().default(".claude").refine(
|
|
170
|
+
(s) => !s.includes("..") && !s.startsWith("/"),
|
|
171
|
+
{ message: 'claudeDirName must not contain ".." or start with "/"' }
|
|
172
|
+
),
|
|
173
|
+
sessionStatePath: z.string().default(".claude/session-state/CURRENT.md").refine(
|
|
174
|
+
(s) => !s.includes("..") && !s.startsWith("/"),
|
|
175
|
+
{ message: 'sessionStatePath must not contain ".." or start with "/"' }
|
|
176
|
+
),
|
|
177
|
+
sessionArchivePath: z.string().default(".claude/session-state/archive").refine(
|
|
178
|
+
(s) => !s.includes("..") && !s.startsWith("/"),
|
|
179
|
+
{ message: 'sessionArchivePath must not contain ".." or start with "/"' }
|
|
180
|
+
),
|
|
181
|
+
knowledgeCategories: z.array(z.string()).default([
|
|
182
|
+
"patterns",
|
|
183
|
+
"commands",
|
|
184
|
+
"incidents",
|
|
185
|
+
"reference",
|
|
186
|
+
"protocols",
|
|
187
|
+
"checklists",
|
|
188
|
+
"playbooks",
|
|
189
|
+
"critical",
|
|
190
|
+
"scripts",
|
|
191
|
+
"status",
|
|
192
|
+
"templates",
|
|
193
|
+
"loop-state",
|
|
194
|
+
"session-state",
|
|
195
|
+
"agents"
|
|
196
|
+
]),
|
|
197
|
+
knowledgeSourceFiles: z.array(z.string()).default(["CLAUDE.md", "MEMORY.md", "corrections.md"]),
|
|
198
|
+
excludePatterns: z.array(z.string()).default(["/ARCHIVE/", "/SESSION-HISTORY/"])
|
|
199
|
+
}).optional();
|
|
200
|
+
var PythonDomainConfigSchema = z.object({
|
|
201
|
+
name: z.string(),
|
|
202
|
+
packages: z.array(z.string()),
|
|
203
|
+
allowed_imports_from: z.array(z.string()).default([])
|
|
204
|
+
});
|
|
205
|
+
var PythonConfigSchema = z.object({
|
|
206
|
+
root: z.string(),
|
|
207
|
+
alembic_dir: z.string().optional(),
|
|
208
|
+
domains: z.array(PythonDomainConfigSchema).default([]),
|
|
209
|
+
exclude_dirs: z.array(z.string()).default(["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"])
|
|
210
|
+
}).optional();
|
|
211
|
+
var PathsConfigSchema = z.object({
|
|
212
|
+
source: z.string().default("src"),
|
|
213
|
+
aliases: z.record(z.string(), z.string()).default({ "@": "src" }),
|
|
214
|
+
routers: z.string().optional(),
|
|
215
|
+
routerRoot: z.string().optional(),
|
|
216
|
+
pages: z.string().optional(),
|
|
217
|
+
middleware: z.string().optional(),
|
|
218
|
+
schema: z.string().optional(),
|
|
219
|
+
components: z.string().optional(),
|
|
220
|
+
hooks: z.string().optional()
|
|
221
|
+
});
|
|
222
|
+
var RawConfigSchema = z.object({
|
|
223
|
+
project: z.object({
|
|
224
|
+
name: z.string().default("my-project"),
|
|
225
|
+
root: z.string().default("auto")
|
|
226
|
+
}).default({ name: "my-project", root: "auto" }),
|
|
227
|
+
framework: z.object({
|
|
228
|
+
type: z.string().default("typescript"),
|
|
229
|
+
router: z.string().default("none"),
|
|
230
|
+
orm: z.string().default("none"),
|
|
231
|
+
ui: z.string().default("none")
|
|
232
|
+
}).default({ type: "typescript", router: "none", orm: "none", ui: "none" }),
|
|
233
|
+
paths: PathsConfigSchema.default({ source: "src", aliases: { "@": "src" } }),
|
|
234
|
+
toolPrefix: z.string().default("massu"),
|
|
235
|
+
dbAccessPattern: z.string().optional(),
|
|
236
|
+
knownMismatches: z.record(z.string(), z.record(z.string(), z.string())).optional(),
|
|
237
|
+
accessScopes: z.array(z.string()).optional(),
|
|
238
|
+
domains: z.array(DomainConfigSchema).default([]),
|
|
239
|
+
rules: z.array(PatternRuleConfigSchema).default([]),
|
|
240
|
+
analytics: AnalyticsConfigSchema,
|
|
241
|
+
governance: GovernanceConfigSchema,
|
|
242
|
+
security: SecurityConfigSchema,
|
|
243
|
+
team: TeamConfigSchema,
|
|
244
|
+
regression: RegressionConfigSchema,
|
|
245
|
+
cloud: CloudConfigSchema,
|
|
246
|
+
conventions: ConventionsConfigSchema,
|
|
247
|
+
python: PythonConfigSchema,
|
|
248
|
+
autoLearning: AutoLearningConfigSchema
|
|
249
|
+
}).passthrough();
|
|
250
|
+
var _config = null;
|
|
251
|
+
var _projectRoot = null;
|
|
252
|
+
function findProjectRoot() {
|
|
253
|
+
const cwd = process.cwd();
|
|
254
|
+
let dir = cwd;
|
|
255
|
+
while (true) {
|
|
256
|
+
if (existsSync(resolve(dir, "massu.config.yaml"))) {
|
|
257
|
+
return dir;
|
|
258
|
+
}
|
|
259
|
+
const parent = dirname(dir);
|
|
260
|
+
if (parent === dir) break;
|
|
261
|
+
dir = parent;
|
|
262
|
+
}
|
|
263
|
+
dir = cwd;
|
|
264
|
+
while (true) {
|
|
265
|
+
if (existsSync(resolve(dir, "package.json"))) {
|
|
266
|
+
return dir;
|
|
267
|
+
}
|
|
268
|
+
if (existsSync(resolve(dir, ".git"))) {
|
|
269
|
+
return dir;
|
|
270
|
+
}
|
|
271
|
+
const parent = dirname(dir);
|
|
272
|
+
if (parent === dir) break;
|
|
273
|
+
dir = parent;
|
|
274
|
+
}
|
|
275
|
+
return cwd;
|
|
276
|
+
}
|
|
277
|
+
function getProjectRoot() {
|
|
278
|
+
if (!_projectRoot) {
|
|
279
|
+
_projectRoot = findProjectRoot();
|
|
280
|
+
}
|
|
281
|
+
return _projectRoot;
|
|
282
|
+
}
|
|
283
|
+
function getConfig() {
|
|
284
|
+
if (_config) return _config;
|
|
285
|
+
const root = getProjectRoot();
|
|
286
|
+
const configPath = resolve(root, "massu.config.yaml");
|
|
287
|
+
let rawYaml = {};
|
|
288
|
+
if (existsSync(configPath)) {
|
|
289
|
+
const content = readFileSync(configPath, "utf-8");
|
|
290
|
+
rawYaml = parseYaml(content) ?? {};
|
|
291
|
+
}
|
|
292
|
+
const parsed = RawConfigSchema.parse(rawYaml);
|
|
293
|
+
const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root : resolve(root, parsed.project.root);
|
|
294
|
+
_config = {
|
|
295
|
+
project: {
|
|
296
|
+
name: parsed.project.name,
|
|
297
|
+
root: projectRoot
|
|
298
|
+
},
|
|
299
|
+
framework: parsed.framework,
|
|
300
|
+
paths: parsed.paths,
|
|
301
|
+
toolPrefix: parsed.toolPrefix,
|
|
302
|
+
dbAccessPattern: parsed.dbAccessPattern,
|
|
303
|
+
knownMismatches: parsed.knownMismatches,
|
|
304
|
+
accessScopes: parsed.accessScopes,
|
|
305
|
+
domains: parsed.domains,
|
|
306
|
+
rules: parsed.rules,
|
|
307
|
+
analytics: parsed.analytics,
|
|
308
|
+
governance: parsed.governance,
|
|
309
|
+
security: parsed.security,
|
|
310
|
+
team: parsed.team,
|
|
311
|
+
regression: parsed.regression,
|
|
312
|
+
cloud: parsed.cloud,
|
|
313
|
+
conventions: parsed.conventions,
|
|
314
|
+
python: parsed.python
|
|
315
|
+
};
|
|
316
|
+
if (!_config.cloud?.apiKey && process.env.MASSU_API_KEY) {
|
|
317
|
+
_config.cloud = {
|
|
318
|
+
enabled: true,
|
|
319
|
+
sync: { memory: true, analytics: true, audit: true },
|
|
320
|
+
..._config.cloud,
|
|
321
|
+
apiKey: process.env.MASSU_API_KEY
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
return _config;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/hooks/incident-pipeline.ts
|
|
328
|
+
async function main() {
|
|
329
|
+
try {
|
|
330
|
+
const input = await readStdin();
|
|
331
|
+
const hookInput = JSON.parse(input);
|
|
332
|
+
const filePath = hookInput.tool_input?.file_path;
|
|
333
|
+
if (!filePath) {
|
|
334
|
+
process.exit(0);
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
const config = getConfig();
|
|
338
|
+
if (config.autoLearning?.enabled === false) {
|
|
339
|
+
process.exit(0);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
const root = getProjectRoot();
|
|
343
|
+
const incidentDir = config.autoLearning?.incidentDir ?? "docs/incidents";
|
|
344
|
+
const memoryDir = config.autoLearning?.memoryDir ?? "memory";
|
|
345
|
+
const relPath = filePath.startsWith(root + "/") ? filePath.slice(root.length + 1) : filePath;
|
|
346
|
+
if (!relPath.startsWith(incidentDir) || !relPath.endsWith(".md")) {
|
|
347
|
+
process.exit(0);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (!existsSync2(filePath)) {
|
|
351
|
+
process.exit(0);
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
const content = readFileSync2(filePath, "utf-8");
|
|
355
|
+
const titleMatch = content.match(/^#\s+(.+)/m);
|
|
356
|
+
const title = titleMatch?.[1] ?? basename(filePath, ".md");
|
|
357
|
+
const slug = basename(filePath, ".md").replace(/^\d{4}-\d{2}-\d{2}-?/, "").toLowerCase();
|
|
358
|
+
const memoryDirAbs = resolve2(root, memoryDir);
|
|
359
|
+
let hasExistingRule = false;
|
|
360
|
+
if (existsSync2(memoryDirAbs)) {
|
|
361
|
+
const ruleFiles = readdirSync(memoryDirAbs).filter((f) => f.startsWith("feedback_"));
|
|
362
|
+
for (const ruleFile of ruleFiles) {
|
|
363
|
+
if (ruleFile.toLowerCase().includes(slug.slice(0, 20))) {
|
|
364
|
+
hasExistingRule = true;
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
if (hasExistingRule) {
|
|
370
|
+
process.exit(0);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
const hasPrevention = /## Prevention Rules|## Prevention|## Rules/i.test(content);
|
|
374
|
+
if (config.autoLearning?.pipeline?.requirePreventionRule === false) {
|
|
375
|
+
process.exit(0);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const lines = [];
|
|
379
|
+
lines.push("");
|
|
380
|
+
lines.push("============================================================================");
|
|
381
|
+
lines.push(" AUTO-LEARNING: Incident Report Created \u2014 Rule Derivation Required");
|
|
382
|
+
lines.push("============================================================================");
|
|
383
|
+
lines.push("");
|
|
384
|
+
lines.push(` Incident: ${title}`);
|
|
385
|
+
lines.push(` File: ${filePath}`);
|
|
386
|
+
lines.push("");
|
|
387
|
+
if (!hasPrevention) {
|
|
388
|
+
lines.push(' No "## Prevention Rules" section found in the incident report.');
|
|
389
|
+
lines.push(" Add one first, then proceed with rule derivation.");
|
|
390
|
+
lines.push("");
|
|
391
|
+
}
|
|
392
|
+
lines.push(" DERIVE A PREVENTION RULE:");
|
|
393
|
+
lines.push(` a) Read the incident root cause and prevention rules`);
|
|
394
|
+
lines.push(` b) Create: ${memoryDir}/feedback_<rule_name>.md`);
|
|
395
|
+
lines.push(" Template:");
|
|
396
|
+
lines.push(" ---");
|
|
397
|
+
lines.push(" name: <Rule Name>");
|
|
398
|
+
lines.push(" description: <one-line description>");
|
|
399
|
+
lines.push(" type: feedback");
|
|
400
|
+
lines.push(" ---");
|
|
401
|
+
lines.push(" <Rule statement>");
|
|
402
|
+
lines.push(" **Why:** <Root cause from incident>");
|
|
403
|
+
lines.push(" **How to apply:** <Concrete steps>");
|
|
404
|
+
lines.push("");
|
|
405
|
+
lines.push(` c) Add one-line entry to ${config.autoLearning?.memoryIndexFile ?? "MEMORY.md"}`);
|
|
406
|
+
lines.push("");
|
|
407
|
+
lines.push(" This step is MANDATORY per the auto-learning pipeline.");
|
|
408
|
+
lines.push("============================================================================");
|
|
409
|
+
lines.push("");
|
|
410
|
+
console.log(lines.join("\n"));
|
|
411
|
+
} catch {
|
|
412
|
+
}
|
|
413
|
+
process.exit(0);
|
|
414
|
+
}
|
|
415
|
+
function readStdin() {
|
|
416
|
+
return new Promise((resolve3) => {
|
|
417
|
+
let data = "";
|
|
418
|
+
process.stdin.setEncoding("utf-8");
|
|
419
|
+
process.stdin.on("data", (chunk) => {
|
|
420
|
+
data += chunk;
|
|
421
|
+
});
|
|
422
|
+
process.stdin.on("end", () => resolve3(data));
|
|
423
|
+
setTimeout(() => resolve3(data), 3e3);
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
main();
|
|
@@ -129,6 +129,32 @@ var RegressionConfigSchema = z.object({
|
|
|
129
129
|
warning: z.number().default(50)
|
|
130
130
|
}).optional()
|
|
131
131
|
}).optional();
|
|
132
|
+
var AutoLearningConfigSchema = z.object({
|
|
133
|
+
enabled: z.boolean().default(true),
|
|
134
|
+
incidentDir: z.string().default("docs/incidents"),
|
|
135
|
+
memoryDir: z.string().default("memory"),
|
|
136
|
+
memoryIndexFile: z.string().default("MEMORY.md"),
|
|
137
|
+
enforcementHooksDir: z.string().default("scripts/hooks"),
|
|
138
|
+
fixDetection: z.object({
|
|
139
|
+
enabled: z.boolean().default(true),
|
|
140
|
+
lookbackDays: z.number().default(7),
|
|
141
|
+
signals: z.array(z.string()).default([
|
|
142
|
+
"removed_broken_code",
|
|
143
|
+
"added_error_handling",
|
|
144
|
+
"method_name_correction",
|
|
145
|
+
"auth_fix",
|
|
146
|
+
"nil_handling_fix",
|
|
147
|
+
"concurrency_fix",
|
|
148
|
+
"async_pattern_fix",
|
|
149
|
+
"added_missing_import"
|
|
150
|
+
])
|
|
151
|
+
}).default({}),
|
|
152
|
+
pipeline: z.object({
|
|
153
|
+
requireIncidentReport: z.boolean().default(true),
|
|
154
|
+
requirePreventionRule: z.boolean().default(true),
|
|
155
|
+
requireEnforcement: z.boolean().default(true)
|
|
156
|
+
}).default({})
|
|
157
|
+
}).optional();
|
|
132
158
|
var CloudConfigSchema = z.object({
|
|
133
159
|
enabled: z.boolean().default(false),
|
|
134
160
|
apiKey: z.string().optional(),
|
|
@@ -218,7 +244,8 @@ var RawConfigSchema = z.object({
|
|
|
218
244
|
regression: RegressionConfigSchema,
|
|
219
245
|
cloud: CloudConfigSchema,
|
|
220
246
|
conventions: ConventionsConfigSchema,
|
|
221
|
-
python: PythonConfigSchema
|
|
247
|
+
python: PythonConfigSchema,
|
|
248
|
+
autoLearning: AutoLearningConfigSchema
|
|
222
249
|
}).passthrough();
|
|
223
250
|
var _config = null;
|
|
224
251
|
var _projectRoot = null;
|
|
@@ -131,6 +131,32 @@ var RegressionConfigSchema = z.object({
|
|
|
131
131
|
warning: z.number().default(50)
|
|
132
132
|
}).optional()
|
|
133
133
|
}).optional();
|
|
134
|
+
var AutoLearningConfigSchema = z.object({
|
|
135
|
+
enabled: z.boolean().default(true),
|
|
136
|
+
incidentDir: z.string().default("docs/incidents"),
|
|
137
|
+
memoryDir: z.string().default("memory"),
|
|
138
|
+
memoryIndexFile: z.string().default("MEMORY.md"),
|
|
139
|
+
enforcementHooksDir: z.string().default("scripts/hooks"),
|
|
140
|
+
fixDetection: z.object({
|
|
141
|
+
enabled: z.boolean().default(true),
|
|
142
|
+
lookbackDays: z.number().default(7),
|
|
143
|
+
signals: z.array(z.string()).default([
|
|
144
|
+
"removed_broken_code",
|
|
145
|
+
"added_error_handling",
|
|
146
|
+
"method_name_correction",
|
|
147
|
+
"auth_fix",
|
|
148
|
+
"nil_handling_fix",
|
|
149
|
+
"concurrency_fix",
|
|
150
|
+
"async_pattern_fix",
|
|
151
|
+
"added_missing_import"
|
|
152
|
+
])
|
|
153
|
+
}).default({}),
|
|
154
|
+
pipeline: z.object({
|
|
155
|
+
requireIncidentReport: z.boolean().default(true),
|
|
156
|
+
requirePreventionRule: z.boolean().default(true),
|
|
157
|
+
requireEnforcement: z.boolean().default(true)
|
|
158
|
+
}).default({})
|
|
159
|
+
}).optional();
|
|
134
160
|
var CloudConfigSchema = z.object({
|
|
135
161
|
enabled: z.boolean().default(false),
|
|
136
162
|
apiKey: z.string().optional(),
|
|
@@ -220,7 +246,8 @@ var RawConfigSchema = z.object({
|
|
|
220
246
|
regression: RegressionConfigSchema,
|
|
221
247
|
cloud: CloudConfigSchema,
|
|
222
248
|
conventions: ConventionsConfigSchema,
|
|
223
|
-
python: PythonConfigSchema
|
|
249
|
+
python: PythonConfigSchema,
|
|
250
|
+
autoLearning: AutoLearningConfigSchema
|
|
224
251
|
}).passthrough();
|
|
225
252
|
var _config = null;
|
|
226
253
|
var _projectRoot = null;
|
|
@@ -131,6 +131,32 @@ var RegressionConfigSchema = z.object({
|
|
|
131
131
|
warning: z.number().default(50)
|
|
132
132
|
}).optional()
|
|
133
133
|
}).optional();
|
|
134
|
+
var AutoLearningConfigSchema = z.object({
|
|
135
|
+
enabled: z.boolean().default(true),
|
|
136
|
+
incidentDir: z.string().default("docs/incidents"),
|
|
137
|
+
memoryDir: z.string().default("memory"),
|
|
138
|
+
memoryIndexFile: z.string().default("MEMORY.md"),
|
|
139
|
+
enforcementHooksDir: z.string().default("scripts/hooks"),
|
|
140
|
+
fixDetection: z.object({
|
|
141
|
+
enabled: z.boolean().default(true),
|
|
142
|
+
lookbackDays: z.number().default(7),
|
|
143
|
+
signals: z.array(z.string()).default([
|
|
144
|
+
"removed_broken_code",
|
|
145
|
+
"added_error_handling",
|
|
146
|
+
"method_name_correction",
|
|
147
|
+
"auth_fix",
|
|
148
|
+
"nil_handling_fix",
|
|
149
|
+
"concurrency_fix",
|
|
150
|
+
"async_pattern_fix",
|
|
151
|
+
"added_missing_import"
|
|
152
|
+
])
|
|
153
|
+
}).default({}),
|
|
154
|
+
pipeline: z.object({
|
|
155
|
+
requireIncidentReport: z.boolean().default(true),
|
|
156
|
+
requirePreventionRule: z.boolean().default(true),
|
|
157
|
+
requireEnforcement: z.boolean().default(true)
|
|
158
|
+
}).default({})
|
|
159
|
+
}).optional();
|
|
134
160
|
var CloudConfigSchema = z.object({
|
|
135
161
|
enabled: z.boolean().default(false),
|
|
136
162
|
apiKey: z.string().optional(),
|
|
@@ -220,7 +246,8 @@ var RawConfigSchema = z.object({
|
|
|
220
246
|
regression: RegressionConfigSchema,
|
|
221
247
|
cloud: CloudConfigSchema,
|
|
222
248
|
conventions: ConventionsConfigSchema,
|
|
223
|
-
python: PythonConfigSchema
|
|
249
|
+
python: PythonConfigSchema,
|
|
250
|
+
autoLearning: AutoLearningConfigSchema
|
|
224
251
|
}).passthrough();
|
|
225
252
|
var _config = null;
|
|
226
253
|
var _projectRoot = null;
|
|
@@ -130,6 +130,32 @@ var RegressionConfigSchema = z.object({
|
|
|
130
130
|
warning: z.number().default(50)
|
|
131
131
|
}).optional()
|
|
132
132
|
}).optional();
|
|
133
|
+
var AutoLearningConfigSchema = z.object({
|
|
134
|
+
enabled: z.boolean().default(true),
|
|
135
|
+
incidentDir: z.string().default("docs/incidents"),
|
|
136
|
+
memoryDir: z.string().default("memory"),
|
|
137
|
+
memoryIndexFile: z.string().default("MEMORY.md"),
|
|
138
|
+
enforcementHooksDir: z.string().default("scripts/hooks"),
|
|
139
|
+
fixDetection: z.object({
|
|
140
|
+
enabled: z.boolean().default(true),
|
|
141
|
+
lookbackDays: z.number().default(7),
|
|
142
|
+
signals: z.array(z.string()).default([
|
|
143
|
+
"removed_broken_code",
|
|
144
|
+
"added_error_handling",
|
|
145
|
+
"method_name_correction",
|
|
146
|
+
"auth_fix",
|
|
147
|
+
"nil_handling_fix",
|
|
148
|
+
"concurrency_fix",
|
|
149
|
+
"async_pattern_fix",
|
|
150
|
+
"added_missing_import"
|
|
151
|
+
])
|
|
152
|
+
}).default({}),
|
|
153
|
+
pipeline: z.object({
|
|
154
|
+
requireIncidentReport: z.boolean().default(true),
|
|
155
|
+
requirePreventionRule: z.boolean().default(true),
|
|
156
|
+
requireEnforcement: z.boolean().default(true)
|
|
157
|
+
}).default({})
|
|
158
|
+
}).optional();
|
|
133
159
|
var CloudConfigSchema = z.object({
|
|
134
160
|
enabled: z.boolean().default(false),
|
|
135
161
|
apiKey: z.string().optional(),
|
|
@@ -219,7 +245,8 @@ var RawConfigSchema = z.object({
|
|
|
219
245
|
regression: RegressionConfigSchema,
|
|
220
246
|
cloud: CloudConfigSchema,
|
|
221
247
|
conventions: ConventionsConfigSchema,
|
|
222
|
-
python: PythonConfigSchema
|
|
248
|
+
python: PythonConfigSchema,
|
|
249
|
+
autoLearning: AutoLearningConfigSchema
|
|
223
250
|
}).passthrough();
|
|
224
251
|
var _config = null;
|
|
225
252
|
var _projectRoot = null;
|
|
@@ -131,6 +131,32 @@ var RegressionConfigSchema = z.object({
|
|
|
131
131
|
warning: z.number().default(50)
|
|
132
132
|
}).optional()
|
|
133
133
|
}).optional();
|
|
134
|
+
var AutoLearningConfigSchema = z.object({
|
|
135
|
+
enabled: z.boolean().default(true),
|
|
136
|
+
incidentDir: z.string().default("docs/incidents"),
|
|
137
|
+
memoryDir: z.string().default("memory"),
|
|
138
|
+
memoryIndexFile: z.string().default("MEMORY.md"),
|
|
139
|
+
enforcementHooksDir: z.string().default("scripts/hooks"),
|
|
140
|
+
fixDetection: z.object({
|
|
141
|
+
enabled: z.boolean().default(true),
|
|
142
|
+
lookbackDays: z.number().default(7),
|
|
143
|
+
signals: z.array(z.string()).default([
|
|
144
|
+
"removed_broken_code",
|
|
145
|
+
"added_error_handling",
|
|
146
|
+
"method_name_correction",
|
|
147
|
+
"auth_fix",
|
|
148
|
+
"nil_handling_fix",
|
|
149
|
+
"concurrency_fix",
|
|
150
|
+
"async_pattern_fix",
|
|
151
|
+
"added_missing_import"
|
|
152
|
+
])
|
|
153
|
+
}).default({}),
|
|
154
|
+
pipeline: z.object({
|
|
155
|
+
requireIncidentReport: z.boolean().default(true),
|
|
156
|
+
requirePreventionRule: z.boolean().default(true),
|
|
157
|
+
requireEnforcement: z.boolean().default(true)
|
|
158
|
+
}).default({})
|
|
159
|
+
}).optional();
|
|
134
160
|
var CloudConfigSchema = z.object({
|
|
135
161
|
enabled: z.boolean().default(false),
|
|
136
162
|
apiKey: z.string().optional(),
|
|
@@ -220,7 +246,8 @@ var RawConfigSchema = z.object({
|
|
|
220
246
|
regression: RegressionConfigSchema,
|
|
221
247
|
cloud: CloudConfigSchema,
|
|
222
248
|
conventions: ConventionsConfigSchema,
|
|
223
|
-
python: PythonConfigSchema
|
|
249
|
+
python: PythonConfigSchema,
|
|
250
|
+
autoLearning: AutoLearningConfigSchema
|
|
224
251
|
}).passthrough();
|
|
225
252
|
var _config = null;
|
|
226
253
|
var _projectRoot = null;
|