|
|
@@ -0,0 +1,1503 @@
|
|
|
+# 01 — Feature & Content Inventory
|
|
|
+
|
|
|
+> **Owner:** Agent A
|
|
|
+> **Status:** Spec only — no implementation.
|
|
|
+> **Read first:** [`00-INDEX.md`](./00-INDEX.md) for locked decisions.
|
|
|
+>
|
|
|
+> **Purpose:** Exhaustive inventory of every feature and capability that exists today in
|
|
|
+> `.opencode/` (source), `registry.json`, and `plugins/claude-code/`. Each item is classified
|
|
|
+> **UNIVERSAL** (belongs in the neutral `/content/` schema) vs **OPENCODE-SPECIFIC**
|
|
|
+> (needs adapter handling) vs **AT RISK** (no obvious home — will be silently lost unless
|
|
|
+> a decision is made).
|
|
|
+>
|
|
|
+> The user's #1 requirement: **nothing gets lost.** Every row below must land somewhere.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Legend
|
|
|
+
|
|
|
+| Tag | Meaning |
|
|
|
+|-----|---------|
|
|
|
+| 🟢 **UNIVERSAL** | Belongs in the neutral IR. All/most target tools express this concept. |
|
|
|
+| 🟡 **OPENCODE-SPECIFIC** | Real capability, but expressed in OpenCode syntax. Adapter must render it; other adapters may degrade it (with a warning). |
|
|
|
+| 🔵 **REGISTRY/BUILD** | Not agent-facing content — belongs to the catalog or build pipeline. |
|
|
|
+| 🔴 **AT RISK** | Currently has no home in the target architecture. **Needs a human decision** (see Open Questions). |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 0. Census — what is actually on disk
|
|
|
+
|
|
|
+Counts verified by enumeration, not by trusting the docs.
|
|
|
+
|
|
|
+| Area | Path | Count | Notes |
|
|
|
+|------|------|-------|-------|
|
|
|
+| Agents (markdown) | `.opencode/agent/**/*.md` | **34** | Task brief said 39; 39 = 34 `.md` + 5 `0-category.json`. |
|
|
|
+| Category descriptors | `.opencode/agent/**/0-category.json` | **5** | `content`, `core`, `data`, `meta`, `subagents/development`. |
|
|
|
+| Agent metadata entries | `.opencode/config/agent-metadata.json` | **28** | 8 `type: agent`, 20 `type: subagent`. **6 disk agents have no entry.** |
|
|
|
+| Commands | `.opencode/command/**/*.md` | **20** | Task brief said 29; 29 = 20 `.md` + 9 `.yaml` eval templates. |
|
|
|
+| Context files | `.opencode/context/**/*` | **300** | 297 `.md` + `paths.json` + 2 JSON schemas. 79 are `navigation.md`. |
|
|
|
+| Skills (plural dir) | `.opencode/skills/*/SKILL.md` | **4** | `task-management`, `context-manager`, `context7`, `smart-router-skill`. |
|
|
|
+| Skills (singular dir) | `.opencode/skill/*/` | **2** | `project-orchestration`, `task-management` — **not in registry** (see §4.3). |
|
|
|
+| Tools | `.opencode/tool/*/index.ts` | **3** | `env`, `gemini`, `template`. |
|
|
|
+| Plugins | `.opencode/plugin/*.ts` | **2** | `notify.ts`, `agent-validator.ts` (+ `.disabled` twin). |
|
|
|
+| Plugins (plural dir) | `.opencode/plugins/*/` | **1** | `coder-verification`. |
|
|
|
+| Profiles | `.opencode/profiles/*/profile.json` | **5** | **Stale duplicates** of `registry.json#profiles` (see §8.2). |
|
|
|
+| Prompts | `.opencode/prompts/**` | **6 agents × N models** | Per-model prompt variants + eval results. |
|
|
|
+| Registry components | `registry.json#components` | **8 types / 245 entries** | agents 8, subagents 19, commands 17, tools 2, plugins 1, skills 4, contexts 191, config 3. |
|
|
|
+| CC plugin agents | `plugins/claude-code/agents/` | **7** | vs 34 in `.opencode/` — **the drift**. |
|
|
|
+| CC plugin skills | `plugins/claude-code/skills/` | **12** | vs 4 in `.opencode/skills/` — **CC is ahead here**. |
|
|
|
+
|
|
|
+> **Drift is bidirectional.** The common framing is "CC has 7 agents vs OpenCode's 34, CC is
|
|
|
+> behind." That is only half true: **CC has 12 skills vs OpenCode's 4**, and CC's session-start
|
|
|
+> context-injection has no OpenCode equivalent at all. The migration must merge *both*
|
|
|
+> directions, not just replay `.opencode/` into CC.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 1. Agents & Subagents
|
|
|
+
|
|
|
+### 1.1 Frontmatter fields actually in use
|
|
|
+
|
|
|
+Measured across all 34 agent `.md` files (`awk` over the YAML block):
|
|
|
+
|
|
|
+| Field | Occurrences | What it does | Class | Post-migration home |
|
|
|
+|-------|-------------|--------------|-------|---------------------|
|
|
|
+| `name` | 34 | Display/invocation name. PascalCase in OpenCode (`CodeReviewer`). | 🟢 UNIVERSAL | `id` (canonical, kebab) + `name` (human). Adapters slugify: OpenCode→PascalCase, Claude→kebab. |
|
|
|
+| `description` | 34 | One-line purpose; drives delegation routing. | 🟢 UNIVERSAL | `description`. Claude adapter **appends `examples[]`** into this field (see §1.5). |
|
|
|
+| `mode` | 34 | `primary` \| `subagent`. | 🟢 UNIVERSAL | `role: primary \| subagent`. OpenCode adapter renames `role`→`mode`. |
|
|
|
+| `temperature` | 33 | Sampling temperature (`0`–`0.2` in practice). | 🟡 OPENCODE-SPECIFIC | `inference.temperature`. **Claude Code has no per-agent temperature → degradation warning** (already predicted in `00-INDEX.md`). |
|
|
|
+| `permission` | 24 | Granular per-tool, per-glob allow/ask/deny. | 🟡 OPENCODE-SPECIFIC | `capabilities` (intent). This is the **hardest transform** — see §1.3. |
|
|
|
+| `model` | **0** | — | 🟢 UNIVERSAL | `inference.model: null`. **Confirms Locked Decision #2:** no agent hardcodes a model today. PRs #311/#324 would have *introduced* the problem, not preserved it. |
|
|
|
+| `tools` | **0** | — | 🟢 UNIVERSAL | OpenCode expresses tool access via `permission`, not `tools`. Claude adapter derives `tools:` allowlist from `capabilities`. |
|
|
|
+| `hooks` | **0** | — | n/a | No agent declares hooks in frontmatter. Hooks exist only as *plugins* (§6) and CC `hooks.json` (§9.2). |
|
|
|
+| `id`,`category`,`type`,`version`,`author` | **1** | Only `eval-runner.md` inlines these. | 🔵 REGISTRY | Everywhere else these live in the `agent-metadata.json` sidecar. `eval-runner` is the **inconsistent outlier**. |
|
|
|
+
|
|
|
+**Representative — `.opencode/agent/subagents/code/reviewer.md`** (the `00-INDEX.md` worked example, verified verbatim):
|
|
|
+
|
|
|
+```yaml
|
|
|
+---
|
|
|
+name: CodeReviewer
|
|
|
+description: Code review, security, and quality assurance agent
|
|
|
+mode: subagent
|
|
|
+temperature: 0.1
|
|
|
+permission:
|
|
|
+ bash: { "*": "deny" }
|
|
|
+ edit: { "**/*": "deny" }
|
|
|
+ write: { "**/*": "deny" }
|
|
|
+ task: { contextscout: "allow" }
|
|
|
+---
|
|
|
+```
|
|
|
+
|
|
|
+**Representative — `.opencode/agent/core/openagent.md`** (primary agent, security-critical denies):
|
|
|
+
|
|
|
+```yaml
|
|
|
+---
|
|
|
+name: OpenAgent
|
|
|
+description: "Universal agent for answering queries, executing tasks, and coordinating workflows across any domain"
|
|
|
+mode: primary
|
|
|
+temperature: 0.2
|
|
|
+permission:
|
|
|
+ bash:
|
|
|
+ "*": "ask"
|
|
|
+ "rm -rf *": "ask"
|
|
|
+ "rm -rf /*": "deny"
|
|
|
+ "sudo *": "deny"
|
|
|
+ "> /dev/*": "deny"
|
|
|
+ edit:
|
|
|
+ "**/*.env*": "deny"
|
|
|
+ "**/*.key": "deny"
|
|
|
+ "**/*.secret": "deny"
|
|
|
+ "node_modules/**": "deny"
|
|
|
+ ".git/**": "deny"
|
|
|
+---
|
|
|
+```
|
|
|
+
|
|
|
+**Representative — `.opencode/agent/subagents/code/coder-agent.md`** (the `allow`-listed-command pattern):
|
|
|
+
|
|
|
+```yaml
|
|
|
+permission:
|
|
|
+ bash:
|
|
|
+ "*": "deny"
|
|
|
+ "bash .opencode/skills/task-management/router.sh complete*": "allow"
|
|
|
+ "bash .opencode/skills/task-management/router.sh status*": "allow"
|
|
|
+ task:
|
|
|
+ contextscout: "allow"
|
|
|
+ externalscout: "allow"
|
|
|
+ TestEngineer: "allow"
|
|
|
+```
|
|
|
+
|
|
|
+> ⚠️ Two failure modes visible in this one block:
|
|
|
+> 1. The allowed bash commands **hardcode `.opencode/skills/...`** — a build-output path baked into
|
|
|
+> neutral content. See §3.4.
|
|
|
+> 2. `task:` mixes **id-style** (`contextscout`) and **name-style** (`TestEngineer`) references in the
|
|
|
+> same map. The neutral `delegate:` map must pick one (canonical `id`) and the OpenCode adapter
|
|
|
+> must re-render to whatever OpenCode matches on. See §1.4.
|
|
|
+
|
|
|
+### 1.2 The three-way naming problem (highest-risk aliasing)
|
|
|
+
|
|
|
+For a single agent there are up to **four** distinct identifiers:
|
|
|
+
|
|
|
+| Surface | Value | Source |
|
|
|
+|---------|-------|--------|
|
|
|
+| Registry / dependency id | `tester` | `registry.json#components.subagents[].id` |
|
|
|
+| Filename | `test-engineer.md` | `.opencode/agent/subagents/code/test-engineer.md` |
|
|
|
+| Frontmatter `name` | `TestEngineer` | the agent file |
|
|
|
+| CC plugin name | `test-engineer` | `plugins/claude-code/agents/test-engineer.md` |
|
|
|
+
|
|
|
+`agent-metadata.json` confirms the split:
|
|
|
+
|
|
|
+```json
|
|
|
+"tester": {
|
|
|
+ "id": "tester", "name": "TestEngineer",
|
|
|
+ "category": "subagents/code", "type": "subagent",
|
|
|
+ "dependencies": ["context:standards-tests"]
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+…while `registry.json` maps that same id to a *differently named file*:
|
|
|
+
|
|
|
+```json
|
|
|
+{ "id": "tester", "name": "TestEngineer",
|
|
|
+ "path": ".opencode/agent/subagents/code/test-engineer.md" }
|
|
|
+```
|
|
|
+
|
|
|
+**Class: 🔴 AT RISK.** A naive "filename = id" migration silently breaks every
|
|
|
+`subagent:tester` dependency edge and every `task: { TestEngineer: allow }` permission entry.
|
|
|
+The neutral schema needs an explicit `id` **plus** an `aliases[]` field, and the build must
|
|
|
+emit an id→name→path map per target. See Open Question **Q1**.
|
|
|
+
|
|
|
+### 1.3 `permission` → `capabilities` transform (the crown-jewel transform for agents)
|
|
|
+
|
|
|
+OpenCode's `permission` is a **three-valued, glob-scoped, per-tool matrix**:
|
|
|
+
|
|
|
+```
|
|
|
+permission.<tool>.<glob-pattern> = "allow" | "ask" | "deny"
|
|
|
+```
|
|
|
+
|
|
|
+The neutral `capabilities` shape in `00-INDEX.md` is **flatter**:
|
|
|
+
|
|
|
+```yaml
|
|
|
+capabilities:
|
|
|
+ read: allow
|
|
|
+ edit: deny
|
|
|
+ delegate: { contextscout: allow }
|
|
|
+```
|
|
|
+
|
|
|
+Concrete losses if the flat shape is adopted as-is:
|
|
|
+
|
|
|
+| OpenCode construct | Example | Survives flat `capabilities`? |
|
|
|
+|---|---|---|
|
|
|
+| Tri-state `ask` | `bash: { "*": "ask" }` | ⚠️ Only if the enum is `allow\|ask\|deny`, **not** `allow\|deny`. Claude has no `ask` → maps to prompt-on-use or `deny`. |
|
|
|
+| Glob scoping | `edit: { "**/*.env*": "deny" }` | ❌ **Lost.** Flat `edit: deny` cannot express "deny only secrets, allow the rest". |
|
|
|
+| Deny-by-default + narrow allow | `bash: {"*":"deny", "bash .../router.sh complete*":"allow"}` | ❌ **Lost.** This is a *security control* on `coder-agent`. |
|
|
|
+| Ordered precedence | `"*": "ask"` then `"rm -rf /*": "deny"` | ❌ **Lost.** Specificity/ordering semantics disappear. |
|
|
|
+
|
|
|
+**Class: 🟡 OPENCODE-SPECIFIC, but 🔴 AT RISK of silent loss.**
|
|
|
+
|
|
|
+**Recommendation to Agent B:** `capabilities.<tool>` must accept **either** a scalar
|
|
|
+(`allow|ask|deny`) **or** an ordered **rule list**:
|
|
|
+
|
|
|
+```yaml
|
|
|
+capabilities:
|
|
|
+ bash:
|
|
|
+ - { pattern: "*", effect: ask }
|
|
|
+ - { pattern: "sudo *", effect: deny }
|
|
|
+ edit:
|
|
|
+ - { pattern: "**/*.env*", effect: deny }
|
|
|
+ - { pattern: "**/*", effect: allow }
|
|
|
+```
|
|
|
+
|
|
|
+The scalar form is sugar for `[{pattern: "**/*", effect: <v>}]`. The OpenCode adapter renders
|
|
|
+this back losslessly; the Claude adapter collapses to a `tools:`/`disallowedTools:` allowlist
|
|
|
+**and emits a warning naming each dropped glob rule**. This makes the loss *known and reported*,
|
|
|
+per the `00-INDEX.md` principle. See Open Question **Q2**.
|
|
|
+
|
|
|
+### 1.4 `permission.task` → `delegate`
|
|
|
+
|
|
|
+`permission.task` is the **delegation graph** — which subagents an agent may call.
|
|
|
+
|
|
|
+| Aspect | Detail | Class | Home |
|
|
|
+|---|---|---|---|
|
|
|
+| Delegation allowlist | `task: { contextscout: "allow" }` | 🟢 UNIVERSAL | `capabilities.delegate` |
|
|
|
+| Delegation denylist | `task: { "*": "deny" }` (contextscout) | 🟢 UNIVERSAL | `capabilities.delegate` with `"*"` rule |
|
|
|
+| Mixed id/name refs | `contextscout` vs `TestEngineer` | 🔴 AT RISK | Canonicalize to `id`; adapter re-renders. |
|
|
|
+| Claude Code equivalent | CC has no per-agent delegation allowlist; it has `disallowedTools: Task` (all-or-nothing) | 🟡 | Claude adapter: any `delegate` entry ⇒ `Task` in `tools`; a `delegate` denylist ⇒ `Task` in `disallowedTools` **+ warning** that per-target granularity was dropped. |
|
|
|
+
|
|
|
+### 1.5 Claude Code agent frontmatter (what the neutral schema must *also* feed)
|
|
|
+
|
|
|
+`plugins/claude-code/agents/code-reviewer.md` uses a **different field set** that the neutral
|
|
|
+schema must be able to produce:
|
|
|
+
|
|
|
+```yaml
|
|
|
+---
|
|
|
+name: code-reviewer
|
|
|
+description: |
|
|
|
+ Review code for security vulnerabilities, correctness, and quality. Use after implementation is complete and before committing.
|
|
|
+ Examples:
|
|
|
+ <example>
|
|
|
+ Context: coder-agent has finished implementing a new auth service.
|
|
|
+ user: "The auth service is done, can you check it?"
|
|
|
+ assistant: "I'll run the code-review skill to have code-reviewer validate it before we commit."
|
|
|
+ <commentary>Implementation is complete — code-reviewer validates before commit.</commentary>
|
|
|
+ </example>
|
|
|
+tools: Read, Glob, Grep
|
|
|
+disallowedTools: Write, Edit, Bash, Task
|
|
|
+model: sonnet
|
|
|
+---
|
|
|
+```
|
|
|
+
|
|
|
+| CC field | Neutral source | Class | Notes |
|
|
|
+|---|---|---|---|
|
|
|
+| `name` (kebab) | `id` | 🟢 | Adapter slugifies. |
|
|
|
+| `description` (multiline + `<example>` blocks) | `description` + `examples[]` | 🟢 | **`examples[]` is a first-class neutral field** — CC folds it into `description`; OpenCode drops it. Today these examples exist **only** in the CC files and would be lost if `.opencode/` is treated as the sole migration source. |
|
|
|
+| `tools` (allowlist) | `capabilities` allow-set | 🟢 | Derived. |
|
|
|
+| `disallowedTools` | `capabilities` deny-set | 🟢 | Derived. |
|
|
|
+| `model: sonnet` | `inference.model` | 🔴 **VIOLATES Locked Decision #2** | CC agents **hardcode `model: sonnet`**. Under `model: null` the build must emit **no** `model:` line. This is a deliberate behavior change — confirm with Open Question **Q3**. |
|
|
|
+
|
|
|
+> 🔴 **Preservation alert:** the `<example>` blocks in all 7 CC agents are hand-authored content
|
|
|
+> that exists **nowhere in `.opencode/`**. If `/content/` is seeded only from `.opencode/`,
|
|
|
+> **these are lost.** They must be harvested from `plugins/claude-code/agents/` into `examples[]`.
|
|
|
+
|
|
|
+### 1.6 `0-category.json` — category descriptors
|
|
|
+
|
|
|
+5 files, e.g. `.opencode/agent/core/0-category.json`:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "name": "Core Agents",
|
|
|
+ "description": "System-level agents with Open branding - the Operating System",
|
|
|
+ "icon": "⚙️",
|
|
|
+ "agents": {
|
|
|
+ "openagent": {
|
|
|
+ "description": "Universal task coordinator",
|
|
|
+ "commonSubagents": ["subagents/core/task-manager", "subagents/code/*"],
|
|
|
+ "commonTools": ["gemini", "env"],
|
|
|
+ "commonContext": ["core/essential-patterns", "core/workflows/*", "core/standards/*"]
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+| Field | What it does | Class | Home |
|
|
|
+|---|---|---|---|
|
|
|
+| `name`, `description`, `icon` | Category display metadata for install UX | 🔵 REGISTRY | `registry.json#categories[]` — **must gain `icon` + `order` + `status`**, which it lacks today. |
|
|
|
+| `order` | Display sort (only in `subagents/development`) | 🔵 REGISTRY | `registry.json#categories[].order` |
|
|
|
+| `status` | `active` (only in `subagents/development`) | 🔵 REGISTRY | `registry.json#categories[].status` |
|
|
|
+| `agents.<id>.description` | Per-agent blurb — **duplicates** the agent's own `description` | 🔴 DUPLICATE | Delete; single-source from the agent file. |
|
|
|
+| `agents.<id>.commonSubagents` | Suggested delegation targets, **supports `*` globs** | 🔴 AT RISK | Overlaps `dependencies` + `capabilities.delegate` but is **advisory, not enforced**. No consumer found. See **Q4**. |
|
|
|
+| `agents.<id>.commonTools` | Suggested tools | 🔴 AT RISK | Same — no consumer found. |
|
|
|
+| `agents.<id>.commonContext` | Suggested context, **supports `*` globs** | 🔴 AT RISK | Overlaps `context[]`. No consumer found. |
|
|
|
+
|
|
|
+> **Finding:** `0-category.json` is **read by nothing** — no reference in `install.sh`,
|
|
|
+> `registry.json`, or `scripts/`. It is *latent documentation*. Its category metadata
|
|
|
+> (`icon`/`order`/`status`) is genuinely useful and **richer than `registry.json#categories`**
|
|
|
+> (which is a flat `id: "description string"` map). Decision needed: promote or delete. See **Q4**.
|
|
|
+
|
|
|
+### 1.7 `agent-metadata.json` sidecar
|
|
|
+
|
|
|
+`.opencode/config/agent-metadata.json` — 28 entries + a `defaults` block.
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "$schema": "https://opencode.ai/schemas/agent-metadata.json",
|
|
|
+ "schema_version": "1.0.0",
|
|
|
+ "agents": { "openagent": { "id": "openagent", "name": "OpenAgent", "category": "core",
|
|
|
+ "type": "agent", "version": "1.0.0", "author": "opencode",
|
|
|
+ "tags": ["universal", "coordination", "primary"],
|
|
|
+ "dependencies": ["subagent:task-manager", "context:standards-code", ...] } },
|
|
|
+ "defaults": {
|
|
|
+ "agent": { "version": "1.0.0", "author": "opencode", "type": "agent", "tags": [] },
|
|
|
+ "subagent": { "version": "1.0.0", "author": "opencode", "type": "subagent", "tags": [] }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+| Field | What it does | Class | Home |
|
|
|
+|---|---|---|---|
|
|
|
+| `id` | Canonical id (dependency-graph key) | 🟢 UNIVERSAL | Neutral `id` — **promote into the agent's own frontmatter**. |
|
|
|
+| `name` | Display name | 🟢 UNIVERSAL | Neutral `name`. |
|
|
|
+| `category` | Grouping. **Two incompatible formats:** `"core"` (flat) vs `"subagents/core"` (path) | 🔴 AT RISK | Neutral `category`. **Must normalize** — see **Q5**. |
|
|
|
+| `type` | `agent` \| `subagent` | 🟢 UNIVERSAL | Redundant with `role`/`mode`. Collapse into `role`. |
|
|
|
+| `version` | SemVer per agent (`1.0.0`, `task-manager` is `2.0.0`) | 🔵 REGISTRY | Neutral `version`; flows to registry. |
|
|
|
+| `author` | Attribution (`opencode` for all 28) | 🔵 REGISTRY | Neutral `author`. Note: value `"opencode"` is a **tool name used as an author name** — rename to `oac`? **Q6**. |
|
|
|
+| `tags` | Search/filter | 🟢 UNIVERSAL | Neutral `tags[]`. |
|
|
|
+| `dependencies` | `subagent:x` / `context:y` edges | 🟢 UNIVERSAL | Neutral `dependencies[]`. **The crown jewel — see §7.** |
|
|
|
+| `defaults.*` | Fallbacks when an entry omits fields | 🔵 REGISTRY | Build-time defaults in the Zod schema (`.default()`). |
|
|
|
+
|
|
|
+> **The sidecar exists only because OpenCode's agent schema rejects unknown frontmatter keys.**
|
|
|
+> That is an *OpenCode adapter constraint*, not a content constraint. In `/content/`, all of this
|
|
|
+> belongs **in the agent's own frontmatter** (single file, single source). The OpenCode adapter
|
|
|
+> then **splits** it back out into `agent-metadata.json` at build time — exactly as
|
|
|
+> `00-INDEX.md` states ("Plus metadata split into `agent-metadata.json` sidecar").
|
|
|
+>
|
|
|
+> **This inverts today's authoring model** and is the single biggest ergonomic win of the refactor.
|
|
|
+
|
|
|
+### 1.8 🔴 Agents with NO metadata and NO registry entry
|
|
|
+
|
|
|
+Verified by set-difference between disk, `agent-metadata.json`, and `registry.json`:
|
|
|
+
|
|
|
+| Agent | File | In metadata? | In registry? |
|
|
|
+|---|---|---|---|
|
|
|
+| `adr-manager` | `.opencode/agent/subagents/planning/adr-manager.md` | ❌ | ❌ |
|
|
|
+| `architecture-analyzer` | `.opencode/agent/subagents/planning/architecture-analyzer.md` | ❌ | ❌ |
|
|
|
+| `contract-manager` | `.opencode/agent/subagents/planning/contract-manager.md` | ❌ | ❌ |
|
|
|
+| `prioritization-engine` | `.opencode/agent/subagents/planning/prioritization-engine.md` | ❌ | ❌ |
|
|
|
+| `story-mapper` | `.opencode/agent/subagents/planning/story-mapper.md` | ❌ | ❌ |
|
|
|
+| `stage-orchestrator` | `.opencode/agent/subagents/core/stage-orchestrator.md` | ❌ | ❌ |
|
|
|
+| `test-engineer` | `.opencode/agent/subagents/code/test-engineer.md` | ⚠️ as `tester` | ⚠️ as `tester` |
|
|
|
+| `batch-executor` | `.opencode/agent/subagents/core/batch-executor.md` | ✅ | ❌ **registry only** |
|
|
|
+
|
|
|
+**6 agents are entirely invisible to the installer** — they ship in the repo but no profile can
|
|
|
+install them. The whole `subagents/planning/` category (5 agents) plus `stage-orchestrator` are
|
|
|
+orphans, despite `.opencode/docs/agents/planning-agents-guide.md` and
|
|
|
+`.opencode/skill/project-orchestration/workflows/planning-agents.md` documenting them as a
|
|
|
+feature.
|
|
|
+
|
|
|
+**Migration decision required:** are these (a) real features to be registered, or (b) dead code
|
|
|
+to be deleted? Silently carrying them into `/content/` re-creates the mess. See **Q7**.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 2. Commands
|
|
|
+
|
|
|
+20 markdown commands under `.opencode/command/` (+9 `.yaml` eval templates counted in the "29").
|
|
|
+
|
|
|
+### 2.1 Frontmatter fields in use
|
|
|
+
|
|
|
+| Field | Occurrences | What it does | Class | Home |
|
|
|
+|---|---|---|---|---|
|
|
|
+| `description` | 18 | Command purpose; shown in the picker | 🟢 UNIVERSAL | `description` |
|
|
|
+| `tags` | 3 | Search/filter | 🟢 UNIVERSAL | `tags[]` |
|
|
|
+| `dependencies` | 3 | `subagent:` / `context:` edges | 🟢 UNIVERSAL | `dependencies[]` |
|
|
|
+| `id`,`name`,`type`,`category`,`version` | 1 | Only `analyze-patterns.md` inlines these | 🔵 REGISTRY | Neutral frontmatter (same inversion as agents). |
|
|
|
+| `mode`,`temperature`,`tools`,`permissions` | 2 | **Only in `new-agents/README.md` and `templates/agent-template.md`** | 🔵 NOT COMMANDS | These are *agent templates* misfiled under `command/`. See §2.3. |
|
|
|
+
|
|
|
+**Two commands carry no frontmatter at all** beyond `description` — the minimum viable command
|
|
|
+is literally `description:` + a markdown body.
|
|
|
+
|
|
|
+**Representative — `.opencode/command/context.md`** (block-style deps):
|
|
|
+
|
|
|
+```yaml
|
|
|
+---
|
|
|
+description: Context system manager - harvest summaries, extract knowledge, organize context
|
|
|
+tags:
|
|
|
+ - context
|
|
|
+ - knowledge-management
|
|
|
+ - harvest
|
|
|
+dependencies:
|
|
|
+ - subagent:context-organizer
|
|
|
+ - subagent:contextscout
|
|
|
+---
|
|
|
+```
|
|
|
+
|
|
|
+**Representative — `.opencode/command/add-context.md`** (flow-style tags + **path-style deps**):
|
|
|
+
|
|
|
+```yaml
|
|
|
+---
|
|
|
+description: Interactive wizard to add project patterns using Project Intelligence standard
|
|
|
+tags: [context, onboarding, project-intelligence, wizard]
|
|
|
+dependencies:
|
|
|
+ - subagent:context-organizer
|
|
|
+ - context:core/context-system/standards/mvi.md
|
|
|
+ - context:core/context-system/standards/frontmatter.md
|
|
|
+ - context:core/standards/project-intelligence.md
|
|
|
+---
|
|
|
+```
|
|
|
+
|
|
|
+> 🔴 **Critical inconsistency.** `add-context.md` uses **full-path** context refs
|
|
|
+> (`context:core/context-system/standards/mvi.md`, with `.md`), while `agent-metadata.json`
|
|
|
+> uses **short-id** refs (`context:standards-code`). Both are fed to the same
|
|
|
+> `resolve_dependencies()`. See §7.3 — this is a **live bug**, not just a style nit.
|
|
|
+
|
|
|
+### 2.2 Command body structure
|
|
|
+
|
|
|
+Bodies are **prompt templates** using a house XML-ish DSL. From `.opencode/command/context.md`:
|
|
|
+
|
|
|
+```markdown
|
|
|
+<critical_rules priority="absolute" enforcement="strict">
|
|
|
+ <rule id="mvi_strict">
|
|
|
+ Files MUST be <200 lines. Extract core concepts only ...
|
|
|
+ </rule>
|
|
|
+ <rule id="lazy_load">
|
|
|
+ ALWAYS read required context files from .opencode/context/core/context-system/ BEFORE executing operations.
|
|
|
+ </rule>
|
|
|
+</critical_rules>
|
|
|
+
|
|
|
+<execution_priority>
|
|
|
+ <tier level="1" desc="Safety & MVI"> ... </tier>
|
|
|
+ <tier level="2" desc="Core Operations"> ... </tier>
|
|
|
+</execution_priority>
|
|
|
+```
|
|
|
+
|
|
|
+| Feature | Class | Home |
|
|
|
+|---|---|---|
|
|
|
+| Markdown body as prompt | 🟢 UNIVERSAL | Neutral body (verbatim). |
|
|
|
+| `<critical_rules>` / `<rule id=… enforcement=…>` DSL | 🟢 UNIVERSAL | Body prose — **passes through untouched**. Not schema. |
|
|
|
+| `<execution_priority>` / `<tier>` DSL | 🟢 UNIVERSAL | Body prose — passes through. |
|
|
|
+| `@rule.id` cross-references (e.g. `@critical_rules.mvi_strict`) | 🟢 UNIVERSAL | Body prose. |
|
|
|
+| Hardcoded `.opencode/context/...` inside bodies | 🔴 **AT RISK** | **11 command files** embed `.opencode/` paths in prose. See §3.4. |
|
|
|
+
|
|
|
+> The body DSL is **tool-agnostic prose** — it works because LLMs read it, not because
|
|
|
+> OpenCode parses it. It needs **zero** adapter work. Good news: the highest-value content
|
|
|
+> (the actual prompt engineering) is already portable.
|
|
|
+
|
|
|
+### 2.3 🔴 Misfiled agent templates
|
|
|
+
|
|
|
+`.opencode/command/openagents/new-agents/` is **not commands**. It contains:
|
|
|
+
|
|
|
+- `templates/agent-template.md` — an *agent* scaffold with `mode`/`temperature`/`tools`/`permissions`
|
|
|
+- `templates/context-template.md` — a *context* scaffold
|
|
|
+- `templates/test-{1..8}-*.yaml` + `test-config-template.yaml` — **9 eval scenario templates**
|
|
|
+ (planning-approval, context-loading, incremental, tool-usage, error-handling,
|
|
|
+ extended-thinking, compaction, completion)
|
|
|
+- `create-agent.md`, `create-tests.md`, `README.md` — the actual commands
|
|
|
+
|
|
|
+The 8 numbered YAML tests encode **OAC's agent quality bar** (every new agent should pass these
|
|
|
+8 scenarios). This is real IP filed in the wrong place and **not in the registry**.
|
|
|
+
|
|
|
+| Item | Class | Home |
|
|
|
+|---|---|---|
|
|
|
+| `create-agent.md`, `create-tests.md` | 🟢 UNIVERSAL | `/content/commands/` |
|
|
|
+| `agent-template.md`, `context-template.md` | 🔵 BUILD | Scaffolding templates → `/packages/cli` templates (used by `oac add`). |
|
|
|
+| `test-{1..8}-*.yaml` | 🔴 AT RISK | Belongs with `/evals`. Not registered, not run by CI as far as can be seen. See **Q8**. |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 3. Context System — **DEEP DIVE** 🏆
|
|
|
+
|
|
|
+> This is OAC's crown jewel and the most at-risk asset: **300 files, 79 navigation hubs,
|
|
|
+> 191 registry entries, and a metadata convention that is not YAML frontmatter.**
|
|
|
+
|
|
|
+### 3.1 Context metadata is an HTML comment, not frontmatter
|
|
|
+
|
|
|
+Standard defined in `.opencode/context/core/context-system/standards/frontmatter.md`:
|
|
|
+
|
|
|
+```markdown
|
|
|
+<rule id="frontmatter_required" enforcement="strict">
|
|
|
+ ALL context files MUST start with:
|
|
|
+
|
|
|
+ <!-- Context: {category}/{function} | Priority: {level} | Version: X.Y | Updated: YYYY-MM-DD -->
|
|
|
+</rule>
|
|
|
+```
|
|
|
+
|
|
|
+Live example — `.opencode/context/core/standards/code-quality.md` line 1:
|
|
|
+
|
|
|
+```markdown
|
|
|
+<!-- Context: standards/code | Priority: critical | Version: 2.0 | Updated: 2025-01-21 -->
|
|
|
+```
|
|
|
+
|
|
|
+| Component | Values | What it does | Class | Home |
|
|
|
+|---|---|---|---|---|
|
|
|
+| `Context: {category}/{function}` | `standards/code`, `core/mvi`, … | Dual taxonomy: **category** = domain, **function** = file type (`concepts`/`examples`/`guides`/`lookup`/`errors`) | 🟢 UNIVERSAL | Neutral `category` + `function`. |
|
|
|
+| `Priority` | `critical` \| `high` \| `medium` \| `low` | **Load-ordering + budget signal.** Documented distribution: critical=80% of use cases, high=15%, medium=4%, low=1%. | 🟢 UNIVERSAL | Neutral `priority` — **already in the `00-INDEX.md` worked example** (`context: [{path, priority}]`). |
|
|
|
+| `Version` | `X.Y` | Change tracking | 🟢 UNIVERSAL | Neutral `version`. ⚠️ **`X.Y`, not SemVer `X.Y.Z`** — conflicts with agent `version: 1.0.0`. See **Q9**. |
|
|
|
+| `Updated` | `YYYY-MM-DD` | Staleness signal; "must match metadata section" | 🟢 UNIVERSAL | Neutral `updated`. |
|
|
|
+
|
|
|
+> **Why an HTML comment and not YAML?** Because context files are **read as prose by agents**.
|
|
|
+> A `<!-- -->` header renders invisibly in every markdown viewer while staying machine-parseable.
|
|
|
+> YAML frontmatter would display as a table or raw text in some renderers.
|
|
|
+>
|
|
|
+> **Migration risk 🔴:** a generic markdown/frontmatter parser (e.g. `gray-matter`) will find
|
|
|
+> **no frontmatter** on ~297 context files and treat `Priority`/`Version`/`Updated` as body text.
|
|
|
+> **All priority information silently vanishes**, and priority is what drives context ordering.
|
|
|
+> The neutral parser **must** implement a dedicated HTML-comment reader. This is the single
|
|
|
+> most likely way the refactor silently destroys the crown jewel. See **Q10**.
|
|
|
+
|
|
|
+**Compliance is not universal.** The frontmatter-key census over non-navigation context files
|
|
|
+shows only ~16 files with a `description:` key and a long tail of *false positives* — lines like
|
|
|
+`Agent:`, `User:`, `Voice:`, `--text-muted:`, `curl:` matched as "frontmatter keys" because they
|
|
|
+are **body content** (dialogue transcripts, CSS variables, code samples). Real finding:
|
|
|
+**most context files carry only the HTML-comment header**, and a handful (`.opencode/context/tasks/`,
|
|
|
+some `openagents-repo/` files) additionally use YAML frontmatter with `id`/`type`/`category`/`model`/`tools`.
|
|
|
+**Two metadata conventions coexist in one tree.** See **Q10**.
|
|
|
+
|
|
|
+### 3.2 `navigation.md` — the discovery backbone
|
|
|
+
|
|
|
+**79 `navigation.md` files** — one per directory, at every level. This is a **hand-maintained
|
|
|
+routing tree**, not an index generated from the filesystem.
|
|
|
+
|
|
|
+Root — `.opencode/context/navigation.md`:
|
|
|
+
|
|
|
+```markdown
|
|
|
+<!-- Context: core/navigation | Priority: critical | Version: 1.0 | Updated: 2026-02-15 -->
|
|
|
+# Context Navigation
|
|
|
+
|
|
|
+**New here?** → `openagents-repo/quick-start.md`
|
|
|
+
|
|
|
+## Structure
|
|
|
+.opencode/context/
|
|
|
+├── core/ # Universal standards & workflows
|
|
|
+├── openagents-repo/ # OpenAgents Control repository work
|
|
|
+...
|
|
|
+
|
|
|
+## Quick Routes
|
|
|
+| Task | Path |
|
|
|
+|------|------|
|
|
|
+| **Write code** | `core/standards/code-quality.md` |
|
|
|
+| **Review code** | `core/workflows/code-review.md` |
|
|
|
+| **Delegate task** | `core/workflows/task-delegation-basics.md` |
|
|
|
+```
|
|
|
+
|
|
|
+| Feature | What it does | Class | Home |
|
|
|
+|---|---|---|---|
|
|
|
+| Per-directory `navigation.md` | Human+agent routing hub | 🟢 UNIVERSAL | Neutral content, verbatim. |
|
|
|
+| **Task→path "Quick Routes" table** | **Intent-based routing** — the actual discovery mechanism | 🟢 UNIVERSAL | Verbatim. This is *the* feature. |
|
|
|
+| Registry id `root-navigation` | Makes the root hub installable | 🔵 REGISTRY | Registry entry. |
|
|
|
+| Directory-tree ASCII diagram | Orientation | 🔴 AT RISK | **Hardcodes `.opencode/context/`** — wrong after any rename. |
|
|
|
+| Relative path links (`core/navigation.md`) | Chain traversal | 🟢 UNIVERSAL | Portable **because relative**. |
|
|
|
+
|
|
|
+> **Design insight worth preserving explicitly:** navigation uses **relative** links between
|
|
|
+> hubs (`core/navigation.md`) but the *root* hub hardcodes the absolute tree
|
|
|
+> (`.opencode/context/`). So the **chain is portable; only the entry point is not.** The adapter
|
|
|
+> only needs to rewrite the root, not all 79. This is a much smaller job than it first appears —
|
|
|
+> and worth stating so nobody "fixes" all 79 files.
|
|
|
+
|
|
|
+### 3.3 Context discovery / loading — the runtime chain
|
|
|
+
|
|
|
+Two *different* discovery systems exist today.
|
|
|
+
|
|
|
+**(a) OpenCode: `paths.json` + `@`-reference.** `.opencode/context/core/config/paths.json`:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "description": "Additional context file paths - agents load this via @ reference for dynamic pathing",
|
|
|
+ "paths": { "local": ".opencode/context", "global": "~/.config/opencode/context" }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+| Feature | Class | Home |
|
|
|
+|---|---|---|
|
|
|
+| local + global context roots | 🟢 UNIVERSAL | Neutral config; adapter rewrites values per tool. |
|
|
|
+| Registry id `context-paths-config` | 🔵 REGISTRY | Registry entry — **the only non-`.md` context component** (fixed by PR #252 per git log; the `expand_context_wildcard` `sub("\\.md$";"")` strips `.md`, so a `.json` context is a special case). |
|
|
|
+| `@`-reference loading | 🟡 OPENCODE-SPECIFIC | OpenCode's `@file` syntax. Claude uses the session-start hook instead (§9.2). |
|
|
|
+
|
|
|
+**(b) Claude Code: `.oac.json` + a documented protocol.**
|
|
|
+`plugins/claude-code/skills/context-discovery/context-discovery-protocol.md`:
|
|
|
+
|
|
|
+```
|
|
|
+.oac.json exists? YES → read context.root → done (fast path)
|
|
|
+ NO → run discovery chain
|
|
|
+ Found? YES → signal main agent to write .oac.json (if project-local)
|
|
|
+ NO → return setup tips
|
|
|
+```
|
|
|
+
|
|
|
+```json
|
|
|
+{ "version": "1", "context": { "root": ".claude/context" } }
|
|
|
+```
|
|
|
+
|
|
|
+| Feature | What it does | Class | Home |
|
|
|
+|---|---|---|---|
|
|
|
+| `.oac.json` fast path | Cache the resolved context root | 🟢 UNIVERSAL | **Should be the neutral, cross-tool mechanism.** |
|
|
|
+| Discovery chain fallback | Find context root heuristically | 🟢 UNIVERSAL | Neutral. |
|
|
|
+| `navigation.md` presence = validity check | "if `context.root` has no `navigation.md`, warn and fall through" | 🟢 UNIVERSAL | Neutral. Ties (a) and (b) together. |
|
|
|
+| Self-healing (write `.oac.json` on discovery) | Fast path next session | 🟢 UNIVERSAL | Neutral. |
|
|
|
+| "Single source of truth for all context root discovery" | Referenced by `context-scout` agent, `context-discovery` skill | 🟢 UNIVERSAL | Neutral doc. |
|
|
|
+
|
|
|
+> 🔴 **These two systems are unaware of each other.** `paths.json` says the root is
|
|
|
+> `.opencode/context`; `.oac.json` says `.claude/context`. There is no shared abstraction.
|
|
|
+> The refactor should **unify on the `.oac.json` protocol** (it is strictly better: fast path,
|
|
|
+> fallback chain, validity check, self-healing) and have `paths.json` become an
|
|
|
+> OpenCode-adapter-generated artifact. **The CC protocol is the more mature design and must not
|
|
|
+> be discarded just because it lives in the "drifted" plugin.** See **Q11**.
|
|
|
+
|
|
|
+### 3.4 🔴 Hardcoded `.opencode/` paths in content bodies — the migration's biggest mechanical risk
|
|
|
+
|
|
|
+Counted by `grep -rl '\.opencode/'`:
|
|
|
+
|
|
|
+| Area | Files containing `.opencode/` in body | Worst offenders |
|
|
|
+|---|---|---|
|
|
|
+| Agents | **31 / 34** | `openagent.md` (31 refs), `task-manager.md` (23), `context-retriever.md` (23), `repo-manager.md` (19) |
|
|
|
+| Context docs | **73** | across the tree |
|
|
|
+| Skills | **14** | routers + SKILL.md |
|
|
|
+| Commands | **11** | `context.md` et al. |
|
|
|
+| **Total** | **~129 files** | |
|
|
|
+
|
|
|
+Example — `.opencode/agent/core/openagent.md`:
|
|
|
+
|
|
|
+```
|
|
|
+- Code tasks → .opencode/context/core/standards/code-quality.md
|
|
|
+- Docs tasks → .opencode/context/core/standards/documentation.md
|
|
|
+...
|
|
|
+- code (write/edit code) → Read .opencode/context/core/standards/code-quality.md NOW
|
|
|
+```
|
|
|
+
|
|
|
+**Why this matters:** `00-INDEX.md` says bodies are "authored once" in `/content/`. But a body
|
|
|
+containing `.opencode/context/...` is **not neutral** — it instructs the agent to read a path
|
|
|
+that only exists in the OpenCode build output. On the Claude target, context lives at
|
|
|
+`.claude/context/`, so **every one of those instructions points at a non-existent file.**
|
|
|
+
|
|
|
+This is almost certainly *already broken* in `plugins/claude-code/` today and is a strong
|
|
|
+candidate for why the CC plugin was hand-rewritten rather than generated.
|
|
|
+
|
|
|
+| Option | Approach | Trade-off |
|
|
|
+|---|---|---|
|
|
|
+| **A. Token substitution** | Author `{{CONTEXT_ROOT}}/core/standards/code-quality.md`; adapters substitute. | Explicit, greppable, verifiable. Requires touching ~129 files once. |
|
|
|
+| **B. Adapter rewrite** | Adapters regex-replace `.opencode/context/` → target root. | Zero content churn; brittle, silent when it misses a variant. |
|
|
|
+| **C. Runtime indirection** | Bodies reference *ids* (`context:standards-code`); agent resolves via the discovery protocol. | Cleanest, most portable; largest rewrite; adds runtime lookup. |
|
|
|
+
|
|
|
+**Recommendation:** **A** for paths + **C** long-term for dependencies. A is mechanical,
|
|
|
+one-time, and testable with a lint rule (`no raw .opencode/ in /content/`). See **Q12**.
|
|
|
+
|
|
|
+### 3.5 🔴 Context registry coverage gaps
|
|
|
+
|
|
|
+Computed by set-difference between disk and `registry.json#components.contexts`:
|
|
|
+
|
|
|
+| Metric | Count |
|
|
|
+|---|---|
|
|
|
+| Context files on disk | **300** |
|
|
|
+| Registry context entries | **191** (188 unique paths) |
|
|
|
+| On disk but **NOT** in registry | **112** |
|
|
|
+| In registry but **NOT** on disk (broken) | **0** ✅ |
|
|
|
+| `navigation.md` on disk | **79** |
|
|
|
+| `navigation.md` in registry | **36** |
|
|
|
+
|
|
|
+**43 of 79 navigation hubs are unregistered** ⇒ installing a context subtree can produce a
|
|
|
+directory whose `navigation.md` was never installed ⇒ **the discovery chain dead-ends**, and the
|
|
|
+`.oac.json` protocol's "no `navigation.md` ⇒ invalid root" check then rejects a root that *is*
|
|
|
+correct. This is a **silent, in-the-field breakage of the crown jewel**.
|
|
|
+
|
|
|
+Unregistered examples: `.opencode/context/CODEBASE_STANDARDS.md`,
|
|
|
+`.opencode/context/content-creation/**/navigation.md` (all 5),
|
|
|
+`.opencode/context/core/context-system/{examples,guides,operations,standards}/navigation.md`,
|
|
|
+`.opencode/context/core/context-system/standards/typescript-coding.md`.
|
|
|
+
|
|
|
+**Migration requirement:** the build must **generate** registry context entries from disk, not
|
|
|
+hand-maintain them. A `navigation.md` must be **auto-included** whenever any file in its
|
|
|
+directory is installed (a structural dependency, not a declared one). See **Q13**.
|
|
|
+
|
|
|
+### 3.6 🔴 Registry context duplicates (live bugs)
|
|
|
+
|
|
|
+**Three files have two ids each** (alias-by-duplication instead of the `aliases[]` field):
|
|
|
+
|
|
|
+| Path | ids |
|
|
|
+|---|---|
|
|
|
+| `core/standards/code-quality.md` | `standards-code` **and** `code-quality` |
|
|
|
+| `core/standards/test-coverage.md` | `standards-tests` **and** `test-coverage` |
|
|
|
+| `core/standards/documentation.md` | `standards-docs` **and** `documentation` |
|
|
|
+
|
|
|
+⇒ `resolve_dependencies` can add **both** ids for the same file, and `install.sh` will copy it
|
|
|
+twice. Meanwhile a proper `aliases[]` field **does exist** and is used by exactly 3 entries
|
|
|
+(`feature-breakdown → workflows-task-breakdown`, `session-management → workflows-sessions`,
|
|
|
+`component-planning → workflows-component-planning`). **Two mechanisms for one concept.**
|
|
|
+
|
|
|
+**Three duplicate ids** also exist within `components.contexts`: **`agents`**, **`ui-navigation`**,
|
|
|
+**`context-bundle-template`**. Since `resolve_dependencies` matches with
|
|
|
+`select(.id == "…")` and jq returns **all** matches, a dependency on any of these emits
|
|
|
+**multiple paths** — nondeterministic install behavior.
|
|
|
+
|
|
|
+**Requirement:** neutral schema enforces **unique `id`**, aliases go in `aliases[]` only, and the
|
|
|
+build **fails** on duplicates. This is a test the minimal-test-first slice should include.
|
|
|
+
|
|
|
+### 3.7 Context sub-features worth naming explicitly
|
|
|
+
|
|
|
+| Feature | Where | Class | Home |
|
|
|
+|---|---|---|---|
|
|
|
+| **MVI principle** | `core/context-system/standards/mvi.md` | 🟢 UNIVERSAL | Neutral content. Formula: Core Concept (1-3 sentences) → Key Points (3-5 bullets) → Quick Example (5-10 lines) → Reference Link → Related Files. "Scannable in <30 seconds." |
|
|
|
+| **<200-line rule** | enforced in `command/context.md` `<rule id="mvi_strict">` | 🟢 UNIVERSAL | Neutral + **lintable**. Candidate `oac doctor` check. |
|
|
|
+| **Function-based structure** | `concepts/ examples/ guides/ lookup/ errors/` | 🟢 UNIVERSAL | Neutral convention; visible across `mastra-ai/`, `openagents-repo/`, `ui/web/design/`. |
|
|
|
+| Structure/templates/codebase-reference standards | `core/context-system/standards/{structure,templates,codebase-references}.md` | 🟢 UNIVERSAL | Neutral. |
|
|
|
+| Context **operations** | `core/context-system/operations/{harvest,extract,organize,update,migrate,error}.md` | 🟢 UNIVERSAL | Neutral. The verbs behind `/context`. |
|
|
|
+| Context **guides** | `.../guides/{compact,creation,organizing-context,workflows,navigation-design-basics,navigation-templates}.md` | 🟢 UNIVERSAL | Neutral. |
|
|
|
+| Context-system **CHANGELOG** | `core/context-system/CHANGELOG.md` | 🟢 UNIVERSAL | Neutral. |
|
|
|
+| Task JSON schemas | `context/tasks/schemas/{task,subtask}-schema.json` | 🟢 UNIVERSAL | Neutral — **non-`.md` context**, same special case as `paths.json`. |
|
|
|
+| `index.md` (root) | `.opencode/context/index.md` | 🟢 UNIVERSAL | Neutral. Note: **`index.md` AND `navigation.md` both at root** — overlapping entry points. **Q14**. |
|
|
|
+| Project Intelligence standard | `core/standards/project-intelligence.md`, `context/project-intelligence/` | 🟢 UNIVERSAL | Neutral. Driven by `/add-context`. |
|
|
|
+| `CONTEXT_SYSTEM_GUIDE.md` (16KB, repo root) | root | 🟢 UNIVERSAL | **Outside `.opencode/`** — easily missed by a `.opencode/`-only migration. |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 4. Skills
|
|
|
+
|
|
|
+### 4.1 Format
|
|
|
+
|
|
|
+A skill = `SKILL.md` (frontmatter + body) + optional `router.sh` + `scripts/` + `workflows/` + `tests/`.
|
|
|
+
|
|
|
+```yaml
|
|
|
+---
|
|
|
+name: task-management
|
|
|
+description: Task management CLI for tracking and managing feature subtasks with status, dependencies, and validation
|
|
|
+version: 1.0.0
|
|
|
+author: opencode
|
|
|
+type: skill
|
|
|
+category: development
|
|
|
+tags: [tasks, management, tracking, dependencies, cli]
|
|
|
+---
|
|
|
+```
|
|
|
+
|
|
|
+| Field | Class | Home |
|
|
|
+|---|---|---|
|
|
|
+| `name` | 🟢 UNIVERSAL | `id`/`name`. **Already kebab-case in both OpenCode and CC** — skills need no slugify transform. |
|
|
|
+| `description` | 🟢 UNIVERSAL | `description`. **Load-bearing at runtime:** CC's `session-start.sh` greps `^description:` to build the skill catalogue. |
|
|
|
+| `version`, `author`, `type`, `category`, `tags` | 🔵 REGISTRY | Neutral frontmatter → registry. **Skills already inline their metadata** — no sidecar. **This is the model agents should follow** (§1.7). |
|
|
|
+| `router.sh` | 🟡 | Bash entrypoint; adapter must preserve the executable bit + `files[]`. |
|
|
|
+| `scripts/*.ts` | 🟡 | Bun/TS runtime. See §4.4. |
|
|
|
+| `workflows/*.md` | 🟢 UNIVERSAL | Prose. |
|
|
|
+| `tests/*.test.ts` | 🔵 BUILD | Should move to `/evals` or a package test dir. |
|
|
|
+
|
|
|
+> **Skills are the most portable content type in the repo**: kebab ids, self-contained metadata,
|
|
|
+> `SKILL.md` convention identical across OpenCode and Claude Code. The skill adapter is mostly
|
|
|
+> `cp` + `files[]` bookkeeping.
|
|
|
+
|
|
|
+### 4.2 Multi-file skills need `files[]`
|
|
|
+
|
|
|
+Skills are the **only** component type using the registry `files[]` field:
|
|
|
+
|
|
|
+```json
|
|
|
+{ "id": "task-management", "path": ".opencode/skills/task-management/SKILL.md",
|
|
|
+ "files": [".opencode/skills/task-management/SKILL.md",
|
|
|
+ ".opencode/skills/task-management/router.sh",
|
|
|
+ ".opencode/skills/task-management/scripts/task-cli.ts"] }
|
|
|
+```
|
|
|
+
|
|
|
+| Registry `files[]` count | Actual disk files | |
|
|
|
+|---|---|---|
|
|
|
+| `task-management` | 3 | 3 ✅ |
|
|
|
+| `context-manager` | 2 | 2 ✅ |
|
|
|
+| `context7` | 4 | 4 ✅ |
|
|
|
+| `smart-router-skill` | 6 | 6 ✅ |
|
|
|
+
|
|
|
+Hand-maintained but currently **accurate**. Should be **generated** (glob the skill dir) so it
|
|
|
+cannot drift. 🔵 BUILD.
|
|
|
+
|
|
|
+### 4.3 🔴 `skill/` vs `skills/` — an orphaned directory
|
|
|
+
|
|
|
+**Two sibling directories exist.** The registry only knows `.opencode/skills/` (plural).
|
|
|
+
|
|
|
+| Path | In registry? | Contents |
|
|
|
+|---|---|---|
|
|
|
+| `.opencode/skills/` (plural) | ✅ 4 skills | task-management, context-manager, context7, smart-router-skill |
|
|
|
+| `.opencode/skill/project-orchestration/` | ❌ **orphan** | `SKILL.md`, `router.sh`, 3 scripts (`context-index.ts`, `session-context-manager.ts`, `stage-cli.ts`), 3 workflows (`8-stage-delivery.md`, `context-handoff.md`, `planning-agents.md`) |
|
|
|
+| `.opencode/skill/task-management/tests/` | ❌ **orphan** | `enhanced-schema.test.ts`, `line-number-validation.test.ts` — tests **split from** the skill in `skills/` |
|
|
|
+
|
|
|
+`project-orchestration` is a **fully-built, uninstallable skill** — with an 8-stage delivery
|
|
|
+workflow and a stage CLI. It pairs with the 6 unregistered planning agents (§1.8): the
|
|
|
+`planning-agents.md` workflow references exactly the `subagents/planning/` agents that have no
|
|
|
+registry entry. **An entire orchestration feature is dark.**
|
|
|
+
|
|
|
+Likewise `.opencode/skill/task-management/tests/` are the tests for
|
|
|
+`.opencode/skills/task-management/` — the same skill, split across two directory names.
|
|
|
+
|
|
|
+**Decision required:** ship `project-orchestration` + planning agents as a feature, or delete
|
|
|
+both. They are coupled — decide together. See **Q7**.
|
|
|
+
|
|
|
+### 4.4 🔴 Runtime dependency: Bun/TypeScript
|
|
|
+
|
|
|
+`.opencode/skills/task-management/scripts/task-cli.ts`, `.opencode/scripts/task-cli.ts`,
|
|
|
+`.opencode/skill/project-orchestration/scripts/*.ts`, and every `router.sh` shell out to a
|
|
|
+TypeScript runtime. `.opencode/{package.json,bun.lock,node_modules}` and
|
|
|
+`.opencode/tool/{package.json,tsconfig.json,bun.lock}` confirm **Bun**.
|
|
|
+
|
|
|
+For npm distribution (`04-cli-build-distribution.md`), this is a real constraint: an installed
|
|
|
+OAC skill requires Bun on the user's machine. Cross-platform (Windows) `router.sh` is a further
|
|
|
+problem. Flagging for Agent D. See **Q15**.
|
|
|
+
|
|
|
+### 4.5 🔴 CC has 12 skills; OpenCode has 4
|
|
|
+
|
|
|
+`plugins/claude-code/skills/`: `code-execution`, `code-review`, `context-discovery`,
|
|
|
+`context-setup`, `debugger`, `external-research`, `oac-approach`, `parallel-execution`,
|
|
|
+`task-breakdown`, `test-generation`, `using-oac`, `verification-before-completion`.
|
|
|
+
|
|
|
+**Only `context-manager`/`context7`/`task-management`/`smart-router-skill` exist on the OpenCode
|
|
|
+side, and none of those 4 names appear in CC.** The two skill sets are **disjoint**.
|
|
|
+
|
|
|
+These 12 CC skills are the **primary UX of the shipped plugin** (they are what the
|
|
|
+`session-start.sh` catalogue advertises, and what this very repo's tooling exposes as
|
|
|
+`oac:code-review`, `oac:task-breakdown`, …). They are **not derivable from `.opencode/`**.
|
|
|
+
|
|
|
+🔴 **If `/content/` is seeded only from `.opencode/`, all 12 are lost.** They must be harvested
|
|
|
+from `plugins/claude-code/skills/` — and arguably they, not the OpenCode 4, are the better
|
|
|
+starting point. See **Q16**.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 5. Tools
|
|
|
+
|
|
|
+`.opencode/tool/` — TypeScript modules.
|
|
|
+
|
|
|
+| Item | Path | Registry | Class | Home |
|
|
|
+|---|---|---|---|---|
|
|
|
+| `env` | `.opencode/tool/env/index.ts` | ✅ `tool:env` | 🟡 | Loads `.env` from a search-path list (`./.env`, `../.env`, `../../.env`, `../plugin/.env`, …). Exports `loadEnvVariables(config)`. |
|
|
|
+| `gemini` | `.opencode/tool/gemini/index.ts` | ✅ `tool:gemini`, `dependencies: ["tool:env"]` | 🟡 | Image gen/edit/analysis. **The only tool→tool dependency in the registry.** |
|
|
|
+| `template` | `.opencode/tool/template/index.ts` + `README.md` | ❌ | 🔵 BUILD | Scaffold for new tools → CLI template. |
|
|
|
+| `index.ts` | `.opencode/tool/index.ts` | ❌ | 🟡 | Barrel export. |
|
|
|
+| `.opencode/tool/.env` | — | 🔴 **SECURITY** | A committed `.env` inside the tool dir. **Must not be copied into `/content/`.** See **Q17**. |
|
|
|
+| `package.json`/`tsconfig.json`/`bun.lock` | — | 🔵 BUILD | Tool workspace config. |
|
|
|
+
|
|
|
+**Class overall: 🟡 OPENCODE-SPECIFIC.** Tools implement the OpenCode plugin/tool API. Claude
|
|
|
+Code has no equivalent user-defined "tool" primitive (its analogue is an MCP server). The tool
|
|
|
+adapter is either (a) OpenCode-only with a "not supported" warning for other targets, or
|
|
|
+(b) tools get re-expressed as MCP servers. Big scope call — see **Q18**.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 6. Plugins & Hooks
|
|
|
+
|
|
|
+Two directories again (`plugin/` singular, `plugins/` plural).
|
|
|
+
|
|
|
+| Item | Path | Registry | Class | Notes |
|
|
|
+|---|---|---|---|---|
|
|
|
+| `notify` | `.opencode/plugin/notify.ts` | ✅ `plugin:notify` | 🟡 | Hooks OpenCode's `event` with `session.idle` → `say "Your code is done!"`. **Ships disabled** (`const ENABLED = false`). |
|
|
|
+| `agent-validator` | `.opencode/plugin/agent-validator.ts` | ❌ | 🔴 | **Also present as `agent-validator.ts.disabled`** — two copies, neither registered. Has `docs/VALIDATOR_GUIDE.md` + `tests/validator/{test-validation.sh,test-validator.sh,interactive.md}`. |
|
|
|
+| `coder-verification` | `.opencode/plugins/coder-verification/` | ❌ | 🔴 | Own `plugin.json` (name/description/version/author), `index.ts`, `README.md`, `IMPLEMENTATION_SUMMARY.md`. "Reminds about checks and auto-completes tasks" for CoderAgent. **Unregistered.** |
|
|
|
+| `.opencode/plugin/.env` | — | 🔴 **SECURITY** | Second committed `.env`. See **Q17**. |
|
|
|
+
|
|
|
+**Findings:**
|
|
|
+- **Hooks exist only as plugins in OpenCode** — there is no `hooks:` frontmatter field anywhere
|
|
|
+ (§1.1 confirmed 0 occurrences). OpenCode hooks = a plugin exporting an `event` handler.
|
|
|
+ Claude Code hooks = declarative `hooks.json` (§9.2). **These models are fundamentally different**
|
|
|
+ (imperative TS callback vs declarative JSON→shell command).
|
|
|
+- `plugin.json` (in `plugins/coder-verification/`) has **the same shape** as
|
|
|
+ `plugins/claude-code/.claude-plugin/plugin.json` — name/description/version/author. A neutral
|
|
|
+ plugin-manifest schema could cover both.
|
|
|
+- The registry knows about **1 of 3** plugins.
|
|
|
+
|
|
|
+**Class: 🟡 OPENCODE-SPECIFIC**, and the **hook model is 🔴 AT RISK** — there is no neutral
|
|
|
+abstraction that covers both an OpenCode TS `event` callback and a CC `SessionStart` shell hook.
|
|
|
+Agent C must decide whether `hooks` is a neutral content type at all, or purely per-adapter.
|
|
|
+See **Q19**.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 7. Dependency Resolution — **DEEP DIVE** 🏆
|
|
|
+
|
|
|
+> The second crown jewel. This is what makes `oac add code-reviewer` pull in the right context
|
|
|
+> and subagents. It drives installation.
|
|
|
+
|
|
|
+### 7.1 The reference grammar
|
|
|
+
|
|
|
+Dependencies are strings of the form `<type>:<id>`:
|
|
|
+
|
|
|
+```
|
|
|
+subagent:contextscout
|
|
|
+context:standards-code
|
|
|
+tool:env
|
|
|
+context:core/* ← wildcard
|
|
|
+context:core/context-system/standards/mvi.md ← full path with extension
|
|
|
+```
|
|
|
+
|
|
|
+Declared in **three** places:
|
|
|
+1. `registry.json#components.<type>[].dependencies[]` — **what `install.sh` actually reads**
|
|
|
+2. `.opencode/config/agent-metadata.json#agents.<id>.dependencies[]` — parallel copy
|
|
|
+3. Command frontmatter `dependencies:` — e.g. `add-context.md`, `context.md`
|
|
|
+
|
|
|
+### 7.2 The algorithm (`install.sh:420-481`)
|
|
|
+
|
|
|
+```bash
|
|
|
+resolve_dependencies() {
|
|
|
+ local component=$1
|
|
|
+ local type="${component%%:*}" # left of first ':'
|
|
|
+ local id="${component##*:}" # right of last ':'
|
|
|
+ registry_key=$(get_registry_key "$type") # singular → plural
|
|
|
+
|
|
|
+ deps=$(jq_exec ".components.${registry_key}[] \
|
|
|
+ | select(.id == \"${id}\" or (.aliases // [] | index(\"${id}\"))) \
|
|
|
+ | .dependencies[]?" "$TEMP_DIR/registry.json")
|
|
|
+
|
|
|
+ for dep in $deps; do
|
|
|
+ if [[ "$dep" == *"*"* ]] && [ "$dep_type" = "context" ]; then
|
|
|
+ matched=$(expand_context_wildcard "$dep_id")
|
|
|
+ # add each match if not already selected, then recurse
|
|
|
+ fi
|
|
|
+ # add dep if not already in SELECTED_COMPONENTS, then recurse
|
|
|
+ done
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+| Property | Behavior | Class |
|
|
|
+|---|---|---|
|
|
|
+| **Recursive transitive closure** | Yes — recurses into each newly added dep | 🟢 UNIVERSAL |
|
|
|
+| **Cycle safety** | **Implicit** — recursion only fires when the dep was *not* already in `SELECTED_COMPONENTS`, so a cycle terminates. Never *detected* or reported. | 🟡 Fragile |
|
|
|
+| **Dedupe** | Linear scan of `SELECTED_COMPONENTS` before add (O(n²), fine at this scale) | 🔵 BUILD |
|
|
|
+| **Alias resolution** | `.id == id or (.aliases // []) | index(id)` | 🟢 UNIVERSAL |
|
|
|
+| **Wildcard expansion** | **`context:` only**; `expand_selected_components` prints `"Wildcard only supported for context components"` otherwise | 🟢 UNIVERSAL |
|
|
|
+| **Missing dep handling** | `jq … || echo ""` ⇒ an **unknown id resolves to zero deps, silently**. No "unknown component" error. | 🔴 **AT RISK** |
|
|
|
+| **Type↔registry-key mapping** | `get_registry_key()`: `agent→agents`, `context→contexts`, `skill→skills`, `config→config` (special: stays singular), `*s→as-is`, default `+s` | 🟡 |
|
|
|
+| **Install path mapping** | `get_install_path()`: strips `.opencode/` prefix, prepends `$INSTALL_DIR` | 🟡 → adapter |
|
|
|
+
|
|
|
+**Wildcard expansion (`install.sh:361-371`):**
|
|
|
+
|
|
|
+```bash
|
|
|
+expand_context_wildcard() {
|
|
|
+ prefix="${pattern%%\**}"; prefix="${prefix%/}"; [ -n "$prefix" ] && prefix="${prefix}/"
|
|
|
+ jq_exec ".components.contexts[]? | select(.path | startswith(\".opencode/context/${prefix}\"))
|
|
|
+ | .path | sub(\"^\\\\.opencode/context/\"; \"\") | sub(\"\\\\.md$\"; \"\")"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+| Detail | Consequence |
|
|
|
+|---|---|
|
|
|
+| `*` is a **prefix match**, not a glob | `core/*` matches `core/**` recursively too. `ui/web/a*` would match anything starting `ui/web/a`. **Not real glob semantics.** |
|
|
|
+| `sub("\\.md$"; "")` strips the extension | A **non-`.md` context** (`paths.json`, `tasks/schemas/*.json`) survives wildcard expansion **with its extension intact**, producing id `core/config/paths.json` — which then must match a registry `id`. This is exactly the class of bug PR #252 ("resolve non-.md context paths like paths.json") fixed. 🔴 |
|
|
|
+| Matches on **`path`**, emits a **path-derived id** | So wildcards produce **path-style** ids while hand-written deps use **short-style** ids. Two id namespaces in one list. 🔴 |
|
|
|
+
|
|
|
+### 7.3 🔴 The dual-namespace bug
|
|
|
+
|
|
|
+`resolve_dependencies` matches **`.id`**, but wildcards and some hand-written deps supply
|
|
|
+**paths**:
|
|
|
+
|
|
|
+| Reference | Form | Resolves? |
|
|
|
+|---|---|---|
|
|
|
+| `context:standards-code` | short id | ✅ matches `.id == "standards-code"` |
|
|
|
+| `context:core/*` | wildcard → `core/standards/code-quality` … | ⚠️ produces **path-style** strings; the *next* recursion looks for `.id == "core/standards/code-quality"` — **no such id** ⇒ **its dependencies are silently skipped** |
|
|
|
+| `context:core/context-system/standards/mvi.md` (`add-context.md`) | full path **with `.md`** | ❌ **no registry entry has that as `.id`** ⇒ **silently resolves to nothing** |
|
|
|
+
|
|
|
+So `/add-context`'s three declared context dependencies — the MVI standard, the frontmatter
|
|
|
+standard, and the project-intelligence standard, i.e. **exactly the docs the command tells the
|
|
|
+agent to follow** — **almost certainly do not install today.** Because `jq` failure is swallowed
|
|
|
+by `|| echo ""`, there is no error.
|
|
|
+
|
|
|
+**Requirement for the neutral schema:** ONE reference form. Recommend canonical **`<type>:<id>`
|
|
|
+with unique ids**, plus `aliases[]`, plus a build-time validation pass that **fails** on an
|
|
|
+unresolvable reference. The "silently resolves to nothing" behavior is the single most dangerous
|
|
|
+property of the current system and the easiest thing to lose *and not notice* during migration.
|
|
|
+See **Q20**.
|
|
|
+
|
|
|
+### 7.4 Structural (undeclared) dependencies
|
|
|
+
|
|
|
+Not expressible today; must be **inferred** by the build:
|
|
|
+
|
|
|
+| Implicit dependency | Why | Today |
|
|
|
+|---|---|---|
|
|
|
+| context file → its dir's `navigation.md` | Discovery chain dead-ends without it | ❌ **not declared** — 43 hubs unregistered (§3.5) |
|
|
|
+| context file → parent `navigation.md` … → root `navigation.md` | Chain traversal from the root | ❌ not declared |
|
|
|
+| agent → `agent-metadata.json` | The sidecar carries its metadata | ⚠️ `config:agent-metadata` in some profiles |
|
|
|
+| skill → `files[]` | Multi-file skills | ✅ via `files[]` |
|
|
|
+| agent → `context-paths-config` | `@`-reference loading | ⚠️ only in `.opencode/profiles/*/profile.json`, **not** in `registry.json#profiles` (§8.2) |
|
|
|
+| tool `gemini` → `tool:env` | Reads API key | ✅ declared |
|
|
|
+| CC agent → its plugin skills | `code-reviewer` says "I'll run the code-review skill" | ❌ not declared |
|
|
|
+
|
|
|
+**Requirement:** the build **auto-includes the navigation chain** for every installed context
|
|
|
+file. This is a structural rule, not a declared edge.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 8. Registry (`registry.json`, 107KB) — **the installation driver**
|
|
|
+
|
|
|
+### 8.1 Schema
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "version": "2.0.0",
|
|
|
+ "schema_version": "2.0.0",
|
|
|
+ "repository": "https://github.com/darrenhinde/OpenAgentsControl",
|
|
|
+ "categories": { "essential": "…", "standard": "…", "extended": "…",
|
|
|
+ "specialized": "…", "meta": "…" },
|
|
|
+ "components": { "agents": [], "subagents": [], "commands": [], "tools": [],
|
|
|
+ "plugins": [], "skills": [], "contexts": [], "config": [] },
|
|
|
+ "profiles": { "essential": {}, "developer": {}, "business": {}, "full": {}, "advanced": {} },
|
|
|
+ "metadata": { "lastUpdated": "2026-03-21", "schemaVersion": "1.0.0" },
|
|
|
+ "subagents": { "test": { "simple-responder": { … } } }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Component entry — union of all keys observed across all 8 types:**
|
|
|
+`id`, `name`, `type`, `path`, `description`, `tags[]`, `dependencies[]`, `category`,
|
|
|
+`aliases[]` (3 contexts), `files[]` (4 skills), `version` (rare).
|
|
|
+
|
|
|
+| Field | What it does | Class | Home |
|
|
|
+|---|---|---|---|
|
|
|
+| `id` | Dependency-graph key | 🟢 UNIVERSAL | Neutral `id`. **Must be unique — 3 dupes today (§3.6).** |
|
|
|
+| `name` | Display name | 🟢 UNIVERSAL | Neutral `name`. |
|
|
|
+| `type` | Component type | 🔵 REGISTRY | Derived from `/content/` subdir. |
|
|
|
+| `path` | **Source** path (`.opencode/agent/...`) | 🔵 REGISTRY | **Becomes `/content/...`; per-target output path is adapter-computed.** This field is the load-bearing OpenCode assumption in the registry. |
|
|
|
+| `description` | Install-UI text | 🟢 UNIVERSAL | Neutral `description`. |
|
|
|
+| `tags[]` | Filter/search | 🟢 UNIVERSAL | Neutral `tags[]`. |
|
|
|
+| `dependencies[]` | Resolution graph | 🟢 UNIVERSAL | Neutral `dependencies[]`. |
|
|
|
+| `category` | `essential`\|`standard`\|`extended`\|`specialized`\|`meta` | 🔵 REGISTRY | ⚠️ **Collides with the agent's *domain* category** (`core`, `meta`, `content`). Registry `category` = **install tier**; metadata `category` = **domain**. **Same word, two meanings.** See **Q5**. |
|
|
|
+| `aliases[]` | Alt ids | 🟢 UNIVERSAL | Neutral `aliases[]`. |
|
|
|
+| `files[]` | Multi-file components | 🔵 REGISTRY | **Generate** by globbing. |
|
|
|
+| `version` | SemVer | 🔵 REGISTRY | Neutral `version`. |
|
|
|
+| `categories` (top) | id → description **string** | 🔵 REGISTRY | Should become an object (`{description, icon, order, status}`) to absorb `0-category.json` (§1.6). |
|
|
|
+| `repository` | Source repo for fetches | 🔵 REGISTRY | Registry. |
|
|
|
+| `version` vs `schema_version` vs `metadata.schemaVersion` | **Three** version fields; `metadata.schemaVersion` (`1.0.0`) **contradicts** top-level `schema_version` (`2.0.0`) | 🔴 | Collapse to one. **Q21**. |
|
|
|
+| `subagents` (top-level) | 🔴 **Orphan key** — `{test: {simple-responder: {…}}}`, a *second* place subagents are described, with fields (`mode`, `status`) the components entries lack. `simple-responder` is **also** in `components.subagents`. | 🔴 | **Delete.** Dead schema wart. |
|
|
|
+
|
|
|
+### 8.2 🔴 Profiles are duplicated AND drifted
|
|
|
+
|
|
|
+Profiles exist in **two** places:
|
|
|
+- `registry.json#profiles` — **what `install.sh` reads** (`jq '.profiles.developer.components[]'`, lines 294/636-688/1222)
|
|
|
+- `.opencode/profiles/<name>/profile.json` — read **only** by `scripts/registry/check-dependencies.ts:159`
|
|
|
+
|
|
|
+**All 5 profiles differ:**
|
|
|
+
|
|
|
+| Profile | registry components | file components | Identical? |
|
|
|
+|---|---|---|---|
|
|
|
+| `essential` | 25 | 27 | ❌ |
|
|
|
+| `developer` | 41 | 39 | ❌ |
|
|
|
+| `business` | 25 | 26 | ❌ |
|
|
|
+| `full` | 50 | 42 | ❌ |
|
|
|
+| `advanced` | 68 | 51 | ❌ |
|
|
|
+
|
|
|
+For `developer` alone:
|
|
|
+- **registry-only (15):** `command:add-context`, `config:agent-metadata`, `context:quick-start`,
|
|
|
+ `context:clean-code`, `context:api-design`, `context:development/*`, `context:openagents-repo/*`,
|
|
|
+ `context:ui/*`, `context:react-patterns`, `context:design-systems`, `context:animation-{basics,components,advanced}`,
|
|
|
+ `context:ui-styling-standards`, `context:adding-skill-basics`
|
|
|
+- **file-only (13):** `subagent:image-specialist`, `tool:gemini`, `skill:context-manager`,
|
|
|
+ `context:root-navigation`, `context:context-paths-config`, `context:context-system`,
|
|
|
+ `context:workflows-external-context-{management,integration}`, `context:ui/web/*` (5 path-style variants)
|
|
|
+
|
|
|
+Note the **id-vs-path drift** inside this diff: registry says `context:ui-styling-standards`
|
|
|
+(short id), the file says `context:ui/web/ui-styling-standards` (path) — **the §7.3 dual-namespace
|
|
|
+bug, frozen into the profiles.**
|
|
|
+
|
|
|
+Also note `context:root-navigation` and `context:context-paths-config` are **file-only** ⇒ the
|
|
|
+**authoritative** registry `developer` profile installs **neither the root navigation hub nor the
|
|
|
+context paths config** — i.e. the context system's entry point and its path config are **missing
|
|
|
+from the recommended profile**. 🔴
|
|
|
+
|
|
|
+**Requirement:** ONE profile source. `registry.json#profiles` wins (it is what runs).
|
|
|
+`.opencode/profiles/` must be **deleted** (and `check-dependencies.ts` repointed), or generated.
|
|
|
+But **first reconcile the diffs** — the file versions contain fixes the registry lacks and vice
|
|
|
+versa. See **Q22**.
|
|
|
+
|
|
|
+**Profile fields:** `name`, `description`, `components[]`, `badge` (developer: `"RECOMMENDED"`),
|
|
|
+`additionalPaths[]` (**advanced only**: `[".Building/", ".github/workflows/"]` — raw directory
|
|
|
+copies outside the component model, read at `install.sh:1222`). 🔴 `additionalPaths` is an
|
|
|
+escape hatch that bypasses the component/dependency system entirely.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 9. `plugins/claude-code/` — the drifted, hand-maintained CC plugin
|
|
|
+
|
|
|
+Per `00-INDEX.md` this becomes **generated output** and the directory is deleted. Everything of
|
|
|
+value must therefore be captured **now**.
|
|
|
+
|
|
|
+### 9.1 Inventory
|
|
|
+
|
|
|
+| Item | Count | Class | Notes |
|
|
|
+|---|---|---|---|
|
|
|
+| `agents/` | 7 | 🟢 → regenerate | `code-reviewer`, `coder-agent`, `context-manager`, `context-scout`, `external-scout`, `task-manager`, `test-engineer` |
|
|
|
+| `commands/` | 6 | 🔴 **CC-only** | `brainstorm`, `debug`, `install-context`, `oac-cleanup`, `oac-help`, `oac-status` — **none exist in `.opencode/command/`** |
|
|
|
+| `skills/` | 12 | 🔴 **CC-only** | §4.5 — disjoint from OpenCode's 4 |
|
|
|
+| `hooks/hooks.json` + `hooks/session-start.sh` | 2 | 🔴 **CC-only, critical** | §9.2 |
|
|
|
+| `.claude-plugin/plugin.json` | 1 | 🔵 | name `oac`, version `1.0.2`, author, license, repo, homepage, keywords[] |
|
|
|
+| `.context-manifest.json` | 1 (×2 copies) | 🔴 **CC-only, critical** | §9.3 — also duplicated at `scripts/.context-manifest.json` |
|
|
|
+| `.oac.json.example` + `.oac.example` | 2 | 🔴 | **Two example files**, one presumably stale |
|
|
|
+| `scripts/` | 12 files | 🔴 | `install-context.{js,sh,ts}` — **three implementations of the same thing** — plus `test-install.ts`, `cleanup-tmp.sh`, `types/{manifest,registry}.ts`, `utils/{git-sparse,registry-fetcher}.ts`, `tsconfig.json` |
|
|
|
+| `settings.json` / `settings.local.json` | 2 | 🟡 | Per git log #264: "add settings.json with opusplan model" |
|
|
|
+| `README.md` | 1 | 🔵 | |
|
|
|
+
|
|
|
+### 9.2 🏆 `session-start.sh` — the highest-value CC-only feature
|
|
|
+
|
|
|
+`plugins/claude-code/hooks/hooks.json`:
|
|
|
+
|
|
|
+```json
|
|
|
+{ "hooks": { "SessionStart": [ { "hooks": [
|
|
|
+ { "type": "command",
|
|
|
+ "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh\"",
|
|
|
+ "timeout": 30 } ] } ] } }
|
|
|
+```
|
|
|
+
|
|
|
+`session-start.sh` does **six** distinct things — every one must survive:
|
|
|
+
|
|
|
+| # | Capability | Detail | Class | Home |
|
|
|
+|---|---|---|---|---|
|
|
|
+| 1 | **Inline `using-oac` skill** | Reads `skills/using-oac/SKILL.md` **in full** into session context | 🟢 UNIVERSAL intent | Neutral: "bootstrap doc". Adapter renders per tool. |
|
|
|
+| 2 | **Skill catalogue generation** | Loops `skills/*/SKILL.md`, greps `^description:`, emits `- oac:<name> — <description>` | 🔵 BUILD/adapter | **Could be build-time (static) instead of runtime (shell).** |
|
|
|
+| 3 | **First-run context warning** | If neither `$(pwd)/.claude/.context-manifest.json` nor `~/.claude/.context-manifest.json` exists ⇒ inject an `<important-reminder>` telling the agent to run `context-setup` | 🟢 UNIVERSAL intent | Neutral onboarding rule. |
|
|
|
+| 4 | **OAC system paths block** | Emits `Plugin Root:` + `Context Discovery Protocol:` absolute paths | 🟢 UNIVERSAL intent | Neutral; adapter computes paths. |
|
|
|
+| 5 | **Context-discovery instruction** | "Before responding to any coding request this session, use `oac:context-discovery` … runs once per session" | 🟢 UNIVERSAL | **This is the runtime entry point to the whole context system.** |
|
|
|
+| 6 | **Dual-format JSON output** | Emits **both** `additional_context` (Cursor/OpenCode/other) **and** `hookSpecificOutput.additionalContext` (Claude Code) | 🟡 | **Already a hand-rolled adapter!** Proof the cross-tool need is real. |
|
|
|
+
|
|
|
+Plus a **security control** worth naming: `escape_for_json()` with the comment
|
|
|
+*"SECURITY: Prevents command injection attacks from malicious SKILL.md files"*, escaping
|
|
|
+backslash-first then quotes/newlines/CR/tabs. **If the build generates this hook, the generator
|
|
|
+must preserve the escaping** — a naive template would reintroduce the injection vuln.
|
|
|
+
|
|
|
+> 🔴 **Nothing in `.opencode/` does any of this.** OpenCode has no session-start context
|
|
|
+> injection at all. This is the CC plugin being **ahead**, not behind. It is the mechanism by
|
|
|
+> which OAC introduces itself, advertises its skills, and bootstraps context discovery — arguably
|
|
|
+> **the most important runtime feature in the entire product**, and it exists in exactly one
|
|
|
+> file that the refactor plans to delete.
|
|
|
+
|
|
|
+### 9.3 `.context-manifest.json` — installed-state tracking
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "version": "1.0.0",
|
|
|
+ "profile": "standard",
|
|
|
+ "source": { "repository": "darrenhinde/OpenAgentsControl", "branch": "main",
|
|
|
+ "commit": "1442740b4a776a790754c9dbde64ab7f1aa9d4e8",
|
|
|
+ "downloaded_at": "2026-02-23T11:37:10Z" },
|
|
|
+ "categories": ["core", "openagents-repo"],
|
|
|
+ "files": { "core": 86, "openagents-repo": 107 }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+| Feature | What it does | Class | Home |
|
|
|
+|---|---|---|---|
|
|
|
+| Provenance (`repository`/`branch`/**`commit`**) | Pins the exact source commit | 🟢 UNIVERSAL | **`oac update`/`oac doctor` need this.** Agent D. |
|
|
|
+| `downloaded_at` | Staleness | 🟢 UNIVERSAL | Same. |
|
|
|
+| `profile` | Which profile was installed | 🟢 UNIVERSAL | Same. ⚠️ Value is **`"standard"` — not one of the 5 profile names** (essential/developer/business/full/advanced). `standard` is a *registry **category***, not a profile. Another id-namespace collision. 🔴 |
|
|
|
+| `categories[]` + `files{}` | What/how much was installed | 🟢 UNIVERSAL | Same. |
|
|
|
+| Dual location (project `.claude/` or global `~/.claude/`) | Local vs global install | 🟢 UNIVERSAL | Mirrors `paths.json`'s `local`/`global`. |
|
|
|
+| Used as the first-run sentinel | `session-start.sh` §9.2 #3 | 🟢 UNIVERSAL | |
|
|
|
+
|
|
|
+> `install.sh` (the OpenCode path) writes **no equivalent manifest**. So **OpenCode installs are
|
|
|
+> not updatable or auditable** — you cannot tell what version is installed. The CC plugin solved
|
|
|
+> a problem the "source of truth" side never did. **`oac update` depends on this existing.**
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 10. Other assets (easily missed)
|
|
|
+
|
|
|
+| Asset | Path | Class | Notes |
|
|
|
+|---|---|---|---|
|
|
|
+| Per-model prompt variants | `.opencode/prompts/core/openagent/{gemini,gpt,grok,llama,minimax,openrouter}.md` | 🔴 AT RISK | **6 model-specific rewrites of the OpenAgent prompt.** Directly tensions Locked Decision #2 (`model: null`). Also `prompts/core/opencoder/{gemini,gpt,grok,llama}.md`. |
|
|
|
+| Prompt templates | `.opencode/prompts/*/TEMPLATE.md`, `README.md` | 🔵 | |
|
|
|
+| Eval results | `.opencode/prompts/core/openagent/results/*.json`, `default-output.log` | 🔵 | Build artifacts committed to git. |
|
|
|
+| `.opencode/docs/` | `agents/planning-agents-guide.md`, `guides/task-schema-migration.md`, `workflows/full-project-workflow.md` | 🟢 | 3 docs. `planning-agents-guide.md` documents the **unregistered** planning agents (§1.8). |
|
|
|
+| `.opencode/scripts/task-cli.ts` | | 🔴 | **Duplicate** of `.opencode/skills/task-management/scripts/task-cli.ts`? Unregistered. |
|
|
|
+| `.opencode/opencode.json` | `{"$schema": "https://opencode.ai/config.json"}` | 🟡 | Empty but for the schema ref. |
|
|
|
+| `.opencode/config.json` | `{"agent": "eval-runner"}` | 🟡 | Sets the default agent — **to the eval harness**, which is marked `DO NOT USE DIRECTLY`. Likely a committed local override. 🔴 |
|
|
|
+| `CONTEXT_SYSTEM_GUIDE.md` | repo root, 16KB | 🟢 | Outside `.opencode/` — the main context-system doc. |
|
|
|
+| `COMPATIBILITY.md` | repo root | 🔵 | |
|
|
|
+| `registry:config` entries | `env.example`, `README.md`, `.opencode/config/agent-metadata.json` | 🔵 | **`config:readme` installs the repo README into the user's project.** Intentional? 🔴 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 11. FEATURE PRESERVATION CHECKLIST
|
|
|
+
|
|
|
+> Flat list. Every capability that **must survive**. Each maps to its new home.
|
|
|
+> `[ ]` = must be verified in the migrated system before `.opencode/` is demoted.
|
|
|
+
|
|
|
+### Agents
|
|
|
+- [ ] **34 agent bodies** preserved verbatim → `/content/agents/**/*.md` body
|
|
|
+- [ ] `name` → neutral `name` + `id`; adapters slugify (OpenCode PascalCase, Claude kebab)
|
|
|
+- [ ] `description` → neutral `description`
|
|
|
+- [ ] `mode: primary|subagent` → neutral `role`
|
|
|
+- [ ] `temperature` (33 agents) → `inference.temperature`; **Claude drops it → warning**
|
|
|
+- [ ] `model` stays absent → `inference.model: null` (Locked Decision #2)
|
|
|
+- [ ] `permission.<tool>.<glob>` **tri-state** (`allow`/`ask`/`deny`) → `capabilities` **rule list** (§1.3)
|
|
|
+- [ ] **Glob-scoped denies preserved** (`**/*.env*`, `**/*.key`, `**/*.secret`, `node_modules/**`, `.git/**`) — *security control*
|
|
|
+- [ ] **Deny-by-default + narrow allow preserved** (`coder-agent` bash allowlist) — *security control*
|
|
|
+- [ ] `permission.bash` destructive-command denies preserved (`sudo *`, `rm -rf /*`, `> /dev/*`) — *security control*
|
|
|
+- [ ] `permission.task` → `capabilities.delegate`; **id vs name refs canonicalized**
|
|
|
+- [ ] **`tester`/`test-engineer`/`TestEngineer` aliasing** resolved without breaking dep edges (§1.2)
|
|
|
+- [ ] `eval-runner.md`'s inline `id`/`category`/`type`/`version`/`author` normalized
|
|
|
+- [ ] **CC `<example>` blocks harvested** from `plugins/claude-code/agents/` → neutral `examples[]` (§1.5)
|
|
|
+- [ ] CC `tools:` / `disallowedTools:` derivable from `capabilities`
|
|
|
+- [ ] 6 unregistered planning/orchestration agents: **registered or deleted** (§1.8, Q7)
|
|
|
+- [ ] `batch-executor` (in metadata, not registry) resolved
|
|
|
+
|
|
|
+### Agent metadata
|
|
|
+- [ ] `id`, `name`, `category`, `type`, `version`, `author`, `tags[]`, `dependencies[]` → **neutral frontmatter**
|
|
|
+- [ ] `defaults.{agent,subagent}` → Zod `.default()`
|
|
|
+- [ ] OpenCode adapter **re-splits** metadata into `agent-metadata.json` (OpenCode rejects unknown keys)
|
|
|
+- [ ] `agent-metadata.json` `$schema` + `schema_version` emitted by the adapter
|
|
|
+- [ ] `category` dual format (`core` vs `subagents/core`) normalized (Q5)
|
|
|
+
|
|
|
+### Categories
|
|
|
+- [ ] `0-category.json` `name`/`description`/`icon`/`order`/`status` → `registry.json#categories[]` (upgraded to objects)
|
|
|
+- [ ] `commonSubagents`/`commonTools`/`commonContext` — **promoted or deleted** (Q4)
|
|
|
+
|
|
|
+### Commands
|
|
|
+- [ ] **20 command bodies** verbatim → `/content/commands/`
|
|
|
+- [ ] `description`, `tags[]`, `dependencies[]` preserved
|
|
|
+- [ ] `<critical_rules>`/`<rule id= enforcement=>`/`<execution_priority>`/`<tier>` DSL passes through untouched
|
|
|
+- [ ] `@rule.id` cross-refs intact
|
|
|
+- [ ] `analyze-patterns.md` inline metadata normalized
|
|
|
+- [ ] Agent/context templates relocated out of `command/` → CLI scaffolds (§2.3)
|
|
|
+- [ ] **8 numbered eval templates** (`test-1-planning-approval` … `test-8-completion`) relocated → `/evals` (Q8)
|
|
|
+- [ ] **6 CC-only commands** (`brainstorm`, `debug`, `install-context`, `oac-cleanup`, `oac-help`, `oac-status`) harvested → `/content/commands/`
|
|
|
+
|
|
|
+### Context system 🏆
|
|
|
+- [ ] **All 300 context files** migrated (297 `.md` + `paths.json` + 2 task schemas)
|
|
|
+- [ ] **HTML-comment header parsed, not ignored**: `<!-- Context: {cat}/{fn} | Priority: … | Version: X.Y | Updated: … -->` (§3.1) — **the #1 silent-loss risk**
|
|
|
+- [ ] `Priority` (`critical`/`high`/`medium`/`low`) → neutral `priority` — **drives load order**
|
|
|
+- [ ] `Category`/`Function` dual taxonomy preserved
|
|
|
+- [ ] `Version` `X.Y` form reconciled with SemVer (Q9)
|
|
|
+- [ ] `Updated` date preserved
|
|
|
+- [ ] **All 79 `navigation.md` hubs** migrated
|
|
|
+- [ ] **Task→path "Quick Routes" tables** preserved verbatim — *the* discovery mechanism
|
|
|
+- [ ] **Relative inter-hub links** stay relative (portable); only the **root** tree diagram is rewritten (§3.2)
|
|
|
+- [ ] **43 unregistered `navigation.md`** registered / auto-included (§3.5)
|
|
|
+- [ ] **112 unregistered context files** registered or consciously dropped (§3.5)
|
|
|
+- [ ] **Navigation chain auto-included** as a structural dependency (§7.4)
|
|
|
+- [ ] **3 duplicate-path context ids** collapsed to `aliases[]` (§3.6)
|
|
|
+- [ ] **3 duplicate context ids** (`agents`, `ui-navigation`, `context-bundle-template`) made unique (§3.6)
|
|
|
+- [ ] `paths.json` local/global roots → neutral config; adapter rewrites
|
|
|
+- [ ] **`.oac.json` discovery protocol preserved** (fast path → chain → validity check → self-heal) (§3.3)
|
|
|
+- [ ] `navigation.md`-presence validity check preserved
|
|
|
+- [ ] Non-`.md` contexts (`paths.json`, task schemas) survive wildcard expansion (§7.2, PR #252)
|
|
|
+- [ ] **MVI standard** preserved (formula, what-to-extract/skip, <30s scannable)
|
|
|
+- [ ] **<200-line rule** preserved (candidate `oac doctor` lint)
|
|
|
+- [ ] **Function-based structure** (`concepts/ examples/ guides/ lookup/ errors/`) preserved
|
|
|
+- [ ] Context **operations** (harvest/extract/organize/update/migrate/error) preserved
|
|
|
+- [ ] Context **guides** (compact/creation/organizing/workflows/navigation-design) preserved
|
|
|
+- [ ] `structure.md`/`templates.md`/`codebase-references.md`/`typescript-coding.md` preserved
|
|
|
+- [ ] `core/context-system/CHANGELOG.md` preserved
|
|
|
+- [ ] Task JSON schemas (`tasks/schemas/{task,subtask}-schema.json`) preserved
|
|
|
+- [ ] Root `index.md` **and** `navigation.md` reconciled (Q14)
|
|
|
+- [ ] `CODEBASE_STANDARDS.md` (unregistered) preserved
|
|
|
+- [ ] **`CONTEXT_SYSTEM_GUIDE.md`** (repo root, outside `.opencode/`) preserved
|
|
|
+- [ ] Project Intelligence standard + `context/project-intelligence/` preserved
|
|
|
+- [ ] **~129 files with hardcoded `.opencode/` paths** de-hardcoded (§3.4, Q12)
|
|
|
+
|
|
|
+### Dependency resolution 🏆
|
|
|
+- [ ] `<type>:<id>` grammar preserved
|
|
|
+- [ ] **Recursive transitive closure** preserved
|
|
|
+- [ ] **Dedupe** preserved
|
|
|
+- [ ] **Cycle termination** preserved — and now **detected + reported**
|
|
|
+- [ ] `aliases[]` resolution preserved
|
|
|
+- [ ] **`context:` wildcard expansion** preserved (note: **prefix match**, not true glob)
|
|
|
+- [ ] Wildcard **restricted to `context:`** (or consciously widened)
|
|
|
+- [ ] `get_registry_key` singular↔plural mapping preserved (incl. `config` staying singular)
|
|
|
+- [ ] `get_install_path` (`.opencode/` → `$INSTALL_DIR`) → **adapter output-path logic**
|
|
|
+- [ ] 🔴 **Unresolvable refs now FAIL** instead of silently resolving to nothing (§7.3)
|
|
|
+- [ ] 🔴 **Dual-namespace (id vs path) refs unified** — fixes `/add-context`'s 3 dead deps
|
|
|
+- [ ] Wildcard-produced path-ids resolve their own transitive deps
|
|
|
+
|
|
|
+### Registry
|
|
|
+- [ ] All **245 component entries** across 8 types preserved
|
|
|
+- [ ] `id`/`name`/`type`/`path`/`description`/`tags[]`/`dependencies[]`/`category` preserved
|
|
|
+- [ ] `aliases[]` (3) + `files[]` (4 skills) preserved
|
|
|
+- [ ] `path` re-pointed `.opencode/…` → `/content/…`; **output paths adapter-computed**
|
|
|
+- [ ] `categories` install tiers (essential/standard/extended/specialized/meta) preserved
|
|
|
+- [ ] 🔴 **`category` name collision** (install tier vs domain) resolved (Q5)
|
|
|
+- [ ] `repository` preserved
|
|
|
+- [ ] 3 conflicting version fields collapsed (Q21)
|
|
|
+- [ ] Orphan top-level `subagents.test.simple-responder` key deleted
|
|
|
+- [ ] **`files[]` generated**, not hand-maintained
|
|
|
+
|
|
|
+### Profiles
|
|
|
+- [ ] All **5 profiles** preserved (essential/developer/business/full/advanced)
|
|
|
+- [ ] `name`/`description`/`components[]` preserved
|
|
|
+- [ ] `badge` (`RECOMMENDED`) preserved
|
|
|
+- [ ] `additionalPaths[]` (advanced: `.Building/`, `.github/workflows/`) preserved or replaced (§8.2)
|
|
|
+- [ ] 🔴 **registry-vs-file profile drift reconciled** before deleting `.opencode/profiles/` (§8.2, Q22)
|
|
|
+- [ ] 🔴 `developer` profile regains `context:root-navigation` + `context:context-paths-config`
|
|
|
+- [ ] `scripts/registry/check-dependencies.ts` repointed off `.opencode/profiles/`
|
|
|
+
|
|
|
+### Skills
|
|
|
+- [ ] **4 OpenCode skills** preserved (task-management, context-manager, context7, smart-router-skill)
|
|
|
+- [ ] 🔴 **12 CC skills harvested** (§4.5, Q16) — `code-execution`, `code-review`, `context-discovery`, `context-setup`, `debugger`, `external-research`, `oac-approach`, `parallel-execution`, `task-breakdown`, `test-generation`, `using-oac`, `verification-before-completion`
|
|
|
+- [ ] `SKILL.md` frontmatter (`name`/`description`/`version`/`author`/`type`/`category`/`tags[]`)
|
|
|
+- [ ] `description` remains greppable by `^description:` (session-start catalogue depends on it)
|
|
|
+- [ ] `router.sh` preserved **with the executable bit**
|
|
|
+- [ ] `scripts/*.ts` preserved
|
|
|
+- [ ] `workflows/*.md` preserved (incl. `8-stage-delivery.md`, `context-handoff.md`, `planning-agents.md`)
|
|
|
+- [ ] `tests/*.test.ts` relocated
|
|
|
+- [ ] `smart-router-skill` `config/personality-config.json` + `scripts/{sherlock,stark,yoda}-workflow.sh` preserved
|
|
|
+- [ ] `context7` `library-registry.md` + `navigation.md` preserved
|
|
|
+- [ ] 🔴 `.opencode/skill/project-orchestration` (orphan) registered or deleted (§4.3, Q7)
|
|
|
+- [ ] 🔴 `.opencode/skill/task-management/tests/` reunited with its skill
|
|
|
+- [ ] Bun/TS runtime dependency addressed for npm distribution (§4.4, Q15)
|
|
|
+
|
|
|
+### Tools
|
|
|
+- [ ] `tool:env` (`loadEnvVariables`, multi-path `.env` search) preserved
|
|
|
+- [ ] `tool:gemini` (image gen/edit/analyze) preserved
|
|
|
+- [ ] `tool:gemini → tool:env` dependency preserved
|
|
|
+- [ ] `tool/template/` → CLI scaffold
|
|
|
+- [ ] Non-OpenCode targets: tools unsupported → **explicit warning**, or MCP path (Q18)
|
|
|
+- [ ] 🔴 `.opencode/tool/.env` **NOT** carried into `/content/` (Q17)
|
|
|
+
|
|
|
+### Plugins & hooks
|
|
|
+- [ ] `plugin:notify` preserved (incl. `ENABLED = false` default)
|
|
|
+- [ ] 🔴 `agent-validator.ts` + `.disabled` twin resolved; `VALIDATOR_GUIDE.md` + tests preserved
|
|
|
+- [ ] 🔴 `plugins/coder-verification/` (index.ts, plugin.json, README, IMPLEMENTATION_SUMMARY) registered or deleted
|
|
|
+- [ ] `plugin.json` manifest shape unified with `.claude-plugin/plugin.json`
|
|
|
+- [ ] 🔴 OpenCode `event` callback vs CC `hooks.json` — hook model decided (§6, Q19)
|
|
|
+- [ ] 🔴 `.opencode/plugin/.env` **NOT** carried into `/content/` (Q17)
|
|
|
+
|
|
|
+### Claude Code plugin 🏆
|
|
|
+- [ ] `.claude-plugin/plugin.json` generated (name/description/version/author/license/repo/homepage/keywords)
|
|
|
+- [ ] `hooks/hooks.json` `SessionStart` (+ `timeout: 30`, `${CLAUDE_PLUGIN_ROOT}`) generated
|
|
|
+- [ ] **`session-start.sh` #1** inline `using-oac` full text
|
|
|
+- [ ] **#2** skill catalogue (`- oac:<name> — <description>`)
|
|
|
+- [ ] **#3** first-run warning when no `.context-manifest.json` (project **or** global)
|
|
|
+- [ ] **#4** OAC system paths block (plugin root + protocol path)
|
|
|
+- [ ] **#5** context-discovery instruction ("once per session")
|
|
|
+- [ ] **#6** dual-format JSON (`additional_context` **and** `hookSpecificOutput.additionalContext`)
|
|
|
+- [ ] 🔴 **`escape_for_json()` injection defense preserved** (backslash-first ordering) — *security control*
|
|
|
+- [ ] `<EXTREMELY_IMPORTANT>` / `<important-reminder>` wrappers preserved
|
|
|
+- [ ] **`.context-manifest.json`** written on install: `version`/`profile`/`source.{repository,branch,commit}`/`downloaded_at`/`categories[]`/`files{}`
|
|
|
+- [ ] 🔴 **OpenCode installs gain a manifest too** (today they have none ⇒ not updatable)
|
|
|
+- [ ] `.oac.json` (`version`, `context.root`) supported; **`.oac.example` vs `.oac.json.example` deduped**
|
|
|
+- [ ] Project-local **and** global manifest locations supported
|
|
|
+- [ ] `scripts/install-context.{js,sh,ts}` → **one** implementation in `/packages/cli`
|
|
|
+- [ ] `scripts/utils/{git-sparse,registry-fetcher}.ts` (sparse-checkout fetch) preserved → CLI
|
|
|
+- [ ] `scripts/types/{manifest,registry}.ts` → `/packages/core` types
|
|
|
+- [ ] `scripts/cleanup-tmp.sh` → CLI (`oac clean`)
|
|
|
+- [ ] `settings.json` (opusplan model, PR #264) + `settings.local.json` decided (Q3)
|
|
|
+- [ ] 🔴 `.context-manifest.json` `profile: "standard"` (not a real profile name) fixed
|
|
|
+
|
|
|
+### Prompts / misc
|
|
|
+- [ ] 🔴 **10 per-model prompt variants** (`openagent/{gemini,gpt,grok,llama,minimax,openrouter}.md`, `opencoder/{gemini,gpt,grok,llama}.md`) — tension with `model: null` (Q23)
|
|
|
+- [ ] `prompts/*/TEMPLATE.md` + READMEs preserved
|
|
|
+- [ ] Eval `results/*.json` — keep or gitignore
|
|
|
+- [ ] `.opencode/docs/` (3 docs) relocated
|
|
|
+- [ ] 🔴 `.opencode/scripts/task-cli.ts` duplicate resolved
|
|
|
+- [ ] `.opencode/config.json` (`{"agent": "eval-runner"}`) — **almost certainly a bad committed default**
|
|
|
+- [ ] `config:env-example`, `config:readme`, `config:agent-metadata` install-components decided (Q24)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Open Questions
|
|
|
+
|
|
|
+Ordered by blocking-ness. **Q1, Q2, Q10, Q12, Q16, Q20 block the schema (Agent B) and should be
|
|
|
+answered first.**
|
|
|
+
|
|
|
+**Q1 — Canonical id vs filename vs display name.** `tester` (id) / `test-engineer.md` (file) /
|
|
|
+`TestEngineer` (frontmatter `name`) / `test-engineer` (CC) all denote one agent. Is `id`
|
|
|
+independent of filename (needs `aliases[]` + an id→path map), or do we **rename files to match
|
|
|
+ids** as a one-time migration and make `filename == id` an invariant? The latter is much simpler
|
|
|
+but breaks any external reference to the old paths. **Recommendation: filename == id, with
|
|
|
+`aliases[]` retained for dependency back-compat.**
|
|
|
+
|
|
|
+**Q2 — `capabilities`: flat scalars or ordered rule lists?** The `00-INDEX.md` worked example
|
|
|
+shows `read: allow` / `edit: deny`. That shape **cannot** express OpenCode's glob-scoped,
|
|
|
+ordered, tri-state permissions — and those encode real security controls (`**/*.env*: deny`,
|
|
|
+`coder-agent`'s bash allowlist, `rm -rf /*: deny`). Adopt the rule-list form (§1.3) with scalar
|
|
|
+sugar? **This changes the worked example in `00-INDEX.md`** and needs sign-off.
|
|
|
+
|
|
|
+**Q3 — Model policy vs shipped reality.** Locked Decision #2 says `model: null`. But
|
|
|
+`plugins/claude-code/agents/*.md` hardcode `model: sonnet`, `settings.json` sets `opusplan`
|
|
|
+(PR #264, merged), and `.opencode/prompts/` holds 10 per-model prompt variants. Does `model: null`
|
|
|
+mean (a) **never** emit `model:` for any target, or (b) allow a **per-adapter default** in adapter
|
|
|
+config (not content)? (b) preserves shipped behavior; (a) is a deliberate behavior change.
|
|
|
+
|
|
|
+**Q4 — `0-category.json`: promote or delete?** It's read by nothing. Its `icon`/`order`/`status`
|
|
|
+are richer than `registry.json#categories` (flat strings) and worth promoting. But
|
|
|
+`commonSubagents`/`commonTools`/`commonContext` (with globs) overlap `dependencies` +
|
|
|
+`capabilities.delegate` + `context[]` without being enforced. Promote the category display
|
|
|
+metadata and **delete** the `common*` advisory fields?
|
|
|
+
|
|
|
+**Q5 — `category` means two things.** Registry `category` = **install tier**
|
|
|
+(`essential`/`standard`/`extended`/`specialized`/`meta`). Metadata `category` = **domain**
|
|
|
+(`core`/`meta`/`content`/`subagents/core`). Same key, different value spaces, both on the same
|
|
|
+component. Rename to `tier` + `category`? And normalize the flat-vs-path domain form
|
|
|
+(`core` vs `subagents/core`)?
|
|
|
+
|
|
|
+**Q6 — `author: "opencode"`.** All 28 metadata entries claim author `opencode` — a *tool name*
|
|
|
+used as an author. Now that OpenCode is "just another adapter", should this become `oac`? Affects
|
|
|
+every generated `agent-metadata.json`.
|
|
|
+
|
|
|
+**Q7 — The dark orchestration feature.** 6 unregistered agents (`subagents/planning/*` +
|
|
|
+`stage-orchestrator`) + the unregistered `.opencode/skill/project-orchestration` skill
|
|
|
+(8-stage delivery workflow, stage CLI, context handoff) + `.opencode/docs/agents/planning-agents-guide.md`
|
|
|
+form **one coherent, fully-built, uninstallable feature**. Ship it (register + profile it) or
|
|
|
+delete it? Carrying it into `/content/` as-is just relocates the ambiguity.
|
|
|
+
|
|
|
+**Q8 — The 8 eval templates.** `command/openagents/new-agents/templates/test-{1..8}-*.yaml`
|
|
|
+encode OAC's agent quality bar (planning-approval, context-loading, incremental, tool-usage,
|
|
|
+error-handling, extended-thinking, compaction, completion). Move to `/evals`? Wire into CI as the
|
|
|
+acceptance gate for new agents? Coordinate with Agent E.
|
|
|
+
|
|
|
+**Q9 — Version format.** Context files use `Version: X.Y`; agents/skills use SemVer `X.Y.Z`;
|
|
|
+registry has `version` **and** `schema_version` **and** `metadata.schemaVersion`. One format
|
|
|
+(SemVer) with a migration of ~300 context headers, or keep `X.Y` for context as a distinct field?
|
|
|
+
|
|
|
+**Q10 — Context metadata: HTML comment or YAML frontmatter?** ~297 files use
|
|
|
+`<!-- Context: … | Priority: … -->`; a handful additionally use YAML. **Two conventions in one
|
|
|
+tree.** Options: (a) neutral parser reads the HTML comment (zero content churn, must be
|
|
|
+hand-written — `gray-matter` will silently return nothing); (b) migrate all ~297 to YAML
|
|
|
+(one-time churn, standard tooling, but YAML renders visibly in markdown viewers — which is *why*
|
|
|
+the HTML comment was chosen). **This is the highest-risk decision in the doc: pick (a) or (b),
|
|
|
+but never let a generic parser near these files.**
|
|
|
+
|
|
|
+**Q11 — Unify context discovery on `.oac.json`?** OpenCode has `paths.json` (static local/global);
|
|
|
+CC has the `.oac.json` protocol (fast path → discovery chain → `navigation.md` validity check →
|
|
|
+self-healing write). The CC design is strictly better. Make `.oac.json` the neutral mechanism and
|
|
|
+demote `paths.json` to OpenCode-adapter output?
|
|
|
+
|
|
|
+**Q12 — De-hardcoding `.opencode/` from ~129 content bodies.** Token substitution
|
|
|
+(`{{CONTEXT_ROOT}}`, explicit + lintable, touches 129 files), adapter regex rewrite (zero churn,
|
|
|
+brittle), or id-based indirection (cleanest, biggest rewrite)? **Recommendation: tokens now +
|
|
|
+a `no raw .opencode/ in /content/` lint; ids later.** Without this, generated CC agents point at
|
|
|
+paths that don't exist — likely why the CC plugin was hand-written in the first place.
|
|
|
+
|
|
|
+**Q13 — Auto-generate registry context entries?** 112 of 300 context files are unregistered
|
|
|
+(incl. 43 of 79 `navigation.md`). Hand-maintenance has demonstrably failed. Generate all context
|
|
|
+entries from disk at build time, with `navigation.md` auto-included whenever any sibling is
|
|
|
+installed? What then determines a context's `category`/tier — the HTML `Priority`? Its directory?
|
|
|
+
|
|
|
+**Q14 — Root `index.md` vs root `navigation.md`.** Both exist at `.opencode/context/`. Which is
|
|
|
+the canonical entry point? (`navigation.md` is what `context-discovery-protocol.md` checks for.)
|
|
|
+Merge or define the split.
|
|
|
+
|
|
|
+**Q15 — Bun/TypeScript runtime for skills.** Every `router.sh` shells out to `.ts` under Bun.
|
|
|
+For npm distribution, does OAC (a) require Bun, (b) precompile skills to JS, or (c) rewrite
|
|
|
+routers in Node? Also: `router.sh` is bash — **what is the Windows story?** Blocks Agent D.
|
|
|
+
|
|
|
+**Q16 — Which skill set seeds `/content/skills/`?** OpenCode has 4 skills; CC has 12; the sets
|
|
|
+are **disjoint**. The CC 12 are the product's actual shipped UX (`oac:code-review`,
|
|
|
+`oac:task-breakdown`, …). Seed from CC, from OpenCode, or the union of 16? **If `/content/` is
|
|
|
+seeded only from `.opencode/`, the 12 CC skills are silently destroyed.**
|
|
|
+
|
|
|
+**Q17 — Committed `.env` files.** `.opencode/tool/.env` and `.opencode/plugin/.env` are in the
|
|
|
+repo. Are they real secrets (⇒ rotate + purge history) or empty templates? Either way they must
|
|
|
+**not** be copied into `/content/` or any build output. Needs a human to look.
|
|
|
+
|
|
|
+**Q18 — Tools on non-OpenCode targets.** `.opencode/tool/*` implements the OpenCode tool API.
|
|
|
+Claude Code has no equivalent primitive (nearest: MCP servers). Are tools (a) OpenCode-only with
|
|
|
+an explicit "unsupported on target X" warning, or (b) re-expressed as MCP servers for CC? (b) is
|
|
|
+a large scope increase. Agent C.
|
|
|
+
|
|
|
+**Q19 — Is `hooks` a neutral content type?** OpenCode hooks = a TS plugin exporting an `event`
|
|
|
+callback. CC hooks = declarative `hooks.json` → shell command. These are not the same shape and
|
|
|
+don't obviously unify. Options: (a) `hooks` is per-adapter, not content; (b) a neutral
|
|
|
+event→action schema that both render (constrains OpenCode plugins to declarative actions);
|
|
|
+(c) declare only `SessionStart` neutrally (the one hook that matters) and leave the rest
|
|
|
+per-adapter. **Recommendation: (c).**
|
|
|
+
|
|
|
+**Q20 — Fail-fast on unresolvable dependencies?** Today `jq … || echo ""` means an unknown
|
|
|
+component resolves to **zero dependencies, silently** — which is why `/add-context`'s three
|
|
|
+path-style context deps (mvi, frontmatter, project-intelligence) almost certainly install
|
|
|
+nothing today. Confirm the new resolver **errors** on unresolvable refs. This is a **behavior
|
|
|
+change that will surface currently-hidden breakage** (probably a lot of it) — the migration
|
|
|
+should expect a burst of newly-visible failures and budget for it. Coordinate with Agent E.
|
|
|
+
|
|
|
+**Q21 — Registry version fields.** Top-level `version: "2.0.0"`, top-level
|
|
|
+`schema_version: "2.0.0"`, and `metadata.schemaVersion: "1.0.0"` — the last **contradicts** the
|
|
|
+second. Which is authoritative? Collapse to one `schemaVersion` + one `contentVersion`?
|
|
|
+
|
|
|
+**Q22 — Reconciling profile drift before deletion.** All 5 profiles differ between
|
|
|
+`registry.json#profiles` (authoritative — `install.sh` reads it) and `.opencode/profiles/*/profile.json`
|
|
|
+(read only by `scripts/registry/check-dependencies.ts`). Each side has things the other lacks —
|
|
|
+the file side has `root-navigation` + `context-paths-config` (which the recommended `developer`
|
|
|
+profile is **missing**), the registry side has broader wildcards. This needs a **human to
|
|
|
+reconcile 5 diffs**; it cannot be auto-merged. Blocks deleting `.opencode/profiles/`.
|
|
|
+
|
|
|
+**Q23 — Per-model prompt variants.** `.opencode/prompts/core/{openagent,opencoder}/{gemini,gpt,grok,llama,minimax,openrouter}.md`
|
|
|
+are 10 model-specific rewrites of two agents' system prompts, with committed eval results. Under
|
|
|
+"no hardcoded models", do these (a) get deleted, (b) become an opt-in `prompts/` overlay keyed by
|
|
|
+model family, or (c) move to `/evals` as prompt-engineering artifacts? Are they even current?
|
|
|
+
|
|
|
+**Q24 — `config:` components.** `config:readme` installs **this repo's `README.md`** into the
|
|
|
+user's project; `config:env-example` installs `env.example`; `config:agent-metadata` installs the
|
|
|
+sidecar. `readme` looks like a bug (why would a user want OAC's README in their project?).
|
|
|
+Keep, drop, or replace with a generated project README?
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Appendix — Sources
|
|
|
+
|
|
|
+Every claim above is grounded in these files (all paths repo-relative):
|
|
|
+
|
|
|
+- `.opencode/agent/**/*.md` (34), `.opencode/agent/**/0-category.json` (5)
|
|
|
+- `.opencode/config/agent-metadata.json`
|
|
|
+- `.opencode/command/**/*.md` (20), `.opencode/command/openagents/new-agents/templates/*.yaml` (9)
|
|
|
+- `.opencode/context/**` (300), esp.
|
|
|
+ `context/navigation.md`, `context/index.md`, `context/CODEBASE_STANDARDS.md`,
|
|
|
+ `context/core/config/paths.json`,
|
|
|
+ `context/core/context-system/standards/{frontmatter,mvi,structure,templates,codebase-references}.md`,
|
|
|
+ `context/core/context-system/operations/*.md`, `context/core/standards/code-quality.md`,
|
|
|
+ `context/tasks/schemas/{task,subtask}-schema.json`
|
|
|
+- `.opencode/skills/*/SKILL.md` (4), `.opencode/skill/{project-orchestration,task-management}/**`
|
|
|
+- `.opencode/tool/{env,gemini,template}/index.ts`, `.opencode/tool/.env`
|
|
|
+- `.opencode/plugin/{notify.ts,agent-validator.ts,agent-validator.ts.disabled,.env}`,
|
|
|
+ `.opencode/plugins/coder-verification/{index.ts,plugin.json}`
|
|
|
+- `.opencode/profiles/*/profile.json` (5), `.opencode/prompts/**`, `.opencode/docs/**`,
|
|
|
+ `.opencode/scripts/task-cli.ts`, `.opencode/{opencode.json,config.json}`
|
|
|
+- `registry.json` (107KB) — `components` (8 types / 245 entries), `profiles` (5), `categories` (5)
|
|
|
+- `install.sh` — `get_registry_key():331`, `get_install_path():353`,
|
|
|
+ `expand_context_wildcard():361`, `expand_selected_components():373`,
|
|
|
+ `resolve_dependencies():420-481`, profile reads `:294,:636-688`, `additionalPaths` `:1222`
|
|
|
+- `scripts/registry/check-dependencies.ts:159`
|
|
|
+- `plugins/claude-code/**` — `hooks/{hooks.json,session-start.sh}`,
|
|
|
+ `.claude-plugin/plugin.json`, `.context-manifest.json`, `.oac.json.example`, `.oac.example`,
|
|
|
+ `agents/*.md` (7), `commands/*.md` (6), `skills/*/SKILL.md` (12),
|
|
|
+ `skills/context-discovery/context-discovery-protocol.md`, `scripts/**`, `settings.json`
|
|
|
+- `CONTEXT_SYSTEM_GUIDE.md`, `COMPATIBILITY.md` (repo root)
|