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
Build univeros/agent-spec — a manifest generator that emits machine-readable descriptions of every framework package and every user-defined endpoint/command/event/job, so AI coding agents (Claude Code, Cursor, Codex, etc.) can understand the codebase in seconds without reading source.
Concretely: a CLI command that walks the framework's packages and the user's application, and writes per-package .agent/MANIFEST.md files plus a global index.
Why this is the framework's differentiator
The framework's current modernization already makes it the most agent-friendly PHP framework on the market (no magic, fully typed, single-pass middleware, readonly value objects). But "agent-friendly source code" still requires the agent to read the source. A manifest collapses that — the agent reads one structured file and knows what's available, what types flow through, what tests assert, where to look next.
This is the pitch:
univeros is the only PHP framework where an AI agent can be productive without reading a line of framework source.
Manifest format (per package)
Markdown, structured, deterministic. Example for univeros/http:
# univeros/http · Altair\Http**Purpose:** PSR-15 HTTP middleware pipeline + Action/Domain/Input/Responder application layer.
## Public contracts| Interface | Method | Returns | Notes ||---|---|---|---||`MiddlewareInterface`|`process(ServerRequestInterface, RequestHandlerInterface)`|`ResponseInterface`| Extends `Psr\Http\Server\MiddlewareInterface` + adds attribute constants ||`ResponderInterface`|`__invoke(ServerRequestInterface, ResponseInterface, PayloadInterface)`|`ResponseInterface`|||`FormatNegotiatorInterface`|`getFromServerRequestUriPath`, `getFromServerRequestHeaderLine`, `getContentTypeByFormat`| various ||## Concrete middleware (PSR-15)-`IpAddressMiddleware` — populates `MiddlewareInterface::ATTRIBUTE_IP_ADDRESS` with detected client IPs
-`IpRestrictionMiddleware` — CIDR-based allow/deny based on the above attribute
-`CorsMiddleware`, `CsrfMiddleware`, `CacheMiddleware`, `ExceptionHandlerMiddleware`, `FormatNegotiatorMiddleware`, `BasicAuthenticationMiddleware`, `DigestAuthenticationMiddleware`, `TokenAuthenticationMiddleware`, `SpamBlockerMiddleware`, `DispatcherMiddleware`, `JsonContentMiddleware`, `FormContentMiddleware`, `SessionHeadersMiddleware`, `ActionMiddleware`## Request attribute conventions| Attribute | Set by | Consumed by | Type ||---|---|---|---||`altair:http:ip-address`|`IpAddressMiddleware`|`IpRestrictionMiddleware`, app code |`list<string>`||`altair:http:action`|`DispatcherMiddleware`|`ActionMiddleware`|`Altair\Http\Base\Action`||`altair:http:format`|`FormatNegotiatorMiddleware`| responders |`string`||`altair:http:username`|`BasicAuth`/`DigestAuth`| app |`string`||`altair:http:exception`|`ExceptionHandlerMiddleware`| error responders |`Throwable`|## Common patterns### Build a middleware pipeline```php
new Relay([
new IpAddressMiddleware(),
new IpRestrictionMiddleware($responseFactory, deny: ['10.0.0.0/8']),
new CorsMiddleware($analyzer, $responseFactory),
new ActionMiddleware($resolver, $responseFactory),
])
Short-circuit early
Middleware that fail closed (auth, IP block, CSRF) return a response built via ResponseFactoryInterface rather than calling $handler->handle().
Tests as documentation
tests/Http/Middleware/IpAddressMiddlewareTest.php — IP extraction conventions
univeros/cookie — used by session + csrf middleware
Stability
PSR-15 single-pass migration completed 2026-05. No deprecated APIs remain.
The same structure for every package, plus a per-application manifest that lists user-defined endpoints, commands, events, and jobs (once the scaffolder from #3 / #5 lands).
## Why Markdown not JSON?
Two reasons:
- Agents are LLMs; they read Markdown faster than JSON. Tables + bullets compress better in context than nested JSON.
- Markdown renders on github.com for free, so it doubles as human-readable docs (the #15 docs link to manifests for "go deeper").
A `.json` sidecar can be emitted alongside the Markdown for tools that need structured data (search index, autocomplete extensions).
## Shape
src/Altair/AgentSpec/
├── Cli/
│ └── GenerateManifestCommand.php # bin/altair manifest:generate
├── Generator/
│ ├── PackageManifestGenerator.php # introspects one src/Altair//
│ ├── ApplicationManifestGenerator.php # introspects user app code
│ └── IndexGenerator.php # the top-level .agent/MANIFEST.md
├── Reflection/
│ ├── ContractScanner.php # finds interfaces under Contracts/
│ ├── AttributeScanner.php # finds class-level constants like ATTRIBUTE_*
│ └── TestFixtureScanner.php # collects test file paths per source class
├── Template/
│ └── *.md.twig # one per section (or built-in to PHP, doesn't have to be twig)
└── composer.json
CLI:
```bash
bin/altair manifest:generate # writes to .agent/packages/*.md + .agent/MANIFEST.md
bin/altair manifest:generate --check # exit 1 if manifests are out of date with source
bin/altair manifest:show http # print one package's manifest to stdout
The framework:// resolver (stretch goal)
Optional helper: a tiny HTTP server (or CLI subcommand) that serves manifest contents via the framework:// URI scheme so agents can fetch sections without filesystem access. framework://packages/http/middleware → the Middleware section of http's manifest. Skip if it complicates the v1 scope.
Acceptance criteria
Running bin/altair manifest:generate from the monorepo root produces .agent/packages/<pkg>.md for all 16 framework packages
Each manifest covers: purpose, public contracts (table), concrete classes (list), attribute conventions where applicable, common patterns (2–4 code blocks), test-file references, related packages, stability note
Output is deterministic — running twice produces byte-identical files (no timestamps, no random ordering, sorted lists)
--check mode: compares regenerated content to disk; exits non-zero on diff; CI can use this to enforce manifests stay current
.agent/MANIFEST.md index lists every package with a one-line description + link
Goal
Build
univeros/agent-spec— a manifest generator that emits machine-readable descriptions of every framework package and every user-defined endpoint/command/event/job, so AI coding agents (Claude Code, Cursor, Codex, etc.) can understand the codebase in seconds without reading source.Concretely: a CLI command that walks the framework's packages and the user's application, and writes per-package
.agent/MANIFEST.mdfiles plus a global index.Why this is the framework's differentiator
The framework's current modernization already makes it the most agent-friendly PHP framework on the market (no magic, fully typed, single-pass middleware, readonly value objects). But "agent-friendly source code" still requires the agent to read the source. A manifest collapses that — the agent reads one structured file and knows what's available, what types flow through, what tests assert, where to look next.
This is the pitch:
Manifest format (per package)
Markdown, structured, deterministic. Example for
univeros/http:Short-circuit early
Middleware that fail closed (auth, IP block, CSRF) return a response built via
ResponseFactoryInterfacerather than calling$handler->handle().Tests as documentation
tests/Http/Middleware/IpAddressMiddlewareTest.php— IP extraction conventionstests/Http/Middleware/IpRestrictionMiddlewareTest.php— allow/deny precedencetests/Http/Support/CidrMatcherTest.php— CIDR matching edge casesRelated packages
univeros/middleware— non-HTTP middleware substrateuniveros/session—SessionHeadersMiddlewareconsumeruniveros/cookie— used by session + csrf middlewareStability
PSR-15 single-pass migration completed 2026-05. No deprecated APIs remain.
src/Altair/AgentSpec/
├── Cli/
│ └── GenerateManifestCommand.php #
bin/altair manifest:generate├── Generator/
│ ├── PackageManifestGenerator.php # introspects one src/Altair//
│ ├── ApplicationManifestGenerator.php # introspects user app code
│ └── IndexGenerator.php # the top-level .agent/MANIFEST.md
├── Reflection/
│ ├── ContractScanner.php # finds interfaces under Contracts/
│ ├── AttributeScanner.php # finds class-level constants like ATTRIBUTE_*
│ └── TestFixtureScanner.php # collects test file paths per source class
├── Template/
│ └── *.md.twig # one per section (or built-in to PHP, doesn't have to be twig)
└── composer.json
The
framework://resolver (stretch goal)Optional helper: a tiny HTTP server (or CLI subcommand) that serves manifest contents via the
framework://URI scheme so agents can fetch sections without filesystem access.framework://packages/http/middleware→ the Middleware section ofhttp's manifest. Skip if it complicates the v1 scope.Acceptance criteria
bin/altair manifest:generatefrom the monorepo root produces.agent/packages/<pkg>.mdfor all 16 framework packages--checkmode: compares regenerated content to disk; exits non-zero on diff; CI can use this to enforce manifests stay current.agent/MANIFEST.mdindex lists every package with a one-line description + linktests/AgentSpec/PackageManifestGeneratorTest.php— fixture package → expected manifesttests/AgentSpec/IndexGeneratorTest.phpuniveros/cookie, regenerate, diffOut of scope
Dependencies
univeros/cli) — the manifest command needs the CLI substrate