zhuge-workflow 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# zhuge-workflow
|
|
2
|
+
|
|
3
|
+
`zhuge-workflow` 是一个面向 AI 开发协作场景的 CLI 工具,命令名为 `zhuge`。
|
|
4
|
+
|
|
5
|
+
它的目标是:
|
|
6
|
+
|
|
7
|
+
- 自动检测并安装常用 AI 工作流工具
|
|
8
|
+
- 在本机部署统一的 Claude 配置模板
|
|
9
|
+
- 在项目内初始化协作文档与脚本
|
|
10
|
+
- 提供可复现的 CI/CD 发包流程(GitHub Actions → npm)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 支持项总览
|
|
15
|
+
|
|
16
|
+
### 1) CLI 命令支持
|
|
17
|
+
|
|
18
|
+
| 命令 | 说明 | 关键行为 |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| `zhuge setup` | 安装/更新外部工具并部署配置 | 检测状态、选择 install/update、可选择锁定版本、部署配置模板 |
|
|
21
|
+
| `zhuge setup --yes` | CI/无人值守模式 | 跳过交互、执行可操作项、跳过配置部署交互 |
|
|
22
|
+
| `zhuge init` | 初始化当前项目 | 调用 OpenSpec/Trellis 初始化(若已安装)、生成 `.zhuge` 状态文件、创建/更新 `CLAUDE.md` |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
### 2) 外部工具适配支持
|
|
27
|
+
|
|
28
|
+
当前内置 4 个 adapter(按执行顺序):
|
|
29
|
+
|
|
30
|
+
| 工具 | 标识 | 安装方式 | 版本策略 | 交互式 |
|
|
31
|
+
| --- | --- | --- | --- | --- |
|
|
32
|
+
| OpenSpec | `openspec` | npm global | 支持锁定版本(默认 `1.1.1`)或 latest | 否 |
|
|
33
|
+
| Trellis | `trellis` | npm global | 支持锁定版本(默认 `0.2.15`)或 latest | 否 |
|
|
34
|
+
| Claude Code Bridge | `ccb` | git clone + install 脚本 | 无锁定版本策略 | 否 |
|
|
35
|
+
| CCG Workflow | `ccg` | `npx ccg-workflow` | 支持锁定版本(默认 `1.7.61`)或 latest | 是 |
|
|
36
|
+
|
|
37
|
+
补充说明:
|
|
38
|
+
|
|
39
|
+
- 每个 adapter 都有安装状态检测(install / update / skip)
|
|
40
|
+
- 支持失败隔离:某个工具失败不会中断其它工具执行
|
|
41
|
+
- 交互式工具(如 CCG)会关闭 spinner,直接把终端控制权交给工具本身
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### 3) 配置部署支持(当前目标:Claude Code)
|
|
46
|
+
|
|
47
|
+
当前配置目标为 `Claude Code (~/.claude)`,支持以下部署规则:
|
|
48
|
+
|
|
49
|
+
| 模板源 | 目标路径 | 策略 | 说明 |
|
|
50
|
+
| --- | --- | --- | --- |
|
|
51
|
+
| `templates/claude/CLAUDE.md` | `~/.claude/CLAUDE.md` | `merge-section` | 替换 `<!-- Global -->` 区段 |
|
|
52
|
+
| `templates/claude/CLAUDE-ccg.md` | `~/.claude/CLAUDE.md` | `merge-section` | 替换 `<!-- CCG 增强 -->` 区段 |
|
|
53
|
+
| `templates/claude/rules/` | `~/.claude/rules/` | `replace` | 递归复制目录 |
|
|
54
|
+
| `templates/claude/skills/` | `~/.claude/skills/` | `replace` | 递归复制目录 |
|
|
55
|
+
| `templates/claude/commands/` | `~/.claude/commands/` | `replace` | 递归复制目录 |
|
|
56
|
+
|
|
57
|
+
支持的部署策略:
|
|
58
|
+
|
|
59
|
+
- `replace`:目标存在时先备份,再替换(文件)或递归复制(目录)
|
|
60
|
+
- `append`:追加内容且幂等(已有内容不重复追加)
|
|
61
|
+
- `merge-section`:按 marker 区段替换;marker 不存在时自动降级 append
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### 4) 项目初始化支持(`zhuge init`)
|
|
66
|
+
|
|
67
|
+
`zhuge init` 在当前 git 项目内执行以下动作:
|
|
68
|
+
|
|
69
|
+
1. 校验当前目录是 git 仓库(否则退出)
|
|
70
|
+
2. 检测 OpenSpec/Trellis 是否可用,已安装则调用其 `init`
|
|
71
|
+
3. 创建 `.zhuge/init-state.json` 记录初始化状态
|
|
72
|
+
4. 创建或更新项目级 `CLAUDE.md`(幂等写入 zhuge 区段)
|
|
73
|
+
5. 部署增强模板:
|
|
74
|
+
- `templates/init/claude-agents/` → `.claude/agents/`
|
|
75
|
+
- `templates/init/claude-hooks/` → `.claude/hooks/`
|
|
76
|
+
- `templates/init/claude-commands-trellis/` → `.claude/commands/trellis/`
|
|
77
|
+
- `templates/init/trellis-scripts/` → `.trellis/scripts/`
|
|
78
|
+
6. 若存在 `.gitignore`,自动追加 `.zhuge/`
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### 5) CI/CD 与发布支持
|
|
83
|
+
|
|
84
|
+
仓库内已提供 npm 自动发布工作流:
|
|
85
|
+
|
|
86
|
+
- 文件:`.github/workflows/publish-npm.yml`
|
|
87
|
+
- 触发:
|
|
88
|
+
- push tag(`v*.*.*`)
|
|
89
|
+
- 手动 `workflow_dispatch`
|
|
90
|
+
- 发布前校验:测试、类型检查、构建、tag 与 `package.json` 版本一致性
|
|
91
|
+
- 发布命令:`npm publish --access public --provenance`
|
|
92
|
+
|
|
93
|
+
发布说明文档:`docs/npm-trusted-publishing.md`
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 快速开始
|
|
98
|
+
|
|
99
|
+
### 环境要求
|
|
100
|
+
|
|
101
|
+
- Node.js `>=20`
|
|
102
|
+
- 推荐 `pnpm`(开发)
|
|
103
|
+
- Git(`zhuge init` 依赖)
|
|
104
|
+
- 建议 Unix-like 环境(macOS / Linux)
|
|
105
|
+
|
|
106
|
+
### 安装
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npm i -g zhuge-workflow
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 常用命令
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# 交互式安装/更新工具 + 配置部署
|
|
116
|
+
zhuge setup
|
|
117
|
+
|
|
118
|
+
# CI 模式(跳过交互)
|
|
119
|
+
zhuge setup --yes
|
|
120
|
+
|
|
121
|
+
# 初始化当前项目
|
|
122
|
+
zhuge init
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 开发与测试
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# 安装依赖
|
|
131
|
+
pnpm install
|
|
132
|
+
|
|
133
|
+
# 构建
|
|
134
|
+
pnpm build
|
|
135
|
+
|
|
136
|
+
# 单元测试
|
|
137
|
+
pnpm test -- --run
|
|
138
|
+
|
|
139
|
+
# 类型检查
|
|
140
|
+
pnpm lint
|
|
141
|
+
|
|
142
|
+
# Docker E2E(可选)
|
|
143
|
+
pnpm test:e2e
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
沙盒开发脚本(不污染真实 HOME):
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
bash scripts/dev-sandbox.sh
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 环境变量
|
|
155
|
+
|
|
156
|
+
| 变量 | 用途 |
|
|
157
|
+
| --- | --- |
|
|
158
|
+
| `ZHUGE_HOME` | 覆盖 HOME 用于工具路径定位(便于测试沙盒) |
|
|
159
|
+
| `ZHUGE_CI` | 设为 `true` 时启用 CI 模式(等价无人值守) |
|
|
160
|
+
| `CI` | 设为 `true` 时同样启用 CI 模式 |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 当前边界与说明
|
|
165
|
+
|
|
166
|
+
- 当前内置配置目标为 Claude Code(`~/.claude`)
|
|
167
|
+
- CCG 适配器安装是交互式流程
|
|
168
|
+
- `zhuge init` 要求在 git 仓库内执行
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -646,8 +646,30 @@ async function deployConfigsPhase(ciMode) {
|
|
|
646
646
|
}
|
|
647
647
|
|
|
648
648
|
// src/commands/init.ts
|
|
649
|
-
import { existsSync as existsSync6, writeFileSync as writeFileSync2, readFileSync as
|
|
649
|
+
import { existsSync as existsSync6, writeFileSync as writeFileSync2, readFileSync as readFileSync3, mkdirSync as mkdirSync2, copyFileSync as copyFileSync2, readdirSync as readdirSync2 } from "fs";
|
|
650
650
|
import { resolve as resolve6 } from "path";
|
|
651
|
+
|
|
652
|
+
// src/utils/version.ts
|
|
653
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
654
|
+
var FALLBACK_VERSION = "0.0.0";
|
|
655
|
+
var PACKAGE_JSON_RELATIVE_PATHS = ["../package.json", "../../package.json"];
|
|
656
|
+
function getCliVersion() {
|
|
657
|
+
for (const relativePath of PACKAGE_JSON_RELATIVE_PATHS) {
|
|
658
|
+
try {
|
|
659
|
+
const packageJsonPath = new URL(relativePath, import.meta.url);
|
|
660
|
+
const packageJsonRaw = readFileSync2(packageJsonPath, "utf-8");
|
|
661
|
+
const packageJson = JSON.parse(packageJsonRaw);
|
|
662
|
+
if (packageJson.version) {
|
|
663
|
+
return packageJson.version;
|
|
664
|
+
}
|
|
665
|
+
} catch {
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
return FALLBACK_VERSION;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// src/commands/init.ts
|
|
651
673
|
async function initCommand() {
|
|
652
674
|
const cwd = process.cwd();
|
|
653
675
|
title("zhuge init");
|
|
@@ -701,7 +723,7 @@ async function zhugeOwnInit(cwd) {
|
|
|
701
723
|
mkdirSync2(zhugeDir, { recursive: true });
|
|
702
724
|
const stateFile = resolve6(zhugeDir, "init-state.json");
|
|
703
725
|
const state = {
|
|
704
|
-
version:
|
|
726
|
+
version: getCliVersion(),
|
|
705
727
|
initializedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
706
728
|
tools: {
|
|
707
729
|
openspec: existsSync6(resolve6(cwd, "openspec")) || existsSync6(resolve6(cwd, "specs")),
|
|
@@ -711,7 +733,7 @@ async function zhugeOwnInit(cwd) {
|
|
|
711
733
|
writeFileSync2(stateFile, JSON.stringify(state, null, 2));
|
|
712
734
|
const claudeMdPath = resolve6(cwd, "CLAUDE.md");
|
|
713
735
|
if (existsSync6(claudeMdPath)) {
|
|
714
|
-
const existing =
|
|
736
|
+
const existing = readFileSync3(claudeMdPath, "utf-8");
|
|
715
737
|
const zhugeSection = buildZhugeSection(cwd);
|
|
716
738
|
if (!existing.includes("<!-- zhuge-workflow -->")) {
|
|
717
739
|
writeFileSync2(claudeMdPath, existing + "\n" + zhugeSection);
|
|
@@ -727,7 +749,7 @@ async function zhugeOwnInit(cwd) {
|
|
|
727
749
|
deployInitTemplates(cwd);
|
|
728
750
|
const gitignorePath = resolve6(cwd, ".gitignore");
|
|
729
751
|
if (existsSync6(gitignorePath)) {
|
|
730
|
-
const gitignore =
|
|
752
|
+
const gitignore = readFileSync3(gitignorePath, "utf-8");
|
|
731
753
|
if (!gitignore.includes(".zhuge/")) {
|
|
732
754
|
writeFileSync2(gitignorePath, gitignore.trimEnd() + "\n.zhuge/\n");
|
|
733
755
|
}
|
|
@@ -768,6 +790,7 @@ function deployInitTemplates(cwd) {
|
|
|
768
790
|
const mappings = [
|
|
769
791
|
{ source: "claude-agents", target: ".claude/agents" },
|
|
770
792
|
{ source: "claude-hooks", target: ".claude/hooks" },
|
|
793
|
+
{ source: "claude-commands-trellis", target: ".claude/commands/trellis" },
|
|
771
794
|
{ source: "trellis-scripts", target: ".trellis/scripts" }
|
|
772
795
|
];
|
|
773
796
|
let count = 0;
|
|
@@ -790,7 +813,7 @@ function deployInitTemplates(cwd) {
|
|
|
790
813
|
|
|
791
814
|
// src/index.ts
|
|
792
815
|
var program = new Command();
|
|
793
|
-
program.name("zhuge").description("AI development workflow installer and manager").version(
|
|
816
|
+
program.name("zhuge").description("AI development workflow installer and manager").version(getCliVersion());
|
|
794
817
|
program.command("setup").description("Install external tools and deploy AI config files").option("--yes", "Skip all prompts and use defaults (CI mode)").action(async (options) => {
|
|
795
818
|
await setupCommand(options);
|
|
796
819
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/setup.ts","../src/utils/shell.ts","../src/adapters/base-adapter.ts","../src/adapters/openspec.adapter.ts","../src/adapters/trellis.adapter.ts","../src/adapters/ccb.adapter.ts","../src/utils/platform.ts","../src/adapters/ccg.adapter.ts","../src/adapters/index.ts","../src/utils/logger.ts","../src/core/plugin-runner.ts","../src/core/config-deployer.ts","../src/core/config-source.ts","../src/configs/claude.config.ts","../src/configs/index.ts","../src/commands/init.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { setupCommand } from './commands/setup.js'\nimport { initCommand } from './commands/init.js'\n\nconst program = new Command()\n\nprogram\n .name('zhuge')\n .description('AI development workflow installer and manager')\n .version('0.1.0')\n\nprogram\n .command('setup')\n .description('Install external tools and deploy AI config files')\n .option('--yes', 'Skip all prompts and use defaults (CI mode)')\n .action(async (options) => {\n await setupCommand(options)\n })\n\nprogram\n .command('init')\n .description('Initialize project-level documents in current directory')\n .action(async () => {\n await initCommand()\n })\n\nprogram.parse()\n","import chalk from 'chalk'\nimport { checkbox, confirm, select } from '@inquirer/prompts'\nimport { getAllAdapters } from '../adapters/index.js'\nimport { checkAllAdapters, runAdapter, type AdapterAction } from '../core/plugin-runner.js'\nimport type { SetupOptions } from '../core/types.js'\nimport { isCI } from '../utils/platform.js'\nimport * as logger from '../utils/logger.js'\nimport { deployConfigs } from '../core/config-deployer.js'\nimport { getConfigTargetsByNames } from '../configs/index.js'\n\nexport async function setupCommand(options: SetupOptions) {\n const ciMode = options.yes || isCI()\n\n logger.title('zhuge setup')\n\n // 1. 检测所有工具状态\n const adapters = getAllAdapters()\n const actions = await checkAllAdapters(adapters)\n\n // 2. 展示状态表格\n printStatusTable(actions)\n\n // 3. 筛选可操作的工具\n const actionable = actions.filter((a) => a.action !== 'skip')\n const skippable = actions.filter((a) => a.action === 'skip')\n\n if (actionable.length === 0 && skippable.length === actions.length) {\n logger.success('All tools are up to date!')\n }\n\n // 4. 交互选择要安装/更新的工具\n let selected: AdapterAction[]\n\n if (ciMode) {\n // CI 模式:全部执行\n selected = actionable\n } else if (actionable.length === 0) {\n // 没有可操作的,询问是否重新配置已安装的工具\n const reconfig = await confirm({\n message: 'All tools installed. Reconfigure any tool?',\n default: false,\n })\n if (!reconfig) {\n selected = []\n } else {\n const choices = skippable.map((a) => ({\n name: `${a.adapter.meta.displayName} (reconfigure)`,\n value: a,\n }))\n const picked = await checkbox({\n message: 'Select tools to reconfigure:',\n choices,\n })\n // 重新配置 = 重新安装\n selected = picked.map((p) => ({ ...p, action: 'install' as const }))\n }\n } else {\n const choices = actionable.map((a) => ({\n name: formatActionChoice(a),\n value: a,\n checked: true,\n }))\n selected = await checkbox({\n message: 'Select tools to install/update:',\n choices,\n })\n }\n\n // 5. 逐个询问版本策略 & 依次执行\n if (selected.length > 0) {\n // 为每个支持版本锁定的工具单独询问版本策略\n const versionMap = new Map<string, string | undefined>()\n\n if (!ciMode) {\n for (const item of selected) {\n if (item.adapter.meta.pinnedVersion) {\n const strategy = await select({\n message: `${item.adapter.meta.displayName} - Version strategy:`,\n choices: [\n {\n name: `Pinned v${item.adapter.meta.pinnedVersion} (tested with zhuge)`,\n value: 'pinned' as const,\n },\n { name: 'Latest version', value: 'latest' as const },\n ],\n })\n if (strategy === 'pinned') {\n versionMap.set(item.adapter.meta.name, item.adapter.meta.pinnedVersion)\n }\n }\n }\n }\n\n console.log()\n for (const item of selected) {\n try {\n const version = versionMap.get(item.adapter.meta.name)\n await runAdapter(item.adapter, item.action === 'skip' ? 'install' : item.action, version)\n } catch (err) {\n logger.error(`Failed: ${item.adapter.meta.displayName} - ${err}`)\n }\n }\n }\n\n // 6. 配置部署阶段\n await deployConfigsPhase(ciMode)\n\n // 7. 完成摘要\n console.log()\n logger.title('Setup Complete')\n if (selected.length > 0) {\n for (const item of selected) {\n const verb = item.action === 'update' ? 'Updated' : 'Installed'\n logger.success(`${verb}: ${item.adapter.meta.displayName}`)\n }\n } else {\n logger.info('No tools were installed or updated.')\n }\n}\n\nfunction printStatusTable(actions: AdapterAction[]) {\n console.log()\n const header = ` ${pad('Tool', 24)} ${pad('Status', 10)} ${pad('Version', 12)} Action`\n console.log(chalk.dim(header))\n console.log(chalk.dim(' ' + '─'.repeat(64)))\n\n for (const { adapter, status, action } of actions) {\n const name = pad(adapter.meta.displayName, 24)\n const st = status.installed\n ? chalk.green(pad('OK', 10))\n : chalk.red(pad('Missing', 10))\n const ver = pad(status.version || '-', 12)\n const act =\n action === 'install'\n ? chalk.yellow('Install')\n : action === 'update'\n ? chalk.cyan(`Update → ${status.latestVersion || '?'}`)\n : chalk.dim('Skip')\n console.log(` ${name} ${st} ${ver} ${act}`)\n }\n console.log()\n}\n\nfunction formatActionChoice(a: AdapterAction): string {\n if (a.action === 'install') {\n return `${a.adapter.meta.displayName} - Install`\n }\n return `${a.adapter.meta.displayName} - Update to ${a.status.latestVersion || 'latest'}`\n}\n\nfunction pad(s: string, len: number): string {\n return s.padEnd(len)\n}\n\nasync function deployConfigsPhase(ciMode: boolean) {\n console.log()\n if (ciMode) {\n logger.info('Config deployment skipped in CI mode (use zhuge setup interactively)')\n return\n }\n\n const deploy = await confirm({\n message: 'Deploy AI tool config files?',\n default: true,\n })\n\n if (!deploy) return\n\n const targets = await checkbox({\n message: 'Deploy configs to:',\n choices: [\n { name: 'Claude Code (~/.claude/)', value: 'claude', checked: true },\n ],\n })\n\n if (targets.length === 0) {\n logger.info('No config targets selected, skipping.')\n return\n }\n\n const configTargets = getConfigTargetsByNames(targets)\n await deployConfigs(configTargets)\n}\n","import { execa, type Options as ExecaOptions } from 'execa'\n\n/** 捕获输出的执行(用于 check、获取版本等) */\nexport async function exec(cmd: string, args: string[], opts?: ExecaOptions) {\n return execa(cmd, args, { ...opts, reject: true })\n}\n\n/** 透传 stdio 的执行(用于交互式安装) */\nexport async function execInherit(cmd: string, args: string[], opts?: ExecaOptions) {\n return execa(cmd, args, {\n ...opts,\n stdio: 'inherit',\n })\n}\n\n/** 检查命令是否存在 */\nexport async function commandExists(cmd: string): Promise<boolean> {\n try {\n await execa('which', [cmd])\n return true\n } catch {\n return false\n }\n}\n","import type { PluginAdapter, AdapterMeta, ToolStatus } from '../core/types.js'\nimport { exec, commandExists } from '../utils/shell.js'\n\nexport abstract class BaseAdapter implements PluginAdapter {\n abstract readonly meta: AdapterMeta\n\n abstract check(): Promise<ToolStatus>\n abstract install(version?: string): Promise<void>\n abstract update(version?: string): Promise<void>\n abstract uninstall(): Promise<void>\n\n /** 执行命令并提取版本号 */\n protected async getVersionFromCommand(\n cmd: string,\n args: string[] = ['--version'],\n ): Promise<string | undefined> {\n try {\n const result = await exec(cmd, args)\n const stdout = String(result.stdout ?? '')\n const match = stdout.match(/v?(\\d+\\.\\d+\\.\\d+)/)\n return match?.[1]\n } catch {\n return undefined\n }\n }\n\n /** 检查命令是否存在 */\n protected commandExists(cmd: string): Promise<boolean> {\n return commandExists(cmd)\n }\n\n /** 获取 npm 包最新版本 */\n protected async getLatestNpmVersion(packageName: string): Promise<string | undefined> {\n try {\n const result = await exec('npm', ['info', packageName, 'version'])\n return String(result.stdout ?? '').trim()\n } catch {\n return undefined\n }\n }\n}\n","import { BaseAdapter } from './base-adapter.js'\nimport type { AdapterMeta, ToolStatus } from '../core/types.js'\nimport { execInherit } from '../utils/shell.js'\n\nexport class OpenSpecAdapter extends BaseAdapter {\n readonly meta: AdapterMeta = {\n name: 'openspec',\n displayName: 'OpenSpec',\n description: 'AI-native spec-driven development',\n installMethod: 'npm-global',\n required: false,\n order: 1,\n interactive: false,\n pinnedVersion: '1.1.1',\n }\n\n private readonly packageName = '@fission-ai/openspec'\n private readonly binName = 'openspec'\n\n async check(): Promise<ToolStatus> {\n const installed = await this.commandExists(this.binName)\n if (!installed) return { installed: false }\n\n const version = await this.getVersionFromCommand(this.binName)\n const latest = await this.getLatestNpmVersion(this.packageName)\n return {\n installed: true,\n version,\n latestVersion: latest,\n updateAvailable: !!(version && latest && version !== latest),\n }\n }\n\n async install(version?: string): Promise<void> {\n const pkg = version ? `${this.packageName}@${version}` : this.packageName\n await execInherit('npm', ['install', '-g', pkg])\n }\n\n async update(version?: string): Promise<void> {\n if (version) {\n await execInherit('npm', ['install', '-g', `${this.packageName}@${version}`])\n } else {\n await execInherit('npm', ['update', '-g', this.packageName])\n }\n }\n\n async uninstall(): Promise<void> {\n await execInherit('npm', ['uninstall', '-g', this.packageName])\n }\n\n async initProject(cwd: string): Promise<void> {\n await execInherit(this.binName, ['init'], { cwd })\n }\n}\n","import { BaseAdapter } from './base-adapter.js'\nimport type { AdapterMeta, ToolStatus } from '../core/types.js'\nimport { execInherit } from '../utils/shell.js'\n\nexport class TrellisAdapter extends BaseAdapter {\n readonly meta: AdapterMeta = {\n name: 'trellis',\n displayName: 'Trellis',\n description: 'AI workflow structure for Claude Code and Cursor',\n installMethod: 'npm-global',\n required: false,\n order: 2,\n interactive: false,\n pinnedVersion: '0.2.15',\n }\n\n private readonly packageName = '@mindfoldhq/trellis'\n private readonly binName = 'trellis'\n\n async check(): Promise<ToolStatus> {\n const installed = await this.commandExists(this.binName)\n if (!installed) return { installed: false }\n\n const version = await this.getVersionFromCommand(this.binName)\n const latest = await this.getLatestNpmVersion(this.packageName)\n return {\n installed: true,\n version,\n latestVersion: latest,\n updateAvailable: !!(version && latest && version !== latest),\n }\n }\n\n async install(version?: string): Promise<void> {\n const pkg = version ? `${this.packageName}@${version}` : this.packageName\n await execInherit('npm', ['install', '-g', pkg])\n }\n\n async update(version?: string): Promise<void> {\n if (version) {\n await execInherit('npm', ['install', '-g', `${this.packageName}@${version}`])\n } else {\n await execInherit('npm', ['update', '-g', this.packageName])\n }\n }\n\n async uninstall(): Promise<void> {\n await execInherit('npm', ['uninstall', '-g', this.packageName])\n }\n\n async initProject(cwd: string): Promise<void> {\n await execInherit(this.binName, ['init'], { cwd })\n }\n}\n","import { BaseAdapter } from './base-adapter.js'\nimport type { AdapterMeta, ToolStatus } from '../core/types.js'\nimport { execInherit } from '../utils/shell.js'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { getHome } from '../utils/platform.js'\n\nexport class CcbAdapter extends BaseAdapter {\n readonly meta: AdapterMeta = {\n name: 'ccb',\n displayName: 'Claude Code Bridge (CCB)',\n description: 'Multi-model collaboration via split-pane terminal',\n installMethod: 'git-clone-script',\n required: false,\n order: 3,\n interactive: false,\n }\n\n private readonly repoUrl = 'https://github.com/bfly123/claude_code_bridge.git'\n\n private get cloneDir(): string {\n return resolve(getHome(), '.local/share/claude_code_bridge')\n }\n\n async check(): Promise<ToolStatus> {\n const installed = await this.commandExists('ccb')\n if (!installed) return { installed: false }\n\n const version = await this.getVersionFromCommand('ccb')\n return { installed: true, version }\n }\n\n async install(): Promise<void> {\n if (!existsSync(this.cloneDir)) {\n await execInherit('git', ['clone', this.repoUrl, this.cloneDir])\n }\n await execInherit('bash', ['./install.sh', 'install'], { cwd: this.cloneDir })\n }\n\n async update(): Promise<void> {\n if (existsSync(this.cloneDir)) {\n await execInherit('git', ['-C', this.cloneDir, 'pull'])\n } else {\n await execInherit('git', ['clone', this.repoUrl, this.cloneDir])\n }\n await execInherit('bash', ['./install.sh', 'install'], { cwd: this.cloneDir })\n }\n\n async uninstall(): Promise<void> {\n if (existsSync(this.cloneDir)) {\n await execInherit('bash', ['./install.sh', 'uninstall'], { cwd: this.cloneDir })\n }\n }\n}\n","import { homedir } from 'node:os'\nimport { resolve } from 'node:path'\n\n/** 展开路径中的 ~ 为用户 HOME 目录 */\nexport function expandHome(p: string): string {\n if (p.startsWith('~/') || p === '~') {\n return resolve(homedir(), p.slice(2))\n }\n return p\n}\n\n/** 获取 HOME 目录(支持 ZHUGE_HOME 环境变量覆盖,用于测试沙盒) */\nexport function getHome(): string {\n return process.env.ZHUGE_HOME || homedir()\n}\n\n/** 是否 CI 模式 */\nexport function isCI(): boolean {\n return process.env.ZHUGE_CI === 'true' || process.env.CI === 'true'\n}\n","import { BaseAdapter } from './base-adapter.js'\nimport type { AdapterMeta, ToolStatus } from '../core/types.js'\nimport { execInherit } from '../utils/shell.js'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { getHome } from '../utils/platform.js'\n\nexport class CcgAdapter extends BaseAdapter {\n readonly meta: AdapterMeta = {\n name: 'ccg',\n displayName: 'CCG Workflow',\n description: 'Claude Code enhanced multi-model workflow',\n installMethod: 'npx',\n required: false,\n order: 4,\n interactive: true,\n pinnedVersion: '1.7.61',\n }\n\n private get configPath(): string {\n return resolve(getHome(), '.claude/.ccg/config.toml')\n }\n\n async check(): Promise<ToolStatus> {\n const installed = existsSync(this.configPath)\n if (!installed) return { installed: false }\n return { installed: true, version: 'detected' }\n }\n\n async install(version?: string): Promise<void> {\n const pkg = version ? `ccg-workflow@${version}` : 'ccg-workflow@latest'\n await execInherit('npx', [pkg])\n }\n\n async update(version?: string): Promise<void> {\n await this.install(version)\n }\n\n async uninstall(): Promise<void> {\n // ccg 无专用 uninstall 命令\n const ccgDir = resolve(getHome(), '.claude/.ccg')\n if (existsSync(ccgDir)) {\n const { rmSync } = await import('node:fs')\n rmSync(ccgDir, { recursive: true, force: true })\n }\n }\n}\n","import type { PluginAdapter } from '../core/types.js'\nimport { OpenSpecAdapter } from './openspec.adapter.js'\nimport { TrellisAdapter } from './trellis.adapter.js'\nimport { CcbAdapter } from './ccb.adapter.js'\nimport { CcgAdapter } from './ccg.adapter.js'\n\n/** 所有已注册的 adapter,按 order 排序 */\nexport function getAllAdapters(): PluginAdapter[] {\n return [\n new OpenSpecAdapter(),\n new TrellisAdapter(),\n new CcbAdapter(),\n new CcgAdapter(),\n ].sort((a, b) => a.meta.order - b.meta.order)\n}\n","import chalk from 'chalk'\nimport ora, { type Ora } from 'ora'\n\nexport function info(msg: string) {\n console.log(chalk.blue('ℹ'), msg)\n}\n\nexport function success(msg: string) {\n console.log(chalk.green('✔'), msg)\n}\n\nexport function warn(msg: string) {\n console.log(chalk.yellow('⚠'), msg)\n}\n\nexport function error(msg: string) {\n console.log(chalk.red('✖'), msg)\n}\n\nexport function spinner(text: string): Ora {\n return ora({ text, color: 'cyan' }).start()\n}\n\nexport function title(text: string) {\n console.log()\n console.log(chalk.bold.cyan(text))\n console.log(chalk.dim('─'.repeat(text.length + 4)))\n}\n","import type { PluginAdapter, ToolStatus } from './types.js'\nimport * as logger from '../utils/logger.js'\n\nexport interface AdapterAction {\n adapter: PluginAdapter\n status: ToolStatus\n action: 'install' | 'update' | 'skip'\n}\n\n/** 检测所有工具状态 */\nexport async function checkAllAdapters(adapters: PluginAdapter[]): Promise<AdapterAction[]> {\n const spin = logger.spinner('Checking installed tools...')\n\n const results: AdapterAction[] = []\n for (const adapter of adapters) {\n try {\n const status = await adapter.check()\n let action: 'install' | 'update' | 'skip'\n if (!status.installed) {\n action = 'install'\n } else if (status.updateAvailable) {\n action = 'update'\n } else {\n action = 'skip'\n }\n results.push({ adapter, status, action })\n } catch {\n results.push({\n adapter,\n status: { installed: false },\n action: 'install',\n })\n }\n }\n\n spin.succeed('Tool check complete')\n return results\n}\n\n/** 执行单个 adapter 的安装/更新 */\nexport async function runAdapter(\n adapter: PluginAdapter,\n action: 'install' | 'update',\n version?: string,\n): Promise<void> {\n if (adapter.meta.interactive) {\n // 交互式工具:暂停 spinner,让工具自己控制终端\n console.log()\n logger.info(`Starting ${adapter.meta.displayName} (interactive)...`)\n console.log()\n await adapter[action](version)\n console.log()\n } else {\n const spin = logger.spinner(\n `${action === 'install' ? 'Installing' : 'Updating'} ${adapter.meta.displayName}${version ? `@${version}` : ''}...`,\n )\n try {\n await adapter[action](version)\n spin.succeed(`${adapter.meta.displayName} ${action === 'install' ? 'installed' : 'updated'}${version ? ` (v${version})` : ''}`)\n } catch (err) {\n spin.fail(`${adapter.meta.displayName} ${action} failed`)\n throw err\n }\n }\n}\n","import { resolve, dirname, basename } from 'node:path'\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n copyFileSync,\n mkdirSync,\n renameSync,\n readdirSync,\n statSync,\n} from 'node:fs'\nimport type { ConfigDeployRule, ConfigTarget } from './types.js'\nimport { getBundledTemplatesDir } from './config-source.js'\nimport { expandHome } from '../utils/platform.js'\nimport * as logger from '../utils/logger.js'\n\n/** 部署配置到目标 */\nexport async function deployConfigs(\n targets: ConfigTarget[],\n): Promise<void> {\n const templatesDir = getBundledTemplatesDir()\n\n for (const target of targets) {\n const spin = logger.spinner(`Deploying configs to ${target.displayName}...`)\n\n try {\n let deployed = 0\n for (const rule of target.rules) {\n const sourcePath = resolve(templatesDir, target.name, rule.source)\n const targetPath = expandHome(rule.target)\n\n if (!existsSync(sourcePath)) {\n continue\n }\n\n // 确保目标目录存在\n mkdirSync(dirname(targetPath), { recursive: true })\n\n if (statSync(sourcePath).isDirectory()) {\n deployed += deployDirectory(sourcePath, targetPath, rule.strategy)\n } else {\n deployFile(sourcePath, targetPath, rule)\n deployed++\n }\n }\n\n spin.succeed(`${target.displayName}: ${deployed} file(s) deployed`)\n } catch (err) {\n spin.fail(`${target.displayName}: deploy failed`)\n logger.error(String(err))\n }\n }\n}\n\n/** 部署单个文件 */\nfunction deployFile(source: string, target: string, rule: ConfigDeployRule): void {\n switch (rule.strategy) {\n case 'replace':\n deployReplace(source, target)\n break\n case 'append':\n deployAppend(source, target)\n break\n case 'merge-section':\n if (!rule.sectionMarker) {\n throw new Error(`merge-section requires sectionMarker for ${rule.source}`)\n }\n deployMergeSection(source, target, rule.sectionMarker)\n break\n }\n}\n\n/** 整文件替换(备份旧文件) */\nfunction deployReplace(source: string, target: string): void {\n if (existsSync(target)) {\n const backupPath = `${target}.bak.${Date.now()}`\n renameSync(target, backupPath)\n }\n copyFileSync(source, target)\n}\n\n/** 追加到文件末尾(幂等:已包含则跳过) */\nfunction deployAppend(source: string, target: string): void {\n const content = readFileSync(source, 'utf-8')\n\n if (existsSync(target)) {\n const existing = readFileSync(target, 'utf-8')\n if (existing.includes(content.trim())) return\n writeFileSync(target, existing + '\\n' + content)\n } else {\n writeFileSync(target, content)\n }\n}\n\n/** 用 HTML comment marker 替换指定区段 */\nfunction deployMergeSection(\n source: string,\n target: string,\n marker: { start: string; end: string },\n): void {\n const newContent = readFileSync(source, 'utf-8')\n\n if (!existsSync(target)) {\n writeFileSync(target, newContent)\n return\n }\n\n const existing = readFileSync(target, 'utf-8')\n const startIdx = existing.indexOf(marker.start)\n const endIdx = existing.indexOf(marker.end)\n\n if (startIdx !== -1 && endIdx !== -1) {\n const before = existing.substring(0, startIdx)\n const after = existing.substring(endIdx + marker.end.length)\n writeFileSync(target, before + newContent + after)\n } else {\n // marker 不存在,降级为 append\n logger.warn(`Section markers not found in ${basename(target)}, appending instead`)\n writeFileSync(target, existing + '\\n' + newContent)\n }\n}\n\n/** 部署整个目录(递归复制) */\nfunction deployDirectory(sourceDir: string, targetDir: string, _strategy: string): number {\n mkdirSync(targetDir, { recursive: true })\n let count = 0\n\n for (const entry of readdirSync(sourceDir, { withFileTypes: true })) {\n const srcPath = resolve(sourceDir, entry.name)\n const tgtPath = resolve(targetDir, entry.name)\n\n if (entry.isDirectory()) {\n count += deployDirectory(srcPath, tgtPath, _strategy)\n } else {\n copyFileSync(srcPath, tgtPath)\n count++\n }\n }\n\n return count\n}\n","import { resolve, dirname } from 'node:path'\nimport { existsSync, statSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\n/** 获取模板目录路径 */\nexport function getBundledTemplatesDir(): string {\n let dir = __dirname\n for (let i = 0; i < 5; i++) {\n const candidate = resolve(dir, 'templates')\n if (existsSync(candidate) && statSync(candidate).isDirectory()) {\n return candidate\n }\n dir = resolve(dir, '..')\n }\n throw new Error('Could not find templates directory')\n}\n","import { existsSync } from 'node:fs'\nimport type { ConfigTarget } from '../core/types.js'\nimport { expandHome } from '../utils/platform.js'\n\nexport const claudeConfig: ConfigTarget = {\n name: 'claude',\n displayName: 'Claude Code',\n configDir: '~/.claude',\n detect: async () => existsSync(expandHome('~/.claude')),\n rules: [\n // CLAUDE.md - Global 区块(个人配置)\n {\n source: 'CLAUDE.md',\n target: '~/.claude/CLAUDE.md',\n strategy: 'merge-section',\n sectionMarker: {\n start: '<!-- Global -->',\n end: '<!-- Global_END -->',\n },\n },\n // CLAUDE.md - CCG 增强区块\n {\n source: 'CLAUDE-ccg.md',\n target: '~/.claude/CLAUDE.md',\n strategy: 'merge-section',\n sectionMarker: {\n start: '<!-- CCG 增强 -->',\n end: '<!-- CCG 增强_END -->',\n },\n },\n // rules - 整体替换(全部由 zhuge 管理)\n {\n source: 'rules',\n target: '~/.claude/rules',\n strategy: 'replace',\n },\n // skills - 只复制 zhuge 管理的,不删除已有的(保护 CCB/第三方 skill)\n {\n source: 'skills',\n target: '~/.claude/skills',\n strategy: 'replace',\n },\n // commands/developer - 只复制 zhuge 管理的(保护 CCG 的 commands/ccg/)\n {\n source: 'commands',\n target: '~/.claude/commands',\n strategy: 'replace',\n },\n ],\n}\n","import type { ConfigTarget } from '../core/types.js'\nimport { claudeConfig } from './claude.config.js'\n\n/** 所有配置目标 */\nexport function getAllConfigTargets(): ConfigTarget[] {\n return [claudeConfig]\n}\n\n/** 按名称获取配置目标 */\nexport function getConfigTargetsByNames(names: string[]): ConfigTarget[] {\n const all = getAllConfigTargets()\n return all.filter((t) => names.includes(t.name))\n}\n","import { existsSync, writeFileSync, readFileSync, mkdirSync, copyFileSync, readdirSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { execInherit, commandExists } from '../utils/shell.js'\nimport * as logger from '../utils/logger.js'\nimport { getBundledTemplatesDir } from '../core/config-source.js'\n\nexport async function initCommand() {\n const cwd = process.cwd()\n\n logger.title('zhuge init')\n\n // 1. 前置检查\n if (!existsSync(resolve(cwd, '.git'))) {\n logger.error('Current directory is not a git repository. Run \"git init\" first.')\n process.exit(1)\n }\n\n const checks = await Promise.all([\n commandExists('openspec'),\n commandExists('trellis'),\n ])\n\n if (!checks[0]) {\n logger.warn('OpenSpec not installed. Run \"zhuge setup\" first to install it.')\n logger.info('Skipping OpenSpec init...')\n }\n\n if (!checks[1]) {\n logger.warn('Trellis not installed. Run \"zhuge setup\" first to install it.')\n logger.info('Skipping Trellis init...')\n }\n\n // 2. OpenSpec init\n if (checks[0]) {\n console.log()\n logger.info('Running OpenSpec init...')\n console.log()\n try {\n await execInherit('openspec', ['init'], { cwd })\n logger.success('OpenSpec init complete')\n } catch (err) {\n logger.error(`OpenSpec init failed: ${err}`)\n }\n }\n\n // 3. Trellis init\n if (checks[1]) {\n console.log()\n logger.info('Running Trellis init...')\n console.log()\n try {\n await execInherit('trellis', ['init'], { cwd })\n logger.success('Trellis init complete')\n } catch (err) {\n logger.error(`Trellis init failed: ${err}`)\n }\n }\n\n // 4. zhuge 自身初始化\n console.log()\n logger.info('Running zhuge init...')\n await zhugeOwnInit(cwd)\n\n // 5. 完成摘要\n console.log()\n logger.title('Init Complete')\n logger.success(`Project initialized at ${cwd}`)\n}\n\nasync function zhugeOwnInit(cwd: string) {\n // 创建 .zhuge/ 目录\n const zhugeDir = resolve(cwd, '.zhuge')\n mkdirSync(zhugeDir, { recursive: true })\n\n // 写入 init 状态记录\n const stateFile = resolve(zhugeDir, 'init-state.json')\n const state = {\n version: '0.1.0',\n initializedAt: new Date().toISOString(),\n tools: {\n openspec: existsSync(resolve(cwd, 'openspec')) || existsSync(resolve(cwd, 'specs')),\n trellis: existsSync(resolve(cwd, '.trellis')),\n },\n }\n writeFileSync(stateFile, JSON.stringify(state, null, 2))\n\n // 生成/修改项目级 CLAUDE.md\n const claudeMdPath = resolve(cwd, 'CLAUDE.md')\n if (existsSync(claudeMdPath)) {\n // 已有 CLAUDE.md,追加 zhuge 区段\n const existing = readFileSync(claudeMdPath, 'utf-8')\n const zhugeSection = buildZhugeSection(cwd)\n if (!existing.includes('<!-- zhuge-workflow -->')) {\n writeFileSync(claudeMdPath, existing + '\\n' + zhugeSection)\n logger.success('Updated project CLAUDE.md with zhuge section')\n } else {\n logger.info('CLAUDE.md already contains zhuge section, skipping')\n }\n } else {\n // 创建新的 CLAUDE.md\n const content = buildProjectClaudeMd(cwd)\n writeFileSync(claudeMdPath, content)\n logger.success('Created project CLAUDE.md')\n }\n\n // 替换 Trellis/Claude 生成的文件为 zhuge 增强版\n deployInitTemplates(cwd)\n\n // 添加 .zhuge/ 到 .gitignore(如果需要)\n const gitignorePath = resolve(cwd, '.gitignore')\n if (existsSync(gitignorePath)) {\n const gitignore = readFileSync(gitignorePath, 'utf-8')\n if (!gitignore.includes('.zhuge/')) {\n writeFileSync(gitignorePath, gitignore.trimEnd() + '\\n.zhuge/\\n')\n }\n }\n\n logger.success('zhuge init complete')\n}\n\nfunction buildZhugeSection(cwd: string): string {\n const parts: string[] = [\n '<!-- zhuge-workflow -->',\n '',\n '## Workflow',\n '',\n ]\n\n // 检测 OpenSpec 生成的内容\n if (existsSync(resolve(cwd, 'specs')) || existsSync(resolve(cwd, 'openspec'))) {\n parts.push('- OpenSpec specs available in `specs/` or `openspec/`')\n }\n\n // 检测 Trellis 生成的内容\n if (existsSync(resolve(cwd, '.trellis'))) {\n parts.push('- Trellis workflow configured in `.trellis/`')\n }\n\n parts.push('')\n parts.push('<!-- zhuge-workflow-end -->')\n\n return parts.join('\\n')\n}\n\nfunction buildProjectClaudeMd(cwd: string): string {\n const parts: string[] = [\n `# ${resolve(cwd).split('/').pop() || 'Project'}`,\n '',\n ]\n\n parts.push(buildZhugeSection(cwd))\n\n return parts.join('\\n')\n}\n\n/**\n * 将 zhuge 增强版文件替换到项目中\n * templates/init/claude-agents/ → {cwd}/.claude/agents/\n * templates/init/claude-hooks/ → {cwd}/.claude/hooks/\n * templates/init/trellis-scripts/ → {cwd}/.trellis/scripts/\n */\nfunction deployInitTemplates(cwd: string) {\n const templatesDir = resolve(getBundledTemplatesDir(), 'init')\n\n if (!existsSync(templatesDir)) {\n logger.warn('Init templates not found, skipping file replacements')\n return\n }\n\n const mappings: Array<{ source: string; target: string }> = [\n { source: 'claude-agents', target: '.claude/agents' },\n { source: 'claude-hooks', target: '.claude/hooks' },\n { source: 'trellis-scripts', target: '.trellis/scripts' },\n ]\n\n let count = 0\n for (const { source, target } of mappings) {\n const srcDir = resolve(templatesDir, source)\n if (!existsSync(srcDir)) continue\n\n const tgtDir = resolve(cwd, target)\n mkdirSync(tgtDir, { recursive: true })\n\n for (const entry of readdirSync(srcDir, { withFileTypes: true })) {\n if (entry.isFile()) {\n copyFileSync(resolve(srcDir, entry.name), resolve(tgtDir, entry.name))\n count++\n }\n }\n }\n\n if (count > 0) {\n logger.success(`Deployed ${count} zhuge enhanced file(s)`)\n }\n}\n"],"mappings":"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","names":["chalk","resolve","resolve","existsSync","resolve","resolve","existsSync","resolve","dirname","existsSync","statSync","resolve","existsSync","resolve","existsSync","dirname","statSync","existsSync","existsSync","chalk","existsSync","writeFileSync","readFileSync","mkdirSync","copyFileSync","readdirSync","resolve","existsSync","resolve","mkdirSync","writeFileSync","readFileSync","readdirSync","copyFileSync"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/setup.ts","../src/utils/shell.ts","../src/adapters/base-adapter.ts","../src/adapters/openspec.adapter.ts","../src/adapters/trellis.adapter.ts","../src/adapters/ccb.adapter.ts","../src/utils/platform.ts","../src/adapters/ccg.adapter.ts","../src/adapters/index.ts","../src/utils/logger.ts","../src/core/plugin-runner.ts","../src/core/config-deployer.ts","../src/core/config-source.ts","../src/configs/claude.config.ts","../src/configs/index.ts","../src/commands/init.ts","../src/utils/version.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { setupCommand } from './commands/setup.js'\nimport { initCommand } from './commands/init.js'\nimport { getCliVersion } from './utils/version.js'\n\nconst program = new Command()\n\nprogram\n .name('zhuge')\n .description('AI development workflow installer and manager')\n .version(getCliVersion())\n\nprogram\n .command('setup')\n .description('Install external tools and deploy AI config files')\n .option('--yes', 'Skip all prompts and use defaults (CI mode)')\n .action(async (options) => {\n await setupCommand(options)\n })\n\nprogram\n .command('init')\n .description('Initialize project-level documents in current directory')\n .action(async () => {\n await initCommand()\n })\n\nprogram.parse()\n","import chalk from 'chalk'\nimport { checkbox, confirm, select } from '@inquirer/prompts'\nimport { getAllAdapters } from '../adapters/index.js'\nimport { checkAllAdapters, runAdapter, type AdapterAction } from '../core/plugin-runner.js'\nimport type { SetupOptions } from '../core/types.js'\nimport { isCI } from '../utils/platform.js'\nimport * as logger from '../utils/logger.js'\nimport { deployConfigs } from '../core/config-deployer.js'\nimport { getConfigTargetsByNames } from '../configs/index.js'\n\nexport async function setupCommand(options: SetupOptions) {\n const ciMode = options.yes || isCI()\n\n logger.title('zhuge setup')\n\n // 1. 检测所有工具状态\n const adapters = getAllAdapters()\n const actions = await checkAllAdapters(adapters)\n\n // 2. 展示状态表格\n printStatusTable(actions)\n\n // 3. 筛选可操作的工具\n const actionable = actions.filter((a) => a.action !== 'skip')\n const skippable = actions.filter((a) => a.action === 'skip')\n\n if (actionable.length === 0 && skippable.length === actions.length) {\n logger.success('All tools are up to date!')\n }\n\n // 4. 交互选择要安装/更新的工具\n let selected: AdapterAction[]\n\n if (ciMode) {\n // CI 模式:全部执行\n selected = actionable\n } else if (actionable.length === 0) {\n // 没有可操作的,询问是否重新配置已安装的工具\n const reconfig = await confirm({\n message: 'All tools installed. Reconfigure any tool?',\n default: false,\n })\n if (!reconfig) {\n selected = []\n } else {\n const choices = skippable.map((a) => ({\n name: `${a.adapter.meta.displayName} (reconfigure)`,\n value: a,\n }))\n const picked = await checkbox({\n message: 'Select tools to reconfigure:',\n choices,\n })\n // 重新配置 = 重新安装\n selected = picked.map((p) => ({ ...p, action: 'install' as const }))\n }\n } else {\n const choices = actionable.map((a) => ({\n name: formatActionChoice(a),\n value: a,\n checked: true,\n }))\n selected = await checkbox({\n message: 'Select tools to install/update:',\n choices,\n })\n }\n\n // 5. 逐个询问版本策略 & 依次执行\n if (selected.length > 0) {\n // 为每个支持版本锁定的工具单独询问版本策略\n const versionMap = new Map<string, string | undefined>()\n\n if (!ciMode) {\n for (const item of selected) {\n if (item.adapter.meta.pinnedVersion) {\n const strategy = await select({\n message: `${item.adapter.meta.displayName} - Version strategy:`,\n choices: [\n {\n name: `Pinned v${item.adapter.meta.pinnedVersion} (tested with zhuge)`,\n value: 'pinned' as const,\n },\n { name: 'Latest version', value: 'latest' as const },\n ],\n })\n if (strategy === 'pinned') {\n versionMap.set(item.adapter.meta.name, item.adapter.meta.pinnedVersion)\n }\n }\n }\n }\n\n console.log()\n for (const item of selected) {\n try {\n const version = versionMap.get(item.adapter.meta.name)\n await runAdapter(item.adapter, item.action === 'skip' ? 'install' : item.action, version)\n } catch (err) {\n logger.error(`Failed: ${item.adapter.meta.displayName} - ${err}`)\n }\n }\n }\n\n // 6. 配置部署阶段\n await deployConfigsPhase(ciMode)\n\n // 7. 完成摘要\n console.log()\n logger.title('Setup Complete')\n if (selected.length > 0) {\n for (const item of selected) {\n const verb = item.action === 'update' ? 'Updated' : 'Installed'\n logger.success(`${verb}: ${item.adapter.meta.displayName}`)\n }\n } else {\n logger.info('No tools were installed or updated.')\n }\n}\n\nfunction printStatusTable(actions: AdapterAction[]) {\n console.log()\n const header = ` ${pad('Tool', 24)} ${pad('Status', 10)} ${pad('Version', 12)} Action`\n console.log(chalk.dim(header))\n console.log(chalk.dim(' ' + '─'.repeat(64)))\n\n for (const { adapter, status, action } of actions) {\n const name = pad(adapter.meta.displayName, 24)\n const st = status.installed\n ? chalk.green(pad('OK', 10))\n : chalk.red(pad('Missing', 10))\n const ver = pad(status.version || '-', 12)\n const act =\n action === 'install'\n ? chalk.yellow('Install')\n : action === 'update'\n ? chalk.cyan(`Update → ${status.latestVersion || '?'}`)\n : chalk.dim('Skip')\n console.log(` ${name} ${st} ${ver} ${act}`)\n }\n console.log()\n}\n\nfunction formatActionChoice(a: AdapterAction): string {\n if (a.action === 'install') {\n return `${a.adapter.meta.displayName} - Install`\n }\n return `${a.adapter.meta.displayName} - Update to ${a.status.latestVersion || 'latest'}`\n}\n\nfunction pad(s: string, len: number): string {\n return s.padEnd(len)\n}\n\nasync function deployConfigsPhase(ciMode: boolean) {\n console.log()\n if (ciMode) {\n logger.info('Config deployment skipped in CI mode (use zhuge setup interactively)')\n return\n }\n\n const deploy = await confirm({\n message: 'Deploy AI tool config files?',\n default: true,\n })\n\n if (!deploy) return\n\n const targets = await checkbox({\n message: 'Deploy configs to:',\n choices: [\n { name: 'Claude Code (~/.claude/)', value: 'claude', checked: true },\n ],\n })\n\n if (targets.length === 0) {\n logger.info('No config targets selected, skipping.')\n return\n }\n\n const configTargets = getConfigTargetsByNames(targets)\n await deployConfigs(configTargets)\n}\n","import { execa, type Options as ExecaOptions } from 'execa'\n\n/** 捕获输出的执行(用于 check、获取版本等) */\nexport async function exec(cmd: string, args: string[], opts?: ExecaOptions) {\n return execa(cmd, args, { ...opts, reject: true })\n}\n\n/** 透传 stdio 的执行(用于交互式安装) */\nexport async function execInherit(cmd: string, args: string[], opts?: ExecaOptions) {\n return execa(cmd, args, {\n ...opts,\n stdio: 'inherit',\n })\n}\n\n/** 检查命令是否存在 */\nexport async function commandExists(cmd: string): Promise<boolean> {\n try {\n await execa('which', [cmd])\n return true\n } catch {\n return false\n }\n}\n","import type { PluginAdapter, AdapterMeta, ToolStatus } from '../core/types.js'\nimport { exec, commandExists } from '../utils/shell.js'\n\nexport abstract class BaseAdapter implements PluginAdapter {\n abstract readonly meta: AdapterMeta\n\n abstract check(): Promise<ToolStatus>\n abstract install(version?: string): Promise<void>\n abstract update(version?: string): Promise<void>\n abstract uninstall(): Promise<void>\n\n /** 执行命令并提取版本号 */\n protected async getVersionFromCommand(\n cmd: string,\n args: string[] = ['--version'],\n ): Promise<string | undefined> {\n try {\n const result = await exec(cmd, args)\n const stdout = String(result.stdout ?? '')\n const match = stdout.match(/v?(\\d+\\.\\d+\\.\\d+)/)\n return match?.[1]\n } catch {\n return undefined\n }\n }\n\n /** 检查命令是否存在 */\n protected commandExists(cmd: string): Promise<boolean> {\n return commandExists(cmd)\n }\n\n /** 获取 npm 包最新版本 */\n protected async getLatestNpmVersion(packageName: string): Promise<string | undefined> {\n try {\n const result = await exec('npm', ['info', packageName, 'version'])\n return String(result.stdout ?? '').trim()\n } catch {\n return undefined\n }\n }\n}\n","import { BaseAdapter } from './base-adapter.js'\nimport type { AdapterMeta, ToolStatus } from '../core/types.js'\nimport { execInherit } from '../utils/shell.js'\n\nexport class OpenSpecAdapter extends BaseAdapter {\n readonly meta: AdapterMeta = {\n name: 'openspec',\n displayName: 'OpenSpec',\n description: 'AI-native spec-driven development',\n installMethod: 'npm-global',\n required: false,\n order: 1,\n interactive: false,\n pinnedVersion: '1.1.1',\n }\n\n private readonly packageName = '@fission-ai/openspec'\n private readonly binName = 'openspec'\n\n async check(): Promise<ToolStatus> {\n const installed = await this.commandExists(this.binName)\n if (!installed) return { installed: false }\n\n const version = await this.getVersionFromCommand(this.binName)\n const latest = await this.getLatestNpmVersion(this.packageName)\n return {\n installed: true,\n version,\n latestVersion: latest,\n updateAvailable: !!(version && latest && version !== latest),\n }\n }\n\n async install(version?: string): Promise<void> {\n const pkg = version ? `${this.packageName}@${version}` : this.packageName\n await execInherit('npm', ['install', '-g', pkg])\n }\n\n async update(version?: string): Promise<void> {\n if (version) {\n await execInherit('npm', ['install', '-g', `${this.packageName}@${version}`])\n } else {\n await execInherit('npm', ['update', '-g', this.packageName])\n }\n }\n\n async uninstall(): Promise<void> {\n await execInherit('npm', ['uninstall', '-g', this.packageName])\n }\n\n async initProject(cwd: string): Promise<void> {\n await execInherit(this.binName, ['init'], { cwd })\n }\n}\n","import { BaseAdapter } from './base-adapter.js'\nimport type { AdapterMeta, ToolStatus } from '../core/types.js'\nimport { execInherit } from '../utils/shell.js'\n\nexport class TrellisAdapter extends BaseAdapter {\n readonly meta: AdapterMeta = {\n name: 'trellis',\n displayName: 'Trellis',\n description: 'AI workflow structure for Claude Code and Cursor',\n installMethod: 'npm-global',\n required: false,\n order: 2,\n interactive: false,\n pinnedVersion: '0.2.15',\n }\n\n private readonly packageName = '@mindfoldhq/trellis'\n private readonly binName = 'trellis'\n\n async check(): Promise<ToolStatus> {\n const installed = await this.commandExists(this.binName)\n if (!installed) return { installed: false }\n\n const version = await this.getVersionFromCommand(this.binName)\n const latest = await this.getLatestNpmVersion(this.packageName)\n return {\n installed: true,\n version,\n latestVersion: latest,\n updateAvailable: !!(version && latest && version !== latest),\n }\n }\n\n async install(version?: string): Promise<void> {\n const pkg = version ? `${this.packageName}@${version}` : this.packageName\n await execInherit('npm', ['install', '-g', pkg])\n }\n\n async update(version?: string): Promise<void> {\n if (version) {\n await execInherit('npm', ['install', '-g', `${this.packageName}@${version}`])\n } else {\n await execInherit('npm', ['update', '-g', this.packageName])\n }\n }\n\n async uninstall(): Promise<void> {\n await execInherit('npm', ['uninstall', '-g', this.packageName])\n }\n\n async initProject(cwd: string): Promise<void> {\n await execInherit(this.binName, ['init'], { cwd })\n }\n}\n","import { BaseAdapter } from './base-adapter.js'\nimport type { AdapterMeta, ToolStatus } from '../core/types.js'\nimport { execInherit } from '../utils/shell.js'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { getHome } from '../utils/platform.js'\n\nexport class CcbAdapter extends BaseAdapter {\n readonly meta: AdapterMeta = {\n name: 'ccb',\n displayName: 'Claude Code Bridge (CCB)',\n description: 'Multi-model collaboration via split-pane terminal',\n installMethod: 'git-clone-script',\n required: false,\n order: 3,\n interactive: false,\n }\n\n private readonly repoUrl = 'https://github.com/bfly123/claude_code_bridge.git'\n\n private get cloneDir(): string {\n return resolve(getHome(), '.local/share/claude_code_bridge')\n }\n\n async check(): Promise<ToolStatus> {\n const installed = await this.commandExists('ccb')\n if (!installed) return { installed: false }\n\n const version = await this.getVersionFromCommand('ccb')\n return { installed: true, version }\n }\n\n async install(): Promise<void> {\n if (!existsSync(this.cloneDir)) {\n await execInherit('git', ['clone', this.repoUrl, this.cloneDir])\n }\n await execInherit('bash', ['./install.sh', 'install'], { cwd: this.cloneDir })\n }\n\n async update(): Promise<void> {\n if (existsSync(this.cloneDir)) {\n await execInherit('git', ['-C', this.cloneDir, 'pull'])\n } else {\n await execInherit('git', ['clone', this.repoUrl, this.cloneDir])\n }\n await execInherit('bash', ['./install.sh', 'install'], { cwd: this.cloneDir })\n }\n\n async uninstall(): Promise<void> {\n if (existsSync(this.cloneDir)) {\n await execInherit('bash', ['./install.sh', 'uninstall'], { cwd: this.cloneDir })\n }\n }\n}\n","import { homedir } from 'node:os'\nimport { resolve } from 'node:path'\n\n/** 展开路径中的 ~ 为用户 HOME 目录 */\nexport function expandHome(p: string): string {\n if (p.startsWith('~/') || p === '~') {\n return resolve(homedir(), p.slice(2))\n }\n return p\n}\n\n/** 获取 HOME 目录(支持 ZHUGE_HOME 环境变量覆盖,用于测试沙盒) */\nexport function getHome(): string {\n return process.env.ZHUGE_HOME || homedir()\n}\n\n/** 是否 CI 模式 */\nexport function isCI(): boolean {\n return process.env.ZHUGE_CI === 'true' || process.env.CI === 'true'\n}\n","import { BaseAdapter } from './base-adapter.js'\nimport type { AdapterMeta, ToolStatus } from '../core/types.js'\nimport { execInherit } from '../utils/shell.js'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { getHome } from '../utils/platform.js'\n\nexport class CcgAdapter extends BaseAdapter {\n readonly meta: AdapterMeta = {\n name: 'ccg',\n displayName: 'CCG Workflow',\n description: 'Claude Code enhanced multi-model workflow',\n installMethod: 'npx',\n required: false,\n order: 4,\n interactive: true,\n pinnedVersion: '1.7.61',\n }\n\n private get configPath(): string {\n return resolve(getHome(), '.claude/.ccg/config.toml')\n }\n\n async check(): Promise<ToolStatus> {\n const installed = existsSync(this.configPath)\n if (!installed) return { installed: false }\n return { installed: true, version: 'detected' }\n }\n\n async install(version?: string): Promise<void> {\n const pkg = version ? `ccg-workflow@${version}` : 'ccg-workflow@latest'\n await execInherit('npx', [pkg])\n }\n\n async update(version?: string): Promise<void> {\n await this.install(version)\n }\n\n async uninstall(): Promise<void> {\n // ccg 无专用 uninstall 命令\n const ccgDir = resolve(getHome(), '.claude/.ccg')\n if (existsSync(ccgDir)) {\n const { rmSync } = await import('node:fs')\n rmSync(ccgDir, { recursive: true, force: true })\n }\n }\n}\n","import type { PluginAdapter } from '../core/types.js'\nimport { OpenSpecAdapter } from './openspec.adapter.js'\nimport { TrellisAdapter } from './trellis.adapter.js'\nimport { CcbAdapter } from './ccb.adapter.js'\nimport { CcgAdapter } from './ccg.adapter.js'\n\n/** 所有已注册的 adapter,按 order 排序 */\nexport function getAllAdapters(): PluginAdapter[] {\n return [\n new OpenSpecAdapter(),\n new TrellisAdapter(),\n new CcbAdapter(),\n new CcgAdapter(),\n ].sort((a, b) => a.meta.order - b.meta.order)\n}\n","import chalk from 'chalk'\nimport ora, { type Ora } from 'ora'\n\nexport function info(msg: string) {\n console.log(chalk.blue('ℹ'), msg)\n}\n\nexport function success(msg: string) {\n console.log(chalk.green('✔'), msg)\n}\n\nexport function warn(msg: string) {\n console.log(chalk.yellow('⚠'), msg)\n}\n\nexport function error(msg: string) {\n console.log(chalk.red('✖'), msg)\n}\n\nexport function spinner(text: string): Ora {\n return ora({ text, color: 'cyan' }).start()\n}\n\nexport function title(text: string) {\n console.log()\n console.log(chalk.bold.cyan(text))\n console.log(chalk.dim('─'.repeat(text.length + 4)))\n}\n","import type { PluginAdapter, ToolStatus } from './types.js'\nimport * as logger from '../utils/logger.js'\n\nexport interface AdapterAction {\n adapter: PluginAdapter\n status: ToolStatus\n action: 'install' | 'update' | 'skip'\n}\n\n/** 检测所有工具状态 */\nexport async function checkAllAdapters(adapters: PluginAdapter[]): Promise<AdapterAction[]> {\n const spin = logger.spinner('Checking installed tools...')\n\n const results: AdapterAction[] = []\n for (const adapter of adapters) {\n try {\n const status = await adapter.check()\n let action: 'install' | 'update' | 'skip'\n if (!status.installed) {\n action = 'install'\n } else if (status.updateAvailable) {\n action = 'update'\n } else {\n action = 'skip'\n }\n results.push({ adapter, status, action })\n } catch {\n results.push({\n adapter,\n status: { installed: false },\n action: 'install',\n })\n }\n }\n\n spin.succeed('Tool check complete')\n return results\n}\n\n/** 执行单个 adapter 的安装/更新 */\nexport async function runAdapter(\n adapter: PluginAdapter,\n action: 'install' | 'update',\n version?: string,\n): Promise<void> {\n if (adapter.meta.interactive) {\n // 交互式工具:暂停 spinner,让工具自己控制终端\n console.log()\n logger.info(`Starting ${adapter.meta.displayName} (interactive)...`)\n console.log()\n await adapter[action](version)\n console.log()\n } else {\n const spin = logger.spinner(\n `${action === 'install' ? 'Installing' : 'Updating'} ${adapter.meta.displayName}${version ? `@${version}` : ''}...`,\n )\n try {\n await adapter[action](version)\n spin.succeed(`${adapter.meta.displayName} ${action === 'install' ? 'installed' : 'updated'}${version ? ` (v${version})` : ''}`)\n } catch (err) {\n spin.fail(`${adapter.meta.displayName} ${action} failed`)\n throw err\n }\n }\n}\n","import { resolve, dirname, basename } from 'node:path'\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n copyFileSync,\n mkdirSync,\n renameSync,\n readdirSync,\n statSync,\n} from 'node:fs'\nimport type { ConfigDeployRule, ConfigTarget } from './types.js'\nimport { getBundledTemplatesDir } from './config-source.js'\nimport { expandHome } from '../utils/platform.js'\nimport * as logger from '../utils/logger.js'\n\n/** 部署配置到目标 */\nexport async function deployConfigs(\n targets: ConfigTarget[],\n): Promise<void> {\n const templatesDir = getBundledTemplatesDir()\n\n for (const target of targets) {\n const spin = logger.spinner(`Deploying configs to ${target.displayName}...`)\n\n try {\n let deployed = 0\n for (const rule of target.rules) {\n const sourcePath = resolve(templatesDir, target.name, rule.source)\n const targetPath = expandHome(rule.target)\n\n if (!existsSync(sourcePath)) {\n continue\n }\n\n // 确保目标目录存在\n mkdirSync(dirname(targetPath), { recursive: true })\n\n if (statSync(sourcePath).isDirectory()) {\n deployed += deployDirectory(sourcePath, targetPath, rule.strategy)\n } else {\n deployFile(sourcePath, targetPath, rule)\n deployed++\n }\n }\n\n spin.succeed(`${target.displayName}: ${deployed} file(s) deployed`)\n } catch (err) {\n spin.fail(`${target.displayName}: deploy failed`)\n logger.error(String(err))\n }\n }\n}\n\n/** 部署单个文件 */\nfunction deployFile(source: string, target: string, rule: ConfigDeployRule): void {\n switch (rule.strategy) {\n case 'replace':\n deployReplace(source, target)\n break\n case 'append':\n deployAppend(source, target)\n break\n case 'merge-section':\n if (!rule.sectionMarker) {\n throw new Error(`merge-section requires sectionMarker for ${rule.source}`)\n }\n deployMergeSection(source, target, rule.sectionMarker)\n break\n }\n}\n\n/** 整文件替换(备份旧文件) */\nfunction deployReplace(source: string, target: string): void {\n if (existsSync(target)) {\n const backupPath = `${target}.bak.${Date.now()}`\n renameSync(target, backupPath)\n }\n copyFileSync(source, target)\n}\n\n/** 追加到文件末尾(幂等:已包含则跳过) */\nfunction deployAppend(source: string, target: string): void {\n const content = readFileSync(source, 'utf-8')\n\n if (existsSync(target)) {\n const existing = readFileSync(target, 'utf-8')\n if (existing.includes(content.trim())) return\n writeFileSync(target, existing + '\\n' + content)\n } else {\n writeFileSync(target, content)\n }\n}\n\n/** 用 HTML comment marker 替换指定区段 */\nfunction deployMergeSection(\n source: string,\n target: string,\n marker: { start: string; end: string },\n): void {\n const newContent = readFileSync(source, 'utf-8')\n\n if (!existsSync(target)) {\n writeFileSync(target, newContent)\n return\n }\n\n const existing = readFileSync(target, 'utf-8')\n const startIdx = existing.indexOf(marker.start)\n const endIdx = existing.indexOf(marker.end)\n\n if (startIdx !== -1 && endIdx !== -1) {\n const before = existing.substring(0, startIdx)\n const after = existing.substring(endIdx + marker.end.length)\n writeFileSync(target, before + newContent + after)\n } else {\n // marker 不存在,降级为 append\n logger.warn(`Section markers not found in ${basename(target)}, appending instead`)\n writeFileSync(target, existing + '\\n' + newContent)\n }\n}\n\n/** 部署整个目录(递归复制) */\nfunction deployDirectory(sourceDir: string, targetDir: string, _strategy: string): number {\n mkdirSync(targetDir, { recursive: true })\n let count = 0\n\n for (const entry of readdirSync(sourceDir, { withFileTypes: true })) {\n const srcPath = resolve(sourceDir, entry.name)\n const tgtPath = resolve(targetDir, entry.name)\n\n if (entry.isDirectory()) {\n count += deployDirectory(srcPath, tgtPath, _strategy)\n } else {\n copyFileSync(srcPath, tgtPath)\n count++\n }\n }\n\n return count\n}\n","import { resolve, dirname } from 'node:path'\nimport { existsSync, statSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\n/** 获取模板目录路径 */\nexport function getBundledTemplatesDir(): string {\n let dir = __dirname\n for (let i = 0; i < 5; i++) {\n const candidate = resolve(dir, 'templates')\n if (existsSync(candidate) && statSync(candidate).isDirectory()) {\n return candidate\n }\n dir = resolve(dir, '..')\n }\n throw new Error('Could not find templates directory')\n}\n","import { existsSync } from 'node:fs'\nimport type { ConfigTarget } from '../core/types.js'\nimport { expandHome } from '../utils/platform.js'\n\nexport const claudeConfig: ConfigTarget = {\n name: 'claude',\n displayName: 'Claude Code',\n configDir: '~/.claude',\n detect: async () => existsSync(expandHome('~/.claude')),\n rules: [\n // CLAUDE.md - Global 区块(个人配置)\n {\n source: 'CLAUDE.md',\n target: '~/.claude/CLAUDE.md',\n strategy: 'merge-section',\n sectionMarker: {\n start: '<!-- Global -->',\n end: '<!-- Global_END -->',\n },\n },\n // CLAUDE.md - CCG 增强区块\n {\n source: 'CLAUDE-ccg.md',\n target: '~/.claude/CLAUDE.md',\n strategy: 'merge-section',\n sectionMarker: {\n start: '<!-- CCG 增强 -->',\n end: '<!-- CCG 增强_END -->',\n },\n },\n // rules - 整体替换(全部由 zhuge 管理)\n {\n source: 'rules',\n target: '~/.claude/rules',\n strategy: 'replace',\n },\n // skills - 只复制 zhuge 管理的,不删除已有的(保护 CCB/第三方 skill)\n {\n source: 'skills',\n target: '~/.claude/skills',\n strategy: 'replace',\n },\n // commands/developer - 只复制 zhuge 管理的(保护 CCG 的 commands/ccg/)\n {\n source: 'commands',\n target: '~/.claude/commands',\n strategy: 'replace',\n },\n ],\n}\n","import type { ConfigTarget } from '../core/types.js'\nimport { claudeConfig } from './claude.config.js'\n\n/** 所有配置目标 */\nexport function getAllConfigTargets(): ConfigTarget[] {\n return [claudeConfig]\n}\n\n/** 按名称获取配置目标 */\nexport function getConfigTargetsByNames(names: string[]): ConfigTarget[] {\n const all = getAllConfigTargets()\n return all.filter((t) => names.includes(t.name))\n}\n","import { existsSync, writeFileSync, readFileSync, mkdirSync, copyFileSync, readdirSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { execInherit, commandExists } from '../utils/shell.js'\nimport * as logger from '../utils/logger.js'\nimport { getBundledTemplatesDir } from '../core/config-source.js'\nimport { getCliVersion } from '../utils/version.js'\n\nexport async function initCommand() {\n const cwd = process.cwd()\n\n logger.title('zhuge init')\n\n // 1. 前置检查\n if (!existsSync(resolve(cwd, '.git'))) {\n logger.error('Current directory is not a git repository. Run \"git init\" first.')\n process.exit(1)\n }\n\n const checks = await Promise.all([\n commandExists('openspec'),\n commandExists('trellis'),\n ])\n\n if (!checks[0]) {\n logger.warn('OpenSpec not installed. Run \"zhuge setup\" first to install it.')\n logger.info('Skipping OpenSpec init...')\n }\n\n if (!checks[1]) {\n logger.warn('Trellis not installed. Run \"zhuge setup\" first to install it.')\n logger.info('Skipping Trellis init...')\n }\n\n // 2. OpenSpec init\n if (checks[0]) {\n console.log()\n logger.info('Running OpenSpec init...')\n console.log()\n try {\n await execInherit('openspec', ['init'], { cwd })\n logger.success('OpenSpec init complete')\n } catch (err) {\n logger.error(`OpenSpec init failed: ${err}`)\n }\n }\n\n // 3. Trellis init\n if (checks[1]) {\n console.log()\n logger.info('Running Trellis init...')\n console.log()\n try {\n await execInherit('trellis', ['init'], { cwd })\n logger.success('Trellis init complete')\n } catch (err) {\n logger.error(`Trellis init failed: ${err}`)\n }\n }\n\n // 4. zhuge 自身初始化\n console.log()\n logger.info('Running zhuge init...')\n await zhugeOwnInit(cwd)\n\n // 5. 完成摘要\n console.log()\n logger.title('Init Complete')\n logger.success(`Project initialized at ${cwd}`)\n}\n\nasync function zhugeOwnInit(cwd: string) {\n // 创建 .zhuge/ 目录\n const zhugeDir = resolve(cwd, '.zhuge')\n mkdirSync(zhugeDir, { recursive: true })\n\n // 写入 init 状态记录\n const stateFile = resolve(zhugeDir, 'init-state.json')\n const state = {\n version: getCliVersion(),\n initializedAt: new Date().toISOString(),\n tools: {\n openspec: existsSync(resolve(cwd, 'openspec')) || existsSync(resolve(cwd, 'specs')),\n trellis: existsSync(resolve(cwd, '.trellis')),\n },\n }\n writeFileSync(stateFile, JSON.stringify(state, null, 2))\n\n // 生成/修改项目级 CLAUDE.md\n const claudeMdPath = resolve(cwd, 'CLAUDE.md')\n if (existsSync(claudeMdPath)) {\n // 已有 CLAUDE.md,追加 zhuge 区段\n const existing = readFileSync(claudeMdPath, 'utf-8')\n const zhugeSection = buildZhugeSection(cwd)\n if (!existing.includes('<!-- zhuge-workflow -->')) {\n writeFileSync(claudeMdPath, existing + '\\n' + zhugeSection)\n logger.success('Updated project CLAUDE.md with zhuge section')\n } else {\n logger.info('CLAUDE.md already contains zhuge section, skipping')\n }\n } else {\n // 创建新的 CLAUDE.md\n const content = buildProjectClaudeMd(cwd)\n writeFileSync(claudeMdPath, content)\n logger.success('Created project CLAUDE.md')\n }\n\n // 替换 Trellis/Claude 生成的文件为 zhuge 增强版\n deployInitTemplates(cwd)\n\n // 添加 .zhuge/ 到 .gitignore(如果需要)\n const gitignorePath = resolve(cwd, '.gitignore')\n if (existsSync(gitignorePath)) {\n const gitignore = readFileSync(gitignorePath, 'utf-8')\n if (!gitignore.includes('.zhuge/')) {\n writeFileSync(gitignorePath, gitignore.trimEnd() + '\\n.zhuge/\\n')\n }\n }\n\n logger.success('zhuge init complete')\n}\n\nfunction buildZhugeSection(cwd: string): string {\n const parts: string[] = [\n '<!-- zhuge-workflow -->',\n '',\n '## Workflow',\n '',\n ]\n\n // 检测 OpenSpec 生成的内容\n if (existsSync(resolve(cwd, 'specs')) || existsSync(resolve(cwd, 'openspec'))) {\n parts.push('- OpenSpec specs available in `specs/` or `openspec/`')\n }\n\n // 检测 Trellis 生成的内容\n if (existsSync(resolve(cwd, '.trellis'))) {\n parts.push('- Trellis workflow configured in `.trellis/`')\n }\n\n parts.push('')\n parts.push('<!-- zhuge-workflow-end -->')\n\n return parts.join('\\n')\n}\n\nfunction buildProjectClaudeMd(cwd: string): string {\n const parts: string[] = [\n `# ${resolve(cwd).split('/').pop() || 'Project'}`,\n '',\n ]\n\n parts.push(buildZhugeSection(cwd))\n\n return parts.join('\\n')\n}\n\n/**\n * 将 zhuge 增强版文件替换到项目中\n * templates/init/claude-agents/ → {cwd}/.claude/agents/\n * templates/init/claude-hooks/ → {cwd}/.claude/hooks/\n * templates/init/claude-commands-trellis/ → {cwd}/.claude/commands/trellis/\n * templates/init/trellis-scripts/ → {cwd}/.trellis/scripts/\n */\nfunction deployInitTemplates(cwd: string) {\n const templatesDir = resolve(getBundledTemplatesDir(), 'init')\n\n if (!existsSync(templatesDir)) {\n logger.warn('Init templates not found, skipping file replacements')\n return\n }\n\n const mappings: Array<{ source: string; target: string }> = [\n { source: 'claude-agents', target: '.claude/agents' },\n { source: 'claude-hooks', target: '.claude/hooks' },\n { source: 'claude-commands-trellis', target: '.claude/commands/trellis' },\n { source: 'trellis-scripts', target: '.trellis/scripts' },\n ]\n\n let count = 0\n for (const { source, target } of mappings) {\n const srcDir = resolve(templatesDir, source)\n if (!existsSync(srcDir)) continue\n\n const tgtDir = resolve(cwd, target)\n mkdirSync(tgtDir, { recursive: true })\n\n for (const entry of readdirSync(srcDir, { withFileTypes: true })) {\n if (entry.isFile()) {\n copyFileSync(resolve(srcDir, entry.name), resolve(tgtDir, entry.name))\n count++\n }\n }\n }\n\n if (count > 0) {\n logger.success(`Deployed ${count} zhuge enhanced file(s)`)\n }\n}\n","import { readFileSync } from 'node:fs'\n\ntype PackageJson = {\n version?: string\n}\n\nconst FALLBACK_VERSION = '0.0.0'\nconst PACKAGE_JSON_RELATIVE_PATHS = ['../package.json', '../../package.json'] as const\n\nexport function getCliVersion(): string {\n for (const relativePath of PACKAGE_JSON_RELATIVE_PATHS) {\n try {\n const packageJsonPath = new URL(relativePath, import.meta.url)\n const packageJsonRaw = readFileSync(packageJsonPath, 'utf-8')\n const packageJson = JSON.parse(packageJsonRaw) as PackageJson\n\n if (packageJson.version) {\n return packageJson.version\n }\n } catch {\n continue\n }\n }\n\n return FALLBACK_VERSION\n}\n"],"mappings":"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","names":["chalk","resolve","resolve","existsSync","resolve","resolve","existsSync","resolve","dirname","existsSync","statSync","resolve","existsSync","resolve","existsSync","dirname","statSync","existsSync","existsSync","chalk","existsSync","writeFileSync","readFileSync","mkdirSync","copyFileSync","readdirSync","resolve","readFileSync","existsSync","resolve","mkdirSync","writeFileSync","readFileSync","readdirSync","copyFileSync"]}
|
package/package.json
CHANGED
|
@@ -200,7 +200,18 @@ description: '多模型分析 → 消除歧义 → 零决策可执行计划 →
|
|
|
200
200
|
./.trellis/scripts/task.sh list
|
|
201
201
|
```
|
|
202
202
|
|
|
203
|
-
**6.5
|
|
203
|
+
**6.5 激活第一个任务**
|
|
204
|
+
|
|
205
|
+
自动激活第一个 Phase 的任务,使 hook 能注入 context:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# 用第一个 create-from-phase 返回的目录路径
|
|
209
|
+
./.trellis/scripts/task.sh start "$FIRST_PHASE_TASK_DIR"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
其中 `$FIRST_PHASE_TASK_DIR` 是 Step 6.3 中 Phase 1 的 `create-from-phase` 输出路径。
|
|
213
|
+
|
|
214
|
+
**6.6 输出任务执行顺序**
|
|
204
215
|
|
|
205
216
|
向用户报告创建的任务列表和建议的执行顺序:
|
|
206
217
|
|
|
@@ -209,11 +220,14 @@ description: '多模型分析 → 消除歧义 → 零决策可执行计划 →
|
|
|
209
220
|
|
|
210
221
|
| Task | Phase | Dev Type | 状态 |
|
|
211
222
|
|------|-------|----------|------|
|
|
212
|
-
| 02-10-xxx-phase-1 | Phase 1: 后端 DTO | backend |
|
|
223
|
+
| 02-10-xxx-phase-1 | Phase 1: 后端 DTO | backend | in_progress |
|
|
213
224
|
| 02-10-xxx-phase-2 | Phase 2: 树构建 | backend | planning |
|
|
214
225
|
| 02-10-xxx-phase-3 | Phase 3: API 端点 | backend | planning |
|
|
215
226
|
| ... | ... | ... | ... |
|
|
216
|
-
|
|
227
|
+
|
|
228
|
+
**下一步**:运行 `/clear` 清理上下文,然后在新 session 中执行:
|
|
229
|
+
- `/trellis:start` → 自动检测当前任务 → 调用 ccg-impl → ccg-review → finish
|
|
230
|
+
- 或直接调用 `Task(subagent_type: "ccg-impl")` 开始实现
|
|
217
231
|
```
|
|
218
232
|
|
|
219
233
|
7. **Context Checkpoint**
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# Start Session
|
|
2
|
+
|
|
3
|
+
Initialize your AI development session and begin working on tasks.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Operation Types
|
|
8
|
+
|
|
9
|
+
| Marker | Meaning | Executor |
|
|
10
|
+
|--------|---------|----------|
|
|
11
|
+
| `[AI]` | Bash scripts or Task calls executed by AI | You (AI) |
|
|
12
|
+
| `[USER]` | Slash commands executed by user | User |
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Initialization `[AI]`
|
|
17
|
+
|
|
18
|
+
### Step 1: Understand Development Workflow
|
|
19
|
+
|
|
20
|
+
First, read the workflow guide to understand the development process:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
cat .trellis/workflow.md
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Follow the instructions in workflow.md** - it contains:
|
|
27
|
+
- Core principles (Read Before Write, Follow Standards, etc.)
|
|
28
|
+
- File system structure
|
|
29
|
+
- Development process
|
|
30
|
+
- Best practices
|
|
31
|
+
|
|
32
|
+
### Step 2: Get Current Context
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
./.trellis/scripts/get-context.sh
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This shows: developer identity, git status, current task (if any), active tasks.
|
|
39
|
+
|
|
40
|
+
### Step 3: Read Guidelines Index
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
cat .trellis/spec/frontend/index.md # Frontend guidelines
|
|
44
|
+
cat .trellis/spec/backend/index.md # Backend guidelines
|
|
45
|
+
cat .trellis/spec/guides/index.md # Thinking guides
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Step 4: Report and Ask
|
|
49
|
+
|
|
50
|
+
Report what you learned and ask: "What would you like to work on?"
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Task Classification
|
|
55
|
+
|
|
56
|
+
When user describes a task, classify it:
|
|
57
|
+
|
|
58
|
+
| Type | Criteria | Workflow |
|
|
59
|
+
|------|----------|----------|
|
|
60
|
+
| **Question** | User asks about code, architecture, or how something works | Answer directly |
|
|
61
|
+
| **Trivial Fix** | Typo fix, comment update, single-line change, < 5 minutes | Direct Edit |
|
|
62
|
+
| **Development Task** | Any code change that: modifies logic, adds features, fixes bugs, touches multiple files | **Task Workflow** |
|
|
63
|
+
|
|
64
|
+
### Decision Rule
|
|
65
|
+
|
|
66
|
+
> **If in doubt, use Task Workflow.**
|
|
67
|
+
>
|
|
68
|
+
> Task Workflow ensures specs are injected to agents, resulting in higher quality code.
|
|
69
|
+
> The overhead is minimal, but the benefit is significant.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Question / Trivial Fix
|
|
74
|
+
|
|
75
|
+
For questions or trivial fixes, work directly:
|
|
76
|
+
|
|
77
|
+
1. Answer question or make the fix
|
|
78
|
+
2. If code was changed, remind user to run `/trellis:finish-work`
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Task Workflow (Development Tasks)
|
|
83
|
+
|
|
84
|
+
**Why this workflow?**
|
|
85
|
+
- Research Agent analyzes what specs are needed
|
|
86
|
+
- Specs are configured in jsonl files
|
|
87
|
+
- Implement Agent receives specs via Hook injection
|
|
88
|
+
- Check Agent verifies against specs
|
|
89
|
+
- Result: Code that follows project conventions automatically
|
|
90
|
+
|
|
91
|
+
### Step 1: Understand the Task `[AI]`
|
|
92
|
+
|
|
93
|
+
Before creating anything, understand what user wants:
|
|
94
|
+
- What is the goal?
|
|
95
|
+
- What type of development? (frontend / backend / fullstack)
|
|
96
|
+
- Any specific requirements or constraints?
|
|
97
|
+
|
|
98
|
+
If unclear, ask clarifying questions.
|
|
99
|
+
|
|
100
|
+
### Step 2: Research the Codebase `[AI]`
|
|
101
|
+
|
|
102
|
+
Call Research Agent to analyze:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
Task(
|
|
106
|
+
subagent_type: "research",
|
|
107
|
+
prompt: "Analyze the codebase for this task:
|
|
108
|
+
|
|
109
|
+
Task: <user's task description>
|
|
110
|
+
Type: <frontend/backend/fullstack>
|
|
111
|
+
|
|
112
|
+
Please find:
|
|
113
|
+
1. Relevant spec files in .trellis/spec/
|
|
114
|
+
2. Existing code patterns to follow (find 2-3 examples)
|
|
115
|
+
3. Files that will likely need modification
|
|
116
|
+
|
|
117
|
+
Output:
|
|
118
|
+
## Relevant Specs
|
|
119
|
+
- <path>: <why it's relevant>
|
|
120
|
+
|
|
121
|
+
## Code Patterns Found
|
|
122
|
+
- <pattern>: <example file path>
|
|
123
|
+
|
|
124
|
+
## Files to Modify
|
|
125
|
+
- <path>: <what change>
|
|
126
|
+
|
|
127
|
+
## Suggested Task Name
|
|
128
|
+
- <short-slug-name>",
|
|
129
|
+
model: "opus"
|
|
130
|
+
)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Step 3: Create Task Directory `[AI]`
|
|
134
|
+
|
|
135
|
+
Based on research results:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
TASK_DIR=$(./.trellis/scripts/task.sh create "<title from research>" --slug <suggested-slug>)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Step 4: Configure Context `[AI]`
|
|
142
|
+
|
|
143
|
+
Initialize default context:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
./.trellis/scripts/task.sh init-context "$TASK_DIR" <type>
|
|
147
|
+
# type: backend | frontend | fullstack
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Add specs found by Research Agent:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# For each relevant spec and code pattern:
|
|
154
|
+
./.trellis/scripts/task.sh add-context "$TASK_DIR" implement "<path>" "<reason>"
|
|
155
|
+
./.trellis/scripts/task.sh add-context "$TASK_DIR" check "<path>" "<reason>"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Step 5: Write Requirements `[AI]`
|
|
159
|
+
|
|
160
|
+
Create `prd.md` in the task directory with:
|
|
161
|
+
|
|
162
|
+
```markdown
|
|
163
|
+
# <Task Title>
|
|
164
|
+
|
|
165
|
+
## Goal
|
|
166
|
+
<What we're trying to achieve>
|
|
167
|
+
|
|
168
|
+
## Requirements
|
|
169
|
+
- <Requirement 1>
|
|
170
|
+
- <Requirement 2>
|
|
171
|
+
|
|
172
|
+
## Acceptance Criteria
|
|
173
|
+
- [ ] <Criterion 1>
|
|
174
|
+
- [ ] <Criterion 2>
|
|
175
|
+
|
|
176
|
+
## Technical Notes
|
|
177
|
+
<Any technical decisions or constraints>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Step 6: Activate Task `[AI]`
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
./.trellis/scripts/task.sh start "$TASK_DIR"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
This sets `.current-task` so hooks can inject context.
|
|
187
|
+
|
|
188
|
+
### Step 7: Implement `[AI]`
|
|
189
|
+
|
|
190
|
+
Call Implement Agent (specs are auto-injected by hook):
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
Task(
|
|
194
|
+
subagent_type: "ccg-impl",
|
|
195
|
+
prompt: "Implement the task described in prd.md.
|
|
196
|
+
|
|
197
|
+
Follow all specs that have been injected into your context.
|
|
198
|
+
Run lint and typecheck before finishing.",
|
|
199
|
+
model: "opus"
|
|
200
|
+
)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Step 8: Check Quality `[AI]`
|
|
204
|
+
|
|
205
|
+
Call Check Agent (specs are auto-injected by hook):
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
Task(
|
|
209
|
+
subagent_type: "ccg-review",
|
|
210
|
+
prompt: "Review all code changes against the specs.
|
|
211
|
+
|
|
212
|
+
Fix any issues you find directly.
|
|
213
|
+
Ensure lint and typecheck pass.",
|
|
214
|
+
model: "opus"
|
|
215
|
+
)
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Step 9: Complete `[AI]`
|
|
219
|
+
|
|
220
|
+
1. Verify lint and typecheck pass
|
|
221
|
+
2. Report what was implemented
|
|
222
|
+
3. Remind user to:
|
|
223
|
+
- Test the changes
|
|
224
|
+
- Commit when ready
|
|
225
|
+
- Run `/trellis:record-session` to record this session
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Continuing Existing Task
|
|
230
|
+
|
|
231
|
+
If `get-context.sh` shows a current task:
|
|
232
|
+
|
|
233
|
+
1. Read the task's `prd.md` to understand the goal
|
|
234
|
+
2. Check `task.json` for current status and phase
|
|
235
|
+
3. Ask user: "Continue working on <task-name>?"
|
|
236
|
+
|
|
237
|
+
If yes, resume from the appropriate step (usually Step 7 or 8).
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Commands Reference
|
|
242
|
+
|
|
243
|
+
### User Commands `[USER]`
|
|
244
|
+
|
|
245
|
+
| Command | When to Use |
|
|
246
|
+
|---------|-------------|
|
|
247
|
+
| `/trellis:start` | Begin a session (this command) |
|
|
248
|
+
| `/trellis:parallel` | Complex tasks needing isolated worktree |
|
|
249
|
+
| `/trellis:finish-work` | Before committing changes |
|
|
250
|
+
| `/trellis:record-session` | After completing a task |
|
|
251
|
+
|
|
252
|
+
### AI Scripts `[AI]`
|
|
253
|
+
|
|
254
|
+
| Script | Purpose |
|
|
255
|
+
|--------|---------|
|
|
256
|
+
| `get-context.sh` | Get session context |
|
|
257
|
+
| `task.sh create` | Create task directory |
|
|
258
|
+
| `task.sh init-context` | Initialize jsonl files |
|
|
259
|
+
| `task.sh add-context` | Add spec to jsonl |
|
|
260
|
+
| `task.sh start` | Set current task |
|
|
261
|
+
| `task.sh finish` | Clear current task |
|
|
262
|
+
| `task.sh archive` | Archive completed task |
|
|
263
|
+
|
|
264
|
+
### Sub Agents `[AI]`
|
|
265
|
+
|
|
266
|
+
| Agent | Purpose | Hook Injection |
|
|
267
|
+
|-------|---------|----------------|
|
|
268
|
+
| research | Analyze codebase | No (reads directly) |
|
|
269
|
+
| ccg-impl | Write code (multi-model) | Yes (implement.jsonl) |
|
|
270
|
+
| ccg-review | Review & fix (dual-model) | Yes (check.jsonl) |
|
|
271
|
+
| debug | Fix specific issues | Yes (debug.jsonl) |
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Key Principle
|
|
276
|
+
|
|
277
|
+
> **Specs are injected, not remembered.**
|
|
278
|
+
>
|
|
279
|
+
> The Task Workflow ensures agents receive relevant specs automatically.
|
|
280
|
+
> This is more reliable than hoping the AI "remembers" conventions.
|
|
@@ -1128,8 +1128,7 @@ cmd_create_from_phase() {
|
|
|
1128
1128
|
"next_action": [
|
|
1129
1129
|
{"phase": 1, "action": "ccg-impl"},
|
|
1130
1130
|
{"phase": 2, "action": "ccg-review"},
|
|
1131
|
-
{"phase": 3, "action": "finish"}
|
|
1132
|
-
{"phase": 4, "action": "create-pr"}
|
|
1131
|
+
{"phase": 3, "action": "finish"}
|
|
1133
1132
|
],
|
|
1134
1133
|
"openspec_change": "$change_dir",
|
|
1135
1134
|
"phase_number": $phase_num,
|