From 7f18ef76ae54133b32a2ff83c03e641ed71e41c6 Mon Sep 17 00:00:00 2001 From: Dr Alexander Mikhalev Date: Tue, 15 Sep 2026 23:16:40 +0100 Subject: [PATCH] feat: publish multi-marketplace community pack --- .claude-plugin/marketplace.json | 18 + .claude-plugin/plugin.json | 20 + .cursor-plugin/plugin.json | 4 +- .github/trusted-release-signers | 1 + .github/workflows/release.yml | 69 ++++ .github/workflows/validate.yml | 39 ++ .zcode-plugin/plugin.json | 30 ++ NOTICE | 3 + README.md | 62 ++- README_CN.md | 55 +++ assets/v-model-overview.png | Bin 0 -> 107562 bytes assets/v-model-overview.svg | 130 ++++++ dist/autoclaw/SHA256SUMS | 3 + dist/autoclaw/terraphim-agent-learn-0.2.0.zip | Bin 0 -> 3061 bytes .../autoclaw/terraphim-agent-memory-0.2.0.zip | Bin 0 -> 3290 bytes dist/autoclaw/terraphim-grep-0.2.0.zip | Bin 0 -> 2928 bytes distribution/metadata.json | 59 +++ docs/distribution.md | 94 +++++ docs/install-dependencies.md | 58 +++ docs/marketplace-submission-pack.md | 120 ++++++ docs/permissions.md | 14 + docs/uat/evidence-v0.2.0.md | 98 +++++ docs/uat/multi-marketplace.md | 88 ++++ kimi.plugin.json | 31 ++ marketplaces/kimi.json | 11 + marketplaces/zcode.json | 31 ++ plugin.json | 31 ++ scripts/generate_distribution.py | 384 ++++++++++++++++++ skills/terraphim-agent-learn/SKILL.md | 24 ++ skills/terraphim-agent-learn/skill.toml | 10 +- skills/terraphim-agent-memory/SKILL.md | 28 +- .../references/command-guide.md | 2 +- skills/terraphim-agent-memory/skill.toml | 12 +- skills/terraphim-grep/SKILL.md | 23 ++ skills/terraphim-grep/skill.toml | 10 +- tests/test_distribution.py | 204 ++++++++++ 36 files changed, 1733 insertions(+), 33 deletions(-) create mode 100644 .claude-plugin/marketplace.json create mode 100644 .claude-plugin/plugin.json create mode 100644 .github/trusted-release-signers create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/validate.yml create mode 100644 .zcode-plugin/plugin.json create mode 100644 README_CN.md create mode 100644 assets/v-model-overview.png create mode 100644 assets/v-model-overview.svg create mode 100644 dist/autoclaw/SHA256SUMS create mode 100644 dist/autoclaw/terraphim-agent-learn-0.2.0.zip create mode 100644 dist/autoclaw/terraphim-agent-memory-0.2.0.zip create mode 100644 dist/autoclaw/terraphim-grep-0.2.0.zip create mode 100644 distribution/metadata.json create mode 100644 docs/distribution.md create mode 100644 docs/install-dependencies.md create mode 100644 docs/marketplace-submission-pack.md create mode 100644 docs/permissions.md create mode 100644 docs/uat/evidence-v0.2.0.md create mode 100644 docs/uat/multi-marketplace.md create mode 100644 kimi.plugin.json create mode 100644 marketplaces/kimi.json create mode 100644 marketplaces/zcode.json create mode 100644 plugin.json create mode 100644 scripts/generate_distribution.py create mode 100644 tests/test_distribution.py diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 0000000..c9568d6 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,18 @@ +{ + "name": "terraphim-skills", + "description": "Public Community skills from Terraphim AI.", + "owner": { + "name": "Terraphim AI", + "email": "engineering@terraphim.ai" + }, + "plugins": [ + { + "name": "terraphim-skills-intro", + "source": "./", + "description": "Search code, capture learning, and retrieve memory with Terraphim command-line tools.", + "version": "0.2.0", + "category": "development", + "homepage": "https://terraphim-skills.md/" + } + ] +} diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..17c3605 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,20 @@ +{ + "name": "terraphim-skills-intro", + "description": "Search code, capture learning, and retrieve memory with Terraphim command-line tools.", + "version": "0.2.0", + "author": { + "name": "Terraphim AI", + "email": "engineering@terraphim.ai" + }, + "homepage": "https://terraphim-skills.md/", + "repository": "https://github.com/terraphim/terraphim-cursor-plugin", + "license": "Apache-2.0", + "keywords": [ + "terraphim", + "code-search", + "learning", + "memory", + "knowledge-graph", + "developer-tools" + ] +} diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json index ab8199f..dab9cf6 100644 --- a/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "terraphim-skills-intro", "description": "Search code, capture learning, and retrieve memory with Terraphim command-line tools.", - "version": "0.1.0", + "version": "0.2.0", "author": { "name": "Terraphim AI", "email": "engineering@terraphim.ai" @@ -9,7 +9,6 @@ "homepage": "https://terraphim-skills.md/", "repository": "https://github.com/terraphim/terraphim-cursor-plugin", "license": "Apache-2.0", - "logo": "assets/logo.svg", "keywords": [ "terraphim", "code-search", @@ -18,6 +17,7 @@ "knowledge-graph", "developer-tools" ], + "logo": "assets/logo.svg", "skills": [ "skills/terraphim-grep", "skills/terraphim-agent-learn", diff --git a/.github/trusted-release-signers b/.github/trusted-release-signers new file mode 100644 index 0000000..5e7c4b7 --- /dev/null +++ b/.github/trusted-release-signers @@ -0,0 +1 @@ +alex@metacortex.engineer namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICRY4s+NewIgKEE/fgGCtIF0Kd9Q9y6pELMuY+xM2mLC diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..43a5efb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,69 @@ +name: Publish marketplace pack + +on: + push: + tags: + - "v*" + +permissions: + contents: read + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Check out tagged source + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.12" + + - name: Validate tagged pack + run: | + expected_tag="v$(python3 scripts/generate_distribution.py --print-version)" + test "$GITHUB_REF_NAME" = "$expected_tag" + git config gpg.format ssh + git config gpg.ssh.allowedSignersFile \ + "$GITHUB_WORKSPACE/.github/trusted-release-signers" + git verify-tag "$GITHUB_REF_NAME" + python3 scripts/generate_distribution.py --check + python3 -m unittest discover -s tests -p 'test_*.py' + + - name: Rebuild and compare AutoClaw archives + run: | + output="$(mktemp -d)" + python3 scripts/generate_distribution.py --autoclaw-dist "$output" + diff -u dist/autoclaw/SHA256SUMS "$output/SHA256SUMS" + for archive in dist/autoclaw/*.zip; do + name="$(basename "$archive")" + cmp "$archive" "$output/$name" + done + + publish: + needs: validate + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Check out validated tagged source + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + + - name: Publish immutable release assets + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release create "$GITHUB_REF_NAME" \ + dist/autoclaw/*.zip \ + dist/autoclaw/SHA256SUMS \ + assets/v-model-overview.svg \ + assets/v-model-overview.png \ + --repo "$GITHUB_REPOSITORY" \ + --title "Terraphim Skills Introduction $GITHUB_REF_NAME" \ + --generate-notes \ + --verify-tag diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..179f6dd --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,39 @@ +name: Validate public marketplace pack + +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.12" + + - name: Check generated manifests + run: python3 scripts/generate_distribution.py --check + + - name: Run tests + run: python3 -m unittest discover -s tests -p 'test_*.py' + + - name: Verify reproducible AutoClaw archives + run: | + output="$(mktemp -d)" + python3 scripts/generate_distribution.py --autoclaw-dist "$output" + diff -u dist/autoclaw/SHA256SUMS "$output/SHA256SUMS" + + - name: Reject whitespace errors + run: git diff --check diff --git a/.zcode-plugin/plugin.json b/.zcode-plugin/plugin.json new file mode 100644 index 0000000..82087fa --- /dev/null +++ b/.zcode-plugin/plugin.json @@ -0,0 +1,30 @@ +{ + "name": "terraphim-skills-intro", + "description": "Search code, capture learning, and retrieve memory with Terraphim command-line tools.", + "version": "0.2.0", + "author": { + "name": "Terraphim AI", + "email": "engineering@terraphim.ai" + }, + "homepage": "https://terraphim-skills.md/", + "repository": "https://github.com/terraphim/terraphim-cursor-plugin", + "license": "Apache-2.0", + "keywords": [ + "terraphim", + "code-search", + "learning", + "memory", + "knowledge-graph", + "developer-tools" + ], + "displayName": "Terraphim Skills Introduction", + "description_i18n": { + "en": "Search code, capture learning, and retrieve memory with Terraphim command-line tools.", + "zh-CN": "使用 Terraphim 命令行工具搜索代码、记录经验并检索记忆。" + }, + "skills": [ + "./skills/terraphim-grep", + "./skills/terraphim-agent-learn", + "./skills/terraphim-agent-memory" + ] +} diff --git a/NOTICE b/NOTICE index 088550c..f0e4833 100644 --- a/NOTICE +++ b/NOTICE @@ -1,2 +1,5 @@ Terraphim Skills Introduction for Cursor Copyright 2026 Terraphim AI + +The V-model overview artwork in assets/ is Copyright 2026 Terraphim AI and is +distributed under the Apache License 2.0 with the rest of this repository. diff --git a/README.md b/README.md index c2d964c..9d737f0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ -# Terraphim Skills Introduction for Cursor +# Terraphim Skills Introduction -Three small, open-source skills introduce Cursor users to Terraphim's local code search, operational learning, and agentic memory commands. +Three small, open-source skills bring Terraphim's local code search, operational +learning, and agent memory workflows to Cursor, Kimi Code, AutoClaw, ZCode, +Hermes Agent, skills.sh, and Claude Code. | Skill | Command family | Purpose | |---|---|---| @@ -8,38 +10,67 @@ Three small, open-source skills introduce Cursor users to Terraphim's local code | `terraphim-agent-learn` | `terraphim-agent learn` | Inspect failures and capture verified operational corrections. | | `terraphim-agent-memory` | `terraphim-agent memory` | Retrieve role-scoped memory, inspect provenance, and govern its lifecycle. | -These are independently written Apache-2.0 command wrappers. They do not contain or redistribute the proprietary Terraphim Skills catalogue. +These Apache-2.0 command wrappers do not bundle executables, secrets, hooks, or +proprietary skill content. They remain useful without a marketplace account. -## Prerequisites +## Install the command dependencies -Install current Terraphim command-line tools using the release instructions at , then verify the installed surface: +On macOS or Linux with Homebrew: ```bash +brew tap terraphim/terraphim +brew install terraphim-grep terraphim-agent terraphim-grep --version terraphim-agent --version terraphim-agent learn --help terraphim-agent memory --help ``` -The wrappers inspect `--help` at runtime so they remain honest about the locally installed version. +The formulae install the signed, checksummed Terraphim Clients v1.21.14 release. +See [dependency installation](docs/install-dependencies.md) for updates, removal, +non-Homebrew installation, signature checks, and PATH troubleshooting. The skills +never install dependencies automatically. + +## Install in your agent + +| Host | Installation | +|---|---| +| Cursor | Already submitted; install from Cursor Marketplace, or use the local-copy instructions below. | +| Kimi Code | Install this repository or add `marketplaces/kimi.json` as a custom marketplace. | +| AutoClaw | Import one checksummed ZIP per skill with **Skills & Connectors → Skills → Create → Add skill file**. | +| ZCode | Add `marketplaces/zcode.json` as a personal marketplace and install `terraphim-skills-intro`; curated listing is a separate maintainer-reviewed PR. | +| Hermes Agent | Add `terraphim/terraphim-cursor-plugin` as a tap, then inspect and install the three skills. | +| skills.sh | Run `npx skills add terraphim/terraphim-cursor-plugin`; use `DISABLE_TELEMETRY=1` to opt out of anonymous telemetry. | +| Claude Code | Add the repository as a marketplace, then install the plugin as shown below. | + +Claude Code commands: + +```text +claude plugin marketplace add terraphim/terraphim-cursor-plugin +claude plugin install terraphim-skills-intro@terraphim-skills +``` + +Availability in a host's curated public marketplace is separate from direct or +custom installation. See the [distribution guide](docs/distribution.md) for exact +install, update, discovery, and removal steps and current publication status. ## Local Cursor installation -For local development, copy this repository into Cursor's local plugin directory: +For local development, copy this repository into: ```text ~/.cursor/plugins/local/terraphim-skills-intro ``` Cursor 3.20 rejects a symlink when its resolved target is outside -`~/.cursor/plugins/local`, so use a real directory for a reliable test. For example: +`~/.cursor/plugins/local`, so use a real directory: ```sh cp -R /path/to/terraphim-cursor-plugin \ ~/.cursor/plugins/local/terraphim-skills-intro ``` -Reload Cursor, open **Customize**, and confirm that all three skills appear. Invoke them by name or ask Cursor to search code, inspect an earlier command failure, or retrieve project memory. +Reload Cursor, open **Customize**, and confirm that all three skills appear. ## Example requests @@ -47,16 +78,23 @@ Reload Cursor, open **Customize**, and confirm that all three skills appear. Inv - “Search project learnings for an earlier failed deployment command.” - “Retrieve role-scoped memory about OAuth redirect validation and show its provenance.” -The skills default to local, read-only operations. Persistent learning or memory changes remain explicit and scoped. +The skills default to local, read-only operations. Persistent learning or memory +changes remain explicit and scoped. Review [permissions and side effects](docs/permissions.md) +before enabling writes or configured model synthesis. -## Terraphim Skills +## Continue with Terraphim Skills -Browse the Terraphim catalogue and non-technical guidance at . This introductory plugin remains useful on its own and requires no marketplace account. +Browse the [Community, Core, and Premium catalogue](https://terraphim-skills.md/skills/). +The public introduction contains no proprietary instructions or entitlement token. +Following a related-skill link never creates a checkout or transaction. Access and +purchase decisions remain on Terraphim's authenticated site and MCP services. ## Development ```bash +python3 scripts/generate_distribution.py --check python3 -m unittest discover -s tests -p 'test_*.py' +python3 scripts/generate_distribution.py --autoclaw-dist dist/autoclaw ``` ## Licence diff --git a/README_CN.md b/README_CN.md new file mode 100644 index 0000000..b655a07 --- /dev/null +++ b/README_CN.md @@ -0,0 +1,55 @@ +# Terraphim Skills Introduction + +本插件提供三个开源技能,让 Kimi Code、ZCode 及其他智能体能够使用 +Terraphim 的本地代码搜索、经验学习和智能体记忆工作流。 + +## 技能 + +- `terraphim-grep`:在本地代码和文档中进行有界搜索,默认离线。 +- `terraphim-agent-learn`:检查失败并记录经过验证的操作修正。 +- `terraphim-agent-memory`:检索角色范围内的记忆并检查来源。 + +这些技能采用 Apache-2.0 许可证,不包含可执行文件、密钥、后台任务或 +Terraphim 专有技能内容。 + +## 安装依赖 + +在 macOS 或安装了 Homebrew 的 Linux 上运行: + +```bash +brew tap terraphim/terraphim +brew install terraphim-grep terraphim-agent +terraphim-grep --version +terraphim-agent --version +terraphim-agent learn --help +terraphim-agent memory --help +``` + +技能不会自动安装软件。没有 Homebrew 时,请从 +[Terraphim Clients v1.21.14](https://github.com/terraphim/terraphim-clients/releases/tag/v1.21.14) +下载适合平台的文件,并用 `SHA256SUMS` 验证。 + +## 安装与使用 + +在 ZCode 的“发现”页面把仓库内的 `marketplaces/zcode.json` 添加为个人市场, +然后安装 `terraphim-skills-intro`。进入官方精选市场仍需由维护者审核并合并 +单独的 Pull Request。各平台的安装、更新和卸载步骤见 +[分发指南](docs/distribution.md)。 + +示例请求: + +- “使用 Terraphim Grep 查找授权回调并显示两行上下文。” +- “搜索项目经验,找出之前失败的部署命令。” +- “检索有关 OAuth 重定向验证的角色记忆,并显示其来源。” + +默认操作是本地且只读的。写入学习或记忆必须获得明确授权;启用模型综合 +前必须确认数据边界和可能的费用。 + +浏览 [Community、Core 和 Premium 技能目录](https://terraphim-skills.md/skills/)。 +此链接只提供信息,不会自动创建结账、付款或交易。 + +隐私政策: + +服务条款: + +许可证:Apache-2.0 diff --git a/assets/v-model-overview.png b/assets/v-model-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..2f2a2958364e18e941abf3d8a45eec176ec6aa6f GIT binary patch literal 107562 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

!m{hs^Ly0@?LL4 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 + + + + + + + + + + + + + + + + + + + + + + The V-Model: Architecture of Discipline + + LEFT SIDE + Planning + RIGHT SIDE + Testing + + + + + + + validates + + + verifies + + + + EXPLORE + + + ELIMINATE + + + EXECUTE + + + + + + VERIFY + + + VALIDATE + + + + + Phase 1: Research + Problem understanding + Constraints & risks + Success criteria + + + + + + Phase 5: Validation + System testing + UAT with stakeholders + Formal sign-off + + + + + + Phase 2: Design + File changes + API signatures + Test strategy + Document NOT-doing + + + + + + Phase 4: Verification + Unit testing + Integration testing + Traceability matrix + Test execution + + + + + + Phase 2.5 + Specification + Deep interview + Edge cases + Tradeoffs + + + + + + Quality + Gate + Code review + UBS & security + Traceability + + + + + + Phase 3: Implementation + Test first | Small commits | Quality checks + + + + DEFECT LOOP-BACK + Defects trace back to the originating left-side phase + diff --git a/dist/autoclaw/SHA256SUMS b/dist/autoclaw/SHA256SUMS new file mode 100644 index 0000000..24c9734 --- /dev/null +++ b/dist/autoclaw/SHA256SUMS @@ -0,0 +1,3 @@ +38d8f394d04aeec419cc52a1d146525b8357bc48df5b03b0f24970e5b37453d9 terraphim-grep-0.2.0.zip +69c2be81b8ff879fc7f9a62f5d48399be98e9a9934f3b17e2fcd657729590012 terraphim-agent-learn-0.2.0.zip +b0f9de6fa5eff647b92bd6a6aeabe825ed3f7e00d1f690ae4f0145a7489357e9 terraphim-agent-memory-0.2.0.zip diff --git a/dist/autoclaw/terraphim-agent-learn-0.2.0.zip b/dist/autoclaw/terraphim-agent-learn-0.2.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..7e2b0e94a368c346f3477c09911e5deaac24fd9d GIT binary patch literal 3061 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 literal 0 HcmV?d00001 diff --git a/dist/autoclaw/terraphim-agent-memory-0.2.0.zip b/dist/autoclaw/terraphim-agent-memory-0.2.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..adc4533de4ed69a437df02fe272d1969ed79fa8f GIT binary patch literal 3290 zcmai%X*3jU8^^~sM3%BEyBJyX*taZ`rLl~r5JqE}VK9R+rX>3=jJn+a%gGT3bY*ER zKLi2*vm5|`=*bHniNm@0d7?22E*?lMUIBx|_~L?;U=VW)3q_23mYpSWQk|=H)sE{; z0Xt&i&Equ}7~{A!hC3e}>4RfsjnD2@ALA+8c$s*(dKgP_UzeV&E2&5NYi=*LYCH{u z+nMa*W$CqK;&NBKn=Wv#kngUh+%Rnm^kV7Bfo!Hk!tnVq&~DC=*ceT-3T?p+vm7g* zwTMS&WFx(<>z>{FrttzC*k^t@uI&^O^{e zF#2ut5l5oQy+BHqlUzlo4Oe<%I?R~`Ts#nETfuq&azCxJIx_vtn95#Hvkd^F8y4~s zW$gGk4pwVg5Ux`I6@Di-qEaA!aTTN{8&NG;L$D<*NJlS9WY1L;vWNOLUAd+NrVm)TP9HUV zM1QqL8cfsBV&r+smAhq#h6Ci;$uGe7K9`zeAw1jA=PLSU6)>DIySuiELV1uISZPvY z?A{_La&D#~4dYkdf_SeszLX|Qt1RC$ zOPJ4|*Z=(G{V22%R8MPT=H;-?=C{ta4&}1Y2n2}ct_@EHRF&Jxwb83eF4OH%`<(7W zoxzfvVo^@s0Mec4VH{vQ3YJQ%807u+!@sTm)zRu9oF%H=siMK)V&wzG#EKkgM2olm z;?mK@*K1yhyQOo|49xXfth{1Z-t0(oTjA8z?yg z!h-;Qr6*Vh}Az7V+q|EdeFZ5)xcu) zZ?7pM*R+eyXNk^YP;l=)6U=-x=WEAay3zMloA;B+!&$EJr7f188!h)#l%p62*RqyO zY7H5JHgYVb$HiS{3nyQzbBDz;b{U)r0S4xXEbq8NrlY$o<3x^*WYcx@gT-*0cTziM zlmDzY^wQ3htfudSB#?J^J}X@9Dc{GVvovn$8|}kzw%DIUTQ+ zhU>ms<$gn7BRn2Aen(UcdWwPI0oMP*%~-w?8wafvBXkcr&L%T+pe4v7 z4%ogr`T@c#2DYR=?zh!OmkiN`Nvx{NUoqtAubBwAtCL{#5o3VT_*72XAK5`)i0WR_ z(DYN*yyv1w7(}7!zVBOwt^wR?TzDH@=La_wRf=?U$IE3igKqDRm!Y}*`5(iZ*^+@D ztVbf?q1L9yz?V;f_Ab~SRkcF%=B+6zU#TnZ*-dbU?RKspX?j~?rz<_Z?TwX?i9%+XP#@fp7+F{gM~sdbrLWl%WiJ`>iH*UHs+sdtDe za!(mAy7gskT~kuJ7DBJ%2pB+FNGR|}V>Cc8r>*iR<&1^!@6uikAGs~mim`JZhJ4LI zx69wYD=8g9f$SxrHge9bGio;u(A@Kk(rzfu8B7GmHT*8LC;CO5iw0m7v6s0M#_b~E z3T4=J&dA6+L-a2B5Q~nF7zyA&mW~vzR2R!Osqw`$K>YjuP-VI<*KIIsNRw$mmfxZ6O|$985p-%1e$>NJKblfJ*SI<1W zJa2Q97DCs0s`-ex#R>f{UmMP3Mjz1u0DTMqfXeTE4TnS_aY(EiGC;}A7lU!Zx+{1D zqTP`vRtJX}Vkeckp0Dzmrt*U4?pMTU zsa72Hjze@np`?~@E@4^6h3c_S*LVe-6m>TluX-g(3g~^lNr>TZ{fmIlVG^h#T4jUYN1q(zgWi!$^!D zg-!||Uy=6U`6c2Ux+bFkgPa#_{Be7584s*V$oyUqzMf~K6A;;VOp}S@)b(dq8T6}) zxL`%GvGcEXw0wQQMtV-%eR6k<=eb&7(}apW;q$Y@V2c?$(+mnXzWcjaV4XzM^G;jO zmtRmY58Rn*WcC_NVt?LVH8`ivSXq`&RZva3R&`t$*@rSK5*yf#U!vSB17TwNFX`p8 ztL?)H7@>VF0| zQk>Fqf3hjh;Xu|;XfB8&EvYTb!&&|S>L^aM{1M-;o3iMidW)q!+bmTWD>&~JCsH>% zJ5W0}4a~Y&vl1|_lF82>b7;eqTBB4=J5rsmG>(gq`%^Mzb2$X$S{Oq9$^741((vRG zLec{OohMon|Gkz1ywN^Big;g)4?N>d%9I#a?0P8cLV!|uGCTL@RJTkmWRtsUA}grb zCYXC%Z&^2_hkT*O?0i0`?O;{uQ2dtbm>wU)_t*Nhxb94ZHZ7D>=KNv^@h1t3^zX`? z*L)&7_k#1Wye{g&oN7C`eeRKjvp;PvRR+JE0x!5Pf@1BMnLtZ*zfkwVe--Q{&)q|< zC$>!qj}w#RlM;$*UWO3nqmOssCT8D~f@sCy89HEG68$%$f^AJ_P|8@mHQr+UN_EZs z?PT!;2Lx}c8@PKK#t(ngaxMy~Pn10_5Q3lnf~|B+P=2HwhF~)fTDLS6inT$r}!NRTfm--q%AysC3(C{|=ByLf+T?iYK$yqO?J(7CrIr%Ibz zbvJ6wG?TUZsciTF@{;VdFi}PYSHtWoGR^gi5Zp-7E&e&8P@1<~xlBgyli3`m zwb~~~2Wo$?K_PVXJPf~|p=IWy>ic#+oh5ph09xw(N9_ zA!QlcFxhvG45cZ3&iDOsuCH@_-}_$g^<2;U$Nj$7bwAH@-zaldHX#52xDL-50BLAA z{D~a^295!M$l*MHcjL}yiuovOSedV?|cD$$HOINg=uM)B}}SiV*d ze~hfIrrR*IA=uoqS_y0(m4@hGQX64=Y6-Pt=yDM9q5UWAJDobYPuh%=O52;1E9aE; z^{EJP{-G`*s{Kh{?JGS!+ZcDK5_n{Ad^7SI?dHkyBGqiH{y{ZIiKCKo#S-G^mH09S z=AFfTF6jp@&M>4G;v?AMtl$`SKECf4ah`$c*LL zRF)T`K!gzkaoLP&s7O9Q-^o>)&s$W zFw%sRb*9KjH;+JEKOcUl%Ch1~tzw8bN^H5p{e=E*Q@@Jf5puDOjwiJ6eu_`(lyBr7 zM<8MSi;>9ZxsB~%`9(dwH!6HHz776uL-kd!oBrrrA@-pi zCihOtk@Ye|C$^0WM*1i1GL`SQ?0-M-LioiAC%woT$uwg+@cLq*g2#uY9u<96ufCWY zQ^QM0|D5nXlxG}XFz~)n+>{Y5mvFCGjb8EXyLkh1lLY@(xDe3OZ466RJpWN5ED9?O zXlv<#;UO+8Sg9pmKCCkDenH!DlHOJqopeLANs!kcIucvSkEk8@AEPWC_3#QHbu{lx zS}g4$a8@&pnmaK`djSJy8a{fh`=ESy4ayvsy7aq*Y^UjITrh;8jjDnI3U6-?<@I6Cr*kjpd zdzR~`dC<-DM6;+3VK}%0KWroI^QBbq)$3)47Ll6s&bDrbrV%SHe2>g7sK8YuydI4@ zZ-8HU_%=$Q+n3Y9o170LqPgBADdo}7ECEWi`Ho#7+a#7V2a)Bi4d@>qaP_j=s?G56 zhhTAL>?tAh5Z!dufoM|S$Cy#;mQwTcicawRLcFm#&^2|x9}+l(@gMa=k3sMUmlYXJ z5ZDt6O|yKba+P&nSit*-3xR0qBt3{KKHZwGe!(oP)IgjKE&dvAoSkA528|=E<}>?G zS0sGn|4Kv@F3i7~&(qq*P0lLRaWJY(O8Gi#y=&A`a6lmoRjkCjLl{pvf*>6Dr@cq^ zpDUz89(2AQe)dk0&RegSC1-{wKXy-2RezDMJEuiL-*Q=w86sJ0tdCdYsef`y`YGKV zt-e&8K4TgXu2HfRl<#C-%AYfA`NhJO^x6FtPZA<&mPziCE_1YtuaokzkStV`QBF*~ z;UfZKD2FAOq&}Qc_2oDCPImq?8dINo1iPQ?ceW@fxcJh?5A;H+_JOu~f?N%4Z%_=x;A}ExE?$ygfQWmgIb?g7mj_vOYDZ z=(OHd1)j4Vk7KR6c#b>h~4x(0YCdWT{>JP&mOdxa8DgMi*L6~u#0r9N}Uy1Ix82;-5$)Ns4%kvD1S;3531 z=;GW^hQ+Dmn3R$7)vEI=yw~Q`Tp|JjDR43iWW=~37|IO=5j7yCW&|dr+Kb;TZ z7u7u0MZ{+7&@R>A`Z|w`4ZmS$Hez`ho|-`O3OWk{Ii0uV-fk&q%$I?Q4c5&s?9E zHbKurW!7JWpatsNMJz$)`IIx8;qk7&>zS8}M&4^o(`0wkah(bN`s3A${DGgcIEG2v z?p8=s#1H$z#54%ufqmzmt%uIVO=2nU52~~^PGIWOyN(=9GR4TDQ)9A37;3H{g_h>S zza`&MkK?!i|JgDP{=D{SZcwB37qY+YQ50c^MEkJ=H3F@ogn^IjA7$RM-VTHYH*|EQttqm~J#3KC_{;p9&&iotGMn!xFF$)39Ca|ERSgz){1eH&AqXPJz_>610PZ!}rc z1kAC#Vtz?qXHb0h7JRRNcZs?4y$}ik9-JLoqskD$yFFQdy%6YHg?&!%90l(gAWk77Xv56S;@`GYf+21w4j`}>`H)qUUmerSri^ufusZ_~G0Sy1LIM}%1a zx9>bGynio3)L-F$xX@ogew|bQfdBwP)CrD%fc&4S^(*eLE%7(*kwe$~%jf=X5R^Il S;j;k1dbsBg<4x|rvVQ^gvQoSN literal 0 HcmV?d00001 diff --git a/distribution/metadata.json b/distribution/metadata.json new file mode 100644 index 0000000..8b7a809 --- /dev/null +++ b/distribution/metadata.json @@ -0,0 +1,59 @@ +{ + "schema_version": 1, + "plugin": { + "name": "terraphim-skills-intro", + "display_name": "Terraphim Skills Introduction", + "version": "0.2.0", + "description": "Search code, capture learning, and retrieve memory with Terraphim command-line tools.", + "description_zh_cn": "使用 Terraphim 命令行工具搜索代码、记录经验并检索记忆。", + "author_name": "Terraphim AI", + "author_email": "engineering@terraphim.ai", + "homepage": "https://terraphim-skills.md/", + "catalogue": "https://terraphim-skills.md/skills/", + "repository": "https://github.com/terraphim/terraphim-cursor-plugin", + "license": "Apache-2.0", + "category": "developer-tools", + "keywords": [ + "terraphim", + "code-search", + "learning", + "memory", + "knowledge-graph", + "developer-tools" + ] + }, + "runtime": { + "tap": "terraphim/terraphim", + "release": "https://github.com/terraphim/terraphim-clients/releases/tag/v1.21.14", + "formulae": [ + "terraphim-grep", + "terraphim-agent" + ], + "verify": [ + "terraphim-grep --version", + "terraphim-agent --version", + "terraphim-agent learn --help", + "terraphim-agent memory --help" + ] + }, + "skills": [ + { + "name": "terraphim-grep", + "path": "skills/terraphim-grep", + "command": "terraphim-grep", + "mode": "read-only-by-default" + }, + { + "name": "terraphim-agent-learn", + "path": "skills/terraphim-agent-learn", + "command": "terraphim-agent learn", + "mode": "explicit-writes" + }, + { + "name": "terraphim-agent-memory", + "path": "skills/terraphim-agent-memory", + "command": "terraphim-agent memory", + "mode": "explicit-writes" + } + ] +} diff --git a/docs/distribution.md b/docs/distribution.md new file mode 100644 index 0000000..10b0846 --- /dev/null +++ b/docs/distribution.md @@ -0,0 +1,94 @@ +# Multi-marketplace distribution + +This repository is the canonical source for all hosts. Release `v0.2.0` contains +exactly three skills and deterministic AutoClaw archives. + +## Availability model + +- **Direct/custom install** is controlled by the user and available from the + immutable GitHub release. +- **Curated marketplace listing** is controlled by each marketplace maintainer and + remains pending until that marketplace confirms indexing or approval. +- Cursor is already submitted and is a regression target, not a new submission. +- AutoClaw local ZIP import is supported. ZhipuAI Skills Center inclusion is a + separate external review; ClawHub is not treated as proof of that inclusion. + +## Kimi Code + +Install the immutable release URL through Kimi Code's `/plugins install`, or +open `/plugins marketplace` with +`https://raw.githubusercontent.com/terraphim/terraphim-cursor-plugin/v0.2.0/marketplaces/kimi.json` +and install +`terraphim-skills-intro`. Run `/plugins reload` (or start a new session), then +confirm that exactly the three documented skills appear. The native manifest is +`kimi.plugin.json`; root `plugin.json` provides compatibility with Kimi CLI +releases whose shell-level `kimi plugin install` command expects that filename. +Update by installing the newer tag; remove through Kimi's plugin manager. + +## AutoClaw + +Download the three ZIP files and `SHA256SUMS` from the `v0.2.0` release. Verify +each digest, then use **Skills & Connectors → Skills → Create → Add skill file**. +Import each ZIP separately. Restart AutoClaw and confirm the skills persist. Remove +them through the same Skills screen. If Homebrew binaries are missing from the GUI +`PATH`, restart AutoClaw after installing the dependencies. + +## ZCode + +Open ZCode's **Discover** view and add +`https://raw.githubusercontent.com/terraphim/terraphim-cursor-plugin/v0.2.0/marketplaces/zcode.json` +as a personal marketplace source, install `terraphim-skills-intro`, then confirm the Plugin +Skills view shows exactly three skills. Curated discovery requires a separate +pull request to `zai-org/zcode-plugins`; this repository does not claim that +acceptance before the maintainers merge it. Update or remove the installed +plugin through ZCode's plugin manager. + +## Hermes Agent + +Add the repository as a GitHub tap, then inspect each skill before installing: + +```bash +hermes skills tap add terraphim/terraphim-cursor-plugin +hermes skills inspect terraphim/terraphim-cursor-plugin/skills/terraphim-grep +hermes skills inspect terraphim/terraphim-cursor-plugin/skills/terraphim-agent-learn +hermes skills inspect terraphim/terraphim-cursor-plugin/skills/terraphim-agent-memory +``` + +Record the immutable `v0.2.0` provenance. Remove the skills with Hermes' normal +skill-management command. + +## skills.sh + +Use an isolated agent target and run: + +```bash +npx skills add terraphim/terraphim-cursor-plugin +``` + +Set `DISABLE_TELEMETRY=1` to opt out of anonymous telemetry. Confirm exactly three +skills are offered and that their files match tag `v0.2.0`. Update by repeating the +command for the new tag; remove the installed skill directories through the target +agent's documented skill manager. + +## Claude Code + +```text +claude plugin marketplace add terraphim/terraphim-cursor-plugin +claude plugin install terraphim-skills-intro@terraphim-skills +``` + +Run `claude plugin validate --strict .` before release. Use `claude plugin list` +to verify the installed version and normal Claude plugin commands to update or +remove it. + +## Cursor + +Install from Cursor Marketplace. For local testing, follow the real-directory +copy instructions in the README; Cursor 3.20 rejects external symlink targets. + +## Catalogue boundary + +Each host links to . Community skills are +freely obtainable; Core and Premium content follows the catalogue's entitlement +rules. Public packages never embed proprietary bodies, tokens, checkout URLs, or +automatic transactions. diff --git a/docs/install-dependencies.md b/docs/install-dependencies.md new file mode 100644 index 0000000..aafdf44 --- /dev/null +++ b/docs/install-dependencies.md @@ -0,0 +1,58 @@ +# Install Terraphim command dependencies + +The three skills are workflow instructions. They call two local binaries and never +install software automatically. + +## Homebrew installation + +On macOS or Linux with Homebrew: + +```bash +brew tap terraphim/terraphim +brew install terraphim-grep terraphim-agent +terraphim-grep --version +terraphim-agent --version +terraphim-agent learn --help +terraphim-agent memory --help +``` + +The formulae use immutable, signed and checksummed v1.21.14 archives. If both +binaries already pass the four probes, do not reinstall them. + +## Update + +```bash +brew update +brew upgrade terraphim-grep terraphim-agent +``` + +Run the four probes again after upgrading. The installed `--help` output is the +authority for available options. + +## Remove + +```bash +brew uninstall terraphim-grep terraphim-agent +brew untap terraphim/terraphim +``` + +Removing the binaries does not remove learning or memory data. Review local data +locations before deleting user-created state. + +## Without Homebrew + +Download the correct archive and `SHA256SUMS` from the +[v1.21.14 release](https://github.com/terraphim/terraphim-clients/releases/tag/v1.21.14). +Verify the archive checksum before extracting it. macOS archives are signed and +notarized; do not bypass Gatekeeper. Linux archives are signed through the release +checksum and signature chain. + +## Troubleshooting + +- If a host cannot resolve a binary, restart it after installation so it receives + the current `PATH`. +- Homebrew usually installs to `/opt/homebrew/bin` on Apple Silicon, + `/usr/local/bin` on Intel macOS, and `/home/linuxbrew/.linuxbrew/bin` on Linux. +- Do not copy credentials or private memory into diagnostics. +- Do not use `xattr` or Gatekeeper-bypass commands. Verify the official archive + and report a signature failure instead. diff --git a/docs/marketplace-submission-pack.md b/docs/marketplace-submission-pack.md new file mode 100644 index 0000000..b1dd09e --- /dev/null +++ b/docs/marketplace-submission-pack.md @@ -0,0 +1,120 @@ +# Terraphim Skills Introduction — marketplace submission pack + +This document is the reusable, public submission collateral for the Terraphim +introductory skills plugin. Platform-specific manifests are generated from +`distribution/metadata.json`; this copy should remain consistent with that +canonical source. + +## Listing identity + +- **Name:** Terraphim Skills Introduction +- **Slug:** `terraphim-skills-intro` +- **Publisher:** Terraphim AI +- **Category:** Developer tools +- **Licence:** Apache-2.0 +- **Homepage:** +- **Public catalogue:** +- **Repository:** + +### Tagline + +Search code, capture learning, and retrieve memory with Terraphim command-line +tools. + +### Short description + +Three Community skills introduce local code search, structured learning +capture, and reusable memory. The skills run Terraphim's local command-line +tools and explain every write before it happens. + +### Long description + +Terraphim Skills Introduction gives coding agents three focused, open-source +workflows: + +1. `terraphim-grep` searches local code and documentation with context. +2. `terraphim-agent-learn` turns an explicit lesson into a reusable local + knowledge entry. +3. `terraphim-agent-memory` retrieves, records, and applies local project + memory. + +The plugin contains instructions, not bundled executables. Users install the +signed Terraphim binaries through Homebrew and can verify both tools before an +agent uses them. Search is read-only by default. Learning and memory writes are +performed only when the user asks for them. + +The Community skills stand on their own. They also link neutrally to the +Terraphim Skills catalogue, where users can discover Community, Core, and +Premium workflows without an in-skill checkout or purchase prompt. + +## Suggested prompts + +- “Use Terraphim Grep to find where OAuth callback state is validated.” +- “Capture what we learned from this incident for the next session.” +- “Search project memory for the deployment constraints, then cite the source.” + +## Runtime prerequisites + +```sh +brew tap terraphim/terraphim +brew install terraphim-grep terraphim-agent +terraphim-grep --version +terraphim-agent --version +terraphim-agent learn --help +terraphim-agent memory --help +``` + +See [Install dependencies](install-dependencies.md) for signed-release and +non-Homebrew options. + +## Permissions and data handling + +- No credentials are bundled. +- No telemetry is added by this plugin. +- Search reads only paths the user supplies. +- Learning and memory commands write only after an explicit request. +- The user controls the local Terraphim configuration and storage location. + +See [Permissions](permissions.md) for the complete boundary. + +## Editorial collateral + +Use the canonical article only: +. + +The repository includes Terraphim-owned V-model artwork in both formats: + +- `assets/v-model-overview.svg` +- `assets/v-model-overview.png` + +## Platform artefacts + +| Host | Artefact | Delivery route | +| --- | --- | --- | +| Cursor | `.cursor-plugin/plugin.json` | Existing Cursor marketplace listing; do not resubmit | +| Kimi Code | `kimi.plugin.json`, compatibility `plugin.json`, and `marketplaces/kimi.json` | Direct install and publisher-owned marketplace | +| AutoClaw | `dist/autoclaw/*.zip` and `SHA256SUMS` | Import one skill ZIP at a time | +| ZCode | `.zcode-plugin/plugin.json` and `marketplaces/zcode.json` | Personal marketplace; separate curated-marketplace PR | +| Hermes Agent | `skills/*/SKILL.md` | Repository/local skills directory | +| skills.sh | `skills/*/SKILL.md` | Repository URL discovery/install | +| Claude Code | `.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json` | Direct install and publisher-owned marketplace | + +An artefact being present does not imply that a third-party catalogue has +accepted or featured the plugin. Record curated acceptance only after the host +confirms it. + +## Submission checklist + +1. Run `python3 scripts/generate_distribution.py --check`. +2. Run `python3 -m unittest discover -s tests -p 'test_*.py'`. +3. Build AutoClaw archives and verify `dist/autoclaw/SHA256SUMS`. +4. Install and exercise the plugin with the host-specific UAT protocol. +5. Confirm the listing uses the canonical homepage, repository, licence, and + article URL above. +6. Confirm the listing does not claim bundled binaries, automatic dependency + installation, proprietary skill content, or curated acceptance. +7. Publish the SSH-signed tag with the trusted release key; the release workflow + verifies that signature, revalidates the pack in a read-only job, then uses a + separate write-scoped job to attach the deterministic AutoClaw archives, + checksums, and V-model artwork. +8. Save the host's submission URL and status in the release evidence. diff --git a/docs/permissions.md b/docs/permissions.md new file mode 100644 index 0000000..dc5abad --- /dev/null +++ b/docs/permissions.md @@ -0,0 +1,14 @@ +# Permissions and side effects + +| Skill | Network | Command execution | Default writes | Explicit side effects | +|---|---|---|---|---| +| Terraphim Grep | None by default; configured synthesis may call a model | `terraphim-grep` | None | Paid or external synthesis only when requested | +| Agent Learn | None required for local commands | `terraphim-agent learn` | None | Capture, correction, hooks, replay, or export only when authorised | +| Agent Memory | None required for local commands | `terraphim-agent memory` | None | Capture, distil, retire, or export only when authorised | + +The package requires local `terraphim-grep` and `terraphim-agent` binaries. It +contains no executables, secrets, hooks, MCP servers, agents, background tasks, or +proprietary skill bodies. Source is Apache-2.0. + +Read-only inspection comes first. A skill must identify a write, execution, model +call, scope change, or export before requesting the corresponding authorisation. diff --git a/docs/uat/evidence-v0.2.0.md b/docs/uat/evidence-v0.2.0.md new file mode 100644 index 0000000..04e7e33 --- /dev/null +++ b/docs/uat/evidence-v0.2.0.md @@ -0,0 +1,98 @@ +# Validation evidence — v0.2.0 + +Date: 2026-09-15 + +This record distinguishes automated proof from checks that still require a +specific desktop host or third-party marketplace decision. + +## Package and dependency proof + +- `terraphim-grep --version`: `1.21.14` +- `terraphim-agent --version`: `1.21.14` +- `terraphim-agent learn --help`: passed +- `terraphim-agent memory --help`: passed +- Every command and option shown in the three `SKILL.md` files was checked + against the installed v1.21.14 command help. +- Generated-manifest drift check: passed. +- `tsm validate` passed for all three signed Community skill directories at + skill version `1.0.1`. +- Python contract/regression suite: 22 tests passed, including local Markdown + link resolution. +- Ruff lint and formatting checks: passed. +- Markdown structure lint (with the repository's long-line and compact-table + style accepted): passed. +- GitHub Actions workflow lint: passed. +- Release CI uses exact action commit pins, disables persisted checkout + credentials, verifies the SSH-signed tag against the committed trusted public + key, and separates read-only validation from the write-scoped publication job. +- `git diff --check`: passed. + +## Host proof + +### Claude Code + +- CLI validator: `claude plugin validate --strict .` passed. +- A temporary isolated Claude configuration added this repository as the + `terraphim-skills` marketplace. +- `terraphim-skills-intro@terraphim-skills` installed successfully at version + `0.2.0`. +- The installed copy contained exactly the three allowlisted `SKILL.md` files. + +### Kimi Code + +- Kimi CLI `1.44.0` installed the repository in an isolated `KIMI_SHARE_DIR`. +- `kimi plugin info terraphim-skills-intro` reported version `0.2.0`. +- The installed copy contained exactly the three allowlisted `SKILL.md` files. +- The pack includes Kimi's native `kimi.plugin.json`, a compatible root + `plugin.json`, and the current version-2 custom marketplace contract. + +### skills.sh + +- The current `skills` CLI inspected the local repository with telemetry + disabled. +- It reported `Found 3 skills` and listed only `terraphim-grep`, + `terraphim-agent-learn`, and `terraphim-agent-memory`. + +### ZCode + +- The plugin was staged into a clean checkout of `zai-org/zcode-plugins`. +- The official `scripts/validate.py` accepted all 22 entries, including + `terraphim-skills-intro`. +- The official `scripts/build_dist.py` built + `plugins/terraphim-skills-intro/0.2.0/plugin.zip` successfully. +- Curated availability remains pending until Z.ai maintainers merge a separate + submission pull request. + +### AutoClaw + +- Three deterministic archives were built, one per skill. +- `unzip -t` passed for every archive. +- `shasum -a 256 -c SHA256SUMS` passed for all three archives. +- Desktop import and agent invocation still require the Zhipu AutoClaw desktop + application; archive validation is not represented as desktop UAT. + +### Hermes Agent + +- Hermes Agent `v1.0.0` accepted `terraphim/terraphim-cursor-plugin` as a tap + at the expected `skills/` path. +- Live search could not complete because Hermes uses GitHub's Contents API and + the unauthenticated host IP returned HTTP 403 `API rate limit exceeded`. +- The Git remote and `main` branch were independently reachable. This is an + external rate-limit constraint, not proof of package failure or a completed + Hermes runtime UAT. + +### Cursor + +- Cursor manifest contract tests passed and the existing real-directory local + installation warning remains documented. +- Cursor marketplace submission was completed before this multi-host revision. + A post-release Cursor update check remains a publication task, not a local + package-validation result. + +## Publication boundary + +Direct/custom installation is proven only where stated above. Curated +marketplace acceptance is controlled by each marketplace owner and must not be +claimed until that owner confirms it. The public package contains Community +skill instructions only; Core and Premium content remains on the Terraphim +Skills service. diff --git a/docs/uat/multi-marketplace.md b/docs/uat/multi-marketplace.md new file mode 100644 index 0000000..eff5b3f --- /dev/null +++ b/docs/uat/multi-marketplace.md @@ -0,0 +1,88 @@ +# Multi-marketplace UAT protocol + +This protocol validates the same three public Community skills in every +supported host. Run it from a clean temporary profile or test workspace so an +older installation cannot make a failed package appear healthy. + +## Preconditions + +1. Install and verify the runtime dependencies using + [Install dependencies](../install-dependencies.md). +2. Confirm the plugin version is `0.2.0`. +3. Confirm the installed skill set is exactly: + `terraphim-grep`, `terraphim-agent-learn`, and + `terraphim-agent-memory`. +4. Use a disposable repository containing one searchable marker and a writable + local Terraphim memory store. + +## Shared acceptance scenarios + +Run all scenarios through the host's agent interface, not only from a shell. + +### UAT-1 — dependency guidance + +Ask: “Check whether the Terraphim dependencies are installed.” + +Pass when the agent runs or proposes the documented version/help probes. If a +binary is absent, it must show the Homebrew commands and must not silently +install software. + +### UAT-2 — local search + +Ask: “Use Terraphim Grep to find the unique marker in this workspace and show +two lines of context.” + +Pass when the result comes from `terraphim-grep`, identifies the expected file, +and makes no file changes. + +### UAT-3 — learning capture + +Ask: “Capture this explicit lesson with Terraphim Agent: use the staging API +for marketplace smoke tests.” + +Pass when the agent explains the intended write, invokes the documented +`terraphim-agent learn` flow only after the request, and the lesson can be +retrieved afterward. + +### UAT-4 — memory retrieval and write boundary + +Ask first: “Search Terraphim memory for marketplace smoke tests.” Then ask: +“Record that production payment tests require an amount-bounded mandate.” + +Pass when retrieval cites the matching local memory, the first request writes +nothing, and the second explicit request creates a retrievable entry. + +### UAT-5 — catalogue boundary + +Ask: “Where can I find more Terraphim skills?” + +Pass when the agent provides as neutral +discovery. It must not initiate checkout, fabricate access, or present Premium +content as bundled. + +## Host-specific installation and evidence + +| Host | Installation route | Required evidence | +| --- | --- | --- | +| Cursor | Existing marketplace listing or repository plugin install | Plugin version, three discovered skills, UAT-1 through UAT-5 | +| Kimi Code | Install the tagged repository with `/plugins install`, or open `/plugins marketplace` with `marketplaces/kimi.json`; use `kimi plugin install` for the compatibility CLI | Plugin listing, exactly three skills after reload, plus UAT-1 through UAT-5 | +| AutoClaw | Import each ZIP from `dist/autoclaw/` | Successful import, checksum match, one skill per archive, UAT for all three skills | +| ZCode | Install from the repository using `.zcode-plugin/plugin.json` | Plugin listing and UAT-1 through UAT-5 | +| Hermes Agent | Add the repository's `skills/` entries to the configured skills directory | Three discovered skills and UAT-1 through UAT-5 | +| skills.sh | Install/discover from the public repository URL | Three discovered skills and UAT-1 through UAT-5 | +| Claude Code | Add the local/publisher marketplace, then install `terraphim-skills-intro` | Strict plugin validation, installed listing, UAT-1 through UAT-5 | + +Capture the host and version, plugin version, command transcript or screenshots, +and the final pass/fail result. Redact local paths or memory content that is not +intended for publication. + +## Stop conditions + +Do not publish for a host when any of these conditions holds: + +- a manifest fails the host's current validator; +- extra skills or proprietary files are included; +- dependency installation happens without user approval; +- a read-only search changes files; +- the plugin implies that Community installation grants Core or Premium access; +- the AutoClaw checksum or reproducibility check fails. diff --git a/kimi.plugin.json b/kimi.plugin.json new file mode 100644 index 0000000..a036352 --- /dev/null +++ b/kimi.plugin.json @@ -0,0 +1,31 @@ +{ + "name": "terraphim-skills-intro", + "description": "Search code, capture learning, and retrieve memory with Terraphim command-line tools.", + "version": "0.2.0", + "author": { + "name": "Terraphim AI", + "email": "engineering@terraphim.ai" + }, + "homepage": "https://terraphim-skills.md/", + "repository": "https://github.com/terraphim/terraphim-cursor-plugin", + "license": "Apache-2.0", + "keywords": [ + "terraphim", + "code-search", + "learning", + "memory", + "knowledge-graph", + "developer-tools" + ], + "skills": [ + "./skills/terraphim-grep", + "./skills/terraphim-agent-learn", + "./skills/terraphim-agent-memory" + ], + "interface": { + "displayName": "Terraphim Skills Introduction", + "shortDescription": "Local search, learning, and memory workflows", + "developerName": "Terraphim AI", + "websiteURL": "https://terraphim-skills.md/" + } +} diff --git a/marketplaces/kimi.json b/marketplaces/kimi.json new file mode 100644 index 0000000..aec5409 --- /dev/null +++ b/marketplaces/kimi.json @@ -0,0 +1,11 @@ +{ + "version": "2", + "plugins": [ + { + "id": "terraphim-skills-intro", + "displayName": "Terraphim Skills Introduction", + "description": "Search code, capture learning, and retrieve memory with Terraphim command-line tools.", + "source": "https://github.com/terraphim/terraphim-cursor-plugin/archive/refs/tags/v0.2.0.zip" + } + ] +} diff --git a/marketplaces/zcode.json b/marketplaces/zcode.json new file mode 100644 index 0000000..0a0b6eb --- /dev/null +++ b/marketplaces/zcode.json @@ -0,0 +1,31 @@ +{ + "name": "terraphim-skills", + "description": "Public Community skills from Terraphim AI.", + "plugins": [ + { + "name": "terraphim-skills-intro", + "source": { + "source": "github", + "repo": "terraphim/terraphim-cursor-plugin", + "path": ".", + "ref": "v0.2.0" + }, + "description": "Search code, capture learning, and retrieve memory with Terraphim command-line tools.", + "description_i18n": { + "en": "Search code, capture learning, and retrieve memory with Terraphim command-line tools.", + "zh-CN": "使用 Terraphim 命令行工具搜索代码、记录经验并检索记忆。" + }, + "version": "0.2.0", + "category": "developer-tools", + "tags": [ + "terraphim", + "code-search", + "learning", + "memory", + "knowledge-graph", + "developer-tools" + ], + "strict": true + } + ] +} diff --git a/plugin.json b/plugin.json new file mode 100644 index 0000000..a036352 --- /dev/null +++ b/plugin.json @@ -0,0 +1,31 @@ +{ + "name": "terraphim-skills-intro", + "description": "Search code, capture learning, and retrieve memory with Terraphim command-line tools.", + "version": "0.2.0", + "author": { + "name": "Terraphim AI", + "email": "engineering@terraphim.ai" + }, + "homepage": "https://terraphim-skills.md/", + "repository": "https://github.com/terraphim/terraphim-cursor-plugin", + "license": "Apache-2.0", + "keywords": [ + "terraphim", + "code-search", + "learning", + "memory", + "knowledge-graph", + "developer-tools" + ], + "skills": [ + "./skills/terraphim-grep", + "./skills/terraphim-agent-learn", + "./skills/terraphim-agent-memory" + ], + "interface": { + "displayName": "Terraphim Skills Introduction", + "shortDescription": "Local search, learning, and memory workflows", + "developerName": "Terraphim AI", + "websiteURL": "https://terraphim-skills.md/" + } +} diff --git a/scripts/generate_distribution.py b/scripts/generate_distribution.py new file mode 100644 index 0000000..d2f8a12 --- /dev/null +++ b/scripts/generate_distribution.py @@ -0,0 +1,384 @@ +#!/usr/bin/env python3 +"""Render native marketplace manifests and deterministic AutoClaw archives.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path +import re +from typing import Sequence +import zipfile + + +ROOT = Path(__file__).resolve().parents[1] +METADATA = ROOT / "distribution" / "metadata.json" +ALLOWED_SKILLS = ( + "terraphim-grep", + "terraphim-agent-learn", + "terraphim-agent-memory", +) + + +def load_metadata(root: Path) -> dict[str, object]: + """Load canonical distribution metadata. + + Raises: + ValueError: If the metadata root is not a JSON object. + """ + + value = json.loads((root / "distribution" / "metadata.json").read_text()) + if not isinstance(value, dict): + raise ValueError("distribution metadata must be a JSON object") + return value + + +def _frontmatter(path: Path) -> dict[str, str]: + text = path.read_text(encoding="utf-8") + match = re.match(r"\A---\n(.*?)\n---\n", text, re.DOTALL) + if not match: + return {} + fields: dict[str, str] = {} + for line in match.group(1).splitlines(): + key, separator, value = line.partition(":") + if separator: + fields[key.strip()] = value.strip() + return fields + + +def validate_metadata(root: Path, metadata: dict[str, object]) -> list[str]: + """Return deterministic validation errors; empty means valid.""" + + errors: list[str] = [] + plugin = metadata.get("plugin") + runtime = metadata.get("runtime") + skills = metadata.get("skills") + if metadata.get("schema_version") != 1: + errors.append("schema_version must be 1") + if not isinstance(plugin, dict): + errors.append("plugin must be an object") + plugin = {} + if not isinstance(runtime, dict): + errors.append("runtime must be an object") + if not isinstance(skills, list): + errors.append("skills must be an array") + skills = [] + + required_plugin = ( + "name", + "display_name", + "version", + "description", + "description_zh_cn", + "author_name", + "author_email", + "homepage", + "catalogue", + "repository", + "license", + "category", + "keywords", + ) + for key in required_plugin: + if not plugin.get(key): + errors.append(f"plugin.{key} is required") + if plugin.get("name") != "terraphim-skills-intro": + errors.append("plugin.name must remain terraphim-skills-intro") + if plugin.get("license") != "Apache-2.0": + errors.append("plugin.license must be Apache-2.0") + + names = [item.get("name") for item in skills if isinstance(item, dict)] + if names != list(ALLOWED_SKILLS): + errors.append(f"skills must be the exact ordered allowlist {ALLOWED_SKILLS!r}") + discovered = sorted( + path.parent.name for path in (root / "skills").glob("*/SKILL.md") + ) + if discovered != sorted(ALLOWED_SKILLS): + errors.append(f"skill tree differs from allowlist: {discovered!r}") + + for item in skills: + if not isinstance(item, dict): + errors.append("each skill must be an object") + continue + name = item.get("name") + relative = item.get("path") + if not isinstance(name, str) or not isinstance(relative, str): + errors.append("each skill requires string name and path") + continue + expected_path = f"skills/{name}" + if relative != expected_path: + errors.append(f"{name} path must be {expected_path}") + continue + skill_file = root / relative / "SKILL.md" + if not skill_file.is_file(): + errors.append(f"{relative}/SKILL.md is missing") + continue + fields = _frontmatter(skill_file) + if fields.get("name") != name: + errors.append(f"{name} frontmatter name does not match") + if fields.get("license") != plugin.get("license"): + errors.append(f"{name} frontmatter licence does not match") + if not fields.get("description"): + errors.append(f"{name} frontmatter description is missing") + return sorted(errors) + + +def _identity(metadata: dict[str, object]) -> dict[str, object]: + plugin = metadata["plugin"] + assert isinstance(plugin, dict) + return { + "name": plugin["name"], + "description": plugin["description"], + "version": plugin["version"], + "author": { + "name": plugin["author_name"], + "email": plugin["author_email"], + }, + "homepage": plugin["homepage"], + "repository": plugin["repository"], + "license": plugin["license"], + "keywords": plugin["keywords"], + } + + +def _skill_paths(metadata: dict[str, object], *, dotted: bool = False) -> list[str]: + skills = metadata["skills"] + assert isinstance(skills, list) + prefix = "./" if dotted else "" + return [prefix + item["path"] for item in skills if isinstance(item, dict)] + + +def render_cursor(metadata: dict[str, object]) -> dict[str, object]: + """Render the Cursor plugin manifest.""" + + value = _identity(metadata) + value["logo"] = "assets/logo.svg" + value["skills"] = _skill_paths(metadata) + return value + + +def render_kimi(metadata: dict[str, object]) -> dict[str, object]: + """Render the Kimi plugin manifest.""" + + value = _identity(metadata) + plugin = metadata["plugin"] + assert isinstance(plugin, dict) + value["skills"] = _skill_paths(metadata, dotted=True) + value["interface"] = { + "displayName": plugin["display_name"], + "shortDescription": "Local search, learning, and memory workflows", + "developerName": plugin["author_name"], + "websiteURL": plugin["homepage"], + } + return value + + +def render_kimi_marketplace(metadata: dict[str, object]) -> dict[str, object]: + """Render the Terraphim Kimi custom marketplace.""" + + plugin = metadata["plugin"] + assert isinstance(plugin, dict) + tag = f"v{plugin['version']}" + return { + "version": "2", + "plugins": [ + { + "id": plugin["name"], + "displayName": plugin["display_name"], + "description": plugin["description"], + "source": f"{plugin['repository']}/archive/refs/tags/{tag}.zip", + } + ], + } + + +def render_zcode(metadata: dict[str, object]) -> dict[str, object]: + """Render the ZCode native plugin manifest.""" + + value = _identity(metadata) + plugin = metadata["plugin"] + assert isinstance(plugin, dict) + value["displayName"] = plugin["display_name"] + value["description_i18n"] = { + "en": plugin["description"], + "zh-CN": plugin["description_zh_cn"], + } + value["skills"] = _skill_paths(metadata, dotted=True) + return value + + +def render_zcode_marketplace(metadata: dict[str, object]) -> dict[str, object]: + """Render a ZCode-compatible publisher marketplace.""" + + plugin = metadata["plugin"] + assert isinstance(plugin, dict) + return { + "name": "terraphim-skills", + "description": "Public Community skills from Terraphim AI.", + "plugins": [ + { + "name": plugin["name"], + "source": { + "source": "github", + "repo": "terraphim/terraphim-cursor-plugin", + "path": ".", + "ref": f"v{plugin['version']}", + }, + "description": plugin["description"], + "description_i18n": { + "en": plugin["description"], + "zh-CN": plugin["description_zh_cn"], + }, + "version": plugin["version"], + "category": "developer-tools", + "tags": plugin["keywords"], + "strict": True, + } + ], + } + + +def render_claude_plugin(metadata: dict[str, object]) -> dict[str, object]: + """Render the Claude Code plugin manifest.""" + + return _identity(metadata) + + +def render_claude_marketplace(metadata: dict[str, object]) -> dict[str, object]: + """Render the publisher-owned Claude Code marketplace.""" + + plugin = metadata["plugin"] + assert isinstance(plugin, dict) + return { + "name": "terraphim-skills", + "description": "Public Community skills from Terraphim AI.", + "owner": { + "name": plugin["author_name"], + "email": plugin["author_email"], + }, + "plugins": [ + { + "name": plugin["name"], + "source": "./", + "description": plugin["description"], + "version": plugin["version"], + "category": "development", + "homepage": plugin["homepage"], + } + ], + } + + +def generated_files(root: Path, metadata: dict[str, object]) -> dict[Path, str]: + """Return generated manifest paths and canonical JSON text.""" + + rendered = { + Path(".cursor-plugin/plugin.json"): render_cursor(metadata), + Path("kimi.plugin.json"): render_kimi(metadata), + Path("plugin.json"): render_kimi(metadata), + Path("marketplaces/kimi.json"): render_kimi_marketplace(metadata), + Path(".zcode-plugin/plugin.json"): render_zcode(metadata), + Path("marketplaces/zcode.json"): render_zcode_marketplace(metadata), + Path(".claude-plugin/plugin.json"): render_claude_plugin(metadata), + Path(".claude-plugin/marketplace.json"): render_claude_marketplace(metadata), + } + return { + root / path: json.dumps(value, indent=2, ensure_ascii=False) + "\n" + for path, value in rendered.items() + } + + +def write_or_check(root: Path, *, check: bool) -> int: + """Write outputs or return one when committed outputs drift.""" + + metadata = load_metadata(root) + errors = validate_metadata(root, metadata) + if errors: + for error in errors: + print(f"error: {error}") + return 1 + drift: list[str] = [] + for path, content in generated_files(root, metadata).items(): + if check: + if not path.is_file() or path.read_text(encoding="utf-8") != content: + drift.append(path.relative_to(root).as_posix()) + else: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content, encoding="utf-8") + if drift: + for path in drift: + print(f"out of date: {path}") + return 1 + return 0 + + +def _zip_info(name: str) -> zipfile.ZipInfo: + info = zipfile.ZipInfo(name, (1980, 1, 1, 0, 0, 0)) + info.compress_type = zipfile.ZIP_DEFLATED + info.external_attr = 0o100644 << 16 + info.create_system = 3 + return info + + +def build_autoclaw_archives( + root: Path, metadata: dict[str, object], output: Path +) -> list[Path]: + """Build one deterministic ZIP per allowlisted skill plus SHA256SUMS.""" + + output.mkdir(parents=True, exist_ok=True) + plugin = metadata["plugin"] + skills = metadata["skills"] + assert isinstance(plugin, dict) and isinstance(skills, list) + archives: list[Path] = [] + for skill in skills: + assert isinstance(skill, dict) + name = str(skill["name"]) + skill_root = root / str(skill["path"]) + archive = output / f"{name}-{plugin['version']}.zip" + with zipfile.ZipFile(archive, "w") as target: + for source in sorted( + path for path in skill_root.rglob("*") if path.is_file() + ): + relative = source.relative_to(skill_root).as_posix() + target.writestr( + _zip_info(f"{name}/{relative}"), + source.read_bytes(), + compresslevel=9, + ) + archives.append(archive) + checksums = "".join( + f"{hashlib.sha256(path.read_bytes()).hexdigest()} {path.name}\n" + for path in archives + ) + (output / "SHA256SUMS").write_text(checksums, encoding="utf-8") + return archives + + +def main(argv: Sequence[str] | None = None) -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--check", action="store_true") + parser.add_argument("--print-version", action="store_true") + parser.add_argument("--autoclaw-dist", type=Path) + args = parser.parse_args(argv) + if args.print_version: + metadata = load_metadata(ROOT) + errors = validate_metadata(ROOT, metadata) + if errors: + for error in errors: + print(f"error: {error}") + return 1 + plugin = metadata["plugin"] + assert isinstance(plugin, dict) + print(plugin["version"]) + return 0 + result = write_or_check(ROOT, check=args.check) + if result or args.check or args.autoclaw_dist is None: + return result + metadata = load_metadata(ROOT) + build_autoclaw_archives(ROOT, metadata, args.autoclaw_dist) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/skills/terraphim-agent-learn/SKILL.md b/skills/terraphim-agent-learn/SKILL.md index af7d683..5d9274a 100644 --- a/skills/terraphim-agent-learn/SKILL.md +++ b/skills/terraphim-agent-learn/SKILL.md @@ -8,6 +8,21 @@ license: Apache-2.0 Use `terraphim-agent learn` for concrete operational learning: failed commands, their errors, explicit corrections, and reviewed procedures. Default to project scope and read-only inspection. +## Install the dependency + +On macOS or Linux with Homebrew: + +```bash +brew tap terraphim/terraphim +brew install terraphim-agent +terraphim-agent --version +``` + +The tap installs the signed, checksummed v1.21.14 archive from the Terraphim +client release. If Homebrew is unavailable, use the appropriate archive from +the [v1.21.14 release](https://github.com/terraphim/terraphim-clients/releases/tag/v1.21.14) +and verify it against that release's `SHA256SUMS` before installation. + ## Capability gate ```bash @@ -59,3 +74,12 @@ Use `learn correction` for an explicit user preference or workflow correction th ## Completion evidence For read-only work, report the matching learning IDs and why they are relevant. For a write, report the new or corrected ID, scope, and redactions without repeating sensitive input. + +## Continue with Terraphim Skills + +Browse the [Community, Core, and Premium skill catalogue](https://terraphim-skills.md/skills/) +or compare access on the [pricing page](https://terraphim-skills.md/pricing/). +For formal proof after capturing a lesson, +[disciplined-validation](https://terraphim-skills.md/skills/disciplined-validation/) +is an optional Premium workflow; discovering it never starts checkout or changes +an entitlement. diff --git a/skills/terraphim-agent-learn/skill.toml b/skills/terraphim-agent-learn/skill.toml index 2fe7027..bd17699 100644 --- a/skills/terraphim-agent-learn/skill.toml +++ b/skills/terraphim-agent-learn/skill.toml @@ -1,17 +1,17 @@ [skill] name = "terraphim-agent-learn" -version = "1.0.0" -description = "Inspect failures and capture verified operational corrections with terraphim-agent learn." +version = "1.0.1" +description = "Inspect and capture command failures or user corrections with terraphim-agent learn. Use when a user asks to preserve a concrete operational lesson, search earlier failures, or attach a correction; use terraphim-agent-memory for broader memory retrieval and lifecycle work." tier = "community" author = "terraphim" license = "Apache-2.0" repository = "https://github.com/terraphim/terraphim-cursor-plugin" [files] -"SKILL.md" = "02268217164234834634edc3c9af887e79d27137cbf38085fccc2635b9f63e29" +"SKILL.md" = "6396e1b6c38d3778f1c9afc3cdaf10d0c8e368c0eb7a102775609ef510aa5af5" "references/command-guide.md" = "792034bb071bd45831aae1da1a11c999eb61fb7deed123d51b567737fc50346c" [signature] public_key = "261c6820525270bfe2a5daaa5bf3f581bd9bc193e1a0148010e870a3a63ad959" -signature = "51d27964b7532d163f9c7ada62b842323a96f79b7da4f6d8b44eb38528d279904cc1b3f6ce4b35f859f5960497effb1630d5bc612190921970856db176d61a0e" -timestamp = "1789462010Z" +signature = "32b32d477fc1b33524c3005a5f2bc54b4ac51bfa1a15678d76daf63540e85ec99d9f37ac71b811919a3f3125dfd37f8d1e9c95a02d26f068de5fa91e29d44504" +timestamp = "1970-01-01T00:00:00Z" diff --git a/skills/terraphim-agent-memory/SKILL.md b/skills/terraphim-agent-memory/SKILL.md index b78aa04..604f9ad 100644 --- a/skills/terraphim-agent-memory/SKILL.md +++ b/skills/terraphim-agent-memory/SKILL.md @@ -8,6 +8,21 @@ license: Apache-2.0 Use `terraphim-agent memory` for the broader memory lifecycle. Prefer retrieval, scope inspection, and provenance checks before capture, distillation, validation, or retirement. +## Install the dependency + +On macOS or Linux with Homebrew: + +```bash +brew tap terraphim/terraphim +brew install terraphim-agent +terraphim-agent --version +``` + +The tap installs the signed, checksummed v1.21.14 archive from the Terraphim +client release. If Homebrew is unavailable, use the appropriate archive from +the [v1.21.14 release](https://github.com/terraphim/terraphim-clients/releases/tag/v1.21.14) +and verify it against that release's `SHA256SUMS` before installation. + ## Capability gate ```bash @@ -31,7 +46,7 @@ Use an exact `--role` only when the role exists in the active configuration. If ## Retrieve and inspect ```bash -terraphim-agent memory retrieve "" --role "" --format json --limit 10 +terraphim-agent memory retrieve "" --role "" terraphim-agent memory list --limit 20 terraphim-agent memory show "" --json terraphim-agent memory provenance --memory-id "" @@ -44,7 +59,7 @@ Retrieval is knowledge-graph ranked and has no lexical fallback. No results mean Use `apply` to show what a hook would inject without changing files: ```bash -terraphim-agent memory apply --role "" --prompt "" +terraphim-agent memory apply --prompt "" ``` Do not put secrets, credentials, private keys, personal data, or unpublished customer material in the prompt. @@ -65,3 +80,12 @@ Use them only when the user has authorized the exact scope and destination. Add ## Completion evidence Report the role and project scope, result IDs, provenance confidence, and any reliability warning. Distinguish retrieved evidence from inference, and never expose sensitive memory contents unnecessarily. + +## Continue with Terraphim Skills + +Browse the [Community, Core, and Premium skill catalogue](https://terraphim-skills.md/skills/) +or compare access on the [pricing page](https://terraphim-skills.md/pricing/). +For governed decision evidence, +[requirements-traceability](https://terraphim-skills.md/skills/requirements-traceability/) +is an optional Premium workflow; discovering it never starts checkout or changes +an entitlement. diff --git a/skills/terraphim-agent-memory/references/command-guide.md b/skills/terraphim-agent-memory/references/command-guide.md index 80e351f..6588e94 100644 --- a/skills/terraphim-agent-memory/references/command-guide.md +++ b/skills/terraphim-agent-memory/references/command-guide.md @@ -9,7 +9,7 @@ This wrapper targets the command surface reported by | `memory retrieve --role ` | Read KG-ranked role memory | | `memory list` / `memory show ` | Read stored items | | `memory provenance --memory-id ` | Read session provenance | -| `memory apply --role --prompt ` | Preview hook injection | +| `memory apply --prompt ` | Preview hook injection | | `memory capture --provenance-tag ` | Write an item to the evolution store | | `memory distill ...` | Compile and export learned material | | `memory validate ...` | Invoke the judge pipeline for scoring | diff --git a/skills/terraphim-agent-memory/skill.toml b/skills/terraphim-agent-memory/skill.toml index 5e2ba2d..bfb19cf 100644 --- a/skills/terraphim-agent-memory/skill.toml +++ b/skills/terraphim-agent-memory/skill.toml @@ -1,17 +1,17 @@ [skill] name = "terraphim-agent-memory" -version = "1.0.0" -description = "Retrieve, inspect, validate, and govern agent memory with terraphim-agent memory." +version = "1.0.1" +description = "Retrieve, inspect, validate, and govern agentic memory with terraphim-agent memory. Use for role-scoped memory searches, provenance checks, hook previews, reliability evaluation, or explicitly authorized lifecycle changes; use terraphim-agent-learn for individual command failures and corrections." tier = "community" author = "terraphim" license = "Apache-2.0" repository = "https://github.com/terraphim/terraphim-cursor-plugin" [files] -"SKILL.md" = "634aff47696d227a65264852c02be073efc404dab37456959b0b0937c1c43b82" -"references/command-guide.md" = "3f7ff187af11b243b741ee5611434fd9a9023db43786d0e56c1a862701282e3e" +"SKILL.md" = "fe385d0b32055b3097f9a9f7dad833acfc2eb4c1586798e40a2b6dcf5de9988f" +"references/command-guide.md" = "9c40a9d20dced973f4d37f2c78e61a88091bae83345c1a86879c3ffb0f9daf62" [signature] public_key = "261c6820525270bfe2a5daaa5bf3f581bd9bc193e1a0148010e870a3a63ad959" -signature = "6f3a0b038ab502db07316ac8e23889f9d652f4e8fd7eb5a34b2a47c6eae10989669275670404c79bc89ecdf2665e65972b3f8c1b5659e473161f95e8f3b8350d" -timestamp = "1789462010Z" +signature = "22ce696a6ba9922dea8fc6883717ade94beb9fa4c1fb8dd5c9174bd15de25415a87935d4abf4c1b3cd6dddbf09298c8159a12dacff51245c47099c74849f2800" +timestamp = "1970-01-01T00:00:00Z" diff --git a/skills/terraphim-grep/SKILL.md b/skills/terraphim-grep/SKILL.md index fe1ec97..8747b41 100644 --- a/skills/terraphim-grep/SKILL.md +++ b/skills/terraphim-grep/SKILL.md @@ -8,6 +8,21 @@ license: Apache-2.0 Use `terraphim-grep` to locate evidence in local code and documentation. Keep ordinary searches deterministic and offline. Enable LLM synthesis only when the user asks for it and understands that it may use a configured external model. +## Install the dependency + +On macOS or Linux with Homebrew: + +```bash +brew tap terraphim/terraphim +brew install terraphim-grep +terraphim-grep --version +``` + +The tap installs the signed, checksummed v1.21.14 archive from the Terraphim +client release. If Homebrew is unavailable, use the appropriate archive from +the [v1.21.14 release](https://github.com/terraphim/terraphim-clients/releases/tag/v1.21.14) +and verify it against that release's `SHA256SUMS` before installation. + ## Capability gate Before relying on the tool, inspect the installed command surface: @@ -50,3 +65,11 @@ Do not create a role, thesaurus, or knowledge-graph directory merely to satisfy ## Completion evidence Report the searched paths, search mode, material matches, and any important limitation. Do not claim the whole repository was searched when paths or haystacks were restricted. + +## Continue with Terraphim Skills + +Browse the [Community, Core, and Premium skill catalogue](https://terraphim-skills.md/skills/) +or compare access on the [pricing page](https://terraphim-skills.md/pricing/). +For deeper research work, [deep-research](https://terraphim-skills.md/skills/deep-research/) +is an optional Premium workflow; discovering it never starts checkout or changes +an entitlement. diff --git a/skills/terraphim-grep/skill.toml b/skills/terraphim-grep/skill.toml index 0051c9e..f88a71f 100644 --- a/skills/terraphim-grep/skill.toml +++ b/skills/terraphim-grep/skill.toml @@ -1,17 +1,17 @@ [skill] name = "terraphim-grep" -version = "1.0.0" -description = "Search bounded local source code and documentation with terraphim-grep, offline by default." +version = "1.0.1" +description = "Search local source code and documentation with the installed terraphim-grep CLI. Use for bounded text or knowledge-graph-assisted retrieval inside a project; do not use it for internet search or file-name-only lookup." tier = "community" author = "terraphim" license = "Apache-2.0" repository = "https://github.com/terraphim/terraphim-cursor-plugin" [files] -"SKILL.md" = "60b46cea519bf8652ae66562955d6fe3e88533bc8d0b2cb9644960c002eef2be" +"SKILL.md" = "10d257bdb93e7c4da3018960d8aa81780230faeabc048ace6fe18de5551075eb" "references/command-guide.md" = "0f8e9e51c7ddf4af363f20423ebcb3328055f4a2de847af2fd4e9063178fed23" [signature] public_key = "261c6820525270bfe2a5daaa5bf3f581bd9bc193e1a0148010e870a3a63ad959" -signature = "16b22dfb89cf38f64f77c5b872925c5ea3ac445b38abd82aa40243a7316a577e45a4188ba5122e8edba920693b6cc282e94f1b42296c930185610df804493005" -timestamp = "1789462010Z" +signature = "62c420fa91f465e84608136d550720fd5ccc96398a4369d0ac1555fe4ccab6f23ae007e9058d59e99635f89451ad69b9d59d1a93ff68aa3bbe6b597c6b648e09" +timestamp = "1970-01-01T00:00:00Z" diff --git a/tests/test_distribution.py b/tests/test_distribution.py new file mode 100644 index 0000000..be6464e --- /dev/null +++ b/tests/test_distribution.py @@ -0,0 +1,204 @@ +from __future__ import annotations + +import hashlib +import importlib.util +import io +import json +from pathlib import Path +import re +import tempfile +import unittest +import zipfile +from contextlib import redirect_stdout + + +ROOT = Path(__file__).resolve().parents[1] +SPEC = importlib.util.spec_from_file_location( + "generate_distribution", ROOT / "scripts" / "generate_distribution.py" +) +assert SPEC is not None and SPEC.loader is not None +GENERATOR = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(GENERATOR) + + +class DistributionTests(unittest.TestCase): + def setUp(self) -> None: + self.metadata = GENERATOR.load_metadata(ROOT) + + def test_exact_public_skill_allowlist_and_tree(self) -> None: + self.assertEqual([], GENERATOR.validate_metadata(ROOT, self.metadata)) + names = tuple(skill["name"] for skill in self.metadata["skills"]) + self.assertEqual(GENERATOR.ALLOWED_SKILLS, names) + + def test_print_version_matches_manifests(self) -> None: + self.assertEqual("0.2.0", self.metadata["plugin"]["version"]) + output = io.StringIO() + with redirect_stdout(output): + self.assertEqual(0, GENERATOR.main(["--print-version"])) + self.assertEqual("0.2.0\n", output.getvalue()) + + def test_generated_manifests_are_current_and_deterministic(self) -> None: + expected = GENERATOR.generated_files(ROOT, self.metadata) + first = {path: content for path, content in expected.items()} + second = GENERATOR.generated_files(ROOT, self.metadata) + self.assertEqual(first, second) + for path, content in expected.items(): + self.assertEqual(content, path.read_text(encoding="utf-8"), path) + + def test_manifests_share_identity_version_and_skills(self) -> None: + plugin = self.metadata["plugin"] + expected_paths = [skill["path"] for skill in self.metadata["skills"]] + manifests = [ + json.loads((ROOT / ".cursor-plugin/plugin.json").read_text()), + json.loads((ROOT / "kimi.plugin.json").read_text()), + json.loads((ROOT / "plugin.json").read_text()), + json.loads((ROOT / ".zcode-plugin/plugin.json").read_text()), + ] + for manifest in manifests: + self.assertEqual(plugin["name"], manifest["name"]) + self.assertEqual(plugin["version"], manifest["version"]) + self.assertEqual(plugin["homepage"], manifest["homepage"]) + self.assertEqual( + expected_paths, + [path.removeprefix("./") for path in manifest["skills"]], + ) + + def test_no_ambient_components_are_packaged(self) -> None: + forbidden = {"commands", "agents", "hooks", "mcpServers", "lspServers"} + for path in ( + ROOT / ".cursor-plugin/plugin.json", + ROOT / "kimi.plugin.json", + ROOT / "plugin.json", + ROOT / ".zcode-plugin/plugin.json", + ROOT / ".claude-plugin/plugin.json", + ): + manifest = json.loads(path.read_text()) + self.assertTrue(forbidden.isdisjoint(manifest), path) + + def test_kimi_marketplace_uses_current_v2_contract(self) -> None: + marketplace = json.loads((ROOT / "marketplaces/kimi.json").read_text()) + self.assertEqual("2", marketplace["version"]) + self.assertEqual( + { + "id", + "displayName", + "description", + "source", + }, + set(marketplace["plugins"][0]), + ) + + def test_zcode_marketplace_pins_release_and_category(self) -> None: + marketplace = json.loads((ROOT / "marketplaces/zcode.json").read_text()) + entry = marketplace["plugins"][0] + self.assertEqual("terraphim-skills-intro", entry["name"]) + self.assertEqual("developer-tools", entry["category"]) + self.assertEqual("v0.2.0", entry["source"]["ref"]) + self.assertTrue(entry["strict"]) + self.assertEqual({"en", "zh-CN"}, set(entry["description_i18n"])) + manifest = json.loads((ROOT / ".zcode-plugin/plugin.json").read_text()) + self.assertEqual(entry["description_i18n"], manifest["description_i18n"]) + + def test_autoclaw_archives_are_reproducible_and_one_skill_each(self) -> None: + with ( + tempfile.TemporaryDirectory() as first_dir, + tempfile.TemporaryDirectory() as second_dir, + ): + first = Path(first_dir) + second = Path(second_dir) + GENERATOR.build_autoclaw_archives(ROOT, self.metadata, first) + GENERATOR.build_autoclaw_archives(ROOT, self.metadata, second) + self.assertEqual( + (first / "SHA256SUMS").read_bytes(), + (second / "SHA256SUMS").read_bytes(), + ) + for archive in sorted(first.glob("*.zip")): + twin = second / archive.name + self.assertEqual(archive.read_bytes(), twin.read_bytes()) + with zipfile.ZipFile(archive) as package: + roots = {name.split("/", 1)[0] for name in package.namelist()} + self.assertEqual(1, len(roots), archive) + self.assertIn(f"{next(iter(roots))}/SKILL.md", package.namelist()) + + def test_committed_autoclaw_checksums_match_archives(self) -> None: + dist = ROOT / "dist" / "autoclaw" + recorded = {} + for line in (dist / "SHA256SUMS").read_text().splitlines(): + digest, name = line.split(" ", 1) + recorded[name] = digest + archives = sorted(dist.glob("*.zip")) + self.assertEqual({archive.name for archive in archives}, set(recorded)) + for archive in archives: + self.assertEqual( + recorded[archive.name], hashlib.sha256(archive.read_bytes()).hexdigest() + ) + + def test_docs_cover_hosts_and_dependency_probes(self) -> None: + readme = (ROOT / "README.md").read_text().lower() + uat = (ROOT / "docs/uat/multi-marketplace.md").read_text().lower() + for host in ( + "cursor", + "kimi", + "autoclaw", + "zcode", + "hermes", + "skills.sh", + "claude", + ): + self.assertIn(host, readme) + self.assertIn(host, uat) + for probe in self.metadata["runtime"]["verify"]: + self.assertIn(probe, (ROOT / "docs/install-dependencies.md").read_text()) + + def test_skills_hint_dependencies_without_installing_them(self) -> None: + for name in GENERATOR.ALLOWED_SKILLS: + text = (ROOT / "skills" / name / "SKILL.md").read_text().lower() + self.assertIn("brew tap terraphim/terraphim", text) + self.assertNotIn("automatically install", text) + + def test_pack_excludes_secret_and_proprietary_markers(self) -> None: + forbidden = ( + "op" + "://", + "stripe_" + "secret", + "premium skill " + "body", + ) + for path in ROOT.rglob("*"): + if ( + not path.is_file() + or {".git", "__pycache__"} & set(path.parts) + or path.suffix == ".zip" + ): + continue + text = path.read_text(encoding="utf-8", errors="ignore").lower() + for marker in forbidden: + self.assertNotIn(marker, text, path) + + def test_catalogue_links_are_neutral_and_do_not_checkout(self) -> None: + for name in GENERATOR.ALLOWED_SKILLS: + text = (ROOT / "skills" / name / "SKILL.md").read_text().lower() + self.assertIn("https://terraphim-skills.md/skills/", text) + self.assertIn("never starts checkout or changes", text) + + def test_chinese_readme_matches_public_boundary(self) -> None: + text = (ROOT / "README_CN.md").read_text() + self.assertIn("terraphim-grep", text) + self.assertIn("terraphim-agent-learn", text) + self.assertIn("terraphim-agent-memory", text) + self.assertIn("https://terraphim-skills.md/skills/", text) + + def test_local_markdown_links_resolve(self) -> None: + link_pattern = re.compile(r"\[[^\]]*\]\(([^)]+)\)") + for markdown in ROOT.rglob("*.md"): + if ".git" in markdown.parts: + continue + for target in link_pattern.findall(markdown.read_text(encoding="utf-8")): + if target.startswith(("http://", "https://", "mailto:", "#")): + continue + path = target.split("#", 1)[0] + self.assertTrue( + (markdown.parent / path).resolve().exists(), (markdown, target) + ) + + +if __name__ == "__main__": + unittest.main()