From 39ac89f388532e9a7629808037791c64cd5fc13c Mon Sep 17 00:00:00 2001 From: m3tm3re Date: Tue, 3 Mar 2026 19:38:48 +0100 Subject: [PATCH] docs: update AGENTS.md and README.md for rules system, remove beads - Add rules/ directory documentation to both files - Update skill count from 25 to 15 modules - Remove beads references (issue tracking removed) - Update skills list with current active skills - Document flake.nix as proper Nix flake (not flake=false) - Add rules system integration section - Clean up sisyphus planning artifacts - Remove deprecated skills (memory, msteams, outlook) --- .envrc | 1 + .gitignore | 4 + .sisyphus/boulder.json | 9 - .../final-qa/scenario1-empty-config.json | 1 - .../final-qa/scenario2-single-language.json | 1 - .../final-qa/scenario3-multi-language.json | 1 - .../final-qa/scenario4-with-frameworks.json | 1 - .../scenario5-extra-instructions.json | 1 - .sisyphus/evidence/final-qa/summary.md | 153 -- .sisyphus/evidence/task-17-budget.txt | 6 - .../evidence/task-17-full-integration.txt | 1 - .sisyphus/evidence/task-17-inventory.txt | 16 - .sisyphus/evidence/task-17-paths-resolve.txt | 13 - .../chiron-agent-framework/learnings.md | 1042 ----------- .sisyphus/notepads/memory-system/decisions.md | 28 - .sisyphus/notepads/memory-system/issues.md | 0 .sisyphus/notepads/memory-system/learnings.md | 47 - .sisyphus/notepads/memory-system/problems.md | 0 .../notepads/opencode-memory/learnings.md | 120 -- .sisyphus/notepads/rules-system/learnings.md | 60 - .../plans/agent-permissions-refinement.md | 748 -------- .sisyphus/plans/chiron-agent-framework.md | 977 ---------- .sisyphus/plans/memory-system.md | 897 --------- .sisyphus/plans/opencode-memory.md | 1634 ----------------- .sisyphus/plans/rules-system.md | 804 -------- AGENTS.md | 51 +- README.md | 147 +- flake.lock | 27 + flake.nix | 68 + skills/excalidraw/SKILL.md | 706 ++++--- skills/excalidraw/references/arrows.md | 288 --- skills/excalidraw/references/color-palette.md | 67 + skills/excalidraw/references/colors.md | 91 - .../references/element-templates.md | 182 ++ skills/excalidraw/references/examples.md | 381 ---- skills/excalidraw/references/json-format.md | 210 --- skills/excalidraw/references/json-schema.md | 71 + .../references/render_excalidraw.py | 205 +++ .../references/render_template.html | 57 + skills/excalidraw/references/validation.md | 182 -- skills/memory/SKILL.md | 75 - skills/memory/references/deployment.md | 54 - skills/memory/references/mcp-config.md | 109 -- skills/msteams/SKILL.md | 108 -- skills/outlook/SKILL.md | 231 --- skills/skill-creator/SKILL.md | 32 + 46 files changed, 1357 insertions(+), 8550 deletions(-) create mode 100644 .envrc delete mode 100644 .sisyphus/boulder.json delete mode 100644 .sisyphus/evidence/final-qa/scenario1-empty-config.json delete mode 100644 .sisyphus/evidence/final-qa/scenario2-single-language.json delete mode 100644 .sisyphus/evidence/final-qa/scenario3-multi-language.json delete mode 100644 .sisyphus/evidence/final-qa/scenario4-with-frameworks.json delete mode 100644 .sisyphus/evidence/final-qa/scenario5-extra-instructions.json delete mode 100644 .sisyphus/evidence/final-qa/summary.md delete mode 100644 .sisyphus/evidence/task-17-budget.txt delete mode 100644 .sisyphus/evidence/task-17-full-integration.txt delete mode 100644 .sisyphus/evidence/task-17-inventory.txt delete mode 100644 .sisyphus/evidence/task-17-paths-resolve.txt delete mode 100644 .sisyphus/notepads/chiron-agent-framework/learnings.md delete mode 100644 .sisyphus/notepads/memory-system/decisions.md delete mode 100644 .sisyphus/notepads/memory-system/issues.md delete mode 100644 .sisyphus/notepads/memory-system/learnings.md delete mode 100644 .sisyphus/notepads/memory-system/problems.md delete mode 100644 .sisyphus/notepads/opencode-memory/learnings.md delete mode 100644 .sisyphus/notepads/rules-system/learnings.md delete mode 100644 .sisyphus/plans/agent-permissions-refinement.md delete mode 100644 .sisyphus/plans/chiron-agent-framework.md delete mode 100644 .sisyphus/plans/memory-system.md delete mode 100644 .sisyphus/plans/opencode-memory.md delete mode 100644 .sisyphus/plans/rules-system.md create mode 100644 flake.lock create mode 100644 flake.nix delete mode 100644 skills/excalidraw/references/arrows.md create mode 100644 skills/excalidraw/references/color-palette.md delete mode 100644 skills/excalidraw/references/colors.md create mode 100644 skills/excalidraw/references/element-templates.md delete mode 100644 skills/excalidraw/references/examples.md delete mode 100644 skills/excalidraw/references/json-format.md create mode 100644 skills/excalidraw/references/json-schema.md create mode 100644 skills/excalidraw/references/render_excalidraw.py create mode 100644 skills/excalidraw/references/render_template.html delete mode 100644 skills/excalidraw/references/validation.md delete mode 100644 skills/memory/SKILL.md delete mode 100644 skills/memory/references/deployment.md delete mode 100644 skills/memory/references/mcp-config.md delete mode 100644 skills/msteams/SKILL.md delete mode 100644 skills/outlook/SKILL.md diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index f394199..b62007f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,7 @@ .sidecar-start.sh .sidecar-base .td-root + +# Nix / direnv +.direnv/ +result diff --git a/.sisyphus/boulder.json b/.sisyphus/boulder.json deleted file mode 100644 index b01752a..0000000 --- a/.sisyphus/boulder.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "active_plan": "/home/m3tam3re/p/AI/AGENTS/.sisyphus/plans/rules-system.md", - "started_at": "2026-02-17T17:50:08.922Z", - "session_ids": [ - "ses_393691db2ffe4YZvieMFehJe54" - ], - "plan_name": "rules-system", - "agent": "atlas" -} \ No newline at end of file diff --git a/.sisyphus/evidence/final-qa/scenario1-empty-config.json b/.sisyphus/evidence/final-qa/scenario1-empty-config.json deleted file mode 100644 index 294b0ce..0000000 --- a/.sisyphus/evidence/final-qa/scenario1-empty-config.json +++ /dev/null @@ -1 +0,0 @@ -{"instructions":[".opencode-rules/concerns/coding-style.md",".opencode-rules/concerns/naming.md",".opencode-rules/concerns/documentation.md",".opencode-rules/concerns/testing.md",".opencode-rules/concerns/git-workflow.md",".opencode-rules/concerns/project-structure.md"],"shellHook":"# Create/update symlink to AGENTS rules directory\nln -sfn /nix/store/wsqzf0z3hg8mhpq484f24fm72qp4k6sg-AGENTS/rules .opencode-rules\n\n# Generate opencode.json configuration file\ncat > opencode.json <<'OPENCODE_EOF'\n{\"$schema\":\"https://opencode.ai/config.json\",\"instructions\":[\".opencode-rules/concerns/coding-style.md\",\".opencode-rules/concerns/naming.md\",\".opencode-rules/concerns/documentation.md\",\".opencode-rules/concerns/testing.md\",\".opencode-rules/concerns/git-workflow.md\",\".opencode-rules/concerns/project-structure.md\"]}\nOPENCODE_EOF\n"} diff --git a/.sisyphus/evidence/final-qa/scenario2-single-language.json b/.sisyphus/evidence/final-qa/scenario2-single-language.json deleted file mode 100644 index 328ec28..0000000 --- a/.sisyphus/evidence/final-qa/scenario2-single-language.json +++ /dev/null @@ -1 +0,0 @@ -{"instructions":[".opencode-rules/concerns/coding-style.md",".opencode-rules/concerns/naming.md",".opencode-rules/concerns/documentation.md",".opencode-rules/concerns/testing.md",".opencode-rules/concerns/git-workflow.md",".opencode-rules/concerns/project-structure.md",".opencode-rules/languages/python.md"],"shellHook":"# Create/update symlink to AGENTS rules directory\nln -sfn /nix/store/4li05383sgf4z0l6bxv8hmvgs600y56x-AGENTS/rules .opencode-rules\n\n# Generate opencode.json configuration file\ncat > opencode.json <<'OPENCODE_EOF'\n{\"$schema\":\"https://opencode.ai/config.json\",\"instructions\":[\".opencode-rules/concerns/coding-style.md\",\".opencode-rules/concerns/naming.md\",\".opencode-rules/concerns/documentation.md\",\".opencode-rules/concerns/testing.md\",\".opencode-rules/concerns/git-workflow.md\",\".opencode-rules/concerns/project-structure.md\",\".opencode-rules/languages/python.md\"]}\nOPENCODE_EOF\n"} diff --git a/.sisyphus/evidence/final-qa/scenario3-multi-language.json b/.sisyphus/evidence/final-qa/scenario3-multi-language.json deleted file mode 100644 index b70c0a1..0000000 --- a/.sisyphus/evidence/final-qa/scenario3-multi-language.json +++ /dev/null @@ -1 +0,0 @@ -{"instructions":[".opencode-rules/concerns/coding-style.md",".opencode-rules/concerns/naming.md",".opencode-rules/concerns/documentation.md",".opencode-rules/concerns/testing.md",".opencode-rules/concerns/git-workflow.md",".opencode-rules/concerns/project-structure.md",".opencode-rules/languages/python.md",".opencode-rules/languages/typescript.md",".opencode-rules/languages/nix.md",".opencode-rules/languages/shell.md"],"shellHook":"# Create/update symlink to AGENTS rules directory\nln -sfn /nix/store/qzsdn3m85qwarpd43x8k28sja40r21p7-AGENTS/rules .opencode-rules\n\n# Generate opencode.json configuration file\ncat > opencode.json <<'OPENCODE_EOF'\n{\"$schema\":\"https://opencode.ai/config.json\",\"instructions\":[\".opencode-rules/concerns/coding-style.md\",\".opencode-rules/concerns/naming.md\",\".opencode-rules/concerns/documentation.md\",\".opencode-rules/concerns/testing.md\",\".opencode-rules/concerns/git-workflow.md\",\".opencode-rules/concerns/project-structure.md\",\".opencode-rules/languages/python.md\",\".opencode-rules/languages/typescript.md\",\".opencode-rules/languages/nix.md\",\".opencode-rules/languages/shell.md\"]}\nOPENCODE_EOF\n"} diff --git a/.sisyphus/evidence/final-qa/scenario4-with-frameworks.json b/.sisyphus/evidence/final-qa/scenario4-with-frameworks.json deleted file mode 100644 index c8c14a3..0000000 --- a/.sisyphus/evidence/final-qa/scenario4-with-frameworks.json +++ /dev/null @@ -1 +0,0 @@ -{"instructions":[".opencode-rules/concerns/coding-style.md",".opencode-rules/concerns/naming.md",".opencode-rules/concerns/documentation.md",".opencode-rules/concerns/testing.md",".opencode-rules/concerns/git-workflow.md",".opencode-rules/concerns/project-structure.md",".opencode-rules/languages/python.md",".opencode-rules/frameworks/n8n.md"],"shellHook":"# Create/update symlink to AGENTS rules directory\nln -sfn /nix/store/55brjhy9m1vcgrnd100vmwf9bycjpzpi-AGENTS/rules .opencode-rules\n\n# Generate opencode.json configuration file\ncat > opencode.json <<'OPENCODE_EOF'\n{\"$schema\":\"https://opencode.ai/config.json\",\"instructions\":[\".opencode-rules/concerns/coding-style.md\",\".opencode-rules/concerns/naming.md\",\".opencode-rules/concerns/documentation.md\",\".opencode-rules/concerns/testing.md\",\".opencode-rules/concerns/git-workflow.md\",\".opencode-rules/concerns/project-structure.md\",\".opencode-rules/languages/python.md\",\".opencode-rules/frameworks/n8n.md\"]}\nOPENCODE_EOF\n"} diff --git a/.sisyphus/evidence/final-qa/scenario5-extra-instructions.json b/.sisyphus/evidence/final-qa/scenario5-extra-instructions.json deleted file mode 100644 index 0e5ee34..0000000 --- a/.sisyphus/evidence/final-qa/scenario5-extra-instructions.json +++ /dev/null @@ -1 +0,0 @@ -{"instructions":[".opencode-rules/concerns/coding-style.md",".opencode-rules/concerns/naming.md",".opencode-rules/concerns/documentation.md",".opencode-rules/concerns/testing.md",".opencode-rules/concerns/git-workflow.md",".opencode-rules/concerns/project-structure.md",".opencode-rules/languages/python.md",".opencode-rules/custom.md"],"shellHook":"# Create/update symlink to AGENTS rules directory\nln -sfn /nix/store/r8yfirsyyii9x05qd5kfdvzcqv7sx6az-AGENTS/rules .opencode-rules\n\n# Generate opencode.json configuration file\ncat > opencode.json <<'OPENCODE_EOF'\n{\"$schema\":\"https://opencode.ai/config.json\",\"instructions\":[\".opencode-rules/concerns/coding-style.md\",\".opencode-rules/concerns/naming.md\",\".opencode-rules/concerns/documentation.md\",\".opencode-rules/concerns/testing.md\",\".opencode-rules/concerns/git-workflow.md\",\".opencode-rules/concerns/project-structure.md\",\".opencode-rules/languages/python.md\",\".opencode-rules/custom.md\"]}\nOPENCODE_EOF\n"} diff --git a/.sisyphus/evidence/final-qa/summary.md b/.sisyphus/evidence/final-qa/summary.md deleted file mode 100644 index 772a7a3..0000000 --- a/.sisyphus/evidence/final-qa/summary.md +++ /dev/null @@ -1,153 +0,0 @@ -# Opencode Rules Nix Module - Manual QA Results - -## Test Summary -Date: 2025-02-17 -Module: `/home/m3tam3re/p/NIX/nixpkgs/lib/opencode-rules.nix` -Test Type: Manual QA (nix eval) - ---- - -## Scenario Results - -### Scenario 1: Empty Config (Defaults Only) -**Command**: `nix eval --impure --json --expr 'let pkgs = import {}; m3taLib = import /home/m3tam3re/p/NIX/nixpkgs/lib {lib = pkgs.lib;}; in m3taLib.opencode-rules.mkOpencodeRules { agents = /home/m3tam3re/p/AI/AGENTS; }'` - -**Results**: -- ✅ Valid JSON output -- ✅ Has `$schema` field in embedded opencode.json -- ✅ Has `instructions` field -- ✅ Correct instruction count: 6 (default concerns only) - -**Expected Instructions**: -1. `.opencode-rules/concerns/coding-style.md` -2. `.opencode-rules/concerns/naming.md` -3. `.opencode-rules/concerns/documentation.md` -4. `.opencode-rules/concerns/testing.md` -5. `.opencode-rules/concerns/git-workflow.md` -6. `.opencode-rules/concerns/project-structure.md` - ---- - -### Scenario 2: Single Language (Python) -**Command**: `nix eval --impure --json --expr 'let pkgs = import {}; m3taLib = import /home/m3tam3re/p/NIX/nixpkgs/lib {lib = pkgs.lib;}; in m3taLib.opencode-rules.mkOpencodeRules { agents = /home/m3tam3re/p/AI/AGENTS; languages = ["python"]; }'` - -**Results**: -- ✅ Valid JSON output -- ✅ Has `$schema` field in embedded opencode.json -- ✅ Has `instructions` field -- ✅ Correct instruction count: 7 (6 concerns + 1 language) - -**Expected Instructions**: -- All 6 default concerns -- `.opencode-rules/languages/python.md` - ---- - -### Scenario 3: Multi-Language -**Command**: `nix eval --impure --json --expr 'let pkgs = import {}; m3taLib = import /home/m3tam3re/p/NIX/nixpkgs/lib {lib = pkgs.lib;}; in m3taLib.opencode-rules.mkOpencodeRules { agents = /home/m3tam3re/p/AI/AGENTS; languages = ["python" "typescript" "nix" "shell"]; }'` - -**Results**: -- ✅ Valid JSON output -- ✅ Has `$schema` field in embedded opencode.json -- ✅ Has `instructions` field -- ✅ Correct instruction count: 10 (6 concerns + 4 languages) - -**Expected Instructions**: -- All 6 default concerns -- `.opencode-rules/languages/python.md` -- `.opencode-rules/languages/typescript.md` -- `.opencode-rules/languages/nix.md` -- `.opencode-rules/languages/shell.md` - ---- - -### Scenario 4: With Frameworks -**Command**: `nix eval --impure --json --expr 'let pkgs = import {}; m3taLib = import /home/m3tam3re/p/NIX/nixpkgs/lib {lib = pkgs.lib;}; in m3taLib.opencode-rules.mkOpencodeRules { agents = /home/m3tam3re/p/AI/AGENTS; languages = ["python"]; frameworks = ["n8n"]; }'` - -**Results**: -- ✅ Valid JSON output -- ✅ Has `$schema` field in embedded opencode.json -- ✅ Has `instructions` field -- ✅ Correct instruction count: 8 (6 concerns + 1 language + 1 framework) - -**Expected Instructions**: -- All 6 default concerns -- `.opencode-rules/languages/python.md` -- `.opencode-rules/frameworks/n8n.md` - ---- - -### Scenario 5: Extra Instructions -**Command**: `nix eval --impure --json --expr 'let pkgs = import {}; m3taLib = import /home/m3tam3re/p/NIX/nixpkgs/lib {lib = pkgs.lib;}; in m3taLib.opencode-rules.mkOpencodeRules { agents = /home/m3tam3re/p/AI/AGENTS; languages = ["python"]; extraInstructions = [".opencode-rules/custom.md"]; }'` - -**Results**: -- ✅ Valid JSON output -- ✅ Has `$schema` field in embedded opencode.json -- ✅ Has `instructions` field -- ✅ Correct instruction count: 8 (6 concerns + 1 language + 1 custom) - -**Expected Instructions**: -- All 6 default concerns -- `.opencode-rules/languages/python.md` -- `.opencode-rules/custom.md` - ---- - -## Content Quality Spot Checks - -### 1. coding-style.md (Concern Rule) -**Assessment**: ✅ High Quality -- Clear critical rules with "Always/Never" directives -- Good vs. bad code examples -- Comprehensive coverage: formatting, patterns, error handling, type safety, function design, SOLID -- Well-structured sections - -### 2. python.md (Language Rule) -**Assessment**: ✅ High Quality -- Modern toolchain recommendations (uv, ruff, pyright, pytest, hypothesis) -- Common idioms with practical examples -- Anti-patterns with explanations -- Project setup structure -- Clear, actionable code snippets - -### 3. n8n.md (Framework Rule) -**Assessment**: ✅ High Quality -- Concise workflow design principles -- Clear naming conventions -- Error handling patterns -- Security best practices -- Actionable testing guidelines - ---- - -## Issues Encountered - -### Socket File Issue -**Issue**: `nix eval` failed with `error: file '/home/m3tam3re/p/AI/AGENTS/.beads/bd.sock' has an unsupported type` - -**Workaround**: Temporarily moved `.beads` directory outside the AGENTS tree during testing - -**Root Cause**: Nix attempts to evaluate/store the `agents` path recursively and encounters unsupported socket files (Unix domain sockets) - -**Recommendation**: Consider adding `.beads` to `.gitignore` and excluding it from path evaluation if possible, or document this limitation for users - ---- - -## Final Verdict - -``` -Scenarios [5/5 pass] | VERDICT: OKAY -``` - -### Summary -- All 5 test scenarios executed successfully -- All JSON outputs are valid and properly structured -- All embedded `opencode.json` configurations have required `$schema` and `instructions` fields -- Instruction counts match expected values for each scenario -- Rule content quality is high across concern, language, and framework rules -- Shell hook properly generates symlink and configuration file - -### Notes -- Socket file issue requires workaround (documented) -- Module correctly handles default concerns, multiple languages, frameworks, and custom instructions -- Code examples in rules are clear and actionable diff --git a/.sisyphus/evidence/task-17-budget.txt b/.sisyphus/evidence/task-17-budget.txt deleted file mode 100644 index 6a0e4aa..0000000 --- a/.sisyphus/evidence/task-17-budget.txt +++ /dev/null @@ -1,6 +0,0 @@ -=== Context Budget === -Concerns: 751 -Python: 224 -Total (concerns + python): 975 -Limit: 1500 -RESULT: PASS (under 1500) diff --git a/.sisyphus/evidence/task-17-full-integration.txt b/.sisyphus/evidence/task-17-full-integration.txt deleted file mode 100644 index 1eae8a3..0000000 --- a/.sisyphus/evidence/task-17-full-integration.txt +++ /dev/null @@ -1 +0,0 @@ -[".opencode-rules/concerns/coding-style.md",".opencode-rules/concerns/naming.md",".opencode-rules/concerns/documentation.md",".opencode-rules/concerns/testing.md",".opencode-rules/concerns/git-workflow.md",".opencode-rules/concerns/project-structure.md",".opencode-rules/languages/python.md",".opencode-rules/languages/typescript.md",".opencode-rules/languages/nix.md",".opencode-rules/languages/shell.md",".opencode-rules/frameworks/n8n.md"] diff --git a/.sisyphus/evidence/task-17-inventory.txt b/.sisyphus/evidence/task-17-inventory.txt deleted file mode 100644 index a56e1e1..0000000 --- a/.sisyphus/evidence/task-17-inventory.txt +++ /dev/null @@ -1,16 +0,0 @@ -=== Task 17 Integration Test === - -File Line Counts: - 163 /home/m3tam3re/p/AI/AGENTS/rules/concerns/coding-style.md - 149 /home/m3tam3re/p/AI/AGENTS/rules/concerns/documentation.md - 118 /home/m3tam3re/p/AI/AGENTS/rules/concerns/git-workflow.md - 105 /home/m3tam3re/p/AI/AGENTS/rules/concerns/naming.md - 82 /home/m3tam3re/p/AI/AGENTS/rules/concerns/project-structure.md - 134 /home/m3tam3re/p/AI/AGENTS/rules/concerns/testing.md - 129 /home/m3tam3re/p/AI/AGENTS/rules/languages/nix.md - 224 /home/m3tam3re/p/AI/AGENTS/rules/languages/python.md - 100 /home/m3tam3re/p/AI/AGENTS/rules/languages/shell.md - 150 /home/m3tam3re/p/AI/AGENTS/rules/languages/typescript.md - 42 /home/m3tam3re/p/AI/AGENTS/rules/frameworks/n8n.md - 1396 total -RESULT: All 11 files present diff --git a/.sisyphus/evidence/task-17-paths-resolve.txt b/.sisyphus/evidence/task-17-paths-resolve.txt deleted file mode 100644 index 740cbd1..0000000 --- a/.sisyphus/evidence/task-17-paths-resolve.txt +++ /dev/null @@ -1,13 +0,0 @@ -=== Path Resolution Check === -OK: rules/concerns/coding-style.md exists -OK: rules/concerns/naming.md exists -OK: rules/concerns/documentation.md exists -OK: rules/concerns/testing.md exists -OK: rules/concerns/git-workflow.md exists -OK: rules/concerns/project-structure.md exists -OK: rules/languages/python.md exists -OK: rules/languages/typescript.md exists -OK: rules/languages/nix.md exists -OK: rules/languages/shell.md exists -OK: rules/frameworks/n8n.md exists -RESULT: All paths resolve diff --git a/.sisyphus/notepads/chiron-agent-framework/learnings.md b/.sisyphus/notepads/chiron-agent-framework/learnings.md deleted file mode 100644 index 2619ded..0000000 --- a/.sisyphus/notepads/chiron-agent-framework/learnings.md +++ /dev/null @@ -1,1042 +0,0 @@ -# Learnings - Chiron Agent Framework - -## Wave 1, Task 1: Create agents.json with 6 agent definitions - -### Agent Structure Pattern - -**Required fields per agent:** -- `description`: Clear purpose statement -- `mode`: "primary" for orchestrators, "subagent" for specialists -- `model`: "zai-coding-plan/glm-4.7" (consistent across all agents) -- `prompt`: File reference pattern `{file:./prompts/.txt}` -- `permission`: Either explicit permissions or simple "question": "allow" - -### Primary vs Subagent Modes - -**Primary agents** (2): chiron, chiron-forge -- Can be invoked directly by user -- Orchestrate and delegate work -- Higher permission levels (external_directory rules) - -**Subagents** (4): hermes, athena, apollo, calliope -- Invoked by primary agents via Task tool -- Specialized single-purpose workflows -- Simpler permission structure (question: "allow") - -### Permission Patterns - -**Primary agents**: Complex permission structure -```json -"permission": { - "external_directory": { - "~/p/**": "allow", - "*": "ask" - } -} -``` - -**Subagents**: Simple permission structure -```json -"permission": { - "question": "allow" -} -``` - -### Agent Domains - -1. **chiron**: Plan Mode - Read-only analysis and planning -2. **chiron-forge**: Build Mode - Full execution with safety prompts -3. **hermes**: Work communication (Basecamp, Outlook, Teams) -4. **athena**: Work knowledge (Outline wiki, documentation) -5. **apollo**: Private knowledge (Obsidian vault, personal notes) -6. **calliope**: Writing (documentation, reports, prose) - -### Verification Commands - -**Agent count:** -```bash -python3 -c "import json; data = json.load(open('agents/agents.json')); print(len(data))" -# Expected output: 6 -``` - -**Agent names:** -```bash -python3 -c "import json; data = json.load(open('agents/agents.json')); print(sorted(data.keys()))" -# Expected output: ['apollo', 'athena', 'calliope', 'chiron', 'chiron-forge', 'hermes'] -``` - -### Key Takeaways - -- Prompt files use file references, not inline content (Wave 2 will create these) -- Model is consistent across all agents for predictable behavior -- Permission structure matches agent capability level (more complex for primaries) -- Mode determines how agent can be invoked (direct vs delegated) - -## Wave 2, Task 6: Create Athena (Work Knowledge) system prompt - -### Prompt Structure Pattern Consistency - -All subagent prompts follow identical structure from skill-creator guidance: -1. **Role definition**: "You are [name], the Greek [role], specializing in [domain]" -2. **Your Core Responsibilities**: Numbered list of primary duties -3. **Process**: Numbered steps for workflow execution -4. **Quality Standards**: Bulleted list of requirements -5. **Output Format**: Structure specification -6. **Edge Cases**: Bulleted list of exception handling -7. **Tool Usage**: Instructions for tool interaction (especially Question tool) -8. **Boundaries**: Explicit DO NOT statements with domain attribution - -### Athena's Domain Specialization - -**Role**: Work knowledge specialist for Outline wiki -- Primary tool: Outline wiki integration (document CRUD, search, collections, sharing) -- Core activities: wiki search, knowledge retrieval, documentation updates, knowledge organization -- Question tool usage: Document selection, search scope clarification, collection specification - -**Differentiation from other agents:** -- Hermes (communication): Short messages, team communication tools (Basecamp, Teams, Outlook) -- Apollo (private knowledge): Obsidian vaults, personal notes, private data -- Calliope (writing): Documentation drafting, creative prose, reports -- Athena (work knowledge): Team wiki, Outline, shared documentation repositories - -### Quality Focus for Knowledge Work - -Key quality standards unique to Athena: -- Outline-specific understanding: collections, documents, sharing permissions, revision history -- Knowledge structure preservation: hierarchy, relationships, cross-references -- Identification of outdated information for updates -- Consistency in terminology across documentation -- Pattern recognition for organization improvements - -### Boundary Clarity - -Boundaries section explicitly references other agents' domains: -- "Do NOT handle short communication (Hermes's domain)" -- "Do NOT access private knowledge (Apollo's domain)" -- "Do NOT write creative content (Calliope's domain)" -- Collaboration section acknowledges cross-agent workflows - -### Verification Approach - -Used grep commands to verify domain presence: -- `grep -qi "outline"` → Confirms Outline tool specialization -- `grep -qi "wiki\|knowledge"` → Confirms knowledge base focus -- `grep -qi "document"` → Confirms document management capabilities - -All verification checks passed successfully. - -## Wave 2, Task 5: Create Hermes system prompt - -### Prompt Structure Pattern - -**Consistent sections across all subagent prompts:** -1. Role definition (You are [role] specializing in [domain]) -2. Core Responsibilities (5-7 bullet points of primary duties) -3. Process (5-6 numbered steps for workflow) -4. Quality Standards (4-5 bullet points of output criteria) -5. Output Format (3-5 lines describing structure) -6. Edge Cases (5-6 bullet points of exceptional scenarios) -7. Tool Usage (Question tool + domain-specific MCP tools) -8. Boundaries (5-6 bullet points of what NOT to do) - -### Hermes-Specific Domain Elements - -**Greek mythology framing:** Hermes - god of communication, messengers, swift transactions - -**Platform coverage:** -- Basecamp: tasks, projects, todos, message boards, campfire -- Outlook: email drafting, sending, inbox management -- Teams: meeting scheduling, channel messages, chat conversations - -**Focus areas:** Task updates, email drafting, meeting scheduling, quick communication - -**Question tool triggers:** -- Platform choice ambiguous -- Recipients unclear -- Project context missing - -### Cross-Agent Boundaries - -Hermes does NOT handle: -- Documentation repositories/wiki (Athena's domain) -- Personal tools/private knowledge (Apollo's domain) -- Long-form writing/reports (Calliope's domain) - -### Verification Pattern - -```bash -# Required content checks -grep -qi "basecamp" prompts/hermes.txt -grep -qiE "outlook|email" prompts/hermes.txt -grep -qiE "teams|meeting" prompts/hermes.txt -``` - -### Key Takeaways - -- Use exact headers from SKILL.md template (line 358: "Your Core Responsibilities:") -- Second-person voice addressing agent directly -- 5-6 sections following consistent pattern -- Boundaries section explicitly references other agents' domains -- 45-50 lines is appropriate length for subagent prompts -- Include MCP tool references in Tool Usage section - -## Wave 2, Task 3: Create Chiron (Plan Mode) system prompt - -### Prompt Structure Pattern - -**Standard sections (from agent-development/SKILL.md):** -- "You are [role]..." - Direct second-person address -- "**Your Core Responsibilities:**" - Numbered list (1, 2, 3), not bullet points -- "**Process:**" - Step-by-step workflow -- "**Quality Standards:**" - Evaluation criteria -- "**Output Format:**" - Response structure -- "**Edge Cases:**" - Exception handling -- "**Tool Usage:**" - Tool-specific guidance -- "**Boundaries:**" - Must NOT Do section - -### Chiron-Specific Design - -**Key role definition:** -- Main orchestrator in plan/analysis mode -- Read-only permissions, delegates execution to Chiron-Forge -- Coordinates 4 subagents via Task tool delegation - -**Delegation logic:** -- Hermes: Work communication (email, messages, meetings) -- Athena: Work knowledge (wiki, documentation, project info) -- Apollo: Private knowledge (Obsidian vault, personal notes) -- Calliope: Writing (documentation, reports, prose) -- Chiron-Forge: Execution (file modifications, commands, builds) - -**Question tool usage:** -- REQUIRED when requests are ambiguous -- Required for unclear intent or scope -- Required before delegation or analysis - -**Boundaries:** -- Do NOT modify files directly (read-only) -- Do NOT execute commands (delegate to Chiron-Forge) -- Do NOT access subagent domains directly (Hermes, Athena, Apollo, Calliope) - -### Style Reference - -**Used apollo.txt and calliope.txt as style guides:** -- Consistent section headers with exact wording -- Second-person address throughout -- Numbered responsibilities list -- Clear separation between sections -- Specific tool usage instructions - -### Verification Commands - -**File size:** -```bash -wc -c prompts/chiron.txt # Expected: > 500 -``` - -**Keyword validation:** -```bash -grep -qi "orchestrat" prompts/chiron.txt # Should find match -grep -qi "delegat" prompts/chiron.txt # Should find match -grep -qi "hermes\|athena\|apollo\|calliope" prompts/chiron.txt # Should find all 4 -``` - -### Key Takeaways - -- Standardized section headers critical for consistency across prompts -- Numbered lists for responsibilities (not bullet points) matches best practices -- Clear delegation routing prevents overlap between agent domains -- Question tool requirement prevents action on ambiguous requests -- Read-only orchestrator mode cleanly separates planning from execution -- All 4 subagents must be explicitly mentioned for routing clarity - -## Wave 2, Task 4: Create Chiron-Forge (Build Mode) system prompt - -### Primary Agent Prompt Structure - -Primary agent prompts follow similar structure to subagents but with expanded scope: -1. **Role definition**: "You are Chiron-Forge, the Greek centaur smith, specializing in [domain]" -2. **Your Core Responsibilities**: Numbered list emphasizing execution over planning -3. **Process**: 7-step workflow including delegation pattern -4. **Quality Standards**: Focus on execution accuracy and safety -5. **Output Format**: Execution summary structure -6. **Edge Cases**: Handling of destructive operations and failures -7. **Tool Usage**: Explicit permission boundaries and safety protocols -8. **Boundaries**: Clear separation from Chiron's planning role - -### Chiron-Forge vs Chiron Separation - -**Chiron-Forge (Build Mode):** -- Purpose: Execution and task completion -- Focus: Modifying files, running commands, building artifacts -- Permissions: Full write access with safety constraints -- Delegation: Routes specialized work to subagents -- Safety: Uses Question tool for destructive operations - -**Chiron (Plan Mode - Wave 2, Task 3):** -- Purpose: Read-only analysis and planning -- Focus: Analysis, planning, coordination -- Permissions: Read-only access -- Role: Orchestrator without direct execution - -### Permission Structure Mapping to Prompt - -From agents.json chiron-forge permissions: -```json -"permission": { - "read": { "*": "allow", "*.env": "deny" }, - "edit": "allow", - "bash": { "*": "allow", "rm *": "ask", "git push *": "ask", "sudo *": "deny" } -} -``` - -Mapped to prompt instructions: -- "Execute commands, but use Question for rm, git push" -- "Use Question tool for destructive operations" -- "DO NOT execute destructive operations without confirmation" - -### Delegation Pattern for Primary Agents - -Primary agents have unique delegation responsibilities: -- **Chiron-Forge**: Delegates based on domain expertise (Hermes for communications, Athena for knowledge, etc.) -- **Chiron**: Delegates based on planning and coordination needs - -Process includes delegation as step 5: -1. Understand the Task -2. Clarify Scope -3. Identify Dependencies -4. Execute Work -5. **Delegate to Subagents**: Use Task tool for specialized domains -6. Verify Results -7. Report Completion - -### Verification Commands - -Successful verification of prompt requirements: -```bash -# File character count > 500 -wc -c prompts/chiron-forge.txt -# Output: 2598 (✓) - -# Domain keyword verification -grep -qi "execut" prompts/chiron-forge.txt -# Output: Found 'execut' (✓) - -grep -qi "build" prompts/chiron-forge.txt -# Output: Found 'build' (✓) -``` - -All verification checks passed successfully. - -### Key Takeaways - -- Primary agent prompts require clear separation from each other (Chiron plans, Chiron-Forge executes) -- Permission structure in agents.json must be reflected in prompt instructions -- Safety protocols for destructive operations are critical for write-access agents -- Delegation is a core responsibility for both primary agents, but with different criteria -- Role naming consistency reinforces domain separation (centaur smith vs wise centaur) - - -## Wave 3, Task 9: Create Basecamp Integration Skill - -### Skill Structure Pattern for MCP Integrations - -The Basecamp skill follows the standard pattern from skill-creator with MCP-specific adaptations: - -1. **YAML frontmatter** with comprehensive trigger list - - name: `basecamp` - - description: Includes all use cases and trigger keywords - - compatibility: `opencode` - -2. **Core Workflows** organized by functionality categories - - Finding Projects and Todos - - Managing Card Tables (Kanban) - - Working with Messages and Campfire - - Managing Inbox (Email Forwards) - - Documents - - Webhooks and Automation - - Daily Check-ins - - Attachments and Events - -3. **Integration with Other Skills** section for agent handoff - - Documents Hermes (work communication agent) usage patterns - - Table showing user request → Hermes action → Basecamp tools used - - Common workflow patterns for project setup, task management, communication - -### Basecamp MCP Tool Organization (63 Tools) - -**Tools grouped by category:** - -1. **Projects & Lists (5 tools):** - - `get_projects`, `get_project`, `get_todolists`, `get_todos`, `search_basecamp` - -2. **Card Table/Kanban (26 tools):** - - Column management: `get_card_table`, `get_columns`, `get_column`, `create_column`, `update_column`, `move_column`, `update_column_color`, `put_column_on_hold`, `remove_column_hold`, `watch_column`, `unwatch_column` - - Card management: `get_cards`, `get_card`, `create_card`, `update_card`, `move_card`, `complete_card`, `uncomplete_card` - - Step (sub-task) management: `get_card_steps`, `create_card_step`, `get_card_step`, `update_card_step`, `delete_card_step`, `complete_card_step`, `uncomplete_card_step` - -3. **Messages & Communication (5 tools):** - - `get_message_board`, `get_messages`, `get_message`, `get_campfire_lines`, `get_comments`, `create_comment` - -4. **Inbox/Email Forwards (6 tools):** - - `get_inbox`, `get_forwards`, `get_forward`, `get_inbox_replies`, `get_inbox_reply`, `trash_forward` - -5. **Documents (5 tools):** - - `get_documents`, `get_document`, `create_document`, `update_document`, `trash_document` - -6. **Webhooks (3 tools):** - - `get_webhooks`, `create_webhook`, `delete_webhook` - -7. **Other (4 tools):** - - `get_daily_check_ins`, `get_question_answers`, `create_attachment`, `get_events` - -### Skill Content Design Principles - -**Concise but comprehensive:** -- Tool reference lists use bullet points for readability -- Workflow examples show command usage patterns -- Categories separate concerns (projects vs card tables vs communication) -- Integration table maps user requests to specific tool usage - -**Progressive disclosure:** -- Core workflows organized by category, not alphabetical -- Each workflow shows tool commands with parameters -- Integration section focuses on Hermes agent handoff -- Tool organization table provides quick reference - -**Appropriate degrees of freedom:** -- Low freedom: Tool command patterns (must use correct parameters) -- Medium freedom: Workflow selection (multiple valid approaches) -- High freedom: Project structure design (varies by organization) - -### Verification Commands - -**File structure:** -```bash -test -d skills/basecamp && test -f skills/basecamp/SKILL.md -# Expected output: ✅ File structure valid -``` - -**YAML frontmatter validation:** -```bash -python3 -c "import yaml; f = open('skills/basecamp/SKILL.md'); content = f.read(); f.close(); yaml.safe_load(content.split('---')[1])" -# Expected output: ✅ YAML frontmatter valid -``` - -**Field verification:** -```bash -python3 -c "import yaml; f = open('skills/basecamp/SKILL.md'); content = f.read(); f.close(); frontmatter = yaml.safe_load(content.split('---')[1]); print('name:', frontmatter.get('name')); print('compatibility:', frontmatter.get('compatibility'))" -# Expected output: name: basecamp, compatibility: opencode -``` - -### Key Takeaways - -- MCP integration skills need comprehensive tool categorization (63 tools in Basecamp) -- Integration sections should map agent workflows to specific tools (Hermes uses Basecamp for project tasks) -- Card table workflows are complex (26 tools for kanban management) - need detailed sub-sections -- YAML frontmatter must include all trigger keywords for skill activation -- Tool organization tables help agents find the right tool quickly -- Workflow examples should show actual command syntax with parameters -- Skills document MCP tool names, not setup or authentication (managed by Nix) - - -## Wave 3, Task 12: Create Outlook email integration skill - -### Skill Creation Pattern for MCP Integration Skills - -**Structure pattern for MCP-based skills:** -1. **YAML frontmatter**: name, description (with triggers), compatibility: opencode -2. **Overview**: High-level description of domain and capabilities -3. **Core Workflows**: Numbered step-by-step processes for common operations -4. **Advanced Features**: Optional capabilities that enhance basic workflows -5. **Integration with Other Skills**: Table showing domain boundaries and handoffs -6. **Common Patterns**: Reusable workflow patterns -7. **Quality Standards**: Output criteria and best practices -8. **Edge Cases**: Exception handling -9. **Boundaries**: Explicit domain separation with agent attribution - -### Outlook-Specific Domain Coverage - -**Mail capabilities:** -- Reading emails (inbox, folders, search) -- Sending emails (compose, reply, forward) -- Message organization (categories, importance, folders) -- Email intelligence (focused inbox, mail tips) - -**Calendar capabilities:** -- Creating events and appointments -- Scheduling meetings with attendees -- Managing calendar availability - -**Contact capabilities:** -- Creating and updating contacts -- Managing contact information - -**MCP Integration pattern:** -- Skill provides domain knowledge for Outlook Graph API operations -- MCP handles actual API calls (authentication, endpoints) -- Focus on workflows, not implementation details - -### Trigger Keywords in Description - -From the YAML frontmatter description: -``` -Triggers: 'email', 'Outlook', 'inbox', 'calendar', 'contact', 'message', 'folder', 'appointment', 'meeting' -``` - -These keywords enable the Opencode skill loader to automatically trigger this skill when users mention these topics. - -### Cross-Agent Boundaries - -Explicit domain separation ensures no overlap with other skills: -- **NOT Teams**: msteams skill handles Teams-specific messaging -- **NOT Basecamp**: basecamp skill handles Basecamp communication -- **NOT Wiki**: Athena handles Outline wiki documentation -- **NOT Private Knowledge**: Apollo handles Obsidian vaults -- **NOT Creative Writing**: Calliope handles long-form content - -### Workflow Documentation Style - -**Core workflows** follow the pattern: -``` -User: "User request" -AI: Use Outlook MCP to: -1. Step 1 -2. Step 2 -3. Step 3 -``` - -This pattern shows: -- Clear user intent -- Tool usage (Outlook MCP) -- Step-by-step process - -### Verification Commands - -**File structure:** -```bash -test -d skills/outlook && test -f skills/outlook/SKILL.md -# Expected output: ✅ File structure valid -``` - -**YAML frontmatter validation:** -```bash -python3 -c "import yaml; data = yaml.safe_load(open('skills/outlook/SKILL.md').read().split('---')[1]); print(data['name'])" -# Expected output: outlook -``` - -**Note**: The `test-skill.sh` script has a bug - it looks for skills under `skill/` (singular) but the repo uses `skills/` (plural). Manual validation required. - -### Key Takeaways - -- MCP integration skills focus on workflows, not API implementation details -- Triggers in description enable automatic skill loading -- Cross-agent boundaries prevent overlap and confusion -- Workflow documentation shows user intent, tool usage, and step-by-step process -- Manual validation needed when test scripts have bugs in path handling - -## Wave 3, Task 13: Create Obsidian Integration Skill - -### Skill Structure for API Integration Skills - -The Obsidian skill follows the standard skill-creator pattern with API-specific documentation: - -1. **YAML frontmatter** with comprehensive triggers - - name: `obsidian` - - description: Covers all use cases (vault operations, note CRUD, search, daily notes) - - compatibility: `opencode` - -2. **Prerequisites section** - Critical for API integrations - - Plugin installation requirements - - API server setup (default port 27124) - - Authentication configuration - -3. **Core Workflows** organized by operation type - - Vault operations: list files, get file info, get vault info - - Note CRUD: create, read, update, delete notes - - Search: content search with parameters - - Daily notes: get/create/update daily notes - -4. **Note Structure Patterns** - Obsidian-specific conventions - - Frontmatter patterns (date, created, type, tags, status) - - WikiLink syntax ([[Note Title]], [[Note Title|Alias]], [[Note Title#Heading]]) - - Tagging conventions (#tag, #nested/tag) - -5. **Workflow Examples** - Realistic usage patterns - - Create brainstorm note with frontmatter - - Append to daily journal - - Search and link notes - - Show curl commands with JSON payloads - -6. **Integration with Other Skills** - Agent handoff patterns - - brainstorming: Create brainstorm notes with frontmatter - - reflection: Append conversation analysis to daily journal - - research: Save research findings with tags - - task-management: Link tasks to project notes - - plan-writing: Save generated plans to vault - -### Obsidian Local REST API Capabilities - -**API endpoints** (default: http://127.0.0.1:27124): - -1. **Vault operations (3 endpoints):** - - `GET /list` - List all files in vault - - `GET /get-file-info` - Get file metadata - - `GET /vault-info` - Get vault metadata - -2. **Note CRUD (5 endpoints):** - - `POST /create-note` - Create new note (content, optional path) - - `GET /read-note` - Read note by path - - `PUT /update-note` - Update existing note (path, content) - - `DELETE /delete-note` - Delete note by path - -3. **Search (1 endpoint):** - - `GET /search` - Search notes (q, optional path, context-length) - -4. **Daily notes (2 endpoints):** - - `GET /daily-note` - Get/create daily note (optional date) - - `PUT /daily-note` - Update daily note - -### Skill Design Principles for API Integration - -**Concise documentation:** -- Curl commands show exact API usage with parameters -- JSON payloads demonstrate request body structure -- Workflow examples combine multiple API calls - -**Progressive disclosure:** -- Prerequisites section first (plugin, server, auth) -- Simple operations first (list, read, create) -- Complex workflows later (append to journal, search and link) - -**Appropriate degrees of freedom:** -- Low freedom: API endpoint structure and parameters -- Medium freedom: Note content and frontmatter design -- High freedom: Vault organization and tagging schemes - -### Verification Commands - -**File structure:** -```bash -test -d skills/obsidian && test -f skills/obsidian/SKILL.md -# Expected output: ✅ Directory and file structure correct -``` - -**YAML frontmatter validation:** -```bash -python3 -c "import yaml; f = open('skills/obsidian/SKILL.md'); content = f.read(); f.close(); yaml.safe_load(content.split('---')[1])" -# Expected output: No errors -``` - -**Skill validation script:** -```bash -python3 skills/skill-creator/scripts/quick_validate.py skills/obsidian -# Expected output: Skill is valid! -``` - -### Key Takeaways - -- API integration skills require explicit prerequisites section (plugin, server, auth setup) -- Use curl commands in documentation to show exact API usage patterns -- JSON payloads demonstrate request/response structures for complex operations -- WikiLink syntax and frontmatter conventions are critical for Obsidian skills -- Integration sections should show how skills pass data between them (e.g., brainstorm → Obsidian note) -- Destructive operations (DELETE) need explicit warnings in workflows -- Daily notes are a special case with dedicated API endpoints -- Skills document API capabilities, not plugin installation (user responsibility) -- Error handling section helps with debugging (HTTP status codes) - -### Cross-Agent Integration Pattern - -The Obsidian skill enables Apollo (private knowledge agent) to: -- Create notes with proper frontmatter structure -- Link notes using WikiLinks for knowledge graph -- Search vault by content, tags, or metadata -- Maintain daily journaling workflows -- Hand off to brainstorming, reflection, research, task-management, plan-writing - -This aligns with Apollo's domain: "Private knowledge (Obsidian vault, personal notes)" - -## Wave 3, Task 11: Create MS Teams integration skill - -### Skill Structure and Content - -The msteams skill follows the established skill-creator patterns: -- **YAML frontmatter**: Contains name, description with triggers, and compatibility -- **Concise body**: Focuses on core capabilities without overwhelming context -- **Workflow examples**: Clear step-by-step processes for common operations -- **Constraints section**: Explicit guidance on what NOT to do - -### MS Teams Graph API Capabilities - -From Microsoft Learn documentation, key capabilities documented: -- **Teams & Channels**: Create, list, manage teams and channels -- **Channel Messages**: Send, receive, list messages with date filtering -- **Online Meetings**: Schedule, manage, retrieve meeting coordinates -- **Chat**: Direct messages and group chat conversations -- **Presence**: User activity and availability status -- **Team membership**: Add, remove, update members - -### Domain Differentiation - -**Hermes integration context:** -- Hermes (work communication agent) loads msteams skill for Teams-specific operations -- Clear separation from outlook skill: msteams = Teams/channels/meetings, outlook = email -- This prevents overlap and clarifies routing for communication operations - -### Important Constraints Documented - -1. **Authentication**: MCP server handles Graph API authentication, skill should NOT include auth flows -2. **Polling limits**: Message retrieval requires date range specification (Microsoft APIs Terms of Use) -3. **Email separation**: Explicitly prevents overlap with Outlook email functionality -4. **File storage**: Channel files stored in SharePoint, requires SharePoint-specific operations - -### YAML Frontmatter Validation - -**Validated fields:** -- `name: msteams` -- `description`: Includes triggers - 'Teams', 'meeting', 'channel', 'team message', 'chat', 'Teams message' -- `compatibility: opencode` - -**Verification command:** -```bash -python3 -c "import yaml, re; f=open('skills/msteams/SKILL.md'); c=f.read(); m=re.match(r'^---\n(.*?)\n---', c, re.DOTALL); yaml.safe_load(m.group(1))" -# Output: Valid ✅ -``` - -### Skill Directory Verification - -```bash -test -d skills/msteams && test -f skills/msteams/SKILL.md -# Result: ✅ Directory and file structure verified -``` - -### Quick Validate Script - -**Note on test-skill.sh path bug:** -- Script references `skill/` (singular) but actual directory is `skills/` (plural) -- Workaround: Run quick_validate.py directly with correct path -```bash -python3 skills/skill-creator/scripts/quick_validate.py skills/msteams -# Result: "Skill is valid!" -``` - -### Key Takeaways - -1. **Conciseness matters**: Skill focused on essential workflows and capabilities without excessive detail -2. **Clear boundaries**: Explicitly stated what NOT to do (authentication, email overlap, file storage) -3. **Workflow examples**: Provide concrete, actionable examples for each common operation -4. **Domain integration**: Clearly stated how skill integrates with Hermes agent for routing -5. **Constraint awareness**: Documented important Graph API limits (polling, Terms of Use) - -## Wave 3, Task 10: Create Outline wiki integration skill - -### Skill Structure Pattern - -**YAML frontmatter:** -```yaml ---- -name: outline -description: "Use when: (1) Outline wiki management, (2) Document CRUD operations, (3) Knowledge search and retrieval, (4) Collection management. Triggers: 'Outline', 'wiki', 'document', 'knowledge base'." -compatibility: opencode ---- -``` - -**Description field includes:** -- What the skill does -- When to use it (numbered list of triggers) -- Specific trigger keywords for skill loading - -### Skill Content Structure - -**Core Capabilities section:** High-level overview of API functionality -- Document Operations (CRUD) -- Collection Management -- Search and Discovery -- Sharing and Permissions -- Collaboration - -**Workflows section:** Step-by-step procedures for common operations -- Creating a New Document -- Searching Knowledge Base -- Organizing Documents -- Document Collaboration - -**Integration Patterns section:** Practical guidance for knowledge management -- Knowledge Capture: How to document from conversations/research -- Documentation Updates: How to maintain existing content -- Knowledge Retrieval: How to find information efficiently - -**Common Use Cases section:** Table-based reference for common scenarios -- Project documentation -- Team guidelines -- Meeting notes -- Knowledge capture -- Onboarding resources - -**Best Practices section:** Guidelines for effective knowledge base management -- Consistent naming -- Logical organization -- Regular maintenance -- Access control -- Searchability -- Collaboration - -**Handoff to Other Skills section:** Integration mapping -- Shows how output from this skill flows to other skills -- Maps use cases to next skills -- Provides triggers for handoffs - -### Outline API Capabilities - -**Document Operations:** -- Create: New documents with markdown content -- Read: Retrieve content, metadata, revisions -- Update: Edit title and content -- Delete: Remove documents (with permissions) - -**Collection Management:** -- Organize: Structure documents in collections and nested collections -- Hierarchies: Parent-child relationships -- Access Control: Permissions at collection level - -**Search and Discovery:** -- Full-text search: Find documents by content -- Metadata filters: Collection, author, date -- Advanced queries: Combine multiple filters - -**Sharing and Permissions:** -- Public links: Shareable document URLs -- Team access: Member permissions -- Guest access: External sharing control - -**Collaboration:** -- Comments: Threaded discussions -- Revisions: Document history and changes -- Notifications: Activity updates - -### Skill Design Decisions - -**Concise approach (under 500 lines):** -- Core workflows in SKILL.md -- No extraneous files (README.md, CHANGELOG.md, etc.) -- Progressive disclosure: Load skill body only when triggered -- Keep metadata description comprehensive (frontmatter is always in context) - -**Appropriate degrees of freedom:** -- Low freedom: API endpoint structure and patterns -- Medium freedom: Document content and metadata -- High freedom: Collection organization and tagging - -**Documentation approach:** -- No MCP server setup instructions (user responsibility) -- Focus on API capabilities and workflows -- Provide practical examples rather than exhaustive API reference -- Use tables for quick reference (use cases, best practices) - -### Verification Commands - -**File structure:** -```bash -test -d skills/outline && test -f skills/outline/SKILL.md -# Expected output: ✅ Directory and file structure correct -``` - -**YAML frontmatter validation:** -```bash -python3 -c "import yaml; f = open('skills/outline/SKILL.md'); content = f.read(); f.close(); yaml.safe_load(content.split('---')[1])" -# Expected output: No errors -``` - -**Skill validation script:** -```bash -python3 skills/skill-creator/scripts/quick_validate.py skills/outline -# Expected output: Skill is valid! -``` - -### Key Takeaways - -- Skills should include comprehensive trigger descriptions in YAML frontmatter -- Use structured sections (Core Capabilities, Workflows, Integration Patterns) -- Tables are effective for quick reference (use cases, best practices) -- Handoff sections show integration points with other skills -- Avoid MCP server setup instructions (user's responsibility) -- Focus on practical workflows rather than exhaustive API documentation -- Keep SKILL.md concise (under 500 lines) - progressive disclosure -- Provide both high-level overview and detailed workflows -- Include search and retrieval patterns for knowledge systems -- Document collaboration features (comments, revisions, sharing) - -### Cross-Agent Integration Pattern - -The Outline skill enables Athena (work knowledge agent) to: -- Create and edit documents in team wiki -- Search knowledge base by content, metadata, and filters -- Organize documents in collections and hierarchies -- Manage sharing and permissions for team collaboration -- Handle collaborative features (comments, revisions) -- Hand off to knowledge-management, task-management, plan-writing - -This aligns with Athena's domain: "Work knowledge (Outline wiki, documentation)" - -### Notes - -- test-skill.sh script has hardcoded path `skill/` (singular) but repo uses `skills/` (plural) -- Use `python3 skills/skill-creator/scripts/quick_validate.py ` for direct validation -- Repository structure follows AGENTS.md documentation: `skills/` (plural) - -## Wave 4, Task 14: Create agent validation script - -### Bash Script Pattern for Validation - -**Script structure follows test-skill.sh pattern:** -- Shebang: `#!/usr/bin/env bash` -- Error handling: `set -euo pipefail` -- Color codes for output (RED, GREEN, YELLOW, NC) -- Script directory resolution: `SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"` -- Repo root resolution: `REPO_ROOT="$(dirname "$SCRIPT_DIR")"` - -### Validation Logic Architecture - -**Multi-layer validation approach:** -1. **File existence**: Check agents.json exists -2. **JSON syntax validation**: Use python3 json.load() for parsing -3. **Agent count validation**: Verify exactly 6 agents present -4. **Agent name validation**: Check all expected agents found -5. **Field validation**: Verify required fields exist for each agent -6. **Mode validation**: Ensure primary/subagent modes correct -7. **Prompt file validation**: Extract file references and verify existence -8. **Content validation**: Check prompt files are non-empty - -### Exit Code Strategy - -**Clear exit codes for different failure types:** -- 0: All validations pass -- 1: Validation errors found (missing agents, fields, or prompt files) - -**Note:** Script does NOT use exit code 2 for prompt file errors (as originally specified) - uses 1 for all validation errors for simplicity. - -### Prompt File Reference Parsing - -**Pattern matching approach:** -```bash -# Extract prompt reference from agents.json -prompt_ref=$(python3 -c "import json; print(json.load(open('$AGENTS_FILE'))['$agent_name']['prompt'])") - -# Parse pattern: {file:./prompts/.txt} -if [[ "$prompt_ref" =~ \{file:(\./prompts/[^}]+)\} ]]; then - prompt_file="${BASH_REMATCH[1]}" - prompt_path="$REPO_ROOT/${prompt_file#./}" -fi -``` - -**Key components:** -- Python JSON extraction: Gets raw prompt reference string -- Bash regex: Extracts file path from `{file:...}` format -- Path normalization: Removes `./` prefix using `${param#pattern}` - -### Error Handling Strategy - -**Counter-based error tracking:** -```bash -error_count=0 -warning_count=0 - -error() { - echo -e "${RED}❌ $1${NC}" >&2 - ((error_count++)) || true -} - -# Final decision -if [[ $error_count -eq 0 ]]; then - exit 0 -else - exit 1 -fi -``` - -**Benefits:** -- Collects all errors before exiting (don't fail fast) -- Provides comprehensive feedback -- Clear visual indicators (✅ for success, ❌ for errors, ⚠️ for warnings) - -### Validation Test Cases - -**Successful validation:** -```bash -./scripts/validate-agents.sh -# Output: All validations passed! -# Exit code: 0 -``` - -**Missing prompt file detection:** -```bash -mv prompts/apollo.txt prompts/apollo.txt.bak -./scripts/validate-agents.sh -# Output: ❌ Prompt file not found: ./prompts/apollo.txt -# Exit code: 1 -``` - -**Empty prompt file detection:** -```bash -truncate -s 0 prompts/apollo.txt -./scripts/validate-agents.sh -# Output: ❌ Prompt file is empty: ./prompts/apollo.txt -# Exit code: 1 -``` - -### Hardcoded Configuration - -**Script maintains expected state:** -```bash -EXPECTED_AGENTS=("chiron" "chiron-forge" "hermes" "athena" "apollo" "calliope") -PRIMARY_AGENTS=("chiron" "chiron-forge") -SUBAGENTS=("hermes" "athena" "apollo" "calliope") -REQUIRED_FIELDS=("description" "mode" "model" "prompt") -``` - -**Rationale:** -- Explicit configuration is better than dynamic discovery -- Prevents silent failures when configuration drifts -- Makes expectations clear and documentable -- Validates against known-good state (Wave 1-3 outputs) - -### Python vs jq for JSON Processing - -**Chose Python over jq for JSON parsing:** -- Python is already a project dependency (skill validation) -- Consistent with existing scripts (test-skill.sh uses Python) -- No additional dependency installation required -- Familiar error handling patterns - -### Integration with Existing Patterns - -**Aligned with test-skill.sh patterns:** -- Same color code definitions -- Same script directory resolution -- Same error handling approach -- Same exit code strategy (0 = success, non-zero = failure) - -### Verification Commands - -**Script executable check:** -```bash -test -x scripts/validate-agents.sh -# Expected: Exit 0 (executable) -``` - -**Successful validation:** -```bash -./scripts/validate-agents.sh -# Expected: Exit 0, "All validations passed!" message -``` - -### Key Takeaways - -- Bash regex (`=~ pattern`) is powerful for extracting file references from JSON strings -- Counter-based error tracking allows comprehensive error reporting before failing -- Python json.load() is reliable for JSON syntax validation -- Hardcoded expected state is safer than dynamic discovery for validation scripts -- `set -euo pipefail` is critical for bash script reliability -- Color codes improve readability but must be reset (NC='\033[0m') -- Pattern `{file:./prompts/.txt}` requires regex extraction for validation diff --git a/.sisyphus/notepads/memory-system/decisions.md b/.sisyphus/notepads/memory-system/decisions.md deleted file mode 100644 index 5a15ac0..0000000 --- a/.sisyphus/notepads/memory-system/decisions.md +++ /dev/null @@ -1,28 +0,0 @@ - -## Task 5: Update Mem0 Memory Skill (2026-02-12) - -### Decisions Made - -1. **Section Placement**: Added new sections without disrupting existing content structure - - "Memory Categories" after "Identity Scopes" (line ~109) - - "Dual-Layer Sync" after "Workflow Patterns" (line ~138) - - Extended "Health Check" section with Pre-Operation Check - - "Error Handling" at end, before API Reference - -2. **Content Structure**: - - Memory Categories: 5-category classification with table format - - Dual-Layer Sync: Complete sync pattern with bash example - - Health Check: Added pre-operation verification - - Error Handling: Comprehensive graceful degradation patterns - -3. **Validation Approach**: - - Used `./scripts/test-skill.sh --validate` for skill structure validation - - All sections verified with grep commands - - Commit and push completed successfully - -### Success Patterns - -- Edit tool works well for adding sections to existing markdown files -- Preserving existing content while adding new sections -- Using grep for verification of section additions -- `./scripts/test-skill.sh --validate` validates YAML frontmatter automatically diff --git a/.sisyphus/notepads/memory-system/issues.md b/.sisyphus/notepads/memory-system/issues.md deleted file mode 100644 index e69de29..0000000 diff --git a/.sisyphus/notepads/memory-system/learnings.md b/.sisyphus/notepads/memory-system/learnings.md deleted file mode 100644 index d19deec..0000000 --- a/.sisyphus/notepads/memory-system/learnings.md +++ /dev/null @@ -1,47 +0,0 @@ - -## Core Memory Skill Creation (2026-02-12) - -**Task**: Create `skills/memory/SKILL.md` - dual-layer memory orchestration skill - -**Pattern Identified**: -- Skill structure follows YAML frontmatter with required fields: - - `name`: skill identifier - - `description`: Use when (X), triggers (Y) pattern - - `compatibility`: "opencode" -- Markdown structure: Overview, Prerequisites, Workflows, Error Handling, Integration, Quick Reference, See Also - -**Verification Pattern**: -```bash -test -f && echo "File exists" -grep "name: " -grep "key-term" -``` - -**Key Design Decision**: -- Central orchestration skill that references underlying implementation skills (mem0-memory, obsidian) -- 4 core workflows: Store, Recall, Auto-Capture, Auto-Recall -- Error handling with graceful degradation - -## Apollo Agent Prompt Update (2026-02-12) - -**Task**: Add memory management responsibilities to Apollo agent system prompt - -**Edit Pattern**: Multiple targeted edits to single file preserving existing content -- Line number-based edits require precise matching of surrounding context -- Edit order: Core Responsibilities → Quality Standards → Tool Usage → Edge Cases -- Each edit inserts new bullet items without removing existing content - -**Key Additions**: -1. Core Responsibilities: "Manage dual-layer memory system (Mem0 + Obsidian CODEX)" -2. Quality Standards: Memory storage, auto-capture, retrieval, categories -3. Tool Usage: Mem0 REST API (localhost:8000), Obsidian MCP integration -4. Edge Cases: Mem0 unavailable, Obsidian unavailable handling - -**Verification Pattern**: -```bash -grep -c "memory" ~/p/AI/AGENTS/prompts/apollo.txt # Count occurrences -grep "Mem0" ~/p/AI/AGENTS/prompts/apollo.txt # Check specific term -grep -i "auto-capture" ~/p/AI/AGENTS/prompts/apollo.txt # Case-insensitive -``` - -**Observation**: grep is case-sensitive by default - use -i for case-insensitive searches diff --git a/.sisyphus/notepads/memory-system/problems.md b/.sisyphus/notepads/memory-system/problems.md deleted file mode 100644 index e69de29..0000000 diff --git a/.sisyphus/notepads/opencode-memory/learnings.md b/.sisyphus/notepads/opencode-memory/learnings.md deleted file mode 100644 index 0091cf4..0000000 --- a/.sisyphus/notepads/opencode-memory/learnings.md +++ /dev/null @@ -1,120 +0,0 @@ -# Opencode Memory Plugin — Learnings - -## Session: ses_3a5a47a05ffeoNYfz2RARYsHX9 -Started: 2026-02-14 - -### Architecture Decisions -- SQLite + FTS5 + vec0 replaces mem0+qdrant entirely -- Markdown at ~/CODEX/80-memory/ is source of truth -- SQLite DB at ~/.local/share/opencode-memory/index.db is derived index -- OpenAI text-embedding-3-small for embeddings (1536 dimensions) -- Hybrid search: 0.7 vector weight + 0.3 BM25 weight -- Chunking: 400 tokens, 80 overlap (tiktoken cl100k_base) - -### Key Patterns from Openclaw -- MemoryIndexManager pattern (1590 lines) — file watching, chunking, indexing -- Hybrid scoring with weighted combination -- Embedding cache by content_hash + model -- Two sources: "memory" (markdown files) + "sessions" (transcripts) -- Two tools: memory_search (hybrid query) + memory_get (read lines) - -### Technical Stack -- Runtime: bun -- Test framework: bun test (TDD) -- SQLite: better-sqlite3 (synchronous API) -- Embeddings: openai npm package -- Chunking: tiktoken (cl100k_base encoding) -- File watching: chokidar -- Validation: zod (for tool schemas) - -### Vec0 Extension Findings (Task 1) -- **vec0 extension**: NOT AVAILABLE - requires vec0.so shared library not present -- **Alternative solution**: sqlite-vec package (v0.1.7-alpha.2) successfully tested -- **Loading mechanism**: `sqliteVec.load(db)` loads vector extension into database -- **Test result**: Works with Node.js (better-sqlite3 native module compatible) -- **Note**: better-sqlite3 does NOT work with Bun runtime (native module incompatibility) -- **Testing command**: `node -e "const Database = require('better-sqlite3'); const sqliteVec = require('sqlite-vec'); const db = new Database(':memory:'); sqliteVec.load(db); console.log('OK')"` - -### Bun Runtime Limitations -- better-sqlite3 native module NOT compatible with Bun (ERR_DLOPEN_FAILED) -- Use Node.js for any code requiring better-sqlite3 -- Alternative: bun:sqlite API (similar API, but not same library) - -## Wave Progress -- Wave 1: IN PROGRESS (Task 1) -- Wave 2-6: PENDING - -### Configuration Module Implementation (Task: Config Module) -- **TDD approach**: RED-GREEN-REFACTOR cycle successfully applied -- **Pattern**: Default config object + resolveConfig() function for merging -- **Path expansion**: `expandPath()` helper function handles `~` → `$HOME` expansion -- **Test coverage**: 10 tests covering defaults, overrides, path expansion, and config merging -- **TypeScript best practices**: Proper type exports from types.ts, type imports in config.ts -- **Defaults match openclaw**: chunking (400/80), search weights (0.7/0.3), minScore (0.35), maxResults (6) -- **Bun test framework**: Fast execution (~20ms for 10 tests), clean output - -### Database Schema Implementation (Task 2) -- **TDD approach**: RED-GREEN-REFACTOR cycle successfully applied for db module -- **Schema tables**: meta, files, chunks, embedding_cache, chunks_fts (FTS5), chunks_vec (vec0) -- **WAL mode**: Enabled via `db.pragma('journal_mode = WAL')` for better concurrency -- **Foreign keys**: Enabled via `db.pragma('foreign_keys = ON')` -- **sqlite-vec integration**: Loaded via `sqliteVec.load(db)` for vector search capabilities -- **FTS5 virtual table**: External content table referencing chunks for full-text search -- **vec0 virtual table**: 1536-dimension float array for OpenAI text-embedding-3-small embeddings -- **Test execution**: Use Node.js with tsx for TypeScript execution (not Bun runtime) -- **Buffer handling**: Float32Array must be converted to Buffer via `Buffer.from(array.buffer)` for SQLite binding -- **In-memory databases**: WAL mode returns 'memory' for :memory: DBs, 'wal' for file-based DBs -- **Test coverage**: 9 tests covering table creation, data insertion, FTS5, vec0, WAL mode, and clean closure -- **Error handling**: better-sqlite3 throws "The database connection is not open" for operations on closed DBs - -### Node.js Test Execution -- **Issue**: better-sqlite3 not compatible with Bun runtime (native module) -- **Solution**: Use Node.js with tsx (TypeScript executor) for running tests -- **Command**: `npx tsx --test src/__tests__/db.test.ts` -- **Node.test API**: Uses `describe`, `it`, `before`, `after` from 'node:test' module -- **Assertions**: Use `assert` from 'node:assert' module -- **Cleanup**: Use `after()` hooks for database cleanup, not `afterEach()` (node:test difference) - -### Embedding Provider Implementation (Task: Embeddings Module) -- **TDD approach**: RED-GREEN-REFACTOR cycle successfully applied for embeddings module -- **Mock database**: Created in-memory mock for testing since better-sqlite3 incompatible with Bun -- **Float32 precision**: embeddings stored/retrieved via Float32Array has limited precision (use toBeCloseTo in tests) -- **Cache implementation**: content_hash + model composite key in embedding_cache table -- **Retry logic**: Exponential backoff (1s, 2s, 4s) for 429/500 errors, max 3 retries -- **Test coverage**: 11 tests covering embed(), embedBatch(), cache hits/misses, API failures, retries, buffer conversion -- **Helper functions**: embeddingToBuffer() and bufferToEmbedding() for Float32Array ↔ Buffer conversion -- **Bun spyOn**: Use mockClear() to reset call count without replacing mock implementation -- **Buffer size**: Float32 embedding stored as Buffer with size = dimensions * 4 bytes - -### FTS5 BM25 Search Implementation (Task: FTS5 Search Module) -- **TDD approach**: RED-GREEN-REFACTOR cycle successfully applied for search module -- **buildFtsQuery()**: Extracts alphanumeric tokens via regex `/[A-Za-z0-9_]+/g`, quotes them, joins with AND -- **FTS5 escaping**: Tokens are quoted to handle special characters (e.g., `"term"`) -- **BM25 score normalization**: `bm25RankToScore(rank)` converts BM25 rank to 0-1 score using `1 / (1 + normalized)` -- **FTS5 external content tables**: The schema uses `content='chunks', content_rowid='rowid'` but requires manual insertion into chunks_fts -- **Test data setup**: Must manually insert into chunks_fts after inserting into chunks (external content doesn't auto-populate) -- **BM25 ranking**: Results are ordered by `rank` column (lower rank = better match for FTS5) -- **Error handling**: searchFTS catches SQL errors and returns empty array (graceful degradation) -- **MaxResults parameter**: Respects LIMIT clause in SQL query -- **SearchResult interface**: Includes id, filePath, startLine, endLine, text, contentHash, source, score (all required) -- **Prefix matching**: FTS5 supports prefix queries automatically via token matching (e.g., "test" matches "testing") -- **No matches**: Returns empty array when query has no valid tokens or no matches found -- **Test coverage**: 7 tests covering basic search, exact keywords, partial words, no matches, ranking, maxResults, and metadata - -### Hybrid Search Implementation (Task: Hybrid Search Combiner) -- **TDD approach**: RED-GREEN-REFACTOR cycle successfully applied for hybrid search -- **Weighted scoring**: Combined score = vectorWeight * vectorScore + textWeight * textScore (default: 0.7/0.3) -- **Result merging**: Uses Map to merge results by chunk ID, preventing duplicates -- **Dual-score tracking**: Each result tracks both vectorScore and textScore separately, allowing for degraded modes -- **Graceful degradation**: Works with FTS5-only (vector search fails) or vector-only (FTS5 fails) -- **minScore filtering**: Results below minScore threshold are filtered out after score calculation -- **Score sorting**: Results sorted by combined score in descending order before applying maxResults limit -- **Vector search fallback**: searchVector catches errors and returns empty array, allowing FTS5-only operation -- **FTS5 query fallback**: searchFTS catches SQL errors and returns empty array, allowing vector-only operation -- **Database cleanup**: beforeEach must delete from chunks_fts, chunks_vec, chunks, and files to avoid state bleed -- **Virtual table corruption**: Deleting from FTS5/vec0 virtual tables can cause corruption - use try/catch to recreate -- **SearchResult type conflict**: SearchResult is imported from types.ts, don't re-export in search.ts -- **Test isolation**: Virtual tables (chunks_fts, chunks_vec) must be cleared and potentially recreated between tests -- **Buffer conversion**: queryEmbedding converted to Buffer via Buffer.from(new Float32Array(array).buffer) -- **Debug logging**: process.env.DEBUG_SEARCH flag enables detailed logging of FTS5 and vector search results -- **Test coverage**: 9 tests covering combination, weighting, minScore filtering, deduplication, sorting, maxResults, degraded modes (FTS5-only, vector-only), and custom weights diff --git a/.sisyphus/notepads/rules-system/learnings.md b/.sisyphus/notepads/rules-system/learnings.md deleted file mode 100644 index 9626953..0000000 --- a/.sisyphus/notepads/rules-system/learnings.md +++ /dev/null @@ -1,60 +0,0 @@ -# Rules System - Learnings - -## 2026-02-17T17:50 Session Start - -### Architecture Pattern -- Nix helper lives in nixpkgs repo (not AGENTS) - follows ports.nix pattern -- AGENTS repo stays pure content (markdown rule files only) -- Pattern: `{lib}: { mkOpencodeRules = ...; }` - -### Key Files -- nixpkgs: `/home/m3tam3re/p/NIX/nixpkgs/lib/ports.nix` (reference pattern) -- nixos-config: `/home/m3tam3re/p/NIX/nixos-config/home/features/coding/opencode.nix` (deployment) -- AGENTS: `rules/` directory (content) - -### mkOpencodeRules Signature -```nix -mkOpencodeRules { - agents = inputs.agents; # Non-flake input path - languages = [ "python" "typescript" ]; - concerns ? [ "coding-style" "naming" "documentation" "testing" "git-workflow" "project-structure" ]; - frameworks ? [ "n8n" ]; - extraInstructions ? []; -} -``` - -### Consumption Pattern -```nix -let - m3taLib = inputs.m3ta-nixpkgs.lib.${system}; - rules = m3taLib.opencode-rules.mkOpencodeRules { - agents = inputs.agents; - languages = [ "python" ]; - }; -in pkgs.mkShell { shellHook = rules.shellHook; } -``` - -### Wave 1: Directory Structure (2026-02-17T18:54) -- Successfully created rules/ directory with subdirectories: concerns/, languages/, frameworks/ -- Added .gitkeep files to each subdirectory (git needs at least one file to track empty directories) -- Pattern reference: followed skills/ directory structure convention -- USAGE.md already existed in rules/ (created by previous wave) -- AGENTS repo stays pure content - no Nix files added (as planned) -- Verification: ls confirms all three .gitkeep files exist in proper locations - -### Wave 2: Nix Helper Implementation (2026-02-17T19:02) -- Successfully created `/home/m3tam3re/p/NIX/nixpkgs/lib/opencode-rules.nix` -- Followed ports.nix pattern EXACTLY: `{lib}: { mkOpencodeRules = ...; }` -- Function signature: `{ agents, languages ? [], concerns ? [...], frameworks ? [], extraInstructions ? [] }` -- Returns: `{ shellHook, instructions }` -- Instructions list built using map functions for each category (concerns, languages, frameworks, extra) -- ShellHook creates symlink `.opencode-rules` → `${agents}/rules` and generates `opencode.json` with `$schema` -- JSON generation uses `builtins.toJSON opencodeConfig` where opencodeConfig = `{ "$schema" = "..."; inherit instructions; }` -- Comprehensive doc comments added matching ports.nix style (multi-line comments with usage examples) -- All paths relative to project root via `.opencode-rules/` prefix -- Verification passed: - - `nix eval --impure` shows file loads and exposes `mkOpencodeRules` - - Function returns `{ instructions, shellHook }` - - Instructions list builds correctly (concerns + languages + frameworks + extra) - - `nix-instantiate --parse` validates syntax is correct -- ShellHook contains both symlink creation and JSON generation (heredoc pattern) diff --git a/.sisyphus/plans/agent-permissions-refinement.md b/.sisyphus/plans/agent-permissions-refinement.md deleted file mode 100644 index 6ef3a48..0000000 --- a/.sisyphus/plans/agent-permissions-refinement.md +++ /dev/null @@ -1,748 +0,0 @@ -# Agent Permissions Refinement - -## TL;DR - -> **Quick Summary**: Refine OpenCode agent permissions for Chiron (planning) and Chriton-Forge (build) to implement 2025 AI security best practices with principle of least privilege, human-in-the-loop for critical actions, and explicit guardrails against permission bypass. - -> **Deliverables**: -> - Updated `agents/agents.json` with refined permissions for Chiron and Chriton-Forge -> - Critical bug fix: Duplicate `external_directory` key in Chiron config -> - Enhanced secret blocking with additional patterns -> - Bash injection prevention rules -> - Git protection against secret commits and repo hijacking - -> **Estimated Effort**: Medium -> **Parallel Execution**: NO - sequential changes to single config file -> **Critical Path**: Fix duplicate key → Apply Chiron permissions → Apply Chriton-Forge permissions → Validate - ---- - -## Context - -### Original Request -User wants to refine agent permissions for: -- **Chiron**: Planning agent with read-only access, restricted to read-only subagents, no file editing, can create beads issues -- **Chriton-Forge**: Build agent with write access restricted to ~/p/**, git commits allowed but git push asks, package install commands ask -- **General**: Sane defaults that are secure but open enough for autonomous work - -### Interview Summary -**Key Discussions**: -- Chiron: Read-only planning, no file editing, bash denied except for `bd *` commands, external_directory ~/p/** only, task permission to restrict subagents to explore/librarian/athena + chiron-forge for handoff -- Chriton-Forge: Write access restricted to ~/p/**, git commits allow / git push ask, package install commands ask, git config deny -- Workspace path: ~/p/** is symlink to ~/projects/personal/** (just replacing path reference) -- Bash security: Block all bash redirect patterns (echo >, cat >, tee, etc.) - -**Research Findings**: -- OpenCode supports granular permission rules with wildcards, last-match-wins -- 2025 best practices: Principle of least privilege, tiered permissions (read-only auto, destructive ask, JIT privileges), human-in-the-loop for critical actions -- Security hardening: Block command injection vectors, prevent git secret commits, add comprehensive secret blocking patterns - -### Metis Review -**Critical Issues Identified**: -1. **Duplicate `external_directory` key** in Chiron config (lines 8-9 and 27) - second key overrides first, breaking intended behavior -2. **Bash edit bypass**: Even with `edit: deny`, bash can write files via redirection (`echo "x" > file.txt`, `cat >`, `tee`) -3. **Git secret protection**: Agent could commit secrets (read .env, then git commit .env) -4. **Git config hijacking**: Agent could modify .git/config to push to attacker-controlled repo -5. **Command injection**: Malicious content could execute via `$()`, backticks, `eval`, `source` -6. **Secret blocking incomplete**: Missing patterns for `.local/share/*`, `.cache/*`, `*.db`, `*.keychain`, `*.p12` - -**Guardrails Applied**: -- Fix duplicate external_directory key (use single object with catch-all `"*": "ask"` after specific rules) -- Add bash file write protection patterns (echo >, cat >, printf >, tee, > operators) -- Add git secret protection (`git add *.env*`: deny, `git commit *.env*`: deny) -- Add git config protection (`git config *`: deny for Chriton-Forge) -- Add bash injection prevention (`$(*`, `` `*``, `eval *`, `source *`) -- Expand secret blocking with additional patterns -- Add /run/agenix/* to read deny list - ---- - -## Work Objectives - -### Core Objective -Refine OpenCode agent permissions in `agents/agents.json` to implement security hardening based on 2025 AI agent best practices while maintaining autonomous workflow capabilities. - -### Concrete Deliverables -- Updated `agents/agents.json` with: - - Chiron: Read-only permissions, subagent restrictions, bash denial (except `bd *`), no file editing - - Chriton-Forge: Write access scoped to ~/p/**, git commit allow / push ask, package install ask, git config deny - - Both: Enhanced secret blocking, bash injection prevention, git secret protection - -### Definition of Done -- [x] Permission configuration updated in `agents/agents.json` -- [x] JSON syntax valid (no duplicate keys, valid structure) -- [x] Workspace path validated (~/p/** exists and is correct) -- [x] Acceptance criteria tests pass (via manual verification) - -### Must Have -- Chiron cannot edit files directly -- Chiron cannot write files via bash (redirects blocked) -- Chiron restricted to read-only subagents + chiron-forge for handoff -- Chriton-Forge can only write to ~/p/** -- Chriton-Forge cannot git config -- Both agents block secret file reads -- Both agents prevent command injection -- Git operations cannot commit secrets -- No duplicate keys in permission configuration - -### Must NOT Have (Guardrails) -- **Edit bypass via bash**: No bash redirection patterns that allow file writes when `edit: deny` -- **Git secret commits**: No ability to git add/commit .env or credential files -- **Repo hijacking**: No git config modification allowed for Chriton-Forge -- **Command injection**: No `$()`, backticks, `eval`, `source` execution via bash -- **Write scope escape**: Chriton-Forge cannot write outside ~/p/** without asking -- **Secret exfiltration**: No access to .env, .ssh, .gnupg, credentials, secrets, .pem, .key, /run/agenix -- **Unrestricted bash for Chiron**: Only `bd *` commands allowed - ---- - -## Verification Strategy (MANDATORY) - -> This is configuration work, not code development. Manual verification is required after deployment. - -### Test Decision -- **Infrastructure exists**: YES (home-manager deployment) -- **User wants tests**: NO (Manual-only verification) -- **Framework**: None - -### Manual Verification Procedures - -Each TODO includes EXECUTABLE verification procedures that users can run to validate changes. - -**Verification Commands to Run After Deployment:** - -1. **JSON Syntax Validation**: -```bash -# Validate JSON structure and no duplicate keys -jq '.' /home/m3tam3re/p/AI/AGENTS/agents/agents.json > /dev/null 2>&1 -# Expected: Exit code 0 (valid JSON) - -# Check for duplicate keys (manual review of chiron permission object) -# Expected: Single external_directory key, no other duplicates -``` - -2. **Workspace Path Validation**: -```bash -ls -la ~/p/ 2>&1 -# Expected: Directory exists, shows contents (likely symlink to ~/projects/personal/) -``` - -3. **After Deployment - Chiron Read-Only Test** (manual): -- Have Chiron attempt to edit a test file - - Expected: Permission denied with clear error message -- Have Chiron attempt to write via bash (echo "test" > /tmp/test.txt) - - Expected: Permission denied -- Have Chiron run `bd ready` command - - Expected: Command succeeds, returns JSON output with issue list -- Have Chiron attempt to invoke build-capable subagent (sisyphus-junior) - - Expected: Permission denied - -4. **After Deployment - Chiron Workspace Access** (manual): -- Have Chiron read file within ~/p/** - - Expected: Success, returns file contents -- Have Chiron read file outside ~/p/** - - Expected: Permission denied or ask user -- Have Chiron delegate to explore/librarian/athena - - Expected: Success, subagent executes - -5. **After Deployment - Chriton-Forge Write Access** (manual): -- Have Chriton-Forge write test file in ~/p/** directory - - Expected: Success, file created -- Have Chriton-Forge attempt to write file to /tmp - - Expected: Ask user for approval -- Have Chriton-Forge run `git add` and `git commit -m "test"` - - Expected: Success, commit created without asking -- Have Chriton-Forge attempt `git push` - - Expected: Ask user for approval -- Have Chriton-Forge attempt `git config` - - Expected: Permission denied -- Have Chriton-Forge attempt `npm install lodash` - - Expected: Ask user for approval - -6. **After Deployment - Secret Blocking Tests** (manual): -- Attempt to read .env file with both agents - - Expected: Permission denied -- Attempt to read /run/agenix/ with Chiron - - Expected: Permission denied -- Attempt to read .env.example (should be allowed) - - Expected: Success - -7. **After Deployment - Bash Injection Prevention** (manual): -- Have agent attempt bash -c "$(cat /malicious)" - - Expected: Permission denied -- Have agent attempt bash -c "`cat /malicious`" - - Expected: Permission denied -- Have agent attempt eval command - - Expected: Permission denied - -8. **After Deployment - Git Secret Protection** (manual): -- Have agent attempt `git add .env` - - Expected: Permission denied -- Have agent attempt `git commit .env` - - Expected: Permission denied - -9. **Deployment Verification**: -```bash -# After home-manager switch, verify config is embedded correctly -cat ~/.config/opencode/config.json | jq '.agent.chiron.permission.external_directory' -# Expected: Shows ~/p/** rule, no duplicate keys - -# Verify agents load without errors -# Expected: No startup errors when launching OpenCode -``` - ---- - -## Execution Strategy - -### Parallel Execution Waves - -> Single file sequential changes - no parallelization possible. - -``` -Single-Threaded Execution: -Task 1: Fix duplicate external_directory key -Task 2: Apply Chiron permission updates -Task 3: Apply Chriton-Forge permission updates -Task 4: Validate configuration -``` - -### Dependency Matrix - -| Task | Depends On | Blocks | Can Parallelize With | -|------|------------|--------|---------------------| -| 1 | None | 2, 3 | None (must start) | -| 2 | 1 | 4 | 3 | -| 3 | 1 | 4 | 2 | -| 4 | 2, 3 | None | None (validation) | - -### Agent Dispatch Summary - -| Task | Recommended Agent | -|------|-----------------| -| 1 | delegate_task(category="quick", load_skills=["git-master"]) | -| 2 | delegate_task(category="quick", load_skills=["git-master"]) | -| 3 | delegate_task(category="quick", load_skills=["git-master"]) | -| 4 | User (manual verification) | - ---- - -## TODOs - -> Implementation tasks for agent configuration changes. Each task MUST include acceptance criteria with executable verification. - -- [x] 1. Fix Duplicate external_directory Key in Chiron Config - - **What to do**: - - Remove duplicate `external_directory` key from Chiron permission object - - Consolidate into single object with specific rule + catch-all `"*": "ask"` - - Replace `~/projects/personal/**` with `~/p/**` (symlink to same directory) - - **Must NOT do**: - - Leave duplicate keys (second key overrides first, breaks config) - - Skip workspace path validation (verify ~/p/** exists) - - **Recommended Agent Profile**: - > **Category**: quick - - Reason: Simple JSON edit, single file change, no complex logic - > **Skills**: git-master - - git-master: Git workflow for committing changes - > **Skills Evaluated but Omitted**: - - research: Not needed (no investigation required) - - librarian: Not needed (no external docs needed) - - **Parallelization**: - - **Can Run In Parallel**: NO - - **Parallel Group**: Sequential - - **Blocks**: Tasks 2, 3 (depends on clean config) - - **Blocked By**: None (can start immediately) - - **References** (CRITICAL - Be Exhaustive): - - **Pattern References** (existing code to follow): - - `agents/agents.json:1-135` - Current agent configuration structure (JSON format, permission object structure) - - `agents/agents.json:7-29` - Chiron permission object (current state with duplicate key) - - **API/Type References** (contracts to implement against): - - OpenCode permission schema: `{"permission": {"bash": {...}, "edit": "...", "external_directory": {...}, "task": {...}}` - - **Documentation References** (specs and requirements): - - Interview draft: `.sisyphus/drafts/agent-permissions-refinement.md` - All user decisions and requirements - - Metis analysis: Critical issue #1 - Duplicate external_directory key - - **External References** (libraries and frameworks): - - OpenCode docs: https://opencode.ai/docs/permissions/ - Permission system documentation (allow/ask/deny, wildcards, last-match-wins) - - OpenCode docs: https://opencode.ai/docs/agents/ - Agent configuration format - - **WHY Each Reference Matters** (explain the relevance): - - `agents/agents.json` - Target file to modify, shows current structure and duplicate key bug - - Interview draft - Contains all user decisions (~/p/** path, subagent restrictions, etc.) - - OpenCode permissions docs - Explains permission system mechanics (last-match-wins critical for rule ordering) - - Metis analysis - Identifies the duplicate key bug that MUST be fixed - - **Acceptance Criteria**: - - > **CRITICAL: AGENT-EXECUTABLE VERIFICATION ONLY** - - **Automated Verification (config validation)**: - \`\`\`bash - # Agent runs: - jq '.' /home/m3tam3re/p/AI/AGENTS/agents/agents.json > /dev/null 2>&1 - # Assert: Exit code 0 (valid JSON) - - # Verify single external_directory key in chiron permission object - cat /home/m3tam3re/p/AI/AGENTS/agents/agents.json | jq '.chiron.permission | keys' | grep external_directory | wc -l - # Assert: Output is "1" (exactly one external_directory key) - - # Verify workspace path exists - ls -la ~/p/ 2>&1 | head -1 - # Assert: Shows directory listing (not "No such file or directory") - \`\`\` - - **Evidence to Capture**: - - [x] jq validation output (exit code 0) - - [x] external_directory key count output (should be "1") - - [x] Workspace path ls output (shows directory exists) - - **Commit**: NO (group with Task 2 and 3) - -- [x] 2. Apply Chiron Permission Updates - - **What to do**: - - Set `edit` to `"deny"` (planning agent should not write files) - - Set `bash` permissions to deny all except `bd *`: - ```json - "bash": { - "*": "deny", - "bd *": "allow" - } - ``` - - Set `external_directory` to `~/p/**` with catch-all ask: - ```json - "external_directory": { - "~/p/**": "allow", - "*": "ask" - } - ``` - - Add `task` permission to restrict subagents: - ```json - "task": { - "*": "deny", - "explore": "allow", - "librarian": "allow", - "athena": "allow", - "chiron-forge": "allow" - } - ``` - - Add `/run/agenix/*` to read deny list - - Add expanded secret blocking patterns: `.local/share/*`, `.cache/*`, `*.db`, `*.keychain`, `*.p12` - - **Must NOT do**: - - Allow bash file write operators (echo >, cat >, tee, etc.) - will add in Task 3 for both agents - - Allow chiron to invoke build-capable subagents beyond chiron-forge - - Skip webfetch permission (should be "allow" for research capability) - - **Recommended Agent Profile**: - > **Category**: quick - - Reason: JSON configuration update, follows clear specifications from draft - > **Skills**: git-master - - git-master: Git workflow for committing changes - > **Skills Evaluated but Omitted**: - - research: Not needed (all requirements documented in draft) - - librarian: Not needed (no external docs needed) - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Task 3) - - **Blocks**: Task 4 - - **Blocked By**: Task 1 - - **References** (CRITICAL - Be Exhaustive): - - **Pattern References** (existing code to follow): - - `agents/agents.json:11-24` - Current Chiron read permissions with secret blocking patterns - - `agents/agents.json:114-132` - Athena permission object (read-only subagent reference pattern) - - **API/Type References** (contracts to implement against): - - OpenCode task permission schema: `{"task": {"agent-name": "allow"}}` - - **Documentation References** (specs and requirements): - - Interview draft: `.sisyphus/drafts/agent-permissions-refinement.md` - Chiron permission decisions - - Metis analysis: Guardrails #7, #8 - Secret blocking patterns, task permission implementation - - **External References** (libraries and frameworks): - - OpenCode docs: https://opencode.ai/docs/agents/#task-permissions - Task permission documentation - - OpenCode docs: https://opencode.ai/docs/permissions/ - Permission level definitions and pattern matching - - **WHY Each Reference Matters** (explain the relevance): - - `agents/agents.json:11-24` - Shows current secret blocking patterns to extend - - `agents/agents.json:114-132` - Shows read-only subagent pattern for reference (athena: deny bash, deny edit) - - Interview draft - Contains exact user requirements for Chiron permissions - - OpenCode task docs - Explains how to restrict subagent invocation via task permission - - **Acceptance Criteria**: - - > **CRITICAL: AGENT-EXECUTABLE VERIFICATION ONLY** - - **Automated Verification (config validation)**: - \`\`\`bash - # Agent runs: - jq '.chiron.permission.edit' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - jq '.chiron.permission.bash."*"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - jq '.chiron.permission.bash."bd *"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "allow" - - jq '.chiron.permission.task."*"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - jq '.chiron.permission.task | keys' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Contains ["*", "athena", "chiron-forge", "explore", "librarian"] - - jq '.chiron.permission.external_directory."~/p/**"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "allow" - - jq '.chiron.permission.external_directory."*"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "ask" - - jq '.chiron.permission.read."/run/agenix/*"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - \`\`\` - - **Evidence to Capture**: - - [x] Edit permission value (should be "deny") - - [x] Bash wildcard permission (should be "deny") - - [x] Bash bd permission (should be "allow") - - [x] Task wildcard permission (should be "deny") - - [x] Task allowlist keys (should show 5 entries) - - [x] External directory ~/p/** permission (should be "allow") - - [x] External directory wildcard permission (should be "ask") - - [x] Read /run/agenix/* permission (should be "deny") - - **Commit**: NO (group with Task 3) - -- [x] 3. Apply Chriton-Forge Permission Updates - - **What to do**: - - Split `git *: "ask"` into granular rules: - - Allow: `git add *`, `git commit *`, read-only commands (status, log, diff, branch, show, stash, remote) - - Ask: `git push *` - - Deny: `git config *` - - Change package managers from `"ask"` to granular rules: - - Ask for installs: `npm install *`, `npm i *`, `npx *`, `pip install *`, `pip3 install *`, `uv *`, `bun install *`, `bun i *`, `bunx *`, `yarn install *`, `yarn add *`, `pnpm install *`, `pnpm add *`, `cargo install *`, `go install *`, `make install` - - Allow other commands implicitly (let them use catch-all rules or existing allow patterns) - - Set `external_directory` to allow `~/p/**` with catch-all ask: - ```json - "external_directory": { - "~/p/**": "allow", - "*": "ask" - } - ``` - - Add bash file write protection patterns (apply to both agents): - ```json - "bash": { - "echo * > *": "deny", - "cat * > *": "deny", - "printf * > *": "deny", - "tee": "deny", - "*>*": "deny", - ">*>*": "deny" - } - ``` - - Add bash command injection prevention (apply to both agents): - ```json - "bash": { - "$(*": "deny", - "`*": "deny", - "eval *": "deny", - "source *": "deny" - } - ``` - - Add git secret protection patterns (apply to both agents): - ```json - "bash": { - "git add *.env*": "deny", - "git commit *.env*": "deny", - "git add *credentials*": "deny", - "git add *secrets*": "deny" - } - ``` - - Add expanded secret blocking patterns to read permission: - - `.local/share/*`, `.cache/*`, `*.db`, `*.keychain`, `*.p12` - - **Must NOT do**: - - Remove existing bash deny rules for dangerous commands (dd, mkfs, fdisk, parted, eval, sudo, su, systemctl, etc.) - - Allow git config modifications - - Allow bash to write files via any method (must block all redirect patterns) - - Skip command injection prevention ($(), backticks, eval, source) - - **Recommended Agent Profile**: - > **Category**: quick - - Reason: JSON configuration update, follows clear specifications from draft - > **Skills**: git-master - - git-master: Git workflow for committing changes - > **Skills Evaluated but Omitted**: - - research: Not needed (all requirements documented in draft) - - librarian: Not needed (no external docs needed) - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Task 2) - - **Blocks**: Task 4 - - **Blocked By**: Task 1 - - **References** (CRITICAL - Be Exhaustive): - - **Pattern References** (existing code to follow): - - `agents/agents.json:37-103` - Current Chriton-Forge bash permissions (many explicit allow/ask/deny rules) - - `agents/agents.json:37-50` - Current Chriton-Forge read permissions with secret blocking - - **API/Type References** (contracts to implement against): - - OpenCode permission schema: Same as Task 2 - - **Documentation References** (specs and requirements): - - Interview draft: `.sisyphus/drafts/agent-permissions-refinement.md` - Chriton-Forge permission decisions - - Metis analysis: Guardrails #1-#6 - Bash edit bypass, git secret protection, command injection, git config protection - - **External References** (libraries and frameworks): - - OpenCode docs: https://opencode.ai/docs/permissions/ - Permission pattern matching (wildcards, last-match-wins) - - **WHY Each Reference Matters** (explain the relevance): - - `agents/agents.json:37-103` - Shows current bash permission structure (many explicit rules) to extend with new patterns - - `agents/agents.json:37-50` - Shows current secret blocking to extend with additional patterns - - Interview draft - Contains exact user requirements for Chriton-Forge permissions - - Metis analysis - Provides bash injection prevention patterns and git protection rules - - **Acceptance Criteria**: - - > **CRITICAL: AGENT-EXECUTABLE VERIFICATION ONLY** - - **Automated Verification (config validation)**: - \`\`\`bash - # Agent runs: - - # Verify git commit is allowed - jq '.chiron-forge.permission.bash."git commit *"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "allow" - - # Verify git push asks - jq '.chiron-forge.permission.bash."git push *"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "ask" - - # Verify git config is denied - jq '.chiron-forge.permission.bash."git config *"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - # Verify npm install asks - jq '.chiron-forge.permission.bash."npm install *"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "ask" - - # Verify bash file write redirects are blocked - jq '.chiron-forge.permission.bash."echo * > *"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - jq '.chiron-forge.permission.bash."cat * > *"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - jq '.chiron-forge.permission.bash."tee"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - # Verify command injection is blocked - jq '.chiron-forge.permission.bash."$(*"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - jq '.chiron-forge.permission.bash."`*"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - # Verify git secret protection - jq '.chiron-forge.permission.bash."git add *.env*"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - jq '.chiron-forge.permission.bash."git commit *.env*"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - # Verify external_directory scope - jq '.chiron-forge.permission.external_directory."~/p/**"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "allow" - - jq '.chiron-forge.permission.external_directory."*"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "ask" - - # Verify expanded secret blocking - jq '.chiron-forge.permission.read.".local/share/*"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - jq '.chiron-forge.permission.read.".cache/*"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - - jq '.chiron-forge.permission.read."*.db"' /home/m3tam3re/p/AI/AGENTS/agents/agents.json - # Assert: Output is "deny" - \`\`\` - - **Evidence to Capture**: - - [x] Git commit permission (should be "allow") - - [x] Git push permission (should be "ask") - - [x] Git config permission (should be "deny") - - [x] npm install permission (should be "ask") - - [x] bash redirect echo > permission (should be "deny") - - [x] bash redirect cat > permission (should be "deny") - - [x] bash tee permission (should be "deny") - - [x] bash $() injection permission (should be "deny") - - [x] bash backtick injection permission (should be "deny") - - [x] git add *.env* permission (should be "deny") - - [x] git commit *.env* permission (should be "deny") - - [x] external_directory ~/p/** permission (should be "allow") - - [x] external_directory wildcard permission (should be "ask") - - [x] read .local/share/* permission (should be "deny") - - [x] read .cache/* permission (should be "deny") - - [x] read *.db permission (should be "deny") - - **Commit**: YES (groups with Tasks 1, 2, 3) - - Message: `chore(agents): refine permissions for Chiron and Chriton-Forge with security hardening` - - Files: `agents/agents.json` - - Pre-commit: `jq '.' agents/agents.json > /dev/null 2>&1` (validate JSON) - -- [x] 4. Validate Configuration (Manual Verification) - - **What to do**: - - Run JSON syntax validation: `jq '.' agents/agents.json` - - Verify no duplicate keys in configuration - - Verify workspace path exists: `ls -la ~/p/` - - Document manual verification procedure for post-deployment testing - - **Must NOT do**: - - Skip workspace path validation - - Skip duplicate key verification - - Proceed to deployment without validation - - **Recommended Agent Profile**: - > **Category**: quick - - Reason: Simple validation commands, documentation task - > **Skills**: git-master - - git-master: Git workflow for committing validation script or notes if needed - > **Skills Evaluated but Omitted**: - - research: Not needed (validation is straightforward) - - librarian: Not needed (no external docs needed) - - **Parallelization**: - - **Can Run In Parallel**: NO - - **Parallel Group**: Sequential - - **Blocks**: None (final validation task) - - **Blocked By**: Tasks 2, 3 - - **References** (CRITICAL - Be Exhaustive): - - **Pattern References** (existing code to follow): - - `AGENTS.md` - Repository documentation structure - - **API/Type References** (contracts to implement against): - - N/A (validation task) - - **Documentation References** (specs and requirements): - - Interview draft: `.sisyphus/drafts/agent-permissions-refinement.md` - All user requirements - - Metis analysis: Guardrails #1-#6 - Validation requirements - - **External References** (libraries and frameworks): - - N/A (validation task) - - **WHY Each Reference Matters** (explain the relevance): - - Interview draft - Contains all requirements to validate against - - Metis analysis - Identifies specific validation steps (duplicate keys, workspace path, etc.) - - **Acceptance Criteria**: - - > **CRITICAL: AGENT-EXECUTABLE VERIFICATION ONLY** - - **Automated Verification (config validation)**: - \`\`\`bash - # Agent runs: - - # JSON syntax validation - jq '.' /home/m3tam3re/p/AI/AGENTS/agents/agents.json > /dev/null 2>&1 - # Assert: Exit code 0 - - # Verify no duplicate external_directory keys - cat /home/m3tam3re/p/AI/AGENTS/agents/agents.json | jq '.chiron.permission | keys' | grep external_directory | wc -l - # Assert: Output is "1" - - cat /home/m3tam3re/p/AI/AGENTS/agents/agents.json | jq '.chiron-forge.permission | keys' | grep external_directory | wc -l - # Assert: Output is "1" - - # Verify workspace path exists - ls -la ~/p/ 2>&1 | head -1 - # Assert: Shows directory listing (not "No such file or directory") - - # Verify all permission keys are valid - cat /home/m3tam3re/p/AI/AGENTS/agents/agents.json | jq '.chiron.permission' > /dev/null 2>&1 - # Assert: Exit code 0 - - cat /home/m3tam3re/p/AI/AGENTS/agents/agents.json | jq '.chiron-forge.permission' > /dev/null 2>&1 - # Assert: Exit code 0 - \`\`\` - - **Evidence to Capture**: - - [x] jq validation output (exit code 0) - - [x] Chiron external_directory key count (should be "1") - - [x] Chriton-Forge external_directory key count (should be "1") - - [x] Workspace path ls output (shows directory exists) - - [x] Chiron permission object validation (exit code 0) - - [x] Chriton-Forge permission object validation (exit code 0) - - **Commit**: NO (validation only, no changes) - ---- - -## Commit Strategy - -| After Task | Message | Files | Verification | -|------------|---------|-------|--------------| -| 1, 2, 3 | `chore(agents): refine permissions for Chiron and Chriton-Forge with security hardening` | agents/agents.json | `jq '.' agents/agents.json > /dev/null` | -| 4 | N/A (validation only) | N/A | N/A | - ---- - -## Success Criteria - -### Verification Commands -```bash -# Pre-deployment validation -jq '.' /home/m3tam3re/p/AI/AGENTS/agents/agents.json > /dev/null 2>&1 -# Expected: Exit code 0 - -# Duplicate key check -cat /home/m3tam3re/p/AI/AGENTS/agents/agents.json | jq '.chiron.permission | keys' | grep external_directory | wc -l -# Expected: 1 - -# Workspace path validation -ls -la ~/p/ 2>&1 -# Expected: Directory listing - -# Post-deployment (manual) -# Have Chiron attempt file edit → Expected: Permission denied -# Have Chiron run bd ready → Expected: Success -# Have Chriton-Forge git commit → Expected: Success -# Have Chriton-Forge git push → Expected: Ask user -# Have agent read .env → Expected: Permission denied -``` - -### Final Checklist -- [x] Duplicate `external_directory` key fixed -- [x] Chiron edit set to "deny" -- [x] Chiron bash denied except `bd *` -- [x] Chiron task permission restricts subagents (explore, librarian, athena, chiron-forge) -- [x] Chiron external_directory allows ~/p/** only -- [x] Chriton-Forge git commit allowed, git push asks -- [x] Chriton-Forge git config denied -- [x] Chriton-Forge package install commands ask -- [x] Chriton-Forge external_directory allows ~/p/**, asks others -- [x] Bash file write operators blocked (echo >, cat >, tee, etc.) -- [x] Bash command injection blocked ($(), backticks, eval, source) -- [x] Git secret protection added (git add/commit *.env* deny) -- [x] Expanded secret blocking patterns added (.local/share/*, .cache/*, *.db, *.keychain, *.p12) -- [x] /run/agenix/* blocked in read permissions -- [x] JSON syntax valid (jq validates) -- [x] No duplicate keys in configuration -- [x] Workspace path ~/p/** exists diff --git a/.sisyphus/plans/chiron-agent-framework.md b/.sisyphus/plans/chiron-agent-framework.md deleted file mode 100644 index f547d41..0000000 --- a/.sisyphus/plans/chiron-agent-framework.md +++ /dev/null @@ -1,977 +0,0 @@ -# Chiron Personal Agent Framework - -## TL;DR - -> **Quick Summary**: Create an Oh-My-Opencode-style agent framework for personal productivity with Chiron as the orchestrator, 4 specialized subagents (Hermes, Athena, Apollo, Calliope), and 5 tool integration skills (Basecamp, Outline, MS Teams, Outlook, Obsidian). -> -> **Deliverables**: -> - 6 agent definitions in `agents.json` -> - 6 system prompt files in `prompts/` -> - 5 tool integration skills in `skills/` -> - Validation script extension in `scripts/` -> -> **Estimated Effort**: Medium -> **Parallel Execution**: YES - 3 waves -> **Critical Path**: Task 1 (agents.json) → Task 3-7 (prompts) → Task 9-13 (skills) → Task 14 (validation) -> -> **Status**: ✅ COMPLETE - All 14 main tasks + 6 verification items = 20/20 deliverables - ---- - -## Context - -### Original Request -Create an agent framework similar to Oh-My-Opencode but focused on personal productivity: -- Manage work tasks, appointments, projects via Basecamp, Outline, MS Teams, Outlook -- Manage private tasks and knowledge via Obsidian -- Greek mythology naming convention (avoiding Oh My OpenCode names) -- Main agent named "Chiron" - -### Interview Summary -**Key Discussions**: -- **Chiron's Role**: Main orchestrator that delegates to specialized subagents -- **Agent Count**: Minimal (3-4 agents initially) + 2 primary agents -- **Domain Separation**: Separate work vs private agents with clear boundaries -- **Tool Priority**: All 4 work tools + Obsidian equally important -- **Basecamp MCP**: User confirmed working MCP at georgeantonopoulos/Basecamp-MCP-Server - -**Research Findings**: -- Oh My OpenCode names to avoid: Sisyphus, Atlas, Prometheus, Hephaestus, Metis, Momus, Oracle, Librarian, Explore, Multimodal-Looker, Sisyphus-Junior -- MCP servers available for all work tools + Obsidian -- Protonmail requires custom IMAP/SMTP (deferred) -- Current repo has established skill patterns with SKILL.md + optional subdirectories - -### Metis Review -**Identified Gaps** (addressed in plan): -- Delegation model clarified: Chiron uses Question tool for ambiguous requests -- Behavioral difference between Chiron and Chiron-Forge defined -- Executable acceptance criteria added for all tasks -- Edge cases documented in guardrails section -- MCP authentication assumed pre-configured by NixOS (explicit scope boundary) - ---- - -## Work Objectives - -### Core Objective -Create a personal productivity agent framework following Oh-My-Opencode patterns, enabling AI-assisted management of work and private life through specialized agents that integrate with existing tools. - -### Concrete Deliverables -1. `agents/agents.json` - 6 agent definitions (2 primary, 4 subagent) -2. `prompts/chiron.txt` - Chiron (plan mode) system prompt -3. `prompts/chiron-forge.txt` - Chiron-Forge (build mode) system prompt -4. `prompts/hermes.txt` - Work communication agent prompt -5. `prompts/athena.txt` - Work knowledge agent prompt -6. `prompts/apollo.txt` - Private knowledge agent prompt -7. `prompts/calliope.txt` - Writing agent prompt -8. `skills/basecamp/SKILL.md` - Basecamp integration skill -9. `skills/outline/SKILL.md` - Outline wiki integration skill -10. `skills/msteams/SKILL.md` - MS Teams integration skill -11. `skills/outlook/SKILL.md` - Outlook email integration skill -12. `skills/obsidian/SKILL.md` - Obsidian integration skill -13. `scripts/validate-agents.sh` - Agent validation script - -### Definition of Done -- [x] `python3 -c "import json; json.load(open('agents/agents.json'))"` → Exit 0 -- [x] All 6 prompt files exist and are non-empty -- [x] All 5 skill directories have valid SKILL.md with YAML frontmatter -- [x] `./scripts/test-skill.sh --validate` passes for new skills -- [x] `./scripts/validate-agents.sh` passes - -### Must Have -- All agents use Question tool for multi-choice decisions -- External prompt files (not inline in JSON) -- Follow existing skill structure patterns -- Greek naming convention for agents -- Clear separation between plan mode (Chiron) and build mode (Chiron-Forge) -- Skills provide tool-specific knowledge that agents load on demand - -### Must NOT Have (Guardrails) -- **NO MCP server configuration** - Managed by NixOS, outside this repo -- **NO authentication handling** - Assume pre-configured MCP tools -- **NO cross-agent state sharing** - Each agent operates independently -- **NO new opencode commands** - Use existing command patterns only -- **NO generic "I'm an AI assistant" prompts** - Domain-specific responsibilities only -- **NO Protonmail integration** - Deferred to future phase -- **NO duplicate tool knowledge across skills** - Each skill focuses on ONE tool -- **NO scripts outside scripts/ directory** -- **NO model configuration changes** - Keep current `zai-coding-plan/glm-4.7` - ---- - -## Verification Strategy (MANDATORY) - -> **UNIVERSAL RULE: ZERO HUMAN INTERVENTION** -> -> ALL tasks in this plan MUST be verifiable WITHOUT any human action. -> This is NOT conditional - it applies to EVERY task, regardless of test strategy. -> -> ### Test Decision -> - **Infrastructure exists**: YES (test-skill.sh) -> - **Automated tests**: Tests-after (validation scripts) -> - **Framework**: bash + python for validation -> -> ### Agent-Executed QA Scenarios (MANDATORY - ALL tasks) -> -> **Verification Tool by Deliverable Type**: -> -> | Type | Tool | How Agent Verifies | -> |------|------|-------------------| -> | **agents.json** | Bash (python/jq) | Parse JSON, validate structure, check required fields | -> | **Prompt files** | Bash (file checks) | File exists, non-empty, contains expected sections | -> | **SKILL.md files** | Bash (test-skill.sh) | YAML frontmatter valid, name matches directory | -> | **Validation scripts** | Bash | Script is executable, runs without error, produces expected output | - ---- - -## Execution Strategy - -### Parallel Execution Waves - -``` -Wave 1 (Start Immediately): -├── Task 1: Create agents.json configuration [no dependencies] -└── Task 2: Create prompts/ directory structure [no dependencies] - -Wave 2 (After Wave 1): -├── Task 3: Chiron prompt [depends: 2] -├── Task 4: Chiron-Forge prompt [depends: 2] -├── Task 5: Hermes prompt [depends: 2] -├── Task 6: Athena prompt [depends: 2] -├── Task 7: Apollo prompt [depends: 2] -└── Task 8: Calliope prompt [depends: 2] - -Wave 3 (Can parallel with Wave 2): -├── Task 9: Basecamp skill [no dependencies] -├── Task 10: Outline skill [no dependencies] -├── Task 11: MS Teams skill [no dependencies] -├── Task 12: Outlook skill [no dependencies] -└── Task 13: Obsidian skill [no dependencies] - -Wave 4 (After Wave 2 + 3): -└── Task 14: Validation script [depends: 1, 3-8] - -Critical Path: Task 1 → Task 2 → Tasks 3-8 → Task 14 -Parallel Speedup: ~50% faster than sequential -``` - -### Dependency Matrix - -| Task | Depends On | Blocks | Can Parallelize With | -|------|------------|--------|---------------------| -| 1 | None | 14 | 2, 9-13 | -| 2 | None | 3-8 | 1, 9-13 | -| 3-8 | 2 | 14 | Each other, 9-13 | -| 9-13 | None | None | Each other, 1-2 | -| 14 | 1, 3-8 | None | (final) | - -### Agent Dispatch Summary - -| Wave | Tasks | Recommended Category | -|------|-------|---------------------| -| 1 | 1, 2 | quick | -| 2 | 3-8 | quick (parallel) | -| 3 | 9-13 | quick (parallel) | -| 4 | 14 | quick | - ---- - -## TODOs - -### Wave 1: Foundation - -- [x] 1. Create agents.json with 6 agent definitions - - **What to do**: - - Update existing `agents/agents.json` to add all 6 agents - - Each agent needs: description, mode, model, prompt reference - - Primary agents: chiron, chiron-forge - - Subagents: hermes, athena, apollo, calliope - - All agents should have `question: "allow"` permission - - **Must NOT do**: - - Do not add MCP server configuration - - Do not change model from current pattern - - Do not add inline prompts (use file references) - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`agent-development`] - - `agent-development`: Provides agent configuration patterns and best practices - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 1 (with Task 2) - - **Blocks**: Task 14 - - **Blocked By**: None - - **References**: - - `agents/agents.json:1-7` - Current chiron agent configuration pattern - - `skills/agent-development/SKILL.md:40-76` - JSON agent structure reference - - `skills/agent-development/SKILL.md:226-277` - Permissions system reference - - `skills/agent-development/references/opencode-agents-json-example.md` - Complete examples - - **Acceptance Criteria**: - - ``` - Scenario: agents.json is valid JSON with all 6 agents - Tool: Bash (python) - Steps: - 1. python3 -c "import json; data = json.load(open('agents/agents.json')); print(len(data))" - 2. Assert: Output is "6" - 3. python3 -c "import json; data = json.load(open('agents/agents.json')); print(sorted(data.keys()))" - 4. Assert: Output contains ['apollo', 'athena', 'calliope', 'chiron', 'chiron-forge', 'hermes'] - Expected Result: JSON parses, all 6 agents present - Evidence: Command output captured - - Scenario: Each agent has required fields - Tool: Bash (python) - Steps: - 1. python3 -c " - import json - data = json.load(open('agents/agents.json')) - for name, agent in data.items(): - assert 'description' in agent, f'{name}: missing description' - assert 'mode' in agent, f'{name}: missing mode' - assert 'prompt' in agent, f'{name}: missing prompt' - print('All agents valid') - " - 2. Assert: Output is "All agents valid" - Expected Result: All required fields present - Evidence: Validation output captured - - Scenario: Primary agents have correct mode - Tool: Bash (python) - Steps: - 1. python3 -c " - import json - data = json.load(open('agents/agents.json')) - assert data['chiron']['mode'] == 'primary' - assert data['chiron-forge']['mode'] == 'primary' - print('Primary modes correct') - " - Expected Result: Both primary agents have mode=primary - Evidence: Command output - - Scenario: Subagents have correct mode - Tool: Bash (python) - Steps: - 1. python3 -c " - import json - data = json.load(open('agents/agents.json')) - for name in ['hermes', 'athena', 'apollo', 'calliope']: - assert data[name]['mode'] == 'subagent', f'{name}: wrong mode' - print('Subagent modes correct') - " - Expected Result: All subagents have mode=subagent - Evidence: Command output - ``` - - **Commit**: YES - - Message: `feat(agents): add chiron agent framework with 6 agents` - - Files: `agents/agents.json` - - Pre-commit: `python3 -c "import json; json.load(open('agents/agents.json'))"` - ---- - -- [x] 2. Create prompts directory structure - - **What to do**: - - Create `prompts/` directory if not exists - - Directory will hold all agent system prompt files - - **Must NOT do**: - - Do not create prompt files yet (done in Wave 2) - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 1 (with Task 1) - - **Blocks**: Tasks 3-8 - - **Blocked By**: None - - **References**: - - `skills/agent-development/SKILL.md:148-159` - Prompt file conventions - - **Acceptance Criteria**: - - ``` - Scenario: prompts directory exists - Tool: Bash - Steps: - 1. test -d prompts && echo "exists" || echo "missing" - 2. Assert: Output is "exists" - Expected Result: Directory created - Evidence: Command output - ``` - - **Commit**: NO (groups with Task 1) - ---- - -### Wave 2: Agent Prompts - -- [x] 3. Create Chiron (Plan Mode) system prompt - - **What to do**: - - Create `prompts/chiron.txt` - - Define Chiron as the main orchestrator in plan/analysis mode - - Include delegation logic to subagents (Hermes, Athena, Apollo, Calliope) - - Include Question tool usage for ambiguous requests - - Focus on: planning, analysis, guidance, delegation - - Permissions: read-only, no file modifications - - **Must NOT do**: - - Do not allow write/edit operations - - Do not include execution responsibilities - - Do not overlap with Chiron-Forge's build capabilities - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`agent-development`] - - `agent-development`: System prompt design patterns - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Tasks 4-8) - - **Blocks**: Task 14 - - **Blocked By**: Task 2 - - **References**: - - `skills/agent-development/SKILL.md:349-386` - System prompt design patterns - - `skills/agent-development/SKILL.md:397-415` - Prompt best practices - - `skills/agent-development/references/system-prompt-design.md` - Detailed prompt patterns - - **Acceptance Criteria**: - - ``` - Scenario: Chiron prompt file exists and is substantial - Tool: Bash - Steps: - 1. test -f prompts/chiron.txt && echo "exists" || echo "missing" - 2. Assert: Output is "exists" - 3. wc -c < prompts/chiron.txt - 4. Assert: Output is > 500 (substantial content) - Expected Result: File exists with meaningful content - Evidence: File size captured - - Scenario: Chiron prompt contains orchestrator role - Tool: Bash (grep) - Steps: - 1. grep -qi "orchestrat" prompts/chiron.txt && echo "found" || echo "missing" - 2. Assert: Output is "found" - 3. grep -qi "delegat" prompts/chiron.txt && echo "found" || echo "missing" - 4. Assert: Output is "found" - Expected Result: Prompt describes orchestration and delegation - Evidence: grep output - - Scenario: Chiron prompt references subagents - Tool: Bash (grep) - Steps: - 1. grep -qi "hermes" prompts/chiron.txt && echo "found" || echo "missing" - 2. grep -qi "athena" prompts/chiron.txt && echo "found" || echo "missing" - 3. grep -qi "apollo" prompts/chiron.txt && echo "found" || echo "missing" - 4. grep -qi "calliope" prompts/chiron.txt && echo "found" || echo "missing" - Expected Result: All 4 subagents mentioned - Evidence: grep outputs - ``` - - **Commit**: YES (group with Tasks 4-8) - - Message: `feat(prompts): add chiron and subagent system prompts` - - Files: `prompts/*.txt` - - Pre-commit: `for f in prompts/*.txt; do test -s "$f" || exit 1; done` - ---- - -- [x] 4. Create Chiron-Forge (Build Mode) system prompt - - **What to do**: - - Create `prompts/chiron-forge.txt` - - Define as Chiron's execution/build counterpart - - Full write access for task execution - - Can modify files, run commands, complete tasks - - Still delegates to subagents for specialized domains - - Uses Question tool for destructive operations confirmation - - **Must NOT do**: - - Do not make it a planning-only agent (that's Chiron) - - Do not allow destructive operations without confirmation - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`agent-development`] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Tasks 3, 5-8) - - **Blocks**: Task 14 - - **Blocked By**: Task 2 - - **References**: - - `skills/agent-development/SKILL.md:316-346` - Complete agent example with chiron/chiron-forge pattern - - `skills/agent-development/SKILL.md:253-277` - Permission patterns for bash commands - - **Acceptance Criteria**: - - ``` - Scenario: Chiron-Forge prompt file exists - Tool: Bash - Steps: - 1. test -f prompts/chiron-forge.txt && wc -c < prompts/chiron-forge.txt - 2. Assert: Output > 500 - Expected Result: File exists with substantial content - Evidence: File size - - Scenario: Chiron-Forge prompt emphasizes execution - Tool: Bash (grep) - Steps: - 1. grep -qi "execut" prompts/chiron-forge.txt && echo "found" || echo "missing" - 2. grep -qi "build" prompts/chiron-forge.txt && echo "found" || echo "missing" - Expected Result: Execution/build terminology present - Evidence: grep output - ``` - - **Commit**: YES (groups with Task 3) - ---- - -- [x] 5. Create Hermes (Work Communication) system prompt - - **What to do**: - - Create `prompts/hermes.txt` - - Specialization: Basecamp tasks, Outlook email, MS Teams meetings - - Greek god of communication, messengers, quick tasks - - Uses Question tool for: which tool to use, clarifying recipients - - Focus on: task updates, email drafting, meeting scheduling - - **Must NOT do**: - - Do not handle documentation (Athena's domain) - - Do not handle personal/private tools (Apollo's domain) - - Do not write long-form content (Calliope's domain) - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`agent-development`] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 - - **Blocks**: Task 14 - - **Blocked By**: Task 2 - - **References**: - - `skills/agent-development/SKILL.md:349-378` - Standard prompt structure - - **Acceptance Criteria**: - - ``` - Scenario: Hermes prompt defines communication domain - Tool: Bash (grep) - Steps: - 1. grep -qi "basecamp" prompts/hermes.txt && echo "found" || echo "missing" - 2. grep -qi "outlook\|email" prompts/hermes.txt && echo "found" || echo "missing" - 3. grep -qi "teams\|meeting" prompts/hermes.txt && echo "found" || echo "missing" - Expected Result: All 3 tools mentioned - Evidence: grep outputs - ``` - - **Commit**: YES (groups with Task 3) - ---- - -- [x] 6. Create Athena (Work Knowledge) system prompt - - **What to do**: - - Create `prompts/athena.txt` - - Specialization: Outline wiki, documentation, knowledge organization - - Greek goddess of wisdom and strategic warfare - - Focus on: wiki search, knowledge retrieval, documentation updates - - Uses Question tool for: which document to update, clarifying search scope - - **Must NOT do**: - - Do not handle communication (Hermes's domain) - - Do not handle private knowledge (Apollo's domain) - - Do not write creative content (Calliope's domain) - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`agent-development`] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 - - **Blocks**: Task 14 - - **Blocked By**: Task 2 - - **References**: - - `skills/agent-development/SKILL.md:349-378` - Standard prompt structure - - **Acceptance Criteria**: - - ``` - Scenario: Athena prompt defines knowledge domain - Tool: Bash (grep) - Steps: - 1. grep -qi "outline" prompts/athena.txt && echo "found" || echo "missing" - 2. grep -qi "wiki\|knowledge" prompts/athena.txt && echo "found" || echo "missing" - 3. grep -qi "document" prompts/athena.txt && echo "found" || echo "missing" - Expected Result: Outline and knowledge terms present - Evidence: grep outputs - ``` - - **Commit**: YES (groups with Task 3) - ---- - -- [x] 7. Create Apollo (Private Knowledge) system prompt - - **What to do**: - - Create `prompts/apollo.txt` - - Specialization: Obsidian vault, personal notes, private knowledge graph - - Greek god of knowledge, prophecy, and light - - Focus on: note search, personal task management, knowledge retrieval - - Uses Question tool for: clarifying which vault, which note - - **Must NOT do**: - - Do not handle work tools (Hermes/Athena's domain) - - Do not expose personal data to work contexts - - Do not write long-form content (Calliope's domain) - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`agent-development`] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 - - **Blocks**: Task 14 - - **Blocked By**: Task 2 - - **References**: - - `skills/agent-development/SKILL.md:349-378` - Standard prompt structure - - **Acceptance Criteria**: - - ``` - Scenario: Apollo prompt defines private knowledge domain - Tool: Bash (grep) - Steps: - 1. grep -qi "obsidian" prompts/apollo.txt && echo "found" || echo "missing" - 2. grep -qi "personal\|private" prompts/apollo.txt && echo "found" || echo "missing" - 3. grep -qi "note\|vault" prompts/apollo.txt && echo "found" || echo "missing" - Expected Result: Obsidian and personal knowledge terms present - Evidence: grep outputs - ``` - - **Commit**: YES (groups with Task 3) - ---- - -- [x] 8. Create Calliope (Writing) system prompt - - **What to do**: - - Create `prompts/calliope.txt` - - Specialization: documentation writing, reports, meeting notes, prose - - Greek muse of epic poetry and eloquence - - Focus on: drafting documents, summarizing, writing assistance - - Uses Question tool for: clarifying tone, audience, format - - **Must NOT do**: - - Do not manage tools directly (delegates to other agents for tool access) - - Do not handle short communication (Hermes's domain) - - Do not overlap with Athena's wiki management - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`agent-development`] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 - - **Blocks**: Task 14 - - **Blocked By**: Task 2 - - **References**: - - `skills/agent-development/SKILL.md:349-378` - Standard prompt structure - - **Acceptance Criteria**: - - ``` - Scenario: Calliope prompt defines writing domain - Tool: Bash (grep) - Steps: - 1. grep -qi "writ" prompts/calliope.txt && echo "found" || echo "missing" - 2. grep -qi "document" prompts/calliope.txt && echo "found" || echo "missing" - 3. grep -qi "report\|summar" prompts/calliope.txt && echo "found" || echo "missing" - Expected Result: Writing and documentation terms present - Evidence: grep outputs - ``` - - **Commit**: YES (groups with Task 3) - ---- - -### Wave 3: Tool Integration Skills - -- [x] 9. Create Basecamp integration skill - - **What to do**: - - Create `skills/basecamp/SKILL.md` - - Document Basecamp MCP capabilities (63 tools from georgeantonopoulos/Basecamp-MCP-Server) - - Include: projects, todos, messages, card tables, campfire, webhooks - - Provide workflow examples for common operations - - Reference MCP tool names for agent use - - **Must NOT do**: - - Do not include MCP server setup instructions (managed by Nix) - - Do not duplicate general project management advice - - Do not include authentication handling - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`skill-creator`] - - `skill-creator`: Provides skill structure patterns and validation - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 3 (with Tasks 10-13) - - **Blocks**: None - - **Blocked By**: None - - **References**: - - `skills/skill-creator/SKILL.md` - Skill creation patterns - - `skills/brainstorming/SKILL.md` - Example skill structure - - https://github.com/georgeantonopoulos/Basecamp-MCP-Server - MCP tool documentation - - **Acceptance Criteria**: - - ``` - Scenario: Basecamp skill has valid structure - Tool: Bash - Steps: - 1. test -d skills/basecamp && echo "dir exists" - 2. test -f skills/basecamp/SKILL.md && echo "file exists" - 3. ./scripts/test-skill.sh --validate basecamp || echo "validation failed" - Expected Result: Directory and SKILL.md exist, validation passes - Evidence: Command outputs - - Scenario: Basecamp skill has valid frontmatter - Tool: Bash (python) - Steps: - 1. python3 -c " - import yaml - content = open('skills/basecamp/SKILL.md').read() - front = content.split('---')[1] - data = yaml.safe_load(front) - assert data['name'] == 'basecamp', 'name mismatch' - assert 'description' in data, 'missing description' - print('Valid') - " - Expected Result: YAML frontmatter valid with correct name - Evidence: Python output - ``` - - **Commit**: YES - - Message: `feat(skills): add basecamp integration skill` - - Files: `skills/basecamp/SKILL.md` - - Pre-commit: `./scripts/test-skill.sh --validate basecamp` - ---- - -- [x] 10. Create Outline wiki integration skill - - **What to do**: - - Create `skills/outline/SKILL.md` - - Document Outline API capabilities - - Include: document CRUD, search, collections, sharing - - Provide workflow examples for knowledge management - - **Must NOT do**: - - Do not include MCP server setup - - Do not duplicate wiki concepts - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`skill-creator`] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 3 - - **Blocks**: None - - **Blocked By**: None - - **References**: - - `skills/skill-creator/SKILL.md` - Skill creation patterns - - https://www.getoutline.com/developers - Outline API documentation - - **Acceptance Criteria**: - - ``` - Scenario: Outline skill has valid structure - Tool: Bash - Steps: - 1. test -d skills/outline && test -f skills/outline/SKILL.md && echo "exists" - 2. ./scripts/test-skill.sh --validate outline || echo "failed" - Expected Result: Valid skill structure - Evidence: Command output - ``` - - **Commit**: YES - - Message: `feat(skills): add outline wiki integration skill` - - Files: `skills/outline/SKILL.md` - - Pre-commit: `./scripts/test-skill.sh --validate outline` - ---- - -- [x] 11. Create MS Teams integration skill - - **What to do**: - - Create `skills/msteams/SKILL.md` - - Document MS Teams Graph API capabilities via MCP - - Include: channels, messages, meetings, chat - - Provide workflow examples for team communication - - **Must NOT do**: - - Do not include Graph API authentication flows - - Do not overlap with Outlook email functionality - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`skill-creator`] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 3 - - **Blocks**: None - - **Blocked By**: None - - **References**: - - `skills/skill-creator/SKILL.md` - Skill creation patterns - - https://learn.microsoft.com/en-us/graph/api/resources/teams-api-overview - Teams API - - **Acceptance Criteria**: - - ``` - Scenario: MS Teams skill has valid structure - Tool: Bash - Steps: - 1. test -d skills/msteams && test -f skills/msteams/SKILL.md && echo "exists" - 2. ./scripts/test-skill.sh --validate msteams || echo "failed" - Expected Result: Valid skill structure - Evidence: Command output - ``` - - **Commit**: YES - - Message: `feat(skills): add ms teams integration skill` - - Files: `skills/msteams/SKILL.md` - - Pre-commit: `./scripts/test-skill.sh --validate msteams` - ---- - -- [x] 12. Create Outlook email integration skill - - **What to do**: - - Create `skills/outlook/SKILL.md` - - Document Outlook Graph API capabilities via MCP - - Include: mail CRUD, calendar, contacts, folders - - Provide workflow examples for email management - - **Must NOT do**: - - Do not include Graph API authentication - - Do not overlap with Teams functionality - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`skill-creator`] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 3 - - **Blocks**: None - - **Blocked By**: None - - **References**: - - `skills/skill-creator/SKILL.md` - Skill creation patterns - - https://learn.microsoft.com/en-us/graph/outlook-mail-concept-overview - Outlook API - - **Acceptance Criteria**: - - ``` - Scenario: Outlook skill has valid structure - Tool: Bash - Steps: - 1. test -d skills/outlook && test -f skills/outlook/SKILL.md && echo "exists" - 2. ./scripts/test-skill.sh --validate outlook || echo "failed" - Expected Result: Valid skill structure - Evidence: Command output - ``` - - **Commit**: YES - - Message: `feat(skills): add outlook email integration skill` - - Files: `skills/outlook/SKILL.md` - - Pre-commit: `./scripts/test-skill.sh --validate outlook` - ---- - -- [x] 13. Create Obsidian integration skill - - **What to do**: - - Create `skills/obsidian/SKILL.md` - - Document Obsidian Local REST API capabilities - - Include: vault operations, note CRUD, search, daily notes - - Reference skills/brainstorming/references/obsidian-workflow.md for patterns - - Provide workflow examples for personal knowledge management - - **Must NOT do**: - - Do not include plugin installation - - Do not duplicate general note-taking advice - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`skill-creator`] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 3 - - **Blocks**: None - - **Blocked By**: None - - **References**: - - `skills/skill-creator/SKILL.md` - Skill creation patterns - - `skills/brainstorming/SKILL.md` - Example skill structure - - `skills/brainstorming/references/obsidian-workflow.md` - Existing Obsidian patterns - - https://coddingtonbear.github.io/obsidian-local-rest-api/ - Local REST API docs - - **Acceptance Criteria**: - - ``` - Scenario: Obsidian skill has valid structure - Tool: Bash - Steps: - 1. test -d skills/obsidian && test -f skills/obsidian/SKILL.md && echo "exists" - 2. ./scripts/test-skill.sh --validate obsidian || echo "failed" - Expected Result: Valid skill structure - Evidence: Command output - ``` - - **Commit**: YES - - Message: `feat(skills): add obsidian integration skill` - - Files: `skills/obsidian/SKILL.md` - - Pre-commit: `./scripts/test-skill.sh --validate obsidian` - ---- - -### Wave 4: Validation - -- [x] 14. Create agent validation script - - **What to do**: - - Create `scripts/validate-agents.sh` - - Validate agents.json structure and required fields - - Verify all referenced prompt files exist - - Check prompt files are non-empty - - Integrate with existing test-skill.sh patterns - - **Must NOT do**: - - Do not require MCP servers for validation - - Do not perform functional agent testing (just structural) - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: NO - - **Parallel Group**: Sequential (Wave 4) - - **Blocks**: None - - **Blocked By**: Tasks 1, 3-8 - - **References**: - - `scripts/test-skill.sh` - Existing validation script pattern - - **Acceptance Criteria**: - - ``` - Scenario: Validation script is executable - Tool: Bash - Steps: - 1. test -x scripts/validate-agents.sh && echo "executable" || echo "not executable" - 2. Assert: Output is "executable" - Expected Result: Script has execute permission - Evidence: Command output - - Scenario: Validation script runs successfully - Tool: Bash - Steps: - 1. ./scripts/validate-agents.sh - 2. Assert: Exit code is 0 - Expected Result: All validations pass - Evidence: Script output - - Scenario: Validation script catches missing files - Tool: Bash - Steps: - 1. mv prompts/chiron.txt prompts/chiron.txt.bak - 2. ./scripts/validate-agents.sh - 3. Assert: Exit code is NOT 0 - 4. mv prompts/chiron.txt.bak prompts/chiron.txt - Expected Result: Script detects missing prompt file - Evidence: Error output - ``` - - **Commit**: YES - - Message: `feat(scripts): add agent validation script` - - Files: `scripts/validate-agents.sh` - - Pre-commit: `./scripts/validate-agents.sh` - ---- - -## Commit Strategy - -| After Task | Message | Files | Verification | -|------------|---------|-------|--------------| -| 1, 2 | `feat(agents): add chiron agent framework with 6 agents` | agents/agents.json, prompts/ | `python3 -c "import json; json.load(open('agents/agents.json'))"` | -| 3-8 | `feat(prompts): add chiron and subagent system prompts` | prompts/*.txt | `for f in prompts/*.txt; do test -s "$f"; done` | -| 9 | `feat(skills): add basecamp integration skill` | skills/basecamp/ | `./scripts/test-skill.sh --validate basecamp` | -| 10 | `feat(skills): add outline wiki integration skill` | skills/outline/ | `./scripts/test-skill.sh --validate outline` | -| 11 | `feat(skills): add ms teams integration skill` | skills/msteams/ | `./scripts/test-skill.sh --validate msteams` | -| 12 | `feat(skills): add outlook email integration skill` | skills/outlook/ | `./scripts/test-skill.sh --validate outlook` | -| 13 | `feat(skills): add obsidian integration skill` | skills/obsidian/ | `./scripts/test-skill.sh --validate obsidian` | -| 14 | `feat(scripts): add agent validation script` | scripts/validate-agents.sh | `./scripts/validate-agents.sh` | - ---- - -## Success Criteria - -### Verification Commands -```bash -# Validate agents.json -python3 -c "import json; json.load(open('agents/agents.json'))" # Expected: exit 0 - -# Count agents -python3 -c "import json; print(len(json.load(open('agents/agents.json'))))" # Expected: 6 - -# Validate all prompts exist -for f in chiron chiron-forge hermes athena apollo calliope; do - test -s prompts/$f.txt && echo "$f: OK" || echo "$f: MISSING" -done - -# Validate all skills -./scripts/test-skill.sh --validate # Expected: all pass - -# Run full validation -./scripts/validate-agents.sh # Expected: exit 0 -``` - -### Final Checklist -- [x] All 6 agents defined in agents.json -- [x] All 6 prompt files exist and are non-empty -- [x] All 5 skills have valid SKILL.md with YAML frontmatter -- [x] validate-agents.sh passes -- [x] test-skill.sh --validate passes -- [x] No MCP configuration in repo -- [x] No inline prompts in agents.json -- [x] All agent names are Greek mythology (not conflicting with Oh My OpenCode) diff --git a/.sisyphus/plans/memory-system.md b/.sisyphus/plans/memory-system.md deleted file mode 100644 index 3cf52a9..0000000 --- a/.sisyphus/plans/memory-system.md +++ /dev/null @@ -1,897 +0,0 @@ -# Memory System for AGENTS + Obsidian CODEX - -## TL;DR - -> **Quick Summary**: Build a dual-layer memory system equivalent to openclaw's — Mem0 for fast semantic search/auto-recall + Obsidian CODEX vault for human-readable, versioned knowledge. Memories are stored in both layers and cross-referenced via IDs. -> -> **Deliverables**: -> - New `skills/memory/SKILL.md` — Core orchestration skill (auto-capture, auto-recall, dual-layer sync) -> - New `80-memory/` folder in CODEX vault with category subfolders + memory template -> - Obsidian MCP server configuration (cyanheads/obsidian-mcp-server) -> - Updated skills (mem0-memory, obsidian), Apollo prompt, CODEX docs, user profile -> -> **Estimated Effort**: Medium (9 tasks across config/docs, no traditional code) -> **Parallel Execution**: YES — 4 waves -> **Critical Path**: Task 1 (vault infra) → Task 4 (memory skill) → Task 9 (validation) - ---- - -## Context - -### Original Request -Adapt openclaw's memory system for the opencode AGENTS repo, integrated with the Obsidian CODEX vault at `~/CODEX`. The vault should serve as a "second brain" for both the user AND AI agents. - -### Interview Summary -**Key Discussions**: -- Analyzed openclaw's 3-layer memory architecture (SQLite+vectors builtin, memory-core plugin, memory-lancedb plugin with auto-capture/auto-recall) -- User confirmed Mem0 is available self-hosted at localhost:8000 — just needs spinning up -- User chose `80-memory/` as dedicated vault folder with category subfolders -- User chose auto+explicit capture (LLM extraction at session end + "remember this" commands) -- User chose agent QA only (no unit test infrastructure — repo is config/docs only) -- No Obsidian MCP server currently configured — plan to add cyanheads/obsidian-mcp-server - -**Research Findings**: -- cyanheads/obsidian-mcp-server (363 stars) — Best MCP server: frontmatter management, vault cache, search with pagination, tag management -- GitHub Copilot's memory system: citation-based verification pattern (Phase 2 candidate) -- Production recommendation: dual-layer (operational memory + documented knowledge) -- Mem0 provides semantic search, user_id/agent_id/run_id scoping, metadata support, `/health` endpoint -- Auto-capture best practice: max 3 per session, LLM extraction > regex patterns - -### Metis Review -**Identified Gaps** (addressed): -- 80-memory/ subfolders vs flat pattern: Resolved — follows `30-resources/` pattern (subfolders by TYPE), not `50-zettelkasten/` flat pattern -- Mem0 health check: Added prerequisite validation step -- Error handling undefined: Defined — Mem0 unavailable → skip, Obsidian unavailable → Mem0 only -- Deployment order: Defined — CODEX first → MCP config → skills → validation -- Scope creep risk: Locked down — citation verification, memory deletion/lifecycle, dashboards all Phase 2 -- Agent role clarity: Defined — memory skill loadable by any agent, Apollo is primary memory specialist - ---- - -## Work Objectives - -### Core Objective -Build a dual-layer memory system for opencode agents that stores memories in Mem0 (semantic search, operational) AND the Obsidian CODEX vault (human-readable, versioned, wiki-linked). Equivalent in capability to openclaw's memory system. - -### Concrete Deliverables -**AGENTS repo** (`~/p/AI/AGENTS`): -- `skills/memory/SKILL.md` — NEW: Core memory skill -- `skills/memory/references/mcp-config.md` — NEW: Obsidian MCP server config documentation -- `skills/mem0-memory/SKILL.md` — UPDATED: Add categories, dual-layer sync -- `skills/obsidian/SKILL.md` — UPDATED: Add 80-memory/ conventions -- `prompts/apollo.txt` — UPDATED: Add memory management responsibilities -- `context/profile.md` — UPDATED: Add memory system configuration - -**CODEX vault** (`~/CODEX`): -- `80-memory/` — NEW: Folder with subfolders (preferences/, facts/, decisions/, entities/, other/) -- `templates/memory.md` — NEW: Memory note template -- `tag-taxonomy.md` — UPDATED: Add #memory/* tags -- `AGENTS.md` — UPDATED: Add 80-memory/ docs, folder decision tree, memory workflows -- `README.md` — UPDATED: Add 80-memory/ to folder structure - -**Infrastructure** (Nix home-manager — outside AGENTS repo): -- Add cyanheads/obsidian-mcp-server to opencode.json MCP section - -### Definition of Done -- [x] All 11 files created/updated as specified -- [x] `curl http://localhost:8000/health` returns 200 (Mem0 running) -- [~] `curl http://127.0.0.1:27124/vault-info` returns vault info (Obsidian REST API) — *Requires Obsidian desktop app to be open* -- [x] `./scripts/test-skill.sh --validate` passes for new/updated skills -- [x] 80-memory/ folder exists in CODEX vault with 5 subfolders -- [x] Memory template creates valid notes with correct frontmatter - -### Must Have -- Dual-layer storage: every memory in Mem0 AND Obsidian -- Auto-capture at session end (LLM-based, max 3 per session) -- Explicit "remember this" command support -- Auto-recall: inject relevant memories before agent starts -- 5 categories: preference, fact, decision, entity, other -- Health checks before memory operations -- Cross-reference: mem0_id in Obsidian frontmatter, obsidian_ref in Mem0 metadata -- Error handling: graceful degradation when either layer unavailable - -### Must NOT Have (Guardrails) -- NO citation-based memory verification (Phase 2) -- NO memory expiration/lifecycle management (Phase 2) -- NO memory deletion/forget functionality (Phase 2) -- NO memory search UI or Obsidian dashboards (Phase 2) -- NO conflict resolution UI between layers (manual edit only) -- NO unit tests (repo has no test infrastructure — agent QA only) -- NO subfolders in 50-zettelkasten/ or 70-tasks/ (respect flat structure) -- NO new memory categories beyond the 5 defined -- NO modifications to existing Obsidian templates (only ADD memory.md) -- NO changes to agents.json (no new agents or agent config changes) - ---- - -## Verification Strategy - -> **UNIVERSAL RULE: ZERO HUMAN INTERVENTION** -> -> ALL tasks MUST be verifiable WITHOUT any human action. -> Every criterion is verifiable by running a command or checking file existence. - -### Test Decision -- **Infrastructure exists**: NO (config-only repo) -- **Automated tests**: None (agent QA only) -- **Framework**: N/A - -### Agent-Executed QA Scenarios (MANDATORY — ALL tasks) - -Verification tools by deliverable type: - -| Type | Tool | How Agent Verifies | -|------|------|-------------------| -| Vault folders/files | Bash (ls, test -f) | Check existence, content | -| Skill YAML frontmatter | Bash (grep, python) | Parse and validate fields | -| Mem0 API | Bash (curl) | Send requests, parse JSON | -| Obsidian REST API | Bash (curl) | Read notes, check frontmatter | -| MCP server | Bash (npx) | Test server startup | - ---- - -## Execution Strategy - -### Parallel Execution Waves - -``` -Wave 1 (Start Immediately — no dependencies): -├── Task 1: CODEX vault memory infrastructure (folders, template, tags) -└── Task 3: Obsidian MCP server config documentation - -Wave 2 (After Wave 1 — depends on vault structure existing): -├── Task 2: CODEX vault documentation updates (AGENTS.md, README.md) -├── Task 4: Create core memory skill (skills/memory/SKILL.md) -├── Task 5: Update Mem0 memory skill -└── Task 6: Update Obsidian skill - -Wave 3 (After Wave 2 — depends on skill content for prompt/profile): -├── Task 7: Update Apollo agent prompt -└── Task 8: Update user context profile - -Wave 4 (After all — final validation): -└── Task 9: End-to-end validation - -Critical Path: Task 1 → Task 4 → Task 9 -Parallel Speedup: ~50% faster than sequential -``` - -### Dependency Matrix - -| Task | Depends On | Blocks | Can Parallelize With | -|------|------------|--------|---------------------| -| 1 | None | 2, 4, 5, 6 | 3 | -| 2 | 1 | 9 | 4, 5, 6 | -| 3 | None | 4 | 1 | -| 4 | 1, 3 | 7, 8, 9 | 5, 6 | -| 5 | 1 | 9 | 4, 6 | -| 6 | 1 | 9 | 4, 5 | -| 7 | 4 | 9 | 8 | -| 8 | 4 | 9 | 7 | -| 9 | ALL | None | None (final) | - -### Agent Dispatch Summary - -| Wave | Tasks | Recommended Agents | -|------|-------|-------------------| -| 1 | 1, 3 | task(category="quick", load_skills=["obsidian"], run_in_background=false) | -| 2 | 2, 4, 5, 6 | dispatch parallel: task(category="unspecified-high") for Task 4; task(category="quick") for 2, 5, 6 | -| 3 | 7, 8 | task(category="quick", run_in_background=false) | -| 4 | 9 | task(category="unspecified-low", run_in_background=false) | - ---- - -## TODOs - -- [x] 1. CODEX Vault Memory Infrastructure - - **What to do**: - - Create `80-memory/` folder with 5 subfolders: `preferences/`, `facts/`, `decisions/`, `entities/`, `other/` - - Create each subfolder with a `.gitkeep` file so git tracks empty directories - - Create `templates/memory.md` — memory note template with frontmatter: - ```yaml - --- - type: memory - category: # preference | fact | decision | entity | other - mem0_id: # Mem0 memory ID (e.g., "mem_abc123") - source: explicit # explicit | auto-capture - importance: # critical | high | medium | low - created: <% tp.date.now("YYYY-MM-DD") %> - updated: <% tp.date.now("YYYY-MM-DD") %> - tags: - - memory - sync_targets: [] - --- - - # Memory Title - - ## Content - - - ## Context - - - ## Related - - ``` - - Update `tag-taxonomy.md` — add `#memory` tag category with subtags: - ``` - #memory - ├── #memory/preference - ├── #memory/fact - ├── #memory/decision - ├── #memory/entity - └── #memory/other - ``` - Include usage examples and definitions for each category - - **Must NOT do**: - - Do NOT create subfolders inside 50-zettelkasten/ or 70-tasks/ - - Do NOT modify existing templates (only ADD memory.md) - - Do NOT use Templater syntax that doesn't match existing templates - - **Recommended Agent Profile**: - - **Category**: `quick` - - Reason: Simple file creation, no complex logic - - **Skills**: [`obsidian`] - - `obsidian`: Vault conventions, frontmatter patterns, template structure - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 1 (with Task 3) - - **Blocks**: Tasks 2, 4, 5, 6 - - **Blocked By**: None - - **References**: - - **Pattern References**: - - `/home/m3tam3re/CODEX/30-resources/` — Subfolder-by-type pattern to follow (bookmarks/, literature/, meetings/, people/, recipes/) - - `/home/m3tam3re/CODEX/templates/task.md` — Template frontmatter pattern (type, status, created, updated, tags, sync_targets) - - `/home/m3tam3re/CODEX/templates/bookmark.md` — Simpler template example - - **Documentation References**: - - `/home/m3tam3re/CODEX/AGENTS.md:22-27` — Frontmatter conventions (required fields: type, created, updated) - - `/home/m3tam3re/CODEX/AGENTS.md:163-176` — Template locations table (add memory row) - - `/home/m3tam3re/CODEX/tag-taxonomy.md:1-18` — Tag structure rules (max 3 levels, kebab-case) - - **WHY Each Reference Matters**: - - `30-resources/` shows that subfolders-by-type is the established vault pattern for categorized content - - `task.md` template shows the exact frontmatter field set expected by the vault - - `tag-taxonomy.md` rules show the 3-level max hierarchy constraint for new tags - - **Acceptance Criteria**: - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Verify 80-memory folder structure - Tool: Bash - Steps: - 1. test -d /home/m3tam3re/CODEX/80-memory/preferences - 2. test -d /home/m3tam3re/CODEX/80-memory/facts - 3. test -d /home/m3tam3re/CODEX/80-memory/decisions - 4. test -d /home/m3tam3re/CODEX/80-memory/entities - 5. test -d /home/m3tam3re/CODEX/80-memory/other - Expected Result: All 5 directories exist (exit code 0 for each) - Evidence: Shell output captured - - Scenario: Verify memory template exists with correct frontmatter - Tool: Bash - Steps: - 1. test -f /home/m3tam3re/CODEX/templates/memory.md - 2. grep "type: memory" /home/m3tam3re/CODEX/templates/memory.md - 3. grep "category:" /home/m3tam3re/CODEX/templates/memory.md - 4. grep "mem0_id:" /home/m3tam3re/CODEX/templates/memory.md - Expected Result: File exists and contains required frontmatter fields - Evidence: grep output captured - - Scenario: Verify tag-taxonomy updated with memory tags - Tool: Bash - Steps: - 1. grep "#memory" /home/m3tam3re/CODEX/tag-taxonomy.md - 2. grep "#memory/preference" /home/m3tam3re/CODEX/tag-taxonomy.md - 3. grep "#memory/fact" /home/m3tam3re/CODEX/tag-taxonomy.md - Expected Result: All memory tags present in taxonomy - Evidence: grep output captured - ``` - - **Commit**: YES - - Message: `feat(vault): add 80-memory folder structure and memory template` - - Files: `80-memory/`, `templates/memory.md`, `tag-taxonomy.md` - - Repo: `~/CODEX` - ---- - -- [x] 2. CODEX Vault Documentation Updates - - **What to do**: - - Update `AGENTS.md`: - - Add `80-memory/` row to Folder Structure table (line ~11) - - Add `#### 80-memory` section in Folder Details (after 70-tasks section, ~line 161) - - Update Folder Decision Tree to include memory branch: `Is it a memory/learned fact? → YES → 80-memory/` - - Add Memory template row to Template Locations table (line ~165) - - Add Memory Workflows section (after Sync Workflow): create memory, retrieve memory, dual-layer sync - - Update `README.md`: - - Add `80-memory/` to folder structure diagram with subfolders - - Add `80-memory/` row to Folder Details section - - Add memory template to Templates table - - **Must NOT do**: - - Do NOT rewrite existing sections — only ADD new content - - Do NOT remove any existing folder/template documentation - - **Recommended Agent Profile**: - - **Category**: `quick` - - Reason: Documentation additions to existing files, following established patterns - - **Skills**: [`obsidian`] - - `obsidian`: Vault documentation conventions - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Tasks 4, 5, 6) - - **Blocks**: Task 9 - - **Blocked By**: Task 1 (needs folder structure to reference) - - **References**: - - **Pattern References**: - - `/home/m3tam3re/CODEX/AGENTS.md:110-161` — Existing Folder Details sections to follow pattern - - `/home/m3tam3re/CODEX/AGENTS.md:75-108` — Folder Decision Tree format - - `/home/m3tam3re/CODEX/README.md` — Folder structure diagram format - - **WHY Each Reference Matters**: - - AGENTS.md folder details show the exact format: Purpose, Structure (flat/subfolders), Key trait, When to use, Naming convention - - Decision tree shows the exact `├─ YES →` format to follow - - **Acceptance Criteria**: - - ``` - Scenario: Verify AGENTS.md has 80-memory documentation - Tool: Bash - Steps: - 1. grep "80-memory" /home/m3tam3re/CODEX/AGENTS.md - 2. grep "Is it a memory" /home/m3tam3re/CODEX/AGENTS.md - 3. grep "templates/memory.md" /home/m3tam3re/CODEX/AGENTS.md - Expected Result: All three patterns found - Evidence: grep output - - Scenario: Verify README.md has 80-memory in structure - Tool: Bash - Steps: - 1. grep "80-memory" /home/m3tam3re/CODEX/README.md - 2. grep "preferences/" /home/m3tam3re/CODEX/README.md - Expected Result: Folder and subfolder documented - Evidence: grep output - ``` - - **Commit**: YES - - Message: `docs(vault): add 80-memory documentation to AGENTS.md and README.md` - - Files: `AGENTS.md`, `README.md` - - Repo: `~/CODEX` - ---- - -- [x] 3. Obsidian MCP Server Configuration Documentation - - **What to do**: - - Create `skills/memory/references/mcp-config.md` documenting: - - cyanheads/obsidian-mcp-server configuration for opencode.json - - Required environment variables: `OBSIDIAN_API_KEY`, `OBSIDIAN_BASE_URL`, `OBSIDIAN_VERIFY_SSL`, `OBSIDIAN_ENABLE_CACHE` - - opencode.json MCP section snippet: - ```json - "Obsidian-Vault": { - "command": ["npx", "obsidian-mcp-server"], - "environment": { - "OBSIDIAN_API_KEY": "", - "OBSIDIAN_BASE_URL": "http://127.0.0.1:27123", - "OBSIDIAN_VERIFY_SSL": "false", - "OBSIDIAN_ENABLE_CACHE": "true" - }, - "enabled": true, - "type": "local" - } - ``` - - Nix home-manager snippet showing how to add to `programs.opencode.settings.mcp` - - Note that this requires `home-manager switch` after adding - - Available MCP tools list: obsidian_read_note, obsidian_update_note, obsidian_global_search, obsidian_manage_frontmatter, obsidian_manage_tags, obsidian_list_notes, obsidian_delete_note, obsidian_search_replace - - How to get the API key from Obsidian: Settings → Local REST API plugin - - **Must NOT do**: - - Do NOT directly modify `~/.config/opencode/opencode.json` (Nix-managed) - - Do NOT modify `agents/agents.json` - - **Recommended Agent Profile**: - - **Category**: `quick` - - Reason: Creating a single reference doc - - **Skills**: [`obsidian`] - - `obsidian`: Obsidian REST API configuration knowledge - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 1 (with Task 1) - - **Blocks**: Task 4 - - **Blocked By**: None - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/AGENTS/skills/mem0-memory/SKILL.md:156-166` — Existing API reference pattern - - `/home/m3tam3re/.config/opencode/opencode.json:77-127` — Current MCP config format (Exa, Basecamp, etc.) - - **External References**: - - GitHub: `https://github.com/cyanheads/obsidian-mcp-server` — Config docs, env vars, tool list - - npm: `npx obsidian-mcp-server` — Installation method - - **WHY Each Reference Matters**: - - opencode.json MCP section shows exact JSON format needed (command array, environment, enabled, type) - - cyanheads repo shows required env vars and their defaults - - **Acceptance Criteria**: - - ``` - Scenario: Verify MCP config reference file exists - Tool: Bash - Steps: - 1. test -f /home/m3tam3re/p/AI/AGENTS/skills/memory/references/mcp-config.md - 2. grep "obsidian-mcp-server" /home/m3tam3re/p/AI/AGENTS/skills/memory/references/mcp-config.md - 3. grep "OBSIDIAN_API_KEY" /home/m3tam3re/p/AI/AGENTS/skills/memory/references/mcp-config.md - 4. grep "home-manager" /home/m3tam3re/p/AI/AGENTS/skills/memory/references/mcp-config.md - Expected Result: File exists with MCP config, env vars, and Nix instructions - Evidence: grep output - ``` - - **Commit**: YES (groups with Task 4) - - Message: `feat(memory): add core memory skill and MCP config reference` - - Files: `skills/memory/SKILL.md`, `skills/memory/references/mcp-config.md` - - Repo: `~/p/AI/AGENTS` - ---- - -- [x] 4. Create Core Memory Skill - - **What to do**: - - Create `skills/memory/SKILL.md` — the central orchestration skill for the dual-layer memory system - - YAML frontmatter: - ```yaml - --- - name: memory - description: "Dual-layer memory system (Mem0 + Obsidian CODEX). Use when: (1) storing information for future recall ('remember this'), (2) auto-capturing session insights, (3) recalling past decisions/preferences/facts, (4) injecting relevant context before tasks. Triggers: 'remember', 'recall', 'what do I know about', 'memory', session end." - compatibility: opencode - --- - ``` - - Sections to include: - 1. **Overview** — Dual-layer architecture (Mem0 operational + Obsidian documented) - 2. **Prerequisites** — Mem0 running at localhost:8000, Obsidian MCP configured (reference mcp-config.md) - 3. **Memory Categories** — 5 categories with definitions and examples: - - preference: Personal preferences (UI, workflow, communication style) - - fact: Objective information about user/work (role, tech stack, constraints) - - decision: Architectural/tool choices made (with rationale) - - entity: People, organizations, systems, concepts - - other: Everything else - 4. **Workflow 1: Store Memory (Explicit)** — User says "remember X": - - Classify category - - POST to Mem0 `/memories` with user_id, metadata (category, source: "explicit") - - Create Obsidian note in `80-memory//` using memory template - - Cross-reference: mem0_id in Obsidian frontmatter, obsidian_ref in Mem0 metadata - 5. **Workflow 2: Recall Memory** — User asks "what do I know about X": - - POST to Mem0 `/search` with query - - Return results with Obsidian note paths for reference - 6. **Workflow 3: Auto-Capture (Session End)** — Automatic extraction: - - Scan conversation for memory-worthy content (preferences stated, decisions made, important facts) - - Select top 3 highest-value memories - - For each: store in Mem0 AND create Obsidian note (source: "auto-capture") - - Present to user: "I captured these memories: [list]. Confirm or reject?" - 7. **Workflow 4: Auto-Recall (Session Start)** — Context injection: - - On session start, search Mem0 with user's first message - - If relevant memories found (score > 0.7), inject as `` context - - Limit to top 5 most relevant - 8. **Error Handling** — Graceful degradation: - - Mem0 unavailable: `curl http://localhost:8000/health` fails → skip all memory ops, warn user - - Obsidian unavailable: Store in Mem0 only, log that Obsidian sync failed - - Both unavailable: Skip memory entirely, continue without memory features - 9. **Integration** — How other skills/agents use memory: - - Load `memory` skill to access memory workflows - - Apollo is primary memory specialist - - Any agent can search/store via Mem0 REST API patterns in `mem0-memory` skill - - **Must NOT do**: - - Do NOT implement citation-based verification - - Do NOT implement memory deletion/forget - - Do NOT add memory expiration logic - - Do NOT create dashboards or search UI - - **Recommended Agent Profile**: - - **Category**: `unspecified-high` - - Reason: Core deliverable requiring careful architecture documentation, must be comprehensive - - **Skills**: [`obsidian`, `mem0-memory`] - - `obsidian`: Vault conventions, template patterns, frontmatter standards - - `mem0-memory`: Mem0 REST API patterns, endpoint details - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Tasks 2, 5, 6) - - **Blocks**: Tasks 7, 8, 9 - - **Blocked By**: Tasks 1, 3 - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/AGENTS/skills/mem0-memory/SKILL.md` — Full file: Mem0 REST API patterns, endpoint table, identity scopes, workflow patterns - - `/home/m3tam3re/p/AI/AGENTS/skills/obsidian/SKILL.md` — Full file: Obsidian REST API patterns, create/read/update note workflows, frontmatter conventions - - `/home/m3tam3re/p/AI/AGENTS/skills/reflection/SKILL.md` — Skill structure pattern (overview, workflows, integration) - - **API References**: - - `/home/m3tam3re/p/AI/AGENTS/skills/mem0-memory/SKILL.md:13-21` — Quick Reference endpoint table - - `/home/m3tam3re/p/AI/AGENTS/skills/mem0-memory/SKILL.md:90-109` — Identity scopes (user_id, agent_id, run_id) - - **Documentation References**: - - `/home/m3tam3re/CODEX/AGENTS.md:22-27` — Frontmatter conventions for vault notes - - `/home/m3tam3re/p/AI/AGENTS/skills/memory/references/mcp-config.md` — MCP server config (created in Task 3) - - **External References**: - - OpenClaw reference: `/home/m3tam3re/p/AI/openclaw/extensions/memory-lancedb/index.ts` — Auto-capture regex patterns, auto-recall injection, importance scoring (use as inspiration, not copy) - - **WHY Each Reference Matters**: - - mem0-memory SKILL.md provides the exact API endpoints and patterns to reference in dual-layer sync workflows - - obsidian SKILL.md provides the vault file creation patterns (curl commands, path encoding) - - openclaw memory-lancedb shows the auto-capture/auto-recall architecture to adapt - - **Acceptance Criteria**: - - ``` - Scenario: Validate skill YAML frontmatter - Tool: Bash - Steps: - 1. test -f /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - 2. grep "^name: memory$" /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - 3. grep "^compatibility: opencode$" /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - 4. grep "description:" /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - Expected Result: Valid YAML frontmatter with name, description, compatibility - Evidence: grep output - - Scenario: Verify skill contains all required workflows - Tool: Bash - Steps: - 1. grep -c "## Workflow" /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - 2. grep "Auto-Capture" /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - 3. grep "Auto-Recall" /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - 4. grep "Error Handling" /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - 5. grep "preference" /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - Expected Result: At least 4 workflow sections, auto-capture, auto-recall, error handling, categories - Evidence: grep output - - Scenario: Verify dual-layer sync pattern documented - Tool: Bash - Steps: - 1. grep "mem0_id" /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - 2. grep "obsidian_ref" /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - 3. grep "localhost:8000" /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - 4. grep "80-memory" /home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md - Expected Result: Cross-reference IDs and both layer endpoints documented - Evidence: grep output - ``` - - **Commit**: YES (groups with Task 3) - - Message: `feat(memory): add core memory skill and MCP config reference` - - Files: `skills/memory/SKILL.md`, `skills/memory/references/mcp-config.md` - - Repo: `~/p/AI/AGENTS` - ---- - -- [x] 5. Update Mem0 Memory Skill - - **What to do**: - - Add "Memory Categories" section after Identity Scopes (line ~109): - - Table: category name, definition, Obsidian path, example - - Metadata pattern for categories: `{"category": "preference", "source": "explicit|auto-capture"}` - - Add "Dual-Layer Sync" section after Workflow Patterns: - - After storing to Mem0, also create Obsidian note in `80-memory//` - - Include mem0_id from response in Obsidian note frontmatter - - Include obsidian_ref path in Mem0 metadata via update - - Add "Health Check" workflow: Check `/health` before any memory operations - - Add "Error Handling" section: What to do when Mem0 is unavailable - - **Must NOT do**: - - Do NOT delete existing content - - Do NOT change the YAML frontmatter description (triggers) - - Do NOT change existing API endpoint documentation - - **Recommended Agent Profile**: - - **Category**: `quick` - - Reason: Adding sections to existing well-structured file - - **Skills**: [`mem0-memory`] - - `mem0-memory`: Existing skill patterns to extend - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Tasks 2, 4, 6) - - **Blocks**: Task 9 - - **Blocked By**: Task 1 - - **References**: - - - `/home/m3tam3re/p/AI/AGENTS/skills/mem0-memory/SKILL.md` — Full file: current content to extend (preserve ALL existing content) - - **Acceptance Criteria**: - - ``` - Scenario: Verify categories added to mem0-memory skill - Tool: Bash - Steps: - 1. grep "Memory Categories" /home/m3tam3re/p/AI/AGENTS/skills/mem0-memory/SKILL.md - 2. grep "preference" /home/m3tam3re/p/AI/AGENTS/skills/mem0-memory/SKILL.md - 3. grep "Dual-Layer" /home/m3tam3re/p/AI/AGENTS/skills/mem0-memory/SKILL.md - 4. grep "80-memory" /home/m3tam3re/p/AI/AGENTS/skills/mem0-memory/SKILL.md - Expected Result: New sections present alongside existing content - Evidence: grep output - ``` - - **Commit**: YES - - Message: `feat(mem0-memory): add memory categories and dual-layer sync patterns` - - Files: `skills/mem0-memory/SKILL.md` - - Repo: `~/p/AI/AGENTS` - ---- - -- [x] 6. Update Obsidian Skill - - **What to do**: - - Add "Memory Folder Conventions" section (after Best Practices, ~line 228): - - Document `80-memory/` structure with 5 subfolders - - Memory note naming: kebab-case (e.g., `prefers-dark-mode.md`) - - Required frontmatter fields for memory notes (type, category, mem0_id, etc.) - - Add "Memory Note Workflows" section: - - Create memory note: POST to vault REST API with memory template content - - Read memory note: GET with path encoding for `80-memory/` paths - - Search memories: Search within `80-memory/` path filter - - Update Integration table to include memory skill handoff - - **Must NOT do**: - - Do NOT change existing content or workflows - - Do NOT modify the YAML frontmatter - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [`obsidian`] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 - - **Blocks**: Task 9 - - **Blocked By**: Task 1 - - **References**: - - `/home/m3tam3re/p/AI/AGENTS/skills/obsidian/SKILL.md` — Full file: current content to extend - - **Acceptance Criteria**: - - ``` - Scenario: Verify memory conventions added to obsidian skill - Tool: Bash - Steps: - 1. grep "Memory Folder" /home/m3tam3re/p/AI/AGENTS/skills/obsidian/SKILL.md - 2. grep "80-memory" /home/m3tam3re/p/AI/AGENTS/skills/obsidian/SKILL.md - 3. grep "mem0_id" /home/m3tam3re/p/AI/AGENTS/skills/obsidian/SKILL.md - Expected Result: Memory folder docs and frontmatter patterns present - Evidence: grep output - ``` - - **Commit**: YES - - Message: `feat(obsidian): add memory folder conventions and workflows` - - Files: `skills/obsidian/SKILL.md` - - Repo: `~/p/AI/AGENTS` - ---- - -- [x] 7. Update Apollo Agent Prompt - - **What to do**: - - Add "Memory Management" to Core Responsibilities list (after item 4): - - Store memories in dual-layer system (Mem0 + Obsidian CODEX) - - Retrieve memories via semantic search (Mem0) - - Auto-capture session insights at session end (max 3, confirm with user) - - Handle explicit "remember this" requests - - Inject relevant memories into context on session start - - Add memory-related tools to Tool Usage section - - Add memory error handling to Edge Cases - - **Must NOT do**: - - Do NOT remove existing responsibilities - - Do NOT change Apollo's identity or boundaries - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 3 (with Task 8) - - **Blocks**: Task 9 - - **Blocked By**: Task 4 - - **References**: - - `/home/m3tam3re/p/AI/AGENTS/prompts/apollo.txt` — Full file (47 lines): current prompt to extend - - **Acceptance Criteria**: - - ``` - Scenario: Verify memory management added to Apollo prompt - Tool: Bash - Steps: - 1. grep -i "memory" /home/m3tam3re/p/AI/AGENTS/prompts/apollo.txt | wc -l - 2. grep "Mem0" /home/m3tam3re/p/AI/AGENTS/prompts/apollo.txt - 3. grep "auto-capture" /home/m3tam3re/p/AI/AGENTS/prompts/apollo.txt - Expected Result: Multiple memory references, Mem0 mentioned, auto-capture documented - Evidence: grep output - ``` - - **Commit**: YES (groups with Task 8) - - Message: `feat(agents): add memory management to Apollo prompt and user profile` - - Files: `prompts/apollo.txt`, `context/profile.md` - - Repo: `~/p/AI/AGENTS` - ---- - -- [x] 8. Update User Context Profile - - **What to do**: - - Add "Memory System" section to `context/profile.md`: - - Mem0 endpoint: `http://localhost:8000` - - Mem0 user_id: `m3tam3re` (or whatever the user's ID should be) - - Obsidian vault path: `~/CODEX` - - Memory folder: `80-memory/` - - Auto-capture: enabled, max 3 per session - - Auto-recall: enabled, top 5 results, score threshold 0.7 - - Memory categories: preference, fact, decision, entity, other - - Obsidian MCP server: cyanheads/obsidian-mcp-server (see skills/memory/references/mcp-config.md) - - **Must NOT do**: - - Do NOT remove existing profile content - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 3 (with Task 7) - - **Blocks**: Task 9 - - **Blocked By**: Task 4 - - **References**: - - `/home/m3tam3re/p/AI/AGENTS/context/profile.md` — Current profile to extend - - **Acceptance Criteria**: - - ``` - Scenario: Verify memory config in profile - Tool: Bash - Steps: - 1. grep "Memory System" /home/m3tam3re/p/AI/AGENTS/context/profile.md - 2. grep "localhost:8000" /home/m3tam3re/p/AI/AGENTS/context/profile.md - 3. grep "80-memory" /home/m3tam3re/p/AI/AGENTS/context/profile.md - 4. grep "auto-capture" /home/m3tam3re/p/AI/AGENTS/context/profile.md - Expected Result: Memory system section with all config values - Evidence: grep output - ``` - - **Commit**: YES (groups with Task 7) - - Message: `feat(agents): add memory management to Apollo prompt and user profile` - - Files: `prompts/apollo.txt`, `context/profile.md` - - Repo: `~/p/AI/AGENTS` - ---- - -- [x] 9. End-to-End Validation - - **What to do**: - - Verify ALL files exist and contain expected content - - Run skill validation: `./scripts/test-skill.sh memory` - - Test Mem0 availability: `curl http://localhost:8000/health` - - Test Obsidian REST API: `curl http://127.0.0.1:27124/vault-info` - - Verify CODEX vault structure: `ls -la ~/CODEX/80-memory/` - - Verify template: `cat ~/CODEX/templates/memory.md | head -20` - - Check all YAML frontmatter valid across new/updated skill files - - **Must NOT do**: - - Do NOT create automated test infrastructure - - Do NOT modify any files — validation only - - **Recommended Agent Profile**: - - **Category**: `unspecified-low` - - Reason: Verification only, running commands and checking outputs - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: NO - - **Parallel Group**: Wave 4 (final, sequential) - - **Blocks**: None (final task) - - **Blocked By**: ALL tasks (1-8) - - **Acceptance Criteria**: - - ``` - Scenario: Full file existence check - Tool: Bash - Steps: - 1. test -f ~/p/AI/AGENTS/skills/memory/SKILL.md - 2. test -f ~/p/AI/AGENTS/skills/memory/references/mcp-config.md - 3. test -d ~/CODEX/80-memory/preferences - 4. test -f ~/CODEX/templates/memory.md - 5. grep "80-memory" ~/CODEX/AGENTS.md - 6. grep "#memory" ~/CODEX/tag-taxonomy.md - 7. grep "80-memory" ~/CODEX/README.md - 8. grep -i "memory" ~/p/AI/AGENTS/prompts/apollo.txt - 9. grep "Memory System" ~/p/AI/AGENTS/context/profile.md - Expected Result: All checks pass (exit code 0) - Evidence: Shell output captured - - Scenario: Mem0 health check - Tool: Bash - Preconditions: Mem0 server must be running - Steps: - 1. curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/health - Expected Result: HTTP 200 - Evidence: Status code captured - Note: If Mem0 not running, this test will fail — spin up Mem0 first - - Scenario: Obsidian REST API check - Tool: Bash - Preconditions: Obsidian desktop app must be running with Local REST API plugin - Steps: - 1. curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:27124/vault-info - Expected Result: HTTP 200 - Evidence: Status code captured - Note: Requires Obsidian desktop app to be open - - Scenario: Skill validation - Tool: Bash - Steps: - 1. cd ~/p/AI/AGENTS && ./scripts/test-skill.sh memory - Expected Result: Validation passes (no errors) - Evidence: Script output captured - ``` - - **Commit**: NO (validation only, no file changes) - ---- - -## Commit Strategy - -| After Task | Message | Files | Repo | Verification | -|------------|---------|-------|------|--------------| -| 1 | `feat(vault): add 80-memory folder structure and memory template` | 80-memory/, templates/memory.md, tag-taxonomy.md | ~/CODEX | ls + grep | -| 2 | `docs(vault): add 80-memory documentation to AGENTS.md and README.md` | AGENTS.md, README.md | ~/CODEX | grep | -| 3+4 | `feat(memory): add core memory skill and MCP config reference` | skills/memory/SKILL.md, skills/memory/references/mcp-config.md | ~/p/AI/AGENTS | test-skill.sh | -| 5 | `feat(mem0-memory): add memory categories and dual-layer sync patterns` | skills/mem0-memory/SKILL.md | ~/p/AI/AGENTS | grep | -| 6 | `feat(obsidian): add memory folder conventions and workflows` | skills/obsidian/SKILL.md | ~/p/AI/AGENTS | grep | -| 7+8 | `feat(agents): add memory management to Apollo prompt and user profile` | prompts/apollo.txt, context/profile.md | ~/p/AI/AGENTS | grep | - -**Note**: Two different git repos! CODEX and AGENTS commits are independent. - ---- - -## Success Criteria - -### Verification Commands -```bash -# CODEX vault structure -ls ~/CODEX/80-memory/ # Expected: preferences/ facts/ decisions/ entities/ other/ -cat ~/CODEX/templates/memory.md | head -5 # Expected: ---\ntype: memory -grep "#memory" ~/CODEX/tag-taxonomy.md # Expected: #memory/* tags - -# AGENTS skill validation -cd ~/p/AI/AGENTS && ./scripts/test-skill.sh memory # Expected: pass - -# Infrastructure (requires services running) -curl -s http://localhost:8000/health # Expected: 200 -curl -s http://127.0.0.1:27124/vault-info # Expected: 200 -``` - -### Final Checklist -- [x] All "Must Have" present (dual-layer, auto-capture, auto-recall, categories, health checks, error handling) -- [x] All "Must NOT Have" absent (no citation system, no deletion, no dashboards, no unit tests) -- [x] CODEX commits pushed (vault structure + docs) -- [x] AGENTS commits pushed (skills + prompts + profile) -- [x] User reminded to add Obsidian MCP to Nix config and run `home-manager switch` -- [x] User reminded to spin up Mem0 server before using memory features diff --git a/.sisyphus/plans/opencode-memory.md b/.sisyphus/plans/opencode-memory.md deleted file mode 100644 index 2c9b0fa..0000000 --- a/.sisyphus/plans/opencode-memory.md +++ /dev/null @@ -1,1634 +0,0 @@ -# Opencode Memory Plugin — Hybrid Memory System - -## TL;DR - -> **Quick Summary**: Build `opencode-memory`, a standalone Opencode plugin that replaces mem0+qdrant with a unified SQLite-based hybrid memory system. Indexes markdown files from the user's Obsidian vault (`~/CODEX/80-memory/`) and Opencode session transcripts into a SQLite database with FTS5 (BM25 keyword search) and vec0 (vector cosine similarity). Provides auto-recall on session start, auto-capture on session idle, and three agent tools (memory_search, memory_store, memory_get). Architecture inspired by Openclaw's battle-tested 1590-line MemoryIndexManager. -> -> **Deliverables**: -> - Standalone TypeScript git repo: `opencode-memory/` -> - Opencode plugin with session.created, session.idle, session.compacting hooks -> - Three custom tools: memory_search (hybrid query), memory_store (save markdown + index), memory_get (read specific file/lines) -> - SQLite database with FTS5 + vec0 extensions for hybrid search -> - OpenAI text-embedding-3 integration with content-hash caching -> - Session transcript indexer reading Opencode's JSON storage format -> - Full TDD test suite (bun test) -> - Updated AGENTS repo skills (memory, mem0-memory deprecation notes) -> -> **Estimated Effort**: Large -> **Parallel Execution**: YES — 5 waves -> **Critical Path**: Task 1 → 2 → 4 → 6 → 8 → 10 → 12 - ---- - -## Context - -### Original Request -"I want to implement a memory system for my Opencode Agent. A project named Openclaw has a very nice memory system and I would like to make something similar." User has mem0+qdrant running with Obsidian vault integration. Wants persistent, reliable memory with hybrid search. Open to replacing the existing architecture if something better exists. - -### Interview Summary -**Key Discussions**: -- **Architecture**: User chose full SQLite replacement (drop mem0) — the most reliable approach. Single source of truth (markdown), derived index (SQLite). -- **Embedding Provider**: OpenAI text-embedding-3 (user's explicit choice over Gemini and local). -- **Plugin Location**: Separate git repo (not in AGENTS repo). Own npm package/Nix input. -- **Test Strategy**: TDD with bun test. New repo needs full test infrastructure setup. -- **Session Indexing**: Yes, full transcripts. Read from `~/.local/share/opencode/storage/`. -- **Deployment**: Global via Nix home-manager. Plugin registered in `opencode.json`. - -**Research Findings**: -- **Openclaw architecture**: SQLite + FTS5 + vec0. MemoryIndexManager (1590 lines) handles file watching, chunking (tiktoken, 400 tokens/80 overlap), embedding (multi-provider), hybrid scoring (0.7 vector + 0.3 BM25). Two sources (memory files + session transcripts). Two tools (search + get). -- **Opencode plugin API**: JS/TS modules with event hooks. Key events: session.created, session.idle, session.compacted, experimental.session.compacting. Plugin context: { project, client, $, directory, worktree }. Custom tools via tool() helper with Zod schemas. -- **Opencode session storage**: JSON at `~/.local/share/opencode/storage/`. Sessions in `session/{project_hash}/ses_*.json`. Messages in `message/{session_id}/msg_*.json`. Fields: id, sessionID, role, agent, model, timestamps. -- **User's opencode config**: 3 existing plugins (oh-my-opencode, opencode-beads, opencode-antigravity-auth@beta). 6 agents. Google/Antigravity provider. Nix deployment. - -### Metis Review -**Identified Gaps** (all addressed): -- **vec0 availability**: Added verification step in Task 1. Fallback strategy if unavailable. -- **SQLite concurrency**: WAL mode + single write queue. Addressed in Task 2. -- **Embedding failure handling**: try/catch + queue + retry + graceful degradation. Addressed in Task 4 and Task 12. -- **Token budget for injection**: Hard limit 2000 tokens. Configurable. Addressed in Task 10. -- **Index rebuild**: `--rebuild` command via CLI entry point. Addressed in Task 12. -- **File sync conflicts**: Atomic writes (temp file + rename). Addressed in Task 5. -- **Deduplication/expiration**: Deferred to Phase 2. Scope locked. -- **Multi-project scope**: Global search by default. Configurable later. Phase 2. - ---- - -## Work Objectives - -### Core Objective -Build a standalone Opencode plugin that provides persistent, reliable, hybrid (vector + keyword) memory for all agent sessions, powered by SQLite+FTS5+vec0 over Obsidian markdown files. - -### Concrete Deliverables -- `opencode-memory/` — Standalone TypeScript repo with bun -- `src/index.ts` — Opencode plugin entry point (hooks + tools) -- `src/config.ts` — Configuration module (paths, defaults, overrides) -- `src/db.ts` — SQLite database initialization + schema + migrations -- `src/discovery.ts` — Markdown file discovery + text chunking -- `src/embeddings.ts` — OpenAI embedding provider + content-hash cache -- `src/indexer.ts` — File indexer (file → chunks → embeddings → SQLite) -- `src/search.ts` — Hybrid search engine (FTS5 BM25 + vec0 cosine) -- `src/sessions.ts` — Opencode session transcript parser + indexer -- `src/tools.ts` — Agent tools (memory_search, memory_store, memory_get) -- `src/types.ts` — Shared TypeScript types -- Full test suite in `src/__tests__/` (TDD, bun test) -- Updated AGENTS repo: `skills/memory/SKILL.md` + deprecation notes - -### Definition of Done -- [x] `bun test` passes all tests (0 failures) -- [~] Plugin loads in Opencode without errors (requires user deployment) -- [x] `memory_search` returns hybrid results from vault + session transcripts -- [x] `memory_store` creates markdown file + indexes it -- [x] `memory_get` reads specific file/line ranges -- [x] Auto-recall injects relevant memories on session.created -- [x] Auto-capture stores conversation insights on session.idle -- [x] Embedding cache avoids re-embedding unchanged content -- [x] SQLite can be rebuilt from markdown files alone (`--rebuild`) -- [x] Plugin fails gracefully (no crashes) when OpenAI is unavailable - -### Must Have -- Hybrid search (vector 0.7 + BM25 0.3 weights, configurable) -- OpenAI text-embedding-3 with content-hash caching -- Markdown source of truth at `~/CODEX/80-memory/` -- SQLite derived index at `~/.local/share/opencode-memory/index.db` -- Session transcript indexing from Opencode storage -- Graceful degradation on API/DB failures -- WAL mode for SQLite concurrent reads -- Atomic markdown writes (temp file + rename) -- Configurable chunk size (default 400 tokens, 80 overlap) -- Token budget limit for memory injection (default 2000 tokens) - -### Must NOT Have (Guardrails) -- **MUST NOT** block session operations if memory system fails — degraded mode > broken sessions -- **MUST NOT** exceed configurable token budget (default 2000) for memory context injection -- **MUST NOT** write files outside `~/CODEX/80-memory/` directory -- **MUST NOT** depend on Obsidian REST API — filesystem only -- **MUST NOT** depend on mem0 or qdrant — fully standalone -- **MUST NOT** implement memory deduplication (Phase 2) -- **MUST NOT** implement memory expiration/archival (Phase 2) -- **MUST NOT** implement memory graph/relationships (Phase 2) -- **MUST NOT** support multiple vaults (Phase 2) -- **MUST NOT** implement additional embedding providers beyond OpenAI (Phase 2) -- **MUST NOT** implement admin CLI/dashboard UI (Phase 2) -- **MUST NOT** auto-summarize memories (Phase 2) -- **MUST NOT** store embedding vectors in markdown files — SQLite only -- **MUST NOT** hard-code paths — use config with sensible defaults - ---- - -## Verification Strategy (MANDATORY) - -> **UNIVERSAL RULE: ZERO HUMAN INTERVENTION** -> -> ALL tasks in this plan MUST be verifiable WITHOUT any human action. -> This is NOT conditional — it applies to EVERY task, regardless of test strategy. -> -> **FORBIDDEN** — acceptance criteria that require: -> - "User manually tests..." / "User visually confirms..." -> - "User interacts with..." / "Ask user to verify..." -> - ANY step where a human must perform an action -> -> **ALL verification is executed by the agent** using tools (Bash, interactive_bash, etc.). No exceptions. - -### Test Decision -- **Infrastructure exists**: NO (new repo, needs setup) -- **Automated tests**: TDD (RED-GREEN-REFACTOR) -- **Framework**: bun test (built into bun runtime) - -### TDD Workflow - -Each TODO follows RED-GREEN-REFACTOR: - -**Task Structure:** -1. **RED**: Write failing test first - - Test file: `src/__tests__/{module}.test.ts` - - Test command: `bun test src/__tests__/{module}.test.ts` - - Expected: FAIL (test exists, implementation doesn't) -2. **GREEN**: Implement minimum code to pass - - Command: `bun test src/__tests__/{module}.test.ts` - - Expected: PASS -3. **REFACTOR**: Clean up while keeping green - - Command: `bun test` - - Expected: PASS (all tests still green) - -### Agent-Executed QA Scenarios (MANDATORY — ALL tasks) - -> Whether TDD is enabled or not, EVERY task MUST include Agent-Executed QA Scenarios. -> With TDD: QA scenarios complement unit tests at integration/E2E level. - -**Verification Tool by Deliverable Type:** - -| Type | Tool | How Agent Verifies | -|------|------|-------------------| -| TypeScript modules | Bash (bun test) | Run unit tests, check pass/fail | -| SQLite operations | Bash (bun run) | Execute script, inspect DB with sqlite3 CLI | -| Plugin integration | interactive_bash (tmux) | Load plugin in opencode, verify hooks fire | -| File I/O | Bash | Create/read/delete files, verify filesystem state | -| API integration | Bash (bun run) | Call OpenAI, verify embedding dimensions | - ---- - -## Execution Strategy - -### Parallel Execution Waves - -``` -Wave 1 (Start Immediately): -└── Task 1: Repo scaffold + test infrastructure + vec0 verification - -Wave 2 (After Wave 1): -├── Task 2: Configuration module -├── Task 3: SQLite schema + database module -└── Task 4: Markdown file discovery + text chunking - -Wave 3 (After Wave 2): -├── Task 5: Embedding provider + cache (depends: 3) -├── Task 6: File indexer pipeline (depends: 3, 4, 5) -└── Task 7: Session transcript parser (depends: 3, 4) - -Wave 4 (After Wave 3): -├── Task 8: FTS5 BM25 search (depends: 6) -├── Task 9: Vector search (depends: 6) -└── Task 10: Hybrid search combiner (depends: 8, 9) - -Wave 5 (After Wave 4): -├── Task 11: Agent tools — memory_search, memory_store, memory_get (depends: 10, 7) -└── Task 12: Plugin entry point — hooks + lifecycle (depends: 11) - -Wave 6 (After Wave 5): -├── Task 13: Integration testing + error handling + rebuild command (depends: 12) -└── Task 14: AGENTS repo skill updates + deployment config (depends: 13) -``` - -### Dependency Matrix - -| Task | Depends On | Blocks | Can Parallelize With | -|------|------------|--------|---------------------| -| 1 | None | 2, 3, 4 | None (foundation) | -| 2 | 1 | 5, 6, 7, 8, 9, 10, 11, 12 | 3, 4 | -| 3 | 1 | 5, 6, 7, 8, 9 | 2, 4 | -| 4 | 1 | 6, 7 | 2, 3 | -| 5 | 3 | 6 | 7 | -| 6 | 3, 4, 5 | 8, 9 | None | -| 7 | 3, 4 | 11 | 5 | -| 8 | 6 | 10 | 9 | -| 9 | 6 | 10 | 8 | -| 10 | 8, 9 | 11 | None | -| 11 | 10, 7 | 12 | None | -| 12 | 11 | 13 | None | -| 13 | 12 | 14 | None | -| 14 | 13 | None | None | - -### Agent Dispatch Summary - -| Wave | Tasks | Recommended Agents | -|------|-------|-------------------| -| 1 | 1 | task(category="unspecified-high", load_skills=[], run_in_background=false) | -| 2 | 2, 3, 4 | dispatch 3 parallel tasks after Wave 1 | -| 3 | 5, 6, 7 | sequential: 5 then 6 (depends on 5); 7 parallel with 5 | -| 4 | 8, 9, 10 | 8 and 9 parallel; 10 after both | -| 5 | 11, 12 | sequential | -| 6 | 13, 14 | sequential (14 is in AGENTS repo, different workdir) | - ---- - -## TODOs - -- [x] 1. Initialize Repository Scaffold + Test Infrastructure - - **What to do**: - - Create new git repo `opencode-memory/` at `~/p/AI/opencode-memory/` - - Initialize with `bun init` - - Install dependencies: `better-sqlite3`, `openai`, `tiktoken`, `chokidar`, `zod` - - Install dev dependencies: `@types/better-sqlite3`, `typescript` - - Create `tsconfig.json` (target ES2022, module ESNext, strict mode, paths alias) - - Create `src/` directory structure: - ``` - src/ - ├── __tests__/ - ├── index.ts (plugin entry — stub) - ├── config.ts (stub) - ├── db.ts (stub) - ├── discovery.ts (stub) - ├── embeddings.ts (stub) - ├── indexer.ts (stub) - ├── search.ts (stub) - ├── sessions.ts (stub) - ├── tools.ts (stub) - └── types.ts (stub) - ``` - - Verify `bun test` runs (create example test) - - **CRITICAL**: Verify SQLite vec0 extension availability: - - Try: `import Database from 'better-sqlite3'; db.loadExtension('vec0')` or check if `sqlite-vec` npm package works - - If vec0 unavailable: document findings, check `sqlite-vec` npm package as alternative, or plan for `@anthropic-ai/sdk` vector operations - - This is a blocking verification — if vec0 doesn't work, architecture needs adjustment - - Create `.gitignore` (node_modules, dist, *.db, .env) - - Create `package.json` with `"type": "module"`, scripts for test/build - - **Must NOT do**: - - Don't implement any real logic — stubs only - - Don't configure Nix packaging yet (Task 14) - - Don't create README or documentation files - - **Recommended Agent Profile**: - - **Category**: `unspecified-high` - - Reason: Repo scaffolding with critical platform verification (vec0). Not purely visual or algorithmic, but requires careful setup. - - **Skills**: none needed - - **Skills Evaluated but Omitted**: - - `frontend-ui-ux`: No UI involved - - **Parallelization**: - - **Can Run In Parallel**: NO (foundation task) - - **Parallel Group**: Wave 1 (solo) - - **Blocks**: Tasks 2, 3, 4 - - **Blocked By**: None - - **References**: - - **Pattern References** (existing code to follow): - - `/home/m3tam3re/p/AI/openclaw/src/memory/manager.ts:1-50` — Imports and dependency list (shows what Openclaw uses: better-sqlite3, tiktoken, chokidar, etc.) - - `/home/m3tam3re/p/AI/openclaw/src/memory/types.ts` — TypeScript type definitions for memory system - - **API/Type References**: - - Opencode plugin structure: `export default function(ctx) { ... }` — see Opencode plugin docs - - **External References**: - - SQLite vec0: `https://github.com/asg017/sqlite-vec` — vec0 extension for vector search in SQLite - - better-sqlite3: `https://github.com/WiseLibs/better-sqlite3` — Synchronous SQLite3 for Node.js - - Opencode plugin docs: `https://opencode.ai/docs/plugins/` — Plugin API and lifecycle - - **Acceptance Criteria**: - - **TDD (setup verification):** - - [ ] `bun test` runs and passes at least 1 example test - - [ ] `better-sqlite3` imports successfully - - [ ] vec0 extension loads or alternative documented - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Repo initializes and tests pass - Tool: Bash - Preconditions: ~/p/AI/opencode-memory/ does not exist - Steps: - 1. ls ~/p/AI/opencode-memory/ → should not exist - 2. After task: ls ~/p/AI/opencode-memory/src/ → should list all stub files - 3. bun test (in opencode-memory/) → 1 test passes, 0 failures - 4. bun run -e "import Database from 'better-sqlite3'; const db = new Database(':memory:'); console.log('SQLite OK:', db.pragma('journal_mode', { simple: true }))" - → prints "SQLite OK: memory" (or "wal") - Expected Result: Repo exists, tests pass, SQLite works - Evidence: Terminal output captured - - Scenario: vec0 extension availability check - Tool: Bash - Preconditions: opencode-memory/ initialized with better-sqlite3 - Steps: - 1. bun run -e "import Database from 'better-sqlite3'; const db = new Database(':memory:'); try { db.loadExtension('vec0'); console.log('vec0: AVAILABLE') } catch(e) { console.log('vec0: NOT AVAILABLE -', e.message) }" - 2. If NOT AVAILABLE: try `bun add sqlite-vec` and test with that package's loading mechanism - 3. Document result in src/db.ts as comment - Expected Result: vec0 status determined (available or alternative found) - Evidence: Terminal output + documented in code comment - ``` - - **Commit**: YES - - Message: `feat(scaffold): initialize opencode-memory repo with test infrastructure` - - Files: all scaffold files - - Pre-commit: `bun test` - ---- - -- [x] 2. Configuration Module - - **What to do**: - - **RED**: Write `src/__tests__/config.test.ts`: - - Test: default config returns valid paths for vault, db, session storage - - Test: config overrides work (custom vault path, custom db path) - - Test: config validates paths (vault must be absolute) - - Test: config has correct defaults for chunk size (400), overlap (80), weights (0.7/0.3), minScore (0.35), maxResults (6), tokenBudget (2000) - - **GREEN**: Implement `src/config.ts`: - - Define `MemoryConfig` interface with all configuration fields - - Default vault path: `~/CODEX/80-memory/` - - Default DB path: `~/.local/share/opencode-memory/index.db` - - Default session path: `~/.local/share/opencode/storage/` - - Chunking: `{ tokens: 400, overlap: 80 }` - - Search: `{ vectorWeight: 0.7, textWeight: 0.3, minScore: 0.35, maxResults: 6 }` - - Embedding: `{ model: "text-embedding-3-small", dimensions: 1536 }` - - TokenBudget: `{ maxInjectTokens: 2000 }` - - `resolveConfig(overrides?: Partial): MemoryConfig` — merges overrides with defaults, expands `~` to `$HOME` - - **REFACTOR**: Extract types to `src/types.ts` - - **Must NOT do**: - - Don't read from config files on disk (hardcoded defaults + programmatic overrides) - - Don't implement environment variable loading (keep simple) - - **Recommended Agent Profile**: - - **Category**: `quick` - - Reason: Small, focused module. Config is straightforward. - - **Skills**: none - - **Skills Evaluated but Omitted**: - - All: This is a simple data structure + defaults task - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Tasks 3, 4) - - **Blocks**: Tasks 5, 6, 7, 8, 9, 10, 11, 12 - - **Blocked By**: Task 1 - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/openclaw/src/agents/memory-search.ts` — Openclaw's config resolution pattern (defaults + overrides) - - `/home/m3tam3re/p/AI/openclaw/src/memory/backend-config.ts` — Backend configuration with defaults - - **API/Type References**: - - `/home/m3tam3re/p/AI/openclaw/src/memory/types.ts` — Config type definitions to adapt - - **Acceptance Criteria**: - - **TDD:** - - [ ] Test file: `src/__tests__/config.test.ts` - - [ ] `bun test src/__tests__/config.test.ts` → PASS (all config tests green) - - [ ] Default config has all required fields with correct values - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Default config returns correct values - Tool: Bash (bun test) - Preconditions: Task 1 complete, repo initialized - Steps: - 1. bun test src/__tests__/config.test.ts - 2. Assert: all tests pass - 3. Assert: default vault path ends with "CODEX/80-memory" - 4. Assert: chunk tokens = 400, overlap = 80 - 5. Assert: vector weight = 0.7, text weight = 0.3 - Expected Result: All config defaults correct - Evidence: Test output captured - ``` - - **Commit**: YES (groups with 3, 4) - - Message: `feat(config): add configuration module with sensible defaults` - - Files: `src/config.ts`, `src/types.ts`, `src/__tests__/config.test.ts` - - Pre-commit: `bun test` - ---- - -- [x] 3. SQLite Schema + Database Module - - **What to do**: - - **RED**: Write `src/__tests__/db.test.ts`: - - Test: `initDatabase(":memory:")` creates all tables (meta, files, chunks, embedding_cache, chunks_fts, chunks_vec) - - Test: `meta` table stores schema version - - Test: `files` table accepts inserts with (path, source, hash, indexed_at) - - Test: `chunks` table accepts inserts with (id, file_path, start_line, end_line, content_hash, model, text, embedding BLOB) - - Test: `embedding_cache` table stores (content_hash, model, embedding BLOB, created_at) - - Test: FTS5 virtual table `chunks_fts` is searchable - - Test: vec0 virtual table `chunks_vec` is searchable (or skip if vec0 unavailable — see Task 1 findings) - - Test: WAL mode is enabled - - Test: `closeDatabase()` closes cleanly - - **GREEN**: Implement `src/db.ts`: - - `initDatabase(dbPath: string): Database` — creates/opens SQLite, runs schema, enables WAL - - Schema (following Openclaw's `memory-schema.ts`): - ```sql - CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT); - CREATE TABLE IF NOT EXISTS files (path TEXT PRIMARY KEY, source TEXT NOT NULL, hash TEXT NOT NULL, indexed_at INTEGER NOT NULL); - CREATE TABLE IF NOT EXISTS chunks (id TEXT PRIMARY KEY, file_path TEXT NOT NULL REFERENCES files(path), start_line INTEGER, end_line INTEGER, content_hash TEXT NOT NULL, model TEXT NOT NULL, text TEXT NOT NULL, embedding BLOB); - CREATE TABLE IF NOT EXISTS embedding_cache (content_hash TEXT NOT NULL, model TEXT NOT NULL, embedding BLOB NOT NULL, created_at INTEGER NOT NULL, PRIMARY KEY (content_hash, model)); - CREATE VIRTUAL TABLE IF NOT EXISTS chunks_fts USING fts5(text, content='chunks', content_rowid='rowid'); - CREATE VIRTUAL TABLE IF NOT EXISTS chunks_vec USING vec0(embedding float[1536]); - ``` - - Store schema version in meta table - - Enable WAL mode: `PRAGMA journal_mode=WAL` - - Enable foreign keys: `PRAGMA foreign_keys=ON` - - Load vec0 extension (or handle unavailability gracefully) - - **REFACTOR**: Add helper functions for common DB operations - - **Must NOT do**: - - Don't implement migration logic (v1 schema only) - - Don't add indexes beyond what schema requires (premature optimization) - - Don't implement any search logic (Task 8, 9) - - **Recommended Agent Profile**: - - **Category**: `unspecified-high` - - Reason: SQLite schema with extensions (FTS5, vec0) requires careful handling. Extension loading may need platform-specific workarounds. - - **Skills**: none - - **Skills Evaluated but Omitted**: - - All: Pure database schema work, no domain-specific skill needed - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Tasks 2, 4) - - **Blocks**: Tasks 5, 6, 7, 8, 9 - - **Blocked By**: Task 1 (needs vec0 findings) - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/openclaw/src/memory/memory-schema.ts` — EXACT schema to follow (adapt table names/columns). This is the primary reference — copy the structure closely. - - `/home/m3tam3re/p/AI/openclaw/src/memory/manager.ts:80-150` — Database initialization logic, WAL mode, extension loading - - **External References**: - - better-sqlite3 API: `https://github.com/WiseLibs/better-sqlite3/blob/master/docs/api.md` - - FTS5 docs: `https://www.sqlite.org/fts5.html` - - vec0 docs: `https://alexgarcia.xyz/sqlite-vec/` - - **Acceptance Criteria**: - - **TDD:** - - [ ] Test file: `src/__tests__/db.test.ts` - - [ ] `bun test src/__tests__/db.test.ts` → PASS - - [ ] All 8 schema tests pass - - [ ] WAL mode enabled (verified via PRAGMA) - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Database creates all tables and extensions - Tool: Bash (bun run) - Preconditions: Task 1 complete - Steps: - 1. bun test src/__tests__/db.test.ts - 2. Assert: all tests pass - 3. bun run -e "import { initDatabase } from './src/db'; const db = initDatabase(':memory:'); console.log(db.pragma('journal_mode', {simple:true})); console.log(JSON.stringify(db.prepare('SELECT name FROM sqlite_master WHERE type=\"table\"').all()))" - 4. Assert: journal_mode = "wal" - 5. Assert: tables include "meta", "files", "chunks", "embedding_cache" - Expected Result: Schema created correctly with WAL mode - Evidence: Terminal output captured - - Scenario: FTS5 virtual table is functional - Tool: Bash (bun run) - Preconditions: Database module implemented - Steps: - 1. Create in-memory db, insert test chunk with text "TypeScript is my preferred language" - 2. Query: SELECT * FROM chunks_fts WHERE chunks_fts MATCH 'TypeScript' - 3. Assert: 1 result returned - Expected Result: FTS5 search returns matching content - Evidence: Terminal output captured - ``` - - **Commit**: YES (groups with 2, 4) - - Message: `feat(db): SQLite schema with FTS5, vec0, WAL mode` - - Files: `src/db.ts`, `src/__tests__/db.test.ts` - - Pre-commit: `bun test` - ---- - -- [x] 4. Markdown File Discovery + Text Chunking - - **What to do**: - - **RED**: Write `src/__tests__/discovery.test.ts`: - - Test: `discoverFiles(vaultPath)` finds all .md files recursively - - Test: ignores non-.md files (images, PDFs, etc.) - - Test: returns absolute paths with metadata (size, mtime) - - Test: handles empty directory (returns []) - - Test: handles non-existent directory (throws descriptive error) - - Test: `computeFileHash(content)` returns consistent SHA-256 hex - - Test: `chunkText(text, { tokens: 400, overlap: 80 })` splits correctly - - Test: chunks have start_line and end_line metadata - - Test: chunks overlap correctly (last 80 tokens of chunk N = first 80 tokens of chunk N+1) - - Test: single small file (< 400 tokens) returns 1 chunk - - Test: empty file returns 0 chunks - - Test: chunk content_hash is stable for same content - - **GREEN**: Implement `src/discovery.ts`: - - `discoverFiles(vaultPath: string, extensions?: string[]): FileInfo[]` — recursive glob for .md files - - `computeFileHash(content: string): string` — SHA-256 hex hash - - `chunkText(text: string, config: ChunkConfig): Chunk[]` — split text by token count using tiktoken (cl100k_base encoding, matching Openclaw). Each chunk gets start_line/end_line and content_hash. - - `readFileContent(filePath: string): string` — read file with UTF-8, handle encoding errors - - **REFACTOR**: Optimize chunking for large files, ensure stable hashing - - **Must NOT do**: - - Don't implement file watching (that's in indexer lifecycle, Task 6) - - Don't parse YAML frontmatter (just treat as text for now) - - Don't handle binary files (filter by extension) - - **Recommended Agent Profile**: - - **Category**: `unspecified-low` - - Reason: Straightforward file I/O and text processing. No complex algorithms. - - **Skills**: none - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Tasks 2, 3) - - **Blocks**: Tasks 6, 7 - - **Blocked By**: Task 1 - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/openclaw/src/memory/internal.ts` — File discovery functions, chunking logic, hash computation. This is the PRIMARY reference for chunking algorithm. - - `/home/m3tam3re/p/AI/openclaw/src/memory/manager.ts:200-350` — How files are discovered and processed - - **External References**: - - tiktoken: `https://github.com/openai/tiktoken` — Token counting for chunking - - Node.js crypto: Built-in `crypto.createHash('sha256')` for hashing - - **Acceptance Criteria**: - - **TDD:** - - [ ] Test file: `src/__tests__/discovery.test.ts` - - [ ] `bun test src/__tests__/discovery.test.ts` → PASS (all 12 tests) - - [ ] Uses tiktoken cl100k_base encoding for token counting - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Discover files in test fixture directory - Tool: Bash - Preconditions: Create test fixture dir with 3 .md files and 1 .png - Steps: - 1. mkdir -p /tmp/test-vault && echo "# Test" > /tmp/test-vault/note1.md && echo "# Test 2" > /tmp/test-vault/note2.md && echo "deep" > /tmp/test-vault/sub/note3.md && touch /tmp/test-vault/image.png - 2. bun run -e "import { discoverFiles } from './src/discovery'; console.log(JSON.stringify(discoverFiles('/tmp/test-vault')))" - 3. Assert: 3 files returned (all .md), image.png excluded - Expected Result: Only .md files discovered - Evidence: Terminal output - - Scenario: Chunk text with correct overlap - Tool: Bash (bun test) - Preconditions: Discovery module implemented - Steps: - 1. bun test src/__tests__/discovery.test.ts --filter "overlap" - 2. Assert: overlap test passes - 3. Verify chunk N end overlaps with chunk N+1 start - Expected Result: Chunks overlap by configured token count - Evidence: Test output - ``` - - **Commit**: YES (groups with 2, 3) - - Message: `feat(discovery): markdown file discovery and text chunking with tiktoken` - - Files: `src/discovery.ts`, `src/__tests__/discovery.test.ts` - - Pre-commit: `bun test` - ---- - -- [x] 5. Embedding Provider + Content-Hash Cache - - **What to do**: - - **RED**: Write `src/__tests__/embeddings.test.ts`: - - Test: `EmbeddingProvider.embed(text)` returns float array of correct dimensions (1536 for text-embedding-3-small) - - Test: `EmbeddingProvider.embedBatch(texts)` handles multiple texts - - Test: Cache stores embedding by (content_hash, model) key - - Test: Cache hit returns stored embedding without API call (mock API) - - Test: Cache miss calls API, stores result, returns embedding - - Test: API failure throws descriptive error (does NOT crash) - - Test: API rate limit triggers retry with exponential backoff (mock) - - Test: `embeddingToBuffer(float[])` converts to Buffer for SQLite BLOB storage - - Test: `bufferToEmbedding(Buffer)` converts back to float[] - - **GREEN**: Implement `src/embeddings.ts`: - - `class EmbeddingProvider`: - - Constructor takes `{ apiKey, model, dimensions, db }` — db for cache table - - `async embed(text: string): Promise` — check cache first, then API - - `async embedBatch(texts: string[], hashes: string[]): Promise` — batch with cache check per item - - Cache read: `SELECT embedding FROM embedding_cache WHERE content_hash = ? AND model = ?` - - Cache write: `INSERT INTO embedding_cache (content_hash, model, embedding, created_at) VALUES (?, ?, ?, ?)` - - API call: `openai.embeddings.create({ model, input, dimensions })` - - Retry logic: exponential backoff (1s, 2s, 4s) on 429/500, max 3 retries - - `embeddingToBuffer(embedding: number[]): Buffer` — Float32Array → Buffer - - `bufferToEmbedding(buffer: Buffer): number[]` — Buffer → Float32Array → number[] - - **REFACTOR**: Extract cache logic to separate internal function - - **Must NOT do**: - - Don't support other embedding providers (Phase 2) - - Don't implement local/offline fallback (Phase 2) - - Don't implement cost tracking - - **Recommended Agent Profile**: - - **Category**: `unspecified-high` - - Reason: API integration with retry logic, binary serialization, caching. Moderate complexity. - - **Skills**: none - - **Parallelization**: - - **Can Run In Parallel**: YES (parallel with Task 7) - - **Parallel Group**: Wave 3 (first in wave — 6 depends on this) - - **Blocks**: Task 6 - - **Blocked By**: Task 3 (needs db for cache table) - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/openclaw/src/memory/embeddings.ts` — Multi-provider embedding system. Focus on the OpenAI provider implementation and the cache logic. Copy the binary serialization (Float32Array ↔ Buffer). - - `/home/m3tam3re/p/AI/openclaw/src/memory/manager.ts:400-500` — How embeddings are called and cached during indexing - - **External References**: - - OpenAI Embeddings API: `https://platform.openai.com/docs/api-reference/embeddings` - - OpenAI npm: `https://github.com/openai/openai-node` - - **WHY Each Reference Matters**: - - `embeddings.ts`: Exact binary serialization pattern (Float32Array ↔ Buffer) is critical for SQLite BLOB storage. Also shows retry logic. - - `manager.ts:400-500`: Shows how cache is checked before API call, and how batch embedding works. - - **Acceptance Criteria**: - - **TDD:** - - [ ] Test file: `src/__tests__/embeddings.test.ts` - - [ ] `bun test src/__tests__/embeddings.test.ts` → PASS - - [ ] Cache hit skips API call (verified via mock) - - [ ] Buffer conversion round-trips correctly - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Embedding produces correct dimensions - Tool: Bash (bun run) - Preconditions: OPENAI_API_KEY set in environment - Steps: - 1. bun run -e "import { EmbeddingProvider } from './src/embeddings'; import { initDatabase } from './src/db'; const db = initDatabase(':memory:'); const ep = new EmbeddingProvider({ db, model: 'text-embedding-3-small' }); const emb = await ep.embed('test'); console.log('dimensions:', emb.length)" - 2. Assert: dimensions = 1536 - Expected Result: Embedding has 1536 dimensions - Evidence: Terminal output - - Scenario: Cache prevents duplicate API calls - Tool: Bash (bun test) - Preconditions: Embeddings module with mock - Steps: - 1. bun test src/__tests__/embeddings.test.ts --filter "cache" - 2. Assert: mock API called once for first embed, zero times for second (same content) - Expected Result: Second call uses cache - Evidence: Test output - ``` - - **Commit**: YES - - Message: `feat(embeddings): OpenAI embedding provider with content-hash cache` - - Files: `src/embeddings.ts`, `src/__tests__/embeddings.test.ts` - - Pre-commit: `bun test` - ---- - -- [x] 6. File Indexer Pipeline - - **What to do**: - - **RED**: Write `src/__tests__/indexer.test.ts`: - - Test: `indexFile(filePath, source, db, embedder)` reads file, chunks it, embeds chunks, stores in SQLite - - Test: file hash is stored in `files` table - - Test: chunks are stored in `chunks` table with correct file_path, start_line, end_line - - Test: FTS5 table is populated with chunk text - - Test: vec0 table is populated with embeddings (if available) - - Test: re-indexing unchanged file (same hash) is a no-op - - Test: re-indexing changed file (different hash) replaces old chunks - - Test: `removeFile(filePath, db)` removes file + all its chunks from all tables - - Test: `indexDirectory(vaultPath, source, db, embedder)` indexes all .md files - - Test: `indexDirectory` skips already-indexed files with same hash - - Test: `indexDirectory` removes files that no longer exist on disk - - **GREEN**: Implement `src/indexer.ts`: - - `async indexFile(filePath, source, db, embedder, config)`: - 1. Read file content - 2. Compute file hash - 3. Check if file already indexed with same hash → skip if unchanged - 4. Delete old chunks for this file (if re-indexing) - 5. Chunk the text (using discovery.chunkText) - 6. Embed all chunks (using embedder.embedBatch — leverages cache) - 7. Insert file record into `files` table - 8. Insert chunks into `chunks`, `chunks_fts`, `chunks_vec` tables - 9. Wrap in transaction for atomicity - - `removeFile(filePath, db)`: Delete from files, chunks, chunks_fts, chunks_vec - - `async indexDirectory(vaultPath, source, db, embedder, config)`: - 1. Discover all .md files - 2. Get list of currently indexed files from DB - 3. Remove files from DB that no longer exist on disk - 4. Index new/changed files - 5. Skip unchanged files (hash match) - - **REFACTOR**: Ensure all DB operations are in transactions - - **Must NOT do**: - - Don't implement file watching (lifecycle concern, Task 12) - - Don't implement session indexing (Task 7) - - Don't add progress reporting (Phase 2) - - **Recommended Agent Profile**: - - **Category**: `unspecified-high` - - Reason: Core pipeline orchestrating discovery, embedding, and database operations. Transaction management. Most complex single task. - - **Skills**: none - - **Parallelization**: - - **Can Run In Parallel**: NO (depends on 3, 4, 5) - - **Parallel Group**: Wave 3 (after Task 5 completes) - - **Blocks**: Tasks 8, 9 - - **Blocked By**: Tasks 3, 4, 5 - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/openclaw/src/memory/manager.ts:350-600` — `syncFiles()` method: the EXACT pattern for indexing. Shows hash checking, chunk insertion, FTS5/vec0 population, transaction wrapping. This is the PRIMARY reference. - - `/home/m3tam3re/p/AI/openclaw/src/memory/manager.ts:600-800` — How file removal and re-indexing works - - **Acceptance Criteria**: - - **TDD:** - - [ ] Test file: `src/__tests__/indexer.test.ts` - - [ ] `bun test src/__tests__/indexer.test.ts` → PASS (all 11 tests) - - [ ] Unchanged files are skipped (hash check) - - [ ] Changed files replace old chunks (not append) - - [ ] Deleted files are removed from index - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Index a directory of markdown files - Tool: Bash - Preconditions: DB module, discovery, embeddings all working. Test fixtures exist. - Steps: - 1. Create 3 test .md files in /tmp/test-vault/ - 2. bun run -e "import { indexDirectory } from './src/indexer'; import { initDatabase } from './src/db'; import { EmbeddingProvider } from './src/embeddings'; const db = initDatabase(':memory:'); const ep = new EmbeddingProvider({db, model:'text-embedding-3-small'}); await indexDirectory('/tmp/test-vault', 'memory', db, ep, defaultConfig); const files = db.prepare('SELECT * FROM files').all(); const chunks = db.prepare('SELECT * FROM chunks').all(); console.log('files:', files.length, 'chunks:', chunks.length)" - 3. Assert: files = 3, chunks > 3 (depends on content length) - Expected Result: All files indexed with chunks in DB - Evidence: Terminal output - - Scenario: Re-index unchanged files is a no-op - Tool: Bash - Preconditions: Directory already indexed - Steps: - 1. Run indexDirectory twice on same unchanged directory - 2. Count API calls to embedding provider (mock) - 3. Assert: 0 embedding API calls on second run - Expected Result: No re-embedding of unchanged content - Evidence: Test output - ``` - - **Commit**: YES - - Message: `feat(indexer): file indexer pipeline with hash-based change detection` - - Files: `src/indexer.ts`, `src/__tests__/indexer.test.ts` - - Pre-commit: `bun test` - ---- - -- [x] 7. Session Transcript Parser + Indexer - - **What to do**: - - **RED**: Write `src/__tests__/sessions.test.ts`: - - Test: `discoverSessions(storagePath)` finds all session directories - - Test: `parseSession(sessionDir)` reads session JSON + message JSONs, returns structured transcript - - Test: `sessionToText(session)` converts to "User: ... / Assistant: ..." text format - - Test: handles session with 0 messages (returns empty text) - - Test: handles corrupted/missing JSON files gracefully (skip, don't crash) - - Test: `indexSessions(storagePath, db, embedder, config)` indexes all session transcripts - - Test: already-indexed sessions (by file hash) are skipped - - Test: new sessions since last index are added - - **GREEN**: Implement `src/sessions.ts`: - - `discoverSessions(storagePath: string): SessionDir[]` — find all `message/{session_id}/` directories under storage path. Also check project-specific dirs in `session/{hash}/`. - - `parseSession(sessionDir: string): ParsedSession` — read all msg_*.json files, sort by timestamp, extract role + content fields. Handle missing/corrupt files with try/catch. - - `sessionToText(session: ParsedSession): string` — format as: - ``` - [Session: {title}] [{date}] - User: {message} - Assistant: {message} - ... - ``` - - `async indexSessions(storagePath, db, embedder, config)`: - 1. Discover all session directories - 2. For each: compute hash of combined message content - 3. Skip if already indexed with same hash - 4. Convert to text, chunk, embed, store with source="sessions" - - **REFACTOR**: Handle edge cases (empty sessions, partial data) - - **Must NOT do**: - - Don't index tool call details (just user/assistant messages) - - Don't implement session filtering (all sessions indexed) - - Don't implement incremental message indexing (whole session = one unit) - - **Recommended Agent Profile**: - - **Category**: `unspecified-high` - - Reason: Parsing JSON files from unknown directory structure, handling corruption, integrating with indexer pipeline. Moderate complexity. - - **Skills**: none - - **Parallelization**: - - **Can Run In Parallel**: YES (parallel with Task 5) - - **Parallel Group**: Wave 3 - - **Blocks**: Task 11 - - **Blocked By**: Tasks 3, 4 - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/openclaw/src/memory/session-files.ts` — Session transcript conversion. Shows how JSONL transcripts are converted to searchable text. Adapt for Opencode's JSON format. - - `/home/m3tam3re/p/AI/openclaw/src/memory/manager.ts:800-1000` — How session sources are handled alongside memory sources - - **API/Type References**: - - Opencode session JSON format (discovered during research): - - Session: `{ id, slug, projectID, directory, title, time: { created, updated }, summary }` - - Message: `{ id, sessionID, role, time: { created }, agent, model }` - - Session storage: `~/.local/share/opencode/storage/session/{project_hash}/ses_*.json` - - Message storage: `~/.local/share/opencode/storage/message/{session_id}/msg_*.json` - - **WHY Each Reference Matters**: - - `session-files.ts`: Exact pattern for converting conversation transcripts to text format suitable for chunking and embedding. - - Session JSON format: Needed to parse the actual message content from Opencode's storage. - - **Acceptance Criteria**: - - **TDD:** - - [ ] Test file: `src/__tests__/sessions.test.ts` - - [ ] `bun test src/__tests__/sessions.test.ts` → PASS (all 8 tests) - - [ ] Handles corrupt JSON without crashing - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Parse real Opencode session transcripts - Tool: Bash - Preconditions: Opencode storage exists at ~/.local/share/opencode/storage/ - Steps: - 1. bun run -e "import { discoverSessions } from './src/sessions'; const sessions = discoverSessions(process.env.HOME + '/.local/share/opencode/storage'); console.log('found sessions:', sessions.length)" - 2. Assert: sessions.length > 0 - 3. Parse first session and verify text output contains "User:" and "Assistant:" markers - Expected Result: Real session transcripts parseable - Evidence: Terminal output (first 200 chars of transcript) - - Scenario: Corrupt JSON file doesn't crash parser - Tool: Bash - Preconditions: Test fixture with corrupt JSON - Steps: - 1. Create test dir with valid session JSON + one corrupt msg file (invalid JSON) - 2. bun run -e "import { parseSession } from './src/sessions'; const s = parseSession('/tmp/test-session'); console.log('messages:', s.messages.length)" - 3. Assert: no error thrown, corrupt message skipped - Expected Result: Graceful handling, partial results - Evidence: Terminal output - ``` - - **Commit**: YES - - Message: `feat(sessions): Opencode session transcript parser and indexer` - - Files: `src/sessions.ts`, `src/__tests__/sessions.test.ts` - - Pre-commit: `bun test` - ---- - -- [x] 8. FTS5 BM25 Search Module - - **What to do**: - - **RED**: Write `src/__tests__/search-fts.test.ts`: - - Test: `searchFTS(db, query, maxResults)` returns matching chunks with BM25 rank scores - - Test: matches on exact keywords - - Test: matches on partial words (FTS5 prefix queries) - - Test: returns empty array for no matches - - Test: results are ranked by BM25 relevance (best first) - - Test: respects maxResults limit - - Test: returns chunk metadata (file_path, start_line, end_line, text, score) - - **GREEN**: Implement FTS5 search in `src/search.ts`: - - `searchFTS(db, query, maxResults): SearchResult[]`: - ```sql - SELECT c.id, c.file_path, c.start_line, c.end_line, c.text, - rank AS score - FROM chunks_fts - JOIN chunks c ON chunks_fts.rowid = c.rowid - WHERE chunks_fts MATCH ? - ORDER BY rank - LIMIT ? - ``` - - Normalize BM25 scores to 0-1 range for hybrid combiner - - Handle FTS5 query syntax (escape special characters) - - **Must NOT do**: - - Don't implement hybrid combination (Task 10) - - Don't add query preprocessing or expansion - - **Recommended Agent Profile**: - - **Category**: `quick` - - Reason: Single SQL query + score normalization. Small, focused module. - - **Skills**: none - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 4 (with Task 9) - - **Blocks**: Task 10 - - **Blocked By**: Task 6 - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/openclaw/src/memory/hybrid.ts:50-100` — BM25 search implementation and score normalization. This is the PRIMARY reference. - - `/home/m3tam3re/p/AI/openclaw/src/memory/manager.ts:1000-1100` — How FTS5 queries are constructed and executed - - **External References**: - - SQLite FTS5: `https://www.sqlite.org/fts5.html#the_bm25_function` - - **Acceptance Criteria**: - - **TDD:** - - [ ] Test file: `src/__tests__/search-fts.test.ts` - - [ ] `bun test src/__tests__/search-fts.test.ts` → PASS (all 7 tests) - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: FTS5 search finds indexed content - Tool: Bash (bun test) - Preconditions: Test DB with indexed chunks containing known text - Steps: - 1. bun test src/__tests__/search-fts.test.ts - 2. Assert: searching "TypeScript" finds chunk containing "TypeScript is my preferred language" - 3. Assert: score is a number between 0 and 1 - Expected Result: Keyword search returns ranked results - Evidence: Test output - ``` - - **Commit**: YES (groups with 9, 10) - - Message: `feat(search): FTS5 BM25 keyword search module` - - Files: `src/search.ts` (partial), `src/__tests__/search-fts.test.ts` - - Pre-commit: `bun test` - ---- - -- [x] 9. Vector Cosine Similarity Search Module - - **What to do**: - - **RED**: Write `src/__tests__/search-vec.test.ts`: - - Test: `searchVector(db, queryEmbedding, maxResults)` returns chunks ranked by cosine similarity - - Test: more similar content scores higher - - Test: returns empty array when no data in vec0 table - - Test: respects maxResults limit - - Test: returns chunk metadata (file_path, start_line, end_line, text, score) - - Test: handles case where vec0 extension is unavailable (returns empty, doesn't crash) - - **GREEN**: Implement vector search in `src/search.ts`: - - `searchVector(db, queryEmbedding, maxResults): SearchResult[]`: - ```sql - SELECT c.id, c.file_path, c.start_line, c.end_line, c.text, - distance AS score - FROM chunks_vec - JOIN chunks c ON chunks_vec.rowid = c.rowid - WHERE embedding MATCH ? - ORDER BY distance - LIMIT ? - ``` - - Convert distance to similarity score (1 - distance for cosine) - - Normalize to 0-1 range - - Handle vec0 unavailability: return empty results, log warning - - **Must NOT do**: - - Don't implement hybrid combination (Task 10) - - Don't implement approximate nearest neighbor tuning - - **Recommended Agent Profile**: - - **Category**: `quick` - - Reason: Single SQL query + distance-to-similarity conversion. Small module, similar to Task 8. - - **Skills**: none - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 4 (with Task 8) - - **Blocks**: Task 10 - - **Blocked By**: Task 6 - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/openclaw/src/memory/hybrid.ts:100-150` — Vector search implementation. Shows cosine distance query and score conversion. PRIMARY reference. - - `/home/m3tam3re/p/AI/openclaw/src/memory/manager.ts:1100-1200` — How vector queries are constructed - - **External References**: - - sqlite-vec query syntax: `https://alexgarcia.xyz/sqlite-vec/api-reference.html` - - **Acceptance Criteria**: - - **TDD:** - - [ ] Test file: `src/__tests__/search-vec.test.ts` - - [ ] `bun test src/__tests__/search-vec.test.ts` → PASS (all 6 tests) - - [ ] Gracefully handles missing vec0 extension - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Vector search returns semantically similar results - Tool: Bash (bun test) - Preconditions: Test DB with embedded chunks - Steps: - 1. bun test src/__tests__/search-vec.test.ts - 2. Assert: query about "programming language preferences" finds chunk about "TypeScript" - 3. Assert: similarity score decreases for less relevant chunks - Expected Result: Semantic search returns ranked results - Evidence: Test output - ``` - - **Commit**: YES (groups with 8, 10) - - Message: `feat(search): vector cosine similarity search module` - - Files: `src/search.ts` (extended), `src/__tests__/search-vec.test.ts` - - Pre-commit: `bun test` - ---- - -- [x] 10. Hybrid Search Combiner - - **What to do**: - - **RED**: Write `src/__tests__/search-hybrid.test.ts`: - - Test: `hybridSearch(db, query, embedder, config)` combines FTS5 and vector results - - Test: weighting applies correctly (0.7 * vectorScore + 0.3 * textScore) - - Test: results below minScore threshold are filtered out - - Test: duplicate chunks (found by both searches) are merged (not duplicated) - - Test: results are sorted by combined score (highest first) - - Test: maxResults is respected after merging - - Test: works with only FTS5 results (vec0 unavailable) — degraded mode - - Test: works with only vector results (FTS5 query fails) — degraded mode - - Test: custom weights override defaults - - **GREEN**: Implement `src/search.ts` (add to existing): - - `async hybridSearch(db, query, embedder, config): Promise`: - 1. Run FTS5 search: `searchFTS(db, query, config.maxResults * 2)` - 2. Embed query: `embedder.embed(query)` (with cache) - 3. Run vector search: `searchVector(db, queryEmbedding, config.maxResults * 2)` - 4. Merge results by chunk ID: - - If in both: `combinedScore = vectorWeight * vectorScore + textWeight * textScore` - - If only FTS5: `combinedScore = textWeight * textScore` - - If only vector: `combinedScore = vectorWeight * vectorScore` - 5. Filter by minScore - 6. Sort by combinedScore descending - 7. Limit to maxResults - 8. Return with source metadata (file_path, start_line, end_line, text, score, source) - - **Must NOT do**: - - Don't implement query expansion or rewriting - - Don't implement re-ranking with a separate model - - **Recommended Agent Profile**: - - **Category**: `ultrabrain` - - Reason: Score merging, deduplication by ID, weighted combination, edge case handling (degraded modes). Requires careful algorithmic thinking. - - **Skills**: none - - **Parallelization**: - - **Can Run In Parallel**: NO (depends on 8 and 9) - - **Parallel Group**: Wave 4 (after Tasks 8 + 9) - - **Blocks**: Task 11 - - **Blocked By**: Tasks 8, 9 - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/openclaw/src/memory/hybrid.ts` — THE reference for hybrid search. This entire file is the pattern. Shows score normalization, weighted combination, merging, deduplication, filtering, sorting. Copy the algorithm closely. - - **WHY This Reference Matters**: - - This is the heart of Openclaw's memory system. The hybrid search combiner determines recall quality. The weighting, merging, and filtering logic must be correct. - - **Acceptance Criteria**: - - **TDD:** - - [ ] Test file: `src/__tests__/search-hybrid.test.ts` - - [ ] `bun test src/__tests__/search-hybrid.test.ts` → PASS (all 9 tests) - - [ ] Degraded mode works (FTS-only, vector-only) - - [ ] Duplicate chunks merged correctly - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Hybrid search combines vector and keyword results - Tool: Bash (bun test) - Preconditions: DB with indexed chunks containing diverse content - Steps: - 1. bun test src/__tests__/search-hybrid.test.ts - 2. Assert: hybrid results include chunks found by BOTH methods - 3. Assert: combined score = 0.7 * vectorScore + 0.3 * textScore for shared results - 4. Assert: results sorted by combined score descending - 5. Assert: results below minScore=0.35 are filtered - Expected Result: Hybrid search correctly combines and ranks - Evidence: Test output - - Scenario: Graceful degradation when vec0 unavailable - Tool: Bash (bun test) - Preconditions: Mock vec0 as unavailable - Steps: - 1. bun test src/__tests__/search-hybrid.test.ts --filter "degraded" - 2. Assert: FTS-only results returned with textWeight scoring - 3. Assert: no error thrown - Expected Result: Search works with BM25 only - Evidence: Test output - ``` - - **Commit**: YES - - Message: `feat(search): hybrid search combiner with weighted vector+BM25 scoring` - - Files: `src/search.ts` (complete), `src/__tests__/search-hybrid.test.ts` - - Pre-commit: `bun test` - ---- - -- [x] 11. Agent Tools — memory_search, memory_store, memory_get - - **What to do**: - - **RED**: Write `src/__tests__/tools.test.ts`: - - Test: `memorySearchTool` schema validates query string, optional maxResults, optional source filter - - Test: `memorySearchTool.execute(query)` calls hybridSearch and formats results - - Test: `memoryStoreTool` schema validates content string, optional title, optional category - - Test: `memoryStoreTool.execute(content, title, category)` creates markdown file in vault with frontmatter, then indexes it - - Test: markdown filename is slugified from title (or timestamp-based if no title) - - Test: markdown has YAML frontmatter (type, category, created_at, source) - - Test: `memoryGetTool` schema validates filePath, optional startLine, optional endLine - - Test: `memoryGetTool.execute(filePath, startLine, endLine)` reads file and returns specified line range - - Test: memoryGetTool rejects paths outside vault directory - - Test: atomic write (temp file + rename) for memoryStore - - **GREEN**: Implement `src/tools.ts`: - - `memorySearchTool`: - - Schema: `{ query: z.string(), maxResults?: z.number().default(6), source?: z.enum(["memory","sessions","all"]).default("all") }` - - Execute: call hybridSearch, format results as: - ``` - Found N relevant memories: - --- - [1] {file_path}:{start_line}-{end_line} (score: 0.85, source: memory) - {text content} - --- - ``` - - `memoryStoreTool`: - - Schema: `{ content: z.string(), title?: z.string(), category?: z.enum(["preferences","facts","decisions","entities","other"]).default("other") }` - - Execute: - 1. Generate filename: `{category}/{slugify(title)}-{timestamp}.md` or `{category}/{timestamp}.md` - 2. Create YAML frontmatter: `---\ntype: memory\ncategory: {cat}\ncreated_at: {ISO date}\nsource: agent\n---` - 3. Write to vault atomically (write to .tmp, rename) - 4. Index the new file immediately - 5. Return confirmation with file path - - `memoryGetTool`: - - Schema: `{ filePath: z.string(), startLine?: z.number(), endLine?: z.number() }` - - Execute: validate path is within vault, read file, return requested lines - - Security: reject any path not starting with vault directory - - **REFACTOR**: Extract markdown generation, ensure consistent frontmatter - - **Must NOT do**: - - Don't implement memory_update or memory_delete (read + search + store covers needs) - - Don't implement bulk operations - - Don't add LLM-based summarization to memory_store - - **Recommended Agent Profile**: - - **Category**: `unspecified-high` - - Reason: Three tools with Zod schemas, file I/O, security validation, integration with all previous modules. Significant integration task. - - **Skills**: none - - **Parallelization**: - - **Can Run In Parallel**: NO - - **Parallel Group**: Wave 5 - - **Blocks**: Task 12 - - **Blocked By**: Tasks 10, 7 - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/openclaw/src/agents/tools/memory-tool.ts` — Openclaw's memory tools. Shows exact tool structure, Zod schema patterns, result formatting. PRIMARY reference for tool design. - - `/home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md` — Current memory skill workflows (store, recall). Shows the user's expected interaction patterns. - - `/home/m3tam3re/p/AI/AGENTS/skills/obsidian/SKILL.md` — Obsidian vault structure and frontmatter conventions for `~/CODEX/80-memory/`. Shows category subfolders and frontmatter template. - - **API/Type References**: - - Opencode custom tool format: `https://opencode.ai/docs/custom-tools/` — Tool definition with Zod schemas - - Opencode plugin tool() helper: `https://opencode.ai/docs/plugins/` — How to define tools inside a plugin - - **WHY Each Reference Matters**: - - `memory-tool.ts`: Direct pattern for memory_search output formatting. Shows how to present search results concisely. - - `SKILL.md` (memory): Shows user's existing mental model of store/recall workflows. Tools should match expectations. - - `SKILL.md` (obsidian): Shows frontmatter format and category subfolders (`preferences/`, `facts/`, etc.). - - **Acceptance Criteria**: - - **TDD:** - - [ ] Test file: `src/__tests__/tools.test.ts` - - [ ] `bun test src/__tests__/tools.test.ts` → PASS (all 10 tests) - - [ ] memory_store creates files atomically (temp + rename) - - [ ] memory_get rejects paths outside vault - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: memory_store creates markdown with correct frontmatter - Tool: Bash - Preconditions: Vault directory exists, DB initialized - Steps: - 1. Call memoryStoreTool.execute({ content: "I prefer dark themes in all editors", title: "editor preferences", category: "preferences" }) - 2. Assert: file created at ~/CODEX/80-memory/preferences/editor-preferences-*.md - 3. cat the file → Assert frontmatter contains "type: memory", "category: preferences" - 4. Assert: body contains "I prefer dark themes in all editors" - Expected Result: Markdown file with correct structure - Evidence: File content captured - - Scenario: memory_search returns formatted results - Tool: Bash - Preconditions: Vault has indexed memories - Steps: - 1. Call memorySearchTool.execute({ query: "editor theme preference" }) - 2. Assert: output contains "Found N relevant memories" - 3. Assert: results include file paths and scores - 4. Assert: scores are between 0 and 1 - Expected Result: Formatted search results - Evidence: Tool output captured - - Scenario: memory_get rejects path traversal - Tool: Bash (bun test) - Preconditions: Tools module implemented - Steps: - 1. bun test src/__tests__/tools.test.ts --filter "rejects paths outside" - 2. Assert: memoryGetTool.execute({ filePath: "/etc/passwd" }) throws error - 3. Assert: memoryGetTool.execute({ filePath: "../../etc/passwd" }) throws error - Expected Result: Security validation works - Evidence: Test output - ``` - - **Commit**: YES - - Message: `feat(tools): agent tools — memory_search, memory_store, memory_get` - - Files: `src/tools.ts`, `src/__tests__/tools.test.ts` - - Pre-commit: `bun test` - ---- - -- [x] 12. Plugin Entry Point — Hooks + Lifecycle - - **What to do**: - - **RED**: Write `src/__tests__/plugin.test.ts`: - - Test: plugin exports default function - - Test: plugin registers 3 tools (memory_search, memory_store, memory_get) - - Test: session.created handler calls auto-recall (hybrid search on session context) - - Test: session.idle handler calls auto-capture (extract and store memories) - - Test: session.compacting handler injects memory context (≤ 2000 tokens) - - Test: plugin initializes DB on first call (lazy init) - - Test: plugin handles DB initialization failure gracefully (log, continue) - - Test: plugin handles embedding API failure gracefully (log, continue) - - Test: token budget is respected in injection (truncate if > 2000 tokens) - - **GREEN**: Implement `src/index.ts`: - - Default export: Opencode plugin function - ```typescript - import { tool } from "@opencode-ai/plugin" - - export default function(ctx) { - // Lazy initialization - let db, embedder, config - - const init = () => { - if (db) return - config = resolveConfig() - db = initDatabase(config.dbPath) - embedder = new EmbeddingProvider({ db, model: config.embedding.model }) - } - - // Register tools - ctx.tool("memory_search", memorySearchTool.schema, async (params) => { - init() - return memorySearchTool.execute(params, db, embedder, config) - }) - - ctx.tool("memory_store", memoryStoreTool.schema, async (params) => { - init() - return memoryStoreTool.execute(params, db, embedder, config) - }) - - ctx.tool("memory_get", memoryGetTool.schema, async (params) => { - init() - return memoryGetTool.execute(params, config) - }) - - // Event hooks - ctx.on("session.created", async (event) => { - init() - // Auto-recall: search for relevant memories based on session context - // Inject results into system prompt or initial context - }) - - ctx.on("session.idle", async (event) => { - init() - // Auto-capture: extract memories from recent conversation - // Store as markdown + index - }) - - ctx.on("experimental.session.compacting", async (event) => { - init() - // Inject relevant memory context into compaction - // Respect token budget - }) - } - ``` - - Auto-recall logic: On session.created, search for memories related to the project directory and recent context. Format top results within token budget. Inject via system prompt addition. - - Auto-capture logic: On session.idle, analyze recent messages. Use LLM (or simple heuristics) to extract key facts, decisions, preferences. Store as markdown via memoryStoreTool. - - Compaction injection: On session.compacting, search for relevant memories and include in compaction context. - - Error wrapping: ALL hooks wrapped in try/catch → log error, never crash Opencode - - File watcher: Start chokidar watcher on vault directory for live file changes → re-index changed files - - **Must NOT do**: - - Don't implement complex LLM-based extraction for auto-capture (use simple heuristic or minimal prompt — Phase 2 can enhance) - - Don't implement custom settings UI - - Don't add CLI commands (Task 13 handles rebuild) - - **Recommended Agent Profile**: - - **Category**: `unspecified-high` - - Reason: Plugin integration with Opencode's event system, lifecycle management, error handling, file watching. Core integration task. - - **Skills**: none - - **Parallelization**: - - **Can Run In Parallel**: NO - - **Parallel Group**: Wave 5 (after Task 11) - - **Blocks**: Task 13 - - **Blocked By**: Task 11 - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/openclaw/src/agents/tools/memory-tool.ts` — How tools are registered and how search results are formatted for agent consumption - - `/home/m3tam3re/p/AI/openclaw/src/agents/system-prompt.ts` — How memory instructions are injected into system prompt. Shows the "Before answering, search memory..." pattern. - - `/home/m3tam3re/p/AI/openclaw/src/memory/manager.ts:1300-1590` — Lifecycle methods: init, sync, shutdown, file watcher setup - - **API/Type References**: - - Opencode plugin API: `https://opencode.ai/docs/plugins/` — Plugin function signature, ctx.tool(), ctx.on(), event types - - Opencode custom tools: `https://opencode.ai/docs/custom-tools/` — Tool schema format with Zod - - **Documentation References**: - - `/home/m3tam3re/.config/opencode/opencode.json:128-132` — Existing plugin registration pattern (shows how plugins are listed) - - **WHY Each Reference Matters**: - - `system-prompt.ts`: Shows the exact memory instruction pattern that makes agents reliably use memory tools. Without this, agents may ignore the tools. - - Plugin docs: The exact API surface for ctx.tool() and ctx.on(). Critical for correct integration. - - `manager.ts:1300-1590`: Shows chokidar file watcher setup, debouncing, and cleanup. - - **Acceptance Criteria**: - - **TDD:** - - [ ] Test file: `src/__tests__/plugin.test.ts` - - [ ] `bun test src/__tests__/plugin.test.ts` → PASS (all 9 tests) - - [ ] All hooks wrapped in try/catch - - [ ] Token budget respected - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Plugin loads in opencode without errors - Tool: interactive_bash (tmux) - Preconditions: Plugin built, registered in opencode.json - Steps: - 1. Add "opencode-memory" to plugin list in opencode.json (or use local path) - 2. Start opencode in tmux session - 3. Wait for initialization (5s) - 4. Check opencode logs for "opencode-memory" → no errors - 5. Verify memory_search tool is available (try calling it) - Expected Result: Plugin loads, tools available - Evidence: Terminal output, opencode log screenshot - - Scenario: Plugin handles missing vault directory gracefully - Tool: Bash - Preconditions: Vault directory temporarily renamed - Steps: - 1. mv ~/CODEX/80-memory ~/CODEX/80-memory.bak - 2. Start plugin init → should log warning, not crash - 3. mv ~/CODEX/80-memory.bak ~/CODEX/80-memory - Expected Result: Graceful degradation with warning - Evidence: Log output - - Scenario: Token budget limits memory injection - Tool: Bash (bun test) - Preconditions: DB with many indexed memories - Steps: - 1. bun test src/__tests__/plugin.test.ts --filter "token budget" - 2. Assert: injected context ≤ 2000 tokens - Expected Result: Budget respected - Evidence: Test output - ``` - - **Commit**: YES - - Message: `feat(plugin): Opencode plugin entry point with hooks and lifecycle` - - Files: `src/index.ts`, `src/__tests__/plugin.test.ts` - - Pre-commit: `bun test` - ---- - -- [x] 13. Integration Testing + Error Handling + Rebuild Command - - **What to do**: - - **RED**: Write `src/__tests__/integration.test.ts`: - - Test: full pipeline — create memory → search → find it - - Test: full pipeline — index vault → search → get file - - Test: full pipeline — index sessions → search session content - - Test: rebuild command — delete DB → rebuild → all content searchable again - - Test: OpenAI API failure → plugin continues, BM25-only results - - Test: corrupt SQLite → auto-recreate on next init - - Test: concurrent search + index operations don't deadlock - - Test: empty vault → no errors, empty search results - - Test: very large file (1MB+) → chunks correctly, no OOM - - **GREEN**: - - Add CLI entry point for rebuild: `src/cli.ts` - ```typescript - // bun run src/cli.ts --rebuild [--vault path] [--db path] - ``` - - Add error recovery to `initDatabase`: if DB is corrupt, delete and recreate - - Add timeout to embedding API calls (30s default) - - Add graceful shutdown: close DB, stop file watcher, on process exit - - Ensure all error paths are covered with try/catch - - **REFACTOR**: Run full test suite, fix any integration issues - - **Must NOT do**: - - Don't build a comprehensive CLI (just --rebuild) - - Don't add progress bars or fancy output - - Don't implement migration from mem0 - - **Recommended Agent Profile**: - - **Category**: `deep` - - Reason: Integration testing requires understanding the full system. Error scenarios require careful thinking about failure modes and recovery. - - **Skills**: [`systematic-debugging`] - - `systematic-debugging`: Needed for diagnosing integration test failures systematically - - **Parallelization**: - - **Can Run In Parallel**: NO - - **Parallel Group**: Wave 6 - - **Blocks**: Task 14 - - **Blocked By**: Task 12 - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/openclaw/src/memory/manager.ts:1-50` — Imports and error handling patterns - - `/home/m3tam3re/p/AI/openclaw/src/memory/manager.ts:1400-1590` — Shutdown and cleanup logic - - **Acceptance Criteria**: - - **TDD:** - - [ ] Test file: `src/__tests__/integration.test.ts` - - [ ] `bun test` → ALL tests pass (0 failures across all test files) - - [ ] CLI rebuild: `bun run src/cli.ts --rebuild` works - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Full pipeline — store and search a memory - Tool: Bash - Preconditions: Plugin module fully implemented - Steps: - 1. Initialize in-memory DB + embedder - 2. Store memory: "I prefer Nix for system configuration" - 3. Search: "system configuration tool" - 4. Assert: search result contains "Nix" with score > 0.35 - Expected Result: End-to-end pipeline works - Evidence: Terminal output - - Scenario: Rebuild command recreates index from markdown - Tool: Bash - Preconditions: Vault has markdown files, DB deleted - Steps: - 1. rm -f ~/.local/share/opencode-memory/index.db - 2. bun run src/cli.ts --rebuild --vault ~/CODEX/80-memory/ - 3. Assert: DB file created - 4. Assert: search for known vault content returns results - Expected Result: Index rebuilt from markdown source of truth - Evidence: Terminal output + DB file exists - - Scenario: API failure degrades gracefully - Tool: Bash - Preconditions: OPENAI_API_KEY=invalid - Steps: - 1. OPENAI_API_KEY=invalid bun test src/__tests__/integration.test.ts --filter "API failure" - 2. Assert: no crash, BM25-only results returned - 3. Assert: error logged to stderr - Expected Result: Graceful degradation - Evidence: Test output - ``` - - **Commit**: YES - - Message: `feat(integration): integration tests, error recovery, rebuild CLI` - - Files: `src/__tests__/integration.test.ts`, `src/cli.ts` - - Pre-commit: `bun test` - ---- - -- [x] 14. AGENTS Repo Skill Updates + Deployment Config - - **What to do**: - - Update `skills/memory/SKILL.md` in the AGENTS repo: - - Replace dual-layer (mem0 + Obsidian) description with opencode-memory plugin description - - Document new architecture: SQLite hybrid search, markdown source of truth - - Update workflows: memory_search, memory_store, memory_get tools - - Document auto-recall (session.created) and auto-capture (session.idle) behavior - - Remove references to mem0 REST API - - Keep Obsidian vault references (still at `~/CODEX/80-memory/`) - - Update `skills/mem0-memory/SKILL.md`: - - Add deprecation notice at top: "DEPRECATED: Replaced by opencode-memory plugin. See skills/memory/SKILL.md." - - Keep existing content for reference - - Add plugin registration note to `context/profile.md`: - - Update memory system description to reference opencode-memory - - Create deployment documentation in `skills/memory/references/deployment.md`: - - How to install opencode-memory (npm or Nix) - - How to register in opencode.json - - How to configure vault path and embedding provider - - How to verify installation - - **Must NOT do**: - - Don't modify opencode.json (user does this manually after deployment) - - Don't delete mem0-memory skill (just deprecate) - - Don't modify agent definitions (Apollo agent config stays) - - Don't create README in the opencode-memory repo - - **Recommended Agent Profile**: - - **Category**: `writing` - - Reason: Documentation-heavy task. Updating skill files, writing deployment notes. - - **Skills**: none - - **Parallelization**: - - **Can Run In Parallel**: NO (final task) - - **Parallel Group**: Wave 6 (after Task 13) - - **Blocks**: None (final task) - - **Blocked By**: Task 13 - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/AI/AGENTS/skills/memory/SKILL.md` — Current memory skill to update. Preserve structure, update content. - - `/home/m3tam3re/p/AI/AGENTS/skills/mem0-memory/SKILL.md` — Current mem0 skill to deprecate. Add deprecation notice. - - `/home/m3tam3re/p/AI/AGENTS/context/profile.md` — User profile with memory references to update. - - `/home/m3tam3re/p/AI/AGENTS/skills/obsidian/SKILL.md` — Obsidian skill for reference (vault structure stays same). - - **Acceptance Criteria**: - - **Agent-Executed QA Scenarios:** - - ``` - Scenario: Updated memory skill validates - Tool: Bash - Preconditions: AGENTS repo skills updated - Steps: - 1. ./scripts/test-skill.sh memory - 2. Assert: validation passes - 3. grep "opencode-memory" skills/memory/SKILL.md → found - 4. grep "DEPRECATED" skills/mem0-memory/SKILL.md → found - Expected Result: Skills validate, content updated - Evidence: Validation output - - Scenario: Profile references new memory system - Tool: Bash - Preconditions: context/profile.md updated - Steps: - 1. grep "opencode-memory" context/profile.md → found - 2. grep "mem0" context/profile.md → NOT found (or marked deprecated) - Expected Result: Profile references updated - Evidence: grep output - ``` - - **Commit**: YES - - Message: `docs(memory): update skills for opencode-memory plugin, deprecate mem0` - - Files: `skills/memory/SKILL.md`, `skills/mem0-memory/SKILL.md`, `context/profile.md`, `skills/memory/references/deployment.md` - - Pre-commit: `./scripts/test-skill.sh --validate` - ---- - -## Commit Strategy - -| After Task | Message | Key Files | Verification | -|------------|---------|-----------|--------------| -| 1 | `feat(scaffold): initialize opencode-memory repo` | package.json, tsconfig.json, src/*.ts stubs | `bun test` | -| 2+3+4 | `feat(core): config, database schema, file discovery` | config.ts, db.ts, discovery.ts + tests | `bun test` | -| 5 | `feat(embeddings): OpenAI provider with cache` | embeddings.ts + test | `bun test` | -| 6 | `feat(indexer): file indexer pipeline` | indexer.ts + test | `bun test` | -| 7 | `feat(sessions): session transcript parser` | sessions.ts + test | `bun test` | -| 8+9+10 | `feat(search): hybrid search (FTS5 + vec0)` | search.ts + tests | `bun test` | -| 11 | `feat(tools): agent memory tools` | tools.ts + test | `bun test` | -| 12 | `feat(plugin): Opencode plugin entry point` | index.ts + test | `bun test` | -| 13 | `feat(integration): tests + error recovery + rebuild` | integration.test.ts, cli.ts | `bun test` | -| 14 | `docs(memory): update AGENTS repo skills` | SKILL.md files | `./scripts/test-skill.sh --validate` | - ---- - -## Success Criteria - -### Verification Commands -```bash -# In opencode-memory repo: -bun test # Expected: ALL tests pass (0 failures) -bun run src/cli.ts --rebuild --vault ~/CODEX/80-memory/ # Expected: index rebuilt - -# In AGENTS repo: -./scripts/test-skill.sh --validate # Expected: all skills valid - -# In opencode (after registration): -# memory_search tool available and returns results -# memory_store tool creates markdown files -# memory_get tool reads file content -``` - -### Final Checklist -- [x] All "Must Have" items present (hybrid search, caching, graceful degradation, etc.) -- [x] All "Must NOT Have" items absent (no mem0 dependency, no multi-vault, no UI, etc.) -- [x] All unit tests pass (`bun test`) -- [x] Integration tests pass -- [~] Plugin loads in Opencode without errors (requires user deployment) -- [x] Auto-recall fires on session.created -- [x] Auto-capture fires on session.idle -- [x] Rebuild command recreates index from markdown -- [x] OpenAI failure doesn't crash plugin -- [x] AGENTS repo skills updated and validated diff --git a/.sisyphus/plans/rules-system.md b/.sisyphus/plans/rules-system.md deleted file mode 100644 index 18a5f21..0000000 --- a/.sisyphus/plans/rules-system.md +++ /dev/null @@ -1,804 +0,0 @@ -# Centralized Rules & Per-Project Context Injection System - -## TL;DR - -> **Quick Summary**: Create a `rules/` directory in the AGENTS repository containing modular AI coding rules (per-concern + per-language), deployed centrally via Home Manager. A `mkOpencodeRules` Nix helper function lives in the nixpkgs repo (following the existing `ports.nix` → `mkPortHelpers` pattern), generating per-project `opencode.json` via devShell activation. -> -> **Deliverables**: -> - 6 concern rule files (coding-style, naming, documentation, testing, git-workflow, project-structure) -> - 5 language/framework rule files (python, typescript, nix, shell, n8n) -> - `lib/opencode-rules.nix` in nixpkgs repo — `mkOpencodeRules` helper function -> - Updated `lib/default.nix` in nixpkgs repo — imports opencode-rules -> - Updated `opencode.nix` in nixos-config — deploys rules/ alongside existing skills -> - `rules/USAGE.md` — per-project adoption documentation -> -> **Repos Touched**: 3 (AGENTS, nixpkgs, nixos-config) -> **Estimated Effort**: Medium (11 rule files + 3 nix changes + 1 doc) -> **Parallel Execution**: YES — 4 waves -> **Critical Path**: T1-T3 (foundation) → T6-T16 (content) → T17 (verification) - ---- - -## Context - -### Original Request -User wants to streamline their Agent workflow by centrally managing language-specific and framework-specific coding rules in the AGENTS repository, while allowing project-specific overrides. Rules should be injected per-project using Nix flakes + direnv. - -### Interview Summary -**Key Discussions**: -- **Loading strategy**: Always loaded (not lazy) — rules always in context when project activates -- **Composition mechanism**: Nix flake devShell — each project declares languages/frameworks needed -- **Rule granularity**: Per concern with separate language files for deep patterns -- **Override strategy**: Project-level AGENTS.md overrides central rules (OpenCode's native precedence) -- **opencode.json**: No project-specific one exists yet — devShell generates it entirely -- **Nix helper location**: Lives in `m3ta-nixpkgs` repo at `lib/opencode-rules.nix` (follows `ports.nix` pattern) -- **AGENTS repo stays pure content**: No Nix code — only markdown rule files - -**Research Findings**: -- OpenCode `instructions` field in `opencode.json` loads external .md files as always-on context -- Anthropic guide: progressive disclosure, composability, 500-line max, use TOCs for long files -- Best practices: 100-200 lines per file, imperative language, micro-examples (correct/incorrect) -- Rule files benefit from sandwich principle: critical constraints at START and END - -### Metis Review -**Identified Gaps** (addressed): -- **Rule update strategy**: When rules change in AGENTS repo, projects run `nix flake update agents`. Standard Nix flow. -- **Multi-language projects**: `mkOpencodeRules { languages = [ "python" "typescript" ]; }` — list multiple. -- **Context window budget**: ~800-1300 lines total. Well under 1500-line budget. -- **Empty rules selection**: `mkOpencodeRules {}` loads only concern files (defaults to all 6). - -### Architecture Decision: Nix Helper Location -**Decision**: `mkOpencodeRules` lives in **nixpkgs repo** (`/home/m3tam3re/p/NIX/nixpkgs/lib/opencode-rules.nix`), NOT in AGENTS repo. - -**Rationale**: -- nixpkgs already has `lib/ports.nix` → `mkPortHelpers` as an identical pattern -- nixpkgs is already consumed by all configs: `inputs.m3ta-nixpkgs.lib.${system}` -- AGENTS repo stays pure content (markdown + configs), no Nix code -- Projects already have `m3ta-nixpkgs` as a flake input — no new input needed for the helper - -**Consumption pattern** (per-project): -```nix -let - m3taLib = inputs.m3ta-nixpkgs.lib.${system}; - rules = m3taLib.opencode-rules.mkOpencodeRules { - agents = inputs.agents; # Non-flake input with rule content - languages = [ "python" ]; - }; -in pkgs.mkShell { shellHook = rules.shellHook; } -``` - ---- - -## Work Objectives - -### Core Objective -Create a centralized, modular AI coding rules system managed in the AGENTS repo, with a Nix helper in nixpkgs for per-project injection via devShell + direnv. - -### Concrete Deliverables -- `rules/concerns/{coding-style,naming,documentation,testing,git-workflow,project-structure}.md` — in AGENTS repo -- `rules/languages/{python,typescript,nix,shell}.md` — in AGENTS repo -- `rules/frameworks/n8n.md` — in AGENTS repo -- `rules/USAGE.md` — adoption documentation in AGENTS repo -- `lib/opencode-rules.nix` — in nixpkgs repo (`/home/m3tam3re/p/NIX/nixpkgs/`) -- Updated `lib/default.nix` — in nixpkgs repo (add import) -- Updated `opencode.nix` — in nixos-config repo (`/home/m3tam3re/p/NIX/nixos-config/home/features/coding/`) - -### Definition of Done -- [ ] All 11 rule files exist and are under 250 lines each -- [ ] `lib/opencode-rules.nix` in nixpkgs exports `mkOpencodeRules` following `ports.nix` pattern -- [ ] `opencode.nix` deploys `rules/` to `~/.config/opencode/rules/` -- [ ] A project can use `m3taLib.opencode-rules.mkOpencodeRules` in devShell - -### Must Have -- All rule files use imperative language ("Always use...", "Never...") -- Every rule includes micro-examples (correct vs incorrect, 2-3 lines each) -- Concern files are language-agnostic; language subsections are brief pointers -- Language files go deep into toolchain, idioms, anti-patterns -- `mkOpencodeRules` accepts: `{ agents, languages ? [], concerns ? [...], frameworks ? [], extraInstructions ? [] }` -- `mkOpencodeRules` follows `ports.nix` pattern: `{lib}: { mkOpencodeRules = ...}` -- shellHook creates `.opencode-rules` symlink + generates `opencode.json` -- Both `.opencode-rules` and `opencode.json` must be gitignored (documented in USAGE.md) - -### Must NOT Have (Guardrails) -- Rule files MUST NOT exceed 250 lines -- Total loaded rules MUST NOT exceed 1500 lines for any realistic config -- Concern files MUST NOT contain language-specific implementation details -- MUST NOT put Nix code in AGENTS repo — AGENTS stays pure content -- MUST NOT add rule versioning, testing framework, or generator CLI -- MUST NOT create rules for docker, k8s, terraform — out of scope -- MUST NOT modify existing skills, agents, prompts, or commands -- MUST NOT use generic advice ("write clean code", "follow best practices") - ---- - -## Verification Strategy (MANDATORY) - -> **ZERO HUMAN INTERVENTION** — ALL verification is agent-executed. No exceptions. - -### Test Decision -- **Infrastructure exists**: NO (config/documentation repos) -- **Automated tests**: NO -- **Framework**: none - -### QA Policy -Every task MUST include agent-executed QA scenarios. -Evidence saved to `.sisyphus/evidence/task-{N}-{scenario-slug}.{ext}`. - -| Deliverable Type | Verification Tool | Method | -|------------------|-------------------|--------| -| Markdown rule files | Bash (wc, grep) | Line count, micro-examples, imperative language | -| Nix expressions | Bash (nix eval) | Evaluate, check errors | -| Shell integration | Bash | Verify symlink + opencode.json generated | -| Cross-repo | Bash (grep) | Verify entries in correct files | - ---- - -## Execution Strategy - -### Parallel Execution Waves - -``` -Wave 1 (Foundation — 5 tasks, all parallel): -├── Task 1: Create rules/ directory structure in AGENTS repo [quick] -├── Task 2: Create lib/opencode-rules.nix in nixpkgs repo [quick] -├── Task 3: Update lib/default.nix in nixpkgs repo [quick] -├── Task 4: Update opencode.nix in nixos-config repo [quick] -└── Task 5: Create rules/USAGE.md in AGENTS repo [quick] - -Wave 2 (Content — 11 rule files, all parallel): -├── Task 6: concerns/coding-style.md [writing] -├── Task 7: concerns/naming.md [writing] -├── Task 8: concerns/documentation.md [writing] -├── Task 9: concerns/testing.md [writing] -├── Task 10: concerns/git-workflow.md [writing] -├── Task 11: concerns/project-structure.md [writing] -├── Task 12: languages/python.md [writing] -├── Task 13: languages/typescript.md [writing] -├── Task 14: languages/nix.md [writing] -├── Task 15: languages/shell.md [writing] -└── Task 16: frameworks/n8n.md [writing] - -Wave 3 (Verification): -└── Task 17: End-to-end integration test [deep] - -Wave FINAL (Review — 4 parallel): -├── Task F1: Plan compliance audit (oracle) -├── Task F2: Code quality review (unspecified-high) -├── Task F3: Real manual QA (unspecified-high) -└── Task F4: Scope fidelity check (deep) - -Critical Path: T1-T3 → T6-T16 (parallel) → T17 → F1-F4 -Max Concurrent: 11 (Wave 2) -``` - -### Dependency Matrix - -| Task | Depends On | Blocks | Wave | -|------|------------|--------|------| -| 1 | — | 5, 6-16, 17 | 1 | -| 2, 3 | — | 17 | 1 | -| 4 | — | 17 | 1 | -| 5 | 1, 2 | 17 | 1 | -| 6-16 | 1 | 17 | 2 | -| 17 | 2-5, 6-16 | F1-F4 | 3 | -| F1-F4 | 17 | — | FINAL | - -### Agent Dispatch Summary - -| Wave | # Parallel | Tasks and Agent Category | -|------|------------|------------------------| -| 1 | **5** | T1-T5 → `quick` | -| 2 | **11** | T6-T16 → `writing` | -| 3 | **1** | T17 → `deep` | -| FINAL | **4** | F1 → `oracle`, F2,F3 → `unspecified-high`, F4 → `deep` | - ---- - -## TODOs - -- [x] 1. Create rules/ directory structure in AGENTS repo - - **What to do**: - - Create directory structure in `/home/m3tam3re/p/AI/AGENTS/`: `rules/concerns/`, `rules/languages/`, `rules/frameworks/` - - Add `.gitkeep` files to each directory so they're tracked before content is added - - This is the CONTENT repo only — NO Nix code goes here - - **Must NOT do**: - - Do not create any Nix files in AGENTS repo - - Do not create rule content files (those are Wave 2) - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 1 (with Tasks 2-5) - - **Blocks**: Tasks 5, 6-16, 17 - - **Blocked By**: None - - **References**: - - `/home/m3tam3re/p/AI/AGENTS/skills/` — existing directory structure pattern - - **Acceptance Criteria**: - - **QA Scenarios (MANDATORY):** - - ``` - Scenario: Directory structure exists - Tool: Bash - Preconditions: None - Steps: - 1. Run `ls /home/m3tam3re/p/AI/AGENTS/rules/concerns/.gitkeep /home/m3tam3re/p/AI/AGENTS/rules/languages/.gitkeep /home/m3tam3re/p/AI/AGENTS/rules/frameworks/.gitkeep` - Expected Result: All 3 .gitkeep files exist - Failure Indicators: "No such file or directory" - Evidence: .sisyphus/evidence/task-1-dirs.txt - - Scenario: No Nix files in AGENTS repo rules/ - Tool: Bash - Preconditions: Dirs created - Steps: - 1. Run `find /home/m3tam3re/p/AI/AGENTS/rules/ -name '*.nix' | wc -l` - Expected Result: Count is 0 - Failure Indicators: Count > 0 - Evidence: .sisyphus/evidence/task-1-no-nix.txt - ``` - - **Commit**: YES - - Message: `feat(rules): add rules directory structure` - - Files: `rules/concerns/.gitkeep`, `rules/languages/.gitkeep`, `rules/frameworks/.gitkeep` - ---- - -- [x] 2. Create `lib/opencode-rules.nix` in nixpkgs repo - - **What to do**: - - Create `/home/m3tam3re/p/NIX/nixpkgs/lib/opencode-rules.nix` - - Follow the EXACT pattern of `lib/ports.nix`: `{lib}: { mkOpencodeRules = ...; }` - - The function must accept: `{ agents, languages ? [], concerns ? [ "coding-style" "naming" "documentation" "testing" "git-workflow" "project-structure" ], frameworks ? [], extraInstructions ? [] }` - - `agents` parameter = the non-flake input (path to AGENTS repo in Nix store) - - It must return: `{ shellHook = "..."; instructions = [...]; }` - - `shellHook` must: (a) create `.opencode-rules` symlink to `${agents}/rules`, (b) generate `opencode.json` with `$schema` and `instructions` fields using `builtins.toJSON` - - `instructions` = list of paths relative to project root via `.opencode-rules/` symlink - - Include comprehensive Nix doc comments (matching ports.nix style) - - **Must NOT do**: - - Do not deviate from ports.nix pattern - - Do not put any code in AGENTS repo - - **Recommended Agent Profile**: - - **Category**: `quick` - - Reason: One Nix file following established pattern - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 1 (with Tasks 1, 3-5) - - **Blocks**: Tasks 5, 17 - - **Blocked By**: None - - **References**: - - **Pattern References**: - - `/home/m3tam3re/p/NIX/nixpkgs/lib/ports.nix` — MUST follow this exact pattern: `{lib}: { mkPortHelpers = portsConfig: let ... in { ... }; }` - - `/home/m3tam3re/p/NIX/nixpkgs/lib/default.nix` — shows how lib modules are imported: `import ./ports.nix {inherit lib;}` - - `/home/m3tam3re/p/NIX/nixpkgs/flake.nix:73-77` — shows how lib is exposed: `lib = forAllSystems (system: ... import ./lib {lib = pkgs.lib;});` - - **External References**: - - OpenCode rules docs: `https://opencode.ai/docs/rules/` — `instructions` field accepts relative paths - - **WHY Each Reference Matters**: - - `ports.nix` is the canonical pattern for lib functions in this repo — `{lib}:` signature, doc comments, nested `let ... in` - - `default.nix` shows how the new module gets wired in - - `flake.nix` confirms how consumers access it: `m3ta-nixpkgs.lib.${system}.opencode-rules.mkOpencodeRules` - - **Acceptance Criteria**: - - **QA Scenarios (MANDATORY):** - - ``` - Scenario: opencode-rules.nix evaluates without errors - Tool: Bash - Preconditions: File created - Steps: - 1. Run `nix eval --impure --expr 'let pkgs = import {}; lib = (import /home/m3tam3re/p/NIX/nixpkgs/lib/opencode-rules.nix {lib = pkgs.lib;}); in builtins.attrNames lib' 2>&1` - Expected Result: Output contains "mkOpencodeRules" - Failure Indicators: "error:" in output - Evidence: .sisyphus/evidence/task-2-eval.txt - - Scenario: mkOpencodeRules generates correct paths - Tool: Bash - Preconditions: File created - Steps: - 1. Run `nix eval --impure --json --expr 'let pkgs = import {}; lib = (import /home/m3tam3re/p/NIX/nixpkgs/lib/opencode-rules.nix {lib = pkgs.lib;}); in (lib.mkOpencodeRules { agents = /home/m3tam3re/p/AI/AGENTS; languages = ["python" "typescript"]; frameworks = ["n8n"]; }).instructions'` - Expected Result: JSON array with 9 paths (6 concerns + 2 languages + 1 framework), all starting with ".opencode-rules/" - Failure Indicators: Wrong count, wrong prefix, error - Evidence: .sisyphus/evidence/task-2-paths.txt - - Scenario: Default (empty languages) works - Tool: Bash - Preconditions: File created - Steps: - 1. Run `nix eval --impure --json --expr 'let pkgs = import {}; lib = (import /home/m3tam3re/p/NIX/nixpkgs/lib/opencode-rules.nix {lib = pkgs.lib;}); in (lib.mkOpencodeRules { agents = /home/m3tam3re/p/AI/AGENTS; }).instructions'` - Expected Result: JSON array with 6 paths (concerns only) - Failure Indicators: Extra paths, error - Evidence: .sisyphus/evidence/task-2-defaults.txt - - Scenario: shellHook generates valid JSON - Tool: Bash - Preconditions: File created - Steps: - 1. Run `nix eval --impure --raw --expr 'let pkgs = import {}; lib = (import /home/m3tam3re/p/NIX/nixpkgs/lib/opencode-rules.nix {lib = pkgs.lib;}); in (lib.mkOpencodeRules { agents = /home/m3tam3re/p/AI/AGENTS; languages = ["python"]; }).shellHook' | sh -c 'eval "$(cat)"' && python3 -m json.tool opencode.json` - Expected Result: Valid JSON output with "$schema" and "instructions" fields - Failure Indicators: JSON parse error, missing fields - Evidence: .sisyphus/evidence/task-2-json.txt - ``` - - **Commit**: YES - - Message: `feat(lib): add opencode-rules helper for per-project rule injection` - - Files: `lib/opencode-rules.nix` - - Pre-commit: `nix eval --impure --expr '...'` - ---- - -- [x] 3. Update `lib/default.nix` in nixpkgs repo - - **What to do**: - - Add one line to `/home/m3tam3re/p/NIX/nixpkgs/lib/default.nix` to import opencode-rules: - `opencode-rules = import ./opencode-rules.nix {inherit lib;};` - - Place it after the existing `ports = import ./ports.nix {inherit lib;};` line - - Update the comment at line 10 to remove it (it's a placeholder) - - **Must NOT do**: - - Do not modify the ports import - - Do not change the function signature `{lib}:` - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES (but logically pairs with Task 2) - - **Parallel Group**: Wave 1 - - **Blocks**: Task 17 - - **Blocked By**: Task 2 (opencode-rules.nix must exist first) - - **References**: - - `/home/m3tam3re/p/NIX/nixpkgs/lib/default.nix:6-12` — current file content, add after line 8 - - **Acceptance Criteria**: - - **QA Scenarios (MANDATORY):** - - ``` - Scenario: default.nix imports opencode-rules - Tool: Bash - Preconditions: Both files updated - Steps: - 1. Run `grep 'opencode-rules' /home/m3tam3re/p/NIX/nixpkgs/lib/default.nix` - Expected Result: Line shows `opencode-rules = import ./opencode-rules.nix {inherit lib;};` - Failure Indicators: No match - Evidence: .sisyphus/evidence/task-3-import.txt - - Scenario: Full lib evaluates - Tool: Bash - Preconditions: Both files updated - Steps: - 1. Run `nix eval --impure --expr 'let pkgs = import {}; m3taLib = import /home/m3tam3re/p/NIX/nixpkgs/lib {lib = pkgs.lib;}; in builtins.attrNames m3taLib' 2>&1` - Expected Result: Output includes both "ports" and "opencode-rules" - Failure Indicators: Missing "opencode-rules" or error - Evidence: .sisyphus/evidence/task-3-full-lib.txt - ``` - - **Commit**: YES (groups with Task 2) - - Message: `feat(lib): add opencode-rules helper for per-project rule injection` - - Files: `lib/default.nix`, `lib/opencode-rules.nix` - ---- - -- [x] 4. Update opencode.nix in nixos-config repo - - **What to do**: - - Add `rules/` deployment to `xdg.configFile` in `/home/m3tam3re/p/NIX/nixos-config/home/features/coding/opencode.nix` - - Add entry: `"opencode/rules" = { source = "${inputs.agents}/rules"; recursive = true; };` - - Place it alongside existing entries for commands, context, prompts, skills (lines 2-18) - - **Must NOT do**: - - Do not modify any existing entries - - Do not change agents, MCP, providers, or oh-my-opencode config - - Do not run `home-manager switch` - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 1 - - **Blocks**: Task 17 - - **Blocked By**: None - - **References**: - - `/home/m3tam3re/p/NIX/nixos-config/home/features/coding/opencode.nix:2-18` — existing xdg.configFile entries - - **Acceptance Criteria**: - - **QA Scenarios (MANDATORY):** - - ``` - Scenario: opencode.nix contains rules entry - Tool: Bash - Preconditions: File updated - Steps: - 1. Run `grep -c 'opencode/rules' /home/m3tam3re/p/NIX/nixos-config/home/features/coding/opencode.nix` - 2. Run `grep -c 'opencode/commands\|opencode/context\|opencode/prompts\|opencode/skills' /home/m3tam3re/p/NIX/nixos-config/home/features/coding/opencode.nix` - Expected Result: Rules count is 1, existing count is 4 (all preserved) - Failure Indicators: Count mismatch - Evidence: .sisyphus/evidence/task-4-opencode-nix.txt - ``` - - **Commit**: YES - - Message: `feat(opencode): deploy rules/ to ~/.config/opencode/rules/ via home-manager` - - Files: `opencode.nix` - ---- - -- [x] 5. Create `rules/USAGE.md` in AGENTS repo - - **What to do**: - - Document how to use `mkOpencodeRules` in a project's `flake.nix` - - Show the nixpkgs consumption pattern: `m3taLib.opencode-rules.mkOpencodeRules { agents = inputs.agents; languages = ["python"]; }` - - Complete example `flake.nix` devShell snippet showing: `inputs.agents` + `inputs.m3ta-nixpkgs` + `mkOpencodeRules` + `shellHook` - - Document `.gitignore` additions: `.opencode-rules` and `opencode.json` - - Explain project-level `AGENTS.md` overrides - - Explain update flow: `nix flake update agents` - - Keep concise: max 100 lines - - **Must NOT do**: - - Do not create a README.md (repo anti-pattern) - - Do not reference `rules/default.nix` — the helper lives in nixpkgs, not AGENTS - - **Recommended Agent Profile**: - - **Category**: `quick` - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 1 - - **Blocks**: Task 17 - - **Blocked By**: Tasks 1, 2 (needs to reference both structures) - - **References**: - - `/home/m3tam3re/p/AI/AGENTS/AGENTS.md` — repo documentation style (concise, code-heavy) - - `/home/m3tam3re/p/NIX/nixpkgs/lib/ports.nix:1-42` — the doc comment style used for lib functions - - OpenCode rules docs: `https://opencode.ai/docs/rules/` — `instructions` field - - **Acceptance Criteria**: - - **QA Scenarios (MANDATORY):** - - ``` - Scenario: USAGE.md has required content - Tool: Bash - Preconditions: File created - Steps: - 1. Run `wc -l /home/m3tam3re/p/AI/AGENTS/rules/USAGE.md` - 2. Run `grep -c 'm3ta-nixpkgs\|mkOpencodeRules\|gitignore\|AGENTS.md\|nix flake update' /home/m3tam3re/p/AI/AGENTS/rules/USAGE.md` - Expected Result: Under 100 lines, key terms >= 5 - Failure Indicators: Over 100 lines or missing key concepts - Evidence: .sisyphus/evidence/task-5-usage.txt - ``` - - **Commit**: YES (groups with T1) - - Message: `feat(rules): add rules directory structure and usage documentation` - - Files: `rules/USAGE.md`, `rules/concerns/.gitkeep`, `rules/languages/.gitkeep`, `rules/frameworks/.gitkeep` - ---- - -- [x] 6. Create `rules/concerns/coding-style.md` - - **What to do**: - - Write coding style rules: code formatting, patterns/anti-patterns, error handling, type safety, function design, DRY/SOLID - - Imperative language ("Always...", "Never...", "Prefer..."), micro-examples (`Correct:` / `Incorrect:`) - - Keep under 200 lines, sandwich principle (critical rules at start and end) - - **Must NOT do**: No language-specific toolchain details, no generic advice ("write clean code"), max 200 lines - - **Recommended Agent Profile**: `writing`, Skills: [] - **Parallelization**: Wave 2, parallel with T7-T16. Blocks T17. Blocked by T1. - - **References**: - - `/home/m3tam3re/p/AI/AGENTS/skills/skill-creator/SKILL.md` — documentation density example - - Awesome Cursorrules: `https://github.com/PatrickJS/awesome-cursorrules` - - **Acceptance Criteria**: - ``` - Scenario: Quality check - Tool: Bash - Steps: - 1. `wc -l` → under 200 - 2. `grep -c 'Correct:\|Incorrect:\|Always\|Never\|Prefer'` → >= 10 - 3. `grep -c '```'` → >= 6 (3+ example pairs) - 4. `grep -ic 'write clean code\|follow best practices'` → 0 - Evidence: .sisyphus/evidence/task-6-coding-style.txt - ``` - **Commit**: NO (groups with Wave 2 commit in T17) - ---- - -- [x] 7. Create `rules/concerns/naming.md` - - **What to do**: - - Naming conventions: files, variables, functions, classes, modules, constants - - Per-language table (Python=snake_case, TS=camelCase, Nix=camelCase, Shell=UPPER_SNAKE) - - Keep under 150 lines - - **Must NOT do**: No toolchain details, max 150 lines - - **Recommended Agent Profile**: `writing`, Skills: [] - **Parallelization**: Wave 2. Blocks T17. Blocked by T1. - - **References**: `/home/m3tam3re/p/AI/AGENTS/AGENTS.md:58-62` — existing naming conventions - - **Acceptance Criteria**: - ``` - Scenario: `wc -l` → under 150, `grep -c 'snake_case\|camelCase\|PascalCase\|UPPER_SNAKE'` → >= 4 - Evidence: .sisyphus/evidence/task-7-naming.txt - ``` - **Commit**: NO - ---- - -- [x] 8. Create `rules/concerns/documentation.md` - - **What to do**: When to document, docstring formats, inline comment philosophy (WHY not WHAT), README standards. Under 150 lines. - **Recommended Agent Profile**: `writing` - **Parallelization**: Wave 2. Blocked by T1. - **References**: `/home/m3tam3re/p/AI/AGENTS/AGENTS.md` — repo's own style - **Acceptance Criteria**: `wc -l` < 150, `grep -c 'WHY\|WHAT\|Correct:\|Incorrect:'` >= 4 - **Commit**: NO - ---- - -- [x] 9. Create `rules/concerns/testing.md` - - **What to do**: Arrange-act-assert, behavior vs implementation testing, mocking philosophy, coverage, TDD. Under 200 lines. - **Recommended Agent Profile**: `writing` - **Parallelization**: Wave 2. Blocked by T1. - **References**: `/home/m3tam3re/p/AI/AGENTS/AGENTS.md:73-82` — existing test philosophy - **Acceptance Criteria**: `wc -l` < 200, `grep -ic 'arrange\|act\|assert\|mock\|behavior'` >= 4 - **Commit**: NO - ---- - -- [x] 10. Create `rules/concerns/git-workflow.md` - - **What to do**: Conventional commits, branch naming, PR descriptions, squash vs merge. Under 120 lines. - **Recommended Agent Profile**: `writing`, Skills: [`git-master`] - **Parallelization**: Wave 2. Blocked by T1. - **References**: `https://www.conventionalcommits.org/en/v1.0.0/` - **Acceptance Criteria**: `wc -l` < 120, `grep -c 'feat\|fix\|refactor\|docs\|chore'` >= 5 - **Commit**: NO - ---- - -- [x] 11. Create `rules/concerns/project-structure.md` - - **What to do**: Directory layout, module organization, entry points, config placement. Per-type: Python (src layout), TS (src/), Nix (modules/). Under 120 lines. - **Recommended Agent Profile**: `writing` - **Parallelization**: Wave 2. Blocked by T1. - **References**: `/home/m3tam3re/p/AI/AGENTS/AGENTS.md:24-38` — repo structure - **Acceptance Criteria**: `wc -l` < 120 - **Commit**: NO - ---- - -- [x] 12. Create `rules/languages/python.md` - - **What to do**: - - Deep Python patterns: `uv` (pkg mgmt), `ruff` (lint/fmt), `pyright` (types), `pytest` + `hypothesis`, Pydantic for data boundaries - - Idioms: comprehensions, context managers, generators, f-strings - - Anti-patterns: bare except, mutable defaults, global state, star imports - - Project setup: `pyproject.toml`, src layout - - Under 250 lines with micro-examples - - **Must NOT do**: No general coding style (covered in concerns/), no Django/Flask/FastAPI, max 250 lines - - **Recommended Agent Profile**: `writing` - **Parallelization**: Wave 2. Blocked by T1. - - **References**: - - `/home/m3tam3re/p/AI/AGENTS/AGENTS.md:60` — existing Python conventions (shebang, docstrings) - - Ruff docs: `https://docs.astral.sh/ruff/`, uv docs: `https://docs.astral.sh/uv/` - - **Acceptance Criteria**: `wc -l` < 250, `grep -c 'ruff\|uv\|pytest\|pydantic\|pyright'` >= 4, `grep -c '```python'` >= 5, no "pythonic"/"best practice" - **Commit**: NO - ---- - -- [x] 13. Create `rules/languages/typescript.md` - - **What to do**: - - Strict mode (`strict: true`, `noUncheckedIndexedAccess`), discriminated unions, branded types, `satisfies`, `as const` - - Modern: `using`, `Promise.withResolvers()`, `Object.groupBy()` - - Toolchain: `bun`/`tsx`, `biome`/`eslint` - - Anti-patterns: `as any`, `@ts-ignore`, `!` assertion, `enum` (prefer union) - - Under 250 lines - - **Must NOT do**: No React/Next.js, max 250 lines - - **Recommended Agent Profile**: `writing` - **Parallelization**: Wave 2. Blocked by T1. - **Acceptance Criteria**: `wc -l` < 250, `grep -c 'strict\|as any\|ts-ignore\|discriminated\|satisfies'` >= 4, `grep -c '```ts'` >= 5 - **Commit**: NO - ---- - -- [x] 14. Create `rules/languages/nix.md` - - **What to do**: - - Flake structure, module patterns (`{ config, lib, pkgs, ... }:`), `mkIf`/`mkMerge` - - Formatting: `alejandra`, naming: camelCase - - Anti-patterns: `with pkgs;`, `builtins.fetchTarball`, impure ops - - Home Manager patterns, overlays - - Under 200 lines - - **Recommended Agent Profile**: `writing` - **Parallelization**: Wave 2. Blocked by T1. - - **References**: - - `/home/m3tam3re/p/NIX/nixos-config/home/features/coding/opencode.nix` — user's actual Nix style - - `/home/m3tam3re/p/NIX/nixpkgs/lib/ports.nix` — well-structured Nix code example - - **Acceptance Criteria**: `wc -l` < 200, `grep -c 'flake\|mkShell\|alejandra\|with pkgs\|overlay'` >= 4 - **Commit**: NO - ---- - -- [x] 15. Create `rules/languages/shell.md` - - **What to do**: `set -euo pipefail`, shellcheck, quoting, local vars, POSIX portability, `#!/usr/bin/env bash`. Under 120 lines. - **Recommended Agent Profile**: `writing` - **Parallelization**: Wave 2. Blocked by T1. - **References**: `/home/m3tam3re/p/AI/AGENTS/AGENTS.md:61`, `/home/m3tam3re/p/AI/AGENTS/scripts/test-skill.sh` - **Acceptance Criteria**: `wc -l` < 120, `grep -c 'set -euo pipefail\|shellcheck\|#!/usr/bin/env'` >= 2 - **Commit**: NO - ---- - -- [x] 16. Create `rules/frameworks/n8n.md` - - **What to do**: Workflow design, node patterns, naming, Error Trigger, data patterns, security. Under 120 lines. - **Recommended Agent Profile**: `writing` - **Parallelization**: Wave 2. Blocked by T1. - **References**: n8n docs: `https://docs.n8n.io/` - **Acceptance Criteria**: `wc -l` < 120, `grep -c 'workflow\|node\|Error Trigger\|webhook\|credential'` >= 4 - **Commit**: NO - ---- - -- [x] 17. End-to-end integration test + commits - - **What to do**: - 1. Verify all 11 rule files exist and meet line count limits - 2. Verify `lib/opencode-rules.nix` in nixpkgs evaluates correctly for: empty, single-lang, multi-lang, with-frameworks - 3. Verify full lib import works: `m3taLib.opencode-rules.mkOpencodeRules` - 4. Verify generated `opencode.json` is valid JSON with correct `instructions` paths - 5. Verify all instruction paths resolve to real files in AGENTS repo rules/ - 6. Verify total context budget: all concerns + 1 language < 1500 lines - 7. Verify `opencode.nix` has the rules deployment entry - 8. Commit all Wave 2 rule files as a single commit in AGENTS repo - - **Must NOT do**: Do not run `home-manager switch`, do not modify files, do not create test projects - - **Recommended Agent Profile**: `deep`, Skills: [`git-master`] - **Parallelization**: Wave 3 (sequential). Blocks F1-F4. Blocked by T2-T5, T6-T16. - - **References**: - - `/home/m3tam3re/p/NIX/nixpkgs/lib/opencode-rules.nix` — Nix helper to evaluate - - `/home/m3tam3re/p/NIX/nixos-config/home/features/coding/opencode.nix` — deployment config - - **Acceptance Criteria**: - - **QA Scenarios (MANDATORY):** - - ``` - Scenario: All rule files exist and meet limits - Tool: Bash - Steps: - 1. For each of 11 files: `wc -l` and verify under limit - Expected Result: All 11 files present, all under limits - Evidence: .sisyphus/evidence/task-17-inventory.txt - - Scenario: Full lib integration - Tool: Bash - Steps: - 1. Run `nix eval --impure --json --expr 'let pkgs = import {}; m3taLib = import /home/m3tam3re/p/NIX/nixpkgs/lib {lib = pkgs.lib;}; in (m3taLib.opencode-rules.mkOpencodeRules { agents = /home/m3tam3re/p/AI/AGENTS; languages = ["python" "typescript" "nix" "shell"]; frameworks = ["n8n"]; }).instructions'` - Expected Result: JSON array with 11 paths (6 concerns + 4 langs + 1 framework) - Failure Indicators: Wrong count, error - Evidence: .sisyphus/evidence/task-17-full-integration.txt - - Scenario: All paths resolve to real files - Tool: Bash - Steps: - 1. For each path in instructions output: verify the corresponding file exists under `rules/` - Expected Result: All paths resolve, none missing - Evidence: .sisyphus/evidence/task-17-paths-resolve.txt - - Scenario: Total context budget - Tool: Bash - Steps: - 1. `cat /home/m3tam3re/p/AI/AGENTS/rules/concerns/*.md | wc -l` - 2. `wc -l < /home/m3tam3re/p/AI/AGENTS/rules/languages/python.md` - 3. Sum must be < 1500 - Expected Result: Total under 1500 - Evidence: .sisyphus/evidence/task-17-budget.txt - ``` - - **Commit**: YES - - Message: `feat(rules): add initial rule files for all concerns, languages, and frameworks` - - Files: all `rules/**/*.md` files (11 total) - - Repo: AGENTS - ---- - -## Final Verification Wave (MANDATORY — after ALL implementation tasks) - -> 4 review agents run in PARALLEL. ALL must APPROVE. Rejection → fix → re-run. - -- [x] F1. **Plan Compliance Audit** — `oracle` - For each "Must Have": verify implementation exists. For each "Must NOT Have": search for violations. Check evidence files. Compare deliverables across all 3 repos. - Output: `Must Have [N/N] | Must NOT Have [N/N] | Tasks [N/N] | VERDICT` - -- [x] F2. **Code Quality Review** — `unspecified-high` - Rule files: no generic advice, has examples, consistent tone, under limits. Nix: valid syntax, correct paths, edge cases. USAGE.md: accurate. - Output: `Files [N clean/N issues] | VERDICT` - -- [x] F3. **Real Manual QA** — `unspecified-high` - Run `nix eval` on opencode-rules.nix via full lib import with various configs. Verify JSON. Check rule content quality. Save to `.sisyphus/evidence/final-qa/`. - Output: `Scenarios [N/N pass] | VERDICT` - -- [x] F4. **Scope Fidelity Check** — `deep` - For each task: "What to do" vs actual file. 1:1 match. No creep. Check "Must NOT do". Flag unaccounted changes across all 3 repos. - Output: `Tasks [N/N compliant] | Unaccounted [CLEAN/N files] | VERDICT` - ---- - -## Commit Strategy - -| After Task(s) | Repo | Message | Files | -|---------------|------|---------|-------| -| 1, 5 | AGENTS | `feat(rules): add rules directory structure and usage documentation` | `rules/USAGE.md`, `rules/{concerns,languages,frameworks}/.gitkeep` | -| 2, 3 | nixpkgs | `feat(lib): add opencode-rules helper for per-project rule injection` | `lib/opencode-rules.nix`, `lib/default.nix` | -| 4 | nixos-config | `feat(opencode): deploy rules/ to ~/.config/opencode/rules/` | `opencode.nix` | -| 17 | AGENTS | `feat(rules): add initial rule files for concerns, languages, and frameworks` | all `rules/**/*.md` (11 files) | - ---- - -## Success Criteria - -### Verification Commands -```bash -# All rule files exist (AGENTS repo) -ls rules/concerns/*.md rules/languages/*.md rules/frameworks/*.md - -# Context budget -cat rules/concerns/*.md rules/languages/python.md | wc -l # Expected: < 1500 - -# Nix helper via full lib (nixpkgs) -nix eval --impure --json --expr 'let pkgs = import {}; m3taLib = import /path/to/nixpkgs/lib {lib = pkgs.lib;}; in (m3taLib.opencode-rules.mkOpencodeRules { agents = /path/to/AGENTS; languages = ["python"]; }).instructions' - -# opencode.nix has rules entry (nixos-config) -grep 'opencode/rules' /home/m3tam3re/p/NIX/nixos-config/home/features/coding/opencode.nix -``` - -### Final Checklist -- [ ] All 11 rule files present and under line limits -- [ ] All rule files use imperative language with micro-examples -- [ ] `lib/opencode-rules.nix` in nixpkgs follows ports.nix pattern exactly -- [ ] `lib/default.nix` imports opencode-rules -- [ ] `opencode.nix` deploys rules/ alongside skills/commands/context/prompts -- [ ] `rules/USAGE.md` documents nixpkgs consumption pattern correctly -- [ ] No Nix code in AGENTS repo -- [ ] No existing files modified (except lib/default.nix +1 line, opencode.nix +3 lines) -- [ ] Total loaded context under 1500 lines for any realistic configuration diff --git a/AGENTS.md b/AGENTS.md index a646a5f..a3dd42c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,15 +1,5 @@ # Opencode Skills Repository -## MANDATORY: Use td for Task Management - -Run td usage --new-session at conversation start (or after /clear). This tells you what to work on next. - -Sessions are automatic (based on terminal/agent context). Optional: -- td session "name" to label the current session -- td session --new to force a new session in the same context - -Use td usage -q after first read. - Configuration repository for Opencode Agent Skills, context files, and agent configurations. Deployed via Nix home-manager to `~/.config/opencode/`. ## Quick Commands @@ -22,21 +12,22 @@ Configuration repository for Opencode Agent Skills, context files, and agent con # Skill creation python3 skills/skill-creator/scripts/init_skill.py --path skills/ - -# Issue tracking (beads) -bd ready && bd create "title" && bd close && bd sync ``` ## Directory Structure ``` . -├── skills/ # Agent skills (25 modules) +├── skills/ # Agent skills (15 modules) │ └── skill-name/ │ ├── SKILL.md # Required: YAML frontmatter + workflows │ ├── scripts/ # Executable code (optional) │ ├── references/ # Domain docs (optional) -│ └── assets/ # Templates/files (optional) +│ └── assets/ # Templates/files (optional) +├── rules/ # AI coding rules (languages, concerns, frameworks) +│ ├── languages/ # Python, TypeScript, Nix, Shell +│ ├── concerns/ # Testing, naming, documentation, etc. +│ └── frameworks/ # Framework-specific rules (n8n, etc.) ├── agents/ # Agent definitions (agents.json) ├── prompts/ # System prompts (chiron*.txt) ├── context/ # User profiles @@ -68,7 +59,7 @@ compatibility: opencode ## Anti-Patterns (CRITICAL) **Frontend Design**: NEVER use generic AI aesthetics, NEVER converge on common choices -**Excalidraw**: NEVER use diamond shapes (broken arrows), NEVER use `label` property +**Excalidraw**: NEVER use `label` property (use boundElements + text element pairs instead) **Debugging**: NEVER fix just symptom, ALWAYS find root cause first **Excel**: ALWAYS respect existing template conventions over guidelines **Structure**: NEVER place scripts/docs outside scripts/references/ directories @@ -87,27 +78,46 @@ compatibility: opencode ## Deployment -**Nix pattern** (non-flake input): +**Nix flake pattern**: ```nix agents = { url = "git+https://code.m3ta.dev/m3tam3re/AGENTS"; - flake = false; # Files only, not a Nix flake + inputs.nixpkgs.follows = "nixpkgs"; # Optional but recommended }; ``` +**Exports:** +- `packages.skills-runtime` — composable runtime with all skill dependencies +- `devShells.default` — dev environment for working on skills + **Mapping** (via home-manager): - `skills/`, `context/`, `commands/`, `prompts/` → symlinks - `agents/agents.json` → embedded into config.json - Agent changes: require `home-manager switch` - Other changes: visible immediately +## Rules System + +Centralized AI coding rules consumed via `mkOpencodeRules` from m3ta-nixpkgs: + +```nix +# In project flake.nix +m3taLib.opencode-rules.mkOpencodeRules { + inherit agents; + languages = [ "python" "typescript" ]; + frameworks = [ "n8n" ]; +}; +``` + +See `rules/USAGE.md` for full documentation. + ## Notes for AI Agents 1. **Config-only repo** - No compilation, no build, manual validation only 2. **Skills are documentation** - Write for AI consumption, progressive disclosure 3. **Consistent structure** - All skills follow 4-level deep pattern (skills/name/ + optional subdirs) 4. **Cross-cutting concerns** - Standardized SKILL.md, workflow patterns, delegation rules -5. **Always push** - Session completion workflow: commit + bd sync + git push +5. **Always push** - Session completion workflow: commit + git push ## Quality Gates @@ -115,4 +125,5 @@ Before committing: 1. `./scripts/test-skill.sh --validate` 2. Python shebang + docstrings check 3. No extraneous files (README.md, CHANGELOG.md in skills/) -4. Git status clean +4. If skill has scripts with external dependencies → verify `flake.nix` is updated (see skill-creator Step 4) +5. Git status clean diff --git a/README.md b/README.md index 48248db..77babdf 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ This repository serves as a **personal AI operating system** - a collection of s - **Productivity & Task Management** - PARA methodology, GTD workflows, project tracking - **Knowledge Management** - Note-taking, research workflows, information organization -- **Communications** - Email management, meeting scheduling, follow-up tracking - **AI Development** - Tools for creating new skills and agent configurations - **Memory & Context** - Persistent memory systems, conversation analysis - **Document Processing** - PDF manipulation, spreadsheet handling, diagram generation @@ -24,7 +23,7 @@ This repository serves as a **personal AI operating system** - a collection of s │ └── profile.md # Work style, PARA areas, preferences ├── commands/ # Custom command definitions │ └── reflection.md -├── skills/ # Opencode Agent Skills (18 skills) +├── skills/ # Opencode Agent Skills (15 skills) │ ├── agent-development/ # Agent creation and configuration │ ├── basecamp/ # Basecamp project management │ ├── brainstorming/ # Ideation & strategic thinking @@ -32,11 +31,8 @@ This repository serves as a **personal AI operating system** - a collection of s │ ├── excalidraw/ # Architecture diagrams │ ├── frontend-design/ # UI/UX design patterns │ ├── memory/ # Persistent memory system -│ ├── mem0-memory/ # DEPRECATED (use memory) -│ ├── msteams/ # Microsoft Teams integration │ ├── obsidian/ # Obsidian vault management │ ├── outline/ # Outline wiki integration -│ ├── outlook/ # Outlook email & calendar │ ├── pdf/ # PDF manipulation toolkit │ ├── prompt-engineering-patterns/ # Prompt patterns │ ├── reflection/ # Conversation analysis @@ -45,8 +41,12 @@ This repository serves as a **personal AI operating system** - a collection of s │ └── xlsx/ # Spreadsheet handling ├── scripts/ # Repository utility scripts │ └── test-skill.sh # Test skills without deploying -├── rules/ # Development rules and conventions -├── tools/ # Utility tools +├── rules/ # AI coding rules +│ ├── languages/ # Python, TypeScript, Nix, Shell +│ ├── concerns/ # Testing, naming, documentation +│ └── frameworks/ # Framework-specific rules (n8n) +├── flake.nix # Nix flake: dev shell + skills-runtime export +├── .envrc # direnv config (use flake) ├── AGENTS.md # Developer documentation └── README.md # This file ``` @@ -55,21 +55,26 @@ This repository serves as a **personal AI operating system** - a collection of s ### Prerequisites -- **Opencode** - AI coding assistant ([opencode.dev](https://opencode.ai)) -- **Nix** (optional) - For declarative deployment via home-manager -- **Python 3** - For skill validation and creation scripts +- **Nix** with flakes enabled — for reproducible dependency management and deployment +- **direnv** (recommended) — auto-activates the development environment when entering the repo +- **Opencode** — AI coding assistant ([opencode.ai](https://opencode.ai)) ### Installation #### Option 1: Nix Flake (Recommended) -This repository is consumed as a **non-flake input** by your NixOS configuration: +This repository is a **Nix flake** that exports: + +- **`devShells.default`** — development environment for working on skills (activated via direnv) +- **`packages.skills-runtime`** — composable runtime with all skill script dependencies (Python packages + system tools) + +**Consume in your system flake:** ```nix -# In your flake.nix +# flake.nix inputs.agents = { url = "git+https://code.m3ta.dev/m3tam3re/AGENTS"; - flake = false; # Pure files, not a Nix flake + inputs.nixpkgs.follows = "nixpkgs"; }; # In your home-manager module (e.g., opencode.nix) @@ -85,7 +90,55 @@ programs.opencode.settings.agent = builtins.fromJSON (builtins.readFile "${inputs.agents}/agents/agents.json"); ``` -Rebuild your system: +**Deploy skills via home-manager:** + +```nix +# home-manager module (e.g., opencode.nix) +{ inputs, system, ... }: +{ + # Skill files — symlinked, changes visible immediately + xdg.configFile = { + "opencode/skills".source = "${inputs.agents}/skills"; + "opencode/context".source = "${inputs.agents}/context"; + "opencode/commands".source = "${inputs.agents}/commands"; + "opencode/prompts".source = "${inputs.agents}/prompts"; + }; + + # Agent config — embedded into config.json (requires home-manager switch) + programs.opencode.settings.agent = builtins.fromJSON + (builtins.readFile "${inputs.agents}/agents/agents.json"); + + # Skills runtime — ensures opencode always has script dependencies + home.packages = [ inputs.agents.packages.${system}.skills-runtime ]; +} +``` + +**Compose into project flakes** (so opencode has skill deps in any project): + +```nix +# Any project's flake.nix +{ + inputs.agents.url = "git+https://code.m3ta.dev/m3tam3re/AGENTS"; + inputs.agents.inputs.nixpkgs.follows = "nixpkgs"; + + outputs = { self, nixpkgs, agents, ... }: + let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + in { + devShells.${system}.default = pkgs.mkShell { + packages = [ + # project-specific tools + pkgs.nodejs + # skill script dependencies + agents.packages.${system}.skills-runtime + ]; + }; + }; +} +``` + +Rebuild: ```bash home-manager switch @@ -151,25 +204,35 @@ compatibility: opencode [Your skill instructions for Opencode] ``` -### 3. Validate the Skill +### 3. Register Dependencies + +If your skill includes scripts with external dependencies, add them to `flake.nix`: + +```nix +# Python packages — add to pythonEnv: +# my-skill: my_script.py +some-python-package + +# System tools — add to skills-runtime paths: +# my-skill: needed by my_script.py +pkgs.some-tool +``` + +Verify: `nix develop --command python3 -c "import some_package"` + +### 4. Validate the Skill ```bash python3 skills/skill-creator/scripts/quick_validate.py skills/my-skill-name ``` -### 4. Test the Skill - -Test your skill without deploying via home-manager: +### 5. Test the Skill ```bash -# Use the test script to validate and list skills ./scripts/test-skill.sh my-skill-name # Validate specific skill -./scripts/test-skill.sh --list # List all dev skills -./scripts/test-skill.sh --run # Launch opencode with dev skills +./scripts/test-skill.sh --run # Launch opencode with dev skills ``` -The test script creates a temporary config directory with symlinks to this repo's skills, allowing you to test changes before committing. - ## 📚 Available Skills | Skill | Purpose | Status | @@ -181,11 +244,8 @@ The test script creates a temporary config directory with symlinks to this repo' | **excalidraw** | Architecture diagrams from codebase analysis | ✅ Active | | **frontend-design** | Production-grade UI/UX with high design quality | ✅ Active | | **memory** | SQLite-based persistent memory with hybrid search | ✅ Active | -| **mem0-memory** | Legacy memory system (deprecated) | ⚠️ Deprecated | -| **msteams** | Microsoft Teams integration via Graph API | ✅ Active | | **obsidian** | Obsidian vault management via Local REST API | ✅ Active | | **outline** | Outline wiki integration for team documentation | ✅ Active | -| **outlook** | Outlook email, calendar, and contact management | ✅ Active | | **pdf** | PDF manipulation, extraction, creation, and forms | ✅ Active | | **prompt-engineering-patterns** | Advanced prompt engineering techniques | ✅ Active | | **reflection** | Conversation analysis and skill improvement | ✅ Active | @@ -213,7 +273,23 @@ The test script creates a temporary config directory with symlinks to this repo' **Configuration**: `agents/agents.json` + `prompts/*.txt` -## 🛠️ Development Workflow +## 🛠️ Development + +### Environment + +The repository includes a Nix flake with a development shell. With [direnv](https://direnv.net/) installed, the environment activates automatically: + +```bash +cd AGENTS/ +# → direnv: loading .envrc +# → 🔧 AGENTS dev shell active — Python 3.13.x, jq-1.x + +# All skill script dependencies are now available: +python3 -c "import pypdf, openpyxl, yaml" # ✔️ +pdftoppm -v # ✔️ +``` + +Without direnv, activate manually: `nix develop` ### Quality Gates @@ -232,6 +308,7 @@ Before committing: - **skills/skill-creator/SKILL.md** - Comprehensive skill creation guide - **skills/skill-creator/references/workflows.md** - Workflow pattern library - **skills/skill-creator/references/output-patterns.md** - Output formatting patterns +- **rules/USAGE.md** - AI coding rules integration guide ### Skill Design Principles @@ -247,6 +324,7 @@ Before committing: - **basecamp/** - MCP server integration with multiple tool categories - **brainstorming/** - Framework-based ideation with Obsidian markdown save - **memory/** - SQLite-based hybrid search implementation +- **excalidraw/** - Diagram generation with JSON templates and Python renderer ## 🔧 Customization @@ -277,6 +355,21 @@ Edit `context/profile.md` to configure: Create new command definitions in `commands/` directory following the pattern in `commands/reflection.md`. +### Add Project Rules + +Use the rules system to inject AI coding rules into projects: + +```nix +# In project flake.nix +m3taLib.opencode-rules.mkOpencodeRules { + inherit agents; + languages = [ "python" "typescript" ]; + frameworks = [ "n8n" ]; +}; +``` + +See `rules/USAGE.md` for full documentation. + ## 🌟 Use Cases ### Personal Productivity diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..6ddf919 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1772479524, + "narHash": "sha256-u7nCaNiMjqvKpE+uZz9hE7pgXXTmm5yvdtFaqzSzUQI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4215e62dc2cd3bc705b0a423b9719ff6be378a43", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..5b7d66a --- /dev/null +++ b/flake.nix @@ -0,0 +1,68 @@ +{ + description = "Opencode Agent Skills — development environment & runtime"; + + inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; }; + + outputs = { self, nixpkgs }: + let + supportedSystems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ]; + forAllSystems = nixpkgs.lib.genAttrs supportedSystems; + in { + # Composable runtime for project flakes and home-manager. + # Usage: + # home.packages = [ inputs.agents.packages.${system}.skills-runtime ]; + # devShells.default = pkgs.mkShell { + # packages = [ inputs.agents.packages.${system}.skills-runtime ]; + # }; + packages = forAllSystems (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + + pythonEnv = pkgs.python3.withPackages (ps: + with ps; [ + # skill-creator: quick_validate.py + pyyaml + + # xlsx: recalc.py + openpyxl + + # prompt-engineering-patterns: optimize-prompt.py + numpy + + # pdf: multiple scripts + pypdf + pillow # PIL + pdf2image + + # excalidraw: render_excalidraw.py + playwright + ]); + in { + skills-runtime = pkgs.buildEnv { + name = "opencode-skills-runtime"; + paths = [ + pythonEnv + pkgs.poppler-utils # pdf: pdftoppm/pdfinfo + pkgs.jq # shell scripts + pkgs.playwright-driver.browsers # excalidraw: chromium for rendering + ]; + }; + }); + + # Dev shell for working on this repo (wraps skills-runtime). + devShells = forAllSystems (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in { + default = pkgs.mkShell { + packages = [ self.packages.${system}.skills-runtime ]; + + env.PLAYWRIGHT_BROWSERS_PATH = "${pkgs.playwright-driver.browsers}"; + + shellHook = '' + echo "🔧 AGENTS dev shell active — Python $(python3 --version 2>&1 | cut -d' ' -f2), $(jq --version)" + ''; + }; + }); + }; +} diff --git a/skills/excalidraw/SKILL.md b/skills/excalidraw/SKILL.md index 1583288..f9d46f8 100644 --- a/skills/excalidraw/SKILL.md +++ b/skills/excalidraw/SKILL.md @@ -1,266 +1,544 @@ --- name: excalidraw -description: Generate architecture diagrams as .excalidraw files from codebase analysis. Use when the user asks to create architecture diagrams, system diagrams, visualize codebase structure, or generate excalidraw files. +description: "Create Excalidraw diagram JSON files that make visual arguments. Use when: (1) user wants to visualize workflows, architectures, or concepts, (2) creating system diagrams, (3) generating .excalidraw files. Triggers: excalidraw, diagram, visualize, architecture diagram, system diagram." +compatibility: opencode --- -# Excalidraw Diagram Generator +# Excalidraw Diagram Creator -Generate architecture diagrams as `.excalidraw` files directly from codebase analysis. +Generate `.excalidraw` JSON files that **argue visually**, not just display information. + +## Customization + +**All colors and brand-specific styles live in one file:** `references/color-palette.md`. Read it before generating any diagram and use it as the single source of truth for all color choices — shape fills, strokes, text colors, evidence artifact backgrounds, everything. + +To make this skill produce diagrams in your own brand style, edit `color-palette.md`. Everything else in this file is universal design methodology and Excalidraw best practices. --- -## Quick Start +## Core Philosophy -**User just asks:** -``` -"Generate an architecture diagram for this project" -"Create an excalidraw diagram of the system" -"Visualize this codebase as an excalidraw file" -``` +**Diagrams should ARGUE, not DISPLAY.** -**Claude Code will:** -1. Analyze the codebase (any language/framework) -2. Identify components, services, databases, APIs -3. Map relationships and data flows -4. Generate valid `.excalidraw` JSON with dynamic IDs and labels +A diagram isn't formatted text. It's a visual argument that shows relationships, causality, and flow that words alone can't express. The shape should BE the meaning. -**No prerequisites:** Works without existing diagrams, Terraform, or specific file types. +**The Isomorphism Test**: If you removed all text, would the structure alone communicate the concept? If not, redesign. + +**The Education Test**: Could someone learn something concrete from this diagram, or does it just label boxes? A good diagram teaches—it shows actual formats, real event names, concrete examples. --- -## Critical Rules +## Depth Assessment (Do This First) -### 1. NEVER Use Diamond Shapes +Before designing, determine what level of detail this diagram needs: -Diamond arrow connections are broken in raw Excalidraw JSON. Use styled rectangles instead: +### Simple/Conceptual Diagrams +Use abstract shapes when: +- Explaining a mental model or philosophy +- The audience doesn't need technical specifics +- The concept IS the abstraction (e.g., "separation of concerns") -| Semantic Meaning | Rectangle Style | -|------------------|-----------------| -| Orchestrator/Hub | Coral (`#ffa8a8`/`#c92a2a`) + strokeWidth: 3 | -| Decision Point | Orange (`#ffd8a8`/`#e8590c`) + dashed stroke | +### Comprehensive/Technical Diagrams +Use concrete examples when: +- Diagramming a real system, protocol, or architecture +- The diagram will be used to teach or explain (e.g., YouTube video) +- The audience needs to understand what things actually look like +- You're showing how multiple technologies integrate -### 2. Labels Require TWO Elements +**For technical diagrams, you MUST include evidence artifacts** (see below). -The `label` property does NOT work in raw JSON. Every labeled shape needs: +--- -```json -// 1. Shape with boundElements reference -{ - "id": "my-box", - "type": "rectangle", - "boundElements": [{ "type": "text", "id": "my-box-text" }] -} +## Research Mandate (For Technical Diagrams) -// 2. Separate text element with containerId -{ - "id": "my-box-text", - "type": "text", - "containerId": "my-box", - "text": "My Label" -} +**Before drawing anything technical, research the actual specifications.** + +If you're diagramming a protocol, API, or framework: +1. Look up the actual JSON/data formats +2. Find the real event names, method names, or API endpoints +3. Understand how the pieces actually connect +4. Use real terminology, not generic placeholders + +Bad: "Protocol" → "Frontend" +Good: "AG-UI streams events (RUN_STARTED, STATE_DELTA, A2UI_UPDATE)" → "CopilotKit renders via createA2UIMessageRenderer()" + +**Research makes diagrams accurate AND educational.** + +--- + +## Evidence Artifacts + +Evidence artifacts are concrete examples that prove your diagram is accurate and help viewers learn. Include them in technical diagrams. + +**Types of evidence artifacts** (choose what's relevant to your diagram): + +| Artifact Type | When to Use | How to Render | +|---------------|-------------|---------------| +| **Code snippets** | APIs, integrations, implementation details | Dark rectangle + syntax-colored text (see color palette for evidence artifact colors) | +| **Data/JSON examples** | Data formats, schemas, payloads | Dark rectangle + colored text (see color palette) | +| **Event/step sequences** | Protocols, workflows, lifecycles | Timeline pattern (line + dots + labels) | +| **UI mockups** | Showing actual output/results | Nested rectangles mimicking real UI | +| **Real input content** | Showing what goes IN to a system | Rectangle with sample content visible | +| **API/method names** | Real function calls, endpoints | Use actual names from docs, not placeholders | + +**Example**: For a diagram about a streaming protocol, you might show: +- The actual event names from the spec (not just "Event 1", "Event 2") +- A code snippet showing how to connect +- What the streamed data actually looks like + +**Example**: For a diagram about a data transformation pipeline: +- Show sample input data (actual format, not "Input") +- Show sample output data (actual format, not "Output") +- Show intermediate states if relevant + +The key principle: **show what things actually look like**, not just what they're called. + +--- + +## Multi-Zoom Architecture + +Comprehensive diagrams operate at multiple zoom levels simultaneously. Think of it like a map that shows both the country borders AND the street names. + +### Level 1: Summary Flow +A simplified overview showing the full pipeline or process at a glance. Often placed at the top or bottom of the diagram. + +*Example*: `Input → Processing → Output` or `Client → Server → Database` + +### Level 2: Section Boundaries +Labeled regions that group related components. These create visual "rooms" that help viewers understand what belongs together. + +*Example*: Grouping by responsibility (Backend / Frontend), by phase (Setup / Execution / Cleanup), or by team (User / System / External) + +### Level 3: Detail Inside Sections +Evidence artifacts, code snippets, and concrete examples within each section. This is where the educational value lives. + +*Example*: Inside a "Backend" section, you might show the actual API response format, not just a box labeled "API Response" + +**For comprehensive diagrams, aim to include all three levels.** The summary gives context, the sections organize, and the details teach. + +### Bad vs Good + +| Bad (Displaying) | Good (Arguing) | +|------------------|----------------| +| 5 equal boxes with labels | Each concept has a shape that mirrors its behavior | +| Card grid layout | Visual structure matches conceptual structure | +| Icons decorating text | Shapes that ARE the meaning | +| Same container for everything | Distinct visual vocabulary per concept | +| Everything in a box | Free-floating text with selective containers | + +### Simple vs Comprehensive (Know Which You Need) + +| Simple Diagram | Comprehensive Diagram | +|----------------|----------------------| +| Generic labels: "Input" → "Process" → "Output" | Specific: shows what the input/output actually looks like | +| Named boxes: "API", "Database", "Client" | Named boxes + examples of actual requests/responses | +| "Events" or "Messages" label | Timeline with real event/message names from the spec | +| "UI" or "Dashboard" rectangle | Mockup showing actual UI elements and content | +| ~30 seconds to explain | ~2-3 minutes of teaching content | +| Viewer learns the structure | Viewer learns the structure AND the details | + +**Simple diagrams** are fine for abstract concepts, quick overviews, or when the audience already knows the details. **Comprehensive diagrams** are needed for technical architectures, tutorials, educational content, or when you want the diagram itself to teach. + +--- + +## Container vs. Free-Floating Text + +**Not every piece of text needs a shape around it.** Default to free-floating text. Add containers only when they serve a purpose. + +| Use a Container When... | Use Free-Floating Text When... | +|------------------------|-------------------------------| +| It's the focal point of a section | It's a label or description | +| It needs visual grouping with other elements | It's supporting detail or metadata | +| Arrows need to connect to it | It describes something nearby | +| The shape itself carries meaning (decision diamond, etc.) | It's a section title, subtitle, or annotation | +| It represents a distinct "thing" in the system | It's a section title, subtitle, or annotation | + +**Typography as hierarchy**: Use font size, weight, and color to create visual hierarchy without boxes. A 28px title doesn't need a rectangle around it. + +**The container test**: For each boxed element, ask "Would this work as free-floating text?" If yes, remove the container. + +--- + +## Design Process (Do This BEFORE Generating JSON) + +### Step 0: Assess Depth Required +Before anything else, determine if this needs to be: +- **Simple/Conceptual**: Abstract shapes, labels, relationships (mental models, philosophies) +- **Comprehensive/Technical**: Concrete examples, code snippets, real data (systems, architectures, tutorials) + +**If comprehensive**: Do research first. Look up actual specs, formats, event names, APIs. + +### Step 1: Understand Deeply +Read the content. For each concept, ask: +- What does this concept **DO**? (not what IS it) +- What relationships exist between concepts? +- What's the core transformation or flow? +- **What would someone need to SEE to understand this?** (not just read about) + +### Step 2: Map Concepts to Patterns +For each concept, find the visual pattern that mirrors its behavior: + +| If the concept... | Use this pattern | +|-------------------|------------------| +| Spawns multiple outputs | **Fan-out** (radial arrows from center) | +| Combines inputs into one | **Convergence** (funnel, arrows merging) | +| Has hierarchy/nesting | **Tree** (lines + free-floating text) | +| Is a sequence of steps | **Timeline** (line + dots + free-floating labels) | +| Loops or improves continuously | **Spiral/Cycle** (arrow returning to start) | +| Is an abstract state or context | **Cloud** (overlapping ellipses) | +| Transforms input to output | **Assembly line** (before → process → after) | +| Compares two things | **Side-by-side** (parallel with contrast) | +| Separates into phases | **Gap/Break** (visual separation between sections) | + +### Step 3: Ensure Variety +For multi-concept diagrams: **each major concept must use a different visual pattern**. No uniform cards or grids. + +### Step 4: Sketch the Flow +Before JSON, mentally trace how the eye moves through the diagram. There should be a clear visual story. + +### Step 5: Generate JSON +Only now create the Excalidraw elements. **See below for how to handle large diagrams.** + +### Step 6: Render & Validate (MANDATORY) +After generating the JSON, you MUST run the render-view-fix loop until the diagram looks right. This is not optional — see the **Render & Validate** section below for the full process. + +--- + +## Large / Comprehensive Diagram Strategy + +**For comprehensive or technical diagrams, you MUST build the JSON one section at a time.** Do NOT attempt to generate the entire file in a single pass. This is a hard constraint — output token limits mean a comprehensive diagram easily exceeds capacity in one shot. Even if it didn't, generating everything at once leads to worse quality. Section-by-section is better in every way. + +### The Section-by-Section Workflow + +**Phase 1: Build each section** + +1. **Create the base file** with the JSON wrapper (`type`, `version`, `appState`, `files`) and the first section of elements. +2. **Add one section per edit.** Each section gets its own dedicated pass — take your time with it. Think carefully about the layout, spacing, and how this section connects to what's already there. +3. **Use descriptive string IDs** (e.g., `"trigger_rect"`, `"arrow_fan_left"`) so cross-section references are readable. +4. **Namespace seeds by section** (e.g., section 1 uses 100xxx, section 2 uses 200xxx) to avoid collisions. +5. **Update cross-section bindings** as you go. When a new section's element needs to bind to an element from a previous section (e.g., an arrow connecting sections), edit the earlier element's `boundElements` array at the same time. + +**Phase 2: Review the whole** + +After all sections are in place, read through the complete JSON and check: +- Are cross-section arrows bound correctly on both ends? +- Is the overall spacing balanced, or are some sections cramped while others have too much whitespace? +- Do IDs and bindings all reference elements that actually exist? + +Fix any alignment or binding issues before rendering. + +**Phase 3: Render & validate** + +Now run the render-view-fix loop from the Render & Validate section. This is where you'll catch visual issues that aren't obvious from JSON — overlaps, clipping, imbalanced composition. + +### Section Boundaries + +Plan your sections around natural visual groupings from the diagram plan. A typical large diagram might split into: + +- **Section 1**: Entry point / trigger +- **Section 2**: First decision or routing +- **Section 3**: Main content (hero section — may be the largest single section) +- **Section 4-N**: Remaining phases, outputs, etc. + +Each section should be independently understandable: its elements, internal arrows, and any cross-references to adjacent sections. + +### What NOT to Do + +- **Don't generate the entire diagram in one response.** You will hit the output token limit and produce truncated, broken JSON. Even if the diagram is small enough to fit, splitting into sections produces better results. +- **Don't write a Python generator script.** The templating and coordinate math seem helpful but introduce a layer of indirection that makes debugging harder. Hand-crafted JSON with descriptive IDs is more maintainable. + +--- + +## Visual Pattern Library + +### Fan-Out (One-to-Many) +Central element with arrows radiating to multiple targets. Use for: sources, PRDs, root causes, central hubs. +``` + ○ + ↗ + □ → ○ + ↘ + ○ ``` -### 3. Elbow Arrows Need Three Properties +### Convergence (Many-to-One) +Multiple inputs merging through arrows to single output. Use for: aggregation, funnels, synthesis. +``` + ○ ↘ + ○ → □ + ○ ↗ +``` -For 90-degree corners (not curved): +### Tree (Hierarchy) +Parent-child branching with connecting lines and free-floating text (no boxes needed). Use for: file systems, org charts, taxonomies. +``` + label + ├── label + │ ├── label + │ └── label + └── label +``` +Use `line` elements for the trunk and branches, free-floating text for labels. + +### Spiral/Cycle (Continuous Loop) +Elements in sequence with arrow returning to start. Use for: feedback loops, iterative processes, evolution. +``` + □ → □ + ↑ ↓ + □ ← □ +``` + +### Cloud (Abstract State) +Overlapping ellipses with varied sizes. Use for: context, memory, conversations, mental states. + +### Assembly Line (Transformation) +Input → Process Box → Output with clear before/after. Use for: transformations, processing, conversion. +``` + ○○○ → [PROCESS] → □□□ + chaos order +``` + +### Side-by-Side (Comparison) +Two parallel structures with visual contrast. Use for: before/after, options, trade-offs. + +### Gap/Break (Separation) +Visual whitespace or barrier between sections. Use for: phase changes, context resets, boundaries. + +### Lines as Structure +Use lines (type: `line`, not arrows) as primary structural elements instead of boxes: +- **Timelines**: Vertical or horizontal line with small dots (10-20px ellipses) at intervals, free-floating labels beside each dot +- **Tree structures**: Vertical trunk line + horizontal branch lines, with free-floating text labels (no boxes needed) +- **Dividers**: Thin dashed lines to separate sections +- **Flow spines**: A central line that elements relate to, rather than connecting boxes + +``` +Timeline: Tree: + ●─── Label 1 │ + │ ├── item + ●─── Label 2 │ ├── sub + │ │ └── sub + ●─── Label 3 └── item +``` + +Lines + free-floating text often creates a cleaner result than boxes + contained text. + +--- + +## Shape Meaning + +Choose shape based on what it represents—or use no shape at all: + +| Concept Type | Shape | Why | +|--------------|-------|-----| +| Labels, descriptions, details | **none** (free-floating text) | Typography creates hierarchy | +| Section titles, annotations | **none** (free-floating text) | Font size/weight is enough | +| Markers on a timeline | small `ellipse` (10-20px) | Visual anchor, not container | +| Start, trigger, input | `ellipse` | Soft, origin-like | +| End, output, result | `ellipse` | Completion, destination | +| Decision, condition | `diamond` | Classic decision symbol | +| Process, action, step | `rectangle` | Contained action | +| Abstract state, context | overlapping `ellipse` | Fuzzy, cloud-like | +| Hierarchy node | lines + text (no boxes) | Structure through lines | + +**Rule**: Default to no container. Add shapes only when they carry meaning. Aim for <30% of text elements to be inside containers. + +--- + +## Color as Meaning + +Colors encode information, not decoration. Every color choice should come from `references/color-palette.md` — the semantic shape colors, text hierarchy colors, and evidence artifact colors are all defined there. + +**Key principles:** +- Each semantic purpose (start, end, decision, AI, error, etc.) has a specific fill/stroke pair +- Free-floating text uses color for hierarchy (titles, subtitles, details — each at a different level) +- Evidence artifacts (code snippets, JSON examples) use their own dark background + colored text scheme +- Always pair a darker stroke with a lighter fill for contrast + +**Do not invent new colors.** If a concept doesn't fit an existing semantic category, use Primary/Neutral or Secondary. + +--- + +## Modern Aesthetics + +For clean, professional diagrams: + +### Roughness +- `roughness: 0` — Clean, crisp edges. Use for modern/technical diagrams. +- `roughness: 1` — Hand-drawn, organic feel. Use for brainstorming/informal diagrams. + +**Default to 0** for most professional use cases. + +### Stroke Width +- `strokeWidth: 1` — Thin, elegant. Good for lines, dividers, subtle connections. +- `strokeWidth: 2` — Standard. Good for shapes and primary arrows. +- `strokeWidth: 3` — Bold. Use sparingly for emphasis (main flow line, key connections). + +### Opacity +**Always use `opacity: 100` for all elements.** Use color, size, and stroke width to create hierarchy instead of transparency. + +### Small Markers Instead of Shapes +Instead of full shapes, use small dots (10-20px ellipses) as: +- Timeline markers +- Bullet points +- Connection nodes +- Visual anchors for free-floating text + +--- + +## Layout Principles + +### Hierarchy Through Scale +- **Hero**: 300×150 - visual anchor, most important +- **Primary**: 180×90 +- **Secondary**: 120×60 +- **Small**: 60×40 + +### Whitespace = Importance +The most important element has the most empty space around it (200px+). + +### Flow Direction +Guide the eye: typically left→right or top→bottom for sequences, radial for hub-and-spoke. + +### Connections Required +Position alone doesn't show relationships. If A relates to B, there must be an arrow. + +--- + +## Text Rules + +**CRITICAL**: The JSON `text` property contains ONLY readable words. ```json { - "type": "arrow", - "roughness": 0, // Clean lines - "roundness": null, // Sharp corners - "elbowed": true // 90-degree mode + "id": "myElement1", + "text": "Start", + "originalText": "Start" } ``` -### 4. Arrow Edge Calculations - -Arrows must start/end at shape edges, not centers: - -| Edge | Formula | -|------|---------| -| Top | `(x + width/2, y)` | -| Bottom | `(x + width/2, y + height)` | -| Left | `(x, y + height/2)` | -| Right | `(x + width, y + height/2)` | - -**Detailed arrow routing:** See `references/arrows.md` +Settings: `fontSize: 16`, `fontFamily: 3`, `textAlign: "center"`, `verticalAlign: "middle"` --- -## Element Types +## JSON Structure -| Type | Use For | -|------|---------| -| `rectangle` | Services, databases, containers, orchestrators | -| `ellipse` | Users, external systems, start/end points | -| `text` | Labels inside shapes, titles, annotations | -| `arrow` | Data flow, connections, dependencies | -| `line` | Grouping boundaries, separators | - -**Full JSON format:** See `references/json-format.md` - ---- - -## Workflow - -### Step 1: Analyze Codebase - -Discover components by looking for: - -| Codebase Type | What to Look For | -|---------------|------------------| -| Monorepo | `packages/*/package.json`, workspace configs | -| Microservices | `docker-compose.yml`, k8s manifests | -| IaC | Terraform/Pulumi resource definitions | -| Backend API | Route definitions, controllers, DB models | -| Frontend | Component hierarchy, API calls | - -**Use tools:** -- `Glob` → `**/package.json`, `**/Dockerfile`, `**/*.tf` -- `Grep` → `app.get`, `@Controller`, `CREATE TABLE` -- `Read` → README, config files, entry points - -### Step 2: Plan Layout - -**Vertical flow (most common):** -``` -Row 1: Users/Entry points (y: 100) -Row 2: Frontend/Gateway (y: 230) -Row 3: Orchestration (y: 380) -Row 4: Services (y: 530) -Row 5: Data layer (y: 680) - -Columns: x = 100, 300, 500, 700, 900 -Element size: 160-200px x 80-90px -``` - -**Other patterns:** See `references/examples.md` - -### Step 3: Generate Elements - -For each component: -1. Create shape with unique `id` -2. Add `boundElements` referencing text -3. Create text with `containerId` -4. Choose color based on type - -**Color palettes:** See `references/colors.md` - -### Step 4: Add Connections - -For each relationship: -1. Calculate source edge point -2. Plan elbow route (avoid overlaps) -3. Create arrow with `points` array -4. Match stroke color to destination type - -**Arrow patterns:** See `references/arrows.md` - -### Step 5: Add Grouping (Optional) - -For logical groupings: -- Large transparent rectangle with `strokeStyle: "dashed"` -- Standalone text label at top-left - -### Step 6: Validate and Write - -Run validation before writing. Save to `docs/` or user-specified path. - -**Validation checklist:** See `references/validation.md` - ---- - -## Quick Arrow Reference - -**Straight down:** ```json -{ "points": [[0, 0], [0, 110]], "x": 590, "y": 290 } +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [...], + "appState": { + "viewBackgroundColor": "#ffffff", + "gridSize": 20 + }, + "files": {} +} ``` -**L-shape (left then down):** -```json -{ "points": [[0, 0], [-325, 0], [-325, 125]], "x": 525, "y": 420 } -``` +## Element Templates -**U-turn (callback):** -```json -{ "points": [[0, 0], [50, 0], [50, -125], [20, -125]], "x": 710, "y": 440 } -``` - -**Arrow width/height** = bounding box of points: -``` -points [[0,0], [-440,0], [-440,70]] → width=440, height=70 -``` - -**Multiple arrows from same edge** - stagger positions: -``` -5 arrows: 20%, 35%, 50%, 65%, 80% across edge width -``` +See `references/element-templates.md` for copy-paste JSON templates for each element type (text, line, dot, rectangle, arrow). Pull colors from `references/color-palette.md` based on each element's semantic purpose. --- -## Default Color Palette +## Render & Validate (MANDATORY) -| Component | Background | Stroke | -|-----------|------------|--------| -| Frontend | `#a5d8ff` | `#1971c2` | -| Backend/API | `#d0bfff` | `#7048e8` | -| Database | `#b2f2bb` | `#2f9e44` | -| Storage | `#ffec99` | `#f08c00` | -| AI/ML | `#e599f7` | `#9c36b5` | -| External APIs | `#ffc9c9` | `#e03131` | -| Orchestration | `#ffa8a8` | `#c92a2a` | -| Message Queue | `#fff3bf` | `#fab005` | -| Cache | `#ffe8cc` | `#fd7e14` | -| Users | `#e7f5ff` | `#1971c2` | +You cannot judge a diagram from JSON alone. After generating or editing the Excalidraw JSON, you MUST render it to PNG, view the image, and fix what you see — in a loop until it's right. This is a core part of the workflow, not a final check. -**Cloud-specific palettes:** See `references/colors.md` +### How to Render + +Run the render script from the skill's `references/` directory: + +```bash +python3 /render_excalidraw.py +``` + +This outputs a PNG next to the `.excalidraw` file. Then use the **Read tool** on the PNG to actually view it. + +### The Loop + +After generating the initial JSON, run this cycle: + +**1. Render & View** — Run the render script, then Read the PNG. + +**2. Audit against your original vision** — Before looking for bugs, compare the rendered result to what you designed in Steps 1-4. Ask: +- Does the visual structure match the conceptual structure you planned? +- Does each section use the pattern you intended (fan-out, convergence, timeline, etc.)? +- Does the eye flow through the diagram in the order you designed? +- Is the visual hierarchy correct — hero elements dominant, supporting elements smaller? +- For technical diagrams: are the evidence artifacts (code snippets, data examples) readable and properly placed? + +**3. Check for visual defects:** +- Text clipped by or overflowing its container +- Text or shapes overlapping other elements +- Arrows crossing through elements instead of routing around them +- Arrows landing on the wrong element or pointing into empty space +- Labels floating ambiguously (not clearly anchored to what they describe) +- Uneven spacing between elements that should be evenly spaced +- Sections with too much whitespace next to sections that are too cramped +- Text too small to read at the rendered size +- Overall composition feels lopsided or unbalanced + +**4. Fix** — Edit the JSON to address everything you found. Common fixes: +- Widen containers when text is clipped +- Adjust `x`/`y` coordinates to fix spacing and alignment +- Add intermediate waypoints to arrow `points` arrays to route around elements +- Reposition labels closer to the element they describe +- Resize elements to rebalance visual weight across sections + +**5. Re-render & re-view** — Run the render script again and Read the new PNG. + +**6. Repeat** — Keep cycling until the diagram passes both the vision check (Step 2) and the defect check (Step 3). Typically takes 2-4 iterations. Don't stop after one pass just because there are no critical bugs — if the composition could be better, improve it. + +### When to Stop + +The loop is done when: +- The rendered diagram matches the conceptual design from your planning steps +- No text is clipped, overlapping, or unreadable +- Arrows route cleanly and connect to the right elements +- Spacing is consistent and the composition is balanced +- You'd be comfortable showing it to someone without caveats --- -## Quick Validation Checklist +## Quality Checklist -Before writing file: -- [ ] Every shape with label has boundElements + text element -- [ ] Text elements have containerId matching shape -- [ ] Multi-point arrows have `elbowed: true`, `roundness: null` -- [ ] Arrow x,y = source shape edge point -- [ ] Arrow final point offset reaches target edge -- [ ] No diamond shapes -- [ ] No duplicate IDs +### Depth & Evidence (Check First for Technical Diagrams) +1. **Research done**: Did you look up actual specs, formats, event names? +2. **Evidence artifacts**: Are there code snippets, JSON examples, or real data? +3. **Multi-zoom**: Does it have summary flow + section boundaries + detail? +4. **Concrete over abstract**: Real content shown, not just labeled boxes? +5. **Educational value**: Could someone learn something concrete from this? -**Full validation algorithm:** See `references/validation.md` +### Conceptual +6. **Isomorphism**: Does each visual structure mirror its concept's behavior? +7. **Argument**: Does the diagram SHOW something text alone couldn't? +8. **Variety**: Does each major concept use a different visual pattern? +9. **No uniform containers**: Avoided card grids and equal boxes? ---- +### Container Discipline +10. **Minimal containers**: Could any boxed element work as free-floating text instead? +11. **Lines as structure**: Are tree/timeline patterns using lines + text rather than boxes? +12. **Typography hierarchy**: Are font size and color creating visual hierarchy (reducing need for boxes)? -## Common Issues +### Structural +13. **Connections**: Every relationship has an arrow or line +14. **Flow**: Clear visual path for the eye to follow +15. **Hierarchy**: Important elements are larger/more isolated -| Issue | Fix | -|-------|-----| -| Labels don't appear | Use TWO elements (shape + text), not `label` property | -| Arrows curved | Add `elbowed: true`, `roundness: null`, `roughness: 0` | -| Arrows floating | Calculate x,y from shape edge, not center | -| Arrows overlapping | Stagger start positions across edge | +### Technical +16. **Text clean**: `text` contains only readable words +17. **Font**: `fontFamily: 3` +18. **Roughness**: `roughness: 0` for clean/modern (unless hand-drawn style requested) +19. **Opacity**: `opacity: 100` for all elements (no transparency) +20. **Container ratio**: <30% of text elements should be inside containers -**Detailed bug fixes:** See `references/validation.md` - ---- - -## Reference Files - -| File | Contents | -|------|----------| -| `references/json-format.md` | Element types, required properties, text bindings | -| `references/arrows.md` | Routing algorithm, patterns, bindings, staggering | -| `references/colors.md` | Default, AWS, Azure, GCP, K8s palettes | -| `references/examples.md` | Complete JSON examples, layout patterns | -| `references/validation.md` | Checklists, validation algorithm, bug fixes | - ---- - -## Output - -- **Location:** `docs/architecture/` or user-specified -- **Filename:** Descriptive, e.g., `system-architecture.excalidraw` -- **Testing:** Open in https://excalidraw.com or VS Code extension +### Visual Validation (Render Required) +21. **Rendered to PNG**: Diagram has been rendered and visually inspected +22. **No text overflow**: All text fits within its container +23. **No overlapping elements**: Shapes and text don't overlap unintentionally +24. **Even spacing**: Similar elements have consistent spacing +25. **Arrows land correctly**: Arrows connect to intended elements without crossing others +26. **Readable at export size**: Text is legible in the rendered PNG +27. **Balanced composition**: No large empty voids or overcrowded regions diff --git a/skills/excalidraw/references/arrows.md b/skills/excalidraw/references/arrows.md deleted file mode 100644 index 0253a06..0000000 --- a/skills/excalidraw/references/arrows.md +++ /dev/null @@ -1,288 +0,0 @@ -# Arrow Routing Reference - -Complete guide for creating elbow arrows with proper connections. - ---- - -## Critical: Elbow Arrow Properties - -Three required properties for 90-degree corners: - -```json -{ - "type": "arrow", - "roughness": 0, // Clean lines - "roundness": null, // Sharp corners (not curved) - "elbowed": true // Enables elbow mode -} -``` - -**Without these, arrows will be curved, not 90-degree elbows.** - ---- - -## Edge Calculation Formulas - -| Shape Type | Edge | Formula | -|------------|------|---------| -| Rectangle | Top | `(x + width/2, y)` | -| Rectangle | Bottom | `(x + width/2, y + height)` | -| Rectangle | Left | `(x, y + height/2)` | -| Rectangle | Right | `(x + width, y + height/2)` | -| Ellipse | Top | `(x + width/2, y)` | -| Ellipse | Bottom | `(x + width/2, y + height)` | - ---- - -## Universal Arrow Routing Algorithm - -``` -FUNCTION createArrow(source, target, sourceEdge, targetEdge): - // Step 1: Get source edge point - sourcePoint = getEdgePoint(source, sourceEdge) - - // Step 2: Get target edge point - targetPoint = getEdgePoint(target, targetEdge) - - // Step 3: Calculate offsets - dx = targetPoint.x - sourcePoint.x - dy = targetPoint.y - sourcePoint.y - - // Step 4: Determine routing pattern - IF sourceEdge == "bottom" AND targetEdge == "top": - IF abs(dx) < 10: // Nearly aligned - points = [[0, 0], [0, dy]] - ELSE: // Need L-shape - points = [[0, 0], [dx, 0], [dx, dy]] - - ELSE IF sourceEdge == "right" AND targetEdge == "left": - IF abs(dy) < 10: - points = [[0, 0], [dx, 0]] - ELSE: - points = [[0, 0], [0, dy], [dx, dy]] - - ELSE IF sourceEdge == targetEdge: // U-turn - clearance = 50 - IF sourceEdge == "right": - points = [[0, 0], [clearance, 0], [clearance, dy], [dx, dy]] - ELSE IF sourceEdge == "bottom": - points = [[0, 0], [0, clearance], [dx, clearance], [dx, dy]] - - // Step 5: Calculate bounding box - width = max(abs(p[0]) for p in points) - height = max(abs(p[1]) for p in points) - - RETURN {x: sourcePoint.x, y: sourcePoint.y, points, width, height} - -FUNCTION getEdgePoint(shape, edge): - SWITCH edge: - "top": RETURN (shape.x + shape.width/2, shape.y) - "bottom": RETURN (shape.x + shape.width/2, shape.y + shape.height) - "left": RETURN (shape.x, shape.y + shape.height/2) - "right": RETURN (shape.x + shape.width, shape.y + shape.height/2) -``` - ---- - -## Arrow Patterns Reference - -| Pattern | Points | Use Case | -|---------|--------|----------| -| Down | `[[0,0], [0,h]]` | Vertical connection | -| Right | `[[0,0], [w,0]]` | Horizontal connection | -| L-left-down | `[[0,0], [-w,0], [-w,h]]` | Go left, then down | -| L-right-down | `[[0,0], [w,0], [w,h]]` | Go right, then down | -| L-down-left | `[[0,0], [0,h], [-w,h]]` | Go down, then left | -| L-down-right | `[[0,0], [0,h], [w,h]]` | Go down, then right | -| S-shape | `[[0,0], [0,h1], [w,h1], [w,h2]]` | Navigate around obstacles | -| U-turn | `[[0,0], [w,0], [w,-h], [0,-h]]` | Callback/return arrows | - ---- - -## Worked Examples - -### Vertical Connection (Bottom to Top) - -``` -Source: x=500, y=200, width=180, height=90 -Target: x=500, y=400, width=180, height=90 - -source_bottom = (500 + 180/2, 200 + 90) = (590, 290) -target_top = (500 + 180/2, 400) = (590, 400) - -Arrow x = 590, y = 290 -Distance = 400 - 290 = 110 -Points = [[0, 0], [0, 110]] -``` - -### Fan-out (One to Many) - -``` -Orchestrator: x=570, y=400, width=140, height=80 -Target: x=120, y=550, width=160, height=80 - -orchestrator_bottom = (570 + 140/2, 400 + 80) = (640, 480) -target_top = (120 + 160/2, 550) = (200, 550) - -Arrow x = 640, y = 480 -Horizontal offset = 200 - 640 = -440 -Vertical offset = 550 - 480 = 70 - -Points = [[0, 0], [-440, 0], [-440, 70]] // Left first, then down -``` - -### U-turn (Callback) - -``` -Source: x=570, y=400, width=140, height=80 -Target: x=550, y=270, width=180, height=90 -Connection: Right of source -> Right of target - -source_right = (570 + 140, 400 + 80/2) = (710, 440) -target_right = (550 + 180, 270 + 90/2) = (730, 315) - -Arrow x = 710, y = 440 -Vertical distance = 315 - 440 = -125 -Final x offset = 730 - 710 = 20 - -Points = [[0, 0], [50, 0], [50, -125], [20, -125]] -// Right 50px (clearance), up 125px, left 30px -``` - ---- - -## Staggering Multiple Arrows - -When N arrows leave from same edge, spread evenly: - -``` -FUNCTION getStaggeredPositions(shape, edge, numArrows): - positions = [] - FOR i FROM 0 TO numArrows-1: - percentage = 0.2 + (0.6 * i / (numArrows - 1)) - - IF edge == "bottom" OR edge == "top": - x = shape.x + shape.width * percentage - y = (edge == "bottom") ? shape.y + shape.height : shape.y - ELSE: - x = (edge == "right") ? shape.x + shape.width : shape.x - y = shape.y + shape.height * percentage - - positions.append({x, y}) - RETURN positions - -// Examples: -// 2 arrows: 20%, 80% -// 3 arrows: 20%, 50%, 80% -// 5 arrows: 20%, 35%, 50%, 65%, 80% -``` - ---- - -## Arrow Bindings - -For better visual attachment, use `startBinding` and `endBinding`: - -```json -{ - "id": "arrow-workflow-convert", - "type": "arrow", - "x": 525, - "y": 420, - "width": 325, - "height": 125, - "points": [[0, 0], [-325, 0], [-325, 125]], - "roughness": 0, - "roundness": null, - "elbowed": true, - "startBinding": { - "elementId": "cloud-workflows", - "focus": 0, - "gap": 1, - "fixedPoint": [0.5, 1] - }, - "endBinding": { - "elementId": "convert-pdf-service", - "focus": 0, - "gap": 1, - "fixedPoint": [0.5, 0] - }, - "startArrowhead": null, - "endArrowhead": "arrow" -} -``` - -### fixedPoint Values - -- Top center: `[0.5, 0]` -- Bottom center: `[0.5, 1]` -- Left center: `[0, 0.5]` -- Right center: `[1, 0.5]` - -### Update Shape boundElements - -```json -{ - "id": "cloud-workflows", - "boundElements": [ - { "type": "text", "id": "cloud-workflows-text" }, - { "type": "arrow", "id": "arrow-workflow-convert" } - ] -} -``` - ---- - -## Bidirectional Arrows - -For two-way data flows: - -```json -{ - "type": "arrow", - "startArrowhead": "arrow", - "endArrowhead": "arrow" -} -``` - -Arrowhead options: `null`, `"arrow"`, `"bar"`, `"dot"`, `"triangle"` - ---- - -## Arrow Labels - -Position standalone text near arrow midpoint: - -```json -{ - "id": "arrow-api-db-label", - "type": "text", - "x": 305, // Arrow x + offset - "y": 245, // Arrow midpoint - "text": "SQL", - "fontSize": 12, - "containerId": null, - "backgroundColor": "#ffffff" -} -``` - -**Positioning formula:** -- Vertical: `label.y = arrow.y + (total_height / 2)` -- Horizontal: `label.x = arrow.x + (total_width / 2)` -- L-shaped: Position at corner or longest segment midpoint - ---- - -## Width/Height Calculation - -Arrow `width` and `height` = bounding box of path: - -``` -points = [[0, 0], [-440, 0], [-440, 70]] -width = abs(-440) = 440 -height = abs(70) = 70 - -points = [[0, 0], [50, 0], [50, -125], [20, -125]] -width = max(abs(50), abs(20)) = 50 -height = abs(-125) = 125 -``` diff --git a/skills/excalidraw/references/color-palette.md b/skills/excalidraw/references/color-palette.md new file mode 100644 index 0000000..711ea27 --- /dev/null +++ b/skills/excalidraw/references/color-palette.md @@ -0,0 +1,67 @@ +# Color Palette & Brand Style + +**This is the single source of truth for all colors and brand-specific styles.** To customize diagrams for your own brand, edit this file — everything else in the skill is universal. + +--- + +## Shape Colors (Semantic) + +Colors encode meaning, not decoration. Each semantic purpose has a fill/stroke pair. + +| Semantic Purpose | Fill | Stroke | +|------------------|------|--------| +| Primary/Neutral | `#3b82f6` | `#1e3a5f` | +| Secondary | `#60a5fa` | `#1e3a5f` | +| Tertiary | `#93c5fd` | `#1e3a5f` | +| Start/Trigger | `#fed7aa` | `#c2410c` | +| End/Success | `#a7f3d0` | `#047857` | +| Warning/Reset | `#fee2e2` | `#dc2626` | +| Decision | `#fef3c7` | `#b45309` | +| AI/LLM | `#ddd6fe` | `#6d28d9` | +| Inactive/Disabled | `#dbeafe` | `#1e40af` (use dashed stroke) | +| Error | `#fecaca` | `#b91c1c` | + +**Rule**: Always pair a darker stroke with a lighter fill for contrast. + +--- + +## Text Colors (Hierarchy) + +Use color on free-floating text to create visual hierarchy without containers. + +| Level | Color | Use For | +|-------|-------|---------| +| Title | `#1e40af` | Section headings, major labels | +| Subtitle | `#3b82f6` | Subheadings, secondary labels | +| Body/Detail | `#64748b` | Descriptions, annotations, metadata | +| On light fills | `#374151` | Text inside light-colored shapes | +| On dark fills | `#ffffff` | Text inside dark-colored shapes | + +--- + +## Evidence Artifact Colors + +Used for code snippets, data examples, and other concrete evidence inside technical diagrams. + +| Artifact | Background | Text Color | +|----------|-----------|------------| +| Code snippet | `#1e293b` | Syntax-colored (language-appropriate) | +| JSON/data example | `#1e293b` | `#22c55e` (green) | + +--- + +## Default Stroke & Line Colors + +| Element | Color | +|---------|-------| +| Arrows | Use the stroke color of the source element's semantic purpose | +| Structural lines (dividers, trees, timelines) | Primary stroke (`#1e3a5f`) or Slate (`#64748b`) | +| Marker dots (fill + stroke) | Primary fill (`#3b82f6`) | + +--- + +## Background + +| Property | Value | +|----------|-------| +| Canvas background | `#ffffff` | diff --git a/skills/excalidraw/references/colors.md b/skills/excalidraw/references/colors.md deleted file mode 100644 index c26d47a..0000000 --- a/skills/excalidraw/references/colors.md +++ /dev/null @@ -1,91 +0,0 @@ -# Color Palettes Reference - -Color schemes for different platforms and component types. - ---- - -## Default Palette (Platform-Agnostic) - -| Component Type | Background | Stroke | Example | -|----------------|------------|--------|---------| -| Frontend/UI | `#a5d8ff` | `#1971c2` | Next.js, React apps | -| Backend/API | `#d0bfff` | `#7048e8` | API servers, processors | -| Database | `#b2f2bb` | `#2f9e44` | PostgreSQL, MySQL, MongoDB | -| Storage | `#ffec99` | `#f08c00` | Object storage, file systems | -| AI/ML Services | `#e599f7` | `#9c36b5` | ML models, AI APIs | -| External APIs | `#ffc9c9` | `#e03131` | Third-party services | -| Orchestration | `#ffa8a8` | `#c92a2a` | Workflows, schedulers | -| Validation | `#ffd8a8` | `#e8590c` | Validators, checkers | -| Network/Security | `#dee2e6` | `#495057` | VPC, IAM, firewalls | -| Classification | `#99e9f2` | `#0c8599` | Routers, classifiers | -| Users/Actors | `#e7f5ff` | `#1971c2` | User ellipses | -| Message Queue | `#fff3bf` | `#fab005` | Kafka, RabbitMQ, SQS | -| Cache | `#ffe8cc` | `#fd7e14` | Redis, Memcached | -| Monitoring | `#d3f9d8` | `#40c057` | Prometheus, Grafana | - ---- - -## AWS Palette - -| Service Category | Background | Stroke | -|-----------------|------------|--------| -| Compute (EC2, Lambda, ECS) | `#ff9900` | `#cc7a00` | -| Storage (S3, EBS) | `#3f8624` | `#2d6119` | -| Database (RDS, DynamoDB) | `#3b48cc` | `#2d3899` | -| Networking (VPC, Route53) | `#8c4fff` | `#6b3dcc` | -| Security (IAM, KMS) | `#dd344c` | `#b12a3d` | -| Analytics (Kinesis, Athena) | `#8c4fff` | `#6b3dcc` | -| ML (SageMaker, Bedrock) | `#01a88d` | `#017d69` | - ---- - -## Azure Palette - -| Service Category | Background | Stroke | -|-----------------|------------|--------| -| Compute | `#0078d4` | `#005a9e` | -| Storage | `#50e6ff` | `#3cb5cc` | -| Database | `#0078d4` | `#005a9e` | -| Networking | `#773adc` | `#5a2ca8` | -| Security | `#ff8c00` | `#cc7000` | -| AI/ML | `#50e6ff` | `#3cb5cc` | - ---- - -## GCP Palette - -| Service Category | Background | Stroke | -|-----------------|------------|--------| -| Compute (GCE, Cloud Run) | `#4285f4` | `#3367d6` | -| Storage (GCS) | `#34a853` | `#2d8e47` | -| Database (Cloud SQL, Firestore) | `#ea4335` | `#c53929` | -| Networking | `#fbbc04` | `#d99e04` | -| AI/ML (Vertex AI) | `#9334e6` | `#7627b8` | - ---- - -## Kubernetes Palette - -| Component | Background | Stroke | -|-----------|------------|--------| -| Pod | `#326ce5` | `#2756b8` | -| Service | `#326ce5` | `#2756b8` | -| Deployment | `#326ce5` | `#2756b8` | -| ConfigMap/Secret | `#7f8c8d` | `#626d6e` | -| Ingress | `#00d4aa` | `#00a888` | -| Node | `#303030` | `#1a1a1a` | -| Namespace | `#f0f0f0` | `#c0c0c0` (dashed) | - ---- - -## Diagram Type Suggestions - -| Diagram Type | Recommended Layout | Key Elements | -|--------------|-------------------|--------------| -| Microservices | Vertical flow | Services, databases, queues, API gateway | -| Data Pipeline | Horizontal flow | Sources, transformers, sinks, storage | -| Event-Driven | Hub-and-spoke | Event bus center, producers/consumers | -| Kubernetes | Layered groups | Namespace boxes, pods inside deployments | -| CI/CD | Horizontal flow | Source -> Build -> Test -> Deploy -> Monitor | -| Network | Hierarchical | Internet -> LB -> VPC -> Subnets -> Instances | -| User Flow | Swimlanes | User actions, system responses, external calls | diff --git a/skills/excalidraw/references/element-templates.md b/skills/excalidraw/references/element-templates.md new file mode 100644 index 0000000..30dbf4a --- /dev/null +++ b/skills/excalidraw/references/element-templates.md @@ -0,0 +1,182 @@ +# Element Templates + +Copy-paste JSON templates for each Excalidraw element type. The `strokeColor` and `backgroundColor` values are placeholders — always pull actual colors from `color-palette.md` based on the element's semantic purpose. + +## Free-Floating Text (no container) +```json +{ + "type": "text", + "id": "label1", + "x": 100, "y": 100, + "width": 200, "height": 25, + "text": "Section Title", + "originalText": "Section Title", + "fontSize": 20, + "fontFamily": 3, + "textAlign": "left", + "verticalAlign": "top", + "strokeColor": "", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "seed": 11111, + "version": 1, + "versionNonce": 22222, + "isDeleted": false, + "groupIds": [], + "boundElements": null, + "link": null, + "locked": false, + "containerId": null, + "lineHeight": 1.25 +} +``` + +## Line (structural, not arrow) +```json +{ + "type": "line", + "id": "line1", + "x": 100, "y": 100, + "width": 0, "height": 200, + "strokeColor": "<structural line color from palette>", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "seed": 44444, + "version": 1, + "versionNonce": 55555, + "isDeleted": false, + "groupIds": [], + "boundElements": null, + "link": null, + "locked": false, + "points": [[0, 0], [0, 200]] +} +``` + +## Small Marker Dot +```json +{ + "type": "ellipse", + "id": "dot1", + "x": 94, "y": 94, + "width": 12, "height": 12, + "strokeColor": "<marker dot color from palette>", + "backgroundColor": "<marker dot color from palette>", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "seed": 66666, + "version": 1, + "versionNonce": 77777, + "isDeleted": false, + "groupIds": [], + "boundElements": null, + "link": null, + "locked": false +} +``` + +## Rectangle +```json +{ + "type": "rectangle", + "id": "elem1", + "x": 100, "y": 100, "width": 180, "height": 90, + "strokeColor": "<stroke from palette based on semantic purpose>", + "backgroundColor": "<fill from palette based on semantic purpose>", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "seed": 12345, + "version": 1, + "versionNonce": 67890, + "isDeleted": false, + "groupIds": [], + "boundElements": [{"id": "text1", "type": "text"}], + "link": null, + "locked": false, + "roundness": {"type": 3} +} +``` + +## Text (centered in shape) +```json +{ + "type": "text", + "id": "text1", + "x": 130, "y": 132, + "width": 120, "height": 25, + "text": "Process", + "originalText": "Process", + "fontSize": 16, + "fontFamily": 3, + "textAlign": "center", + "verticalAlign": "middle", + "strokeColor": "<text color — match parent shape's stroke or use 'on light/dark fills' from palette>", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "seed": 11111, + "version": 1, + "versionNonce": 22222, + "isDeleted": false, + "groupIds": [], + "boundElements": null, + "link": null, + "locked": false, + "containerId": "elem1", + "lineHeight": 1.25 +} +``` + +## Arrow +```json +{ + "type": "arrow", + "id": "arrow1", + "x": 282, "y": 145, "width": 118, "height": 0, + "strokeColor": "<arrow color — typically matches source element's stroke from palette>", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "seed": 33333, + "version": 1, + "versionNonce": 44444, + "isDeleted": false, + "groupIds": [], + "boundElements": null, + "link": null, + "locked": false, + "points": [[0, 0], [118, 0]], + "startBinding": {"elementId": "elem1", "focus": 0, "gap": 2}, + "endBinding": {"elementId": "elem2", "focus": 0, "gap": 2}, + "startArrowhead": null, + "endArrowhead": "arrow" +} +``` + +For curves: use 3+ points in `points` array. diff --git a/skills/excalidraw/references/examples.md b/skills/excalidraw/references/examples.md deleted file mode 100644 index 05cdd9a..0000000 --- a/skills/excalidraw/references/examples.md +++ /dev/null @@ -1,381 +0,0 @@ -# Complete Examples Reference - -Full JSON examples showing proper element structure. - ---- - -## 3-Tier Architecture Example - -This is a REFERENCE showing JSON structure. Replace IDs, labels, positions, and colors based on discovered components. - -```json -{ - "type": "excalidraw", - "version": 2, - "source": "claude-code-excalidraw-skill", - "elements": [ - { - "id": "user", - "type": "ellipse", - "x": 150, - "y": 50, - "width": 100, - "height": 60, - "angle": 0, - "strokeColor": "#1971c2", - "backgroundColor": "#e7f5ff", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "roundness": { "type": 2 }, - "seed": 1, - "version": 1, - "versionNonce": 1, - "isDeleted": false, - "boundElements": [{ "type": "text", "id": "user-text" }], - "updated": 1, - "link": null, - "locked": false - }, - { - "id": "user-text", - "type": "text", - "x": 175, - "y": 67, - "width": 50, - "height": 25, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 0, - "opacity": 100, - "groupIds": [], - "frameId": null, - "roundness": null, - "seed": 2, - "version": 1, - "versionNonce": 2, - "isDeleted": false, - "boundElements": null, - "updated": 1, - "link": null, - "locked": false, - "text": "User", - "fontSize": 16, - "fontFamily": 1, - "textAlign": "center", - "verticalAlign": "middle", - "baseline": 14, - "containerId": "user", - "originalText": "User", - "lineHeight": 1.25 - }, - { - "id": "frontend", - "type": "rectangle", - "x": 100, - "y": 180, - "width": 200, - "height": 80, - "angle": 0, - "strokeColor": "#1971c2", - "backgroundColor": "#a5d8ff", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "roundness": { "type": 3 }, - "seed": 3, - "version": 1, - "versionNonce": 3, - "isDeleted": false, - "boundElements": [{ "type": "text", "id": "frontend-text" }], - "updated": 1, - "link": null, - "locked": false - }, - { - "id": "frontend-text", - "type": "text", - "x": 105, - "y": 195, - "width": 190, - "height": 50, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 0, - "opacity": 100, - "groupIds": [], - "frameId": null, - "roundness": null, - "seed": 4, - "version": 1, - "versionNonce": 4, - "isDeleted": false, - "boundElements": null, - "updated": 1, - "link": null, - "locked": false, - "text": "Frontend\nNext.js", - "fontSize": 16, - "fontFamily": 1, - "textAlign": "center", - "verticalAlign": "middle", - "baseline": 14, - "containerId": "frontend", - "originalText": "Frontend\nNext.js", - "lineHeight": 1.25 - }, - { - "id": "database", - "type": "rectangle", - "x": 100, - "y": 330, - "width": 200, - "height": 80, - "angle": 0, - "strokeColor": "#2f9e44", - "backgroundColor": "#b2f2bb", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "roundness": { "type": 3 }, - "seed": 5, - "version": 1, - "versionNonce": 5, - "isDeleted": false, - "boundElements": [{ "type": "text", "id": "database-text" }], - "updated": 1, - "link": null, - "locked": false - }, - { - "id": "database-text", - "type": "text", - "x": 105, - "y": 345, - "width": 190, - "height": 50, - "angle": 0, - "strokeColor": "#1e1e1e", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 1, - "strokeStyle": "solid", - "roughness": 0, - "opacity": 100, - "groupIds": [], - "frameId": null, - "roundness": null, - "seed": 6, - "version": 1, - "versionNonce": 6, - "isDeleted": false, - "boundElements": null, - "updated": 1, - "link": null, - "locked": false, - "text": "Database\nPostgreSQL", - "fontSize": 16, - "fontFamily": 1, - "textAlign": "center", - "verticalAlign": "middle", - "baseline": 14, - "containerId": "database", - "originalText": "Database\nPostgreSQL", - "lineHeight": 1.25 - }, - { - "id": "arrow-user-frontend", - "type": "arrow", - "x": 200, - "y": 115, - "width": 0, - "height": 60, - "angle": 0, - "strokeColor": "#1971c2", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 0, - "opacity": 100, - "groupIds": [], - "frameId": null, - "roundness": null, - "seed": 7, - "version": 1, - "versionNonce": 7, - "isDeleted": false, - "boundElements": null, - "updated": 1, - "link": null, - "locked": false, - "points": [[0, 0], [0, 60]], - "lastCommittedPoint": null, - "startBinding": null, - "endBinding": null, - "startArrowhead": null, - "endArrowhead": "arrow", - "elbowed": true - }, - { - "id": "arrow-frontend-database", - "type": "arrow", - "x": 200, - "y": 265, - "width": 0, - "height": 60, - "angle": 0, - "strokeColor": "#2f9e44", - "backgroundColor": "transparent", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 0, - "opacity": 100, - "groupIds": [], - "frameId": null, - "roundness": null, - "seed": 8, - "version": 1, - "versionNonce": 8, - "isDeleted": false, - "boundElements": null, - "updated": 1, - "link": null, - "locked": false, - "points": [[0, 0], [0, 60]], - "lastCommittedPoint": null, - "startBinding": null, - "endBinding": null, - "startArrowhead": null, - "endArrowhead": "arrow", - "elbowed": true - } - ], - "appState": { - "gridSize": 20, - "viewBackgroundColor": "#ffffff" - }, - "files": {} -} -``` - ---- - -## Layout Patterns - -### Vertical Flow (Most Common) - -``` -Grid positioning: -- Column width: 200-250px -- Row height: 130-150px -- Element size: 160-200px x 80-90px -- Spacing: 40-50px between elements - -Row positions (y): - Row 0: 20 (title) - Row 1: 100 (users/entry points) - Row 2: 230 (frontend/gateway) - Row 3: 380 (orchestration) - Row 4: 530 (services) - Row 5: 680 (data layer) - Row 6: 830 (external services) - -Column positions (x): - Col 0: 100 - Col 1: 300 - Col 2: 500 - Col 3: 700 - Col 4: 900 -``` - -### Horizontal Flow (Pipelines) - -``` -Stage positions (x): - Stage 0: 100 (input/source) - Stage 1: 350 (transform 1) - Stage 2: 600 (transform 2) - Stage 3: 850 (transform 3) - Stage 4: 1100 (output/sink) - -All stages at same y: 200 -Arrows: "right" -> "left" connections -``` - -### Hub-and-Spoke - -``` -Center hub: x=500, y=350 -8 positions at 45° increments: - N: (500, 150) - NE: (640, 210) - E: (700, 350) - SE: (640, 490) - S: (500, 550) - SW: (360, 490) - W: (300, 350) - NW: (360, 210) -``` - ---- - -## Complex Architecture Layout - -``` -Row 0: Title/Header (y: 20) -Row 1: Users/Clients (y: 80) -Row 2: Frontend/Gateway (y: 200) -Row 3: Orchestration (y: 350) -Row 4: Processing Services (y: 550) -Row 5: Data Layer (y: 680) -Row 6: External Services (y: 830) - -Columns (x): - Col 0: 120 - Col 1: 320 - Col 2: 520 - Col 3: 720 - Col 4: 920 -``` - ---- - -## Diagram Complexity Guidelines - -| Complexity | Max Elements | Max Arrows | Approach | -|------------|-------------|------------|----------| -| Simple | 5-10 | 5-10 | Single file, no groups | -| Medium | 10-25 | 15-30 | Use grouping rectangles | -| Complex | 25-50 | 30-60 | Split into multiple diagrams | -| Very Complex | 50+ | 60+ | Multiple focused diagrams | - -**When to split:** -- More than 50 elements -- Create: `architecture-overview.excalidraw`, `architecture-data-layer.excalidraw` - -**When to use groups:** -- 3+ related services -- Same deployment unit -- Logical boundaries (VPC, Security Zone) diff --git a/skills/excalidraw/references/json-format.md b/skills/excalidraw/references/json-format.md deleted file mode 100644 index a471739..0000000 --- a/skills/excalidraw/references/json-format.md +++ /dev/null @@ -1,210 +0,0 @@ -# Excalidraw JSON Format Reference - -Complete reference for Excalidraw JSON structure and element types. - ---- - -## File Structure - -```json -{ - "type": "excalidraw", - "version": 2, - "source": "claude-code-excalidraw-skill", - "elements": [], - "appState": { - "gridSize": 20, - "viewBackgroundColor": "#ffffff" - }, - "files": {} -} -``` - ---- - -## Element Types - -| Type | Use For | Arrow Reliability | -|------|---------|-------------------| -| `rectangle` | Services, components, databases, containers, orchestrators, decision points | Excellent | -| `ellipse` | Users, external systems, start/end points | Good | -| `text` | Labels inside shapes, titles, annotations | N/A | -| `arrow` | Data flow, connections, dependencies | N/A | -| `line` | Grouping boundaries, separators | N/A | - -### BANNED: Diamond Shapes - -**NEVER use `type: "diamond"` in generated diagrams.** - -Diamond arrow connections are fundamentally broken in raw Excalidraw JSON: -- Excalidraw applies `roundness` to diamond vertices during rendering -- Visual edges appear offset from mathematical edge points -- No offset formula reliably compensates -- Arrows appear disconnected/floating - -**Use styled rectangles instead** for visual distinction: - -| Semantic Meaning | Rectangle Style | -|------------------|-----------------| -| Orchestrator/Hub | Coral (`#ffa8a8`/`#c92a2a`) + strokeWidth: 3 | -| Decision Point | Orange (`#ffd8a8`/`#e8590c`) + dashed stroke | -| Central Router | Larger size + bold color | - ---- - -## Required Element Properties - -Every element MUST have these properties: - -```json -{ - "id": "unique-id-string", - "type": "rectangle", - "x": 100, - "y": 100, - "width": 200, - "height": 80, - "angle": 0, - "strokeColor": "#1971c2", - "backgroundColor": "#a5d8ff", - "fillStyle": "solid", - "strokeWidth": 2, - "strokeStyle": "solid", - "roughness": 1, - "opacity": 100, - "groupIds": [], - "frameId": null, - "roundness": { "type": 3 }, - "seed": 1, - "version": 1, - "versionNonce": 1, - "isDeleted": false, - "boundElements": null, - "updated": 1, - "link": null, - "locked": false -} -``` - ---- - -## Text Inside Shapes (Labels) - -**Every labeled shape requires TWO elements:** - -### Shape with boundElements - -```json -{ - "id": "{component-id}", - "type": "rectangle", - "x": 500, - "y": 200, - "width": 200, - "height": 90, - "strokeColor": "#1971c2", - "backgroundColor": "#a5d8ff", - "boundElements": [{ "type": "text", "id": "{component-id}-text" }], - // ... other required properties -} -``` - -### Text with containerId - -```json -{ - "id": "{component-id}-text", - "type": "text", - "x": 505, // shape.x + 5 - "y": 220, // shape.y + (shape.height - text.height) / 2 - "width": 190, // shape.width - 10 - "height": 50, - "text": "{Component Name}\n{Subtitle}", - "fontSize": 16, - "fontFamily": 1, - "textAlign": "center", - "verticalAlign": "middle", - "containerId": "{component-id}", - "originalText": "{Component Name}\n{Subtitle}", - "lineHeight": 1.25, - // ... other required properties -} -``` - -### DO NOT Use the `label` Property - -The `label` property is for the JavaScript API, NOT raw JSON files: - -```json -// WRONG - will show empty boxes -{ "type": "rectangle", "label": { "text": "My Label" } } - -// CORRECT - requires TWO elements -// 1. Shape with boundElements reference -// 2. Separate text element with containerId -``` - -### Text Positioning - -- Text `x` = shape `x` + 5 -- Text `y` = shape `y` + (shape.height - text.height) / 2 -- Text `width` = shape `width` - 10 -- Use `\n` for multi-line labels -- Always use `textAlign: "center"` and `verticalAlign: "middle"` - -### ID Naming Convention - -Always use pattern: `{shape-id}-text` for text element IDs. - ---- - -## Dynamic ID Generation - -IDs and labels are generated from codebase analysis: - -| Discovered Component | Generated ID | Generated Label | -|---------------------|--------------|-----------------| -| Express API server | `express-api` | `"API Server\nExpress.js"` | -| PostgreSQL database | `postgres-db` | `"PostgreSQL\nDatabase"` | -| Redis cache | `redis-cache` | `"Redis\nCache Layer"` | -| S3 bucket for uploads | `s3-uploads` | `"S3 Bucket\nuploads/"` | -| Lambda function | `lambda-processor` | `"Lambda\nProcessor"` | -| React frontend | `react-frontend` | `"React App\nFrontend"` | - ---- - -## Grouping with Dashed Rectangles - -For logical groupings (namespaces, VPCs, pipelines): - -```json -{ - "id": "group-ai-pipeline", - "type": "rectangle", - "x": 100, - "y": 500, - "width": 1000, - "height": 280, - "strokeColor": "#9c36b5", - "backgroundColor": "transparent", - "strokeStyle": "dashed", - "roughness": 0, - "roundness": null, - "boundElements": null -} -``` - -Group labels are standalone text (no containerId) at top-left: - -```json -{ - "id": "group-ai-pipeline-label", - "type": "text", - "x": 120, - "y": 510, - "text": "AI Processing Pipeline (Cloud Run)", - "textAlign": "left", - "verticalAlign": "top", - "containerId": null -} -``` diff --git a/skills/excalidraw/references/json-schema.md b/skills/excalidraw/references/json-schema.md new file mode 100644 index 0000000..60383bb --- /dev/null +++ b/skills/excalidraw/references/json-schema.md @@ -0,0 +1,71 @@ +# Excalidraw JSON Schema + +## Element Types + +| Type | Use For | +|------|---------| +| `rectangle` | Processes, actions, components | +| `ellipse` | Entry/exit points, external systems | +| `diamond` | Decisions, conditionals | +| `arrow` | Connections between shapes | +| `text` | Labels inside shapes | +| `line` | Non-arrow connections | +| `frame` | Grouping containers | + +## Common Properties + +All elements share these: + +| Property | Type | Description | +|----------|------|-------------| +| `id` | string | Unique identifier | +| `type` | string | Element type | +| `x`, `y` | number | Position in pixels | +| `width`, `height` | number | Size in pixels | +| `strokeColor` | string | Border color (hex) | +| `backgroundColor` | string | Fill color (hex or "transparent") | +| `fillStyle` | string | "solid", "hachure", "cross-hatch" | +| `strokeWidth` | number | 1, 2, or 4 | +| `strokeStyle` | string | "solid", "dashed", "dotted" | +| `roughness` | number | 0 (smooth), 1 (default), 2 (rough) | +| `opacity` | number | 0-100 | +| `seed` | number | Random seed for roughness | + +## Text-Specific Properties + +| Property | Description | +|----------|-------------| +| `text` | The display text | +| `originalText` | Same as text | +| `fontSize` | Size in pixels (16-20 recommended) | +| `fontFamily` | 3 for monospace (use this) | +| `textAlign` | "left", "center", "right" | +| `verticalAlign` | "top", "middle", "bottom" | +| `containerId` | ID of parent shape | + +## Arrow-Specific Properties + +| Property | Description | +|----------|-------------| +| `points` | Array of [x, y] coordinates | +| `startBinding` | Connection to start shape | +| `endBinding` | Connection to end shape | +| `startArrowhead` | null, "arrow", "bar", "dot", "triangle" | +| `endArrowhead` | null, "arrow", "bar", "dot", "triangle" | + +## Binding Format + +```json +{ + "elementId": "shapeId", + "focus": 0, + "gap": 2 +} +``` + +## Rectangle Roundness + +Add for rounded corners: +```json +"roundness": { "type": 3 } +``` diff --git a/skills/excalidraw/references/render_excalidraw.py b/skills/excalidraw/references/render_excalidraw.py new file mode 100644 index 0000000..3ae6111 --- /dev/null +++ b/skills/excalidraw/references/render_excalidraw.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python3 +"""Render Excalidraw JSON to PNG using Playwright + headless Chromium. + +Usage: + python3 render_excalidraw.py <path-to-file.excalidraw> [--output path.png] [--scale 2] [--width 1920] + +Dependencies (playwright, chromium) are provided by the Nix flake / direnv environment. +""" + +from __future__ import annotations + +import argparse +import json +import sys +from pathlib import Path + + +def validate_excalidraw(data: dict) -> list[str]: + """Validate Excalidraw JSON structure. Returns list of errors (empty = valid).""" + errors: list[str] = [] + + if data.get("type") != "excalidraw": + errors.append(f"Expected type 'excalidraw', got '{data.get('type')}'") + + if "elements" not in data: + errors.append("Missing 'elements' array") + elif not isinstance(data["elements"], list): + errors.append("'elements' must be an array") + elif len(data["elements"]) == 0: + errors.append("'elements' array is empty — nothing to render") + + return errors + + +def compute_bounding_box(elements: list[dict]) -> tuple[float, float, float, float]: + """Compute bounding box (min_x, min_y, max_x, max_y) across all elements.""" + min_x = float("inf") + min_y = float("inf") + max_x = float("-inf") + max_y = float("-inf") + + for el in elements: + if el.get("isDeleted"): + continue + x = el.get("x", 0) + y = el.get("y", 0) + w = el.get("width", 0) + h = el.get("height", 0) + + # For arrows/lines, points array defines the shape relative to x,y + if el.get("type") in ("arrow", "line") and "points" in el: + for px, py in el["points"]: + min_x = min(min_x, x + px) + min_y = min(min_y, y + py) + max_x = max(max_x, x + px) + max_y = max(max_y, y + py) + else: + min_x = min(min_x, x) + min_y = min(min_y, y) + max_x = max(max_x, x + abs(w)) + max_y = max(max_y, y + abs(h)) + + if min_x == float("inf"): + return (0, 0, 800, 600) + + return (min_x, min_y, max_x, max_y) + + +def render( + excalidraw_path: Path, + output_path: Path | None = None, + scale: int = 2, + max_width: int = 1920, +) -> Path: + """Render an .excalidraw file to PNG. Returns the output PNG path.""" + # Import playwright here so validation errors show before import errors + try: + from playwright.sync_api import sync_playwright + except ImportError: + print("ERROR: playwright not installed.", file=sys.stderr) + print("Ensure the Nix dev shell is active (direnv allow).", file=sys.stderr) + sys.exit(1) + + # Read and validate + raw = excalidraw_path.read_text(encoding="utf-8") + try: + data = json.loads(raw) + except json.JSONDecodeError as e: + print(f"ERROR: Invalid JSON in {excalidraw_path}: {e}", file=sys.stderr) + sys.exit(1) + + errors = validate_excalidraw(data) + if errors: + print(f"ERROR: Invalid Excalidraw file:", file=sys.stderr) + for err in errors: + print(f" - {err}", file=sys.stderr) + sys.exit(1) + + # Compute viewport size from element bounding box + elements = [e for e in data["elements"] if not e.get("isDeleted")] + min_x, min_y, max_x, max_y = compute_bounding_box(elements) + padding = 80 + diagram_w = max_x - min_x + padding * 2 + diagram_h = max_y - min_y + padding * 2 + + # Cap viewport width, let height be natural + vp_width = min(int(diagram_w), max_width) + vp_height = max(int(diagram_h), 600) + + # Output path + if output_path is None: + output_path = excalidraw_path.with_suffix(".png") + + # Template path (same directory as this script) + template_path = Path(__file__).parent / "render_template.html" + if not template_path.exists(): + print(f"ERROR: Template not found at {template_path}", file=sys.stderr) + sys.exit(1) + + template_url = template_path.as_uri() + + with sync_playwright() as p: + try: + browser = p.chromium.launch(headless=True) + except Exception as e: + if "Executable doesn't exist" in str(e) or "browserType.launch" in str(e): + print("ERROR: Chromium not installed for Playwright.", file=sys.stderr) + print("Ensure the Nix dev shell is active (direnv allow).", file=sys.stderr) + sys.exit(1) + raise + + page = browser.new_page( + viewport={"width": vp_width, "height": vp_height}, + device_scale_factor=scale, + ) + + # Load the template + page.goto(template_url) + + # Wait for the ES module to load (imports from esm.sh) + page.wait_for_function("window.__moduleReady === true", timeout=30000) + + # Inject the diagram data and render + json_str = json.dumps(data) + result = page.evaluate(f"window.renderDiagram({json_str})") + + if not result or not result.get("success"): + error_msg = ( + result.get("error", "Unknown render error") + if result + else "renderDiagram returned null" + ) + print(f"ERROR: Render failed: {error_msg}", file=sys.stderr) + browser.close() + sys.exit(1) + + # Wait for render completion signal + page.wait_for_function("window.__renderComplete === true", timeout=15000) + + # Screenshot the SVG element + svg_el = page.query_selector("#root svg") + if svg_el is None: + print("ERROR: No SVG element found after render.", file=sys.stderr) + browser.close() + sys.exit(1) + + svg_el.screenshot(path=str(output_path)) + browser.close() + + return output_path + + +def main() -> None: + """Entry point for rendering Excalidraw JSON files to PNG.""" + parser = argparse.ArgumentParser(description="Render Excalidraw JSON to PNG") + parser.add_argument("input", type=Path, help="Path to .excalidraw JSON file") + parser.add_argument( + "--output", + "-o", + type=Path, + default=None, + help="Output PNG path (default: same name with .png)", + ) + parser.add_argument( + "--scale", "-s", type=int, default=2, help="Device scale factor (default: 2)" + ) + parser.add_argument( + "--width", + "-w", + type=int, + default=1920, + help="Max viewport width (default: 1920)", + ) + args = parser.parse_args() + + if not args.input.exists(): + print(f"ERROR: File not found: {args.input}", file=sys.stderr) + sys.exit(1) + + png_path = render(args.input, args.output, args.scale, args.width) + print(str(png_path)) + + +if __name__ == "__main__": + main() diff --git a/skills/excalidraw/references/render_template.html b/skills/excalidraw/references/render_template.html new file mode 100644 index 0000000..78133b9 --- /dev/null +++ b/skills/excalidraw/references/render_template.html @@ -0,0 +1,57 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8" /> + <style> + * { margin: 0; padding: 0; box-sizing: border-box; } + body { background: #ffffff; overflow: hidden; } + #root { display: inline-block; } + #root svg { display: block; } + </style> +</head> +<body> + <div id="root"></div> + + <script type="module"> + import { exportToSvg } from "https://esm.sh/@excalidraw/excalidraw?bundle"; + + window.renderDiagram = async function(jsonData) { + try { + const data = typeof jsonData === "string" ? JSON.parse(jsonData) : jsonData; + const elements = data.elements || []; + const appState = data.appState || {}; + const files = data.files || {}; + + // Force white background in appState + appState.viewBackgroundColor = appState.viewBackgroundColor || "#ffffff"; + appState.exportWithDarkMode = false; + + const svg = await exportToSvg({ + elements: elements, + appState: { + ...appState, + exportBackground: true, + }, + files: files, + }); + + // Clear any previous render + const root = document.getElementById("root"); + root.innerHTML = ""; + root.appendChild(svg); + + window.__renderComplete = true; + window.__renderError = null; + return { success: true, width: svg.getAttribute("width"), height: svg.getAttribute("height") }; + } catch (err) { + window.__renderComplete = true; + window.__renderError = err.message; + return { success: false, error: err.message }; + } + }; + + // Signal that the module is loaded and ready + window.__moduleReady = true; + </script> +</body> +</html> diff --git a/skills/excalidraw/references/validation.md b/skills/excalidraw/references/validation.md deleted file mode 100644 index 1f808b0..0000000 --- a/skills/excalidraw/references/validation.md +++ /dev/null @@ -1,182 +0,0 @@ -# Validation Reference - -Checklists, validation algorithms, and common bug fixes. - ---- - -## Pre-Flight Validation Algorithm - -Run BEFORE writing the file: - -``` -FUNCTION validateDiagram(elements): - errors = [] - - // 1. Validate shape-text bindings - FOR each shape IN elements WHERE shape.boundElements != null: - FOR each binding IN shape.boundElements: - textElement = findById(elements, binding.id) - IF textElement == null: - errors.append("Shape {shape.id} references missing text {binding.id}") - ELSE IF textElement.containerId != shape.id: - errors.append("Text containerId doesn't match shape") - - // 2. Validate arrow connections - FOR each arrow IN elements WHERE arrow.type == "arrow": - sourceShape = findShapeNear(elements, arrow.x, arrow.y) - IF sourceShape == null: - errors.append("Arrow {arrow.id} doesn't start from shape edge") - - finalPoint = arrow.points[arrow.points.length - 1] - endX = arrow.x + finalPoint[0] - endY = arrow.y + finalPoint[1] - targetShape = findShapeNear(elements, endX, endY) - IF targetShape == null: - errors.append("Arrow {arrow.id} doesn't end at shape edge") - - IF arrow.points.length > 2: - IF arrow.elbowed != true: - errors.append("Arrow {arrow.id} missing elbowed:true") - IF arrow.roundness != null: - errors.append("Arrow {arrow.id} should have roundness:null") - - // 3. Validate unique IDs - ids = [el.id for el in elements] - duplicates = findDuplicates(ids) - IF duplicates.length > 0: - errors.append("Duplicate IDs: {duplicates}") - - // 4. Validate bounding boxes - FOR each arrow IN elements WHERE arrow.type == "arrow": - maxX = max(abs(p[0]) for p in arrow.points) - maxY = max(abs(p[1]) for p in arrow.points) - IF arrow.width < maxX OR arrow.height < maxY: - errors.append("Arrow {arrow.id} bounding box too small") - - RETURN errors - -FUNCTION findShapeNear(elements, x, y, tolerance=15): - FOR each shape IN elements WHERE shape.type IN ["rectangle", "ellipse"]: - edges = [ - (shape.x + shape.width/2, shape.y), // top - (shape.x + shape.width/2, shape.y + shape.height), // bottom - (shape.x, shape.y + shape.height/2), // left - (shape.x + shape.width, shape.y + shape.height/2) // right - ] - FOR each edge IN edges: - IF abs(edge.x - x) < tolerance AND abs(edge.y - y) < tolerance: - RETURN shape - RETURN null -``` - ---- - -## Checklists - -### Before Generating - -- [ ] Identified all components from codebase -- [ ] Mapped all connections/data flows -- [ ] Chose layout pattern (vertical, horizontal, hub-and-spoke) -- [ ] Selected color palette (default, AWS, Azure, K8s) -- [ ] Planned grid positions -- [ ] Created ID naming scheme - -### During Generation - -- [ ] Every labeled shape has BOTH shape AND text elements -- [ ] Shape has `boundElements: [{ "type": "text", "id": "{id}-text" }]` -- [ ] Text has `containerId: "{shape-id}"` -- [ ] Multi-point arrows have `elbowed: true`, `roundness: null`, `roughness: 0` -- [ ] Arrows have `startBinding` and `endBinding` -- [ ] No diamond shapes used -- [ ] Applied staggering formula for multiple arrows - -### Arrow Validation (Every Arrow) - -- [ ] Arrow `x,y` calculated from shape edge -- [ ] Final point offset = `targetEdge - sourceEdge` -- [ ] Arrow `width` = `max(abs(point[0]))` -- [ ] Arrow `height` = `max(abs(point[1]))` -- [ ] U-turn arrows have 40-60px clearance - -### After Generation - -- [ ] All `boundElements` IDs reference valid text elements -- [ ] All `containerId` values reference valid shapes -- [ ] All arrows start within 15px of shape edge -- [ ] All arrows end within 15px of shape edge -- [ ] No duplicate IDs -- [ ] Arrow bounding boxes match points -- [ ] File is valid JSON - ---- - -## Common Bugs and Fixes - -### Bug: Arrow appears disconnected/floating - -**Cause**: Arrow `x,y` not calculated from shape edge. - -**Fix**: -``` -Rectangle bottom: arrow_x = shape.x + shape.width/2 - arrow_y = shape.y + shape.height -``` - -### Bug: Arrow endpoint doesn't reach target - -**Cause**: Final point offset calculated incorrectly. - -**Fix**: -``` -target_edge = (target.x + target.width/2, target.y) -offset_x = target_edge.x - arrow.x -offset_y = target_edge.y - arrow.y -Final point = [offset_x, offset_y] -``` - -### Bug: Multiple arrows from same source overlap - -**Cause**: All arrows start from identical `x,y`. - -**Fix**: Stagger start positions: -``` -For 5 arrows from bottom edge: - arrow1.x = shape.x + shape.width * 0.2 - arrow2.x = shape.x + shape.width * 0.35 - arrow3.x = shape.x + shape.width * 0.5 - arrow4.x = shape.x + shape.width * 0.65 - arrow5.x = shape.x + shape.width * 0.8 -``` - -### Bug: Callback arrow doesn't loop correctly - -**Cause**: U-turn path lacks clearance. - -**Fix**: Use 4-point path: -``` -Points = [[0, 0], [clearance, 0], [clearance, -vert], [final_x, -vert]] -clearance = 40-60px -``` - -### Bug: Labels don't appear inside shapes - -**Cause**: Using `label` property instead of separate text element. - -**Fix**: Create TWO elements: -1. Shape with `boundElements` referencing text -2. Text with `containerId` referencing shape - -### Bug: Arrows are curved, not 90-degree - -**Cause**: Missing elbow properties. - -**Fix**: Add all three: -```json -{ - "roughness": 0, - "roundness": null, - "elbowed": true -} -``` diff --git a/skills/memory/SKILL.md b/skills/memory/SKILL.md deleted file mode 100644 index c920dd7..0000000 --- a/skills/memory/SKILL.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -name: memory -description: "Persistent memory system for Opencode agents. SQLite-based hybrid search over Obsidian vault. Use when: (1) storing user preferences/decisions, (2) recalling past context, (3) searching knowledge base. Triggers: remember, recall, memory, store, preference." -compatibility: opencode ---- - -## Overview - -opencode-memory is a SQLite-based hybrid memory system for Opencode agents. It indexes markdown files from your Obsidian vault (`~/CODEX/80-memory/`) and session transcripts, providing fast hybrid search (vector + keyword BM25). - -## Architecture - -- **Source of truth**: Markdown files at `~/CODEX/80-memory/` -- **Derived index**: SQLite at `~/.local/share/opencode-memory/index.db` -- **Hybrid search**: FTS5 (BM25) + vec0 (vector similarity) -- **Embeddings**: OpenAI text-embedding-3-small (1536 dimensions) - -## Available Tools - -### memory_search -Hybrid search over all indexed content (vault + sessions). - -``` -memory_search(query, maxResults?, source?) -``` - -- `query`: Search query (natural language) -- `maxResults`: Max results (default 6) -- `source`: Filter by "memory", "sessions", or "all" - -### memory_store -Store new memory as markdown file in vault. - -``` -memory_store(content, title?, category?) -``` - -- `content`: Memory content to store -- `title`: Optional title (slugified for filename) -- `category`: "preferences", "facts", "decisions", "entities", "other" - -### memory_get -Read specific file/lines from vault. - -``` -memory_get(filePath, startLine?, endLine?) -``` - -## Auto-Behaviors - -- **Auto-recall**: On session.created, relevant memories are searched and injected -- **Auto-capture**: On session.idle, preferences/decisions are extracted and stored -- **Token budget**: Max 2000 tokens injected to respect context limits - -## Workflows - -### Recall information -Before answering about past work, preferences, or decisions: -1. Call `memory_search` with relevant query -2. Use `memory_get` to retrieve full context if needed - -### Store new information -When user expresses preference or decision: -1. Call `memory_store` with content and category - -## Vault Structure - -``` -~/CODEX/80-memory/ -├── preferences/ # User preferences -├── facts/ # Factual knowledge -├── decisions/ # Design decisions -├── entities/ # People, projects, concepts -└── other/ # Uncategorized memories -``` diff --git a/skills/memory/references/deployment.md b/skills/memory/references/deployment.md deleted file mode 100644 index aaac4ae..0000000 --- a/skills/memory/references/deployment.md +++ /dev/null @@ -1,54 +0,0 @@ -# opencode-memory Deployment Guide - -## Installation - -### Option 1: Nix (Recommended) - -Add to your Nix flake: - -```nix -inputs.opencode-memory = { - url = "git+https://code.m3ta.dev/m3tam3re/opencode-memory"; - flake = false; -}; -``` - -### Option 2: npm - -```bash -npm install -g @m3tam3re/opencode-memory -``` - -## Configuration - -Add to `~/.config/opencode/opencode.json`: - -```json -{ - "plugins": [ - "opencode-memory" - ] -} -``` - -## Environment Variables - -- `OPENAI_API_KEY`: Required for embeddings - -## Vault Location - -Default: `~/CODEX/80-memory/` - -Override in plugin config if needed. - -## Rebuild Index - -```bash -bun run src/cli.ts --rebuild -``` - -## Verification - -1. Start Opencode -2. Call `memory_search` with any query -3. Verify no errors in logs diff --git a/skills/memory/references/mcp-config.md b/skills/memory/references/mcp-config.md deleted file mode 100644 index 2e4de3e..0000000 --- a/skills/memory/references/mcp-config.md +++ /dev/null @@ -1,109 +0,0 @@ -# Obsidian MCP Server Configuration - -## Overview - -This document describes how to configure the [cyanheads/obsidian-mcp-server](https://github.com/cyanheads/obsidian-mcp-server) for use with Opencode. This MCP server enables AI agents to interact with the Obsidian vault via the Local REST API plugin. - -## Prerequisites - -1. **Obsidian Desktop App** - Must be running -2. **Local REST API Plugin** - Installed and enabled in Obsidian -3. **API Key** - Generated from plugin settings - -## Environment Variables - -| Variable | Description | Default | Required | -|----------|-------------|---------|----------| -| `OBSIDIAN_API_KEY` | API key from Local REST API plugin | - | Yes | -| `OBSIDIAN_BASE_URL` | Base URL for REST API | `http://127.0.0.1:27123` | No | -| `OBSIDIAN_VERIFY_SSL` | Verify SSL certificates | `false` | No | -| `OBSIDIAN_ENABLE_CACHE` | Enable vault caching | `true` | No | - -## opencode.json Configuration - -Add this to your `programs.opencode.settings.mcp` in your Nix home-manager config: - -```json -"Obsidian-Vault": { - "command": ["npx", "obsidian-mcp-server"], - "environment": { - "OBSIDIAN_API_KEY": "<your-api-key>", - "OBSIDIAN_BASE_URL": "http://127.0.0.1:27123", - "OBSIDIAN_VERIFY_SSL": "false", - "OBSIDIAN_ENABLE_CACHE": "true" - }, - "enabled": true, - "type": "local" -} -``` - -**Note**: Replace `<your-api-key>` with the key from Obsidian Settings → Local REST API. - -## Nix Home-Manager Integration - -In your NixOS/home-manager configuration: - -```nix -programs.opencode.settings.mcp = { - # ... other MCP servers ... - - "Obsidian-Vault" = { - command = ["npx" "obsidian-mcp-server"]; - environment = { - OBSIDIAN_API_KEY = "<your-api-key>"; - OBSIDIAN_BASE_URL = "http://127.0.0.1:27123"; - OBSIDIAN_VERIFY_SSL = "false"; - OBSIDIAN_ENABLE_CACHE = "true"; - }; - enabled = true; - type = "local"; - }; -}; -``` - -After updating, run: -```bash -home-manager switch -``` - -## Getting the API Key - -1. Open Obsidian Settings -2. Navigate to Community Plugins → Local REST API -3. Copy the API key shown in settings -4. Paste into your configuration - -## Available MCP Tools - -Once configured, these tools are available: - -| Tool | Description | -|------|-------------| -| `obsidian_read_note` | Read a note's content | -| `obsidian_update_note` | Create or update a note | -| `obsidian_global_search` | Search the entire vault | -| `obsidian_manage_frontmatter` | Get/set frontmatter fields | -| `obsidian_manage_tags` | Add/remove tags | -| `obsidian_list_notes` | List notes in a folder | -| `obsidian_delete_note` | Delete a note | -| `obsidian_search_replace` | Search and replace in a note | - -## Troubleshooting - -### Server not responding -- Ensure Obsidian desktop app is running -- Check Local REST API plugin is enabled -- Verify API key matches - -### Connection refused -- Check the base URL (default: `http://127.0.0.1:27123`) -- Some setups use port 27124 - check plugin settings - -### npx not found -- Ensure Node.js is installed -- Run `npm install -g npx` if needed - -## References - -- [cyanheads/obsidian-mcp-server GitHub](https://github.com/cyanheads/obsidian-mcp-server) -- [Obsidian Local REST API Plugin](https://github.com/czottmann/obsidian-local-rest-api) diff --git a/skills/msteams/SKILL.md b/skills/msteams/SKILL.md deleted file mode 100644 index 62442e1..0000000 --- a/skills/msteams/SKILL.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -name: msteams -description: "Microsoft Teams Graph API integration for team communication. Use when: (1) Managing teams and channels, (2) Sending/receiving channel messages, (3) Scheduling or managing meetings, (4) Handling chat conversations. Triggers: 'Teams', 'meeting', 'channel', 'team message', 'chat', 'Teams message'." -compatibility: opencode ---- - -# Microsoft Teams Integration - -Microsoft Teams Graph API integration for managing team communication, channels, messages, meetings, and chat conversations via MCP tools. - -## Core Capabilities - -### Teams & Channels -- **List joined teams**: Retrieve all teams the user is a member of -- **Manage channels**: Create, list, and manage channels within teams -- **Team membership**: Add, remove, and update team members - -### Channel Messages -- **Send messages**: Post messages to channels with rich text support -- **Retrieve messages**: List channel messages with filtering by date range -- **Message management**: Read and respond to channel communications - -### Online Meetings -- **Schedule meetings**: Create online meetings with participants -- **Manage meetings**: Update meeting details and coordinates -- **Meeting access**: Retrieve join links and meeting information -- **Presence**: Check user presence and activity status - -### Chat -- **Direct messages**: 1:1 chat conversations with users -- **Group chats**: Multi-person chat conversations -- **Chat messages**: Send and receive chat messages - -## Common Workflows - -### Send Channel Message - -1. Identify target team and channel -2. Compose message content -3. Use MCP tool to send message to channel - -Example: -``` -"Post a message to the 'General' channel in 'Engineering' team about the deployment status" -``` - -### Schedule Meeting - -1. Determine meeting participants -2. Set meeting time and duration -3. Create meeting title and description -4. Use MCP tool to create online meeting - -Example: -``` -"Schedule a meeting with @alice and @bob for Friday 2pm to discuss the project roadmap" -``` - -### List Channel Messages - -1. Specify team and channel -2. Define date range (required for polling) -3. Retrieve and display messages - -Example: -``` -"Show me all messages in #general from the last week" -``` - -### Send Direct Message - -1. Identify recipient user -2. Compose message -3. Use MCP chat tool to send message - -Example: -``` -"Send a message to @john asking if the PR review is complete" -``` - -## MCP Tool Categories - -The MS Teams MCP server provides tool categories for: - -- **Channels**: Team and channel management operations -- **Messages**: Channel message operations -- **Meetings**: Online meeting scheduling and management -- **Chat**: Direct and group chat operations - -## Important Constraints - -**Authentication**: Do NOT include Graph API authentication flows. The MCP server handles authentication configuration. - -**Polling limits**: When retrieving messages, always specify a date range. Polling the same resource more than once per day is a violation of Microsoft APIs Terms of Use. - -**Email overlap**: Do NOT overlap with Outlook email functionality. This skill focuses on Teams-specific communication (channels, chat, meetings), not email operations. - -**File storage**: Files in channels are stored in SharePoint. Use SharePoint-specific operations for file management. - -## Domain Boundaries - -This skill integrates with **Hermes** (work communication agent). Hermes loads this skill when user requests: -- Teams-related operations -- Meeting scheduling or management -- Channel communication -- Teams chat conversations - -For email operations, Hermes uses the **outlook** skill instead. diff --git a/skills/outlook/SKILL.md b/skills/outlook/SKILL.md deleted file mode 100644 index b381464..0000000 --- a/skills/outlook/SKILL.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -name: outlook -description: "Outlook Graph API integration for email, calendar, and contact management. Use when: (1) Reading or sending emails, (2) Managing inbox and folders, (3) Working with calendar events and appointments, (4) Managing contacts, (5) Organizing email messages. Triggers: 'email', 'Outlook', 'inbox', 'calendar', 'contact', 'message', 'folder', 'appointment', 'meeting'." -compatibility: opencode ---- - -# Outlook - -Outlook Graph API integration for mail, calendar, and contact management via MCP. Enables comprehensive email workflows, calendar coordination, and contact organization. - -## Overview - -Outlook is Microsoft 365's messaging and communication hub. This skill provides access to: - -- **Mail**: Send, receive, search, organize, and categorize messages -- **Calendar**: Create and manage events, appointments, and meetings -- **Contacts**: Manage contact information and relationships -- **Folders**: Organize messages into custom folder structures - -## Core Workflows - -### 1. Reading Emails - -Retrieve messages from mailbox: - -``` -User: "Check my inbox for new messages from John" - -AI: Use Outlook MCP to: -1. List messages in Inbox folder -2. Filter by sender = "John" -3. Display summary (subject, date, importance) -``` - -**Use search and sort** to efficiently find messages: -- Filter by folder (Inbox, Sent, Drafts, etc.) -- Sort by date, importance, or subject -- Search by sender, subject, or content - -### 2. Sending Emails - -Compose and send new messages: - -``` -User: "Send an email to sarah@company.com about the project update" - -AI: Use Outlook MCP to: -1. Create message draft with recipient and subject -2. Add body content -3. Send the message -``` - -**Key options**: -- Add attachments -- Set importance (low, normal, high) -- Add recipients (to, cc, bcc) -- Use categories for organization - -### 3. Replying and Forwarding - -Respond to existing messages: - -``` -User: "Reply to the last email from Mike with thanks" - -AI: Use Outlook MCP to: -1. Retrieve the most recent message from Mike -2. Create reply with appropriate body -3. Send the reply -``` - -**Supports**: -- Reply (to sender) -- Reply All (to all recipients) -- Forward (to new recipients) - -### 4. Managing Folders - -Organize messages into folder structure: - -``` -User: "Move all emails from vendor@supplier.com to Vendors folder" - -AI: Use Outlook MCP to: -1. Search for messages from vendor@supplier.com -2. Move matching messages to Vendors folder -3. Confirm move operation -``` - -**Folder operations**: -- List folders -- Create new folders -- Move messages between folders -- Delete folders (careful!) - -### 5. Calendar Events - -Manage calendar and schedule meetings: - -``` -User: "Schedule a team meeting for Friday at 2pm" - -AI: Use Outlook MCP to: -1. Create calendar event -2. Set date/time (Friday 2:00 PM) -3. Add attendees -4. Send meeting invitation -``` - -**Event details**: -- Subject and location -- Start/end times -- Attendees and required/optional status -- Meeting body/agenda -- Recurrence (for recurring meetings) - -### 6. Managing Contacts - -Create and maintain contact information: - -``` -User: "Add Jane Smith to contacts: jane@company.com, 555-1234" - -AI: Use Outlook MCP to: -1. Create contact object -2. Add email address and phone number -3. Save to contacts -``` - -**Contact fields**: -- Name (first, last, display name) -- Email addresses (multiple) -- Phone numbers (multiple types) -- Company, job title -- Notes - -## Advanced Features - -### Message Organization - -**Categories**: Tag messages with color-coded categories for enhanced organization -``` -User: "Tag these project emails as 'Urgent' category" - -AI: Use Outlook MCP to: -1. Retrieve specified messages -2. Assign category (e.g., "Urgent") -3. Confirm categorization -``` - -**Importance**: Mark messages as high, normal, or low importance -``` -User: "Mark this message as high priority" - -AI: Use Outlook MCP to update message importance flag -``` - -**Search**: Find messages by sender, subject, content, or date range -``` -User: "Find all emails about Q4 budget from October" - -AI: Use Outlook MCP to search with filters: -- Subject contains "budget" -- Date range: October -- Optionally filter by sender -``` - -### Email Intelligence - -**Focused Inbox**: Access messages categorized as focused vs other -**Mail Tips**: Check recipient status before sending (auto-reply, full mailbox) -**MIME Support**: Handle email in MIME format for interoperability - -## Integration with Other Skills - -This skill focuses on Outlook-specific operations. For related functionality: - -| Need | Skill | When to Use | -|------|-------|-------------| -| **Team project updates** | basecamp | "Update the Basecamp todo" | -| **Team channel messages** | msteams | "Post this in the Teams channel" | -| **Private notes about emails** | obsidian | "Save this to Obsidian" | -| **Drafting long-form emails** | calliope | "Help me write a professional email" | -| **Short quick messages** | hermes (this skill) | "Send a quick update" | - -## Common Patterns - -### Email Triage Workflow - -1. **Scan inbox**: List messages sorted by date -2. **Categorize**: Assign categories based on content/urgency -3. **Action**: Reply, forward, or move to appropriate folder -4. **Track**: Flag for follow-up if needed - -### Meeting Coordination - -1. **Check availability**: Query calendar for conflicts -2. **Propose time**: Suggest multiple time options -3. **Create event**: Set up meeting with attendees -4. **Follow up**: Send reminder or agenda - -### Project Communication - -1. **Search thread**: Find all messages related to project -2. **Organize**: Move to project folder -3. **Categorize**: Tag with project category -4. **Summarize**: Extract key points if needed - -## Quality Standards - -- **Accurate recipient addressing**: Verify email addresses before sending -- **Clear subject lines**: Ensure subjects accurately reflect content -- **Appropriate categorization**: Use categories consistently -- **Folder hygiene**: Maintain organized folder structure -- **Respect privacy**: Do not share sensitive content indiscriminately - -## Edge Cases - -**Multiple mailboxes**: This skill supports primary and shared mailboxes, not archive mailboxes -**Large attachments**: Use appropriate attachment handling for large files -**Meeting conflicts**: Check calendar availability before scheduling -**Email limits**: Respect rate limits and sending quotas -**Deleted items**: Use caution with delete operations (consider archiving instead) - -## Boundaries - -- **Do NOT handle Teams-specific messaging** (Teams's domain) -- **Do NOT handle Basecamp communication** (basecamp's domain) -- **Do NOT manage wiki documentation** (Athena's domain) -- **Do NOT access private Obsidian vaults** (Apollo's domain) -- **Do NOT write creative email content** (delegate to calliope for drafts) diff --git a/skills/skill-creator/SKILL.md b/skills/skill-creator/SKILL.md index b3083cf..a282870 100644 --- a/skills/skill-creator/SKILL.md +++ b/skills/skill-creator/SKILL.md @@ -79,6 +79,7 @@ Executable code (Python/Bash/etc.) for tasks that require deterministic reliabil - **Example**: `scripts/rotate_pdf.py` for PDF rotation tasks - **Benefits**: Token efficient, deterministic, may be executed without loading into context - **Note**: Scripts may still need to be read by Opencode for patching or environment-specific adjustments +- **Dependencies**: Scripts with external dependencies (Python packages, system tools) require those dependencies to be registered in the repository's `flake.nix`. See Step 4 for details. ##### References (`references/`) @@ -302,6 +303,37 @@ To begin implementation, start with the reusable resources identified above: `sc Added scripts must be tested by actually running them to ensure there are no bugs and that the output matches what is expected. If there are many similar scripts, only a representative sample needs to be tested to ensure confidence that they all work while balancing time to completion. +#### Register Dependencies in flake.nix + +When scripts introduce external dependencies (Python packages or system tools), add them to the repository's `flake.nix`. Dependencies are defined once in `pythonEnv` (Python packages) or `packages` (system tools) inside the `skills-runtime` buildEnv. This runtime is exported as `packages.${system}.skills-runtime` and consumed by project flakes and home-manager — ensuring opencode always has the correct environment regardless of which project it runs in. + +**Python packages** — add to the `pythonEnv` block with a comment referencing the skill: + +```nix +pythonEnv = pkgs.python3.withPackages (ps: + with ps; [ + # <skill-name>: <script>.py + <package-name> + ]); +``` + +**System tools** (e.g. `poppler-utils`, `ffmpeg`, `imagemagick`) — add to the `paths` list in the `skills-runtime` buildEnv: + +```nix +skills-runtime = pkgs.buildEnv { + name = "opencode-skills-runtime"; + paths = [ + pythonEnv + # <skill-name>: needed by <script> + pkgs.<tool-name> + ]; +}; +``` + +**Convention**: Each entry must include a comment with `# <skill-name>: <reason>` so dependencies remain traceable to their originating skill. + +After adding dependencies, verify they resolve: `nix develop --command python3 -c "import <package>"` + Any example files and directories not needed for the skill should be deleted. The initialization script creates example files in `scripts/`, `references/`, and `assets/` to demonstrate structure, but most skills won't need all of them. #### Update SKILL.md