[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6HR35B3QWHPEVGWHZ1AW08P":3,"skill-same:01M6HR35B3QWHPEVGWHZ1AW08P":78},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":47,"linkOnly":48,"markdownContent":49,"markdownBody":50,"frontMatter":51,"refName":54,"commitSha":55,"skillDirectory":56,"forksCount":57,"repositoryHtmlUrl":58,"repositoryHomepageUrl":59,"ownerHtmlUrl":60,"ownerBlogUrl":61,"ownerDescription":62,"updatedAt":63,"install":64,"resources":77},"01M6HR35B3QWHPEVGWHZ1AW08P","design-implementation",null,"Write coding-ready specs: the API layer (controllers, DTOs, validation), domain services,\nrepository ports and their Fakes, value objects and exception mapping. Runs after the design\nphase.","wfukatsu\u002Fnexus-architect","wfukatsu","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F11712747?v=4","01M6HR128TEJY1WD0C36TDQD7S","Wataru Fukatsu","01M6HR12D55WNY36YSW845YXZ1",13,"MIT","https:\u002F\u002Fgithub.com\u002Fwfukatsu\u002Fnexus-architect\u002Fblob\u002Fmain\u002Fskills\u002Fdesign-implementation\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],"design implementation","implementation","design","ready","layer","opus","mapping","domain","objects","clean","write","coding","ports","api","services","repository","ddd","validation","2026-11-10 10:12:30",false,"---\ndescription: |\n  Write coding-ready specs: the API layer (controllers, DTOs, validation), domain services,\n  repository ports and their Fakes, value objects and exception mapping. Runs after the design\n  phase.\nargument-hint: '[--layering=ddd|clean]'\nmodel: opus\n---\n\n# Implementation Design\n\nShared files: a path written `@rules\u002F…`, `@skills\u002F…`, `@templates\u002F…` or `@docs\u002F…` is relative to the\nplugin root, `${CLAUDE_PLUGIN_ROOT}` — not to the project being worked on. Read it from there.\n\n**Usage:** `\u002Farchitect:design-implementation [--layering=ddd|clean]`\n\n`--layering=clean` switches the application layer to Clean Architecture vocabulary (Use Case \u002F\nInteractor \u002F Presenter); the default keeps DDD application services.\n\n## Desired Outcome\n\nGenerate detailed, coding-ready implementation specifications from design documents:\n- **API layer specification** — controller \u002F DTO \u002F mapper \u002F application-service layering, bound to the\n  API contract operation by operation\n- Method signatures and responsibility definitions for domain services\n- Repository interface specifications (CRUD + custom queries)\n- Value object definitions and invariant conditions\n- Exception hierarchy and external exception mapping, including the Problem Details mapping\n- Interface contracts for inter-service communication\n\n## API Layer Specification\n\nThis is the specification that closes the gap between the API contract and the domain: it says which\nclass serves which REST `operationId` or GraphQL field coordinate, and what happens between the wire\nand the aggregate. Governed by @rules\u002Fapi-contract-fidelity.md and\n@rules\u002Fgraphql-contract-fidelity.md.\n\nSpecify, per REST `operationId` or GraphQL `\u003CparentType>.\u003CfieldName>` in\n`reports\u002F03_design\u002Fapi-specifications\u002F`:\n\n| Element | Content |\n|---------|---------|\n| Handler | The controller class and method that serves this operation, 1:1. REST names from `operationId`; GraphQL binds by field coordinate |\n| Request DTO | Class name from the `components\u002Fschemas` key, even when it collides with a domain simple name — the collision is resolved by package and import, never by re-styling the DTO (`MoneyDto`), which breaks the contract binding @rules\u002Fapi-contract-fidelity.md relies on. **Never the domain object and never the persistence entity** — binding a request body straight onto an entity is the mass-assignment defect |\n| Validation | The Bean Validation constraints derived from the schema: `minLength` -> `@Size`, `pattern` -> `@Pattern`, `enum` -> an enum type, `required` -> `@NotNull`. Derived, not hand-chosen; the request DTO is `@Valid` at the handler boundary. A `required` scalar is a **boxed** type (`Integer`, `Long`) — `@NotNull` on a primitive can never fire, and the constraint is silently dropped |\n| Mapper | The explicit DTO \u003C-> domain mapping, listing exactly the fields the schema declares. Under `clean` the row names two halves with two owners: `Request` -> `InputData` in `api\u002F` (`generate-api-code`), domain -> `OutputData` in the interactor or a `usecase\u002F` assembler (`generate-scalardb-code`) |\n| Response DTO | Class name from the schema key, carrying exactly the schema's properties — this is what stops an internal field leaking when the domain model later grows |\n| Application service | The method the handler delegates to, and **the transaction boundary**: which operations open a transaction, which join one, which are read-only. This must match the transaction placement recorded in `operation-contracts.md` |\n| Authorization | Where the operation's declared authorization rule is enforced — the role\u002Fscope check and the object-level ownership predicate. An operation with an ownership predicate needs the check named here, not assumed |\n| Idempotency | For operations carrying an `Idempotency-Key` obligation: where the key is read, where the record is stored, and the requirement that the record and the business write share **one** transaction (@rules\u002Fapi-error-standard.md §5) |\n\nThe layering is directional and the direction is part of the specification: controller -> application\nservice -> domain -> repository (under `--layering=clean`: controller -> use case boundary ->\ninteractor -> domain -> repository, with the presenter behind the output boundary — see Layering\nStyle). No reverse dependency, and no persistence or ScalarDB type appearing in a controller\nsignature. `generate-contract-tests` turns this into executable ArchUnit rules.\n\n## Layering Style (`--layering=ddd|clean`)\n\nThe layering above is the same under either style; the option decides the **names, granularity and\npackages** the application layer and its wire adapters take. Precedence: `--layering` ->\n`options.layering_style` in `work\u002Fpipeline-progress.json` -> `ddd`. The chosen style is recorded\nonce, as `layering_style: ddd|clean` in the frontmatter of `reports\u002F06_implementation\u002Fapi-layer-spec.md`,\nand mirrored to `options.layering_style` so a later run defaults to it. Every downstream generator\n(`generate-api-code`, `generate-graphql-code`, `generate-scalardb-code`, `generate-contract-tests`,\n`generate-acceptance-tests`) and `verify-implementation` read it from that frontmatter — none takes a\nflag of its own, so every generator in a run agrees on the vocabulary.\n\n**Switching the style of an already-generated service is a migration, not a regeneration**, and the\ntree is legitimately transitional between the two generator runs: `generate-api-code` runs first and\nadds `usecase\u002F` boundaries beside the existing `application\u002F`; `generate-scalardb-code` then moves\n`application\u002F` (`tx\u002F`, `view\u002F`, `worker\u002F`, shared collaborators) to `usecase\u002F`, writes the\ninteractors by splitting the existing services, deletes the replaced services, and repairs what\nstill names the old package — the JaCoCo includes, the ArchUnit rules, the component scan. A tree\nthat still holds both packages after that second run is the `verify-implementation` finding, and\nthe first run's summary names the transitional state rather than reporting a finished service.\n\n| Element | `ddd` (default) | `clean` (Clean Architecture vocabulary) |\n|---------|-----------------|-----------------------------------------|\n| Application package | `…\u002Fapplication\u002F` | `…\u002Fusecase\u002F` |\n| Unit of the application layer | one application service per aggregate or operation group (`OrderApplicationService`) | one **use case per `operationId`** (or GraphQL field coordinate): the input boundary `PlaceOrderUseCase` and its `PlaceOrderInteractor` |\n| What the handler passes in | request DTO mapped to domain values \u002F a command | `PlaceOrderInputData` — an immutable record in `usecase\u002F`, built by the controller's mapper |\n| What comes back | a domain value or result object the controller maps to the response DTO | `PlaceOrderOutputData`, handed to the **output boundary** `PlaceOrderOutputBoundary`; `PlaceOrderPresenter` in `…\u002Fapi\u002Fpresenter\u002F` implements it and produces the view model — the response DTO |\n| Wire package | `…\u002Fapi\u002F` (controllers, DTOs, mappers, exception handler) | `…\u002Fapi\u002F` unchanged, plus `…\u002Fapi\u002Fpresenter\u002F`; the response DTO doubles as the view model |\n| Repository port | `domain\u002F…\u002F\u003CRoot>Repository` | **unchanged** — Clean Architecture's *gateway* is this same domain-owned interface. The toolkit keeps the DDD name because the aggregate manifest, the Fakes (@rules\u002Ftdd-workflow.md §4) and the coverage \u002F mutation thresholds are keyed on it |\n| Transaction boundary | the application service opens it and passes it down | the interactor opens it and passes it down — same rule, same place |\n| Dependency rule | controller -> application service -> domain -> repository; no reverse edge | controller -> input boundary; interactor -> domain, repository ports, output boundary; presenter \u003C- output boundary. The interactor never imports `api\u002F` or `infrastructure\u002F`; the controller never imports an interactor class, only its boundary; the presenter never imports a domain type |\n| Cross-service outbound port | `domain\u002Fport\u002F\u003CX>Port` + Fake | unchanged |\n\nUnder `clean`, the per-operation table above names the use case (boundary + interactor), the input\ndata, the output boundary and the presenter in place of the single \"Application service\" row; every\nother row is unchanged. The naming is Robert C. Martin's (*Clean Architecture*, ch. 22); the layering\nit describes is the one `evaluate-ddd` already scores as criteria 10–12, so choosing `clean` changes\nvocabulary and granularity, not the architecture. Existing hand-written source that already has\napplication services is not asked to rename them; the specification this skill writes, however, is\nentirely in the chosen vocabulary — one document never mixes the two.\n\nOne behaviour-visible consequence follows from the presenter holding no business judgment: an outcome\nthe `ddd` mapper could decide from a returned read model (a declined payment returned as a\n`CANCELLED` order and mapped to 402) must under `clean` be decided in the interactor — it throws the\nexception the problem type registry maps — so the status the caller sees can change with the style.\nName such cases in the specification instead of discovering them in the contract tests.\n\n### `clean` — the details the table leaves open\n\n- **Boundary method.** The input boundary declares one method, `execute(\u003COp>InputData)`. Wire-facing\n  use cases return `void`; the result travels through the output boundary.\n- **Output boundary.** `void present(\u003COp>OutputData)`. The boundary lives in `usecase\u002F` and therefore\n  cannot name a response DTO, so the presenter is **request-scoped and stateful**: it stores the view\n  model it built, and the controller reads it back after `execute` returns.\n- **Domain-free data records.** `InputData`, `OutputData` and every nested record (`MoneyData`,\n  `PrincipalData` for the caller's identity and scopes) carry primitives, strings, and their own\n  enums only — never a domain type — because the presenter imports no domain type. The interactor\n  (or an assembler in `usecase\u002F` when several interactors share one shape) copies domain → output\n  data; the `api\u002F` mapper keeps the request side only (`Request` → `InputData`). This moves half of\n  the `ddd` mapper out of `generate-api-code`'s package into `generate-scalardb-code`'s — record the\n  transfer in the Mapper row.\n- **Entries without an `operationId`** — saga confirm \u002F compensate, recovery and expiry workers,\n  outbox relays: still one use case each (input boundary + interactor, `execute`) with **no output\n  boundary and no presenter**; there is nothing to present to. When a caller inside `usecase\u002F` (a\n  worker) needs the outcome, `execute` returns a domain-free result record; a `ddd` `boolean` that\n  would otherwise vanish is specified this way, or the caller reads the outcome from state.\n- **Shared collaborators are allowed in `usecase\u002F`.** Splitting one application service into N\n  interactors leaves shared logic (a settlement step, an unknown-status resolver, an assembler, the\n  workers and relays) that is not an interactor and has no boundary. It lives in `usecase\u002F`, is\n  called only from `usecase\u002F`, and may open a transaction. The \"who opens a transaction\" rule is\n  therefore stated **by package** (`usecase..` only), never by class-name suffix — a suffix rule is\n  the one that goes red on the first shared collaborator.\n- **Transactions.** The interactor of the orchestrating operation opens the transaction and passes\n  it down; a participant operation (`reserveStock`, `recordPayment`, …) joins the transaction it is\n  handed and never calls `begin()`. Carry the participant carve-out from the `ddd` specification\n  over verbatim.\n- **Exception types the handler branches on** (a contract's 402 \u002F 409 \u002F 422 problem types) live in\n  `usecase\u002F`, since `usecase\u002F` never imports `api\u002F`; the transaction exceptions live in\n  `usecase\u002Ftx\u002F`. The `api\u002F` exception handler imports them from there.\n- **Component scan.** `clean` introduces the `api\u002F` package; state that the Spring application\n  scans it (or lists its configuration) — a `ddd`-era `scanBasePackages` that names only\n  `infrastructure.config` starts an application with no controller in it.\n- **Rule ids.** Give the clean dependency rules numbers that continue the sequence the `ddd`\n  specification already declared (the test specifications cite rule ids), and state each rule so\n  ArchUnit can express it: \"controller never references an `*Interactor`\", \"`usecase` never\n  imports `api` or `infrastructure`\", \"`api.presenter` and the data records import no domain type\",\n  \"exactly one input boundary and one interactor per `operationId`, each output boundary implemented\n  exactly once, in `api.presenter`\". \"The presenter reaches the interactor only through the output\n  boundary\" is a description, not a rule — the presenter never reaches the interactor at all.\n\n## Testability Constraints (specify them — the generators and ArchUnit enforce them)\n\nThe specifications decide whether the code can be written test-first (@rules\u002Ftdd-workflow.md §4).\nState, in `repository-interfaces-spec.md` and `domain-services-spec.md`:\n\n- every repository interface is a **port** the domain owns, with an in-memory Fake named next to it\n  (`InMemory\u003CRoot>Repository`), and its not-found \u002F version-check contract stated so the Fake and the\n  ScalarDB adapter can be held to the same behaviour;\n- `Clock` and the id generator are **constructor dependencies** of every factory, application\n  service and saga step that reads time or mints an id — no `now()` \u002F `randomUUID()` inside domain or\n  application code;\n- the transaction is opened by the application service (the interactor, under `clean`) and passed\n  down; no domain type holds one.\n\nThese become ArchUnit rules in `generate-contract-tests` and are checked at stage 8 of the gate.\n\n## Repository Exception Strategy (specify it — do not leave it to codegen)\n\n`repository-interfaces-spec.md` states one exception-propagation strategy for the whole\nproject, because \"technology-independent interfaces\" and \"single-point retry classification\"\npull in opposite directions and every code generator otherwise invents its own bridge:\n\n- **Standard form**: domain repository interfaces throw no checked infrastructure exceptions;\n  infrastructure implementations wrap ScalarDB's checked exceptions in one project-wide\n  **unchecked wrapper** carrying the original as its cause; the application layer's retry\n  template unwraps the cause and performs the *only* conflict\u002Fcondition\u002Fpermanent classification\n  in the project (@rules\u002Fscalardb-exception-handling.md catch-order rules apply there, once).\n- A project may instead declare `throws TransactionException` on the interfaces — but that is a\n  recorded decision in the spec, not a per-service improvisation. Either way, `TxContext` (or an\n  equivalent wrapper) keeps transaction objects out of interface signatures, and conditional\n  mutations may return `boolean` so `UnsatisfiedConditionException` never escapes a repository.\n\n## Exception Mapping\n\n`exception-mapping-spec.md` covers two mappings, not one:\n\n1. **Internal** — infrastructure exceptions to domain exceptions, per @rules\u002Fscalardb-exception-handling.md\n   (catch order, rollback, retry policy).\n2. **External** — domain and infrastructure exceptions to RFC 9457 Problem Details responses, per\n   @rules\u002Fapi-error-standard.md §3. Every row of that table is covered, and\n   `UnknownTransactionStatusException` gets its own branch per §3.1 — it is neither a plain 500 nor a\n   blanket 503, and folding it into a generic handler is a blocker-severity defect downstream.\n\nThe retry policy belongs here too: a conflict exception must not reach the API layer before the\nservice has applied its own retries, so the specification says where retry lives and how many.\n\n## Acceptance Criteria\n\n- Every `operationId` in the API specifications has exactly one handler specified, and no handler is\n  specified that has no `operationId`\n- Every GraphQL resolver-bound field coordinate has exactly one handler specified, with no extra\n  annotated or runtime-wired handler\n- Every request DTO is distinct from the domain object and the persistence entity, with an explicit mapper\n- Every DTO field constraint is traceable to a schema constraint — no constraint invented, none dropped\n- Every operation's transaction boundary matches its placement in `operation-contracts.md`\n- Under `layering_style: clean`, every `operationId` has exactly one input boundary and one interactor, and every interactor that returns data names its output boundary and presenter\n- Every operation's authorization enforcement point is named\n- Every ScalarDB exception in @rules\u002Fapi-error-standard.md §3 has a mapped response, with §3.1 handled separately\n- All entities and aggregates in the design documents are covered\n- Interfaces are described at an abstraction level independent of implementation technology\n- When using ScalarDB, comply with @rules\u002Fscalardb-coding-patterns.md\n\n## Prerequisites\n\n| File | Required\u002FRecommended | Source |\n|------|---------------------|--------|\n| reports\u002F03_design\u002F | Required | design-* skill group |\n| reports\u002F03_design\u002Fapi-specifications\u002F | Required | \u002Farchitect:design-api — the contract the API layer specification binds to |\n| reports\u002F03_design\u002Fapi-specifications\u002Foperation-contracts.md | Required | \u002Farchitect:design-api — per-operation authorization, idempotency, timeout, transaction placement |\n| reports\u002F03_design\u002Fapi-specifications\u002Fproblem-types.md | Required | \u002Farchitect:design-api — the problem type registry the exception mapping resolves against |\n| reports\u002F03_design\u002Fapi-specifications\u002Fgraphql\u002Fresolver-contracts.md | Required when GraphQL is selected | \u002Farchitect:design-graphql |\n| reports\u002F03_design\u002Faggregates\u002Faggregate-manifest.json | Optional | \u002Farchitect:design-aggregate — the domain layer skeleton: root, interior entities, value objects, factory, specifications, one repository interface per aggregate |\n| reports\u002F02_evaluation\u002F | Recommended | integrate-evaluations |\n\n## Output\n\nOutput language and frontmatter: @rules\u002Foutput-conventions.md.\n\n| File | Content |\n|------|---------|\n| `reports\u002F06_implementation\u002Fapi-layer-spec.md` | `layering_style: ddd\\|clean` in the frontmatter; per-`operationId` handler, DTOs, validation, mapper, application service (or use case \u002F interactor \u002F presenter), transaction boundary, authorization enforcement point, idempotency handling |\n| `reports\u002F06_implementation\u002Fdomain-services-spec.md` | Service specifications |\n| `reports\u002F06_implementation\u002Frepository-interfaces-spec.md` | Repository specifications |\n| `reports\u002F06_implementation\u002Fvalue-objects-spec.md` | Value object definitions |\n| `reports\u002F06_implementation\u002Fexception-mapping-spec.md` | Exception mapping |\n\n## Related Skills\n\n| Skill | Relationship |\n|-------|-------------|\n| \u002Farchitect:design-microservices | Input source |\n| \u002Farchitect:design-scalardb | Input source |\n| \u002Farchitect:design-api | Input source — the contract the API layer specification binds to |\n| \u002Farchitect:generate-test-specs | Output consumer |\n| \u002Farchitect:generate-api-code | Output consumer — generates the API layer from `api-layer-spec.md` |\n| \u002Farchitect:generate-scalardb-code | Output consumer — generates the domain and persistence layers |\n| \u002Farchitect:verify-implementation | Output consumer — verifies the code against this specification |\n","# Implementation Design\n\nShared files: a path written `@rules\u002F…`, `@skills\u002F…`, `@templates\u002F…` or `@docs\u002F…` is relative to the\nplugin root, `${CLAUDE_PLUGIN_ROOT}` — not to the project being worked on. Read it from there.\n\n**Usage:** `\u002Farchitect:design-implementation [--layering=ddd|clean]`\n\n`--layering=clean` switches the application layer to Clean Architecture vocabulary (Use Case \u002F\nInteractor \u002F Presenter); the default keeps DDD application services.\n\n## Desired Outcome\n\nGenerate detailed, coding-ready implementation specifications from design documents:\n- **API layer specification** — controller \u002F DTO \u002F mapper \u002F application-service layering, bound to the\n  API contract operation by operation\n- Method signatures and responsibility definitions for domain services\n- Repository interface specifications (CRUD + custom queries)\n- Value object definitions and invariant conditions\n- Exception hierarchy and external exception mapping, including the Problem Details mapping\n- Interface contracts for inter-service communication\n\n## API Layer Specification\n\nThis is the specification that closes the gap between the API contract and the domain: it says which\nclass serves which REST `operationId` or GraphQL field coordinate, and what happens between the wire\nand the aggregate. Governed by @rules\u002Fapi-contract-fidelity.md and\n@rules\u002Fgraphql-contract-fidelity.md.\n\nSpecify, per REST `operationId` or GraphQL `\u003CparentType>.\u003CfieldName>` in\n`reports\u002F03_design\u002Fapi-specifications\u002F`:\n\n| Element | Content |\n|---------|---------|\n| Handler | The controller class and method that serves this operation, 1:1. REST names from `operationId`; GraphQL binds by field coordinate |\n| Request DTO | Class name from the `components\u002Fschemas` key, even when it collides with a domain simple name — the collision is resolved by package and import, never by re-styling the DTO (`MoneyDto`), which breaks the contract binding @rules\u002Fapi-contract-fidelity.md relies on. **Never the domain object and never the persistence entity** — binding a request body straight onto an entity is the mass-assignment defect |\n| Validation | The Bean Validation constraints derived from the schema: `minLength` -> `@Size`, `pattern` -> `@Pattern`, `enum` -> an enum type, `required` -> `@NotNull`. Derived, not hand-chosen; the request DTO is `@Valid` at the handler boundary. A `required` scalar is a **boxed** type (`Integer`, `Long`) — `@NotNull` on a primitive can never fire, and the constraint is silently dropped |\n| Mapper | The explicit DTO \u003C-> domain mapping, listing exactly the fields the schema declares. Under `clean` the row names two halves with two owners: `Request` -> `InputData` in `api\u002F` (`generate-api-code`), domain -> `OutputData` in the interactor or a `usecase\u002F` assembler (`generate-scalardb-code`) |\n| Response DTO | Class name from the schema key, carrying exactly the schema's properties — this is what stops an internal field leaking when the domain model later grows |\n| Application service | The method the handler delegates to, and **the transaction boundary**: which operations open a transaction, which join one, which are read-only. This must match the transaction placement recorded in `operation-contracts.md` |\n| Authorization | Where the operation's declared authorization rule is enforced — the role\u002Fscope check and the object-level ownership predicate. An operation with an ownership predicate needs the check named here, not assumed |\n| Idempotency | For operations carrying an `Idempotency-Key` obligation: where the key is read, where the record is stored, and the requirement that the record and the business write share **one** transaction (@rules\u002Fapi-error-standard.md §5) |\n\nThe layering is directional and the direction is part of the specification: controller -> application\nservice -> domain -> repository (under `--layering=clean`: controller -> use case boundary ->\ninteractor -> domain -> repository, with the presenter behind the output boundary — see Layering\nStyle). No reverse dependency, and no persistence or ScalarDB type appearing in a controller\nsignature. `generate-contract-tests` turns this into executable ArchUnit rules.\n\n## Layering Style (`--layering=ddd|clean`)\n\nThe layering above is the same under either style; the option decides the **names, granularity and\npackages** the application layer and its wire adapters take. Precedence: `--layering` ->\n`options.layering_style` in `work\u002Fpipeline-progress.json` -> `ddd`. The chosen style is recorded\nonce, as `layering_style: ddd|clean` in the frontmatter of `reports\u002F06_implementation\u002Fapi-layer-spec.md`,\nand mirrored to `options.layering_style` so a later run defaults to it. Every downstream generator\n(`generate-api-code`, `generate-graphql-code`, `generate-scalardb-code`, `generate-contract-tests`,\n`generate-acceptance-tests`) and `verify-implementation` read it from that frontmatter — none takes a\nflag of its own, so every generator in a run agrees on the vocabulary.\n\n**Switching the style of an already-generated service is a migration, not a regeneration**, and the\ntree is legitimately transitional between the two generator runs: `generate-api-code` runs first and\nadds `usecase\u002F` boundaries beside the existing `application\u002F`; `generate-scalardb-code` then moves\n`application\u002F` (`tx\u002F`, `view\u002F`, `worker\u002F`, shared collaborators) to `usecase\u002F`, writes the\ninteractors by splitting the existing services, deletes the replaced services, and repairs what\nstill names the old package — the JaCoCo includes, the ArchUnit rules, the component scan. A tree\nthat still holds both packages after that second run is the `verify-implementation` finding, and\nthe first run's summary names the transitional state rather than reporting a finished service.\n\n| Element | `ddd` (default) | `clean` (Clean Architecture vocabulary) |\n|---------|-----------------|-----------------------------------------|\n| Application package | `…\u002Fapplication\u002F` | `…\u002Fusecase\u002F` |\n| Unit of the application layer | one application service per aggregate or operation group (`OrderApplicationService`) | one **use case per `operationId`** (or GraphQL field coordinate): the input boundary `PlaceOrderUseCase` and its `PlaceOrderInteractor` |\n| What the handler passes in | request DTO mapped to domain values \u002F a command | `PlaceOrderInputData` — an immutable record in `usecase\u002F`, built by the controller's mapper |\n| What comes back | a domain value or result object the controller maps to the response DTO | `PlaceOrderOutputData`, handed to the **output boundary** `PlaceOrderOutputBoundary`; `PlaceOrderPresenter` in `…\u002Fapi\u002Fpresenter\u002F` implements it and produces the view model — the response DTO |\n| Wire package | `…\u002Fapi\u002F` (controllers, DTOs, mappers, exception handler) | `…\u002Fapi\u002F` unchanged, plus `…\u002Fapi\u002Fpresenter\u002F`; the response DTO doubles as the view model |\n| Repository port | `domain\u002F…\u002F\u003CRoot>Repository` | **unchanged** — Clean Architecture's *gateway* is this same domain-owned interface. The toolkit keeps the DDD name because the aggregate manifest, the Fakes (@rules\u002Ftdd-workflow.md §4) and the coverage \u002F mutation thresholds are keyed on it |\n| Transaction boundary | the application service opens it and passes it down | the interactor opens it and passes it down — same rule, same place |\n| Dependency rule | controller -> application service -> domain -> repository; no reverse edge | controller -> input boundary; interactor -> domain, repository ports, output boundary; presenter \u003C- output boundary. The interactor never imports `api\u002F` or `infrastructure\u002F`; the controller never imports an interactor class, only its boundary; the presenter never imports a domain type |\n| Cross-service outbound port | `domain\u002Fport\u002F\u003CX>Port` + Fake | unchanged |\n\nUnder `clean`, the per-operation table above names the use case (boundary + interactor), the input\ndata, the output boundary and the presenter in place of the single \"Application service\" row; every\nother row is unchanged. The naming is Robert C. Martin's (*Clean Architecture*, ch. 22); the layering\nit describes is the one `evaluate-ddd` already scores as criteria 10–12, so choosing `clean` changes\nvocabulary and granularity, not the architecture. Existing hand-written source that already has\napplication services is not asked to rename them; the specification this skill writes, however, is\nentirely in the chosen vocabulary — one document never mixes the two.\n\nOne behaviour-visible consequence follows from the presenter holding no business judgment: an outcome\nthe `ddd` mapper could decide from a returned read model (a declined payment returned as a\n`CANCELLED` order and mapped to 402) must under `clean` be decided in the interactor — it throws the\nexception the problem type registry maps — so the status the caller sees can change with the style.\nName such cases in the specification instead of discovering them in the contract tests.\n\n### `clean` — the details the table leaves open\n\n- **Boundary method.** The input boundary declares one method, `execute(\u003COp>InputData)`. Wire-facing\n  use cases return `void`; the result travels through the output boundary.\n- **Output boundary.** `void present(\u003COp>OutputData)`. The boundary lives in `usecase\u002F` and therefore\n  cannot name a response DTO, so the presenter is **request-scoped and stateful**: it stores the view\n  model it built, and the controller reads it back after `execute` returns.\n- **Domain-free data records.** `InputData`, `OutputData` and every nested record (`MoneyData`,\n  `PrincipalData` for the caller's identity and scopes) carry primitives, strings, and their own\n  enums only — never a domain type — because the presenter imports no domain type. The interactor\n  (or an assembler in `usecase\u002F` when several interactors share one shape) copies domain → output\n  data; the `api\u002F` mapper keeps the request side only (`Request` → `InputData`). This moves half of\n  the `ddd` mapper out of `generate-api-code`'s package into `generate-scalardb-code`'s — record the\n  transfer in the Mapper row.\n- **Entries without an `operationId`** — saga confirm \u002F compensate, recovery and expiry workers,\n  outbox relays: still one use case each (input boundary + interactor, `execute`) with **no output\n  boundary and no presenter**; there is nothing to present to. When a caller inside `usecase\u002F` (a\n  worker) needs the outcome, `execute` returns a domain-free result record; a `ddd` `boolean` that\n  would otherwise vanish is specified this way, or the caller reads the outcome from state.\n- **Shared collaborators are allowed in `usecase\u002F`.** Splitting one application service into N\n  interactors leaves shared logic (a settlement step, an unknown-status resolver, an assembler, the\n  workers and relays) that is not an interactor and has no boundary. It lives in `usecase\u002F`, is\n  called only from `usecase\u002F`, and may open a transaction. The \"who opens a transaction\" rule is\n  therefore stated **by package** (`usecase..` only), never by class-name suffix — a suffix rule is\n  the one that goes red on the first shared collaborator.\n- **Transactions.** The interactor of the orchestrating operation opens the transaction and passes\n  it down; a participant operation (`reserveStock`, `recordPayment`, …) joins the transaction it is\n  handed and never calls `begin()`. Carry the participant carve-out from the `ddd` specification\n  over verbatim.\n- **Exception types the handler branches on** (a contract's 402 \u002F 409 \u002F 422 problem types) live in\n  `usecase\u002F`, since `usecase\u002F` never imports `api\u002F`; the transaction exceptions live in\n  `usecase\u002Ftx\u002F`. The `api\u002F` exception handler imports them from there.\n- **Component scan.** `clean` introduces the `api\u002F` package; state that the Spring application\n  scans it (or lists its configuration) — a `ddd`-era `scanBasePackages` that names only\n  `infrastructure.config` starts an application with no controller in it.\n- **Rule ids.** Give the clean dependency rules numbers that continue the sequence the `ddd`\n  specification already declared (the test specifications cite rule ids), and state each rule so\n  ArchUnit can express it: \"controller never references an `*Interactor`\", \"`usecase` never\n  imports `api` or `infrastructure`\", \"`api.presenter` and the data records import no domain type\",\n  \"exactly one input boundary and one interactor per `operationId`, each output boundary implemented\n  exactly once, in `api.presenter`\". \"The presenter reaches the interactor only through the output\n  boundary\" is a description, not a rule — the presenter never reaches the interactor at all.\n\n## Testability Constraints (specify them — the generators and ArchUnit enforce them)\n\nThe specifications decide whether the code can be written test-first (@rules\u002Ftdd-workflow.md §4).\nState, in `repository-interfaces-spec.md` and `domain-services-spec.md`:\n\n- every repository interface is a **port** the domain owns, with an in-memory Fake named next to it\n  (`InMemory\u003CRoot>Repository`), and its not-found \u002F version-check contract stated so the Fake and the\n  ScalarDB adapter can be held to the same behaviour;\n- `Clock` and the id generator are **constructor dependencies** of every factory, application\n  service and saga step that reads time or mints an id — no `now()` \u002F `randomUUID()` inside domain or\n  application code;\n- the transaction is opened by the application service (the interactor, under `clean`) and passed\n  down; no domain type holds one.\n\nThese become ArchUnit rules in `generate-contract-tests` and are checked at stage 8 of the gate.\n\n## Repository Exception Strategy (specify it — do not leave it to codegen)\n\n`repository-interfaces-spec.md` states one exception-propagation strategy for the whole\nproject, because \"technology-independent interfaces\" and \"single-point retry classification\"\npull in opposite directions and every code generator otherwise invents its own bridge:\n\n- **Standard form**: domain repository interfaces throw no checked infrastructure exceptions;\n  infrastructure implementations wrap ScalarDB's checked exceptions in one project-wide\n  **unchecked wrapper** carrying the original as its cause; the application layer's retry\n  template unwraps the cause and performs the *only* conflict\u002Fcondition\u002Fpermanent classification\n  in the project (@rules\u002Fscalardb-exception-handling.md catch-order rules apply there, once).\n- A project may instead declare `throws TransactionException` on the interfaces — but that is a\n  recorded decision in the spec, not a per-service improvisation. Either way, `TxContext` (or an\n  equivalent wrapper) keeps transaction objects out of interface signatures, and conditional\n  mutations may return `boolean` so `UnsatisfiedConditionException` never escapes a repository.\n\n## Exception Mapping\n\n`exception-mapping-spec.md` covers two mappings, not one:\n\n1. **Internal** — infrastructure exceptions to domain exceptions, per @rules\u002Fscalardb-exception-handling.md\n   (catch order, rollback, retry policy).\n2. **External** — domain and infrastructure exceptions to RFC 9457 Problem Details responses, per\n   @rules\u002Fapi-error-standard.md §3. Every row of that table is covered, and\n   `UnknownTransactionStatusException` gets its own branch per §3.1 — it is neither a plain 500 nor a\n   blanket 503, and folding it into a generic handler is a blocker-severity defect downstream.\n\nThe retry policy belongs here too: a conflict exception must not reach the API layer before the\nservice has applied its own retries, so the specification says where retry lives and how many.\n\n## Acceptance Criteria\n\n- Every `operationId` in the API specifications has exactly one handler specified, and no handler is\n  specified that has no `operationId`\n- Every GraphQL resolver-bound field coordinate has exactly one handler specified, with no extra\n  annotated or runtime-wired handler\n- Every request DTO is distinct from the domain object and the persistence entity, with an explicit mapper\n- Every DTO field constraint is traceable to a schema constraint — no constraint invented, none dropped\n- Every operation's transaction boundary matches its placement in `operation-contracts.md`\n- Under `layering_style: clean`, every `operationId` has exactly one input boundary and one interactor, and every interactor that returns data names its output boundary and presenter\n- Every operation's authorization enforcement point is named\n- Every ScalarDB exception in @rules\u002Fapi-error-standard.md §3 has a mapped response, with §3.1 handled separately\n- All entities and aggregates in the design documents are covered\n- Interfaces are described at an abstraction level independent of implementation technology\n- When using ScalarDB, comply with @rules\u002Fscalardb-coding-patterns.md\n\n## Prerequisites\n\n| File | Required\u002FRecommended | Source |\n|------|---------------------|--------|\n| reports\u002F03_design\u002F | Required | design-* skill group |\n| reports\u002F03_design\u002Fapi-specifications\u002F | Required | \u002Farchitect:design-api — the contract the API layer specification binds to |\n| reports\u002F03_design\u002Fapi-specifications\u002Foperation-contracts.md | Required | \u002Farchitect:design-api — per-operation authorization, idempotency, timeout, transaction placement |\n| reports\u002F03_design\u002Fapi-specifications\u002Fproblem-types.md | Required | \u002Farchitect:design-api — the problem type registry the exception mapping resolves against |\n| reports\u002F03_design\u002Fapi-specifications\u002Fgraphql\u002Fresolver-contracts.md | Required when GraphQL is selected | \u002Farchitect:design-graphql |\n| reports\u002F03_design\u002Faggregates\u002Faggregate-manifest.json | Optional | \u002Farchitect:design-aggregate — the domain layer skeleton: root, interior entities, value objects, factory, specifications, one repository interface per aggregate |\n| reports\u002F02_evaluation\u002F | Recommended | integrate-evaluations |\n\n## Output\n\nOutput language and frontmatter: @rules\u002Foutput-conventions.md.\n\n| File | Content |\n|------|---------|\n| `reports\u002F06_implementation\u002Fapi-layer-spec.md` | `layering_style: ddd\\|clean` in the frontmatter; per-`operationId` handler, DTOs, validation, mapper, application service (or use case \u002F interactor \u002F presenter), transaction boundary, authorization enforcement point, idempotency handling |\n| `reports\u002F06_implementation\u002Fdomain-services-spec.md` | Service specifications |\n| `reports\u002F06_implementation\u002Frepository-interfaces-spec.md` | Repository specifications |\n| `reports\u002F06_implementation\u002Fvalue-objects-spec.md` | Value object definitions |\n| `reports\u002F06_implementation\u002Fexception-mapping-spec.md` | Exception mapping |\n\n## Related Skills\n\n| Skill | Relationship |\n|-------|-------------|\n| \u002Farchitect:design-microservices | Input source |\n| \u002Farchitect:design-scalardb | Input source |\n| \u002Farchitect:design-api | Input source — the contract the API layer specification binds to |\n| \u002Farchitect:generate-test-specs | Output consumer |\n| \u002Farchitect:generate-api-code | Output consumer — generates the API layer from `api-layer-spec.md` |\n| \u002Farchitect:generate-scalardb-code | Output consumer — generates the domain and persistence layers |\n| \u002Farchitect:verify-implementation | Output consumer — verifies the code against this specification |\n",{"model":34,"description":52,"argument-hint":53},"Write coding-ready specs: the API layer (controllers, DTOs, validation), domain services,\nrepository ports and their Fakes, value objects and exception mapping. Runs after the design\nphase.\n","[--layering=ddd|clean]","main","fed4c7ebb79ed82ce5c961f944a1ab0ab21bae26","skills\u002Fdesign-implementation",1,"https:\u002F\u002Fgithub.com\u002Fwfukatsu\u002Fnexus-architect","https:\u002F\u002Fnexus-architect-docs-070772.gitlab.io\u002F","https:\u002F\u002Fgithub.com\u002Fwfukatsu","https:\u002F\u002Fwww.scalar-labs.com\u002F","Wataru Fukatsu | Co-Founder and CEO, Scalar, Inc.","2026-11-10 07:17:53",{"source":8,"skillName":5,"commands":65,"prompt":75,"zipAvailable":76},[66,69,72],{"tool":67,"command":68},"npx","npx skills add wfukatsu\u002Fnexus-architect --skill design-implementation",{"tool":70,"command":71},"bunx","bunx skills add wfukatsu\u002Fnexus-architect --skill design-implementation",{"tool":73,"command":74},"pnpm","pnpm dlx skills add wfukatsu\u002Fnexus-architect --skill design-implementation","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fwfukatsu\u002Fnexus-architect\u002Fblob\u002Fmain\u002Fskills\u002Fdesign-implementation\u002FSKILL.md",true,[],[79,112,139,168,191,209],{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":91,"publishedAt":47},"01M6HRH10GPAVTZ8W90WD9HJK1","verify-sql-migration","Prove a SQL migration on data: golden checks against an authorized source database and\ndifferential tests against ScalarDB. Never touches production.","https:\u002F\u002Fgithub.com\u002Fwfukatsu\u002Fnexus-architect\u002Fblob\u002Fmain\u002Fskills\u002Fverify-sql-migration\u002FSKILL.md",[85,88],{"categoryNo":86,"categoryName":87,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":89,"categoryName":90,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000033","数据分析师",[92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111],"sql","verify","migration","verify sql migration","core","database","data","Production","auto","never","en","properties","fetcher","tests","id","golden","sonnet","true","mode","source",{"skillNo":113,"name":114,"nameZh":6,"description":115,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":125,"publishedAt":47},"01M6HRGWK643YKN0QVRQSNSDCR","verify-implementation","Check code against the design (API contract, transactions, security, requirements, the example\nchain) and report every divergence; optionally runs the eight-stage quality gate.","https:\u002F\u002Fgithub.com\u002Fwfukatsu\u002Fnexus-architect\u002Fblob\u002Fmain\u002Fskills\u002Fverify-implementation\u002FSKILL.md",[118,119,122],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":120,"categoryName":121,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000030","开发工程师",{"categoryNo":123,"categoryName":124,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000037","律师与法务",[93,30,126,31,127,128,42,129,130,100,131,102,132,133,134,135,136,137,138,109],"verify implementation","quality gate","code","repo","check","example","api contract","backlog","stage","requirements","contract","chain","scope",{"skillNo":140,"name":141,"nameZh":6,"description":142,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":143,"categories":144,"keywords":151,"publishedAt":47},"01M6HRGS929NK1B5WG1ZANSXQ1","update-knowledge","Fetch or update an OKF knowledge bundle: ScalarDB\u002FScalarDL, or the vendored Kubernetes\u002FTerraform\nbundle.","https:\u002F\u002Fgithub.com\u002Fwfukatsu\u002Fnexus-architect\u002Fblob\u002Fmain\u002Fskills\u002Fupdate-knowledge\u002FSKILL.md",[145,148],{"categoryNo":146,"categoryName":147,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署",{"categoryNo":149,"categoryName":150,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000021","资料检索与研究",[152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167],"update","knowledge","update knowledge","kubernetes","status","plugin","terraform","Tools","Bash","okf","haiku","fetch","bundle","name","root","latest",{"skillNo":169,"name":170,"nameZh":6,"description":171,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":172,"categories":173,"keywords":176,"publishedAt":47},"01M6HRGNMYSK70R8Y9BY41E74D","start","Interactive entry point for system architecture work: refactor a legacy application into services,\nor design a new system from requirements; picks the path from the project's state. To move a\ndatabase to ScalarDB, use migrate-database.","https:\u002F\u002Fgithub.com\u002Fwfukatsu\u002Fnexus-architect\u002Fblob\u002Fmain\u002Fskills\u002Fstart\u002FSKILL.md",[174,175],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},[170,31,177,178,97,43,179,180,181,182,183,184,185,186,187,135,188,189,190],"architecture","state","refactor","migrate","system","work","interactive","use","Legacy","application","project","move","path","for",{"skillNo":192,"name":193,"nameZh":6,"description":194,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":195,"categories":196,"keywords":197,"publishedAt":47},"01M6HRGHZXK0NXF6W62MMNS46H","select-scalardb-edition","Choose the ScalarDB edition (Community, Enterprise Standard or Premium, plus Enterprise Options),\ndeployment mode and cluster topology through a short interview.","https:\u002F\u002Fgithub.com\u002Fwfukatsu\u002Fnexus-architect\u002Fblob\u002Fmain\u002Fskills\u002Fselect-scalardb-edition\u002FSKILL.md",[],[198,199,200,201,202,203,204,205,206,207,208,108,110],"select","select scalardb edition","deployment","topology","Enterprise","choose","short","interview","community","options","cluster",{"skillNo":210,"name":211,"nameZh":6,"description":212,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":213,"categories":214,"keywords":216,"publishedAt":47},"01M6HRGESF0BH6KCT70BP70B2J","scaffold","Generate a runnable ScalarDB starter project for any of the six interface combinations: build,\nconfig, schema, service class, docker-compose and README.","https:\u002F\u002Fgithub.com\u002Fwfukatsu\u002Fnexus-architect\u002Fblob\u002Fmain\u002Fskills\u002Fscaffold\u002FSKILL.md",[215],{"categoryNo":86,"categoryName":87,"taxonomyType":21,"taxonomyTypeDesc":22},[211,217,218,219,220,221,222,223,224,187,225,226,227,228,108,190],"docker","config","generate","README","schema","compose","build","docker-compose","combinations","service","starter","interface"]