claudeos-core 1.5.0 → 1.6.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 (39) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.de.md +54 -27
  3. package/README.es.md +54 -26
  4. package/README.fr.md +54 -26
  5. package/README.hi.md +54 -27
  6. package/README.ja.md +53 -26
  7. package/README.ko.md +56 -29
  8. package/README.md +53 -26
  9. package/README.ru.md +54 -27
  10. package/README.vi.md +54 -27
  11. package/README.zh-CN.md +54 -27
  12. package/bin/cli.js +6 -2
  13. package/bin/commands/init.js +48 -46
  14. package/bin/lib/cli-utils.js +6 -10
  15. package/bin/lib/lang-selector.js +10 -8
  16. package/bin/lib/resume-selector.js +10 -8
  17. package/content-validator/index.js +7 -12
  18. package/health-checker/index.js +7 -17
  19. package/lib/plan-parser.js +149 -0
  20. package/lib/safe-fs.js +2 -2
  21. package/lib/stale-report.js +36 -0
  22. package/manifest-generator/index.js +13 -36
  23. package/package.json +87 -87
  24. package/pass-json-validator/index.js +7 -12
  25. package/pass-prompts/templates/node-nestjs/pass1.md +132 -0
  26. package/pass-prompts/templates/node-nestjs/pass2.md +97 -0
  27. package/pass-prompts/templates/node-nestjs/pass3.md +121 -0
  28. package/pass-prompts/templates/vue-nuxt/pass1.md +119 -0
  29. package/pass-prompts/templates/vue-nuxt/pass2.md +83 -0
  30. package/pass-prompts/templates/vue-nuxt/pass3.md +100 -0
  31. package/plan-installer/domain-grouper.js +5 -2
  32. package/plan-installer/prompt-generator.js +1 -4
  33. package/plan-installer/scanners/scan-frontend.js +14 -7
  34. package/plan-installer/scanners/scan-java.js +18 -13
  35. package/plan-installer/scanners/scan-kotlin.js +47 -23
  36. package/plan-installer/scanners/scan-node.js +16 -2
  37. package/plan-installer/stack-detector.js +42 -1
  38. package/plan-validator/index.js +11 -121
  39. package/sync-checker/index.js +6 -19
@@ -0,0 +1,149 @@
1
+ /**
2
+ * ClaudeOS-Core — Plan Parser (shared)
3
+ *
4
+ * Shared parsing logic for plan files used by both manifest-generator and plan-validator.
5
+ * Two block formats:
6
+ * - <file path="..."> ... </file> (standard plan format)
7
+ * - ## N. `path` \n```markdown ... ``` (code block format, e.g. sync-rules-master)
8
+ *
9
+ * Each function accepts a content string and returns parsed blocks.
10
+ * Replace functions modify content in-place and return the updated string.
11
+ */
12
+
13
+ // ─── Extract <file path="..."> blocks ───────────────────────
14
+
15
+ /**
16
+ * Parse <file path="..."> ... </file> blocks from plan content.
17
+ * @param {string} content - plan file content
18
+ * @param {{ includeContent?: boolean }} options
19
+ * @returns {Array<{ path: string, content?: string }>}
20
+ */
21
+ function parseFileBlocks(content, { includeContent = false } = {}) {
22
+ const result = [];
23
+ if (includeContent) {
24
+ const re = /<file\s+path="([^"]+)">\s*\n([\s\S]*?)\n<\/file>/g;
25
+ let m;
26
+ while ((m = re.exec(content)) !== null) {
27
+ result.push({ path: m[1], content: m[2] });
28
+ }
29
+ } else {
30
+ const re = /<file\s+path="([^"]+)">/g;
31
+ let m;
32
+ while ((m = re.exec(content)) !== null) {
33
+ result.push({ path: m[1] });
34
+ }
35
+ }
36
+ return result;
37
+ }
38
+
39
+ // ─── Extract ## N. `path` ```markdown ... ``` blocks ────────
40
+
41
+ /**
42
+ * Parse ## N. `path` + ```markdown ... ``` blocks from plan content.
43
+ * Uses indexOf-based parsing to correctly handle nested code fences.
44
+ * @param {string} content - plan file content
45
+ * @param {{ includeContent?: boolean }} options
46
+ * @returns {Array<{ path: string, content?: string }>}
47
+ */
48
+ function parseCodeBlocks(content, { includeContent = false } = {}) {
49
+ const result = [];
50
+ const headingRe = includeContent
51
+ ? /^##\s+\d+\.\s+([^\n]+)/gm
52
+ : /^##\s+\d+\.\s+`?([^`\n]+)`?/gm;
53
+ let headingMatch;
54
+ while ((headingMatch = headingRe.exec(content)) !== null) {
55
+ const filePath = headingMatch[1].replace(/`/g, "").trim();
56
+
57
+ if (!includeContent) {
58
+ // Path-only mode: just validate and collect
59
+ if (filePath && filePath.includes("/")) {
60
+ result.push({ path: filePath });
61
+ }
62
+ continue;
63
+ }
64
+
65
+ // Content mode: find opening ```markdown and matching closing ```
66
+ const openFence = content.indexOf("```markdown\n", headingMatch.index);
67
+ if (openFence < 0) continue;
68
+ const contentStart = openFence + "```markdown\n".length;
69
+ const closingPos = findClosingFence(content, contentStart);
70
+ if (closingPos < 0) continue;
71
+ const blockContent = content.substring(contentStart, closingPos).trimEnd();
72
+ result.push({ path: filePath, content: blockContent });
73
+ // Advance headingRe past this block to avoid re-matching inside content
74
+ headingRe.lastIndex = closingPos;
75
+ }
76
+ return result;
77
+ }
78
+
79
+ // ─── Replace <file> block content ───────────────────────────
80
+
81
+ /**
82
+ * Replace content inside a <file path="..."> block.
83
+ * @param {string} content - full plan file content
84
+ * @param {string} filePath - path attribute to match
85
+ * @param {string} newContent - replacement content
86
+ * @returns {string} updated content
87
+ */
88
+ function replaceFileBlock(content, filePath, newContent) {
89
+ const escaped = filePath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
90
+ return content.replace(
91
+ new RegExp(`(<file\\s+path="${escaped}">\\s*\\n)[\\s\\S]*?(\\n</file>)`, "g"),
92
+ `$1${newContent}$2`
93
+ );
94
+ }
95
+
96
+ // ─── Replace code block content ─────────────────────────────
97
+
98
+ /**
99
+ * Replace content inside a ## N. `path` ```markdown ... ``` block.
100
+ * Uses indexOf-based approach to handle nested code fences.
101
+ * @param {string} content - full plan file content
102
+ * @param {string} filePath - path to match in heading
103
+ * @param {string} newContent - replacement content
104
+ * @returns {string} updated content
105
+ */
106
+ function replaceCodeBlock(content, filePath, newContent) {
107
+ const cleanPath = filePath.replace(/`/g, "");
108
+ const headingPattern = new RegExp(`^##\\s+\\d+\\.\\s+\`?${cleanPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\`?`, "m");
109
+ const headingMatch = headingPattern.exec(content);
110
+ if (!headingMatch) return content;
111
+ const afterHeading = content.indexOf("```markdown\n", headingMatch.index);
112
+ if (afterHeading < 0) return content;
113
+ const contentStart = afterHeading + "```markdown\n".length;
114
+ const closingPos = findClosingFence(content, contentStart);
115
+ if (closingPos < 0) return content;
116
+ return content.substring(0, contentStart) + newContent + "\n" + content.substring(closingPos);
117
+ }
118
+
119
+ // ─── Internal: find closing ``` with nesting ────────────────
120
+
121
+ function findClosingFence(content, startPos) {
122
+ let searchPos = startPos;
123
+ let nestDepth = 0;
124
+ while (searchPos < content.length) {
125
+ const nextFence = content.indexOf("\n```", searchPos);
126
+ if (nextFence < 0) break;
127
+ const fenceLineStart = nextFence + 1;
128
+ const nextNewline = content.indexOf("\n", fenceLineStart + 3);
129
+ const restOfLine = nextNewline >= 0
130
+ ? content.substring(fenceLineStart + 3, nextNewline)
131
+ : content.substring(fenceLineStart + 3);
132
+ const isOpening = /^[a-zA-Z]/.test(restOfLine.trim());
133
+ if (isOpening) {
134
+ nestDepth++;
135
+ searchPos = nextNewline >= 0 ? nextNewline : fenceLineStart + 3;
136
+ } else if (nestDepth > 0) {
137
+ nestDepth--;
138
+ searchPos = nextNewline >= 0 ? nextNewline : fenceLineStart + 3;
139
+ } else {
140
+ return fenceLineStart;
141
+ }
142
+ }
143
+ return -1;
144
+ }
145
+
146
+ // Plan files that use code block format instead of <file> block format
147
+ const CODE_BLOCK_PLANS = ["21.sync-rules-master.md"];
148
+
149
+ module.exports = { parseFileBlocks, parseCodeBlocks, replaceFileBlock, replaceCodeBlock, CODE_BLOCK_PLANS };
package/lib/safe-fs.js CHANGED
@@ -50,7 +50,7 @@ function readJsonSafe(filePath, fallback = null) {
50
50
  function existsSafe(filePath) {
51
51
  try {
52
52
  return fs.existsSync(filePath);
53
- } catch {
53
+ } catch (_e) {
54
54
  return false;
55
55
  }
56
56
  }
@@ -95,7 +95,7 @@ function statSafe(filePath) {
95
95
  bytes: s.size,
96
96
  modified: s.mtime.toISOString().split("T")[0],
97
97
  };
98
- } catch {
98
+ } catch (_e) {
99
99
  return null;
100
100
  }
101
101
  }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * ClaudeOS-Core — Stale Report Utility
3
+ *
4
+ * Shared helper for reading/updating claudeos-core/generated/stale-report.json.
5
+ * Used by: content-validator, sync-checker, plan-validator, health-checker,
6
+ * pass-json-validator, manifest-generator.
7
+ */
8
+
9
+ const fs = require("fs");
10
+ const path = require("path");
11
+
12
+ /**
13
+ * Update stale-report.json with a new key and optional summary patch.
14
+ * Reads existing file, merges data, writes back. Safe against missing/malformed files.
15
+ *
16
+ * @param {string} genDir - path to claudeos-core/generated/
17
+ * @param {string} key - top-level key to set (e.g. "contentValidation", "syncMisses")
18
+ * @param {object} data - value for that key
19
+ * @param {object} [summaryPatch] - fields to merge into ex.summary
20
+ */
21
+ function updateStaleReport(genDir, key, data, summaryPatch) {
22
+ if (!fs.existsSync(genDir)) return;
23
+ const rp = path.join(genDir, "stale-report.json");
24
+ let ex = {};
25
+ if (fs.existsSync(rp)) {
26
+ try { ex = JSON.parse(fs.readFileSync(rp, "utf-8")); } catch (_e) { ex = {}; }
27
+ }
28
+ ex[key] = data;
29
+ if (summaryPatch) {
30
+ if (!ex.summary) ex.summary = {};
31
+ Object.assign(ex.summary, summaryPatch);
32
+ }
33
+ fs.writeFileSync(rp, JSON.stringify(ex, null, 2));
34
+ }
35
+
36
+ module.exports = { updateStaleReport };
@@ -17,6 +17,8 @@ const fs = require("fs");
17
17
  const path = require("path");
18
18
  const matter = require("gray-matter");
19
19
  const { glob } = require("glob");
20
+ const { parseFileBlocks, parseCodeBlocks, CODE_BLOCK_PLANS } = require("../lib/plan-parser");
21
+ const { updateStaleReport } = require("../lib/stale-report");
20
22
 
21
23
  const ROOT = process.env.CLAUDEOS_ROOT || path.resolve(__dirname, "../..");
22
24
  const GEN = path.join(ROOT, "claudeos-core/generated");
@@ -48,39 +50,23 @@ function stat(f) {
48
50
  function frontmatter(f) {
49
51
  try {
50
52
  return matter(fs.readFileSync(f, "utf-8")).data || {};
51
- } catch {
53
+ } catch (_e) {
52
54
  return {};
53
55
  }
54
56
  }
55
57
 
56
58
 
57
- // Plans using <file path="..."> block format
58
- function extractFileBlocks(f) {
59
+ // Wrappers: read file parse → attach planFile metadata
60
+ function extractFileBlocksFromFile(f) {
59
61
  if (!fs.existsSync(f)) return [];
60
62
  const content = fs.readFileSync(f, "utf-8");
61
- const result = [];
62
- let m;
63
- const re = /<file\s+path="([^"]+)">/g;
64
- while ((m = re.exec(content)) !== null) {
65
- result.push({ sourcePath: m[1], planFile: rel(f) });
66
- }
67
- return result;
63
+ return parseFileBlocks(content).map(b => ({ sourcePath: b.path, planFile: rel(f) }));
68
64
  }
69
65
 
70
- // Plans using ## N. `path` ```markdown code block format (e.g., 21.sync-rules-master.md)
71
- function extractCodeBlockPaths(f) {
66
+ function extractCodeBlockPathsFromFile(f) {
72
67
  if (!fs.existsSync(f)) return [];
73
68
  const content = fs.readFileSync(f, "utf-8");
74
- const result = [];
75
- const headingRe = /^##\s+\d+\.\s+`?([^`\n]+)`?/gm;
76
- let headingMatch;
77
- while ((headingMatch = headingRe.exec(content)) !== null) {
78
- const filePath = headingMatch[1].trim();
79
- if (filePath && filePath.includes("/")) {
80
- result.push({ sourcePath: filePath, planFile: rel(f) });
81
- }
82
- }
83
- return result;
69
+ return parseCodeBlocks(content).map(b => ({ sourcePath: b.path, planFile: rel(f) }));
84
70
  }
85
71
 
86
72
  async function main() {
@@ -136,15 +122,15 @@ async function main() {
136
122
  // import-graph.json removed — @import was never a Claude Code feature
137
123
 
138
124
  // ─── sync-map.json ─────────────────────────────────────
139
- const CODE_BLOCK_PLANS = ["21.sync-rules-master.md"];
125
+ // CODE_BLOCK_PLANS imported from lib/plan-parser.js
140
126
  const sm = { generatedAt: new Date().toISOString(), mappings: [] };
141
127
  if (fs.existsSync(DIRS.plan)) {
142
128
  for (const p of await glob("*.md", { cwd: DIRS.plan, absolute: true })) {
143
129
  const bn = path.basename(p);
144
130
  if (CODE_BLOCK_PLANS.includes(bn)) {
145
- sm.mappings.push(...extractCodeBlockPaths(p));
131
+ sm.mappings.push(...extractCodeBlockPathsFromFile(p));
146
132
  } else {
147
- sm.mappings.push(...extractFileBlocks(p));
133
+ sm.mappings.push(...extractFileBlocksFromFile(p));
148
134
  }
149
135
  }
150
136
  }
@@ -158,7 +144,7 @@ async function main() {
158
144
  for (const p of await glob("*.md", { cwd: DIRS.plan, absolute: true })) {
159
145
  const r = rel(p);
160
146
  const s = stat(p);
161
- const blocks = extractFileBlocks(p);
147
+ const blocks = extractFileBlocksFromFile(p);
162
148
  pm.plans.push({ path: r, ...s, fileBlocks: blocks.length, status: "ok" });
163
149
  }
164
150
  }
@@ -166,16 +152,7 @@ async function main() {
166
152
  console.log(` ✅ plan-manifest.json — ${pm.plans.length} plans`);
167
153
 
168
154
  // ─── Initialize stale-report.json (preserve existing sub-tool results) ──
169
- const srPath = path.join(GEN, "stale-report.json");
170
- let sr = {};
171
- if (fs.existsSync(srPath)) {
172
- try { sr = JSON.parse(fs.readFileSync(srPath, "utf-8")); } catch { sr = {}; }
173
- }
174
- sr.generatedAt = new Date().toISOString();
175
- if (!sr.summary) sr.summary = {};
176
- sr.summary.totalIssues = 0;
177
- sr.summary.status = "initial";
178
- fs.writeFileSync(srPath, JSON.stringify(sr, null, 2));
155
+ updateStaleReport(GEN, "generatedAt", new Date().toISOString(), { totalIssues: 0, status: "initial" });
179
156
  console.log(" ✅ stale-report.json — initialized");
180
157
  console.log("\n 📁 Output: claudeos-core/generated/ (4 files)\n");
181
158
  }
package/package.json CHANGED
@@ -1,87 +1,87 @@
1
- {
2
- "name": "claudeos-core",
3
- "version": "1.5.0",
4
- "description": "Auto-generate Claude Code documentation from your actual source code — Standards, Rules, Skills, and Guides tailored to your project",
5
- "main": "bin/cli.js",
6
- "bin": {
7
- "claudeos-core": "bin/cli.js"
8
- },
9
- "files": [
10
- "bin/",
11
- "lib/",
12
- "content-validator/",
13
- "health-checker/",
14
- "manifest-generator/",
15
- "pass-json-validator/",
16
- "pass-prompts/",
17
- "plan-installer/",
18
- "plan-validator/",
19
- "sync-checker/",
20
- "bootstrap.sh",
21
- "README.md",
22
- "README.ko.md",
23
- "LICENSE",
24
- "CHANGELOG.md",
25
- "CONTRIBUTING.md",
26
- "README.zh-CN.md",
27
- "README.ja.md",
28
- "README.es.md",
29
- "README.vi.md",
30
- "README.hi.md",
31
- "README.ru.md",
32
- "README.fr.md",
33
- "README.de.md"
34
- ],
35
- "scripts": {
36
- "init": "node bin/cli.js init",
37
- "health": "node bin/cli.js health",
38
- "validate": "node bin/cli.js validate",
39
- "refresh": "node bin/cli.js refresh",
40
- "restore": "node bin/cli.js restore",
41
- "test": "node --test tests/*.test.js",
42
- "test:health": "node health-checker/index.js"
43
- },
44
- "keywords": [
45
- "claude-code",
46
- "automation",
47
- "code-analysis",
48
- "CLAUDE.md",
49
- "standards",
50
- "rules",
51
- "skills",
52
- "scaffolding",
53
- "i18n",
54
- "multi-language",
55
- "spring-boot",
56
- "kotlin",
57
- "exposed",
58
- "jooq",
59
- "cqrs",
60
- "bff",
61
- "multi-module",
62
- "monorepo",
63
- "nextjs",
64
- "express",
65
- "fastify",
66
- "angular",
67
- "django",
68
- "fastapi"
69
- ],
70
- "author": "claudeos-core <claudeoscore@gmail.com> (https://github.com/claudeos-core)",
71
- "license": "ISC",
72
- "repository": {
73
- "type": "git",
74
- "url": "git+https://github.com/claudeos-core/claudeos-core.git"
75
- },
76
- "homepage": "https://github.com/claudeos-core/claudeos-core#readme",
77
- "bugs": {
78
- "url": "https://github.com/claudeos-core/claudeos-core/issues"
79
- },
80
- "engines": {
81
- "node": ">=18.0.0"
82
- },
83
- "dependencies": {
84
- "glob": "^13.0.6",
85
- "gray-matter": "^4.0.3"
86
- }
87
- }
1
+ {
2
+ "name": "claudeos-core",
3
+ "version": "1.6.0",
4
+ "description": "Auto-generate Claude Code documentation from your actual source code — Standards, Rules, Skills, and Guides tailored to your project",
5
+ "main": "bin/cli.js",
6
+ "bin": {
7
+ "claudeos-core": "bin/cli.js"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "lib/",
12
+ "content-validator/",
13
+ "health-checker/",
14
+ "manifest-generator/",
15
+ "pass-json-validator/",
16
+ "pass-prompts/",
17
+ "plan-installer/",
18
+ "plan-validator/",
19
+ "sync-checker/",
20
+ "bootstrap.sh",
21
+ "README.md",
22
+ "README.ko.md",
23
+ "LICENSE",
24
+ "CHANGELOG.md",
25
+ "CONTRIBUTING.md",
26
+ "README.zh-CN.md",
27
+ "README.ja.md",
28
+ "README.es.md",
29
+ "README.vi.md",
30
+ "README.hi.md",
31
+ "README.ru.md",
32
+ "README.fr.md",
33
+ "README.de.md"
34
+ ],
35
+ "scripts": {
36
+ "init": "node bin/cli.js init",
37
+ "health": "node bin/cli.js health",
38
+ "validate": "node bin/cli.js validate",
39
+ "refresh": "node bin/cli.js refresh",
40
+ "restore": "node bin/cli.js restore",
41
+ "test": "node --test tests/*.test.js",
42
+ "test:health": "node health-checker/index.js"
43
+ },
44
+ "keywords": [
45
+ "claude-code",
46
+ "automation",
47
+ "code-analysis",
48
+ "CLAUDE.md",
49
+ "standards",
50
+ "rules",
51
+ "skills",
52
+ "scaffolding",
53
+ "i18n",
54
+ "multi-language",
55
+ "spring-boot",
56
+ "kotlin",
57
+ "exposed",
58
+ "jooq",
59
+ "cqrs",
60
+ "bff",
61
+ "multi-module",
62
+ "monorepo",
63
+ "nextjs",
64
+ "express",
65
+ "fastify",
66
+ "angular",
67
+ "django",
68
+ "fastapi"
69
+ ],
70
+ "author": "claudeos-core <claudeoscore@gmail.com> (https://github.com/claudeos-core)",
71
+ "license": "ISC",
72
+ "repository": {
73
+ "type": "git",
74
+ "url": "git+https://github.com/claudeos-core/claudeos-core.git"
75
+ },
76
+ "homepage": "https://github.com/claudeos-core/claudeos-core#readme",
77
+ "bugs": {
78
+ "url": "https://github.com/claudeos-core/claudeos-core/issues"
79
+ },
80
+ "engines": {
81
+ "node": ">=18.0.0"
82
+ },
83
+ "dependencies": {
84
+ "glob": "^13.0.6",
85
+ "gray-matter": "^4.0.3"
86
+ }
87
+ }
@@ -17,6 +17,7 @@
17
17
  const fs = require("fs");
18
18
  const path = require("path");
19
19
  const { glob } = require("glob");
20
+ const { updateStaleReport } = require("../lib/stale-report");
20
21
 
21
22
  const ROOT = process.env.CLAUDEOS_ROOT || path.resolve(__dirname, "../..");
22
23
  const GEN_DIR = path.join(ROOT, "claudeos-core/generated");
@@ -197,7 +198,7 @@ async function main() {
197
198
  isBackend = !frontend || ["express", "nestjs", "django", "fastapi", "spring-boot"].includes(framework);
198
199
  isKotlin = language === "kotlin";
199
200
  isKotlinCqrs = isKotlin && (architecture === "cqrs" || paData.stack?.multiModule);
200
- } catch { /* If project-analysis parsing fails, conservatively assume backend */ }
201
+ } catch (_e) { /* If project-analysis parsing fails, conservatively assume backend */ }
201
202
  }
202
203
 
203
204
  const sectionsToCheck = [
@@ -282,23 +283,17 @@ async function main() {
282
283
  }
283
284
 
284
285
  // Record in stale-report
285
- if (fs.existsSync(GEN_DIR)) {
286
- const rp = path.join(GEN_DIR, "stale-report.json");
287
- let ex = {};
288
- if (fs.existsSync(rp)) {
289
- try { ex = JSON.parse(fs.readFileSync(rp, "utf-8")); } catch { ex = {}; }
290
- }
291
- ex.jsonValidation = { checkedAt: new Date().toISOString(), checked, errors: errors.length, warnings: warnings.length };
292
- ex.summary = { ...ex.summary, jsonErrors: errors.length, jsonWarnings: warnings.length };
293
- fs.writeFileSync(rp, JSON.stringify(ex, null, 2));
294
- }
286
+ updateStaleReport(GEN_DIR, "jsonValidation",
287
+ { checkedAt: new Date().toISOString(), checked, errors: errors.length, warnings: warnings.length },
288
+ { jsonErrors: errors.length, jsonWarnings: warnings.length }
289
+ );
295
290
 
296
291
  console.log(` Total: ${errors.length} errors, ${warnings.length} warnings\n`);
297
292
  process.exit(errors.length > 0 ? 1 : 0);
298
293
  }
299
294
 
300
295
  if (require.main === module) {
301
- main().catch(console.error);
296
+ main().catch(e => { console.error(`\n ❌ Unexpected error: ${e.message || e}`); process.exit(1); });
302
297
  }
303
298
 
304
299
  module.exports = { main };
@@ -0,0 +1,132 @@
1
+ Read claudeos-core/generated/project-analysis.json and
2
+ perform a deep analysis of the following domains only: {{DOMAIN_GROUP}}
3
+
4
+ For each domain, select one representative file per layer, read its code, and analyze it.
5
+ Prioritize files with the richest patterns.
6
+
7
+ Analysis items (per domain):
8
+
9
+ 1. Module & Controller Patterns
10
+ - @Module() structure (imports, controllers, providers, exports)
11
+ - @Controller() decorator, route prefix conventions
12
+ - @Get/@Post/@Put/@Patch/@Delete decorators, parameter decorators (@Body, @Param, @Query, @Headers)
13
+ - Response handling (@Res() vs return value, interceptors, class-transformer serialization)
14
+ - If a custom response wrapper/interceptor exists, record its EXACT class name, method signatures, and import path
15
+ - **Response wrapping layer (CRITICAL)**: Which layer ACTUALLY calls the response wrapper?
16
+ Does Controller call it directly, or does a Service/UseCase layer return the wrapped response?
17
+ Record EXACTLY: "Controller wraps response" or "Service wraps response"
18
+ - If a dedicated orchestration layer exists between Controller and Service (e.g., UseCase, Facade, Aggregator),
19
+ record its name, responsibilities, and return type
20
+ - Error handling (HttpException hierarchy, ExceptionFilter, @Catch())
21
+ - @UseGuards() for authentication (JwtAuthGuard, RolesGuard, custom guards)
22
+ - API documentation (@ApiTags, @ApiOperation, @ApiResponse, @ApiBearerAuth)
23
+ - Pagination patterns (offset/limit, cursor, custom)
24
+ - @Version() API versioning
25
+
26
+ 2. Provider & Service Patterns
27
+ - @Injectable() and dependency injection (constructor injection, custom providers, useFactory/useClass/useValue)
28
+ - Module scoping (DEFAULT, REQUEST, TRANSIENT)
29
+ - Transaction strategy (Prisma.$transaction, TypeORM QueryRunner, Sequelize.transaction)
30
+ - Business exception handling (custom exception hierarchy extending HttpException)
31
+ - Validation (@UsePipes, ValidationPipe, class-validator decorators)
32
+ - Event handling (@OnEvent, EventEmitter2)
33
+ - CQRS pattern usage (@nestjs/cqrs CommandBus/QueryBus/EventBus)
34
+
35
+ 3. Data Access Patterns
36
+ - ORM/query builder (Prisma, TypeORM, Sequelize, MikroORM, Mongoose)
37
+ - Repository pattern (@InjectRepository, custom repository classes)
38
+ - Query optimization (relations/eager/lazy loading, N+1 prevention)
39
+ - Migration tools (Prisma Migrate, TypeORM Migration)
40
+ - Seed data management
41
+ - Connection management (TypeOrmModule.forRootAsync, PrismaModule)
42
+
43
+ 4. DTO & Validation Patterns
44
+ - class-validator decorators (@IsString, @IsNotEmpty, @IsEmail, @ValidateNested)
45
+ - class-transformer decorators (@Expose, @Exclude, @Type, @Transform)
46
+ - Request/Response DTO separation
47
+ - Mapped types (PartialType, PickType, OmitType, IntersectionType)
48
+ - Custom validation decorators
49
+ - Enum/constants management
50
+ - File entry pattern: is the main file `index.ts` or named by module (e.g., `users.controller.ts`)? Record exact convention
51
+ - Import paths: record EXACT path aliases and import patterns (e.g., `@/modules/`, `@app/`, relative paths)
52
+
53
+ 5. Middleware, Guard, Pipe, Interceptor Patterns
54
+ - @Injectable() middleware (NestMiddleware) vs Express-style middleware
55
+ - Guards (@CanActivate) — authentication, authorization, role-based
56
+ - Pipes (ValidationPipe, ParseIntPipe, custom pipes)
57
+ - Interceptors (logging, caching, timeout, response transformation)
58
+ - Execution order (middleware → guard → interceptor(pre) → pipe → handler → interceptor(post) → filter)
59
+
60
+ 6. Configuration & Environment Patterns
61
+ - @nestjs/config (ConfigModule, ConfigService, registerAs)
62
+ - Environment validation (Joi schema, class-validator)
63
+ - Per-environment branching (development/staging/production)
64
+ - Custom configuration namespaces
65
+
66
+ 7. Logging Patterns
67
+ - NestJS Logger vs external (winston, pino, nestjs-pino)
68
+ - Log level policy
69
+ - Structured logging (JSON format, correlation ID)
70
+ - Request/response logging (LoggingInterceptor)
71
+
72
+ 8. Testing Patterns
73
+ - Test framework (Jest, Vitest)
74
+ - Test.createTestingModule() usage
75
+ - Mocking strategy (jest.mock, overrideProvider, custom TestModule)
76
+ - E2E testing (supertest, @nestjs/testing)
77
+ - Test data management (Factory, Fixture, Faker)
78
+ - DB test strategy (in-memory, test container, separate DB)
79
+
80
+ 9. Domain-Specific Patterns
81
+ - File upload (@UseInterceptors(FileInterceptor), Multer, S3)
82
+ - WebSocket (@WebSocketGateway, Socket.io)
83
+ - Queue/job processing (@nestjs/bull, BullMQ)
84
+ - External API integration (HttpModule/HttpService, Axios)
85
+ - Caching (@nestjs/cache-manager, Redis, @CacheKey, @CacheTTL)
86
+ - Microservices (@nestjs/microservices, Transport)
87
+ - Scheduling (@nestjs/schedule, @Cron, @Interval)
88
+ - Health checks (@nestjs/terminus)
89
+
90
+ 10. Anti-patterns / Inconsistencies
91
+ - Mixing NestJS patterns with raw Express patterns
92
+ - Business logic in controllers (should be in services)
93
+ - Circular dependencies
94
+ - Missing @Injectable() on providers
95
+ - Type safety issues (any abuse, missing types)
96
+
97
+ Do not create or modify source files. Analysis only.
98
+ Save results to claudeos-core/generated/pass1-{{PASS_NUM}}.json in the following format:
99
+
100
+ {
101
+ "analyzedAt": "ISO timestamp",
102
+ "passNum": {{PASS_NUM}},
103
+ "domains": ["users", "auth", "orders", "products"],
104
+ "analysisPerDomain": {
105
+ "users": {
106
+ "representativeFiles": {
107
+ "module": "users.module.ts",
108
+ "controller": "users.controller.ts",
109
+ "service": "users.service.ts",
110
+ "repository": "users.repository.ts",
111
+ "dto": "create-user.dto.ts"
112
+ },
113
+ "patterns": {
114
+ "module": { ... },
115
+ "controller": { ... },
116
+ "service": { ... },
117
+ "dataAccess": { ... },
118
+ "dto": { ... },
119
+ "middleware": { ... },
120
+ "config": { ... },
121
+ "logging": { ... },
122
+ "testing": { ... }
123
+ },
124
+ "specialPatterns": [],
125
+ "antiPatterns": []
126
+ }
127
+ },
128
+ "crossDomainCommon": {
129
+ "description": "Patterns commonly used across domains in this group",
130
+ "patterns": []
131
+ }
132
+ }