You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: AGENTS.md
+117-1Lines changed: 117 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,6 +10,122 @@ Initial packages:
10
10
-`stellarwp/foundation-log`
11
11
-`stellarwp/foundation-pipeline`
12
12
13
+
## Namespaces
14
+
13
15
Use package namespaces under `StellarWP\Foundation\<Package>\`.
14
16
15
-
TODO: finish this.
17
+
## Code Organization
18
+
19
+
Prefer feature-first organization, also known as vertical slice architecture or package-by-feature, when adding command/tooling features. Group a command and its private collaborators under the command feature namespace.
20
+
21
+
For example, use:
22
+
23
+
```text
24
+
Commands/
25
+
Package/
26
+
Contracts/
27
+
PackageRepositoryCreator.php
28
+
CreateCommand.php
29
+
PackageResolver.php
30
+
PackageFilesValidator.php
31
+
GitHubPackageRepositoryCreator.php
32
+
```
33
+
34
+
instead of splitting those private collaborators into broad technical folders too early.
35
+
36
+
If a collaborator is only useful for one command group, keep it under that command group's feature folder. If it becomes useful across multiple command groups, promote it to a broader domain or infrastructure namespace such as `Package/`, `GitHub/`, `Console/`, or `Process/`.
37
+
38
+
When it is very clear that a class will be reused by many similar features, promote it immediately instead of burying it in the first feature slice. This is especially true for command/tooling infrastructure where many commands will need the same capability, such as shell command formatting, process execution, console IO helpers, package discovery, or GitHub API clients.
39
+
40
+
Feature-local interfaces should live in a `Contracts/` folder inside the feature slice, for example `Commands/Package/Contracts/PackageRepositoryCreator.php`. Only promote contracts to a package-level `Contracts/` namespace when they are intended to be shared across multiple features or consumed as public extension points.
41
+
42
+
Shared infrastructure interfaces should live under that shared namespace's `Contracts/` folder, for example `Process/Contracts/ProcessRunner.php`.
43
+
44
+
## Container Providers
45
+
46
+
When writing providers or container registration code, prefer container-driven construction over inline factories with explicit `new` calls. Bind classes and interfaces directly when the container can autowire them.
47
+
48
+
Use contextual bindings with `$this->container->when()->needs()->give()` for scalar constructor arguments, command lists, or feature-specific substitutions. Use a factory closure only when the value must be computed or resolved from the container, and keep that closure focused on supplying the constructor dependency rather than constructing the full object.
49
+
50
+
## Split Packages
51
+
52
+
Split packages live in `src/<Package>/` and are split to read-only repositories named `stellarwp/foundation-<package>`.
53
+
54
+
When adding a new split package, set its package `composer.json` PHP constraint to `>=8.3` unless the user explicitly says otherwise. PHP 7.4 release compatibility will be handled later by an automated Rector downgrade workflow, not by lowering the package PHP constraint during development.
55
+
56
+
When adding external dependencies for split packages, choose version constraints whose package line supports PHP 7.4. Use `>=` constraints for those dependencies instead of caret constraints when preserving the PHP 7.4-compatible floor matters. For example, use a Symfony component version such as `>=5.4` rather than a newer line that requires PHP 8+.
57
+
58
+
Important exception: dependencies on this monorepo's own split packages, such as `stellarwp/foundation-container`, should use the correct Composer release constraint like `^1.0`. Do not use `>=` for internal Foundation package dependencies; Monorepo Builder commands such as `composer monorepo bump-interdependency` are expected to bump those constraints during releases.
59
+
60
+
### Required Files
61
+
62
+
Each split package should include:
63
+
64
+
-`composer.json`
65
+
-`README.md`
66
+
-`.gitattributes`
67
+
-`.gitignore`
68
+
-`.github/workflows/close-pull-request.yml`
69
+
70
+
Each split package `README.md` must include this warning immediately after the package heading:
71
+
72
+
```markdown
73
+
> [!WARNING]
74
+
> **This is a read-only repository!** For pull requests or issues, see [stellarwp/foundation](https://github.com/stellarwp/foundation).
75
+
```
76
+
77
+
### GitHub Repositories
78
+
79
+
When creating a new split repository on GitHub, use the description `[READ ONLY] Subtree split of the Foundation <Component> component (see stellarwp/foundation)` and disable wikis, issues, projects, and pull requests.
80
+
81
+
## PHP Feature Policy
82
+
83
+
Allowed for current PHP 8.3 source:
84
+
85
+
- constructor property promotion
86
+
- union types
87
+
- intersection types
88
+
- readonly properties/classes
89
+
- enums
90
+
- nullsafe operator
91
+
- match expressions
92
+
- named arguments
93
+
- first-class callables
94
+
- typed class constants
95
+
96
+
Avoid unless there is a clear reason:
97
+
98
+
- enums in public APIs
99
+
- reflection-heavy code
100
+
- attributes that affect runtime behavior
101
+
- DNF types
102
+
-`never` in public APIs
103
+
104
+
Banned while the project targets PHP 8.3:
105
+
106
+
- PHP 8.4 property hooks
107
+
- PHP 8.4 asymmetric visibility
108
+
- PHP 8.4 lazy objects API
109
+
-`#[Deprecated]`; use `@deprecated` PHPDoc instead
110
+
- PHP 8.4-only functions/classes/constants
111
+
112
+
## Monorepo Commands
113
+
114
+
After adding or changing split package dependencies, run `composer monorepo merge` and then `composer update` so root `composer.json`/lock state includes package dependency changes.
115
+
116
+
Use `composer monorepo list` to inspect available Monorepo Builder commands.
117
+
118
+
## Verification
119
+
120
+
When `composer lint` reports style-only issues, run `composer format` to let the project formatter fix them before making manual formatting edits.
121
+
122
+
Reusable test fixtures, sample classes, and test doubles should live under `tests/Support/Fixtures/<Namespace>/` instead of being declared inline in a test class file. Keep truly local one-off fakes inline only when they are not reusable and do not represent a domain/package fixture.
123
+
124
+
After completing a feature, run `composer test:coverage`, review `clover.xml` for missed source coverage, and add meaningful tests for uncovered behavior before considering the feature complete.
125
+
126
+
## Releases
127
+
128
+
- Adding a new split package is usually a minor SemVer release because it introduces new functionality without breaking existing packages. Use a major release only if the change also breaks an existing public API or package contract.
129
+
- Run `composer monorepo bump-interdependency <version>` when planning a major version release so Foundation packages that depend on each other require the new major line. It may also be useful for a minor release when one package must require APIs added in that new minor.
130
+
- Run `composer monorepo package-alias` when `dev-main` should move to a new development line, usually after a minor or major release. Do not run it for every patch release when the current branch alias is still correct.
131
+
- The monorepo split workflow deploys package code to each sub-repository after a GitHub release is drafted.
Copy file name to clipboardExpand all lines: README.md
+25-4Lines changed: 25 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -80,17 +80,38 @@ After any needed command, commit the updated `composer.json` files. Then draft a
80
80
81
81
The [monorepo split GitHub workflow](./.github/workflows/monorepo-split.yml) will deploy each project's code to their sub-repository.
82
82
83
+
Adding a new split package is usually a minor [semver](https://semver.org/) release because it adds new functionality without breaking existing packages. Use a major release only if the change also breaks an existing public API or package contract.
84
+
83
85
### Monorepo
84
86
85
87
This uses [Symplify's Monorepo Builder](https://github.com/symplify/monorepo-builder). There is a shortcut composer script you can
86
88
run to access their CLI: `composer monorepo list` to see the available commands.
87
89
88
90
#### Adding a New Package
89
91
90
-
1. Copy the composer.json from one of the packages and modify the `name` and `psr-4` autoload namespace.
91
-
2. Ensure you have the `close-pull-request.yml` GitHub workflow, a `.gitattributes`, `.gitignore` and `README.md` files.
92
-
3. Once you've added the specific dependencies your package needs to its composer.json, run `composer monorepo merge` and then `composer update` and commit the changes. This will merge the dependencies into the root composer.json.
93
-
4. Create your [new repository](https://github.com/organizations/stellarwp/repositories/new), add the description: `[READ ONLY] Subtree split of the Foundation <NEW_COMPONENT_NAME> component (see stellarwp/foundation)` and disable wikis, issues, projects and pull requests.
92
+
1. Run the package creation command:
93
+
94
+
```bash
95
+
composer run foundation -- package:create <Package>
96
+
```
97
+
98
+
The package argument can be a new package component such as `WPCli`, an existing package directory, short package name, or Composer package name, for example `Log`, `foundation-log`, or `stellarwp/foundation-log`.
99
+
100
+
If the package does not exist yet, the command asks whether to create the local scaffold in `src/<Package>` and asks for the Composer package name with a default such as `stellarwp/foundation-wpcli`. The scaffold includes the required `composer.json`, `README.md`, `.gitattributes`, `.gitignore`, and `close-pull-request.yml` files. After scaffolding, the command runs `composer monorepo merge` so the root `composer.json` includes the new package.
101
+
102
+
The command runs as a dry run by default. It validates the required split package files, prints the target repository name and description, and shows the GitHub CLI commands it will run.
103
+
104
+
2. Add source code, tests, and any package-specific dependencies to the new package.
105
+
106
+
3. Once you've added the specific dependencies your package needs to its composer.json, run `composer monorepo merge` again and then `composer update` and commit the changes. This will merge the dependency changes into the root composer.json.
107
+
108
+
4. Create and configure the read-only split repository:
109
+
110
+
```bash
111
+
composer run foundation -- package:create <Package> --apply
112
+
```
113
+
114
+
The command creates the `stellarwp/foundation-<package>` repository with the standard `[READ ONLY]` description, disables issues, wiki, and projects, and relies on the package's `close-pull-request.yml` workflow to close pull requests.
0 commit comments