Skip to content

fix: 升级以往正式发布的 skill,安装脚本先装 CLI 并输出单行 JSON - #12

Merged
KirbyInGitHub merged 4 commits into
mainfrom
fix/skill-upgrade-and-installer-output
Sep 13, 2026
Merged

KirbyInGitHub merged 4 commits into
mainfrom
fix/skill-upgrade-and-installer-output

Conversation

@KirbyInGitHub

@KirbyInGitHub KirbyInGitHub commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

问题与证据

2026-09-13 复现:先用 0.1.3 安装 skill(npx @hiq-ai/cortex-org-wiki-cli@0.1.3 skill setup --agent claude-code --scope project),再用 0.1.4 执行同一命令,返回 {"ok":false,"kind":"config","code":"skill_conflict"},退出码 2。文档给出的升级路径(docs/agent-setup.md、SKILL.md)是"版本过低时重新运行安装脚本",但:

  • src/skill.ts 把任何内容不同的已有文件都当成冲突,旧的官方 skill 也不例外,所以按文档升级必然冲突。
  • scripts/install.shset -eu 下先执行 skill setup(原第 53 行),之后才把 CLI 移到位(原第 60 行);install.ps1 同样(原第 33–34 行)。skill 一冲突,CLI 升级也跟着中止。
  • 安装脚本 stdout 混有 CLI 的 JSON 和中文提示,Agent 无法可靠解析结果。

已核实:每个 v* tag 的 skills/cortex-org-wiki/SKILL.md blob 摘要与 npm 上 0.1.1–0.1.4 及 v0.1.0 Release tarball 内嵌 skill 的摘要逐一相同(v0.1.0–v0.1.2 4873e530…,v0.1.3 8d049e2b…,v0.1.4 f45580ba…,即当前内容),因此以 tag 内容作为"以往正式发布"的判据成立。

变更

  1. 升级以往官方 skillscripts/generate-assets.mjs 在生成 SKILL_SHA256 的同时,对每个 v* tag 读取当时的 SKILL.md(该 tag 没有此文件则跳过),输出 PREVIOUS_OFFICIAL_SKILL_SHA256(不含当前摘要)。src/skill.ts 判定:与当前摘要相同为 unchanged;属于以往官方摘要时原子替换并返回 updated;只有未知内容才报 skill_conflict,提示用 --replace
    • tag 构建(GITHUB_REF_TYPE=tag)看不到任何更早的 v* tag 时生成脚本直接失败;本地无 tag 的开发构建只是列表为空。CI 和 release 中需要构建或跑升级测试的 checkout(ci、package、binaries、verify-install)改为 fetch-depth: 0
  2. 安装脚本顺序与输出install.sh / install.ps1 先把 CLI 放到位,再用已安装的 CLI 执行 skill setup(--skill-only 仍用临时二进制)。进度全部写 stderr。成功时 stdout 只有一行 JSON:{"ok":true,"tool":"install","data":{"cli":{"path","version","previous_version"},"skills":[...]}}previous_version 取安装前同位置 CLI 的 version 输出,没有则为 null--skill-onlyclinull--cli-onlyskills[]。失败时 stderr 输出 {"ok":false,"kind","code","message"} 并以非零退出;skill_conflict 的提示改为 --replace-skill / -ReplaceSkill,此时 CLI 已经升级。
    • PowerShell 失败后用 throw 而不是 exit:本机 pwsh 实测,[scriptblock]::Create 方式调用时 exit 会直接结束调用方会话。代价是 JSON 行之后还有 PowerShell 的错误渲染,退出码固定为 1。Write-Host 在子进程里会写到 stdout,所以进度改用 [Console]::Error
  3. 多个宿主skill setup --agent 可重复(yargs array);安装脚本接受重复或逗号分隔(PowerShell 为 -Agent codex,claude-code)。每个宿主写入同一份内容并有各自的 status。所有宿主先检查,任一冲突则整条命令非零退出,且所有宿主都不写入,确认后用 replace 重跑即可。仍不自动探测宿主。
  4. 测试tests/cli.test.ts 对每个以往 tag 的 SKILL.md 验证 updated;未知内容仍冲突;多宿主安装;一个宿主冲突时不写入任何宿主。tests/native.test.ts 验证安装脚本 stdout 恰为一行可解析 JSON、stderr 带进度;重跑时 previous_version 与以往官方 skill 升级;自定义内容冲突时 CLI 仍已升级并提示 replace 参数,replace 后 updated;CLI-only / skill-only 的 cliskills 形状;校验失败返回 checksum_mismatch
  5. 文档docs/agent-setup.md 新增"升级"和"安装后检查"两节,说明 JSON 行、升级行为和多宿主用法;README、docs/release.md 同步。SKILL.md 没有引用旧输出,未改动,内嵌 skill 摘要不变。

说明:Windows 上 cli.path 为长路径形式(首轮 CI 中测试从 Node 的 8.3 临时路径 RUNNER~1 拼出期望值,而 PowerShell 返回 runneradmin,两者是同一文件);测试改为比较 realpath,安装脚本行为未改。

评审修正

  • install.sh 不支持的 agent 报错:macOS 默认 /bin/sh(bash 3.2.57)在 UTF-8 locale 下把未加花括号的 $agent 后面的全角 读成变量名的一部分,set -u 直接中止(line 39: agent�: unbound variable,退出码 1,stderr 没有 JSON)。本机已复现,改为 ${agent}。脚本中没有其他未加花括号且后跟多字节字符的展开。dash 不受影响,所以 Ubuntu CI 发现不了。
  • CLI 失败行总带 code:非 CortexClientError 错误(例如只读目录的 EACCES)和 yargs 参数错误原来没有 code,安装脚本原样转出,与文档里"按 code 报告"不符。现在 src/cli.ts 统一补上该 kind 的通用 code:unknownunexpected_errorvalidationinvalid_argumentconfig/transport/upstreamconfig_error/transport_error/upstream_error;已有的具体 code 保持不变。字段顺序统一为 ok, kind, code, message
  • 冲突提示不再断定来源:未知内容也可能是较新的正式版本(例如旧 CLI 或固定 --base-url 遇到新 skill)。提示改为"已有与本版本不同且不在以往正式发布版本中的 skill 内容(本地修改、较新版本或来源不明)",docs/agent-setup.md 措辞同步。

共享接口影响

  • skill setup --jsondata 由单个对象改为 {"skills":[...]},每个宿主一项,字段与原来相同。已在本机 cortex(desktop/nomad/deck)和 cortex-skills 中检索 skill setup 的输出消费者,未找到;Cortex Cowork 市场安装由 Host 使用市场产物的 metadata.cli,不调用 skill setup
  • 安装脚本 stdout 由原先的混合文本改为单行 JSON;verify-install 已改为解析这一行。
  • CLI 的 --json 失败行现在总有 code(原来可能缺失),字段顺序变化不影响 JSON 解析。

验证

命令 结果
npm test(含 tsc 构建) 12 通过,1 跳过(native,无二进制时预期跳过)
bun build src/cli.ts --compilenpm run test:binsh 为 macOS 默认 8/8 通过
同上,sh 指向 dash(与 Ubuntu 一致) 8/8 通过
portable pwsh 7.6.6(macOS)以 -File 和 scriptblock 两种方式运行 install.ps1,本地 HTTP 下载源 多宿主首次安装、重跑(previous_versionunchanged)、冲突(CLI 已落地,提示 -ReplaceSkill,非零退出且后续语句不执行)、-ReplaceSkill-SkillOnly-CliOnly 均符合预期
生成脚本:无 tag 的浅克隆 开发构建得到空列表;GITHUB_REF_TYPE=tag 时报错失败
评审修正后 npm test 12 通过,1 跳过;新增断言:参数错误为 validation/invalid_argument,项目路径是文件时为 unknown/unexpected_error,退出码 1
评审修正后重新 bun build --compile + npm run test:bin(macOS sh = bash 3.2) 9/9 通过;新增"不支持的 agent(LC_ALL=en_US.UTF-8)"用例在修复前失败并报 agent�: unbound variable,修复后通过(退出码 3)
手工:/bin/sh/bin/bash/bin/dash × en_US.UTF-8zh_CN.UTF-8 运行 --agent codex,cortex 均输出 {"ok":false,"kind":"validation","code":"invalid_argument",…}
手工:编译后的二进制对只读项目目录执行 skill setup --json {"ok":false,"kind":"unknown","code":"unexpected_error","message":"EACCES…"},退出码 1
PR CI run 34762655784fetch-depth: 0,npm test + 编译后的 native 测试) ubuntu-latest、windows-latest 均通过;Windows 上 install.ps1 的单行 JSON、升级、冲突、模式形状全部由 pwsh 7 实跑

上线

合并后按 docs/release.md 发布 v0.1.5(bump package.json 并打 tag),然后更新 cortex-skills 中的配对版本。安装脚本和二进制通过同一次 release 推到 CDN;新的 install.sh 依赖新 CLI 的 skill setup 输出形状,遇到旧二进制时会以 unexpected_output 明确失败,不会输出无效 JSON。

未验证

  • Windows PowerShell 5.1:兼容写法(New-Object Text.UTF8Encoding2>&1 区分 ErrorRecord、控制台 UTF-8 编码临时切换)未实测,含中文路径时的编码也未实测。
  • 真实 CDN 安装与 release 流程要到 v0.1.5 发布时由 verify-install 验证。
  • 评审修正这一轮本机没有 pwsh:Windows 上新增的不支持 agent 用例(只断言 JSON 失败行,不断言退出码)以及 dash 下完整的 native 套件,都依赖本次 push 触发的 CI。

🤖 Generated with Claude Code

https://claude.ai/code/session_01SyjxHtzc5bneQgSH85QULN

KirbyInGitHub and others added 4 commits September 13, 2026 22:22
…r result

Rerunning the installer is the documented upgrade path, but any existing
skill that differed from the embedded one was a conflict, and both
installers ran skill setup before moving the CLI into place, so a stale
official skill also blocked the CLI upgrade.

- The build lists the SKILL.md digest of every released v* tag; setup
  replaces those atomically (status updated) and only unknown content
  conflicts. Tag builds fail when earlier tags are missing; CI and release
  checkouts fetch full history.
- install.sh / install.ps1 move the CLI first, then run skill setup with
  it. Progress goes to stderr; success prints one JSON line with cli
  {path, version, previous_version} and per-host skills; failures print a
  JSON error, and a skill conflict names --replace-skill / -ReplaceSkill.
- skill setup --agent is repeatable (installers also accept comma lists);
  data becomes {skills: [...]}, and a conflict on any host writes none.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyjxHtzc5bneQgSH85QULN
Windows CI reported the installer's path in long form
(C:\Users\runneradmin\...) while the test built it from Node's 8.3 temp
path (C:\Users\RUNNER~1\...). Both name the same file; compare realpaths.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyjxHtzc5bneQgSH85QULN
…l conflict wording

- install.sh: macOS sh (bash 3.2) under a UTF-8 locale read the fullwidth
  parenthesis after an unbraced $agent as part of the name, so set -u aborted
  with "unbound variable" instead of the JSON validation failure.
- cli.ts: JSON failure lines always carry code; errors without a specific one
  get their kind's generic code (unexpected errors: unexpected_error).
- skill_conflict message and agent-setup.md no longer call unknown content
  unofficial; it may also be a newer release.
- Tests: unsupported agent through the installer under en_US.UTF-8 (exit 3 on
  sh), validation and unexpected CLI failures carry a code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyjxHtzc5bneQgSH85QULN
- install.sh 缺 HOME 时 kind 与 code 对齐为 config / config_error
- install.ps1 去掉 ValidateSet,非法 -Scope 也输出约定的失败 JSON

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyjxHtzc5bneQgSH85QULN
@KirbyInGitHub
KirbyInGitHub merged commit 27c62df into main Sep 13, 2026
2 checks passed
This was referenced Sep 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant