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.
Files changed (43) hide show
  1. package/CHANGELOG.md +1460 -73
  2. package/CODE_OF_CONDUCT.md +15 -0
  3. package/README.de.md +321 -883
  4. package/README.es.md +322 -883
  5. package/README.fr.md +322 -883
  6. package/README.hi.md +322 -883
  7. package/README.ja.md +322 -883
  8. package/README.ko.md +322 -882
  9. package/README.md +321 -883
  10. package/README.ru.md +322 -885
  11. package/README.vi.md +322 -883
  12. package/README.zh-CN.md +321 -881
  13. package/SECURITY.md +51 -0
  14. package/bin/commands/init.js +570 -264
  15. package/content-validator/index.js +185 -12
  16. package/health-checker/index.js +44 -10
  17. package/package.json +92 -90
  18. package/pass-json-validator/index.js +58 -7
  19. package/pass-prompts/templates/angular/pass3.md +15 -14
  20. package/pass-prompts/templates/common/claude-md-scaffold.md +203 -20
  21. package/pass-prompts/templates/common/pass3-footer.md +297 -56
  22. package/pass-prompts/templates/common/pass3a-facts.md +48 -3
  23. package/pass-prompts/templates/common/pass4.md +78 -40
  24. package/pass-prompts/templates/java-spring/pass1.md +54 -0
  25. package/pass-prompts/templates/java-spring/pass3.md +20 -19
  26. package/pass-prompts/templates/kotlin-spring/pass1.md +45 -0
  27. package/pass-prompts/templates/kotlin-spring/pass3.md +24 -23
  28. package/pass-prompts/templates/node-express/pass3.md +18 -17
  29. package/pass-prompts/templates/node-fastify/pass3.md +11 -10
  30. package/pass-prompts/templates/node-nestjs/pass3.md +11 -10
  31. package/pass-prompts/templates/node-nextjs/pass3.md +18 -17
  32. package/pass-prompts/templates/node-vite/pass3.md +11 -10
  33. package/pass-prompts/templates/python-django/pass3.md +18 -17
  34. package/pass-prompts/templates/python-fastapi/pass3.md +18 -17
  35. package/pass-prompts/templates/python-flask/pass3.md +9 -8
  36. package/pass-prompts/templates/vue-nuxt/pass3.md +9 -8
  37. package/plan-installer/domain-grouper.js +45 -5
  38. package/plan-installer/index.js +34 -1
  39. package/plan-installer/pass3-context-builder.js +14 -0
  40. package/plan-installer/scanners/scan-frontend.js +2 -1
  41. package/plan-installer/scanners/scan-java.js +98 -2
  42. package/plan-installer/source-paths.js +242 -0
  43. package/plan-installer/stack-detector.js +522 -42
@@ -56,20 +56,20 @@ Generation targets:
56
56
  - 00.core/01.project-overview.md — Stack, app list, server info
57
57
  - 00.core/02.architecture.md — MTV structure, request flow, app structure
58
58
  - 00.core/03.naming-conventions.md — App/model/view/serializer naming conventions
59
- - 10.backend-api/01.view-patterns.md — FBV/CBV/ViewSet patterns + examples
60
- - 10.backend-api/02.serializer-patterns.md — Serializer writing rules + validation
61
- - 10.backend-api/03.model-patterns.md — Model structure, Manager, Signal, QuerySet
62
- - 10.backend-api/04.response-exception.md — Response/error handling patterns
63
- - 10.backend-api/05.business-logic.md — Service Layer, transactions, Celery
64
- - 10.backend-api/06.admin-patterns.md — Admin customization, Inline, actions
59
+ - 10.backend/01.view-patterns.md — FBV/CBV/ViewSet patterns + examples
60
+ - 10.backend/02.serializer-patterns.md — Serializer writing rules + validation
61
+ - 10.backend/03.model-patterns.md — Model structure, Manager, Signal, QuerySet
62
+ - 10.backend/04.response-exception.md — Response/error handling patterns
63
+ - 10.backend/05.business-logic.md — Service Layer, transactions, Celery
64
+ - 10.backend/06.admin-patterns.md — Admin customization, Inline, actions
65
65
  - 30.security-db/01.security-auth.md — JWT, Permission, CORS, CSRF
66
66
  - 30.security-db/02.database-schema.md — Migrations, fixtures, schema conventions
67
67
  - 30.security-db/03.common-utilities.md — Common utils, custom Manager, constants
68
68
  - 40.infra/01.environment-config.md — Settings separation, environment variables
69
69
  - 40.infra/02.logging-monitoring.md — Logging standards, monitoring
70
70
  - 40.infra/03.cicd-deployment.md — CI/CD, Docker, deployment strategy
71
- - 50.verification/01.development-verification.md — Testing, startup, API testing
72
- - 50.verification/02.testing-strategy.md — pytest, Factory, mocking, coverage
71
+ - 80.verification/01.development-verification.md — Testing, startup, API testing
72
+ - 80.verification/02.testing-strategy.md — pytest, Factory, mocking, coverage
73
73
 
74
74
  Each file MUST include:
75
75
  - Correct examples (✅ code blocks)
@@ -83,7 +83,7 @@ Generation targets:
83
83
  - Each rule file MUST end with a `## Reference` section linking to the corresponding standard file(s):
84
84
  ```
85
85
  ## Reference
86
- > For detailed patterns and examples, Read: claudeos-core/standard/10.backend-api/01.view-patterns.md
86
+ > For detailed patterns and examples, Read: claudeos-core/standard/10.backend/01.view-patterns.md
87
87
  ```
88
88
  - `paths:` frontmatter per rule category:
89
89
  - `00.core/*` rules: `paths: ["**/*"]` — always loaded (architecture, naming are universally needed)
@@ -94,6 +94,7 @@ Generation targets:
94
94
  - `40.infra/03.cicd-deployment-rules.md` paths: `["**/*.yml", "**/*.yaml", "**/Dockerfile*", "**/*.py"]` — CI / deploy config + source
95
95
  - `50.sync/*` rules: `paths: ["**/claudeos-core/**", "**/.claude/**"]` — loaded only when editing claudeos-core files
96
96
  - `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.
97
+ - `70.domains/*` rules (multi-domain projects only): per-domain rules at `.claude/rules/70.domains/{type}/{domain}-rules.md` (where `{type}` is `backend` or `frontend`, ALWAYS present even in single-stack projects for uniform layout + zero-migration future-proofing), each with a `paths:` glob scoped to that domain's source directories so the rule auto-loads only when editing files within the relevant domain. Folder name is PLURAL (`domains/`) — collection of N per-domain files — and each file inside uses the SINGULAR domain name (`{domain}-rules.md`). DO NOT use `60.domains/` (collides with `60.memory/`) and DO NOT skip the `{type}/` sub-folder. See pass3-footer.md "Per-domain folder convention" for the full rationale.
97
98
  - MUST generate `.claude/rules/00.core/00.standard-reference.md` — a directory of all standard files. This is NOT a "read all" instruction. Claude should Read ONLY the standards relevant to the current task. Structure it as:
98
99
  ```
99
100
  ---
@@ -110,12 +111,12 @@ Generation targets:
110
111
  - claudeos-core/standard/00.core/03.naming-conventions.md
111
112
  - claudeos-core/standard/00.core/04.doc-writing-guide.md
112
113
  ## Backend API
113
- - claudeos-core/standard/10.backend-api/01.view-patterns.md
114
- - claudeos-core/standard/10.backend-api/02.serializer-patterns.md
115
- - claudeos-core/standard/10.backend-api/03.model-patterns.md
116
- - claudeos-core/standard/10.backend-api/04.response-exception.md
117
- - claudeos-core/standard/10.backend-api/05.business-logic.md
118
- - claudeos-core/standard/10.backend-api/06.admin-patterns.md
114
+ - claudeos-core/standard/10.backend/01.view-patterns.md
115
+ - claudeos-core/standard/10.backend/02.serializer-patterns.md
116
+ - claudeos-core/standard/10.backend/03.model-patterns.md
117
+ - claudeos-core/standard/10.backend/04.response-exception.md
118
+ - claudeos-core/standard/10.backend/05.business-logic.md
119
+ - claudeos-core/standard/10.backend/06.admin-patterns.md
119
120
  ## Security & DB
120
121
  - claudeos-core/standard/30.security-db/01.security-auth.md
121
122
  - claudeos-core/standard/30.security-db/02.database-schema.md
@@ -124,8 +125,8 @@ Generation targets:
124
125
  - claudeos-core/standard/40.infra/01.environment-config.md
125
126
  - claudeos-core/standard/40.infra/02.logging-monitoring.md
126
127
  - claudeos-core/standard/40.infra/03.cicd-deployment.md
127
- - claudeos-core/standard/50.verification/01.development-verification.md
128
- - claudeos-core/standard/50.verification/02.testing-strategy.md
128
+ - claudeos-core/standard/80.verification/01.development-verification.md
129
+ - claudeos-core/standard/80.verification/02.testing-strategy.md
129
130
  ```
130
131
  List only the standard files that were actually generated above. NOTE: `00.core/04.doc-writing-guide.md` is a FORWARD REFERENCE — Pass 4 will generate it; include it anyway. Do NOT add a "DO NOT Read" section here — that information lives in CLAUDE.md Section 7 (the single source of truth).
131
132
 
@@ -57,20 +57,20 @@ Generation targets:
57
57
  - 00.core/01.project-overview.md — Stack, modules, server info
58
58
  - 00.core/02.architecture.md — Layer structure, request flow, directory structure
59
59
  - 00.core/03.naming-conventions.md — Module/schema/model/router naming conventions
60
- - 10.backend-api/01.router-endpoint-patterns.md — Router patterns + decorators
61
- - 10.backend-api/02.schema-pydantic-patterns.md — Pydantic conventions, validation
62
- - 10.backend-api/03.data-access-patterns.md — ORM, Repository, query optimization
63
- - 10.backend-api/04.response-exception.md — Response/error handling patterns
64
- - 10.backend-api/05.dependency-injection.md — Depends chain, lifecycle
65
- - 10.backend-api/06.middleware-patterns.md — CORS, custom middleware, order
60
+ - 10.backend/01.router-endpoint-patterns.md — Router patterns + decorators
61
+ - 10.backend/02.schema-pydantic-patterns.md — Pydantic conventions, validation
62
+ - 10.backend/03.data-access-patterns.md — ORM, Repository, query optimization
63
+ - 10.backend/04.response-exception.md — Response/error handling patterns
64
+ - 10.backend/05.dependency-injection.md — Depends chain, lifecycle
65
+ - 10.backend/06.middleware-patterns.md — CORS, custom middleware, order
66
66
  - 30.security-db/01.security-auth.md — JWT, OAuth2, CORS, Rate Limit
67
67
  - 30.security-db/02.database-schema.md — Alembic, schema conventions
68
68
  - 30.security-db/03.common-utilities.md — Common utils, dependency functions, constants
69
69
  - 40.infra/01.environment-config.md — pydantic-settings, environment variables
70
70
  - 40.infra/02.logging-monitoring.md — Logging standards, monitoring
71
71
  - 40.infra/03.cicd-deployment.md — CI/CD, Docker, uvicorn deployment
72
- - 50.verification/01.development-verification.md — pytest, startup, API testing
73
- - 50.verification/02.testing-strategy.md — Async testing, dependency overrides, mocking
72
+ - 80.verification/01.development-verification.md — pytest, startup, API testing
73
+ - 80.verification/02.testing-strategy.md — Async testing, dependency overrides, mocking
74
74
 
75
75
  Each file MUST include:
76
76
  - Correct examples (✅ code blocks)
@@ -84,7 +84,7 @@ Generation targets:
84
84
  - Each rule file MUST end with a `## Reference` section linking to the corresponding standard file(s):
85
85
  ```
86
86
  ## Reference
87
- > For detailed patterns and examples, Read: claudeos-core/standard/10.backend-api/01.router-endpoint-patterns.md
87
+ > For detailed patterns and examples, Read: claudeos-core/standard/10.backend/01.router-endpoint-patterns.md
88
88
  ```
89
89
  - `paths:` frontmatter per rule category:
90
90
  - `00.core/*` rules: `paths: ["**/*"]` — always loaded (architecture, naming are universally needed)
@@ -95,6 +95,7 @@ Generation targets:
95
95
  - `40.infra/03.cicd-deployment-rules.md` paths: `["**/*.yml", "**/*.yaml", "**/Dockerfile*", "**/*.py"]` — CI / deploy config + source
96
96
  - `50.sync/*` rules: `paths: ["**/claudeos-core/**", "**/.claude/**"]` — loaded only when editing claudeos-core files
97
97
  - `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.
98
+ - `70.domains/*` rules (multi-domain projects only): per-domain rules at `.claude/rules/70.domains/{type}/{domain}-rules.md` (where `{type}` is `backend` or `frontend`, ALWAYS present even in single-stack projects for uniform layout + zero-migration future-proofing), each with a `paths:` glob scoped to that domain's source directories so the rule auto-loads only when editing files within the relevant domain. Folder name is PLURAL (`domains/`) — collection of N per-domain files — and each file inside uses the SINGULAR domain name (`{domain}-rules.md`). DO NOT use `60.domains/` (collides with `60.memory/`) and DO NOT skip the `{type}/` sub-folder. See pass3-footer.md "Per-domain folder convention" for the full rationale.
98
99
  - MUST generate `.claude/rules/00.core/00.standard-reference.md` — a directory of all standard files. This is NOT a "read all" instruction. Claude should Read ONLY the standards relevant to the current task. Structure it as:
99
100
  ```
100
101
  ---
@@ -111,12 +112,12 @@ Generation targets:
111
112
  - claudeos-core/standard/00.core/03.naming-conventions.md
112
113
  - claudeos-core/standard/00.core/04.doc-writing-guide.md
113
114
  ## Backend API
114
- - claudeos-core/standard/10.backend-api/01.router-endpoint-patterns.md
115
- - claudeos-core/standard/10.backend-api/02.schema-pydantic-patterns.md
116
- - claudeos-core/standard/10.backend-api/03.data-access-patterns.md
117
- - claudeos-core/standard/10.backend-api/04.response-exception.md
118
- - claudeos-core/standard/10.backend-api/05.dependency-injection.md
119
- - claudeos-core/standard/10.backend-api/06.middleware-patterns.md
115
+ - claudeos-core/standard/10.backend/01.router-endpoint-patterns.md
116
+ - claudeos-core/standard/10.backend/02.schema-pydantic-patterns.md
117
+ - claudeos-core/standard/10.backend/03.data-access-patterns.md
118
+ - claudeos-core/standard/10.backend/04.response-exception.md
119
+ - claudeos-core/standard/10.backend/05.dependency-injection.md
120
+ - claudeos-core/standard/10.backend/06.middleware-patterns.md
120
121
  ## Security & DB
121
122
  - claudeos-core/standard/30.security-db/01.security-auth.md
122
123
  - claudeos-core/standard/30.security-db/02.database-schema.md
@@ -125,8 +126,8 @@ Generation targets:
125
126
  - claudeos-core/standard/40.infra/01.environment-config.md
126
127
  - claudeos-core/standard/40.infra/02.logging-monitoring.md
127
128
  - claudeos-core/standard/40.infra/03.cicd-deployment.md
128
- - claudeos-core/standard/50.verification/01.development-verification.md
129
- - claudeos-core/standard/50.verification/02.testing-strategy.md
129
+ - claudeos-core/standard/80.verification/01.development-verification.md
130
+ - claudeos-core/standard/80.verification/02.testing-strategy.md
130
131
  ```
131
132
  List only the standard files that were actually generated above. NOTE: `00.core/04.doc-writing-guide.md` is a FORWARD REFERENCE — Pass 4 will generate it; include it anyway. Do NOT add a "DO NOT Read" section here — that information lives in CLAUDE.md Section 7 (the single source of truth).
132
133
 
@@ -51,21 +51,21 @@ Generation targets:
51
51
  - 00.core/01.project-overview.md — Stack, modules, server info
52
52
  - 00.core/02.architecture.md — Application factory, Blueprint hierarchy, request flow
53
53
  - 00.core/03.naming-conventions.md — Module/model/blueprint/route naming conventions
54
- - 10.backend-api/01.route-blueprint-patterns.md — Blueprint structure, route decorators, request/response handling
55
- - 10.backend-api/02.model-schema-patterns.md — SQLAlchemy models, marshmallow/WTForms serialization
56
- - 10.backend-api/03.service-patterns.md — Service layer, business logic separation
57
- - 10.backend-api/04.response-error-patterns.md — Response formatting, error handlers, custom exceptions
54
+ - 10.backend/01.route-blueprint-patterns.md — Blueprint structure, route decorators, request/response handling
55
+ - 10.backend/02.model-schema-patterns.md — SQLAlchemy models, marshmallow/WTForms serialization
56
+ - 10.backend/03.service-patterns.md — Service layer, business logic separation
57
+ - 10.backend/04.response-error-patterns.md — Response formatting, error handlers, custom exceptions
58
58
  - 30.security-db/01.security-auth.md — Authentication, CSRF, session management, environment variables
59
59
  - 30.security-db/02.database-patterns.md — SQLAlchemy patterns, migrations, relationships
60
60
  - 40.infra/01.environment-config.md — Config classes, environment variables, extension initialization
61
61
  - 40.infra/02.logging-monitoring.md — app.logger, request logging, error tracking
62
62
  - 40.infra/03.cicd-deployment.md — CI/CD, gunicorn, Docker deployment
63
- - 50.verification/01.development-verification.md — Build, startup, flask run
64
- - 50.verification/02.testing-strategy.md — pytest, test_client, fixtures, DB testing
63
+ - 80.verification/01.development-verification.md — Build, startup, flask run
64
+ - 80.verification/02.testing-strategy.md — pytest, test_client, fixtures, DB testing
65
65
 
66
66
  Each file MUST include:
67
- - Correct examples (code blocks)
68
- - Incorrect examples (code blocks)
67
+ - Correct examples (code blocks)
68
+ - Incorrect examples (code blocks)
69
69
  - Key rules summary table
70
70
 
71
71
  3. .claude/rules/ (active domains only)
@@ -82,6 +82,7 @@ Generation targets:
82
82
  - `40.infra/03.cicd-deployment-rules.md` paths: `["**/*.yml", "**/*.yaml", "**/Dockerfile*", "**/*.py"]` — CI / deploy config + source
83
83
  - `50.sync/*` rules: `paths: ["**/claudeos-core/**", "**/.claude/**"]`
84
84
  - `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.
85
+ - `70.domains/*` rules (multi-domain projects only): per-domain rules at `.claude/rules/70.domains/{type}/{domain}-rules.md` (where `{type}` is `backend` or `frontend`, ALWAYS present even in single-stack projects for uniform layout + zero-migration future-proofing), each with a `paths:` glob scoped to that domain's source directories so the rule auto-loads only when editing files within the relevant domain. Folder name is PLURAL (`domains/`) — collection of N per-domain files — and each file inside uses the SINGULAR domain name (`{domain}-rules.md`). DO NOT use `60.domains/` (collides with `60.memory/`) and DO NOT skip the `{type}/` sub-folder. See pass3-footer.md "Per-domain folder convention" for the full rationale.
85
86
  - MUST generate `.claude/rules/00.core/00.standard-reference.md` — directory of all standard files
86
87
 
87
88
  4. .claude/rules/50.sync/ (2 sync rules)
@@ -47,18 +47,18 @@ Generation targets:
47
47
  - 00.core/01.project-overview.md — Stack, routing approach, deployment environment
48
48
  - 00.core/02.architecture.md — Nuxt/Vue structure, component hierarchy, data flow, Nitro server
49
49
  - 00.core/03.naming-conventions.md — File/component/composable/store naming conventions
50
- - 20.frontend-ui/01.component-patterns.md — SFC, <script setup>, Props/Emits, slots, provide/inject
51
- - 20.frontend-ui/02.page-routing-patterns.md — Pages/layouts/dynamic routes/middleware/definePageMeta
52
- - 20.frontend-ui/03.data-fetching.md — useFetch, useAsyncData, $fetch, server routes, caching
53
- - 20.frontend-ui/04.state-management.md — Pinia stores, composables, useState, form state
54
- - 20.frontend-ui/05.styling-patterns.md — Scoped styles, CSS Modules, Tailwind/UnoCSS, theming
55
- - 10.backend-api/01.server-routes.md — Nitro server routes (server/api/), H3 event handlers
50
+ - 20.frontend/01.component-patterns.md — SFC, <script setup>, Props/Emits, slots, provide/inject
51
+ - 20.frontend/02.page-routing-patterns.md — Pages/layouts/dynamic routes/middleware/definePageMeta
52
+ - 20.frontend/03.data-fetching.md — useFetch, useAsyncData, $fetch, server routes, caching
53
+ - 20.frontend/04.state-management.md — Pinia stores, composables, useState, form state
54
+ - 20.frontend/05.styling-patterns.md — Scoped styles, CSS Modules, Tailwind/UnoCSS, theming
55
+ - 10.backend/01.server-routes.md — Nitro server routes (server/api/), H3 event handlers
56
56
  - 30.security-db/01.security-auth.md — Auth, middleware protection, environment variables
57
57
  - 40.infra/01.environment-config.md — Runtime config, nuxt.config.ts, Nitro presets
58
58
  - 40.infra/02.logging-monitoring.md — Error tracking, analytics, Web Vitals
59
59
  - 40.infra/03.cicd-deployment.md — CI/CD, deployment (Vercel/Netlify/Docker), preview
60
- - 50.verification/01.development-verification.md — Build, startup, Lighthouse
61
- - 50.verification/02.testing-strategy.md — Vitest, @vue/test-utils, E2E, @nuxt/test-utils
60
+ - 80.verification/01.development-verification.md — Build, startup, Lighthouse
61
+ - 80.verification/02.testing-strategy.md — Vitest, @vue/test-utils, E2E, @nuxt/test-utils
62
62
 
63
63
  Each file MUST include:
64
64
  - Correct examples (✅ code blocks)
@@ -80,6 +80,7 @@ Generation targets:
80
80
  - `40.infra/03.cicd-deployment-rules.md` paths: `["**/*.yml", "**/*.yaml", "**/Dockerfile*", "**/*.ts", "**/*.vue"]` — CI config + source
81
81
  - `50.sync/*` rules: `paths: ["**/claudeos-core/**", "**/.claude/**"]`
82
82
  - `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.
83
+ - `70.domains/*` rules (multi-domain projects only): per-domain rules at `.claude/rules/70.domains/{type}/{domain}-rules.md` (where `{type}` is `backend` or `frontend`, ALWAYS present even in single-stack projects for uniform layout + zero-migration future-proofing), each with a `paths:` glob scoped to that domain's source directories so the rule auto-loads only when editing files within the relevant domain. Folder name is PLURAL (`domains/`) — collection of N per-domain files — and each file inside uses the SINGULAR domain name (`{domain}-rules.md`). DO NOT use `60.domains/` (collides with `60.memory/`) and DO NOT skip the `{type}/` sub-folder. See pass3-footer.md "Per-domain folder convention" for the full rationale.
83
84
  - MUST generate `.claude/rules/00.core/00.standard-reference.md` — directory of all standard files
84
85
 
85
86
  4. .claude/rules/50.sync/ (2 sync rules)
@@ -5,22 +5,62 @@
5
5
  * and selects appropriate templates based on detected stack.
6
6
  */
7
7
 
8
+ // ─── Splitting thresholds ───────────────────────────────────────
9
+ //
10
+ // MAX_FILES_PER_GROUP and MAX_DOMAINS_PER_GROUP are the original budgets that
11
+ // have governed Pass 1 batching since v1.x. They are sound for projects with
12
+ // a roughly uniform file-size distribution but can produce time-outlier
13
+ // batches when a single domain contains a very large file (e.g. a 2500-line
14
+ // TUI Grid wrapper) — observed in field testing where a group of ~29
15
+ // files ran ~70% longer than a group of 39 files.
16
+ //
17
+ // MAX_LINES_PER_GROUP is the optional second axis. It only fires when the
18
+ // caller supplies per-domain `totalLines`; scanners that do not yet record
19
+ // line counts leave it unset and the line-budget check is skipped, so this
20
+ // field is strictly additive (no behavior change for existing scanners).
21
+ //
22
+ // The 8000-line threshold is a pragmatic starting point calibrated against
23
+ // observed field tests: ~40 files × ~200 lines/file average. It can be
24
+ // tuned later once more scanners populate `totalLines` and we have more
25
+ // data on per-stack line-count distributions.
26
+ const MAX_FILES_PER_GROUP = 40;
27
+ const MAX_DOMAINS_PER_GROUP = 4;
28
+ const MAX_LINES_PER_GROUP = 8000;
29
+
8
30
  function splitDomainGroups(domains, type, template) {
9
- const MAX_FILES_PER_GROUP = 40;
10
- const MAX_DOMAINS_PER_GROUP = 4;
11
31
  const groups = [];
12
32
  let current = [];
13
33
  let fileCount = 0;
34
+ let lineCount = 0;
14
35
 
15
36
  for (const d of domains) {
16
- // Flush current group before adding if it would exceed limits
17
- if (current.length > 0 && (fileCount + d.totalFiles > MAX_FILES_PER_GROUP || current.length >= MAX_DOMAINS_PER_GROUP)) {
37
+ // Read `totalLines` as an optional signal. Domains produced by scanners
38
+ // that have not yet been extended to record line counts leave this
39
+ // undefined, which makes the line-budget check a no-op (0 + undefined
40
+ // stays undefined; the `hasLines` guard below suppresses the comparison
41
+ // entirely in that case). This preserves exact byte-for-byte output for
42
+ // all existing callers.
43
+ const domainLines = (typeof d.totalLines === "number" && d.totalLines >= 0) ? d.totalLines : 0;
44
+ const hasLines = domainLines > 0;
45
+
46
+ // Flush current group before adding if it would exceed any budget.
47
+ // The line-budget condition (`hasLines && ...`) is only evaluated when
48
+ // the incoming domain actually carries line-count data — callers using
49
+ // the legacy `{ name, totalFiles }` shape retain the original 2-axis
50
+ // behavior.
51
+ const wouldExceedFiles = fileCount + d.totalFiles > MAX_FILES_PER_GROUP;
52
+ const wouldExceedDomains = current.length >= MAX_DOMAINS_PER_GROUP;
53
+ const wouldExceedLines = hasLines && (lineCount + domainLines > MAX_LINES_PER_GROUP);
54
+
55
+ if (current.length > 0 && (wouldExceedFiles || wouldExceedDomains || wouldExceedLines)) {
18
56
  groups.push({ type, template, domains: [...current], estimatedFiles: fileCount });
19
57
  current = [];
20
58
  fileCount = 0;
59
+ lineCount = 0;
21
60
  }
22
61
  current.push(d.name);
23
62
  fileCount += d.totalFiles;
63
+ lineCount += domainLines;
24
64
  }
25
65
  if (current.length > 0) {
26
66
  groups.push({ type, template, domains: [...current], estimatedFiles: fileCount });
@@ -38,7 +78,7 @@ function determineActiveDomains(stack) {
38
78
  "20.frontend": !!stack.frontend,
39
79
  "30.security-db": !!(stack.database || isBackend || stack.frontend),
40
80
  "40.infra": true,
41
- "50.verification": true,
81
+ "80.verification": true,
42
82
  "90.optional": true,
43
83
  };
44
84
  }
@@ -16,6 +16,7 @@ const { detectStack } = require("./stack-detector");
16
16
  const { scanStructure } = require("./structure-scanner");
17
17
  const { splitDomainGroups, determineActiveDomains, selectTemplates } = require("./domain-grouper");
18
18
  const { generatePrompts } = require("./prompt-generator");
19
+ const { collectSourcePaths } = require("./source-paths");
19
20
 
20
21
  const ROOT = process.env.CLAUDEOS_ROOT || path.resolve(__dirname, "../..");
21
22
  const GENERATED_DIR = path.join(ROOT, "claudeos-core/generated");
@@ -39,7 +40,17 @@ async function main() {
39
40
  console.warn(" Ensure you have build.gradle, package.json, pyproject.toml, or requirements.txt in the project root.\n");
40
41
  }
41
42
  console.log(` Frontend: ${stack.frontend || "none"} ${stack.frontendVersion || ""}`);
42
- console.log(` Database: ${stack.database || "none"}`);
43
+ // v2.4.0 — when a project ships more than one DB driver (e.g. Oracle +
44
+ // MySQL master/slave), surface the full list so downstream LLMs (Pass 1)
45
+ // see the dual-dialect setup without having to re-derive it from source
46
+ // code. Singular `Database:` line preserved for byte-for-byte parity in
47
+ // single-DB projects (the dominant case).
48
+ if (Array.isArray(stack.databases) && stack.databases.length > 1) {
49
+ console.log(` Database: ${stack.database} (primary)`);
50
+ console.log(` Databases: ${stack.databases.join(", ")} (multi-dialect)`);
51
+ } else {
52
+ console.log(` Database: ${stack.database || "none"}`);
53
+ }
43
54
  console.log(` ORM: ${stack.orm || "none"}`);
44
55
  console.log(` PackageMgr: ${stack.packageManager || "none"}\n`);
45
56
 
@@ -57,6 +68,23 @@ async function main() {
57
68
  }
58
69
  console.log();
59
70
 
71
+ // Phase 2.5: Allowed source paths (v2.3.x+ — path-hallucination prevention)
72
+ //
73
+ // Collect the authoritative list of source files that actually exist on
74
+ // disk. Pass 3/4 prompts use this list (via pass3a-facts.md and the
75
+ // pass3-footer.md grounding rule) to refuse citations of convention-based
76
+ // fabricated paths like `src/app/providers.tsx` when the project does
77
+ // not in fact ship that file. See plan-installer/source-paths.js for
78
+ // the full rationale.
79
+ console.log(" [Phase 2.5] Collecting source-path allowlist...");
80
+ const sourcePaths = await collectSourcePaths(ROOT);
81
+ if (sourcePaths.mode === "full") {
82
+ console.log(` ${sourcePaths.totalFiles} source file(s) enumerated (full mode)`);
83
+ } else {
84
+ console.log(` ${sourcePaths.totalFiles} source files across ${sourcePaths.paths.length} dirs (rollup mode — project exceeds enumeration budget)`);
85
+ }
86
+ console.log();
87
+
60
88
  // Phase 3: Template selection
61
89
  console.log(" [Phase 3] Selecting templates...");
62
90
  const templates = selectTemplates(stack);
@@ -111,6 +139,11 @@ async function main() {
111
139
  templates, isMultiStack, rootPackage,
112
140
  domains, backendDomains, frontendDomains, frontend,
113
141
  activeDomains: active,
142
+ // v2.3.x+: authoritative on-disk source-file list. Consumed by
143
+ // pass3-context-builder → pass3a-facts.md → Pass 3/4 prompts to
144
+ // prevent convention-based path hallucination (e.g. Next.js
145
+ // `src/app/providers.tsx` when the project does not ship it).
146
+ allowedSourcePaths: sourcePaths,
114
147
  summary: {
115
148
  totalDomains: domains.length, backendDomains: backendDomains.length,
116
149
  frontendDomains: frontendDomains.length,
@@ -192,6 +192,20 @@ function buildPass3Context(generatedDir) {
192
192
  // ─── Frontend stats (if scan-frontend ran) ──────────────────────────
193
193
  frontend: analysis.frontend || { exists: false },
194
194
 
195
+ // ─── Source path allowlist (v2.3.x+ — path-hallucination prevention) ─
196
+ // Authoritative on-disk source-file list, copied from project-analysis.
197
+ // Pass 3a includes a rendered form of this in pass3a-facts.md as
198
+ // "## Allowed Source Paths". Pass 3b/3c/3d then cite ONLY from this
199
+ // list when writing `src/...` / `packages/...` / language-specific
200
+ // paths in rule/standard files.
201
+ //
202
+ // Shape: { mode: "full" | "rollup", paths: string[], totalFiles: number,
203
+ // excludedDirs: string[] }
204
+ // See plan-installer/source-paths.js for the full contract.
205
+ allowedSourcePaths: (analysis.allowedSourcePaths && typeof analysis.allowedSourcePaths === "object")
206
+ ? analysis.allowedSourcePaths
207
+ : { mode: "full", paths: [], totalFiles: 0, excludedDirs: [] },
208
+
195
209
  // ─── pass2-merged.json descriptor (signals, not contents) ───────────
196
210
  // Pass 3 reads this to decide whether it's safe to open the full file
197
211
  // for a specific missing detail, and how aggressively to summarize first.
@@ -383,7 +383,8 @@ async function scanFrontendDomains(stack, ROOT) {
383
383
  // Emitting those as domains fragments one logical app into 5+
384
384
  // pseudo-domains, which in turn primes Pass 3 to fabricate
385
385
  // prefixed filenames (featureRoutePath.ts, admin-api.service.ts) —
386
- // the hallucination class observed in frontend-react-B dogfooding.
386
+ // a canonical hallucination class the single-SPA rule is designed
387
+ // to prevent.
387
388
  //
388
389
  // Detection of "single-SPA" mode: inspect the top-level platform
389
390
  // segment for every glob match and count distinct values. If only
@@ -22,9 +22,42 @@ async function scanJavaDomains(stack, ROOT) {
22
22
  let rootPackage = null;
23
23
 
24
24
  const javaFiles = (await glob("src/main/java/**/*.java", { cwd: ROOT })).map(norm);
25
+
26
+ // v2.4.0 — Pick the LONGEST package prefix (1-4 segments) that still
27
+ // covers ≥80% of layer-bearing files. Pre-v2.4.0 the first matched file
28
+ // won, which misclassified projects whose actual production code lives
29
+ // under one root (e.g. `<orgA>.<projectA>.*`) but where a small number
30
+ // of stub files happen to sit under another deeper subtree (e.g.
31
+ // `<orgA>.<otherModule>.core.<dir>.*`) — glob enumeration order then
32
+ // determined the rootPackage non-deterministically.
33
+ //
34
+ // Algorithm: count every (1-, 2-, 3-, 4-)segment prefix preceding a
35
+ // known layer marker. Then pick the longest prefix whose count is at
36
+ // least 80% of the maximum (1-segment) count. This gives:
37
+ // • Mono-package project (`com.example.app.*` only): root = `com.example.app`
38
+ // (all 4 prefix lengths tied, longest = most specific root).
39
+ // • Multi-module project (95% under `<root>.api.*`, 5% stubs under
40
+ // `<root>.misc.*`): root = `<root>.api` (the LONGEST prefix that
41
+ // still covers ≥80% of files), not `<root>` (too generic) and
42
+ // not the minority `<root>.misc.*` location (no longer first-match).
43
+ const pkgCounts = new Map();
25
44
  for (const f of javaFiles) {
26
45
  const m = f.match(/src\/main\/java\/(.+?)\/(controller|aggregator|facade|usecase|orchestrator|service|mapper|dao|dto|entity|repository|adapter)/);
27
- if (m) { rootPackage = m[1].replace(/\//g, "."); break; }
46
+ if (!m) continue;
47
+ const segs = m[1].split("/");
48
+ for (let len = Math.min(4, segs.length); len >= 1; len--) {
49
+ const prefix = segs.slice(0, len).join(".");
50
+ pkgCounts.set(prefix, (pkgCounts.get(prefix) || 0) + 1);
51
+ }
52
+ }
53
+ if (pkgCounts.size > 0) {
54
+ const maxCount = Math.max(...pkgCounts.values());
55
+ const threshold = Math.ceil(maxCount * 0.8);
56
+ const candidates = [...pkgCounts.entries()].filter(([_, c]) => c >= threshold);
57
+ // Among candidates, pick the longest prefix (most specific root that
58
+ // still covers the majority of files). Tie-break on length DESC.
59
+ candidates.sort((a, b) => b[0].length - a[0].length);
60
+ rootPackage = candidates[0][0];
28
61
  }
29
62
  const domainMap = {};
30
63
  let detectedPattern = null;
@@ -172,7 +205,70 @@ async function scanJavaDomains(stack, ROOT) {
172
205
  domainMap[d].mappers = mpr.length;
173
206
  domainMap[d].dtos = dto.length;
174
207
  domainMap[d].xmlMappers = xml.length;
175
- const totalFiles = svc.length + agg.length + mpr.length + dto.length + xml.length + domainMap[d].controllers;
208
+
209
+ // v2.4.0 — Deep-sweep fallback (Pattern B/D only).
210
+ //
211
+ // Pre-v2.4.0: standard globs assume `{domain}/{layer}/X.java`. This
212
+ // misses two real-world layouts:
213
+ // (a) Multi-module split: `front/{domain}/{layer}/` for HTTP
214
+ // layer + `core/{domain}/{layer}/` for service/dao layer.
215
+ // Standard glob `**/{domain}/{layer}/` actually matches BOTH
216
+ // via the leading `**`, so this case generally works.
217
+ // (b) Cross-domain coupling: `core/{otherDomain}/{layer}/{domain}/`
218
+ // — services for `{domain}` living under a different module's
219
+ // layer directory (the layer dir comes BEFORE the domain dir).
220
+ // Standard glob `**/{domain}/{layer}/*.java` does NOT match
221
+ // this layout.
222
+ //
223
+ // When standard globs return zero files for a Pattern B/D domain
224
+ // that is registered in domainMap (so it does exist), fall back to
225
+ // a deep sweep: `**/${dn}/**/*.java` finds every .java file under
226
+ // ANY directory named ${dn}. We then classify each file by walking
227
+ // up its path to find the nearest layer dir, which catches both
228
+ // `${dn}/{layer}/` AND `{layer}/${dn}/` placements.
229
+ //
230
+ // Restricting to Pattern B/D and to the zero-files case keeps the
231
+ // legacy behavior identical for projects whose standard globs
232
+ // already cover everything, and prevents over-counting for
233
+ // domains with healthy direct-layout file counts.
234
+ const standardCount = svc.length + agg.length + mpr.length + dto.length + xml.length;
235
+ if (standardCount === 0 && (p === "B" || p === "D")) {
236
+ const deepFiles = (await glob(`src/main/java/**/${dn}/**/*.java`, { cwd: ROOT })).map(norm);
237
+ // v2.4.0 — extended layer recognition. Real-world enterprise codebases
238
+ // commonly include implementation/support layers beyond the canonical
239
+ // controller/service/mapper/dto trio. Files in `factory/`, `strategy/`,
240
+ // `impl/`, `helper/`, etc. were previously dropped by deep-sweep
241
+ // (no `break`), causing domains with non-standard layer names to
242
+ // report 0 totalFiles. The recognized list is augmented and a
243
+ // catch-all classifies any remaining `.java` file under the domain
244
+ // tree as a service (the most generic backend layer).
245
+ const SVC_LAYERS = ["aggregator", "facade", "usecase", "orchestrator", "service",
246
+ "factory", "strategy", "impl", "helper", "support",
247
+ "client", "provider", "manager", "handler", "interceptor",
248
+ "filter", "listener", "task", "scheduler", "command", "query",
249
+ "validator", "converter", "translator", "resolver"];
250
+ const DAO_LAYERS = ["mapper", "repository", "dao"];
251
+ const DTO_LAYERS = ["dto", "vo", "entity", "model", "request", "response", "payload"];
252
+ for (const f of deepFiles) {
253
+ const parts = f.split("/");
254
+ let classified = false;
255
+ for (let i = parts.length - 2; i >= 0; i--) {
256
+ const seg = parts[i];
257
+ if (seg === "controller") { domainMap[d].controllers++; classified = true; break; }
258
+ if (SVC_LAYERS.includes(seg)) { domainMap[d].services++; classified = true; break; }
259
+ if (DAO_LAYERS.includes(seg)) { domainMap[d].mappers++; classified = true; break; }
260
+ if (DTO_LAYERS.includes(seg)) { domainMap[d].dtos++; classified = true; break; }
261
+ }
262
+ // Fallback: any unclassified .java file under the domain tree is
263
+ // counted as a service. This catches layouts like
264
+ // `core/${dn}/X.java` (no layer subdir) and prevents legitimate
265
+ // backend domains from reporting 0 totalFiles when their files
266
+ // happen to live under unrecognized parent directories.
267
+ if (!classified) domainMap[d].services++;
268
+ }
269
+ }
270
+
271
+ const totalFiles = domainMap[d].services + domainMap[d].mappers + domainMap[d].dtos + domainMap[d].xmlMappers + domainMap[d].controllers;
176
272
  backendDomains.push({ name: d, type: "backend", ...domainMap[d], totalFiles });
177
273
  }
178
274