claudeos-core 2.3.1 → 2.3.2
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/CHANGELOG.md +725 -0
- package/README.de.md +1 -1
- package/README.es.md +1 -1
- package/README.fr.md +1 -1
- package/README.hi.md +1 -1
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +2 -2
- package/README.ru.md +1 -1
- package/README.vi.md +1 -1
- package/README.zh-CN.md +1 -1
- package/bin/commands/init.js +378 -227
- package/content-validator/index.js +89 -9
- package/package.json +1 -1
- package/pass-prompts/templates/common/claude-md-scaffold.md +122 -20
- package/pass-prompts/templates/common/pass3-footer.md +193 -56
- package/pass-prompts/templates/common/pass3a-facts.md +48 -3
- package/pass-prompts/templates/common/pass4.md +78 -40
- package/pass-prompts/templates/java-spring/pass1.md +54 -0
- package/pass-prompts/templates/java-spring/pass3.md +1 -1
- package/pass-prompts/templates/kotlin-spring/pass1.md +45 -0
- package/pass-prompts/templates/kotlin-spring/pass3.md +1 -1
- package/plan-installer/index.js +23 -0
- package/plan-installer/pass3-context-builder.js +14 -0
- package/plan-installer/scanners/scan-frontend.js +2 -1
- package/plan-installer/source-paths.js +242 -0
- package/plan-installer/stack-detector.js +478 -42
|
@@ -259,14 +259,30 @@ Do NOT declare CLAUDE.md generation complete until count = 8 AND
|
|
|
259
259
|
Section 8 contains exactly 2 `###` sub-sections.
|
|
260
260
|
|
|
261
261
|
STEP 4b — Title determinism check. For each of the 8 `## N.` headings,
|
|
262
|
-
confirm that
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
262
|
+
confirm that:
|
|
263
|
+
(a) the English canonical phrase is present as the primary heading text
|
|
264
|
+
(LANGUAGE-INVARIANT — applied regardless of `{OUTPUT_LANG}`), AND
|
|
265
|
+
(b) if `{OUTPUT_LANG}` != `en`, the canonical native-language gloss is
|
|
266
|
+
appended in parentheses (REQUIRED, not optional). If `{OUTPUT_LANG}`
|
|
267
|
+
== `en`, no gloss is emitted. The canonical gloss table lives in
|
|
268
|
+
`claude-md-scaffold.md` under "Section heading format".
|
|
269
|
+
|
|
270
|
+
en output:
|
|
271
|
+
✅ `## 7. DO NOT Read`
|
|
272
|
+
❌ `## 7. DO NOT Read (Files Not to Be Read Directly)`
|
|
273
|
+
— no gloss when OUTPUT_LANG == en
|
|
274
|
+
|
|
275
|
+
ko output:
|
|
276
|
+
✅ `## 7. DO NOT Read (직접 읽지 말아야 할 파일)`
|
|
277
|
+
❌ `## 7. DO NOT Read`
|
|
278
|
+
— gloss is required when OUTPUT_LANG != en
|
|
279
|
+
❌ `## 7. 읽지 말 것 (Files Not to Be Read Directly)`
|
|
280
|
+
— English canonical must be PRIMARY, not parenthetical
|
|
281
|
+
|
|
282
|
+
ja output:
|
|
283
|
+
✅ `## 7. DO NOT Read (直接読まないファイル)`
|
|
284
|
+
❌ `## 7. DO NOT Read`
|
|
285
|
+
— gloss is required when OUTPUT_LANG != en
|
|
270
286
|
|
|
271
287
|
Required canonical tokens by section number:
|
|
272
288
|
§1 → "Role Definition"
|
|
@@ -300,71 +316,192 @@ write in rules, standard, or CLAUDE.md MUST be a literal, verbatim path
|
|
|
300
316
|
from `pass2-merged.json` / `project-analysis.json` / `pass1-*.json`.
|
|
301
317
|
Do not invent, augment, or "normalize" filenames.
|
|
302
318
|
|
|
303
|
-
|
|
304
|
-
|
|
319
|
+
**PRIMARY CHECK — pass3a-facts.md's Allowed Source Paths section**
|
|
320
|
+
**(v2.3.x+ allowlist):**
|
|
321
|
+
|
|
322
|
+
Before writing ANY `src/...`, `packages/...`, `apps/...`, or
|
|
323
|
+
language-specific source path in a rule or standard file, you MUST
|
|
324
|
+
verify the path appears VERBATIM in the `## Allowed Source Paths`
|
|
325
|
+
section of `pass3a-facts.md`. If the section is in "full" mode (lists
|
|
326
|
+
individual files), the exact filename must be present. If the section
|
|
327
|
+
is in "rollup" mode (lists directories because the project exceeds the
|
|
328
|
+
enumeration budget), at minimum the path's parent directory must match
|
|
329
|
+
a listed directory entry — and for the specific filename you must
|
|
330
|
+
cross-check `pass2-merged.json` before writing it.
|
|
331
|
+
|
|
332
|
+
A path NOT in the allowlist is a fabrication. Do not write it under
|
|
333
|
+
any circumstance. Not even when:
|
|
334
|
+
- The framework's documentation shows that path as "canonical" — this
|
|
335
|
+
covers Next.js app-router provider files, Vite test-setup or mock
|
|
336
|
+
handler modules, Spring resource config files, Django settings
|
|
337
|
+
modules, and similar framework-canonical locations. These paths
|
|
338
|
+
may be canonical in framework docs yet absent from THIS project's
|
|
339
|
+
allowlist because the project chose a different layout; citing
|
|
340
|
+
the canonical form is still a fabrication. (Do NOT quote the
|
|
341
|
+
specific canonical paths here — describe the category abstractly
|
|
342
|
+
if you must warn about it.)
|
|
343
|
+
- A similar path appears in the allowlist and you are tempted to
|
|
344
|
+
"extrapolate" a sibling — for example, if the allowlist has a
|
|
345
|
+
list-operation file under some API directory, do NOT cite a
|
|
346
|
+
hypothetical create-operation file in the same directory just
|
|
347
|
+
because it would be a natural sibling. Cite only what the
|
|
348
|
+
allowlist actually contains.
|
|
349
|
+
- A TypeScript constant, Java annotation, or Python decorator name
|
|
350
|
+
suggests a filename (an ALL_CAPS constant naming a route path does
|
|
351
|
+
NOT mean a matching camelCase-basename .ts file exists; this was
|
|
352
|
+
the canonical v2.3.0 failure case and must remain a category
|
|
353
|
+
warning, not a filename warning).
|
|
354
|
+
|
|
355
|
+
If the concept you want to describe has no corresponding file in the
|
|
356
|
+
allowlist, either:
|
|
357
|
+
(a) describe the pattern abstractly ("a central router module"
|
|
358
|
+
rather than a fabricated concrete filename), OR
|
|
359
|
+
(b) omit the concrete citation entirely.
|
|
305
360
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
361
|
+
This rule is enforced post-generation by `content-validator [10/10]
|
|
362
|
+
path-claim verification`. Fabricated paths will be flagged as
|
|
363
|
+
`STALE_PATH` advisories. The allowlist exists so that those advisories
|
|
364
|
+
become rare — not so they become suppressible.
|
|
309
365
|
|
|
310
|
-
|
|
311
|
-
(prepended "feature" because the dir is `feature/`)
|
|
312
|
-
❌ WRONG: write `src/feature/routers/FEATURE_COMPONENT_MAP.ts`
|
|
313
|
-
(uppercased to match the TS constant name)
|
|
314
|
-
✅ RIGHT: write `src/feature/routers/routePath.ts`
|
|
366
|
+
**Secondary: filename-from-parent-directory hallucination:**
|
|
315
367
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
368
|
+
The single most common Pass 3 hallucination pattern is inferring a
|
|
369
|
+
filename from its parent directory. Consider a hypothetical project
|
|
370
|
+
where pass3a-facts.md lists a directory `src/feature/Xxx/` containing
|
|
371
|
+
files `Yyy.ts` and `Zzz.ts`:
|
|
372
|
+
|
|
373
|
+
Directory seen in facts: src/feature/Xxx/
|
|
374
|
+
File seen in facts: src/feature/Xxx/Yyy.ts
|
|
375
|
+
src/feature/Xxx/Zzz.ts
|
|
376
|
+
|
|
377
|
+
❌ WRONG: invent a new filename by prepending the parent directory
|
|
378
|
+
name (writing `src/feature/Xxx/featureYyy.ts` because the
|
|
379
|
+
parent dir is named `feature/`).
|
|
380
|
+
❌ WRONG: uppercase the filename to match a TypeScript constant
|
|
381
|
+
name (writing `src/feature/Xxx/YYY_MAP.ts` because the
|
|
382
|
+
module exports a constant named `YYY_MAP`).
|
|
383
|
+
✅ RIGHT: write the filename exactly as pass3a-facts.md lists it
|
|
384
|
+
(`src/feature/Xxx/Yyy.ts`).
|
|
385
|
+
|
|
386
|
+
Mechanism of the error: the model sees an ALL_CAPS TypeScript
|
|
387
|
+
constant name and "renormalizes" the filename to match it. TypeScript
|
|
388
|
+
identifiers and filenames are independent — do NOT let the constant's
|
|
389
|
+
name drive the filename you write. The filename in
|
|
390
|
+
`pass2-merged.json` is authoritative.
|
|
321
391
|
|
|
322
392
|
Same rule applies to domain prefixes in general:
|
|
323
|
-
- `src/feature/
|
|
393
|
+
- `src/feature/Xxx.ts` is the correct reference even when the file's
|
|
324
394
|
exported symbols start with `Feature*` or `FEATURE_*`.
|
|
325
395
|
- Do NOT prepend the parent directory name to the filename as a
|
|
326
396
|
disambiguator. The directory path is already the scope.
|
|
327
397
|
|
|
328
398
|
Library-convention hallucination class (equally important):
|
|
329
399
|
|
|
330
|
-
When
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
400
|
+
When discussing testing, mocking, styling, state management, environment
|
|
401
|
+
configuration, or similar library-centric topics in ANY generated file
|
|
402
|
+
(standard, rule, skill, guide — not just files named for the topic), do
|
|
403
|
+
NOT reach for "the canonical file location" from the library's own docs.
|
|
404
|
+
There is no canonical location — every project chooses its own.
|
|
405
|
+
|
|
406
|
+
**Scope note (v2.3.2+):** this constraint applies to EVERY file being
|
|
407
|
+
generated, not only to files whose names match the topic. A rule file
|
|
408
|
+
called `52.ai-work-rules.md` discussing test-running protocol can still
|
|
409
|
+
trip this trap; an infra file `01.environment-config.md` discussing env
|
|
410
|
+
typing can still trip it. The trigger is **the topic being described**,
|
|
411
|
+
not the filename of the document describing it.
|
|
412
|
+
|
|
413
|
+
Guidance (by topic):
|
|
414
|
+
|
|
415
|
+
- **Testing / mocking.** If pass3a-facts.md lists no test setup file
|
|
416
|
+
(e.g., the project has 0% coverage with vitest installed but no
|
|
417
|
+
tests), write the testing guidance in abstract terms ("a shared setup
|
|
418
|
+
module in a test directory of your choice") without citing a
|
|
419
|
+
framework-canonical path.
|
|
420
|
+
- **Environment typing.** If no `.d.ts` file appears in the allowlist,
|
|
421
|
+
describe the `ImportMetaEnv` interface inline ("augment `ImportMetaEnv`
|
|
422
|
+
in a type-declaration file of your project's choosing") without
|
|
423
|
+
naming a specific filename.
|
|
424
|
+
- **Styling / theming / state management.** If the specific file is
|
|
425
|
+
not in pass3a-facts.md, describe the pattern by role (what the file
|
|
426
|
+
does) rather than by name (what it is called).
|
|
427
|
+
|
|
428
|
+
**Important — how to write examples in rules (v2.3.2+):** rule files
|
|
429
|
+
(especially `52.ai-work-rules.md` and similar "meta" rules) sometimes
|
|
430
|
+
need to illustrate bad path habits as educational examples. When they
|
|
431
|
+
do, write the illustrative paths as **abstract placeholders** so the
|
|
432
|
+
validator recognizes them as teaching examples, not as concrete path
|
|
433
|
+
claims:
|
|
434
|
+
|
|
435
|
+
- Use generic directory references with a glob or ellipsis:
|
|
436
|
+
`src/test/…`, `src/types/*.d.ts`, `src/*/mocks/…`
|
|
437
|
+
- Use the `{placeholder}` form the validator already skips:
|
|
438
|
+
`src/{feature}/api/{Entity}.ts`, `src/hooks/use{Domain}.ts`
|
|
439
|
+
- Use the prose form: "a mock handler file under a `__mocks__/`
|
|
440
|
+
directory of your choice" rather than a concrete filename.
|
|
441
|
+
|
|
442
|
+
Do NOT cite a specific literal path (e.g., naming an exact file and
|
|
443
|
+
extension that happens to be the library's canonical location) in an
|
|
444
|
+
educational example. Literal paths are interpreted as real claims by
|
|
445
|
+
`content-validator [10/10]` regardless of surrounding prose. If the
|
|
446
|
+
example you want to give MUST be literal, add it to pass3a-facts.md
|
|
447
|
+
first (i.e., only literal paths that actually exist in the project).
|
|
448
|
+
|
|
449
|
+
**Hypothetical / future-tense framing is NOT a loophole (v2.3.2+):**
|
|
450
|
+
wrapping a framework-canonical path in conditional or future-tense
|
|
451
|
+
language (`if we adopted X`, `were this feature introduced, it would
|
|
452
|
+
live at …`, `for a future Y`, `when Z is added later`, etc., in ANY
|
|
453
|
+
output language) does NOT make the literal path safe. The validator
|
|
454
|
+
is content-blind and will flag
|
|
455
|
+
``if middleware is added later, place it at `src/middleware.ts` `` as
|
|
456
|
+
a `STALE_PATH` advisory because `src/middleware.ts` does not exist on
|
|
457
|
+
disk. This is the Next.js / Vite / Spring blind spot: the LLM, when
|
|
458
|
+
discussing future extensions, reaches for the framework's canonical
|
|
459
|
+
path as the "natural" location and writes it verbatim.
|
|
460
|
+
|
|
461
|
+
The correct hypothetical form describes the ROLE or DIRECTORY without
|
|
462
|
+
committing to a filename:
|
|
463
|
+
|
|
464
|
+
- ❌ WRONG: "If middleware is added, place it at `src/middleware.ts`."
|
|
465
|
+
- ❌ WRONG: "For a health endpoint in the future,
|
|
466
|
+
`src/app/api/health/route.ts`."
|
|
467
|
+
- ✅ RIGHT: "If middleware is added later, place it at the path
|
|
468
|
+
Next.js's routing convention expects for the version in use
|
|
469
|
+
(describe the role; do not cite a literal filename)."
|
|
470
|
+
- ✅ RIGHT: "A future health endpoint belongs under the project's
|
|
471
|
+
API route directory structure (see Next.js documentation for the
|
|
472
|
+
routing convention — do not assume a specific filename until the
|
|
473
|
+
file exists)."
|
|
474
|
+
- ✅ RIGHT: "If an env-typing file is introduced, augment
|
|
475
|
+
`ImportMetaEnv` in a type-declaration file placed under the
|
|
476
|
+
project's chosen convention."
|
|
477
|
+
|
|
478
|
+
In every case, if you cannot name the role + directory without
|
|
479
|
+
committing to a specific `src/...` path that does NOT appear in
|
|
480
|
+
pass3a-facts.md, OMIT the example entirely. An omitted example is
|
|
481
|
+
better than a fabricated path that downstream readers may treat as
|
|
482
|
+
authoritative. This rule applies regardless of the output language:
|
|
483
|
+
translated conditional phrases (Korean, Japanese, Chinese, etc.) do
|
|
484
|
+
not change the validator's literal-path detection — use a placeholder
|
|
485
|
+
form or omit.
|
|
486
|
+
|
|
487
|
+
Critical triggers for this class (the **topic**, not the filename):
|
|
488
|
+
- Testing / mocking / test-runner protocol — almost always tempts a mock
|
|
489
|
+
handler file or test setup file, even in AI-work or onboarding rules.
|
|
490
|
+
- Environment configuration / env typing — almost always tempts a
|
|
491
|
+
`.d.ts` file for `ImportMetaEnv` augmentation.
|
|
492
|
+
- Styling / theming — almost always tempts a global stylesheet or
|
|
493
|
+
theme file.
|
|
494
|
+
- State management — almost always tempts a store bootstrap file
|
|
495
|
+
(Redux, Zustand, etc.) even when the project uses only React Context.
|
|
361
496
|
|
|
362
497
|
The rule in all cases: if pass3a-facts.md has the concrete path,
|
|
363
498
|
use it verbatim; if not, describe the role without naming a file.
|
|
364
499
|
|
|
365
500
|
This rule is enforced post-generation by `content-validator [10/10]
|
|
366
501
|
path-claim verification`. Fabricated paths will be flagged as
|
|
367
|
-
`STALE_PATH`
|
|
502
|
+
`STALE_PATH` advisories with the path quoted back; the allowlist and
|
|
503
|
+
this explicit denylist exist so that those advisories become rare —
|
|
504
|
+
not so they become suppressible.
|
|
368
505
|
|
|
369
506
|
CRITICAL — MANIFEST ↔ CLAUDE.md §6 Skills consistency:
|
|
370
507
|
|
|
@@ -124,6 +124,42 @@ IMPORT, not redefine.
|
|
|
124
124
|
|
|
125
125
|
- ...
|
|
126
126
|
- ...
|
|
127
|
+
|
|
128
|
+
## Allowed Source Paths (v2.3.x+ — MANDATORY)
|
|
129
|
+
|
|
130
|
+
Copy the **entire** `allowedSourcePaths` section from `pass3-context.json`
|
|
131
|
+
verbatim into this pass3a-facts.md. Do NOT summarize it, do NOT truncate
|
|
132
|
+
it, do NOT reword it. The shape to copy:
|
|
133
|
+
|
|
134
|
+
- Header: whether the list is in `full` mode (individual file paths) or
|
|
135
|
+
`rollup` mode (parent directories, used when the project exceeds the
|
|
136
|
+
enumeration budget).
|
|
137
|
+
- Body: the exact list of paths (or directories in rollup mode), each
|
|
138
|
+
wrapped in backticks as a markdown bullet.
|
|
139
|
+
|
|
140
|
+
This section is the authoritative allowlist that Pass 3b/3c/3d consult
|
|
141
|
+
when deciding whether a `src/...`, `packages/...`, `apps/...`, or
|
|
142
|
+
language-specific source path may appear in a generated rule or standard
|
|
143
|
+
file. A path not appearing in this allowlist MUST NOT be written by
|
|
144
|
+
later passes — no exceptions, not even for paths that are "obvious" from
|
|
145
|
+
framework convention.
|
|
146
|
+
|
|
147
|
+
Rendering spec:
|
|
148
|
+
|
|
149
|
+
```markdown
|
|
150
|
+
## Allowed Source Paths
|
|
151
|
+
|
|
152
|
+
Source files on disk (total: <N>). [full-mode description paragraph from
|
|
153
|
+
pass3-context.json's allowedSourcePaths.paths field, copied verbatim.]
|
|
154
|
+
|
|
155
|
+
- `path/to/file1.ts`
|
|
156
|
+
- `path/to/file2.ts`
|
|
157
|
+
- ... (every entry from pass3-context.json)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
If `pass3-context.json`'s `allowedSourcePaths.paths` array is empty
|
|
161
|
+
(collection failed), emit a single line `(allowlist unavailable —
|
|
162
|
+
fall back to pass2-merged.json verification per file)` instead.
|
|
127
163
|
```
|
|
128
164
|
|
|
129
165
|
## Rules for Pass 3a
|
|
@@ -131,13 +167,22 @@ IMPORT, not redefine.
|
|
|
131
167
|
1. **Read each input file AT MOST ONCE.** After reading, all fact extraction
|
|
132
168
|
must be from your in-context memory of the file.
|
|
133
169
|
2. **Be terse.** This document will be loaded into every subsequent Pass 3
|
|
134
|
-
step's context. Keep
|
|
170
|
+
step's context. Keep the non-allowlist portions under 10 KB. The
|
|
171
|
+
`## Allowed Source Paths` section is exempt from the 10 KB budget
|
|
172
|
+
because it is the authoritative path reference that prevents Pass 3
|
|
173
|
+
hallucination — its size is bounded by the MAX_PATHS (500) / MAX_DIRS
|
|
174
|
+
(300) caps in plan-installer/source-paths.js.
|
|
135
175
|
3. **Exact values only.** Every class name, method name, package path, and
|
|
136
176
|
file path must be verbatim from the analysis data. If a value is not
|
|
137
177
|
captured in the analysis, write `(not in analysis)` — do NOT guess.
|
|
138
|
-
4. **
|
|
178
|
+
4. **Allowed Source Paths section is COPIED, not extracted.** Do not apply
|
|
179
|
+
judgment, ranking, or "relevance filtering" to the allowlist. The
|
|
180
|
+
whole point is that Pass 3b/3c/3d get the complete enumeration; any
|
|
181
|
+
path you drop here becomes a path they can fabricate later without
|
|
182
|
+
the downstream validator catching it until after Pass 3 completes.
|
|
183
|
+
5. **Do NOT write any other files.** CLAUDE.md, standard/, rules/, etc.
|
|
139
184
|
come in later Pass 3 steps. Writing them here is a bug.
|
|
140
|
-
|
|
185
|
+
6. **Do NOT read source code.** All information comes from the three JSON
|
|
141
186
|
inputs. The source has already been analyzed in Pass 1 and Pass 2.
|
|
142
187
|
|
|
143
188
|
Once `pass3a-facts.md` is written, Pass 3a is complete.
|
|
@@ -29,48 +29,86 @@ MUST appear verbatim in `pass3a-facts.md` or `pass2-merged.json`. If a
|
|
|
29
29
|
concrete path is not in those analysis artifacts, OMIT it — do NOT write it.
|
|
30
30
|
|
|
31
31
|
Do NOT invent paths based on framework convention, prior training knowledge,
|
|
32
|
-
or extrapolation from symbol names. The most common
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
32
|
+
or extrapolation from symbol names. The three most common hallucination
|
|
33
|
+
failures are described below by MECHANISM (not by literal example path,
|
|
34
|
+
because literal examples in educational prose have historically leaked
|
|
35
|
+
into generated outputs as real claims):
|
|
36
|
+
|
|
37
|
+
❌ **Framework-convention entry-point invention.**
|
|
38
|
+
Citing a framework's stock entry-point file (Vite's main module, Next.js
|
|
39
|
+
app-router files, Spring's default resource config, etc.) because the
|
|
40
|
+
framework docs show that as the canonical location. This project may use
|
|
41
|
+
a different entry, a renamed entry, or a multi-entry layout where no
|
|
42
|
+
single canonical file exists. Check pass3a-facts.md; if no such path is
|
|
43
|
+
listed, do NOT write it.
|
|
44
|
+
|
|
45
|
+
❌ **Parent-directory or constant-name renormalization of a filename.**
|
|
46
|
+
Inventing a filename by prepending the parent directory's name to it
|
|
47
|
+
(the <dirname><actual-basename>.ts anti-pattern), or by converting a
|
|
48
|
+
TypeScript constant / Java annotation / Python decorator name into
|
|
49
|
+
a filename (an ALL_CAPS_CONSTANT becoming a camelCase or PascalCase
|
|
50
|
+
filename). Identifiers and filenames are independent. The
|
|
51
|
+
authoritative filename is whatever pass3a-facts.md lists under the
|
|
52
|
+
relevant section — use that verbatim, do not "normalize" it.
|
|
53
|
+
|
|
54
|
+
❌ **Plausibly-named utility invention.**
|
|
55
|
+
Writing a concrete filename for a utility that "would naturally" exist
|
|
56
|
+
under a seen directory (a class-name-builder helper under a `utils/`
|
|
57
|
+
directory, a string-formatter under a `helpers/` directory). "Plausible"
|
|
58
|
+
is not a sufficient ground for a concrete path claim. If you want to
|
|
59
|
+
reference a utility layer in a rule file, reference the directory
|
|
60
|
+
itself rather than inventing a filename.
|
|
61
|
+
|
|
62
|
+
❌ Library-convention canonical paths (testing / env typing / styling /
|
|
63
|
+
state management / routing conventions) — invented based on framework
|
|
64
|
+
or library documentation.
|
|
65
|
+
— Testing frameworks (MSW, Vitest, Jest, RTL) show canonical mock /
|
|
66
|
+
setup / test-utility locations in their docs; TypeScript + Vite /
|
|
67
|
+
CRA show a canonical `ImportMetaEnv` augmentation location; CSS-in-JS
|
|
68
|
+
and state-management libraries show canonical store / theme
|
|
69
|
+
locations. These are PROJECT-CHOICE files — every project picks its
|
|
70
|
+
own structure, and the library's canonical path may not exist here.
|
|
71
|
+
**Scope note (v2.3.2+):** this trap fires whenever the topic of a
|
|
72
|
+
generated file touches these areas (testing, env typing, styling,
|
|
73
|
+
state management), not only when the file is named after the topic.
|
|
74
|
+
It fires in `ai-work-rules.md`, onboarding guides, infra rules,
|
|
75
|
+
CRUD skills — anywhere the topic appears. If pass3a-facts.md lacks
|
|
76
|
+
the concrete file, describe the pattern by role ("a shared setup
|
|
77
|
+
module under a test directory of your choice", "augment
|
|
78
|
+
`ImportMetaEnv` in a type-declaration file of your choosing"), not
|
|
79
|
+
by filename. When illustrating bad path habits as an educational
|
|
80
|
+
example in a rule, use abstract placeholders (`{placeholder}`,
|
|
81
|
+
`src/*/dir/…`) rather than literal paths — literal example paths
|
|
82
|
+
are interpreted as real claims by `content-validator [10/10]`
|
|
83
|
+
regardless of surrounding prose.
|
|
84
|
+
|
|
85
|
+
❌ **Hypothetical / future-tense framing is NOT a loophole (v2.3.2+).**
|
|
86
|
+
Wrapping a framework-canonical path in conditional or future-tense
|
|
87
|
+
language (`if we adopted X`, `were this feature introduced, it
|
|
88
|
+
would live at …`, `for a future Y`, `when Z is added later`, etc.,
|
|
89
|
+
in ANY output language — translated conditional phrases do not
|
|
90
|
+
change the validator's literal-path detection) does NOT make the
|
|
91
|
+
literal path safe. The validator is content-blind and will flag
|
|
92
|
+
``if middleware is added later, place it at `src/middleware.ts` ``
|
|
93
|
+
as a `STALE_PATH` advisory because the file does not exist on disk.
|
|
94
|
+
This is the Next.js / Vite / Spring blind spot: the LLM, when
|
|
95
|
+
discussing future extensions, reaches for the framework's canonical
|
|
96
|
+
path as the "natural" location and writes it verbatim. The correct
|
|
97
|
+
hypothetical form describes the ROLE or DIRECTORY without
|
|
98
|
+
committing to a filename (e.g., "If middleware is added, place it
|
|
99
|
+
at the path the routing convention expects — do not cite a
|
|
100
|
+
specific filename until the file actually exists"). When in doubt,
|
|
101
|
+
OMIT the hypothetical example entirely; an omitted example is
|
|
102
|
+
better than a fabricated path readers may treat as authoritative.
|
|
103
|
+
|
|
104
|
+
✅ If pass3a-facts.md shows a specific filename and path for a role
|
|
105
|
+
(e.g., a response-wrapper module at a specific location under the
|
|
106
|
+
api directory), write that exact path verbatim — do not re-describe
|
|
107
|
+
it, do not abbreviate it, do not rename it.
|
|
71
108
|
|
|
72
109
|
✅ When in doubt, write the rule in terms of the pattern (e.g., "handwritten
|
|
73
|
-
API modules under
|
|
110
|
+
API modules under the api directory listed in pass3a-facts.md") rather
|
|
111
|
+
than a specific file name invented on the spot.
|
|
74
112
|
A directory-scoped rule is correct; an invented file path is a bug.
|
|
75
113
|
|
|
76
114
|
✅ For testing-strategy documents specifically: if the project has zero
|
|
@@ -1,6 +1,60 @@
|
|
|
1
1
|
Read claudeos-core/generated/project-analysis.json and
|
|
2
2
|
perform a deep analysis of the following domains only: {{DOMAIN_GROUP}}
|
|
3
3
|
|
|
4
|
+
## MANDATORY: Configuration file verification (read before analysis)
|
|
5
|
+
|
|
6
|
+
Before analyzing domain source code, read the following configuration
|
|
7
|
+
files if they exist in the project root. The stack metadata in
|
|
8
|
+
`project-analysis.json` is produced by a regex-based static analyzer
|
|
9
|
+
and may be incomplete for modern Gradle/Maven projects. Reading these
|
|
10
|
+
files directly gives you the ground truth for Java version, server
|
|
11
|
+
port, active profile, datasource configuration, and logging setup.
|
|
12
|
+
|
|
13
|
+
Required reads (if the file exists):
|
|
14
|
+
|
|
15
|
+
1. **`build.gradle` or `build.gradle.kts`** (or **`pom.xml`** for Maven).
|
|
16
|
+
Specifically check:
|
|
17
|
+
- Java version: look inside `java { ... }`, `java { toolchain { ... } }`,
|
|
18
|
+
`sourceCompatibility`, `targetCompatibility`, or `<java.version>` /
|
|
19
|
+
`<maven.compiler.source>` in pom.xml. If the value is a variable
|
|
20
|
+
reference (e.g., `sourceCompatibility = "${javaVersion}"`), resolve
|
|
21
|
+
the variable inside `ext { ... }` or `<properties>`. Record the
|
|
22
|
+
ACTUAL Java version — do NOT infer "Java 17+" from the Spring
|
|
23
|
+
Boot version.
|
|
24
|
+
- Spring Boot version: verify it matches `project-analysis.json`'s
|
|
25
|
+
frameworkVersion field; if they disagree, trust the build file.
|
|
26
|
+
- Dependencies that indicate specific patterns (MyBatis/iBatis/JPA,
|
|
27
|
+
multiple DB drivers, Jasypt, JWT library, Logback extras).
|
|
28
|
+
|
|
29
|
+
2. **`application.yml` / `application.yaml` / `application.properties`
|
|
30
|
+
and their profile variants** (`application-{profile}.{yml,yaml,properties}`).
|
|
31
|
+
Specifically check:
|
|
32
|
+
- Server port: look for `server.port`. Spring Boot accepts property
|
|
33
|
+
placeholders with defaults like `port: ${G_PORT:8090}` — extract the
|
|
34
|
+
default value (the post-colon number) as the ACTUAL port. Do NOT
|
|
35
|
+
assume "port 8080" from the Spring Boot framework default.
|
|
36
|
+
- Active profile(s): `spring.profiles.active` and `spring.profiles.group`.
|
|
37
|
+
- Datasource: every `spring.datasource.*` block (multi-dialect projects
|
|
38
|
+
declare more than one; a `group` profile block like
|
|
39
|
+
`"local": "local,postgres"` reveals which DB is active per profile).
|
|
40
|
+
- Logging configuration file reference: `logging.config` points to
|
|
41
|
+
the real log setup (e.g., `classpath:logback-app.xml`). Read that
|
|
42
|
+
file too to understand appenders, levels, and JDBC logging
|
|
43
|
+
adapters like `log4jdbc`.
|
|
44
|
+
|
|
45
|
+
3. **Any referenced logging configuration files**: `logback*.xml`,
|
|
46
|
+
`logback*.groovy`, `log4j*.xml`, `log4j*.properties`,
|
|
47
|
+
`log4jdbc*.properties`. These reveal the actual logging framework
|
|
48
|
+
in use (Logback is the Spring Boot default but legacy projects may
|
|
49
|
+
use Log4j2 or mix with JDBC adapters).
|
|
50
|
+
|
|
51
|
+
When `project-analysis.json` and the configuration files disagree,
|
|
52
|
+
record the configuration-file value as the truth and note the
|
|
53
|
+
discrepancy in your analysis output. This is the path to eliminate
|
|
54
|
+
"Java 17+" / "port 8080" hallucinations observed in pre-v2.3.2 runs.
|
|
55
|
+
|
|
56
|
+
## Domain analysis
|
|
57
|
+
|
|
4
58
|
For each domain, select one representative file per layer, read its code, and analyze it.
|
|
5
59
|
Prioritize files with the richest patterns.
|
|
6
60
|
|
|
@@ -114,7 +114,7 @@ Generation targets:
|
|
|
114
114
|
- `10.backend/*` rules: `paths: ["**/*"]` — always loaded (backend rules needed for any source editing)
|
|
115
115
|
- `30.security-db/*` rules: `paths: ["**/*"]` — always loaded (cross-cutting concerns)
|
|
116
116
|
- `40.infra/01.environment-config-rules.md` paths: `["**/*.properties", "**/*.yml", "**/*.yaml", "**/.env*", "**/config/**", "**/application*.properties"]` — Spring config files
|
|
117
|
-
- `40.infra/02.logging-monitoring-rules.md` paths: `["**/*.java", "**/logback*.xml", "**/log4j*.xml"]` — source code where logs live + log config
|
|
117
|
+
- `40.infra/02.logging-monitoring-rules.md` paths: `["**/*.java", "**/logback*.xml", "**/logback*.groovy", "**/log4j*.xml", "**/log4j*.properties", "**/log4jdbc*.properties"]` — source code where logs live + log config (covers Logback XML/Groovy DSL, Log4j/Log4j2 XML/properties, and log4jdbc JDBC-logging adapter properties)
|
|
118
118
|
- `40.infra/03.cicd-deployment-rules.md` paths: `["**/*.yml", "**/*.yaml", "**/Dockerfile*", "**/*.gradle*", "**/pom.xml", "**/*.java"]` — CI / build config + source
|
|
119
119
|
- `50.sync/*` rules: `paths: ["**/claudeos-core/**", "**/.claude/**"]` — loaded only when editing claudeos-core files
|
|
120
120
|
- `60.memory/*` rules: forward reference — Pass 4 will generate 4 files (01.decision-log, 02.failure-patterns, 03.compaction, 04.auto-rule-update), each with file-specific `paths`. Pass 3 must STILL list ```.claude/rules/60.memory/*``` as a row in CLAUDE.md Section 6 Rules table so developers/Claude see the category exists.
|
|
@@ -1,6 +1,51 @@
|
|
|
1
1
|
Read claudeos-core/generated/project-analysis.json and
|
|
2
2
|
perform a deep analysis of the following domains only: {{DOMAIN_GROUP}}
|
|
3
3
|
|
|
4
|
+
## MANDATORY: Configuration file verification (read before analysis)
|
|
5
|
+
|
|
6
|
+
Before analyzing domain source code, read the following configuration
|
|
7
|
+
files if they exist in the project root. The stack metadata in
|
|
8
|
+
`project-analysis.json` is produced by a regex-based static analyzer
|
|
9
|
+
and may be incomplete for modern Gradle/Maven projects. Reading these
|
|
10
|
+
files directly gives you the ground truth for Kotlin/Java version,
|
|
11
|
+
server port, active profile, datasource configuration, and logging.
|
|
12
|
+
|
|
13
|
+
Required reads (if the file exists):
|
|
14
|
+
|
|
15
|
+
1. **`build.gradle.kts` or `build.gradle`** (or **`pom.xml`** for Maven).
|
|
16
|
+
Specifically check:
|
|
17
|
+
- Kotlin version: look inside `plugins { kotlin("jvm") version "..." }`
|
|
18
|
+
or `libs.versions.toml`. If it's a variable reference, resolve it.
|
|
19
|
+
- Java target: look inside `kotlin { jvmToolchain(N) }`,
|
|
20
|
+
`tasks.withType<KotlinCompile> { kotlinOptions.jvmTarget = "..." }`,
|
|
21
|
+
or `java { toolchain { languageVersion = JavaLanguageVersion.of(N) } }`.
|
|
22
|
+
Record the ACTUAL target — do NOT infer from the Spring Boot version.
|
|
23
|
+
- Spring Boot version: verify it matches `project-analysis.json`'s
|
|
24
|
+
frameworkVersion field; if they disagree, trust the build file.
|
|
25
|
+
- Dependencies that indicate specific patterns (Exposed/JPA/jOOQ/R2DBC,
|
|
26
|
+
multiple DB drivers, Koin/Kodein, coroutines extensions).
|
|
27
|
+
|
|
28
|
+
2. **`application.yml` / `application.yaml` / `application.properties`
|
|
29
|
+
and their profile variants** (`application-{profile}.{yml,yaml,properties}`).
|
|
30
|
+
Specifically check:
|
|
31
|
+
- Server port: look for `server.port`. Spring Boot accepts property
|
|
32
|
+
placeholders with defaults like `port: ${PORT:8080}` — extract the
|
|
33
|
+
default value (the post-colon number) as the ACTUAL port. Do NOT
|
|
34
|
+
assume "port 8080" from the Spring Boot framework default.
|
|
35
|
+
- Active profile(s): `spring.profiles.active` and `spring.profiles.group`.
|
|
36
|
+
- Datasource: every `spring.datasource.*` block.
|
|
37
|
+
- Logging configuration file reference: `logging.config` points to
|
|
38
|
+
the real log setup. Read that file too.
|
|
39
|
+
|
|
40
|
+
3. **Any referenced logging configuration files**: `logback*.xml`,
|
|
41
|
+
`logback*.groovy`, `log4j*.xml`, `log4j*.properties`.
|
|
42
|
+
|
|
43
|
+
When `project-analysis.json` and the configuration files disagree,
|
|
44
|
+
record the configuration-file value as the truth and note the
|
|
45
|
+
discrepancy in your analysis output.
|
|
46
|
+
|
|
47
|
+
## Domain analysis
|
|
48
|
+
|
|
4
49
|
For each domain, select one representative file per layer, read its code, and analyze it.
|
|
5
50
|
Prioritize files with the richest patterns.
|
|
6
51
|
For multi-module domains, analyze files from EACH module (command, query, bff) separately.
|
|
@@ -119,7 +119,7 @@ Generation targets:
|
|
|
119
119
|
- `10.backend/*` rules: `paths: ["**/*"]` — always loaded (backend rules needed for any source editing)
|
|
120
120
|
- `30.security-db/*` rules: `paths: ["**/*"]` — always loaded (cross-cutting concerns)
|
|
121
121
|
- `40.infra/01.environment-config-rules.md` paths: `["**/*.properties", "**/*.yml", "**/*.yaml", "**/.env*", "**/config/**", "**/application*.properties"]` — Spring config files
|
|
122
|
-
- `40.infra/02.logging-monitoring-rules.md` paths: `["**/*.kt", "**/*.kts", "**/logback*.xml"]` — source code where logs live + log config
|
|
122
|
+
- `40.infra/02.logging-monitoring-rules.md` paths: `["**/*.kt", "**/*.kts", "**/logback*.xml", "**/logback*.groovy", "**/log4j*.xml", "**/log4j*.properties", "**/log4jdbc*.properties"]` — source code where logs live + log config (covers Logback XML/Groovy DSL, Log4j/Log4j2 XML/properties, and log4jdbc JDBC-logging adapter properties)
|
|
123
123
|
- `40.infra/03.cicd-deployment-rules.md` paths: `["**/*.yml", "**/*.yaml", "**/Dockerfile*", "**/*.gradle*", "**/*.kt", "**/*.kts"]` — CI / build config + source
|
|
124
124
|
- `50.sync/*` rules: `paths: ["**/claudeos-core/**", "**/.claude/**"]` — loaded only when editing claudeos-core files
|
|
125
125
|
- `60.memory/*` rules: forward reference — Pass 4 will generate 4 files (01.decision-log, 02.failure-patterns, 03.compaction, 04.auto-rule-update), each with file-specific `paths`. Pass 3 must STILL list ```.claude/rules/60.memory/*``` as a row in CLAUDE.md Section 6 Rules table so developers/Claude see the category exists.
|