@flyin-ai/alloy 0.1.0

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.
Files changed (94) hide show
  1. package/README.md +151 -0
  2. package/commands/alloy/apply.md +485 -0
  3. package/commands/alloy/archive.md +170 -0
  4. package/commands/alloy/discard.md +80 -0
  5. package/commands/alloy/finish.md +204 -0
  6. package/commands/alloy/fix.md +149 -0
  7. package/commands/alloy/plan.md +360 -0
  8. package/commands/alloy/start.md +314 -0
  9. package/commands/alloy/status.md +79 -0
  10. package/compat.yaml +10 -0
  11. package/dist/cli/commands/completion.d.ts +1 -0
  12. package/dist/cli/commands/completion.js +155 -0
  13. package/dist/cli/commands/completion.js.map +1 -0
  14. package/dist/cli/commands/doctor.d.ts +7 -0
  15. package/dist/cli/commands/doctor.js +93 -0
  16. package/dist/cli/commands/doctor.js.map +1 -0
  17. package/dist/cli/commands/init.d.ts +6 -0
  18. package/dist/cli/commands/init.js +168 -0
  19. package/dist/cli/commands/init.js.map +1 -0
  20. package/dist/cli/commands/internal/archive.d.ts +1 -0
  21. package/dist/cli/commands/internal/archive.js +91 -0
  22. package/dist/cli/commands/internal/archive.js.map +1 -0
  23. package/dist/cli/commands/internal/guard.d.ts +1 -0
  24. package/dist/cli/commands/internal/guard.js +135 -0
  25. package/dist/cli/commands/internal/guard.js.map +1 -0
  26. package/dist/cli/commands/internal/record.d.ts +1 -0
  27. package/dist/cli/commands/internal/record.js +144 -0
  28. package/dist/cli/commands/internal/record.js.map +1 -0
  29. package/dist/cli/commands/internal/state.d.ts +1 -0
  30. package/dist/cli/commands/internal/state.js +99 -0
  31. package/dist/cli/commands/internal/state.js.map +1 -0
  32. package/dist/cli/commands/status.d.ts +1 -0
  33. package/dist/cli/commands/status.js +112 -0
  34. package/dist/cli/commands/status.js.map +1 -0
  35. package/dist/cli/commands/update.d.ts +1 -0
  36. package/dist/cli/commands/update.js +162 -0
  37. package/dist/cli/commands/update.js.map +1 -0
  38. package/dist/cli/index.d.ts +2 -0
  39. package/dist/cli/index.js +291 -0
  40. package/dist/cli/index.js.map +1 -0
  41. package/dist/cli/utils/state.d.ts +6 -0
  42. package/dist/cli/utils/state.js +64 -0
  43. package/dist/cli/utils/state.js.map +1 -0
  44. package/dist/core/agents.d.ts +8 -0
  45. package/dist/core/agents.js +85 -0
  46. package/dist/core/agents.js.map +1 -0
  47. package/dist/core/claude-md.d.ts +4 -0
  48. package/dist/core/claude-md.js +47 -0
  49. package/dist/core/claude-md.js.map +1 -0
  50. package/dist/core/compat.d.ts +2 -0
  51. package/dist/core/compat.js +8 -0
  52. package/dist/core/compat.js.map +1 -0
  53. package/dist/core/detect.d.ts +2 -0
  54. package/dist/core/detect.js +22 -0
  55. package/dist/core/detect.js.map +1 -0
  56. package/dist/core/health.d.ts +22 -0
  57. package/dist/core/health.js +283 -0
  58. package/dist/core/health.js.map +1 -0
  59. package/dist/core/openspec.d.ts +2 -0
  60. package/dist/core/openspec.js +79 -0
  61. package/dist/core/openspec.js.map +1 -0
  62. package/dist/core/skills.d.ts +3 -0
  63. package/dist/core/skills.js +68 -0
  64. package/dist/core/skills.js.map +1 -0
  65. package/dist/core/superpowers.d.ts +1 -0
  66. package/dist/core/superpowers.js +31 -0
  67. package/dist/core/superpowers.js.map +1 -0
  68. package/dist/core/types.d.ts +76 -0
  69. package/dist/core/types.js +2 -0
  70. package/dist/core/types.js.map +1 -0
  71. package/dist/utils/fs.d.ts +1 -0
  72. package/dist/utils/fs.js +7 -0
  73. package/dist/utils/fs.js.map +1 -0
  74. package/dist/utils/prompt.d.ts +10 -0
  75. package/dist/utils/prompt.js +90 -0
  76. package/dist/utils/prompt.js.map +1 -0
  77. package/openspec/schemas/alloy/instructions/design.md +46 -0
  78. package/openspec/schemas/alloy/instructions/draft.md +39 -0
  79. package/openspec/schemas/alloy/instructions/plans.md +59 -0
  80. package/openspec/schemas/alloy/instructions/proposal.md +34 -0
  81. package/openspec/schemas/alloy/instructions/retrospective.md +157 -0
  82. package/openspec/schemas/alloy/instructions/specs.md +53 -0
  83. package/openspec/schemas/alloy/instructions/tasks.md +40 -0
  84. package/openspec/schemas/alloy/instructions/verify.md +90 -0
  85. package/openspec/schemas/alloy/schema.yaml +100 -0
  86. package/openspec/schemas/alloy/templates/design.md +15 -0
  87. package/openspec/schemas/alloy/templates/draft.md +17 -0
  88. package/openspec/schemas/alloy/templates/plans.md +28 -0
  89. package/openspec/schemas/alloy/templates/proposal.md +22 -0
  90. package/openspec/schemas/alloy/templates/retrospective.md +163 -0
  91. package/openspec/schemas/alloy/templates/specs.md +54 -0
  92. package/openspec/schemas/alloy/templates/tasks.md +8 -0
  93. package/openspec/schemas/alloy/templates/verify.md +55 -0
  94. package/package.json +43 -0
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: "Alloy: Status"
3
+ description: 查看 Alloy change 的当前阶段、制品状态和下一步操作
4
+ category: Workflow
5
+ tags: [alloy, workflow]
6
+ ---
7
+
8
+ # alloy-status
9
+
10
+ 你是 Alloy 的状态查看器。你的职责是:读取 change 的状态文件,检查文件系统,输出结构化的状态报告。
11
+
12
+ 状态信息通过 `alloy _state` 命令读取(保证解析一致性),文件存在性通过文件系统检查。
13
+
14
+ ---
15
+
16
+ ## 参数
17
+
18
+ - `/alloy:status` — 显示所有活跃 change 总览
19
+ - `/alloy:status <name>` — 显示指定 change 详情
20
+
21
+ ---
22
+
23
+ ## 无参数:总览模式
24
+
25
+ ```
26
+ Alloy · 状态查看
27
+ ──────────────────────────────────────
28
+ ```
29
+
30
+ 扫描 `openspec/changes/*/.alloy.yaml`,对每个活跃 change 读取 phase 并检查制品状态:
31
+
32
+ ```
33
+ 活跃 Change:
34
+ login-feature planned artifacts: draft ✓ proposal ✓ design ✓ specs ✓ tasks ✓ plans ✓
35
+ payment-fix started artifacts: draft ✓
36
+
37
+ 下一步:login-feature 等待 /alloy:apply,payment-fix 等待 /alloy:plan
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 指定 name:详情模式
43
+
44
+ 读取指定 change 的完整信息。先通过 `alloy _state` 获取元数据:
45
+ ```bash
46
+ alloy _state read openspec/changes/<name> phase
47
+ alloy _state read openspec/changes/<name> worktree
48
+ alloy _state read openspec/changes/<name> created_at
49
+ alloy _state read openspec/changes/<name> updated_at
50
+ ```
51
+
52
+ 再检查文件系统中各制品是否存在,输出:
53
+
54
+ ```
55
+ 阶段: planned
56
+ Change: login-feature
57
+ 路径: openspec/changes/login-feature/
58
+ 创建时间: 2026-05-28
59
+ 更新时间: 2026-05-28
60
+ Worktree: .worktrees/login-feature/
61
+ 制品状态:
62
+ draft ✓
63
+ proposal ✓
64
+ design ✓
65
+ specs ✓
66
+ tasks ✓
67
+ plans ✓
68
+ 下一步: 等待 /alloy:apply
69
+ ```
70
+
71
+ ---
72
+
73
+ ## 一致性检查(自动附带)
74
+
75
+ 每次 status 运行时自动检查:
76
+
77
+ 1. `.alloy.yaml` 中 `worktree` 字段有值但磁盘路径不存在 → "worktree 残留"
78
+ 2. `.alloy.yaml` 中 `worktree` 字段为 null 但 `.worktrees/<name>/` 目录存在 → "worktree 孤儿"(状态写入缺失,apply 阶段可能未正确记录 worktree 路径)
79
+ 3. `git worktree list` 中存在孤立 worktree(`.worktrees/` 下存在目录但没有对应的 `.alloy.yaml`)→ 提示可能存在可清理的残留
package/compat.yaml ADDED
@@ -0,0 +1,10 @@
1
+ compatible:
2
+ node: ">=18.0.0"
3
+ openspec: ">=1.3.0 <2.0.0"
4
+ superpowers: ">=5.0.0 <6.0.0"
5
+ alloy: ">=0.1.0"
6
+ schema: 1
7
+
8
+ install:
9
+ openspec: "@fission-ai/openspec@1"
10
+ superpowers: "obra/superpowers@5"
@@ -0,0 +1 @@
1
+ export declare function generateCompletion(shell: string): string;
@@ -0,0 +1,155 @@
1
+ export function generateCompletion(shell) {
2
+ if (shell.includes("zsh"))
3
+ return zshCompletion();
4
+ if (shell.includes("pwsh") || shell.includes("powershell"))
5
+ return powershellCompletion();
6
+ return bashCompletion();
7
+ }
8
+ function bashCompletion() {
9
+ return [
10
+ "# alloy bash completion — 添加到 ~/.bashrc 或 ~/.bash_profile:",
11
+ "# source <(alloy completion bash)",
12
+ "",
13
+ "_alloy_completion() {",
14
+ ' local cur="${COMP_WORDS[COMP_CWORD]}"',
15
+ "",
16
+ " if [ \"$COMP_CWORD\" -eq 1 ]; then",
17
+ ' COMPREPLY=($(compgen -W "-v --version -h --help init status doctor update completion" -- "$cur"))',
18
+ " return 0",
19
+ " fi",
20
+ "",
21
+ ' case "${COMP_WORDS[1]}" in',
22
+ " init)",
23
+ ' COMPREPLY=($(compgen -W "--scope --inject-claude-md --help -h" -- "$cur"))',
24
+ " ;;",
25
+ " status|doctor)",
26
+ ' COMPREPLY=($(compgen -W "--json --help -h" -- "$cur"))',
27
+ " ;;",
28
+ " update)",
29
+ ' COMPREPLY=($(compgen -W "--help -h" -- "$cur"))',
30
+ " ;;",
31
+ " completion)",
32
+ ' COMPREPLY=($(compgen -W "bash zsh pwsh powershell" -- "$cur"))',
33
+ " ;;",
34
+ " esac",
35
+ "}",
36
+ "",
37
+ "complete -F _alloy_completion alloy",
38
+ "",
39
+ ].join("\n");
40
+ }
41
+ function zshCompletion() {
42
+ return [
43
+ "# alloy zsh completion — 添加到 ~/.zshrc:",
44
+ "# source <(alloy completion zsh)",
45
+ "",
46
+ "#compdef alloy",
47
+ "",
48
+ "_alloy_commands() {",
49
+ " local -a cmds",
50
+ " cmds=(",
51
+ " 'init:项目初始化——检测环境 → 安装依赖 → 部署 schema + skill'",
52
+ " 'status:查看所有活跃 change 总览'",
53
+ " 'doctor:诊断——版本兼容性、文件一致性'",
54
+ " 'update:更新 Alloy skill 文件到最新版'",
55
+ " 'completion:生成 shell 补全脚本'",
56
+ " )",
57
+ " _describe 'command' cmds",
58
+ "}",
59
+ "",
60
+ "_alloy() {",
61
+ " local context state state_descr line",
62
+ " typeset -A opt_args",
63
+ "",
64
+ " _arguments -C \\",
65
+ " '--version[显示版本号]' \\",
66
+ " '-v[显示版本号]' \\",
67
+ " '--help[显示帮助]' \\",
68
+ " '-h[显示帮助]' \\",
69
+ " '1: :_alloy_commands' \\",
70
+ " '*:: :->args'",
71
+ "",
72
+ " case $state in",
73
+ " args)",
74
+ " case $words[1] in",
75
+ " init)",
76
+ " _arguments \\",
77
+ " '--scope[安装范围]:scope:(project global)' \\",
78
+ " '--inject-claude-md[注入 CLAUDE.md]' \\",
79
+ " '--help[显示帮助]' \\",
80
+ " '-h[显示帮助]'",
81
+ " ;;",
82
+ " status|doctor)",
83
+ " _arguments \\",
84
+ " '--json[JSON 格式输出]' \\",
85
+ " '--help[显示帮助]' \\",
86
+ " '-h[显示帮助]'",
87
+ " ;;",
88
+ " update|completion)",
89
+ " _arguments \\",
90
+ " '--help[显示帮助]' \\",
91
+ " '-h[显示帮助]'",
92
+ " ;;",
93
+ " esac",
94
+ " ;;",
95
+ " esac",
96
+ "}",
97
+ "",
98
+ "# 注册补全(source 和 compinit 两种方式均兼容)",
99
+ "compdef _alloy alloy 2>/dev/null",
100
+ "",
101
+ ].join("\n");
102
+ }
103
+ function powershellCompletion() {
104
+ return [
105
+ "# alloy PowerShell completion",
106
+ "# 添加到 PowerShell profile($PROFILE 所在目录可能不存在,需先创建):",
107
+ "# New-Item -ItemType Directory -Force -Path (Split-Path $PROFILE)",
108
+ "# alloy completion pwsh | Out-File -FilePath $PROFILE -Append",
109
+ "# 重新加载 profile 使之生效: . $PROFILE(或重启 PowerShell)",
110
+ "",
111
+ "Register-ArgumentCompleter -Native -CommandName alloy -ScriptBlock {",
112
+ " param($wordToComplete, $commandAst, $cursorPosition)",
113
+ "",
114
+ " $commands = @('init', 'status', 'doctor', 'update', 'completion')",
115
+ " $globalOpts = @('--version', '-v', '--help', '-h')",
116
+ "",
117
+ " $tokens = $commandAst.CommandElements",
118
+ " $command = $null",
119
+ "",
120
+ " foreach ($token in $tokens) {",
121
+ " $value = $token.Value",
122
+ " if ($value -in $commands) {",
123
+ " $command = $value",
124
+ " }",
125
+ " }",
126
+ "",
127
+ " if (-not $command) {",
128
+ " $completionText = @()",
129
+ " foreach ($cmd in $commands) {",
130
+ ' if ($cmd -like "$wordToComplete*") { $completionText += $cmd }',
131
+ " }",
132
+ " foreach ($opt in $globalOpts) {",
133
+ ' if ($opt -like "$wordToComplete*") { $completionText += $opt }',
134
+ " }",
135
+ " $completionText | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }",
136
+ " return",
137
+ " }",
138
+ "",
139
+ " $opts = @()",
140
+ " switch ($command) {",
141
+ " 'init' { $opts = @('--scope', '--inject-claude-md', '--help', '-h') }",
142
+ " 'status' { $opts = @('--json', '--help', '-h') }",
143
+ " 'doctor' { $opts = @('--json', '--help', '-h') }",
144
+ " 'update' { $opts = @('--help', '-h') }",
145
+ " 'completion' { $opts = @('bash', 'zsh', 'pwsh', 'powershell', '--help', '-h') }",
146
+ " }",
147
+ "",
148
+ " $opts | Where-Object { $_ -like \"$wordToComplete*\" } | ForEach-Object {",
149
+ " [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)",
150
+ " }",
151
+ "}",
152
+ "",
153
+ ].join("\n");
154
+ }
155
+ //# sourceMappingURL=completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.js","sourceRoot":"","sources":["../../../src/cli/commands/completion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { HealthCheckResult } from "../../core/types.js";
2
+ export interface DoctorResult {
3
+ healthResults: HealthCheckResult[];
4
+ consistencyWarnings: string[];
5
+ }
6
+ export declare function doctorCommand(projectPath: string): Promise<DoctorResult>;
7
+ export declare function formatDoctorResult(result: DoctorResult, useJson: boolean): string;
@@ -0,0 +1,93 @@
1
+ import { join, dirname } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { existsSync } from "node:fs";
4
+ import { runHealthCheck } from "../../core/health.js";
5
+ import { findActiveChanges } from "../utils/state.js";
6
+ function detectScope(projectPath) {
7
+ const home = process.env.HOME || process.env.USERPROFILE || "~";
8
+ const probe = (dir) => existsSync(join(dir, ".claude", "commands", "alloy"));
9
+ if (probe(projectPath))
10
+ return "project";
11
+ if (probe(home))
12
+ return "global";
13
+ return undefined;
14
+ }
15
+ export async function doctorCommand(projectPath) {
16
+ const packageDir = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
17
+ const scope = detectScope(projectPath);
18
+ // 1. 版本兼容性
19
+ const healthResults = await runHealthCheck(packageDir, projectPath, scope);
20
+ // 2. 文件一致性(双向检查)
21
+ const consistencyWarnings = [];
22
+ const changesDir = join(projectPath, "openspec", "changes");
23
+ const changes = await findActiveChanges(changesDir);
24
+ for (const [name, state] of changes) {
25
+ const changePath = join(changesDir, name);
26
+ // 检查 1: worktree 字段有值但磁盘路径不存在
27
+ // "skipped" 是用户明确选择不创建 worktree 的标记,跳过此项检查
28
+ if (state.worktree && state.worktree !== "skipped") {
29
+ const worktreePath = join(projectPath, state.worktree);
30
+ if (!existsSync(worktreePath)) {
31
+ consistencyWarnings.push(`${name}: worktree 残留 — .alloy.yaml 声称 worktree 在 ${state.worktree} 但路径不可达`);
32
+ }
33
+ }
34
+ // 检查 2: worktree 字段为 null(从未设置)但 .worktrees/<name>/ 目录存在
35
+ // "skipped" 不触发此检查——用户选择不创建,孤儿目录由 git worktree list 覆盖
36
+ if (!state.worktree) {
37
+ const orphanPath = join(projectPath, ".worktrees", name);
38
+ if (existsSync(orphanPath)) {
39
+ consistencyWarnings.push(`${name}: worktree 孤儿 — .alloy.yaml 中 worktree 为 null 但 .worktrees/${name}/ 目录存在(状态写入可能缺失)`);
40
+ }
41
+ }
42
+ }
43
+ // 检查 3: git worktree list 中有孤立 worktree
44
+ try {
45
+ const { execSync } = await import("node:child_process");
46
+ const output = execSync("git worktree list --porcelain", {
47
+ cwd: projectPath,
48
+ stdio: "pipe",
49
+ }).toString();
50
+ const listedPaths = output
51
+ .split("\n")
52
+ .filter((line) => line.startsWith("worktree "))
53
+ .map((line) => line.slice("worktree ".length));
54
+ for (const wtPath of listedPaths) {
55
+ if (wtPath === projectPath)
56
+ continue; // 主 worktree
57
+ // 检查此 worktree 路径是否属于已知 change
58
+ const isTracked = [...changes.keys()].some((name) => {
59
+ const expectedPath = join(projectPath, ".worktrees", name);
60
+ return wtPath.startsWith(expectedPath);
61
+ });
62
+ if (!isTracked) {
63
+ consistencyWarnings.push(`孤立 worktree: ${wtPath}(不属于任何活跃 change)`);
64
+ }
65
+ }
66
+ }
67
+ catch {
68
+ // 不在 git 仓库中或无 worktree,跳过
69
+ }
70
+ return { healthResults, consistencyWarnings };
71
+ }
72
+ export function formatDoctorResult(result, useJson) {
73
+ if (useJson) {
74
+ return JSON.stringify(result, null, 2);
75
+ }
76
+ const lines = [];
77
+ lines.push("健康检查:");
78
+ for (const r of result.healthResults) {
79
+ const mark = r.status === "pass" ? "✓" : r.status === "warn" ? "⚠️" : "✗";
80
+ lines.push(` ${mark} ${r.name}: ${r.current}(要求 ${r.required})`);
81
+ }
82
+ if (result.consistencyWarnings.length > 0) {
83
+ lines.push("\n文件一致性:");
84
+ for (const w of result.consistencyWarnings) {
85
+ lines.push(` ⚠️ ${w}`);
86
+ }
87
+ }
88
+ else {
89
+ lines.push("\n文件一致性:✓ 无问题");
90
+ }
91
+ return lines.join("\n");
92
+ }
93
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { AgentInfo, DeployOptions } from "../../core/types.js";
2
+ export declare function selectScope(passedScope?: string): Promise<"global" | "project">;
3
+ export declare function selectTargetAgents(): Promise<AgentInfo[]>;
4
+ export interface InitOptions extends DeployOptions {
5
+ }
6
+ export declare function initCommand(opts: InitOptions): Promise<void>;
@@ -0,0 +1,168 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { detectEnv } from "../../core/detect.js";
4
+ import { runHealthCheck } from "../../core/health.js";
5
+ import { installOpenSpecCli, initOpenSpecProject } from "../../core/openspec.js";
6
+ import { installSuperpowers } from "../../core/superpowers.js";
7
+ import { deployCommands, deploySchema } from "../../core/skills.js";
8
+ import { injectClaudeMd } from "../../core/claude-md.js";
9
+ import { KNOWN_AGENTS } from "../../core/agents.js";
10
+ import { getPackageRoot } from "../../utils/fs.js";
11
+ import { promptSelect, promptMultiSelect } from "../../utils/prompt.js";
12
+ export async function selectScope(passedScope) {
13
+ if (passedScope)
14
+ return passedScope;
15
+ return promptSelect("Install scope:", [
16
+ { name: "Project (current directory)", value: "project" },
17
+ { name: "Global (home directory)", value: "global" },
18
+ ]);
19
+ }
20
+ export async function selectTargetAgents() {
21
+ const choices = KNOWN_AGENTS.map((a) => ({ name: a.label, value: a.id }));
22
+ const ids = await promptMultiSelect("请选择要安装的 AI 工具(可多选,至少选一项):", choices, {
23
+ validate: (ids) => ids.length > 0 ? true : "请至少选择一个 AI 工具",
24
+ });
25
+ return KNOWN_AGENTS.filter((a) => ids.includes(a.id));
26
+ }
27
+ const GITIGNORE_RULES = ["docs/superpowers/", ".worktrees/", "worktrees/", "*.local.*", ".superpowers/"];
28
+ async function ensureGitignore(projectPath) {
29
+ const gitignorePath = join(projectPath, ".gitignore");
30
+ let content = "";
31
+ try {
32
+ content = await readFile(gitignorePath, "utf-8");
33
+ if (!content.endsWith("\n"))
34
+ content += "\n";
35
+ }
36
+ catch {
37
+ // 文件不存在,稍后创建
38
+ }
39
+ const missing = GITIGNORE_RULES.filter((rule) => !content.includes(rule));
40
+ if (missing.length === 0)
41
+ return;
42
+ const block = `\n### Alloy + Superpowers 运行时 ###\n${missing.join("\n")}\n`;
43
+ await writeFile(gitignorePath, content + block, "utf-8");
44
+ console.log(` ✓ .gitignore → 已追加 ${missing.length} 条规则`);
45
+ }
46
+ export async function initCommand(opts) {
47
+ console.log("\n 🔍 检测环境...");
48
+ // 1. 环境检测
49
+ const env = detectEnv();
50
+ console.log(` Node.js ${env.nodeVersion} ✓`);
51
+ console.log(` git ${env.gitInstalled ? "✓" : "✗ 未安装"}`);
52
+ console.log(` Claude Code ${env.claudeCodeInstalled ? "✓" : "⚠ 未检测到 CLI,请确保已安装"}`);
53
+ if (!env.gitInstalled) {
54
+ console.error("\n ❌ 缺少必要依赖,请先安装 git");
55
+ process.exit(1);
56
+ }
57
+ // 2. 安装 OpenSpec CLI(npm 全局包)
58
+ console.log("\n 📥 OpenSpec CLI...");
59
+ const openspecResult = await installOpenSpecCli();
60
+ if (openspecResult === "installed") {
61
+ console.log(" ✓ @fission-ai/openspec@1 已安装");
62
+ }
63
+ else if (openspecResult === "failed") {
64
+ console.error(" ✗ OpenSpec CLI 安装失败");
65
+ process.exit(1);
66
+ }
67
+ // "skipped" — 函数内部已输出跳过信息
68
+ // 3. 初始化 OpenSpec 项目结构(openspec/ 目录 + .claude/commands/opsx/)
69
+ console.log("\n 📂 初始化 OpenSpec 项目结构...");
70
+ const initResult = await initOpenSpecProject(opts.projectPath, opts.scope);
71
+ if (initResult === "failed") {
72
+ console.error(" ✗ OpenSpec 项目初始化失败");
73
+ process.exit(1);
74
+ }
75
+ // 4. 安装 Superpowers
76
+ console.log("\n 📥 Superpowers...");
77
+ const superpowersResult = await installSuperpowers(opts.scope);
78
+ if (superpowersResult === "installed") {
79
+ console.log(" ✓ obra/superpowers@5 已安装");
80
+ }
81
+ else if (superpowersResult === "skipped") {
82
+ console.log(" ✓ Superpowers 已安装,跳过");
83
+ }
84
+ else {
85
+ console.log(" ⚠ Superpowers 安装失败,请稍后手动运行 alloy init 重试");
86
+ }
87
+ // 5. 部署 Alloy commands
88
+ console.log("\n 🚀 部署 Alloy commands...");
89
+ if (opts.targetAgents.length === 0) {
90
+ console.log(" ⚠ 未选择任何 AI 工具,跳过 command 部署");
91
+ }
92
+ else {
93
+ try {
94
+ const paths = await deployCommands(opts);
95
+ for (const p of paths) {
96
+ console.log(` ✓ ${p}`);
97
+ }
98
+ }
99
+ catch (e) {
100
+ console.error(` ✗ command 部署失败: ${e.message}`);
101
+ process.exit(1);
102
+ }
103
+ }
104
+ const schemaPath = await deploySchema(opts);
105
+ console.log(` ✓ 项目 schema → ${schemaPath}`);
106
+ // 6. 确保 .gitignore 包含 Alloy 运行时目录
107
+ await ensureGitignore(opts.projectPath);
108
+ // 7. 注入 CLAUDE.md
109
+ const injected = await injectClaudeMd(opts);
110
+ if (injected) {
111
+ console.log(" ✓ CLAUDE.md → 已追加 Alloy 工作流提示");
112
+ }
113
+ // 8. 兼容性检查
114
+ console.log("\n 🩺 兼容性检查...");
115
+ const packageDir = getPackageRoot();
116
+ const results = await runHealthCheck(packageDir, opts.projectPath, opts.scope);
117
+ for (const r of results) {
118
+ const mark = r.status === "pass" ? "✓" : r.status === "warn" ? "⚠️" : "✗";
119
+ console.log(` ${mark} ${r.name} ${r.current}(要求 ${r.required})`);
120
+ }
121
+ // 9. 自动注册 shell 补全(失败不阻断 init)
122
+ console.log("\n 🐚 注册 shell 补全...");
123
+ try {
124
+ const home = process.env.HOME || process.env.USERPROFILE || "~";
125
+ const shell = process.env.SHELL || "";
126
+ let completionLine = "source <(alloy completion bash)";
127
+ let rcFile = null;
128
+ if (shell.includes("zsh")) {
129
+ rcFile = join(home, ".zshrc");
130
+ completionLine = "source <(alloy completion zsh)";
131
+ }
132
+ else if (shell.includes("bash")) {
133
+ rcFile = join(home, ".bashrc");
134
+ completionLine = "source <(alloy completion bash)";
135
+ }
136
+ if (rcFile) {
137
+ let rcContent = "";
138
+ try {
139
+ rcContent = await readFile(rcFile, "utf-8");
140
+ }
141
+ catch {
142
+ // 文件不存在,稍后创建
143
+ }
144
+ if (!rcContent.includes("alloy completion")) {
145
+ const block = [
146
+ "",
147
+ "# Alloy shell 补全 — Tab 自动补全 alloy 命令",
148
+ completionLine,
149
+ "",
150
+ ].join("\n");
151
+ await writeFile(rcFile, rcContent.trimEnd() + block, "utf-8");
152
+ console.log(` ✓ shell 补全已注册 → ${rcFile}`);
153
+ }
154
+ else {
155
+ console.log(" ✓ shell 补全已存在,跳过");
156
+ }
157
+ }
158
+ else {
159
+ console.log(" ⚠ 未检测到 bash/zsh,跳过补全注册");
160
+ }
161
+ }
162
+ catch {
163
+ // 注册失败不阻断 init,静默忽略
164
+ }
165
+ console.log("\n ✅ Alloy 就绪!");
166
+ console.log(" 在 Claude Code 中输入 /alloy:start <topic> 开始工作\n");
167
+ }
168
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function archiveCommand(args: string[]): Promise<void>;
@@ -0,0 +1,91 @@
1
+ // src/cli/commands/internal/archive.ts
2
+ import { join } from "node:path";
3
+ import { readFile, access } from "node:fs/promises";
4
+ import { execSync } from "node:child_process";
5
+ import { readState, writeState } from "../../utils/state.js";
6
+ const FAIL_MARKER = "- [x] ❌ FAIL";
7
+ function isCommandNotFound(err) {
8
+ const msg = err?.stderr?.toString() || err?.message || "";
9
+ return /command not found|not recognized|no such file/i.test(msg);
10
+ }
11
+ export async function archiveCommand(args) {
12
+ const projectDir = args[0];
13
+ const changeName = args[1];
14
+ const dryRun = args.includes("--dry-run");
15
+ if (!projectDir || !changeName) {
16
+ console.error("用法: alloy _archive <project-dir> <change-name> [--dry-run]");
17
+ process.exit(1);
18
+ }
19
+ const changeDir = join(projectDir, "openspec", "changes", changeName);
20
+ // 1. 验证 phase = applied
21
+ const state = await readState(changeDir);
22
+ if (state.phase !== "applied") {
23
+ console.error(`[HARD STOP] phase 必须为 applied,当前为 ${state.phase}`);
24
+ process.exit(1);
25
+ }
26
+ // 2. 验证 verify.md 存在且 Overall Decision 不是 FAIL
27
+ let verifyContent;
28
+ try {
29
+ await access(join(changeDir, "verify.md"));
30
+ verifyContent = await readFile(join(changeDir, "verify.md"), "utf-8");
31
+ }
32
+ catch (e) {
33
+ if (e.code === "ENOENT") {
34
+ console.error("[HARD STOP] verify.md 不存在,无法归档。请先运行 /alloy:apply 完成执行阶段。");
35
+ process.exit(1);
36
+ }
37
+ console.error(`[HARD STOP] 无法读取 verify.md: ${e.message}`);
38
+ process.exit(1);
39
+ }
40
+ if (verifyContent.includes(FAIL_MARKER)) {
41
+ console.error("[HARD STOP] verify.md Overall Decision 为 FAIL,无法归档。请先修复阻塞问题。");
42
+ process.exit(1);
43
+ }
44
+ if (dryRun) {
45
+ console.log(`[DRY RUN] 将归档 change '${changeName}' (phase=${state.phase})`);
46
+ console.log(`[DRY RUN] openspec archive -y ${changeName}`);
47
+ return;
48
+ }
49
+ // 3. 执行 openspec archive
50
+ try {
51
+ execSync(`openspec archive -y "${changeName}"`, {
52
+ stdio: "pipe",
53
+ cwd: projectDir,
54
+ });
55
+ console.log("✓ delta spec 已同步,change 已归档");
56
+ }
57
+ catch (e) {
58
+ const msg = e.stderr?.toString() || e.message || "";
59
+ if (isCommandNotFound(e)) {
60
+ // openspec CLI 不可用:警告但不阻断(skill 层已验证过,这里做兜底)
61
+ console.log(`⚠️ openspec CLI 不可用,跳过 delta spec 同步(错误: ${msg.trim()})`);
62
+ }
63
+ else {
64
+ // 实际归档操作失败:HARD STOP,不推进 phase
65
+ console.error(`[HARD STOP] openspec archive 失败: ${msg.trim()}`);
66
+ process.exit(1);
67
+ }
68
+ }
69
+ // 4. 更新 phase → archived
70
+ state.phase = "archived";
71
+ await writeState(changeDir, state);
72
+ console.log("✓ phase → archived");
73
+ // 5. 提交归档变更
74
+ try {
75
+ execSync("git diff --quiet && git diff --cached --quiet", {
76
+ stdio: "pipe",
77
+ cwd: projectDir,
78
+ });
79
+ console.log("⚠️ 没有需要提交的变更");
80
+ }
81
+ catch {
82
+ try {
83
+ execSync("git add openspec/specs/ openspec/changes/archive/ 2>/dev/null; " +
84
+ `git commit -m "chore(${changeName}): Delta Spec 已同步并归档" 2>/dev/null`, { stdio: "pipe", cwd: projectDir });
85
+ }
86
+ catch {
87
+ console.log("⚠️ git commit 失败(可能不是 git 仓库)");
88
+ }
89
+ }
90
+ }
91
+ //# sourceMappingURL=archive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../../../src/cli/commands/internal/archive.ts"],"names":[],"mappings":"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"}