@massu/core 0.9.2 → 1.0.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.
Files changed (50) hide show
  1. package/dist/cli.js +10519 -1661
  2. package/dist/hooks/auto-learning-pipeline.js +99 -19
  3. package/dist/hooks/classify-failure.js +99 -19
  4. package/dist/hooks/cost-tracker.js +97 -11
  5. package/dist/hooks/fix-detector.js +99 -19
  6. package/dist/hooks/incident-pipeline.js +97 -11
  7. package/dist/hooks/post-edit-context.js +97 -11
  8. package/dist/hooks/post-tool-use.js +101 -20
  9. package/dist/hooks/pre-compact.js +97 -11
  10. package/dist/hooks/pre-delete-check.js +97 -11
  11. package/dist/hooks/quality-event.js +97 -11
  12. package/dist/hooks/rule-enforcement-pipeline.js +97 -11
  13. package/dist/hooks/session-end.js +97 -11
  14. package/dist/hooks/session-start.js +98 -12
  15. package/dist/hooks/user-prompt.js +98 -43
  16. package/package.json +13 -3
  17. package/reference/hook-execution-order.md +17 -25
  18. package/src/cli.ts +2 -1
  19. package/src/commands/doctor.ts +1 -29
  20. package/src/commands/init.ts +752 -216
  21. package/src/config.ts +168 -12
  22. package/src/detect/domain-inferrer.ts +142 -0
  23. package/src/detect/drift.ts +199 -0
  24. package/src/detect/framework-detector.ts +281 -0
  25. package/src/detect/index.ts +174 -0
  26. package/src/detect/migrate.ts +278 -0
  27. package/src/detect/monorepo-detector.ts +347 -0
  28. package/src/detect/package-detector.ts +728 -0
  29. package/src/detect/source-dir-detector.ts +264 -0
  30. package/src/detect/vr-command-map.ts +167 -0
  31. package/src/hooks/auto-learning-pipeline.ts +2 -2
  32. package/src/hooks/classify-failure.ts +2 -2
  33. package/src/hooks/fix-detector.ts +2 -2
  34. package/src/hooks/session-start.ts +1 -1
  35. package/src/hooks/user-prompt.ts +1 -21
  36. package/src/knowledge-indexer.ts +1 -1
  37. package/src/license.ts +1 -2
  38. package/src/memory-db.ts +0 -5
  39. package/src/memory-file-ingest.ts +6 -13
  40. package/src/tools.ts +0 -8
  41. package/templates/multi-runtime/massu.config.yaml +80 -0
  42. package/templates/python-django/massu.config.yaml +51 -0
  43. package/templates/python-fastapi/massu.config.yaml +50 -0
  44. package/templates/rust-actix/massu.config.yaml +38 -0
  45. package/templates/swift-ios/massu.config.yaml +37 -0
  46. package/templates/ts-nestjs/massu.config.yaml +43 -0
  47. package/templates/ts-nextjs/massu.config.yaml +43 -0
  48. package/README.md +0 -40
  49. package/src/claude-md-templates.ts +0 -342
  50. package/src/mcp-bridge-tools.ts +0 -458
@@ -21,7 +21,8 @@ var DomainConfigSchema = z.object({
21
21
  });
22
22
  var PatternRuleConfigSchema = z.object({
23
23
  pattern: z.string().default("**"),
24
- rules: z.array(z.string()).default([])
24
+ rules: z.array(z.string()).default([]),
25
+ language: z.string().optional()
25
26
  });
26
27
  var CostModelSchema = z.object({
27
28
  input_per_million: z.number(),
@@ -233,17 +234,59 @@ var PathsConfigSchema = z.object({
233
234
  components: z.string().optional(),
234
235
  hooks: z.string().optional()
235
236
  });
237
+ var LanguageFrameworkEntrySchema = z.object({
238
+ framework: z.string().optional(),
239
+ test_framework: z.string().optional(),
240
+ test: z.string().optional(),
241
+ runtime: z.string().optional(),
242
+ orm: z.string().optional(),
243
+ router: z.string().optional(),
244
+ ui: z.string().optional()
245
+ }).passthrough();
246
+ var FrameworkConfigSchema = z.object({
247
+ type: z.string().default("typescript"),
248
+ primary: z.string().optional(),
249
+ router: z.string().default("none"),
250
+ orm: z.string().default("none"),
251
+ ui: z.string().default("none"),
252
+ languages: z.record(z.string(), LanguageFrameworkEntrySchema).optional()
253
+ }).passthrough();
254
+ var VerificationEntrySchema = z.object({
255
+ type: z.string().optional(),
256
+ test: z.string().optional(),
257
+ syntax: z.string().optional(),
258
+ lint: z.string().optional(),
259
+ build: z.string().optional()
260
+ }).passthrough();
261
+ var VerificationConfigSchema = z.record(z.string(), VerificationEntrySchema).optional();
262
+ var CanonicalPathsSchema = z.record(z.string(), z.string()).optional();
263
+ var VerificationTypesSchema = z.record(z.string(), z.string()).optional();
264
+ var DetectionRuleEntrySchema = z.object({
265
+ signals: z.array(z.string()).default([]),
266
+ priority: z.number().optional()
267
+ }).passthrough();
268
+ var DetectionConfigSchema = z.object({
269
+ rules: z.record(
270
+ z.string(),
271
+ // language
272
+ z.record(z.string(), DetectionRuleEntrySchema)
273
+ // framework -> rule entry
274
+ ).optional(),
275
+ signal_weights: z.record(z.string(), z.number()).optional(),
276
+ disable_builtin: z.boolean().optional()
277
+ }).passthrough().optional();
236
278
  var RawConfigSchema = z.object({
279
+ schema_version: z.union([z.literal(1), z.literal(2)]).default(1),
237
280
  project: z.object({
238
281
  name: z.string().default("my-project"),
239
282
  root: z.string().default("auto")
240
283
  }).default({ name: "my-project", root: "auto" }),
241
- framework: z.object({
242
- type: z.string().default("typescript"),
243
- router: z.string().default("none"),
244
- orm: z.string().default("none"),
245
- ui: z.string().default("none")
246
- }).default({ type: "typescript", router: "none", orm: "none", ui: "none" }),
284
+ framework: FrameworkConfigSchema.default({
285
+ type: "typescript",
286
+ router: "none",
287
+ orm: "none",
288
+ ui: "none"
289
+ }),
247
290
  paths: PathsConfigSchema.default({ source: "src", aliases: { "@": "src" } }),
248
291
  toolPrefix: z.string().default("massu"),
249
292
  dbAccessPattern: z.string().optional(),
@@ -258,8 +301,13 @@ var RawConfigSchema = z.object({
258
301
  regression: RegressionConfigSchema,
259
302
  cloud: CloudConfigSchema,
260
303
  conventions: ConventionsConfigSchema,
304
+ autoLearning: AutoLearningConfigSchema,
261
305
  python: PythonConfigSchema,
262
- autoLearning: AutoLearningConfigSchema
306
+ // P2-004 / P2-005 / P2-006 / P2-008: v2 extensions (all optional)
307
+ verification: VerificationConfigSchema,
308
+ canonical_paths: CanonicalPathsSchema,
309
+ verification_types: VerificationTypesSchema,
310
+ detection: DetectionConfigSchema
263
311
  }).passthrough();
264
312
  var _config = null;
265
313
  var _projectRoot = null;
@@ -303,14 +351,47 @@ function getConfig() {
303
351
  const content = readFileSync(configPath, "utf-8");
304
352
  rawYaml = parseYaml(content) ?? {};
305
353
  }
306
- const parsed = RawConfigSchema.parse(rawYaml);
354
+ const result = RawConfigSchema.safeParse(rawYaml);
355
+ if (!result.success) {
356
+ const issues = result.error.issues.map((i) => {
357
+ const path = i.path.length > 0 ? i.path.join(".") : "(root)";
358
+ const received = "received" in i && i.received !== void 0 ? ` (received ${JSON.stringify(i.received)})` : "";
359
+ return ` - ${path}: ${i.message}${received}`;
360
+ }).join("\n");
361
+ throw new Error(
362
+ `Invalid massu.config.yaml at ${configPath}:
363
+ ${issues}
364
+ Hint: run \`massu config refresh\` to regenerate a valid config or fix the listed fields manually.`
365
+ );
366
+ }
367
+ const parsed = result.data;
307
368
  const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root : resolve(root, parsed.project.root);
369
+ const fw = parsed.framework;
370
+ let router = fw.router;
371
+ let orm = fw.orm;
372
+ let ui = fw.ui;
373
+ if (fw.type === "multi" && fw.primary && fw.languages) {
374
+ const primaryEntry = fw.languages[fw.primary];
375
+ if (primaryEntry) {
376
+ if (router === "none" && primaryEntry.router) router = primaryEntry.router;
377
+ if (orm === "none" && primaryEntry.orm) orm = primaryEntry.orm;
378
+ if (ui === "none" && primaryEntry.ui) ui = primaryEntry.ui;
379
+ }
380
+ }
308
381
  _config = {
382
+ schema_version: parsed.schema_version,
309
383
  project: {
310
384
  name: parsed.project.name,
311
385
  root: projectRoot
312
386
  },
313
- framework: parsed.framework,
387
+ framework: {
388
+ type: fw.type,
389
+ router,
390
+ orm,
391
+ ui,
392
+ primary: fw.primary,
393
+ languages: fw.languages
394
+ },
314
395
  paths: parsed.paths,
315
396
  toolPrefix: parsed.toolPrefix,
316
397
  dbAccessPattern: parsed.dbAccessPattern,
@@ -325,7 +406,12 @@ function getConfig() {
325
406
  regression: parsed.regression,
326
407
  cloud: parsed.cloud,
327
408
  conventions: parsed.conventions,
328
- python: parsed.python
409
+ autoLearning: parsed.autoLearning,
410
+ python: parsed.python,
411
+ verification: parsed.verification,
412
+ canonical_paths: parsed.canonical_paths,
413
+ verification_types: parsed.verification_types,
414
+ detection: parsed.detection
329
415
  };
330
416
  if (!_config.cloud?.apiKey && process.env.MASSU_API_KEY) {
331
417
  _config.cloud = {
@@ -986,7 +1072,7 @@ async function main() {
986
1072
  process.stdout.write(
987
1073
  `=== MASSU AI: Active ===
988
1074
  Session memory, code intelligence, and governance are now active.
989
- 15 hooks monitoring this session. Type "${getConfig().toolPrefix ?? "massu"}_sync" to index your codebase.
1075
+ 11 hooks monitoring this session. Type "${getConfig().toolPrefix ?? "massu"}_sync" to index your codebase.
990
1076
  === END MASSU ===
991
1077
 
992
1078
  `
@@ -21,7 +21,8 @@ var DomainConfigSchema = z.object({
21
21
  });
22
22
  var PatternRuleConfigSchema = z.object({
23
23
  pattern: z.string().default("**"),
24
- rules: z.array(z.string()).default([])
24
+ rules: z.array(z.string()).default([]),
25
+ language: z.string().optional()
25
26
  });
26
27
  var CostModelSchema = z.object({
27
28
  input_per_million: z.number(),
@@ -233,17 +234,59 @@ var PathsConfigSchema = z.object({
233
234
  components: z.string().optional(),
234
235
  hooks: z.string().optional()
235
236
  });
237
+ var LanguageFrameworkEntrySchema = z.object({
238
+ framework: z.string().optional(),
239
+ test_framework: z.string().optional(),
240
+ test: z.string().optional(),
241
+ runtime: z.string().optional(),
242
+ orm: z.string().optional(),
243
+ router: z.string().optional(),
244
+ ui: z.string().optional()
245
+ }).passthrough();
246
+ var FrameworkConfigSchema = z.object({
247
+ type: z.string().default("typescript"),
248
+ primary: z.string().optional(),
249
+ router: z.string().default("none"),
250
+ orm: z.string().default("none"),
251
+ ui: z.string().default("none"),
252
+ languages: z.record(z.string(), LanguageFrameworkEntrySchema).optional()
253
+ }).passthrough();
254
+ var VerificationEntrySchema = z.object({
255
+ type: z.string().optional(),
256
+ test: z.string().optional(),
257
+ syntax: z.string().optional(),
258
+ lint: z.string().optional(),
259
+ build: z.string().optional()
260
+ }).passthrough();
261
+ var VerificationConfigSchema = z.record(z.string(), VerificationEntrySchema).optional();
262
+ var CanonicalPathsSchema = z.record(z.string(), z.string()).optional();
263
+ var VerificationTypesSchema = z.record(z.string(), z.string()).optional();
264
+ var DetectionRuleEntrySchema = z.object({
265
+ signals: z.array(z.string()).default([]),
266
+ priority: z.number().optional()
267
+ }).passthrough();
268
+ var DetectionConfigSchema = z.object({
269
+ rules: z.record(
270
+ z.string(),
271
+ // language
272
+ z.record(z.string(), DetectionRuleEntrySchema)
273
+ // framework -> rule entry
274
+ ).optional(),
275
+ signal_weights: z.record(z.string(), z.number()).optional(),
276
+ disable_builtin: z.boolean().optional()
277
+ }).passthrough().optional();
236
278
  var RawConfigSchema = z.object({
279
+ schema_version: z.union([z.literal(1), z.literal(2)]).default(1),
237
280
  project: z.object({
238
281
  name: z.string().default("my-project"),
239
282
  root: z.string().default("auto")
240
283
  }).default({ name: "my-project", root: "auto" }),
241
- framework: z.object({
242
- type: z.string().default("typescript"),
243
- router: z.string().default("none"),
244
- orm: z.string().default("none"),
245
- ui: z.string().default("none")
246
- }).default({ type: "typescript", router: "none", orm: "none", ui: "none" }),
284
+ framework: FrameworkConfigSchema.default({
285
+ type: "typescript",
286
+ router: "none",
287
+ orm: "none",
288
+ ui: "none"
289
+ }),
247
290
  paths: PathsConfigSchema.default({ source: "src", aliases: { "@": "src" } }),
248
291
  toolPrefix: z.string().default("massu"),
249
292
  dbAccessPattern: z.string().optional(),
@@ -258,8 +301,13 @@ var RawConfigSchema = z.object({
258
301
  regression: RegressionConfigSchema,
259
302
  cloud: CloudConfigSchema,
260
303
  conventions: ConventionsConfigSchema,
304
+ autoLearning: AutoLearningConfigSchema,
261
305
  python: PythonConfigSchema,
262
- autoLearning: AutoLearningConfigSchema
306
+ // P2-004 / P2-005 / P2-006 / P2-008: v2 extensions (all optional)
307
+ verification: VerificationConfigSchema,
308
+ canonical_paths: CanonicalPathsSchema,
309
+ verification_types: VerificationTypesSchema,
310
+ detection: DetectionConfigSchema
263
311
  }).passthrough();
264
312
  var _config = null;
265
313
  var _projectRoot = null;
@@ -303,14 +351,47 @@ function getConfig() {
303
351
  const content = readFileSync(configPath, "utf-8");
304
352
  rawYaml = parseYaml(content) ?? {};
305
353
  }
306
- const parsed = RawConfigSchema.parse(rawYaml);
354
+ const result = RawConfigSchema.safeParse(rawYaml);
355
+ if (!result.success) {
356
+ const issues = result.error.issues.map((i) => {
357
+ const path = i.path.length > 0 ? i.path.join(".") : "(root)";
358
+ const received = "received" in i && i.received !== void 0 ? ` (received ${JSON.stringify(i.received)})` : "";
359
+ return ` - ${path}: ${i.message}${received}`;
360
+ }).join("\n");
361
+ throw new Error(
362
+ `Invalid massu.config.yaml at ${configPath}:
363
+ ${issues}
364
+ Hint: run \`massu config refresh\` to regenerate a valid config or fix the listed fields manually.`
365
+ );
366
+ }
367
+ const parsed = result.data;
307
368
  const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root : resolve(root, parsed.project.root);
369
+ const fw = parsed.framework;
370
+ let router = fw.router;
371
+ let orm = fw.orm;
372
+ let ui = fw.ui;
373
+ if (fw.type === "multi" && fw.primary && fw.languages) {
374
+ const primaryEntry = fw.languages[fw.primary];
375
+ if (primaryEntry) {
376
+ if (router === "none" && primaryEntry.router) router = primaryEntry.router;
377
+ if (orm === "none" && primaryEntry.orm) orm = primaryEntry.orm;
378
+ if (ui === "none" && primaryEntry.ui) ui = primaryEntry.ui;
379
+ }
380
+ }
308
381
  _config = {
382
+ schema_version: parsed.schema_version,
309
383
  project: {
310
384
  name: parsed.project.name,
311
385
  root: projectRoot
312
386
  },
313
- framework: parsed.framework,
387
+ framework: {
388
+ type: fw.type,
389
+ router,
390
+ orm,
391
+ ui,
392
+ primary: fw.primary,
393
+ languages: fw.languages
394
+ },
314
395
  paths: parsed.paths,
315
396
  toolPrefix: parsed.toolPrefix,
316
397
  dbAccessPattern: parsed.dbAccessPattern,
@@ -325,7 +406,12 @@ function getConfig() {
325
406
  regression: parsed.regression,
326
407
  cloud: parsed.cloud,
327
408
  conventions: parsed.conventions,
328
- python: parsed.python
409
+ autoLearning: parsed.autoLearning,
410
+ python: parsed.python,
411
+ verification: parsed.verification,
412
+ canonical_paths: parsed.canonical_paths,
413
+ verification_types: parsed.verification_types,
414
+ detection: parsed.detection
329
415
  };
330
416
  if (!_config.cloud?.apiKey && process.env.MASSU_API_KEY) {
331
417
  _config.cloud = {
@@ -952,9 +1038,7 @@ function linkSessionToTask(db, sessionId, taskId) {
952
1038
  }
953
1039
 
954
1040
  // src/hooks/user-prompt.ts
955
- import { existsSync as existsSync3, writeFileSync } from "fs";
956
- import { tmpdir } from "os";
957
- import { join } from "path";
1041
+ import { existsSync as existsSync3 } from "fs";
958
1042
  async function main() {
959
1043
  try {
960
1044
  const input = await readStdin();
@@ -1027,35 +1111,6 @@ async function main() {
1027
1111
  }
1028
1112
  } catch (_memoryNagErr) {
1029
1113
  }
1030
- try {
1031
- const failureKeywords = [
1032
- "bug",
1033
- "broken",
1034
- "crash",
1035
- "error",
1036
- "fail",
1037
- "fix",
1038
- "wrong",
1039
- "missing",
1040
- "undefined",
1041
- "null",
1042
- "exception",
1043
- "stack trace",
1044
- "regression",
1045
- "revert",
1046
- "doesn't work",
1047
- "not working",
1048
- "stopped working",
1049
- "broke"
1050
- ];
1051
- const promptLower = prompt.toLowerCase();
1052
- const matched = failureKeywords.filter((kw) => promptLower.includes(kw));
1053
- if (matched.length > 0) {
1054
- const contextFile = join(tmpdir(), `massu-failure-context-${session_id.slice(0, 8)}-${Date.now()}`);
1055
- writeFileSync(contextFile, matched.join(" "), "utf-8");
1056
- }
1057
- } catch {
1058
- }
1059
1114
  } finally {
1060
1115
  db.close();
1061
1116
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@massu/core",
3
- "version": "0.9.2",
3
+ "version": "1.0.0",
4
4
  "type": "module",
5
- "description": "AI Engineering Governance MCP Server - Session memory, knowledge system, feature registry, code intelligence, rule enforcement, auto-learning pipeline, tiered tooling (12 free / 72 total), 55+ workflow commands, 15 agents, 20+ patterns",
5
+ "description": "AI Engineering Governance MCP Server - Session memory, knowledge system, feature registry, code intelligence, rule enforcement, tiered tooling (12 free / 72 total), 55+ workflow commands, 11 agents, 20+ patterns",
6
6
  "main": "src/server.ts",
7
7
  "bin": {
8
8
  "massu": "./dist/cli.js"
@@ -16,7 +16,10 @@
16
16
  "prepublishOnly": "bash ../../scripts/prepublish-check.sh && npm run build"
17
17
  },
18
18
  "dependencies": {
19
+ "@clack/prompts": "^0.9.1",
19
20
  "better-sqlite3": "^12.6.2",
21
+ "fast-glob": "^3.3.0",
22
+ "smol-toml": "^1.3.0",
20
23
  "yaml": "^2.4.0",
21
24
  "zod": "^3.23.0"
22
25
  },
@@ -29,13 +32,20 @@
29
32
  },
30
33
  "files": [
31
34
  "src/**/*",
32
- "!src/__tests__/**",
35
+ "!src/**/__tests__/**",
36
+ "!src/**/*.test.ts",
37
+ "!src/**/*.spec.ts",
38
+ "!**/.build/**",
39
+ "!**/.swiftpm/**",
40
+ "!**/node_modules/**",
41
+ "!**/__pycache__/**",
33
42
  "dist/**/*",
34
43
  "commands/**/*",
35
44
  "agents/**/*",
36
45
  "patterns/**/*",
37
46
  "protocols/**/*",
38
47
  "reference/**/*",
48
+ "templates/**/*",
39
49
  "LICENSE"
40
50
  ],
41
51
  "keywords": [
@@ -52,9 +52,9 @@ Security blocking -> advisory warnings -> matcher-specific -> observability.
52
52
 
53
53
  ---
54
54
 
55
- ## PostToolUse (14 hooks)
55
+ ## PostToolUse (11 hooks)
56
56
 
57
- Security scan -> immediate feedback -> context tracking -> fix detection -> incident capture -> pipeline triggers -> memory sync -> observability.
57
+ Security scan -> immediate feedback -> context tracking -> incident capture -> memory sync -> observability.
58
58
 
59
59
  | position: 1 | CI monitor | standard | Bash(git push) -- immediate push feedback |
60
60
  |---|---|---|---|
@@ -62,23 +62,17 @@ Security scan -> immediate feedback -> context tracking -> fix detection -> inci
62
62
  | position: 3 | `pattern-feedback.sh` | standard | Edit\|Write -- immediate pattern violation feedback |
63
63
  | position: 4 | `post-edit-context.js` | strict | Edit\|Write -- detailed semantic analysis |
64
64
  | position: 5 | `post-tool-use.js` | standard | Edit\|Write\|Bash -- structured context tracking |
65
- | position: 6 | `fix-detector.js` | standard | Edit\|Write -- detect bug fixes via git diff heuristics |
66
- | position: 7 | `auto-ingest-incident.sh` | strict | Edit\|Write -- auto-capture incident patterns |
67
- | position: 8 | `incident-pipeline.js` | standard | Write -- trigger rule derivation on incident report writes |
68
- | position: 9 | `rule-enforcement-pipeline.js` | standard | Write -- trigger enforcement on prevention rule writes |
69
- | position: 10 | `memory-auto-ingest.sh` | standard | Write -- auto-sync memory files to codegraph SQLite DB |
70
- | position: 11 | `validate-deliverables.sh` | strict | Bash\|Edit\|Write -- deliverable validation |
71
- | position: 12 | `pattern-scanner.sh --single-file` | strict | Edit\|Write -- per-file pattern scan |
72
- | position: 13 | `mcp-usage-tracker.sh` | strict | MCP tools -- append-only MCP audit log |
73
- | position: 14 | `compaction-advisor.sh` | standard | Bash\|Edit\|Write\|Read\|Grep\|Glob -- context tracking, widest matcher |
65
+ | position: 6 | `auto-ingest-incident.sh` | strict | Edit\|Write -- auto-capture incident patterns |
66
+ | position: 7 | `memory-auto-ingest.sh` | standard | Write -- auto-sync memory files to codegraph SQLite DB |
67
+ | position: 8 | `validate-deliverables.sh` | strict | Bash\|Edit\|Write -- deliverable validation |
68
+ | position: 9 | `pattern-scanner.sh --single-file` | strict | Edit\|Write -- per-file pattern scan |
69
+ | position: 10 | `mcp-usage-tracker.sh` | strict | MCP tools -- append-only MCP audit log |
70
+ | position: 11 | `compaction-advisor.sh` | standard | Bash\|Edit\|Write\|Read\|Grep\|Glob -- context tracking, widest matcher |
74
71
 
75
72
  **Dependencies**:
76
73
  - `output-secret-filter.sh` MUST run before any feedback hooks -- security first
77
74
  - `pattern-feedback.sh` before `post-tool-use.js` -- immediate feedback before tracking
78
- - `fix-detector.js` after `post-tool-use.js` -- needs structured tracking context
79
- - `incident-pipeline.js` after `auto-ingest-incident.sh` -- incident must be captured first
80
- - `rule-enforcement-pipeline.js` after `incident-pipeline.js` -- rule derivation before enforcement
81
- - `memory-auto-ingest.sh` runs after pipeline hooks -- memory sync is data-writing, before validation
75
+ - `memory-auto-ingest.sh` runs after incident capture -- memory sync is data-writing, before validation
82
76
  - `compaction-advisor.sh` MUST be last -- widest matcher, just counts tool calls
83
77
 
84
78
  ---
@@ -111,23 +105,21 @@ Quick state capture -> full DB snapshot.
111
105
 
112
106
  ---
113
107
 
114
- ## Stop (8 hooks)
108
+ ## Stop (7 hooks)
115
109
 
116
- Session summary -> auto-learning check -> warnings -> memory extraction -> review -> validation.
110
+ Session summary -> warnings -> memory extraction -> review -> validation.
117
111
 
118
112
  | position: 1 | `session-end.js` | standard | Write session summary to memory DB |
119
113
  |---|---|---|---|
120
- | position: 2 | `auto-learning-pipeline.js` | standard | Enforce fix→incident→rule→enforcement pipeline completion |
121
- | position: 3 | Uncommitted changes warning | standard (inline) | Alert user about unstaged work |
122
- | position: 4 | `memory-auto-extract.sh` | standard | Auto-extract memories from DB observations |
123
- | position: 5 | `auto-review-on-stop.sh` | strict | Automated code review of session changes |
124
- | position: 6 | `surface-review-findings.sh` | strict | Display review findings to user |
125
- | position: 7 | `validate-deliverables.sh` | strict | Final deliverable validation |
126
- | position: 8 | `pattern-extractor.sh` | advisory | Extract new patterns from session |
114
+ | position: 2 | Uncommitted changes warning | standard (inline) | Alert user about unstaged work |
115
+ | position: 3 | `memory-auto-extract.sh` | standard | Auto-extract memories from DB observations |
116
+ | position: 4 | `auto-review-on-stop.sh` | strict | Automated code review of session changes |
117
+ | position: 5 | `surface-review-findings.sh` | strict | Display review findings to user |
118
+ | position: 6 | `validate-deliverables.sh` | strict | Final deliverable validation |
119
+ | position: 7 | `pattern-extractor.sh` | advisory | Extract new patterns from session |
127
120
 
128
121
  **Dependencies**:
129
122
  - `session-end.js` MUST be position 1 -- writes DB data that `memory-auto-extract.sh` reads
130
- - `auto-learning-pipeline.js` MUST run early -- needs to output mandatory instructions before session ends
131
123
  - `memory-auto-extract.sh` MUST come after `session-end.js` -- depends on DB observations
132
124
  - `surface-review-findings.sh` MUST come after `auto-review-on-stop.sh` -- displays its output
133
125
  - `pattern-extractor.sh` runs last -- advisory tier (skipped in minimal/standard profiles)
package/src/cli.ts CHANGED
@@ -89,7 +89,8 @@ Options:
89
89
  --version, -v Show version
90
90
 
91
91
  Getting started:
92
- npx massu init # Full setup in one command
92
+ npx massu init # Full setup in one command
93
+ npx massu init --help # Show all init options (--ci, --force, --template)
93
94
 
94
95
  Documentation: https://massu.ai/docs
95
96
  `);
@@ -8,14 +8,13 @@
8
8
  * 1. massu.config.yaml exists and parses correctly
9
9
  * 2. .mcp.json has massu entry
10
10
  * 3. .claude/settings.local.json has hooks config
11
- * 4. All 15 compiled hook files exist
11
+ * 4. All 11 compiled hook files exist
12
12
  * 5. Knowledge DB exists (.massu/memory.db)
13
13
  * 6. Memory directory exists (~/.claude/projects/.../memory/)
14
14
  * 7. Shell hooks wired in settings.local.json
15
15
  * 8. better-sqlite3 native module loads
16
16
  * 9. Node.js version >= 18
17
17
  * 10. Git repository detected
18
- * 11. CLAUDE.md exists with content
19
18
  */
20
19
 
21
20
  import { existsSync, readFileSync, readdirSync } from 'fs';
@@ -374,32 +373,6 @@ function checkPythonHealth(projectRoot: string): CheckResult | null {
374
373
  };
375
374
  }
376
375
 
377
- function checkClaudeMd(projectRoot: string): CheckResult {
378
- const claudeMdPath = resolve(projectRoot, 'CLAUDE.md');
379
- if (!existsSync(claudeMdPath)) {
380
- return {
381
- name: 'CLAUDE.md',
382
- status: 'warn',
383
- detail: 'CLAUDE.md not found. Run: npx massu init (or create manually)',
384
- };
385
- }
386
-
387
- const content = readFileSync(claudeMdPath, 'utf-8');
388
- if (content.trim().length < 50) {
389
- return {
390
- name: 'CLAUDE.md',
391
- status: 'warn',
392
- detail: 'CLAUDE.md exists but appears empty or minimal',
393
- };
394
- }
395
-
396
- return {
397
- name: 'CLAUDE.md',
398
- status: 'pass',
399
- detail: 'CLAUDE.md found and has content',
400
- };
401
- }
402
-
403
376
  // ============================================================
404
377
  // Main Doctor Flow
405
378
  // ============================================================
@@ -424,7 +397,6 @@ export async function runDoctor(): Promise<void> {
424
397
  checkNodeVersion(),
425
398
  await checkGitRepo(projectRoot),
426
399
  await checkLicenseStatus(),
427
- checkClaudeMd(projectRoot),
428
400
  ];
429
401
 
430
402
  // Add Python health check if configured