Files
obsidian-vault/wiki/personal-os-architecture.md
T

9.6 KiB
Raw Blame History

namespace, tags, last_updated, confidence
namespace tags last_updated confidence
work
system
architecture
2026-05-15 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: morning-brief (08:30 MTWRF), eod-summary (18:00 MTWRF), inbox-check (30 min 0919 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 (0918 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.

⚠️ 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/