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
The public Plan seam is surrounded by a large, externally visible implementation pipeline. Understanding how one contribution becomes a planned outcome currently requires following several modules and an intermediate representation that permits many invalid combinations.
flowchart LR
B[Blueprint] --> R[ContributionResolver service]
R --> N[NormalizedContributions]
N --> C[PlanningIntentCompiler service]
C --> W[wide PlanningIntentPath]
W --> A[PlanAssessor service]
A --> P[Plan]
Loading
PlanningIntentPath holds numerous independent arrays and optional fields:
The compiler must then maintain a family compatibility matrix, while the assessor rediscovers which combination it received. The JSX-slot defect in #178 demonstrates how easily a contribution family can be accepted by one part of the pipeline and omitted by another.
Two pure transformations are represented as injectable Effect services with no external dependencies:
CLI catalog/debug behavior consumes ContributionResolver directly, bypassing PlanService. Meanwhile, NormalizedContributions lives in the domain package even though it is an internal handoff, while other planning-intent types remain private. The public seam is therefore less clear than the canonical Blueprint -> Plan flow suggests.
Contribution token handling adds another manifestation of the same problem: resolution is distributed by contribution tag, and several string-bearing structural fields are treated differently from paths, contents, and package fields. The contract does not make clear which fields may contain tokens.
Why does this matter?
Changes to one contribution kind require coordinated edits across several shallow modules.
Intermediate invalid states are representable and must be rejected later.
Test setup reflects internal module topology instead of the public Plan behavior.
CLI consumers can couple themselves to transitional planning representations.
Token behavior depends on which internal branch processes a contribution.
The package interface implies supported substitution seams that the current CLI does not need.
The objective is a deeper Plan module: a small stable interface with enough internal implementation to absorb planning complexity. This issue intentionally does not prescribe the exact internal types, number of files, or whether every existing service must disappear.
Scope
Public versus internal planning interfaces in @repo/scaffold.
The representation used to group compatible contribution intent per path.
Invalid combinations and exhaustive handling of contribution kinds.
Whether stateless planning transformations earn injectable service seams.
A deliberate query interface for CLI catalog inspection if that use case must remain.
An explicit, exhaustive token-resolution contract for contribution fields.
Tests organized around public Plan behavior plus focused internal pure behavior where valuable.
Acceptance criteria
Consumers can use the supported Blueprint -> Plan behavior without importing planner implementation modules.
Every supported contribution kind maps exhaustively to one valid planning behavior or an explicit incompatibility.
The per-path planning representation does not permit arbitrary incompatible family combinations without immediate validation.
Adding or changing one contribution kind has one clear locality for compilation and assessment behavior.
Dependency injection is retained only where the module provides meaningful substitution or side-effect isolation.
CLI catalog inspection uses an intentional public interface rather than a Plan implementation helper.
Token-capable fields and token resolution behavior are explicitly defined and tested for every contribution tag.
The package export surface distinguishes lifecycle use cases from implementation details.
Plan tests no longer require replacing pure implementation helpers merely to exercise the public interface.
What problem are we solving?
The public Plan seam is surrounded by a large, externally visible implementation pipeline. Understanding how one contribution becomes a planned outcome currently requires following several modules and an intermediate representation that permits many invalid combinations.
PlanningIntentPathholds numerous independent arrays and optional fields:The compiler must then maintain a family compatibility matrix, while the assessor rediscovers which combination it received. The JSX-slot defect in #178 demonstrates how easily a contribution family can be accepted by one part of the pipeline and omitted by another.
Two pure transformations are represented as injectable Effect services with no external dependencies:
This forces Plan tests to construct and override a multi-layer service graph without providing a real production adapter seam.
Planner internals are also exported from
@repo/scaffold:CLI catalog/debug behavior consumes
ContributionResolverdirectly, bypassingPlanService. Meanwhile,NormalizedContributionslives in the domain package even though it is an internal handoff, while other planning-intent types remain private. The public seam is therefore less clear than the canonicalBlueprint -> Planflow suggests.Contribution token handling adds another manifestation of the same problem: resolution is distributed by contribution tag, and several string-bearing structural fields are treated differently from paths, contents, and package fields. The contract does not make clear which fields may contain tokens.
Why does this matter?
The objective is a deeper Plan module: a small stable interface with enough internal implementation to absorb planning complexity. This issue intentionally does not prescribe the exact internal types, number of files, or whether every existing service must disappear.
Scope
@repo/scaffold.Acceptance criteria
Blueprint -> Planbehavior without importing planner implementation modules.Blocked by