Tool relationships — specodelic, OpenSpec, and the ah companion
specodelic does not replace the tools a repo already uses for change
management — it plugs into them. Two relationships matter, and this
page names both honestly: the dual-format protocol that binds
specodelic files to the OpenSpec change
workflow, and the ah companion CLI
(espectacular) that
checks spec↔test correspondence around those files without ever
editing them.
| Tool | What it does | Who owns what |
|---|---|---|
| OpenSpec | proposal → tasks → archive change workflow | owns the openspec/ directory structure |
specodelic (spk) | the format + linter; every change delta is also a lint-clean specodelic file | owns the content of the dual-format layer |
espectacular (ah) | spec↔test correspondence checking | read-only over openspec/ — never edits a spec file |
The OpenSpec dual-format relationship
This repo manages its engineering changes in openspec: a change lives
in openspec/changes/<id>/ as a proposal plus task list, and when it
ships, openspec archive moves its deltas into the capability specs
under openspec/specs/. The dual-format protocol makes every one of
those files a specodelic file at the same time: one markdown file,
two parsers, requirement text authored once.
A dual-format file carries both grammars:
- the specodelic half — YAML frontmatter (a real
idfrom the naming law,kind: intent, one EARSstatement) plus the## Constraints,## Model, and## Propertiestables; - the openspec half —
## Purpose, a delta section such as## ADDED Requirements, and a sibling## Requirementssection with identical text.
Two rules keep the halves honest:
- Naming law: openspec hard-requires the filename
spec.md, so the id law derives aspec.mdfile’s id from its parent directory name —openspec/specs/ge-cli/spec.mddeclaresid: ge.cli. - No drift:
linter.requirement_driftfails when the delta requirements and the mirrored## Requirementssection drift apart, andlinter.dual_format_validrequires a capability spec underopenspec/specs/to be dual-format at all.
The full protocol — the migration recipe, the delta-mirror rules, and the exact gate commands — is served from inside the binary:
spk explain dual-format
That topic is the single source of truth for the protocol; this page
only orients you. When the protocol text and spk explain dual-format
disagree, trust the command — it ships with the linter that enforces
it.
Why not plain openspec archive? The stock archive command
regenerates spec files and destroys the specodelic layer (frontmatter
and the three tables). specodelic ships spk archive-companion — it
runs openspec archive with default spec application (plain deltas
are openspec’s native merge), then re-attaches the dual-format layer
from the change’s archived layer.md sidecar; a change whose deltas
lack restorable sidecars is refused before the destructive archive.
spk hooks install wires the dual-format gate (spk lint openspec)
into the repo’s pre-commit chain, so an unwrapped delta is caught
before commit, not after archive.
The ah companion (espectacular)
espectacular is a
sibling tool in the charly-vibes ecosystem — a separate crate whose
binary is ah (see its upstream
README for install and
the full command table). It solves a problem specodelic deliberately
does not: spec↔test correspondence. A spec scenario is only as
good as the test that actually runs it, and ah keeps those two
honestly wired together.
How it works, in this repo:
- Each deployed scenario in
openspec/specs/<capability>/spec.mdis backed by a contract TOML at.espectacular/<capability>/<scenario-id>.toml, which declares the tests that verify that scenario. ah checkvalidates every deployed scenario against its contract — and with--run-testsexecutes the declared tests.ah doctordiagnoses the setup;ah explain <topic>serves playbook guidance for a finding or workflow question.
The boundary is one sentence and it is a hard constraint, recorded in this repo’s AGENTS.md sibling-tool rules:
espectacular is read-only over
openspec/specs/andopenspec/changes/: it reads the#### Scenario:blocks, checks correspondence, and reports — it never edits, regenerates, or archives spec files.
That is why the companion archive recipe above exists as the only
sanctioned write path for capability specs: the two tools split the
work cleanly, with specodelic owning content and espectacular owning
the correspondence check. Nothing in ah’s enforcement is
specodelic-owned, and no specodelic command changes ah’s behavior —
if a docs page or tool output ever claims otherwise, it is wrong; the
guards in this repo’s CI (scripts/guards/sibling-blockers.sh) treat
boundary violations as bugs, not preferences.
Reading order for an OpenSpec user
- Run
spk explain dual-format— the protocol, from the binary that enforces it. - Skim the core format — the four specodelic layers the dual-format layer adds to an openspec delta.
- Read verification boundaries — what a
lint-clean or verified file does not assure; the same honesty
discipline
ah checkapplies to spec↔test claims.