claudeos-core 2.4.0 → 2.4.1

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.
package/README.md CHANGED
@@ -7,7 +7,11 @@
7
7
  [![license](https://img.shields.io/npm/l/claudeos-core.svg?color=blue)](LICENSE)
8
8
  [![downloads](https://img.shields.io/npm/dm/claudeos-core.svg?logo=npm&color=blue&label=downloads)](https://www.npmjs.com/package/claudeos-core)
9
9
 
10
- **Auto-generate Claude Code documentation from your actual source code.** A CLI tool that statically analyzes your project, then runs a 4-pass Claude pipeline to generate `.claude/rules/`, standards, skills, and guides so Claude Code follows your project's conventions, not generic ones.
10
+ **Make Claude Code follow YOUR project's conventions on the first try — not generic defaults.**
11
+
12
+ A deterministic Node.js scanner reads your code first; a 4-pass Claude pipeline then writes the full set — `CLAUDE.md` + auto-loaded `.claude/rules/` + standards + skills + L4 memory. 10 output languages, 5 post-generation validators, and an explicit path allowlist that prevents the LLM from inventing files or frameworks not in your code.
13
+
14
+ Works on [**12 stacks**](#supported-stacks) (monorepos included) — one `npx` command, no config, resume-safe, idempotent.
11
15
 
12
16
  ```bash
13
17
  npx claudeos-core init
@@ -19,18 +23,28 @@ npx claudeos-core init
19
23
 
20
24
  ## What is this?
21
25
 
22
- You use Claude Code. It's smart, but it doesn't know **your project's conventions**:
23
- - Your team uses MyBatis, but Claude generates JPA code.
24
- - Your wrapper is `ApiResponse.ok()`, but Claude writes `ResponseEntity.success()`.
25
- - Your packages are `controller/order/`, but Claude creates `order/controller/`.
26
+ You use Claude Code. It's powerful, but every session starts fresh — it has no memory of how _your_ project is structured. So it falls back to "generally good" defaults that rarely match what your team actually does:
27
+
28
+ - Your team uses **MyBatis**, but Claude generates JPA repositories.
29
+ - Your response wrapper is `ApiResponse.ok()`, but Claude writes `ResponseEntity.success()`.
30
+ - Your packages are layer-first (`controller/order/`), but Claude creates domain-first (`order/controller/`).
31
+ - Your errors go through centralized middleware, but Claude scatters `try/catch` in every endpoint.
32
+
33
+ You'd want a `.claude/rules/` set per project — Claude Code auto-loads it every session — but writing those rules by hand for each new repo takes hours, and they drift as the code evolves.
34
+
35
+ **ClaudeOS-Core writes them for you, from your actual source code.** A deterministic Node.js scanner reads your project first (stack, ORM, package layout, conventions, file paths). Then a 4-pass Claude pipeline turns the extracted facts into a complete documentation set:
26
36
 
27
- So you spend a chunk of time fixing every generated file.
37
+ - **`CLAUDE.md`** the project index Claude reads on every session
38
+ - **`.claude/rules/`** — auto-loaded rules per category (`00.core` / `10.backend` / `20.frontend` / `30.security-db` / `40.infra` / `60.memory` / `70.domains` / `80.verification`)
39
+ - **`claudeos-core/standard/`** — reference docs (the "why" behind each rule)
40
+ - **`claudeos-core/skills/`** — reusable patterns (CRUD scaffolding, page templates)
41
+ - **`claudeos-core/memory/`** — decision log + failure patterns that grow with the project
28
42
 
29
- **ClaudeOS-Core fixes this.** It scans your actual source code, figures out your conventions, and writes a complete set of rules into `.claude/rules/` the directory Claude Code reads automatically. Next time you say *"Create a CRUD for orders"*, Claude follows your conventions on the first try.
43
+ Because the scanner hands Claude an explicit path allowlist, the LLM **cannot invent files or frameworks that aren't in your code**. Five post-generation validators (`claude-md-validator`, `content-validator`, `pass-json-validator`, `plan-validator`, `sync-checker`) verify the output before it ships language-invariant, so the same rules apply whether you generate in English, Korean, or any of 8 other languages.
30
44
 
31
45
  ```
32
- Before: You → Claude Code → "generally good" code → manual fixing
33
- After: You → Claude Code → code that matches your project → ship it
46
+ Before: You → Claude Code → "generally good" code → manual fixing each time
47
+ After: You → Claude Code → code that matches YOUR project → ship it
34
48
  ```
35
49
 
36
50
  ---
@@ -119,37 +133,45 @@ Run on [`spring-boot-realworld-example-app`](https://github.com/gothinkster/spri
119
133
  </details>
120
134
 
121
135
  <details>
122
- <summary><strong>📄 What ends up in your <code>CLAUDE.md</code> (real excerpt)</strong></summary>
136
+ <summary><strong>📄 What ends up in your <code>CLAUDE.md</code> (real excerpt — Section 1 + 2)</strong></summary>
123
137
 
124
138
  ```markdown
125
- ## 4. Core Architecture
126
-
127
- ### Core Patterns
128
-
129
- - **Hexagonal ports & adapters**: domain ports live in `io.spring.core.{aggregate}`
130
- and are implemented by `io.spring.infrastructure.repository.MyBatis{Aggregate}Repository`.
131
- The domain layer has zero MyBatis imports.
132
- - **CQRS-lite read/write split (same DB)**: write side goes through repository ports
133
- + entities; read side is a separate `readservice` package whose `@Mapper`
134
- interfaces return `*Data` DTOs directly (no entity hydration).
135
- - **No aggregator/orchestrator layer**: multi-source orchestration happens inside
136
- application services (e.g., `ArticleQueryService`); there is no `*Aggregator`
137
- class in the codebase.
138
- - **Application-supplied UUIDs**: entity constructors assign their own UUID; PK is
139
- passed via `#{user.id}` on INSERT. The global
140
- `mybatis.configuration.use-generated-keys=true` flag is dead config
141
- (auto-increment is unused).
142
- - **JWT HS512 authentication**: `io.spring.infrastructure.service.DefaultJwtService`
143
- is the sole token subject in/out; `io.spring.api.security.JwtTokenFilter`
144
- extracts the token at the servlet layer.
139
+ # CLAUDE.md spring-boot-realworld-example-app
140
+
141
+ > Reference implementation of the RealWorld backend specification on
142
+ > Java 11 + Spring Boot 2.6, exposing both REST and GraphQL endpoints
143
+ > over a hexagonal MyBatis persistence layer.
144
+
145
+ ## 1. Role Definition
146
+
147
+ As the senior developer for this repository, you are responsible for
148
+ writing, modifying, and reviewing code. Responses must be written in English.
149
+ A Java Spring Boot REST + GraphQL API server organized around a hexagonal
150
+ (ports & adapters) architecture, with a CQRS-lite read/write split inside
151
+ an XML-driven MyBatis persistence layer and JWT-based authentication.
152
+
153
+ ## 2. Project Overview
154
+
155
+ | Item | Value |
156
+ |---|---|
157
+ | Language | Java 11 |
158
+ | Framework | Spring Boot 2.6.3 |
159
+ | Build Tool | Gradle (Groovy DSL) |
160
+ | Persistence | MyBatis 3 via `mybatis-spring-boot-starter:2.2.2` (no JPA) |
161
+ | Database | SQLite (`org.xerial:sqlite-jdbc:3.36.0.3`) — `dev.db` (default), `:memory:` (test) |
162
+ | Migration | Flyway — single baseline `V1__create_tables.sql` |
163
+ | API Style | REST (`io.spring.api.*`) + GraphQL via Netflix DGS `:4.9.21` |
164
+ | Authentication | JWT HS512 (`jjwt-api:0.11.2`) + Spring Security `PasswordEncoder` |
165
+ | Server Port | 8080 (default) |
166
+ | Test Stack | JUnit Jupiter 5, Mockito, AssertJ, rest-assured, spring-mock-mvc |
145
167
  ```
146
168
 
147
- Note: every claim above is grounded in the actual source class names, package paths, configuration keys, and the dead-config flag are all extracted by the scanner before Claude writes the file.
169
+ Every value above exact dependency coordinates, the `dev.db` filename, the `V1__create_tables.sql` migration name, "no JPA" is extracted by the scanner from `build.gradle` / `application.properties` / source tree before Claude writes the file. Nothing is guessed.
148
170
 
149
171
  </details>
150
172
 
151
173
  <details>
152
- <summary><strong>🛡️ A real auto-loaded rule (<code>.claude/rules/10.backend/03.data-access-rules.md</code>)</strong></summary>
174
+ <summary><strong>🛡️ A real auto-loaded rule (<code>.claude/rules/10.backend/01.controller-rules.md</code>)</strong></summary>
153
175
 
154
176
  ````markdown
155
177
  ---
@@ -157,42 +179,56 @@ paths:
157
179
  - "**/*"
158
180
  ---
159
181
 
160
- # Data Access Rules
182
+ # Controller Rules
183
+
184
+ ## REST (`io.spring.api.*`)
161
185
 
162
- ## XML-only SQL
163
- - Every SQL statement lives in `src/main/resources/mapper/*.xml`.
164
- NO `@Select` / `@Insert` / `@Update` / `@Delete` annotations on `@Mapper` methods.
165
- - Each `@Mapper` interface has exactly one XML file at
166
- `src/main/resources/mapper/{InterfaceName}.xml`.
167
- - `<mapper namespace="...">` MUST be the fully qualified Java interface name.
168
- The single existing exception is `TransferData.xml` (free-form `transfer.data`).
186
+ - Controllers are the SOLE response wrapper for HTTP — no aggregator/facade above them.
187
+ Return `ResponseEntity<?>` or a body Spring serializes via `JacksonCustomizations`.
188
+ - Each controller method calls exactly ONE application service method. Multi-source
189
+ composition lives in the application service.
190
+ - Controllers MUST NOT import `io.spring.infrastructure.*`. No direct `@Mapper` access.
191
+ - Validate command-param arguments with `@Valid`. Custom JSR-303 constraints live under
192
+ `io.spring.application.{aggregate}.*`.
193
+ - Resolve the current user via `@AuthenticationPrincipal User`.
194
+ - Let exceptions propagate to `io.spring.api.exception.CustomizeExceptionHandler`
195
+ (`@ControllerAdvice`). Do NOT `try/catch` business exceptions inside the controller.
169
196
 
170
- ## Dynamic SQL
171
- - `<if>` predicates MUST guard both null and empty:
172
- `<if test="X != null and X != ''">`. Empty-only is the existing HIGH-severity bug pattern.
173
- - Prefer `LIMIT n OFFSET m` over MySQL-style `LIMIT m, n`.
197
+ ## GraphQL (`io.spring.graphql.*`)
198
+
199
+ - DGS components (`@DgsComponent`) are the sole GraphQL response wrappers.
200
+ Use `@DgsQuery` / `@DgsData` / `@DgsMutation`.
201
+ - Resolve the current user via `io.spring.graphql.SecurityUtil.getCurrentUser()`.
174
202
 
175
203
  ## Examples
176
204
 
177
205
  ✅ Correct:
178
- ```xml
179
- <update id="update">
180
- UPDATE articles
181
- <set>
182
- <if test="article.title != null and article.title != ''">title = #{article.title},</if>
183
- updated_at = #{article.updatedAt}
184
- </set>
185
- WHERE id = #{article.id}
186
- </update>
206
+ ```java
207
+ @PostMapping
208
+ public ResponseEntity<?> createArticle(@AuthenticationPrincipal User user,
209
+ @Valid @RequestBody NewArticleParam param) {
210
+ Article article = articleCommandService.createArticle(param, user);
211
+ ArticleData data = articleQueryService.findById(article.getId(), user)
212
+ .orElseThrow(ResourceNotFoundException::new);
213
+ return ResponseEntity.ok(Map.of("article", data));
214
+ }
187
215
  ```
188
216
 
189
217
  ❌ Incorrect:
190
- ```xml
191
- <mapper namespace="article.mapper"> <!-- NO — namespace MUST be FQCN -->
218
+ ```java
219
+ @PostMapping
220
+ public ResponseEntity<?> create(@RequestBody NewArticleParam p) {
221
+ try {
222
+ articleCommandService.createArticle(p, currentUser);
223
+ } catch (Exception e) { // NO — let CustomizeExceptionHandler handle it
224
+ return ResponseEntity.status(500).body(e.getMessage()); // NO — leaks raw message
225
+ }
226
+ return ResponseEntity.ok().build();
227
+ }
192
228
  ```
193
229
  ````
194
230
 
195
- The `paths: ["**/*"]` glob means Claude Code auto-loads this rule whenever you edit any file in the project. The ✅/❌ examples come straight from this codebase's actual conventions and existing bug patterns.
231
+ The `paths: ["**/*"]` glob means Claude Code auto-loads this rule whenever you edit any file in the project. Every class name, package path, and exception handler in the rule comes directly from the scanned source — including the project's actual `CustomizeExceptionHandler` and `JacksonCustomizations`.
196
232
 
197
233
  </details>
198
234
 
@@ -200,25 +236,26 @@ The `paths: ["**/*"]` glob means Claude Code auto-loads this rule whenever you e
200
236
  <summary><strong>🧠 An auto-generated <code>decision-log.md</code> seed (real excerpt)</strong></summary>
201
237
 
202
238
  ```markdown
203
- ## 2026-04-26 — CQRS-lite read/write split inside the persistence layer
204
-
205
- - **Context:** Writes go through `core.*Repository` port → `MyBatis*Repository`
206
- adapter → `io.spring.infrastructure.mybatis.mapper.{Aggregate}Mapper`.
207
- Reads bypass the domain port: application service →
208
- `io.spring.infrastructure.mybatis.readservice.{Concept}ReadService` directly,
209
- returning flat `*Data` DTOs from `io.spring.application.data.*`.
210
- - **Options considered:** Single repository surface returning hydrated entities
211
- for both reads and writes.
212
- - **Decision:** Same database, two `@Mapper` packages — `mapper/` (write side,
213
- operates on core entities) and `readservice/` (read side, returns `*Data` DTOs).
214
- Read DTOs avoid entity hydration overhead.
215
- - **Consequences:** Reads are NOT routed through the domain port this is
216
- intentional, not a bug. Application services may inject both a `*Repository`
217
- (writes) and one or more `*ReadService` interfaces (reads) at the same time.
218
- Do NOT add hydrate-then-map glue in the read path.
239
+ ## 2026-04-26 — Hexagonal ports & adapters with MyBatis-only persistence
240
+
241
+ - **Context:** `io.spring.core.*` exposes `*Repository` ports (e.g.,
242
+ `io.spring.core.article.ArticleRepository`) implemented by
243
+ `io.spring.infrastructure.repository.MyBatis*Repository` adapters.
244
+ The domain layer has zero `org.springframework.*` /
245
+ `org.apache.ibatis.*` / `io.spring.infrastructure.*` imports.
246
+ - **Options considered:** JPA/Hibernate, Spring Data, MyBatis-Plus
247
+ `BaseMapper`. None adopted.
248
+ - **Decision:** MyBatis 3 (`mybatis-spring-boot-starter:2.2.2`) with
249
+ hand-written XML statements under `src/main/resources/mapper/*.xml`.
250
+ Hexagonal port/adapter wiring keeps the domain framework-free.
251
+ - **Consequences:** Every SQL lives in XML`@Select`/`@Insert`/`@Update`/`@Delete`
252
+ annotations are forbidden. New aggregates require both a
253
+ `core.{aggregate}.{Aggregate}Repository` port AND a
254
+ `MyBatis{Aggregate}Repository` adapter; introducing a JPA repository would
255
+ split the persistence model.
219
256
  ```
220
257
 
221
- Pass 4 seeds `decision-log.md` with the architectural decisions extracted from `pass2-merged.json` so future sessions remember *why* the codebase looks the way it does — not just *what* it looks like.
258
+ Pass 4 seeds `decision-log.md` with the architectural decisions extracted from `pass2-merged.json` so future sessions remember *why* the codebase looks the way it does — not just *what* it looks like. Every option ("JPA/Hibernate", "MyBatis-Plus") and every consequence is grounded in the actual `build.gradle` dependency block.
222
259
 
223
260
  </details>
224
261
 
@@ -277,13 +314,17 @@ Categories sharing the same number prefix between `rules/` and `standard/` repre
277
314
 
278
315
  ## Who is this for?
279
316
 
280
- | You are... | This helps you... |
317
+ | You are... | The pain this removes |
281
318
  |---|---|
282
- | **A solo dev** starting a new project with Claude Code | Skip the "teach Claude my conventions" phase entirely |
283
- | **A team lead** maintaining shared standards | Automate the tedious part of keeping `.claude/rules/` up to date |
284
- | **Already using Claude Code** but tired of fixing generated code | Make Claude follow YOUR patterns, not "generally good" patterns |
319
+ | **A solo dev** starting a new project with Claude Code | "Teach Claude my conventions every session" gone. `CLAUDE.md` + 8-category `.claude/rules/` generated in one pass. |
320
+ | **A team lead** maintaining shared standards across repos | `.claude/rules/` drift as people rename packages, switch ORMs, or change response wrappers. ClaudeOS-Core re-syncs deterministically — same input, byte-identical output, no diff noise. |
321
+ | **Already using Claude Code** but tired of fixing generated code | Wrong response wrapper, wrong package layout, JPA when you use MyBatis, `try/catch` scattered when your project uses centralized middleware. The scanner extracts your real conventions; every Claude pass runs against an explicit path allowlist. |
322
+ | **Onboarding to a new repo** (existing project, joining a team) | Run `init` on the repo, get a living architecture map: stack table in CLAUDE.md, per-layer rules with ✅/❌ examples, decision log seeded with "why" behind major choices (JPA vs MyBatis, REST vs GraphQL, etc.). Reading 5 files beats reading 5,000 source files. |
323
+ | **Working in Korean / Japanese / Chinese / 7 more languages** | Most Claude Code rule generators are English-only. ClaudeOS-Core writes the full set in **10 languages** (`en/ko/ja/zh-CN/es/vi/hi/ru/fr/de`) with **byte-identical structural validation** — same `claude-md-validator` verdict regardless of output language. |
324
+ | **Running on a monorepo** (Turborepo, pnpm/yarn workspaces, Lerna) | Backend + frontend domains analyzed in one run with separate prompts; `apps/*/` and `packages/*/` walked automatically; per-stack rules emitted under `70.domains/{type}/`. |
325
+ | **Contributing to OSS or experimenting** | Output is gitignore-friendly — `claudeos-core/` is your local working dir, only `CLAUDE.md` + `.claude/` need to ship. Resume-safe if interrupted; idempotent on re-runs (your manual edits to rules survive without `--force`). |
285
326
 
286
- **Not a fit if:** you want a one-size-fits-all preset bundle of agents/skills/rules that works on day one without a scan step (see [docs/comparison.md](docs/comparison.md) for what fits where), or your project doesn't fit one of the [supported stacks](#supported-stacks) yet.
327
+ **Not a fit if:** you want a one-size-fits-all preset bundle of agents/skills/rules that works on day one without a scan step (see [docs/comparison.md](docs/comparison.md) for what fits where), your project doesn't match one of the [supported stacks](#supported-stacks) yet, or you only need a single `CLAUDE.md` (built-in `claude /init` is enough — no need to install another tool).
287
328
 
288
329
  ---
289
330
 
@@ -296,9 +337,28 @@ Usual: You describe project → Claude guesses your stack → Claude writes d
296
337
  This: Code reads your stack → Code passes confirmed facts to Claude → Claude writes docs from facts
297
338
  ```
298
339
 
299
- The key idea: **a Node.js scanner reads your source code first** (deterministic, no AI), then a 4-pass Claude pipeline writes the documentation, constrained by what the scanner found. Claude can't invent paths or frameworks that aren't actually in your code.
340
+ The pipeline runs in **three stages**, with code on both sides of the LLM call:
341
+
342
+ **1. Step A — Scanner (deterministic, no LLM).** A Node.js scanner walks your project root, reads `package.json` / `build.gradle` / `pom.xml` / `pyproject.toml`, parses `.env*` files (with sensitive-variable redaction for `PASSWORD/SECRET/TOKEN/JWT_SECRET/...`), classifies your architecture pattern (Java's 5 patterns A/B/C/D/E, Kotlin CQRS / multi-module, Next.js App vs. Pages Router, FSD, components-pattern), discovers domains, and builds an explicit allowlist of every source file path that exists. Output: `project-analysis.json` — the single source of truth for what follows.
343
+
344
+ **2. Step B — 4-Pass Claude pipeline (constrained by Step A's facts).**
345
+ - **Pass 1** reads representative files per domain group and extracts ~50–100 conventions per domain — response wrappers, logging libraries, error handling, naming conventions, test patterns. Runs once per domain group (`max 4 domains, 40 files per group`) so context never overflows.
346
+ - **Pass 2** merges all per-domain analysis into a project-wide picture and resolves disagreements by picking the dominant convention.
347
+ - **Pass 3** writes `CLAUDE.md` + `.claude/rules/` + `claudeos-core/standard/` + skills + guides — split into stages (`3a` facts → `3b-core/3b-N` rules+standards → `3c-core/3c-N` skills+guides → `3d-aux` database+mcp-guide) so each stage's prompt fits the LLM's context window even when `pass2-merged.json` is large. Sub-divides 3b/3c into ≤15-domain batches for ≥16-domain projects.
348
+ - **Pass 4** seeds the L4 memory layer (`decision-log.md`, `failure-patterns.md`, `compaction.md`, `auto-rule-update.md`) and adds universal scaffold rules. Pass 4 is **forbidden from modifying `CLAUDE.md`** — Pass 3's Section 8 is authoritative.
349
+
350
+ **3. Step C — Verification (deterministic, no LLM).** Five validators check the output:
351
+ - `claude-md-validator` — 25 structural checks on `CLAUDE.md` (8 sections, H3/H4 counts, memory file uniqueness, T1 canonical heading invariant). Language-invariant: same verdict regardless of `--lang`.
352
+ - `content-validator` — 10 content checks including path-claim verification (`STALE_PATH` catches fabricated `src/...` references) and MANIFEST drift detection.
353
+ - `pass-json-validator` — Pass 1/2/3/4 JSON well-formedness + stack-aware section count.
354
+ - `plan-validator` — plan ↔ disk consistency (legacy, mostly no-op since v2.1.0).
355
+ - `sync-checker` — disk ↔ `sync-map.json` registration consistency across 7 tracked dirs.
356
+
357
+ Three severity tiers (`fail` / `warn` / `advisory`) so warnings never deadlock CI on LLM hallucinations the user can fix manually.
358
+
359
+ The invariant that ties it all together: **Claude can only cite paths that actually exist in your code**, because Step A hands it a finite allowlist. If the LLM still tries to invent something (rare but happens on certain seeds), Step C catches it before the docs ship.
300
360
 
301
- For the full architecture, see [docs/architecture.md](docs/architecture.md).
361
+ For per-pass details, marker-based resume, the staged-rules workaround for Claude Code's `.claude/` sensitive-path block, and stack detection internals, see [docs/architecture.md](docs/architecture.md).
302
362
 
303
363
  ---
304
364