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
|
@@ -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
|
|
60
|
-
- 10.backend
|
|
61
|
-
- 10.backend
|
|
62
|
-
- 10.backend
|
|
63
|
-
- 10.backend
|
|
64
|
-
- 10.backend
|
|
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
|
-
-
|
|
72
|
-
-
|
|
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
|
|
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
|
|
114
|
-
- claudeos-core/standard/10.backend
|
|
115
|
-
- claudeos-core/standard/10.backend
|
|
116
|
-
- claudeos-core/standard/10.backend
|
|
117
|
-
- claudeos-core/standard/10.backend
|
|
118
|
-
- claudeos-core/standard/10.backend
|
|
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/
|
|
128
|
-
- claudeos-core/standard/
|
|
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
|
|
61
|
-
- 10.backend
|
|
62
|
-
- 10.backend
|
|
63
|
-
- 10.backend
|
|
64
|
-
- 10.backend
|
|
65
|
-
- 10.backend
|
|
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
|
-
-
|
|
73
|
-
-
|
|
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
|
|
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
|
|
115
|
-
- claudeos-core/standard/10.backend
|
|
116
|
-
- claudeos-core/standard/10.backend
|
|
117
|
-
- claudeos-core/standard/10.backend
|
|
118
|
-
- claudeos-core/standard/10.backend
|
|
119
|
-
- claudeos-core/standard/10.backend
|
|
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/
|
|
129
|
-
- claudeos-core/standard/
|
|
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
|
|
55
|
-
- 10.backend
|
|
56
|
-
- 10.backend
|
|
57
|
-
- 10.backend
|
|
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
|
-
-
|
|
64
|
-
-
|
|
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
|
|
51
|
-
- 20.frontend
|
|
52
|
-
- 20.frontend
|
|
53
|
-
- 20.frontend
|
|
54
|
-
- 20.frontend
|
|
55
|
-
- 10.backend
|
|
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
|
-
-
|
|
61
|
-
-
|
|
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
|
-
//
|
|
17
|
-
|
|
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
|
-
"
|
|
81
|
+
"80.verification": true,
|
|
42
82
|
"90.optional": true,
|
|
43
83
|
};
|
|
44
84
|
}
|
package/plan-installer/index.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
//
|
|
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)
|
|
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
|
-
|
|
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
|
|