Initial commit
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
---
|
||||
name: tdfddd-assembly
|
||||
description: "Phase 4: Implementation Assembly. Translates F# models into TypeScript/Effect code. Triggers on: Implement the code, Phase 4, Start assembly, Generate TypeScript, Write Effect code."
|
||||
---
|
||||
|
||||
# Assembly Agent: The Implementer
|
||||
|
||||
## Description
|
||||
|
||||
Phase 4: Implementation Assembly. Translates F# models into TypeScript/Effect code.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Activate when the user:
|
||||
|
||||
- Says "Implement the code".
|
||||
- Says "Phase 4" or "Start assembly".
|
||||
- Says "Generate TypeScript" or "Write Effect code".
|
||||
- Has already completed Blueprint for one workflow slice.
|
||||
|
||||
## Core Function: The Translator
|
||||
|
||||
**Goal:** Mechanically translate the F# Domain Model into idiomatic TypeScript/Effect code.
|
||||
|
||||
F# is the primary design language and contract artifact for this phase. Assembly is a translation step from the frozen F# blueprint, not a redesign step.
|
||||
|
||||
Use TDD during assembly, but only after the design is frozen. The contract from the blueprint determines the test surface.
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- Read `design/workflows/<bounded-context-slug>/shared-model.fs` when present and `design/workflows/<bounded-context-slug>/<workflow-slug>/04-blueprint.fs` as input.
|
||||
- Generate valid, **type-safe** TypeScript code using the Effect library.
|
||||
- **Do not** deviate from the blueprint.
|
||||
- **Do not** invent new business rules.
|
||||
- Implement exactly one workflow slice at a time.
|
||||
|
||||
**Instructions:**
|
||||
|
||||
1. Read `design/workflows/<bounded-context-slug>/shared-model.fs` when present and `design/workflows/<bounded-context-slug>/<workflow-slug>/04-blueprint.fs`.
|
||||
2. Read `design/feature/<feature-slug>/status.md` and confirm this workflow slice is selected for implementation.
|
||||
3. Confirm the design/security gate is approved before writing implementation code.
|
||||
4. Treat the selected `04-blueprint.fs` as the complete contract for exactly one workflow slice. Do not look for or assume additional slice blueprints in the same artifact.
|
||||
5. Defer all other workflow slices to their own blueprint and assembly passes.
|
||||
6. **Follow Strict Project Structure:**
|
||||
7. Derive tests from the frozen contract before or alongside code:
|
||||
- workflow scenarios from commands and events
|
||||
- policy examples from decision points
|
||||
- model properties from invariants and state transitions
|
||||
8. Implement in vertical **RED -> GREEN -> REFACTOR** cycles.
|
||||
- **RED:** pick one behavior from the frozen contract, write one test through the public seam, and confirm it fails for the expected reason.
|
||||
- **GREEN:** write the minimum production code needed to make that single test pass. Do not implement extra behaviors early.
|
||||
- **REFACTOR:** once green, improve names, duplication, and module depth without changing behavior. Re-run tests after each refactor.
|
||||
- Avoid premature indirection during refactor: keep logic combined by default, and extract only when the green code shows a real gain in nameability, testability, reuse, boundary clarity, or duplicated complexity.
|
||||
- Good names help reveal useful extractions, but they do not justify an unnecessary layer by themselves.
|
||||
- Start with one **tracer bullet** test that proves the end-to-end path, then add one behavior at a time.
|
||||
- Never refactor while red.
|
||||
9. **Follow Strict Project Structure:**
|
||||
- **`src/domain/models/`** (Pure Domain Knowledge):
|
||||
- Place `Effect.Schema` definitions here.
|
||||
- Place `Brand` types here.
|
||||
- Place Pure Logic (e.g., `Money.add`, `Cart.isEmpty`).
|
||||
- **NO** external dependencies, **NO** `Effect<...>`, **NO** Side Effects.
|
||||
- **`src/domain/interfaces/`** (Service Contracts):
|
||||
- Define interfaces for repositories and services (e.g., `interface PaymentRepo`).
|
||||
- Use `Context.Tag` for dependency injection.
|
||||
- **`src/policies/`** (Business Decisions):
|
||||
- Pure functions that make decisions based on multi-entity context.
|
||||
- Returns `Result` or `Strategy Decision`.
|
||||
- **NO** Side Effects.
|
||||
- Example: `determinePaymentStrategy(amount)`, `canAccessResource(user, resource)`.
|
||||
- **`src/workflows/`** (Orchestration):
|
||||
- The "Impure Shell". Connects pieces, manages transaction flow.
|
||||
- Uses `Effect.gen(function*(_) { ... })`.
|
||||
- Orchestrates: 1. Fetch State (Repo) -> 2. Policy Decision (Policy) -> 3. Apply Change (Model) -> 4. Save (Repo).
|
||||
- **`src/registries/`** (Dynamic Wiring):
|
||||
- Strategy Pattern implementation (e.g., selecting Stripe vs PayPal based on Policy).
|
||||
- **`src/adapters/`** (Infrastructure):
|
||||
- Concrete implementations of interfaces (e.g., `Stripe.service.ts`).
|
||||
- Place adapters here.
|
||||
- **`src/layers/`** (Dependency Injection):
|
||||
- `Main.layer.ts` for wiring production dependencies.
|
||||
10. Integrate **Input Security** (See docs/explanation/architecture/input-security.md):
|
||||
- **Wrappers:** Never pass raw strings to sensitive sinks. Translate raw string inputs into strongly typed wrappers (e.g., `TrustedInput`, `TaintedInput`) at the boundary.
|
||||
- **Provenance:** Ensure the type explicitly states the source and trust level.
|
||||
- **Strict Ingestion:** Implement strict filtering (length, type, format) at the ingestion point (e.g., in the Controller or the very beginning of the Workflow).
|
||||
- **Late Sanitization:** Apply encoding or context-specific escaping right before the string is consumed (e.g., in an Adapter right before a DB call or API request).
|
||||
- **Structural Safety:** Use parameterized queries or structural objects instead of string concatenation.
|
||||
11. Translate **Primitives**:
|
||||
- `type Weight = int<kg>` -> `const Weight = Schema.Number.pipe(Schema.brand("Kg"))`
|
||||
- Always export the type: `export type Weight = typeof Weight.Type`
|
||||
12. Translate **Structures (Records)**:
|
||||
- `type User = { Name: string }` -> `const User = Schema.Struct({ name: Schema.String })`
|
||||
13. Translate **Unions (Aggregates/Events)**:
|
||||
- `type State = A | B` -> `Schema.Union(A, B)` (Discriminated Union)
|
||||
14. Implement the **Contract**:
|
||||
- `decide : State -> Command -> Result` -> `export const decide = (state: State, cmd: Command): Either<Error, Event> => ...`
|
||||
- `apply : State -> Event -> State` -> `export const apply = (state: State, event: Event): State => ...`
|
||||
- `workflow : Command -> Effect<Result>` -> `export const workflow = (cmd: Command) => Effect.gen(...)`
|
||||
15. **Action:** Write the implementation files to `src/` and the tests to `test/`, then update `design/feature/<feature-slug>/status.md` for the current workflow slice.
|
||||
- `src/domain/models/`: Types & Schemas
|
||||
- `src/policies/`: Pure Logic (`decide`)
|
||||
- `src/workflows/`: Effect Orchestration (`workflow`)
|
||||
16. **Format:** Use strict TypeScript with Effect.
|
||||
17. **Test style by layer:**
|
||||
- `src/domain/models/` and `src/policies/`: example tests plus property-based tests for invariants.
|
||||
- `src/workflows/`: scenario tests with Effect test layers / in-memory adapters.
|
||||
- `src/adapters/`: contract tests and integration tests where appropriate.
|
||||
18. **Per-cycle checklist:**
|
||||
- test describes behavior, not implementation
|
||||
- test uses the public interface only
|
||||
- code change is minimal for the current failing test
|
||||
- no speculative features or extra cases are added
|
||||
19. **Verification before completion:**
|
||||
- Run `pnpm verify` before declaring the implementation complete.
|
||||
- Run `pnpm effect:check <filepath>` for each modified Effect file.
|
||||
- Report verification results faithfully, including any failing command output.
|
||||
|
||||
## Translation Table
|
||||
|
||||
| F# Concept | TypeScript / Effect Implementation |
|
||||
| :-------------------- | :---------------------------------------------------- | -------------------- |
|
||||
| `type T = int<brand>` | `const T = Schema.Number.pipe(Schema.brand("Brand"))` |
|
||||
| `type R = { f: T }` | `const R = Schema.Struct({ f: T })` |
|
||||
| `type U = A | B` | `Schema.Union(A, B)` |
|
||||
| `Result<T, E>` | `Either<E, T>` |
|
||||
| `Async<Result<T, E>>` | `Effect<T, E>` |
|
||||
|
||||
## Usage Examples
|
||||
|
||||
**User:** "Implement it."
|
||||
**Agent (Implementer):** [Reads `design/workflows/loading/load-truck/04-blueprint.fs` and `design/feature/truck-loading/status.md`]
|
||||
[Generates `src/domain/models/Truck.ts`]
|
||||
[Generates `src/policies/LoadPolicy.ts`]
|
||||
[Generates `src/workflows/LoadWorkflow.ts`]
|
||||
"Implementation complete for the selected workflow slice based on the blueprint."
|
||||
Reference in New Issue
Block a user