claudeos-core 2.3.1 → 2.4.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.
- package/CHANGELOG.md +1460 -73
- package/CODE_OF_CONDUCT.md +15 -0
- package/README.de.md +321 -883
- package/README.es.md +322 -883
- package/README.fr.md +322 -883
- package/README.hi.md +322 -883
- package/README.ja.md +322 -883
- package/README.ko.md +322 -882
- package/README.md +321 -883
- package/README.ru.md +322 -885
- package/README.vi.md +322 -883
- package/README.zh-CN.md +321 -881
- package/SECURITY.md +51 -0
- package/bin/commands/init.js +570 -264
- package/content-validator/index.js +185 -12
- package/health-checker/index.js +44 -10
- package/package.json +92 -90
- package/pass-json-validator/index.js +58 -7
- package/pass-prompts/templates/angular/pass3.md +15 -14
- package/pass-prompts/templates/common/claude-md-scaffold.md +203 -20
- package/pass-prompts/templates/common/pass3-footer.md +297 -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 +20 -19
- package/pass-prompts/templates/kotlin-spring/pass1.md +45 -0
- package/pass-prompts/templates/kotlin-spring/pass3.md +24 -23
- package/pass-prompts/templates/node-express/pass3.md +18 -17
- package/pass-prompts/templates/node-fastify/pass3.md +11 -10
- package/pass-prompts/templates/node-nestjs/pass3.md +11 -10
- package/pass-prompts/templates/node-nextjs/pass3.md +18 -17
- package/pass-prompts/templates/node-vite/pass3.md +11 -10
- package/pass-prompts/templates/python-django/pass3.md +18 -17
- package/pass-prompts/templates/python-fastapi/pass3.md +18 -17
- package/pass-prompts/templates/python-flask/pass3.md +9 -8
- package/pass-prompts/templates/vue-nuxt/pass3.md +9 -8
- package/plan-installer/domain-grouper.js +45 -5
- package/plan-installer/index.js +34 -1
- package/plan-installer/pass3-context-builder.js +14 -0
- package/plan-installer/scanners/scan-frontend.js +2 -1
- package/plan-installer/scanners/scan-java.js +98 -2
- package/plan-installer/source-paths.js +242 -0
- package/plan-installer/stack-detector.js +522 -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
|
|
|
@@ -398,5 +535,109 @@ level (the scaffold's PROJECT_CONTEXT mentions architecture style),
|
|
|
398
535
|
but it does NOT enumerate rules. Section 6 "Standard / Rules / Skills
|
|
399
536
|
Reference" provides a REFERENCE INDEX (what exists), not rule content.
|
|
400
537
|
|
|
538
|
+
CRITICAL — Standard files MUST include both ✅ and ❌ examples:
|
|
539
|
+
Every file under `claudeos-core/standard/**/*.md` (except pure index/overview
|
|
540
|
+
files like `00.core/01.project-overview.md`) MUST contain BOTH:
|
|
541
|
+
- At least one ✅ Correct example (a fenced code block showing the right way)
|
|
542
|
+
- At least one ❌ Incorrect example (a fenced code block showing the wrong way)
|
|
543
|
+
|
|
544
|
+
Skipping the ❌ block is a common Pass 3b LLM failure mode that produces
|
|
545
|
+
`[NO_BAD_EXAMPLE]` advisories from `content-validator`. Even if you can only
|
|
546
|
+
think of a minimal contrastive ❌ (a one-line wrong call, a missing
|
|
547
|
+
annotation, a typo'd config key), include it. The contrast is what gives
|
|
548
|
+
the standard its didactic value — a file with only ✅ examples reads as
|
|
549
|
+
"this is one way to do it", whereas ✅+❌ reads as "this is the way; here is
|
|
550
|
+
the failure mode".
|
|
551
|
+
|
|
552
|
+
Self-check before finalizing each standard file:
|
|
553
|
+
- Does this file have at least one ```...``` block marked ✅?
|
|
554
|
+
- Does this file have at least one ```...``` block marked ❌?
|
|
555
|
+
If either is missing, add it before moving on.
|
|
556
|
+
|
|
557
|
+
CRITICAL — Per-domain folder convention (`70.domains/{type}/`, plural):
|
|
558
|
+
|
|
559
|
+
When generating per-domain files (any output that's specific to one
|
|
560
|
+
project domain — e.g. `payment.md`, `order.md`, `member.md`), use the
|
|
561
|
+
canonical `70.domains/` folder (PLURAL, collection-style) and ALWAYS
|
|
562
|
+
include a `{type}/` sub-folder (`backend/` or `frontend/`) regardless
|
|
563
|
+
of single-stack or multi-stack project. Uniform-convention rationale
|
|
564
|
+
in the next paragraph.
|
|
565
|
+
|
|
566
|
+
- Per-domain standard:
|
|
567
|
+
`claudeos-core/standard/70.domains/{type}/{domain}.md`
|
|
568
|
+
where `{type}` is `backend` or `frontend`
|
|
569
|
+
- Per-domain rule:
|
|
570
|
+
`.claude/rules/70.domains/{type}/{domain}-rules.md`
|
|
571
|
+
(via staging-override path
|
|
572
|
+
`claudeos-core/generated/.staged-rules/70.domains/{type}/{domain}-rules.md`,
|
|
573
|
+
each rule file MUST have a `paths:` frontmatter glob scoping to that
|
|
574
|
+
domain's source directories)
|
|
575
|
+
|
|
576
|
+
**Why ALWAYS the `{type}/` sub-folder, even for single-stack projects?**
|
|
577
|
+
A single-stack project pays a 1-folder depth cost
|
|
578
|
+
(`70.domains/backend/order.md` instead of `70.domains/order.md`). In
|
|
579
|
+
exchange:
|
|
580
|
+
|
|
581
|
+
1. **Zero migration when the other stack is added.** A backend-only
|
|
582
|
+
project that later adds a Next.js frontend does NOT need to move
|
|
583
|
+
existing files to `backend/` — they're already there.
|
|
584
|
+
2. **No LLM probabilistic drift.** Pass 3 LLM never has to decide
|
|
585
|
+
"is this single-stack or multi?" — the pattern is always the
|
|
586
|
+
same.
|
|
587
|
+
3. **One pattern for validators.** `content-validator` and
|
|
588
|
+
`claude-md-validator` recognize a single layout instead of
|
|
589
|
+
branching.
|
|
590
|
+
4. **Future-proof for new stack types** (mobile, cli, agent, ...).
|
|
591
|
+
|
|
592
|
+
The Pass 3 orchestrator (`bin/commands/init.js`) classifies each
|
|
593
|
+
domain via `project-analysis.json` and emits per-domain target paths
|
|
594
|
+
explicitly in the batch scope note. **Follow the explicit
|
|
595
|
+
per-domain target paths shown in the scope note** rather than infer
|
|
596
|
+
from the domain name. If the scope note shows
|
|
597
|
+
`order → claudeos-core/standard/70.domains/backend/order.md`, that's
|
|
598
|
+
the path to use — the type sub-folder is already classified for you.
|
|
599
|
+
|
|
600
|
+
- Per-domain skill notes:
|
|
601
|
+
`claudeos-core/skills/{category}/domains/{domain}.md`
|
|
602
|
+
(sub-folder under skill category — `skills/` is a separate namespace
|
|
603
|
+
from standard/rules, so no number prefix here. The `{category}`
|
|
604
|
+
folder name already encodes stack: `10.backend-crud/`,
|
|
605
|
+
`20.frontend-page/`. So skills don't need the additional `{type}/`
|
|
606
|
+
sub-folder that standard/rules use.)
|
|
607
|
+
- Per-domain skill ORCHESTRATOR (sibling to the `domains/` sub-folder):
|
|
608
|
+
`claudeos-core/skills/{category}/02.domains.md`
|
|
609
|
+
The orchestrator is REQUIRED when the `domains/` sub-folder is
|
|
610
|
+
populated. It mirrors the canonical pattern already used for
|
|
611
|
+
`01.scaffold-crud-feature.md` ↔ `scaffold-crud-feature/` (orchestrator
|
|
612
|
+
file at category root + sub-folder of the same stem). The basename
|
|
613
|
+
stem (`domains`) MUST match the sub-folder name so
|
|
614
|
+
`content-validator`'s standard orchestrator-stem matching covers
|
|
615
|
+
the sub-skills directly — without depending on the
|
|
616
|
+
global-MANIFEST coverage fallback. The orchestrator content lists
|
|
617
|
+
every per-domain note file in the `domains/` sub-folder, links to
|
|
618
|
+
`00.shared/MANIFEST.md`, and describes the per-domain anti-pattern
|
|
619
|
+
catalog if applicable. Numbered `02.` because `01.scaffold-*-feature.md`
|
|
620
|
+
already occupies the `01.` slot at the category root.
|
|
621
|
+
|
|
622
|
+
Why `70.` and not `60.`: `60.memory/*` is the canonical L4 memory rules
|
|
623
|
+
folder (regression-guarded since v2.0.0; cannot move to 70). Putting
|
|
624
|
+
domains at `60.domains/` causes a `60.` prefix collision with
|
|
625
|
+
`60.memory/` that makes directory listings ambiguous. `70.domains/` sits
|
|
626
|
+
after memory and before `90.optional/`, giving per-domain content its
|
|
627
|
+
own clean slot.
|
|
628
|
+
|
|
629
|
+
Why PLURAL `domains/`: the folder holds N files, one per project domain
|
|
630
|
+
— `payment.md`, `order.md`, etc. This matches the standard filesystem
|
|
631
|
+
convention for collections (`users/user.md`, `posts/post.md`). The other
|
|
632
|
+
numbered category folders (`00.core/`, `10.backend/`, etc.) are singular
|
|
633
|
+
because each represents ONE topic, not a collection of items.
|
|
634
|
+
|
|
635
|
+
DO NOT use:
|
|
636
|
+
- `60.domains/` (collides with `60.memory/`)
|
|
637
|
+
- `70.domain/` (singular is wrong for a collection folder)
|
|
638
|
+
- Inlining per-domain content into `00.core/*` or topical files
|
|
639
|
+
(per-domain content is DOMAIN-scoped, topical files are TOPIC-scoped
|
|
640
|
+
— `paths` glob scoping breaks if they share files)
|
|
641
|
+
|
|
401
642
|
After completion, run the following commands in order:
|
|
402
643
|
1. npx claudeos-core health
|
|
@@ -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
|