claudeos-core 2.2.0 → 2.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +1649 -907
  2. package/CONTRIBUTING.md +92 -92
  3. package/README.de.md +32 -0
  4. package/README.es.md +32 -0
  5. package/README.fr.md +32 -0
  6. package/README.hi.md +32 -0
  7. package/README.ja.md +32 -0
  8. package/README.ko.md +1018 -986
  9. package/README.md +1020 -987
  10. package/README.ru.md +32 -0
  11. package/README.vi.md +1019 -987
  12. package/README.zh-CN.md +32 -0
  13. package/bin/cli.js +152 -148
  14. package/bin/commands/init.js +1673 -1554
  15. package/bin/commands/lint.js +62 -0
  16. package/bin/commands/memory.js +438 -438
  17. package/bin/lib/cli-utils.js +206 -206
  18. package/claude-md-validator/index.js +184 -0
  19. package/claude-md-validator/reporter.js +66 -0
  20. package/claude-md-validator/structural-checks.js +528 -0
  21. package/content-validator/index.js +666 -441
  22. package/lib/expected-guides.js +23 -23
  23. package/lib/expected-outputs.js +90 -90
  24. package/lib/language-config.js +35 -35
  25. package/lib/memory-scaffold.js +1058 -1054
  26. package/lib/plan-parser.js +165 -165
  27. package/lib/staged-rules.js +118 -118
  28. package/manifest-generator/index.js +174 -174
  29. package/package.json +90 -87
  30. package/pass-json-validator/index.js +337 -337
  31. package/pass-prompts/templates/common/claude-md-scaffold.md +52 -10
  32. package/pass-prompts/templates/common/pass3-footer.md +402 -224
  33. package/pass-prompts/templates/common/pass3b-core-header.md +43 -0
  34. package/pass-prompts/templates/common/pass4.md +375 -305
  35. package/pass-prompts/templates/common/staging-override.md +26 -26
  36. package/pass-prompts/templates/node-vite/pass1.md +117 -117
  37. package/pass-prompts/templates/node-vite/pass2.md +78 -78
  38. package/pass-prompts/templates/python-flask/pass1.md +119 -119
  39. package/pass-prompts/templates/python-flask/pass2.md +85 -85
  40. package/plan-installer/domain-grouper.js +76 -76
  41. package/plan-installer/index.js +137 -137
  42. package/plan-installer/prompt-generator.js +188 -145
  43. package/plan-installer/scanners/scan-frontend.js +505 -473
  44. package/plan-installer/scanners/scan-java.js +226 -226
  45. package/plan-installer/scanners/scan-node.js +57 -57
  46. package/plan-installer/scanners/scan-python.js +85 -85
  47. package/plan-installer/stack-detector.js +482 -482
  48. package/plan-installer/structure-scanner.js +65 -65
  49. package/sync-checker/index.js +177 -177
@@ -1,1054 +1,1058 @@
1
- /**
2
- * ClaudeOS-Core — Memory / Rule scaffold
3
- *
4
- * Creates initial L4 memory/ files, L4 rule files, and appends L4
5
- * reference section to CLAUDE.md.
6
- *
7
- * Shared between Pass 4 generation fallback and the memory CLI command.
8
- * All writes are idempotent-safe: callers decide whether to overwrite.
9
- */
10
-
11
- const path = require("path");
12
- const fs = require("fs");
13
- const { ensureDir, existsSafe, writeFileSafe, readFileSafe } = require("./safe-fs");
14
-
15
- // ─── Language labels — single source of truth: lib/language-config.js ──
16
- // Re-aliased as LANG_LABELS for the translation prompt context.
17
- const { LANGUAGES: LANG_LABELS } = require("./language-config");
18
-
19
- // ─── Translation cache ─────────────────────────────────────────
20
- // Cache translated content on disk under claudeos-core/generated/ so
21
- // repeated init runs don't re-translate the same static content.
22
- // Cache file: fallback-cache-<lang>.json with shape { "<contentKey>": "<translatedText>" }.
23
- // contentKey is a stable identifier like "MEMORY_FILES.decision-log.md" or
24
- // "RULE_FILES_60.01.decision-log.md".
25
- //
26
- // Cache location is derived from the first directory argument passed to the
27
- // scaffold functions (e.g. memoryDir ends with "claudeos-core/memory", so the
28
- // cache root is its sibling "claudeos-core/generated/").
29
- function cachePathFor(anyClaudeOsCoreDir, lang) {
30
- // Walk up until we find a directory named "claudeos-core" or hit filesystem root.
31
- let cur = path.resolve(anyClaudeOsCoreDir);
32
- let steps = 0;
33
- while (path.basename(cur) !== "claudeos-core" && cur !== path.dirname(cur) && steps < 10) {
34
- cur = path.dirname(cur);
35
- steps++;
36
- }
37
- // If we found claudeos-core, use its generated/ sibling. Otherwise, fall back
38
- // to a temp-style cache inside the passed dir.
39
- if (path.basename(cur) === "claudeos-core") {
40
- return path.join(cur, "generated", `fallback-cache-${lang}.json`);
41
- }
42
- return path.join(anyClaudeOsCoreDir, `.fallback-cache-${lang}.json`);
43
- }
44
-
45
- function readCache(cacheFile) {
46
- try {
47
- if (!existsSafe(cacheFile)) return {};
48
- return JSON.parse(readFileSafe(cacheFile, "{}")) || {};
49
- } catch (_e) {
50
- return {};
51
- }
52
- }
53
-
54
- function writeCache(cacheFile, cache) {
55
- try {
56
- ensureDir(path.dirname(cacheFile));
57
- writeFileSafe(cacheFile, JSON.stringify(cache, null, 2));
58
- } catch (_e) { /* best-effort */ }
59
- }
60
-
61
- // Translate English static content to the requested language via Claude CLI.
62
- //
63
- // Behavior contract:
64
- // - lang === "en" or unset → return English content as-is (no Claude call)
65
- // - lang is supported → MUST translate. If translation fails, THROW an
66
- // error with a clear message. We do NOT silently
67
- // fall back to English, because the user
68
- // explicitly chose a non-English lang and mixing
69
- // English into that output is a correctness
70
- // regression (bug #21).
71
- // - lang is unknown/invalid → throw (defensive — CLI should have validated)
72
- //
73
- // A disk cache (claudeos-core/generated/fallback-cache-<lang>.json) skips
74
- // re-translation across init runs.
75
- function translateIfNeeded(englishContent, lang, contentKey, cacheFile) {
76
- if (!lang || lang === "en") return englishContent;
77
- if (!LANG_LABELS[lang]) {
78
- throw new Error(
79
- `memory-scaffold: unsupported lang='${lang}'. ` +
80
- `Supported: ${Object.keys(LANG_LABELS).join(", ")}`
81
- );
82
- }
83
-
84
- // M2: CI / deterministic-test escape hatch. When
85
- // CLAUDEOS_SKIP_TRANSLATION=1 is set, throw instead of shelling out to
86
- // `claude -p`. This makes the "translation fails without real Claude CLI"
87
- // test family pass deterministically on dev machines where the CLI IS
88
- // authenticated (previously the tests shelled out, got real translations,
89
- // and their `assert.throws` fired). CI environments set this env var in
90
- // their test step so they don't need `claude` installed at all.
91
- if (process.env.CLAUDEOS_SKIP_TRANSLATION === "1") {
92
- throw new Error(
93
- `memory-scaffold: translation skipped for lang='${lang}' ` +
94
- `(CLAUDEOS_SKIP_TRANSLATION=1). Unset this env var to translate via \`claude -p\`.`
95
- );
96
- }
97
-
98
- // Cache hit → return immediately
99
- const cache = readCache(cacheFile);
100
- if (cache[contentKey] && typeof cache[contentKey] === "string" && cache[contentKey].trim().length > 0) {
101
- return cache[contentKey];
102
- }
103
-
104
- // Lazy-load CLI utils to avoid a circular dependency at module-load time.
105
- let runClaudeCapture;
106
- try {
107
- ({ runClaudeCapture } = require("../bin/lib/cli-utils"));
108
- } catch (e) {
109
- throw new Error(
110
- `memory-scaffold: translation required for lang='${lang}' but CLI utils ` +
111
- `could not be loaded: ${e.message}`
112
- );
113
- }
114
- if (typeof runClaudeCapture !== "function") {
115
- throw new Error(
116
- `memory-scaffold: translation required for lang='${lang}' but ` +
117
- `runClaudeCapture is not available`
118
- );
119
- }
120
-
121
- const langLabel = LANG_LABELS[lang];
122
- // Visible progress — translation can take 5-20s per file, user should see it.
123
- process.stdout.write(` 🌐 Translating ${contentKey} → ${lang}...`);
124
- const t0 = Date.now();
125
-
126
- try {
127
- return performTranslation(englishContent, lang, langLabel, contentKey, cache, cacheFile, runClaudeCapture, t0);
128
- } catch (err) {
129
- // Close the progress line before the exception bubbles up
130
- process.stdout.write(` ❌\n`);
131
- throw err;
132
- }
133
- }
134
-
135
- // Extracted from translateIfNeeded so the caller can wrap the work in
136
- // try/catch-with-log-cleanup without duplicating the logic.
137
- function performTranslation(englishContent, lang, langLabel, contentKey, cache, cacheFile, runClaudeCapture, t0) {
138
-
139
- // Translation prompt. Rules are strict because Claude's default behaviour
140
- // is to over-paraphrase and sometimes drop code fences or frontmatter.
141
- const prompt = `You are a professional technical translator. Translate the Markdown document below into ${langLabel}.
142
-
143
- === ABSOLUTE RULES (violating any of these is a failure) ===
144
-
145
- 1. PRESERVE Markdown structure BYTE-FOR-BYTE:
146
- - Headings: same level (#, ##, ###, ####), same number, same order.
147
- - Code fences: \`\`\` and ~~~ blocks — content inside code fences is NEVER translated. Preserve verbatim.
148
- - Inline code: \`...\` — preserve verbatim (do not translate).
149
- - Tables: keep the | separators and column count identical.
150
- - Lists: preserve bullet style (-, *, 1.) and indentation.
151
- - Bold/italic: **...**, *...*, _..._ — preserve markers, translate text inside.
152
- - Blockquotes (>): preserve.
153
- - Horizontal rules (---): preserve.
154
- - Blank lines: preserve count and position.
155
-
156
- 2. PRESERVE LITERALLY (DO NOT translate, DO NOT transliterate):
157
- - YAML frontmatter keys: \`name:\`, \`paths:\`, \`---\` markers.
158
- (The VALUE of \`name:\` MAY be translated if it's a human label.)
159
- - All file paths: \`claudeos-core/memory/\`, \`.claude/rules/60.memory/\`, etc.
160
- - All CLI commands: \`npx claudeos-core memory compact\`, \`npm install\`, etc.
161
- - Path glob patterns: \`"**/*"\`, \`"src/**/*.java"\`, etc.
162
- - CLI-parsed field keywords (these are parsed by code, translating breaks the tool):
163
- * \`frequency:\`, \`count:\`, \`last seen:\`, \`importance:\` (failure-pattern fields)
164
- * \`fix\`, \`solution\` (fix-field keywords)
165
- * \`## Last Compaction\` (section heading parsed verbatim)
166
- * \`(L4)\` token in headings (language-independent marker)
167
- - Code identifiers, class names, method names, package names.
168
- - URLs and email addresses.
169
-
170
- 3. TRANSLATION QUALITY:
171
- - Translate prose, comments, descriptions, table cell text, explanations.
172
- - Use natural, professional ${langLabel}. NOT machine-translated style.
173
- - Keep the document's tone (this is developer documentation — be precise and concise).
174
- - Domain terms (e.g. "entry", "anchor", "confidence") should use natural ${langLabel} equivalents, not awkward literal translations.
175
-
176
- 4. OUTPUT FORMAT:
177
- - Output ONLY the translated Markdown document.
178
- - NO preamble ("Here is the translation:", etc.).
179
- - NO postamble ("Let me know if...", etc.).
180
- - NO wrapping the output in a code fence.
181
- - The FIRST character of your response must be the first character of the translated document.
182
- - The LAST character of your response must be the last character of the translated document.
183
-
184
- === DOCUMENT TO TRANSLATE ===
185
- ${englishContent}
186
- === END DOCUMENT ===
187
-
188
- Translate now. Output only the translated document.`;
189
-
190
- const raw = runClaudeCapture(prompt, { timeout: 180000 });
191
- if (raw === null || typeof raw !== "string") {
192
- throw new Error(
193
- `memory-scaffold: Claude CLI call failed while translating '${contentKey}' to ${lang}. ` +
194
- `Ensure \`claude\` CLI is available and authenticated.`
195
- );
196
- }
197
-
198
- // Strip any stray "=== ... ===" markers or common preamble Claude may echo.
199
- let cleaned = raw
200
- .replace(/^===\s*DOCUMENT TO TRANSLATE\s*===\s*\n?/m, "")
201
- .replace(/\n?===\s*END DOCUMENT\s*===\s*$/m, "")
202
- .replace(/^---\s*BEGIN DOCUMENT\s*---\s*\n?/m, "")
203
- .replace(/\n?---\s*END DOCUMENT\s*---\s*$/m, "")
204
- .replace(/^\s*Here is the translation[^\n]*\n/i, "")
205
- .replace(/^\s*```(?:markdown|md)?\s*\n/i, "")
206
- .replace(/\n```\s*$/, "")
207
- .trim();
208
-
209
- // Validation: must have non-trivial content
210
- if (cleaned.length < Math.max(50, englishContent.length * 0.4)) {
211
- throw new Error(
212
- `memory-scaffold: translation of '${contentKey}' to ${lang} is suspiciously short ` +
213
- `(got ${cleaned.length} chars, expected at least ${Math.max(50, Math.floor(englishContent.length * 0.4))}). ` +
214
- `Claude may have refused or returned only a preamble.`
215
- );
216
- }
217
-
218
- // Validation: preserve key structural elements
219
- const origHeadings = (englishContent.match(/^#{1,6}\s+/gm) || []).length;
220
- const newHeadings = (cleaned.match(/^#{1,6}\s+/gm) || []).length;
221
- if (origHeadings >= 3 && newHeadings < Math.ceil(origHeadings * 0.6)) {
222
- throw new Error(
223
- `memory-scaffold: translation of '${contentKey}' to ${lang} lost too many headings ` +
224
- `(orig=${origHeadings}, new=${newHeadings}). Translation quality rejected.`
225
- );
226
- }
227
-
228
- const origFences = (englishContent.match(/^```/gm) || []).length;
229
- const newFences = (cleaned.match(/^```/gm) || []).length;
230
- if (origFences > 0 && newFences !== origFences) {
231
- throw new Error(
232
- `memory-scaffold: translation of '${contentKey}' to ${lang} broke code fences ` +
233
- `(orig=${origFences}, new=${newFences}). Translation quality rejected.`
234
- );
235
- }
236
-
237
- // Validation: CLI-parsed keywords must survive verbatim (they are parsed by
238
- // the memory CLI — if translated they break the tool silently).
239
- const MUST_PRESERVE = ["frequency:", "last seen:", "importance:", "(L4)"];
240
- for (const kw of MUST_PRESERVE) {
241
- if (englishContent.includes(kw) && !cleaned.includes(kw)) {
242
- throw new Error(
243
- `memory-scaffold: translation of '${contentKey}' to ${lang} lost required ` +
244
- `keyword '${kw}' which must be preserved literally (CLI parser depends on it).`
245
- );
246
- }
247
- }
248
-
249
- // Validation: frontmatter boundary markers must match original count
250
- const origFrontmatter = (englishContent.match(/^---\s*$/gm) || []).length;
251
- const newFrontmatter = (cleaned.match(/^---\s*$/gm) || []).length;
252
- if (origFrontmatter > 0 && newFrontmatter !== origFrontmatter) {
253
- throw new Error(
254
- `memory-scaffold: translation of '${contentKey}' to ${lang} broke YAML frontmatter ` +
255
- `markers (orig=${origFrontmatter}, new=${newFrontmatter}).`
256
- );
257
- }
258
-
259
- // Success — save to cache for future init runs
260
- cache[contentKey] = cleaned;
261
- writeCache(cacheFile, cache);
262
-
263
- const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
264
- process.stdout.write(` ✅ (${elapsed}s)\n`);
265
-
266
- return cleaned;
267
- }
268
-
269
- // ─── L4 Memory files ───────────────────────────────────────────
270
- const MEMORY_FILES = {
271
- "decision-log.md": `# Decision Log
272
-
273
- _Permanent record of "why" behind design choices. Append-only._
274
- _Format: \`## YYYY-MM-DD — <Title>\` then Context / Options / Decision / Consequences._
275
- `,
276
-
277
- "failure-patterns.md": `# Failure Patterns
278
-
279
- _Recurring errors and their fixes. Importance auto-scored by \`npx claudeos-core memory score\`._
280
- _Format: \`## <pattern-id>\` with Frequency / Last Seen / Importance / Fix._
281
- `,
282
-
283
- "compaction.md": `# Compaction Strategy
284
-
285
- _4-stage compaction rules for \`decision-log.md\` and \`failure-patterns.md\`._
286
- _Run via \`npx claudeos-core memory compact\`._
287
-
288
- ## Preservation Priority
289
- Entries are preserved if ANY of:
290
- - \`importance >= 7\`
291
- - \`lastSeen\` within 30 days
292
- - Referenced by an active rule (path listed in rule-manifest.json)
293
-
294
- ## Stages
295
-
296
- ### Stage 1 — Summarize aged entries
297
- Entries older than 30 days with no recent reference are summarized:
298
- - Keep: pattern-id, frequency, one-line fix summary
299
- - Drop: verbose context, full stack traces
300
-
301
- ### Stage 2 — Merge duplicate patterns
302
- Failure entries with the same root cause are merged:
303
- - \`frequency = sum\`
304
- - \`lastSeen = max\`
305
- - \`fix\` unified to the most recent working solution
306
-
307
- ### Stage 3 — Drop low-importance entries
308
- Entries with \`importance < 3\` AND \`lastSeen > 60 days\` are removed.
309
-
310
- ### Stage 4 — Enforce file size cap
311
- Each target file is capped at 400 lines.
312
- When exceeded, the oldest (by \`lastSeen\`) low-importance entries are dropped first.
313
-
314
- ## Last Compaction
315
- (never — run \`npx claudeos-core memory compact\`)
316
- `,
317
-
318
- "auto-rule-update.md": `# Auto Rule Update Proposals
319
-
320
- _Generated by \`npx claudeos-core memory propose-rules\`._
321
- _Each proposal: failure pattern → affected rule → diff → confidence._
322
-
323
- ## How to apply
324
- 1. Review each proposal below.
325
- 2. If accepted, edit the affected rule file and commit.
326
- 3. Move the accepted proposal into \`decision-log.md\` as a record.
327
-
328
- ## Proposals
329
- (none yet — run \`npx claudeos-core memory propose-rules\` after accumulating failure patterns)
330
- `,
331
- };
332
-
333
- // ─── 00.core additional rule files (always scaffolded) ─────────
334
- const RULE_FILES_00 = {
335
- "51.doc-writing-rules.md": `---
336
- name: Document Writing Rules
337
- paths:
338
- - "**/*"
339
- ---
340
-
341
- # Standard / Rules / Skills Document Writing Rules
342
-
343
- ## [CRITICAL] Rules File paths Frontmatter Required
344
-
345
- Every file in \`.claude/rules/\` MUST include a \`paths\` field in its YAML frontmatter. Without \`paths\`, Claude Code cannot determine when to load the rule.
346
-
347
- - Set \`paths\` to match the **file patterns where the rule is actually needed**.
348
- - Example: document writing rules → \`"**/claudeos-core/**"\`, \`"**/.claude/**"\` (not needed during code editing)
349
- - Example: coding conventions → \`"**/*"\` (applies to all code)
350
- - Do NOT propose narrowing core rules from \`"**/*"\` to specific patterns like \`src/**/*.tsx\` — this increases management complexity and risks rules not loading when needed.
351
-
352
- ## [CRITICAL] No Domain-Specific Hardcoding
353
-
354
- When adding or modifying rules in \`claudeos-core/standard/\`, \`.claude/rules/\`, or \`claudeos-core/skills/\`, **never hardcode project-specific domain names**. Always write in generic, reusable patterns.
355
-
356
- ### Prohibited
357
-
358
- - Specific table names (e.g., \`user_account\`, \`st_ntc_base\`)
359
- - Specific URL paths (e.g., \`/notice/getList\`, \`/api/v1/orders\`)
360
- - Specific domain codes (e.g., \`NOTICE\`, \`ORDER\`, \`SYSTEM\`)
361
- - Specific DTO/Entity class names (e.g., \`GetOrderListReqDto\`)
362
-
363
- ### Correct Approach
364
-
365
- | Item | Wrong | Correct |
366
- |------|-------|---------|
367
- | Path key | \`ORDER: /api/orders\` | \`{DOMAIN_KEY}: /{category}/{domain}\` |
368
- | Table | \`user_account\` | \`{prefix}_{table_name}\` |
369
- | URL | \`/notice/getList\` | \`/{domain}/{action}\` |
370
- | DTO | \`GetOrderListReqDto\` | \`{Action}{Entity}ReqDto\` |
371
-
372
- ### Allowed Exceptions
373
-
374
- - **Project-wide common fields**: audit columns, base classes, and fields used across ALL domains
375
- - **Framework/infrastructure names**: \`BaseEntity\`, \`SecurityConfig\`, framework annotations
376
- - **Existing domain listing**: only when explaining how to ADD NEW domains (configuration examples)
377
-
378
- ### Rationale
379
-
380
- These documents are project-wide **common rules**. If specific domain names appear, developers working on other domains may ignore the rules as irrelevant. All developers must follow the same rules — write generically.
381
-
382
- ## [CRITICAL] No System Absolute Path Hardcoding
383
-
384
- **Never hardcode system absolute paths** (\`/Users/xxx/\`, \`/home/xxx/\`, \`C:\\\\Users\\\\xxx\\\\\`) in documents. User names and machine-specific paths are environment-dependent. Always use the current working directory or project-relative paths instead.
385
-
386
- ## [CRITICAL] Code Examples Must Reflect Actual Project Structure
387
-
388
- When writing code examples in documents (file paths, import statements, directory tree diagrams), **verify against the actual project structure** before writing. Do not guess or invent fictional paths. If unsure, check the real directory layout first.
389
-
390
- ## Reference
391
- - claudeos-core/standard/00.core/*doc-writing-guide.md
392
- `,
393
-
394
- "52.ai-work-rules.md": `---
395
- name: AI Work Rules
396
- paths:
397
- - "**/*"
398
- ---
399
-
400
- # AI Work Rules
401
-
402
- > **IMPORTANT: Rules that AI must follow in this project.**
403
-
404
- ## Accuracy First
405
-
406
- - **Accuracy over token saving.** Never skip file verification or code validation steps.
407
- - **Always read and judge critical facts directly** (file paths, version numbers, API signatures, schema definitions). Sub-agents can explore and summarize, but their summaries must not replace direct verification of facts that affect the code you write.
408
- - **Verify file paths before writing them in documents.** Never record a path that does not exist on disk.
409
- - **No flattery, no exaggeration.** If uncertain, say "verification needed" — do not be confidently wrong.
410
-
411
- ## Safety & Security
412
-
413
- > **CRITICAL: These rules override every other rule in this file. Violations cause data loss, security breaches, or unauthorized publication.**
414
-
415
- - **Destructive commands require explicit user confirmation in this conversation.** Never run \`rm -rf\`, \`git reset --hard\`, \`git push --force\`, \`git branch -D\`, \`git clean -fd\`, \`DROP TABLE\`/\`TRUNCATE\`, \`npm publish\`/\`mvn deploy\`/\`pip publish\`, migration \`down\`/\`revert\` commands, or equivalents without the user explicitly approving the exact command. Authorization for one destructive command is NOT general authorization — re-confirm each time.
416
- - **Never echo, log, write to comments, or commit values from secret files.** Files: \`.env*\`, \`secrets/\`, \`*.pem\`, \`*.key\`, \`id_rsa*\`, credentials JSON, service account files. Reference secrets by variable name only (e.g., \`process.env.DB_PASSWORD\`, not the actual value). Never quote secret values in error messages, chat responses, or test fixtures.
417
-
418
- ## Hallucination Prevention
419
-
420
- Before analysis or evaluation, review this table and do not repeat these patterns.
421
-
422
- | # | Prohibited Pattern | Explanation |
423
- |---|-------------------|-------------|
424
- | 1 | Labeling DO NOT Read files as "token waste" or "unnecessary" | Blocked from reading ≠ unnecessary. DO NOT Read means "AI should not read directly", not "the file has no value" |
425
- | 2 | Labeling intentional design as "inefficient" or "redundant" | Ask "why was it designed this way?" before suggesting changes |
426
- | 3 | Labeling intentional summary-to-detail layering as "duplication" | Multi-layer design (anchor → rules → standard) is intentional — each layer has a different density and role |
427
- | 4 | Judging source values as "serious inconsistency" without checking the primary source | Always verify against the actual source file |
428
- | 5 | Repeating a hallucination already recorded in this project | Check this table + \`memory/failure-patterns.md\` before analysis |
429
- | 6 | Proposing path scoping changes for intentional \`**/*\` designs | Confirm the intent first |
430
- | 7 | Labeling code examples in rules as "excessive" | Code examples are essential for AI-assisted code generation — they reduce hallucination risk regardless of audience experience |
431
- | 8 | Making quantitative judgments based on unverified numbers, then reversing when challenged | No speculation-based quantitative claims |
432
- | 9 | Judging a standard document as "low practical value" without reading it | No judgment before verification |
433
- | 10 | Proposing to merge/reduce same-layer intentional duplication | Different perspectives on the same topic in different files is intentional. Rule accessibility > token saving |
434
- | 11 | Suggesting an import or package name without verifying it exists in the dependency manifest | Hallucinated module/named export. Verify by reading \`package.json\` / \`pom.xml\` / \`build.gradle\` / \`pyproject.toml\` / \`requirements.txt\` before recommending an import |
435
- | 12 | Mixing API signatures from different major versions of the same library | Verify by checking the manifest AND lockfile for the exact installed version (lockfile pins the truth): \`package-lock.json\`/\`pnpm-lock.yaml\`/\`yarn.lock\`, \`gradle.lockfile\`/\`gradle/libs.versions.toml\`, \`poetry.lock\`/\`Pipfile.lock\`/\`uv.lock\`, or fall back to the manifest (\`pom.xml\`/\`build.gradle\`/\`package.json\`/\`pyproject.toml\`) |
436
- | 13 | Editing one environment config file without checking sibling parity | Verify by \`Glob\` for the config family before a partial edit. Backend: \`.env*\`, \`application-*.yml/.properties\`, \`*settings.py\`. Frontend: \`environment*.ts\` (Angular), \`next.config.*\`, \`vite.config.*\`, \`nuxt.config.*\`, \`.env.local\`/\`.env.production\` |
437
- | 14 | Mixing server/client component boundaries (SSR frameworks) — using client-only APIs (\`useState\`, \`useEffect\`, \`window\`, \`localStorage\`) in a server component, or server-only operations (DB access, secret reads, filesystem) in a client component | Read the file's boundary directive before adding code: Next.js App Router (\`"use client"\` opt-in), Nuxt (server vs client composables), Remix (\`loader\`/\`action\` exports). N/A for pure SPA or pure backend projects |
438
- | 15 | Inventing component prop names or function arguments without reading the target's interface | Read the target's prop type definition (\`interface Props\`, \`defineProps<>\`, function signature) or method signature before invoking. Hallucinated props may compile in loose-TS code and crash at runtime |
439
- | 16 | Hardcoding API keys, tokens, passwords, or DB credentials in source code — even in tests, examples, fixtures, or commit messages | Verify by \`Grep\` for patterns like \`(api[_-]?key\|token\|password\|secret)\\s*=\\s*["']\\w+["']\` before committing. Use env vars (\`process.env.X\`/\`os.getenv("X")\`/\`@Value("\${X}")\`), secret managers, or \`.env.example\` placeholders instead |
440
- | 17 | Editing historical database migration files after they've been applied | Migration files (\`migrations/V*.sql\` (Flyway), \`alembic/versions/*.py\`, \`db/migrate/*.rb\` (Rails), \`prisma/migrations/*/migration.sql\`, \`migrations/*.ts\` (TypeORM)) are append-only once applied. Add a NEW migration to revert/modify; never edit historical ones. Verify by checking migration history (\`flyway info\`, \`alembic history\`, \`prisma migrate status\`) before editing |
441
-
442
- **Core Principle:**
443
- - Do not label a system built by the designer as "inefficient", "redundant", or "needs optimization" — **confirm the intent first**
444
- - When evaluating system structure, first ask "why was it built this way?"
445
- - Before pointing out problems, check whether they are already solved or intentionally designed
446
-
447
- ## No Unsolicited Work
448
-
449
- - **Do not make unsolicited suggestions.** If uncertain, ask instead of suggesting. *Exception: factual errors in this project's own docs (wrong file paths, dead references, internally contradicting rules) should be reported even if not asked. Distinguish factual errors (report) from stylistic preferences (stay silent).*
450
- - **Do not modify onboarding/guide documents (\`claudeos-core/guide/\`) unless specifically requested.**
451
- - Do not clean up surrounding code during bug fixes, or add unnecessary refactoring during feature additions.
452
- - **Empty directories may be intentional placeholders — verify markers before flagging or removing.** Markers of intent: a \`.gitkeep\` / \`KEEP_EMPTY.md\` file inside, the directory listed in CLAUDE.md as planned, or referenced by an active plan/standard/skills document. If none of these exist, an empty directory may be neglect — ask the user before deleting.
453
- - **\`plan/\` master documents are internal sync management tools.** Do not suggest removing them. "DO NOT Read" means "AI should not read directly", not "the file is unnecessary".
454
- - **Do not duplicate into memory what is already directly verifiable in code, config files, or rule documents.** Configuration values, paths, and names already recorded in CLAUDE.md, rules, or standard must not be redundantly stored in memory. Examples — backend: port numbers, pool sizes, handler names, transaction propagation modes; frontend: dev server port, build output dir, env var prefix (\`VITE_\`/\`NEXT_PUBLIC_\`/\`REACT_APP_\`), route definitions, bundle size budgets.
455
- - **Do not directly read internal document directories (\`guide/\`, \`plan/\`, \`generated/\`, \`mcp-guide/\`) for routine context loading.** \`.claude/rules/\` and \`claudeos-core/standard/\` already contain the essential content. *Exception: read directly when the user explicitly asks about these contents, or when debugging an issue requires inspecting them.*
456
- - **Established codebase conventions take precedence over textbook-ideal patterns.** Propose modernization, refactoring, or "current best practices" migration ONLY when the user explicitly requests it (e.g., "modernize", "migrate to v3", "refactor to current best practices"). Otherwise, follow the existing pattern even if you would write it differently in a greenfield project.
457
-
458
- ## Project Architecture — Hands Off
459
-
460
- This project uses the CLAUDE.md → rules → standard 3-layer architecture, plus a separate L4 Memory layer. Understand these design principles:
461
-
462
- - **Cross-layer summary/detail duplication is intentional.** Each layer has a different role: CLAUDE.md (anchor/index, always loaded) → rules (detailed rules, conditionally loaded by path) → standard (original specification, referenced when needed). The same topic across layers is layer-appropriate density, not duplication.
463
- - **Same-layer duplication across files is also intentional.** Each file covers a different perspective (DB design, code implementation, DTO design, etc.). Do not propose "consolidating into one file because it's the same layer".
464
- - **Memory (\`claudeos-core/memory/\`, on-demand) and Rules (\`.claude/rules/\`, auto-loaded by path match) are never simultaneously loaded by default.** Similar content between them is NOT duplication. Do not propose "memory cleanup", "dedupe memory vs rules", or "consolidate memory into rules" — they have different roles (on-demand history/context vs auto-loaded enforcement).
465
- - **Multi-rule load provides reinforcement.** Do not label co-loaded defensive rules as "redundant" — the reinforcement effect is intentional and the context cost is negligible.
466
- - **Rules \`paths: ["**/*"]\` — do not propose conditional path conversion for core rules.** When developing new features (no matching files exist yet), conditional paths would prevent rules from loading, risking non-standard code generation.
467
- - **\`00.standard-reference.md\` index additions — avoid unless specifically requested.** Each rules file already links to its corresponding standard via the \`## Reference\` section. Adding paths to the index only consumes additional tokens per conversation.
468
- - **Minor wording or item count differences across layers are NOT "inconsistency risks".** If no information is missing, trivial expression differences are not a problem.
469
-
470
- ## Planned References — No "Missing" Judgment
471
-
472
- - Paths and directories referenced in CLAUDE.md, Rules, Standard, or Skills documents **may not yet exist on disk**.
473
- - These are **planned references for future implementation** — intentional forward declarations.
474
- - Do NOT label them as "missing", "inconsistent", "stale", or "needs deletion". *Exception: if a referenced path appears in 3+ documents and doesn't exist on disk, it may be a typo masquerading as a planned reference — flag for human review (consistent with §"No Unsolicited Work" Exception for factual errors in own docs).*
475
- - Do NOT propose removing or modifying these references. Preserve them as-is.
476
-
477
- ## Code/Document Generation Accuracy
478
-
479
- - **Before writing new code, read 2-3 neighboring files in the same directory for existing patterns** — naming conventions, error handling, logging style, import order, return type idioms, test structure. Match what you find rather than introducing new patterns. Greenfield/textbook idioms come second to in-codebase consistency.
480
- - **Do not guess framework class/type/component shapes — check actual source code.** Backend: base classes, DTOs, entity field naming, repository method signatures. Frontend: component prop interfaces, store/state shapes (Pinia/Redux/Zustand), API response types, route param types, CSS module class names.
481
- - **When modifying skills/standard/rules/memory documents, keep related files in sync.** If a standard changes, update its rule file; if a skill changes, update \`MANIFEST.md\`. If CLAUDE.md summary sections cover the same topic, update them together.
482
- `,
483
- };
484
-
485
- // ─── L4 Rule files (English static fallback) ────────────────
486
- const RULE_FILES_60 = {
487
- "01.decision-log.md": `---
488
- name: Decision Log
489
- paths:
490
- - "claudeos-core/memory/decision-log.md"
491
- ---
492
-
493
- # Decision Log (\`memory/decision-log.md\`)
494
-
495
- Permanent, append-only record of architectural decisions and their rationale.
496
- Commit this file to version control — it is team knowledge.
497
-
498
- ## Read timing
499
-
500
- - **Session start** — skim recent entries to understand past design rationale.
501
- - **Before suggesting architectural changes** — check if a prior decision already addressed this.
502
-
503
- ## Write timing
504
-
505
- Append a new entry when:
506
- - Choosing between competing patterns
507
- - Selecting a library or framework
508
- - Defining a convention the team must follow
509
- - Deciding NOT to do something
510
-
511
- ## Entry format
512
-
513
- \`\`\`markdown
514
- ## YYYY-MM-DD — <Short title>
515
-
516
- - **Context:** why this decision was needed
517
- - **Options considered:** what alternatives existed
518
- - **Decision:** what was chosen and why
519
- - **Consequences:** what this locks in, trade-offs accepted
520
- \`\`\`
521
-
522
- ## Rules
523
-
524
- - Always use the actual current date (UTC, YYYY-MM-DD).
525
- - Never edit or delete existing entries. This is append-only.
526
- - Keep entries concise — 5~10 lines max.
527
- `,
528
-
529
- "02.failure-patterns.md": `---
530
- name: Failure Patterns
531
- paths:
532
- - "claudeos-core/memory/failure-patterns.md"
533
- ---
534
-
535
- # Failure Patterns (\`memory/failure-patterns.md\`)
536
-
537
- Registry of recurring errors, their root causes, and fixes.
538
- Importance is auto-scored by \`npx claudeos-core memory score\` (frequency x recency).
539
- Commit this file — it prevents the team from hitting the same errors repeatedly.
540
-
541
- ## Read timing
542
-
543
- - **Session start** — scan high-importance entries (importance >= 7).
544
- - **When encountering an error** — search this file first. Apply the recorded fix if a match exists.
545
-
546
- ## Write timing
547
-
548
- Append when:
549
- - You encounter an error for the **second time**.
550
- - You discover a non-obvious root cause.
551
- - A workaround exists that is not documented elsewhere.
552
-
553
- ## Entry format
554
-
555
- \`\`\`markdown
556
- ## <pattern-id>
557
-
558
- - **frequency:** 1
559
- - **last seen:** YYYY-MM-DD
560
- - **symptoms:** what the error looks like
561
- - **root cause:** why it happens
562
- - **fix:** step-by-step resolution
563
- \`\`\`
564
-
565
- ## Rules
566
-
567
- - Use a descriptive \`pattern-id\`.
568
- - When encountering a known pattern again, increment \`frequency\` and update \`last seen\`.
569
- - Never delete entries manually — use \`npx claudeos-core memory compact\`.
570
- `,
571
-
572
- "03.compaction.md": `---
573
- name: Compaction Strategy
574
- paths:
575
- - "claudeos-core/memory/compaction.md"
576
- ---
577
-
578
- # Compaction Strategy (\`memory/compaction.md\`)
579
-
580
- Reference document defining the 4-stage compaction policy.
581
- Executed by \`npx claudeos-core memory compact\`.
582
-
583
- ## Rules
584
-
585
- - Do NOT edit unless intentionally changing the compaction policy.
586
- - Do NOT run compaction logic manually — always use the CLI command.
587
-
588
- ## 4 stages (reference)
589
-
590
- 1. **Summarize aged** — entries >30 days, body replaced with one-line summary
591
- 2. **Merge duplicates** — same heading, frequency summed, latest fix kept
592
- 3. **Drop low-importance** — importance <3 AND lastSeen >60 days removed
593
- 4. **Enforce cap** — 400 lines max per file, oldest low-importance entries dropped first
594
-
595
- ## Preservation
596
-
597
- Entries preserved if ANY of: importance >= 7, lastSeen within 30 days, referenced by active rule.
598
- `,
599
-
600
- "04.auto-rule-update.md": `---
601
- name: Auto Rule Update
602
- paths:
603
- - "claudeos-core/memory/auto-rule-update.md"
604
- ---
605
-
606
- # Auto Rule Update (\`memory/auto-rule-update.md\`)
607
-
608
- Machine-generated rule improvement proposals based on recurring failure patterns (frequency >= 3).
609
- Generated by \`npx claudeos-core memory propose-rules\`.
610
-
611
- ## Read timing
612
-
613
- - **When proposals exist** — review them before starting work.
614
-
615
- ## Action workflow
616
-
617
- 1. Read the proposal: which failure pattern triggered it, which rule is affected, confidence score.
618
- 2. If accepted: edit the affected rule file to address the pattern.
619
- 3. After editing: move the accepted proposal into \`decision-log.md\` as a permanent record.
620
- 4. If rejected: add a brief note explaining why.
621
-
622
- ## Rules
623
-
624
- - Do NOT edit proposals directly — they are machine-generated references.
625
- - Proposals with confidence >= 0.70 deserve serious consideration.
626
- `,
627
- };
628
-
629
- // ─── CLAUDE.md append block (English static fallback) ──────────
630
- const CLAUDE_MD_APPEND = `
631
- ## Memory (L4)
632
-
633
- This project uses the ClaudeOS-Core L4 Memory layer for persistent team knowledge.
634
-
635
- ### Common rules (\`.claude/rules/00.core/\`)
636
-
637
- | File | Purpose |
638
- |---|---|
639
- | \`51.doc-writing-rules.md\` | Rules paths frontmatter, no domain/path hardcoding, code examples must reflect actual structure |
640
- | \`52.ai-work-rules.md\` | AI accuracy, hallucination prevention, 3-layer design, memory vs rules separation, planned references |
641
-
642
- ### L4 Memory — persistent team knowledge (\`claudeos-core/memory/\`)
643
-
644
- Detailed rules: \`.claude/rules/60.memory/\` (4 rules).
645
-
646
- | File | Purpose | Action |
647
- |---|---|---|
648
- | \`decision-log.md\` | "Why" behind architectural choices | Read at session start; append when making decisions |
649
- | \`failure-patterns.md\` | Recurring errors & fixes (auto-scored) | Scan at session start; append on repeat errors |
650
- | \`compaction.md\` | 4-stage compaction policy reference | Read-only (edit only to change policy) |
651
- | \`auto-rule-update.md\` | Rule improvement proposals (freq >= 3) | Review proposals; accept -> edit rule + record in decision-log |
652
-
653
- ### Memory workflow
654
-
655
- 1. Scan \`memory/failure-patterns.md\` at session start -> avoid known pitfalls
656
- 2. Skim recent \`memory/decision-log.md\` entries -> understand past design rationale
657
- 3. Record decisions -> append to \`memory/decision-log.md\`
658
- 4. Record repeat errors (2nd occurrence) -> append to \`memory/failure-patterns.md\`
659
- 5. Periodically run \`npx claudeos-core memory compact\` to enforce the 4-stage compaction policy
660
- 6. When \`auto-rule-update.md\` has proposals with confidence >= 0.70, review and act
661
- `;
662
-
663
- // ─── Scaffold functions ────────────────────────────────────────
664
-
665
- function scaffoldMemory(memoryDir, { overwrite = false, lang = "en" } = {}) {
666
- ensureDir(memoryDir);
667
- const cacheFile = cachePathFor(memoryDir, lang);
668
- const results = [];
669
- for (const [name, body] of Object.entries(MEMORY_FILES)) {
670
- const full = path.join(memoryDir, name);
671
- if (!overwrite && existsSafe(full)) {
672
- results.push({ file: name, status: "skipped" });
673
- continue;
674
- }
675
- const content = translateIfNeeded(body, lang, `MEMORY_FILES.${name}`, cacheFile);
676
- const ok = writeFileSafe(full, content);
677
- results.push({ file: name, status: ok ? "written" : "error" });
678
- }
679
- return results;
680
- }
681
-
682
- /**
683
- * Scaffold L4 memory rule files + 00.core common rules (English static fallback).
684
- * Used when Pass 4 Claude prompt fails or is unavailable.
685
- * 00.core rules are always scaffolded (gap-fill only, never overwrite Pass 3 output).
686
- */
687
- function scaffoldRules(rulesBaseDir, { overwrite = false, lang = "en" } = {}) {
688
- const cacheFile = cachePathFor(rulesBaseDir, lang);
689
- const results = [];
690
- const dirs = {
691
- "00.core": RULE_FILES_00,
692
- "60.memory": RULE_FILES_60,
693
- };
694
- for (const [dirName, files] of Object.entries(dirs)) {
695
- const dir = path.join(rulesBaseDir, dirName);
696
- ensureDir(dir);
697
- for (const [name, body] of Object.entries(files)) {
698
- const full = path.join(dir, name);
699
- if (!overwrite && existsSafe(full)) {
700
- results.push({ file: `${dirName}/${name}`, status: "skipped" });
701
- continue;
702
- }
703
- const content = translateIfNeeded(body, lang, `RULE_FILES.${dirName}.${name}`, cacheFile);
704
- const ok = writeFileSafe(full, content);
705
- results.push({ file: `${dirName}/${name}`, status: ok ? "written" : "error" });
706
- }
707
- }
708
- return results;
709
- }
710
-
711
- /**
712
- * Append L4 Memory section to CLAUDE.md (English static fallback).
713
- * Only appends if the section marker is not already present.
714
- * Uses a language-independent marker ("L4 Memory" / "Memory (L4)") that
715
- * survives translation of the heading into other languages.
716
- * @param {string} claudeMdPath - full path to CLAUDE.md
717
- * @returns {boolean} true if appended or already present
718
- */
719
- function appendClaudeMdL4Memory(claudeMdPath, { lang = "en" } = {}) {
720
- // Heading pattern: lines starting with `##` (or more) that contain `(L4)`.
721
- // Using a heading-scoped regex avoids false positives when the user has
722
- // written `(L4)` elsewhere in body text (e.g. "Layer 4 load balancer (L4)").
723
- // The language-independent `(L4)` token still allows translated
724
- // headings (in any of the 10 supported output languages) to be
725
- // recognised only the `(L4)` suffix is stable; the preceding
726
- // "Memory" word varies per language.
727
- const MARKER_REGEX = /^#{2,}\s+.*\(L4\)/m;
728
- if (!existsSafe(claudeMdPath)) return false;
729
- const existing = readFileSafe(claudeMdPath);
730
- if (MARKER_REGEX.test(existing)) return true;
731
- const cacheFile = cachePathFor(path.dirname(claudeMdPath), lang);
732
- const appendBlock = translateIfNeeded(CLAUDE_MD_APPEND, lang, "CLAUDE_MD_APPEND", cacheFile);
733
- const appended = existing.trimEnd() + "\n" + appendBlock;
734
- return writeFileSafe(claudeMdPath, appended);
735
- }
736
-
737
- /**
738
- * Scaffold master plan file for L4 Memory.
739
- *
740
- * DEPRECATED: master plan generation was removed from claudeos-core because
741
- * master plans are internal tool backup files that are not consumed by Claude
742
- * Code at runtime, and generating them required aggregating many files in a
743
- * single session (which could trigger "Prompt is too long" on mid-sized
744
- * projects). This function is now a no-op that returns an empty result list.
745
- * Kept as an export for backward compatibility with existing callers.
746
- *
747
- * @param {string} planDir - path to claudeos-core/plan/ (unused)
748
- * @param {string} memoryDir - path to claudeos-core/memory/ (unused)
749
- * @param {object} [opts] (unused)
750
- * @returns {Array} always empty (no-op)
751
- */
752
- function scaffoldMasterPlans(_planDir, _memoryDir, _opts = {}) {
753
- return [];
754
- }
755
-
756
- // ─── Standard doc-writing-guide (English static fallback) ───
757
- const STANDARD_DOC_WRITING_GUIDE = `# Standard / Rules / Skills Document Writing Guide
758
-
759
- > This document is the detailed guide for writing and modifying ClaudeOS documentation (Standard, Rules, Skills).
760
- > For enforcement rules (loaded automatically), see: .claude/rules/00.core/51.doc-writing-rules.md
761
-
762
- ---
763
-
764
- ## 1. Document Layer Structure
765
-
766
- | Layer | Path | Role | Loading |
767
- |-------|------|------|---------|
768
- | CLAUDE.md | \`CLAUDE.md\` | Entry point overview | Auto-loaded every conversation |
769
- | Rules | \`.claude/rules/\` | Enforcement summary | Conditionally loaded by \`paths\` pattern match |
770
- | Standard | \`claudeos-core/standard/\` | Detailed guide | Manually Read via Rules \`## Reference\` links |
771
- | Skills | \`claudeos-core/skills/\` | Scaffolding automation | Registered in MANIFEST.md |
772
- | Memory | \`claudeos-core/memory/\` | Persistent team knowledge | On-demand Read only |
773
-
774
- ### Layer relationships
775
-
776
- \`\`\`
777
- CLAUDE.md (overview) → Rules (enforcement) → Standard (detailed)
778
- Reference link
779
- \`\`\`
780
-
781
- - **CLAUDE.md Rules Standard content overlap is NOT duplication.** Each layer has a different role and density.
782
- - **Memory and Rules/CLAUDE.md content overlap is NOT duplication.** Memory is on-demand loaded, Rules are auto-loaded. Different loading mechanisms.
783
-
784
- ---
785
-
786
- ## 2. Rules File Writing Rules
787
-
788
- ### [CRITICAL] paths frontmatter required
789
-
790
- Every \`.claude/rules/\` file MUST have \`paths\` in YAML frontmatter. Without it, Claude Code cannot determine when to load the rule.
791
-
792
- \`\`\`markdown
793
- ---
794
- paths:
795
- - "**/*"
796
- ---
797
- # Rule Title
798
- \`\`\`
799
-
800
- ### paths scope settings
801
-
802
- | Scope | paths | Examples |
803
- |-------|-------|---------|
804
- | All code files | \`"**/*"\` | Architecture, naming, coding conventions |
805
- | Document files only | \`"**/claudeos-core/**"\`, \`"**/.claude/**"\` | Document writing rules |
806
- | Config files only | \`"**/*.json"\`, \`"**/*.env*"\`, \`"**/*.yml"\` | Environment/config rules |
807
- | Specific directory | \`"**/claudeos-core/**"\`, \`"**/.claude/**"\` | Sync rules |
808
-
809
- Do NOT propose narrowing core rules \`"**/*"\` to specific patterns — this increases management complexity and risks rules not loading when needed.
810
-
811
- ### Rules file structure
812
-
813
- \`\`\`markdown
814
- ---
815
- paths:
816
- - "pattern"
817
- ---
818
- # Rule Title
819
-
820
- - Rule items (bullet points)
821
- - Code examples recommended
822
-
823
- ## Reference
824
- - claudeos-core/standard/XX.category/YY.name.md
825
- \`\`\`
826
-
827
- - **Write concisely**: detailed content goes in Standard, Rules are enforcement summary only.
828
- - **\`## Reference\` required**: always link to the corresponding Standard document.
829
- - Do not judge short Rules files as "needs expansion".
830
-
831
- ---
832
-
833
- ## 3. Standard File Writing Rules
834
-
835
- - Standard files are detailed guides — **long files are normal**. Do not judge as "too large" or "needs splitting".
836
- - File naming: \`number.name.md\` (e.g., \`01.project-overview.md\`)
837
- - When adding a new Standard, also add it to the \`00.standard-reference.md\` list.
838
-
839
- ---
840
-
841
- ## 4. Skills File Writing Rules
842
-
843
- - When adding a new skill, register it in \`skills/00.shared/MANIFEST.md\`.
844
- - If a skill generates Rules files, those Rules MUST include \`paths\` frontmatter.
845
- - Reference paths in skill templates must be verified against actual project files.
846
-
847
- ---
848
-
849
- ## 5. Planned References
850
-
851
- Paths and directories referenced in documents may not yet exist on disk. These are **planned references for future implementation**.
852
-
853
- Do NOT label them as:
854
- - "missing", "MISSING", "inconsistency" — planned item, normal
855
- - "needs deletion", "stale", "dead reference" future addition, preserve
856
- - "needs correction", "path error" — intentional reference, no change needed
857
-
858
- When discovered during review/audit, **do not report as issues — preserve as-is**.
859
-
860
- ---
861
-
862
- ## 5-1. Multi-Layer Defensive Rule Placement is Intentional
863
-
864
- The same defensive rules (no duplication judgment, no planned reference deletion, no speculation, etc.) are **intentionally repeated across multiple Rules files**. Do NOT judge this as "duplication → needs consolidation".
865
-
866
- ### Design intent
867
-
868
- Each Rules file is loaded in a different work context (standard reference lookup, general coding, document editing). Repeating defensive principles ensures they are active in each context.
869
-
870
- Even when multiple files are loaded simultaneously:
871
- - **Reinforcement effect**: repeated exposure increases AI compliance
872
- - **Independent context preservation**: each file is self-contained in its context
873
-
874
- ### Prohibited
875
-
876
- - Do not report this placement as an optimization target in context analysis
877
- - "Co-loaded therefore redundant" is a hallucination
878
- - Do not propose "consolidate into 52.ai-work-rules.md and replace others with references"
879
-
880
- ---
881
-
882
- ## 5-2. Do Not Over-Report Topic Repetition as "Duplication" or "Inconsistency Risk"
883
-
884
- The same topic (directory structure, API rules, environment variables, path aliases, state management, etc.) may be mentioned in CLAUDE.md and multiple Rules files. This is because **each occurrence serves a different layer role (overview vs enforcement) or domain role (architecture vs security vs config)** — it is not duplication.
885
-
886
- ### Prohibited
887
-
888
- - Do not report tens-of-lines repetition as a "context optimization issue"
889
- - Do not produce "removing duplication saves N lines/bytes" analysis
890
- - Do not over-report trivial expression differences (comment phrasing, item count differences) as "inconsistency risk"
891
- - If no information is missing, it is not a problem
892
-
893
- ---
894
-
895
- ## 6. No Domain-Specific Hardcoding
896
-
897
- When adding or modifying rules in \`claudeos-core/standard/\`, \`.claude/rules/\`, or \`claudeos-core/skills/\`, **never hardcode project-specific domain names**. Always write in generic, reusable patterns.
898
-
899
- ### Rationale
900
-
901
- These documents are project-wide **common rules**. If specific domain names appear, developers working on other domains may ignore the rules as irrelevant.
902
-
903
- ---
904
-
905
- ## 6-1. No System Absolute Path Hardcoding
906
-
907
- **Never hardcode system absolute paths** (\`/Users/xxx/\`, \`/home/xxx/\`, \`C:\\\\Users\\\\xxx\\\\\`) in documents.
908
-
909
- - \`/Users/developer/projects/my-app/src/...\`
910
- - ✅ \`current working directory\` or project-relative path (\`src/...\`)
911
-
912
- ### Rationale
913
-
914
- Absolute paths are specific to one developer's local environment and cannot be used in other environments. Always use relative paths or generic expressions to ensure document portability.
915
-
916
- ---
917
-
918
- ## 6-2. Code Examples Must Follow Project Conventions
919
-
920
- When writing code examples in documents (file paths, import statements, directory tree diagrams), **follow the project's naming conventions**. Specifically:
921
-
922
- - **Directory structure examples must reflect actual project structure** — do not guess or invent fictional paths
923
- - **Follow the project's file naming convention** — check existing files before writing examples
924
- - **Verify paths exist** before including them in documentation
925
-
926
- ### Rationale
927
-
928
- If document examples differ from actual code conventions, developers following the Standard may write incorrectly named code. Examples are normative — they must match the real project.
929
-
930
- ---
931
-
932
- ## 7. Change Synchronization Procedure
933
-
934
- After modifying documents, always synchronize related files:
935
-
936
- | Changed | Sync target |
937
- |---------|-------------|
938
- | Standard modified | Corresponding Rules file |
939
- | Rules modified | Corresponding Standard (\`## Reference\` link still valid?) |
940
- | Skills modified | \`MANIFEST.md\` |
941
- | Document added | \`00.standard-reference.md\` list |
942
-
943
- After changes, directly verify related files (Rules Standard) and update consistently.
944
- `;
945
-
946
- /**
947
- * Scaffold doc-writing-guide standard file.
948
- * Scans 00.core/ for the next available number.
949
- * @param {string} standardCoreDir - path to claudeos-core/standard/00.core/
950
- * @param {object} [opts]
951
- * @param {boolean} [opts.overwrite=false]
952
- * @returns {{ file: string, status: string }}
953
- */
954
- function scaffoldDocWritingGuide(standardCoreDir, { overwrite = false, lang = "en" } = {}) {
955
- ensureDir(standardCoreDir);
956
-
957
- // Check if doc-writing-guide already exists (any number)
958
- const existing = fs.readdirSync(standardCoreDir)
959
- .filter(f => f.endsWith(".doc-writing-guide.md"));
960
- if (existing.length > 0 && !overwrite) {
961
- return { file: existing[0], status: "skipped" };
962
- }
963
-
964
- // Find next available number
965
- const nums = fs.readdirSync(standardCoreDir)
966
- .map(f => parseInt(f.match(/^(\d+)\./)?.[1], 10))
967
- .filter(n => !isNaN(n));
968
- const nextNum = nums.length > 0 ? Math.max(...nums) + 1 : 1;
969
- const fileName = `${String(nextNum).padStart(2, "0")}.doc-writing-guide.md`;
970
-
971
- const target = existing.length > 0 && overwrite
972
- ? path.join(standardCoreDir, existing[0])
973
- : path.join(standardCoreDir, fileName);
974
-
975
- const cacheFile = cachePathFor(standardCoreDir, lang);
976
- const content = translateIfNeeded(STANDARD_DOC_WRITING_GUIDE, lang, "STANDARD_DOC_WRITING_GUIDE", cacheFile);
977
- const ok = writeFileSafe(target, content);
978
- return { file: path.basename(target), status: ok ? "written" : "error" };
979
- }
980
-
981
- // ─── Skills MANIFEST stub (English static fallback) ────────
982
- // Pass 3c is expected to generate claudeos-core/skills/00.shared/MANIFEST.md,
983
- // but the stack pass3.md templates list it among generation targets without
984
- // marking it REQUIRED. On frontend-only or skill-sparse projects Claude may
985
- // omit it, leaving .claude/rules/50.sync/02.skills-sync.md (which names
986
- // MANIFEST.md as the single source of truth for skill registration) pointing
987
- // at a non-existent file. This gap-fill creates a minimal stub in Pass 4 if
988
- // the file is missing after Pass 3 completes same contract as
989
- // scaffoldDocWritingGuide (skip if exists, write English or translated stub).
990
- const SKILLS_MANIFEST_STUB = `# Skill Registry
991
-
992
- _Single source of truth for registered skills in this project._
993
- _Referenced by: \`.claude/rules/50.sync/02.skills-sync.md\`_
994
-
995
- ## How to register a skill
996
-
997
- When adding a new skill under \`claudeos-core/skills/\`, append an entry below
998
- with its path, purpose, and the orchestrator file that invokes it.
999
-
1000
- ## Registered skills
1001
-
1002
- | Skill | Orchestrator | Purpose |
1003
- |-------|-------------|---------|
1004
- | _(none registered yet)_ | — | — |
1005
-
1006
- ## Sync contract
1007
-
1008
- - When a skill file is added/renamed/deleted under \`claudeos-core/skills/\`,
1009
- update this manifest in the same commit.
1010
- - When this manifest is modified, \`.claude/rules/50.sync/02.skills-sync.md\`
1011
- is NOT modified — it references this file by path, not by content.
1012
- `;
1013
-
1014
- /**
1015
- * Create claudeos-core/skills/00.shared/MANIFEST.md if absent.
1016
- * Skip-safe: returns { status: "skipped" } when the file already exists with
1017
- * any non-trivial content.
1018
- *
1019
- * @param {string} skillsSharedDir - absolute path to .../claudeos-core/skills/00.shared
1020
- * @param {object} [opts]
1021
- * @param {boolean} [opts.overwrite=false]
1022
- * @param {string} [opts.lang="en"]
1023
- * @returns {{ file: string, status: string }}
1024
- */
1025
- function scaffoldSkillsManifest(skillsSharedDir, { overwrite = false, lang = "en" } = {}) {
1026
- ensureDir(skillsSharedDir);
1027
- const target = path.join(skillsSharedDir, "MANIFEST.md");
1028
- if (existsSafe(target) && !overwrite) {
1029
- // Guard against Pass 3c producing an empty MANIFEST.md only skip if it
1030
- // has real content (> 20 chars, trimming BOM/whitespace).
1031
- const current = readFileSafe(target, "");
1032
- const stripped = current.replace(/^\uFEFF/, "").trim();
1033
- if (stripped.length > 20) return { file: "MANIFEST.md", status: "skipped" };
1034
- }
1035
- const cacheFile = cachePathFor(skillsSharedDir, lang);
1036
- const content = translateIfNeeded(SKILLS_MANIFEST_STUB, lang, "SKILLS_MANIFEST_STUB", cacheFile);
1037
- const ok = writeFileSafe(target, content);
1038
- return { file: "MANIFEST.md", status: ok ? "written" : "error" };
1039
- }
1040
-
1041
- module.exports = {
1042
- MEMORY_FILES,
1043
- RULE_FILES_00,
1044
- RULE_FILES_60,
1045
- CLAUDE_MD_APPEND,
1046
- STANDARD_DOC_WRITING_GUIDE,
1047
- SKILLS_MANIFEST_STUB,
1048
- scaffoldMemory,
1049
- scaffoldRules,
1050
- appendClaudeMdL4Memory,
1051
- scaffoldMasterPlans,
1052
- scaffoldDocWritingGuide,
1053
- scaffoldSkillsManifest,
1054
- };
1
+ /**
2
+ * ClaudeOS-Core — Memory / Rule scaffold
3
+ *
4
+ * Creates initial L4 memory/ files, L4 rule files, and appends L4
5
+ * reference section to CLAUDE.md.
6
+ *
7
+ * Shared between Pass 4 generation fallback and the memory CLI command.
8
+ * All writes are idempotent-safe: callers decide whether to overwrite.
9
+ */
10
+
11
+ const path = require("path");
12
+ const fs = require("fs");
13
+ const { ensureDir, existsSafe, writeFileSafe, readFileSafe } = require("./safe-fs");
14
+
15
+ // ─── Language labels — single source of truth: lib/language-config.js ──
16
+ // Re-aliased as LANG_LABELS for the translation prompt context.
17
+ const { LANGUAGES: LANG_LABELS } = require("./language-config");
18
+
19
+ // ─── Translation cache ─────────────────────────────────────────
20
+ // Cache translated content on disk under claudeos-core/generated/ so
21
+ // repeated init runs don't re-translate the same static content.
22
+ // Cache file: fallback-cache-<lang>.json with shape { "<contentKey>": "<translatedText>" }.
23
+ // contentKey is a stable identifier like "MEMORY_FILES.decision-log.md" or
24
+ // "RULE_FILES_60.01.decision-log.md".
25
+ //
26
+ // Cache location is derived from the first directory argument passed to the
27
+ // scaffold functions (e.g. memoryDir ends with "claudeos-core/memory", so the
28
+ // cache root is its sibling "claudeos-core/generated/").
29
+ function cachePathFor(anyClaudeOsCoreDir, lang) {
30
+ // Walk up until we find a directory named "claudeos-core" or hit filesystem root.
31
+ let cur = path.resolve(anyClaudeOsCoreDir);
32
+ let steps = 0;
33
+ while (path.basename(cur) !== "claudeos-core" && cur !== path.dirname(cur) && steps < 10) {
34
+ cur = path.dirname(cur);
35
+ steps++;
36
+ }
37
+ // If we found claudeos-core, use its generated/ sibling. Otherwise, fall back
38
+ // to a temp-style cache inside the passed dir.
39
+ if (path.basename(cur) === "claudeos-core") {
40
+ return path.join(cur, "generated", `fallback-cache-${lang}.json`);
41
+ }
42
+ return path.join(anyClaudeOsCoreDir, `.fallback-cache-${lang}.json`);
43
+ }
44
+
45
+ function readCache(cacheFile) {
46
+ try {
47
+ if (!existsSafe(cacheFile)) return {};
48
+ return JSON.parse(readFileSafe(cacheFile, "{}")) || {};
49
+ } catch (_e) {
50
+ return {};
51
+ }
52
+ }
53
+
54
+ function writeCache(cacheFile, cache) {
55
+ try {
56
+ ensureDir(path.dirname(cacheFile));
57
+ writeFileSafe(cacheFile, JSON.stringify(cache, null, 2));
58
+ } catch (_e) { /* best-effort */ }
59
+ }
60
+
61
+ // Translate English static content to the requested language via Claude CLI.
62
+ //
63
+ // Behavior contract:
64
+ // - lang === "en" or unset → return English content as-is (no Claude call)
65
+ // - lang is supported → MUST translate. If translation fails, THROW an
66
+ // error with a clear message. We do NOT silently
67
+ // fall back to English, because the user
68
+ // explicitly chose a non-English lang and mixing
69
+ // English into that output is a correctness
70
+ // regression (bug #21).
71
+ // - lang is unknown/invalid → throw (defensive — CLI should have validated)
72
+ //
73
+ // A disk cache (claudeos-core/generated/fallback-cache-<lang>.json) skips
74
+ // re-translation across init runs.
75
+ function translateIfNeeded(englishContent, lang, contentKey, cacheFile) {
76
+ if (!lang || lang === "en") return englishContent;
77
+ if (!LANG_LABELS[lang]) {
78
+ throw new Error(
79
+ `memory-scaffold: unsupported lang='${lang}'. ` +
80
+ `Supported: ${Object.keys(LANG_LABELS).join(", ")}`
81
+ );
82
+ }
83
+
84
+ // M2: CI / deterministic-test escape hatch. When
85
+ // CLAUDEOS_SKIP_TRANSLATION=1 is set, throw instead of shelling out to
86
+ // `claude -p`. This makes the "translation fails without real Claude CLI"
87
+ // test family pass deterministically on dev machines where the CLI IS
88
+ // authenticated (previously the tests shelled out, got real translations,
89
+ // and their `assert.throws` fired). CI environments set this env var in
90
+ // their test step so they don't need `claude` installed at all.
91
+ if (process.env.CLAUDEOS_SKIP_TRANSLATION === "1") {
92
+ throw new Error(
93
+ `memory-scaffold: translation skipped for lang='${lang}' ` +
94
+ `(CLAUDEOS_SKIP_TRANSLATION=1). Unset this env var to translate via \`claude -p\`.`
95
+ );
96
+ }
97
+
98
+ // Cache hit → return immediately
99
+ const cache = readCache(cacheFile);
100
+ if (cache[contentKey] && typeof cache[contentKey] === "string" && cache[contentKey].trim().length > 0) {
101
+ return cache[contentKey];
102
+ }
103
+
104
+ // Lazy-load CLI utils to avoid a circular dependency at module-load time.
105
+ let runClaudeCapture;
106
+ try {
107
+ ({ runClaudeCapture } = require("../bin/lib/cli-utils"));
108
+ } catch (e) {
109
+ throw new Error(
110
+ `memory-scaffold: translation required for lang='${lang}' but CLI utils ` +
111
+ `could not be loaded: ${e.message}`
112
+ );
113
+ }
114
+ if (typeof runClaudeCapture !== "function") {
115
+ throw new Error(
116
+ `memory-scaffold: translation required for lang='${lang}' but ` +
117
+ `runClaudeCapture is not available`
118
+ );
119
+ }
120
+
121
+ const langLabel = LANG_LABELS[lang];
122
+ // Visible progress — translation can take 5-20s per file, user should see it.
123
+ process.stdout.write(` 🌐 Translating ${contentKey} → ${lang}...`);
124
+ const t0 = Date.now();
125
+
126
+ try {
127
+ return performTranslation(englishContent, lang, langLabel, contentKey, cache, cacheFile, runClaudeCapture, t0);
128
+ } catch (err) {
129
+ // Close the progress line before the exception bubbles up
130
+ process.stdout.write(` ❌\n`);
131
+ throw err;
132
+ }
133
+ }
134
+
135
+ // Extracted from translateIfNeeded so the caller can wrap the work in
136
+ // try/catch-with-log-cleanup without duplicating the logic.
137
+ function performTranslation(englishContent, lang, langLabel, contentKey, cache, cacheFile, runClaudeCapture, t0) {
138
+
139
+ // Translation prompt. Rules are strict because Claude's default behaviour
140
+ // is to over-paraphrase and sometimes drop code fences or frontmatter.
141
+ const prompt = `You are a professional technical translator. Translate the Markdown document below into ${langLabel}.
142
+
143
+ === ABSOLUTE RULES (violating any of these is a failure) ===
144
+
145
+ 1. PRESERVE Markdown structure BYTE-FOR-BYTE:
146
+ - Headings: same level (#, ##, ###, ####), same number, same order.
147
+ - Code fences: \`\`\` and ~~~ blocks — content inside code fences is NEVER translated. Preserve verbatim.
148
+ - Inline code: \`...\` — preserve verbatim (do not translate).
149
+ - Tables: keep the | separators and column count identical.
150
+ - Lists: preserve bullet style (-, *, 1.) and indentation.
151
+ - Bold/italic: **...**, *...*, _..._ — preserve markers, translate text inside.
152
+ - Blockquotes (>): preserve.
153
+ - Horizontal rules (---): preserve.
154
+ - Blank lines: preserve count and position.
155
+
156
+ 2. PRESERVE LITERALLY (DO NOT translate, DO NOT transliterate):
157
+ - YAML frontmatter keys: \`name:\`, \`paths:\`, \`---\` markers.
158
+ (The VALUE of \`name:\` MAY be translated if it's a human label.)
159
+ - All file paths: \`claudeos-core/memory/\`, \`.claude/rules/60.memory/\`, etc.
160
+ - All CLI commands: \`npx claudeos-core memory compact\`, \`npm install\`, etc.
161
+ - Path glob patterns: \`"**/*"\`, \`"src/**/*.java"\`, etc.
162
+ - CLI-parsed field keywords (these are parsed by code, translating breaks the tool):
163
+ * \`frequency:\`, \`count:\`, \`last seen:\`, \`importance:\` (failure-pattern fields)
164
+ * \`fix\`, \`solution\` (fix-field keywords)
165
+ * \`## Last Compaction\` (section heading parsed verbatim)
166
+ * \`(L4)\` token in headings (language-independent marker)
167
+ - Code identifiers, class names, method names, package names.
168
+ - URLs and email addresses.
169
+
170
+ 3. TRANSLATION QUALITY:
171
+ - Translate prose, comments, descriptions, table cell text, explanations.
172
+ - Use natural, professional ${langLabel}. NOT machine-translated style.
173
+ - Keep the document's tone (this is developer documentation — be precise and concise).
174
+ - Domain terms (e.g. "entry", "anchor", "confidence") should use natural ${langLabel} equivalents, not awkward literal translations.
175
+
176
+ 4. OUTPUT FORMAT:
177
+ - Output ONLY the translated Markdown document.
178
+ - NO preamble ("Here is the translation:", etc.).
179
+ - NO postamble ("Let me know if...", etc.).
180
+ - NO wrapping the output in a code fence.
181
+ - The FIRST character of your response must be the first character of the translated document.
182
+ - The LAST character of your response must be the last character of the translated document.
183
+
184
+ === DOCUMENT TO TRANSLATE ===
185
+ ${englishContent}
186
+ === END DOCUMENT ===
187
+
188
+ Translate now. Output only the translated document.`;
189
+
190
+ const raw = runClaudeCapture(prompt, { timeout: 180000 });
191
+ if (raw === null || typeof raw !== "string") {
192
+ throw new Error(
193
+ `memory-scaffold: Claude CLI call failed while translating '${contentKey}' to ${lang}. ` +
194
+ `Ensure \`claude\` CLI is available and authenticated.`
195
+ );
196
+ }
197
+
198
+ // Strip any stray "=== ... ===" markers or common preamble Claude may echo.
199
+ let cleaned = raw
200
+ .replace(/^===\s*DOCUMENT TO TRANSLATE\s*===\s*\n?/m, "")
201
+ .replace(/\n?===\s*END DOCUMENT\s*===\s*$/m, "")
202
+ .replace(/^---\s*BEGIN DOCUMENT\s*---\s*\n?/m, "")
203
+ .replace(/\n?---\s*END DOCUMENT\s*---\s*$/m, "")
204
+ .replace(/^\s*Here is the translation[^\n]*\n/i, "")
205
+ .replace(/^\s*```(?:markdown|md)?\s*\n/i, "")
206
+ .replace(/\n```\s*$/, "")
207
+ .trim();
208
+
209
+ // Validation: must have non-trivial content
210
+ if (cleaned.length < Math.max(50, englishContent.length * 0.4)) {
211
+ throw new Error(
212
+ `memory-scaffold: translation of '${contentKey}' to ${lang} is suspiciously short ` +
213
+ `(got ${cleaned.length} chars, expected at least ${Math.max(50, Math.floor(englishContent.length * 0.4))}). ` +
214
+ `Claude may have refused or returned only a preamble.`
215
+ );
216
+ }
217
+
218
+ // Validation: preserve key structural elements
219
+ const origHeadings = (englishContent.match(/^#{1,6}\s+/gm) || []).length;
220
+ const newHeadings = (cleaned.match(/^#{1,6}\s+/gm) || []).length;
221
+ if (origHeadings >= 3 && newHeadings < Math.ceil(origHeadings * 0.6)) {
222
+ throw new Error(
223
+ `memory-scaffold: translation of '${contentKey}' to ${lang} lost too many headings ` +
224
+ `(orig=${origHeadings}, new=${newHeadings}). Translation quality rejected.`
225
+ );
226
+ }
227
+
228
+ const origFences = (englishContent.match(/^```/gm) || []).length;
229
+ const newFences = (cleaned.match(/^```/gm) || []).length;
230
+ if (origFences > 0 && newFences !== origFences) {
231
+ throw new Error(
232
+ `memory-scaffold: translation of '${contentKey}' to ${lang} broke code fences ` +
233
+ `(orig=${origFences}, new=${newFences}). Translation quality rejected.`
234
+ );
235
+ }
236
+
237
+ // Validation: CLI-parsed keywords must survive verbatim (they are parsed by
238
+ // the memory CLI — if translated they break the tool silently).
239
+ const MUST_PRESERVE = ["frequency:", "last seen:", "importance:", "(L4)"];
240
+ for (const kw of MUST_PRESERVE) {
241
+ if (englishContent.includes(kw) && !cleaned.includes(kw)) {
242
+ throw new Error(
243
+ `memory-scaffold: translation of '${contentKey}' to ${lang} lost required ` +
244
+ `keyword '${kw}' which must be preserved literally (CLI parser depends on it).`
245
+ );
246
+ }
247
+ }
248
+
249
+ // Validation: frontmatter boundary markers must match original count
250
+ const origFrontmatter = (englishContent.match(/^---\s*$/gm) || []).length;
251
+ const newFrontmatter = (cleaned.match(/^---\s*$/gm) || []).length;
252
+ if (origFrontmatter > 0 && newFrontmatter !== origFrontmatter) {
253
+ throw new Error(
254
+ `memory-scaffold: translation of '${contentKey}' to ${lang} broke YAML frontmatter ` +
255
+ `markers (orig=${origFrontmatter}, new=${newFrontmatter}).`
256
+ );
257
+ }
258
+
259
+ // Success — save to cache for future init runs
260
+ cache[contentKey] = cleaned;
261
+ writeCache(cacheFile, cache);
262
+
263
+ const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
264
+ process.stdout.write(` ✅ (${elapsed}s)\n`);
265
+
266
+ return cleaned;
267
+ }
268
+
269
+ // ─── L4 Memory files ───────────────────────────────────────────
270
+ const MEMORY_FILES = {
271
+ "decision-log.md": `# Decision Log
272
+
273
+ _Permanent record of "why" behind design choices. Append-only._
274
+ _Format: \`## YYYY-MM-DD — <Title>\` then Context / Options / Decision / Consequences._
275
+ `,
276
+
277
+ "failure-patterns.md": `# Failure Patterns
278
+
279
+ _Recurring errors and their fixes. Importance auto-scored by \`npx claudeos-core memory score\`._
280
+ _Format: \`## <pattern-id>\` with Frequency / Last Seen / Importance / Fix._
281
+ `,
282
+
283
+ "compaction.md": `# Compaction Strategy
284
+
285
+ _4-stage compaction rules for \`decision-log.md\` and \`failure-patterns.md\`._
286
+ _Run via \`npx claudeos-core memory compact\`._
287
+
288
+ ## Preservation Priority
289
+ Entries are preserved if ANY of:
290
+ - \`importance >= 7\`
291
+ - \`lastSeen\` within 30 days
292
+ - Referenced by an active rule (path listed in rule-manifest.json)
293
+
294
+ ## Stages
295
+
296
+ ### Stage 1 — Summarize aged entries
297
+ Entries older than 30 days with no recent reference are summarized:
298
+ - Keep: pattern-id, frequency, one-line fix summary
299
+ - Drop: verbose context, full stack traces
300
+
301
+ ### Stage 2 — Merge duplicate patterns
302
+ Failure entries with the same root cause are merged:
303
+ - \`frequency = sum\`
304
+ - \`lastSeen = max\`
305
+ - \`fix\` unified to the most recent working solution
306
+
307
+ ### Stage 3 — Drop low-importance entries
308
+ Entries with \`importance < 3\` AND \`lastSeen > 60 days\` are removed.
309
+
310
+ ### Stage 4 — Enforce file size cap
311
+ Each target file is capped at 400 lines.
312
+ When exceeded, the oldest (by \`lastSeen\`) low-importance entries are dropped first.
313
+
314
+ ## Last Compaction
315
+ (never — run \`npx claudeos-core memory compact\`)
316
+ `,
317
+
318
+ "auto-rule-update.md": `# Auto Rule Update Proposals
319
+
320
+ _Generated by \`npx claudeos-core memory propose-rules\`._
321
+ _Each proposal: failure pattern → affected rule → diff → confidence._
322
+
323
+ ## How to apply
324
+ 1. Review each proposal below.
325
+ 2. If accepted, edit the affected rule file and commit.
326
+ 3. Move the accepted proposal into \`decision-log.md\` as a record.
327
+
328
+ ## Proposals
329
+ (none yet — run \`npx claudeos-core memory propose-rules\` after accumulating failure patterns)
330
+ `,
331
+ };
332
+
333
+ // ─── 00.core additional rule files (always scaffolded) ─────────
334
+ const RULE_FILES_00 = {
335
+ "51.doc-writing-rules.md": `---
336
+ name: Document Writing Rules
337
+ paths:
338
+ - "**/*"
339
+ ---
340
+
341
+ # Standard / Rules / Skills Document Writing Rules
342
+
343
+ ## [CRITICAL] Rules File paths Frontmatter Required
344
+
345
+ Every file in \`.claude/rules/\` MUST include a \`paths\` field in its YAML frontmatter. Without \`paths\`, Claude Code cannot determine when to load the rule.
346
+
347
+ - Set \`paths\` to match the **file patterns where the rule is actually needed**.
348
+ - Example: document writing rules → \`"**/claudeos-core/**"\`, \`"**/.claude/**"\` (not needed during code editing)
349
+ - Example: coding conventions → \`"**/*"\` (applies to all code)
350
+ - Do NOT propose narrowing core rules from \`"**/*"\` to specific patterns like \`src/**/*.tsx\` — this increases management complexity and risks rules not loading when needed.
351
+
352
+ ## [CRITICAL] No Domain-Specific Hardcoding
353
+
354
+ When adding or modifying rules in \`claudeos-core/standard/\`, \`.claude/rules/\`, or \`claudeos-core/skills/\`, **never hardcode project-specific domain names**. Always write in generic, reusable patterns.
355
+
356
+ ### Prohibited
357
+
358
+ - Specific table names (e.g., \`user_account\`, \`st_ntc_base\`)
359
+ - Specific URL paths (e.g., \`/notice/getList\`, \`/api/v1/orders\`)
360
+ - Specific domain codes (e.g., \`NOTICE\`, \`ORDER\`, \`SYSTEM\`)
361
+ - Specific DTO/Entity class names (e.g., \`GetOrderListReqDto\`)
362
+
363
+ ### Correct Approach
364
+
365
+ | Item | Wrong | Correct |
366
+ |------|-------|---------|
367
+ | Path key | \`ORDER: /api/orders\` | \`{DOMAIN_KEY}: /{category}/{domain}\` |
368
+ | Table | \`user_account\` | \`{prefix}_{table_name}\` |
369
+ | URL | \`/notice/getList\` | \`/{domain}/{action}\` |
370
+ | DTO | \`GetOrderListReqDto\` | \`{Action}{Entity}ReqDto\` |
371
+
372
+ ### Allowed Exceptions
373
+
374
+ - **Project-wide common fields**: audit columns, base classes, and fields used across ALL domains
375
+ - **Framework/infrastructure names**: \`BaseEntity\`, \`SecurityConfig\`, framework annotations
376
+ - **Existing domain listing**: only when explaining how to ADD NEW domains (configuration examples)
377
+
378
+ ### Rationale
379
+
380
+ These documents are project-wide **common rules**. If specific domain names appear, developers working on other domains may ignore the rules as irrelevant. All developers must follow the same rules — write generically.
381
+
382
+ ## [CRITICAL] No System Absolute Path Hardcoding
383
+
384
+ **Never hardcode system absolute paths** (\`/Users/xxx/\`, \`/home/xxx/\`, \`C:\\\\Users\\\\xxx\\\\\`) in documents. User names and machine-specific paths are environment-dependent. Always use the current working directory or project-relative paths instead.
385
+
386
+ ## [CRITICAL] Code Examples Must Reflect Actual Project Structure
387
+
388
+ When writing code examples in documents (file paths, import statements, directory tree diagrams), **verify against the actual project structure** before writing. Do not guess or invent fictional paths. If unsure, check the real directory layout first.
389
+
390
+ ## Reference
391
+ - claudeos-core/standard/00.core/*doc-writing-guide.md
392
+ `,
393
+
394
+ "52.ai-work-rules.md": `---
395
+ name: AI Work Rules
396
+ paths:
397
+ - "**/*"
398
+ ---
399
+
400
+ # AI Work Rules
401
+
402
+ > **IMPORTANT: Rules that AI must follow in this project.**
403
+
404
+ ## Accuracy First
405
+
406
+ - **Accuracy over token saving.** Never skip file verification or code validation steps.
407
+ - **Always read and judge critical facts directly** (file paths, version numbers, API signatures, schema definitions). Sub-agents can explore and summarize, but their summaries must not replace direct verification of facts that affect the code you write.
408
+ - **Verify file paths before writing them in documents.** Never record a path that does not exist on disk.
409
+ - **No flattery, no exaggeration.** If uncertain, say "verification needed" — do not be confidently wrong.
410
+
411
+ ## Safety & Security
412
+
413
+ > **CRITICAL: These rules override every other rule in this file. Violations cause data loss, security breaches, or unauthorized publication.**
414
+
415
+ - **Destructive commands require explicit user confirmation in this conversation.** Never run \`rm -rf\`, \`git reset --hard\`, \`git push --force\`, \`git branch -D\`, \`git clean -fd\`, \`DROP TABLE\`/\`TRUNCATE\`, \`npm publish\`/\`mvn deploy\`/\`pip publish\`, migration \`down\`/\`revert\` commands, or equivalents without the user explicitly approving the exact command. Authorization for one destructive command is NOT general authorization — re-confirm each time.
416
+ - **Never echo, log, write to comments, or commit values from secret files.** Files: \`.env*\`, \`secrets/\`, \`*.pem\`, \`*.key\`, \`id_rsa*\`, credentials JSON, service account files. Reference secrets by variable name only (e.g., \`process.env.DB_PASSWORD\`, not the actual value). Never quote secret values in error messages, chat responses, or test fixtures.
417
+
418
+ ## Hallucination Prevention
419
+
420
+ Before analysis or evaluation, review this table and do not repeat these patterns.
421
+
422
+ | # | Prohibited Pattern | Explanation |
423
+ |---|-------------------|-------------|
424
+ | 1 | Labeling DO NOT Read files as "token waste" or "unnecessary" | Blocked from reading ≠ unnecessary. DO NOT Read means "AI should not read directly", not "the file has no value" |
425
+ | 2 | Labeling intentional design as "inefficient" or "redundant" | Ask "why was it designed this way?" before suggesting changes |
426
+ | 3 | Labeling intentional summary-to-detail layering as "duplication" | Multi-layer design (anchor → rules → standard) is intentional — each layer has a different density and role |
427
+ | 4 | Judging source values as "serious inconsistency" without checking the primary source | Always verify against the actual source file |
428
+ | 5 | Repeating a hallucination already recorded in this project | Check this table + \`memory/failure-patterns.md\` before analysis |
429
+ | 6 | Proposing path scoping changes for intentional \`**/*\` designs | Confirm the intent first |
430
+ | 7 | Labeling code examples in rules as "excessive" | Code examples are essential for AI-assisted code generation — they reduce hallucination risk regardless of audience experience |
431
+ | 8 | Making quantitative judgments based on unverified numbers, then reversing when challenged | No speculation-based quantitative claims |
432
+ | 9 | Judging a standard document as "low practical value" without reading it | No judgment before verification |
433
+ | 10 | Proposing to merge/reduce same-layer intentional duplication | Different perspectives on the same topic in different files is intentional. Rule accessibility > token saving |
434
+ | 11 | Suggesting an import or package name without verifying it exists in the dependency manifest | Hallucinated module/named export. Verify by reading \`package.json\` / \`pom.xml\` / \`build.gradle\` / \`pyproject.toml\` / \`requirements.txt\` before recommending an import |
435
+ | 12 | Mixing API signatures from different major versions of the same library | Verify by checking the manifest AND lockfile for the exact installed version (lockfile pins the truth): \`package-lock.json\`/\`pnpm-lock.yaml\`/\`yarn.lock\`, \`gradle.lockfile\`/\`gradle/libs.versions.toml\`, \`poetry.lock\`/\`Pipfile.lock\`/\`uv.lock\`, or fall back to the manifest (\`pom.xml\`/\`build.gradle\`/\`package.json\`/\`pyproject.toml\`) |
436
+ | 13 | Editing one environment config file without checking sibling parity | Verify by \`Glob\` for the config family before a partial edit. Backend: \`.env*\`, \`application-*.yml/.properties\`, \`*settings.py\`. Frontend: \`environment*.ts\` (Angular), \`next.config.*\`, \`vite.config.*\`, \`nuxt.config.*\`, \`.env.local\`/\`.env.production\` |
437
+ | 14 | Mixing server/client component boundaries (SSR frameworks) — using client-only APIs (\`useState\`, \`useEffect\`, \`window\`, \`localStorage\`) in a server component, or server-only operations (DB access, secret reads, filesystem) in a client component | Read the file's boundary directive before adding code: Next.js App Router (\`"use client"\` opt-in), Nuxt (server vs client composables), Remix (\`loader\`/\`action\` exports). N/A for pure SPA or pure backend projects |
438
+ | 15 | Inventing component prop names or function arguments without reading the target's interface | Read the target's prop type definition (\`interface Props\`, \`defineProps<>\`, function signature) or method signature before invoking. Hallucinated props may compile in loose-TS code and crash at runtime |
439
+ | 16 | Hardcoding API keys, tokens, passwords, or DB credentials in source code — even in tests, examples, fixtures, or commit messages | Verify by \`Grep\` for patterns like \`(api[_-]?key\|token\|password\|secret)\\s*=\\s*["']\\w+["']\` before committing. Use env vars (\`process.env.X\`/\`os.getenv("X")\`/\`@Value("\${X}")\`), secret managers, or \`.env.example\` placeholders instead |
440
+ | 17 | Editing historical database migration files after they've been applied | Migration files (\`migrations/V*.sql\` (Flyway), \`alembic/versions/*.py\`, \`db/migrate/*.rb\` (Rails), \`prisma/migrations/*/migration.sql\`, \`migrations/*.ts\` (TypeORM)) are append-only once applied. Add a NEW migration to revert/modify; never edit historical ones. Verify by checking migration history (\`flyway info\`, \`alembic history\`, \`prisma migrate status\`) before editing |
441
+
442
+ **Core Principle:**
443
+ - Do not label a system built by the designer as "inefficient", "redundant", or "needs optimization" — **confirm the intent first**
444
+ - When evaluating system structure, first ask "why was it built this way?"
445
+ - Before pointing out problems, check whether they are already solved or intentionally designed
446
+
447
+ ## No Unsolicited Work
448
+
449
+ - **Do not make unsolicited suggestions.** If uncertain, ask instead of suggesting. *Exception: factual errors in this project's own docs (wrong file paths, dead references, internally contradicting rules) should be reported even if not asked. Distinguish factual errors (report) from stylistic preferences (stay silent).*
450
+ - **Do not modify onboarding/guide documents (\`claudeos-core/guide/\`) unless specifically requested.**
451
+ - Do not clean up surrounding code during bug fixes, or add unnecessary refactoring during feature additions.
452
+ - **Empty directories may be intentional placeholders — verify markers before flagging or removing.** Markers of intent: a \`.gitkeep\` / \`KEEP_EMPTY.md\` file inside, the directory listed in CLAUDE.md as planned, or referenced by an active plan/standard/skills document. If none of these exist, an empty directory may be neglect — ask the user before deleting.
453
+ - **\`plan/\` master documents are internal sync management tools.** Do not suggest removing them. "DO NOT Read" means "AI should not read directly", not "the file is unnecessary".
454
+ - **Do not duplicate into memory what is already directly verifiable in code, config files, or rule documents.** Configuration values, paths, and names already recorded in CLAUDE.md, rules, or standard must not be redundantly stored in memory. Examples — backend: port numbers, pool sizes, handler names, transaction propagation modes; frontend: dev server port, build output dir, env var prefix (\`VITE_\`/\`NEXT_PUBLIC_\`/\`REACT_APP_\`), route definitions, bundle size budgets.
455
+ - **Do not directly read internal document directories (\`guide/\`, \`plan/\`, \`generated/\`, \`mcp-guide/\`) for routine context loading.** \`.claude/rules/\` and \`claudeos-core/standard/\` already contain the essential content. *Exception: read directly when the user explicitly asks about these contents, or when debugging an issue requires inspecting them.*
456
+ - **Established codebase conventions take precedence over textbook-ideal patterns.** Propose modernization, refactoring, or "current best practices" migration ONLY when the user explicitly requests it (e.g., "modernize", "migrate to v3", "refactor to current best practices"). Otherwise, follow the existing pattern even if you would write it differently in a greenfield project.
457
+
458
+ ## Project Architecture — Hands Off
459
+
460
+ This project uses the CLAUDE.md → rules → standard 3-layer architecture, plus a separate L4 Memory layer. Understand these design principles:
461
+
462
+ - **Cross-layer summary/detail duplication is intentional.** Each layer has a different role: CLAUDE.md (anchor/index, always loaded) → rules (detailed rules, conditionally loaded by path) → standard (original specification, referenced when needed). The same topic across layers is layer-appropriate density, not duplication.
463
+ - **Same-layer duplication across files is also intentional.** Each file covers a different perspective (DB design, code implementation, DTO design, etc.). Do not propose "consolidating into one file because it's the same layer".
464
+ - **Memory (\`claudeos-core/memory/\`, on-demand) and Rules (\`.claude/rules/\`, auto-loaded by path match) are never simultaneously loaded by default.** Similar content between them is NOT duplication. Do not propose "memory cleanup", "dedupe memory vs rules", or "consolidate memory into rules" — they have different roles (on-demand history/context vs auto-loaded enforcement).
465
+ - **Multi-rule load provides reinforcement.** Do not label co-loaded defensive rules as "redundant" — the reinforcement effect is intentional and the context cost is negligible.
466
+ - **Rules \`paths: ["**/*"]\` — do not propose conditional path conversion for core rules.** When developing new features (no matching files exist yet), conditional paths would prevent rules from loading, risking non-standard code generation.
467
+ - **\`00.standard-reference.md\` index additions — avoid unless specifically requested.** Each rules file already links to its corresponding standard via the \`## Reference\` section. Adding paths to the index only consumes additional tokens per conversation.
468
+ - **Minor wording or item count differences across layers are NOT "inconsistency risks".** If no information is missing, trivial expression differences are not a problem.
469
+
470
+ ## Planned References — No "Missing" Judgment
471
+
472
+ - Paths and directories referenced in CLAUDE.md, Rules, Standard, or Skills documents **may not yet exist on disk**.
473
+ - These are **planned references for future implementation** — intentional forward declarations.
474
+ - Do NOT label them as "missing", "inconsistent", "stale", or "needs deletion". *Exception: if a referenced path appears in 3+ documents and doesn't exist on disk, it may be a typo masquerading as a planned reference — flag for human review (consistent with §"No Unsolicited Work" Exception for factual errors in own docs).*
475
+ - Do NOT propose removing or modifying these references. Preserve them as-is.
476
+
477
+ ## Code/Document Generation Accuracy
478
+
479
+ - **Before writing new code, read 2-3 neighboring files in the same directory for existing patterns** — naming conventions, error handling, logging style, import order, return type idioms, test structure. Match what you find rather than introducing new patterns. Greenfield/textbook idioms come second to in-codebase consistency.
480
+ - **Do not guess framework class/type/component shapes — check actual source code.** Backend: base classes, DTOs, entity field naming, repository method signatures. Frontend: component prop interfaces, store/state shapes (Pinia/Redux/Zustand), API response types, route param types, CSS module class names.
481
+ - **When modifying skills/standard/rules/memory documents, keep related files in sync.** If a standard changes, update its rule file; if a skill changes, update \`MANIFEST.md\`. If CLAUDE.md summary sections cover the same topic, update them together.
482
+ `,
483
+ };
484
+
485
+ // ─── L4 Rule files (English static fallback) ────────────────
486
+ const RULE_FILES_60 = {
487
+ "01.decision-log.md": `---
488
+ name: Decision Log
489
+ paths:
490
+ - "claudeos-core/memory/decision-log.md"
491
+ ---
492
+
493
+ # Decision Log (\`memory/decision-log.md\`)
494
+
495
+ Permanent, append-only record of architectural decisions and their rationale.
496
+ Commit this file to version control — it is team knowledge.
497
+
498
+ ## Read timing
499
+
500
+ - **Session start** — skim recent entries to understand past design rationale.
501
+ - **Before suggesting architectural changes** — check if a prior decision already addressed this.
502
+
503
+ ## Write timing
504
+
505
+ Append a new entry when:
506
+ - Choosing between competing patterns
507
+ - Selecting a library or framework
508
+ - Defining a convention the team must follow
509
+ - Deciding NOT to do something
510
+
511
+ ## Entry format
512
+
513
+ \`\`\`markdown
514
+ ## YYYY-MM-DD — <Short title>
515
+
516
+ - **Context:** why this decision was needed
517
+ - **Options considered:** what alternatives existed
518
+ - **Decision:** what was chosen and why
519
+ - **Consequences:** what this locks in, trade-offs accepted
520
+ \`\`\`
521
+
522
+ ## Rules
523
+
524
+ - Always use the actual current date (UTC, YYYY-MM-DD).
525
+ - Never edit or delete existing entries. This is append-only.
526
+ - Keep entries concise — 5~10 lines max.
527
+ `,
528
+
529
+ "02.failure-patterns.md": `---
530
+ name: Failure Patterns
531
+ paths:
532
+ - "claudeos-core/memory/failure-patterns.md"
533
+ ---
534
+
535
+ # Failure Patterns (\`memory/failure-patterns.md\`)
536
+
537
+ Registry of recurring errors, their root causes, and fixes.
538
+ Importance is auto-scored by \`npx claudeos-core memory score\` (frequency x recency).
539
+ Commit this file — it prevents the team from hitting the same errors repeatedly.
540
+
541
+ ## Read timing
542
+
543
+ - **Session start** — scan high-importance entries (importance >= 7).
544
+ - **When encountering an error** — search this file first. Apply the recorded fix if a match exists.
545
+
546
+ ## Write timing
547
+
548
+ Append when:
549
+ - You encounter an error for the **second time**.
550
+ - You discover a non-obvious root cause.
551
+ - A workaround exists that is not documented elsewhere.
552
+
553
+ ## Entry format
554
+
555
+ \`\`\`markdown
556
+ ## <pattern-id>
557
+
558
+ - **frequency:** 1
559
+ - **last seen:** YYYY-MM-DD
560
+ - **symptoms:** what the error looks like
561
+ - **root cause:** why it happens
562
+ - **fix:** step-by-step resolution
563
+ \`\`\`
564
+
565
+ ## Rules
566
+
567
+ - Use a descriptive \`pattern-id\`.
568
+ - When encountering a known pattern again, increment \`frequency\` and update \`last seen\`.
569
+ - Never delete entries manually — use \`npx claudeos-core memory compact\`.
570
+ `,
571
+
572
+ "03.compaction.md": `---
573
+ name: Compaction Strategy
574
+ paths:
575
+ - "claudeos-core/memory/compaction.md"
576
+ ---
577
+
578
+ # Compaction Strategy (\`memory/compaction.md\`)
579
+
580
+ Reference document defining the 4-stage compaction policy.
581
+ Executed by \`npx claudeos-core memory compact\`.
582
+
583
+ ## Rules
584
+
585
+ - Do NOT edit unless intentionally changing the compaction policy.
586
+ - Do NOT run compaction logic manually — always use the CLI command.
587
+
588
+ ## 4 stages (reference)
589
+
590
+ 1. **Summarize aged** — entries >30 days, body replaced with one-line summary
591
+ 2. **Merge duplicates** — same heading, frequency summed, latest fix kept
592
+ 3. **Drop low-importance** — importance <3 AND lastSeen >60 days removed
593
+ 4. **Enforce cap** — 400 lines max per file, oldest low-importance entries dropped first
594
+
595
+ ## Preservation
596
+
597
+ Entries preserved if ANY of: importance >= 7, lastSeen within 30 days, referenced by active rule.
598
+ `,
599
+
600
+ "04.auto-rule-update.md": `---
601
+ name: Auto Rule Update
602
+ paths:
603
+ - "claudeos-core/memory/auto-rule-update.md"
604
+ ---
605
+
606
+ # Auto Rule Update (\`memory/auto-rule-update.md\`)
607
+
608
+ Machine-generated rule improvement proposals based on recurring failure patterns (frequency >= 3).
609
+ Generated by \`npx claudeos-core memory propose-rules\`.
610
+
611
+ ## Read timing
612
+
613
+ - **When proposals exist** — review them before starting work.
614
+
615
+ ## Action workflow
616
+
617
+ 1. Read the proposal: which failure pattern triggered it, which rule is affected, confidence score.
618
+ 2. If accepted: edit the affected rule file to address the pattern.
619
+ 3. After editing: move the accepted proposal into \`decision-log.md\` as a permanent record.
620
+ 4. If rejected: add a brief note explaining why.
621
+
622
+ ## Rules
623
+
624
+ - Do NOT edit proposals directly — they are machine-generated references.
625
+ - Proposals with confidence >= 0.70 deserve serious consideration.
626
+ `,
627
+ };
628
+
629
+ // ─── CLAUDE.md append block (English static fallback) ──────────
630
+ const CLAUDE_MD_APPEND = `
631
+ ## Memory (L4)
632
+
633
+ This project uses the ClaudeOS-Core L4 Memory layer for persistent team knowledge.
634
+
635
+ ### Common rules (\`.claude/rules/00.core/\`)
636
+
637
+ | File | Purpose |
638
+ |---|---|
639
+ | \`51.doc-writing-rules.md\` | Rules paths frontmatter, no domain/path hardcoding, code examples must reflect actual structure |
640
+ | \`52.ai-work-rules.md\` | AI accuracy, hallucination prevention, 3-layer design, memory vs rules separation, planned references |
641
+
642
+ ### L4 Memory — persistent team knowledge (\`claudeos-core/memory/\`)
643
+
644
+ Detailed rules: \`.claude/rules/60.memory/\` (4 rules).
645
+
646
+ | File | Purpose | Action |
647
+ |---|---|---|
648
+ | \`decision-log.md\` | "Why" behind architectural choices | Read at session start; append when making decisions |
649
+ | \`failure-patterns.md\` | Recurring errors & fixes (auto-scored) | Scan at session start; append on repeat errors |
650
+ | \`compaction.md\` | 4-stage compaction policy reference | Read-only (edit only to change policy) |
651
+ | \`auto-rule-update.md\` | Rule improvement proposals (freq >= 3) | Review proposals; accept -> edit rule + record in decision-log |
652
+
653
+ ### Memory workflow
654
+
655
+ 1. Scan \`memory/failure-patterns.md\` at session start -> avoid known pitfalls
656
+ 2. Skim recent \`memory/decision-log.md\` entries -> understand past design rationale
657
+ 3. Record decisions -> append to \`memory/decision-log.md\`
658
+ 4. Record repeat errors (2nd occurrence) -> append to \`memory/failure-patterns.md\`
659
+ 5. Periodically run \`npx claudeos-core memory compact\` to enforce the 4-stage compaction policy
660
+ 6. When \`auto-rule-update.md\` has proposals with confidence >= 0.70, review and act
661
+ `;
662
+
663
+ // ─── Scaffold functions ────────────────────────────────────────
664
+
665
+ function scaffoldMemory(memoryDir, { overwrite = false, lang = "en" } = {}) {
666
+ ensureDir(memoryDir);
667
+ const cacheFile = cachePathFor(memoryDir, lang);
668
+ const results = [];
669
+ for (const [name, body] of Object.entries(MEMORY_FILES)) {
670
+ const full = path.join(memoryDir, name);
671
+ if (!overwrite && existsSafe(full)) {
672
+ results.push({ file: name, status: "skipped" });
673
+ continue;
674
+ }
675
+ const content = translateIfNeeded(body, lang, `MEMORY_FILES.${name}`, cacheFile);
676
+ const ok = writeFileSafe(full, content);
677
+ results.push({ file: name, status: ok ? "written" : "error" });
678
+ }
679
+ return results;
680
+ }
681
+
682
+ /**
683
+ * Scaffold L4 memory rule files + 00.core common rules (English static fallback).
684
+ * Used when Pass 4 Claude prompt fails or is unavailable.
685
+ * 00.core rules are always scaffolded (gap-fill only, never overwrite Pass 3 output).
686
+ */
687
+ function scaffoldRules(rulesBaseDir, { overwrite = false, lang = "en" } = {}) {
688
+ const cacheFile = cachePathFor(rulesBaseDir, lang);
689
+ const results = [];
690
+ const dirs = {
691
+ "00.core": RULE_FILES_00,
692
+ "60.memory": RULE_FILES_60,
693
+ };
694
+ for (const [dirName, files] of Object.entries(dirs)) {
695
+ const dir = path.join(rulesBaseDir, dirName);
696
+ ensureDir(dir);
697
+ for (const [name, body] of Object.entries(files)) {
698
+ const full = path.join(dir, name);
699
+ if (!overwrite && existsSafe(full)) {
700
+ results.push({ file: `${dirName}/${name}`, status: "skipped" });
701
+ continue;
702
+ }
703
+ const content = translateIfNeeded(body, lang, `RULE_FILES.${dirName}.${name}`, cacheFile);
704
+ const ok = writeFileSafe(full, content);
705
+ results.push({ file: `${dirName}/${name}`, status: ok ? "written" : "error" });
706
+ }
707
+ }
708
+ return results;
709
+ }
710
+
711
+ /**
712
+ * Append L4 Memory section to CLAUDE.md.
713
+ *
714
+ * DEPRECATED (v2.3.0): this function is now a no-op. It formerly
715
+ * appended a `## N. Memory (L4)` section to CLAUDE.md as a static
716
+ * fallback when Pass 4 failed to. That append path duplicated content
717
+ * the current Pass 3 scaffold already emits inside Section 8 ("Common
718
+ * Rules & Memory (L4)"), producing a 9-section CLAUDE.md with every
719
+ * memory file listed in two separate tables — the exact
720
+ * `[S1]`/`[M-*]`/`[F2-*]` anti-patterns the v2.3.0 validator flags.
721
+ *
722
+ * The claude-md-validator and content-validator pair together enforce
723
+ * "Section 8 is the single canonical place for memory content", so
724
+ * the fallback append is both unnecessary (Pass 3 already did it) and
725
+ * actively harmful (re-declaration).
726
+ *
727
+ * Signature is preserved so any caller that was wired up before v2.3.0
728
+ * continues to work; the function now returns `true` unconditionally
729
+ * to keep the caller's summary reporting untouched (the semantic was
730
+ * "present or appended" — under the new regime the section is always
731
+ * present, courtesy of Pass 3).
732
+ *
733
+ * @param {string} _claudeMdPath (unused)
734
+ * @param {object} [_opts] (unused)
735
+ * @returns {boolean} always true
736
+ */
737
+ function appendClaudeMdL4Memory(_claudeMdPath, _opts = {}) {
738
+ return true;
739
+ }
740
+
741
+ /**
742
+ * Scaffold master plan file for L4 Memory.
743
+ *
744
+ * DEPRECATED: master plan generation was removed from claudeos-core because
745
+ * master plans are internal tool backup files that are not consumed by Claude
746
+ * Code at runtime, and generating them required aggregating many files in a
747
+ * single session (which could trigger "Prompt is too long" on mid-sized
748
+ * projects). This function is now a no-op that returns an empty result list.
749
+ * Kept as an export for backward compatibility with existing callers.
750
+ *
751
+ * @param {string} planDir - path to claudeos-core/plan/ (unused)
752
+ * @param {string} memoryDir - path to claudeos-core/memory/ (unused)
753
+ * @param {object} [opts] (unused)
754
+ * @returns {Array} always empty (no-op)
755
+ */
756
+ function scaffoldMasterPlans(_planDir, _memoryDir, _opts = {}) {
757
+ return [];
758
+ }
759
+
760
+ // ─── Standard doc-writing-guide (English static fallback) ───
761
+ const STANDARD_DOC_WRITING_GUIDE = `# Standard / Rules / Skills Document Writing Guide
762
+
763
+ > This document is the detailed guide for writing and modifying ClaudeOS documentation (Standard, Rules, Skills).
764
+ > For enforcement rules (loaded automatically), see: .claude/rules/00.core/51.doc-writing-rules.md
765
+
766
+ ---
767
+
768
+ ## 1. Document Layer Structure
769
+
770
+ | Layer | Path | Role | Loading |
771
+ |-------|------|------|---------|
772
+ | CLAUDE.md | \`CLAUDE.md\` | Entry point overview | Auto-loaded every conversation |
773
+ | Rules | \`.claude/rules/\` | Enforcement summary | Conditionally loaded by \`paths\` pattern match |
774
+ | Standard | \`claudeos-core/standard/\` | Detailed guide | Manually Read via Rules \`## Reference\` links |
775
+ | Skills | \`claudeos-core/skills/\` | Scaffolding automation | Registered in MANIFEST.md |
776
+ | Memory | \`claudeos-core/memory/\` | Persistent team knowledge | On-demand Read only |
777
+
778
+ ### Layer relationships
779
+
780
+ \`\`\`
781
+ CLAUDE.md (overview) Rules (enforcement) Standard (detailed)
782
+ Reference link
783
+ \`\`\`
784
+
785
+ - **CLAUDE.md ↔ Rules ↔ Standard content overlap is NOT duplication.** Each layer has a different role and density.
786
+ - **Memory and Rules/CLAUDE.md content overlap is NOT duplication.** Memory is on-demand loaded, Rules are auto-loaded. Different loading mechanisms.
787
+
788
+ ---
789
+
790
+ ## 2. Rules File Writing Rules
791
+
792
+ ### [CRITICAL] paths frontmatter required
793
+
794
+ Every \`.claude/rules/\` file MUST have \`paths\` in YAML frontmatter. Without it, Claude Code cannot determine when to load the rule.
795
+
796
+ \`\`\`markdown
797
+ ---
798
+ paths:
799
+ - "**/*"
800
+ ---
801
+ # Rule Title
802
+ \`\`\`
803
+
804
+ ### paths scope settings
805
+
806
+ | Scope | paths | Examples |
807
+ |-------|-------|---------|
808
+ | All code files | \`"**/*"\` | Architecture, naming, coding conventions |
809
+ | Document files only | \`"**/claudeos-core/**"\`, \`"**/.claude/**"\` | Document writing rules |
810
+ | Config files only | \`"**/*.json"\`, \`"**/*.env*"\`, \`"**/*.yml"\` | Environment/config rules |
811
+ | Specific directory | \`"**/claudeos-core/**"\`, \`"**/.claude/**"\` | Sync rules |
812
+
813
+ Do NOT propose narrowing core rules \`"**/*"\` to specific patterns — this increases management complexity and risks rules not loading when needed.
814
+
815
+ ### Rules file structure
816
+
817
+ \`\`\`markdown
818
+ ---
819
+ paths:
820
+ - "pattern"
821
+ ---
822
+ # Rule Title
823
+
824
+ - Rule items (bullet points)
825
+ - Code examples recommended
826
+
827
+ ## Reference
828
+ - claudeos-core/standard/XX.category/YY.name.md
829
+ \`\`\`
830
+
831
+ - **Write concisely**: detailed content goes in Standard, Rules are enforcement summary only.
832
+ - **\`## Reference\` required**: always link to the corresponding Standard document.
833
+ - Do not judge short Rules files as "needs expansion".
834
+
835
+ ---
836
+
837
+ ## 3. Standard File Writing Rules
838
+
839
+ - Standard files are detailed guides — **long files are normal**. Do not judge as "too large" or "needs splitting".
840
+ - File naming: \`number.name.md\` (e.g., \`01.project-overview.md\`)
841
+ - When adding a new Standard, also add it to the \`00.standard-reference.md\` list.
842
+
843
+ ---
844
+
845
+ ## 4. Skills File Writing Rules
846
+
847
+ - When adding a new skill, register it in \`skills/00.shared/MANIFEST.md\`.
848
+ - If a skill generates Rules files, those Rules MUST include \`paths\` frontmatter.
849
+ - Reference paths in skill templates must be verified against actual project files.
850
+
851
+ ---
852
+
853
+ ## 5. Planned References
854
+
855
+ Paths and directories referenced in documents may not yet exist on disk. These are **planned references for future implementation**.
856
+
857
+ Do NOT label them as:
858
+ - "missing", "MISSING", "inconsistency" planned item, normal
859
+ - "needs deletion", "stale", "dead reference" — future addition, preserve
860
+ - "needs correction", "path error" — intentional reference, no change needed
861
+
862
+ When discovered during review/audit, **do not report as issues — preserve as-is**.
863
+
864
+ ---
865
+
866
+ ## 5-1. Multi-Layer Defensive Rule Placement is Intentional
867
+
868
+ The same defensive rules (no duplication judgment, no planned reference deletion, no speculation, etc.) are **intentionally repeated across multiple Rules files**. Do NOT judge this as "duplication → needs consolidation".
869
+
870
+ ### Design intent
871
+
872
+ Each Rules file is loaded in a different work context (standard reference lookup, general coding, document editing). Repeating defensive principles ensures they are active in each context.
873
+
874
+ Even when multiple files are loaded simultaneously:
875
+ - **Reinforcement effect**: repeated exposure increases AI compliance
876
+ - **Independent context preservation**: each file is self-contained in its context
877
+
878
+ ### Prohibited
879
+
880
+ - Do not report this placement as an optimization target in context analysis
881
+ - "Co-loaded therefore redundant" is a hallucination
882
+ - Do not propose "consolidate into 52.ai-work-rules.md and replace others with references"
883
+
884
+ ---
885
+
886
+ ## 5-2. Do Not Over-Report Topic Repetition as "Duplication" or "Inconsistency Risk"
887
+
888
+ The same topic (directory structure, API rules, environment variables, path aliases, state management, etc.) may be mentioned in CLAUDE.md and multiple Rules files. This is because **each occurrence serves a different layer role (overview vs enforcement) or domain role (architecture vs security vs config)** — it is not duplication.
889
+
890
+ ### Prohibited
891
+
892
+ - Do not report tens-of-lines repetition as a "context optimization issue"
893
+ - Do not produce "removing duplication saves N lines/bytes" analysis
894
+ - Do not over-report trivial expression differences (comment phrasing, item count differences) as "inconsistency risk"
895
+ - If no information is missing, it is not a problem
896
+
897
+ ---
898
+
899
+ ## 6. No Domain-Specific Hardcoding
900
+
901
+ When adding or modifying rules in \`claudeos-core/standard/\`, \`.claude/rules/\`, or \`claudeos-core/skills/\`, **never hardcode project-specific domain names**. Always write in generic, reusable patterns.
902
+
903
+ ### Rationale
904
+
905
+ These documents are project-wide **common rules**. If specific domain names appear, developers working on other domains may ignore the rules as irrelevant.
906
+
907
+ ---
908
+
909
+ ## 6-1. No System Absolute Path Hardcoding
910
+
911
+ **Never hardcode system absolute paths** (\`/Users/xxx/\`, \`/home/xxx/\`, \`C:\\\\Users\\\\xxx\\\\\`) in documents.
912
+
913
+ - ❌ \`/Users/developer/projects/my-app/src/...\`
914
+ - \`current working directory\` or project-relative path (\`src/...\`)
915
+
916
+ ### Rationale
917
+
918
+ Absolute paths are specific to one developer's local environment and cannot be used in other environments. Always use relative paths or generic expressions to ensure document portability.
919
+
920
+ ---
921
+
922
+ ## 6-2. Code Examples Must Follow Project Conventions
923
+
924
+ When writing code examples in documents (file paths, import statements, directory tree diagrams), **follow the project's naming conventions**. Specifically:
925
+
926
+ - **Directory structure examples must reflect actual project structure** — do not guess or invent fictional paths
927
+ - **Follow the project's file naming convention** — check existing files before writing examples
928
+ - **Verify paths exist** before including them in documentation
929
+
930
+ ### Rationale
931
+
932
+ If document examples differ from actual code conventions, developers following the Standard may write incorrectly named code. Examples are normative — they must match the real project.
933
+
934
+ ---
935
+
936
+ ## 7. Change Synchronization Procedure
937
+
938
+ After modifying documents, always synchronize related files:
939
+
940
+ | Changed | Sync target |
941
+ |---------|-------------|
942
+ | Standard modified | Corresponding Rules file |
943
+ | Rules modified | Corresponding Standard (\`## Reference\` link still valid?) |
944
+ | Skills modified | \`MANIFEST.md\` |
945
+ | Document added | \`00.standard-reference.md\` list |
946
+
947
+ After changes, directly verify related files (Rules ↔ Standard) and update consistently.
948
+ `;
949
+
950
+ /**
951
+ * Scaffold doc-writing-guide standard file.
952
+ * Scans 00.core/ for the next available number.
953
+ * @param {string} standardCoreDir - path to claudeos-core/standard/00.core/
954
+ * @param {object} [opts]
955
+ * @param {boolean} [opts.overwrite=false]
956
+ * @returns {{ file: string, status: string }}
957
+ */
958
+ function scaffoldDocWritingGuide(standardCoreDir, { overwrite = false, lang = "en" } = {}) {
959
+ ensureDir(standardCoreDir);
960
+
961
+ // Check if doc-writing-guide already exists (any number)
962
+ const existing = fs.readdirSync(standardCoreDir)
963
+ .filter(f => f.endsWith(".doc-writing-guide.md"));
964
+ if (existing.length > 0 && !overwrite) {
965
+ return { file: existing[0], status: "skipped" };
966
+ }
967
+
968
+ // Find next available number
969
+ const nums = fs.readdirSync(standardCoreDir)
970
+ .map(f => parseInt(f.match(/^(\d+)\./)?.[1], 10))
971
+ .filter(n => !isNaN(n));
972
+ const nextNum = nums.length > 0 ? Math.max(...nums) + 1 : 1;
973
+ const fileName = `${String(nextNum).padStart(2, "0")}.doc-writing-guide.md`;
974
+
975
+ const target = existing.length > 0 && overwrite
976
+ ? path.join(standardCoreDir, existing[0])
977
+ : path.join(standardCoreDir, fileName);
978
+
979
+ const cacheFile = cachePathFor(standardCoreDir, lang);
980
+ const content = translateIfNeeded(STANDARD_DOC_WRITING_GUIDE, lang, "STANDARD_DOC_WRITING_GUIDE", cacheFile);
981
+ const ok = writeFileSafe(target, content);
982
+ return { file: path.basename(target), status: ok ? "written" : "error" };
983
+ }
984
+
985
+ // ─── Skills MANIFEST stub (English static fallback) ────────
986
+ // Pass 3c is expected to generate claudeos-core/skills/00.shared/MANIFEST.md,
987
+ // but the stack pass3.md templates list it among generation targets without
988
+ // marking it REQUIRED. On frontend-only or skill-sparse projects Claude may
989
+ // omit it, leaving .claude/rules/50.sync/02.skills-sync.md (which names
990
+ // MANIFEST.md as the single source of truth for skill registration) pointing
991
+ // at a non-existent file. This gap-fill creates a minimal stub in Pass 4 if
992
+ // the file is missing after Pass 3 completes — same contract as
993
+ // scaffoldDocWritingGuide (skip if exists, write English or translated stub).
994
+ const SKILLS_MANIFEST_STUB = `# Skill Registry
995
+
996
+ _Single source of truth for registered skills in this project._
997
+ _Referenced by: \`.claude/rules/50.sync/02.skills-sync.md\`_
998
+
999
+ ## How to register a skill
1000
+
1001
+ When adding a new skill under \`claudeos-core/skills/\`, append an entry below
1002
+ with its path, purpose, and the orchestrator file that invokes it.
1003
+
1004
+ ## Registered skills
1005
+
1006
+ | Skill | Orchestrator | Purpose |
1007
+ |-------|-------------|---------|
1008
+ | _(none registered yet)_ | | |
1009
+
1010
+ ## Sync contract
1011
+
1012
+ - When a skill file is added/renamed/deleted under \`claudeos-core/skills/\`,
1013
+ update this manifest in the same commit.
1014
+ - When this manifest is modified, \`.claude/rules/50.sync/02.skills-sync.md\`
1015
+ is NOT modified it references this file by path, not by content.
1016
+ `;
1017
+
1018
+ /**
1019
+ * Create claudeos-core/skills/00.shared/MANIFEST.md if absent.
1020
+ * Skip-safe: returns { status: "skipped" } when the file already exists with
1021
+ * any non-trivial content.
1022
+ *
1023
+ * @param {string} skillsSharedDir - absolute path to .../claudeos-core/skills/00.shared
1024
+ * @param {object} [opts]
1025
+ * @param {boolean} [opts.overwrite=false]
1026
+ * @param {string} [opts.lang="en"]
1027
+ * @returns {{ file: string, status: string }}
1028
+ */
1029
+ function scaffoldSkillsManifest(skillsSharedDir, { overwrite = false, lang = "en" } = {}) {
1030
+ ensureDir(skillsSharedDir);
1031
+ const target = path.join(skillsSharedDir, "MANIFEST.md");
1032
+ if (existsSafe(target) && !overwrite) {
1033
+ // Guard against Pass 3c producing an empty MANIFEST.md only skip if it
1034
+ // has real content (> 20 chars, trimming BOM/whitespace).
1035
+ const current = readFileSafe(target, "");
1036
+ const stripped = current.replace(/^\uFEFF/, "").trim();
1037
+ if (stripped.length > 20) return { file: "MANIFEST.md", status: "skipped" };
1038
+ }
1039
+ const cacheFile = cachePathFor(skillsSharedDir, lang);
1040
+ const content = translateIfNeeded(SKILLS_MANIFEST_STUB, lang, "SKILLS_MANIFEST_STUB", cacheFile);
1041
+ const ok = writeFileSafe(target, content);
1042
+ return { file: "MANIFEST.md", status: ok ? "written" : "error" };
1043
+ }
1044
+
1045
+ module.exports = {
1046
+ MEMORY_FILES,
1047
+ RULE_FILES_00,
1048
+ RULE_FILES_60,
1049
+ CLAUDE_MD_APPEND,
1050
+ STANDARD_DOC_WRITING_GUIDE,
1051
+ SKILLS_MANIFEST_STUB,
1052
+ scaffoldMemory,
1053
+ scaffoldRules,
1054
+ appendClaudeMdL4Memory,
1055
+ scaffoldMasterPlans,
1056
+ scaffoldDocWritingGuide,
1057
+ scaffoldSkillsManifest,
1058
+ };