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.
- package/CHANGELOG.md +66 -1
- package/README.de.md +41 -6
- package/README.es.md +42 -6
- package/README.fr.md +42 -6
- package/README.hi.md +42 -6
- package/README.ja.md +43 -6
- package/README.ko.md +42 -6
- package/README.md +53 -11
- package/README.ru.md +42 -6
- package/README.vi.md +42 -6
- package/README.zh-CN.md +42 -6
- package/bin/cli.js +171 -36
- package/bootstrap.sh +72 -23
- package/content-validator/index.js +9 -4
- package/health-checker/index.js +4 -3
- package/lib/safe-fs.js +110 -0
- package/manifest-generator/index.js +16 -20
- package/package.json +4 -2
- package/pass-json-validator/index.js +3 -5
- package/pass-prompts/templates/java-spring/pass1.md +3 -0
- package/pass-prompts/templates/java-spring/pass2.md +3 -3
- package/pass-prompts/templates/java-spring/pass3.md +17 -0
- package/pass-prompts/templates/kotlin-spring/pass1.md +3 -0
- package/pass-prompts/templates/kotlin-spring/pass2.md +5 -5
- package/pass-prompts/templates/kotlin-spring/pass3.md +17 -0
- package/pass-prompts/templates/node-express/pass1.md +3 -0
- package/pass-prompts/templates/node-express/pass2.md +4 -1
- package/pass-prompts/templates/node-express/pass3.md +20 -1
- package/pass-prompts/templates/node-nextjs/pass1.md +13 -3
- package/pass-prompts/templates/node-nextjs/pass2.md +6 -4
- package/pass-prompts/templates/node-nextjs/pass3.md +20 -1
- package/pass-prompts/templates/python-django/pass1.md +3 -1
- package/pass-prompts/templates/python-django/pass2.md +4 -4
- package/pass-prompts/templates/python-django/pass3.md +18 -0
- package/pass-prompts/templates/python-fastapi/pass1.md +3 -0
- package/pass-prompts/templates/python-fastapi/pass2.md +4 -4
- package/pass-prompts/templates/python-fastapi/pass3.md +18 -0
- package/plan-installer/domain-grouper.js +74 -0
- package/plan-installer/index.js +43 -1303
- package/plan-installer/prompt-generator.js +99 -0
- package/plan-installer/stack-detector.js +326 -0
- package/plan-installer/structure-scanner.js +783 -0
- package/plan-validator/index.js +84 -20
- 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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
189
|
-
|
|
190
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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("
|
|
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 =>
|
|
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
|
-
|
|
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
|
package/health-checker/index.js
CHANGED
|
@@ -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("
|
|
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
|
-
|
|
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
|
|
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("
|
|
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
|
-
//
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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/ (
|
|
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.
|
|
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
|
|
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("
|
|
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
|
|
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
|