186 lines
10 KiB
Markdown
186 lines
10 KiB
Markdown
---
|
||
namespace: work
|
||
tags: [system, architecture]
|
||
last_updated: 2026-05-18
|
||
confidence: 1.0
|
||
---
|
||
|
||
# Personal OS — Architecture
|
||
|
||
## Why It Exists
|
||
|
||
See: [[personal-os-purpose]] and [[personal-os-agent-rules]] for goals and behavioral constraints.
|
||
|
||
## 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: 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), commit-vault (23:00 daily), wiki-curation (02: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
|
||
- **Zulip plugin**: `~/.hermes/plugins/zulip-topic-routing/` — intercepts `(no topic)` messages; routes to most recent related thread or renames to descriptive topic. Status: ✅ done (2026-05-14)
|
||
|
||
> ⚠️ **Mattermost migration in-progress (2026-05-14):** Work Eagle agent (briefs, inbox, executor) moving from Zulip → corporate Mattermost. Personal/family/journal remain on Zulip/Discord. Blocked on IT Ops creating MM bot accounts (eagle-bot, executor-bot, brief-bot). See `work/plans/mattermost-migration.md`.
|
||
|
||
### Ретроспектор (Retrospector) — Friday pattern analysis
|
||
- 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
|
||
> ⚠️ Stale as of 2026-05-11: Original LLM-orchestrated autonomous cron **paused**. Replaced by v2 bash daemons:
|
||
|
||
**Autonomous mode (v2 — bash daemons, active 2026-05-11+):**
|
||
- `executor-runner.sh` — cron `*/5`; processes queued/in_progress/pr states; max 2 concurrent workers; spawns focused worker prompt per state; exits when no actionable tasks remain
|
||
- `executor-analyzer.sh` — cron `*/5`; picks one unanalyzed task, runs `claude -p` analysis prompt, sets `for_review`/`awaiting_go`/`skip`, exits; restarts for next task
|
||
- Worker prompts in `~/Developer/personal-os/agent/prompts/executor-worker-*.md`
|
||
- Queue state in `executor_queue` table; live plan: `~/Developer/personal-os/briefs/executor-queue.md`
|
||
|
||
**Orchestrator Pattern (Planning — 2026-05-14):**
|
||
> Research phase complete. Executor will become a separate Hermes profile with its own Zulip bot identity ("Исполнитель"), spawned by Eagle as orchestrator. Eagle monitors `#executor` via 2-min cron, auto-approves safe actions (`[REQUEST:create_worktree]`, `[REQUEST:run_tests]`, etc.), escalates ambiguous/risky ones to Alex. See `personal/projects/personal-os/executor-spawning-research.md` for full protocol and auto-approval rules.
|
||
>
|
||
> Key mechanism: **Hermes Profiles** — `~/.hermes/profiles/executor/` with its own SOUL.md, Zulip bot token, and gateway. `hermes profile create executor --clone`.
|
||
|
||
**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
|
||
|
||
**Eagle (Mac M4) — Hermes agent:**
|
||
| Name | Command | Used for |
|
||
|------|---------|---------||
|
||
| obsidian | `node ~/scripts/obsidian-mcp-wrapper.js` (wraps `/opt/homebrew/bin/obsidian-mcp`) | Vault search, read, write. Wrapper handles ZodError/race condition — see [[obsidian-mcp-wrapper]] |
|
||
|
||
**Taiga (TrueNAS) — Hermes agent (`hermes-taiga` container):**
|
||
| Name | Command | Used for |
|
||
|------|---------|---------||
|
||
| obsidian | `/opt/data/.local/bin/mcpvault /vault` | Vault access (sparse: personal/ + family/). Tavily search enabled. |
|
||
|
||
**Kraken (RPi5) — Hermes agent (`hermes-kraken` container):**
|
||
|| Name | Command | Used for |
|
||
||------|---------|---------||
|
||
|| obsidian | `/opt/data/.local/bin/mcpvault /vault` | Vault access (sparse: personal/ + family/). Tavily search enabled. |
|
||
|
||
Skills on Kraken: `~/.hermes/skills/` (host) — **not** visible to the container at `/opt/data/skills/`. Copy skills there if needed.
|
||
Media stack on Kraken: full *arr stack (Prowlarr/Radarr/Sonarr) + Transmission + Jellyfin + media-pipeline. See [[concepts/kraken-media-stack]].
|
||
|
||
> ⚠️ **Kraken image routing (open issue, 2026-05-14):** Gemini API credits depleted → fallback to OpenRouter models (gpt-oss-120b, minimax-m2) → these lack vision → image inbox messages fail. Desired fix: add `save_to_fs` mode to Hermes `image_routing` (save image locally, pass path to agent instead of bytes). Workaround: top up Gemini API credits on Kraken. Tracked in `personal/projects/personal-os/kraken-obsidian-write-bug.md`.
|
||
|
||
> All three nodes run Hermes with obsidian/mcpvault MCP. Eagle uses obsidian-mcp-wrapper.js (fixes ZodError+race); Taiga and Kraken use mcpvault directly.
|
||
|
||
**Claude Code / `claude -p` sessions (Eagle only):**
|
||
| Name | Command | Used for |
|
||
|------|---------|---------||
|
||
| ddg-vm | `npx tsx ~/Developer/virfield/server/mcp-server.ts` | VM lifecycle for UI tests |
|
||
| obsidian | `node ~/scripts/obsidian-mcp-wrapper.js` | 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/
|
||
```
|