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.vi.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
- **Tự động sinh tài liệu Claude Code từ chính nguồn thực tế của bạn.** Một CLI phân tích tĩnh dự án rồi chạy pipeline Claude 4-pass để sinh `.claude/rules/`, standards, skills và guides nhờ đó Claude Code tuân theo **các quy ước của dự án bạn**, không phải các quy ước chung chung.
10
+ **Để Claude Code tuân theo các quy ước của _dự án bạn_ ngay từ lần đầu — không phải các mặc định chung chung.**
11
+
12
+ Một deterministic Node.js scanner đọc mã nguồn của bạn trước; sau đó pipeline Claude 4-pass viết toàn bộ — `CLAUDE.md` + `.claude/rules/` tự động nạp + standards + skills + L4 memory. 10 ngôn ngữ đầu ra, 5 validator hậu sinh, và một path allowlist tường minh ngăn LLM bịa ra các tệp hoặc framework không có trong code của bạn.
13
+
14
+ Hoạt động trên [**12 stack**](#supported-stacks) (bao gồm monorepo) — một lệnh `npx` duy nhất, không cần cấu hình, 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
  ## Công cụ này là gì?
21
25
 
22
- Bạn đang dùng Claude Code. Nó thông minh, nhưng không biết **các quy ước của dự án bạn**:
23
- - Đội của bạn dùng MyBatis, nhưng Claude lại sinh code JPA.
24
- - Wrapper của bạn `ApiResponse.ok()`, nhưng Claude lại viết `ResponseEntity.success()`.
25
- - Package của bạn là `controller/order/`, nhưng Claude lại tạo `order/controller/`.
26
+ Bạn đang dùng Claude Code. Nó mạnh mẽ, nhưng mỗi phiên đều bắt đầu mới — không ức về cách _dự án của bạn_ được tổ chức. Vì vậy nó fallback về các mặc định "tốt nói chung" mà hiếm khi khớp với những gì đội bạn thực sự làm:
27
+
28
+ - Đội bạn dùng **MyBatis**, nhưng Claude lại sinh JPA repository.
29
+ - Response wrapper của bạn là `ApiResponse.ok()`, nhưng Claude lại viết `ResponseEntity.success()`.
30
+ - Package của bạn là layer-first (`controller/order/`), nhưng Claude lại tạo domain-first (`order/controller/`).
31
+ - Lỗi của bạn đi qua centralized middleware, nhưng Claude rải `try/catch` ở mọi endpoint.
32
+
33
+ Bạn muốn có một bộ `.claude/rules/` cho từng dự án — Claude Code tự động nạp mỗi phiên — nhưng viết tay những rule đó cho mỗi repo mới mất hàng giờ, và chúng drift theo sự tiến hóa của code.
34
+
35
+ **ClaudeOS-Core viết chúng cho bạn, từ chính mã nguồn thực tế của bạn.** Một deterministic Node.js scanner đọc dự án bạn trước (stack, ORM, layout package, quy ước, đường dẫn tệp). Sau đó pipeline Claude 4-pass biến các sự kiện đã trích xuất thành một bộ tài liệu hoàn chỉnh:
26
36
 
27
- vậy bạn mất khá nhiều thời gian để sửa từng tệp được sinh ra.
37
+ - **`CLAUDE.md`** chỉ mục dự án Claude đọc mỗi phiên
38
+ - **`.claude/rules/`** — rules tự động nạp theo category (`00.core` / `10.backend` / `20.frontend` / `30.security-db` / `40.infra` / `60.memory` / `70.domains` / `80.verification`)
39
+ - **`claudeos-core/standard/`** — tài liệu tham chiếu ("vì sao" sau mỗi rule)
40
+ - **`claudeos-core/skills/`** — pattern tái sử dụng (CRUD scaffolding, page template)
41
+ - **`claudeos-core/memory/`** — decision log + failure pattern lớn lên cùng dự án
28
42
 
29
- **ClaudeOS-Core khắc phục điều này.** quét nguồn thực tế của bạn, xác định các quy ước, viết một tập rule hoàn chỉnh vào `.claude/rules/` thư mục Claude Code tự động đọc. Lần sau bạn nói *"Tạo CRUD cho orders"*, Claude sẽ tuân theo quy ước của bạn ngay từ lần đầu.
43
+ scanner trao cho Claude một path allowlist tường minh, LLM **không thể bịa ra các tệp hoặc framework không trong code của bạn**. Năm validator hậu sinh (`claude-md-validator`, `content-validator`, `pass-json-validator`, `plan-validator`, `sync-checker`) xác minh đầu ra trước khi ship language-invariant, vậy cùng một bộ rule áp dụng bạn sinh bằng tiếng Anh, tiếng Hàn hay 8 ngôn ngữ còn lại.
30
44
 
31
45
  ```
32
- Trước: Bạn → Claude Code → code "tốt nói chung" → sửa thủ công
33
- Sau: Bạn → Claude Code → code khớp với dự án của bạn → dùng luôn
46
+ Trước: Bạn → Claude Code → code "tốt nói chung" → sửa thủ công mỗi lần
47
+ Sau: Bạn → Claude Code → code khớp với DỰ ÁN CỦA BẠN → dùng luôn
34
48
  ```
35
49
 
36
50
  ---
@@ -119,37 +133,45 @@ Chạy trên [`spring-boot-realworld-example-app`](https://github.com/gothinkste
119
133
  </details>
120
134
 
121
135
  <details>
122
- <summary><strong>📄 Trích đoạn <code>CLAUDE.md</code> được sinh (đầu ra thực tế)</strong></summary>
136
+ <summary><strong>📄 Nội dung kết thúc trong <code>CLAUDE.md</code> của bạn (trích đoạn thực tế — 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
- Lưu ý: mọi luận điểm phía trên đều dựa trên nguồn thực tên class, đường dẫn package, key cấu hình, cờ dead-config đều do scanner trích xuất trước khi Claude viết tệp.
169
+ Mọi giá trị bên trên tọa độ dependency chính xác, tên tệp `dev.db`, tên migration `V1__create_tables.sql`, "no JPA" đều được scanner trích xuất từ `build.gradle` / `application.properties` / cây mã nguồn trước khi Claude viết tệp. Không có gì là phỏng đoán.
148
170
 
149
171
  </details>
150
172
 
151
173
  <details>
152
- <summary><strong>🛡️ Một rule thực tế được tự động nạp (<code>.claude/rules/10.backend/03.data-access-rules.md</code>)</strong></summary>
174
+ <summary><strong>🛡️ Một rule thật được tự động nạp (<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
- Glob `paths: ["**/*"]` có nghĩa là Claude Code tự động nạp rule này mỗi khi bạn chỉnh bất kỳ tệp nào trong dự án. Các dụ ✅/❌ được lấy thẳng từ chính các quy ướcmẫu lỗi đã trong codebase này.
231
+ Glob `paths: ["**/*"]` có nghĩa là Claude Code tự động nạp rule này mỗi khi bạn chỉnh bất kỳ tệp nào trong dự án. Mọi tên class, đường dẫn package, exception handler trong rule đều được lấy thẳng từ source đã scan bao gồm cả `CustomizeExceptionHandler` `JacksonCustomizations` thực tế của dự án.
196
232
 
197
233
  </details>
198
234
 
@@ -200,25 +236,26 @@ Glob `paths: ["**/*"]` có nghĩa là Claude Code tự động nạp rule này m
200
236
  <summary><strong>🧠 Hạt mầm <code>decision-log.md</code> tự sinh (trích đoạn thực tế)</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 gieo `decision-log.md` bằng các quyết định kiến trúc được trích từ `pass2-merged.json`, để các phiên sau ghi nhớ *vì sao* codebase trông như vậy — không chỉ *trông như thế nào*.
258
+ Pass 4 gieo `decision-log.md` bằng các quyết định kiến trúc được trích từ `pass2-merged.json`, để các phiên sau ghi nhớ *vì sao* codebase trông như vậy — không chỉ *trông như thế nào*. Mọi tùy chọn ("JPA/Hibernate", "MyBatis-Plus") và mọi hệ quả đều bắt nguồn từ chính khối dependency `build.gradle` thực tế.
222
259
 
223
260
  </details>
224
261
 
@@ -277,13 +314,17 @@ Các category dùng chung tiền tố số giữa `rules/` và `standard/` đạ
277
314
 
278
315
  ## Dành cho ai?
279
316
 
280
- | Bạn là... | Công cụ này giúp bạn... |
317
+ | Bạn là... | Pain mà công cụ này gỡ bỏ |
281
318
  |---|---|
282
- | **Dev solo** đang khởi tạo dự án mới với Claude Code | Bỏ qua hoàn toàn giai đoạn "dạy Claude quy ước của tôi" |
283
- | **Team lead** duy trì chuẩn dùng chung | Tự động hóa phần tẻ nhạt: giữ `.claude/rules/` luôn cập nhật |
284
- | **Đã dùng Claude Code** nhưng mệt mỏi vì sửa code được sinh | Khiến Claude tuân theo mẫu của BẠN, không phải mẫu "tốt nói chung" |
319
+ | **Dev solo** đang khởi tạo dự án mới với Claude Code | "Dạy Claude quy ước của tôi mỗi phiên" — biến mất. `CLAUDE.md` + `.claude/rules/` 8-category được sinh trong một lần chạy. |
320
+ | **Team lead** duy trì chuẩn dùng chung qua nhiều repo | `.claude/rules/` drift khi mọi người đổi tên package, đổi ORM, đổi response wrapper. ClaudeOS-Core đồng bộ lại deterministic — cùng đầu vào, đầu ra byte-identical, không có diff noise. |
321
+ | **Đã dùng Claude Code** nhưng mệt mỏi vì sửa code được sinh | Sai response wrapper, sai layout package, JPA khi bạn dùng MyBatis, `try/catch` rải khắp khi dự án bạn dùng centralized middleware. Scanner trích các quy ước thật của bạn; mỗi pass Claude chạy dựa trên một path allowlist tường minh. |
322
+ | **Onboarding một repo mới** (dự án sẵn có, gia nhập đội mới) | Chạy `init` trên repo, nhận một bản đồ kiến trúc sống: bảng stack trong CLAUDE.md, rules từng layer kèm ví dụ ✅/❌, decision log đã gieo "vì sao" sau các lựa chọn lớn (JPA vs MyBatis, REST vs GraphQL, v.v.). Đọc 5 tệp thắng đọc 5.000 source file. |
323
+ | **Làm việc bằng tiếng Hàn / Nhật / Trung / 7 ngôn ngữ khác** | Hầu hết các bộ sinh rule Claude Code chỉ hỗ trợ tiếng Anh. ClaudeOS-Core viết toàn bộ bằng **10 ngôn ngữ** (`en/ko/ja/zh-CN/es/vi/hi/ru/fr/de`) với **xác minh cấu trúc byte-identical** — cùng verdict `claude-md-validator` bất kể ngôn ngữ đầu ra. |
324
+ | **Đang chạy trên monorepo** (Turborepo, pnpm/yarn workspaces, Lerna) | Domain backend + frontend được phân tích trong một lần chạy với prompt riêng biệt; `apps/*/` và `packages/*/` được walk tự động; rules theo từng stack được emit dưới `70.domains/{type}/`. |
325
+ | **Đóng góp OSS hoặc thử nghiệm** | Đầu ra thân thiện với gitignore — `claudeos-core/` là thư mục làm việc local của bạn, chỉ `CLAUDE.md` + `.claude/` cần ship. Resume-safe khi bị gián đoạn; idempotent khi chạy lại (chỉnh sửa thủ công của bạn được giữ lại nếu không có `--force`). |
285
326
 
286
- **Không phù hợp nếu:** bạn muốn một bundle preset agents/skills/rules dạng one-size-fits-all chạy được ngay từ ngày đầu mà không cần bước scan (xem [docs/vi/comparison.md](docs/vi/comparison.md) để biết công cụ nào hợp với việc gì), hoặc dự án của bạn chưa khớp với một trong các [stack được hỗ trợ](#supported-stacks).
327
+ **Không phù hợp nếu:** bạn muốn một bundle preset agents/skills/rules dạng one-size-fits-all chạy được ngay từ ngày đầu mà không cần bước scan (xem [docs/vi/comparison.md](docs/vi/comparison.md) để biết công cụ nào hợp với việc gì), dự án của bạn chưa khớp với một trong các [stack được hỗ trợ](#supported-stacks), hoặc bạn chỉ cần một `CLAUDE.md` đơn giản (built-in `claude /init` là đủ — không cần cài thêm công cụ).
287
328
 
288
329
  ---
289
330
 
@@ -296,9 +337,28 @@ Thông thường: Bạn mô tả dự án → Claude đoán stack → Claude vi
296
337
  Công cụ này: Code đọc stack → Code đưa sự kiện đã xác nhận cho Claude → Claude viết doc từ sự kiện
297
338
  ```
298
339
 
299
- Ý tưởng then chốt: **một scanner Node.js đọc nguồn của bạn trước** (deterministic, không AI), sau đó pipeline Claude 4-pass viết tài liệu, bị ràng buộc bởi những gì scanner tìm thấy. Claude không thể bịa ra đường dẫn hay framework không thực sự có trong code.
340
+ Pipeline chạy theo **3 giai đoạn**, với code cả hai phía của lời gọi LLM:
341
+
342
+ **1. Step A — Scanner (deterministic, không LLM).** Một Node.js scanner walk qua thư mục gốc dự án, đọc `package.json` / `build.gradle` / `pom.xml` / `pyproject.toml`, parse các tệp `.env*` (với redaction biến nhạy cảm cho `PASSWORD/SECRET/TOKEN/JWT_SECRET/...`), phân loại pattern kiến trúc (5 pattern A/B/C/D/E của Java, Kotlin CQRS / multi-module, Next.js App vs Pages Router, FSD, components-pattern), khám phá các domain, và xây dựng allowlist tường minh cho mọi đường dẫn source tồn tại. Đầu ra: `project-analysis.json` — single source of truth cho mọi bước sau.
343
+
344
+ **2. Step B — Pipeline Claude 4-pass (bị ràng buộc bởi sự kiện của Step A).**
345
+ - **Pass 1** đọc các tệp đại diện theo nhóm domain và trích ~50–100 quy ước mỗi domain — response wrapper, thư viện logging, error handling, quy ước đặt tên, pattern test. Chạy một lần mỗi nhóm domain (`max 4 domains, 40 files per group`) nên context không bao giờ overflow.
346
+ - **Pass 2** gộp toàn bộ phân tích theo từng domain thành bức tranh toàn dự án và giải quyết bất đồng bằng cách chọn quy ước trội nhất.
347
+ - **Pass 3** viết `CLAUDE.md` + `.claude/rules/` + `claudeos-core/standard/` + skills + guides — split thành các stage (`3a` facts → `3b-core/3b-N` rules+standards → `3c-core/3c-N` skills+guides → `3d-aux` database+mcp-guide) để prompt mỗi stage vừa với context window của LLM kể cả khi `pass2-merged.json` lớn. Sub-divide 3b/3c thành các batch ≤15 domain cho dự án ≥16 domain.
348
+ - **Pass 4** gieo lớp L4 memory (`decision-log.md`, `failure-patterns.md`, `compaction.md`, `auto-rule-update.md`) và thêm các universal scaffold rule. Pass 4 **bị cấm chỉnh sửa `CLAUDE.md`** — Section 8 của Pass 3 là authoritative.
349
+
350
+ **3. Step C — Verification (deterministic, không LLM).** Năm validator kiểm tra đầu ra:
351
+ - `claude-md-validator` — 25 kiểm tra cấu trúc trên `CLAUDE.md` (8 sections, đếm H3/H4, tính duy nhất của memory file, T1 canonical heading invariant). Language-invariant: cùng verdict bất kể `--lang`.
352
+ - `content-validator` — 10 kiểm tra nội dung gồm xác minh path-claim (`STALE_PATH` bắt các tham chiếu `src/...` bị bịa) và phát hiện MANIFEST drift.
353
+ - `pass-json-validator` — Pass 1/2/3/4 well-formed JSON + đếm section theo stack.
354
+ - `plan-validator` — nhất quán plan ↔ disk (legacy, gần như no-op từ v2.1.0).
355
+ - `sync-checker` — nhất quán đăng ký disk ↔ `sync-map.json` qua 7 thư mục được theo dõi.
356
+
357
+ Ba mức severity (`fail` / `warn` / `advisory`) để warning không bao giờ deadlock CI vì hallucination LLM mà người dùng có thể tự sửa.
358
+
359
+ Bất biến gắn kết tất cả: **Claude chỉ có thể trích các đường dẫn thật sự tồn tại trong code của bạn**, vì Step A trao cho nó một allowlist hữu hạn. Nếu LLM vẫn cố bịa (hiếm nhưng xảy ra với vài seed), Step C bắt được trước khi docs ship.
300
360
 
301
- Xem kiến trúc đầy đủ tại [docs/vi/architecture.md](docs/vi/architecture.md).
361
+ Chi tiết per-pass, resume dựa trên marker, workaround staged-rules cho `.claude/` sensitive-path block của Claude Code, và internals của stack detection xem [docs/vi/architecture.md](docs/vi/architecture.md).
302
362
 
303
363
  ---
304
364