Dependency notes for PHP
composer.json is JSON, and JSON has no comments. A require entry names a package and the versions a project accepts, and that is all: not why the package is there, why its constraint stops below the next major, or what to run after composer update moves it.
Pacmon keeps a note for each package in .pacmon/composer/DEPENDENCY-NOTES.md, beside composer.json, and shows it on the package's line. Platform requirements get notes too, so the reason a project needs ext-intl or a given php version sits beside the requirement.
What Pacmon reads
- Manifest:
composer.json - Notes file:
.pacmon/composer/DEPENDENCY-NOTES.md - Section heading: the case-insensitive package or platform name:
## monolog/monolog,## php,## ext-mbstring
Pacmon reads package and platform requirements in the root require and require-dev objects of composer.json, including php, php-*, hhvm, ext-*, lib-* and Composer API packages. Names are matched case-insensitively. provide, replace, conflict, suggest, composer.lock and transitive packages are not dependencies.
Pacmon never runs PHP or Composer, so neither has to be installed.
Example
{
"require": {
"php": "^8.3",
"ext-intl": "*",
"guzzlehttp/guzzle": "^7.9",
"monolog/monolog": "^3.8"
},
"require-dev": {
"phpunit/phpunit": "^11.5"
}
}
.pacmon/composer/DEPENDENCY-NOTES.md:
## guzzlehttp/guzzle
HTTP client for the payment provider. Call it through src/Payments/Client.php.
### Agent notes
- purpose: HTTP client for the payment provider and the shipping-rate APIs
- usage: only through src/Payments/Client.php, which sets the timeouts and retries
- verify: `vendor/bin/phpunit --testsuite payments`
- verified: 7.9.2
The heading is the package or platform name as require writes it, in lower case: "guzzlehttp/guzzle" is ## guzzlehttp/guzzle, "ext-intl" is ## ext-intl, and the PHP version itself is ## php.
Comments in composer.json
Composer refuses a // or /* */ comment anywhere in composer.json: every command stops with Comments are not allowed. The place Composer documents for comments is a top-level _comment key, a string or an array of strings. It sits away from the packages it is about, and it outlives them: composer remove leaves it behind. Comments in composer.json goes through each workaround and what Composer does with it.
Pinning a version
composer require monolog/monolog writes a caret constraint on the newest version, such as "^3.12", which accepts any later 3.x release. A version on its own, "3.8.0", means that version only, and composer validate warns that such an exact constraint should be avoided for a package that follows semantic versioning.
composer.lock records the exact version of every package, and composer install installs exactly that. composer update monolog/monolog moves only the packages it names. Why a constraint stops where it does goes in the package's note, as constraint:.
For AI coding agents
An agent reads a package's section before it adds, upgrades or removes the package. usage: says where the code calls it, and verify: which tests to run after the version moves. See the rules agents follow.