Pioneer Compiler Specification

Living Standard,

This version:
https://specs.pioneer.dev/pioneer-rules/
Issue Tracking:
GitHub
Editor:
Find How

Abstract

This document defines the active Pioneer compiler architecture and rules for porting Illuminate and Laravel-style applications to a statically analyzable Deno and edge runtime.

1. Introduction

Pioneer is a compiler-directed architecture for porting Illuminate and Laravel-style applications to Deno-compatible and edge-compatible runtimes while preserving the productive Laravel programming model. This specification defines the private Find How compiler contract: how source files are discovered, how providers declare application capabilities, how kernel entry points become deployable artifacts, and which rules runtime source must satisfy before it is certified.

The numbered rules in Rule Catalog are normative. Sections that describe motivation, examples, or deferred topics are informative unless they explicitly use RFC 2119 language. A Pioneer implementation conforms to this document only when it enforces the normative rules, emits the generated artifacts described here, and rejects source that would require runtime discovery, dynamic container lookup, unsafe public typing, or unvalidated trust boundary flow.

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in [RFC2119].

2. Goals And Non-Goals

Pioneer exists to make Laravel-style applications statically analyzable without flattening their domain model into a generic JavaScript framework. The compiler owns discovery, identity, dependency wiring, validation gates, and deployment shape so application and Illuminate source can remain small, direct, and tree-shakable.

Normative goals:

Non-goals:

3. Terminology

Application source
User-authored modules that are compiled by Pioneer.
Illuminate source
Pioneer-owned ports of Laravel and Illuminate components.
Provider file
A phase-2 entry point imported through @provider/* or @provider-dev/* that declares bindings, aliases, migrations, model features, config merges, middleware aliases, and other provider-owned compiler facts.
Kernel entry point
A phase-3 file that imports a kernel facade from @find-how/pioneer and makes top-level declarations for HTTP, Artisan, Queue, Schedule, Broadcast, or Event kernels.
Consumed-by-DI module
A handler, listener, command, queue job, middleware, service, policy, observer, model feature, or related module that is reached through compiler wiring rather than imported as a kernel entry point.
Bare nominal path
A compiler-normalized ESM module identity without a file extension, such as @app/http/handlers/ListOrders.
Data resource
A compiler-derived identity for a database table, column, index, or related resource, such as db:edge:users or db:edge:users.email.
Binding snapshot
The exact compile-time binding shape available to one kernel entry point after providers, contextual bindings, middleware context augmentation, and destructuring analysis are applied.
Alias namespace
A compiler-owned lookup domain in which an ergonomic name resolves to a single canonical bare nominal path or generated data resource. Alias namespaces are distinct for bindings, middleware, model aliases, table sugar, and any other compiler-defined lookup domain.
Provider key
The canonical provider identity derived from the import-map provider root and resolved provider file. Provider keys are unique within one compilation unit.
Validation gate
A generated or component-owned function that accepts unknown at a trust boundary and either returns typed data or throws an operational error.
Proof certificate
A compiler-generated record that binds a source content hash, compiler tool versions, checked rule set, and pass/fail state to a component or emitted artifact.

4. Conformance Classes

This specification defines multiple conformance classes. A product MAY conform to more than one class. Claims of conformance MUST identify the class and the rule set version used for certification.

Class Required behavior
Pioneer compiler Implements the compilation algorithms, validates all normative rules, emits diagnostics, and produces generated artifacts from source input.
Runtime emitter Produces Deno-compatible, edge-compatible, or target-specific runtime modules whose observable behavior is justified by compiler graph facts.
Provider authoring surface Accepts only provider declarations allowed by R18 and rejects runtime provider discovery or boot behavior.
Application source Uses kernel facades, consumed-by-DI modules, model declarations, and Laravel folder conventions in ways that the compiler can classify statically.
Generated artifact consumer Reads compiler-generated manifests, contracts, TypeGraph records, and proof certificates without treating them as mutable source-of-truth registries.

5. Architecture Overview

Pioneer splits application interpretation into three compiler phases and one runtime emission stage. Phase 1 constructs the canonical module graph. Phase 2 turns provider declarations, migrations, model declarations, config, and module metadata into a typed application graph. Phase 3 extracts kernel entry points and their binding snapshots. Emission writes runtime modules, contracts, manifests, TypeGraph records, validation gates, and deployment adapters.

The module graph is the root of trust. Any source fact that cannot be derived from Deno-compatible resolution, import maps, provider declarations, migration metadata, or explicit kernel facade calls is not part of the compiled application. Runtime code therefore does not discover providers, scan route files, load a classmap, ask a package manifest for framework metadata, or infer identity from arbitrary strings.

The emitted runtime is allowed to be smaller and more direct than the developer surface. The compiler may inline factories, erase the container, replace facades with direct binding calls, and emit Cloudflare Durable Object wrapper classes for edge processes. These transformations must preserve the public contracts defined by component contracts.d.ts files and parity tests.

6. Compiler Pipeline

The compiler pipeline is deterministic for a fixed source tree, import map, lockfile, compiler version, and external schema inputs.

6.1. Phase 1: Autoload And Module Graph

Phase 1 loads Deno configuration, package/workspace metadata, import maps, and lockfiles. It builds the Deno-compatible module graph, extracts imports and exports, classifies source files, and emits the initial autoload and TypeGraph records. Phase 1 is responsible for resolving extensionless nominal paths and for separating ordinary aliases from provider discovery roots.

6.2. Phase 2: Provider, Data, And Model Wiring

Phase 2 consumes provider files and builds the application graph: binding registry, alias map, tag map, migration registry, config merge map, listener registry, observer registry, policy registry, middleware alias/group registry, publish manifest, contextual bindings, service extensions, data graph, model graph, and generated contracts. Provider declarations are unconditional compile-time facts. There is no provider boot phase.

6.3. Phase 3: Kernel Extraction

Phase 3 consumes kernel facade declarations and unrolls routes, route groups, mounts, resource routes, queue jobs, schedules, events, broadcasts, and Artisan commands. It computes one binding snapshot per entry point, applies middleware context augmentation, validates handler target contracts, and records all resource edges needed by deployment planning.

6.4. Emission

Emission writes only artifacts that are justified by graph reachability. A conforming implementation emits runtime boot modules, kernel adapters, contracts, validation gates, manifests, TypeGraph records, and proof certificates as needed. It may emit separate artifacts for local Deno development, Cloudflare Workers, Cloudflare Durable Objects, queues, scheduled jobs, and CLI processes.

6.5. Source Classification Algorithm

A Pioneer compiler MUST classify every Pioneer-participating source file into exactly one category before phase-2 wiring begins.

  1. If the file is resolved from a @provider/* or @provider-dev/* import-map root, classify it as a provider file and validate it against R18.
  2. Otherwise, if the file imports any kernel facade from @find-how/pioneer and makes at least one top-level kernel declaration, classify it as a kernel entry point and validate it against R15.
  3. Otherwise, if the file is referenced by a provider declaration, kernel declaration, model feature reference, middleware reference, listener registration, policy registration, observer registration, queue registration, command registration, or contextual binding, classify it as a consumed-by-DI module.
  4. Otherwise, if the file is reachable only through ordinary static imports, classify it as a pure internal utility.
  5. If two categories match the same file, the compiler MUST report a source-classification error and MUST NOT emit runtime artifacts for that compilation.

6.6. Provider Discovery Algorithm

A Pioneer compiler MUST discover providers only from import-map entries whose keys match @provider/* or @provider-dev/*. For each provider root, the compiler MUST resolve the root with Deno-compatible resolution, compute a provider key, parse the provider file, and record only top-level declarations from the explicit provider whitelist.

The compiler MUST reject:

6.7. Alias Resolution Algorithm

When source provides a string that is not already a canonical bare nominal path or generated data resource identity, the compiler MUST resolve it through the active alias namespace.

  1. Select the alias namespace from the operation being validated, such as binding lookup, middleware lookup, model lookup, or table sugar.
  2. Find provider declarations that bind the supplied string in that namespace.
  3. If no declaration matches, report an unresolved-alias error.
  4. If more than one canonical identity matches, report an ambiguous-alias error.
  5. Replace the source string with the matched canonical identity in compiler records and emitted artifacts.

The emitted runtime MUST NOT repeat alias lookup unless a target-specific adapter requires a user-facing string for interoperability. Even then, compiler records MUST preserve the canonical identity.

6.8. Binding Snapshot Algorithm

For each kernel entry point, the compiler MUST build a binding snapshot:

  1. Start with globally provided bindings reachable from production providers and the active runtime target.
  2. Apply contextual provider bindings that match the consuming module or kernel entry point.
  3. Apply middleware context extensions in route order for HTTP entry points.
  4. Read destructured parameter names and namespace member accesses from each consumed-by-DI module reachable from the entry point.
  5. Resolve every requested name to a canonical binding or generated data resource.
  6. Report an unavailable-binding error for any requested binding that is not present in the snapshot.
  7. Emit only bindings, modules, validation gates, and adapters that are reachable from the final snapshot.

6.9. Data Resource Identity Algorithm

For each configured database connection, the compiler MUST derive data resource identity from config merges, registered migration directories, migration SQL or schema introspection, and model declarations.

The compiler MUST assign table, column, and index identities using the exact forms defined in Data And Model Resource Model. Table-name sugar MUST resolve to exactly one generated table identity. Ambiguous table sugar, missing migrations, incompatible model table declarations, unresolved model features, and generated contract mismatches are compile-time errors.

7. Runtime Model

Runtime source is intentionally constrained. Components are factories, constants, and plain objects. Instance state is closure state. Public APIs return null for expected absence, throw operational errors for recoverable failures, and throw plain Error for developer errors. Web Standards are the transport base, so request and response abstractions extend platform primitives rather than replacing them.

The emitted runtime must not depend on runtime package scanning, reflection, dynamic class construction, or a mutable global container. It may include compiler-owned wrappers where the target runtime requires a shape not allowed in user source, such as Durable Object classes.

8. Provider Model

Providers are compile-time declaration files, not runtime lifecycle objects. A provider imported through @provider/* or @provider-dev/* imports app from .pioneer/autoload.ts, declares facts at top level, exports nothing, and does not import kernel facades. The provider surface centers on app.provide(canonicalPath, target, options?) and an explicit whitelist of declarations for aliases, tags, migrations, listeners, observers, policies, middleware aliases/groups, context extensions, config merges, translations, views, components, publish mappings, contextual bindings, and service extensions.

Provider declarations must use canonical bare nominal paths or aliases that resolve to canonical paths. Provider-key collisions are fatal because they make provider identity ambiguous. Alias collisions are handled by alias policy and do not replace nominal identity.

9. Kernel Entry Points

A kernel entry point self-identifies by importing one or more kernel facades from @find-how/pioneer and making top-level declarations. The kernel facade set is closed: Route, Artisan, Queue, Schedule, Broadcast, and Event. Middleware is HTTP route metadata and module-backed behavior, not a kernel facade.

Entry-point files have no exports. Handler references, middleware references, queue handlers, listener targets, and command handlers resolve through the same canonical identity and alias policy as provider registrations. The compiler rejects kernel entry points that require unavailable bindings or unresolved module-backed targets.

10. Binding And Identity Model

Pioneer distinguishes canonical identity from ergonomic names. A module-backed entity is identified by its resolved bare ESM module specifier. A generated data resource is identified by a compiler-generated resource key. Aliases are secondary names declared by providers; they must resolve to exactly one canonical identity in the relevant namespace before they can be used.

Binding access is static. Handlers and other consumed-by-DI modules receive a destructured view of the binding snapshot. Namespace-style and leaf-style access are both allowed when they can be resolved to the same nominal leaves. Dynamic member access, computed binding names, and runtime app.make(variable) are not production constructs.

11. Data And Model Resource Model

Database resources are generated from database config, registered migrations, migration SQL, schema introspection, database manager and driver bindings, and model declarations. Table identities use db:<connection>:<table>; column identities use db:<connection>:<table>.<column>; index identities use db:<connection>:<table>#<index>. Model identities use their bare module specifier.

Models bind to the data graph through Model.table(...) and feature references such as Model.use([...]). The compiler validates model fillable/hidden/cast/scope/feature requirements against generated data contracts and emits model contracts, database contracts, validation gates, TypeGraph resource records, and per-entrypoint resource snapshots.

12. Validation And Error Model

Every external trust boundary has a validation gate that accepts unknown and returns typed data or throws an operational error. Trust boundaries include HTTP request bodies, route params, query strings, environment variables, database rows, model hydration, queue payloads, third-party API responses, file reads, and runtime platform events.

Public APIs have three outcome categories. Expected absence returns T | null. Operational failure throws an Error produced by a component-owned error factory declared in contracts.d.ts. Developer error throws plain Error immediately. A single execution path must not conflate absence, operational failure, and invariant failure.

13. Generated Artifacts

A conforming compiler may emit a subset of these artifacts depending on target runtime and graph reachability:

Generated artifacts are compiler outputs. Source code must not treat generated manifests as a second registry that can override module graph facts.

13.1. Artifact Schema Requirements

Generated artifacts MUST be deterministic for the same normalized compiler input. JSON artifacts MUST use stable key ordering when written to disk. Generated TypeScript declaration artifacts MUST be type-checkable without importing runtime source that is not reachable from the same component.

Artifact Required fields or records
autoload.json Compiler version, source roots, import-map roots, resolved modules, module hashes, imports, exports, file classification, and diagnostics summary.
typegraph.json Canonical module identities, generated data resources, bindings, aliases, provider keys, kernel entry points, validation gates, emitted resources, and proof certificate references.
Provider manifests Provider key, provider file, declaration records, alias namespace records, dependency edges, target runtime applicability, and collision status.
Kernel snapshots Entry-point identity, kernel kind, reachable handlers, binding snapshot, validation gates, middleware context extensions, resource dependencies, and emitted adapter kind.
Database and model contracts Connection identity, table/column/index resources, model identity, fillable/hidden/cast/scope metadata, generated create/update/read contracts, and validation gate identities.
Proof certificates Subject identity, content hash, compiler version, tool versions, rule set version, passed rules, failed rules, generated artifact hashes, and invalidation inputs.

Artifact consumers MUST treat unknown fields as non-normative extensions unless the artifact version declares them as required. Artifact producers MUST bump the artifact version when removing a required field or changing the interpretation of a required field.

14. Interoperability Requirements

Two conforming Pioneer compilers processing the same normalized inputs MUST agree on:

Two conforming runtime emitters MAY produce different JavaScript module layouts, but they MUST preserve the same public contracts, validation behavior, error outcome categories, and Laravel parity behavior for the same reachable entry point.

15. Security And Privacy Considerations

Pioneer treats source discovery, generated artifacts, environment variables, database rows, external payloads, and deployment metadata as trust boundaries. A compiler MUST NOT allow unsafe casts, unchecked data hydration, runtime provider discovery, or mutable generated manifests to bypass validation gates.

Generated artifacts can reveal source topology, deployment resources, database schema, model shape, route shape, and private component names. Implementations SHOULD keep generated artifacts inside private build outputs unless explicitly published. This repository is confidential and proprietary; publication of this specification does not grant source, patent, or implementation rights.

16. Rule Catalog

The following rules are active. Rules are grouped by concern for readability, but the rule identifiers are stable and remain the normative reference targets.

16.1. Source Shape Rules

Id Rule
R1 Factory Functions, Not Classes: No class, this, or user-authored new in Illuminate or application code. Factory functions or constants only. Components expose behavior through factory functions that return plain objects with state closed over by closures. Compiler-owned runtime wrappers, such as Durable Object classes, are the narrow exception. Compiler sweeps may mechanically transform legacy classes during porting, and any lost public inference must be restored through R34.
R2 One Export Default Per Module: One method or runtime leaf per file. Folders replace classes, and mod.ts re-exports the folder surface. Laravel PSR-4 parity is represented by import maps, not classmaps or Composer autoload metadata.
R3 Zero Third-Party Runtime Packages: Illuminate runtime source depends only on Deno globals, Deno KV, Deno Temporal, Web Standards, V8 built-ins, and other Illuminate components. Distribution may use supported package specifiers, but provider runtime code must remain statically analyzable and rule-compliant.
R4 Null Out, Both In: Public APIs return T | null, never undefined. Inputs may accept T | null | undefined and normalize absence to null. Defaults use ??; optional three-state input is represented as ?: T | null.
R9 Zero Annotations At Public API Surface And No Unsafe Casts: Runtime source files carry no public API type annotations and no unsafe as T casts. as const and as const satisfies T are allowed. Public contracts come from component contracts.d.ts files through declaration merging, declare module wiring, satisfies, const type parameters, and template-literal parsing. Unsafe casts are tracked as unsafe boundaries and must converge to zero.
R10 No Proxy Anywhere: JavaScript Proxy is forbidden. Static alternatives include predeclared methods, getter maps, Object.defineProperty, and accessor factories. Dev tooling may use V8-native named property handling where the runtime forces it, but production source remains statically knowable.
R11 Illuminate Extends Web Standards: Illuminate Request extends globalThis.Request, and Illuminate Response extends globalThis.Response. ConsoleRequest extends Request by mapping argv into URL/body semantics. Web Standards are the base contract; Pioneer adds ergonomics without replacing them.
R12 Function Scope Properties: A component folder is the namespace. Each file exports one function or constant representing a static leaf, while create factories return plain objects whose instance methods close over shared state. The component contracts.d.ts declares the full namespace type, and the compiler emits only accessed runtime leaves at each destructuring site.
R13 Laravel Folder Conventions Preserved: Laravel folder conventions such as database/migrations/, config/, routes/, and domain folders are preserved. Import maps provide the autoload mapping. There is no classmap and no Composer dump-autoload equivalent.
R16 Types Only In Component contracts.d.ts: All public type contracts live in component-owned contracts.d.ts files. Runtime source files contain no public type annotations, import type, or export type. Contracts files own namespace shape, runtime leaf wiring, registry augmentation, error contracts, driver contracts, taxonomy contracts, and contextual binding contracts.
R24 Native Narrowing Only: No function may declare a value is T or asserts value is T return type. Use native TypeScript narrowing operators directly at the use site: typeof, in, instanceof, Array.isArray, and nullish checks. Array narrowing uses flatMap with an inline conditional rather than filter with a predicate function.
R34 Transition-Safe Factory Conversion: When an exported class-backed implementation is converted to a factory or closure-based leaf, any lost public type inference must be restored in the owning component contracts.d.ts in the same change. A component may not enter an intermediate state where source annotations are removed, class inference is gone, and declaration wiring is absent. The compiler must verify this through inference-gap and component audits before certification.

16.2. Binding And Provider Rules

Id Rule
R5 All DI Through Kernel-Scoped Destructuring From App: All DI flows through kernel-scoped destructuring. Handlers receive a destructured view of the contextually typed app shape, such as ({ request, params, Str, View, session }) => {} for HTTP. Developers do not access app directly in consumed-by-DI modules; the compiler treats handler destructuring as destructuring from app internally and rejects bindings unavailable in the active kernel. Kernel facades establish context through R15, and app remains a compile-time abstraction through R21.
R6 @provider/* Is The Only Import Map Convention: Pioneer recognizes only @provider/* and development-only @provider-dev/* import-map entries as provider discovery roots. The import map is the authoritative provider registry: no glob scan, filesystem fallback, providers array, decorators, runtime registration, package manifest schema, register, or boot. Every provider root resolves to an R18 phase-2 provider file. All other import-map entries are ordinary aliases with no architectural meaning. Provider installation, publishing, dependency ordering, provider-key collision checks, and warnings are compiler-managed from the module graph and installation metadata. Provider-key collisions are fatal because they create ambiguous provider identity; alias collisions are handled by the alias policy, not by treating them as provider identity.
R7 Manager Delegates To Driver Via Config: Drivers are provided at full nominal module paths, and the public alias points to the active driver selected by config. Driver-swap methods inherit Laravel naming, such as connection, store, disk, guard, mailer, or channel, and return new spread objects without mutating the existing manager. Supported access styles are default alias, fluent switch, and direct binding.
R8 Facades Are Constant Wrappers: Facades are constant wrappers over app bindings and never use Proxy. A facade resolves a shorthand key to the active driver and may expose testing helpers only: swap(), spy(), fake(), isFake(), and restore(). Layering is Facade > Manager > Default Driver.
R17 Canonical Identity Is Compiler-Owned: The resolved bare ESM module specifier is nominal identity for module-backed entities. Any registerable entity that has a module path uses that bare nominal path as its canonical identity, including events, listeners, middleware, queue jobs, policies, observers, global scopes, model features, query macros, casts, scopes, model bindings, and handler targets. Database tables, columns, indexes, and migration-derived data resources are canonical compiler resources but not container bindings by default; their identities use db:<connection>:<table>, db:<connection>:<table>.<column>, and db:<connection>:<table>#<index>. Arbitrary strings such as UserRegistered, rateLimit, user:create, or users are never canonical identity unless resolved to a canonical module path or generated data resource. String-literal module and data-resource references in registration and resolution APIs resolve through the same compiler graph as static imports and migration-derived resources and must satisfy the required contract at compile time.
R18 Service Providers As Compile-Time Declarations: A provider is a phase-2 entry point imported through @provider/* or @provider-dev/*. It imports app from .pioneer/autoload.ts, imports no kernel facade, has no exports, and contains only unconditional top-level provider declarations. The primary declaration form is app.provide(canonicalPath, target, options?); provider files may also declare aliases, tags, migrations, listeners, observers, policies, middleware aliases via app.middleware.alias, middleware groups via app.middleware.group, context augmentations via app.context.extend, config merges, translations, views, components, publish mappings, contextual bindings, and service extensions when those forms are on the explicit provider whitelist. Model features, query macros, casts, scopes, model method extensions, and model bindings are ordinary module-backed bindings registered through app.provide, not a separate trait or macro registry. Model files consume those features through static literal references such as Model.use([...]), which R26 resolves through provider bindings. Provider registration arguments that name module-backed entities use canonical bare nominal paths or registered aliases per R17/R26/R28/R32. Route middleware usage belongs to R15 kernel entry points. Routes, queues, schedules, broadcasts, and CLI commands also belong to R15 kernel entry points.
R21 App Is A Compile-Time Abstraction: app is a developer-facing DI specification, not necessarily a runtime object. The compiler may inline factory calls directly at destructuring sites and emit direct function calls in topological order, eliminating the container from runtime output.
R23 Contextual Bindings At Compile Time: Each kernel entry point receives a statically known binding snapshot based on what the handler destructures. Middleware may augment or refine the snapshot, and contextual provider bindings may override globals for specific consumers. The compiler emits only the final required bindings, services, and modules for that entry point.
R26 Binding Resolution Is Template-Literal Typed: Every string key that references a binding, module path, registerable module-backed entity, model feature binding, query macro binding, model binding, or generated data resource is typed as a template-literal union derived from provider registrations, the module graph, and the compiler-derived data graph. A string argument is either a bare nominal path, a generated data resource identity such as db:<connection>:<table>, or an alias lookup. Non-path strings compile only if a provider-declared alias maps them to a canonical bare nominal path or generated data resource in the relevant alias namespace; otherwise they are compile-time errors. Table-name sugar such as DB.table("users") or Model.table("users") compiles only when it resolves to exactly one active data resource. Model.use([...]) feature references resolve through the provider binding registry. The compiled output always resolves to direct imports or generated data-resource metadata with no runtime lookup. Middleware context augmentations declared in contracts.d.ts merge into downstream handler binding types.
R28 Bare Nominal Paths: All container bindings, job keys, middleware keys, module specifiers, and string-based resolutions use bare nominal paths without .ts, .js, or .mjs extensions. The compiler normalizes extensions internally; the user-facing contract is extensionless.
R29 Module Graph Is Single Source Of Truth: The ESM module graph built from Deno manifests, import maps, and resolved import specifiers is the canonical authority for module-backed identity, container bindings, aliases, member access, and module identity. Data resource identity is derived from database config, registered migration directories, and migration SQL or introspection, all rooted in module graph and provider records. No independent runtime schema registry may redefine data identity, and no separate sub-binding registry duplicates graph facts.
R30 Static-Only Container Access: Container access in handlers, jobs, middleware, commands, listeners, and services must be static. Dynamic member access such as computed property reads or app.make(variable) is forbidden in production and is at least a warning, or an error in strict mode.
R31 Dual Access Style Support With Full Tree-Shaking: Leaf style and namespace style are both supported and must tree-shake identically. Leaf style destructures leaves directly, such as const { when } = app. Namespace style destructures an aggregate, such as const { Conditionable } = app, and member accesses like Conditionable.when() resolve to exact nominal leaf paths through the module graph.
R32 Service Providers Register Aggregate Paths With Aliases: Service providers declare aggregate component paths and runtime leaves at bare nominal paths, using app.provide as the canonical provider declaration surface. Providers then add aliases for ergonomic destructuring with app.alias(canonicalPath, aliasName), such as Conditionable, conditionable, or User. Aliases are ergonomic secondary names only: they never create or replace nominal identity, and only map a short name back to one canonical bare nominal path or generated data resource in the relevant alias namespace. Model aliases such as User map to canonical model module paths such as @app/models/user; table names such as users are ergonomic metadata that resolve to generated data resource identities such as db:edge:users. The provider remains the source of truth for aggregate-to-leaf wiring, and aliases never replace model, feature, table, column, or resource identity.

16.3. Compiler, Kernel, Data, And Validation Rules

Id Rule
R14 Harvest Parity Tests: PHP Laravel parity tests run alongside TypeScript tests to verify that each ported method preserves Laravel behavior. Parity gaps are tracked explicitly rather than hidden behind type conformance.
R15 Kernel Facades As Self-Selecting Entry Points: A file becomes a phase-3 entry point by importing one or more kernel facades from @find-how/pioneer and making top-level facade calls. The exhaustive facade set is Route, Artisan, Queue, Schedule, Broadcast, and Event. Middleware is HTTP route metadata and module-backed behavior, not a kernel facade. Entry-point files have no exports. The compiler statically extracts and unrolls route groups, mounts, match/any/resource expansions, schedules, queues, broadcasts, events, route middleware metadata, and commands into kernel-specific TypeGraph records. Registration arguments that name module-backed entities use canonical bare nominal paths or registered aliases per R17/R26/R28/R32. Every Pioneer-participating file must classify as exactly one provider, kernel entry point, consumed-by-DI module, or pure internal utility.
R19 Compiler Phase 1: Autoloader: Phase 1 runs the autoloader pipeline. deno_config loads Deno, package, workspace, import-map, and lockfile data for the compiler. That Deno-compatible configuration feeds deno_graph, which is the canonical resolver and module graph builder using Deno semantics. Source discovery uses import-map roots plus deno_graph reachability when an import map exists, and tsconfig/filesystem discovery when it does not. oxc-parser extracts exports, imports, and source-level metadata from modules after discovery. The CLI emits .pioneer/graph/autoload.json, .pioneer/graph/typegraph.json, and, when requested, .pioneer/graph/autoload.ts and .pioneer/graph/autoload.d.ts.
R20 Compiler Phase 2: Provider, Data, And Model Wiring: Phase 2 consumes the phase-1 autoload map and all R18 provider records. It builds the binding registry, alias map, tag map, migration registry, listener registry, observer registry, policy registry, config merge map, publish manifest, contextual bindings, and service-extension composition. Phase 2 also builds the data graph and model graph from database config merges, registered migration directories, migration SQL or introspection output, database manager and driver bindings, model bindings, model feature bindings, Model.table(...) declarations, and Model.use([...]) references. It emits .pioneer/boot.ts, database manifests, model manifests, generated database contracts, generated model contracts, and TypeGraph edges connecting models, tables, migrations, features, routes, queue jobs, cache keys, responses, and deployed resources, with no provider boot phase and no runtime provider discovery.
R22 Trust Boundaries Require Validation Gates: Every external data entry point must pass through a validation function that accepts unknown and either returns typed data or throws an operational error. Trust boundaries include HTTP request bodies, database results, ORM/model hydration, third-party API responses, environment variables, queue payloads, and file reads. Database query results, migration-introspected rows, and model hydration pass through generated validation gates before entering typed application flow. Model create/update calls that receive external input validate against generated create/update contracts before insert or update, and returned rows validate before becoming model row types. No any intermediary or unsafe cast may stand in for validation.
R25 Three-Tier Error Contract: Public APIs have exactly three outcome categories: expected absence returns T | null; operational failure throws an Error instance created by a component-owned error factory function declared in contracts.d.ts; developer error throws plain Error immediately and is not recovered in production code. User-authored error classes are forbidden by R1 unless compiler/runtime-owned. A function must not conflate absence, operational failure, and invariant failure on the same execution path.
R27 Proof Certificates Are Persistent And Content-Addressed: When a component passes rule checks, the compiler records a proof certificate binding module path, content hash, compiler tool versions, and passed rule set. Any source or relevant compiler-tool change that alters the hash invalidates the certificate. The TypeGraph exposes stale certificates for MCP queries and regression tracking.
R33 Durable Object Drivers For Edge Processes: Artisan, Broadcast, Queue workers, and long-lived components must be deployable as Cloudflare Durable Objects at the edge. The compiler may emit Durable Object wrapper classes around kernel facades while preserving local Deno process behavior for development. Container access remains static and tree-shaken.
R35 Data And Model Resources Are Compiler-Derived Nominal Resources: Database tables, columns, indexes, and model-to-table bindings are compiler-generated resources with stable nominal identities. Table identities use db:<connection>:<table>, column identities use db:<connection>:<table>.<column>, index identities use db:<connection>:<table>#<index>, and model identities use their bare module specifier such as @app/models/user. Database config and registered migrations define the database resource graph. Models bind to that graph through Model.table("tableName") or an explicit connection-qualified form. Model features, casts, scopes, and query macros are ordinary module-backed bindings registered by providers and consumed through static literal references such as Model.use([...]). The compiler validates model declarations against migration-derived table types and feature requirements, then emits database contracts, model contracts, validation gates, TypeGraph records, MCP resources, and per-entrypoint snapshots.

17. Examples

17.1. Canonical Identity Examples

Correct canonical path usage:

app.events.listen("@app/events/UserRegistered", "@app/listeners/SendWelcomeEmail");
Queue.job("@app/queues/ProcessOrder", "@app/queues/handlers/ProcessOrderHandler");
Route.get("/orders", "@app/http/handlers/ListOrders").middleware("@app/http/middleware/RateLimit");

Correct alias usage:

app.alias("@app/events/UserRegistered", "UserRegistered");
app.middleware.alias("@app/http/middleware/RateLimit", "rateLimit");

app.events.listen("UserRegistered", "@app/listeners/NotifyAdmins");
Route.get("/orders", "@app/http/handlers/ListOrders").middleware("rateLimit");

Compile error without a registered alias:

app.events.listen("UserRegistered", "@app/listeners/SendWelcomeEmail");

External trigger names, such as route paths, queue broker names, cron expressions, and Artisan signatures, are transport or user-facing metadata rather than canonical module identity.

17.2. Provider And Model Example

app.config.merge("database", "@app/config/database");
app.migrations("@app/database/migrations");
app.provide("@app/models/user", "@app/models/user");
app.alias("@app/models/user", "User");
app.provide(
  "@find-how/auth/model-features/authenticatable",
  "@find-how/auth/model-features/authenticatable",
);
export default Model
  .use(["@find-how/auth/model-features/authenticatable"])
  .table("users", {
    fillable: ["name", "email"],
    hidden: ["passwordHash"],
  });

The compiler resolves @app/models/user to Model.table("users"), the active database connection, db:edge:users, the migration-derived table type, and all feature requirements. User and users remain ergonomic names, not canonical identity.

17.3. Handler Destructuring Example

export default async ({ request, params, User, View }) => {
  const user = await User.find(params.id);
  if (user === null) {
    return View.notFound();
  }

  return View.render("users.show", { user });
};

The handler does not import or access app. The compiler treats the destructured parameter as a request for bindings from the active HTTP kernel snapshot. If User or View are unavailable in that snapshot, compilation fails before runtime.

18. Conformance And Diagnostics

A conforming implementation MUST reject source that violates any active rule. Diagnostics SHOULD name the rule identifier, the offending module, the relevant canonical identity when known, and the smallest actionable repair.

Every diagnostic record emitted to machine-readable output MUST contain:

Field Requirement
code A stable diagnostic identifier, such as PIO-IDENTITY-UNRESOLVED-ALIAS.
severity One of error, warning, or info. Rule violations that make emission unsound MUST be error.
rule The rule identifier when the diagnostic is tied to a rule, or null for infrastructure failures.
source The module path, generated artifact identity, or external schema input that caused the diagnostic.
message A human-readable explanation.
repair A short actionable suggestion when one can be stated safely.

Required diagnostic classes:

The following diagnostic code prefixes are reserved:

Prefix Meaning
PIO-SOURCE Source-shape or source-classification failure.
PIO-PROVIDER Provider discovery, provider declaration, or provider collision failure.
PIO-IDENTITY Canonical path, alias, or generated resource identity failure.
PIO-BINDING Binding snapshot, contextual binding, destructuring, or unavailable member failure.
PIO-DATA Database, migration, model, data-resource, or validation-gate failure.
PIO-CERT Proof certificate, stale artifact, or rule-certification failure.

Conformance tests SHOULD include harvested Laravel parity tests, static rule fixtures, generated-artifact snapshots, TypeGraph edge checks, and end-to-end kernel emission tests for each supported runtime target.

Each normative rule SHOULD have at least one positive fixture and one negative fixture. Negative fixtures SHOULD assert a stable diagnostic code, rule identifier, and source location. Generated-artifact snapshot tests SHOULD ignore non-semantic ordering only when the artifact format explicitly allows it.

19. Deferred Topics

The following topics are not active rules in this version:

Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

References

Normative References

[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119