diff --git a/package.json b/package.json index 07d8f90..1c2e310 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "shadow-dev-cli", - "version": "1.3.0", + "version": "1.4.0", "description": "Deterministic scaffolding CLI for the Shadow dev workflow: brief lifecycle, plan/execute with plan hashes, git and GitHub operations.", "type": "module", "engines": { diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh new file mode 100755 index 0000000..4c0b889 --- /dev/null +++ b/scripts/bootstrap.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# bootstrap.sh — shadow 生态一键装机:装 CLI → 拉 workflow 产物 → 绑定宿主 skills +# +# 用法(二选一): +# bash bootstrap.sh [host] # 本仓库内直接跑 +# curl -fsSL | bash -s [host] # 远程一条龙(host 缺省 claude-code,原生宿主) +# +# 环境覆盖原样透传给各环节: +# SD_PREFIX / SD_BIN CLI 安装前缀与 shim 位(install-cli.sh) +# SHADOW_WORKFLOW_PREFIX workflow 产物前缀(workflow 域) +# SHADOW_WORKFLOW_HOME 宿主 home 根(bind 域,~/.claude/skills 等由此解析) +set -euo pipefail + +TAG="v1.4.0" +HOST="${1:-claude-code}" +BIN="${SD_BIN:-$HOME/.local/bin}" +TMP="$(mktemp -d)" +cleanup() { rm -rf "$TMP"; } +trap cleanup EXIT + +step() { printf '\n==> %s\n' "$*"; } + +step "1/3 安装 shadow-dev CLI(latest release,双轨 + 托管 shim)" +curl -fsSL "https://raw.githubusercontent.com/stack-wuh/shadow-dev-cli/$TAG/scripts/install-cli.sh" -o "$TMP/install-cli.sh" +bash "$TMP/install-cli.sh" install +SD="$BIN/shadow-dev" +[ -x "$SD" ] || { echo "shim 未生成:$SD" >&2; exit 1; } + +planHash() { node -pe 'JSON.parse(require("fs").readFileSync(0,"utf8")).planHash'; } + +step "2/3 物化 shadow-dev-workflow 产物(release tarball → 版本化布局)" +H="$( "$SD" workflow plan --json | planHash )" +"$SD" workflow execute --plan-hash "$H" --confirm + +step "3/3 绑定宿主:$HOST(adapters 描述符驱动,复制 + 托管标记)" +H2="$( "$SD" bind plan --host "$HOST" --json | planHash )" +"$SD" bind execute --host "$HOST" --plan-hash "$H2" --confirm + +VER="$( "$SD" workflow status --json | node -pe 'JSON.parse(require("fs").readFileSync(0,"utf8")).data.current' )" +printf '\nshadow 生态就绪:CLI + workflow %s → %s(skills 已绑入,sidecar 可 unbind)\n' "$VER" "$HOST" diff --git a/shadow-docs/changes/20260925-chore-bootstrap-v14/brief.md b/shadow-docs/changes/20260925-chore-bootstrap-v14/brief.md new file mode 100644 index 0000000..753d9f4 --- /dev/null +++ b/shadow-docs/changes/20260925-chore-bootstrap-v14/brief.md @@ -0,0 +1,82 @@ +--- +{ + "schema": "shadow-dev/v1", + "name": "20260925-chore-bootstrap-v14", + "type": "chore", + "scope": "distribution", + "status": "branched", + "baseBranch": "main", + "branch": "chore/20260925-chore-bootstrap-v14", + "files": [ + "package.json", + "scripts/bootstrap.sh", + "shadow-docs/knowledge/install-distribution.md" + ], + "github": { + "repository": null, + "issue": null, + "issueUrl": null, + "pullRequest": null, + "pullRequestUrl": null + }, + "review": { + "conclusion": "pending", + "verifiedCommit": null, + "verifiedAt": null + }, + "workflow": { + "operation": null, + "checkpoint": null, + "planHash": "8dfc9ec451e8fce3900c32f521be889b3a740dfd4eb5428ebb4957be4eae97b9", + "updatedAt": null, + "lastError": null, + "release": { + "files": [ + "package.json", + "scripts/bootstrap.sh", + "shadow-docs/changes/20260925-chore-bootstrap-v14/brief.md", + "shadow-docs/knowledge/install-distribution.md" + ], + "message": "chore(cli): bootstrap 一键装机 + v1.4.0 发版 + install-distribution 卡更新(双产物契约/adapters/命名冲突/release 非任务)", + "title": "20260925-chore-bootstrap-v14", + "body": "" + } + } +} +--- + +# bootstrap 一键装机 + CLI v1.4.0 发版 + install-distribution 卡更新 + +## 动机 + +workflow/bind 域已合并(PR #31)但 CLI 最新 release 仍是 v1.3.0,新域不在任何发布产物里;新机器装机缺统一入口(装 CLI → workflow install → bind 三段手工)。本 change 补 bootstrap 脚本、发 v1.4.0、把 PR #31/#20/#19 沉淀的知识写回 install-distribution 卡。 + +## 引用规范 + +- shadow-docs/knowledge/install-distribution.md + - 当前结论: 双轨、指针语义、冒烟前置、托管 guard——bootstrap 与 workflow/bind 域全部沿用 + - 适用 scope: scripts/bootstrap.sh、lib/domains/workflow.mjs、lib/domains/bind.mjs + +## 决策 + +- **选型:** `scripts/bootstrap.sh` 复用 install-cli.sh 装 CLI(复用其双轨/指针/回滚),再编排 workflow plan→execute 与 bind plan→execute 两段凭证链;宿主缺省 claude-code(原生),可传参覆盖;发版 v1.4.0(tag 挂 tarball,bootstrap 以 raw@$TAG 引用 install-cli.sh) +- **对比方案:** bootstrap 自带物化逻辑(否决——与 install-cli.sh 重复,双份维护);不做脚本只写文档(否决——一条命令的装机体验是分发反转的终点) +- **理由:** 装机链路的每一环都复用已验证机制;脚本只做编排不做实现 + +## 任务 + +### Phase 1 +- [x] bootstrap 脚本 — `scripts/bootstrap.sh` — 装 CLI → workflow 物化 → bind 绑定,编排两段 plan/execute 凭证链 +- [x] 版本升 1.4.0 — `package.json` — 配对发版 +- [x] 知识落卡 — `shadow-docs/knowledge/install-distribution.md` — 双产物契约/adapters/命名冲突教训/release 不作为 task/readdir 确定化 + +## 结果 + +- 实际耗时: — +- 验证: — + +## 知识评估 + +- **预期影响:** 更新(本 change 即落卡动作本身) +- **候选卡片:** shadow-docs/knowledge/install-distribution.md +- **理由:** 见任务 3 diff --git a/shadow-docs/knowledge/install-distribution.md b/shadow-docs/knowledge/install-distribution.md index dd7f4a2..bbcee1b 100644 --- a/shadow-docs/knowledge/install-distribution.md +++ b/shadow-docs/knowledge/install-distribution.md @@ -1,8 +1,8 @@ --- title: shadow-dev CLI 安装与分发模型 domain: install-distribution -keywords: [安装, installer, shim, 指针文件, LINK, CURRENT, 双轨, 回滚, 插件钩子, tarball, Git Bash, PowerShell] -scope: [scripts/install-cli.sh, test/install.test.mjs] +keywords: [安装, installer, shim, 指针文件, LINK, CURRENT, 双轨, 回滚, 插件钩子, tarball, Git Bash, PowerShell, workflow 域, bind, adapters, sidecar, bootstrap] +scope: [scripts/install-cli.sh, scripts/bootstrap.sh, lib/domains/workflow.mjs, lib/domains/bind.mjs, test/install.test.mjs, test/cli.test.mjs] status: active source: - changes/20260917-feature-install-cli-script/brief.md @@ -10,14 +10,17 @@ source: - changes/20260917-feature-install-link-mode/brief.md - changes/20260918-fix-installer-ci-cmd-assert/brief.md - changes/20260918-fix-cross-platform-ci/brief.md -verified: 2026-09-18 + - changes/archive/20260925-feature-workflow-domain/brief.md + - shadow-dev-workflow 仓 changes/archive/20260925-feature-pack-release/brief.md(跨仓产物契约) + - shadow-dev-workflow 仓 changes/archive/20260925-fix-pack-adapters/brief.md(跨仓产物契约) +verified: 2026-09-25 --- # shadow-dev CLI 安装与分发模型 ## 当前结论 -`scripts/install-cli.sh` 是唯一安装入口,维护**双轨**:release 物化轨(拉 GitHub Release tarball → 校验 → 物化到 `$PREFIX/shadow-dev-cli-/` → 切 `CURRENT` 指针,`PREVIOUS` 供回滚)与 link 直通轨(`link ` 校验目标目录后把其绝对路径写入 `$PREFIX/LINK`,代码即改即生效,面向 CLI 开发者本人)。`$BIN/shadow-dev`(.sh/.cmd) 是托管 shim,运行时按 `LINK → CURRENT` 两段解析——任何更新、回滚、双轨切换都不改 shim 文件本体。`install --json` 单行输出是 shadow-dev-workflow 插件钩子的跨仓接缝契约。 +`scripts/install-cli.sh` 是唯一安装入口,维护**双轨**:release 物化轨(拉 GitHub Release tarball → 校验 → 物化到 `$PREFIX/shadow-dev-cli-/` → 切 `CURRENT` 指针,`PREVIOUS` 供回滚)与 link 直通轨(`link ` 校验目标目录后把其绝对路径写入 `$PREFIX/LINK`,代码即改即生效,面向 CLI 开发者本人)。`$BIN/shadow-dev`(.sh/.cmd) 是托管 shim,运行时按 `LINK → CURRENT` 两段解析——任何更新、回滚、双轨切换都不改 shim 文件本体。`install --json` 单行输出是 shadow-dev-workflow 插件钩子的跨仓接缝契约。生态分发反转后,CLI 另管**第二产物**:`workflow` 域以同构双轨物化 shadow-dev-workflow 产物(release tarball → `$PREFIX/shadow-dev-workflow-/` → CURRENT/PREVIOUS/current 解析,解析序 LINK → CURRENT),`bind` 域按产物内 `adapters/.json` 描述符把 skills 复制进宿主发现目录并以 sidecar(`.shadow-dev-workflow.json`)记托管清单——**新增宿主 = 产物加一个描述符,CLI 零改动**。`scripts/bootstrap.sh` 编排三段装机(CLI → workflow → bind)。两域均为无 brief 域,`--plan-hash` 是 execute 的唯一凭证,任意目录可用。 ## 执行约束 @@ -27,11 +30,15 @@ verified: 2026-09-18 - `LINK` 与 `CURRENT` 语义互斥不复用:`install` 永不写/删 `LINK`,`unlink` 只删 `LINK`;status 的 `linked` 为 additive 字段。JSON 输出中的 Windows 路径必须转义反斜杠(`sed 's/\\/\\\\/g'`)。 - Windows 上 `LINK` 落盘存 `cygpath -w` 的 Windows 形态(`.cmd` shim 用 `set /p` 直读,POSIX 形态 node 打不开);shim `.cmd` 用 goto 两段分支而非括号块(括号块内 `%errorlevel%` 提前展开会吞掉真实退出码)。 - 信任边界分轨表述:release 轨 HTTPS + GitHub 仓库(无独立校验和),link 轨目标是用户显式给出的本机目录——引入 link 不扩大下载面,也不得把 link 目标喂给任何网络请求。 +- workflow 产物消费契约三件必备:`marketplace.json`/`package.json`/`skills/`;`adapters/` 自 v6.3.1 起必备(bind 依赖),pack 清单与消费方契约两处同源登记。 +- bind 绝不改 SKILL.md 字节:托管凭 sidecar,非托管同名目录在 plan 标记 blocked、execute 拒绝(exit 1),unbind 按 sidecar 逆操作;`readdirSync` 产出的 entries/sidecar keys 必须排序,保证 planHash 与 sidecar 字节确定。 +- 大小写不敏感文件系统(macOS/Windows 默认)上,指针文件与入口软链命名不得仅大小写不同——`CURRENT` 指针文件与 `current` 软链同路径互删(已删软链,统一运行时解析 resolvedRoot)。 +- **release 不作为 brief task**:review execute 的机械门禁要求全部任务勾选,而发布天然在 review 之后——把发布写成 task 会造成死锁(20260925-feature-pack-release 教训,发布放合并后/独立环节)。 - 测试需要打包 tar 时**必须经 `bash -c 'tar ...'` 执行**(与安装器本体同一解析路径):node 直接 `spawnSync('tar')` 在 Windows runner 绑到 System32 bsdtar,读不了 `toUnix()` 产出的 MSYS `/tmp` 路径,导致全部安装器用例在 windows CI 恒红。 ## 适用边界 -适用于 `scripts/install-cli.sh` 及其托管 shim/指针的全部行为变更。不适用于 CLI 运行时输出面(见 cli-output-contract)与 GitHub release 的发布打包(`scripts/pack.mjs` 产物布局另论)。 +适用于 `scripts/install-cli.sh` 及其托管 shim/指针的全部行为变更。不适用于 CLI 运行时输出面(见 cli-output-contract)。GitHub release 打包布局已入契约:CLI 侧 `pack.mjs` 产 `shadow-dev-cli-v.tar.gz`(cli.mjs/lib/package.json/README/LICENSE),workflow 侧产 `shadow-dev-workflow-v.tar.gz`(运行必需集 + adapters,见 workflow 仓 pack.mjs)。 ## 验证方式