opencode-agent-skills-md 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +770 -0
- package/dist/plugin.mjs +1138 -0
- package/dist/src/cli/config.d.ts +144 -0
- package/dist/src/cli/install.d.ts +33 -0
- package/dist/src/cli/main.d.ts +11 -0
- package/dist/src/cli/real-fs.d.ts +6 -0
- package/dist/src/cli/status.d.ts +34 -0
- package/dist/src/cli/uninstall.d.ts +22 -0
- package/dist/src/host.d.ts +51 -0
- package/dist/src/index.d.ts +17 -0
- package/dist/src/plugin.d.ts +35 -0
- package/dist/src/sdk.d.ts +51 -0
- package/dist/src/tools.d.ts +86 -0
- package/package.json +48 -18
- package/{packages/opencode-agent-skills-md/src → src}/cli/main.ts +20 -4
- package/.beads/.local_version +0 -1
- package/.beads/README.md +0 -81
- package/.beads/config.yaml +0 -61
- package/.beads/deletions.jsonl +0 -1
- package/.beads/issues.jsonl +0 -64
- package/.beads/metadata.json +0 -4
- package/.gitattributes +0 -3
- package/.github/CODEOWNERS +0 -1
- package/.github/copilot-instructions.md +0 -78
- package/.github/dependabot.yml +0 -13
- package/.github/workflows/release.yml +0 -51
- package/.opencode/command/test-compaction.md +0 -9
- package/.opencode/command/test-find-skills.md +0 -7
- package/.opencode/command/test-read-skill-file.md +0 -14
- package/.opencode/command/test-run-skill-script.md +0 -13
- package/.opencode/command/test-skills.md +0 -14
- package/.opencode/command/test-use-skill.md +0 -10
- package/.opencode/skills/git-helper/SKILL.md +0 -65
- package/.opencode/skills/test-skill/SKILL.md +0 -43
- package/.opencode/skills/test-skill/example-config.json +0 -16
- package/.opencode/skills/test-skill/helper-docs.md +0 -29
- package/.opencode/skills/test-skill/scripts/echo-args +0 -14
- package/.opencode/skills/test-skill/scripts/greet +0 -6
- package/AGENTS.md +0 -43
- package/CHANGELOG.md +0 -178
- package/Justfile +0 -39
- package/README.md +0 -189
- package/openspec/changes/archive/2026-06-14-skills-core-decouple/specs/core-decoupling/spec.md +0 -74
- package/openspec/changes/archive/2026-06-14-skills-core-decouple/tasks.md +0 -64
- package/openspec/changes/archive/2026-06-14-skills-core-decouple/verify-report.md +0 -75
- package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/apply-progress.md +0 -136
- package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/archive-report.md +0 -77
- package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/design.md +0 -89
- package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/proposal.md +0 -65
- package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/specs/core-decoupling/spec.md +0 -77
- package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/tasks.md +0 -65
- package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/verify-report.md +0 -165
- package/openspec/specs/core-decoupling/spec.md +0 -110
- package/packages/core/package.json +0 -30
- package/packages/core/src/content.d.ts +0 -16
- package/packages/core/src/content.ts +0 -30
- package/packages/core/src/debug.ts +0 -16
- package/packages/core/src/discovery.d.ts +0 -86
- package/packages/core/src/discovery.ts +0 -257
- package/packages/core/src/index.d.ts +0 -20
- package/packages/core/src/index.ts +0 -55
- package/packages/core/src/match.d.ts +0 -19
- package/packages/core/src/match.ts +0 -75
- package/packages/core/src/parse.d.ts +0 -26
- package/packages/core/src/parse.ts +0 -141
- package/packages/core/src/scripts.d.ts +0 -17
- package/packages/core/src/scripts.ts +0 -79
- package/packages/core/src/search.d.ts +0 -83
- package/packages/core/src/search.ts +0 -188
- package/packages/core/src/types.d.ts +0 -82
- package/packages/core/src/types.ts +0 -131
- package/packages/core/src/walk.ts +0 -109
- package/packages/core/tests/agnostic.test.ts +0 -346
- package/packages/core/tests/content.test.ts +0 -65
- package/packages/core/tests/discovery.test.ts +0 -370
- package/packages/core/tests/package-boundary.test.ts +0 -310
- package/packages/core/tests/parse-trigger.test.ts +0 -282
- package/packages/core/tests/search.test.ts +0 -374
- package/packages/core/tests/subpath.test.ts +0 -87
- package/packages/core/tsconfig.json +0 -10
- package/packages/opencode-agent-skills-md/package.json +0 -42
- package/packages/opencode-agent-skills-md/rolldown.config.js +0 -48
- package/packages/opencode-agent-skills-md/tests/cli-commands.test.ts +0 -1423
- package/packages/opencode-agent-skills-md/tests/e2e/startup-smoke.test.ts +0 -66
- package/packages/opencode-agent-skills-md/tests/fixtures/skills/home/.claude/skills/claude-user-only-skill/SKILL.md +0 -8
- package/packages/opencode-agent-skills-md/tests/fixtures/skills/home/.config/opencode/skills/shared-skill/SKILL.md +0 -8
- package/packages/opencode-agent-skills-md/tests/fixtures/skills/home/.config/opencode/skills/user-only-skill/SKILL.md +0 -8
- package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.claude/skills/claude-project-only-skill/SKILL.md +0 -8
- package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/go-tester/SKILL.md +0 -12
- package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/nested/team/nested-skill/SKILL.md +0 -8
- package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/rust-tester/SKILL.md +0 -11
- package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/scripted-skill/SKILL.md +0 -8
- package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/scripted-skill/bin/echo.sh +0 -2
- package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/scripted-skill/docs/reference.md +0 -1
- package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/shared-skill/SKILL.md +0 -8
- package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/using-superpowers/SKILL.md +0 -8
- package/packages/opencode-agent-skills-md/tests/integration/helpers/mock-opencode.ts +0 -114
- package/packages/opencode-agent-skills-md/tests/integration/plugin.test.ts +0 -316
- package/packages/opencode-agent-skills-md/tests/integration/skill-discovery.test.ts +0 -315
- package/packages/opencode-agent-skills-md/tests/opencode/host.test.ts +0 -179
- package/packages/opencode-agent-skills-md/tests/opencode/plugin.test.ts +0 -551
- package/packages/opencode-agent-skills-md/tests/opencode/subpath.test.ts +0 -66
- package/packages/opencode-agent-skills-md/tests/opencode/tools.test.ts +0 -213
- package/packages/opencode-agent-skills-md/tests/package-boundary.test.ts +0 -346
- package/packages/opencode-agent-skills-md/tests/tools-security.test.ts +0 -72
- package/packages/opencode-agent-skills-md/tsconfig.build.json +0 -11
- package/packages/opencode-agent-skills-md/tsconfig.json +0 -10
- package/plans/001-ci-gate.md +0 -177
- package/plans/002-is-path-safe.md +0 -243
- package/plans/003-escape-prompts.md +0 -310
- package/plans/004-test-security-paths.md +0 -228
- package/plans/005-stop-swallowing-errors.md +0 -246
- package/plans/006-preserve-jsonc-commas.md +0 -144
- package/plans/007-write-before-purge.md +0 -144
- package/plans/008-reuse-walkdir-for-list-skill-files.md +0 -164
- package/plans/README.md +0 -43
- package/pnpm-workspace.yaml +0 -6
- package/tests/workspace.test.ts +0 -367
- package/tsconfig.json +0 -15
- /package/{packages/opencode-agent-skills-md/src → src}/cli/config.ts +0 -0
- /package/{packages/opencode-agent-skills-md/src → src}/cli/install.ts +0 -0
- /package/{packages/opencode-agent-skills-md/src → src}/cli/real-fs.ts +0 -0
- /package/{packages/opencode-agent-skills-md/src → src}/cli/status.ts +0 -0
- /package/{packages/opencode-agent-skills-md/src → src}/cli/uninstall.ts +0 -0
- /package/{packages/opencode-agent-skills-md/src → src}/host.ts +0 -0
- /package/{packages/opencode-agent-skills-md/src → src}/index.ts +0 -0
- /package/{packages/opencode-agent-skills-md/src → src}/plugin.ts +0 -0
- /package/{packages/opencode-agent-skills-md/src → src}/sdk.ts +0 -0
- /package/{packages/opencode-agent-skills-md/src → src}/tools.ts +0 -0
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
# Tasks: Skills Core Decouple
|
|
2
|
-
|
|
3
|
-
## Review Workload Forecast
|
|
4
|
-
|
|
5
|
-
| Field | Value |
|
|
6
|
-
|-------|-------|
|
|
7
|
-
| Estimated changed lines | PR1≈350; PR2≈250; PR3≈150; aggregate≈750 |
|
|
8
|
-
| 400-line budget risk | Low per PR |
|
|
9
|
-
| Chained PRs recommended | Yes |
|
|
10
|
-
| Suggested split | PR1 core-extraction → PR2 opencode-adapter → PR3 subpath-exports |
|
|
11
|
-
| Delivery strategy | force-chained |
|
|
12
|
-
| Chain strategy | stacked-to-main |
|
|
13
|
-
|
|
14
|
-
Decision needed before apply: No
|
|
15
|
-
Chained PRs recommended: Yes
|
|
16
|
-
Chain strategy: stacked-to-main
|
|
17
|
-
400-line budget risk: Low
|
|
18
|
-
|
|
19
|
-
### Suggested Work Units
|
|
20
|
-
|
|
21
|
-
| Unit | Goal | Likely PR | Notes |
|
|
22
|
-
|------|------|-----------|-------|
|
|
23
|
-
| 1 | Extract portable core with import guard | PR 1 | Base=main; merge after `pnpm run typecheck` + `pnpm test` |
|
|
24
|
-
| 2 | Add OpenCode host and thin adapter | PR 2 | Base=main after PR1 merge; keep root behavior unchanged |
|
|
25
|
-
| 3 | Publish subpath exports and built smoke tests | PR 3 | Base=main after PR2 merge; verify build + e2e |
|
|
26
|
-
|
|
27
|
-
## Phase 1: PR1 — Core Extraction
|
|
28
|
-
|
|
29
|
-
- [x] 1.1 Capture a green baseline with `pnpm run typecheck` and `pnpm test` before moving files.
|
|
30
|
-
- [x] 1.2 RED: add `tests/core/agnostic.test.ts` with a static walk over `dist/core/**` for zero `@opencode-ai/plugin` imports.
|
|
31
|
-
- [x] 1.3 Move host-agnostic code from `src/utils.ts` and `src/skills.ts` into `src/core/{types,parse,discovery,scripts,match,content}.ts`.
|
|
32
|
-
- [x] 1.4 Add `src/core/index.ts`; update `src/utils.ts` and `src/skills.ts` to re-export or consume core without behavior changes.
|
|
33
|
-
- [x] 1.5 Update `rolldown.config.js` for a temporary `dist/core` entry while preserving the current plugin build. *(Superseded by PR3 3.2 — multi-entry build emits both `dist/opencode/index.js` and `dist/core/index.js` plus the legacy `dist/plugin.mjs` alias.)*
|
|
34
|
-
- [x] 1.6 GREEN gate: `pnpm run typecheck` and `pnpm test` pass with the new core boundary.
|
|
35
|
-
|
|
36
|
-
## Phase 2: PR2 — OpenCode Adapter
|
|
37
|
-
|
|
38
|
-
- [x] 2.1 Add `src/opencode/host.ts` as the only concrete `SkillHostClient` and `SkillHostSession` implementation.
|
|
39
|
-
- [x] 2.2 Add `src/opencode/tools.ts` and rewrite tool factories to compose core logic through the host.
|
|
40
|
-
- [x] 2.3 Move plugin composition to `src/opencode/plugin.ts`; keep `src/plugin.ts` as a thin compatibility shim until PR3.
|
|
41
|
-
- [x] 2.4 Move `src/superpowers.ts` to `src/opencode/superpowers.ts` and wire `src/opencode/index.ts` as the adapter entry.
|
|
42
|
-
- [x] 2.5 Verify R5/R6 by running `tests/integration/plugin.test.ts` and `tests/e2e/startup-smoke.test.ts` unchanged.
|
|
43
|
-
- [x] 2.6 GREEN gate: `pnpm run typecheck` and `pnpm test` pass before merge.
|
|
44
|
-
|
|
45
|
-
## Phase 3: PR3 — Subpath Exports (public surface change)
|
|
46
|
-
|
|
47
|
-
- [x] 3.1 Add `exports` map to `package.json` with `.` and `./core` subpaths (each with `types` + `import` + `default` conditions) and point `main` at `dist/opencode/index.js`.
|
|
48
|
-
- [x] 3.2 Rewrite `rolldown.config.js` to multi-entry emit `dist/opencode/index.js` and `dist/core/index.js`; add `tsconfig.build.json` for `tsc --emitDeclarationOnly` so `.d.ts` files travel with the JS chunks.
|
|
49
|
-
- [x] 3.3 Add `tests/core/subpath.test.ts` — resolves `opencode-agent-skills-md/core` via the package's exports field, asserts the portable API is exported, and walks the built chunk to prove no `@opencode-ai/plugin` reference leaks in.
|
|
50
|
-
- [x] 3.4 Add `tests/opencode/subpath.test.ts` — resolves `opencode-agent-skills-md` (root) via the exports field, asserts the default export + `SkillsPlugin` are the same factory function, and proves module load is side-effect safe.
|
|
51
|
-
- [x] 3.5 Add `pretest` hook that runs `pnpm run build` first so the subpath tests always run against fresh built artifacts.
|
|
52
|
-
- [x] 3.6 Remove `src/plugin.ts` compat shim (now redundant); build entry is `src/opencode/index.ts` directly. A legacy `dist/plugin.mjs` alias is preserved via a third rolldown entry so any downstream consumer still importing the old path keeps working.
|
|
53
|
-
- [x] 3.7 Update `README.md` with a "Programmatic subpath exports" section documenting both subpaths, the intended consumer (harness authors), and a code example using the core.
|
|
54
|
-
- [x] 3.8 GREEN gate (final): `pnpm run typecheck` + `pnpm test` + `pnpm run build` all green; the new subpath tests pass against the freshly built artifacts.
|
|
55
|
-
- [x] 3.9 Update `openspec/changes/skills-core-decouple/tasks.md` to mark all PR3 tasks done and persist the final apply-progress to engram.
|
|
56
|
-
|
|
57
|
-
### PR3 Outcome
|
|
58
|
-
|
|
59
|
-
- `pnpm run typecheck` — clean (0 errors)
|
|
60
|
-
- `pnpm test` — 42/42 (21 unit + 3 agnostic + 3 core-subpath + 8 opencode-host + 3 opencode-subpath + 3 integration + 1 e2e)
|
|
61
|
-
- `pnpm run build` — emits `dist/opencode/{index.js,index.d.ts,...}`, `dist/core/{index.js,index.d.ts,...}`, and the legacy `dist/plugin.mjs` alias
|
|
62
|
-
- The `src/opencode/tools.ts` factory consts needed explicit `: ReturnType<typeof tool>` annotations to break a Zod-shape leak in the inferred return type that broke `tsc --emitDeclarationOnly` with TS2883 (non-portable inferred type). Internal change only — no behavior delta, no public API change.
|
|
63
|
-
- The `package.json#exports` block needed a `default` condition on each subpath in addition to `import` so Node 24 can resolve the package via self-reference when called from a CJS context (`require.resolve`).
|
|
64
|
-
- The integration test (`tests/integration/plugin.test.ts`) and the e2e test (`tests/e2e/startup-smoke.test.ts`) had their import targets updated to the new entry points (`src/opencode` and `dist/opencode/index.js` respectively).
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# Verification Report: skills-core-decouple
|
|
2
|
-
|
|
3
|
-
**Change:** skills-core-decouple
|
|
4
|
-
**Phase:** verify
|
|
5
|
-
**Mode:** strict_tdd=true
|
|
6
|
-
**Date:** 2026-06-14
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## Command Evidence
|
|
11
|
-
|
|
12
|
-
| Command | Result | Evidence |
|
|
13
|
-
|---------|--------|----------|
|
|
14
|
-
| `pnpm run typecheck` | PASS | `tsc --noEmit` exits 0, 0 errors |
|
|
15
|
-
| `pnpm test` | PASS | 42/42 tests pass (21 unit + 3 agnostic + 3 core-subpath + 8 opencode-host + 3 opencode-subpath + 3 integration + 1 e2e) |
|
|
16
|
-
| `pnpm run build` | PASS | Emits `dist/opencode/index.js`, `dist/core/index.js`, `dist/_chunks/*`, and legacy `dist/plugin.mjs` alias |
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## Requirement Compliance Matrix
|
|
21
|
-
|
|
22
|
-
| Requirement | Status | Evidence |
|
|
23
|
-
|-------------|--------|----------|
|
|
24
|
-
| R1 — Core module independence | **PASS** | Grep `@opencode-ai/plugin` in `src/core/**/*.ts` → 0 matches. Test `tests/core/agnostic.test.ts` passes. |
|
|
25
|
-
| R2 — Boundary interface | **PASS** | `SkillHostClient` and `SkillHostSession` declared in `src/core/types.ts`. Only `src/opencode/host.ts` contains a concrete implementation. Grep across `src/` shows no other implementation. |
|
|
26
|
-
| R3 — Backward-compatible root export | **PASS** | `tests/opencode/subpath.test.ts` passes: root resolves to `dist/opencode/index.js`, default export is `SkillsPlugin` factory. Tool names unchanged (`get_available_skills`, `read_skill_file`, `run_skill_script`, `use_skill`). |
|
|
27
|
-
| R4 — Framework-agnostic subpath export | **PASS** | `tests/core/subpath.test.ts` passes: `opencode-agent-skills-md/core` resolves via exports field to `dist/core/index.js`. Build emits `dist/core/index.js` + `.d.ts` files. Static walk of dist proves no `@opencode-ai/plugin` reference leaks in. |
|
|
28
|
-
| R5 — Discovery semantics preservation | **PASS** | `src/core/discovery.ts` `getDefaultOpencodeRoots()` defines 4-location priority (`.opencode/skills/`, `.claude/skills/`, `~/.config/opencode/skills/`, `~/.claude/skills/`). First-match-wins implemented at line 130: `if (!skill || skillsByName.has(skill.name)) continue;`. `tests/integration/plugin.test.ts` passes. |
|
|
29
|
-
| R6 — Public surface freeze | **PASS** | `src/opencode/tools.ts` creates 4 tool factories with unchanged names (`GetAvailableSkills`, `ReadSkillFile`, `RunSkillScript`, `UseSkill`). All `tests/integration/*` and `tests/e2e/*` pass without modification. |
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## Spec Scenario Compliance
|
|
34
|
-
|
|
35
|
-
| Scenario | Covered By | Result |
|
|
36
|
-
|----------|------------|--------|
|
|
37
|
-
| core is decoupled from the OpenCode SDK | `tests/core/agnostic.test.ts` + static grep | PASS |
|
|
38
|
-
| opencode host is the only concrete implementation | `src/opencode/host.ts` + grep search | PASS |
|
|
39
|
-
| root export still loads the OpenCode plugin | `tests/opencode/subpath.test.ts` | PASS |
|
|
40
|
-
| subpath export does not pull in the OpenCode SDK | `tests/core/subpath.test.ts` | PASS |
|
|
41
|
-
| discovery priority and first-match-wins are preserved | `tests/integration/plugin.test.ts` | PASS |
|
|
42
|
-
| public tool surface is unchanged | All test suites (42/42) | PASS |
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## Task Completion
|
|
47
|
-
|
|
48
|
-
All tasks in `openspec/changes/skills-core-decouple/tasks.md` are checked `[x]`.
|
|
49
|
-
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
## Findings
|
|
53
|
-
|
|
54
|
-
### CRITICAL
|
|
55
|
-
None.
|
|
56
|
-
|
|
57
|
-
### WARNING
|
|
58
|
-
None.
|
|
59
|
-
|
|
60
|
-
### SUGGESTION
|
|
61
|
-
None.
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## Final Verdict
|
|
66
|
-
|
|
67
|
-
**PASS**
|
|
68
|
-
|
|
69
|
-
All 6 requirements verified. All 42 tests green. Build emits both subpaths correctly. Public surface unchanged.
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## Next Recommended
|
|
74
|
-
|
|
75
|
-
`sdd-archive` — ready to sync delta specs and close the change.
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
# Apply Progress: Fix Skill-Loading Regression
|
|
2
|
-
|
|
3
|
-
## Status: ok
|
|
4
|
-
|
|
5
|
-
All chained PR tasks complete. Verification clean.
|
|
6
|
-
|
|
7
|
-
## Commit Stack
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
d2c3584 test: correct dedupe assertion to allow other matches
|
|
11
|
-
c1f5b27 chore: verify skill loading regression fix
|
|
12
|
-
8c7de19 refactor: clean up discovery source helpers
|
|
13
|
-
7e4293e fix: restore baseline skill discovery sources
|
|
14
|
-
b764c15 test: add discovery breadth regression coverage
|
|
15
|
-
9e975ab refactor: preserve optional skill callback seam
|
|
16
|
-
fd4ab41 fix: restore use-skill callback wiring
|
|
17
|
-
c64d4e7 test: add skill loading callback regression coverage
|
|
18
|
-
01c4b46 chore(sdd): add fix-skill-loading-regression change artifacts
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## Phase Summary
|
|
22
|
-
|
|
23
|
-
### PR 1: Callback wiring (host-adapter)
|
|
24
|
-
|
|
25
|
-
- **1.1 RED** — `c64d4e7`: failing regression tests in
|
|
26
|
-
`tests/opencode/plugin.test.ts` (3 new) and
|
|
27
|
-
`tests/integration/plugin.test.ts` (1 new).
|
|
28
|
-
- **1.2 GREEN** — `fd4ab41`: added `OnSkillLoaded` type alias and
|
|
29
|
-
optional 4th arg on `createSkillTools` in `src/opencode/tools.ts`;
|
|
30
|
-
passed a 4-line callback that records the loaded skill in
|
|
31
|
-
`loadedSkillsPerSession` from `src/opencode/plugin.ts`.
|
|
32
|
-
- **1.3 REFACTOR** — `9e975ab`: extracted a tiny `sendMessage` helper
|
|
33
|
-
in `tests/opencode/plugin.test.ts` to reduce ~30 lines of chat.message
|
|
34
|
-
dispatch boilerplate. Production code unchanged.
|
|
35
|
-
|
|
36
|
-
### PR 2: Discovery breadth (core)
|
|
37
|
-
|
|
38
|
-
- **2.1 RED** — `b764c15`: added regression nets in
|
|
39
|
-
`tests/integration/skill-discovery.test.ts` covering all four
|
|
40
|
-
priority locations (`.opencode/skills`, `.claude/skills`,
|
|
41
|
-
`~/.config/opencode/skills`, `~/.claude/skills`), first-match-wins
|
|
42
|
-
shadowing, default duplicate-warning callback, and the partial-trigger
|
|
43
|
-
R5 scenario. Added fixtures under
|
|
44
|
-
`tests/fixtures/skills/{project,home}/.claude/skills/`.
|
|
45
|
-
- **2.2 GREEN** — `7e4293e`: tightened JSDoc on `getDefaultOpencodeRoots`
|
|
46
|
-
to reference pre-refactor commit `c2d8e74` and the intentional
|
|
47
|
-
maxDepth widening (commit `12de52a`).
|
|
48
|
-
- **2.3 REFACTOR** — `8c7de19`: extracted `DEFAULT_DISCOVERY_MAX_DEPTH`
|
|
49
|
-
constant to remove the repeated `maxDepth: 3` magic number.
|
|
50
|
-
|
|
51
|
-
### PR 3: Optional cleanup / verification
|
|
52
|
-
|
|
53
|
-
- **3.1 RED/GREEN** — Coverage is complete for spec R3 (callback fires,
|
|
54
|
-
dedupe, missing-callback) and R5 (priority + first-match-wins,
|
|
55
|
-
baseline match, partial-trigger). No additional regression needed.
|
|
56
|
-
- **3.2 REFACTOR** — Production code is already minimal. No
|
|
57
|
-
behavior-neutral cleanup that would reduce duplication.
|
|
58
|
-
- **3.3 VERIFY** — `c1f5b27`: empty chore commit acknowledging
|
|
59
|
-
`pnpm run typecheck` clean and `pnpm test` 102/102 green.
|
|
60
|
-
|
|
61
|
-
## Files Changed
|
|
62
|
-
|
|
63
|
-
### Production (3 files, 33 insertions, 14 deletions)
|
|
64
|
-
|
|
65
|
-
- `src/opencode/tools.ts` — added `OnSkillLoaded` type and optional
|
|
66
|
-
callback parameter on `createSkillTools`.
|
|
67
|
-
- `src/opencode/plugin.ts` — wired the callback to update
|
|
68
|
-
`loadedSkillsPerSession` in the module-level Map.
|
|
69
|
-
- `src/core/discovery.ts` — JSDoc clarified and `DEFAULT_DISCOVERY_MAX_DEPTH`
|
|
70
|
-
constant extracted.
|
|
71
|
-
|
|
72
|
-
### Tests (2 files modified, 4 new tests)
|
|
73
|
-
|
|
74
|
-
- `tests/opencode/plugin.test.ts` — added 3 regression tests covering
|
|
75
|
-
callback wiring, dedupe, and missing-callback. Extracted `sendMessage`
|
|
76
|
-
helper.
|
|
77
|
-
- `tests/integration/plugin.test.ts` — added 1 end-to-end regression
|
|
78
|
-
test for the full plugin path (bootstrap → use_skill → chat.message
|
|
79
|
-
dedupe).
|
|
80
|
-
|
|
81
|
-
### Fixtures (2 new files)
|
|
82
|
-
|
|
83
|
-
- `tests/fixtures/skills/project/.claude/skills/claude-project-only-skill/SKILL.md`
|
|
84
|
-
- `tests/fixtures/skills/home/.claude/skills/claude-user-only-skill/SKILL.md`
|
|
85
|
-
|
|
86
|
-
### Change artifacts (4 new files, tracked in `01c4b46`)
|
|
87
|
-
|
|
88
|
-
- `openspec/changes/fix-skill-loading-regression/{proposal,design,tasks}.md`
|
|
89
|
-
- `openspec/changes/fix-skill-loading-regression/specs/core-decoupling/spec.md`
|
|
90
|
-
|
|
91
|
-
## TDD Cycle Evidence
|
|
92
|
-
|
|
93
|
-
| Task | Test File | Layer | Safety Net | RED | GREEN | TRIANGULATE | REFACTOR |
|
|
94
|
-
|------|-----------|-------|------------|-----|-------|-------------|----------|
|
|
95
|
-
| 1.1 | `tests/opencode/plugin.test.ts` | Unit | ✅ 18/18 | ✅ Written (2 fail) | ✅ Passed | ✅ 3 cases | ✅ Clean |
|
|
96
|
-
| 1.1 | `tests/integration/plugin.test.ts` | Integration | ✅ 18/18 | ✅ Written (1 fail) | ✅ Passed | ➖ Single | ✅ Clean |
|
|
97
|
-
| 1.2 | (production code) | — | ✅ 18/18 | ✅ Written | ✅ Passed | — | — |
|
|
98
|
-
| 1.3 | (test refactor) | Unit | — | — | — | — | ✅ Helper extracted |
|
|
99
|
-
| 2.1 | `tests/integration/skill-discovery.test.ts` | Integration | ✅ 22/22 | ✅ Written (regression net) | ✅ Passed | ✅ 4 cases | ✅ Clean |
|
|
100
|
-
| 2.2 | (production doc update) | — | — | — | — | — | ✅ JSDoc tightened |
|
|
101
|
-
| 2.3 | (production refactor) | — | — | — | — | — | ✅ Constant extracted |
|
|
102
|
-
|
|
103
|
-
## Verification
|
|
104
|
-
|
|
105
|
-
- `pnpm run typecheck` — clean (0 errors)
|
|
106
|
-
- `pnpm test` (full suite: unit + core + opencode + integration + e2e)
|
|
107
|
-
— 102 pass / 0 fail / 0 skipped
|
|
108
|
-
- `node --import tsx --test src/utils.test.ts tests/core/*.test.ts
|
|
109
|
-
tests/opencode/plugin.test.ts tests/integration/plugin.test.ts
|
|
110
|
-
tests/integration/skill-discovery.test.ts tests/e2e/*.test.ts`
|
|
111
|
-
— 89 pass / 0 fail
|
|
112
|
-
|
|
113
|
-
## Notable Discoveries (for sdd-verify)
|
|
114
|
-
|
|
115
|
-
- **Dedupe assertion gotcha**: An earlier draft of the dedupe test
|
|
116
|
-
asserted that zero `<skill-evaluation-required>` injections fire
|
|
117
|
-
after `use_skill`. The keyword matcher legitimately matches other
|
|
118
|
-
skills that share tokens with the query (e.g., `user-only-skill`,
|
|
119
|
-
`nested-skill`, `shared-skill` all match `"use the script skill"`
|
|
120
|
-
via the `script`/`skill`/`use` tokens). The correct regression is
|
|
121
|
-
that the loaded skill is filtered OUT of the matched list — see the
|
|
122
|
-
`for (const prompt of evaluationInjections)` loop in both test files.
|
|
123
|
-
- **`getDefaultOpencodeRoots` maxDepth deviation**: Pre-refactor
|
|
124
|
-
`c2d8e74` used `maxDepth: 1` for the Claude-side roots. Commit
|
|
125
|
-
`12de52a` widened them to 3 deliberately. The current code preserves
|
|
126
|
-
the widening; the spec R5 only requires the four-location priority,
|
|
127
|
-
not the depths. The regression net locks the depth=3 choice.
|
|
128
|
-
- **Plugin cache / marketplace discovery**: `c2d8e74` discovered
|
|
129
|
-
`~/.claude/plugins/cache/` and `~/.claude/plugins/marketplaces/` via
|
|
130
|
-
`claude.ts`. These are intentionally out of scope for this fix; the
|
|
131
|
-
proposal scopes the change to the four standard locations.
|
|
132
|
-
- **Callback wiring shape**: `UseSkill` already accepted an optional
|
|
133
|
-
`onSkillLoaded(sessionID, skillName)` parameter before the fix.
|
|
134
|
-
`createSkillTools` simply never accepted/forwarded it. The fix is a
|
|
135
|
-
minimal signature change on `createSkillTools`; `UseSkill` and the
|
|
136
|
-
host adapter logic are unchanged.
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# Archive Report: fix-skill-loading-regression
|
|
2
|
-
|
|
3
|
-
## Change Metadata
|
|
4
|
-
|
|
5
|
-
| Field | Value |
|
|
6
|
-
|-------|-------|
|
|
7
|
-
| Change name | `fix-skill-loading-regression` |
|
|
8
|
-
| Archived date | 2026-06-17 |
|
|
9
|
-
| Archive path | `openspec/changes/archive/2026-06-17-fix-skill-loading-regression/` |
|
|
10
|
-
| Spec domain | `core-decoupling` |
|
|
11
|
-
| Delivery strategy | force-chained |
|
|
12
|
-
| Chain strategy | stacked-to-main |
|
|
13
|
-
|
|
14
|
-
### Commits (9 total, per tasks.md)
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
d2c3584 test: correct dedupe assertion to allow other matches
|
|
18
|
-
c1f5b27 chore: verify skill loading regression fix
|
|
19
|
-
8c7de19 refactor: clean up discovery source helpers
|
|
20
|
-
7e4293e fix: restore baseline skill discovery sources
|
|
21
|
-
b764c15 test: add discovery breadth regression coverage
|
|
22
|
-
9e975ab refactor: preserve optional skill callback seam
|
|
23
|
-
fd4ab41 fix: restore use-skill callback wiring
|
|
24
|
-
c64d4e7 test: add skill loading callback regression coverage
|
|
25
|
-
01c4b46 chore(sdd): add fix-skill-loading-regression change artifacts
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Spec Delta Summary
|
|
29
|
-
|
|
30
|
-
### MODIFIED Requirements
|
|
31
|
-
|
|
32
|
-
| Requirement | Domain | Action | Details |
|
|
33
|
-
|-------------|--------|--------|---------|
|
|
34
|
-
| R3 — Backward-Compatible Root Export | core-decoupling | MODIFIED | Strengthened to assert observable skill loading: `onSkillLoaded` callback fires once per session, `SKILL.md` injected once per session, session dedupe via `loadedSkillsPerSession`. Added 3 new scenarios: callback fires, session dedupe, missing callback safe. |
|
|
35
|
-
| R5 — Discovery Semantics Preservation | core-decoupling | MODIFIED | Strengthened to pin the surfaced skill set to pre-refactor baseline commit `c2d8e74`. Added 2 new scenarios: matches pre-refactor skill set, partial-trigger regression. |
|
|
36
|
-
|
|
37
|
-
### Unchanged Requirements
|
|
38
|
-
R1 (Core Module Independence), R2 (Boundary Interface Location), R4 (Framework-Agnostic Subpath Export), R6 (Public Surface Freeze) — unchanged by this delta.
|
|
39
|
-
|
|
40
|
-
## Verification Result
|
|
41
|
-
|
|
42
|
-
**PASS** — `verify-report.md` (2026-06-17)
|
|
43
|
-
- 9/9 tasks complete
|
|
44
|
-
- 102/102 tests green (unit: 42, core: 20, opencode: 22, integration: 17, e2e: 1)
|
|
45
|
-
- Typecheck: clean
|
|
46
|
-
- TDD compliance: 7/7 checks passed
|
|
47
|
-
- CRITICAL issues: none
|
|
48
|
-
- 7/7 spec scenarios compliant (R3: 4/4, R5: 3/3)
|
|
49
|
-
|
|
50
|
-
## Artifacts
|
|
51
|
-
|
|
52
|
-
### Archived Change
|
|
53
|
-
- `openspec/changes/archive/2026-06-17-fix-skill-loading-regression/proposal.md`
|
|
54
|
-
- `openspec/changes/archive/2026-06-17-fix-skill-loading-regression/design.md`
|
|
55
|
-
- `openspec/changes/archive/2026-06-17-fix-skill-loading-regression/specs/core-decoupling/spec.md` (delta)
|
|
56
|
-
- `openspec/changes/archive/2026-06-17-fix-skill-loading-regression/tasks.md`
|
|
57
|
-
- `openspec/changes/archive/2026-06-17-fix-skill-loading-regression/verify-report.md`
|
|
58
|
-
- `openspec/changes/archive/2026-06-17-fix-skill-loading-regression/apply-progress.md`
|
|
59
|
-
|
|
60
|
-
### Source of Truth Updated
|
|
61
|
-
- `openspec/specs/core-decoupling/spec.md` — R3 and R5 updated in place
|
|
62
|
-
|
|
63
|
-
## Lessons Learned
|
|
64
|
-
|
|
65
|
-
1. **Callback seam was pre-existing but unwired**: `UseSkill` already accepted `onSkillLoaded?` before the fix; `createSkillTools` simply never accepted or forwarded it. The fix was a minimal 2-line production change — a good reminder that "broken" behavior is often a missing wire, not a missing feature.
|
|
66
|
-
|
|
67
|
-
2. **Dedupe assertion nuance**: The correct regression target for session dedupe is that the *loaded* skill is filtered from `<skill-evaluation-required>` injections — not that zero injections fire (other skills may match the same query tokens). Getting this wrong produces false negatives in the test.
|
|
68
|
-
|
|
69
|
-
3. **maxDepth deviation from baseline was deliberate**: Pre-refactor `c2d8e74` used `maxDepth: 1` for Claude-side roots; `12de52a` widened to 3 deliberately. The JSDoc now documents this intentionally and the regression net locks `maxDepth: 3` in place.
|
|
70
|
-
|
|
71
|
-
4. **Discovery breadth vs. semantic search**: The refactor kept trigger-aware search, tags, Zod validation, and path safety — only the broad/semantic embedding matcher was removed. The fix restores breadth by widening `getDefaultOpencodeRoots` to the four standard locations without reintroducing embeddings.
|
|
72
|
-
|
|
73
|
-
5. **Plugin/marketplace discovery out of scope**: The `c2d8e74` baseline also surfaced `~/.claude/plugins/cache/` and `~/.claude/plugins/marketplaces/`. The proposal correctly scoped the fix to the four standard locations only, leaving marketplace discovery as future work.
|
|
74
|
-
|
|
75
|
-
## SDD Cycle Complete
|
|
76
|
-
|
|
77
|
-
This change was fully planned (`sdd-propose`), specified (`sdd-spec`), designed (`sdd-design`), task-planned (`sdd-tasks`), implemented (`sdd-apply`), verified (`sdd-verify`), and archived (`sdd-archive`). The delta spec has been merged into `openspec/specs/core-decoupling/spec.md`. The archived change at `openspec/changes/archive/2026-06-17-fix-skill-loading-regression/` is the immutable audit trail.
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# Design: Fix Skill-Loading Regression
|
|
2
|
-
|
|
3
|
-
## Technical Approach
|
|
4
|
-
|
|
5
|
-
Restore the two regressions captured in Engram #1734 (`bugfix/skill-loading-regression`) and #1736 (`bugfix/skill-loading-regression-plan`) with the smallest host-adapter changes. First, thread the existing `onSkillLoaded` callback from `SkillsPlugin` through `createSkillTools()` into `UseSkill()` so a successful `use_skill` call updates session loaded-skill state again. Second, align `discoverAllSkills()` default source coverage with the pre-refactor baseline (`c2d8e74`) while keeping the current core/host split, search engine, tag filtering, trigger-aware ranking, Zod parsing, and path-safety checks intact. This design implements the proposal and gives the pending `core-decoupling` R3/R5 spec delta concrete code targets.
|
|
6
|
-
|
|
7
|
-
Strict TDD order: add failing regression tests first, implement the minimum wiring/discovery fix, then refactor only if duplication appears.
|
|
8
|
-
|
|
9
|
-
## Architecture Decisions
|
|
10
|
-
|
|
11
|
-
### Decision: Restore loaded-skill state through the existing callback seam
|
|
12
|
-
|
|
13
|
-
| Option | Tradeoff | Decision |
|
|
14
|
-
|---|---|---|
|
|
15
|
-
| Update `loadedSkillsPerSession` directly inside `UseSkill` | Couples tool code to plugin session state | Rejected |
|
|
16
|
-
| Pass `onSkillLoaded` from `plugin.ts` → `createSkillTools()` → `UseSkill()` | Small signature change, preserves core/host boundaries | Chosen |
|
|
17
|
-
|
|
18
|
-
Rationale: the callback already exists in `UseSkill`; the regression is that `createSkillTools()`/`SkillsPlugin` stopped threading it.
|
|
19
|
-
|
|
20
|
-
### Decision: Restore discovery breadth in `core/discovery.ts`, not in search or host code
|
|
21
|
-
|
|
22
|
-
| Option | Tradeoff | Decision |
|
|
23
|
-
|---|---|---|
|
|
24
|
-
| Reintroduce old semantic matcher | Larger rollback, discards current trigger/tag work | Rejected |
|
|
25
|
-
| Expand default discovery roots/source handling to match baseline coverage | Narrow fix, keeps current search/ranking stack | Chosen |
|
|
26
|
-
|
|
27
|
-
Rationale: discovery breadth is a source-enumeration concern. `searchSkills()`, trigger scoring, Zod validation, and safe file access stay unchanged.
|
|
28
|
-
|
|
29
|
-
## Data Flow
|
|
30
|
-
|
|
31
|
-
```text
|
|
32
|
-
chat.message
|
|
33
|
-
-> getSkillSummaries() / matchSkillsByKeyword()
|
|
34
|
-
-> synthetic skill-evaluation prompt
|
|
35
|
-
-> model calls use_skill
|
|
36
|
-
-> createSkillTools().UseSkill()
|
|
37
|
-
-> host.injectContent(<skill ...>)
|
|
38
|
-
-> onSkillLoaded(sessionID, skillName)
|
|
39
|
-
-> loadedSkillsPerSession.add(skillName)
|
|
40
|
-
-> later chat.message skips already-loaded skills
|
|
41
|
-
|
|
42
|
-
discoverAllSkills(directory)
|
|
43
|
-
-> baseline-aligned default roots
|
|
44
|
-
-> findSkillsRecursive()
|
|
45
|
-
-> parseSkillFile() [Zod]
|
|
46
|
-
-> Map<string, Skill> first-match-wins
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## File Changes
|
|
50
|
-
|
|
51
|
-
| File | Action | Description |
|
|
52
|
-
|---|---|---|
|
|
53
|
-
| `src/opencode/tools.ts` | Modify | Add an optional `onSkillLoaded` parameter to `createSkillTools()` and pass it into `UseSkill()` without changing tool behavior otherwise. |
|
|
54
|
-
| `src/opencode/plugin.ts` | Modify | Provide the callback that records loaded skills per session and keep keyword matching / synthetic injection behavior unchanged. |
|
|
55
|
-
| `src/core/discovery.ts` | Modify | Reconcile default discovery roots/source handling with baseline `c2d8e74`, preserving first-match-wins and duplicate warnings. |
|
|
56
|
-
| `tests/integration/plugin.test.ts` | Modify | Add RED/GREEN regression coverage for baseline discovery breadth and end-to-end tool loading behavior. |
|
|
57
|
-
| `tests/opencode/plugin.test.ts` | Modify | Add focused host-adapter regression coverage proving `use_skill` updates loaded-skill session state and prevents duplicate re-suggestion. |
|
|
58
|
-
|
|
59
|
-
## Interfaces / Contracts
|
|
60
|
-
|
|
61
|
-
```ts
|
|
62
|
-
type OnSkillLoaded = (sessionID: string, skillName: string) => void;
|
|
63
|
-
|
|
64
|
-
export function createSkillTools(
|
|
65
|
-
host: OpencodeSkillHost,
|
|
66
|
-
$: PluginInput["$"],
|
|
67
|
-
directory: string,
|
|
68
|
-
onSkillLoaded?: OnSkillLoaded
|
|
69
|
-
): SkillTools;
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
`getDefaultOpencodeRoots(directory)` remains the canonical discovery-source definition. The fix may adjust its returned roots/depths to match the pre-refactor baseline, but it must continue returning `DiscoveryPath[]` and must not move host-specific knowledge into search or parsing modules.
|
|
73
|
-
|
|
74
|
-
## Testing Strategy
|
|
75
|
-
|
|
76
|
-
| Layer | What to Test | Approach |
|
|
77
|
-
|---|---|---|
|
|
78
|
-
| Unit/host | `use_skill` marks a skill as loaded again | In `tests/opencode/plugin.test.ts`, call `use_skill`, then send a matching message and assert no duplicate matched-skill injection is produced for that session. |
|
|
79
|
-
| Integration | Discovery returns the baseline-visible skill set | In `tests/integration/plugin.test.ts`, extend the temp workspace as needed and compare discovered labels/names against the pre-refactor source expectations. |
|
|
80
|
-
| Integration | Tool wiring still injects skill content | Reuse the mock host client to assert `<skill ...>` injection still happens while the callback seam is restored. |
|
|
81
|
-
| E2E | N/A | No separate UI harness; session bookkeeping is the local proxy for icon-visible behavior. |
|
|
82
|
-
|
|
83
|
-
## Migration / Rollout
|
|
84
|
-
|
|
85
|
-
No migration required. Rollout is a normal bugfix; if the change grows past the 400-line review budget, keep the delivery split aligned with the force-chained stacked PR strategy.
|
|
86
|
-
|
|
87
|
-
## Open Questions
|
|
88
|
-
|
|
89
|
-
- [ ] None; verify the exact restored source set against `c2d8e74` during RED test authoring.
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# Proposal: Fix Skill-Loading Regression
|
|
2
|
-
|
|
3
|
-
## Intent
|
|
4
|
-
|
|
5
|
-
After the core-decoupling / discovery-filtering refactor, the plugin no longer visibly loads skills as before. Two regressions: (1) `onSkillLoaded` is no longer wired through `createSkillTools`/`UseSkill`, so loaded-skill state and the TUI icon never update; (2) discovery narrowed to literal-token search over local roots, so skills the old broad/semantic matcher surfaced no longer appear — blocking the follow-up `use_skill` call. This restores observable behavior while keeping the refactor's architectural wins.
|
|
6
|
-
|
|
7
|
-
## Scope
|
|
8
|
-
|
|
9
|
-
### In Scope
|
|
10
|
-
- Re-wire `onSkillLoaded` through `createSkillTools` → `UseSkill` in `src/opencode/tools.ts` / `src/opencode/plugin.ts`
|
|
11
|
-
- Restore pre-refactor discovery breadth in `src/core/discovery.ts` (surface the same skill set as baseline commit `c2d8e74`)
|
|
12
|
-
- Regression tests in `tests/integration/plugin.test.ts` and `tests/opencode/plugin.test.ts`
|
|
13
|
-
- Strengthen `core-decoupling` spec R3/R5 with skill-loading + discovery-breadth scenarios
|
|
14
|
-
|
|
15
|
-
### Out of Scope
|
|
16
|
-
- Reintroducing the old semantic embedding matcher (kept: trigger-aware search, tags, Zod validation, path safety, core/host split)
|
|
17
|
-
- A new standalone skill-loading domain spec
|
|
18
|
-
- TUI/host icon changes beyond callback wiring
|
|
19
|
-
|
|
20
|
-
## Capabilities
|
|
21
|
-
|
|
22
|
-
### New Capabilities
|
|
23
|
-
- None
|
|
24
|
-
|
|
25
|
-
### Modified Capabilities
|
|
26
|
-
- `core-decoupling`: R3 (Backward-Compatible Root Export) and R5 (Discovery Semantics Preservation) are violated by the refactor. The delta strengthens both to assert observable skill loading (`onSkillLoaded` fires, `SKILL.md` injected, icon appears) and discovery breadth (same skill set as pre-refactor), plus regression scenarios.
|
|
27
|
-
|
|
28
|
-
## Approach
|
|
29
|
-
|
|
30
|
-
Smallest change restoring correctness: (1) thread `onSkillLoaded` back through the OpenCode tool factory so `use_skill` updates host loaded-skill state; (2) widen `discoverAllSkills()` to the pre-refactor source set so literal-token search no longer drops skills. Keep the new search stack; tests confirm the same skills surface. TDD: red regression test first, then green.
|
|
31
|
-
|
|
32
|
-
## Affected Areas
|
|
33
|
-
|
|
34
|
-
| Area | Impact | Description |
|
|
35
|
-
|------|--------|-------------|
|
|
36
|
-
| `src/opencode/tools.ts` | Modified | Re-wire `onSkillLoaded` in `createSkillTools`/`UseSkill` |
|
|
37
|
-
| `src/opencode/plugin.ts` | Modified | Pass loaded-state callback into tool factory |
|
|
38
|
-
| `src/core/discovery.ts` | Modified | Restore pre-refactor discovery breadth |
|
|
39
|
-
| `tests/integration/plugin.test.ts` | New | Regression: skill surfaces + callback fires |
|
|
40
|
-
| `tests/opencode/plugin.test.ts` | New | Regression: loaded-state update + icon |
|
|
41
|
-
| `openspec/specs/core-decoupling/spec.md` | Modified (via delta) | Strengthen R3/R5 |
|
|
42
|
-
|
|
43
|
-
## Risks
|
|
44
|
-
|
|
45
|
-
| Risk | Likelihood | Mitigation |
|
|
46
|
-
|------|------------|------------|
|
|
47
|
-
| Widening discovery re-introduces duplicate / first-match bugs | Low | R5 first-match-wins tests already exist; extend them |
|
|
48
|
-
| Fix scope grows beyond callback + discovery | Med | Delivery strategy `force-chained` → split into stacked PRs at the 400-line budget |
|
|
49
|
-
| Literal-token search still misses edge skills after breadth fix | Low | Regression test mirrors the pre-refactor fixture set from `c2d8e74` |
|
|
50
|
-
|
|
51
|
-
## Rollback Plan
|
|
52
|
-
|
|
53
|
-
Revert the fix commits; the refactor stays intact (regression returns but the build stays green). Changes are isolated to `src/opencode/{tools,plugin}.ts` + `src/core/discovery.ts`, so rollback is a clean `git revert` of the fix PR(s).
|
|
54
|
-
|
|
55
|
-
## Dependencies
|
|
56
|
-
|
|
57
|
-
- Reference baseline: commit `c2d8e74` (pre-refactor `src/plugin.ts` / `src/tools.ts`)
|
|
58
|
-
- Engram observations: #1734 (discovery), #1736 (decision), #664 (config)
|
|
59
|
-
|
|
60
|
-
## Success Criteria
|
|
61
|
-
|
|
62
|
-
- [ ] `use_skill` visibly loads a skill: `SKILL.md` injected, `onSkillLoaded` fires, TUI icon appears
|
|
63
|
-
- [ ] `discoverAllSkills()` surfaces the same skill set as `c2d8e74` for the fixture locations
|
|
64
|
-
- [ ] `pnpm run typecheck` clean; `pnpm test` (integration + opencode layers) green
|
|
65
|
-
- [ ] `core-decoupling` delta spec R3/R5 scenarios pass
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# Delta for Core Decoupling
|
|
2
|
-
|
|
3
|
-
## Purpose
|
|
4
|
-
|
|
5
|
-
This delta strengthens `core-decoupling` R3 and R5 after the refactor introduced two regressions: (1) `onSkillLoaded` was dropped from the tool factory wiring, so `use_skill` no longer updates host loaded-skill state or injects `SKILL.md`; (2) `discoverAllSkills()` narrowed to literal-token search and dropped skills the pre-refactor matcher surfaced. Scope matches the proposal: no new requirements, no new spec domain — only R3 and R5 are tightened with regression scenarios.
|
|
6
|
-
|
|
7
|
-
## MODIFIED Requirements
|
|
8
|
-
|
|
9
|
-
### Requirement: Backward-Compatible Root Export (R3)
|
|
10
|
-
|
|
11
|
-
Importing `opencode-agent-skills-md` (the package root) SHALL return the OpenCode plugin with the same shape and behavior as before this change. The four tool names (`use_skill`, `read_skill_file`, `run_skill_script`, `get_available_skills`) SHALL resolve. Additionally, `use_skill` SHALL visibly load a skill: the `onSkillLoaded` callback registered with `createSkillTools` SHALL fire exactly once per successful load per session, the loaded skill's `SKILL.md` content SHALL be injected into the agent context exactly once per session per skill, and the host SHALL observe the loaded-skill state update (TUI icon visible). The callback SHALL be threaded from `src/opencode/plugin.ts` → `createSkillTools` → `UseSkill`.
|
|
12
|
-
|
|
13
|
-
(Previously: only asserted the four tool names resolve; did not cover observable skill loading or session-level dedupe.)
|
|
14
|
-
|
|
15
|
-
#### Scenario: root export still loads the OpenCode plugin
|
|
16
|
-
|
|
17
|
-
- GIVEN a consumer imports the package via its root export
|
|
18
|
-
- WHEN the consumer resolves the four tool names from the returned plugin object
|
|
19
|
-
- THEN all four tool names (`use_skill`, `read_skill_file`, `run_skill_script`, `get_available_skills`) are present
|
|
20
|
-
- AND the test-skill load assertion in `tests/integration/startup-smoke.test.ts` passes
|
|
21
|
-
|
|
22
|
-
#### Scenario: use_skill fires the onSkillLoaded callback
|
|
23
|
-
|
|
24
|
-
- GIVEN the host registered an `onSkillLoaded` callback via `createSkillTools`
|
|
25
|
-
- WHEN the agent calls `use_skill("test-skill")` on an unloaded skill
|
|
26
|
-
- THEN the callback is invoked exactly once with the loaded skill identifier
|
|
27
|
-
- AND the loaded skill's `SKILL.md` content is present in the agent context
|
|
28
|
-
- AND the host's loaded-skill state reflects the new skill
|
|
29
|
-
|
|
30
|
-
#### Scenario: use_skill does not re-inject the same skill in one session
|
|
31
|
-
|
|
32
|
-
- GIVEN the agent has already loaded a given skill via `use_skill` in the current session
|
|
33
|
-
- WHEN the agent calls `use_skill` with the same skill name again in the same session
|
|
34
|
-
- THEN `onSkillLoaded` is NOT re-fired for that skill
|
|
35
|
-
- AND the `SKILL.md` content is NOT re-injected into the context
|
|
36
|
-
|
|
37
|
-
#### Scenario: missing callback does not break the load
|
|
38
|
-
|
|
39
|
-
- GIVEN no `onSkillLoaded` is registered with `createSkillTools`
|
|
40
|
-
- WHEN the agent calls `use_skill("any-skill")`
|
|
41
|
-
- THEN the skill still loads and `SKILL.md` content is injected
|
|
42
|
-
- AND no thrown error or unhandled rejection occurs
|
|
43
|
-
|
|
44
|
-
### Requirement: Discovery Semantics Preservation (R5)
|
|
45
|
-
|
|
46
|
-
When the OpenCode adapter delegates to the core's `discoverAllSkills()`, the adapter SHALL observe the same four-location priority and first-match-wins semantics defined by the existing skill behavior. The set of skills surfaced for the baseline fixture locations SHALL match the set surfaced by pre-refactor commit `c2d8e74`. An integration test that mirrors `tests/integration/*` SHALL pass against the new boundary.
|
|
47
|
-
|
|
48
|
-
(Previously: asserted priority and first-match-wins but did not pin the surface skill set to the pre-refactor baseline; literal-token search was permitted to drop skills.)
|
|
49
|
-
|
|
50
|
-
#### Scenario: discovery priority and first-match-wins are preserved
|
|
51
|
-
|
|
52
|
-
- GIVEN skill fixtures exist under `.opencode/skills/`, `.claude/skills/`, `~/.config/opencode/skills/`, and `~/.claude/skills/`
|
|
53
|
-
- WHEN the OpenCode adapter calls `discoverAllSkills()`
|
|
54
|
-
- THEN the returned list follows the four-location priority
|
|
55
|
-
- AND duplicate skill names resolve to the first matching location
|
|
56
|
-
- AND the new integration test in `tests/core/` passes
|
|
57
|
-
|
|
58
|
-
#### Scenario: discoverAllSkills matches the pre-refactor skill set
|
|
59
|
-
|
|
60
|
-
- GIVEN the same fixture tree used by pre-refactor commit `c2d8e74`
|
|
61
|
-
- WHEN the OpenCode adapter calls `discoverAllSkills()`
|
|
62
|
-
- THEN every skill the baseline surfaced is also surfaced now
|
|
63
|
-
- AND no skill the baseline surfaced is missing from the result
|
|
64
|
-
|
|
65
|
-
#### Scenario: literal-token search does not drop the pre-refactor skill set
|
|
66
|
-
|
|
67
|
-
- GIVEN a skill whose trigger tokens are partial substrings of the user's query (not exact match)
|
|
68
|
-
- WHEN the user searches via the literal-token path in `discoverAllSkills()`
|
|
69
|
-
- THEN that skill appears in the result
|
|
70
|
-
- AND the four-location priority remains consistent with first-match-wins
|
|
71
|
-
|
|
72
|
-
## Notes
|
|
73
|
-
|
|
74
|
-
- No `ADDED Requirements`, no `REMOVED Requirements`, no `RENAMED Requirements`. R1, R2, R4, R6 are unchanged.
|
|
75
|
-
- The new R3 scenario "missing callback does not break the load" preserves the host-agnostic split (core must not assume a callback).
|
|
76
|
-
- The new R5 scenarios pin the pre-refactor skill set so widening discovery does not silently re-narrow.
|
|
77
|
-
- All scenarios are written to be TDD-friendly: each maps to one or two test cases in `tests/integration/plugin.test.ts` and `tests/opencode/plugin.test.ts`.
|