9.6 KiB
namespace, tags, last_updated, confidence
| namespace | tags | last_updated | confidence | ||
|---|---|---|---|---|---|
| work |
|
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.mdand~/Developer/personal-os/asana_context.md - Writes daily AW activity summaries to
activity_dailytable 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-briefinboxfocusexecutorprojectsjournalretrospector - 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_logtable (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 remainexecutor-analyzer.sh— cron*/5; picks one unanalyzed task, runsclaude -panalysis prompt, setsfor_review/awaiting_go/skip, exits; restarts for next task- Worker prompts in
~/Developer/personal-os/agent/prompts/executor-worker-*.md - Queue state in
executor_queuetable; 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
#executorvia 2-min cron, auto-approves safe actions ([REQUEST:create_worktree],[REQUEST:run_tests], etc.), escalates ambiguous/risky ones to Alex. Seepersonal/projects/personal-os/executor-spawning-research.mdfor 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 fromorigin/main - State machine in
executor_runstable - 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_fsmode to Hermesimage_routing(save image locally, pass path to agent instead of bytes). Workaround: top up Gemini API credits on Kraken. Tracked inpersonal/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/