claudeos-core 1.2.4 → 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 +65 -0
- 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 +71 -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 +13 -7
- 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 +35 -1305
- 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
|
|
@@ -76,12 +83,42 @@ fi
|
|
|
76
83
|
export CLAUDEOS_LANG
|
|
77
84
|
export CLAUDEOS_ROOT="$PROJECT_ROOT"
|
|
78
85
|
|
|
79
|
-
# ───
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
+
|
|
121
|
+
|
|
85
122
|
|
|
86
123
|
echo ""
|
|
87
124
|
echo "╔════════════════════════════════════════════════════╗"
|
|
@@ -176,24 +213,25 @@ for i in $(seq 1 "$TOTAL_GROUPS"); do
|
|
|
176
213
|
if [ ! -f "$PROMPT_FILE" ]; then
|
|
177
214
|
PROMPT_FILE="$GENERATED_DIR/pass1-prompt.md"
|
|
178
215
|
fi
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
# 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)
|
|
182
217
|
TMP_PROMPT="$GENERATED_DIR/_tmp_pass1_prompt.md"
|
|
183
|
-
|
|
218
|
+
cp "$PROMPT_FILE" "$TMP_PROMPT"
|
|
184
219
|
# Use perl with $ENV{} for safe literal replacement (no shell interpolation into Perl code)
|
|
185
220
|
export _DOMAIN_LIST="$DOMAIN_LIST"
|
|
186
221
|
export _PASS_NUM="$i"
|
|
187
222
|
perl -pi -e 's/\{\{DOMAIN_GROUP\}\}/$ENV{_DOMAIN_LIST}/g' "$TMP_PROMPT"
|
|
188
223
|
perl -pi -e 's/\{\{PASS_NUM\}\}/$ENV{_PASS_NUM}/g' "$TMP_PROMPT"
|
|
189
|
-
# inject_project_root
|
|
190
|
-
|
|
191
|
-
|
|
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"
|
|
192
228
|
|
|
193
|
-
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"
|
|
194
231
|
echo " ❌ Pass 1-${i} failed. Aborting."
|
|
195
232
|
exit 1
|
|
196
233
|
fi
|
|
234
|
+
rm -f "$TMP_PROMPT"
|
|
197
235
|
|
|
198
236
|
# Verify JSON was created
|
|
199
237
|
if [ ! -f "$GENERATED_DIR/pass1-${i}.json" ]; then
|
|
@@ -203,6 +241,7 @@ for i in $(seq 1 "$TOTAL_GROUPS"); do
|
|
|
203
241
|
|
|
204
242
|
echo " ✅ pass1-${i}.json created"
|
|
205
243
|
done
|
|
244
|
+
unset _DOMAIN_LIST _PASS_NUM _PROJECT_ROOT
|
|
206
245
|
echo ""
|
|
207
246
|
|
|
208
247
|
# ─── [5] Pass 2: Merge analysis results ─────────────────────────
|
|
@@ -213,12 +252,16 @@ echo "━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
213
252
|
if [ -f "$GENERATED_DIR/pass2-merged.json" ]; then
|
|
214
253
|
echo " ⏭️ pass2-merged.json already exists, skipping"
|
|
215
254
|
else
|
|
216
|
-
|
|
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"
|
|
217
258
|
|
|
218
|
-
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"
|
|
219
261
|
echo " ❌ Pass 2 failed. Aborting."
|
|
220
262
|
exit 1
|
|
221
263
|
fi
|
|
264
|
+
rm -f "$TMP_PASS2"
|
|
222
265
|
|
|
223
266
|
if [ ! -f "$GENERATED_DIR/pass2-merged.json" ]; then
|
|
224
267
|
echo " ❌ pass2-merged.json was not created. Aborting."
|
|
@@ -233,17 +276,22 @@ echo ""
|
|
|
233
276
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
234
277
|
echo "[6] Pass 3 — Generating all files..."
|
|
235
278
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
236
|
-
|
|
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"
|
|
237
282
|
|
|
238
|
-
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"
|
|
239
285
|
echo " ❌ Pass 3 failed. Aborting."
|
|
240
286
|
exit 1
|
|
241
287
|
fi
|
|
288
|
+
rm -f "$TMP_PASS3"
|
|
242
289
|
|
|
243
290
|
if [ ! -f "$PROJECT_ROOT/CLAUDE.md" ]; then
|
|
244
291
|
echo " ❌ CLAUDE.md was not created. Pass 3 may have failed silently."
|
|
245
292
|
exit 1
|
|
246
293
|
fi
|
|
294
|
+
unset _PROJECT_ROOT
|
|
247
295
|
echo ""
|
|
248
296
|
|
|
249
297
|
# ─── [7] Run verification tools ───────────────────────────────
|
|
@@ -271,7 +319,7 @@ fi
|
|
|
271
319
|
echo ""
|
|
272
320
|
|
|
273
321
|
# ─── Complete ───────────────────────────────────────────────
|
|
274
|
-
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 ' ')
|
|
275
323
|
TOTAL_GROUPS_DONE=$TOTAL_GROUPS
|
|
276
324
|
PASS1_FILES=$(ls -1 "$GENERATED_DIR"/pass1-*.json 2>/dev/null | wc -l | tr -d ' ')
|
|
277
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
|
+
};
|
|
@@ -67,9 +67,9 @@ function extractFileBlocks(f) {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
async function main() {
|
|
70
|
-
console.log("\n
|
|
70
|
+
console.log("\n╔═══════════════════════════════════════╗");
|
|
71
71
|
console.log("║ ClaudeOS-Core — Manifest Generator ║");
|
|
72
|
-
console.log("
|
|
72
|
+
console.log("╚═══════════════════════════════════════╝\n");
|
|
73
73
|
|
|
74
74
|
if (!fs.existsSync(GEN)) fs.mkdirSync(GEN, { recursive: true });
|
|
75
75
|
|
|
@@ -142,11 +142,17 @@ async function main() {
|
|
|
142
142
|
fs.writeFileSync(path.join(GEN, "plan-manifest.json"), JSON.stringify(pm, null, 2));
|
|
143
143
|
console.log(` ✅ plan-manifest.json — ${pm.plans.length} plans`);
|
|
144
144
|
|
|
145
|
-
// ─── Initialize stale-report.json
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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));
|
|
150
156
|
console.log(" ✅ stale-report.json — initialized");
|
|
151
157
|
console.log("\n 📁 Output: claudeos-core/generated/ (4 files)\n");
|
|
152
158
|
}
|
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
|
|
@@ -4,11 +4,30 @@ 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 — Package Manager Consistency:
|
|
8
|
+
Check `stack.packageManager` in project-analysis.json (e.g., "pnpm", "yarn", "npm").
|
|
9
|
+
ALL generated files MUST use ONLY that detected package manager's commands.
|
|
10
|
+
For example, if packageManager is "pnpm": use `pnpm run build`, `pnpm run dev`, `pnpm install`, etc.
|
|
11
|
+
NEVER mix npm/yarn/pnpm commands. Also check `scripts` field in the project's package.json
|
|
12
|
+
for actual script names (e.g., "eslint" not "lint", "typecheck" not "tsc --noEmit").
|
|
13
|
+
|
|
14
|
+
CRITICAL — Cross-file Consistency:
|
|
15
|
+
Rules (.claude/rules/) and Standards (claudeos-core/standard/) MUST NOT contradict each other.
|
|
16
|
+
If a standard defines a specific pattern (e.g., import path, file naming, API usage),
|
|
17
|
+
the corresponding rule MUST use the same pattern. Before generating each rule file,
|
|
18
|
+
verify it is consistent with the related standard file.
|
|
19
|
+
|
|
20
|
+
CRITICAL — CLAUDE.md Reference Table Completeness:
|
|
21
|
+
The reference table in CLAUDE.md MUST list ALL generated standard files, not just core.
|
|
22
|
+
Include all frontend-ui, backend-api, security-db, infra, and verification standards.
|
|
23
|
+
Alternatively, add a note directing readers to .claude/rules/00.core/00.standard-reference.md
|
|
24
|
+
for the complete list.
|
|
25
|
+
|
|
7
26
|
Generation targets:
|
|
8
27
|
|
|
9
28
|
1. CLAUDE.md (project root)
|
|
10
29
|
- Role definition (based on detected stack)
|
|
11
|
-
- Build & Run Commands (npm/yarn/pnpm)
|
|
30
|
+
- Build & Run Commands (use ONLY the detected packageManager — never hardcode npm/yarn/pnpm)
|
|
12
31
|
- Core architecture diagram
|
|
13
32
|
- DB table/collection naming
|
|
14
33
|
- Standard/Skills/Guide reference table
|