@atlashub/smartstack-cli 3.39.0 → 3.41.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/.documentation/apex.html +644 -644
- package/.documentation/css/styles.css +2320 -2320
- package/.documentation/init.html +1377 -1377
- package/.documentation/js/app.js +780 -780
- package/.documentation/prd-json-v2.0.0.md +396 -396
- package/.documentation/testing-ba-e2e.md +462 -462
- package/config/default-config.json +95 -95
- package/config/mcp-defaults.json +62 -62
- package/config/settings.json +53 -53
- package/config/settings.local.example.json +16 -16
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +6 -4
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +115 -115
- package/scripts/extract-api-endpoints.ts +325 -325
- package/scripts/extract-business-rules.ts +440 -440
- package/scripts/generate-doc-with-mock-ui.ts +804 -804
- package/scripts/health-check.sh +168 -168
- package/scripts/postinstall.js +18 -18
- package/templates/agents/action.md +37 -37
- package/templates/agents/ba-reader.md +378 -378
- package/templates/agents/ba-writer.md +861 -861
- package/templates/agents/code-reviewer.md +163 -163
- package/templates/agents/db-reader.md +149 -149
- package/templates/agents/docs-context-reader.md +143 -143
- package/templates/agents/docs-sync-checker.md +122 -122
- package/templates/agents/efcore/conflicts.md +95 -84
- package/templates/agents/efcore/db-deploy.md +85 -74
- package/templates/agents/efcore/db-reset.md +96 -85
- package/templates/agents/efcore/db-seed.md +72 -61
- package/templates/agents/efcore/db-status.md +97 -86
- package/templates/agents/efcore/migration.md +197 -186
- package/templates/agents/efcore/rebase-snapshot.md +119 -108
- package/templates/agents/efcore/scan.md +103 -92
- package/templates/agents/efcore/squash.md +172 -161
- package/templates/agents/explore-codebase.md +66 -66
- package/templates/agents/explore-docs.md +98 -98
- package/templates/agents/fix-grammar.md +50 -50
- package/templates/agents/gitflow/abort.md +45 -45
- package/templates/agents/gitflow/cleanup.md +96 -96
- package/templates/agents/gitflow/commit.md +236 -236
- package/templates/agents/gitflow/exec.md +48 -48
- package/templates/agents/gitflow/finish.md +146 -146
- package/templates/agents/gitflow/init-clone.md +199 -199
- package/templates/agents/gitflow/init-detect.md +137 -137
- package/templates/agents/gitflow/init-validate.md +225 -225
- package/templates/agents/gitflow/init.md +340 -340
- package/templates/agents/gitflow/merge.md +145 -145
- package/templates/agents/gitflow/plan.md +42 -42
- package/templates/agents/gitflow/pr.md +191 -191
- package/templates/agents/gitflow/review.md +49 -49
- package/templates/agents/gitflow/start.md +147 -147
- package/templates/agents/gitflow/status.md +95 -95
- package/templates/agents/mcp-healthcheck.md +163 -163
- package/templates/agents/snipper.md +37 -37
- package/templates/agents/websearch.md +46 -46
- package/templates/hooks/appsettings-guard.sh +76 -76
- package/templates/hooks/docs-drift-check.md +96 -96
- package/templates/hooks/ef-migration-check.md +139 -139
- package/templates/hooks/hooks.json +58 -58
- package/templates/hooks/mcp-check.md +64 -64
- package/templates/hooks/ralph-mcp-logger.sh +46 -46
- package/templates/hooks/ralph-session-end.sh +69 -69
- package/templates/hooks/stop-hook.sh +177 -177
- package/templates/hooks/wsl-dotnet-cleanup.sh +24 -24
- package/templates/mcp-scaffolding/component.tsx.hbs +318 -318
- package/templates/mcp-scaffolding/controller.cs.hbs +192 -192
- package/templates/mcp-scaffolding/entity-extension.cs.hbs +239 -239
- package/templates/mcp-scaffolding/frontend/api-client.ts.hbs +116 -116
- package/templates/mcp-scaffolding/frontend/nav-routes.ts.hbs +133 -133
- package/templates/mcp-scaffolding/frontend/routes.tsx.hbs +126 -126
- package/templates/mcp-scaffolding/migrations/seed-roles.cs.hbs +261 -261
- package/templates/mcp-scaffolding/service-extension.cs.hbs +53 -53
- package/templates/mcp-scaffolding/tests/controller.test.cs.hbs +436 -436
- package/templates/mcp-scaffolding/tests/entity.test.cs.hbs +239 -239
- package/templates/mcp-scaffolding/tests/repository.test.cs.hbs +441 -441
- package/templates/mcp-scaffolding/tests/security.test.cs.hbs +442 -442
- package/templates/mcp-scaffolding/tests/service.test.cs.hbs +402 -402
- package/templates/mcp-scaffolding/tests/validator.test.cs.hbs +428 -428
- package/templates/project/DependencyInjection.Application.cs.template +25 -25
- package/templates/project/DependencyInjection.Infrastructure.cs.template +61 -61
- package/templates/project/DesignTimeExtensionsDbContextFactory.cs.template +70 -70
- package/templates/project/ExampleEntity.cs.template +116 -116
- package/templates/project/ExampleEntityConfiguration.cs.template +64 -64
- package/templates/project/ExampleService.cs.template +146 -146
- package/templates/project/ExtensionsDbContext.cs.template +41 -41
- package/templates/project/IExtensionsDbContext.cs.template +22 -22
- package/templates/project/Program.cs.template +47 -47
- package/templates/project/README.md +79 -79
- package/templates/project/api.ts.template +12 -12
- package/templates/project/appsettings.json.template +170 -170
- package/templates/project/claude-settings.json.template +5 -5
- package/templates/project/test-frontend/msw/handlers.ts +58 -58
- package/templates/project/test-frontend/msw/server.ts +25 -25
- package/templates/project/test-frontend/setup.ts +16 -16
- package/templates/project/test-frontend/test-utils.tsx +59 -59
- package/templates/project/test-frontend/vitest.config.ts +31 -31
- package/templates/ralph/README.md +93 -93
- package/templates/ralph/ralph.config.yaml +113 -113
- package/templates/scripts/setup-ralph-loop.sh +173 -173
- package/templates/skills/_resources/config-safety.md +61 -61
- package/templates/skills/_resources/context-digest-template.md +53 -53
- package/templates/skills/_resources/doc-context-cache.md +60 -60
- package/templates/skills/_resources/docs-manifest-schema.md +155 -155
- package/templates/skills/_resources/formatting-guide.md +124 -124
- package/templates/skills/_resources/mcp-validate-documentation-spec.md +181 -181
- package/templates/skills/_shared.md +228 -228
- package/templates/skills/admin/SKILL.md +48 -48
- package/templates/skills/ai-prompt/SKILL.md +107 -107
- package/templates/skills/ai-prompt/steps/step-00-init.md +47 -47
- package/templates/skills/ai-prompt/steps/step-01-implementation.md +122 -122
- package/templates/skills/apex/SKILL.md +168 -168
- package/templates/skills/apex/_shared.md +141 -141
- package/templates/skills/apex/references/agent-teams-protocol.md +164 -164
- package/templates/skills/apex/references/analysis-methods.md +141 -141
- package/templates/skills/apex/references/challenge-questions.md +145 -145
- package/templates/skills/apex/references/code-generation.md +412 -412
- package/templates/skills/apex/references/core-seed-data.md +1437 -1437
- package/templates/skills/apex/references/error-classification.md +144 -144
- package/templates/skills/apex/references/examine-build-validation.md +82 -82
- package/templates/skills/apex/references/execution-frontend-gates.md +177 -177
- package/templates/skills/apex/references/execution-frontend-patterns.md +105 -105
- package/templates/skills/apex/references/execution-layer1-rules.md +96 -96
- package/templates/skills/apex/references/initialization-challenge-flow.md +110 -110
- package/templates/skills/apex/references/planning-layer-mapping.md +151 -151
- package/templates/skills/apex/references/post-checks.md +1584 -1584
- package/templates/skills/apex/references/smartstack-api.md +1053 -1053
- package/templates/skills/apex/references/smartstack-frontend.md +1571 -1571
- package/templates/skills/apex/references/smartstack-layers.md +402 -402
- package/templates/skills/apex/steps/step-00-init.md +307 -307
- package/templates/skills/apex/steps/step-01-analyze.md +165 -165
- package/templates/skills/apex/steps/step-02-plan.md +144 -144
- package/templates/skills/apex/steps/step-03-execute.md +328 -328
- package/templates/skills/apex/steps/step-04-examine.md +263 -263
- package/templates/skills/apex/steps/step-05-deep-review.md +129 -129
- package/templates/skills/apex/steps/step-06-resolve.md +101 -101
- package/templates/skills/apex/steps/step-07-tests.md +238 -238
- package/templates/skills/apex/steps/step-08-run-tests.md +125 -125
- package/templates/skills/application/SKILL.md +4 -4
- package/templates/skills/application/references/application-roles-template.md +227 -227
- package/templates/skills/application/references/backend-controller-hierarchy.md +58 -58
- package/templates/skills/application/references/backend-entity-seeding.md +72 -72
- package/templates/skills/application/references/backend-seeding-and-dto-output.md +83 -83
- package/templates/skills/application/references/backend-table-prefix-mapping.md +79 -79
- package/templates/skills/application/references/backend-verification.md +88 -88
- package/templates/skills/application/references/frontend-i18n-and-output.md +67 -67
- package/templates/skills/application/references/frontend-route-naming.md +117 -117
- package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +107 -107
- package/templates/skills/application/references/frontend-verification.md +156 -156
- package/templates/skills/application/references/migration-checklist-troubleshooting.md +1 -1
- package/templates/skills/application/references/provider-template.md +177 -177
- package/templates/skills/application/references/roles-client-project-handling.md +55 -55
- package/templates/skills/application/references/roles-fallback-procedure.md +149 -149
- package/templates/skills/application/references/test-coverage-requirements.md +213 -213
- package/templates/skills/application/references/test-frontend.md +73 -73
- package/templates/skills/application/references/test-prerequisites.md +72 -72
- package/templates/skills/application/steps/step-05-frontend.md +176 -176
- package/templates/skills/application/steps/step-06-migration.md +193 -193
- package/templates/skills/application/steps/step-07-tests.md +356 -356
- package/templates/skills/application/steps/step-08-documentation.md +137 -137
- package/templates/skills/application/templates-backend.md +463 -463
- package/templates/skills/application/templates-frontend.md +685 -685
- package/templates/skills/application/templates-i18n.md +520 -520
- package/templates/skills/application/templates-seed.md +1096 -1096
- package/templates/skills/business-analyse/SKILL.md +327 -327
- package/templates/skills/business-analyse/_architecture.md +123 -123
- package/templates/skills/business-analyse/_elicitation.md +206 -206
- package/templates/skills/business-analyse/_module-loop.md +115 -115
- package/templates/skills/business-analyse/_shared.md +383 -383
- package/templates/skills/business-analyse/_suggestions.md +34 -34
- package/templates/skills/business-analyse/html/ba-interactive.html +4477 -4477
- package/templates/skills/business-analyse/html/build-html.js +77 -77
- package/templates/skills/business-analyse/html/src/scripts/01-data-init.js +150 -150
- package/templates/skills/business-analyse/html/src/scripts/02-navigation.js +227 -227
- package/templates/skills/business-analyse/html/src/scripts/03-render-cadrage.js +199 -199
- package/templates/skills/business-analyse/html/src/scripts/04-render-modules.js +205 -205
- package/templates/skills/business-analyse/html/src/scripts/05-render-specs.js +647 -647
- package/templates/skills/business-analyse/html/src/scripts/06-render-consolidation.js +195 -195
- package/templates/skills/business-analyse/html/src/scripts/07-render-handoff.js +92 -92
- package/templates/skills/business-analyse/html/src/scripts/08-editing.js +135 -135
- package/templates/skills/business-analyse/html/src/scripts/09-export.js +168 -168
- package/templates/skills/business-analyse/html/src/scripts/10-comments.js +171 -171
- package/templates/skills/business-analyse/html/src/scripts/11-review-panel.js +166 -166
- package/templates/skills/business-analyse/html/src/styles/01-variables.css +38 -38
- package/templates/skills/business-analyse/html/src/styles/02-layout.css +101 -101
- package/templates/skills/business-analyse/html/src/styles/03-navigation.css +120 -120
- package/templates/skills/business-analyse/html/src/styles/04-cards.css +196 -196
- package/templates/skills/business-analyse/html/src/styles/05-modules.css +454 -454
- package/templates/skills/business-analyse/html/src/styles/06-wireframes.css +272 -272
- package/templates/skills/business-analyse/html/src/styles/07-comments.css +184 -184
- package/templates/skills/business-analyse/html/src/styles/08-review-panel.css +241 -241
- package/templates/skills/business-analyse/html/src/template.html +516 -516
- package/templates/skills/business-analyse/patterns/suggestion-catalog.md +546 -546
- package/templates/skills/business-analyse/questionnaire/00-application.md +160 -160
- package/templates/skills/business-analyse/questionnaire/00b-project.md +85 -85
- package/templates/skills/business-analyse/questionnaire/01-context.md +185 -185
- package/templates/skills/business-analyse/questionnaire/02-stakeholders.md +189 -189
- package/templates/skills/business-analyse/questionnaire/03-scope.md +164 -164
- package/templates/skills/business-analyse/questionnaire/04-data.md +88 -88
- package/templates/skills/business-analyse/questionnaire/05-integrations.md +58 -58
- package/templates/skills/business-analyse/questionnaire/06-security.md +68 -68
- package/templates/skills/business-analyse/questionnaire/07-ui.md +76 -76
- package/templates/skills/business-analyse/questionnaire/08-performance.md +42 -42
- package/templates/skills/business-analyse/questionnaire/09-constraints.md +45 -45
- package/templates/skills/business-analyse/questionnaire/10-documentation.md +43 -43
- package/templates/skills/business-analyse/questionnaire/11-data-lifecycle.md +59 -59
- package/templates/skills/business-analyse/questionnaire/12-migration.md +58 -58
- package/templates/skills/business-analyse/questionnaire/13-cross-module.md +69 -69
- package/templates/skills/business-analyse/questionnaire/14-risk-assumptions.md +135 -135
- package/templates/skills/business-analyse/questionnaire/15-success-metrics.md +136 -136
- package/templates/skills/business-analyse/questionnaire.md +337 -337
- package/templates/skills/business-analyse/react/application-viewer.md +242 -242
- package/templates/skills/business-analyse/react/components.md +551 -551
- package/templates/skills/business-analyse/react/i18n-template.md +306 -306
- package/templates/skills/business-analyse/references/acceptance-criteria.md +169 -169
- package/templates/skills/business-analyse/references/agent-module-prompt.md +362 -362
- package/templates/skills/business-analyse/references/agent-pooling-best-practices.md +557 -557
- package/templates/skills/business-analyse/references/analysis-semantic-checks.md +190 -190
- package/templates/skills/business-analyse/references/cache-warming-strategy.md +566 -566
- package/templates/skills/business-analyse/references/cadrage-challenge-patterns.md +41 -41
- package/templates/skills/business-analyse/references/cadrage-coverage-matrix.md +74 -74
- package/templates/skills/business-analyse/references/cadrage-pre-analysis.md +115 -115
- package/templates/skills/business-analyse/references/cadrage-shared-modules.md +68 -69
- package/templates/skills/business-analyse/references/cadrage-structure-cards.md +85 -85
- package/templates/skills/business-analyse/references/compilation-structure-cards.md +297 -297
- package/templates/skills/business-analyse/references/consolidation-structural-checks.md +107 -107
- package/templates/skills/business-analyse/references/deploy-data-build.md +180 -180
- package/templates/skills/business-analyse/references/deploy-modes.md +118 -118
- package/templates/skills/business-analyse/references/detection-strategies.md +424 -424
- package/templates/skills/business-analyse/references/entity-architecture-decision.md +218 -218
- package/templates/skills/business-analyse/references/handoff-file-templates.md +120 -120
- package/templates/skills/business-analyse/references/handoff-mappings.md +81 -81
- package/templates/skills/business-analyse/references/handoff-seeddata-generation.md +312 -312
- package/templates/skills/business-analyse/references/html-data-mapping.md +299 -299
- package/templates/skills/business-analyse/references/init-schema-deployment.md +65 -65
- package/templates/skills/business-analyse/references/naming-conventions.md +243 -243
- package/templates/skills/business-analyse/references/prd-generation.md +258 -258
- package/templates/skills/business-analyse/references/review-data-mapping.md +363 -363
- package/templates/skills/business-analyse/references/robustness-checks.md +542 -542
- package/templates/skills/business-analyse/references/spec-auto-inference.md +111 -111
- package/templates/skills/business-analyse/references/team-orchestration.md +1022 -1022
- package/templates/skills/business-analyse/references/ui-dashboard-spec.md +85 -85
- package/templates/skills/business-analyse/references/ui-resource-cards.md +259 -259
- package/templates/skills/business-analyse/references/validate-incremental-html.md +121 -121
- package/templates/skills/business-analyse/references/validation-checklist.md +347 -347
- package/templates/skills/business-analyse/references/wireframe-svg-style-guide.md +335 -335
- package/templates/skills/business-analyse/schemas/application-schema.json +453 -453
- package/templates/skills/business-analyse/schemas/feature-schema.json +53 -53
- package/templates/skills/business-analyse/schemas/project-schema.json +485 -485
- package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +201 -201
- package/templates/skills/business-analyse/schemas/sections/discovery-schema.json +82 -82
- package/templates/skills/business-analyse/schemas/sections/handoff-schema.json +80 -80
- package/templates/skills/business-analyse/schemas/sections/metadata-schema.json +70 -70
- package/templates/skills/business-analyse/schemas/sections/specification-schema.json +547 -547
- package/templates/skills/business-analyse/schemas/sections/validation-schema.json +93 -93
- package/templates/skills/business-analyse/schemas/shared/common-defs.json +226 -226
- package/templates/skills/business-analyse/steps/step-00-init.md +575 -576
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +767 -767
- package/templates/skills/business-analyse/steps/step-01b-applications.md +419 -419
- package/templates/skills/business-analyse/steps/step-02-decomposition.md +387 -387
- package/templates/skills/business-analyse/steps/step-03a-data.md +16 -16
- package/templates/skills/business-analyse/steps/step-03a1-setup.md +506 -506
- package/templates/skills/business-analyse/steps/step-03a2-analysis.md +252 -252
- package/templates/skills/business-analyse/steps/step-03b-ui.md +425 -425
- package/templates/skills/business-analyse/steps/step-03c-compile.md +611 -611
- package/templates/skills/business-analyse/steps/step-03d-validate.md +783 -783
- package/templates/skills/business-analyse/steps/step-04-consolidation.md +17 -17
- package/templates/skills/business-analyse/steps/step-04a-collect.md +415 -415
- package/templates/skills/business-analyse/steps/step-04b-analyze.md +163 -163
- package/templates/skills/business-analyse/steps/step-04c-decide.md +186 -186
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +840 -840
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +522 -522
- package/templates/skills/business-analyse/steps/step-05c-ralph-readiness.md +703 -703
- package/templates/skills/business-analyse/steps/step-06-review.md +278 -278
- package/templates/skills/business-analyse/templates/tpl-frd.md +168 -168
- package/templates/skills/business-analyse/templates/tpl-handoff.md +186 -186
- package/templates/skills/business-analyse/templates/tpl-launch-displays.md +59 -59
- package/templates/skills/business-analyse/templates/tpl-progress.md +172 -172
- package/templates/skills/business-analyse/templates-frd.md +476 -476
- package/templates/skills/business-analyse/templates-react.md +574 -574
- package/templates/skills/cc-agent/SKILL.md +129 -129
- package/templates/skills/cc-agent/references/agent-behavior-patterns.md +95 -95
- package/templates/skills/cc-agent/references/agent-frontmatter.md +213 -213
- package/templates/skills/cc-agent/references/permission-modes.md +102 -102
- package/templates/skills/cc-agent/references/tools-reference.md +144 -144
- package/templates/skills/cc-agent/steps/step-00-init.md +134 -134
- package/templates/skills/cc-agent/steps/step-01-design.md +186 -186
- package/templates/skills/cc-agent/steps/step-02-generate.md +131 -131
- package/templates/skills/cc-agent/steps/step-03-validate.md +130 -130
- package/templates/skills/cc-agent/templates/agent-categorized.md +67 -67
- package/templates/skills/cc-agent/templates/agent-standalone.md +56 -56
- package/templates/skills/cc-agent/templates/agent-with-skills.md +94 -94
- package/templates/skills/cc-audit/SKILL.md +108 -108
- package/templates/skills/cc-audit/references/agent-checklist.md +91 -91
- package/templates/skills/cc-audit/references/hook-checklist.md +110 -110
- package/templates/skills/cc-audit/references/skill-checklist.md +70 -70
- package/templates/skills/cc-audit/steps/step-00-init.md +98 -98
- package/templates/skills/cc-audit/steps/step-01-scan.md +142 -142
- package/templates/skills/cc-audit/steps/step-02-analyze.md +158 -158
- package/templates/skills/cc-audit/steps/step-03-report.md +142 -142
- package/templates/skills/cc-skill/SKILL.md +134 -134
- package/templates/skills/cc-skill/references/best-practices.md +167 -167
- package/templates/skills/cc-skill/references/frontmatter-reference.md +182 -182
- package/templates/skills/cc-skill/references/skill-patterns.md +199 -199
- package/templates/skills/cc-skill/steps/step-00-init.md +119 -119
- package/templates/skills/cc-skill/steps/step-01-design.md +199 -199
- package/templates/skills/cc-skill/steps/step-02-generate.md +145 -145
- package/templates/skills/cc-skill/steps/step-03-steps.md +151 -151
- package/templates/skills/cc-skill/steps/step-04-validate.md +124 -124
- package/templates/skills/cc-skill/templates/skill-forked.md +85 -85
- package/templates/skills/cc-skill/templates/skill-progressive.md +102 -102
- package/templates/skills/cc-skill/templates/skill-simple.md +75 -75
- package/templates/skills/cc-skill/templates/step-template.md +82 -82
- package/templates/skills/check-version/SKILL.md +196 -196
- package/templates/skills/controller/SKILL.md +162 -162
- package/templates/skills/controller/postman-templates.md +614 -614
- package/templates/skills/controller/references/controller-code-templates.md +159 -159
- package/templates/skills/controller/references/mcp-scaffold-workflow.md +209 -209
- package/templates/skills/controller/references/permission-sync-templates.md +149 -149
- package/templates/skills/controller/steps/step-00-init.md +193 -191
- package/templates/skills/controller/steps/step-01-analyze.md +146 -146
- package/templates/skills/controller/steps/step-02-plan.md +176 -176
- package/templates/skills/controller/steps/step-03-generate.md +189 -189
- package/templates/skills/controller/steps/step-04-perms.md +80 -80
- package/templates/skills/controller/steps/step-05-validate.md +107 -107
- package/templates/skills/controller/templates.md +1555 -1555
- package/templates/skills/debug/SKILL.md +70 -70
- package/templates/skills/debug/references/team-protocol.md +232 -232
- package/templates/skills/debug/steps/step-00-init.md +57 -57
- package/templates/skills/debug/steps/step-01-analyze.md +219 -219
- package/templates/skills/debug/steps/step-02-resolve.md +85 -85
- package/templates/skills/documentation/SKILL.md +132 -132
- package/templates/skills/documentation/data-schema.md +227 -227
- package/templates/skills/documentation/steps/step-00-init.md +70 -70
- package/templates/skills/documentation/steps/step-01-scan.md +113 -113
- package/templates/skills/documentation/steps/step-02-generate.md +231 -231
- package/templates/skills/documentation/steps/step-03-validate.md +251 -238
- package/templates/skills/documentation/templates.md +662 -663
- package/templates/skills/efcore/SKILL.md +168 -167
- package/templates/skills/efcore/references/both-contexts.md +32 -32
- package/templates/skills/efcore/references/database-operations.md +67 -67
- package/templates/skills/efcore/references/destructive-operations.md +38 -38
- package/templates/skills/efcore/references/reset-operations.md +81 -81
- package/templates/skills/efcore/references/seed-methods.md +86 -86
- package/templates/skills/efcore/references/shared-init-functions.md +250 -250
- package/templates/skills/efcore/references/sql-objects-injection.md +61 -61
- package/templates/skills/efcore/references/troubleshooting.md +81 -81
- package/templates/skills/efcore/references/zero-downtime-patterns.md +227 -227
- package/templates/skills/efcore/steps/db/step-deploy.md +217 -217
- package/templates/skills/efcore/steps/db/step-reset.md +186 -186
- package/templates/skills/efcore/steps/db/step-seed.md +166 -166
- package/templates/skills/efcore/steps/db/step-status.md +173 -173
- package/templates/skills/efcore/steps/migration/step-00-init.md +102 -102
- package/templates/skills/efcore/steps/migration/step-01-check.md +164 -164
- package/templates/skills/efcore/steps/migration/step-02-create.md +160 -160
- package/templates/skills/efcore/steps/migration/step-03-validate.md +168 -168
- package/templates/skills/efcore/steps/rebase-snapshot/step-00-init.md +173 -173
- package/templates/skills/efcore/steps/rebase-snapshot/step-01-backup.md +100 -100
- package/templates/skills/efcore/steps/rebase-snapshot/step-02-fetch.md +115 -115
- package/templates/skills/efcore/steps/rebase-snapshot/step-03-create.md +112 -112
- package/templates/skills/efcore/steps/rebase-snapshot/step-04-validate.md +157 -157
- package/templates/skills/efcore/steps/shared/step-00-init.md +131 -131
- package/templates/skills/efcore/steps/squash/step-00-init.md +141 -141
- package/templates/skills/efcore/steps/squash/step-01-backup.md +120 -120
- package/templates/skills/efcore/steps/squash/step-02-fetch.md +168 -168
- package/templates/skills/efcore/steps/squash/step-03-create.md +184 -184
- package/templates/skills/efcore/steps/squash/step-04-validate.md +174 -174
- package/templates/skills/explore/SKILL.md +98 -98
- package/templates/skills/feature-full/SKILL.md +111 -111
- package/templates/skills/feature-full/steps/step-00-init.md +57 -57
- package/templates/skills/feature-full/steps/step-01-implementation.md +120 -120
- package/templates/skills/gitflow/SKILL.md +377 -377
- package/templates/skills/gitflow/_shared.md +620 -620
- package/templates/skills/gitflow/phases/abort.md +189 -189
- package/templates/skills/gitflow/phases/cleanup.md +234 -234
- package/templates/skills/gitflow/phases/status.md +192 -192
- package/templates/skills/gitflow/references/commit-message-generation.md +58 -58
- package/templates/skills/gitflow/references/commit-migration-validation.md +49 -49
- package/templates/skills/gitflow/references/finish-cleanup.md +55 -55
- package/templates/skills/gitflow/references/finish-version-bumping.md +45 -45
- package/templates/skills/gitflow/references/init-config-template.md +135 -135
- package/templates/skills/gitflow/references/init-environment-detection.md +41 -41
- package/templates/skills/gitflow/references/init-name-normalization.md +103 -103
- package/templates/skills/gitflow/references/init-questions.md +185 -185
- package/templates/skills/gitflow/references/init-structure-creation.md +75 -75
- package/templates/skills/gitflow/references/init-version-detection.md +21 -21
- package/templates/skills/gitflow/references/init-workspace-detection.md +43 -43
- package/templates/skills/gitflow/references/merge-ci-status.md +36 -36
- package/templates/skills/gitflow/references/merge-execution.md +62 -62
- package/templates/skills/gitflow/references/merge-pr-context.md +76 -76
- package/templates/skills/gitflow/references/plan-template.md +69 -69
- package/templates/skills/gitflow/references/pr-build-checks.md +60 -60
- package/templates/skills/gitflow/references/pr-generation.md +58 -58
- package/templates/skills/gitflow/references/start-branch-normalization.md +28 -28
- package/templates/skills/gitflow/references/start-efcore-preflight.md +70 -70
- package/templates/skills/gitflow/references/start-local-config.md +113 -113
- package/templates/skills/gitflow/references/start-worktree-creation.md +50 -50
- package/templates/skills/gitflow/references/sync-push-verify.md +44 -44
- package/templates/skills/gitflow/references/sync-rebase-conflicts.md +38 -38
- package/templates/skills/gitflow/steps/step-commit.md +199 -199
- package/templates/skills/gitflow/steps/step-finish.md +147 -147
- package/templates/skills/gitflow/steps/step-init.md +190 -190
- package/templates/skills/gitflow/steps/step-merge.md +85 -85
- package/templates/skills/gitflow/steps/step-plan.md +151 -151
- package/templates/skills/gitflow/steps/step-pr.md +199 -199
- package/templates/skills/gitflow/steps/step-start.md +195 -195
- package/templates/skills/gitflow/steps/step-sync.md +161 -161
- package/templates/skills/gitflow/templates/config.json +72 -72
- package/templates/skills/mcp/SKILL.md +62 -62
- package/templates/skills/mcp/steps/step-01-healthcheck.md +108 -108
- package/templates/skills/mcp/steps/step-02-tools.md +73 -73
- package/templates/skills/notification/SKILL.md +173 -173
- package/templates/skills/quick-search/SKILL.md +99 -99
- package/templates/skills/ralph-loop/SKILL.md +234 -234
- package/templates/skills/ralph-loop/references/category-completeness.md +185 -185
- package/templates/skills/ralph-loop/references/category-rules.md +96 -96
- package/templates/skills/ralph-loop/references/compact-loop.md +300 -300
- package/templates/skills/ralph-loop/references/init-resume-recovery.md +127 -127
- package/templates/skills/ralph-loop/references/module-transition.md +151 -151
- package/templates/skills/ralph-loop/references/multi-module-queue.md +171 -171
- package/templates/skills/ralph-loop/references/parallel-execution.md +246 -246
- package/templates/skills/ralph-loop/references/section-splitting.md +439 -439
- package/templates/skills/ralph-loop/references/task-transform-legacy.md +256 -256
- package/templates/skills/ralph-loop/references/team-orchestration.md +547 -547
- package/templates/skills/ralph-loop/steps/step-00-init.md +150 -150
- package/templates/skills/ralph-loop/steps/step-01-task.md +174 -174
- package/templates/skills/ralph-loop/steps/step-02-execute.md +177 -177
- package/templates/skills/ralph-loop/steps/step-03-commit.md +92 -92
- package/templates/skills/ralph-loop/steps/step-04-check.md +207 -207
- package/templates/skills/ralph-loop/steps/step-05-report.md +175 -175
- package/templates/skills/refactor/SKILL.md +56 -56
- package/templates/skills/refactor/steps/step-01-discover.md +60 -60
- package/templates/skills/refactor/steps/step-02-execute.md +67 -67
- package/templates/skills/review-code/SKILL.md +95 -94
- package/templates/skills/review-code/references/clean-code-principles.md +292 -292
- package/templates/skills/review-code/references/code-quality-metrics.md +174 -174
- package/templates/skills/review-code/references/feedback-patterns.md +149 -149
- package/templates/skills/review-code/references/owasp-api-top10.md +243 -243
- package/templates/skills/review-code/references/security-checklist.md +212 -212
- package/templates/skills/review-code/steps/step-01-smartstack.md +96 -96
- package/templates/skills/review-code/steps/step-02-detailed-review.md +80 -80
- package/templates/skills/review-code/steps/step-03-react.md +44 -44
- package/templates/skills/ui-components/SKILL.md +137 -137
- package/templates/skills/ui-components/accessibility.md +170 -170
- package/templates/skills/ui-components/patterns/dashboard-chart.md +327 -327
- package/templates/skills/ui-components/patterns/data-table.md +39 -39
- package/templates/skills/ui-components/patterns/entity-card.md +77 -77
- package/templates/skills/ui-components/patterns/grid-layout.md +91 -91
- package/templates/skills/ui-components/patterns/kanban.md +43 -43
- package/templates/skills/ui-components/responsive-guidelines.md +278 -278
- package/templates/skills/ui-components/style-guide.md +113 -113
- package/templates/skills/utils/SKILL.md +44 -44
- package/templates/skills/utils/subcommands/test-web-config.md +152 -152
- package/templates/skills/utils/subcommands/test-web.md +123 -123
- package/templates/skills/validate/SKILL.md +181 -181
- package/templates/skills/validate-feature/SKILL.md +101 -101
- package/templates/skills/validate-feature/references/api-smoke-tests.md +140 -140
- package/templates/skills/validate-feature/references/db-validation-checks.md +180 -180
- package/templates/skills/validate-feature/steps/step-00-dependencies.md +121 -121
- package/templates/skills/validate-feature/steps/step-01-compile.md +39 -39
- package/templates/skills/validate-feature/steps/step-02-unit-tests.md +45 -45
- package/templates/skills/validate-feature/steps/step-03-integration-tests.md +53 -53
- package/templates/skills/validate-feature/steps/step-04-api-smoke.md +94 -94
- package/templates/skills/validate-feature/steps/step-05-db-validation.md +149 -149
- package/templates/skills/workflow/SKILL.md +127 -127
- package/templates/skills/workflow/steps/step-00-init.md +57 -57
- package/templates/skills/workflow/steps/step-01-implementation.md +84 -84
- package/templates/test-web/api-health.json +38 -38
- package/templates/test-web/minimal.json +19 -19
- package/templates/test-web/npm-package.json +46 -46
- package/templates/test-web/seo-check.json +54 -54
|
@@ -1,840 +1,840 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: step-05a-handoff
|
|
3
|
-
description: Build development handoff data, map business rules to code, write handoff to feature.json
|
|
4
|
-
model: sonnet
|
|
5
|
-
next_step: steps/step-05b-deploy.md
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
> **Context files:** `_shared.md` | `_architecture.md`
|
|
9
|
-
|
|
10
|
-
# Step 5a: Handoff - Build & Write
|
|
11
|
-
|
|
12
|
-
## MANDATORY EXECUTION RULES
|
|
13
|
-
|
|
14
|
-
- **ALWAYS** verify status = "consolidated" before proceeding
|
|
15
|
-
- **ALWAYS** ask user for implementation strategy preference (multi-module only)
|
|
16
|
-
- **ALWAYS** derive prd.json from feature.json (NEVER independently)
|
|
17
|
-
- **NEVER** invent entities/FRs/BRs not in feature.json
|
|
18
|
-
- **ALL** API routes from specification.apiEndpoints (exact copy)
|
|
19
|
-
- **Permission** paths from specification.permissionMatrix (full format)
|
|
20
|
-
- **ALWAYS** generate CORE SeedData entries: 2 app-level (NavigationApplication + ApplicationRoles) + per module (NavigationModule + NavigationSections + Permissions + Roles)
|
|
21
|
-
|
|
22
|
-
## YOUR TASK
|
|
23
|
-
|
|
24
|
-
Build the development handoff data: verify consolidation, choose implementation strategy, calculate complexity, map specification to files (7 categories), map business rules to code, generate API endpoint summary, and write handoff to EACH module feature.json.
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## EXECUTION SEQUENCE
|
|
29
|
-
|
|
30
|
-
### 1. Verify Consolidation Passed
|
|
31
|
-
|
|
32
|
-
Use ba-reader to locate the feature and verify consolidation status:
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
// Determine feature source based on workflow mode
|
|
36
|
-
IF workflow.mode === "project":
|
|
37
|
-
projectFeature = ba-reader.findProjectFeature()
|
|
38
|
-
// Verify ALL applications are specified
|
|
39
|
-
FOR each app in projectFeature.applications:
|
|
40
|
-
appFeature = ba-reader.findFeature(app.featureJsonPath)
|
|
41
|
-
IF appFeature.status !== "consolidated":
|
|
42
|
-
BLOCKING ERROR: "Application {app.code} not consolidated (status: {appFeature.status})"
|
|
43
|
-
→ Return to step-04a-collect.md
|
|
44
|
-
// Use project-level feature for overall consolidation
|
|
45
|
-
feature = projectFeature
|
|
46
|
-
ELSE:
|
|
47
|
-
ba-reader.findFeature({feature_id})
|
|
48
|
-
→ Check status = "consolidated"
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
**IF** status ≠ "consolidated" → **STOP**. Return to step-04a-collect.md.
|
|
52
|
-
|
|
53
|
-
Display validation summary:
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
✓ Consolidation: APPROVED
|
|
57
|
-
✓ Applications: {app_count} (project mode only)
|
|
58
|
-
✓ Modules: {count} specified and validated
|
|
59
|
-
✓ Cross-module: interactions mapped
|
|
60
|
-
✓ Cross-application: interactions mapped (project mode only)
|
|
61
|
-
✓ Permissions: coherent
|
|
62
|
-
→ Proceeding to handoff...
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Include:
|
|
66
|
-
- Number of applications (project mode only)
|
|
67
|
-
- Number of modules across all applications
|
|
68
|
-
- Number of entities across all modules
|
|
69
|
-
- Number of use cases across all modules
|
|
70
|
-
- Number of business rules across all modules
|
|
71
|
-
- Cross-module interaction count
|
|
72
|
-
- Cross-application interaction count (project mode only)
|
|
73
|
-
|
|
74
|
-
---
|
|
75
|
-
|
|
76
|
-
### 1b. Cache Warming for Handoff & Deploy
|
|
77
|
-
|
|
78
|
-
> **Performance Optimization:** Pre-load handoff templates and references to reduce redundant reads during handoff generation.
|
|
79
|
-
> This step runs ONCE at start of step-05a, files retained through step-05b.
|
|
80
|
-
|
|
81
|
-
```
|
|
82
|
-
// Pre-load handoff & deploy references (Bucket 5)
|
|
83
|
-
const handoffRefs = [
|
|
84
|
-
"~/.claude/skills/business-analyse/references/handoff-file-templates.md",
|
|
85
|
-
"~/.claude/skills/business-analyse/references/handoff-mappings.md",
|
|
86
|
-
"~/.claude/skills/business-analyse/references/deploy-data-build.md",
|
|
87
|
-
"~/.claude/skills/business-analyse/references/deploy-modes.md",
|
|
88
|
-
"~/.claude/skills/business-analyse/references/html-data-mapping.md"
|
|
89
|
-
];
|
|
90
|
-
|
|
91
|
-
for (const file of handoffRefs) {
|
|
92
|
-
read(file); // Pre-load into cache
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Pre-load HTML template (large file, loaded once)
|
|
96
|
-
read("~/.claude/skills/business-analyse/html/ba-interactive.html");
|
|
97
|
-
|
|
98
|
-
Display: "✓ Cache warmed: handoff templates (139KB, 6 files)"
|
|
99
|
-
Display: " Expected token savings: ~3,000 tokens (handoff refs read 2× → 1×)"
|
|
100
|
-
Display: " Retention: through step-05b (deploy)"
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
**Rationale:**
|
|
104
|
-
|
|
105
|
-
- Handoff templates are read 2× during step-05a + step-05b (without caching)
|
|
106
|
-
- HTML template (85KB) is read once but benefits from explicit pre-load (faster deploy)
|
|
107
|
-
- Token savings: ~3,000 tokens for handoff process
|
|
108
|
-
- Cache retained until session end (needed for both handoff and deploy steps)
|
|
109
|
-
|
|
110
|
-
**Why NOT loaded at step-00:**
|
|
111
|
-
- Large files (139KB total), especially ba-interactive.html (85KB)
|
|
112
|
-
- Only used at END of workflow (steps 05a, 05b)
|
|
113
|
-
- Low re-use (1-2× each)
|
|
114
|
-
- Loading at step-05a is more efficient (just-in-time caching)
|
|
115
|
-
|
|
116
|
-
See [references/cache-warming-strategy.md](../references/cache-warming-strategy.md) § Bucket 5 for details.
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
### 2. Implementation Strategy Choice (Multi-Module/Multi-App)
|
|
121
|
-
|
|
122
|
-
**IF** more than 1 module defined in feature.json (or project mode with multiple applications):
|
|
123
|
-
|
|
124
|
-
Ask via AskUserQuestion:
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
question: "Quelle stratégie d'implémentation préférez-vous ?"
|
|
128
|
-
header: "Stratégie d'implémentation"
|
|
129
|
-
options:
|
|
130
|
-
- label: "Module par module (Recommandé)"
|
|
131
|
-
description: "Implémenter chaque module complètement avant de passer au suivant. Suit l'ordre topologique des dépendances."
|
|
132
|
-
- label: "Couche par couche"
|
|
133
|
-
description: "Implémenter toutes les entités, puis tous les services, puis tous les contrôleurs, etc. Plus de parallélisation possible mais plus complexe."
|
|
134
|
-
- label: "Hybride"
|
|
135
|
-
description: "Modules fondation en premier (couche par couche), puis modules dépendants (module par module)"
|
|
136
|
-
- label: "Application par application (Recommandé multi-app)"
|
|
137
|
-
description: "Implémenter chaque application complètement avant de passer à la suivante. Suit l'ordre topologique inter-applications."
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
> **Note:** "Application par application" only appears for project mode with 2+ applications.
|
|
141
|
-
|
|
142
|
-
Store the chosen strategy in `handoff.implementationStrategy`.
|
|
143
|
-
|
|
144
|
-
**IF** only 1 module → default to "Module par module" (no choice needed).
|
|
145
|
-
|
|
146
|
-
---
|
|
147
|
-
|
|
148
|
-
### 3. Calculate Complexity
|
|
149
|
-
|
|
150
|
-
For each module in feature.json.modules[], calculate:
|
|
151
|
-
|
|
152
|
-
```json
|
|
153
|
-
{
|
|
154
|
-
"complexity": "simple|medium|complex",
|
|
155
|
-
"complexityDetails": {
|
|
156
|
-
"entities": {count},
|
|
157
|
-
"useCases": {count},
|
|
158
|
-
"businessRules": {count},
|
|
159
|
-
"calculated": "{level} (≤X entities, ≤Y UCs, ≤Z BRs)"
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
| Criteria | Simple | Medium | Complex |
|
|
165
|
-
|----------|--------|--------|---------|
|
|
166
|
-
| Entities | ≤3 | ≤6 | >6 |
|
|
167
|
-
| Use Cases | ≤5 | ≤12 | >12 |
|
|
168
|
-
| Business Rules | ≤10 | ≤20 | >20 |
|
|
169
|
-
|
|
170
|
-
**Global complexity** = highest complexity across all modules.
|
|
171
|
-
|
|
172
|
-
Example:
|
|
173
|
-
- Module A: 4 entities, 6 use cases, 8 BRs → **simple**
|
|
174
|
-
- Module B: 8 entities, 15 use cases, 25 BRs → **complex**
|
|
175
|
-
- Overall: **complex**
|
|
176
|
-
|
|
177
|
-
---
|
|
178
|
-
|
|
179
|
-
### 4. Map Specification to Files
|
|
180
|
-
|
|
181
|
-
> **IMPORTANT:** Generate `handoff.filesToCreate` as structured object with 7 categories.
|
|
182
|
-
> Each file entry is `{path, type, linkedFRs, linkedUCs, module}`. NO free text.
|
|
183
|
-
> Read `.smartstack/config.json` to extract baseNamespace for project namespace.
|
|
184
|
-
|
|
185
|
-
**Order by topological dependency** (modules with no deps first, then dependents).
|
|
186
|
-
|
|
187
|
-
For **EACH module** in topological order:
|
|
188
|
-
|
|
189
|
-
> **PATH HIERARCHY CONVENTION:** All backend file paths MUST include the application hierarchy.
|
|
190
|
-
> Derive from module feature.json metadata:
|
|
191
|
-
> - `{ApplicationName}` = `metadata.application` (e.g., `"HumanResources"`)
|
|
192
|
-
> - `{ModuleName}` = `metadata.module` (e.g., `"Projects"`)
|
|
193
|
-
>
|
|
194
|
-
> **Example** for application=HumanResources, module=Projects:
|
|
195
|
-
> - Domain: `src/Domain/Entities/HumanResources/Projects/Project.cs`
|
|
196
|
-
> - Application: `src/Application/Services/HumanResources/Projects/ProjectService.cs`
|
|
197
|
-
> - Infrastructure: `src/Infrastructure/Persistence/Configurations/HumanResources/Projects/ProjectConfiguration.cs`
|
|
198
|
-
> - API: `src/API/Controllers/HumanResources/ProjectsController.cs`
|
|
199
|
-
> - Tests: `src/Tests/Unit/Domain/HumanResources/Projects/ProjectTests.cs`
|
|
200
|
-
|
|
201
|
-
#### 4.1-4.7 File Category Templates
|
|
202
|
-
|
|
203
|
-
See [references/handoff-file-templates.md](../references/handoff-file-templates.md) for the complete JSON templates for all 7 categories:
|
|
204
|
-
|
|
205
|
-
| Category | Source | Key rules |
|
|
206
|
-
|----------|--------|-----------|
|
|
207
|
-
| **4.1 Domain** | `analysis.entities[]` | Entities, ValueObjects, Enums, Exceptions |
|
|
208
|
-
| **4.2 Application** | `analysis.useCases[]` | Services, DTOs, Validators |
|
|
209
|
-
| **4.3 Infrastructure** | `analysis.entities[]` | EF Configurations, DbSet, DI. **DEPENDENCY:** Each EF config task MUST `dependsOn` its corresponding domain entity task. |
|
|
210
|
-
| **4.4 API** | `specification.apiEndpoints[]` | Controllers |
|
|
211
|
-
| **4.5 Frontend** | `specification.uiWireframes[]` | Pages, Components, Hooks + wireframe traceability |
|
|
212
|
-
| **4.6 SeedData** | `specification.seedDataCore` | 2 app-level + per module CORE (NavigationModule + NavigationSections + Permissions + Roles) + business + IClientSeedDataProvider |
|
|
213
|
-
| **4.7 Tests** | All layers | Unit, Integration, Security tests |
|
|
214
|
-
|
|
215
|
-
#### Route Convention (CRITICAL)
|
|
216
|
-
|
|
217
|
-
> **MANDATORY:** All NavigationModule/Section routes MUST use kebab-case transformation.
|
|
218
|
-
> See [references/naming-conventions.md](../references/naming-conventions.md) for complete guide.
|
|
219
|
-
|
|
220
|
-
**Problem:**
|
|
221
|
-
- Module codes in feature.json are **PascalCase** (e.g., `"HumanResources"`)
|
|
222
|
-
- Routes in seed data MUST be **kebab-case** (e.g., `"/human-resources"`)
|
|
223
|
-
- Failing to transform causes 404 when clicking menu items
|
|
224
|
-
|
|
225
|
-
**Solution:**
|
|
226
|
-
|
|
227
|
-
When generating `seedDataCore` for handoff, transform PascalCase codes to kebab-case routes:
|
|
228
|
-
|
|
229
|
-
```javascript
|
|
230
|
-
// Transform module codes to kebab-case routes
|
|
231
|
-
function toKebabCase(code) {
|
|
232
|
-
return code
|
|
233
|
-
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
234
|
-
.toLowerCase();
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Example usage in seedDataCore generation
|
|
238
|
-
const moduleCode = "TimeManagement"; // PascalCase (C#)
|
|
239
|
-
const appCode = "HumanResources"; // PascalCase (C#)
|
|
240
|
-
|
|
241
|
-
const route = `/${toKebabCase(appCode)}/${toKebabCase(moduleCode)}`;
|
|
242
|
-
// Result: "/human-resources/time-management"
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
**Validation:** All kebab-case routes in seed data MUST NOT include `/business/` prefix.
|
|
246
|
-
|
|
247
|
-
Example in NavigationModule:
|
|
248
|
-
```csharp
|
|
249
|
-
route = "/human-resources"; // ✓ Correct (kebab-case module code only)
|
|
250
|
-
route = "/business/human-resources"; // ✗ WRONG (contains /business/)
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
**Include in task instructions:**
|
|
254
|
-
|
|
255
|
-
For NavigationSeedData tasks in `handoff.filesToCreate`, add:
|
|
256
|
-
|
|
257
|
-
```json
|
|
258
|
-
{
|
|
259
|
-
"path": "Infrastructure/Persistence/Seeding/Data/{Module}/NavigationSeedData.cs",
|
|
260
|
-
"type": "SeedData",
|
|
261
|
-
"category": "core",
|
|
262
|
-
"instructions": "Generate NavigationModule seed data. CRITICAL: Use ToKebabCase() helper for Route property. Example: Route = ToKebabCase($\"/{app}/{module}\"). See core-seed-data.md template."
|
|
263
|
-
}
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
**Validation:**
|
|
267
|
-
- ralph-loop POST-CHECK validates routes after generation (see step-02-execute.md)
|
|
268
|
-
- MCP `validate_frontend_routes` detects case mismatches
|
|
269
|
-
- Convention documented in naming-conventions.md
|
|
270
|
-
|
|
271
|
-
**Critical rules:**
|
|
272
|
-
- All backend paths include `{ApplicationName}/` hierarchy
|
|
273
|
-
- Frontend pages MUST have `linkedWireframes[]` + `wireframeAcceptanceCriteria`
|
|
274
|
-
- SeedData: 2 app-level CORE (NavigationApplication + ApplicationRoles) + per-module CORE (NavigationModule + NavigationSections + Permissions + Roles) + IClientSeedDataProvider for client projects
|
|
275
|
-
- **Acceptance Criteria Mapping:** Each task's `acceptanceCriteria` MUST be derived from its own `linkedFRs[]` entries (lookup FR → `acceptanceCriteria`). NEVER map by sequential FR index — use the task's explicit linkedFRs to resolve the correct criteria.
|
|
276
|
-
- Path convention: `Persistence/Seeding/Data/` (NEVER `Data/SeedData/`)
|
|
277
|
-
|
|
278
|
-
---
|
|
279
|
-
|
|
280
|
-
### 5. Map Business Rules to Code
|
|
281
|
-
|
|
282
|
-
See [references/handoff-mappings.md](../references/handoff-mappings.md) — Section "Business Rules to Code Mapping".
|
|
283
|
-
|
|
284
|
-
For each BR in `analysis.businessRules[]` of EACH module, generate:
|
|
285
|
-
- **ruleId**, **title**, **module**, **severity** (critical/high/medium/low)
|
|
286
|
-
- **implementationPoints**: Array of `{layer, component, method, implementation}` across Domain, Application, Infrastructure, API, Frontend
|
|
287
|
-
|
|
288
|
-
---
|
|
289
|
-
|
|
290
|
-
### 6. API Endpoint Summary
|
|
291
|
-
|
|
292
|
-
> **ABSOLUTE RULE:** Copy **EXACTLY** from `specification.apiEndpoints[]`. **NEVER** reinvent routes.
|
|
293
|
-
|
|
294
|
-
See [references/handoff-mappings.md](../references/handoff-mappings.md) — Section "API Endpoint Summary".
|
|
295
|
-
|
|
296
|
-
For each endpoint: operation, method, route, linkedUC, linkedFR, permissions, requestSchema, responseSchema, errorCodes, module.
|
|
297
|
-
|
|
298
|
-
Total endpoints = count of specification.apiEndpoints[] across all modules.
|
|
299
|
-
|
|
300
|
-
### 6b. Frontend Task Splitting (MANDATORY)
|
|
301
|
-
|
|
302
|
-
> **CRITICAL:** Frontend MUST be split into discrete tasks, NOT bundled as a single mega-task.
|
|
303
|
-
> A single mega-task covering 5-8 files prevents granular error recovery in ralph-loop.
|
|
304
|
-
|
|
305
|
-
For each module, generate these SEPARATE frontend file entries (not one monolithic entry):
|
|
306
|
-
|
|
307
|
-
```json
|
|
308
|
-
"frontend": [
|
|
309
|
-
{ "path": "src/pages/{App}/{Mod}/{ListPage}Page.tsx", "type": "Page", "linkedWireframes": ["{module}-list"], "module": "{moduleCode}", "skill": "/ui-components" },
|
|
310
|
-
{ "path": "src/pages/{App}/{Mod}/{Entity}CreatePage.tsx", "type": "Page", "linkedWireframes": ["{module}-create"], "module": "{moduleCode}", "skill": "/ui-components", "fkFields": ["EmployeeId→Employee", "DepartmentId→Department"] },
|
|
311
|
-
{ "path": "src/pages/{App}/{Mod}/{Entity}EditPage.tsx", "type": "Page", "linkedWireframes": ["{module}-edit"], "module": "{moduleCode}", "skill": "/ui-components", "fkFields": ["EmployeeId→Employee", "DepartmentId→Department"] },
|
|
312
|
-
{ "path": "src/pages/{App}/{Mod}/{DetailPage}Page.tsx", "type": "Page", "linkedWireframes": ["{module}-detail"], "module": "{moduleCode}", "skill": "/ui-components" },
|
|
313
|
-
{ "path": "src/hooks/use{Module}.ts", "type": "Hook", "module": "{moduleCode}" },
|
|
314
|
-
{ "path": "src/i18n/locales/fr/{moduleLower}.json", "type": "I18n", "language": "fr", "module": "{moduleCode}" },
|
|
315
|
-
{ "path": "src/i18n/locales/en/{moduleLower}.json", "type": "I18n", "language": "en", "module": "{moduleCode}" },
|
|
316
|
-
{ "path": "src/i18n/locales/it/{moduleLower}.json", "type": "I18n", "language": "it", "module": "{moduleCode}" },
|
|
317
|
-
{ "path": "src/i18n/locales/de/{moduleLower}.json", "type": "I18n", "language": "de", "module": "{moduleCode}" }
|
|
318
|
-
]
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
**FK fields in forms:** Create/Edit page entries MUST include `"fkFields"` array listing FK properties and their target entities (format: `"PropertyId→TargetEntity"`). This tells ralph-loop to use `EntityLookup` component instead of plain text inputs. Derive FK fields from `analysis.entities[].relationships[]` where `type = "N:1"` or from properties ending in `Id` with a navigation property. See `smartstack-frontend.md` section 6 for the EntityLookup pattern.
|
|
322
|
-
|
|
323
|
-
**Page generation:** ALL pages MUST use `/ui-components` skill (indicated by `"skill"` field). NEVER write raw TSX without the skill patterns.
|
|
324
|
-
|
|
325
|
-
**I18n generation:** 4 JSON files per module with identical key structures. `{moduleLower}` = lowercase module code. Keys: actions, labels, columns, form, errors, validation, messages, empty. See `smartstack-frontend.md` template.
|
|
326
|
-
|
|
327
|
-
Additional per-section pages (dashboard, import, etc.) are separate entries.
|
|
328
|
-
|
|
329
|
-
**Route wiring task (MANDATORY — separate entry):**
|
|
330
|
-
```json
|
|
331
|
-
{ "path": "src/App.tsx", "type": "RouteWiring", "module": "{moduleCode}", "description": "Wire {module} routes into App.tsx
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
### 6c. Cross-Module PRD (MANDATORY for multi-module features)
|
|
335
|
-
|
|
336
|
-
> **CRITICAL:** Cross-module integration tasks MUST exist in a dedicated PRD file.
|
|
337
|
-
> Without this, ralph-loop will NOT execute E2E tests or FK validation.
|
|
338
|
-
|
|
339
|
-
Generate `.ralph/prd-CrossModule.json` with:
|
|
340
|
-
```json
|
|
341
|
-
{
|
|
342
|
-
"$version": "3.0.0",
|
|
343
|
-
"implementation": {
|
|
344
|
-
"filesToCreate": {
|
|
345
|
-
"tests": [
|
|
346
|
-
{ "path": "src/Tests/Integration/CrossModule/ForeignKeyValidationTests.cs", "type": "IntegrationTests", "module": "CrossModule" },
|
|
347
|
-
{ "path": "src/Tests/Integration/CrossModule/PermissionMatrixTests.cs", "type": "SecurityTests", "module": "CrossModule" },
|
|
348
|
-
{ "path": "src/Tests/Integration/CrossModule/E2EFlowTests.cs", "type": "E2ETests", "module": "CrossModule" }
|
|
349
|
-
]
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
Add to progress.txt after all module tasks.
|
|
356
|
-
|
|
357
|
-
### 6d. Cross-Application PRD (Project Mode Only)
|
|
358
|
-
|
|
359
|
-
> **Only generated when `workflow.mode === "project"`.**
|
|
360
|
-
> Contains cross-application integration tests and shared entity validation.
|
|
361
|
-
|
|
362
|
-
```json
|
|
363
|
-
{
|
|
364
|
-
"$version": "3.0.0",
|
|
365
|
-
"implementation": {
|
|
366
|
-
"filesToCreate": {
|
|
367
|
-
"tests": [
|
|
368
|
-
{ "path": "src/Tests/Integration/CrossApplication/SharedEntityValidationTests.cs", "type": "IntegrationTests", "module": "CrossApplication" },
|
|
369
|
-
{ "path": "src/Tests/Integration/CrossApplication/CrossAppPermissionTests.cs", "type": "SecurityTests", "module": "CrossApplication" },
|
|
370
|
-
{ "path": "src/Tests/Integration/CrossApplication/CrossAppE2EFlowTests.cs", "type": "E2ETests", "module": "CrossApplication" }
|
|
371
|
-
]
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
Write to: `.ralph/prd-CrossApplication.json`
|
|
378
|
-
|
|
379
|
-
> This PRD is generated IN ADDITION to the per-module cross-module PRD.
|
|
380
|
-
> It validates interactions between applications, not just between modules within the same application.
|
|
381
|
-
|
|
382
|
-
---
|
|
383
|
-
|
|
384
|
-
### 7. Write Handoff to Feature.json
|
|
385
|
-
|
|
386
|
-
> **BLOCKING RULE: The handoff MUST be written in EACH module feature.json.**
|
|
387
|
-
> A handoff at master level alone is INSUFFICIENT. Ralph-loop consumes module-level handoffs.
|
|
388
|
-
> An empty module handoff (`"handoff": {}`) is a CRITICAL BUG that blocks all downstream generation.
|
|
389
|
-
|
|
390
|
-
#### 7a. Module Handoff Loop (MANDATORY)
|
|
391
|
-
|
|
392
|
-
> **STRUCTURE CARD: handoff** — Field names are EXACT. Include ALL fields below.
|
|
393
|
-
> **PATH RULE:** All backend paths MUST include `{ApplicationName}/` hierarchy (see section 4).
|
|
394
|
-
> ```json
|
|
395
|
-
> {
|
|
396
|
-
> "complexity": "simple|medium|complex",
|
|
397
|
-
> "filesToCreate": {
|
|
398
|
-
> "domain": [{"path": "src/Domain/Entities/{App}/{Mod}/{Entity}.cs", "type": "Entity|ValueObject|Enum", "linkedFRs": [], "linkedUCs": [], "module": "..."}],
|
|
399
|
-
> "application": [{"path": "src/Application/Services/{App}/{Mod}/{Svc}Service.cs", "type": "Service|Dto|Validator", "linkedFRs": [], "linkedUCs": [], "module": "..."}],
|
|
400
|
-
> "infrastructure": [{"path": "src/Infrastructure/Persistence/Configurations/{App}/{Mod}/{Entity}Configuration.cs", "type": "EFConfiguration", "linkedFRs": [], "module": "..."}],
|
|
401
|
-
> "api": [{"path": "src/API/Controllers/{App}/{Entity}Controller.cs", "type": "ApiController", "linkedUCs": [], "linkedFRs": [], "module": "..."}],
|
|
402
|
-
> "frontend": [{"path": "src/pages/{App}/{Mod}/{Page}Page.tsx", "type": "Page|Component|Hook|DashboardPage|I18n", "linkedUCs": [], "linkedWireframes": [], "module": "...", "skill": "/ui-components"}],
|
|
403
|
-
> "seedData": [{"path": "src/Infrastructure/Persistence/Seeding/Data/{Mod}/...SeedData.cs", "type": "SeedData", "category": "core|business", "source": "...", "module": "..."}],
|
|
404
|
-
> "tests": [{"path": "src/Tests/Unit/Domain/{App}/{Mod}/{Entity}Tests.cs", "type": "UnitTests|IntegrationTests|SecurityTests", "linkedFRs": [], "linkedUCs": [], "module": "..."}]
|
|
405
|
-
> },
|
|
406
|
-
> "brToCodeMapping": [{"ruleId": "BR-...", "files": ["path1", "path2"], "implementation": "description"}],
|
|
407
|
-
> "apiEndpointSummary": [{"method": "GET|POST|PUT|DELETE", "path": "/api/...", "permission": "{app}.{module}.{action}", "linkedUC": "UC-..."}],
|
|
408
|
-
> "prdFile": ".ralph/prd-{module}.json",
|
|
409
|
-
> "totalFiles": 0,
|
|
410
|
-
> "totalTasks": 0,
|
|
411
|
-
> "handedOffAt": "{ISO timestamp}"
|
|
412
|
-
> }
|
|
413
|
-
> ```
|
|
414
|
-
> **MANDATORY fields:** ALL of the above. `filesToCreate` MUST have all 7 categories (even if empty arrays).
|
|
415
|
-
> **FORBIDDEN:** `handoff: {}` (empty object is a CRITICAL BUG). Missing `brToCodeMapping` or `apiEndpointSummary`.
|
|
416
|
-
|
|
417
|
-
**For i = 0; i < modules.length; i++:**
|
|
418
|
-
|
|
419
|
-
```
|
|
420
|
-
1. moduleCode = modules[i].code
|
|
421
|
-
2. moduleFeatureId = modules[i].featureJsonPath or find via ba-reader.findFeature()
|
|
422
|
-
3. Read the module feature.json via ba-reader.findFeature(moduleFeatureId)
|
|
423
|
-
4. Build the handoff payload for THIS module:
|
|
424
|
-
- complexity (from section 3 calculation)
|
|
425
|
-
- filesToCreate (full 7-category structure from section 4, filtered for this module)
|
|
426
|
-
- brToCodeMapping (from section 5, filtered for this module)
|
|
427
|
-
- apiEndpointSummary (from section 6, filtered for this module)
|
|
428
|
-
- prdFile path
|
|
429
|
-
- totalFiles count
|
|
430
|
-
- totalTasks count
|
|
431
|
-
- handedOffAt timestamp
|
|
432
|
-
|
|
433
|
-
5. Write via ba-writer:
|
|
434
|
-
ba-writer.enrichModuleHandoff({
|
|
435
|
-
moduleFeatureId: {moduleFeatureId},
|
|
436
|
-
handoffData: {
|
|
437
|
-
complexity: "{simple|medium|complex}",
|
|
438
|
-
filesToCreate: {...},
|
|
439
|
-
brToCodeMapping: [...],
|
|
440
|
-
apiEndpointSummary: [...],
|
|
441
|
-
prdFile: ".ralph/prd-{moduleCode}.json",
|
|
442
|
-
totalFiles: {count},
|
|
443
|
-
totalTasks: {count},
|
|
444
|
-
handedOffAt: "{ISO timestamp}"
|
|
445
|
-
}
|
|
446
|
-
})
|
|
447
|
-
|
|
448
|
-
6. VERIFICATION (MANDATORY - done automatically by enrichModuleHandoff):
|
|
449
|
-
- handoff !== {}
|
|
450
|
-
- handoff.filesToCreate has 7 categories
|
|
451
|
-
- handoff.brToCodeMapping.length > 0
|
|
452
|
-
IF verification fails → STOP, report error, do NOT continue
|
|
453
|
-
|
|
454
|
-
7. Display progress:
|
|
455
|
-
"✓ Handoff module {i+1}/{N} : {moduleCode} ({fileCount} fichiers, {brCount} BRs mappées)"
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
#### 7b. Generate seedDataCore (MANDATORY for master feature.json)
|
|
459
|
-
|
|
460
|
-
> **Reference:** Load `references/handoff-seeddata-generation.md` for complete seedDataCore generation logic.
|
|
461
|
-
|
|
462
|
-
**The seedDataCore provides ralph-loop with the exact navigation, permissions, and translations to seed.**
|
|
463
|
-
Without seedDataCore, ralph-loop must INVENT this data — leading to inconsistencies.
|
|
464
|
-
|
|
465
|
-
The reference includes:
|
|
466
|
-
- Helper functions (toHumanReadable, toKebabCase)
|
|
467
|
-
- Complete seedDataCore template with all 9 arrays
|
|
468
|
-
- Icon inference for application and module levels
|
|
469
|
-
- POST-CHECK validation rules (BLOCKING for icons/application, warning for counts)
|
|
470
|
-
|
|
471
|
-
Key points:
|
|
472
|
-
- Icons must NEVER be null (use fallback if not inferred)
|
|
473
|
-
- All 9 seedDataCore arrays must be present (even if empty for multi-module scenarios)
|
|
474
|
-
- PROJECT MODE: Generate one entry per application from project feature.json
|
|
475
|
-
- SINGLE-APP MODE: Generate one entry from master feature.json
|
|
476
|
-
|
|
477
|
-
```
|
|
478
|
-
// Derive seedDataCore from modules[], applicationRoles[], and coverageMatrix[]
|
|
479
|
-
|
|
480
|
-
// Helper: PascalCase → "Human Readable" (e.g., "HumanResources" → "Human Resources")
|
|
481
|
-
function toHumanReadable(pascalCase) {
|
|
482
|
-
return pascalCase
|
|
483
|
-
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
484
|
-
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2');
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
const appCode = master.metadata.application;
|
|
488
|
-
const appLabel = toHumanReadable(appCode);
|
|
489
|
-
const appDesc = master.cadrage?.problem?.split('.')[0] || `Gestion ${appLabel}`;
|
|
490
|
-
const lang = master.metadata.language || "fr";
|
|
491
|
-
|
|
492
|
-
const seedDataCore = {
|
|
493
|
-
// Application-level navigation (MANDATORY — one entry per application)
|
|
494
|
-
// PROJECT MODE: Generate one entry per application from project feature.json
|
|
495
|
-
// SINGLE-APP MODE: Generate one entry from master feature.json
|
|
496
|
-
navigationApplications: (() => {
|
|
497
|
-
if (workflow.mode === "project") {
|
|
498
|
-
// Multi-app: one navigation entry per application
|
|
499
|
-
return projectFeature.applications.map((app, idx) => {
|
|
500
|
-
const appLabel = toHumanReadable(app.code);
|
|
501
|
-
return {
|
|
502
|
-
code: app.code.toLowerCase(),
|
|
503
|
-
name: app.code,
|
|
504
|
-
labels: {
|
|
505
|
-
fr: lang === "fr" ? (app.name || appLabel) : appLabel,
|
|
506
|
-
en: lang === "en" ? (app.name || appLabel) : appLabel,
|
|
507
|
-
it: appLabel,
|
|
508
|
-
de: appLabel
|
|
509
|
-
},
|
|
510
|
-
description: {
|
|
511
|
-
fr: lang === "fr" ? (app.description || `Gestion ${appLabel}`) : `Gestion ${appLabel}`,
|
|
512
|
-
en: lang === "en" ? (app.description || `${appLabel} management`) : `${appLabel} management`,
|
|
513
|
-
it: `Gestione ${appLabel}`,
|
|
514
|
-
de: `${appLabel} Verwaltung`
|
|
515
|
-
},
|
|
516
|
-
icon: app.icon || inferIconFromApplication({ metadata: { application: app.code } }) || "layout-grid",
|
|
517
|
-
iconType: "lucide",
|
|
518
|
-
route: `/${toKebabCase(app.code)}`,
|
|
519
|
-
displayOrder: (idx + 1) * 10
|
|
520
|
-
};
|
|
521
|
-
});
|
|
522
|
-
} else {
|
|
523
|
-
// Single-app: one navigation entry
|
|
524
|
-
return [{
|
|
525
|
-
code: appCode.toLowerCase(),
|
|
526
|
-
name: appCode,
|
|
527
|
-
labels: {
|
|
528
|
-
fr: lang === "fr" ? (master.cadrage?.applicationName || appLabel) : appLabel,
|
|
529
|
-
en: lang === "en" ? (master.cadrage?.applicationName || appLabel) : appLabel,
|
|
530
|
-
it: appLabel,
|
|
531
|
-
de: appLabel
|
|
532
|
-
},
|
|
533
|
-
description: {
|
|
534
|
-
fr: lang === "fr" ? appDesc : `Gestion ${appLabel}`,
|
|
535
|
-
en: lang === "en" ? appDesc : `${appLabel} management`,
|
|
536
|
-
it: `Gestione ${appLabel}`,
|
|
537
|
-
de: `${appLabel} Verwaltung`
|
|
538
|
-
},
|
|
539
|
-
icon: inferIconFromApplication(master) || "layout-grid",
|
|
540
|
-
iconType: "lucide",
|
|
541
|
-
route: `/${toKebabCase(appCode)}`,
|
|
542
|
-
displayOrder: 1
|
|
543
|
-
}];
|
|
544
|
-
}
|
|
545
|
-
})(),
|
|
546
|
-
|
|
547
|
-
// PROJECT MODE: Flatten modules from ALL applications
|
|
548
|
-
// SINGLE-APP MODE: Use master.modules directly
|
|
549
|
-
navigationModules: (() => {
|
|
550
|
-
if (workflow.mode === "project") {
|
|
551
|
-
let order = 0;
|
|
552
|
-
return projectFeature.applications.flatMap(app => {
|
|
553
|
-
return (app.modules || []).map(m => ({
|
|
554
|
-
code: m.code,
|
|
555
|
-
applicationCode: app.code,
|
|
556
|
-
label: m.name || m.code,
|
|
557
|
-
description: m.description,
|
|
558
|
-
icon: inferIconFromModule(m) || "folder",
|
|
559
|
-
iconType: "lucide",
|
|
560
|
-
route: `/${toKebabCase(app.code)}/${toKebabCase(m.code)}`,
|
|
561
|
-
displayOrder: (++order) * 10
|
|
562
|
-
}));
|
|
563
|
-
});
|
|
564
|
-
} else {
|
|
565
|
-
return master.modules.map((m, i) => ({
|
|
566
|
-
code: m.code,
|
|
567
|
-
label: m.name || m.code,
|
|
568
|
-
description: m.description,
|
|
569
|
-
icon: inferIconFromModule(m) || "folder",
|
|
570
|
-
iconType: "lucide",
|
|
571
|
-
route: `/${toKebabCase(appCode)}/${toKebabCase(m.code)}`,
|
|
572
|
-
displayOrder: (i + 1) * 10
|
|
573
|
-
}));
|
|
574
|
-
}
|
|
575
|
-
})(),
|
|
576
|
-
|
|
577
|
-
navigationSections: (() => {
|
|
578
|
-
const buildSections = (modules, appCode) =>
|
|
579
|
-
modules.flatMap(m =>
|
|
580
|
-
(m.anticipatedSections || []).map((s, j) => ({
|
|
581
|
-
moduleCode: m.code,
|
|
582
|
-
code: s.code,
|
|
583
|
-
label: s.description?.split(':')[0] || s.code,
|
|
584
|
-
description: s.description || "",
|
|
585
|
-
route: s.code === "list"
|
|
586
|
-
? `/${toKebabCase(appCode)}/${toKebabCase(m.code)}`
|
|
587
|
-
: s.code === "detail"
|
|
588
|
-
? `/${toKebabCase(appCode)}/${toKebabCase(m.code)}/:id`
|
|
589
|
-
: `/${toKebabCase(appCode)}/${toKebabCase(m.code)}/${toKebabCase(s.code)}`,
|
|
590
|
-
displayOrder: (j + 1) * 10,
|
|
591
|
-
navigation: s.code === "detail" ? "hidden" : "visible"
|
|
592
|
-
}))
|
|
593
|
-
);
|
|
594
|
-
|
|
595
|
-
if (workflow.mode === "project") {
|
|
596
|
-
return projectFeature.applications.flatMap(app =>
|
|
597
|
-
buildSections(app.modules || [], app.code)
|
|
598
|
-
);
|
|
599
|
-
} else {
|
|
600
|
-
return buildSections(master.modules, appCode);
|
|
601
|
-
}
|
|
602
|
-
})(),
|
|
603
|
-
|
|
604
|
-
navigationResources: master.cadrage.coverageMatrix
|
|
605
|
-
.filter(cm => cm.module && cm.anticipatedResources?.length > 0)
|
|
606
|
-
.flatMap(cm =>
|
|
607
|
-
cm.anticipatedResources.map((r, k) => ({
|
|
608
|
-
moduleCode: cm.module,
|
|
609
|
-
sectionCode: cm.anticipatedSections?.[0] || "list",
|
|
610
|
-
code: r,
|
|
611
|
-
label: r.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
|
|
612
|
-
displayOrder: (k + 1) * 10
|
|
613
|
-
}))
|
|
614
|
-
),
|
|
615
|
-
|
|
616
|
-
navigationTranslations: master.modules.flatMap(m => {
|
|
617
|
-
const langs = ["fr", "en", "it", "de"]; // all supported languages
|
|
618
|
-
return langs.map(lang => ({
|
|
619
|
-
moduleCode: m.code,
|
|
620
|
-
language: lang,
|
|
621
|
-
label: lang === master.metadata.language ? (m.name || m.code) : m.code,
|
|
622
|
-
description: lang === master.metadata.language ? m.description : ""
|
|
623
|
-
}));
|
|
624
|
-
}),
|
|
625
|
-
|
|
626
|
-
// PROJECT MODE: permissions scoped per application context
|
|
627
|
-
// SINGLE-APP MODE: all permissions under {app}
|
|
628
|
-
permissions: (() => {
|
|
629
|
-
const buildPermissions = (modules, appCode) =>
|
|
630
|
-
modules.flatMap(m => {
|
|
631
|
-
const basePath = `${toKebabCase(appCode)}.${toKebabCase(m.code)}`;
|
|
632
|
-
const actions = ['read', 'create', 'update', 'delete'];
|
|
633
|
-
return [
|
|
634
|
-
{ path: `${basePath}.*`, action: '*', description: `Full ${m.name || m.code} access` },
|
|
635
|
-
...actions.map(action => ({
|
|
636
|
-
path: `${basePath}.${action}`,
|
|
637
|
-
action: action,
|
|
638
|
-
description: `${action.charAt(0).toUpperCase() + action.slice(1)} ${m.name || m.code}`
|
|
639
|
-
}))
|
|
640
|
-
];
|
|
641
|
-
});
|
|
642
|
-
|
|
643
|
-
if (workflow.mode === "project") {
|
|
644
|
-
return projectFeature.applications.flatMap(app =>
|
|
645
|
-
buildPermissions(app.modules || [], app.code)
|
|
646
|
-
);
|
|
647
|
-
} else {
|
|
648
|
-
return buildPermissions(master.modules, appCode);
|
|
649
|
-
}
|
|
650
|
-
})(),
|
|
651
|
-
|
|
652
|
-
rolePermissions: (() => {
|
|
653
|
-
const buildRolePermissions = (roles, modules, appCode) =>
|
|
654
|
-
roles.map(role => ({
|
|
655
|
-
role: role.role,
|
|
656
|
-
level: role.level,
|
|
657
|
-
permissions: modules.map(m => `${toKebabCase(appCode)}.${toKebabCase(m.code)}.${
|
|
658
|
-
role.level === 'admin' ? '*' :
|
|
659
|
-
role.level === 'manager' ? 'read,create,update' :
|
|
660
|
-
role.level === 'contributor' ? 'read,create' : 'read'
|
|
661
|
-
}`)
|
|
662
|
-
}));
|
|
663
|
-
|
|
664
|
-
if (workflow.mode === "project") {
|
|
665
|
-
return projectFeature.applications.flatMap(app =>
|
|
666
|
-
buildRolePermissions(app.applicationRoles || [], app.modules || [], app.code)
|
|
667
|
-
);
|
|
668
|
-
} else {
|
|
669
|
-
return buildRolePermissions(master.cadrage.applicationRoles, master.modules, appCode);
|
|
670
|
-
}
|
|
671
|
-
})(),
|
|
672
|
-
|
|
673
|
-
permissionConstants: (() => {
|
|
674
|
-
const buildConstants = (modules, appCode) =>
|
|
675
|
-
modules.flatMap(m =>
|
|
676
|
-
['Read', 'Create', 'Update', 'Delete', 'Validate', 'Export'].map(action => ({
|
|
677
|
-
module: m.code,
|
|
678
|
-
application: appCode,
|
|
679
|
-
action: action,
|
|
680
|
-
constant: `${appCode}${m.code}${action}`,
|
|
681
|
-
path: `${toKebabCase(appCode)}.${toKebabCase(m.code)}.${action.toLowerCase()}`
|
|
682
|
-
}))
|
|
683
|
-
);
|
|
684
|
-
|
|
685
|
-
if (workflow.mode === "project") {
|
|
686
|
-
return projectFeature.applications.flatMap(app =>
|
|
687
|
-
buildConstants(app.modules || [], app.code)
|
|
688
|
-
);
|
|
689
|
-
} else {
|
|
690
|
-
return buildConstants(master.modules, appCode);
|
|
691
|
-
}
|
|
692
|
-
})()
|
|
693
|
-
};
|
|
694
|
-
|
|
695
|
-
// Icon inference functions are defined in the reference
|
|
696
|
-
// inferIconFromApplication(master) - Application level icons
|
|
697
|
-
// inferIconFromModule(module) - Module level icons
|
|
698
|
-
// See references/handoff-seeddata-generation.md for complete implementation
|
|
699
|
-
|
|
700
|
-
ba-writer.enrichSection({
|
|
701
|
-
featureId: {feature_id},
|
|
702
|
-
section: "seedDataCore",
|
|
703
|
-
data: seedDataCore
|
|
704
|
-
})
|
|
705
|
-
```
|
|
706
|
-
|
|
707
|
-
**POST-CHECK (BLOCKING for icons/application, warning for counts):**
|
|
708
|
-
```
|
|
709
|
-
IF !seedDataCore.navigationApplications || seedDataCore.navigationApplications.length === 0:
|
|
710
|
-
BLOCKING ERROR: "navigationApplications is empty — Application navigation will NOT be seeded. Menu will show (nothing) → Modules."
|
|
711
|
-
IF seedDataCore.navigationApplications[0].icon === null || seedDataCore.navigationApplications[0].icon === undefined:
|
|
712
|
-
BLOCKING ERROR: "Application icon is null — ralph-loop will render empty navigation"
|
|
713
|
-
IF !seedDataCore.navigationApplications[0].labels?.fr || !seedDataCore.navigationApplications[0].labels?.en:
|
|
714
|
-
BLOCKING ERROR: "Application labels missing fr/en — translations will fail"
|
|
715
|
-
IF seedDataCore.navigationModules.length !== master.modules.length:
|
|
716
|
-
WARNING: seedDataCore has ${seedDataCore.navigationModules.length} nav modules but ${master.modules.length} modules exist
|
|
717
|
-
IF seedDataCore.permissions.length === 0:
|
|
718
|
-
WARNING: seedDataCore has 0 permissions — applicationRoles may be missing
|
|
719
|
-
IF seedDataCore.navigationModules.some(m => !m.icon || m.icon === null):
|
|
720
|
-
BLOCKING ERROR: "Navigation modules with null icons detected — ralph-loop will render empty navigation"
|
|
721
|
-
→ Fix: Re-run inferIconFromModule() for modules with null icons
|
|
722
|
-
IF seedDataCore.navigationSections.length === 0:
|
|
723
|
-
WARNING: "0 navigation sections — every module should have at least 1 section (e.g., 'list')"
|
|
724
|
-
```
|
|
725
|
-
|
|
726
|
-
#### 7c. Master Handoff (after ALL modules written + seedDataCore generated)
|
|
727
|
-
|
|
728
|
-
```
|
|
729
|
-
// Write handoff to application-level feature.json (single-app mode)
|
|
730
|
-
// OR to each application feature.json + project feature.json (project mode)
|
|
731
|
-
|
|
732
|
-
IF workflow.mode === "project":
|
|
733
|
-
// Write handoff to EACH application feature.json
|
|
734
|
-
FOR each app in projectFeature.applications:
|
|
735
|
-
ba-writer.enrichSection({
|
|
736
|
-
featureId: app.featureJsonPath,
|
|
737
|
-
section: "handoff",
|
|
738
|
-
data: {
|
|
739
|
-
status: "handed-off",
|
|
740
|
-
complexity: "{app-level complexity}",
|
|
741
|
-
implementationStrategy: "{strategy}",
|
|
742
|
-
moduleCount: app.modules.length,
|
|
743
|
-
moduleOrder: app.modules.map(m => m.code),
|
|
744
|
-
totalFilesToCreate: {sum across app modules},
|
|
745
|
-
totalTasks: {sum across app modules},
|
|
746
|
-
prdFiles: app.modules.map(m => ({ module: m.code, path: `.ralph/prd-${m.code}.json` })),
|
|
747
|
-
handedOffAt: "{ISO timestamp}"
|
|
748
|
-
}
|
|
749
|
-
})
|
|
750
|
-
|
|
751
|
-
// Write project-level handoff summary
|
|
752
|
-
ba-writer.enrichSection({
|
|
753
|
-
featureId: {project_id},
|
|
754
|
-
section: "handoff",
|
|
755
|
-
data: {
|
|
756
|
-
status: "handed-off",
|
|
757
|
-
complexity: "{global complexity}",
|
|
758
|
-
implementationStrategy: "{strategy}",
|
|
759
|
-
applicationCount: projectFeature.applications.length,
|
|
760
|
-
applicationOrder: projectFeature.applicationDependencyGraph.topologicalOrder,
|
|
761
|
-
totalModuleCount: {sum of all app module counts},
|
|
762
|
-
totalFilesToCreate: {sum across ALL applications and modules},
|
|
763
|
-
totalTasks: {sum across ALL applications and modules},
|
|
764
|
-
prdStructure: "per-module",
|
|
765
|
-
prdFiles: [
|
|
766
|
-
...allModulePrdFiles,
|
|
767
|
-
{ module: "CrossModule", path: ".ralph/prd-CrossModule.json" },
|
|
768
|
-
{ module: "CrossApplication", path: ".ralph/prd-CrossApplication.json" }
|
|
769
|
-
],
|
|
770
|
-
progressTrackerPath: ".ralph/progress.txt",
|
|
771
|
-
handedOffAt: "{ISO timestamp}"
|
|
772
|
-
}
|
|
773
|
-
})
|
|
774
|
-
ELSE:
|
|
775
|
-
ba-writer.enrichSection({
|
|
776
|
-
featureId: {feature_id},
|
|
777
|
-
section: "handoff",
|
|
778
|
-
data: {
|
|
779
|
-
status: "handed-off",
|
|
780
|
-
complexity: "{simple|medium|complex}",
|
|
781
|
-
implementationStrategy: "{strategy}",
|
|
782
|
-
moduleCount: {count},
|
|
783
|
-
moduleOrder: [...],
|
|
784
|
-
totalFilesToCreate: {sum across all modules},
|
|
785
|
-
totalTasks: {sum across all modules},
|
|
786
|
-
prdStructure: "per-module | consolidated",
|
|
787
|
-
prdFiles: [
|
|
788
|
-
{ module: "{module1}", path: ".ralph/prd-{module1}.json" },
|
|
789
|
-
{ module: "{module2}", path: ".ralph/prd-{module2}.json" }
|
|
790
|
-
],
|
|
791
|
-
progressTrackerPath: ".ralph/progress.txt",
|
|
792
|
-
handedOffAt: "{ISO timestamp}"
|
|
793
|
-
}
|
|
794
|
-
})
|
|
795
|
-
```
|
|
796
|
-
|
|
797
|
-
#### 7d. Final Verification (BLOCKING)
|
|
798
|
-
|
|
799
|
-
```
|
|
800
|
-
count = 0
|
|
801
|
-
FOR each module in modules[]:
|
|
802
|
-
Read module feature.json
|
|
803
|
-
IF module.handoff !== {} AND module.status === "handed-off":
|
|
804
|
-
count++
|
|
805
|
-
|
|
806
|
-
IF count < modules.length:
|
|
807
|
-
→ BLOCKING ERROR: {modules.length - count} modules missing handoff
|
|
808
|
-
→ List the missing modules by name
|
|
809
|
-
→ DO NOT proceed to step-05b
|
|
810
|
-
→ Return to 7a for missing modules only
|
|
811
|
-
|
|
812
|
-
IF count === modules.length:
|
|
813
|
-
ba-writer.updateStatus({feature_id}, "handed-off")
|
|
814
|
-
Display: "✓ Handoff complet: {count}/{modules.length} modules avec handoff valide"
|
|
815
|
-
```
|
|
816
|
-
|
|
817
|
-
Status journey: analyze → consolidate → handed-off
|
|
818
|
-
|
|
819
|
-
---
|
|
820
|
-
|
|
821
|
-
## SELF-VERIFICATION
|
|
822
|
-
|
|
823
|
-
Before proceeding to step-05b-deploy.md, VERIFY:
|
|
824
|
-
|
|
825
|
-
1. **filesToCreate** has all 7 categories populated (domain, application, infrastructure, api, frontend, seedData, tests) for each module
|
|
826
|
-
2. **Complexity** calculated for all modules
|
|
827
|
-
3. **Implementation strategy** chosen (for multi-module features)
|
|
828
|
-
4. **ALL module feature.json** have `handoff.brToCodeMapping.length > 0`
|
|
829
|
-
5. **ALL module feature.json** have `handoff.apiEndpointSummary.length > 0`
|
|
830
|
-
6. **ALL module feature.json** status = "handed-off"
|
|
831
|
-
7. **Master feature.json** has `handoff` section with implementationStrategy, moduleOrder, totalFilesToCreate
|
|
832
|
-
8. **Master status** = "handed-off"
|
|
833
|
-
|
|
834
|
-
**IF any check fails → FIX before proceeding.**
|
|
835
|
-
|
|
836
|
-
---
|
|
837
|
-
|
|
838
|
-
## NEXT STEP
|
|
839
|
-
|
|
840
|
-
Load: `steps/step-05b-deploy.md`
|
|
1
|
+
---
|
|
2
|
+
name: step-05a-handoff
|
|
3
|
+
description: Build development handoff data, map business rules to code, write handoff to feature.json
|
|
4
|
+
model: sonnet
|
|
5
|
+
next_step: steps/step-05b-deploy.md
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
> **Context files:** `_shared.md` | `_architecture.md`
|
|
9
|
+
|
|
10
|
+
# Step 5a: Handoff - Build & Write
|
|
11
|
+
|
|
12
|
+
## MANDATORY EXECUTION RULES
|
|
13
|
+
|
|
14
|
+
- **ALWAYS** verify status = "consolidated" before proceeding
|
|
15
|
+
- **ALWAYS** ask user for implementation strategy preference (multi-module only)
|
|
16
|
+
- **ALWAYS** derive prd.json from feature.json (NEVER independently)
|
|
17
|
+
- **NEVER** invent entities/FRs/BRs not in feature.json
|
|
18
|
+
- **ALL** API routes from specification.apiEndpoints (exact copy)
|
|
19
|
+
- **Permission** paths from specification.permissionMatrix (full format)
|
|
20
|
+
- **ALWAYS** generate CORE SeedData entries: 2 app-level (NavigationApplication + ApplicationRoles) + per module (NavigationModule + NavigationSections + Permissions + Roles)
|
|
21
|
+
|
|
22
|
+
## YOUR TASK
|
|
23
|
+
|
|
24
|
+
Build the development handoff data: verify consolidation, choose implementation strategy, calculate complexity, map specification to files (7 categories), map business rules to code, generate API endpoint summary, and write handoff to EACH module feature.json.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## EXECUTION SEQUENCE
|
|
29
|
+
|
|
30
|
+
### 1. Verify Consolidation Passed
|
|
31
|
+
|
|
32
|
+
Use ba-reader to locate the feature and verify consolidation status:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
// Determine feature source based on workflow mode
|
|
36
|
+
IF workflow.mode === "project":
|
|
37
|
+
projectFeature = ba-reader.findProjectFeature()
|
|
38
|
+
// Verify ALL applications are specified
|
|
39
|
+
FOR each app in projectFeature.applications:
|
|
40
|
+
appFeature = ba-reader.findFeature(app.featureJsonPath)
|
|
41
|
+
IF appFeature.status !== "consolidated":
|
|
42
|
+
BLOCKING ERROR: "Application {app.code} not consolidated (status: {appFeature.status})"
|
|
43
|
+
→ Return to step-04a-collect.md
|
|
44
|
+
// Use project-level feature for overall consolidation
|
|
45
|
+
feature = projectFeature
|
|
46
|
+
ELSE:
|
|
47
|
+
ba-reader.findFeature({feature_id})
|
|
48
|
+
→ Check status = "consolidated"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**IF** status ≠ "consolidated" → **STOP**. Return to step-04a-collect.md.
|
|
52
|
+
|
|
53
|
+
Display validation summary:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
✓ Consolidation: APPROVED
|
|
57
|
+
✓ Applications: {app_count} (project mode only)
|
|
58
|
+
✓ Modules: {count} specified and validated
|
|
59
|
+
✓ Cross-module: interactions mapped
|
|
60
|
+
✓ Cross-application: interactions mapped (project mode only)
|
|
61
|
+
✓ Permissions: coherent
|
|
62
|
+
→ Proceeding to handoff...
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Include:
|
|
66
|
+
- Number of applications (project mode only)
|
|
67
|
+
- Number of modules across all applications
|
|
68
|
+
- Number of entities across all modules
|
|
69
|
+
- Number of use cases across all modules
|
|
70
|
+
- Number of business rules across all modules
|
|
71
|
+
- Cross-module interaction count
|
|
72
|
+
- Cross-application interaction count (project mode only)
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### 1b. Cache Warming for Handoff & Deploy
|
|
77
|
+
|
|
78
|
+
> **Performance Optimization:** Pre-load handoff templates and references to reduce redundant reads during handoff generation.
|
|
79
|
+
> This step runs ONCE at start of step-05a, files retained through step-05b.
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
// Pre-load handoff & deploy references (Bucket 5)
|
|
83
|
+
const handoffRefs = [
|
|
84
|
+
"~/.claude/skills/business-analyse/references/handoff-file-templates.md",
|
|
85
|
+
"~/.claude/skills/business-analyse/references/handoff-mappings.md",
|
|
86
|
+
"~/.claude/skills/business-analyse/references/deploy-data-build.md",
|
|
87
|
+
"~/.claude/skills/business-analyse/references/deploy-modes.md",
|
|
88
|
+
"~/.claude/skills/business-analyse/references/html-data-mapping.md"
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
for (const file of handoffRefs) {
|
|
92
|
+
read(file); // Pre-load into cache
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Pre-load HTML template (large file, loaded once)
|
|
96
|
+
read("~/.claude/skills/business-analyse/html/ba-interactive.html");
|
|
97
|
+
|
|
98
|
+
Display: "✓ Cache warmed: handoff templates (139KB, 6 files)"
|
|
99
|
+
Display: " Expected token savings: ~3,000 tokens (handoff refs read 2× → 1×)"
|
|
100
|
+
Display: " Retention: through step-05b (deploy)"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Rationale:**
|
|
104
|
+
|
|
105
|
+
- Handoff templates are read 2× during step-05a + step-05b (without caching)
|
|
106
|
+
- HTML template (85KB) is read once but benefits from explicit pre-load (faster deploy)
|
|
107
|
+
- Token savings: ~3,000 tokens for handoff process
|
|
108
|
+
- Cache retained until session end (needed for both handoff and deploy steps)
|
|
109
|
+
|
|
110
|
+
**Why NOT loaded at step-00:**
|
|
111
|
+
- Large files (139KB total), especially ba-interactive.html (85KB)
|
|
112
|
+
- Only used at END of workflow (steps 05a, 05b)
|
|
113
|
+
- Low re-use (1-2× each)
|
|
114
|
+
- Loading at step-05a is more efficient (just-in-time caching)
|
|
115
|
+
|
|
116
|
+
See [references/cache-warming-strategy.md](../references/cache-warming-strategy.md) § Bucket 5 for details.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
### 2. Implementation Strategy Choice (Multi-Module/Multi-App)
|
|
121
|
+
|
|
122
|
+
**IF** more than 1 module defined in feature.json (or project mode with multiple applications):
|
|
123
|
+
|
|
124
|
+
Ask via AskUserQuestion:
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
question: "Quelle stratégie d'implémentation préférez-vous ?"
|
|
128
|
+
header: "Stratégie d'implémentation"
|
|
129
|
+
options:
|
|
130
|
+
- label: "Module par module (Recommandé)"
|
|
131
|
+
description: "Implémenter chaque module complètement avant de passer au suivant. Suit l'ordre topologique des dépendances."
|
|
132
|
+
- label: "Couche par couche"
|
|
133
|
+
description: "Implémenter toutes les entités, puis tous les services, puis tous les contrôleurs, etc. Plus de parallélisation possible mais plus complexe."
|
|
134
|
+
- label: "Hybride"
|
|
135
|
+
description: "Modules fondation en premier (couche par couche), puis modules dépendants (module par module)"
|
|
136
|
+
- label: "Application par application (Recommandé multi-app)"
|
|
137
|
+
description: "Implémenter chaque application complètement avant de passer à la suivante. Suit l'ordre topologique inter-applications."
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
> **Note:** "Application par application" only appears for project mode with 2+ applications.
|
|
141
|
+
|
|
142
|
+
Store the chosen strategy in `handoff.implementationStrategy`.
|
|
143
|
+
|
|
144
|
+
**IF** only 1 module → default to "Module par module" (no choice needed).
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### 3. Calculate Complexity
|
|
149
|
+
|
|
150
|
+
For each module in feature.json.modules[], calculate:
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"complexity": "simple|medium|complex",
|
|
155
|
+
"complexityDetails": {
|
|
156
|
+
"entities": {count},
|
|
157
|
+
"useCases": {count},
|
|
158
|
+
"businessRules": {count},
|
|
159
|
+
"calculated": "{level} (≤X entities, ≤Y UCs, ≤Z BRs)"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
| Criteria | Simple | Medium | Complex |
|
|
165
|
+
|----------|--------|--------|---------|
|
|
166
|
+
| Entities | ≤3 | ≤6 | >6 |
|
|
167
|
+
| Use Cases | ≤5 | ≤12 | >12 |
|
|
168
|
+
| Business Rules | ≤10 | ≤20 | >20 |
|
|
169
|
+
|
|
170
|
+
**Global complexity** = highest complexity across all modules.
|
|
171
|
+
|
|
172
|
+
Example:
|
|
173
|
+
- Module A: 4 entities, 6 use cases, 8 BRs → **simple**
|
|
174
|
+
- Module B: 8 entities, 15 use cases, 25 BRs → **complex**
|
|
175
|
+
- Overall: **complex**
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
### 4. Map Specification to Files
|
|
180
|
+
|
|
181
|
+
> **IMPORTANT:** Generate `handoff.filesToCreate` as structured object with 7 categories.
|
|
182
|
+
> Each file entry is `{path, type, linkedFRs, linkedUCs, module}`. NO free text.
|
|
183
|
+
> Read `.smartstack/config.json` to extract baseNamespace for project namespace.
|
|
184
|
+
|
|
185
|
+
**Order by topological dependency** (modules with no deps first, then dependents).
|
|
186
|
+
|
|
187
|
+
For **EACH module** in topological order:
|
|
188
|
+
|
|
189
|
+
> **PATH HIERARCHY CONVENTION:** All backend file paths MUST include the application hierarchy.
|
|
190
|
+
> Derive from module feature.json metadata:
|
|
191
|
+
> - `{ApplicationName}` = `metadata.application` (e.g., `"HumanResources"`)
|
|
192
|
+
> - `{ModuleName}` = `metadata.module` (e.g., `"Projects"`)
|
|
193
|
+
>
|
|
194
|
+
> **Example** for application=HumanResources, module=Projects:
|
|
195
|
+
> - Domain: `src/Domain/Entities/HumanResources/Projects/Project.cs`
|
|
196
|
+
> - Application: `src/Application/Services/HumanResources/Projects/ProjectService.cs`
|
|
197
|
+
> - Infrastructure: `src/Infrastructure/Persistence/Configurations/HumanResources/Projects/ProjectConfiguration.cs`
|
|
198
|
+
> - API: `src/API/Controllers/HumanResources/ProjectsController.cs`
|
|
199
|
+
> - Tests: `src/Tests/Unit/Domain/HumanResources/Projects/ProjectTests.cs`
|
|
200
|
+
|
|
201
|
+
#### 4.1-4.7 File Category Templates
|
|
202
|
+
|
|
203
|
+
See [references/handoff-file-templates.md](../references/handoff-file-templates.md) for the complete JSON templates for all 7 categories:
|
|
204
|
+
|
|
205
|
+
| Category | Source | Key rules |
|
|
206
|
+
|----------|--------|-----------|
|
|
207
|
+
| **4.1 Domain** | `analysis.entities[]` | Entities, ValueObjects, Enums, Exceptions |
|
|
208
|
+
| **4.2 Application** | `analysis.useCases[]` | Services, DTOs, Validators |
|
|
209
|
+
| **4.3 Infrastructure** | `analysis.entities[]` | EF Configurations, DbSet, DI. **DEPENDENCY:** Each EF config task MUST `dependsOn` its corresponding domain entity task. |
|
|
210
|
+
| **4.4 API** | `specification.apiEndpoints[]` | Controllers |
|
|
211
|
+
| **4.5 Frontend** | `specification.uiWireframes[]` | Pages, Components, Hooks + wireframe traceability |
|
|
212
|
+
| **4.6 SeedData** | `specification.seedDataCore` | 2 app-level + per module CORE (NavigationModule + NavigationSections + Permissions + Roles) + business + IClientSeedDataProvider |
|
|
213
|
+
| **4.7 Tests** | All layers | Unit, Integration, Security tests |
|
|
214
|
+
|
|
215
|
+
#### Route Convention (CRITICAL)
|
|
216
|
+
|
|
217
|
+
> **MANDATORY:** All NavigationModule/Section routes MUST use kebab-case transformation.
|
|
218
|
+
> See [references/naming-conventions.md](../references/naming-conventions.md) for complete guide.
|
|
219
|
+
|
|
220
|
+
**Problem:**
|
|
221
|
+
- Module codes in feature.json are **PascalCase** (e.g., `"HumanResources"`)
|
|
222
|
+
- Routes in seed data MUST be **kebab-case** (e.g., `"/human-resources"`)
|
|
223
|
+
- Failing to transform causes 404 when clicking menu items
|
|
224
|
+
|
|
225
|
+
**Solution:**
|
|
226
|
+
|
|
227
|
+
When generating `seedDataCore` for handoff, transform PascalCase codes to kebab-case routes:
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
// Transform module codes to kebab-case routes
|
|
231
|
+
function toKebabCase(code) {
|
|
232
|
+
return code
|
|
233
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
234
|
+
.toLowerCase();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Example usage in seedDataCore generation
|
|
238
|
+
const moduleCode = "TimeManagement"; // PascalCase (C#)
|
|
239
|
+
const appCode = "HumanResources"; // PascalCase (C#)
|
|
240
|
+
|
|
241
|
+
const route = `/${toKebabCase(appCode)}/${toKebabCase(moduleCode)}`;
|
|
242
|
+
// Result: "/human-resources/time-management"
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Validation:** All kebab-case routes in seed data MUST NOT include `/business/` prefix.
|
|
246
|
+
|
|
247
|
+
Example in NavigationModule:
|
|
248
|
+
```csharp
|
|
249
|
+
route = "/human-resources"; // ✓ Correct (kebab-case module code only)
|
|
250
|
+
route = "/business/human-resources"; // ✗ WRONG (contains /business/)
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Include in task instructions:**
|
|
254
|
+
|
|
255
|
+
For NavigationSeedData tasks in `handoff.filesToCreate`, add:
|
|
256
|
+
|
|
257
|
+
```json
|
|
258
|
+
{
|
|
259
|
+
"path": "Infrastructure/Persistence/Seeding/Data/{Module}/NavigationSeedData.cs",
|
|
260
|
+
"type": "SeedData",
|
|
261
|
+
"category": "core",
|
|
262
|
+
"instructions": "Generate NavigationModule seed data. CRITICAL: Use ToKebabCase() helper for Route property. Example: Route = ToKebabCase($\"/{app}/{module}\"). See core-seed-data.md template."
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Validation:**
|
|
267
|
+
- ralph-loop POST-CHECK validates routes after generation (see step-02-execute.md)
|
|
268
|
+
- MCP `validate_frontend_routes` detects case mismatches
|
|
269
|
+
- Convention documented in naming-conventions.md
|
|
270
|
+
|
|
271
|
+
**Critical rules:**
|
|
272
|
+
- All backend paths include `{ApplicationName}/` hierarchy
|
|
273
|
+
- Frontend pages MUST have `linkedWireframes[]` + `wireframeAcceptanceCriteria`
|
|
274
|
+
- SeedData: 2 app-level CORE (NavigationApplication + ApplicationRoles) + per-module CORE (NavigationModule + NavigationSections + Permissions + Roles) + IClientSeedDataProvider for client projects
|
|
275
|
+
- **Acceptance Criteria Mapping:** Each task's `acceptanceCriteria` MUST be derived from its own `linkedFRs[]` entries (lookup FR → `acceptanceCriteria`). NEVER map by sequential FR index — use the task's explicit linkedFRs to resolve the correct criteria.
|
|
276
|
+
- Path convention: `Persistence/Seeding/Data/` (NEVER `Data/SeedData/`)
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
### 5. Map Business Rules to Code
|
|
281
|
+
|
|
282
|
+
See [references/handoff-mappings.md](../references/handoff-mappings.md) — Section "Business Rules to Code Mapping".
|
|
283
|
+
|
|
284
|
+
For each BR in `analysis.businessRules[]` of EACH module, generate:
|
|
285
|
+
- **ruleId**, **title**, **module**, **severity** (critical/high/medium/low)
|
|
286
|
+
- **implementationPoints**: Array of `{layer, component, method, implementation}` across Domain, Application, Infrastructure, API, Frontend
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
### 6. API Endpoint Summary
|
|
291
|
+
|
|
292
|
+
> **ABSOLUTE RULE:** Copy **EXACTLY** from `specification.apiEndpoints[]`. **NEVER** reinvent routes.
|
|
293
|
+
|
|
294
|
+
See [references/handoff-mappings.md](../references/handoff-mappings.md) — Section "API Endpoint Summary".
|
|
295
|
+
|
|
296
|
+
For each endpoint: operation, method, route, linkedUC, linkedFR, permissions, requestSchema, responseSchema, errorCodes, module.
|
|
297
|
+
|
|
298
|
+
Total endpoints = count of specification.apiEndpoints[] across all modules.
|
|
299
|
+
|
|
300
|
+
### 6b. Frontend Task Splitting (MANDATORY)
|
|
301
|
+
|
|
302
|
+
> **CRITICAL:** Frontend MUST be split into discrete tasks, NOT bundled as a single mega-task.
|
|
303
|
+
> A single mega-task covering 5-8 files prevents granular error recovery in ralph-loop.
|
|
304
|
+
|
|
305
|
+
For each module, generate these SEPARATE frontend file entries (not one monolithic entry):
|
|
306
|
+
|
|
307
|
+
```json
|
|
308
|
+
"frontend": [
|
|
309
|
+
{ "path": "src/pages/{App}/{Mod}/{ListPage}Page.tsx", "type": "Page", "linkedWireframes": ["{module}-list"], "module": "{moduleCode}", "skill": "/ui-components" },
|
|
310
|
+
{ "path": "src/pages/{App}/{Mod}/{Entity}CreatePage.tsx", "type": "Page", "linkedWireframes": ["{module}-create"], "module": "{moduleCode}", "skill": "/ui-components", "fkFields": ["EmployeeId→Employee", "DepartmentId→Department"] },
|
|
311
|
+
{ "path": "src/pages/{App}/{Mod}/{Entity}EditPage.tsx", "type": "Page", "linkedWireframes": ["{module}-edit"], "module": "{moduleCode}", "skill": "/ui-components", "fkFields": ["EmployeeId→Employee", "DepartmentId→Department"] },
|
|
312
|
+
{ "path": "src/pages/{App}/{Mod}/{DetailPage}Page.tsx", "type": "Page", "linkedWireframes": ["{module}-detail"], "module": "{moduleCode}", "skill": "/ui-components" },
|
|
313
|
+
{ "path": "src/hooks/use{Module}.ts", "type": "Hook", "module": "{moduleCode}" },
|
|
314
|
+
{ "path": "src/i18n/locales/fr/{moduleLower}.json", "type": "I18n", "language": "fr", "module": "{moduleCode}" },
|
|
315
|
+
{ "path": "src/i18n/locales/en/{moduleLower}.json", "type": "I18n", "language": "en", "module": "{moduleCode}" },
|
|
316
|
+
{ "path": "src/i18n/locales/it/{moduleLower}.json", "type": "I18n", "language": "it", "module": "{moduleCode}" },
|
|
317
|
+
{ "path": "src/i18n/locales/de/{moduleLower}.json", "type": "I18n", "language": "de", "module": "{moduleCode}" }
|
|
318
|
+
]
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**FK fields in forms:** Create/Edit page entries MUST include `"fkFields"` array listing FK properties and their target entities (format: `"PropertyId→TargetEntity"`). This tells ralph-loop to use `EntityLookup` component instead of plain text inputs. Derive FK fields from `analysis.entities[].relationships[]` where `type = "N:1"` or from properties ending in `Id` with a navigation property. See `smartstack-frontend.md` section 6 for the EntityLookup pattern.
|
|
322
|
+
|
|
323
|
+
**Page generation:** ALL pages MUST use `/ui-components` skill (indicated by `"skill"` field). NEVER write raw TSX without the skill patterns.
|
|
324
|
+
|
|
325
|
+
**I18n generation:** 4 JSON files per module with identical key structures. `{moduleLower}` = lowercase module code. Keys: actions, labels, columns, form, errors, validation, messages, empty. See `smartstack-frontend.md` template.
|
|
326
|
+
|
|
327
|
+
Additional per-section pages (dashboard, import, etc.) are separate entries.
|
|
328
|
+
|
|
329
|
+
**Route wiring task (MANDATORY — separate entry):**
|
|
330
|
+
```json
|
|
331
|
+
{ "path": "src/App.tsx", "type": "RouteWiring", "module": "{moduleCode}", "description": "Wire {module} routes into App.tsx application route block. BLOCKING: pages without route wiring = blank pages." }
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### 6c. Cross-Module PRD (MANDATORY for multi-module features)
|
|
335
|
+
|
|
336
|
+
> **CRITICAL:** Cross-module integration tasks MUST exist in a dedicated PRD file.
|
|
337
|
+
> Without this, ralph-loop will NOT execute E2E tests or FK validation.
|
|
338
|
+
|
|
339
|
+
Generate `.ralph/prd-CrossModule.json` with:
|
|
340
|
+
```json
|
|
341
|
+
{
|
|
342
|
+
"$version": "3.0.0",
|
|
343
|
+
"implementation": {
|
|
344
|
+
"filesToCreate": {
|
|
345
|
+
"tests": [
|
|
346
|
+
{ "path": "src/Tests/Integration/CrossModule/ForeignKeyValidationTests.cs", "type": "IntegrationTests", "module": "CrossModule" },
|
|
347
|
+
{ "path": "src/Tests/Integration/CrossModule/PermissionMatrixTests.cs", "type": "SecurityTests", "module": "CrossModule" },
|
|
348
|
+
{ "path": "src/Tests/Integration/CrossModule/E2EFlowTests.cs", "type": "E2ETests", "module": "CrossModule" }
|
|
349
|
+
]
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Add to progress.txt after all module tasks.
|
|
356
|
+
|
|
357
|
+
### 6d. Cross-Application PRD (Project Mode Only)
|
|
358
|
+
|
|
359
|
+
> **Only generated when `workflow.mode === "project"`.**
|
|
360
|
+
> Contains cross-application integration tests and shared entity validation.
|
|
361
|
+
|
|
362
|
+
```json
|
|
363
|
+
{
|
|
364
|
+
"$version": "3.0.0",
|
|
365
|
+
"implementation": {
|
|
366
|
+
"filesToCreate": {
|
|
367
|
+
"tests": [
|
|
368
|
+
{ "path": "src/Tests/Integration/CrossApplication/SharedEntityValidationTests.cs", "type": "IntegrationTests", "module": "CrossApplication" },
|
|
369
|
+
{ "path": "src/Tests/Integration/CrossApplication/CrossAppPermissionTests.cs", "type": "SecurityTests", "module": "CrossApplication" },
|
|
370
|
+
{ "path": "src/Tests/Integration/CrossApplication/CrossAppE2EFlowTests.cs", "type": "E2ETests", "module": "CrossApplication" }
|
|
371
|
+
]
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Write to: `.ralph/prd-CrossApplication.json`
|
|
378
|
+
|
|
379
|
+
> This PRD is generated IN ADDITION to the per-module cross-module PRD.
|
|
380
|
+
> It validates interactions between applications, not just between modules within the same application.
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
### 7. Write Handoff to Feature.json
|
|
385
|
+
|
|
386
|
+
> **BLOCKING RULE: The handoff MUST be written in EACH module feature.json.**
|
|
387
|
+
> A handoff at master level alone is INSUFFICIENT. Ralph-loop consumes module-level handoffs.
|
|
388
|
+
> An empty module handoff (`"handoff": {}`) is a CRITICAL BUG that blocks all downstream generation.
|
|
389
|
+
|
|
390
|
+
#### 7a. Module Handoff Loop (MANDATORY)
|
|
391
|
+
|
|
392
|
+
> **STRUCTURE CARD: handoff** — Field names are EXACT. Include ALL fields below.
|
|
393
|
+
> **PATH RULE:** All backend paths MUST include `{ApplicationName}/` hierarchy (see section 4).
|
|
394
|
+
> ```json
|
|
395
|
+
> {
|
|
396
|
+
> "complexity": "simple|medium|complex",
|
|
397
|
+
> "filesToCreate": {
|
|
398
|
+
> "domain": [{"path": "src/Domain/Entities/{App}/{Mod}/{Entity}.cs", "type": "Entity|ValueObject|Enum", "linkedFRs": [], "linkedUCs": [], "module": "..."}],
|
|
399
|
+
> "application": [{"path": "src/Application/Services/{App}/{Mod}/{Svc}Service.cs", "type": "Service|Dto|Validator", "linkedFRs": [], "linkedUCs": [], "module": "..."}],
|
|
400
|
+
> "infrastructure": [{"path": "src/Infrastructure/Persistence/Configurations/{App}/{Mod}/{Entity}Configuration.cs", "type": "EFConfiguration", "linkedFRs": [], "module": "..."}],
|
|
401
|
+
> "api": [{"path": "src/API/Controllers/{App}/{Entity}Controller.cs", "type": "ApiController", "linkedUCs": [], "linkedFRs": [], "module": "..."}],
|
|
402
|
+
> "frontend": [{"path": "src/pages/{App}/{Mod}/{Page}Page.tsx", "type": "Page|Component|Hook|DashboardPage|I18n", "linkedUCs": [], "linkedWireframes": [], "module": "...", "skill": "/ui-components"}],
|
|
403
|
+
> "seedData": [{"path": "src/Infrastructure/Persistence/Seeding/Data/{Mod}/...SeedData.cs", "type": "SeedData", "category": "core|business", "source": "...", "module": "..."}],
|
|
404
|
+
> "tests": [{"path": "src/Tests/Unit/Domain/{App}/{Mod}/{Entity}Tests.cs", "type": "UnitTests|IntegrationTests|SecurityTests", "linkedFRs": [], "linkedUCs": [], "module": "..."}]
|
|
405
|
+
> },
|
|
406
|
+
> "brToCodeMapping": [{"ruleId": "BR-...", "files": ["path1", "path2"], "implementation": "description"}],
|
|
407
|
+
> "apiEndpointSummary": [{"method": "GET|POST|PUT|DELETE", "path": "/api/...", "permission": "{app}.{module}.{action}", "linkedUC": "UC-..."}],
|
|
408
|
+
> "prdFile": ".ralph/prd-{module}.json",
|
|
409
|
+
> "totalFiles": 0,
|
|
410
|
+
> "totalTasks": 0,
|
|
411
|
+
> "handedOffAt": "{ISO timestamp}"
|
|
412
|
+
> }
|
|
413
|
+
> ```
|
|
414
|
+
> **MANDATORY fields:** ALL of the above. `filesToCreate` MUST have all 7 categories (even if empty arrays).
|
|
415
|
+
> **FORBIDDEN:** `handoff: {}` (empty object is a CRITICAL BUG). Missing `brToCodeMapping` or `apiEndpointSummary`.
|
|
416
|
+
|
|
417
|
+
**For i = 0; i < modules.length; i++:**
|
|
418
|
+
|
|
419
|
+
```
|
|
420
|
+
1. moduleCode = modules[i].code
|
|
421
|
+
2. moduleFeatureId = modules[i].featureJsonPath or find via ba-reader.findFeature()
|
|
422
|
+
3. Read the module feature.json via ba-reader.findFeature(moduleFeatureId)
|
|
423
|
+
4. Build the handoff payload for THIS module:
|
|
424
|
+
- complexity (from section 3 calculation)
|
|
425
|
+
- filesToCreate (full 7-category structure from section 4, filtered for this module)
|
|
426
|
+
- brToCodeMapping (from section 5, filtered for this module)
|
|
427
|
+
- apiEndpointSummary (from section 6, filtered for this module)
|
|
428
|
+
- prdFile path
|
|
429
|
+
- totalFiles count
|
|
430
|
+
- totalTasks count
|
|
431
|
+
- handedOffAt timestamp
|
|
432
|
+
|
|
433
|
+
5. Write via ba-writer:
|
|
434
|
+
ba-writer.enrichModuleHandoff({
|
|
435
|
+
moduleFeatureId: {moduleFeatureId},
|
|
436
|
+
handoffData: {
|
|
437
|
+
complexity: "{simple|medium|complex}",
|
|
438
|
+
filesToCreate: {...},
|
|
439
|
+
brToCodeMapping: [...],
|
|
440
|
+
apiEndpointSummary: [...],
|
|
441
|
+
prdFile: ".ralph/prd-{moduleCode}.json",
|
|
442
|
+
totalFiles: {count},
|
|
443
|
+
totalTasks: {count},
|
|
444
|
+
handedOffAt: "{ISO timestamp}"
|
|
445
|
+
}
|
|
446
|
+
})
|
|
447
|
+
|
|
448
|
+
6. VERIFICATION (MANDATORY - done automatically by enrichModuleHandoff):
|
|
449
|
+
- handoff !== {}
|
|
450
|
+
- handoff.filesToCreate has 7 categories
|
|
451
|
+
- handoff.brToCodeMapping.length > 0
|
|
452
|
+
IF verification fails → STOP, report error, do NOT continue
|
|
453
|
+
|
|
454
|
+
7. Display progress:
|
|
455
|
+
"✓ Handoff module {i+1}/{N} : {moduleCode} ({fileCount} fichiers, {brCount} BRs mappées)"
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
#### 7b. Generate seedDataCore (MANDATORY for master feature.json)
|
|
459
|
+
|
|
460
|
+
> **Reference:** Load `references/handoff-seeddata-generation.md` for complete seedDataCore generation logic.
|
|
461
|
+
|
|
462
|
+
**The seedDataCore provides ralph-loop with the exact navigation, permissions, and translations to seed.**
|
|
463
|
+
Without seedDataCore, ralph-loop must INVENT this data — leading to inconsistencies.
|
|
464
|
+
|
|
465
|
+
The reference includes:
|
|
466
|
+
- Helper functions (toHumanReadable, toKebabCase)
|
|
467
|
+
- Complete seedDataCore template with all 9 arrays
|
|
468
|
+
- Icon inference for application and module levels
|
|
469
|
+
- POST-CHECK validation rules (BLOCKING for icons/application, warning for counts)
|
|
470
|
+
|
|
471
|
+
Key points:
|
|
472
|
+
- Icons must NEVER be null (use fallback if not inferred)
|
|
473
|
+
- All 9 seedDataCore arrays must be present (even if empty for multi-module scenarios)
|
|
474
|
+
- PROJECT MODE: Generate one entry per application from project feature.json
|
|
475
|
+
- SINGLE-APP MODE: Generate one entry from master feature.json
|
|
476
|
+
|
|
477
|
+
```
|
|
478
|
+
// Derive seedDataCore from modules[], applicationRoles[], and coverageMatrix[]
|
|
479
|
+
|
|
480
|
+
// Helper: PascalCase → "Human Readable" (e.g., "HumanResources" → "Human Resources")
|
|
481
|
+
function toHumanReadable(pascalCase) {
|
|
482
|
+
return pascalCase
|
|
483
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
484
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2');
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
const appCode = master.metadata.application;
|
|
488
|
+
const appLabel = toHumanReadable(appCode);
|
|
489
|
+
const appDesc = master.cadrage?.problem?.split('.')[0] || `Gestion ${appLabel}`;
|
|
490
|
+
const lang = master.metadata.language || "fr";
|
|
491
|
+
|
|
492
|
+
const seedDataCore = {
|
|
493
|
+
// Application-level navigation (MANDATORY — one entry per application)
|
|
494
|
+
// PROJECT MODE: Generate one entry per application from project feature.json
|
|
495
|
+
// SINGLE-APP MODE: Generate one entry from master feature.json
|
|
496
|
+
navigationApplications: (() => {
|
|
497
|
+
if (workflow.mode === "project") {
|
|
498
|
+
// Multi-app: one navigation entry per application
|
|
499
|
+
return projectFeature.applications.map((app, idx) => {
|
|
500
|
+
const appLabel = toHumanReadable(app.code);
|
|
501
|
+
return {
|
|
502
|
+
code: app.code.toLowerCase(),
|
|
503
|
+
name: app.code,
|
|
504
|
+
labels: {
|
|
505
|
+
fr: lang === "fr" ? (app.name || appLabel) : appLabel,
|
|
506
|
+
en: lang === "en" ? (app.name || appLabel) : appLabel,
|
|
507
|
+
it: appLabel,
|
|
508
|
+
de: appLabel
|
|
509
|
+
},
|
|
510
|
+
description: {
|
|
511
|
+
fr: lang === "fr" ? (app.description || `Gestion ${appLabel}`) : `Gestion ${appLabel}`,
|
|
512
|
+
en: lang === "en" ? (app.description || `${appLabel} management`) : `${appLabel} management`,
|
|
513
|
+
it: `Gestione ${appLabel}`,
|
|
514
|
+
de: `${appLabel} Verwaltung`
|
|
515
|
+
},
|
|
516
|
+
icon: app.icon || inferIconFromApplication({ metadata: { application: app.code } }) || "layout-grid",
|
|
517
|
+
iconType: "lucide",
|
|
518
|
+
route: `/${toKebabCase(app.code)}`,
|
|
519
|
+
displayOrder: (idx + 1) * 10
|
|
520
|
+
};
|
|
521
|
+
});
|
|
522
|
+
} else {
|
|
523
|
+
// Single-app: one navigation entry
|
|
524
|
+
return [{
|
|
525
|
+
code: appCode.toLowerCase(),
|
|
526
|
+
name: appCode,
|
|
527
|
+
labels: {
|
|
528
|
+
fr: lang === "fr" ? (master.cadrage?.applicationName || appLabel) : appLabel,
|
|
529
|
+
en: lang === "en" ? (master.cadrage?.applicationName || appLabel) : appLabel,
|
|
530
|
+
it: appLabel,
|
|
531
|
+
de: appLabel
|
|
532
|
+
},
|
|
533
|
+
description: {
|
|
534
|
+
fr: lang === "fr" ? appDesc : `Gestion ${appLabel}`,
|
|
535
|
+
en: lang === "en" ? appDesc : `${appLabel} management`,
|
|
536
|
+
it: `Gestione ${appLabel}`,
|
|
537
|
+
de: `${appLabel} Verwaltung`
|
|
538
|
+
},
|
|
539
|
+
icon: inferIconFromApplication(master) || "layout-grid",
|
|
540
|
+
iconType: "lucide",
|
|
541
|
+
route: `/${toKebabCase(appCode)}`,
|
|
542
|
+
displayOrder: 1
|
|
543
|
+
}];
|
|
544
|
+
}
|
|
545
|
+
})(),
|
|
546
|
+
|
|
547
|
+
// PROJECT MODE: Flatten modules from ALL applications
|
|
548
|
+
// SINGLE-APP MODE: Use master.modules directly
|
|
549
|
+
navigationModules: (() => {
|
|
550
|
+
if (workflow.mode === "project") {
|
|
551
|
+
let order = 0;
|
|
552
|
+
return projectFeature.applications.flatMap(app => {
|
|
553
|
+
return (app.modules || []).map(m => ({
|
|
554
|
+
code: m.code,
|
|
555
|
+
applicationCode: app.code,
|
|
556
|
+
label: m.name || m.code,
|
|
557
|
+
description: m.description,
|
|
558
|
+
icon: inferIconFromModule(m) || "folder",
|
|
559
|
+
iconType: "lucide",
|
|
560
|
+
route: `/${toKebabCase(app.code)}/${toKebabCase(m.code)}`,
|
|
561
|
+
displayOrder: (++order) * 10
|
|
562
|
+
}));
|
|
563
|
+
});
|
|
564
|
+
} else {
|
|
565
|
+
return master.modules.map((m, i) => ({
|
|
566
|
+
code: m.code,
|
|
567
|
+
label: m.name || m.code,
|
|
568
|
+
description: m.description,
|
|
569
|
+
icon: inferIconFromModule(m) || "folder",
|
|
570
|
+
iconType: "lucide",
|
|
571
|
+
route: `/${toKebabCase(appCode)}/${toKebabCase(m.code)}`,
|
|
572
|
+
displayOrder: (i + 1) * 10
|
|
573
|
+
}));
|
|
574
|
+
}
|
|
575
|
+
})(),
|
|
576
|
+
|
|
577
|
+
navigationSections: (() => {
|
|
578
|
+
const buildSections = (modules, appCode) =>
|
|
579
|
+
modules.flatMap(m =>
|
|
580
|
+
(m.anticipatedSections || []).map((s, j) => ({
|
|
581
|
+
moduleCode: m.code,
|
|
582
|
+
code: s.code,
|
|
583
|
+
label: s.description?.split(':')[0] || s.code,
|
|
584
|
+
description: s.description || "",
|
|
585
|
+
route: s.code === "list"
|
|
586
|
+
? `/${toKebabCase(appCode)}/${toKebabCase(m.code)}`
|
|
587
|
+
: s.code === "detail"
|
|
588
|
+
? `/${toKebabCase(appCode)}/${toKebabCase(m.code)}/:id`
|
|
589
|
+
: `/${toKebabCase(appCode)}/${toKebabCase(m.code)}/${toKebabCase(s.code)}`,
|
|
590
|
+
displayOrder: (j + 1) * 10,
|
|
591
|
+
navigation: s.code === "detail" ? "hidden" : "visible"
|
|
592
|
+
}))
|
|
593
|
+
);
|
|
594
|
+
|
|
595
|
+
if (workflow.mode === "project") {
|
|
596
|
+
return projectFeature.applications.flatMap(app =>
|
|
597
|
+
buildSections(app.modules || [], app.code)
|
|
598
|
+
);
|
|
599
|
+
} else {
|
|
600
|
+
return buildSections(master.modules, appCode);
|
|
601
|
+
}
|
|
602
|
+
})(),
|
|
603
|
+
|
|
604
|
+
navigationResources: master.cadrage.coverageMatrix
|
|
605
|
+
.filter(cm => cm.module && cm.anticipatedResources?.length > 0)
|
|
606
|
+
.flatMap(cm =>
|
|
607
|
+
cm.anticipatedResources.map((r, k) => ({
|
|
608
|
+
moduleCode: cm.module,
|
|
609
|
+
sectionCode: cm.anticipatedSections?.[0] || "list",
|
|
610
|
+
code: r,
|
|
611
|
+
label: r.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
|
|
612
|
+
displayOrder: (k + 1) * 10
|
|
613
|
+
}))
|
|
614
|
+
),
|
|
615
|
+
|
|
616
|
+
navigationTranslations: master.modules.flatMap(m => {
|
|
617
|
+
const langs = ["fr", "en", "it", "de"]; // all supported languages
|
|
618
|
+
return langs.map(lang => ({
|
|
619
|
+
moduleCode: m.code,
|
|
620
|
+
language: lang,
|
|
621
|
+
label: lang === master.metadata.language ? (m.name || m.code) : m.code,
|
|
622
|
+
description: lang === master.metadata.language ? m.description : ""
|
|
623
|
+
}));
|
|
624
|
+
}),
|
|
625
|
+
|
|
626
|
+
// PROJECT MODE: permissions scoped per application context
|
|
627
|
+
// SINGLE-APP MODE: all permissions under {app}
|
|
628
|
+
permissions: (() => {
|
|
629
|
+
const buildPermissions = (modules, appCode) =>
|
|
630
|
+
modules.flatMap(m => {
|
|
631
|
+
const basePath = `${toKebabCase(appCode)}.${toKebabCase(m.code)}`;
|
|
632
|
+
const actions = ['read', 'create', 'update', 'delete'];
|
|
633
|
+
return [
|
|
634
|
+
{ path: `${basePath}.*`, action: '*', description: `Full ${m.name || m.code} access` },
|
|
635
|
+
...actions.map(action => ({
|
|
636
|
+
path: `${basePath}.${action}`,
|
|
637
|
+
action: action,
|
|
638
|
+
description: `${action.charAt(0).toUpperCase() + action.slice(1)} ${m.name || m.code}`
|
|
639
|
+
}))
|
|
640
|
+
];
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
if (workflow.mode === "project") {
|
|
644
|
+
return projectFeature.applications.flatMap(app =>
|
|
645
|
+
buildPermissions(app.modules || [], app.code)
|
|
646
|
+
);
|
|
647
|
+
} else {
|
|
648
|
+
return buildPermissions(master.modules, appCode);
|
|
649
|
+
}
|
|
650
|
+
})(),
|
|
651
|
+
|
|
652
|
+
rolePermissions: (() => {
|
|
653
|
+
const buildRolePermissions = (roles, modules, appCode) =>
|
|
654
|
+
roles.map(role => ({
|
|
655
|
+
role: role.role,
|
|
656
|
+
level: role.level,
|
|
657
|
+
permissions: modules.map(m => `${toKebabCase(appCode)}.${toKebabCase(m.code)}.${
|
|
658
|
+
role.level === 'admin' ? '*' :
|
|
659
|
+
role.level === 'manager' ? 'read,create,update' :
|
|
660
|
+
role.level === 'contributor' ? 'read,create' : 'read'
|
|
661
|
+
}`)
|
|
662
|
+
}));
|
|
663
|
+
|
|
664
|
+
if (workflow.mode === "project") {
|
|
665
|
+
return projectFeature.applications.flatMap(app =>
|
|
666
|
+
buildRolePermissions(app.applicationRoles || [], app.modules || [], app.code)
|
|
667
|
+
);
|
|
668
|
+
} else {
|
|
669
|
+
return buildRolePermissions(master.cadrage.applicationRoles, master.modules, appCode);
|
|
670
|
+
}
|
|
671
|
+
})(),
|
|
672
|
+
|
|
673
|
+
permissionConstants: (() => {
|
|
674
|
+
const buildConstants = (modules, appCode) =>
|
|
675
|
+
modules.flatMap(m =>
|
|
676
|
+
['Read', 'Create', 'Update', 'Delete', 'Validate', 'Export'].map(action => ({
|
|
677
|
+
module: m.code,
|
|
678
|
+
application: appCode,
|
|
679
|
+
action: action,
|
|
680
|
+
constant: `${appCode}${m.code}${action}`,
|
|
681
|
+
path: `${toKebabCase(appCode)}.${toKebabCase(m.code)}.${action.toLowerCase()}`
|
|
682
|
+
}))
|
|
683
|
+
);
|
|
684
|
+
|
|
685
|
+
if (workflow.mode === "project") {
|
|
686
|
+
return projectFeature.applications.flatMap(app =>
|
|
687
|
+
buildConstants(app.modules || [], app.code)
|
|
688
|
+
);
|
|
689
|
+
} else {
|
|
690
|
+
return buildConstants(master.modules, appCode);
|
|
691
|
+
}
|
|
692
|
+
})()
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
// Icon inference functions are defined in the reference
|
|
696
|
+
// inferIconFromApplication(master) - Application level icons
|
|
697
|
+
// inferIconFromModule(module) - Module level icons
|
|
698
|
+
// See references/handoff-seeddata-generation.md for complete implementation
|
|
699
|
+
|
|
700
|
+
ba-writer.enrichSection({
|
|
701
|
+
featureId: {feature_id},
|
|
702
|
+
section: "seedDataCore",
|
|
703
|
+
data: seedDataCore
|
|
704
|
+
})
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
**POST-CHECK (BLOCKING for icons/application, warning for counts):**
|
|
708
|
+
```
|
|
709
|
+
IF !seedDataCore.navigationApplications || seedDataCore.navigationApplications.length === 0:
|
|
710
|
+
BLOCKING ERROR: "navigationApplications is empty — Application navigation will NOT be seeded. Menu will show (nothing) → Modules."
|
|
711
|
+
IF seedDataCore.navigationApplications[0].icon === null || seedDataCore.navigationApplications[0].icon === undefined:
|
|
712
|
+
BLOCKING ERROR: "Application icon is null — ralph-loop will render empty navigation"
|
|
713
|
+
IF !seedDataCore.navigationApplications[0].labels?.fr || !seedDataCore.navigationApplications[0].labels?.en:
|
|
714
|
+
BLOCKING ERROR: "Application labels missing fr/en — translations will fail"
|
|
715
|
+
IF seedDataCore.navigationModules.length !== master.modules.length:
|
|
716
|
+
WARNING: seedDataCore has ${seedDataCore.navigationModules.length} nav modules but ${master.modules.length} modules exist
|
|
717
|
+
IF seedDataCore.permissions.length === 0:
|
|
718
|
+
WARNING: seedDataCore has 0 permissions — applicationRoles may be missing
|
|
719
|
+
IF seedDataCore.navigationModules.some(m => !m.icon || m.icon === null):
|
|
720
|
+
BLOCKING ERROR: "Navigation modules with null icons detected — ralph-loop will render empty navigation"
|
|
721
|
+
→ Fix: Re-run inferIconFromModule() for modules with null icons
|
|
722
|
+
IF seedDataCore.navigationSections.length === 0:
|
|
723
|
+
WARNING: "0 navigation sections — every module should have at least 1 section (e.g., 'list')"
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
#### 7c. Master Handoff (after ALL modules written + seedDataCore generated)
|
|
727
|
+
|
|
728
|
+
```
|
|
729
|
+
// Write handoff to application-level feature.json (single-app mode)
|
|
730
|
+
// OR to each application feature.json + project feature.json (project mode)
|
|
731
|
+
|
|
732
|
+
IF workflow.mode === "project":
|
|
733
|
+
// Write handoff to EACH application feature.json
|
|
734
|
+
FOR each app in projectFeature.applications:
|
|
735
|
+
ba-writer.enrichSection({
|
|
736
|
+
featureId: app.featureJsonPath,
|
|
737
|
+
section: "handoff",
|
|
738
|
+
data: {
|
|
739
|
+
status: "handed-off",
|
|
740
|
+
complexity: "{app-level complexity}",
|
|
741
|
+
implementationStrategy: "{strategy}",
|
|
742
|
+
moduleCount: app.modules.length,
|
|
743
|
+
moduleOrder: app.modules.map(m => m.code),
|
|
744
|
+
totalFilesToCreate: {sum across app modules},
|
|
745
|
+
totalTasks: {sum across app modules},
|
|
746
|
+
prdFiles: app.modules.map(m => ({ module: m.code, path: `.ralph/prd-${m.code}.json` })),
|
|
747
|
+
handedOffAt: "{ISO timestamp}"
|
|
748
|
+
}
|
|
749
|
+
})
|
|
750
|
+
|
|
751
|
+
// Write project-level handoff summary
|
|
752
|
+
ba-writer.enrichSection({
|
|
753
|
+
featureId: {project_id},
|
|
754
|
+
section: "handoff",
|
|
755
|
+
data: {
|
|
756
|
+
status: "handed-off",
|
|
757
|
+
complexity: "{global complexity}",
|
|
758
|
+
implementationStrategy: "{strategy}",
|
|
759
|
+
applicationCount: projectFeature.applications.length,
|
|
760
|
+
applicationOrder: projectFeature.applicationDependencyGraph.topologicalOrder,
|
|
761
|
+
totalModuleCount: {sum of all app module counts},
|
|
762
|
+
totalFilesToCreate: {sum across ALL applications and modules},
|
|
763
|
+
totalTasks: {sum across ALL applications and modules},
|
|
764
|
+
prdStructure: "per-module",
|
|
765
|
+
prdFiles: [
|
|
766
|
+
...allModulePrdFiles,
|
|
767
|
+
{ module: "CrossModule", path: ".ralph/prd-CrossModule.json" },
|
|
768
|
+
{ module: "CrossApplication", path: ".ralph/prd-CrossApplication.json" }
|
|
769
|
+
],
|
|
770
|
+
progressTrackerPath: ".ralph/progress.txt",
|
|
771
|
+
handedOffAt: "{ISO timestamp}"
|
|
772
|
+
}
|
|
773
|
+
})
|
|
774
|
+
ELSE:
|
|
775
|
+
ba-writer.enrichSection({
|
|
776
|
+
featureId: {feature_id},
|
|
777
|
+
section: "handoff",
|
|
778
|
+
data: {
|
|
779
|
+
status: "handed-off",
|
|
780
|
+
complexity: "{simple|medium|complex}",
|
|
781
|
+
implementationStrategy: "{strategy}",
|
|
782
|
+
moduleCount: {count},
|
|
783
|
+
moduleOrder: [...],
|
|
784
|
+
totalFilesToCreate: {sum across all modules},
|
|
785
|
+
totalTasks: {sum across all modules},
|
|
786
|
+
prdStructure: "per-module | consolidated",
|
|
787
|
+
prdFiles: [
|
|
788
|
+
{ module: "{module1}", path: ".ralph/prd-{module1}.json" },
|
|
789
|
+
{ module: "{module2}", path: ".ralph/prd-{module2}.json" }
|
|
790
|
+
],
|
|
791
|
+
progressTrackerPath: ".ralph/progress.txt",
|
|
792
|
+
handedOffAt: "{ISO timestamp}"
|
|
793
|
+
}
|
|
794
|
+
})
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
#### 7d. Final Verification (BLOCKING)
|
|
798
|
+
|
|
799
|
+
```
|
|
800
|
+
count = 0
|
|
801
|
+
FOR each module in modules[]:
|
|
802
|
+
Read module feature.json
|
|
803
|
+
IF module.handoff !== {} AND module.status === "handed-off":
|
|
804
|
+
count++
|
|
805
|
+
|
|
806
|
+
IF count < modules.length:
|
|
807
|
+
→ BLOCKING ERROR: {modules.length - count} modules missing handoff
|
|
808
|
+
→ List the missing modules by name
|
|
809
|
+
→ DO NOT proceed to step-05b
|
|
810
|
+
→ Return to 7a for missing modules only
|
|
811
|
+
|
|
812
|
+
IF count === modules.length:
|
|
813
|
+
ba-writer.updateStatus({feature_id}, "handed-off")
|
|
814
|
+
Display: "✓ Handoff complet: {count}/{modules.length} modules avec handoff valide"
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
Status journey: analyze → consolidate → handed-off
|
|
818
|
+
|
|
819
|
+
---
|
|
820
|
+
|
|
821
|
+
## SELF-VERIFICATION
|
|
822
|
+
|
|
823
|
+
Before proceeding to step-05b-deploy.md, VERIFY:
|
|
824
|
+
|
|
825
|
+
1. **filesToCreate** has all 7 categories populated (domain, application, infrastructure, api, frontend, seedData, tests) for each module
|
|
826
|
+
2. **Complexity** calculated for all modules
|
|
827
|
+
3. **Implementation strategy** chosen (for multi-module features)
|
|
828
|
+
4. **ALL module feature.json** have `handoff.brToCodeMapping.length > 0`
|
|
829
|
+
5. **ALL module feature.json** have `handoff.apiEndpointSummary.length > 0`
|
|
830
|
+
6. **ALL module feature.json** status = "handed-off"
|
|
831
|
+
7. **Master feature.json** has `handoff` section with implementationStrategy, moduleOrder, totalFilesToCreate
|
|
832
|
+
8. **Master status** = "handed-off"
|
|
833
|
+
|
|
834
|
+
**IF any check fails → FIX before proceeding.**
|
|
835
|
+
|
|
836
|
+
---
|
|
837
|
+
|
|
838
|
+
## NEXT STEP
|
|
839
|
+
|
|
840
|
+
Load: `steps/step-05b-deploy.md`
|