diff --git a/wiki/ddg-asana-workflow.md b/wiki/ddg-asana-workflow.md new file mode 100644 index 00000000..0e3216db --- /dev/null +++ b/wiki/ddg-asana-workflow.md @@ -0,0 +1,74 @@ +--- +namespace: work +tags: [asana, ddg, workflow, rules] +last_synced: 2026-04-27 +confidence: 1.0 +--- + +# DuckDuckGo Asana Workflow + +## Alex's Identity + +- **Assignee GID**: `1202406491309495` +- **Role**: macOS Browser Developer at DuckDuckGo +- **Career advisor**: Dominik + +## Task Sources in DB + +| `source` | Meaning | Eagle's default role | +|----------|---------|---------------------| +| `my_tasks` | Assigned to Alex | DRI — drives to completion | +| `delegated` | Created by Alex, assigned to others | Delegator — tracks progress | +| `following` | Alex is a follower/CC | Observer — no action unless asked | +| `project` | In a shared project Alex follows | Context only | + +## Task Type Classification + +**Ship Review** — name contains "Ship Review:" or is in "Ship Reviews" project +- Alex as assignee → DRI (drives all AOR approvals) +- Alex as named reviewer → AOR Reviewer (provide feedback, signal done) + +**Tech Design** — name contains "Tech Design:", "TD:", or "Design Doc:" +- Alex as assignee/author → address feedback, drive to approval +- Alex as reviewer → review, comment, approve/iterate + +**PFR (Product Feedback Request)** — name starts "PFR:" +- 3-day implicit deadline. Requestor summarizes decision after window closes. + +**Rotation** — name contains "Maintenance Rotation", "Triage Rotation", "Release DRI", "PFM DRI" +- Has date range + structured checklist + +## Status Labels + +`NEEDS ACTION` | `WAITING` | `BLOCKED` | `STALLED` | `ON TRACK` | `OVERDUE` | `MONITORING` + +Priority order in brief: OVERDUE → NEEDS ACTION → BLOCKED → STALLED → WAITING → MONITORING + +## Weekly Rhythms + +- **TP (Top Priority)**: one task per week, set Monday. Tier 1 = primary. Stale if not changed >2 weeks. +- **1-Must**: one task per day, set each morning. Should be achievable today. +- **1:1 with Dominik**: weekly. Prep agenda in advance. +- **Quick Wins Days**: periodic Wed–Fri sprints. Shift from project deep-work to clearing backlog. +- **Rotation**: active if assigned "Maintenance Rotation" or similar. Handoff notes due Friday. + +## Key Rules + +- Silence ≠ approval. Never assume a task is done without explicit confirmation. +- "No action needed" on a DRI task requires proof (all approvals collected). +- If someone addressed your feedback and re-requested review → **you are the blocker**. NEEDS ACTION. +- Stale TP (>2 weeks unchanged) → surface it. +- Performance review deadline within 3 days → HIGH PRIORITY. +- Major incident with no postmortem >3 days after resolution → OVERDUE, critical. + +## Asana MCP Usage Rules + +Use Asana MCP only in two cases: +1. Task GID is referenced but missing from DB → `asana_get_task` +2. Stories in DB are incomplete/stale → `asana_get_stories_for_task` + +Never bulk-query Asana live. Never use MCP to scan projects — that's sync.js's job. + +## Related + +[[personal-os-agent-rules]] [[personal-os-sync-pipeline]] diff --git a/wiki/personal-os-agent-rules.md b/wiki/personal-os-agent-rules.md new file mode 100644 index 00000000..f4ea366d --- /dev/null +++ b/wiki/personal-os-agent-rules.md @@ -0,0 +1,84 @@ +--- +namespace: work +tags: [system, agent, eagle, rules] +last_synced: 2026-04-27 +confidence: 1.0 +--- + +# Personal OS — Agent Rules & Architecture + +Eagle (Орёл) is the Discord-facing Hermes agent. This page documents what Eagle knows about its own environment and how to reason about it. + +## Data Flow + +``` +Asana API + → sync.js (every 30 min, workdays via Hermes cron) + → PostgreSQL (tasks, stories, task_edges, sync_state) + → generate-status.js + → ~/Developer/personal-os/asana_context.md ← raw Asana data + → ~/Developer/personal-os/status.md ← Eagle reads THIS +``` + +Eagle **only reads** `status.md`. It never touches the DB directly or calls Asana API. + +## Eagle's Knowledge Sources + +1. `~/Developer/personal-os/status.md` — live Asana snapshot (updated every 30 min) +2. `~/Developer/personal-os/briefs/daily/YYYY-MM-DD.md` — today's brief +3. `~/Developer/personal-os/briefs/weekly/plan-MONDAY.md` — weekly plan +4. `~/obsidian/wiki/` — knowledge base (via obsidian MCP) +5. `~/Developer/personal-os/agent/` — playbooks and rules (via file tools) + +## Feedback Loop + +When Alex corrects something: +1. Edit the brief directly (show diff first, confirm before writing) +2. If systemic → edit the prompt template in `agent/prompts/` +3. Log to `~/Developer/personal-os/logs/corrections_log.md`: `YYYY-MM-DD HH:MM | file | what changed` + +## Self-Diagnostics + +If pipeline seems stale, Eagle can check: +```bash +stat -f "%Sm" ~/Developer/personal-os/status.md +# Should be < 40 min old on workdays +``` + +If sync is broken: +```bash +bash ~/scripts/run-pipeline.sh +# Runs sync.js + generate-status.js + healthcheck +``` + +If wiki is stale: +```bash +bash ~/scripts/run-wiki-ingest.sh +# Runs at 22:00 via launchd; call manually if needed +``` + +## Cron Schedule (Hermes) + +| Job | Schedule | Channel | +|-----|----------|---------| +| data-pipeline | */30 7-21 workdays | silent | +| morning-brief | 08:30 workdays | #daily-brief | +| eod-summary | 18:00 workdays | #daily-brief | +| inbox-check | */30 9-19 workdays | #inbox | +| weekly-plan | Mon 08:00 | #daily-brief | +| weekly-review | Fri 17:00 | #daily-brief | +| commit-vault | 23:00 daily | silent | + +wiki-ingest runs at 22:00 via **launchd** (not Hermes) — because API-based Claude has no Mac filesystem access. + +## Allowed File Writes + +Eagle can write to: +- `briefs/daily/YYYY-MM-DD.md` +- `briefs/weekly/plan-MONDAY.md` +- `briefs/weekly/YYYY-MM-DD.md` +- `briefs/inbox/YYYY-MM-DD.md` +- `agent/prompts/*.md` (with confirmation) +- `logs/corrections_log.md` + +Never write to `obsidian/wiki/` directly — that's wiki-ingest's job. diff --git a/wiki/personal-os-sync-pipeline.md b/wiki/personal-os-sync-pipeline.md new file mode 100644 index 00000000..590ce9c9 --- /dev/null +++ b/wiki/personal-os-sync-pipeline.md @@ -0,0 +1,91 @@ +--- +namespace: work +tags: [system, sync, pipeline, debugging] +last_synced: 2026-04-27 +confidence: 1.0 +--- + +# Personal OS — Sync Pipeline + +## Components + +### sync.js +Pulls from 4 Asana sources into PostgreSQL. Run: `node ~/Developer/personal-os/sync.js` + +**Sources fetched:** +1. `fetchMyTasks()` — My Tasks sections by GID (section-by-section) +2. `fetchFollowingTasks()` — tasks I follow, 7-day chunks to work around 100-result cap +3. `fetchDelegatedTasks()` — created by me, assigned to others +4. `fetchProjectTasks()` — tasks from projects I'm a member of (lookback window on full sync) +5. `sweepRecentlyCompleted()` — catch completed tasks missed by above + +**Incremental sync**: uses `modified_since` cursor from `sync_state` table. +**Full sync**: triggered when `full_sync_at` is older than configured threshold. + +### generate-status.js +Reads from PostgreSQL → writes `asana_context.md` + `status.md`. +Run: `node ~/Developer/personal-os/generate-status.js` + +### run-pipeline.sh +Wrapper: runs sync.js + generate-status.js + healthcheck. +`~/scripts/run-pipeline.sh` + +Healthcheck: `asana_context.md` must be < 40 minutes old. Exits 1 if stale. + +## Known Bugs (Fixed) + +### possibly_deleted + overdue tasks appearing +**Root cause**: Full sync marks tasks absent from Asana response as `possibly_deleted=true`. +These tasks remained `completed=false`, causing them to appear overdue. + +**Fix 1 — generate-status.js**: Added `AND t.possibly_deleted = FALSE` to all 5 active-task queries. + +**Fix 2 — sync.js**: Added `sweepRecentlyCompleted()` called after `syncMyTasks()`. +Uses `searchTasksForWorkspace(completed:true, completed_at.after=cursor)` to catch tasks +that vanished from sections (because completed tasks are excluded from section membership results). + +### Completion gap +`getTasksForSection` drops completed tasks. `fetchFollowingTasks` has `completed:false` filter. +→ Completion events never reach DB incrementally. +→ `sweepRecentlyCompleted()` fills this gap. + +## Debugging Checklist + +**Pipeline seems stuck:** +```bash +bash ~/scripts/run-pipeline.sh +# Check exit code and output +``` + +**Check when last sync ran:** +```sql +SELECT key, last_sync_at, full_sync_at FROM sync_state ORDER BY last_sync_at DESC; +``` + +**Check possibly_deleted tasks (should be 0 active):** +```sql +SELECT count(*) FROM tasks WHERE possibly_deleted=true AND completed=false; +``` + +**Check asana_context.md freshness:** +```bash +stat -f "%Sm" ~/Developer/personal-os/asana_context.md +``` + +**Manual full sync (reset cursor):** +```sql +UPDATE sync_state SET cursor = null, full_sync_at = null WHERE key = 'my_tasks'; +``` +Then run `node sync.js`. + +## Files + +- `~/Developer/personal-os/sync.js` — main sync script +- `~/Developer/personal-os/generate-status.js` — status generation +- `~/Developer/personal-os/asana.js` — thin Asana API client +- `~/Developer/personal-os/config.json` — workspace GID, user GID, section GIDs +- `~/.config/personal-os/env` — ASANA_API_KEY, POSTGRES_URL + +## Related + +[[personal-os-architecture]] [[personal-os-agent-rules]] [[ddg-asana-workflow]]