Skip to content

Latest commit

 

History

History
140 lines (114 loc) · 7.22 KB

File metadata and controls

140 lines (114 loc) · 7.22 KB

Layer Architecture

The OpenSpec plugin has four layers that coexist by design. They serve different audiences and return different data shapes. Understanding the boundaries prevents "fixing" the duplication by rewriting one layer to use another.

Layers

┌─────────────────────────────────────────────────────────────┐
│ Skills (11 upstream workflow prompts)                        │
│  openspec-propose, openspec-apply-change, etc.              │
│  Agent auto-loads when user intent matches description.     │
│  Skills instruct agent to run openspec CLI commands.        │
└─────────────┬───────────────────────────────────────────────┘
              │
              ▼
┌─────────────────────────────────────────────────────────────┐
│ CLI interface (two paths, same binary)                      │
│                                                             │
│  openspec_cli tool          terminal tool                   │
│  ├─ Gated by check_fn       ├─ Always available             │
│  ├─ JSON output parsed      ├─ Raw stdout                   │
│  └─ Discoverable in tool    └─ Skills use this by default   │
│     list                                                    │
└─────────────┬───────────────────────────────────────────────┘
              │
              ▼
┌─────────────────────────────────────────────────────────────┐
│ openspec CLI binary                                          │
│  (installed separately via npm, not part of plugin)         │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ Plugin tools (19 existing + openspec_cli = 20)              │
│  openspec_context, openspec_show, openspec_spec_diff, etc.  │
│  Different JSON shapes than CLI.                            │
│  Used for: ad-hoc agent queries, dashboard backend.         │
│  NOT used by: upstream skills (they call CLI directly).     │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ Dashboard                                                   │
│  Board, spec browser, change detail                         │
│  Reads from filesystem + git, not from CLI or plugin tools. │
└─────────────────────────────────────────────────────────────┘

Why skills don't use plugin tools

The upstream OpenSpec skills are structured prompts that instruct the agent to run openspec CLI commands directly:

openspec new change "<name>"
openspec status --change "<name>" --json
openspec instructions apply --change "<name>" --json

The CLI returns JSON with fields like applyRequires, artifacts, contextFiles, actionContext, and planningHome. The skill prompts parse these fields to drive the workflow.

Our plugin tools wrap a subset of the CLI but return different JSON shapes. For example:

CLI output Plugin tool output
openspec status --json{changeName, schemaName, artifacts, applyRequires, planningHome, actionContext} openspec_status{ok, change, status, counts}
openspec instructions apply --json{contextFiles, state, progress, tasks, instruction} openspec_instructions{ok, artifact, instructions}

Rewriting skills to use plugin tools would require modifying every prompt to match our shapes — a permanent sync burden with no value gained. The upstream prompts are the product.

When to use what

You want to… Use
Follow a workflow (propose, apply, verify, archive) Skills — the agent loads them automatically when intent matches
Run a CLI command with raw JSON output openspec_cli tool — gated, discoverable, parses JSON
Run a CLI command via shell pipeline terminal tool — always available, raw stdout
Query a change/spec without the CLI Plugin tools (openspec_context, openspec_show, openspec_spec_diff, etc.) — filesystem-backed, work without the CLI binary
Browse changes and specs visually Dashboard at /openspec

Skill list

11 skills bundled from upstream OpenSpec CLI v1.4.1:

Skill Workflow Profile
openspec-propose propose core
openspec-explore explore core
openspec-apply-change apply core
openspec-archive-change archive core
openspec-new-change new expanded
openspec-continue-change continue expanded
openspec-ff-change ff expanded
openspec-verify-change verify expanded
openspec-sync-specs sync expanded
openspec-bulk-archive-change bulk-archive expanded
openspec-onboard onboard expanded

Skills are generated by openspec init --tools claude and bundled unmodified. The generatedBy version in each skill's frontmatter shows which OpenSpec version produced the content.

Regenerating skills

When upstream OpenSpec updates the workflow prompts:

# 1. Set all workflows in openspec config
python3 -c "
import json
c = json.load(open('~/.config/openspec/config.json'.replace('~', __import__('os').path.expanduser('~'))))
c['profile'] = 'custom'
c['workflows'] = ['propose','explore','new','continue','apply','ff','sync','archive','bulk-archive','verify','onboard']
json.dump(c, open(c_path := __import__('os').path.expanduser('~/.config/openspec/config.json'), 'w'), indent=2)
"

# 2. Generate into a temp dir
mkdir -p /tmp/opsx-regen && cd /tmp/opsx-regen
openspec init . --tools claude

# 3. Copy into the plugin
cp -r .claude/skills/openspec-* /path/to/hermes-openspec/skills/

# 4. Restore core profile
openspec config profile core

Long-term: Hermes adapter upstream

The ideal solution is contributing a Hermes adapter to the OpenSpec CLI's command-generation system (in dist/core/command-generation/adapters/). This would let openspec init --tools hermes generate skills directly into the plugin structure. Until then, the manual regeneration above is mechanical and infrequent.