122 lines
3.7 KiB
Markdown
122 lines
3.7 KiB
Markdown
# Engineering Principles
|
|
|
|
## Purpose
|
|
|
|
This document defines how the tutor platform should be implemented once coding
|
|
begins. The product is expected to grow across web UI, API backend, workflow
|
|
orchestration, learner memory, ontology processing, and generated learning
|
|
assets. Without explicit constraints, those areas can easily collapse into large
|
|
files and overbuilt abstractions.
|
|
|
|
## Core Rules
|
|
|
|
### 0. Backend language
|
|
|
|
The backend is Go.
|
|
|
|
This decision aligns the service with `agent-farm-go` so workflow orchestration
|
|
can become an internal product capability rather than a loosely attached
|
|
automation script. Keep the Go service modular and avoid turning the backend
|
|
into one large workflow coordinator.
|
|
|
|
### 1. File size limit
|
|
|
|
No source file should exceed 600 lines.
|
|
|
|
When a file approaches the limit, split it by responsibility. Good split points:
|
|
|
|
- route registration vs handler logic
|
|
- handler logic vs service logic
|
|
- service orchestration vs domain rules
|
|
- domain rules vs persistence adapter
|
|
- workflow contract definitions vs workflow execution
|
|
- UI page shell vs reusable components
|
|
|
|
Exemptions:
|
|
|
|
- generated files
|
|
- lockfiles
|
|
- vendored files
|
|
- external source snapshots
|
|
- large fixture data
|
|
|
|
### 2. SOLID
|
|
|
|
Apply SOLID pragmatically:
|
|
|
|
- Single responsibility: learner memory, ontology, grading, progression, and
|
|
asset generation should not live in one service.
|
|
- Open/closed: add new interview tracks or asset types through data/config and
|
|
narrow extension points where practical.
|
|
- Liskov substitution: adapters should honor shared contracts without hidden
|
|
behavior changes.
|
|
- Interface segregation: avoid giant service interfaces.
|
|
- Dependency inversion: domain logic should not depend directly on provider SDKs
|
|
or database details.
|
|
|
|
### 3. KISS
|
|
|
|
Prefer the simplest implementation that proves the current product loop:
|
|
|
|
```text
|
|
question -> answer -> grading -> memory update -> next challenge
|
|
```
|
|
|
|
Do not introduce queues, distributed workers, plugin systems, or complex
|
|
multi-agent orchestration until the MVP loop needs them.
|
|
|
|
### 4. YAGNI
|
|
|
|
Do not build features only because they may be useful later.
|
|
|
|
Examples to defer until proven necessary:
|
|
|
|
- multi-school LMS administration
|
|
- marketplace course publishing
|
|
- company-specific interview packs
|
|
- generalized ontology editor
|
|
- multiple image providers
|
|
- complex economy systems
|
|
- social leaderboards
|
|
|
|
## Product Module Boundaries
|
|
|
|
Initial implementation should keep these responsibilities distinct:
|
|
|
|
- `auth`: users, sessions, identity providers.
|
|
- `interview`: questions, rubrics, answers, grading records.
|
|
- `learner_memory`: profiles, concept mastery, misconceptions, evidence.
|
|
- `ontology`: concepts, prerequisites, source evidence, generated candidates.
|
|
- `progression`: readiness maps, challenge ladders, boss questions, streaks.
|
|
- `workflows`: typed contracts and calls into `agent-farm-go` / `third-one`.
|
|
- `assets`: generated diagrams, lesson slices, prompt lineage, review state.
|
|
|
|
The names can change with the chosen stack, but the responsibilities should stay
|
|
separate.
|
|
|
|
## Workflow Contracts
|
|
|
|
LLM workflow outputs should be typed and inspectable. Avoid relying on freeform
|
|
assistant prose for product state changes.
|
|
|
|
First contracts to define:
|
|
|
|
- `DiagnosticResult`
|
|
- `GradedAnswer`
|
|
- `MemoryUpdateCandidate`
|
|
- `NextChallenge`
|
|
- `ReadinessUpdate`
|
|
- `OntologyGap`
|
|
- `TeachingAssetPrompt`
|
|
|
|
## Review Checklist
|
|
|
|
Before considering an implementation slice complete:
|
|
|
|
- No manually authored source file exceeds 600 lines.
|
|
- New behavior maps to an OpenSpec requirement or updates OpenSpec.
|
|
- The implementation keeps responsibilities separated.
|
|
- The simplest useful design was chosen.
|
|
- No future-only abstraction was added.
|
|
- Tests or smoke checks prove the touched behavior.
|