| name | configure-codebase |
| description | Use when a Spryker project adopts a custom namespace instead of Pyz and the code layer must resolve, build, lint, and test it — namespace registration, composer autoload, frontend build config, codeception wiring. A pre-boot wizard step of project start; skipped entirely when the project keeps Pyz. |
configure-codebase
Goal: after this, a class in src/<Ns>/... overrides Pyz/core, a Yves component under src/<Ns>/Yves/*/Theme compiles, and the project has runnable test infrastructure — a committed example test under tests/<Ns>Test/ that codecept build + codecept run prove green (post-boot), not just an empty .gitkeep tree. (Codebase/test failure-signature triage lives in the Known-traps catalog: ../project-starter-wizard/references/pitfalls.md.)
Read .ai-dev/project-setup.md → namespace. If mode: keep-pyz, record the step skipped (keep-Pyz) and stop. Otherwise <Ns> = namespace.name (validated CamelCase, no collision with Pyz/core).
Work from real files; these are judgment edits (each config file has its own idiom), not bulk transforms.
Placement principle — governs the WHOLE project run, not just this step. Once <Ns> is registered (PROJECT_NAMESPACES = ['<Ns>','Pyz'], <Ns> wins resolution), every project-level PHP customization — config classes, plugins, expanders, dependency providers — is created in src/<Ns>/…, EXTENDING the Pyz class (or core if no Pyz counterpart exists), and src/Pyz/… is left pristine as the inherited demoshop layer. Never edit a src/Pyz class in place to customize it when a custom namespace is set — including store-keyed config classes a later step (e.g. define-stores' literal sweep) needs to change. Extend the Pyz class, not core, when a Pyz counterpart exists, or its existing overrides are silently dropped. (keep-pyz mode: src/Pyz is the project layer — edit it directly.) This is the rule the other skills assume; the trap is editing a SalesPaymentMerchant* config in src/Pyz while correctly creating StockConfig/CheckoutPageConfig in src/<Ns> — the same run, two placements.
Edits
- Register the namespace —
config/Shared/config_default.php: KernelConstants::PROJECT_NAMESPACE = '<Ns>' (primary), KernelConstants::PROJECT_NAMESPACES = ['<Ns>', 'Pyz'] (resolver order — project wins, Pyz stays as working fallback so the app keeps booting via its literal Pyz\ bootstraps), and the same in GlueBackendApiApplicationConstants::PROJECT_NAMESPACES.
- CRITICAL — the environment config files CLOBBER this edit. The per-environment overlays load after
config_default.php and this clone re-assigns GlueBackendApiApplicationConstants::PROJECT_NAMESPACES = ['Pyz'] in config/Shared/config_default-docker.dev.php and config_default-ci.php — i.e. in exactly the environment the first boot runs (deploy.dev.yml → environment: docker.dev) and in CI. Editing only the base file ships a Backend Glue API that silently ignores src/<Ns>. Grep every config/Shared/config_default-*.php for PROJECT_NAMESPACE re-assignments and patch each one to ['<Ns>', 'Pyz'] — the base-file edit alone is not registration.
- Glue API Platform source directories are Pyz-hardcoded separately from the resolver.
config/Glue/packages/spryker_api_platform.php, config/GlueBackend/packages/spryker_api_platform.php, and config/GlueStorefront/packages/spryker_api_platform.php each call sourceDirectories([...'src/Pyz'...]) — API resources under src/<Ns> are invisible to discovery until 'src/<Ns>' is appended in all three (anchored edit; the array also carries vendor paths — add, never replace).
- Autoload —
composer.json: autoload.psr-4 add "<Ns>\\": "src/<Ns>/"; autoload-dev.psr-4 add "<Ns>Test\\": "tests/<Ns>Test/". (Autoload dump happens at boot.)
- Skeletons —
src/<Ns>/{Client,Glue,Service,Shared,Yves,Zed}/ with .gitkeep, including src/<Ns>/Zed/Translator/data/ (the project-level Back Office translation location, auto-scanned per project namespace). tests/<Ns>Test/{Zed,Yves,Glue,Shared}/.
Verify (static; runtime proof is boot-and-verify's job)
Namespace registration is complete only when a Grep for PROJECT_NAMESPACE across ALL of config/Shared/config_default*.php (base + every -<env> overlay) shows <Ns> in every assignment — one overlay still assigning ['Pyz'] silently un-registers the namespace in that environment (the docker.dev/ci clobber above). php -l the edited PHP (incl. the seed ExampleCest.php); JSON-validate composer.json/tsconfig*/package.json with php (allowlisted: php -r 'json_decode(file_get_contents("composer.json")); echo json_last_error_msg();') — not node. Only the JS files (frontend/settings.js, *.mjs) need node --check; node isn't in the base allowlist, so either recommend adding node:* or treat the JS syntax-check as optional (it's belt-and-suspenders — the boot's frontend build is the real proof). The codecept build/run green proof for the seed module is post-boot (needs composer install) — carried by boot-and-verify, not here. Update the configure-codebase step; note the eslint backlog follow-up if surfaced.
Test scoping is complete only when BOTH trees are proven in scope — by these greps, not by assertion. Step 4's two mandates (every aggregate config; the projectNamespaces sweep) are the ones runs commonly skip, so verify them rather than assuming them done: an aggregate config left PyzTest-only means <Ns> never runs in that lane (CI runs -c tests/codeception.ci.functional.yml), and an unswept suite stays pinned to ['Pyz']. Both trees must be in scope, and the failure is bidirectional: one direction runs only <Ns>, the other runs only Pyz, and each reports OK while testing half the code. These edits are purely additive — nothing anywhere replaces PyzTest.
grep -n 'Test/\*/\*' codeception.yml tests/codeception.*.yml
grep -n "src/.*\*\.php" codeception.yml tests/codeception.*.yml
grep -rc "projectNamespaces: \['Pyz'\]" tests/ | grep -v ':0$'
A missing PyzTest in (1)/(2) means you replaced instead of appended; a surviving hit in (3) means those suites test src/Pyz config while the application runs src/<Ns> — green on the wrong values, and the thing a developer describes as "the Pyz tests don't cover my namespace". (static-validation is not involved and needs no edit — its diff script never invokes codeception, has no namespace concept, and excludes PyzTest/<Ns>Test symmetrically.)
Yves component discovery — prove BOTH directions with the custom namespace. POST-boot, like the codecept proof: component discovery reads vendor/. Runs whichever frontend shape (a)/(b)/(c) applied. Registering <Ns> in the settings is not proof; a new component and an override fail differently, so run both:
- New component — create
src/<Ns>/Yves/ShopUi/Theme/default/components/atoms/ns-probe/ns-probe.{twig,scss}, the scss carrying one unique marker (.ns-probe { outline: 1px solid red; }), then docker/sdk console frontend:yves:build (or docker/sdk up --assets). Pass = build OK and grep -rl 'ns-probe' public/Yves/assets/ hits a compiled bundle. Empty grep on a green build = src/<Ns>/Yves never entered the component finder's dirs — the settings registration did not take (re-check shape (a)/(b)/(c) above).
- Override of a shipped component — copy one component that renders on the homepage from
vendor/spryker-shop/shop-ui/.../Theme/default/components/molecules/<X>/ into src/<Ns>/Yves/ShopUi/Theme/default/components/molecules/<X>/, change one visible marker in its twig and its scss, rebuild, and load the page. Pass = the marker appears in the rendered HTML and the compiled css — the project namespace outranks the vendor/Pyz copy. Fail = <Ns> is missing or ordered after Pyz in the component dirs; fix the order, not the component.
- Delete both probes and rebuild, so the proof leaves no artefact behind.
Record the result in the step report; an unrun probe stays an open deferred check, not a "done".
Dev-loop reference (verified edit→effect — pass to the team)
- Class override (
src/<Ns>/**/*.php): add/remove/rename → docker/sdk console cache:class-resolver:build (method-body edits need no rebuild).
- Transfer (
src/<Ns>/Shared/*/Transfer/*.transfer.xml): transfer:generate → src/Generated/. Propel schema (src/<Ns>/Zed/*/Persistence/Propel/Schema/*.schema.xml): propel:schema:copy → propel:model:build → propel:diff. Both discover src/<Ns> by path glob — no namespace coupling.
- Tests: a new module copies the
tests/<Ns>Test/Shared/Example seed (its codeception.yml with namespace: <Ns>Test\... + projectNamespaces: ['<Ns>','Pyz'], actor, cest) → vendor/bin/codecept build → codecept run -c <suite-dir> <Suite>. Never copy a PyzTest config's projectNamespaces: ['Pyz'] verbatim — set ['<Ns>','Pyz'] or the test won't see src/<Ns>.
- macOS/OrbStack bind-mount has a sync lag both directions — re-check generated/removed files a beat later before asserting.