feat: FastAPI Morrowind harness + SOUL.md framework (#821, #854)

## FastAPI Morrowind Harness (#821)
- GET /api/v1/morrowind/perception — reads perception.json, validates
  against PerceptionOutput schema
- POST /api/v1/morrowind/command — validates CommandInput, logs via
  CommandLogger, stubs bridge forwarding
- GET /api/v1/morrowind/status — connection state, last perception,
  queue depth, agent vitals
- Router registered in dashboard app alongside existing routers
- 12 tests with FastAPI TestClient

## SOUL.md Framework (#854)
- docs/soul-framework/ — template, authoring guide, role extensions
- src/infrastructure/soul/loader.py — parse SOUL.md into structured
  SoulDocument objects with section extraction and merge support
- src/infrastructure/soul/validator.py — validate structure, detect
  contradictions between values/constraints
- src/infrastructure/soul/versioning.py — hash-based version tracking
  with JSON persistence
- 27 tests covering loader, validator, versioning, and Timmy's soul

Builds on PR #864 (protocol spec + command log).
Closes #821
Closes #854
This commit is contained in:
2026-03-21 22:43:21 +00:00
parent 215329146a
commit a83ea9bdb6
12 changed files with 1752 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
# SOUL.md Authoring Guide
How to write a SOUL.md for a new agent.
---
## Before You Start
1. **Read the template** (`template.md`) to understand the required sections.
2. **Study Timmy's soul** (`memory/self/soul.md`) as a reference implementation.
3. **Decide on the agent's role** — is this a general-purpose agent or a
specialised sub-agent (see `role-extensions.md`)?
---
## Step-by-Step
### Step 1: Define Identity
Start with the shortest possible answer to "who is this agent?"
- Avoid jargon. The identity should be understandable to someone who has
never seen the codebase.
- Include the agent's relationship to sovereignty and autonomy.
- Keep it to three sentences or fewer.
### Step 2: List Values
Values are the non-negotiable principles. They are not personality traits —
they are commitments.
Guidelines:
- **37 values** is the sweet spot. Fewer than 3 is under-specified; more
than 7 is hard to remember under pressure.
- **Order matters.** When two values conflict, the one listed first wins.
- **Name each value.** A single bolded word followed by a definition.
- **Be concrete.** "Honesty" is better than "integrity". "I tell the truth
when I don't know" is better than "I am honest."
### Step 3: Write the Prime Directive
This is the single most important instruction. If context is lost and the
agent can only remember one thing, this is it.
Rules:
- Exactly one sentence.
- No conditional clauses ("if X then Y").
- Must be actionable, not aspirational.
### Step 4: Define Audience Awareness
Different audiences need different behaviour. A developer debugging a crash
needs terse technical output. A first-time user needs patience and context.
- List 24 audience profiles.
- For each, describe what changes: tone, verbosity, assumed knowledge.
### Step 5: Set Constraints
Constraints are hard limits. They cannot be overridden by user instructions.
Guidelines:
- Use "I will not" phrasing.
- Include a fallback rule: what the agent does when it encounters an
ambiguous situation not covered by other constraints.
- Keep the list short (36 items). Too many constraints create paralysis.
---
## Common Mistakes
| Mistake | Fix |
|---------|-----|
| Values that are just personality traits | Rewrite as commitments with concrete implications |
| Prime directive with multiple clauses | Split into prime directive + constraints |
| No fallback constraint | Add "When uncertain, I will [action]" |
| Contradictory values | Reorder by priority or remove the weaker one |
| Too long (>100 lines) | Brevity is a virtue — trim aggressively |
---
## Validation
After writing, run the validator:
```python
from infrastructure.soul.loader import SoulLoader
from infrastructure.soul.validator import SoulValidator
soul = SoulLoader.from_file("path/to/SOUL.md")
issues = SoulValidator.validate(soul)
for issue in issues:
print(f"[{issue.severity}] {issue.section}: {issue.message}")
```
Fix all `error`-level issues before committing. `warning`-level issues
are advisory.