189 lines
8.8 KiB
Markdown
189 lines
8.8 KiB
Markdown
---
|
||
namespace: work
|
||
tags: [system, architecture]
|
||
last_updated: 2026-04-28
|
||
confidence: 1.0
|
||
---
|
||
|
||
# Personal OS — Architecture
|
||
|
||
## Why It Exists
|
||
|
||
See: `personal-os-purpose.md`
|
||
|
||
## Agents
|
||
|
||
### Стратег (Strategist) — data pipeline, no conversation
|
||
- `~/scripts/run-pipeline.sh` → sync.js + generate-status.js every 30 min (workdays via Hermes cron)
|
||
- Writes `~/context/status.md` and `~/Developer/personal-os/asana_context.md`
|
||
- Writes daily AW activity summaries to `activity_daily` table with quadrant classification
|
||
- No Zulip output — pure data layer
|
||
|
||
### Орёл / Eagle (Tactician + reactive layer) — Hermes Zulip agent
|
||
- Reads `~/context/status.md`, daily/weekly briefs, vault via obsidian MCP
|
||
- Zulip streams: `daily-brief` `inbox` `focus` `executor` `projects` `journal` `retrospector`
|
||
- Cron jobs: generate-daily-brief (07:00 MTWRF), morning-brief (08:30 MTWRF), eod-summary (18:00 MTWRF), inbox-check (30 min 09–19 MTWRF), weekly-plan (Mon 08:00), weekly-review (Fri 17:00), retrospector (Fri 17:30), executor-autonomous (every 30 min 09–18 MTWRF), commit-vault (23:00 daily)
|
||
- Logs corrections to `corrections_log` table (SQL INSERT, silently on pushback)
|
||
- **Never accesses Asana API directly** — only reads pre-rendered markdown and DB
|
||
|
||
### Кракен (Kraken) — home NAS agent
|
||
- Hermes на RPi 5, Telegram @kraken_htpc_bot
|
||
- Toolsets: `hermes-cli, terminal, file, web, memory, spotify, homeassistant`
|
||
- Models: `openai/gpt-oss-120b:free` (primary), `minimax/minimax-m2.5:free` (fallback)
|
||
- obsidian-mcp: `npx obsidian-mcp /home/kraken/obsidian` → sparse vault `personal/ + family/`
|
||
- Vault sync: `~/scripts/sync-vault.sh`, cron `0 * * * *`, pulls/pushes via SSH → TrueNAS bare repo
|
||
- Config: `/home/kraken/hermes/`, data on HDD `/srv/dev-disk-by-uuid-49e8f586-.../docker/hermes/`
|
||
|
||
### Тайга (Taiga) — TrueNAS agent
|
||
- Hermes в Docker контейнере `hermes-taiga` на TrueNAS
|
||
- obsidian-mcp: `npx obsidian-mcp /vault` → sparse vault `personal/ + family/`
|
||
- Vault sync: `~/sync-vault.sh` на **хосте** TrueNAS (не в контейнере), cron `0 * * * *`
|
||
- Vault (хост): `/mnt/RED_2TB/docker/hermes/vault`, (контейнер): `/vault:rw`
|
||
|
||
### Vault Sync Pipeline
|
||
```
|
||
Eagle ~/obsidian (full) ──SSH push/pull──┐
|
||
Taiga /vault (sparse) ──file:// ───────├── TrueNAS bare repo
|
||
Kraken ~/obsidian (sparse) ──SSH ────────┘ /mnt/RED_2TB/storage/git/obsidian-vault.git
|
||
```
|
||
- Все 3 узла: stash → fetch → merge → stash pop → commit → push (hourly)
|
||
- Конфликты: сохраняются как markers, не теряются
|
||
- Eagle commit message: генерируется через `claude -p`
|
||
- Подробности: `family/how-to/obsidian-sync.md`
|
||
|
||
|
||
- Runs as separate Hermes cron at 17:30 Friday → `#retrospector`
|
||
- Sources: corrections_log table, status.md subtask counts, obsidian git log, activity_daily quadrants, stories visibility metric
|
||
- Prompt: `~/Developer/personal-os/agent/prompts/retrospector.md`
|
||
|
||
### Исполнитель (Executor) — two modes
|
||
|
||
**Manual mode**: triggered by "fix bug [GID]" in #executor
|
||
- Single STOP gate after analysis; then autonomous: fix → build → test → draft PR → CI loop
|
||
- Prompt: `~/Developer/personal-os/agent/prompts/executor-bug-fix.md`
|
||
|
||
**Autonomous mode**: hourly cron (09–18 workdays) → #executor
|
||
- Maintains a queue from: My Hack Days, Watched, O-L Backlog, stale My Tasks
|
||
- Analyzes tasks → posts "[Auto] Ready to start" with complexity/feasibility
|
||
- Waits for "go {gid}" to start; no reply = moves to next analysis
|
||
- Max 1 active fix at a time; handles CI/review on open draft PRs
|
||
- Stops touching a PR once Alex moves it out of draft or pushes commits
|
||
- No Asana comments; no touching other people's PRs
|
||
- Queue state in `executor_queue` table; live plan: `~/Developer/personal-os/briefs/executor-queue.md`
|
||
- Prompt: `~/Developer/personal-os/agent/prompts/executor-autonomous.md`
|
||
|
||
**Shared**:
|
||
- Worktree at `~/DuckDuckGo/apple-browsers.git/.claude/worktrees/executor-{gid}-{slug}/`
|
||
- Always `git fetch origin main` + branch from `origin/main`
|
||
- State machine in `executor_runs` table
|
||
- For UI tests: spins VM via ddg-vm MCP (virfield), cleans up on PR close/merge
|
||
|
||
**Eagle commands in #executor**:
|
||
| Command | Effect |
|
||
|---------|--------|
|
||
| `fix bug {gid}` | Spawn manual executor (separate agent) |
|
||
| `go {gid}` | Approve autonomous task → starts next tick |
|
||
| `skip {gid}` | Skip task in queue |
|
||
| `stop` | Pause current autonomous task |
|
||
| `next` | Pause current, analyze next |
|
||
| `resume {gid}` | Re-queue paused task |
|
||
| `queue` | Show current executor-queue.md |
|
||
|
||
## Data Flow
|
||
|
||
```
|
||
Asana API
|
||
→ sync.js (30 min, Hermes cron, silent)
|
||
→ PostgreSQL: tasks, stories, task_edges, sync_state, task_annotations
|
||
|
||
ActivityWatch (local daemon)
|
||
→ generate-status.js (reads AW HTTP API)
|
||
→ activity_daily (upserts daily project/quadrant summaries)
|
||
|
||
generate-status.js
|
||
→ ~/context/status.md ← Eagle reads this
|
||
→ ~/Developer/personal-os/asana_context.md ← inbox-check reads this
|
||
|
||
Eagle corrections in Zulip
|
||
→ corrections_log table (INSERT on pushback, no announcement)
|
||
→ Retrospector reads weekly
|
||
|
||
Executor runs
|
||
→ executor_runs table (state machine)
|
||
→ ~/DuckDuckGo/apple-browsers.git/.claude/worktrees/
|
||
→ GitHub draft PRs (--draft, --assignee @me, no reviewers)
|
||
```
|
||
|
||
## Key File Locations
|
||
|
||
| File / Path | Purpose |
|
||
|-------------|---------|
|
||
| `~/context/status.md` | Live Asana + AW snapshot. Written by generate-status.js. Eagle reads this. |
|
||
| `~/Developer/personal-os/asana_context.md` | Raw Asana context for inbox-check |
|
||
| `~/Developer/personal-os/agent/prompts/` | All agent prompts (Hermes cron + on-demand) |
|
||
| `~/.hermes/SOUL.md` | Eagle's identity, rules, vault write permissions |
|
||
| `~/Developer/personal-os/config.json` | Asana workspace/user GIDs, section GIDs |
|
||
| `~/Developer/personal-os/aw-projects.json` | ActivityWatch project classification rules |
|
||
| `~/.hermes/config.yaml` | Hermes config: model, MCP servers, cron settings |
|
||
| `~/obsidian/` | Vault — git repo, NAS remote, obsidian-mcp for search |
|
||
| `~/Developer/personal-os/logs/` | heartbeat.log, wiki-ingest-YYYY-MM-DD.md |
|
||
| `~/Developer/personal-os/briefs/` | daily/, weekly/, inbox/ — agent-written brief files |
|
||
| `~/DuckDuckGo/apple-browsers.git/` | Browser repo (bare), worktrees as sibling dirs |
|
||
| `~/DuckDuckGo/apple-browsers.git/.claude/worktrees/` | Executor worktrees |
|
||
|
||
## Database Tables
|
||
|
||
| Table | Written by | Read by |
|
||
|-------|-----------|---------|
|
||
| tasks | sync.js | generate-status.js, executor, status queries |
|
||
| stories | sync.js | generate-status.js, executor, retrospector |
|
||
| task_edges | sync.js | subtask traversal |
|
||
| sync_state | sync.js | generate-status.js header |
|
||
| task_annotations | manual / Eagle | generate-status.js irrelevant filter |
|
||
| activity_daily | generate-status.js | retrospector quadrant drift |
|
||
| corrections_log | Eagle on pushback | retrospector pattern analysis |
|
||
| executor_runs | executor (manual + autonomous) | generate-status.js active runs, executor state machine |
|
||
| executor_queue | executor-autonomous | generate-status.js queue display, autonomous tick state |
|
||
|
||
## MCP Servers
|
||
|
||
**Hermes agents:**
|
||
| Name | Command | Used for | Node |
|
||
|------|---------|---------|------|
|
||
| obsidian | `/opt/homebrew/bin/obsidian-mcp ~/obsidian` | Vault search, read, write | Eagle |
|
||
| obsidian | `npx obsidian-mcp /home/kraken/obsidian` | Vault search, read, write | Kraken |
|
||
| obsidian | `npx obsidian-mcp /vault` | Vault search, read, write | Taiga |
|
||
|
||
**Claude Code / `claude -p` sessions:**
|
||
| Name | Command | Used for |
|
||
|------|---------|---------|
|
||
| ddg-vm | `npx tsx ~/Developer/virfield/server/mcp-server.ts` | VM lifecycle for UI tests |
|
||
| obsidian | `/opt/homebrew/bin/obsidian-mcp ~/obsidian` | Vault access |
|
||
|
||
## launchd Agents
|
||
|
||
| Label | Schedule | Purpose |
|
||
|-------|----------|---------|
|
||
| personal.os.heartbeat | :05 every hour | Runs run-pipeline.sh directly (no Claude auth needed); also triggers missed Hermes jobs after wake |
|
||
| personal.os.wiki-ingest | 22:00 daily | `claude -p` wiki synthesis (needs filesystem access) |
|
||
|
||
## Vault Structure
|
||
|
||
```
|
||
~/obsidian/
|
||
├── wiki/ ← LLM-generated + hand-written (confidence: 1.0 = never overwrite)
|
||
│ ├── personal-os-architecture.md (this file)
|
||
│ ├── personal-os-purpose.md
|
||
│ ├── personal-os-agent-rules.md
|
||
│ ├── personal-os-self-modification.md
|
||
│ ├── personal-os-sync-pipeline.md
|
||
│ ├── personal-os-schema.md (auto-generated)
|
||
│ ├── ddg-asana-workflow.md
|
||
│ └── vault-filling-guide.md
|
||
├── raw/ ← symlinks to external source files (schema.sql, etc.)
|
||
├── work/
|
||
│ └── wiki/
|
||
│ └── apple-browsers/ ← .cursor/rules copies (.md) + vm-ui-testing.md
|
||
└── personal/ family/
|
||
```
|