RFC 005: package-bounded component resolution#37
Open
irl-dan wants to merge 1 commit into
Open
Conversation
Forme's current resolution rules (./name.md, ./name/index.md, .deps/, registry) force authors into flat layouts or require every internal module to be externalized as a git dep. Layered/categorized trees (responsibilities/, services/, services/firehose/, delivery/) have no resolution path today. Adds a package-bounded recursive walk as resolution rule (3). The package root is the nearest ancestor containing .prose/ or prose.lock. The walk finds .md files by frontmatter name: or filename stem, and skips .deps/, .prose/, .git/, build dirs, and _-prefixed directories. Ambiguity across the walk is a hard error — preserves T2 and T16. A structured path: field on the service entry remains as an escape hatch for cross-package refs and forced disambiguation. Convention over configuration: within a package, component names are unique identifiers. No per-program boilerplate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0ba5053 to
0529063
Compare
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.
Summary
Adds a package-bounded recursive walk as Forme's resolution rule (3), between the entry point's own directory and
.deps/. Authors organize files however they want; Forme finds components by name within the package.rfcs/005-flexible-component-resolution.mdskills/open-prose/forme.md§Step 2Why
Forme's current resolution is
./name.md→./name/index.md→.deps/→ registry. Works for flat trees and externalized-as-dep modules; does not accommodate the common layered shape that appears once a customer project grows past a handful of files:A delivery composite in
delivery/that references a responsibility inresponsibilities/(which delegates to services inservices/firehose/) has no resolution path today. Authors work around this by flattening the tree, forcing./name/index.mdsubdirs, externalizing every module as a git dep, or relying on runtime fuzzy matching — all unsatisfying.What changes
1. New resolution rule (3): package-bounded walk. From the entry point, walk up to the nearest ancestor containing
.prose/orprose.lock(the package root). Recursively scan every.mdfile in the subtree, matching by frontmattername:(or filename stem if noname:frontmatter). Excludes.deps/,.prose/,.git/,node_modules/,.venv/,dist/,build/,target/, and any_-prefixed directory.2. Structured
path:field on service entries. Escape hatch for cross-package references or forced disambiguation.path:is an absolute override — skips all other resolution rules.3. Ambiguity across the walk is a hard error. Two
.mdfiles with the same name in one package fails loudly, listing both paths. No silent "first wins." Authors resolve by renaming or pinning withpath:.Convention
Within a package, a component name is a unique identifier. Pick a name that reflects purpose; Forme finds the file. Zero per-program configuration.
Tenet check
forme.md.Compatibility
Fully backward compatible. Existing rules (1), (2), (4), (5) are unchanged. The walk rule (3) only fires when (1) and (2) don't match. Flat programs continue to resolve identically.
Trade-offs
In favor: zero per-program boilerplate, convention-over-configuration aligns with the "intelligent container" bet, name collisions surface as healthy early signals.
Against: Phase 1 cost is O(files-in-package) — typically hundreds of
.mdfiles, well under a second; collisions at scale (500+ components) require naming discipline; greenfield projects need a package marker (.prose/orprose.lock), a one-time setup cost.Open questions (also listed in the RFC)
std/-relative names we should exclude from the walk explicitly? (Today they're reachable via.deps/openprose/std/.)kind: testfiles — the walk finds them by name. Acceptable or worth calling out?.proseignorefile for author-level additions to the exclusion list? My lean: not in V1.Test plan
.mdpackage size (probably fine for Phase 1; worth flagging if ever a hot path)contract-markdown.mdordeps.md🤖 Generated with Claude Code