Skip to content

re #18 add univeros/agent-spec — AI-readable package manifests#52

Merged
tonydspaniard merged 3 commits into
masterfrom
feat/18-agent-spec
May 26, 2026
Merged

re #18 add univeros/agent-spec — AI-readable package manifests#52
tonydspaniard merged 3 commits into
masterfrom
feat/18-agent-spec

Conversation

@tonydspaniard
Copy link
Copy Markdown
Member

@tonydspaniard tonydspaniard commented May 26, 2026

Closes #18. Stacked on #23 (univeros/cli) — please review/merge #23 first, then change this PR's base to master.

Summary

univeros/agent-spec is 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.md
  • bin/altair manifest:generate --check → exits 1 on drift; CI-gateable
  • bin/altair manifest:show <slug> → prints one package's manifest to stdout

Output is byte-identical across runs (sorted lists, no timestamps).

What's generated per package

Each <slug>.md covers (when applicable):

Section Source
Purpose composer.json description (or <pkg>/.agent/purpose.md override)
Public contracts reflection of Contracts/*Interface.php — methods, params, returns, direct constants
Concrete classes reflection of everything outside Contracts/, Exception/, Traits/
Request attribute conventions ATTRIBUTE_* class constants (the framework's PSR-7 convention)
Common patterns optional <pkg>/.agent/patterns.md sidecar, split on ---
Tests as documentation enumeration of tests/<Pkg>/*Test.php
Related packages composer require list (excluding php/ext-*)
Stability optional <pkg>/.agent/stability.md sidecar

Architecture

Small, focused, immutable classes — every model is readonly, every scanner is single-responsibility:

src/Altair/AgentSpec/
├── Cli/         — manifest:generate / manifest:show, PathResolver, ConsoleReporter
├── Contracts/   — PackageScannerInterface, ManifestRendererInterface, PhpFileFinderInterface
├── Exception/   — AgentSpecException, ManifestDriftException
├── Generator/   — PackageManifestGenerator, IndexGenerator, ApplicationManifestGenerator, ManifestPipeline
├── Model/       — PackageManifest, PackageDescriptor, ContractEntry, ClassEntry, AttributeConvention, MethodSignature, TestReference
├── Reflection/  — PackageScanner, ContractScanner, ConcreteClassScanner, AttributeScanner, TestFixtureScanner, SidecarReader, ClassNameExtractor, TypeStringRenderer, PhpFileFinder
├── Renderer/    — MarkdownPackageRenderer
├── Writer/      — ManifestWriter (write + check modes)
└── composer.json

CLI commands are attribute-driven (#[Command(...)], #[Option(...)]) and auto-discovered by bin/altair from the existing Altair\Cli substrate in #17.

Tests

13 tests / 41 assertions, all green. PHPStan clean on the new code.

Coverage:

  • PackageScannerTest — discovery + determinism
  • PackageManifestGeneratorTest — end-to-end model assembly
  • MarkdownPackageRendererTest — snapshot + determinism
  • IndexGeneratorTest — top-level index
  • ManifestPipelineTest — write, check, byte-idempotence, drift detection
  • ApplicationManifestGeneratorTest — marker-attribute grouping

Fixture package at tests/AgentSpec/Fixtures/SamplePackage/ exercises every renderable section. Snapshot lives in tests/AgentSpec/Snapshots/sample-package.md.

Out of scope (per the issue)

Test plan

  • composer dump-autoload
  • vendor/bin/phpunit tests/AgentSpec — 13/13 pass
  • vendor/bin/phpstan analyse src/Altair/AgentSpec tests/AgentSpec — no errors
  • bin/altair manifest:generate — produces .agent/packages/*.md + MANIFEST.md for all 18 packages
  • bin/altair manifest:generate --check — exits 0 on a fresh tree, 1 after tampering with any manifest
  • bin/altair manifest:show cookie — prints cookie manifest to stdout
  • Manual review of the committed .agent/packages/*.md outputs

@tonydspaniard tonydspaniard force-pushed the feat/17-univeros-cli branch from 2bc507a to 91cd153 Compare May 26, 2026 21:44
@tonydspaniard tonydspaniard changed the base branch from feat/17-univeros-cli to master May 26, 2026 21:53
@tonydspaniard tonydspaniard reopened this May 26, 2026
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).
@tonydspaniard tonydspaniard reopened this May 26, 2026
Antonio Ramirez 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).
@tonydspaniard tonydspaniard merged commit a2ee683 into master May 26, 2026
3 checks passed
@tonydspaniard tonydspaniard deleted the feat/18-agent-spec branch May 27, 2026 05:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

univeros/agent-spec — AI-readable manifests for every package

1 participant