Do and don't¶
A catalog of the conventions that keep FedMS code reviewable, testable, and CI-green. Honor every one of them — they are not preferences, they are the contract.
Tooling¶
✅ DO¶
- Always prefix PHP/Composer/Drush/Ahoy/glab/etc. with
l3d. L3D handles project root detection, container management, and SSH forwarding. - Run
l3dfrom the directory you are working in. L3D detects the project root for you and transitions back into your subdirectory inside the container. - Run
l3d ahoy d4d updateonce per session if the project has adocker-compose.yml.
❌ DON'T¶
- Don't run
php,composer,drush,ahoy,phpunit,phpcs,phpstan,node,npm,glab,drupalorgdirectly on the host. Always prefix withl3d. - Don't
cdto the project root before runningl3d. That defeats subdirectory-aware tools likeglabandgit. - Don't run
mysqlormariadbdirectly. Always usedocker compose exec mariadb mariadb ….
Repositories¶
✅ DO¶
- Identify the right repo for the change using Where things live.
cdinto a module's directory before runninggitorglabon it. Eachfedms_*module is its own repo.- Open an MR on the right repo. Site changes go to the site repo; module changes go to the module repo.
- Target
developfor every MR.
❌ DON'T¶
- Don't run
git statusorglab issue viewfrom the site root when you mean to operate on a module — you'll see the wrong repo. - Don't mix module-level and site-level changes in one MR.
- Don't push to
mainor any release branch directly.
Code style¶
✅ DO¶
- Use US English (
en-US) in code, comments, commit messages, MRs, issues, and identifiers. The cspell pipeline rejects British English. - Use
declare(strict_types=1);in new PHP files. - Use OOP hooks with
#[Hook]for new hook implementations. Seefedms_federation/src/Hook/EntityHooks.phpfor the canonical example. - Use constructor dependency injection for services. Don't use
\Drupal::service()calls in new code. - Add PHPDoc to public methods.
❌ DON'T¶
- Don't use British English (behaviour, colour, organisation,
modeller, artefact, labelled, cancelled, programme, centre,
whilst, …). The full mapping is in the
l3dskill. - Don't write procedural hooks for new code. Use
#[Hook]. - Don't use
\Drupal::static calls in new code.
Configuration¶
✅ DO¶
- Use
l3d ahoy fedms export-configto export config — it runs the export for all 7 modules + profile in one go. - Inspect the diff after exporting (
cd <module> && l3d git diff) and prune unrelated changes before committing. - Commit config to the module that owns it.
- Use
config_splitfor environment-specific overrides.
❌ DON'T¶
- Don't dump module config into the site's
config/sync/. It silently overrides the module's owned config. - Don't hand-edit
eca.eca.*.ymlfiles. Go through the modeler at/admin/config/workflow/ecaand re-export. - Don't commit
.envfiles or anything containing secrets.
ECA models¶
✅ DO¶
- Load the
eca-guideskill before touching any model. - Read the per-model page under Developer guide → ECA models.
- Edit via the modeler at
/admin/config/workflow/eca. - Re-export and review the diff before committing.
- When adding a condition that doesn't exist, implement it as a
PHP plugin in the appropriate module (usually
fedms_task), then reference it from the model.
❌ DON'T¶
- Don't hand-edit the YAML files. The modeler maintains a hash that hand-edits desync.
- Don't add complex logic in YAML. If a model is becoming
unmanageable, split it (see
fedms/components/eca#8) or move logic to PHP plugins. - Don't hard-code BPMN.io specifics anywhere. The modeler is being replaced.
Federation¶
✅ DO¶
- Respect the session-member constraint. A session member must
be an event member, enforced by the
queryEntityReferenceAlterhook infedms_federation. - Use
field_syncsemantics correctly when implementing federation features. - Add a
field_gitlab_idto org groups if you are wiring up a new federation transport step.
❌ DON'T¶
- Don't bypass the
queryEntityReferenceAlterhook to "fix" a picker. Fix the hook or fix the model that drives the form. - Don't write federation transport code yet without coordinating
with the federation transport design — see the
open issues on
fedms/components/federation.
Tasks¶
✅ DO¶
- Spawn tasks via patterns when the case is repeatable.
- Use the right anchor (
task_create,session_start,session_end) for the timestamp. - Reference milestones by UUID (the framework does this for you).
❌ DON'T¶
- Don't create cycles in successor chains.
- Don't reference a pattern's milestone by ID — it's UUID-based for federation safety.
- Don't mark a task complete from a different user without updating the assignee — it breaks the audit trail.
Testing¶
✅ DO¶
- Run
l3d ahoy test phpcsmodule <name>andl3d ahoy test phpstanmodule <name>before pushing PHP changes. - Run
l3d ahoy test phpunitmodule <name>if the module ships tests. - Write new E2E tests in Playwright.
- Target the right Playwright branch:
developfor smoke tests that run on every site daily.feature/advancedfor full role-based tests on the demo site.- Never merge
feature/advancedback intodevelop.
❌ DON'T¶
- Don't add new Cypress tests. Cypress is deprecated.
- Don't merge
feature/advancedintodevelop. It's one-way:develop→feature/advanced. - Don't disable failing tests to push faster. Fix the test or fix the code.
Commits and MRs¶
✅ DO¶
- Imperative mood subjects: "Add task pattern successor logic", "Fix federation hook for orphaned sessions".
- Reference issues with
Closes fedms/components/<project>#<id>when the MR fully resolves the issue. UseRelates to ...for partial. - Test plan in the MR description.
- Screenshots for UI changes.
❌ DON'T¶
- Don't open MRs without a description.
- Don't commit "WIP" code to
developwithout a draft MR. - Don't bypass CI failures. Investigate and fix.
Documentation¶
✅ DO¶
- Update this documentation in the same MR as the code change that affects it.
- Update
AGENTS.mdand thefedmsskill when discovering a cross-cutting convention. - Use the page-level template (frontmatter, hierarchical structure, cross-links, "Next steps" at the bottom).
- Link to GitLab issues when describing forward-looking behavior.
❌ DON'T¶
- Don't leave a feature undocumented while the MR sits open waiting for review.
- Don't write documentation that contradicts the code — documentation reflects reality; if reality is wrong, fix reality.
- Don't create new documentation files without linking them from
the relevant index page and from
mkdocs.yml'snav:section.
Secrets and security¶
✅ DO¶
- Read
.envfor credentials (never hard-code them). - Use the system secret-scan tooling before committing.
❌ DON'T¶
- Don't commit secrets to any repo.
- Don't bypass authentication in any code path.
- Don't grant
administer permissionsto non-admin roles.
Next steps¶
- Common workflows — recipes that apply these rules in practice.
- Where things live — the path lookup.
- Developer guide → Contributing — the full upstream change workflow.