claudeos-core 1.2.3 → 1.3.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.

Potentially problematic release.


This version of claudeos-core might be problematic. Click here for more details.

Files changed (44) hide show
  1. package/CHANGELOG.md +66 -1
  2. package/README.de.md +41 -6
  3. package/README.es.md +42 -6
  4. package/README.fr.md +42 -6
  5. package/README.hi.md +42 -6
  6. package/README.ja.md +43 -6
  7. package/README.ko.md +42 -6
  8. package/README.md +53 -11
  9. package/README.ru.md +42 -6
  10. package/README.vi.md +42 -6
  11. package/README.zh-CN.md +42 -6
  12. package/bin/cli.js +171 -36
  13. package/bootstrap.sh +72 -23
  14. package/content-validator/index.js +9 -4
  15. package/health-checker/index.js +4 -3
  16. package/lib/safe-fs.js +110 -0
  17. package/manifest-generator/index.js +16 -20
  18. package/package.json +4 -2
  19. package/pass-json-validator/index.js +3 -5
  20. package/pass-prompts/templates/java-spring/pass1.md +3 -0
  21. package/pass-prompts/templates/java-spring/pass2.md +3 -3
  22. package/pass-prompts/templates/java-spring/pass3.md +17 -0
  23. package/pass-prompts/templates/kotlin-spring/pass1.md +3 -0
  24. package/pass-prompts/templates/kotlin-spring/pass2.md +5 -5
  25. package/pass-prompts/templates/kotlin-spring/pass3.md +17 -0
  26. package/pass-prompts/templates/node-express/pass1.md +3 -0
  27. package/pass-prompts/templates/node-express/pass2.md +4 -1
  28. package/pass-prompts/templates/node-express/pass3.md +20 -1
  29. package/pass-prompts/templates/node-nextjs/pass1.md +13 -3
  30. package/pass-prompts/templates/node-nextjs/pass2.md +6 -4
  31. package/pass-prompts/templates/node-nextjs/pass3.md +20 -1
  32. package/pass-prompts/templates/python-django/pass1.md +3 -1
  33. package/pass-prompts/templates/python-django/pass2.md +4 -4
  34. package/pass-prompts/templates/python-django/pass3.md +18 -0
  35. package/pass-prompts/templates/python-fastapi/pass1.md +3 -0
  36. package/pass-prompts/templates/python-fastapi/pass2.md +4 -4
  37. package/pass-prompts/templates/python-fastapi/pass3.md +18 -0
  38. package/plan-installer/domain-grouper.js +74 -0
  39. package/plan-installer/index.js +43 -1303
  40. package/plan-installer/prompt-generator.js +99 -0
  41. package/plan-installer/stack-detector.js +326 -0
  42. package/plan-installer/structure-scanner.js +783 -0
  43. package/plan-validator/index.js +84 -20
  44. package/sync-checker/index.js +7 -3
package/bootstrap.sh CHANGED
@@ -23,6 +23,9 @@ GENERATED_DIR="$PROJECT_ROOT/claudeos-core/generated"
23
23
 
24
24
  cd "$PROJECT_ROOT"
25
25
 
26
+ # Cleanup temp files on exit (Ctrl+C, errors, etc.)
27
+ trap 'rm -f "$GENERATED_DIR"/_tmp_*.md "$GENERATED_DIR"/_tmp_*.md.final 2>/dev/null' EXIT
28
+
26
29
  # ─── Language selection (required) ──────────────────────────────
27
30
  SUPPORTED_LANGS=("en" "ko" "zh-CN" "ja" "es" "vi" "hi" "ru" "fr" "de")
28
31
  LANG_LABELS=("English" "한국어 (Korean)" "简体中文 (Chinese Simplified)" "日本語 (Japanese)" "Español (Spanish)" "Tiếng Việt (Vietnamese)" "हिन्दी (Hindi)" "Русский (Russian)" "Français (French)" "Deutsch (German)")
@@ -32,7 +35,7 @@ CLAUDEOS_LANG=""
32
35
  # Parse --lang argument
33
36
  while [[ $# -gt 0 ]]; do
34
37
  case $1 in
35
- --lang) CLAUDEOS_LANG="$2"; shift 2 ;;
38
+ --lang) [ -z "$2" ] && echo " ❌ --lang requires a value" && exit 1; CLAUDEOS_LANG="$2"; shift 2 ;;
36
39
  --lang=*) CLAUDEOS_LANG="${1#*=}"; shift ;;
37
40
  *) echo "⚠️ Unknown argument: $1 (ignored)"; shift ;;
38
41
  esac
@@ -42,17 +45,21 @@ done
42
45
  if [ -z "$CLAUDEOS_LANG" ]; then
43
46
  echo ""
44
47
  echo "╔══════════════════════════════════════════════════╗"
45
- echo "║ Select output language (required) ║"
48
+ echo "║ Select generated document language (required) ║"
46
49
  echo "╚══════════════════════════════════════════════════╝"
47
50
  echo ""
51
+ echo " Generated files (CLAUDE.md, Standards, Rules,"
52
+ echo " Skills, Guides) will be written in this language."
53
+ echo ""
48
54
  for i in "${!SUPPORTED_LANGS[@]}"; do
49
55
  printf " %2d. %-6s — %s\n" "$((i+1))" "${SUPPORTED_LANGS[$i]}" "${LANG_LABELS[$i]}"
50
56
  done
51
57
  echo ""
52
- read -p " Enter number (1-10) or language code: " LANG_INPUT
58
+ LANG_COUNT=${#SUPPORTED_LANGS[@]}
59
+ read -rp " Enter number (1-${LANG_COUNT}) or language code: " LANG_INPUT
53
60
 
54
61
  # Accept number
55
- if [[ "$LANG_INPUT" =~ ^[0-9]+$ ]] && [ "$LANG_INPUT" -ge 1 ] && [ "$LANG_INPUT" -le 10 ]; then
62
+ if [[ "$LANG_INPUT" =~ ^[0-9]+$ ]] && [ "$LANG_INPUT" -ge 1 ] && [ "$LANG_INPUT" -le "$LANG_COUNT" ]; then
56
63
  CLAUDEOS_LANG="${SUPPORTED_LANGS[$((LANG_INPUT-1))]}"
57
64
  else
58
65
  # Accept language code
@@ -74,13 +81,44 @@ if [ "$VALID" = false ]; then
74
81
  fi
75
82
 
76
83
  export CLAUDEOS_LANG
84
+ export CLAUDEOS_ROOT="$PROJECT_ROOT"
85
+
86
+ # ─── Prerequisites check ──────────────────────────────────────
87
+ if ! command -v node &> /dev/null; then
88
+ echo ""
89
+ echo " ❌ Node.js not found."
90
+ echo " Install: https://nodejs.org/"
91
+ echo ""
92
+ exit 1
93
+ fi
94
+
95
+ NODE_MAJOR=$(node -e "console.log(process.versions.node.split('.')[0])")
96
+ if ! [[ "$NODE_MAJOR" =~ ^[0-9]+$ ]] || [ "$NODE_MAJOR" -lt 18 ]; then
97
+ echo ""
98
+ echo " ❌ Node.js v18+ required (current: v$(node --version))"
99
+ echo " Install: https://nodejs.org/"
100
+ echo ""
101
+ exit 1
102
+ fi
103
+
104
+ if ! command -v claude &> /dev/null; then
105
+ echo ""
106
+ echo " ❌ Claude Code CLI not found."
107
+ echo " Install: https://code.claude.com/docs/en/overview"
108
+ echo " Then run: claude (and complete authentication)"
109
+ echo ""
110
+ exit 1
111
+ fi
112
+
113
+ if ! command -v perl &> /dev/null; then
114
+ echo ""
115
+ echo " ❌ perl not found (required for placeholder substitution)."
116
+ echo " Install perl or use the Node.js CLI instead: npx claudeos-core init"
117
+ echo ""
118
+ exit 1
119
+ fi
120
+
77
121
 
78
- # ─── Prompt placeholder substitution helper ────────────────────
79
- inject_project_root() {
80
- # Use perl with $ENV{} to avoid sed metachar issues with &, \, etc. in paths
81
- export _PROJECT_ROOT="$PROJECT_ROOT"
82
- perl -pe 's/\{\{PROJECT_ROOT\}\}/$ENV{_PROJECT_ROOT}/g'
83
- }
84
122
 
85
123
  echo ""
86
124
  echo "╔════════════════════════════════════════════════════╗"
@@ -175,24 +213,25 @@ for i in $(seq 1 "$TOTAL_GROUPS"); do
175
213
  if [ ! -f "$PROMPT_FILE" ]; then
176
214
  PROMPT_FILE="$GENERATED_DIR/pass1-prompt.md"
177
215
  fi
178
- PASS1_TEMPLATE=$(cat "$PROMPT_FILE")
179
-
180
- # Substitute placeholders via temp file (avoids sed special char issues with &, \, etc.)
216
+ # Substitute placeholders via temp file (avoids sed special char issues and $() newline stripping)
181
217
  TMP_PROMPT="$GENERATED_DIR/_tmp_pass1_prompt.md"
182
- printf '%s' "$PASS1_TEMPLATE" > "$TMP_PROMPT"
218
+ cp "$PROMPT_FILE" "$TMP_PROMPT"
183
219
  # Use perl with $ENV{} for safe literal replacement (no shell interpolation into Perl code)
184
220
  export _DOMAIN_LIST="$DOMAIN_LIST"
185
221
  export _PASS_NUM="$i"
186
222
  perl -pi -e 's/\{\{DOMAIN_GROUP\}\}/$ENV{_DOMAIN_LIST}/g' "$TMP_PROMPT"
187
223
  perl -pi -e 's/\{\{PASS_NUM\}\}/$ENV{_PASS_NUM}/g' "$TMP_PROMPT"
188
- # inject_project_root uses perl with $ENV{} which is safe for special chars in paths
189
- PASS1_PROMPT=$(cat "$TMP_PROMPT" | inject_project_root)
190
- rm -f "$TMP_PROMPT"
224
+ # inject_project_root: pipe through perl, write to final temp file
225
+ export _PROJECT_ROOT="$PROJECT_ROOT"
226
+ perl -pe 's/\{\{PROJECT_ROOT\}\}/$ENV{_PROJECT_ROOT}/g' "$TMP_PROMPT" > "${TMP_PROMPT}.final"
227
+ mv "${TMP_PROMPT}.final" "$TMP_PROMPT"
191
228
 
192
- if ! (cd "$PROJECT_ROOT" && claude -p "$PASS1_PROMPT" --dangerously-skip-permissions); then
229
+ if ! (cd "$PROJECT_ROOT" && cat "$TMP_PROMPT" | claude -p --dangerously-skip-permissions); then
230
+ rm -f "$TMP_PROMPT"
193
231
  echo " ❌ Pass 1-${i} failed. Aborting."
194
232
  exit 1
195
233
  fi
234
+ rm -f "$TMP_PROMPT"
196
235
 
197
236
  # Verify JSON was created
198
237
  if [ ! -f "$GENERATED_DIR/pass1-${i}.json" ]; then
@@ -202,6 +241,7 @@ for i in $(seq 1 "$TOTAL_GROUPS"); do
202
241
 
203
242
  echo " ✅ pass1-${i}.json created"
204
243
  done
244
+ unset _DOMAIN_LIST _PASS_NUM _PROJECT_ROOT
205
245
  echo ""
206
246
 
207
247
  # ─── [5] Pass 2: Merge analysis results ─────────────────────────
@@ -212,12 +252,16 @@ echo "━━━━━━━━━━━━━━━━━━━━━━━━
212
252
  if [ -f "$GENERATED_DIR/pass2-merged.json" ]; then
213
253
  echo " ⏭️ pass2-merged.json already exists, skipping"
214
254
  else
215
- PASS2_PROMPT=$(cat "$GENERATED_DIR/pass2-prompt.md" | inject_project_root)
255
+ TMP_PASS2="$GENERATED_DIR/_tmp_pass2_prompt.md"
256
+ export _PROJECT_ROOT="$PROJECT_ROOT"
257
+ perl -pe 's/\{\{PROJECT_ROOT\}\}/$ENV{_PROJECT_ROOT}/g' "$GENERATED_DIR/pass2-prompt.md" > "$TMP_PASS2"
216
258
 
217
- if ! (cd "$PROJECT_ROOT" && claude -p "$PASS2_PROMPT" --dangerously-skip-permissions); then
259
+ if ! (cd "$PROJECT_ROOT" && cat "$TMP_PASS2" | claude -p --dangerously-skip-permissions); then
260
+ rm -f "$TMP_PASS2"
218
261
  echo " ❌ Pass 2 failed. Aborting."
219
262
  exit 1
220
263
  fi
264
+ rm -f "$TMP_PASS2"
221
265
 
222
266
  if [ ! -f "$GENERATED_DIR/pass2-merged.json" ]; then
223
267
  echo " ❌ pass2-merged.json was not created. Aborting."
@@ -232,17 +276,22 @@ echo ""
232
276
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
233
277
  echo "[6] Pass 3 — Generating all files..."
234
278
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
235
- PASS3_PROMPT=$(cat "$GENERATED_DIR/pass3-prompt.md" | inject_project_root)
279
+ TMP_PASS3="$GENERATED_DIR/_tmp_pass3_prompt.md"
280
+ export _PROJECT_ROOT="$PROJECT_ROOT"
281
+ perl -pe 's/\{\{PROJECT_ROOT\}\}/$ENV{_PROJECT_ROOT}/g' "$GENERATED_DIR/pass3-prompt.md" > "$TMP_PASS3"
236
282
 
237
- if ! (cd "$PROJECT_ROOT" && claude -p "$PASS3_PROMPT" --dangerously-skip-permissions); then
283
+ if ! (cd "$PROJECT_ROOT" && cat "$TMP_PASS3" | claude -p --dangerously-skip-permissions); then
284
+ rm -f "$TMP_PASS3"
238
285
  echo " ❌ Pass 3 failed. Aborting."
239
286
  exit 1
240
287
  fi
288
+ rm -f "$TMP_PASS3"
241
289
 
242
290
  if [ ! -f "$PROJECT_ROOT/CLAUDE.md" ]; then
243
291
  echo " ❌ CLAUDE.md was not created. Pass 3 may have failed silently."
244
292
  exit 1
245
293
  fi
294
+ unset _PROJECT_ROOT
246
295
  echo ""
247
296
 
248
297
  # ─── [7] Run verification tools ───────────────────────────────
@@ -270,7 +319,7 @@ fi
270
319
  echo ""
271
320
 
272
321
  # ─── Complete ───────────────────────────────────────────────
273
- TOTAL_FILES=$(find .claude claudeos-core -type f 2>/dev/null | grep -v node_modules | wc -l | tr -d ' ')
322
+ TOTAL_FILES=$(find .claude claudeos-core -type f 2>/dev/null | grep -v '/node_modules/' | grep -v '/generated/' | wc -l | tr -d ' ')
274
323
  TOTAL_GROUPS_DONE=$TOTAL_GROUPS
275
324
  PASS1_FILES=$(ls -1 "$GENERATED_DIR"/pass1-*.json 2>/dev/null | wc -l | tr -d ' ')
276
325
 
@@ -33,9 +33,9 @@ const GEN_DIR = path.join(ROOT, "claudeos-core/generated");
33
33
  function rel(p) { return path.relative(ROOT, p).replace(/\\/g, "/"); }
34
34
 
35
35
  async function main() {
36
- console.log("\n╔══════════════════════════════════════╗");
36
+ console.log("\n╔═══════════════════════════════════════╗");
37
37
  console.log("║ ClaudeOS-Core — Content Validator ║");
38
- console.log("╚══════════════════════════════════════╝\n");
38
+ console.log("╚═══════════════════════════════════════╝\n");
39
39
 
40
40
  const errors = [];
41
41
  const warnings = [];
@@ -83,7 +83,10 @@ async function main() {
83
83
  const enKeywords = SECTION_KEYWORDS.en;
84
84
  for (let i = 0; i < enKeywords.length; i++) {
85
85
  const candidates = [enKeywords[i], langKeywords[i]].filter(Boolean);
86
- const found = candidates.some(kw => content.toLowerCase().includes(kw.toLowerCase()));
86
+ const found = candidates.some(kw => {
87
+ const re = new RegExp(`(^|#|\\s)${kw.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`, "im");
88
+ return re.test(content);
89
+ });
87
90
  if (!found) {
88
91
  warnings.push({ file: "CLAUDE.md", type: "MISSING_SECTION", msg: `'${enKeywords[i]}' / '${langKeywords[i]}' section is missing` });
89
92
  }
@@ -164,7 +167,9 @@ async function main() {
164
167
  if (!badKeywords.some(kw => c.includes(kw))) {
165
168
  warnings.push({ file: r, type: "NO_BAD_EXAMPLE", msg: "No incorrect example (❌) found" });
166
169
  }
167
- if (!c.includes("|") && !c.includes("rule") && !c.includes("Rule") && !c.includes("table")) {
170
+ // Check for markdown table: at least one line with | col | col | pattern
171
+ const hasMarkdownTable = /\|.+\|.+\|/.test(c);
172
+ if (!hasMarkdownTable) {
168
173
  warnings.push({ file: r, type: "NO_TABLE", msg: "Rules summary table appears to be missing" });
169
174
  }
170
175
  // Kotlin code block check: core and backend standard files should contain ```kotlin blocks
@@ -36,9 +36,9 @@ function run(name, script) {
36
36
  }
37
37
 
38
38
  function main() {
39
- console.log("\n╔══════════════════════════════════════╗");
39
+ console.log("\n╔═══════════════════════════════════════╗");
40
40
  console.log("║ ClaudeOS-Core — Health Checker ║");
41
- console.log("╚══════════════════════════════════════╝\n");
41
+ console.log("╚═══════════════════════════════════════╝\n");
42
42
 
43
43
  // ─── [0] Run manifest-generator first (prerequisite) ──────────────────
44
44
  // Must run first because sync-checker reads sync-map.json
@@ -112,10 +112,11 @@ function main() {
112
112
  }
113
113
  ex.generatedAt = new Date().toISOString();
114
114
  ex.healthCheck = { results, status: hasErr ? "fail" : "pass" };
115
+ if (!ex.summary) ex.summary = {};
115
116
  ex.summary = {
116
117
  ...ex.summary,
117
118
  totalIssues: results.filter((r) => r.status === "fail").length,
118
- status: hasErr ? "fail" : "ok",
119
+ healthStatus: hasErr ? "fail" : "ok",
119
120
  };
120
121
  fs.writeFileSync(rp, JSON.stringify(ex, null, 2));
121
122
  }
package/lib/safe-fs.js ADDED
@@ -0,0 +1,110 @@
1
+ /**
2
+ * ClaudeOS-Core — Safe filesystem utilities
3
+ *
4
+ * Wraps fs operations with consistent error handling.
5
+ * All read functions return a fallback value on failure instead of throwing.
6
+ */
7
+
8
+ const fs = require("fs");
9
+ const path = require("path");
10
+
11
+ /**
12
+ * Safely read a file as UTF-8 string.
13
+ * @param {string} filePath
14
+ * @param {string} [fallback=""] - returned on error
15
+ * @returns {string}
16
+ */
17
+ function readFileSafe(filePath, fallback = "") {
18
+ try {
19
+ return fs.readFileSync(filePath, "utf-8");
20
+ } catch (e) {
21
+ if (e.code !== "ENOENT") {
22
+ console.warn(` ⚠️ Cannot read ${path.basename(filePath)}: ${e.code || e.message}`);
23
+ }
24
+ return fallback;
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Safely parse a JSON file.
30
+ * @param {string} filePath
31
+ * @param {*} [fallback=null] - returned on error
32
+ * @returns {*}
33
+ */
34
+ function readJsonSafe(filePath, fallback = null) {
35
+ const raw = readFileSafe(filePath, null);
36
+ if (raw === null) return fallback;
37
+ try {
38
+ return JSON.parse(raw);
39
+ } catch (e) {
40
+ console.warn(` ⚠️ JSON parse error in ${path.basename(filePath)}: ${e.message}`);
41
+ return fallback;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Check if a file exists (swallows permission errors).
47
+ * @param {string} filePath
48
+ * @returns {boolean}
49
+ */
50
+ function existsSafe(filePath) {
51
+ try {
52
+ return fs.existsSync(filePath);
53
+ } catch {
54
+ return false;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Ensure a directory exists (recursive).
60
+ * @param {string} dir
61
+ */
62
+ function ensureDir(dir) {
63
+ if (!fs.existsSync(dir)) {
64
+ fs.mkdirSync(dir, { recursive: true });
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Write a file with error reporting.
70
+ * @param {string} filePath
71
+ * @param {string} content
72
+ * @returns {boolean} success
73
+ */
74
+ function writeFileSafe(filePath, content) {
75
+ try {
76
+ fs.writeFileSync(filePath, content);
77
+ return true;
78
+ } catch (e) {
79
+ console.error(` ❌ Cannot write ${path.basename(filePath)}: ${e.code || e.message}`);
80
+ return false;
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Get file stat safely.
86
+ * @param {string} filePath
87
+ * @returns {{ lines: number, bytes: number, modified: string } | null}
88
+ */
89
+ function statSafe(filePath) {
90
+ try {
91
+ const c = fs.readFileSync(filePath, "utf-8");
92
+ const s = fs.statSync(filePath);
93
+ return {
94
+ lines: c.split("\n").length,
95
+ bytes: s.size,
96
+ modified: s.mtime.toISOString().split("T")[0],
97
+ };
98
+ } catch {
99
+ return null;
100
+ }
101
+ }
102
+
103
+ module.exports = {
104
+ readFileSafe,
105
+ readJsonSafe,
106
+ existsSafe,
107
+ ensureDir,
108
+ writeFileSafe,
109
+ statSafe,
110
+ };
@@ -3,10 +3,9 @@
3
3
  /**
4
4
  * ClaudeOS-Core — Manifest Generator
5
5
  *
6
- * Role: Generate 4 types of metadata JSON + initialize stale-report
6
+ * Role: Generate metadata JSON + initialize stale-report
7
7
  * Output (claudeos-core/generated/):
8
8
  * - rule-manifest.json : rules/standard/skills/guide file list + frontmatter
9
- * - import-graph.json : (deprecated — kept for backward compatibility, @import removed)
10
9
  * - sync-map.json : plan/ <file> block → file path mapping
11
10
  * - plan-manifest.json : plan/ file list + <file> block count
12
11
  * - stale-report.json : initialized (each verification tool appends results)
@@ -68,9 +67,9 @@ function extractFileBlocks(f) {
68
67
  }
69
68
 
70
69
  async function main() {
71
- console.log("\n╔══════════════════════════════════════╗");
70
+ console.log("\n╔═══════════════════════════════════════╗");
72
71
  console.log("║ ClaudeOS-Core — Manifest Generator ║");
73
- console.log("╚══════════════════════════════════════╝\n");
72
+ console.log("╚═══════════════════════════════════════╝\n");
74
73
 
75
74
  if (!fs.existsSync(GEN)) fs.mkdirSync(GEN, { recursive: true });
76
75
 
@@ -117,16 +116,7 @@ async function main() {
117
116
  fs.writeFileSync(path.join(GEN, "rule-manifest.json"), JSON.stringify(mf, null, 2));
118
117
  console.log(` ✅ rule-manifest.json — ${mf.summary.total} files indexed`);
119
118
 
120
- // ─── import-graph.json (deprecated — @import removed) ──
121
- const gr = {
122
- generatedAt: new Date().toISOString(),
123
- deprecated: true,
124
- note: "@import is not a Claude Code feature and has been removed. Rules now use paths: [\"**/*\"] frontmatter.",
125
- nodes: [], edges: [], errors: [],
126
- summary: { totalNodes: 0, totalEdges: 0, brokenImports: 0 },
127
- };
128
- fs.writeFileSync(path.join(GEN, "import-graph.json"), JSON.stringify(gr, null, 2));
129
- console.log(" ✅ import-graph.json — deprecated (no @imports)");
119
+ // import-graph.json removed — @import was never a Claude Code feature
130
120
 
131
121
  // ─── sync-map.json ─────────────────────────────────────
132
122
  const sm = { generatedAt: new Date().toISOString(), mappings: [] };
@@ -152,13 +142,19 @@ async function main() {
152
142
  fs.writeFileSync(path.join(GEN, "plan-manifest.json"), JSON.stringify(pm, null, 2));
153
143
  console.log(` ✅ plan-manifest.json — ${pm.plans.length} plans`);
154
144
 
155
- // ─── Initialize stale-report.json ──────────────────────────
156
- fs.writeFileSync(
157
- path.join(GEN, "stale-report.json"),
158
- JSON.stringify({ generatedAt: new Date().toISOString(), summary: { totalIssues: 0, status: "initial" } }, null, 2)
159
- );
145
+ // ─── Initialize stale-report.json (preserve existing sub-tool results) ──
146
+ const srPath = path.join(GEN, "stale-report.json");
147
+ let sr = {};
148
+ if (fs.existsSync(srPath)) {
149
+ try { sr = JSON.parse(fs.readFileSync(srPath, "utf-8")); } catch { sr = {}; }
150
+ }
151
+ sr.generatedAt = new Date().toISOString();
152
+ if (!sr.summary) sr.summary = {};
153
+ sr.summary.totalIssues = 0;
154
+ sr.summary.status = "initial";
155
+ fs.writeFileSync(srPath, JSON.stringify(sr, null, 2));
160
156
  console.log(" ✅ stale-report.json — initialized");
161
- console.log("\n 📁 Output: claudeos-core/generated/ (5 files)\n");
157
+ console.log("\n 📁 Output: claudeos-core/generated/ (4 files)\n");
162
158
  }
163
159
 
164
160
  main().catch(e => { console.error(e); process.exit(1); });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudeos-core",
3
- "version": "1.2.3",
3
+ "version": "1.3.0",
4
4
  "description": "Auto-generate Claude Code documentation from your actual source code — Standards, Rules, Skills, and Guides tailored to your project",
5
5
  "main": "bin/cli.js",
6
6
  "bin": {
@@ -8,6 +8,7 @@
8
8
  },
9
9
  "files": [
10
10
  "bin/",
11
+ "lib/",
11
12
  "content-validator/",
12
13
  "health-checker/",
13
14
  "manifest-generator/",
@@ -37,7 +38,8 @@
37
38
  "validate": "node bin/cli.js validate",
38
39
  "refresh": "node bin/cli.js refresh",
39
40
  "restore": "node bin/cli.js restore",
40
- "test": "node health-checker/index.js"
41
+ "test": "node --test tests/*.test.js",
42
+ "test:health": "node health-checker/index.js"
41
43
  },
42
44
  "keywords": [
43
45
  "claude-code",
@@ -24,9 +24,9 @@ const GEN_DIR = path.join(ROOT, "claudeos-core/generated");
24
24
  function rel(p) { return path.relative(ROOT, p).replace(/\\/g, "/"); }
25
25
 
26
26
  async function main() {
27
- console.log("\n╔══════════════════════════════════════╗");
27
+ console.log("\n╔═══════════════════════════════════════╗");
28
28
  console.log("║ ClaudeOS-Core — Pass JSON Validator ║");
29
- console.log("╚══════════════════════════════════════╝\n");
29
+ console.log("╚═══════════════════════════════════════╝\n");
30
30
 
31
31
  if (!fs.existsSync(GEN_DIR)) {
32
32
  console.log(" ❌ claudeos-core/generated/ directory not found\n");
@@ -111,9 +111,7 @@ async function main() {
111
111
 
112
112
  // ─── 3. pass1-*.json ──────────────────────────────────
113
113
  console.log(" [3/4] pass1-*.json...");
114
- const pass1Files = await glob("pass1-*.json", { cwd: GEN_DIR, absolute: true });
115
- // Exclude pass1-prompt.md
116
- const pass1JsonFiles = pass1Files.filter(f => f.endsWith(".json"));
114
+ const pass1JsonFiles = await glob("pass1-*.json", { cwd: GEN_DIR, absolute: true });
117
115
  if (pass1JsonFiles.length === 0) {
118
116
  warnings.push({ file: "pass1-*.json", type: "NO_FILES", msg: "No pass1 JSON found (not yet executed?)" });
119
117
  }
@@ -12,6 +12,7 @@ Analysis items (per domain):
12
12
  - URL patterns (RESTful conventions, naming conventions, versioning)
13
13
  - Parameter binding (@RequestBody, @PathVariable, @RequestParam, @ModelAttribute, @RequestHeader)
14
14
  - Response format (ResponseEntity, custom response wrappers, direct return)
15
+ - If a custom response wrapper class exists, record its EXACT class name, EXACT method signatures (e.g., `success()`, `error()`), and EXACT import path. Do NOT guess or invent method names — read the actual source.
15
16
  - Error handling (try-catch patterns, @ExceptionHandler, @ControllerAdvice)
16
17
  - Authentication/authorization (@AuthenticationPrincipal, @PreAuthorize, SecurityContext)
17
18
  - API documentation (Swagger/SpringDoc annotations)
@@ -47,6 +48,8 @@ Analysis items (per domain):
47
48
  - Field type conventions (Boolean handling, date types, Enum management)
48
49
  - Validation annotations (@NotNull, @NotBlank, @Size, @Pattern, custom)
49
50
  - Conversion approach (MapStruct, ModelMapper, manual conversion)
51
+ - Import paths: record EXACT package paths for shared/utility classes
52
+ - Utility class locations: record EXACT package where shared utilities live
50
53
 
51
54
  5. Interceptor/Filter/AOP Patterns
52
55
  - HandlerInterceptor usage
@@ -35,9 +35,9 @@ Merge items:
35
35
  - DB table/column naming
36
36
 
37
37
  6. Common Classes/Utilities List
38
- - Base class fields (must not be redeclared)
39
- - Shared utility classes
40
- - Constants/Enum management approach
38
+ - Base class fields (must not be redeclared) with EXACT fully-qualified class names
39
+ - Shared utility classes with EXACT package paths (e.g., `com.company.common.util.DateUtils`)
40
+ - Constants/Enum management approach with EXACT locations
41
41
 
42
42
  7. Security/Authentication Patterns
43
43
  - Authentication method (JWT, Session, OAuth2)
@@ -4,6 +4,23 @@ generate all ClaudeOS-Core files based on the analysis results.
4
4
 
5
5
  Do not read the original source code again. Reference only the analysis results.
6
6
 
7
+ CRITICAL — Build Tool Consistency:
8
+ Check `stack.buildTool` and `stack.packageManager` in project-analysis.json.
9
+ ALL generated files MUST use the detected build tool's commands (e.g., Gradle or Maven).
10
+ NEVER mix Gradle/Maven commands. Also verify actual task names from build files.
11
+
12
+ CRITICAL — Cross-file Consistency:
13
+ Rules (.claude/rules/) and Standards (claudeos-core/standard/) MUST NOT contradict each other.
14
+ If a standard defines a specific pattern (e.g., import path, file naming, API usage),
15
+ the corresponding rule MUST use the same pattern. Before generating each rule file,
16
+ verify it is consistent with the related standard file.
17
+
18
+ CRITICAL — CLAUDE.md Reference Table Completeness:
19
+ The reference table in CLAUDE.md MUST list ALL generated standard files, not just core.
20
+ Include all backend-api, security-db, infra, and verification standards.
21
+ Alternatively, add a note directing readers to .claude/rules/00.core/00.standard-reference.md
22
+ for the complete list.
23
+
7
24
  Generation targets:
8
25
 
9
26
  1. CLAUDE.md (project root)
@@ -14,6 +14,7 @@ Analysis items (per domain):
14
14
  - URL patterns (RESTful conventions, naming, versioning)
15
15
  - Parameter binding (@RequestBody, @PathVariable, @RequestParam, @ModelAttribute)
16
16
  - Response format (ResponseEntity, custom response wrappers, sealed class responses)
17
+ - If a custom response wrapper class exists, record its EXACT class name, EXACT method signatures (e.g., `success()`, `error()`), and EXACT import path. Do NOT guess or invent method names — read the actual source.
17
18
  - Error handling (try-catch, @ExceptionHandler, @ControllerAdvice, Result/Either pattern)
18
19
  - Authentication/authorization (@AuthenticationPrincipal, @PreAuthorize, SecurityContext)
19
20
  - API documentation (Swagger/SpringDoc annotations)
@@ -61,6 +62,8 @@ Analysis items (per domain):
61
62
  - Validation annotations (@field:NotNull, @field:NotBlank, @field:Size, custom)
62
63
  - Conversion approach (mapstruct-kotlin, manual extension functions, toEntity/toDto)
63
64
  - Serialization (Jackson Kotlin module, kotlinx.serialization)
65
+ - Import paths: record EXACT package paths for shared classes (e.g., `com.company.shared.util.DateUtils`, not an invented path)
66
+ - Utility class locations: record EXACT module and package where shared utilities live
64
67
 
65
68
  6. Aggregate/Aggregate Root Patterns
66
69
  - Aggregate boundary definition (which entities belong together)
@@ -43,11 +43,11 @@ Merge items:
43
43
  - Module naming conventions (what suffix: -server, -lib, -adapter)
44
44
 
45
45
  6. Common Classes/Utilities List
46
- - Shared library (shared-lib) key classes and utilities
47
- - Integration library (integration-lib) contracts and adapters
48
- - Base classes (must not be redeclared)
49
- - Shared constants/Enum management
50
- - Common extension functions
46
+ - Shared library (shared-lib) key classes and utilities with EXACT package paths (e.g., `com.company.shared.util.DateUtils`)
47
+ - Integration library (integration-lib) contracts and adapters with EXACT package paths
48
+ - Base classes (must not be redeclared) with EXACT fully-qualified class names
49
+ - Shared constants/Enum management with EXACT locations
50
+ - Common extension functions with EXACT file locations
51
51
 
52
52
  7. BFF Patterns Summary
53
53
  - Feign Client declaration conventions
@@ -4,6 +4,23 @@ generate all ClaudeOS-Core files based on the analysis results.
4
4
 
5
5
  Do not read the original source code again. Reference only the analysis results.
6
6
 
7
+ CRITICAL — Build Tool Consistency:
8
+ Check `stack.buildTool` and `stack.packageManager` in project-analysis.json.
9
+ ALL generated files MUST use the detected build tool's commands (e.g., Gradle tasks).
10
+ NEVER mix Gradle/Maven commands. Also verify actual task names from build.gradle(.kts).
11
+
12
+ CRITICAL — Cross-file Consistency:
13
+ Rules (.claude/rules/) and Standards (claudeos-core/standard/) MUST NOT contradict each other.
14
+ If a standard defines a specific pattern (e.g., import path, file naming, API usage),
15
+ the corresponding rule MUST use the same pattern. Before generating each rule file,
16
+ verify it is consistent with the related standard file.
17
+
18
+ CRITICAL — CLAUDE.md Reference Table Completeness:
19
+ The reference table in CLAUDE.md MUST list ALL generated standard files, not just core.
20
+ Include all backend-api, security-db, infra, and verification standards.
21
+ Alternatively, add a note directing readers to .claude/rules/00.core/00.standard-reference.md
22
+ for the complete list.
23
+
7
24
  Generation targets:
8
25
 
9
26
  1. CLAUDE.md (project root)
@@ -12,6 +12,7 @@ Analysis items (per domain):
12
12
  - URL patterns (RESTful conventions, naming, versioning)
13
13
  - Parameter handling (req.body, req.params, req.query, @Body(), @Param(), @Query())
14
14
  - Response format (res.json, interceptor, class-transformer, custom wrapper)
15
+ - If a custom response wrapper/helper exists, record its EXACT function/class name, EXACT method signatures, and EXACT import path. Do NOT guess — read the actual source.
15
16
  - Error handling (try-catch, HttpException, ExceptionFilter, error middleware)
16
17
  - Authentication (Passport, JWT Guard, custom middleware)
17
18
  - API documentation (Swagger @ApiTags, @ApiOperation, JSDoc)
@@ -40,6 +41,8 @@ Analysis items (per domain):
40
41
  - TypeScript usage level (interface vs type vs class, Generic usage)
41
42
  - Serialization/deserialization (class-transformer, custom serializer)
42
43
  - Enum/constants management
44
+ - File entry pattern: is the main file `index.ts` or named by module (e.g., `users.controller.ts`)? Record the exact convention.
45
+ - Import paths: record EXACT path aliases and import patterns used (e.g., `@/modules/`, `@app/`, relative paths)
43
46
 
44
47
  5. Configuration/Environment Patterns
45
48
  - Environment variable management (@nestjs/config, dotenv, envalid)
@@ -29,12 +29,15 @@ Merge items:
29
29
 
30
30
  5. Naming Conventions Summary
31
31
  - File/directory naming (kebab-case, camelCase, PascalCase)
32
+ - File entry pattern (index.ts vs module-named files — pick ONE that the project actually uses)
32
33
  - DTO/type naming conventions
33
34
  - Route URL patterns
34
35
  - Module/package structure conventions
35
36
 
36
37
  6. Common Types/Interfaces List
37
- - Shared type definition files
38
+ - Shared type definition files with EXACT import paths
39
+ - Utility functions with EXACT import paths
40
+ - Path aliases used in the project (e.g., `@/` → `src/`)
38
41
  - Utility types
39
42
  - Environment variable types
40
43
  - Constants/Enum management