@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 @@
1
+ export declare function guardCommand(args: string[]): Promise<void>;
@@ -0,0 +1,135 @@
1
+ // src/cli/commands/internal/guard.ts
2
+ import { existsSync } from "node:fs";
3
+ import { createHash } from "node:crypto";
4
+ import { readFile, stat, readdir } from "node:fs/promises";
5
+ import { join, basename } from "node:path";
6
+ import { execSync } from "node:child_process";
7
+ import { readState, writeState } from "../../utils/state.js";
8
+ const VALID_TRANSITIONS = {
9
+ started: ["planned"],
10
+ planned: ["applied"],
11
+ applied: ["archived"],
12
+ archived: ["finished"],
13
+ };
14
+ const ARTIFACT_CHECKS = {
15
+ "started->planned": ["proposal.md", "design.md", "specs", "tasks.md", "plans.md"],
16
+ "planned->applied": ["plans.md"],
17
+ "applied->archived": ["verify.md"],
18
+ };
19
+ const ARTIFACT_FILES = {
20
+ draft: "draft.md",
21
+ proposal: "proposal.md",
22
+ design: "design.md",
23
+ specs: "specs",
24
+ tasks: "tasks.md",
25
+ plans: "plans.md",
26
+ verify: "verify.md",
27
+ retrospective: "retrospective.md",
28
+ };
29
+ function computeHash(content) {
30
+ return createHash("sha256").update(content).digest("hex").substring(0, 12);
31
+ }
32
+ async function computeArtifactHash(changeDir, artifactId) {
33
+ const fileName = ARTIFACT_FILES[artifactId];
34
+ if (!fileName)
35
+ return null;
36
+ const fullPath = join(changeDir, fileName);
37
+ try {
38
+ const st = await stat(fullPath);
39
+ if (st.isDirectory()) {
40
+ const entries = await readdir(fullPath, { withFileTypes: true });
41
+ const files = entries.filter(e => e.isFile()).map(e => e.name).sort();
42
+ const contents = [];
43
+ for (const f of files) {
44
+ contents.push(await readFile(join(fullPath, f)));
45
+ }
46
+ return computeHash(Buffer.concat(contents));
47
+ }
48
+ else {
49
+ const content = await readFile(fullPath);
50
+ return computeHash(content);
51
+ }
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ export async function guardCommand(args) {
58
+ const changeDir = args[0];
59
+ const targetPhase = args[1];
60
+ const apply = args.includes("--apply");
61
+ if (!changeDir || !targetPhase) {
62
+ console.error("用法: alloy _guard <change-dir> <target-phase> [--apply]");
63
+ process.exit(1);
64
+ }
65
+ const state = await readState(changeDir);
66
+ const currentPhase = state.phase;
67
+ // 1. 校验 phase 转换合法性
68
+ const allowed = VALID_TRANSITIONS[currentPhase];
69
+ if (!allowed || !allowed.includes(targetPhase)) {
70
+ console.error(`[HARD STOP] 不允许的 phase 转换: ${currentPhase} → ${targetPhase}`);
71
+ console.error(" 允许的转换: started→planned, planned→applied, applied→archived, archived→finished");
72
+ process.exit(1);
73
+ }
74
+ // 2. 制品完整性检查
75
+ const transition = `${currentPhase}->${targetPhase}`;
76
+ const checks = ARTIFACT_CHECKS[transition];
77
+ if (checks) {
78
+ const missing = [];
79
+ for (const c of checks) {
80
+ const p = join(changeDir, c);
81
+ if (!existsSync(p))
82
+ missing.push(` ${c}`);
83
+ }
84
+ if (missing.length > 0) {
85
+ console.error(`[HARD STOP] 以下制品缺失,无法进入 ${targetPhase} 阶段:`);
86
+ console.error(missing.join("\n"));
87
+ process.exit(1);
88
+ }
89
+ }
90
+ // 3. hash 一致性校验(started→planned、planned→applied、applied→archived)
91
+ if (transition === "started->planned" || transition === "planned->applied" || transition === "applied->archived") {
92
+ const records = state.records || [];
93
+ const mismatches = [];
94
+ for (const record of records) {
95
+ const currentHash = await computeArtifactHash(changeDir, record.artifact);
96
+ if (currentHash === null) {
97
+ mismatches.push(` ${record.artifact}: 文件不存在(记录 hash=${record.hash})`);
98
+ }
99
+ else if (currentHash !== record.hash) {
100
+ mismatches.push(` ${record.artifact}: 记录=${record.hash} 当前=${currentHash}`);
101
+ }
102
+ }
103
+ if (mismatches.length > 0) {
104
+ console.error(`[HARD STOP] hash 一致性校验失败:`);
105
+ console.error(mismatches.join("\n"));
106
+ process.exit(1);
107
+ }
108
+ }
109
+ // started→planned 额外检查:change 目录必须已提交
110
+ if (transition === "started->planned") {
111
+ try {
112
+ execSync("git rev-parse --git-dir", { stdio: "pipe" });
113
+ const relPath = `openspec/changes/${basename(changeDir)}`;
114
+ const status = execSync(`git status --porcelain "${relPath}"`, {
115
+ stdio: "pipe",
116
+ cwd: process.cwd(),
117
+ }).toString();
118
+ if (status.trim()) {
119
+ console.error("[HARD STOP] Change 目录有未提交的变更,请先执行 git add + git commit:");
120
+ console.error(status);
121
+ process.exit(1);
122
+ }
123
+ }
124
+ catch {
125
+ // 不在 git 仓库中,跳过 git 检查
126
+ }
127
+ }
128
+ // 4. --apply: 更新 phase
129
+ if (apply) {
130
+ state.phase = targetPhase;
131
+ await writeState(changeDir, state);
132
+ console.log(`✓ phase: ${currentPhase} → ${targetPhase}`);
133
+ }
134
+ }
135
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../../../src/cli/commands/internal/guard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function recordCommand(args: string[]): Promise<void>;
@@ -0,0 +1,144 @@
1
+ // src/cli/commands/internal/record.ts
2
+ import { createHash } from "node:crypto";
3
+ import { readFile, stat, readdir } from "node:fs/promises";
4
+ import { join } from "node:path";
5
+ import { execSync } from "node:child_process";
6
+ import { readState, writeState } from "../../utils/state.js";
7
+ function computeHash(content) {
8
+ return createHash("sha256").update(content).digest("hex").substring(0, 12);
9
+ }
10
+ const ARTIFACT_FILES = {
11
+ draft: "draft.md",
12
+ proposal: "proposal.md",
13
+ design: "design.md",
14
+ specs: "specs",
15
+ tasks: "tasks.md",
16
+ plans: "plans.md",
17
+ verify: "verify.md",
18
+ retrospective: "retrospective.md",
19
+ };
20
+ async function computeArtifactHash(changeDir, artifactId) {
21
+ const fileName = ARTIFACT_FILES[artifactId];
22
+ if (!fileName)
23
+ return null;
24
+ const fullPath = join(changeDir, fileName);
25
+ try {
26
+ const st = await stat(fullPath);
27
+ if (st.isDirectory()) {
28
+ // specs/: 收集所有文件, 排序, 拼接, hash
29
+ const entries = await readdir(fullPath, { withFileTypes: true });
30
+ const files = entries.filter(e => e.isFile()).map(e => e.name).sort();
31
+ const contents = [];
32
+ for (const f of files) {
33
+ contents.push(await readFile(join(fullPath, f)));
34
+ }
35
+ return computeHash(Buffer.concat(contents));
36
+ }
37
+ else {
38
+ const content = await readFile(fullPath);
39
+ return computeHash(content);
40
+ }
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ }
46
+ export async function recordCommand(args) {
47
+ const action = args[0]; // write | check | compute
48
+ const changeDir = args[1];
49
+ if (!action || !changeDir) {
50
+ console.error("用法: alloy _record <write|check|compute> <change-dir> [artifact] [hash] [committed_at] [approver]");
51
+ process.exit(1);
52
+ }
53
+ switch (action) {
54
+ case "write": {
55
+ const artifact = args[2];
56
+ const hash = args[3];
57
+ const approvedAt = args[4];
58
+ const approver = args[5];
59
+ if (!artifact || !hash || !approvedAt || !approver) {
60
+ console.error("用法: alloy _record write <change-dir> <artifact> <hash> <committed_at> <approver>");
61
+ process.exit(1);
62
+ }
63
+ const state = await readState(changeDir);
64
+ if (!state.records)
65
+ state.records = [];
66
+ const existing = state.records.findIndex(r => r.artifact === artifact);
67
+ const record = { artifact, hash, committed_at: approvedAt, approver };
68
+ if (existing >= 0) {
69
+ state.records[existing] = record;
70
+ }
71
+ else {
72
+ state.records.push(record);
73
+ }
74
+ await writeState(changeDir, state);
75
+ console.log(`✓ record: ${artifact} → ${hash}`);
76
+ break;
77
+ }
78
+ case "check": {
79
+ const artifact = args[2];
80
+ const state = await readState(changeDir);
81
+ if (!state.records)
82
+ state.records = [];
83
+ const targets = artifact
84
+ ? state.records.filter(r => r.artifact === artifact)
85
+ : state.records;
86
+ if (targets.length === 0) {
87
+ if (artifact) {
88
+ console.log(`[WARN] 未找到制品 '${artifact}' 的 record`);
89
+ process.exit(1);
90
+ }
91
+ console.log("[WARN] 无 records 可校验");
92
+ process.exit(0);
93
+ }
94
+ let allMatch = true;
95
+ for (const record of targets) {
96
+ const currentHash = await computeArtifactHash(changeDir, record.artifact);
97
+ if (currentHash === null) {
98
+ console.log(`[FAIL] ${record.artifact}: 文件不存在`);
99
+ allMatch = false;
100
+ }
101
+ else if (currentHash !== record.hash) {
102
+ console.log(`[FAIL] ${record.artifact}: hash 不匹配 (recorded=${record.hash}, current=${currentHash})`);
103
+ allMatch = false;
104
+ }
105
+ else {
106
+ console.log(`[PASS] ${record.artifact}: ${currentHash}`);
107
+ }
108
+ }
109
+ if (!allMatch) {
110
+ process.exit(1);
111
+ }
112
+ break;
113
+ }
114
+ case "compute": {
115
+ const artifact = args[2];
116
+ if (!artifact) {
117
+ console.error("用法: alloy _record compute <change-dir> <artifact>");
118
+ process.exit(1);
119
+ }
120
+ const hash = await computeArtifactHash(changeDir, artifact);
121
+ if (hash === null) {
122
+ console.error(`[FAIL] 无法计算 ${artifact} 的 hash`);
123
+ process.exit(1);
124
+ }
125
+ console.log(hash);
126
+ break;
127
+ }
128
+ case "approver": {
129
+ // 始终从 git config 获取当前审批人,确保审批人一致性
130
+ try {
131
+ const gitUser = execSync("git config user.name", { encoding: "utf-8" }).trim();
132
+ console.log(gitUser || "unknown");
133
+ }
134
+ catch {
135
+ console.log("unknown");
136
+ }
137
+ break;
138
+ }
139
+ default:
140
+ console.error(`未知操作: ${action} (支持: write, check, compute, approver)`);
141
+ process.exit(1);
142
+ }
143
+ }
144
+ //# sourceMappingURL=record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record.js","sourceRoot":"","sources":["../../../../src/cli/commands/internal/record.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function stateCommand(args: string[]): Promise<void>;
@@ -0,0 +1,99 @@
1
+ // src/cli/commands/internal/state.ts
2
+ import { readState, writeState, createInitialState } from "../../utils/state.js";
3
+ // shell 传入的所有值都是字符串,需根据字段类型转换
4
+ const NUMERIC_FIELDS = new Set(["schema_version"]);
5
+ function coerceValue(field, value) {
6
+ if (value === undefined)
7
+ return undefined;
8
+ if (value === "null")
9
+ return null;
10
+ if (NUMERIC_FIELDS.has(field)) {
11
+ const n = Number(value);
12
+ if (isNaN(n)) {
13
+ console.error(`字段 '${field}' 需要 number 类型,收到: ${value}`);
14
+ process.exit(1);
15
+ }
16
+ return n;
17
+ }
18
+ // 尝试解析 JSON 值(用于 phase_timings 等复杂字段)
19
+ if ((value.startsWith("{") && value.endsWith("}")) ||
20
+ (value.startsWith("[") && value.endsWith("]"))) {
21
+ try {
22
+ return JSON.parse(value);
23
+ }
24
+ catch {
25
+ // 不是有效 JSON,保持原字符串
26
+ }
27
+ }
28
+ return value;
29
+ }
30
+ export async function stateCommand(args) {
31
+ const action = args[0];
32
+ const changeDir = args[1];
33
+ const field = args[2];
34
+ const value = args[3];
35
+ if (!action || !changeDir) {
36
+ console.error("用法: alloy _state <init|read|write|check> <change-dir> [field] [value]");
37
+ process.exit(1);
38
+ }
39
+ switch (action) {
40
+ case "init": {
41
+ // 用 createInitialState() 创建完整 state——确保 records: [] 等所有字段存在
42
+ const initialState = createInitialState();
43
+ await writeState(changeDir, initialState);
44
+ console.log(`✓ state 已初始化: ${changeDir}`);
45
+ break;
46
+ }
47
+ case "read": {
48
+ if (!field) {
49
+ console.error("用法: alloy _state read <change-dir> <field>");
50
+ process.exit(1);
51
+ }
52
+ const state = await readState(changeDir);
53
+ const val = state[field];
54
+ if (val === undefined || val === null) {
55
+ console.log("null");
56
+ }
57
+ else if (Array.isArray(val) || typeof val === "object") {
58
+ console.log(JSON.stringify(val));
59
+ }
60
+ else {
61
+ console.log(String(val));
62
+ }
63
+ break;
64
+ }
65
+ case "write": {
66
+ if (!field || value === undefined) {
67
+ console.error("用法: alloy _state write <change-dir> <field> <value>");
68
+ process.exit(1);
69
+ }
70
+ // 如果文件不存在,用 createInitialState() 创建初始状态(确保 records: [] 等所有字段存在)
71
+ let state;
72
+ try {
73
+ state = await readState(changeDir);
74
+ }
75
+ catch {
76
+ state = createInitialState();
77
+ }
78
+ state[field] = coerceValue(field, value);
79
+ await writeState(changeDir, state);
80
+ break;
81
+ }
82
+ case "check": {
83
+ if (!field) {
84
+ console.error("用法: alloy _state check <change-dir> <phase>");
85
+ process.exit(1);
86
+ }
87
+ const state = await readState(changeDir);
88
+ if (state.phase !== field) {
89
+ console.log(`phase 不匹配: 当前=${state.phase}, 期望=${field}`);
90
+ process.exit(1);
91
+ }
92
+ break;
93
+ }
94
+ default:
95
+ console.error(`未知操作: ${action} (支持: init, read, write, check)`);
96
+ process.exit(1);
97
+ }
98
+ }
99
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../../src/cli/commands/internal/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function statusCommand(projectPath: string, changeName?: string): Promise<string>;
@@ -0,0 +1,112 @@
1
+ import { join } from "node:path";
2
+ import { existsSync } from "node:fs";
3
+ import { findActiveChanges, readState } from "../utils/state.js";
4
+ const ARTIFACTS = [
5
+ "draft",
6
+ "proposal",
7
+ "design",
8
+ "specs",
9
+ "tasks",
10
+ "plans",
11
+ ];
12
+ function checkArtifacts(changePath) {
13
+ const status = {};
14
+ for (const a of ARTIFACTS) {
15
+ if (a === "specs") {
16
+ status[a] = existsSync(join(changePath, "specs"));
17
+ }
18
+ else {
19
+ status[a] = existsSync(join(changePath, `${a}.md`));
20
+ }
21
+ }
22
+ return status;
23
+ }
24
+ export async function statusCommand(projectPath, changeName) {
25
+ const changesDir = join(projectPath, "openspec", "changes");
26
+ if (changeName) {
27
+ return detailMode(changesDir, changeName);
28
+ }
29
+ else {
30
+ return overviewMode(changesDir);
31
+ }
32
+ }
33
+ async function overviewMode(changesDir) {
34
+ const changes = await findActiveChanges(changesDir);
35
+ if (changes.size === 0) {
36
+ return "无活跃 change。使用 /alloy-start <topic> 开始新工作流。";
37
+ }
38
+ const lines = ["活跃 Change:"];
39
+ const nextSteps = [];
40
+ for (const [name, state] of changes) {
41
+ const artifacts = checkArtifacts(join(changesDir, name));
42
+ const artifactStatus = ARTIFACTS.map((a) => `${a} ${artifacts[a] ? "✓" : "✗"}`).join(" ");
43
+ lines.push(` ${name.padEnd(20)} ${state.phase.padEnd(10)} artifacts: ${artifactStatus}`);
44
+ const step = getNextStepSimple(state, artifacts, name);
45
+ if (step)
46
+ nextSteps.push(step);
47
+ }
48
+ if (nextSteps.length > 0) {
49
+ lines.push(`\n下一步:${nextSteps.join(";")}`);
50
+ }
51
+ return lines.join("\n");
52
+ }
53
+ async function detailMode(changesDir, name) {
54
+ const changePath = join(changesDir, name);
55
+ if (!existsSync(changePath)) {
56
+ return `未找到 change '${name}'`;
57
+ }
58
+ let state;
59
+ try {
60
+ state = await readState(changePath);
61
+ }
62
+ catch {
63
+ return `change '${name}' 缺少 .alloy.yaml`;
64
+ }
65
+ const artifacts = checkArtifacts(changePath);
66
+ const lines = [
67
+ `阶段: ${state.phase}`,
68
+ `Change: ${name}`,
69
+ `路径: ${changePath}`,
70
+ `创建时间: ${state.created_at}`,
71
+ `更新时间: ${state.updated_at}`,
72
+ "制品状态:",
73
+ ...ARTIFACTS.map((a) => ` ${a.padEnd(12)} ${artifacts[a] ? "✓" : "✗"}`),
74
+ ];
75
+ const nextStep = getNextStepDetail(state, artifacts);
76
+ if (nextStep)
77
+ lines.push(`下一步: ${nextStep}`);
78
+ return lines.join("\n");
79
+ }
80
+ function getNextStepSimple(state, artifacts, name) {
81
+ switch (state.phase) {
82
+ case "started":
83
+ return `${name} 等待 /alloy-plan`;
84
+ case "planned":
85
+ return `${name} 等待 /alloy-apply`;
86
+ case "applied":
87
+ return `${name} 等待 /alloy-archive`;
88
+ case "archived":
89
+ return `${name} 等待 /alloy-finish`;
90
+ case "finished":
91
+ return `${name} 已完成`;
92
+ default:
93
+ return "";
94
+ }
95
+ }
96
+ function getNextStepDetail(state, artifacts) {
97
+ switch (state.phase) {
98
+ case "started":
99
+ return artifacts.plans ? "等待 /alloy-apply" : "继续 /alloy-plan,等待下一个制品生成";
100
+ case "planned":
101
+ return "等待 /alloy-apply";
102
+ case "applied":
103
+ return "等待 /alloy-archive";
104
+ case "archived":
105
+ return "等待 /alloy-finish";
106
+ case "finished":
107
+ return "已完成";
108
+ default:
109
+ return "";
110
+ }
111
+ }
112
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAc,MAAM,mBAAmB,CAAC;AAE7E,MAAM,SAAS,GAAG;IAChB,OAAO;IACP,UAAU;IACV,QAAQ;IACR,OAAO;IACP,OAAO;IACP,OAAO;CACC,CAAC;AAEX,SAAS,cAAc,CAAC,UAAkB;IACxC,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;YAClB,MAAM,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,WAAmB,EACnB,UAAmB;IAEnB,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAE5D,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC5C,CAAC;SAAM,CAAC;QACN,OAAO,YAAY,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,UAAkB;IAC5C,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACpD,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,4CAA4C,CAAC;IACtD,CAAC;IAED,MAAM,KAAK,GAAa,CAAC,YAAY,CAAC,CAAC;IACvC,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;QACpC,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;QACzD,MAAM,cAAc,GAAG,SAAS,CAAC,GAAG,CAClC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAC1C,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,KAAK,CAAC,IAAI,CACR,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,eAAe,cAAc,EAAE,CAC9E,CAAC;QACF,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;QACvD,IAAI,IAAI;YAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,UAAkB,EAClB,IAAY;IAEZ,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,eAAe,IAAI,GAAG,CAAC;IAChC,CAAC;IAED,IAAI,KAAiB,CAAC;IACtB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,SAAS,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,IAAI,kBAAkB,CAAC;IAC3C,CAAC;IAED,MAAM,SAAS,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAa;QACtB,UAAU,KAAK,CAAC,KAAK,EAAE;QACvB,YAAY,IAAI,EAAE;QAClB,UAAU,UAAU,EAAE;QACtB,SAAS,KAAK,CAAC,UAAU,EAAE;QAC3B,SAAS,KAAK,CAAC,UAAU,EAAE;QAC3B,OAAO;QACP,GAAG,SAAS,CAAC,GAAG,CACd,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CACvD;KACF,CAAC;IAEF,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACrD,IAAI,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,QAAQ,EAAE,CAAC,CAAC;IAE/C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,iBAAiB,CACxB,KAAiB,EACjB,SAAkC,EAClC,IAAY;IAEZ,QAAQ,KAAK,CAAC,KAAK,EAAE,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,GAAG,IAAI,iBAAiB,CAAC;QAClC,KAAK,SAAS;YACZ,OAAO,GAAG,IAAI,kBAAkB,CAAC;QACnC,KAAK,SAAS;YACZ,OAAO,GAAG,IAAI,oBAAoB,CAAC;QACrC,KAAK,UAAU;YACb,OAAO,GAAG,IAAI,mBAAmB,CAAC;QACpC,KAAK,UAAU;YACb,OAAO,GAAG,IAAI,MAAM,CAAC;QACvB;YACE,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CACxB,KAAiB,EACjB,SAAkC;IAElC,QAAQ,KAAK,CAAC,KAAK,EAAE,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,0BAA0B,CAAC;QAC1E,KAAK,SAAS;YACZ,OAAO,iBAAiB,CAAC;QAC3B,KAAK,SAAS;YACZ,OAAO,mBAAmB,CAAC;QAC7B,KAAK,UAAU;YACb,OAAO,kBAAkB,CAAC;QAC5B,KAAK,UAAU;YACb,OAAO,KAAK,CAAC;QACf;YACE,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function updateCommand(projectPath: string): Promise<string[]>;