Initial commit

This commit is contained in:
ada
2026-05-25 05:47:28 +00:00
commit 4d6495ffda
97 changed files with 13403 additions and 0 deletions
+64
View File
@@ -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`
+143
View File
@@ -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.
+111
View File
@@ -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.
+117
View File
@@ -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>`
+50
View File
@@ -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).
+101
View File
@@ -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.
+22
View File
@@ -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.
+46
View File
@@ -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?
+73
View File
@@ -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`
+67
View File
@@ -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 {};`
✅ ``
```
+43
View File
@@ -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?