refactor: mkOpencodeSkills -> mkSkills

This commit is contained in:
m3tam3re
2026-05-11 18:49:26 +02:00
parent 9a91f1ee0c
commit d1837fc113
7 changed files with 157 additions and 93 deletions
@@ -1,13 +1,14 @@
# Learnings
## [2026-04-10] Session Initialized
- Plan: harness-agnostic-migration (21 tasks + 4 final)
- AGENTS repo: /home/m3tam3re/p/AI/AGENTS
- nixpkgs repo: /home/m3tam3re/p/NIX/nixpkgs
- TOML chosen as canonical format (builtins.fromTOML, no IFD)
- Renderers belong in nixpkgs, not AGENTS repo
- 6 agents: chiron, chiron-forge, hermes, athena, apollo, calliope
- OpenCode: file-based agents (.opencode/agent/*.md) NOT config.json embedding
- OpenCode: file-based agents (.opencode/agent/\*.md) NOT config.json embedding
- Pi: no subagents — renders AGENTS.md + SYSTEM.md only
- Claude Code: name must be [a-z0-9-]+ (slugified)
- No model in agent.toml (per-machine via home-manager)
@@ -15,19 +16,23 @@
- No YAML files as canonical source
- Permission model: two-level — intent (allow/deny/ask) + rules array "pattern:action"
- mkOpencodeRules → mkCodingRules (backward-compat alias)
- lib.mkOpencodeSkills stays unchanged
- lib.mkSkills stays unchanged
## [2026-04-10] Task 1: Capture Golden File Baseline
### Golden File Created
- **Path**: `.sisyphus/evidence/agents-golden.json`
- **Method**: `jq --sort-keys . agents/agents.json`
- **Status**: ✓ Valid JSON, parseable, verified
### Agent Count
- **Total**: 6 agents
- **Verification**: `jq 'keys | length'` → 6 ✓
### Agent Names (Alphabetically Sorted)
1. Apollo (Knowledge Management) — subagent, private knowledge specialist
2. Athena (Researcher) — subagent, work knowledge specialist
3. Calliope (Writer) — subagent, writing specialist
@@ -36,7 +41,9 @@
6. Hermes (Communication) — subagent, communication specialist
### Agent Object Structure
Every agent has 5 top-level keys:
- `description` (string) — agent purpose and capabilities
- `mode` (string) — "primary" or "subagent"
- `model` (string) — LLM model ID (all use "zai-coding-plan/glm-5")
@@ -44,7 +51,9 @@ Every agent has 5 top-level keys:
- `permission` (object) — capability matrix with granular controls
### Permission Structure
All agents have 6 permission categories:
- `question` → "allow" | "deny" | "ask"
- `webfetch` → "allow" | "deny" | "ask"
- `websearch` → "allow" | "deny" | "ask" (not all agents)
@@ -53,10 +62,12 @@ All agents have 6 permission categories:
- `external_directory` → nested rules (allow/deny per path pattern)
### Baseline Purpose
This golden file serves as the **canonical reference** for backward-compat verification in Task 8.
It will be compared against output from the harness-agnostic bridge to ensure config integrity.
### Next Steps
- Task 8 will generate a comparable JSON from the bridge
- Diff will be computed: `jq --sort-keys . bridge_output.json > bridge-output.json && diff agents-golden.json bridge-output.json`
- Any structural or content changes will be flagged
@@ -66,12 +77,15 @@ It will be compared against output from the harness-agnostic bridge to ensure co
**Result: ✅ PASS**
### Test Execution
- Full Chiron-Forge TOML (16 lines, 5 permission sections, 15 bash rules, 4 external_directory rules): **PARSED SUCCESSFULLY**
- Minimal TOML (2 lines, name + description only): **PARSED SUCCESSFULLY**
- Parser: `nix eval --impure --expr 'builtins.fromTOML (builtins.readFile <path>)' --json`
### Glob Patterns Verified
All complex patterns preserved exactly:
- `rm -rf *` → intact (wildcard in rule)
- `git reset --hard*` → intact (pattern suffix)
- `git push*` → intact (pattern suffix)
@@ -83,25 +97,31 @@ All complex patterns preserved exactly:
- `/tmp/**` → intact (absolute + recursive)
### Special Handling
- TOML arrays of strings work perfectly for `rules` list
- Two-level structure (`intent` + `rules`) maps cleanly from JSON nested objects
- No datetime fields used (confirmed limitation is not a blocker for permissions schema)
- No multi-line inline tables needed (flat key-value structure only)
### Conclusion
**✅ TOML is suitable for agent permission config.** The proposed two-level model (`intent = "allow"|"deny"|"ask"` + `rules = [...]` array) is:
- **Parseable**: `builtins.fromTOML` handles it perfectly with `--impure` flag
- **Pattern-safe**: All glob patterns (wildcards, recursion, flags) preserved exactly
- **Backward-compatible**: Maps cleanly from existing JSON nested object format
### Evidence Files
- `/home/m3tam3re/p/AI/AGENTS/.sisyphus/evidence/task-2-toml-spike.json` (full Chiron-Forge parsed result)
- `/home/m3tam3re/p/AI/AGENTS/.sisyphus/evidence/task-2-toml-minimal.json` (minimal test parsed result)
### Next Steps
No workarounds needed. Ready to implement full harness with TOML permission loader.
## [2026-04-10] Task 3: Canonical Schema Designed
- SCHEMA.md created at agents/SCHEMA.md
- Required fields: name, description
- Optional: display_name, mode, tags, max_turns, skills, context, rules
@@ -115,21 +135,25 @@ No workarounds needed. Ready to implement full harness with TOML permission load
## [2026-04-10] Task 4: OpenCode File-Based Agent Format
### File Location
- **Per-project**: `.opencode/agents/`
- **Global**: `~/.config/opencode/agents/`
- Per-project agents override global agents with same name
### Agent Naming
- **Filename determines agent name** — no `name` field in frontmatter
- Example: `review.md` → agent named `review`
- Naming convention: `[a-z0-9-]+` (lowercase, hyphens)
### YAML Frontmatter Structure
- **Required**: `description` (string)
- **Optional**: `mode` (`primary`|`subagent`|`all`), `model`, `temperature`, `top_p`, `steps`, `disable`, `hidden`, `color`, `permission`, `task`
- Provider-specific fields pass through to LLM (e.g., `reasoningEffort` for OpenAI)
### Permission Format in Markdown
```yaml
permission:
edit:
@@ -146,46 +170,55 @@ permission:
"*": ask
"~/p/**": allow
```
- Actions: `allow` | `ask` | `deny`
- Nested rules support glob patterns (`*`, `**`, wildcards)
- Last matching rule wins
### Mode Field Values
- `primary` — available via Tab switching
- `subagent` — invoked via @mention or by other agents
- `all` — flexible, can be used both ways
### System Prompt Delivery
- Markdown body (after frontmatter) IS the system prompt
- No `{file:...}` syntax in markdown (unlike JSON config)
- Direct markdown content → sent to LLM
### Default Behaviors
- `mode``all` (if omitted)
- `model` → global config (primary agents) or parent's model (subagents)
- `temperature` → model-specific default (0 for most, 0.55 for Qwen)
- `permission` → full access (if omitted, all tools enabled)
### Interaction with config.json
- **Both** JSON and markdown agents are loaded
- Markdown agents **override** JSON agents with same name
- No conflict; complementary
### KEY ADVANTAGE: Prompt Changes Don't Require home-manager switch
- File changes → OpenCode reloads on next startup
- NO home-manager switch needed
- This is the primary motivation for file-based migration
### Limitations
- **No subdirectories**: only root level of `.opencode/agents/` scanned
- **No name field**: filename is authoritative
- **Filename must be valid**: [a-z0-9-]+ convention
### Evidence File
- `/home/m3tam3re/p/AI/AGENTS/.sisyphus/evidence/task-4-opencode-agent-format.md`
- Complete spec with examples, frontmatter reference, permission format, YAML/JSON comparison
### Confirmed Answers
- Directory: `agents/` (both global and per-project) ✅
- File naming: Filename determines agent name ✅
- Required fields: `description` only ✅
@@ -196,13 +229,14 @@ permission:
- Frontmatter needs `name` field: **NO**
### Sources
- https://opencode.ai/docs/agents (official documentation)
- /home/m3tam3re/p/NIX/nixpkgs/modules/home-manager/coding/opencode.nix (current deployment)
- /home/m3tam3re/p/AI/AGENTS/agents/agents.json (current 6 agents)
- /home/m3tam3re/p/AI/AGENTS/AGENTS.md (repo documentation)
## [2026-04-10] Task 4: Key Finding — OpenCode Permission Rule Precedence
- OpenCode uses LAST-MATCHING-RULE-WINS (not first-match!)
- This matters for renderer: when translating `rules[]` array, order must be preserved
- The wildcard `"*"` rule becomes the fallback (keep it first in YAML output, others after)
@@ -214,18 +248,22 @@ permission:
- `task` permission controls which subagents can be invoked (glob patterns)
## [2026-04-10] Task 4: OpenCode Permission YAML Format
The granular format is nested YAML objects, NOT a rule array:
```yaml
permission:
bash:
"*": ask # This is the intent/default
"git status*": allow # These are the rules
"*": ask # This is the intent/default
"git status*": allow # These are the rules
"git push*": deny
```
The renderer must convert from canonical `intent + rules[]` format to this nested YAML format.
The `"*"` key always goes FIRST (as the fallback), then specific rules after it.
## [2026-04-10] Task 5: All 6 agent.toml Files Created
- Directories: agents/{chiron,chiron-forge,hermes,athena,apollo,calliope}/
- Each has: agent.toml + system-prompt.md
- All TOML parse: YES (6/6 verified via `nix eval --impure`)
@@ -243,6 +281,7 @@ The `"*"` key always goes FIRST (as the fallback), then specific rules after it.
- No model field, no prompt field per schema exclusion rules
## [2026-04-10] Task 6: loadAgents + agentsJson Bridge Complete
- Fix applied: description = agent.description + "." (SCHEMA.md has no trailing period; golden file does)
- All 6 agents load correctly via lib.loadAgents
- agentsJson bridge matches golden file exactly (zero diff)