opencode-agent-skills-md 1.0.1 → 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.
Files changed (129) hide show
  1. package/dist/cli.mjs +770 -0
  2. package/dist/plugin.mjs +1138 -0
  3. package/dist/src/cli/config.d.ts +144 -0
  4. package/dist/src/cli/install.d.ts +33 -0
  5. package/dist/src/cli/main.d.ts +11 -0
  6. package/dist/src/cli/real-fs.d.ts +6 -0
  7. package/dist/src/cli/status.d.ts +34 -0
  8. package/dist/src/cli/uninstall.d.ts +22 -0
  9. package/dist/src/host.d.ts +51 -0
  10. package/dist/src/index.d.ts +17 -0
  11. package/dist/src/plugin.d.ts +35 -0
  12. package/dist/src/sdk.d.ts +51 -0
  13. package/dist/src/tools.d.ts +86 -0
  14. package/package.json +48 -18
  15. package/.beads/.local_version +0 -1
  16. package/.beads/README.md +0 -81
  17. package/.beads/config.yaml +0 -61
  18. package/.beads/deletions.jsonl +0 -1
  19. package/.beads/issues.jsonl +0 -64
  20. package/.beads/metadata.json +0 -4
  21. package/.gitattributes +0 -3
  22. package/.github/CODEOWNERS +0 -1
  23. package/.github/copilot-instructions.md +0 -78
  24. package/.github/dependabot.yml +0 -13
  25. package/.github/workflows/release.yml +0 -51
  26. package/.opencode/command/test-compaction.md +0 -9
  27. package/.opencode/command/test-find-skills.md +0 -7
  28. package/.opencode/command/test-read-skill-file.md +0 -14
  29. package/.opencode/command/test-run-skill-script.md +0 -13
  30. package/.opencode/command/test-skills.md +0 -14
  31. package/.opencode/command/test-use-skill.md +0 -10
  32. package/.opencode/skills/git-helper/SKILL.md +0 -65
  33. package/.opencode/skills/test-skill/SKILL.md +0 -43
  34. package/.opencode/skills/test-skill/example-config.json +0 -16
  35. package/.opencode/skills/test-skill/helper-docs.md +0 -29
  36. package/.opencode/skills/test-skill/scripts/echo-args +0 -14
  37. package/.opencode/skills/test-skill/scripts/greet +0 -6
  38. package/AGENTS.md +0 -43
  39. package/CHANGELOG.md +0 -178
  40. package/Justfile +0 -39
  41. package/README.md +0 -220
  42. package/openspec/changes/archive/2026-06-14-skills-core-decouple/specs/core-decoupling/spec.md +0 -74
  43. package/openspec/changes/archive/2026-06-14-skills-core-decouple/tasks.md +0 -64
  44. package/openspec/changes/archive/2026-06-14-skills-core-decouple/verify-report.md +0 -75
  45. package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/apply-progress.md +0 -136
  46. package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/archive-report.md +0 -77
  47. package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/design.md +0 -89
  48. package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/proposal.md +0 -65
  49. package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/specs/core-decoupling/spec.md +0 -77
  50. package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/tasks.md +0 -65
  51. package/openspec/changes/archive/2026-06-17-fix-skill-loading-regression/verify-report.md +0 -165
  52. package/openspec/specs/core-decoupling/spec.md +0 -110
  53. package/packages/core/package.json +0 -30
  54. package/packages/core/src/content.d.ts +0 -16
  55. package/packages/core/src/content.ts +0 -30
  56. package/packages/core/src/debug.ts +0 -16
  57. package/packages/core/src/discovery.d.ts +0 -86
  58. package/packages/core/src/discovery.ts +0 -257
  59. package/packages/core/src/index.d.ts +0 -20
  60. package/packages/core/src/index.ts +0 -55
  61. package/packages/core/src/match.d.ts +0 -19
  62. package/packages/core/src/match.ts +0 -75
  63. package/packages/core/src/parse.d.ts +0 -26
  64. package/packages/core/src/parse.ts +0 -141
  65. package/packages/core/src/scripts.d.ts +0 -17
  66. package/packages/core/src/scripts.ts +0 -79
  67. package/packages/core/src/search.d.ts +0 -83
  68. package/packages/core/src/search.ts +0 -188
  69. package/packages/core/src/types.d.ts +0 -82
  70. package/packages/core/src/types.ts +0 -131
  71. package/packages/core/src/walk.ts +0 -109
  72. package/packages/core/tests/agnostic.test.ts +0 -346
  73. package/packages/core/tests/content.test.ts +0 -65
  74. package/packages/core/tests/discovery.test.ts +0 -370
  75. package/packages/core/tests/package-boundary.test.ts +0 -310
  76. package/packages/core/tests/parse-trigger.test.ts +0 -282
  77. package/packages/core/tests/search.test.ts +0 -374
  78. package/packages/core/tests/subpath.test.ts +0 -87
  79. package/packages/core/tsconfig.json +0 -10
  80. package/packages/opencode-agent-skills-md/package.json +0 -66
  81. package/packages/opencode-agent-skills-md/rolldown.config.js +0 -47
  82. package/packages/opencode-agent-skills-md/tests/cli-commands.test.ts +0 -1423
  83. package/packages/opencode-agent-skills-md/tests/e2e/startup-smoke.test.ts +0 -66
  84. package/packages/opencode-agent-skills-md/tests/fixtures/skills/home/.claude/skills/claude-user-only-skill/SKILL.md +0 -8
  85. package/packages/opencode-agent-skills-md/tests/fixtures/skills/home/.config/opencode/skills/shared-skill/SKILL.md +0 -8
  86. package/packages/opencode-agent-skills-md/tests/fixtures/skills/home/.config/opencode/skills/user-only-skill/SKILL.md +0 -8
  87. package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.claude/skills/claude-project-only-skill/SKILL.md +0 -8
  88. package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/go-tester/SKILL.md +0 -12
  89. package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/nested/team/nested-skill/SKILL.md +0 -8
  90. package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/rust-tester/SKILL.md +0 -11
  91. package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/scripted-skill/SKILL.md +0 -8
  92. package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/scripted-skill/bin/echo.sh +0 -2
  93. package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/scripted-skill/docs/reference.md +0 -1
  94. package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/shared-skill/SKILL.md +0 -8
  95. package/packages/opencode-agent-skills-md/tests/fixtures/skills/project/.opencode/skills/using-superpowers/SKILL.md +0 -8
  96. package/packages/opencode-agent-skills-md/tests/integration/helpers/mock-opencode.ts +0 -114
  97. package/packages/opencode-agent-skills-md/tests/integration/plugin.test.ts +0 -316
  98. package/packages/opencode-agent-skills-md/tests/integration/skill-discovery.test.ts +0 -315
  99. package/packages/opencode-agent-skills-md/tests/opencode/host.test.ts +0 -179
  100. package/packages/opencode-agent-skills-md/tests/opencode/plugin.test.ts +0 -551
  101. package/packages/opencode-agent-skills-md/tests/opencode/subpath.test.ts +0 -66
  102. package/packages/opencode-agent-skills-md/tests/opencode/tools.test.ts +0 -213
  103. package/packages/opencode-agent-skills-md/tests/package-boundary.test.ts +0 -345
  104. package/packages/opencode-agent-skills-md/tests/tools-security.test.ts +0 -72
  105. package/packages/opencode-agent-skills-md/tsconfig.build.json +0 -11
  106. package/packages/opencode-agent-skills-md/tsconfig.json +0 -10
  107. package/plans/001-ci-gate.md +0 -177
  108. package/plans/002-is-path-safe.md +0 -243
  109. package/plans/003-escape-prompts.md +0 -310
  110. package/plans/004-test-security-paths.md +0 -228
  111. package/plans/005-stop-swallowing-errors.md +0 -246
  112. package/plans/006-preserve-jsonc-commas.md +0 -144
  113. package/plans/007-write-before-purge.md +0 -144
  114. package/plans/008-reuse-walkdir-for-list-skill-files.md +0 -164
  115. package/plans/README.md +0 -43
  116. package/pnpm-workspace.yaml +0 -6
  117. package/tests/workspace.test.ts +0 -367
  118. package/tsconfig.json +0 -15
  119. /package/{packages/opencode-agent-skills-md/src → src}/cli/config.ts +0 -0
  120. /package/{packages/opencode-agent-skills-md/src → src}/cli/install.ts +0 -0
  121. /package/{packages/opencode-agent-skills-md/src → src}/cli/main.ts +0 -0
  122. /package/{packages/opencode-agent-skills-md/src → src}/cli/real-fs.ts +0 -0
  123. /package/{packages/opencode-agent-skills-md/src → src}/cli/status.ts +0 -0
  124. /package/{packages/opencode-agent-skills-md/src → src}/cli/uninstall.ts +0 -0
  125. /package/{packages/opencode-agent-skills-md/src → src}/host.ts +0 -0
  126. /package/{packages/opencode-agent-skills-md/src → src}/index.ts +0 -0
  127. /package/{packages/opencode-agent-skills-md/src → src}/plugin.ts +0 -0
  128. /package/{packages/opencode-agent-skills-md/src → src}/sdk.ts +0 -0
  129. /package/{packages/opencode-agent-skills-md/src → src}/tools.ts +0 -0
@@ -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`.
@@ -1,65 +0,0 @@
1
- # Tasks: Fix Skill-Loading Regression
2
-
3
- ## Review Workload Forecast
4
-
5
- | Field | Value |
6
- |-------|-------|
7
- | Estimated changed lines | 180-260 |
8
- | 400-line budget risk | Medium |
9
- | Chained PRs recommended | Yes |
10
- | Suggested split | PR 1 → PR 2 → PR 3 (optional) |
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: Medium
18
-
19
- ### Suggested Work Units
20
-
21
- | Unit | Goal | Likely PR | Notes |
22
- |------|------|-----------|-------|
23
- | 1 | Restore callback seam + session dedupe | PR 1 | `src/opencode/*`; tests first |
24
- | 2 | Restore baseline discovery sources | PR 2 | `src/core/discovery.ts`; stack after PR 1 |
25
- | 3 | Cleanup only if scope stays tight | PR 3 | Optional polish + final verification |
26
-
27
- ## Phase 1: PR 1 — Callback wiring
28
-
29
- - [x] 1.1 RED — Extend `tests/opencode/plugin.test.ts` and `tests/integration/plugin.test.ts` to fail when `use_skill` loads once but does not update loaded-session state or suppress duplicate re-injection; commit `test: add skill loading callback regression coverage`.
30
- - [x] 1.2 GREEN — Update `src/opencode/tools.ts` and `src/opencode/plugin.ts` to thread optional `onSkillLoaded` through `createSkillTools()` → `UseSkill()` and restore `loadedSkillsPerSession` updates; commit `fix: restore use-skill callback wiring`.
31
- - [x] 1.3 REFACTOR — Keep the callback seam optional, trim duplicated plugin-test setup, and rerun `node --import tsx --test tests/opencode/plugin.test.ts tests/integration/plugin.test.ts`; commit `refactor: preserve optional skill callback seam`.
32
-
33
- ## Phase 2: PR 2 — Discovery breadth
34
-
35
- - [x] 2.1 RED — Extend `tests/integration/skill-discovery.test.ts` with baseline-coverage cases for `.opencode/skills`, `.claude/skills`, `~/.config/opencode/skills`, `~/.claude/skills`, plus the partial-trigger regression from spec R5; commit `test: add discovery breadth regression coverage`.
36
- - [x] 2.2 GREEN — Modify `src/core/discovery.ts` to restore the pre-refactor source set from `c2d8e74` while preserving first-match-wins and duplicate warnings; commit `fix: restore baseline skill discovery sources`.
37
- - [x] 2.3 REFACTOR — Normalize any helper/constants in `src/core/discovery.ts`, keep search/host boundaries unchanged, and rerun `node --import tsx --test tests/integration/skill-discovery.test.ts`; commit `refactor: clean up discovery source helpers`.
38
-
39
- ## Phase 3: PR 3 — Optional cleanup / verification
40
-
41
- - [x] 3.1 RED/GREEN — Coverage gap check: PR 1 + PR 2 cover all spec R3/R5 scenarios. No additional regression needed; skip the commit.
42
- - [x] 3.2 REFACTOR — Code is already minimal (OnSkillLoaded type, inlined 4-line callback, DEFAULT_DISCOVERY_MAX_DEPTH constant). No behavior-neutral cleanup needed; skip the commit.
43
- - [x] 3.3 VERIFY — Run `pnpm run typecheck` (clean) and the full `pnpm test` suite (102 tests, 0 fail); commit `chore: verify skill loading regression fix`.
44
-
45
- ## Final Commit Stack
46
-
47
- ```
48
- d2c3584 test: correct dedupe assertion to allow other matches
49
- c1f5b27 chore: verify skill loading regression fix
50
- 8c7de19 refactor: clean up discovery source helpers
51
- 7e4293e fix: restore baseline skill discovery sources
52
- b764c15 test: add discovery breadth regression coverage
53
- 9e975ab refactor: preserve optional skill callback seam
54
- fd4ab41 fix: restore use-skill callback wiring
55
- c64d4e7 test: add skill loading callback regression coverage
56
- 01c4b46 chore(sdd): add fix-skill-loading-regression change artifacts
57
- ```
58
-
59
- ## Verification
60
-
61
- - `pnpm run typecheck` — clean
62
- - `node --import tsx --test src/utils.test.ts tests/core/*.test.ts tests/opencode/plugin.test.ts tests/integration/plugin.test.ts tests/integration/skill-discovery.test.ts tests/e2e/*.test.ts` — 89 pass / 0 fail
63
- - `pnpm test` (unit + core + opencode + integration + e2e) — 102 pass / 0 fail
64
- - All spec R3 scenarios covered: callback fires, dedupe, missing-callback
65
- - All spec R5 scenarios covered: priority + first-match-wins, baseline match, partial-trigger