write-persistence-representations
Write Persistence Representations
Goal
Write or update the persistence representation that maps application data to the storage technology in use.
Keep business defaults out of the representation layer. Let callers, services, commands, factories, or explicit write flows provide values instead of database or ORM defaults.
Enforce the rule that representation definitions must not declare default values, except for the creation-time audit field such as createdAt, created_at, inserted_at, or an equivalent project-specific name.
Detect the Representation Style
-
Identify the persistence technology and the project convention before editing.
- Inspect nearby model, entity, schema, mapping, or migration files.
- Match the local style for file placement, naming, decorators, schema builders, relation declarations, enums, indexes, and timestamp fields.
- Use official documentation when framework semantics are unclear or version-sensitive.
-
Map the requested change to the representation type used by the stack.
- Treat SQL table mappings, ORM entities, schema DSL files, document schemas, collection definitions, record types, and similar storage-facing definitions as the target artifact.
- Prefer updating the existing representation pattern instead of introducing a new abstraction.
Write the Representation
-
Add or update only the storage-facing structure that the task requires.
- Define field names, types, nullability, identifiers, relationships, indexes, constraints, embedded objects, and table or collection names as needed.
- Keep the representation focused on persistence concerns.
- Avoid mixing in service behavior or request-layer shaping unless the framework requires it.
-
Keep required data explicit.
- Use required vs optional markers that reflect the real writing contract.
- Do not weaken a field to optional only to compensate for a missing default.
- If a field must exist but the representation cannot supply it automatically, require the application write path to provide it.
Enforce the No-Defaults Rule
Treat all of these as defaults and avoid them in persistence representations:
- database column defaults
- ORM or schema
defaultordefaultValueoptions - property initializers that silently seed persisted values
- schema hooks or model callbacks that backfill business values
- generated placeholders for status, counters, booleans, enums, arrays, JSON, foreign keys, or similar data
Allow only the creation-time audit timestamp default when the project convention requires it, for example createdAt, created_at, inserted_at, or an equivalent creation field.
Apply the rule strictly:
- Allow
createdAt-style creation timestamps to usenow,CURRENT_TIMESTAMP, or the framework's equivalent creation-time mechanism. - Do not add defaults for
updatedAt,deletedAt,publishedAt,status,enabled,role,count,version,metadata, or any business field. - If a framework bundles
createdAtwith other automatic fields behind a single switch, check the existing project convention first. If the bundled behavior violates this rule, model the fields explicitly instead of enabling the switch blindly. - If the codebase already contains forbidden defaults, do not spread the pattern. Preserve existing behavior unless the task asks to refactor it, but do not introduce new non-audit defaults.
Validate Before Finishing
- Verify that field names, relation wiring, indexes, and nullability match nearby code.
- Verify that omitted defaults do not hide a missing required to be input in the writing flow.
- Run the normal local validation for the stack when it is safe and in scope, such as type checks, schema validation, or generated client checks.
- Call out any assumption when application code must now supply a value that used to be implicit.
Report the Outcome
When finishing the task:
- State which persistence representations were created or updated.
- State which fields, relations, or indexes were added or changed.
- State whether a creation-time audit default was used.
- State whether application code must provide any required values because defaults were intentionally omitted.
More from code-sherpas/agent-skills
neverthrow-return-types
Require `neverthrow`-based return types in TypeScript and JavaScript code whenever the surrounding technology allows it. Use when creating, refactoring, reviewing, or extending standalone functions, exported module functions, class methods, object methods, service methods, repository methods, and similar APIs that should expose explicit success and failure result types in their signatures. Prefer `Result<T, E>` for synchronous code and `ResultAsync<T, E>` for asynchronous code. Only skip a `neverthrow` return type when a framework, library, runtime interface, or externally imposed contract is incompatible and requires a different return shape.
16neverthrow-wrap-exceptions
Capture exceptions and promise failures with `neverthrow` instead of hand-written `try/catch` in TypeScript and JavaScript code. Use when wrapping synchronous functions that may throw, promise-returning functions that may throw before returning, existing `PromiseLike` values that may reject, or third-party APIs such as parsers, database clients, HTTP clients, file-system helpers, serializers, and SDK calls. Prefer `Result.fromThrowable` for synchronous throwers, `ResultAsync.fromThrowable` for promise-returning functions that may throw or reject, and `ResultAsync.fromPromise` when you already have a `PromiseLike` value in hand. Only keep `try/catch` when the language construct, cleanup requirement, or framework boundary truly requires it.
11atomic-design
Create or update web UI components with a strict reuse-first workflow. Use when building, refactoring, restyling, or extending frontend or template components while minimizing raw DOM or HTML by reusing or generalizing existing components first.
10business-logic
Identify, interpret, review, or write business logic in code. Use when an agent needs to decide whether code expresses business rules, business algorithms, or business workflows, or when it must implement, preserve, or refactor code that creates, stores, or transforms data according to real business policies.
7immutable-domain-entities
Require the immutable design pattern for domain entities. Use when an agent needs to create, modify, review, or interpret domain entities and should preserve identity while expressing state changes through new immutable instances. Domain entities must be modeled as immutable classes, not as plain type aliases or interfaces paired with standalone functions.
7update-agent-skills
Update agent skills installed with the `skills` CLI. Use when asked to refresh installed skills, keep a project's skills current, or troubleshoot cases where `npx skills update` reports that everything is up to date. For project-scoped installs, a no-change update must immediately run the bundled reinstall script so tracked skills from `skills-lock.json` are reinstalled without extra investigation.
7