scaffold · git:20261015.36555e0 · 2026-10-15 · sha256 016290f8d27b2b44

scaffold git:20261015.36555e0A

Immutable. This exact content never changes and is served at /api/v1/blob/016290f8d27b2b44.

---
name: scaffold
description: >-
  Creates ONE file of a ddd-ts-kit role from a template with `ddd-ts-kit generate`, with its
  spec, fake and registration, then lists the places where business logic is expected. Use
  whenever a single aggregate, entity, value object, domain event, error or service, port,
  repository, adapter, gateway, policy, job, background job, state machine, process manager,
  event handler, builder, end-to-end spec or context is needed, instead of writing it by hand, or when the guard refuses a hand-written
  file. For a whole feature use use-case; for events between contexts use integration-event.
argument-hint: "<kind> <context> <Name> [options]"
allowed-tools:
  - Read
  - Edit
  - Bash(npx ddd-ts-kit generate *)
  - Bash(npx ddd-ts-kit check *)
  - Bash(npx ddd-ts-kit list *)
---

# Scaffold one file

Requested: `$ARGUMENTS`

Boilerplate is generated, never typed: the generator and the checker share one definition of
the tree, so a generated file conforms by construction and costs no tokens.

## Procedure

1. **Name from the glossary** of the context's `CONTEXT.md`. A missing term is added in the
   same command with `--term "<Term>=<meaning>"`. Technical words (`Manager`, `Helper`,
   `Data`, `Info`, `Impl`, `Model`, ...) are refused (`language/no-technical-name`):
   find the business word; `--allow-name` only when the word really is the business term.
2. **Run with `--json`** (`--dry-run` first when unsure):
   ```bash
   npx ddd-ts-kit generate <kind> ... --json
   ```
   Exact arguments of every kind: [kinds.md](kinds.md), or `npx ddd-ts-kit --help`. A
   worker confined to one context adds `--local-only`: the command refuses, and writes
   nothing, when it would write a shared file.
3. **Open only the `next` places**, each a `file:line` holding a `TODO(domain)` that states
   the decision expected. Decide, write, delete the marker. A marker you cannot resolve is a
   question for the user, not a guess. `notes` says what the generator could not do.
4. **Replace each `it.todo`** of the generated spec by a real test (skill
   `ddd-ts-kit:testing`).
5. `npx ddd-ts-kit check --changed-since HEAD` and the tests of the context.

## What the generator settles for you

- **Registration.** In the declared style (the default with tsyringe) the class carries its
  decorator and the barrel `<context>.declarations.ts` is rewritten; never edit the barrel.
  In the explicit style the binding is added between the markers of `<context>.module.ts`.
- **Dependencies.** A generated class states what it depends on in its constructor, each
  parameter typed by a port, and its decorator lists nothing: the generator reads the
  signature into the generated file of the context. Add a dependency by adding a parameter,
  then `npx ddd-ts-kit docs` (skill `ddd-ts-kit:wiring`).
- **Names.** A generated handler names the aggregate after its concept,
  `const invoice = Invoice.create(..)`, and a generated search names its lines after what it
  searches (`invoice`, `invoices`). Keep the business word when you fill the `TODO(domain)`:
  never `target`, `data` or `item` (`naming/business-name`).
- **Access.** `command` and `query` are refused without `--permission <aggregate>.<action>`
  or `--public`; the permission joins `<context>.permissions.ts`. With roles, add
  `--grant <role>`: the role that holds it, written in the roles of the platform
  (`authz/granted`).
- **Ports.** A port is an abstract class, used as its own injection token: no constant, no
  token file. `port` and `repository` write the fake and the contract suite with it.
- **Dependencies between kinds.** A missing repository or domain event is created; a
  missing aggregate, port, use case or route stops the command with the one to run first.
- **Value objects.** `value-object` writes a class extending `ValueObject` of the kernel, a
  private constructor, a static factory that checks the rules (`create`, renamed after what it
  builds when there are several: `of`, `between`, `closed`) and the type of its props. A value
  is always this class, never a function answering a plain object nor an exported object
  literal (`domain/value-object-class`, under `"stack.values": "classes"`, which `init`
  writes; `npx ddd-ts-kit explain domain/value-object-class` says what it reads): the class
  compares by value (`equals`), checks its invariants once, keeps its operations next to its
  data and is recognised with `instanceof` by a mapper.
- **No role fits?** A type or a function alone is a missing concept, never a new folder: a
  method of the value object, a `domain-service`, a `value-object`, or an abstract service with
  one `domain-service` per variant (`docs/ARCHITECTURE.md`, a concept with no role of its own).
- `route` writes a controller class in its own folder (or a `defineRoute` function under
  `"stack.routes": "functions"`); `controller` always writes the class; `route-group` writes a
  group with its prefix and guards, `guard` a guard of the project with its spec;
  `representation <context> <UseCase> xml,csv` adds what a controller answers in besides JSON,
  `form <context> <UseCase>` the hints of its form.
- `schema` writes one shape of the HTTP contract several routes use, declared once and shared,
  in `presentation/http/shared/` of the context, or in `presentation/` of the shared kernel with
  `schema shared-kernel <Name>`; a command route answers an identifier with `acceptedSchema`.
- **Documents.** The generated lists of `CONTEXT.md` and the generated documentation are
  refreshed.

Never change the structure the generator produced (constructor visibility, factories,
suffixes, folders, decorators). If it does not fit, the model is probably wrong: go back to
`ddd-ts-kit:glossary` or `ddd-ts-kit:bounded-contexts`.