re #18 add univeros/agent-spec — AI-readable package manifests#52
Merged
Conversation
2bc507a to
91cd153
Compare
77677a1 to
9e14bc9
Compare
tonydspaniard
pushed a commit
that referenced
this pull request
May 26, 2026
PR #52's first end-to-end CI run after re-targeting base to master exposed 24 Rector findings in src/Altair/AgentSpec/ plus the same CLI issues already fixed in PR #23 (this branch was cut from feat/17 before those fixes landed). Applied: - All Rector quality/style rules across both sub-packages: blank lines after statements, final readonly classes when all props are readonly, catch-var name matching type, override attributes on interface impls, early returns, etc. - cs-fixer follow-up for files Rector renormalized. - rector.php skip for RemoveUnusedPublicMethodParameterRector on tests/Cli/Discovery/fixtures (mirrors the same fix landing in PR #23 — the fixture's __invoke parameters are the test surface). Local verification: phpstan + cs-fixer + rector all clean; 60 tests across tests/Cli + tests/AgentSpec pass (47 + 13).
added 3 commits
May 27, 2026 00:01
A new sub-package that introspects every framework package via PHP
reflection and emits deterministic Markdown manifests so AI coding
agents can understand the codebase without reading source.
Generator pipeline
- PackageScanner discovers sub-packages by walking src/Altair/* for
composer.json files; reads name, description, root namespace, and
required packages.
- ContractScanner reflects on each Contracts/*Interface.php, capturing
methods with short-name parameter types and directly-declared class
constants (inherited constants intentionally excluded to avoid noise).
- ConcreteClassScanner lists implementations outside Contracts/,
Exception/, Traits/; deduplicates implemented interfaces by short
name to avoid PSR-15-style duplicate "MiddlewareInterface" entries.
- AttributeScanner discovers ATTRIBUTE_* class constants — the
framework's convention for advertising PSR-7 request attribute keys.
- TestFixtureScanner enumerates *Test.php files under the mirrored
tests/<Pkg>/ tree.
- SidecarReader loads optional .agent/{purpose,patterns,stability}.md
fragments per package, since those cannot be derived from PHP source.
Rendering & output
- MarkdownPackageRenderer composes a PackageManifest into sectioned
Markdown: purpose, public contracts (table), concrete classes (list),
request attribute conventions (table), common patterns, tests as
documentation, related packages, stability note. Output is
byte-deterministic across runs (sorted lists, no timestamps).
- IndexGenerator writes the top-level .agent/MANIFEST.md with one row
per package linking into .agent/packages/<slug>.md.
- ApplicationManifestGenerator stub groups user classes by marker
attribute; lights up fully when #1, #3, #5 land.
- ManifestWriter handles both write and check (drift detection) modes.
CLI
Two attribute-driven commands built on the Altair\Cli substrate from
#17 and auto-discovered by bin/altair:
- manifest:generate [--check] writes manifests or exits 1 on drift
for CI gating.
- manifest:show <slug> regenerates a single package's manifest to
stdout for ad-hoc inspection.
PathResolver auto-detects the monorepo root by walking up from cwd.
Tests
13 tests / 41 assertions:
- PackageScanner discovery + determinism
- PackageManifestGenerator end-to-end model assembly
- MarkdownPackageRenderer snapshot test + determinism
- IndexGenerator coverage
- ManifestPipeline write/check/byte-idempotence drift detection
- ApplicationManifestGenerator marker-attribute grouping
Fixture package at tests/AgentSpec/Fixtures/SamplePackage/ exercises
contracts, concrete classes, ATTRIBUTE_* constants, sidecar files,
and test references. Snapshot in tests/AgentSpec/Snapshots/.
Generated artifacts
.agent/MANIFEST.md plus .agent/packages/*.md committed alongside the
generator so agents can read them out-of-the-box.
Depends on #17 (univeros/cli).
PR #52's first end-to-end CI run after re-targeting base to master exposed 24 Rector findings in src/Altair/AgentSpec/ plus the same CLI issues already fixed in PR #23 (this branch was cut from feat/17 before those fixes landed). Applied: - All Rector quality/style rules across both sub-packages: blank lines after statements, final readonly classes when all props are readonly, catch-var name matching type, override attributes on interface impls, early returns, etc. - cs-fixer follow-up for files Rector renormalized. - rector.php skip for RemoveUnusedPublicMethodParameterRector on tests/Cli/Discovery/fixtures (mirrors the same fix landing in PR #23 — the fixture's __invoke parameters are the test surface). Local verification: phpstan + cs-fixer + rector all clean; 60 tests across tests/Cli + tests/AgentSpec pass (47 + 13).
c384d6a to
c8eedea
Compare
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #18. Stacked on #23 (univeros/cli) — please review/merge #23 first, then change this PR's base to
master.Summary
univeros/agent-specis a new sub-package that walks every framework sub-package via PHP reflection and emits deterministic Markdown manifests so AI coding agents (Claude Code, Cursor, Codex…) can understand the codebase without reading source.bin/altair manifest:generate→ writes.agent/packages/*.md+.agent/MANIFEST.mdbin/altair manifest:generate --check→ exits 1 on drift; CI-gateablebin/altair manifest:show <slug>→ prints one package's manifest to stdoutOutput is byte-identical across runs (sorted lists, no timestamps).
What's generated per package
Each
<slug>.mdcovers (when applicable):composer.jsondescription (or<pkg>/.agent/purpose.mdoverride)Contracts/*Interface.php— methods, params, returns, direct constantsContracts/,Exception/,Traits/ATTRIBUTE_*class constants (the framework's PSR-7 convention)<pkg>/.agent/patterns.mdsidecar, split on---tests/<Pkg>/*Test.phpphp/ext-*)<pkg>/.agent/stability.mdsidecarArchitecture
Small, focused, immutable classes — every model is
readonly, every scanner is single-responsibility:CLI commands are attribute-driven (
#[Command(...)],#[Option(...)]) and auto-discovered bybin/altairfrom the existingAltair\Clisubstrate in #17.Tests
13 tests / 41 assertions, all green. PHPStan clean on the new code.
Coverage:
PackageScannerTest— discovery + determinismPackageManifestGeneratorTest— end-to-end model assemblyMarkdownPackageRendererTest— snapshot + determinismIndexGeneratorTest— top-level indexManifestPipelineTest— write, check, byte-idempotence, drift detectionApplicationManifestGeneratorTest— marker-attribute groupingFixture package at
tests/AgentSpec/Fixtures/SamplePackage/exercises every renderable section. Snapshot lives intests/AgentSpec/Snapshots/sample-package.md.Out of scope (per the issue)
ApplicationManifestGeneratorships as a stub today and lights up fully once Milestone tasks univeros components version 1.0.0 #1, Queue Library #3, and Add PSR-7 FileUpload validator #5 land.Test plan
composer dump-autoloadvendor/bin/phpunit tests/AgentSpec— 13/13 passvendor/bin/phpstan analyse src/Altair/AgentSpec tests/AgentSpec— no errorsbin/altair manifest:generate— produces.agent/packages/*.md+MANIFEST.mdfor all 18 packagesbin/altair manifest:generate --check— exits 0 on a fresh tree, 1 after tampering with any manifestbin/altair manifest:show cookie— prints cookie manifest to stdout.agent/packages/*.mdoutputs