Architecture
One rule above all: the kernel stays small. Complexity lives in services around it — never inside it.
The map#
KHAELOR TUI ──── khaelord (daemon)
│ │
▼ ▼
Session Engine (JSONL event log)
│
▼
Agent Kernel ← deriveNext(state) — a pure fold
┌───────────────┼───────────────────┐
▼ ▼ ▼
Context Engine Tool Runtime Model Runtime
(tiers, cache, (permissions, (Anthropic SDK,
compaction) phase gate, streaming)
│ verify loop)
▼ ▼
RepoGraph Workspace ── the ONLY fs/process seam
Memory │
Phases Files · Processes · Git worktrees
The kernel is a fold#
Each iteration, the kernel re-derives “what next” from the recorded event log — not from
loop-local flags. foldTurnState(events) → deriveNext(state) → dispatch to
a service. Interruption, steering injection, compaction, verification, completion: all are
positions in the log, which is why resume, fork, and replay are cheap and exact.
Services around the kernel#
| Service | Owns |
|---|---|
| PhaseService | The gate: per-phase capability policy, design approval, phase events. Consulted by the Tool Runtime — the kernel never sees it. |
| VerifyRunner | Native checks after edit batches, the bounded repair loop. |
| PermissionService | Capability evaluation (deny > ask > allow), grants, the panel seam. |
| ContextEngine | Tiers, byte-stable history projection, prune/compact decisions. |
| RepoGraphService | The incremental semantic index behind symbols/refs/skeletons. |
| SubtaskManager | Worktree lifecycle, child engines, supervised merges. |
| GoalStore / BudgetGuard / ApprovalQueue | The daemon's persistence: goals, ledgers, pending approvals — plain files under .khaelor/daemon/. |
The seams that matter#
- Workspace — four methods (
cwd,readFile,writeFile,exec); the only module allowed to importnode:fs/child_process. Everything above it is testable and portable. - ModelClient — one streaming interface over the Anthropic SDK. Not a multi-provider framework; just a clean wall.
- ChannelAdapter — daemon notifications (webhook, command today; richer channels later without touching the core).
House rules#
- Every displayed number comes from real data — usage metadata, exit codes, git diffs. No fabricated progress, ever.
- Baseline git state is recorded before edits; KHAELOR never assumes an existing diff is its own, and never commits unless asked.
- Whenever something is tempted into the kernel, the question is asked: can this be a service around it? The answer so far has always been yes.