Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down
40 changes: 40 additions & 0 deletions scripts/bootstrap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# bootstrap.sh — shadow 生态一键装机:装 CLI → 拉 workflow 产物 → 绑定宿主 skills
#
# 用法(二选一):
# bash bootstrap.sh [host] # 本仓库内直接跑
# curl -fsSL <raw-url-of-this-file> | 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"
82 changes: 82 additions & 0 deletions shadow-docs/changes/20260925-chore-bootstrap-v14/brief.md
Original file line number Diff line number Diff line change
@@ -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
17 changes: 12 additions & 5 deletions shadow-docs/knowledge/install-distribution.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
---
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
- changes/20260917-fix-installer-url-taint/brief.md
- 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-<ver>/` → 切 `CURRENT` 指针,`PREVIOUS` 供回滚)与 link 直通轨(`link <path>` 校验目标目录后把其绝对路径写入 `$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-<ver>/` → 切 `CURRENT` 指针,`PREVIOUS` 供回滚)与 link 直通轨(`link <path>` 校验目标目录后把其绝对路径写入 `$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-<ver>/` → CURRENT/PREVIOUS/current 解析,解析序 LINK → CURRENT),`bind` 域按产物内 `adapters/<host>.json` 描述符把 skills 复制进宿主发现目录并以 sidecar(`.shadow-dev-workflow.json`)记托管清单——**新增宿主 = 产物加一个描述符,CLI 零改动**。`scripts/bootstrap.sh` 编排三段装机(CLI → workflow → bind)。两域均为无 brief 域,`--plan-hash` 是 execute 的唯一凭证,任意目录可用。

## 执行约束

Expand All @@ -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<ver>.tar.gz`(cli.mjs/lib/package.json/README/LICENSE),workflow 侧产 `shadow-dev-workflow-v<ver>.tar.gz`(运行必需集 + adapters,见 workflow 仓 pack.mjs)。

## 验证方式

Expand Down
Loading