# Dependency notes for PHP

`composer.json` is JSON, and JSON has [no comments](https://pacmon.dev/composer-json-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

```json
{
  "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`:

```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](https://pacmon.dev/composer-json-comments/) 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](https://pacmon.dev/agents/).
