Supporting reference · Working design and evidence, not a promise of complete support.

On this page

Rails Core composition

Status: Implemented for the pinned Rails Core and the bounded Capabilities and Domain the Compiler emits.

Every generated Rails application starts from one pinned Foundation Rails Core archive. The Compiler loads that archive as values, adds renderer output for the selected Capabilities and Domain, and checks path ownership before anything is written. Core paths are immutable unless an explicit registry transfers one path to one named renderer. A dependency plan projects one complete Gemfile and Gemfile.lock from a qualified universe without network access. The Compiler also writes the application's README, AGENTS, and UI documents, substitutes the application identity into Core's configuration, and verifies that no reusable-Core identity token remains. The Rails target profile states the Core, Capabilities, and Domain concept, and the Compiler owner owns rendering and packaging.

On this page

Core pin

The prototype bundles the current Rails Core pin (repository-only) as a deterministic compressed Git archive. The only released tag, v0.1.0, predates material fixes, so this is recorded as an exact revision rather than a release. In pre-alpha mode, a Core repin may repair the current target profile's constant, route, and inflection census in place only after complete local re-extraction and review of the active-pin surfaces. The machine reference (repository-only) names that profile. Cross-platform hosted reproduction on both profile platforms is the landing gate. The dangerous-attribute registry was re-extracted from Core c7955bee62f3e5033f6fa2551aa4e12d22a55be6 under Rails 8.1.4 for the rails-sketch/2026-10 profile and reproduced locally and in hosted CI. No retained-Project migration or coexistence machinery is added; a profile repair starts a new Project or an explicit fork. A later package update should move the same loading boundary to a verified Core release asset.

Moving the pin is an explicit maintenance operation. It verifies the archive digest, embedded revision, root, regular-file count, uncompressed bytes, and lockfile digest; regenerates the maximal dependency universe when Core inputs change; refreshes exact output characterizations; and reruns current-pin profile compatibility and generated-app qualification. Review changed Core commands, dependencies, and UI APIs against the complete application README, AGENTS, and UI templates so their operating guidance stays accurate. Reconcile relevant facts; those templates need not copy Core's contributor prose. A repin removes the superseded archive and dependency pairs unless code, tests, or a frozen profile name them; Git history keeps their bytes. User compilations remain network-free. The loader verifies the compressed-byte SHA-256 and Git revision in the global PAX header before it exposes file values. It accepts regular files and directories, rejects links and special entries, strips one required root, reduces Git's executable bit to 0644 or 0755, and passes the complete file set through OutputManifest.

The profile workflow automatically compares every changed active archive with the frozen compatible surfaces on arm64 Darwin and x86-64 Linux through script/verify_rails_target_profile_compatibility. The default Actions token cannot read the private sibling Core repository, so script/release check reads Core main through gh on the release operator's machine instead. When the pin lags, it warns and lists the missing commits. Merging a Core pull request approves adopting it in the next Compiler release unless the pull request is labeled for separate approval; see owner sign-off (repository-only).

Dev Container

The generated Dev Container selects PostgreSQL client 18 to match its PostgreSQL 18 service. It omits the unused Active Storage media feature; applications adding image variants or previews choose and install their processor. The Dev Container adoption (repository-only) records the exact package and qualification boundary. That adoption changed the Compiler release while retaining its Plan, API, Analyzer, and target profile.

Path ownership

All Core paths are immutable by default. CorePathRegistry contains only explicit path-to-renderer ownership transfers. A registered replacement is required from that exact renderer owner; an absent replacement, a different claimant, or any undeclared collision fails. The default registry transfers nine paths. Five concrete renderers own config/application.rb, config/database.yml, config/locales/en.yml, render.yaml, and README.md; application-document renderers own AGENTS.md and UI.md; the schema renderer owns db/schema.rb; and the application-global renderer owns app/controllers/application_controller.rb. The active application plan adds the Domain-routes and main-navigation Web transfers that Web files and routes describes, plus unconditional Gemfile and Gemfile.lock transfers to their separate generic renderers. Account qualification changes dependency-plan and ApplicationController content without changing global file ownership. It also changes the generic Domain-routes and main-navigation outputs through shared semantic evidence. The Account-self renderer owns only app/controllers/accounts_controller.rb, app/views/accounts/show.html.erb, and its locale. The Web families do not claim Core's application layout. Core retains the layout and responsive navigation. The task plan preflights every selected task-backed transfer, and CoreComposer enforces the planned owner during composition.

Rails frameworks

Implemented. An application requires the Rails frameworks its Plan uses, as Rails 8.1.4 rails new writes them with the --skip flags that fit the Plan, instead of Core's require "rails/all". The owner made this derived-frameworks decision (repository-only) during the emitted-code audit.

Core keeps rails/all, so the profile's constant and route census still covers every Rails framework. An application that loads fewer frameworks occupies a subset of those names and routes, which keeps name availability conservative. Changing Core's requires would change both censuses, and a route-claim change needs a new profile ID.

Core itself leaves out jbuilder, as rails new --skip-jbuilder does, because no Plan has a JSON surface and the Compiler only adds to Core's Gemfile. A Plan-derived removal would have needed a removal path, a projected lockfile for every Plan, and new dependency pairs, all to remove a gem from every application. A future JSON surface can add the gem through a dependency contributor. Pagy and include Pagy::Method stay in every application, without Pagy's sample initializer, so an agent adding a list finds pagination already wired.

Dependency projection

RailsDependencyPlan receives the complete sealed Project, exact compilation input, and base rendering context. Each selected contributor supplies one internal immutable identifier, direct-requirement set, complete Gemfile block, prerequisite list, and source identities. Policy requires Account. The planner orders contributors, rejects duplicate or conflicting claims, coalesces shared identical requirements, and checks every contributor against its digest-gated universe entry, including its prerequisite list. Every contributed requirement must also be a direct dependency of the maximal lock, not merely a reachable specification. Account, Attachment, Normalization, Policy, and State Machine are the current entries. Attachment contributes pinned cloudinary only when an emitted Field is an attachment or image. Normalization contributes pinned strip_attributes only when an emitted Field requests trim. Like Normalization, Attachment entered only the maximal universe, with no overlay pair: the gem adds no Active Record class or Relation methods, and the conservative relock left every existing locked version unchanged. This is a linear contributor registry, not a table of contributor combinations.

The empty selection returns Core's exact Gemfile and Gemfile.lock without starting the projector. A nonempty selection inserts the qualified blocks once into the exact Core Gemfile. It starts one isolated service-Ruby 4.0.6 subprocess with only the checked-in Bundler 4.0.10 package, an empty Bundler configuration, fixed locale and time, private home and temporary directories, and an explicit environment allowlist. Bundler runs lock --local --print; Compilation inherits no proxy, Bundler, Ruby, credential, or ambient gem paths and has no resolution route to the network.

The lock verifier parses Core, the maximal universe, and the candidate. It requires exact direct dependencies, remote, platforms, Bundler version, reachable specifications, and checksums. ApplicationTaskPlan retains the one result in its derived rendering context. The two dependency renderers only emit that retained pair. Six baseline snapshots retain the previous lockfile bytes and compose Gemfiles against the selected Core. A focused regression projects the six additional normalization-bearing selections and verifies that only strip_attributes is added. The standalone qualifier checks seven pairs, including the maximal universe, twice under hostile parent settings. Production selection consults no overlay contract or bytes.

The maximal universe is an upper bound for the current contributor registry, not a permanent gem census. Adding Money, Position, or Counter contributors under the remaining Field-kind work (repository-only) requires regenerating and requalifying the universe. The same dependency advance must requalify the pinned named-scope target namespace (repository-only) facts. Optional library methods must remain qualified by the selected dependency rather than restrict apps that do not load it. Package provenance, qualification, and runtime installation live in the vendor owner (repository-only) and packaging decision (repository-only).

Application documents

The Compiler writes complete application-facing README, AGENTS, and UI documents. The README starts with the application display name and a small replaceable product-description paragraph. Operational instructions derive from the selected emitted clients and retained Rails source, and concrete test-coverage omissions remain visible. Setup runs the specs before the first preview, and a Behavior to write section lists each unwritten scope with the pages that call it and the specs that request them, and each deletion outcome a refusing polymorphic target leaves unwritten. AGENTS.md tells the agent to run the specs first and write what that section lists, previewing before it finishes, and to debug any other failure without weakening a spec; Generated tests owns the details. It also says that the retained Plan and GapSet record what was compiled and never govern later code, and how to add a resource with the generated authorization pattern. It does not turn Plan subjects or gaps into a feature catalogue. The user's agent can replace the paragraph from retained design context after inspecting the emitted source and gaps. That fixed paragraph tells the owner to replace it, which conflicts with the code-worth-keeping requirement. Decided: Plan format 0.24 (repository-only) adds application.description for the README opening and the web manifest description. Until then, the manifest description is the application name, as Rails' own manifest template has it, from the placeholder-copy work (repository-only). Setup, runtime, preview helpers, and application tests work independently of removable .firstdraft/ context.

Core's changelog, contributor guide, and root composition document are omitted; they describe Core maintenance rather than the application's history or operation. The Core path registry rejects replacement claims for these paths. Useful UUID generator, Dev Container, and Codespaces guidance belongs in the application README; UI retains reusable component and native geometry guidance; DEPLOY keeps its existing Account-sensitive operational guidance. License-required third-party notices remain. The placeholder-copy work (repository-only) moved Core's MIT notice from the root LICENSE to licenses/first-draft-MIT.txt, with the same path under ios/ and android/, so the owner chooses the repository's license; rails new emits no license file either. The minimal CLAUDE.md adapter stays @AGENTS.md; removing it would require separate first-session agent-discovery qualification.

Identity and configuration

The identity renderers derive the Rails module, database prefix, display name, and Render service name from Project#application_key and Project#name. README is a full-file renderer: its title is escaped, single-line application display text; its iPhone and Android preview links use the same selected-client projections as the emitted clients and guides. Requested but ungenerated clients receive no preview instructions. README preserves the private Codespaces port default and routes temporary remote-preview exceptions and cleanup to the selected guide. It no longer relies on exact Core prose markers or carries a historical forwarded-host receipt as instruction.

Other identity renderers read verified Core files through RenderingContext and return complete replacements. The module name uses the declared target's camelization rather than mutable Designer inflections. Identity derivation rejects a Project with another target/profile. CoreTemplate validates exact marker counts before one atomic in-memory substitution and verifies replacement counts; JSON quoting and YAML-printable filtering keep valid display text valid in nested Ruby/YAML source. Files retain Core modes. No renderer patches a materialized file or consumes another renderer's output.

The application-configuration renderer substitutes the application namespace in Core's ordinary Rails configuration and the framework requires that Rails frameworks describes. The CSP baseline (repository-only) retains Rails' commented initializer and standard layout helper without custom middleware or nonce wiring.

The composition identity test (repository-only) requires complete Rails output to contain no bare reusable-Core identity token. README and AGENTS carry application guidance; historical Core provenance sentences are no longer exceptions. Replacement values preserve the original file modes, and required third-party notices remain.

References marked “repository-only” name implementation or internal material outside this public guide. They are intentionally not links. Publishing a design does not prove its implementation.