Production catalog architecture¶
The production catalog closes the source-authority boundary for production Composition components and recipes. It defines which canonical component descriptors and recipes participate in supported consumer composition; it does not itself resolve or materialize a concrete consumer repository.
Authority¶
catalog/catalog.json is the inventory authority. It does not duplicate full descriptors or recipes; it names the component and recipe IDs whose canonical documents live at deterministic repository paths.
The catalog is intentionally closed:
catalog component IDs == components/*/component.json identities
catalog recipe IDs == recipes/*.json identities
An unlisted component directory or recipe file is invalid, as is a catalog entry without its canonical file.
Component source closure¶
For copied managed or seed material, materials[].source is relative to the component directory. Production components use a conventional files/ subtree, and every regular file below that subtree must be declared by exactly one copied material.
This makes component source content reviewable as a closed set rather than allowing undeclared files to acquire accidental authority.
Dependency graph¶
Catalog validation requires dependency references to exist and the production graph to be acyclic. Generic capability/lifecycle descriptors must not depend on or conflict with artifact-specific components. Foundation components provide shared mandatory bases for artifact identities and are reached through dependency closure rather than direct recipe selection.
This is source-graph validation, not concrete consumer resolution. The Composer separately applies a recipe, explicit consumer include/exclude intent, parameters, conflicts, and transitive dependency closure to derive one consumer-specific component set.
Recipe validation¶
Every production recipe names one catalog artifact and only catalog capability/lifecycle selections. Required/default/optional groups are pairwise disjoint. Foundation components are not recipe selections: an artifact requires them and the Composer resolves them transitively.
The skill recipe intentionally has no default application capabilities. This preserves the minimal Agent Skill: runtime and public interfaces are opt-in rather than silently materialized.
The website and webapp recipes both resolve the shared foundation.web through their artifact dependency, but remain sibling artifact identities. website adds Website-owned page structure, document metadata, discovery, and Website evidence semantics. webapp adds application-specific routes, surfaces, UI states, and Webapp evidence semantics. Static generation, server rendering, client rendering, CDN hosting, runtime selection, and PWA selection do not choose between the two artifact recipes.
Both browser-facing recipes keep application capabilities optional. Their artifact baselines require reusable implementation evidence, which brings contract evolution transitively, while lifecycle.release-bundle is exposed as an explicit top-level release selection. Runtime selection and release selection are therefore independent consumer intent. capability.pwa is likewise an optional artifact-neutral capability and may be selected by either website or webapp without changing artifact identity.
For Webapp compatibility history, artifact.webapp-core v4 separated the release lifecycle from the baseline. Earlier v3 Webapps received the complete release chain transitively. A v4 upgrade that intends to retain that behavior explicitly selects lifecycle.release-bundle; an upgrade that omits it receives only the Webapp evidence baseline.
Portable destination ownership¶
A resolved production selection must have one portable owner per materialized destination. Validation compares destinations case-insensitively for portable ASCII path identity and rejects file/directory-prefix collisions.
The maximal selection of every current production recipe is regression-tested for this invariant, including all exposed optional capabilities and the complete transitive lifecycle closure. Adding a foundation, artifact, capability, lifecycle component, or recipe must preserve the same ownership rule.
Catalog and consumer resolution¶
The production catalog and the Composer have separate responsibilities. The catalog proves that the available source graph is closed and internally valid. The Composer consumes that validated graph together with a recipe and consumer intent, computes one deterministic resolved closure, materializes copied and generated bytes, and records the resulting managed state in .template-composition/lock.json.
For a new repository, initial composition derives the lock from explicit consumer configuration. For an existing managed repository, update reuses the normalized intent already stored in lock schema version 2, while upgrade accepts explicit replacement intent for compatibility-boundary changes. Planning remains read-only and produces the complete target closure and lock preview before apply mutates managed state.
The lock therefore records a concrete resolution, not a second source catalog. It binds the exact Composition source revision, normalized consumer intent, recipe and component descriptor identities, and materialized destination ownership/digests for that consumer state. Validator dispatch uses that resolved component set rather than inferring intent from files that happen to remain on disk.
See the Composition model for the full authority and ownership model and Composer architecture for resolution, managed reconciliation, transaction, and recovery behavior.