From b27bd3b79983393428d8398a17e7b502e5bf685e Mon Sep 17 00:00:00 2001 From: fastsoab Date: Fri, 11 Sep 2026 10:17:19 +0200 Subject: [PATCH] Install with opencode plugin and rename the repository --- .github/ISSUE_TEMPLATE/config.yml | 2 +- .github/workflows/publish.yml | 26 +++++++++ CONTRIBUTING.md | 11 +++- README.md | 29 ++++------ SECURITY.md | 6 +-- docs/installation.md | 88 +++++++++++++++++++++---------- package-lock.json | 36 +++++++++++-- package.json | 24 ++++++--- scripts/install.sh | 34 ++++++++++++ skills/skill-curation/SKILL.md | 2 +- test/package.test.ts | 29 ++++++++++ 11 files changed, 222 insertions(+), 65 deletions(-) create mode 100644 .github/workflows/publish.yml create mode 100755 scripts/install.sh create mode 100644 test/package.test.ts diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 8f99d30..a221daf 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ blank_issues_enabled: true contact_links: - name: Report a vulnerability - url: https://github.com/Neverdecel/OpenSkillGen/security/advisories/new + url: https://github.com/Neverdecel/opencode-guided-learning/security/advisories/new about: Private security reports only — do not file public issues for exploits or secrets - name: OpenCode plugin docs url: https://opencode.ai/docs/plugins/ diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..bf25d7a --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,26 @@ +name: Publish + +on: + push: + tags: ["v*"] + workflow_dispatch: + +permissions: + contents: read + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 24 + cache: npm + registry-url: https://registry.npmjs.org + - run: npm ci --ignore-scripts + - run: npm run check + - run: npm test + - run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7dcd41f..cb018ef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,8 +10,8 @@ or cleanup infrastructure. Requires Node.js 24+ and npm. OpenCode 1.18.30 is required for live CLI tests. ```sh -git clone https://github.com/Neverdecel/OpenSkillGen.git -cd OpenSkillGen +git clone https://github.com/Neverdecel/opencode-guided-learning.git +cd opencode-guided-learning npm ci npm run check npm test @@ -62,6 +62,13 @@ checks are smoke only. Acceptance criteria: pass does not erase them. Never run evaluation writes against a real skill library. +## Releases + +Package, repo, and plugin id are `opencode-guided-learning`. Publish with a +`v*` tag or `workflow_dispatch` on `.github/workflows/publish.yml`; it needs +the `NPM_TOKEN` secret. Do not `npm publish` from a laptop. Bump +`package.json` version before tagging. + ## Issues Include OpenCode and model versions and a minimal, sanitized reproduction. diff --git a/README.md b/README.md index d1ad82c..adaa8b0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# OpenSkillGen +# opencode-guided-learning -[![Checks](https://github.com/Neverdecel/OpenSkillGen/actions/workflows/checks.yml/badge.svg)](https://github.com/Neverdecel/OpenSkillGen/actions/workflows/checks.yml) +[![Checks](https://github.com/Neverdecel/opencode-guided-learning/actions/workflows/checks.yml/badge.svg)](https://github.com/Neverdecel/opencode-guided-learning/actions/workflows/checks.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) **Agent notices. Human decides. OpenCode remembers.** @@ -16,31 +16,19 @@ Reply **yes**, **no**, **make it global**, **rename it**, **add X**, or **merge ## Requirements - [OpenCode](https://opencode.ai) **1.18.30** (tested). The plugin uses experimental hooks; later versions need a compatibility check. -- A git clone of this repository at a stable path. - -**Not published to npm.** Do not add `opencode-guided-learning` as a package name in `plugin`. Load the source file URL instead. ## Install ```sh -git clone https://github.com/Neverdecel/OpenSkillGen.git -``` - -Add the **absolute** source-file URL to `plugin` in `~/.config/opencode/opencode.json` (all projects) or the project’s `opencode.json`: - -```json -{ - "$schema": "https://opencode.ai/config.json", - "plugin": ["file:///absolute/path/to/OpenSkillGen/src/index.ts"], - "skills": { "paths": ["/absolute/path/to/OpenSkillGen/skills"] } -} +git clone https://github.com/Neverdecel/opencode-guided-learning.git +sh opencode-guided-learning/scripts/install.sh ``` -`skills.paths` is optional; it enables the bundled `skill-mining` and `skill-curation` skills. Keep existing config entries. **Quit and restart OpenCode** (including its backend when using OpenChamber). +That runs `opencode plugin -g` with the checkout’s absolute path (patches global config). `scripts/install.sh --local` is this project only. After npm publish: `opencode plugin -g opencode-guided-learning@0.1.0` (pin the version). -Windows example: `file:///C:/projects/OpenSkillGen/src/index.ts`. +Optional: add the checkout `skills/` directory to `skills.paths` for `skill-mining` and `skill-curation`. **Quit and restart OpenCode** (including its backend when using OpenChamber). -Confirm with `opencode debug config` (the resolved plugin list should include the file URL). Do not paste that output into issues; it can contain secrets. Full steps and troubleshooting: [docs/installation.md](docs/installation.md). +Confirm with `opencode debug config`. Do not paste that output into issues; it can contain secrets. Full steps: [docs/installation.md](docs/installation.md). ## Usage @@ -68,7 +56,7 @@ Both options are optional. Defaults: enabled, conservative, no ignored topics. ```json { "$schema": "https://opencode.ai/config.json", - "plugin": [["file:///absolute/path/to/OpenSkillGen/src/index.ts", { + "plugin": [["opencode-guided-learning@0.1.0", { "enabled": true, "ignoredTopics": ["personal editor preferences", "release-notes"] }]] @@ -91,6 +79,7 @@ The runtime is one file: it appends guidance and a compaction note. No extra mod | [`skills/`](skills/) | Opt-in mining and curation skills | | [`examples/`](examples/) | Sample generated skill (not auto-discovered) | | [`test/`](test/) | Hook tests and isolated live eval | +| [`scripts/install.sh`](scripts/install.sh) | Clone install via `opencode plugin` | | [`docs/`](docs/installation.md) | Install, troubleshooting, hook research, [skill entity](docs/skill-definition.md) | ## Contributing diff --git a/SECURITY.md b/SECURITY.md index 64d5f52..ca9ef21 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,7 +1,7 @@ # Security Report vulnerabilities privately: **Security → Report a vulnerability** on -[Neverdecel/OpenSkillGen](https://github.com/Neverdecel/OpenSkillGen/security/advisories/new). +[Neverdecel/opencode-guided-learning](https://github.com/Neverdecel/opencode-guided-learning/security/advisories/new). Do not open a public issue or pull request with exploit details, secrets, or credentials. @@ -19,5 +19,5 @@ Out of scope: a model ignoring consent, writing a low-quality skill, or following a user request to store secrets — those are instruction-following failures. Disable the plugin and use OpenCode permissions if you need a guard. -Supported: the current `main` branch of this checkout, tested with OpenCode -1.18.30. +Supported: the current `main` branch and published `opencode-guided-learning` +versions that match it, tested with OpenCode 1.18.30. diff --git a/docs/installation.md b/docs/installation.md index 86583f6..187303d 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -1,8 +1,8 @@ # Installation and troubleshooting -OpenSkillGen is a **source checkout**, not an npm package. The plugin id is -`opencode-guided-learning`. Do not put that bare name in OpenCode’s `plugin` -array; use a `file:///` URL to `src/index.ts`. +The package, GitHub repo, and plugin id are `opencode-guided-learning`. +Install with OpenCode’s `plugin` command, which installs the package and +patches `opencode.json`. Official references: [plugins](https://opencode.ai/docs/plugins/), [configuration](https://opencode.ai/docs/config/), @@ -13,22 +13,45 @@ Official references: [plugins](https://opencode.ai/docs/plugins/), 1. Check `opencode --version`. **1.18.30** was tested against its plugin types and session runtime. Experimental hooks may change. -2. Clone `https://github.com/Neverdecel/OpenSkillGen.git` to a path you will - keep. Moving the checkout later requires updating the config URL. -3. Add `file:///absolute/path/to/OpenSkillGen/src/index.ts` to the existing - `plugin` array in global or project config. An absolute file URL avoids - resolving against the wrong config directory. Windows: - `file:///C:/projects/OpenSkillGen/src/index.ts`. -4. Optional: add the checkout’s `skills` directory to `skills.paths` (absolute - path) so `skill-mining` and `skill-curation` are invocable. Do not copy them - into another project’s `.opencode/skills/` unless you want a fork. -5. Quit and restart OpenCode. Restart the backend as well when a frontend such +2. Install into global config (all projects) or omit `--global` / `-g` for the + current project: + + From a clone (works without npm): + + ```sh + git clone https://github.com/Neverdecel/opencode-guided-learning.git + sh opencode-guided-learning/scripts/install.sh + ``` + + `scripts/install.sh --local` patches this project only. `--force` replaces + an existing `opencode-guided-learning` entry. Windows: + + ```bat + opencode plugin -g C:\projects\opencode-guided-learning + ``` + + After the package is published: + + ```sh + opencode plugin -g opencode-guided-learning@0.1.0 + ``` + + Pin the version. OpenCode caches `name@latest` and does not refresh it. +3. Optional: add the checkout’s `skills` directory to `skills.paths` (absolute + path) so `skill-mining` and `skill-curation` are invocable. The installer + prints that path. Do not copy them into another project’s + `.opencode/skills/` unless you want a fork. npm installs keep skills inside + the cached package; prefer the clone path if you want those skills. +4. Quit and restart OpenCode. Restart the backend as well when a frontend such as OpenChamber manages it. OpenCode’s TypeScript loader runs `src/index.ts` directly. No build or -`npm install` is required to use the plugin. `npm ci` is for contributors -(pinned SDK types and tests). `package.json` is `private: true` so the package -is not published by accident; that does not affect GitHub or local loading. +`npm install` is required to use a clone. `npm ci` is for contributors +(pinned SDK types and tests). + +If you previously listed `file:///…/src/index.ts`, remove that entry after +switching to `opencode plugin`. `--force` does not replace `file://` specs, and +both would load. Global config: `~/.config/opencode/opencode.json` or `opencode.jsonc` (honor a custom config directory). Project config: repository root or `.opencode/`. @@ -42,24 +65,34 @@ From the project where you use the plugin: opencode debug config ``` -The resolved plugin list should include the source-file URL. With bundled -skills enabled, `opencode debug skill` should list `skill-mining` and -`skill-curation`. That output can include private configuration — do not paste -it into an issue. +The resolved plugin list should include the checkout directory or +`opencode-guided-learning@…`. With bundled skills enabled, `opencode debug skill` +should list `skill-mining` and `skill-curation`. That output can include private +configuration — do not paste it into an issue. A lack of learning suggestions during ordinary work is expected. Contributors can run the isolated transport test in [CONTRIBUTING.md](../CONTRIBUTING.md). ## Update +Clone: + ```sh git status git pull --ff-only ``` Keep local edits; pin a reviewed commit for a stable install. Restart OpenCode -after pulling. Contributors should rerun `npm ci` when the lockfile changes, -then `npm run check` and `npm test`. +after pulling. + +npm pin (new version uses a new cache directory): + +```sh +opencode plugin -g -f opencode-guided-learning@0.1.1 +``` + +Contributors should rerun `npm ci` when the lockfile changes, then +`npm run check` and `npm test`. ## Disable or uninstall @@ -71,15 +104,16 @@ then `npm run check` and `npm test`. ## Troubleshooting -- **Not in resolved config:** check config scope, the `file:///` URL, and +- **Not in resolved config:** check config scope, the plugin spec, and `XDG` / custom config-directory settings. -- **Checkout moved:** update the URL and restart. +- **Checkout moved:** rerun `scripts/install.sh --force` (or pass the new + absolute path to `opencode plugin`) and restart. - **Schema error:** validate against [https://opencode.ai/config.json](https://opencode.ai/config.json). Options belong in the plugin tuple, not at the top level of the config. - **Stale behavior:** restart the OpenCode backend, not only the UI. -- **Duplicate guidance:** do not also drop `src/index.ts` into - `.opencode/plugins/` or `~/.config/opencode/plugins/` while it is listed in - `plugin`. +- **Duplicate guidance:** remove old `file:///` entries; do not also drop + `src/index.ts` into `.opencode/plugins/` or `~/.config/opencode/plugins/` + while it is listed in `plugin`. - **Ignores consent or writes a poor skill:** model behavior, not a write guard. Disable the plugin if needed. File a credential-free issue with OpenCode/model versions and sanitized tool calls. Never test against a real diff --git a/package-lock.json b/package-lock.json index 4115e40..0cb602e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,8 @@ "name": "opencode-guided-learning", "version": "0.1.0", "license": "MIT", - "dependencies": { - "@opencode-ai/plugin": "1.18.30" - }, "devDependencies": { + "@opencode-ai/plugin": "1.18.30", "@types/node": "^26.5.0", "typescript": "7.0.2" }, @@ -24,6 +22,7 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-3.0.8.tgz", "integrity": "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { "json-schema": "^0.4.0" @@ -39,6 +38,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -52,6 +52,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -65,6 +66,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -78,6 +80,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -91,6 +94,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -104,6 +108,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -114,6 +119,7 @@ "version": "1.18.30", "resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.18.30.tgz", "integrity": "sha512-bXWcA2VD478PXXke1qAYANTq58fCcbgY0GAUqZIFZqPpo48FoG8RH37nNZ78eHtz+ddiKIhFTBZJRaHF3IgFqw==", + "dev": true, "license": "MIT", "dependencies": { "@ai-sdk/provider": "3.0.8", @@ -142,6 +148,7 @@ "version": "1.18.30", "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.18.30.tgz", "integrity": "sha512-uviJ+PZLc/D1szt33WGzzt/rqJ+IaNmRGBb+UcOXrcQANl8XXKJrp4CNQQ2UAnUJ3Ek+VqcamIwjtKHUW/OjOQ==", + "dev": true, "license": "MIT", "dependencies": { "cross-spawn": "7.0.6" @@ -151,6 +158,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, "license": "MIT" }, "node_modules/@types/node": { @@ -507,6 +515,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -521,6 +530,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, "license": "Apache-2.0", "optional": true, "engines": { @@ -531,6 +541,7 @@ "version": "4.0.0-beta.83", "resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-beta.83.tgz", "integrity": "sha512-0wsak8RtgGAr9UWSbVDgJHZcUqMSvicHcvaZv1MbMM7MCGgW4Rn/137J1MHQbwYPcwYGxT/IqehFd+UbYuj78w==", + "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", @@ -549,6 +560,7 @@ "version": "4.9.0", "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.9.0.tgz", "integrity": "sha512-7ms6T7SybUev/PQITciI0yLM2pOSFy5zpG8Ty7tQofcVaQUvrMXp6CBwqF6fThLCLOrfBtuHAtwq6Yu4XPCllg==", + "dev": true, "funding": [ { "type": "individual", @@ -571,12 +583,14 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/find-my-way-ts/-/find-my-way-ts-0.1.6.tgz", "integrity": "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==", + "dev": true, "license": "MIT" }, "node_modules/ini": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-7.0.0.tgz", "integrity": "sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w==", + "dev": true, "license": "ISC", "engines": { "node": "^22.22.2 || ^24.15.0 || >=26.0.0" @@ -586,24 +600,28 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, "license": "ISC" }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true, "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/kubernetes-types": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/kubernetes-types/-/kubernetes-types-1.30.0.tgz", "integrity": "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==", + "dev": true, "license": "Apache-2.0" }, "node_modules/msgpackr": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-2.1.0.tgz", "integrity": "sha512-p/pBCVO63CsvvpkomUnNNag6+n38rULuDA6HHe70o2gtC8ODI52foF/4ko2qQcp6OiErJXTmrZeXmsGGHsIQNQ==", + "dev": true, "license": "MIT", "optionalDependencies": { "msgpackr-extract": "^3.0.4" @@ -613,6 +631,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.4.tgz", "integrity": "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -635,12 +654,14 @@ "version": "0.2.8", "resolved": "https://registry.npmjs.org/multipasta/-/multipasta-0.2.8.tgz", "integrity": "sha512-ZPWuMKyv0cSO29f7hozp+k6+crZbQijV8ipMvxNxRf2SwtYGTX1ZX89Kd20VV4H9Znonx+EQn+iy1wGQsJ+b+Q==", + "dev": true, "license": "MIT" }, "node_modules/node-gyp-build-optional-packages": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -656,6 +677,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -665,6 +687,7 @@ "version": "8.4.2", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.2.tgz", "integrity": "sha512-vvuOGgcuPJAirlHvuQw1TrOiw7ptaIXXmIbNuiNOY6lNGJJH49PQ1Kj4nd783nPdQhQdicgOjVI2yI/9BD6/Ng==", + "dev": true, "funding": [ { "type": "individual", @@ -681,6 +704,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -693,6 +717,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -702,6 +727,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/toml/-/toml-4.3.0.tgz", "integrity": "sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A==", + "dev": true, "license": "MIT", "engines": { "node": ">=20" @@ -753,6 +779,7 @@ "version": "14.0.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.2.tgz", "integrity": "sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ==", + "dev": true, "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -766,6 +793,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -781,6 +809,7 @@ "version": "2.9.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -796,6 +825,7 @@ "version": "4.1.8", "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.8.tgz", "integrity": "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ==", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index 8c4c06f..3c38fbd 100644 --- a/package.json +++ b/package.json @@ -5,20 +5,28 @@ "license": "MIT", "repository": { "type": "git", - "url": "git+https://github.com/Neverdecel/OpenSkillGen.git" + "url": "git+https://github.com/Neverdecel/opencode-guided-learning.git" }, - "homepage": "https://github.com/Neverdecel/OpenSkillGen#readme", - "bugs": { "url": "https://github.com/Neverdecel/OpenSkillGen/issues" }, + "homepage": "https://github.com/Neverdecel/opencode-guided-learning#readme", + "bugs": { "url": "https://github.com/Neverdecel/opencode-guided-learning/issues" }, "keywords": ["opencode", "opencode-plugin", "skills", "guided-learning"], - "private": true, "type": "module", "main": "./src/index.ts", - "exports": { ".": "./src/index.ts" }, + "exports": { + ".": "./src/index.ts", + "./server": "./src/index.ts" + }, + "files": ["src/index.ts", "skills"], + "publishConfig": { "access": "public" }, "scripts": { "check": "tsc --noEmit", - "test": "node --test test/*.test.ts" + "test": "node --test test/*.test.ts", + "prepublishOnly": "npm run check && npm test" }, "engines": { "node": ">=24", "opencode": ">=1.18.30" }, - "dependencies": { "@opencode-ai/plugin": "1.18.30" }, - "devDependencies": { "@types/node": "^26.5.0", "typescript": "7.0.2" } + "devDependencies": { + "@opencode-ai/plugin": "1.18.30", + "@types/node": "^26.5.0", + "typescript": "7.0.2" + } } diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 0000000..51724e1 --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,34 @@ +#!/bin/sh +set -eu +ROOT=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd) +GLOBAL=-g +FORCE= + +while [ $# -gt 0 ]; do + case $1 in + --local) GLOBAL= ;; + --force|-f) FORCE=-f ;; + -h|--help) + printf '%s\n' "usage: scripts/install.sh [--local] [--force]" \ + " (default: global OpenCode config)" \ + "Windows: opencode plugin -g C:\\path\\to\\opencode-guided-learning" + exit 0 + ;; + *) + printf 'unknown option: %s\n' "$1" >&2 + exit 1 + ;; + esac + shift +done + +if ! command -v opencode >/dev/null 2>&1; then + printf 'opencode not found in PATH\n' >&2 + exit 1 +fi + +opencode plugin $GLOBAL $FORCE "$ROOT" + +printf '\nRestart OpenCode.\n' +printf 'Optional bundled skills: add "%s/skills" to skills.paths\n' "$ROOT" +printf 'If you previously used a file:///…/src/index.ts entry, remove it to avoid duplicate guidance.\n' diff --git a/skills/skill-curation/SKILL.md b/skills/skill-curation/SKILL.md index 6bdf67f..290e3a8 100644 --- a/skills/skill-curation/SKILL.md +++ b/skills/skill-curation/SKILL.md @@ -11,7 +11,7 @@ The user asked to curate the skill library. That is initiative to **inspect and Discover skills OpenCode already knows (native `skill` listing and `SKILL.md` under project `.opencode/skills` and global `~/.config/opencode/skills`). Load only what you need to judge overlap. Do not dump bodies into the reply. -Skip bundled OpenSkillGen skills (`skill-mining`, `skill-curation`) and built-ins such as `customize-opencode` unless the user named them. Do not invent skills that are not on disk. +Skip bundled plugin skills (`skill-mining`, `skill-curation`) and built-ins such as `customize-opencode` unless the user named them. Do not invent skills that are not on disk. Judge each skill as one on-demand job whose description is the discovery index and whose body is the procedure the agent would get wrong without it. diff --git a/test/package.test.ts b/test/package.test.ts new file mode 100644 index 0000000..b213778 --- /dev/null +++ b/test/package.test.ts @@ -0,0 +1,29 @@ +import assert from "node:assert/strict" +import { spawnSync } from "node:child_process" +import { readFile } from "node:fs/promises" +import test from "node:test" +import { fileURLToPath } from "node:url" +import plugin from "../src/index.ts" + +const root = new URL("../", import.meta.url) + +test("package.json is opencode plugin-ready", async () => { + const pkg = JSON.parse(await readFile(new URL("package.json", root), "utf8")) + assert.equal(pkg.name, "opencode-guided-learning") + assert.equal(plugin.id, pkg.name) + assert.equal(pkg.main, "./src/index.ts") + assert.equal(pkg.exports["."], "./src/index.ts") + assert.equal(pkg.exports["./server"], "./src/index.ts") + assert.ok(pkg.files.includes("src/index.ts")) + assert.ok(pkg.files.includes("skills")) + assert.equal(typeof pkg.engines?.opencode, "string") + assert.equal(pkg.private, undefined) + assert.equal(pkg.dependencies?.["@opencode-ai/plugin"], undefined) + assert.equal(pkg.devDependencies["@opencode-ai/plugin"], "1.18.30") +}) + +test("install script is valid shell", () => { + const script = fileURLToPath(new URL("scripts/install.sh", root)) + const result = spawnSync("sh", ["-n", script], { encoding: "utf8" }) + assert.equal(result.status, 0, result.stderr) +})