


Work on a Typed Web Framework Repo and Split Database Code into Three Layers
Use when changing a multi-package, typed web framework. It works inside the pinned dev environment, tests quickly then fully, keeps public modules small, layers database access, and never force-pushes.
To use this AI rule
## Work Inside the Repo's Pinned Dev Environment and Find the Owning Package
Enter the development environment through the repository's declared environment manager rather than relying on globally installed tools.
### Environment Setup
- Start from the repository root and activate the approved development shell.
- Use the environment's cached execution path when available for faster repeated commands.
- Confirm that compiler, package manager, database tools, and documentation tools come from the pinned environment.
- Use the runtime version declared by the relevant package or documentation configuration.
- Enable debug logging only when needed for local diagnosis, and do not treat debug mode as a production default.
### Working Context
In a multi-package repository, identify the package that owns the change before running commands. Resolve its source directory, test entry point, generated artifacts, public modules, and local instructions rather than assuming every package shares one workflow.
## Get Quick Type Feedback First, Then Run the Full Tests
Use the fastest reliable feedback loop during iteration, then run the broader authoritative validation required for handoff.
### Focused Iteration
- Prefer an interactive compiler, type checker, or module loader for quick type feedback when a full environment build is expensive.
- Load only the changed module or focused test entry point during early iteration.
- Interactive tools that read standard input must receive commands and an explicit exit path; otherwise they may wait indefinitely.
- When an interactive session supports reload, reuse it after edits instead of repeatedly rebuilding the entire environment.
### Test Registration
- Add new tests to the package's canonical test aggregator or discovery configuration.
- Confirm that the focused test actually runs through that entry point.
- Run the full repository validation when the change is ready or when shared behavior, build configuration, or package boundaries are affected.
- Do not present a focused compile check as proof that the complete test suite passes.
### Development Server
Start local services only from the approved environment and the correct working directory. When the development server depends on a host application or parent directory, establish that context explicitly before invoking its entry point.
## Give Each Package One Job and Expose Only Small Public Modules
Map responsibilities before changing code, especially in a repository that combines runtime, development tools, templates, migrations, synchronization, application programming interfaces, tests, and optional integrations.
### Responsibility Map
- Keep server startup and middleware separate from framework configuration.
- Keep routing and uniform resource locator generation type-safe and isolated from request handling.
- Separate models, validation, authentication, background work, storage, mail, and real-time updates by responsibility.
- Keep code generation, schema design, and development-server behavior outside the core runtime package when the architecture defines them as tooling.
- Treat optional integrations and server-side components as separate packages rather than leaking their dependencies into the core.
### Public Interface
Expose the smallest stable module surface needed by consumers. Keep raw statements, internal composition, helper preludes, and implementation modules private so they can evolve without breaking callers. Add the project's standard API documentation to public modules and functions.
### Language Conventions
Follow the codebase's established idioms for pure values, contextual parameters, field access, templates, type-level routing, and model types. Prefer the convention already used by the project over an equivalent form that increases inconsistency.
## Never Paste Values into Query Text, and Expose Only the Session Layer
Organize database access into statement, transaction, and session layers with explicit ownership of encoding, atomicity, and connections.
### Statement Layer
- Keep raw parameterized queries with their input encoders and result decoders.
- Use placeholders for every runtime value instead of interpolating values into query text.
- Encode nullability and database types explicitly.
- Choose a decoder that matches expected cardinality: optional single row, required single row, or multiple rows.
- Keep statement caching decisions with the statement definition.
### Transaction Layer
- Compose statements into business operations that require atomicity.
- Keep branching rules, existence checks, and creation decisions inside the transaction when they must observe one consistent state.
- Make idempotent outcomes explicit so callers can distinguish an existing record from a newly created one.
- Use independent or selective composition only when operations are truly independent and preserve the intended transaction semantics.
### Session Layer
- Present the session layer as the public database interface.
- Let sessions own connection execution and transaction boundaries while hiding raw statements and internal transactions.
- Use an explicit transaction for multi-statement operations and direct statement execution for a single independent query.
## Match Isolation Levels and Return Types to Each Database Operation
Match isolation, cardinality, and result types to the semantics of the operation rather than applying one pattern everywhere.
### Isolation Choices
- Use a strong write transaction for critical operations whose correctness depends on serialization.
- Use an appropriate read isolation level for queries where concurrency matters and weaker isolation is acceptable.
- Document any operation whose correctness depends on a specific isolation mode.
### Result Conventions
- Represent zero-or-one-row results with an optional value.
- Represent many-row results with the project's standard sequence type.
- Use tuples for small internal multi-column results when named wrappers would add no useful boundary.
- Return an explicit success indicator when an update or deletion may affect no rows.
- For idempotent operations, return both whether work was performed and the resulting value.
### Codec Composition
When an encoder library composes nested pairs, adapt flat input tuples deliberately and keep the mapping next to the statement. Compose decoders to preserve column order, nullability, and row cardinality. Add focused tests for mismatches that could silently map values to the wrong field.
## Add Dependencies Only Where Used and Never Force-Push
Keep changes compatible, reviewable, and recoverable.
### Code and Dependencies
- Use the project's preferred language forms when they improve clarity for contributors.
- Document public interfaces with the repository's standard documentation system.
- Respect the codebase's enabled language extensions and do not introduce new extensions without a concrete need.
- Add dependencies only to the package that uses them.
- Declare lower and upper compatibility bounds appropriate to the supported ecosystem.
- Treat experimental dependencies as explicit risk and isolate them behind narrow interfaces.
### Git Safety
- Never force-push, including force-with-lease.
- If the remote branch advanced, fetch and rebase or merge onto the updated history, resolve conflicts, validate, and push normally.
- Do not hide a rejected push by rewriting shared history.
- Keep unrelated generated files, lockfile changes, and local performance settings out of the commit.
## Keep Local Overrides Out of Commits and Ship Docs Through the Release Process
Use local performance and dependency overrides for development without allowing them to leak into shared source control.
### Local Performance Overrides
- Temporary fast-build flags may be enabled for local iteration when the project supports them.
- Do not commit a local-only performance change.
- Before handoff, inspect the real diff rather than relying only on index flags that can hide modifications.
### Local Dependency Development
When developing a framework and a consuming application together:
1. Place the local framework checkout in a deliberate development location.
2. Point the application dependency at that local path through the supported override mechanism.
3. Activate the required environment and refresh dependency state.
4. Test the application against the local framework.
5. Remove or intentionally document the override before preparing shared changes.
### Documentation and Release
- Preview documentation locally from its designated environment.
- When published documentation is maintained separately, update its framework or documentation dependency through the approved repository workflow.
- Commit only the lock or source changes required by that update.
- Deploy documentation or infrastructure only through the designated release process, preserving the required order between dependency update, committed state, and deployment.
- When a framework release requires downstream documentation synchronization, include that step in the release checklist rather than relying on memory.
