Skip to content

feat(opencode): skill parity — generate the tree from canonical ctx skills - #160

Open
omergk28 wants to merge 3 commits into
ActiveMemory:mainfrom
omergk28:feat/158-opencode-skill-parity
Open

feat(opencode): skill parity — generate the tree from canonical ctx skills#160
omergk28 wants to merge 3 commits into
ActiveMemory:mainfrom
omergk28:feat/158-opencode-skill-parity

Conversation

@omergk28

@omergk28 omergk28 commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

feat(opencode): skill parity — generate the tree from canonical ctx skills

Branch: feat/158-opencode-skill-paritymain · Closes #158
Commits: 0be1d23c, 930325e2, 9cbc1419 · Spec: specs/opencode-skill-parity.md

Rebased onto main after #163 (Codex integration) merged. The
Makefile conflict (both PRs add skill-sync targets) is resolved as a
union: build now runs copilot, codex, and opencode syncs, and
make audit checks all three trees for freshness.

What

Aligns OpenCode with the Copilot CLI model: the skill tree is
generated from internal/assets/claude/skills/ at build time.

  • hack/sync-opencode-skills.sh — sibling of the Copilot script,
    same contract: opt-in by directory presence, allowed-tools:
    frontmatter strip, OpenCode-only skills untouched. shellcheck-clean.
  • Makefile: sync-opencode-skills runs in make build;
    check-opencode-skills gates make audit (fails on staleness and
    restores state, mirroring the Copilot gate).
  • 17 skills enrolled: the existing 10 (terse hand-written variants
    replaced by canonical bodies) + the Design Before Coding planning
    arc (ctx-brainstorm, ctx-plan, ctx-spec, ctx-task-out,
    ctx-implement) + capture pair (ctx-task-add,
    ctx-decision-add). Canonical names, 1:1 with the Claude tree.
  • New test TestSyncedSkillParity
    (internal/assets/read/skill/parity_test.go): asserts every
    synced skill in BOTH generated trees (OpenCode + Copilot CLI) is
    byte-identical to its Claude source minus allowed-tools: lines.
    This moves the sync contract into go test, so CI now enforces
    it
    — previously only make audit on developer machines did.
    Verifies 52 synced skills, 14 Copilot tool-only exempt.
  • Zero Go source changes: embed glob, agent.OpenCodeSkills(), and
    deploySkills() already walk whatever directories exist.
  • Docs: docs/home/opencode.md slash-command section lists the full
    synced set (relative recipe link per docs conventions); site/
    regenerated for that page + search.json only (see below).

Verification

  • make audit fully green (run on main + this + the sibling
    hack-portability fix, i.e. post-merge state), including the new
    check-opencode-skills gate.
  • Byte-parity of all 17 skills verified against the sed transform.
  • Staleness path verified: deliberately staled a skill →
    check-opencode-skills fails and restores state.
  • End-to-end smoke: built binary, ctx setup opencode --write in a
    fresh temp repo → all 17 skills deployed, deployed content
    byte-identical to embedded source.
  • TestSkillFrontmatter covers the 7 new dirs automatically.

Decisions / notes for review

  • No terse transform (issue's open question): the hand-written
    terseness was truncated reference material, so canonical bodies
    replace it. This also drops a couple of genuinely OpenCode-specific
    lines (e.g. ctx-status's "slash command takes no arguments" note) —
    judged not worth a divergent transform; revisit in the sync script
    if OpenCode-specific adaptation is ever needed.
  • site/ regen scoped to the opencode page + search.json: a full
    make site with the exactly-pinned zensical 0.0.51 churns 100+
    unrelated pages with HTML-entity encoding differences (underlying
    library drift; captured as a LEARNING). Excluded to keep the PR
    isolated.
  • Sibling PR fix/hack-script-portability should merge first so
    make audit runs for macOS reviewers; this PR does not depend on
    it for CI.

@omergk28
omergk28 force-pushed the feat/158-opencode-skill-parity branch from a41f087 to b6bf560 Compare August 20, 2026 02:31
…kills

Align OpenCode with the Copilot CLI model (issue ActiveMemory#158):
hack/sync-opencode-skills.sh derives each enrolled skill from
internal/assets/claude/skills/<name>/SKILL.md with the Claude-specific
allowed-tools frontmatter key stripped. Opt-in by directory presence;
wired into make build; check-opencode-skills gates make audit.

Enrolls 17 skills: the existing 10 hand-written ones (terse variants
replaced by canonical bodies) plus the Design Before Coding planning
arc (ctx-brainstorm, ctx-plan, ctx-spec, ctx-task-out, ctx-implement)
and the capture pair (ctx-task-add, ctx-decision-add). No Go changes:
the embed glob, agent.OpenCodeSkills(), and deploySkills() walk
whatever directories exist. docs/home/opencode.md slash-command
section updated (site/ regen tracked in TASKS).

Closes ActiveMemory#158

Spec: specs/opencode-skill-parity.md
Signed-off-by: Omer Kocaoglu <omergk28@gmail.com>
Only the opencode page and search index are committed: the local
zensical 0.0.51 rebuild also churns 100+ unrelated pages with
HTML-entity encoding differences (&ActiveMemory#39; vs ') from underlying
library drift; that churn is excluded to keep this PR isolated.

Spec: specs/opencode-skill-parity.md
Signed-off-by: Omer Kocaoglu <omergk28@gmail.com>
Spec: specs/opencode-skill-parity.md
Signed-off-by: Omer Kocaoglu <omergk28@gmail.com>
@omergk28
omergk28 force-pushed the feat/158-opencode-skill-parity branch from b6bf560 to 9cbc141 Compare August 28, 2026 16:26
@josealekhine

Copy link
Copy Markdown
Member

@omergk28 looking mostly good; here are my comments:

1. Canonical bodies introduce seven dangling slash-command references in the pre-existing ten

specs/opencode-skill-parity.md:66 · behavior · in diff

The closure claim here is scoped to the planning arc, and it holds — verified
the five arc skills reference only enrolled skills. But replacing the terse
bodies breaks closure for four of the pre-existing ten: synced ctx-wrap-up
now instructs the agent to offer /ctx-commit, use /ctx-reflect, run
/ctx-digest next session, and defer to /ctx-journal-enrich-all;
ctx-remember points at /ctx-history and /ctx-digest; ctx-handover and
ctx-kb-note route capture to /ctx-learning-add and /ctx-convention-add.
None of these seven commands exist in the OpenCode tree, and the old
hand-written bodies at ce5a8328 referenced only enrolled skills — so this is
PR-introduced, and they are instruction-level references, not passing mentions.

Cheapest meaningful fix: enroll ctx-learning-add + ctx-convention-add — the
capture-pair rationale that got ctx-task-add/ctx-decision-add in applies
verbatim, since wrap-up's core ceremony is capturing learnings and conventions.
For the rest (commit/reflect/digest/history/journal-enrich-all),
either enroll deliberately or record the dangling references as an accepted gap
in this Decisions section so the next audit doesn't rediscover it.

2. Parity test mirrors the transform's over-reach, so it can't catch it

internal/assets/read/skill/parity_test.go:88 · test-coverage · in diff

sed '/^allowed-tools:/d' deletes every column-0 allowed-tools: line
anywhere in the file, not just the frontmatter key — and stripAllowedTools
intentionally replicates that. Consequence: if a canonical skill body ever
gains a column-0 allowed-tools: line (most plausibly a fenced frontmatter
example in a skill about writing skills), the sync scripts will corrupt the
deployed body and this test will still pass, because expected and actual are
computed by the same over-reaching transform.

Today the tree is safe — every allowed-tools: occurrence sits at frontmatter
line 4, and the one body mention (ctx-skill-create SKILL.md:71) is a table
cell, not column 0 — but this is precisely the class of drift nobody re-checks
by hand. A cheap guard inside this test — assert the canonical source contains
at most one allowed-tools: line and that it sits inside the leading ---
block, and fail loudly otherwise — converts the silent corruption into a red
test without touching either sync script.

Nit

3. Gate restore can leave an untracked generated SKILL.md behind

Makefile:421 · robustness · in diff

If a skill directory is committed without a SKILL.md yet (enrollment done
halfway), the failing gate's restore path copies before/* back over but
cannot delete the SKILL.md the sync just created, leaving untracked residue
in a target that promises to restore state. diff -rq still fails correctly,
and the Copilot gate (line 406) has the identical shape — so this is
consistency-preserving as written. If you tighten it, tighten both siblings
together; don't let them diverge over this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: OpenCode skill parity — generate the tree from canonical Claude skills

2 participants