Files
obsidian-vault/wiki/personal-os-self-modification.md
T

153 lines
5.8 KiB
Markdown

---
namespace: work
tags: [system, self-modification, eagle, meta]
last_updated: 2026-05-14
confidence: 1.0
---
# Personal OS — Self-Modification Guide
How Eagle (and Alex via Claude Code) can safely evolve the system without breaking it.
**Rule**: Always show a diff/draft first, confirm, then apply. Commit the vault after.
---
## What Eagle Can Change (no approval needed — show draft first)
### 1. Prompt files (`~/Developer/personal-os/agent/prompts/*.md`)
Eagle reads and writes its own prompts. When Alex says "add X to the morning brief" or "change how inbox triage handles Y":
1. Read the current prompt: `~/Developer/personal-os/agent/prompts/<name>.md`
2. Draft the change, show the diff in Zulip
3. On confirmation: write the file
4. Commit: `cd ~/Developer/personal-os && git add agent/prompts/<name>.md && git commit -m "[YYYY-MM-DD] prompt: <description>"`
**Do not** change `executor-bug-fix.md` without explicit confirmation — it controls autonomous code changes.
### 2. SOUL.md (`~/.hermes/SOUL.md`)
Eagle's identity, rules, and operating context. Eagle can propose changes to:
- Allowed vault write paths
- Focus gating rules
- Channel routing
Same flow: draft → confirm → write → no vault commit needed (SOUL.md is outside vault).
### 3. ActivityWatch project rules (`~/Developer/personal-os/aw-projects.json`)
To classify a new project as work or personal:
1. Read current `aw-projects.json`
2. Add entry with `project`, `namespace` (omit for work, `"personal"` for pet projects), and `rules`
3. Show draft, confirm, write
4. Commit: `cd ~/Developer/personal-os && git add aw-projects.json && git commit -m "[YYYY-MM-DD] aw: classify <project>"`
The `namespace: "personal"` field excludes a project from work activity in status.md and activity_daily.
### 4. Vault knowledge pages (`~/obsidian/wiki/`, `~/obsidian/work/wiki/`)
Eagle does **not** write to `wiki/` — that's the wiki-ingest job (22:00 launchd). But Eagle **can** write to:
- `~/obsidian/work/projects/SLUG.md` — project notes
- `~/obsidian/work/decisions/YYYY-MM-TOPIC.md` — decisions
- `~/obsidian/personal/` — personal notes
- `~/obsidian/family/` — family docs
After writing: `cd ~/obsidian && git add -A && git commit -m "[YYYY-MM-DD] <description>"`
### 5. Correction logging (corrections_log table)
Eagle silently logs a row whenever Alex pushes back on a suggestion. No approval needed — this is continuous background instrumentation, not a visible change.
```sql
INSERT INTO corrections_log (date, week_number, source, original_plan, correction, deferred_gids, reason_tag)
VALUES (current_date, EXTRACT(WEEK FROM current_date)::int,
'<source>', '<original>', '<user_message>',
ARRAY[<gids>]::text[], '<reason_tag>');
```
---
## What Requires Approval (always confirm explicitly)
### Schema changes (PostgreSQL)
New tables, columns, or indexes require a SQL migration. Pattern:
1. Draft the SQL in Zulip (or Mattermost, post-migration), explain the purpose
2. On "go": run via `psql personal_os -c "..."`
3. Update `~/obsidian/wiki/personal-os-schema.md` (this is auto-generated at 22:00, but a manual update is fine)
Current tables: tasks, stories, task_edges, sync_state, task_annotations, activity_daily, corrections_log, executor_runs.
### New Hermes cron jobs
Add to `~/.hermes/config.yaml`. Format:
```yaml
crons:
- id: my-new-job
schedule: "30 9 * * 1-5"
prompt: |
Run: ~/Developer/personal-os/agent/prompts/my-prompt.md
channel: "#channel-name"
```
Must confirm before writing — a broken cron syntax silently prevents Hermes from starting.
### New launchd agents (`~/Library/LaunchAgents/`)
New plist files. Rarely needed — only if a job requires Mac filesystem access and can't run inside Hermes (e.g., wiki-ingest). Confirm before writing and before loading with `launchctl`.
### Executor prompt (`executor-bug-fix.md`)
Controls autonomous code changes. Changes here need explicit approval because a mistake could cause the Executor to behave incorrectly on real PRs.
### Hermes model or MCP configuration (`~/.hermes/config.yaml`)
Model upgrades, new MCP servers. Show the diff; confirm before writing.
---
## How generate-status.js Gets Extended
When a new data signal should appear in status.md:
1. Add a SQL query function (e.g., `getNewSignal()`)
2. Add a render function (e.g., `renderNewSignal(data)`)
3. Add both to `main()`: Promise.all for the query, the render call in `parts`
4. Test: `node ~/Developer/personal-os/generate-status.js` and read `~/context/status.md`
5. Commit
**Never** edit generate-status.js to change how Asana sync works — that's sync.js territory.
---
## Debugging the System
| Symptom | Check |
|---------|-------|
| status.md is stale (> 40 min old) | `stat -f "%Sm" ~/context/status.md` — if old, run `bash ~/scripts/run-pipeline.sh` |
| Hermes cron didn't fire | Check heartbeat: `tail -20 ~/Developer/personal-os/logs/heartbeat.log` |
| Eagle gave wrong Asana data | The DB may be stale — run `node ~/Developer/personal-os/sync.js` manually |
| activity_daily missing today | generate-status.js runs upsert — check `select * from activity_daily where bucket_day = current_date` |
| corrections_log empty | Eagle only inserts on pushback — expected to be sparse |
| Executor in stuck state | `SELECT id, state, updated_at FROM executor_runs WHERE state NOT IN ('complete','abandoned');` |
---
## Safe Operations Checklist
Before making any system change:
- [ ] Read the current file/config before proposing a change
- [ ] Show the diff, not just a description
- [ ] Wait for explicit confirmation
- [ ] Apply the change
- [ ] Verify: run the component or check output
- [ ] Commit if in a git repo (`personal-os` or `obsidian`)
---
## See Also
- [[personal-os-architecture]] — full system map
- [[personal-os-agent-rules]] — Eagle's rules and channel routing
- [[personal-os-purpose]] — why this system exists