Initial commit
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# Project Conventions
|
||||
|
||||
This page is the quick reference for conventions that a human reviewer is likely to check first.
|
||||
For the philosophy behind these conventions, read the explanation docs.
|
||||
|
||||
## Naming
|
||||
|
||||
- Use domain language, not generic programmer words.
|
||||
- Prefer explicit lifecycle states such as `DraftItem` or `ActiveOrder` over one object with a broad `status` field.
|
||||
- Use nouns for stateful objects, past-tense facts for events, and imperative verb phrases for commands.
|
||||
- Maintain a project-wide shared language in `shared-language.md`.
|
||||
- Maintain bounded-context shared language in `design/workflows/<bounded-context-slug>/shared-language.md`.
|
||||
- Record feature-level naming decisions in `design/feature/<feature-slug>/discovery.md` and slice-level naming decisions in the workflow artifacts.
|
||||
- See `naming-lexicon.md`, `shared-language.md`, and `../explanation/naming-for-domain-modeling.md` for guidance.
|
||||
|
||||
## Design artifact shape
|
||||
|
||||
A complete operational design set now usually includes:
|
||||
|
||||
- feature discovery in `design/feature/<feature-slug>/discovery.md`
|
||||
- feature decomposition in `design/feature/<feature-slug>/design.md`
|
||||
- bounded-context shared language in `design/workflows/<bounded-context-slug>/shared-language.md`
|
||||
- slice discovery, core sketch, and F# blueprint under `design/workflows/<bounded-context-slug>/<workflow-slug>/`
|
||||
- status tracking in `design/feature/<feature-slug>/status.md`
|
||||
|
||||
Use `design-artifact-template.md` for by-hand practice and `design-artifact-structure.md` for the repository artifact layout.
|
||||
|
||||
## Documentation organization
|
||||
|
||||
This repo uses a modified Diátaxis structure:
|
||||
|
||||
- `docs/tutorials/` for learning by example and practice
|
||||
- `docs/how-to/` for specific tasks such as reviewing LLM output
|
||||
- `docs/explanation/` for philosophy and architectural reasoning
|
||||
- `docs/reference/` for templates, checklists, and stable lookup material
|
||||
|
||||
## Code structure pointers
|
||||
|
||||
- `src/contexts/` is the default home for business code.
|
||||
- Each context keeps its own models, policies, workflows, translators, adapters, and other seams as needed.
|
||||
- `src/workflows/` is reserved for top-level workflows that coordinate multiple contexts.
|
||||
- `src/shared/` should contain only tiny ubiquitous primitives and low-meaning technical building blocks.
|
||||
|
||||
## Module boundaries
|
||||
|
||||
- Cross-context imports should go through the target context's public API.
|
||||
- Do not import another context's internal implementation files.
|
||||
- When data crosses context boundaries, prefer translation at the edge over sharing one rich domain type everywhere.
|
||||
|
||||
## Decision preference
|
||||
|
||||
- Prefer correctness, simplicity, and elegance over backwards compatibility.
|
||||
- If compatibility would preserve a worse design, require an explicit reason before keeping it.
|
||||
- Prefer combined local logic by default during initial implementation.
|
||||
- Extract a new layer, module, or helper only when it materially improves nameability, testability, reuse, boundary clarity, or duplicated complexity.
|
||||
- Good names can expose a useful seam, but naming alone does not justify extra indirection.
|
||||
|
||||
## Review reminder
|
||||
|
||||
When in doubt, compare the artifact being reviewed against:
|
||||
|
||||
- `../tutorials/worked-example-truck-loading.md`
|
||||
- `review-checklist.md`
|
||||
- `design-artifact-template.md`
|
||||
@@ -0,0 +1,143 @@
|
||||
# Design Artifact Structure
|
||||
|
||||
This is the current artifact layout for real feature work.
|
||||
Use this structure for feature discovery, bounded-context decomposition, workflow-slice design, implementation tracking, and handoff between agents or humans.
|
||||
|
||||
## Top-level idea
|
||||
|
||||
- **Feature discovery** happens once per feature.
|
||||
- **Decomposition** maps the feature into bounded contexts and workflow slices.
|
||||
- **Slice design and implementation** happen one workflow slice at a time.
|
||||
- **F# blueprint artifacts** are the frozen contract that implementation translates from.
|
||||
|
||||
## Feature-level artifacts
|
||||
|
||||
Store feature-level documents in:
|
||||
|
||||
```text
|
||||
design/feature/<feature-slug>/
|
||||
├── discovery.md
|
||||
├── design.md
|
||||
└── status.md
|
||||
```
|
||||
|
||||
### `discovery.md`
|
||||
|
||||
Capture:
|
||||
|
||||
- feature story
|
||||
- commands and events at feature level
|
||||
- business rules and invariants at feature level
|
||||
- edge cases at feature level
|
||||
- candidate bounded contexts
|
||||
- candidate workflow slices
|
||||
- feature-level shared language notes
|
||||
|
||||
### `design.md`
|
||||
|
||||
Capture:
|
||||
|
||||
- bounded context inventory
|
||||
- feature-step to workflow-slice map
|
||||
- cross-context handoffs
|
||||
- recommended slice order
|
||||
- orchestration notes
|
||||
- open questions
|
||||
|
||||
### `status.md`
|
||||
|
||||
Track:
|
||||
|
||||
- current feature phase
|
||||
- current workflow slice
|
||||
- decomposition completion
|
||||
- per-slice gate status
|
||||
- blockers and handoff notes
|
||||
|
||||
Use [design-status-template.md](design-status-template.md) as the base template.
|
||||
|
||||
## Workflow-level artifacts
|
||||
|
||||
Store workflow-slice documents in:
|
||||
|
||||
```text
|
||||
design/workflows/<bounded-context-slug>/
|
||||
├── shared-language.md
|
||||
├── shared-model.fs # optional, when the context has reusable F# domain pieces
|
||||
└── <workflow-slug>/
|
||||
├── 01-decomposition.md
|
||||
├── 02-discovery.md
|
||||
├── 03-core-sketch.md
|
||||
└── 04-blueprint.fs
|
||||
```
|
||||
|
||||
### `shared-language.md`
|
||||
|
||||
Capture bounded-context-local ubiquitous language:
|
||||
|
||||
- what the context owns
|
||||
- preferred terms
|
||||
- rejected synonyms
|
||||
- notes about overlap with project-wide language in [shared-language.md](shared-language.md)
|
||||
|
||||
### `01-decomposition.md`
|
||||
|
||||
Capture:
|
||||
|
||||
- owning bounded context
|
||||
- trigger
|
||||
- purpose and success outcome
|
||||
- inputs owned by this context
|
||||
- observed inputs from other contexts
|
||||
- downstream handoffs
|
||||
- dependencies on other slices
|
||||
- explicit note that decision logic stays inside the owning context
|
||||
|
||||
### `02-discovery.md`
|
||||
|
||||
Capture:
|
||||
|
||||
- happy path
|
||||
- edge cases
|
||||
- business rules and invariants
|
||||
- decisions owned by this context
|
||||
- handoff assumptions
|
||||
- open questions
|
||||
|
||||
### `03-core-sketch.md`
|
||||
|
||||
Capture:
|
||||
|
||||
- command
|
||||
- required owned state
|
||||
- observed external inputs
|
||||
- pseudo policy signature
|
||||
- events
|
||||
- boundary notes about what remains feature-level orchestration
|
||||
|
||||
### `04-blueprint.fs`
|
||||
|
||||
This is the frozen F# contract for one workflow slice.
|
||||
It should include:
|
||||
|
||||
- domain primitives
|
||||
- commands
|
||||
- events
|
||||
- states / aggregates
|
||||
- `decide`
|
||||
- `apply`
|
||||
- workflow contract signature
|
||||
|
||||
## Rules of use
|
||||
|
||||
- One workflow slice belongs to one bounded context.
|
||||
- No cross-context decision logic belongs inside a workflow slice.
|
||||
- Cross-context behavior belongs in feature-level handoff and orchestration notes.
|
||||
- Shared language should exist both globally and per bounded context.
|
||||
- Implementation should proceed one slice at a time from the frozen F# blueprint.
|
||||
|
||||
## Relationship to the by-hand docs
|
||||
|
||||
The [../by-hand/README.md](../by-hand/README.md) material keeps the simpler 5-phase human practice flow.
|
||||
Use that to build judgment.
|
||||
Use this page for the actual repository artifact structure.
|
||||
@@ -0,0 +1,111 @@
|
||||
# Design Artifact Template
|
||||
|
||||
Use this template when drafting a design manually or when asking an LLM to produce a design artifact for review.
|
||||
|
||||
## 1. Story
|
||||
|
||||
Write the business situation in plain language.
|
||||
|
||||
```text
|
||||
A <role> attempts to <action>.
|
||||
If <condition>, it succeeds.
|
||||
If <condition>, it fails.
|
||||
```
|
||||
|
||||
## 2. Event storming
|
||||
|
||||
### Command
|
||||
|
||||
```text
|
||||
<ImperativeVerbNoun>
|
||||
```
|
||||
|
||||
### Timeline
|
||||
|
||||
1. <user intent>
|
||||
2. <business evaluation>
|
||||
3. <success or failure fact>
|
||||
|
||||
### Events
|
||||
|
||||
```text
|
||||
<SuccessEvent>
|
||||
<FailureEvent>
|
||||
```
|
||||
|
||||
## 3. Core sketch
|
||||
|
||||
Write the first policy sketch with rough concepts if needed.
|
||||
|
||||
```fsharp
|
||||
decide : NeededInput -> NeededState -> Result<SuccessEvent, FailureEvent>
|
||||
```
|
||||
|
||||
Then rewrite it using domain-specific concepts.
|
||||
|
||||
## 4. Domain model
|
||||
|
||||
### Primitives
|
||||
|
||||
```fsharp
|
||||
type ExampleId = string
|
||||
```
|
||||
|
||||
### Compound objects
|
||||
|
||||
```fsharp
|
||||
type Example = {
|
||||
Id: ExampleId
|
||||
}
|
||||
```
|
||||
|
||||
### State variants
|
||||
|
||||
```fsharp
|
||||
type ActiveExample = { Id: ExampleId }
|
||||
type ArchivedExample = { Id: ExampleId }
|
||||
|
||||
type ExampleState =
|
||||
| Active of ActiveExample
|
||||
| Archived of ArchivedExample
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
```fsharp
|
||||
type ExampleSucceeded = { Id: ExampleId }
|
||||
type ExampleRejected = { Reason: RejectionReason }
|
||||
```
|
||||
|
||||
## 5. Final contract
|
||||
|
||||
```fsharp
|
||||
decide : Input -> State -> Result<SuccessEvent, FailureEvent>
|
||||
apply : State -> SuccessEvent -> State
|
||||
workflow : InputId -> Effect<Response>
|
||||
```
|
||||
|
||||
## 6. Shared language and naming decisions
|
||||
|
||||
Record the canonical words for this feature so design and code stay consistent. If a term is project-wide rather than feature-local, also add it to `docs/reference/shared-language.md`.
|
||||
|
||||
### Canonical terms
|
||||
|
||||
- `<Preferred term>`: short definition
|
||||
- `<Preferred term>`: short definition
|
||||
|
||||
### Rejected synonyms
|
||||
|
||||
- Use `<Preferred term>`, not `<Rejected term>`
|
||||
- Use `<Preferred term>`, not `<Rejected term>`
|
||||
|
||||
### Naming grammar for this feature
|
||||
|
||||
- Commands use: `<ImperativeVerbNoun>`
|
||||
- Events use: `<PastTenseFact>`
|
||||
- States / objects use: `<DomainNoun>`
|
||||
- Workflow names use: `<verbNoun>`
|
||||
|
||||
## 7. Reviewer notes
|
||||
|
||||
Document any assumptions, open domain questions, or naming choices the reviewer should inspect.
|
||||
@@ -0,0 +1,117 @@
|
||||
# Design Status Template
|
||||
|
||||
Use this file as `design/feature/<feature-slug>/status.md`.
|
||||
It tracks feature-level discovery/decomposition, workflow slices, and per-slice progress through the downstream pipeline.
|
||||
|
||||
## Feature
|
||||
|
||||
- Name: `<feature-name>`
|
||||
- Feature slug: `<feature-slug>`
|
||||
- Current phase: `Feature Discovery | Context & Workflow Decomposition | Slice Discovery | Core Sketch | Blueprint | Design Security Review | Assembly | Implementation Security Review | Refactor Diagnosis | Refactor Execution | Done`
|
||||
- Overall status: `In Progress | Blocked | Ready for Next Phase | Complete`
|
||||
- Security verification status: `Not Started | Design Review Needed | Design Review Complete | Implementation Review Needed | Implementation Review Complete`
|
||||
- Current workflow slice: `<bounded-context-slug>/<workflow-slug> | none`
|
||||
|
||||
## Feature Artifacts
|
||||
|
||||
- [ ] `design/feature/<feature-slug>/discovery.md`
|
||||
- [ ] `design/feature/<feature-slug>/design.md`
|
||||
- [ ] `design/feature/<feature-slug>/status.md`
|
||||
|
||||
## Feature Discovery Gate
|
||||
|
||||
- [ ] feature goal and actor intents captured
|
||||
- [ ] commands and events identified at feature level
|
||||
- [ ] business rules and invariants captured at feature level
|
||||
- [ ] edge cases captured at feature level
|
||||
- [ ] candidate bounded contexts identified
|
||||
- [ ] candidate workflow inventory identified
|
||||
- [ ] project-wide shared-language updates captured
|
||||
- [ ] approved for context and workflow decomposition
|
||||
|
||||
## Context & Workflow Decomposition Gate
|
||||
|
||||
- [ ] bounded contexts confirmed
|
||||
- [ ] feature steps mapped to workflow slices
|
||||
- [ ] cross-context handoffs recorded
|
||||
- [ ] per-context shared-language files created or updated
|
||||
- [ ] workflow folders created with `01-decomposition.md`
|
||||
- [ ] recommended slice order recorded
|
||||
- [ ] approved to begin slice discovery
|
||||
|
||||
## Workflow Slice Tracker
|
||||
|
||||
| Bounded Context | Workflow Slice | Slice Discovery | Core Sketch | Blueprint | Design Security | Assembly | Impl Security | Refactor | Notes |
|
||||
| :--------------- | :---------------- | :-------------- | :------------ | :------------ | :-------------- | :------------ | :------------ | :------------ | :------- |
|
||||
| `<context-slug>` | `<workflow-slug>` | `Not Started` | `Not Started` | `Not Started` | `Not Started` | `Not Started` | `Not Started` | `Not Started` | `<note>` |
|
||||
| `<context-slug>` | `<workflow-slug>` | `Not Started` | `Not Started` | `Not Started` | `Not Started` | `Not Started` | `Not Started` | `Not Started` | `<note>` |
|
||||
|
||||
## Current Slice Gates
|
||||
|
||||
### Slice Discovery Gate
|
||||
|
||||
- [ ] selected slice named explicitly
|
||||
- [ ] happy path captured
|
||||
- [ ] edge cases captured
|
||||
- [ ] business rules and invariants captured
|
||||
- [ ] handoff assumptions captured
|
||||
- [ ] context shared-language updates captured
|
||||
- [ ] approved for core sketch
|
||||
|
||||
### Core Sketch Gate
|
||||
|
||||
- [ ] required state is explicit
|
||||
- [ ] command and events are explicit
|
||||
- [ ] policy signature is explicit
|
||||
- [ ] slice boundaries are explicit
|
||||
- [ ] no cross-context decision logic inside the slice
|
||||
- [ ] approved for blueprint
|
||||
|
||||
### Blueprint Gate
|
||||
|
||||
- [ ] domain types make illegal states harder to express
|
||||
- [ ] shared concepts reused appropriately
|
||||
- [ ] policy is pure
|
||||
- [ ] reducer/apply shape is explicit
|
||||
- [ ] workflow contract is explicit
|
||||
- [ ] approved for design security review or assembly
|
||||
|
||||
### Design Security Gate
|
||||
|
||||
- [ ] trust boundaries reviewed
|
||||
- [ ] authority and least privilege reviewed
|
||||
- [ ] sink and data-flow risks reviewed
|
||||
- [ ] blocking findings resolved or explicitly accepted
|
||||
- [ ] approved for assembly
|
||||
|
||||
### Assembly Gate
|
||||
|
||||
- [ ] tests added
|
||||
- [ ] implementation completed
|
||||
- [ ] types pass
|
||||
- [ ] tests passing
|
||||
- [ ] effect AST checks run for modified Effect files
|
||||
- [ ] approved for implementation security review or next slice
|
||||
|
||||
### Implementation Security Gate
|
||||
|
||||
- [ ] implementation security review completed or explicitly deferred
|
||||
- [ ] blocking findings resolved or explicitly accepted
|
||||
- [ ] approved for refactor consideration or next slice
|
||||
|
||||
### Refactor Gate
|
||||
|
||||
- [ ] diagnosis completed if structural changes were needed
|
||||
- [ ] execution completed if approved
|
||||
- [ ] verification rerun after refactor
|
||||
- [ ] slice complete
|
||||
|
||||
## Open Questions / Blockers
|
||||
|
||||
- `<question or blocker>`
|
||||
|
||||
## Context Handoff Notes
|
||||
|
||||
- Read first: `<artifact paths>`
|
||||
- Current focus: `<next slice or current gate>`
|
||||
- Do not change: `<frozen decisions or constraints>`
|
||||
@@ -0,0 +1,50 @@
|
||||
# Directory Layout
|
||||
|
||||
This page describes the **target shape** of the repository after the bounded-context shift.
|
||||
The current codebase may still contain older top-level layer folders while the transition is in progress.
|
||||
|
||||
## Preferred top-level structure
|
||||
|
||||
```text
|
||||
src/
|
||||
├── shared/ # tiny ubiquitous primitives only
|
||||
├── workflows/ # top-level cross-context orchestration only
|
||||
├── tasks/ # optional cross-context steps, only if needed
|
||||
└── contexts/ # first-class bounded contexts
|
||||
```
|
||||
|
||||
## Inside a bounded context
|
||||
|
||||
A context is organized around its own language and review seams, not around a mandatory global layer checklist.
|
||||
A context may contain only the folders it actually needs.
|
||||
|
||||
```text
|
||||
src/contexts/
|
||||
└── billing/
|
||||
├── index.ts # public context API / intent entrypoints
|
||||
├── models/ # local rich domain models
|
||||
├── policies/ # local pure decisions
|
||||
├── interfaces/ # internal capability seams for effectful or replaceable collaborators
|
||||
├── workflows/ # local workflow or task logic if helpful
|
||||
├── translators/ # boundary translation to and from other contexts
|
||||
├── adapters/ # concrete implementations owned by this context
|
||||
├── registries/ # optional runtime strategy mapping
|
||||
└── lib/ # local support code with no broader meaning
|
||||
```
|
||||
|
||||
## Layout rules
|
||||
|
||||
- Organize primarily by **bounded context**, not by one global layer tree.
|
||||
- Keep top-level `workflows/` for business processes that coordinate multiple contexts.
|
||||
- Do not let one context reach into another context's internals.
|
||||
- Cross-context access should go through the target context's **public API** and be coordinated by a top-level workflow.
|
||||
- Keep `shared/` tiny. It is for truly ubiquitous primitives and low-meaning technical building blocks, not rich domain models.
|
||||
- Translate data at context boundaries instead of sharing one rich type everywhere.
|
||||
- Start with folders in one package. Split into packages only when the boundary has proven stable enough to justify the extra rigidity.
|
||||
|
||||
## During migration
|
||||
|
||||
Older docs and code may still mention top-level folders like `src/domain/`, `src/policies/`, `src/adapters/`, or `src/registries/`.
|
||||
Treat those as a legacy layout being phased out, not as the preferred structure for new work.
|
||||
|
||||
For the architectural rationale behind this direction, read [../explanation/architecture/bounded-contexts.md](../explanation/architecture/bounded-contexts.md).
|
||||
@@ -0,0 +1,101 @@
|
||||
# Naming Lexicon
|
||||
|
||||
Use this page as a vocabulary prompt when refining domain names.
|
||||
It is not a source of mandatory terms.
|
||||
Its purpose is to help you replace generic programmer language with more precise domain language.
|
||||
|
||||
## Lifecycle and state
|
||||
|
||||
| Concept | Useful terms | Examples |
|
||||
| :--- | :--- | :--- |
|
||||
| Beginning | `Initiate`, `Register`, `Onboard`, `Provision`, `Draft` | `InitiateTransfer`, `ProvisionServer` |
|
||||
| Middle, active | `Active`, `Pending`, `InFlight`, `Outstanding`, `Live`, `Provisional`, `Tentative` | `OutstandingInvoice`, `ProvisionalBooking` |
|
||||
| Middle, paused | `Suspended`, `Dormant`, `Held`, `Frozen` | `AccountFrozen`, `DormantUser` |
|
||||
| Ending, good | `Complete`, `Fulfill`, `Settle`, `Finalize`, `Resolve` | `SettlePayment`, `FulfillOrder` |
|
||||
| Ending, bad | `Fail`, `Reject`, `Decline`, `Abort`, `Revoke`, `Void`, `Expire` | `VoidTransaction`, `JobFailed` |
|
||||
| Ending, neutral | `Archive`, `Retire`, `Conclude`, `Terminate` | `RetireProduct`, `TerminateSession` |
|
||||
|
||||
## Corrections and changes
|
||||
|
||||
| Concept | Useful terms | Examples |
|
||||
| :--- | :--- | :--- |
|
||||
| Making correct | `Rectify`, `Reconcile`, `Adjust`, `Correct`, `Align` | `ReconcileInventory`, `RectifyBalance` |
|
||||
| Difference | `Variance`, `Discrepancy`, `Delta`, `Offset`, `Deviance` | `InventoryVariance`, `PriceDelta` |
|
||||
| Defect | `Anomaly`, `Irregularity`, `Outlier`, `Malformation` | `DetectAnomaly`, `SignalIrregularity` |
|
||||
|
||||
## Data and collections
|
||||
|
||||
| Concept | Useful terms | Examples |
|
||||
| :--- | :--- | :--- |
|
||||
| Subset | `Cohort`, `Segment`, `Batch`, `Cluster` | `UserCohort`, `ProcessBatch` |
|
||||
| Summary | `Digest`, `Manifest`, `Summary`, `Snapshot` | `ShippingManifest`, `DailyDigest` |
|
||||
| Searching | `Locate`, `Query`, `Scan`, `Inspect`, `Retrieve`, `Fetch`, `Filter`, `Sift` | `LocateParcel`, `RetrieveRecords` |
|
||||
| Assigning | `Allocate`, `Assign`, `Designate`, `Map` | `AllocateResources`, `DesignateOwner` |
|
||||
| Communication | `Notify`, `Alert`, `Dispatch`, `Broadcast`, `Deliver` | `DispatchEmail`, `BroadcastEvent` |
|
||||
|
||||
## Verification and security
|
||||
|
||||
| Concept | Useful terms | Examples |
|
||||
| :--- | :--- | :--- |
|
||||
| Checking | `Validate`, `Verify`, `Authenticate`, `Authorize`, `Audit` | `AuthorizePayment`, `AuditLog` |
|
||||
| Allowing | `Grant`, `Permit`, `Enable`, `Whitelist` | `GrantPermission`, `WhitelistIP` |
|
||||
| Blocking | `Deny`, `Restrict`, `Revoke`, `Ban`, `Blacklist` | `DenyEntry`, `RevokeCertificate` |
|
||||
| Subjects | `Actor`, `Principal`, `Subject`, `Resource` | `RequestActor`, `TargetResource` |
|
||||
|
||||
## Time and scheduling
|
||||
|
||||
| Concept | Useful terms | Examples |
|
||||
| :--- | :--- | :--- |
|
||||
| Delaying | `Defer`, `Postpone`, `Reschedule`, `Queue` | `DeferExecution`, `PostponeMeeting` |
|
||||
| Recurring | `Interval`, `Cadence`, `Frequency`, `Period` | `BillingCadence`, `RefreshInterval` |
|
||||
| Deadlines | `Deadline`, `Cutoff`, `Expiry`, `Threshold` | `SubmissionCutoff`, `ExpiryDate` |
|
||||
|
||||
## Financial and transactional
|
||||
|
||||
| Concept | Useful terms | Examples |
|
||||
| :--- | :--- | :--- |
|
||||
| Moving money | `Transfer`, `Remit`, `Disburse`, `Deposit`, `Withdraw` | `DisburseFunds`, `RemitTax` |
|
||||
| Allocating | `Earmark`, `Reserve`, `Allocate`, `Encumber` | `EarmarkFunds`, `EncumberBudget` |
|
||||
| Undoing | `Revert`, `Rollback`, `Compensate`, `Refund` | `CompensateTransaction` |
|
||||
|
||||
## Boundary, intent, and capability prompts
|
||||
|
||||
| Concept | Useful terms | Examples |
|
||||
| :--- | :--- | :--- |
|
||||
| Caller intent | `GetNextTask`, `CompleteTask`, `PlanProgress`, `AdvanceProgress`, `AssignWork` | `getNextTask`, `completeTask`, `advanceStudentProgress` |
|
||||
| Capability and authority | `Read`, `Write`, `Plan`, `Authorize`, `Approve`, `Administer` | `ReadCurriculum`, `WriteCurriculum`, `ApproveEnrollment` |
|
||||
| Boundary meaning | `Projection`, `Snapshot`, `Decision`, `Eligibility`, `Assignment`, `Progress` | `CurriculumSnapshot`, `EnrollmentDecision`, `TaskAssignment` |
|
||||
| Implementation-shaped names to question | `LessonRecord`, `Manager`, `Handler`, `Processor`, `Data`, `Info` | `LessonManager`, `StudentInfo`, `TaskProcessor` |
|
||||
|
||||
## Compare alternatives before settling on a name
|
||||
|
||||
| Naming pressure test | Alternative 1 | Alternative 2 | Alternative 3 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| Progression unit | `nextLesson` | `nextAssignableUnit` | `getNextTask` |
|
||||
| Completion action | `markLessonComplete` | `closeProgressUnit` | `completeTask` |
|
||||
| Sequencing module | `lessonSequencing` | `progressUnitPlanner` | `advanceStudentProgress` |
|
||||
|
||||
Use these comparisons to expose hidden assumptions:
|
||||
|
||||
- does the name lock the model to one current concept?
|
||||
- does it express caller intent or internal structure?
|
||||
- is it naming a capability boundary or only an implementation detail?
|
||||
|
||||
## Bounded seam prompts
|
||||
|
||||
| Seam concern | Useful terms | Examples |
|
||||
| :--- | :--- | :--- |
|
||||
| Reviewable contract | `Decision`, `Command`, `Event`, `Assignment`, `Plan`, `Result` | `PlacementDecision`, `AssignTask`, `TaskPlanned` |
|
||||
| Protected invariant | `Eligible`, `Authorized`, `Assignable`, `Settled`, `Balanced` | `EligibleStudent`, `AssignableTask` |
|
||||
| Black-box boundary | `Service`, `Workflow`, `Policy`, `Gateway`, `Repository` | `StudentProgressWorkflow`, `AuthorizationPolicy` |
|
||||
|
||||
At a bounded seam, prefer names that tell the reviewer:
|
||||
|
||||
- what the caller is trying to achieve
|
||||
- what authority is being exercised
|
||||
- what invariant or decision the boundary protects
|
||||
|
||||
## Reminder
|
||||
|
||||
Prefer domain language from the real problem space over any generic lexicon.
|
||||
This page is a prompt, not a substitute for talking to a domain expert.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Project Structure Overview
|
||||
|
||||
This template now treats **bounded contexts as the primary organizing boundary**.
|
||||
Pure vs impure separation still matters, but it now lives mostly **inside each context** instead of as one global folder tree.
|
||||
|
||||
## Key documentation
|
||||
|
||||
- [Directory Layout](directory-layout.md): The preferred context-first folder map.
|
||||
- [Bounded Context Architecture Statement](../explanation/architecture/bounded-contexts.md): The governing architecture direction.
|
||||
- [Architecture Reasoning](../explanation/architecture/index.md): The deeper rationale behind context boundaries, workflow seams, and purity decisions.
|
||||
- [Architecture Rationale Summary](../explanation/architecture/rationale-summary.md): A short refresher for reviews and interviews.
|
||||
- [Conventions](conventions.md): Naming, file organization, and documentation conventions.
|
||||
- [Review Checklist for TDFDDD Artifacts](review-checklist.md): The quickest way to inspect a generated design artifact.
|
||||
|
||||
## Short version
|
||||
|
||||
- `src/contexts/` holds first-class bounded contexts.
|
||||
- `src/workflows/` holds top-level cross-context orchestration.
|
||||
- `src/shared/` stays tiny.
|
||||
- Cross-context calls go through public APIs, not internal file imports.
|
||||
- Rich domain types stay local to their context unless a primitive is truly ubiquitous.
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# Refactor Checklist
|
||||
|
||||
Use this checklist when reviewing or planning a refactor.
|
||||
|
||||
## Scope
|
||||
|
||||
- Is the refactor scope explicit?
|
||||
- Is preserved behavior stated?
|
||||
- Are non-goals stated?
|
||||
- Is the success boundary clear?
|
||||
|
||||
## Change pressure
|
||||
|
||||
- What is currently changing together?
|
||||
- What should be able to change independently?
|
||||
- Is there evidence of tangling, pass-through plumbing, or repeated branching?
|
||||
- Is the top-level workflow carrying too much coordination detail?
|
||||
|
||||
## Seam quality
|
||||
|
||||
- Is the seam named by intent rather than mechanism?
|
||||
- Does the contract hide mechanics?
|
||||
- Does the caller need less context after the refactor?
|
||||
- Does the seam require narrower authority than before?
|
||||
- Would at least three likely variations still fit the boundary naturally?
|
||||
|
||||
## Correct shape
|
||||
|
||||
- Is pure decision logic in a policy?
|
||||
- Is deterministic state transition logic in a model operation?
|
||||
- Are services limited to capabilities and integration?
|
||||
- Are tasks used for meaningful orchestration steps rather than thin wrappers?
|
||||
- Is a module justified by a real bounded capability?
|
||||
|
||||
## Safety
|
||||
|
||||
- Are there tests or type constraints protecting the public seam?
|
||||
- Is behavior clarified before structure is moved?
|
||||
- Are changes being made in small reviewable steps?
|
||||
|
||||
## Outcome
|
||||
|
||||
- Is preserved behavior still intact?
|
||||
- Is the code easier to explain?
|
||||
- Is review load lower?
|
||||
- Is the new boundary more stable under likely future changes?
|
||||
@@ -0,0 +1,73 @@
|
||||
# Review Checklist for TDFDDD Artifacts
|
||||
|
||||
Use this checklist when reviewing a design produced by a human or an LLM.
|
||||
|
||||
## Feature story and scope
|
||||
|
||||
- Does `design/feature/<feature-slug>/discovery.md` describe a real business action without implementation detail?
|
||||
- Is the user intent clear?
|
||||
- Are candidate bounded contexts and candidate workflows visible?
|
||||
- Are the feature-level outcomes both visible?
|
||||
|
||||
## Decomposition
|
||||
|
||||
- Does `design/feature/<feature-slug>/design.md` map feature steps to workflow slices?
|
||||
- Is each workflow slice owned by one bounded context?
|
||||
- Are cross-context handoffs explicit?
|
||||
- Is the recommended slice order coherent?
|
||||
|
||||
## Slice discovery and core sketch
|
||||
|
||||
- Does `02-discovery.md` capture the happy path, edge cases, and invariants for the slice?
|
||||
- Does `03-core-sketch.md` make the decision boundary obvious?
|
||||
- Is the required owned state explicit?
|
||||
- Are vague placeholders eliminated before the design is frozen?
|
||||
|
||||
## F# blueprint
|
||||
|
||||
- Does `04-blueprint.fs` model important lifecycle states explicitly?
|
||||
- Are illegal combinations harder to express?
|
||||
- Are key primitives wrapped in domain concepts where it matters?
|
||||
- Is the naming precise and domain-oriented?
|
||||
- Is business meaning encoded in the model instead of hidden in generic flags?
|
||||
|
||||
## Contract separation
|
||||
|
||||
- Is the policy pure?
|
||||
- Is the model responsible only for state transition math?
|
||||
- Is the workflow responsible only for orchestration and I/O?
|
||||
- Are infrastructure concerns kept out of the design artifact?
|
||||
- Do cross-module imports go through module public APIs instead of reaching into internal files?
|
||||
|
||||
## Review focus
|
||||
|
||||
- Are the contracts, domain types, policies, workflows, and adapter seams explicit enough to review with high confidence?
|
||||
- Does the architecture keep business meaning concentrated in policies and workflows instead of buried in service internals?
|
||||
- Can service and adapter internals be trusted mostly through seam tests and type constraints rather than line-by-line domain review?
|
||||
- Do service implementations avoid accumulating hidden business logic?
|
||||
|
||||
## Security review readiness
|
||||
|
||||
- Are trust boundaries visible enough for a reviewer to identify where untrusted data enters?
|
||||
- Are parsing boundaries explicit enough to tell where raw input becomes trusted domain types?
|
||||
- Are likely dangerous sinks or sink categories named, even if implementation details come later?
|
||||
- Are capability boundaries explicit enough to spot over-broad authority before assembly?
|
||||
- Are secrets, sensitive config, and external trust assumptions called out where relevant?
|
||||
- Are blast-radius, detection, recovery, and security-testing expectations visible enough to review?
|
||||
|
||||
## Readiness
|
||||
|
||||
- Could an engineer implement this without inventing missing domain meaning?
|
||||
- Could a reviewer explain what is being verified at each phase?
|
||||
- Does the final artifact feel discovered rather than improvised?
|
||||
- When tradeoffs appear, does the result prefer correctness, simplicity, and elegance over backwards compatibility unless compatibility is explicitly required?
|
||||
- For refactors, is backwards compatibility preserved only when there is an explicit reason to keep it, rather than by default?
|
||||
|
||||
## Reference docs
|
||||
|
||||
Compare against:
|
||||
|
||||
- `../tutorials/worked-example-truck-loading.md`
|
||||
- `../reference/design-artifact-template.md`
|
||||
- `../explanation/naming-for-domain-modeling.md`
|
||||
- `../explanation/why-events-not-booleans.md`
|
||||
@@ -0,0 +1,67 @@
|
||||
# Rule Examples
|
||||
|
||||
## Core Rules
|
||||
```markdown
|
||||
- [Primary-No-this] never use `this` keyword
|
||||
```
|
||||
|
||||
## level-1
|
||||
```markdown
|
||||
- [Primary-No-This] Never use `this` keyword
|
||||
❌ `onClick={() => this.handleClick()}`
|
||||
✅ `onClick={() => handleClick()}`
|
||||
```
|
||||
|
||||
## level-2
|
||||
~~~markdown
|
||||
Interfaces use `Context.Tag` to declare dependencies, and layers provide adapter implementations.
|
||||
Keep decisions as pure functions even when they stay local to a module.
|
||||
Do not promote every small decision to `src/policies/`; only extract when it materially improves nameability, testability, reuse, or boundary clarity.
|
||||
|
||||
**❌ WRONG - Do NOT use classes with `this`:**
|
||||
```typescript
|
||||
// DON'T DO THIS - uses 'this' and class-based approach
|
||||
export class UserService extends Effect.Service<UserService>()("UserService", {
|
||||
effect: Effect.gen(function*() {
|
||||
const db = yield* Database
|
||||
|
||||
return {
|
||||
getUser: (id: UserId) => this.db.query(...) // ❌ Uses 'this'
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**✅ CORRECT - Use Context.Tag and plain objects:**
|
||||
```typescript
|
||||
// Define the service interface
|
||||
export interface FileSystemStorageService {
|
||||
readonly readFile: (path: string) => Effect.Effect<string, GitPersistenceError>
|
||||
readonly writeFile: (path: string, content: string) => Effect.Effect<void, GitPersistenceError>
|
||||
readonly listFiles: (path: string) => Effect.Effect<string[], GitPersistenceError>
|
||||
readonly commit: (message: string) => Effect.Effect<void, GitPersistenceError>
|
||||
}
|
||||
|
||||
// Create the service tag
|
||||
export class FileSystemStorageService extends Context.Tag("FileSystemStorageService")<
|
||||
FileSystemStorageService,
|
||||
FileSystemStorageService
|
||||
>() {
|
||||
static of(impl: FileSystemStorageService): FileSystemStorageService {
|
||||
return impl
|
||||
}
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
## checklist
|
||||
```markdown
|
||||
|
||||
- 1. [ ] [Primary-No-This] Never use `this` keyword
|
||||
❌ `onClick={() => this.handleClick()}`
|
||||
✅ `onClick={() => handleClick()}`
|
||||
...
|
||||
- 20. [ ] [Composition-Over-Inheritance] Always use composition, never inheritance
|
||||
❌ `interface Node() {}; class ContentNode extends Node {};`
|
||||
✅ ``
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
# Shared Language
|
||||
|
||||
Use this page to keep the repository's ubiquitous language stable.
|
||||
It is the project-wide glossary for terms that should mean one thing everywhere in design artifacts, code, tests, and reviews.
|
||||
|
||||
## Why this exists
|
||||
|
||||
Naming inconsistency creates design inconsistency.
|
||||
When the same concept is called three different things, reviewers and LLMs start inventing distinctions that are not real.
|
||||
A stable shared language improves design quality, review quality, and implementation consistency.
|
||||
|
||||
This file is for **project-wide terms**.
|
||||
Feature-specific naming choices should also be recorded in the relevant design artifact.
|
||||
|
||||
## How to use it
|
||||
|
||||
- Add terms that appear across multiple features or modules.
|
||||
- Prefer short domain definitions over implementation detail.
|
||||
- Record preferred terms and rejected synonyms.
|
||||
- Update this file when the team decides one name should win.
|
||||
- Keep the grammar consistent with the naming rules in `../explanation/naming-for-domain-modeling.md`.
|
||||
|
||||
## Core grammar
|
||||
|
||||
- **Commands**: imperative intents such as `LoadPackage`
|
||||
- **Events**: past-tense facts such as `PackageLoaded`
|
||||
- **States / Objects**: domain nouns such as `LoadingTruck`
|
||||
- **Workflows**: verb-noun names such as `loadPackage`
|
||||
- **Policies**: decision-oriented names such as `decideLoadEligibility`
|
||||
|
||||
## Project-wide glossary template
|
||||
|
||||
| Term | Meaning | Use this, not that | Notes |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `<PreferredTerm>` | `<Short domain meaning>` | `<PreferredTerm>` not `<RejectedSynonym>` | `<Optional note>` |
|
||||
| `<PreferredTerm>` | `<Short domain meaning>` | `<PreferredTerm>` not `<RejectedSynonym>` | `<Optional note>` |
|
||||
|
||||
## Review questions
|
||||
|
||||
- Would a domain expert recognize these terms?
|
||||
- Are the same concepts named consistently across story, events, model, code, and tests?
|
||||
- Are we accidentally using programmer words where domain words should exist?
|
||||
- Have we documented which synonym is preferred when multiple names are plausible?
|
||||
Reference in New Issue
Block a user