Version 0
Package Governance
Record package boundary decisions before adding MortelOS features.
Every new feature, integration, frontend surface, backend service or reusable workflow starts with a package decision.
This keeps MortelOS composable. It also forces the team to decide what belongs in a reusable package and what belongs in the host app.
Decisions
| Decision | Use when |
|---|---|
package-now |
The capability can serve another MortelOS installation today. Build directly in a package. |
package-ready |
The host needs local wiring first, but the package boundary is explicit. Extract when stable. |
workspace-only |
The behavior is specific to one customer or workspace. |
Default to package-ready when unsure. It preserves speed while keeping the future package boundary visible.
Record a decision
Use mortelos/dev-tools when it is installed:
php artisan mortelos:package-decision "Customer Portal" \
--decision=package-ready \
--surface=mortelos/customer-portal \
--reason="Reusable shell with customer-specific tenant policy and branding." \
--no-interaction
php artisan mortelos:package-decisions:check --require-reason --no-interaction
When the dev tools are not installed, record the same fields in .mortelos/package-decisions.md:
## Customer Portal
Surface: `mortelos/customer-portal`
Decision: `package-ready`
Reason: Reusable shell with customer-specific tenant policy and branding.
Date: 2026-06-07
CI should fail when package governance fails. In host apps, this is usually exposed through:
composer package-governance
Local Source Layout
Use sibling package repositories as the canonical local source for MortelOS work:
| Package family | Local source pattern | Example |
|---|---|---|
| MortelOS packages | ~/Sites/mortelos-* |
~/Sites/mortelos-chat |
| Channel packages | ~/Sites/channel-* |
~/Sites/channel-gmail |
| Widget packages | ~/Sites/widget-* |
~/Sites/widget-compliance |
Host-local package folders such as packages/mortelos/* are only for short-lived testing. Before tagging or releasing a reusable package change, move the work into the matching sibling repository and tag that repository.
Composer path repositories should point to sibling sources, for example:
{
"type": "path",
"url": "../mortelos-mail",
"options": {
"symlink": true
}
}
Use a path repository only while developing or when a package remote is not available yet. Prefer tagged VCS dependencies for normal app installs.
Agent Rules
Package-specific agent instructions should be generated from package rules and docs, then merged into the host AGENTS.md.
Host apps should regenerate the merged block during Composer updates:
{
"scripts": {
"post-autoload-dump": [
"@php artisan package:discover --ansi",
"@php artisan mortelos:agent-rules:publish --target=AGENTS.md --no-interaction"
]
}
}
When a package boundary, widget convention or agent tool contract is unclear, consult the MortelOS docs before implementation and update the relevant package docs when the convention changes.
What stays in the host
Host apps own tenant config, local branding, policy defaults, local orchestration and customer-specific integrations.
Reusable packages own shared routes, views, Livewire namespaces, migrations, commands, extension contracts and tests when those concerns apply to more than one installation.
Examples
| Capability | Likely decision | Reason |
|---|---|---|
| Document review workflow | package-ready |
The host may need local policy and branding first, but review workflow behavior is reusable. |
| Moneybird sync | package-now |
The integration boundary can serve multiple installations. |
| One customer's internal KPI wording | workspace-only |
The behavior is specific to that workspace. |