5.0 KiB
name, description, depth, links
| name | description | depth | links | |||
|---|---|---|---|---|---|---|
| Modules And Spec | Guide to module organisation and documentation standards | 2 |
|
yes. and good catch — consistency matters here because the structure itself becomes architecture documentation.
i’d standardize on nested gradle modules only:
:apps
:apps:cli
:apps:server
:core
:core:events
:core:context
:core:validation
:core:transitions
:core:orchestration
:core:artifacts
:core:sessions
:core:approvals
:core:policies
:core:tools
:core:inference
:infrastructure
:infrastructure:persistence
:infrastructure:providers
:infrastructure:tools
:interfaces
:interfaces:api
:interfaces:cli
i would add:
:core:orchestration:core:artifacts:core:sessions
immediately.
because those are foundational. without them, responsibilities leak everywhere.
and yes — writing specs/design docs module-by-module is the correct approach.
BUT: you need two document types per module:
- contract/spec defines:
- responsibilities
- invariants
- boundaries
- public interfaces
- forbidden dependencies
- event ownership
- lifecycle guarantees
- implementation/design defines:
- concrete architecture
- classes
- flow
- persistence
- threading
- algorithms
- data structures
this separation matters a lot.
recommended documentation structure
docs/
├── architecture/
│ ├── system-overview.md
│ ├── event-model.md
│ ├── replay-model.md
│ ├── context-layers.md
│ └── security-boundaries.md
│
├── modules/
│ ├── core-events/
│ │ ├── spec.md
│ │ └── design.md
│ │
│ ├── core-context/
│ │ ├── spec.md
│ │ └── design.md
│ │
│ ├── core-validation/
│ │ ├── spec.md
│ │ └── design.md
│ │
│ └── ...
│
└── decisions/
├── adr-0001-event-sourcing.md
├── adr-0002-kotlin-choice.md
└── ...
VERY important: use ADRs from the beginning.
Architecture Decision Records
because you WILL forget later:
- why replay works this way
- why approvals are append-only
- why projections are disposable
- why router is isolated
future-you will otherwise rewrite old mistakes.
recommended order for specs
this order minimizes architectural drift:
:core:events
first because: everything depends on event semantics.
must define:
- event contracts
- causation/correlation ids
- append guarantees
- replay guarantees
- snapshotting
- versioning
:core:sessions
defines:
- lifecycle FSM
- ownership boundaries
- session projections
- cancellation semantics
:core:transitions
defines:
- graph execution
- rule evaluation
- deadlock/cycle handling
- retry semantics
:core:artifacts
defines:
- artifact contracts
- lineage
- validation ownership
- immutability guarantees
:core:validation
defines:
- layered validation pipeline
- semantic validators
- policy interaction
- approval interaction
:core:context
probably hardest subsystem after validation.
must define:
- layering
- token budgeting
- compression contracts
- dedup semantics
- rebuild rules
:core:approvals
must be isolated and heavily specified.
:core:orchestration
only AFTER the primitives exist.
because orchestration composes:
- events
- transitions
- approvals
- context
- inference
:core:inference
provider abstraction.
:core:tools
tool contracts + receipts.
infrastructure modules
ONLY after contracts stabilize.
this is important: do NOT start with providers/tools/ui.
that’s how orchestration architectures rot early.
for each module spec, define these sections
mandatory template:
1. purpose
2. responsibilities
3. non-responsibilities
4. invariants
5. public contracts
6. owned events
7. consumed events
8. state model
9. threading/concurrency model
10. failure semantics
11. replay semantics
12. persistence requirements
13. observability requirements
14. security boundaries
15. extension points
16. forbidden dependencies
17. open questions
this will massively reduce ambiguity later.
especially: “non-responsibilities” and “forbidden dependencies”
those prevent architecture erosion.
example:
:core:context
non-responsibilities:
- model execution
- persistence
- tool execution
forbidden dependencies:
- infrastructure modules
- websocket interfaces
- provider implementations
that sounds bureaucratic now. it becomes life-saving later.
one more recommendation: define module dependency rules EARLY.
example:
core modules may depend on:
- contracts
- lower-level core modules
core modules may never depend on:
- infrastructure
- interfaces
- apps
enforce this automatically eventually with:
- archunit
- detekt custom rules
- dependency analysis plugin
because modular architectures silently decay otherwise.