@fitlab-ai/agent-infra 0.5.6 → 0.5.8
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 +92 -4
- package/README.zh-CN.md +92 -4
- package/bin/cli.js +28 -4
- package/lib/defaults.json +5 -2
- package/lib/init.js +86 -5
- package/lib/prompt.js +28 -1
- package/lib/render.js +1 -1
- package/lib/sandbox/commands/rm.js +6 -4
- package/lib/sandbox/commands/vm.js +43 -16
- package/lib/sandbox/config.js +5 -0
- package/lib/sandbox/engine.js +144 -16
- package/lib/sandbox/shell.js +36 -2
- package/lib/sandbox/task-resolver.js +13 -6
- package/lib/update.js +14 -3
- package/package.json +5 -5
- package/templates/.agents/QUICKSTART.en.md +19 -2
- package/templates/.agents/QUICKSTART.zh-CN.md +19 -2
- package/templates/.agents/README.en.md +71 -2
- package/templates/.agents/README.zh-CN.md +71 -2
- package/templates/.agents/rules/issue-pr-commands.en.md +5 -0
- package/templates/.agents/rules/issue-pr-commands.github.en.md +60 -0
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +60 -0
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +5 -0
- package/templates/.agents/rules/issue-sync.en.md +19 -0
- package/templates/.agents/rules/issue-sync.github.en.md +14 -0
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +14 -0
- package/templates/.agents/rules/issue-sync.zh-CN.md +19 -0
- package/templates/.agents/rules/label-milestone-setup.en.md +5 -0
- package/templates/.agents/rules/label-milestone-setup.github.en.md +10 -0
- package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +10 -0
- package/templates/.agents/rules/label-milestone-setup.zh-CN.md +5 -0
- package/templates/.agents/rules/milestone-inference.en.md +5 -0
- package/templates/.agents/rules/milestone-inference.zh-CN.md +5 -0
- package/templates/.agents/rules/pr-sync.en.md +5 -0
- package/templates/.agents/rules/pr-sync.zh-CN.md +5 -0
- package/templates/.agents/rules/release-commands.en.md +5 -0
- package/templates/.agents/rules/release-commands.github.en.md +16 -0
- package/templates/.agents/rules/release-commands.github.zh-CN.md +16 -0
- package/templates/.agents/rules/release-commands.zh-CN.md +5 -0
- package/templates/.agents/rules/security-alerts.en.md +5 -0
- package/templates/.agents/rules/security-alerts.zh-CN.md +5 -0
- package/templates/.agents/scripts/platform-adapters/find-existing-task.github.js +272 -0
- package/templates/.agents/scripts/platform-adapters/find-existing-task.js +5 -0
- package/templates/.agents/scripts/platform-adapters/platform-sync.github.js +88 -8
- package/templates/.agents/scripts/platform-adapters/platform-sync.js +13 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +5 -5
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/analyze-task/config/verify.json +3 -1
- package/templates/.agents/skills/block-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/block-task/config/verify.json +2 -1
- package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/cancel-task/config/verify.json +2 -1
- package/templates/.agents/skills/check-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/close-codescan/SKILL.en.md +3 -3
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +1 -1
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/SKILL.en.md +2 -2
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/commit/config/verify.json +2 -1
- package/templates/.agents/skills/complete-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-task/config/verify.json +2 -1
- package/templates/.agents/skills/create-issue/SKILL.en.md +10 -10
- package/templates/.agents/skills/create-issue/SKILL.zh-CN.md +10 -10
- package/templates/.agents/skills/create-issue/config/verify.json +2 -1
- package/templates/.agents/skills/create-issue/reference/label-and-type.en.md +3 -3
- package/templates/.agents/skills/create-issue/reference/label-and-type.zh-CN.md +3 -3
- package/templates/.agents/skills/create-issue/reference/template-matching.en.md +6 -34
- package/templates/.agents/skills/create-issue/reference/template-matching.zh-CN.md +8 -36
- package/templates/.agents/skills/create-pr/SKILL.en.md +3 -3
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/create-pr/config/verify.json +2 -1
- package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +7 -17
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +27 -37
- package/templates/.agents/skills/create-release-note/SKILL.en.md +16 -9
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +16 -9
- package/templates/.agents/skills/create-task/SKILL.en.md +5 -5
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/implement-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/implement-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/implement-task/config/verify.json +3 -1
- package/templates/.agents/skills/import-codescan/SKILL.en.md +3 -3
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +2 -2
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/import-issue/SKILL.en.md +41 -11
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +41 -11
- package/templates/.agents/skills/init-labels/SKILL.en.md +10 -10
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +10 -10
- package/templates/.agents/skills/init-labels/scripts/init-labels.sh +6 -0
- package/templates/.agents/skills/init-milestones/SKILL.en.md +8 -8
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +8 -8
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +6 -0
- package/templates/.agents/skills/plan-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/plan-task/config/verify.json +3 -1
- package/templates/.agents/skills/post-release/SKILL.en.md +95 -0
- package/templates/.agents/skills/post-release/SKILL.zh-CN.md +95 -0
- package/templates/.agents/skills/refine-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/refine-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/refine-task/config/verify.json +3 -1
- package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
- package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/release/SKILL.en.md +6 -1
- package/templates/.agents/skills/release/SKILL.zh-CN.md +6 -1
- package/templates/.agents/skills/release/scripts/manage-milestones.sh +6 -0
- package/templates/.agents/skills/restore-task/SKILL.en.md +13 -64
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +13 -64
- package/templates/.agents/skills/review-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/review-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/review-task/config/verify.json +3 -1
- package/templates/.agents/skills/test/SKILL.en.md +1 -1
- package/templates/.agents/skills/test/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/test-integration/SKILL.en.md +1 -1
- package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +12 -2
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +6 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +344 -16
- package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +1 -1
- package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +1 -1
- package/templates/.agents/templates/task.en.md +2 -2
- package/templates/.agents/templates/task.zh-CN.md +2 -2
- package/templates/.claude/commands/create-issue.en.md +1 -1
- package/templates/.claude/commands/create-issue.zh-CN.md +1 -1
- package/templates/.claude/commands/import-issue.en.md +1 -1
- package/templates/.claude/commands/import-issue.zh-CN.md +1 -1
- package/templates/.claude/commands/init-labels.en.md +1 -1
- package/templates/.claude/commands/init-labels.zh-CN.md +1 -1
- package/templates/.claude/commands/init-milestones.en.md +1 -1
- package/templates/.claude/commands/init-milestones.zh-CN.md +1 -1
- package/templates/.claude/commands/post-release.en.md +8 -0
- package/templates/.claude/commands/post-release.zh-CN.md +8 -0
- package/templates/.claude/commands/restore-task.en.md +1 -1
- package/templates/.claude/commands/restore-task.zh-CN.md +1 -1
- package/templates/.claude/hooks/check-version-format.sh +1 -1
- package/templates/.gemini/commands/_project_/create-issue.en.toml +1 -1
- package/templates/.gemini/commands/_project_/create-issue.zh-CN.toml +1 -1
- package/templates/.gemini/commands/_project_/import-issue.en.toml +1 -1
- package/templates/.gemini/commands/_project_/import-issue.zh-CN.toml +1 -1
- package/templates/.gemini/commands/_project_/init-labels.en.toml +2 -2
- package/templates/.gemini/commands/_project_/init-labels.zh-CN.toml +2 -2
- package/templates/.gemini/commands/_project_/init-milestones.en.toml +2 -2
- package/templates/.gemini/commands/_project_/init-milestones.zh-CN.toml +2 -2
- package/templates/.gemini/commands/_project_/post-release.en.toml +6 -0
- package/templates/.gemini/commands/_project_/post-release.zh-CN.toml +6 -0
- package/templates/.gemini/commands/_project_/restore-task.en.toml +1 -1
- package/templates/.gemini/commands/_project_/restore-task.zh-CN.toml +1 -1
- package/templates/{.github/hooks → .git-hooks}/check-version-format.sh +2 -2
- package/templates/.github/workflows/pr-label.yml +1 -1
- package/templates/.opencode/commands/create-issue.en.md +1 -1
- package/templates/.opencode/commands/create-issue.zh-CN.md +1 -1
- package/templates/.opencode/commands/import-issue.en.md +1 -1
- package/templates/.opencode/commands/import-issue.zh-CN.md +1 -1
- package/templates/.opencode/commands/init-labels.en.md +1 -1
- package/templates/.opencode/commands/init-labels.zh-CN.md +1 -1
- package/templates/.opencode/commands/init-milestones.en.md +1 -1
- package/templates/.opencode/commands/init-milestones.zh-CN.md +1 -1
- package/templates/.opencode/commands/post-release.en.md +9 -0
- package/templates/.opencode/commands/post-release.zh-CN.md +9 -0
- package/templates/.opencode/commands/restore-task.en.md +1 -1
- package/templates/.opencode/commands/restore-task.zh-CN.md +1 -1
- /package/templates/{.github/hooks → .git-hooks}/pre-commit +0 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
|
|
4
|
+
const markerPattern = /^<!-- sync-issue:(TASK-\d{8}-\d{6}):([a-z][a-z0-9-]*) -->$/;
|
|
5
|
+
|
|
6
|
+
function parseArgs(argv) {
|
|
7
|
+
const args = {
|
|
8
|
+
format: "json"
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
12
|
+
const arg = argv[index];
|
|
13
|
+
if (arg === "--issue") {
|
|
14
|
+
args.issue = argv[index + 1];
|
|
15
|
+
index += 1;
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (arg === "--repo") {
|
|
19
|
+
args.repo = argv[index + 1];
|
|
20
|
+
index += 1;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (arg === "--format") {
|
|
24
|
+
args.format = argv[index + 1];
|
|
25
|
+
index += 1;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (arg === "-h" || arg === "--help") {
|
|
29
|
+
args.help = true;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
throw new Error(`Unknown argument: ${arg}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return args;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function usage() {
|
|
39
|
+
return [
|
|
40
|
+
"Usage:",
|
|
41
|
+
" node .agents/scripts/platform-adapters/find-existing-task.js --issue <number> [--repo <owner/name>] [--format json]"
|
|
42
|
+
].join("\n");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function runGh(args) {
|
|
46
|
+
const ghBin = process.env.IMPORT_ISSUE_GH_BIN || "gh";
|
|
47
|
+
const result = spawnSync(ghBin, args, {
|
|
48
|
+
encoding: "utf8",
|
|
49
|
+
maxBuffer: 10 * 1024 * 1024
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (result.error) {
|
|
53
|
+
const error = new Error(`gh command failed: ${result.error.message}`);
|
|
54
|
+
error.stderr = result.error.message;
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (result.status !== 0) {
|
|
59
|
+
const stderr = result.stderr.trim() || `gh exited with status ${result.status}`;
|
|
60
|
+
const error = new Error(stderr);
|
|
61
|
+
error.stderr = stderr;
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return result.stdout;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function resolveRepo(explicitRepo) {
|
|
69
|
+
if (explicitRepo) {
|
|
70
|
+
return explicitRepo;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const currentRepo = runGh(["repo", "view", "--json", "nameWithOwner", "-q", ".nameWithOwner"]).trim();
|
|
74
|
+
if (!currentRepo) {
|
|
75
|
+
throw new Error("Cannot detect current GitHub repository");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const upstreamRepo = runGh([
|
|
79
|
+
"api",
|
|
80
|
+
`repos/${currentRepo}`,
|
|
81
|
+
"--jq",
|
|
82
|
+
"if .fork then .parent.full_name else .full_name end"
|
|
83
|
+
]).trim();
|
|
84
|
+
|
|
85
|
+
return upstreamRepo || currentRepo;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function parseComments(output) {
|
|
89
|
+
const trimmed = output.trim();
|
|
90
|
+
if (!trimmed) {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const parsed = JSON.parse(trimmed);
|
|
96
|
+
return Array.isArray(parsed) ? parsed : [parsed];
|
|
97
|
+
} catch {
|
|
98
|
+
return trimmed
|
|
99
|
+
.split(/\r?\n/)
|
|
100
|
+
.filter(Boolean)
|
|
101
|
+
.map((line) => JSON.parse(line));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function fetchComments(repo, issueNumber) {
|
|
106
|
+
const output = runGh([
|
|
107
|
+
"api",
|
|
108
|
+
`repos/${repo}/issues/${issueNumber}/comments`,
|
|
109
|
+
"--paginate",
|
|
110
|
+
"--jq",
|
|
111
|
+
".[] | @json"
|
|
112
|
+
]);
|
|
113
|
+
|
|
114
|
+
return parseComments(output);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function firstLine(value) {
|
|
118
|
+
return String(value || "").split(/\r?\n/, 1)[0].trim();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function normalizeScalar(value) {
|
|
122
|
+
const trimmed = value.trim();
|
|
123
|
+
if (
|
|
124
|
+
(trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
125
|
+
(trimmed.startsWith("'") && trimmed.endsWith("'"))
|
|
126
|
+
) {
|
|
127
|
+
return trimmed.slice(1, -1);
|
|
128
|
+
}
|
|
129
|
+
return trimmed;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function parseFrontmatterBlock(block) {
|
|
133
|
+
const match = block.match(/^---\r?\n([\s\S]*?)\r?\n---\s*$/);
|
|
134
|
+
if (!match) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const metadata = {};
|
|
139
|
+
for (const rawLine of match[1].split(/\r?\n/)) {
|
|
140
|
+
const line = rawLine.trim();
|
|
141
|
+
if (!line || line.startsWith("#")) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const separatorIndex = line.indexOf(":");
|
|
146
|
+
if (separatorIndex <= 0) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const key = line.slice(0, separatorIndex).trim();
|
|
151
|
+
const value = line.slice(separatorIndex + 1).trim();
|
|
152
|
+
metadata[key] = normalizeScalar(value);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return Object.keys(metadata).length > 0 ? metadata : null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function recoverTaskFrontmatter(body) {
|
|
159
|
+
const detailsStart = body.search(/<details><summary>[^<]*frontmatter[^<]*<\/summary>/i);
|
|
160
|
+
if (detailsStart < 0) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const detailsBody = body.slice(detailsStart);
|
|
165
|
+
const yamlMatch = detailsBody.match(/```yaml\s*([\s\S]*?)\s*```/i);
|
|
166
|
+
if (!yamlMatch) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return parseFrontmatterBlock(yamlMatch[1].trim());
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function collectCandidates(comments) {
|
|
174
|
+
const byTaskId = new Map();
|
|
175
|
+
|
|
176
|
+
for (const comment of comments) {
|
|
177
|
+
const match = firstLine(comment.body).match(markerPattern);
|
|
178
|
+
if (!match) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const [, taskId, fileStem] = match;
|
|
183
|
+
const existing = byTaskId.get(taskId) || {
|
|
184
|
+
task_id: taskId,
|
|
185
|
+
first_seen_at: comment.created_at || "",
|
|
186
|
+
has_task_comment: false,
|
|
187
|
+
task_comment_body: ""
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
if (!existing.first_seen_at || (comment.created_at && comment.created_at < existing.first_seen_at)) {
|
|
191
|
+
existing.first_seen_at = comment.created_at;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (fileStem === "task") {
|
|
195
|
+
existing.has_task_comment = true;
|
|
196
|
+
existing.task_comment_body = comment.body || "";
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
byTaskId.set(taskId, existing);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return [...byTaskId.values()].sort((left, right) => {
|
|
203
|
+
const createdComparison = String(left.first_seen_at || "").localeCompare(String(right.first_seen_at || ""));
|
|
204
|
+
if (createdComparison !== 0) {
|
|
205
|
+
return createdComparison;
|
|
206
|
+
}
|
|
207
|
+
return left.task_id.localeCompare(right.task_id);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function buildResult(comments) {
|
|
212
|
+
const candidates = collectCandidates(comments);
|
|
213
|
+
if (candidates.length === 0) {
|
|
214
|
+
return { found: false };
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const selectedCandidate = candidates[0];
|
|
218
|
+
const frontmatter = selectedCandidate.has_task_comment
|
|
219
|
+
? recoverTaskFrontmatter(selectedCandidate.task_comment_body)
|
|
220
|
+
: null;
|
|
221
|
+
|
|
222
|
+
const result = {
|
|
223
|
+
found: true,
|
|
224
|
+
task_id: selectedCandidate.task_id
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
if (frontmatter) {
|
|
228
|
+
result.frontmatter = frontmatter;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function main() {
|
|
235
|
+
let args;
|
|
236
|
+
try {
|
|
237
|
+
args = parseArgs(process.argv.slice(2));
|
|
238
|
+
} catch (error) {
|
|
239
|
+
console.error(error.message);
|
|
240
|
+
console.error(usage());
|
|
241
|
+
process.exit(1);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (args.help) {
|
|
245
|
+
console.log(usage());
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (!args.issue) {
|
|
250
|
+
console.error("Missing required argument: --issue");
|
|
251
|
+
console.error(usage());
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (args.format !== "json") {
|
|
256
|
+
console.error(`Unsupported format: ${args.format}`);
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
try {
|
|
261
|
+
const repo = resolveRepo(args.repo);
|
|
262
|
+
const comments = fetchComments(repo, args.issue);
|
|
263
|
+
console.log(JSON.stringify(buildResult(comments), null, 2));
|
|
264
|
+
} catch (error) {
|
|
265
|
+
console.error(`Cannot scan issue comments: ${error.stderr || error.message}`);
|
|
266
|
+
process.exit(2);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
271
|
+
main();
|
|
272
|
+
}
|
|
@@ -9,6 +9,26 @@ const DEFAULT_RETRY_DELAYS_MS = [3000, 10000];
|
|
|
9
9
|
let activeShared = null;
|
|
10
10
|
let repoRoot = "";
|
|
11
11
|
|
|
12
|
+
export function getDefaults() {
|
|
13
|
+
return {
|
|
14
|
+
statusLabels: {
|
|
15
|
+
pendingDesignWork: "status: pending-design-work",
|
|
16
|
+
inProgress: "status: in-progress",
|
|
17
|
+
blocked: "status: blocked",
|
|
18
|
+
completed: "status: completed",
|
|
19
|
+
waitingForTriage: "status: waiting-for-triage"
|
|
20
|
+
},
|
|
21
|
+
markers: {
|
|
22
|
+
task: "<!-- sync-issue:{task-id}:task -->",
|
|
23
|
+
artifact: "<!-- sync-issue:{task-id}:{artifact-stem} -->",
|
|
24
|
+
artifactChunk: "<!-- sync-issue:{task-id}:{artifact-stem}:{part}/{total} -->",
|
|
25
|
+
summary: "<!-- sync-issue:{task-id}:summary -->",
|
|
26
|
+
cancel: "<!-- sync-issue:{task-id}:cancel -->",
|
|
27
|
+
prSummary: "<!-- sync-pr:{task-id}:summary -->"
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
12
32
|
function getShared() {
|
|
13
33
|
if (!activeShared) {
|
|
14
34
|
throw new Error("platform-sync adapter shared utilities are unavailable");
|
|
@@ -124,12 +144,16 @@ function buildSyncContext({ taskDir, config, artifactFile }) {
|
|
|
124
144
|
return { earlyReturn: blockedResult(CHECK_TYPE, upstreamRepo.message, "network_error") };
|
|
125
145
|
}
|
|
126
146
|
const permissions = detectPermissions(upstreamRepo.value, taskDir);
|
|
147
|
+
const expectedValues = resolveExpectedValues(config);
|
|
148
|
+
if (!expectedValues.ok) {
|
|
149
|
+
return { earlyReturn: failResult(CHECK_TYPE, expectedValues.message, "check_failed") };
|
|
150
|
+
}
|
|
127
151
|
|
|
128
|
-
const marker =
|
|
129
|
-
? interpolate(
|
|
152
|
+
const marker = expectedValues.commentMarker
|
|
153
|
+
? interpolate(expectedValues.commentMarker, taskDir, artifactFile)
|
|
130
154
|
: null;
|
|
131
|
-
const prMarker =
|
|
132
|
-
? interpolate(
|
|
155
|
+
const prMarker = expectedValues.prCommentMarker
|
|
156
|
+
? interpolate(expectedValues.prCommentMarker, taskDir, artifactFile)
|
|
133
157
|
: null;
|
|
134
158
|
const artifactPath = artifactFile ? path.join(taskDir, artifactFile) : null;
|
|
135
159
|
|
|
@@ -144,11 +168,65 @@ function buildSyncContext({ taskDir, config, artifactFile }) {
|
|
|
144
168
|
upstreamRepo: upstreamRepo.value,
|
|
145
169
|
hasTriage: permissions.hasTriage,
|
|
146
170
|
hasPush: permissions.hasPush,
|
|
171
|
+
expectedStatusLabel: expectedValues.statusLabel,
|
|
147
172
|
marker,
|
|
148
173
|
prMarker
|
|
149
174
|
};
|
|
150
175
|
}
|
|
151
176
|
|
|
177
|
+
function resolveExpectedValues(config) {
|
|
178
|
+
const defaults = getDefaults();
|
|
179
|
+
const statusLabel = resolveDefaultValue({
|
|
180
|
+
collection: defaults.statusLabels,
|
|
181
|
+
key: config.expected_status_label_key,
|
|
182
|
+
value: config.expected_status_label,
|
|
183
|
+
configKey: "expected_status_label_key"
|
|
184
|
+
});
|
|
185
|
+
if (!statusLabel.ok) {
|
|
186
|
+
return statusLabel;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const commentMarker = resolveDefaultValue({
|
|
190
|
+
collection: defaults.markers,
|
|
191
|
+
key: config.expected_comment_marker_key,
|
|
192
|
+
value: config.expected_comment_marker,
|
|
193
|
+
configKey: "expected_comment_marker_key"
|
|
194
|
+
});
|
|
195
|
+
if (!commentMarker.ok) {
|
|
196
|
+
return commentMarker;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const prCommentMarker = resolveDefaultValue({
|
|
200
|
+
collection: defaults.markers,
|
|
201
|
+
key: config.expected_pr_comment_marker_key,
|
|
202
|
+
value: config.expected_pr_comment_marker,
|
|
203
|
+
configKey: "expected_pr_comment_marker_key"
|
|
204
|
+
});
|
|
205
|
+
if (!prCommentMarker.ok) {
|
|
206
|
+
return prCommentMarker;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
ok: true,
|
|
211
|
+
statusLabel: statusLabel.value,
|
|
212
|
+
commentMarker: commentMarker.value,
|
|
213
|
+
prCommentMarker: prCommentMarker.value
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function resolveDefaultValue({ collection, key, value, configKey }) {
|
|
218
|
+
if (!key) {
|
|
219
|
+
return { ok: true, value: value || null };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const resolvedValue = collection[key];
|
|
223
|
+
if (!resolvedValue) {
|
|
224
|
+
return { ok: false, message: `Unknown ${configKey}: ${key}` };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return { ok: true, value: resolvedValue };
|
|
228
|
+
}
|
|
229
|
+
|
|
152
230
|
function fetchRemoteData(context) {
|
|
153
231
|
let issueResult = withRetry(() => ghJson([
|
|
154
232
|
"issue",
|
|
@@ -209,7 +287,7 @@ function fetchRemoteData(context) {
|
|
|
209
287
|
}
|
|
210
288
|
|
|
211
289
|
let prComments = null;
|
|
212
|
-
if (context.
|
|
290
|
+
if (context.prMarker) {
|
|
213
291
|
if (!context.prNumber) {
|
|
214
292
|
return {
|
|
215
293
|
earlyReturn: failResult(CHECK_TYPE, "Expected a valid pr_number for PR comment verification", "check_failed")
|
|
@@ -323,7 +401,9 @@ function mapTaskTypeToLabel(taskType) {
|
|
|
323
401
|
function shouldFetchComments(config) {
|
|
324
402
|
return Boolean(
|
|
325
403
|
config.expected_comment_marker
|
|
404
|
+
|| config.expected_comment_marker_key
|
|
326
405
|
|| config.expected_pr_comment_marker
|
|
406
|
+
|| config.expected_pr_comment_marker_key
|
|
327
407
|
|| config.verify_pr_comment_last_commit_matches_head
|
|
328
408
|
|| config.verify_comment_content
|
|
329
409
|
|| config.verify_task_comment_content
|
|
@@ -339,7 +419,7 @@ function flattenComments(value) {
|
|
|
339
419
|
}
|
|
340
420
|
|
|
341
421
|
function checkStatusLabel(context, remoteData) {
|
|
342
|
-
if (!context.
|
|
422
|
+
if (!context.expectedStatusLabel || !context.hasTriage) {
|
|
343
423
|
return null;
|
|
344
424
|
}
|
|
345
425
|
|
|
@@ -348,12 +428,12 @@ function checkStatusLabel(context, remoteData) {
|
|
|
348
428
|
}
|
|
349
429
|
|
|
350
430
|
const labels = extractLabelNames(remoteData.issue.labels);
|
|
351
|
-
if (labels.includes(context.
|
|
431
|
+
if (labels.includes(context.expectedStatusLabel)) {
|
|
352
432
|
return null;
|
|
353
433
|
}
|
|
354
434
|
|
|
355
435
|
return failResult(CHECK_TYPE,
|
|
356
|
-
`Expected label '${context.
|
|
436
|
+
`Expected label '${context.expectedStatusLabel}' not found on Issue #${context.issueNumber}`,
|
|
357
437
|
"check_failed"
|
|
358
438
|
);
|
|
359
439
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function getDefaults() {
|
|
2
|
+
return {
|
|
3
|
+
statusLabels: {},
|
|
4
|
+
markers: {}
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function check(_context, shared) {
|
|
9
|
+
return shared.passResult(
|
|
10
|
+
"platform-sync",
|
|
11
|
+
"Skipped: this code platform does not provide a built-in platform-sync adapter"
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -41,7 +41,7 @@ Read `task.md` carefully to understand:
|
|
|
41
41
|
- currently known affected files and constraints
|
|
42
42
|
|
|
43
43
|
If `task.md` contains these source fields, also read the corresponding source information:
|
|
44
|
-
- `issue_number` -
|
|
44
|
+
- `issue_number` - Issue
|
|
45
45
|
- `codescan_alert_number` - Code Scanning alert
|
|
46
46
|
- `security_alert_number` - Dependabot alert
|
|
47
47
|
|
|
@@ -70,7 +70,7 @@ Create `.agents/workspace/active/{task-id}/{analysis-artifact}`.
|
|
|
70
70
|
|
|
71
71
|
## Requirement Source
|
|
72
72
|
|
|
73
|
-
**Source type**: {User description /
|
|
73
|
+
**Source type**: {User description / Issue / Code Scanning / Dependabot / Other}
|
|
74
74
|
**Source summary**:
|
|
75
75
|
> {Task source or key context}
|
|
76
76
|
|
|
@@ -121,7 +121,7 @@ Update `.agents/workspace/active/{task-id}/task.md`:
|
|
|
121
121
|
If task.md contains a valid `issue_number`, perform these sync actions (skip and continue on any failure):
|
|
122
122
|
- Read `.agents/rules/issue-sync.md` before syncing, and complete upstream repository detection plus permission detection
|
|
123
123
|
- Set `status: pending-design-work` by following issue-sync.md
|
|
124
|
-
- Create or update the
|
|
124
|
+
- Create or update the task comment marker defined in `.agents/rules/issue-sync.md` (follow the task.md comment sync rule in issue-sync.md)
|
|
125
125
|
- Publish the `{analysis-artifact}` comment
|
|
126
126
|
|
|
127
127
|
### 7. Verification Gate
|
|
@@ -143,7 +143,7 @@ Keep the gate output in your reply as fresh evidence. Do not claim completion wi
|
|
|
143
143
|
|
|
144
144
|
> Execute this step only after the verification gate passes.
|
|
145
145
|
|
|
146
|
-
> **IMPORTANT**: All TUI command formats listed below must be output in full. Do not show only the format for the current AI agent.
|
|
146
|
+
> **IMPORTANT**: All TUI command formats listed below must be output in full. Do not show only the format for the current AI agent. If `.agents/.airc.json` configures custom TUIs (via `customTUIs`), read each tool's `name` and `invoke`, then add the matching command line in the same format (`${skillName}` becomes the skill name and `${projectName}` becomes the project name).
|
|
147
147
|
|
|
148
148
|
Output format:
|
|
149
149
|
```
|
|
@@ -172,7 +172,7 @@ Next step - create technical plan:
|
|
|
172
172
|
- [ ] Updated `assigned_to` in task.md
|
|
173
173
|
- [ ] Appended an Activity Log entry to task.md
|
|
174
174
|
- [ ] Marked requirement-analysis as complete in workflow progress
|
|
175
|
-
- [ ] Informed the user of the next step (must include all TUI command formats; do not filter)
|
|
175
|
+
- [ ] Informed the user of the next step (must include all TUI command formats, including any custom TUIs; do not filter)
|
|
176
176
|
- [ ] **Did not modify any business code**
|
|
177
177
|
|
|
178
178
|
## STOP
|
|
@@ -41,7 +41,7 @@ description: "分析任务并输出需求分析文档"
|
|
|
41
41
|
- 当前已知的受影响文件和约束
|
|
42
42
|
|
|
43
43
|
如 `task.md` 包含以下来源字段,补充读取对应来源信息:
|
|
44
|
-
- `issue_number` -
|
|
44
|
+
- `issue_number` - Issue
|
|
45
45
|
- `codescan_alert_number` - Code Scanning 告警
|
|
46
46
|
- `security_alert_number` - Dependabot 告警
|
|
47
47
|
|
|
@@ -70,7 +70,7 @@ description: "分析任务并输出需求分析文档"
|
|
|
70
70
|
|
|
71
71
|
## 需求来源
|
|
72
72
|
|
|
73
|
-
**来源类型**:{用户描述 /
|
|
73
|
+
**来源类型**:{用户描述 / Issue / Code Scanning / Dependabot / 其他}
|
|
74
74
|
**来源摘要**:
|
|
75
75
|
> {任务来源或关键上下文}
|
|
76
76
|
|
|
@@ -121,7 +121,7 @@ date "+%Y-%m-%d %H:%M:%S%:z"
|
|
|
121
121
|
如果 task.md 中存在有效的 `issue_number`,执行以下同步操作(任一失败则跳过并继续):
|
|
122
122
|
- 执行前先读取 `.agents/rules/issue-sync.md`,完成 upstream 仓库检测和权限检测
|
|
123
123
|
- 按 issue-sync.md 设置 `status: pending-design-work`
|
|
124
|
-
- 创建或更新
|
|
124
|
+
- 创建或更新 `.agents/rules/issue-sync.md` 中定义的 task 评论标记(按 issue-sync.md 的 task.md 评论同步规则)
|
|
125
125
|
- 发布 `{analysis-artifact}` 评论
|
|
126
126
|
|
|
127
127
|
### 7. 完成校验
|
|
@@ -143,7 +143,7 @@ node .agents/scripts/validate-artifact.js gate analyze-task .agents/workspace/ac
|
|
|
143
143
|
|
|
144
144
|
> 仅在校验通过后执行本步骤。
|
|
145
145
|
|
|
146
|
-
> **重要**:以下「下一步」中列出的所有 TUI 命令格式必须完整输出,不要只展示当前 AI
|
|
146
|
+
> **重要**:以下「下一步」中列出的所有 TUI 命令格式必须完整输出,不要只展示当前 AI 代理对应的格式。如果 `.agents/.airc.json` 中配置了自定义 TUI(`customTUIs`),读取每个工具的 `name` 和 `invoke`,按同样格式补充对应命令行(`${skillName}` 替换为技能名,`${projectName}` 替换为项目名)。
|
|
147
147
|
|
|
148
148
|
输出格式:
|
|
149
149
|
```
|
|
@@ -172,7 +172,7 @@ node .agents/scripts/validate-artifact.js gate analyze-task .agents/workspace/ac
|
|
|
172
172
|
- [ ] 更新了 task.md 中的 `assigned_to`
|
|
173
173
|
- [ ] 追加了 Activity Log 条目到 task.md
|
|
174
174
|
- [ ] 在工作流进度中标记了 requirement-analysis 为已完成
|
|
175
|
-
- [ ] 告知了用户下一步(必须展示所有 TUI
|
|
175
|
+
- [ ] 告知了用户下一步(必须展示所有 TUI 的命令格式,含自定义 TUI,不要筛选)
|
|
176
176
|
- [ ] **没有修改任何业务代码**
|
|
177
177
|
|
|
178
178
|
## 停止
|
|
@@ -37,7 +37,9 @@
|
|
|
37
37
|
"verify_comment_content": true,
|
|
38
38
|
"verify_task_comment_content": true,
|
|
39
39
|
"verify_issue_type": true,
|
|
40
|
-
"verify_milestone": true
|
|
40
|
+
"verify_milestone": true,
|
|
41
|
+
"expected_status_label_key": "pendingDesignWork",
|
|
42
|
+
"expected_comment_marker_key": "artifact"
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
}
|
|
@@ -93,7 +93,7 @@ Keep the gate output in your reply as fresh evidence. Do not claim completion wi
|
|
|
93
93
|
|
|
94
94
|
> Execute this step only after the verification gate passes.
|
|
95
95
|
|
|
96
|
-
> **IMPORTANT**: All TUI command formats listed below must be output in full. Do not show only the format for the current AI agent.
|
|
96
|
+
> **IMPORTANT**: All TUI command formats listed below must be output in full. Do not show only the format for the current AI agent. If `.agents/.airc.json` configures custom TUIs (via `customTUIs`), read each tool's `name` and `invoke`, then add the matching command line in the same format (`${skillName}` becomes the skill name and `${projectName}` becomes the project name).
|
|
97
97
|
|
|
98
98
|
Output format:
|
|
99
99
|
```
|
|
@@ -93,7 +93,7 @@ node .agents/scripts/validate-artifact.js gate block-task .agents/workspace/bloc
|
|
|
93
93
|
|
|
94
94
|
> 仅在校验通过后执行本步骤。
|
|
95
95
|
|
|
96
|
-
> **重要**:以下「下一步」中列出的所有 TUI 命令格式必须完整输出,不要只展示当前 AI
|
|
96
|
+
> **重要**:以下「下一步」中列出的所有 TUI 命令格式必须完整输出,不要只展示当前 AI 代理对应的格式。如果 `.agents/.airc.json` 中配置了自定义 TUI(`customTUIs`),读取每个工具的 `name` 和 `invoke`,按同样格式补充对应命令行(`${skillName}` 替换为技能名,`${projectName}` 替换为项目名)。
|
|
97
97
|
|
|
98
98
|
输出格式:
|
|
99
99
|
```
|
|
@@ -79,8 +79,8 @@ If a valid `issue_number` exists:
|
|
|
79
79
|
- Remove all `in:` labels by following issue-sync.md
|
|
80
80
|
- Remove the milestone by following issue-sync.md
|
|
81
81
|
- Remove all assignees (skip directly when permission is insufficient; no fallback)
|
|
82
|
-
- Publish a cancellation comment using the marker
|
|
83
|
-
- Create or update the
|
|
82
|
+
- Publish a cancellation comment using the cancel marker defined in `.agents/rules/issue-sync.md`
|
|
83
|
+
- Create or update the task comment marker defined in `.agents/rules/issue-sync.md` using the task-comment sync rules from `.agents/rules/issue-sync.md`
|
|
84
84
|
- Close the Issue by following the "Close an Issue" command in `.agents/rules/issue-pr-commands.md`, using the fixed reason `not planned`
|
|
85
85
|
|
|
86
86
|
The cancellation comment must include at least:
|
|
@@ -106,7 +106,7 @@ Keep the gate output in your reply as fresh evidence. Do not claim completion wi
|
|
|
106
106
|
|
|
107
107
|
> Execute this step only after the verification gate passes.
|
|
108
108
|
|
|
109
|
-
> **IMPORTANT**: All TUI command formats listed below must be output in full. Do not show only the format for the current AI agent.
|
|
109
|
+
> **IMPORTANT**: All TUI command formats listed below must be output in full. Do not show only the format for the current AI agent. If `.agents/.airc.json` configures custom TUIs (via `customTUIs`), read each tool's `name` and `invoke`, then add the matching command line in the same format (`${skillName}` becomes the skill name and `${projectName}` becomes the project name).
|
|
110
110
|
|
|
111
111
|
Output format:
|
|
112
112
|
```
|
|
@@ -79,8 +79,8 @@ ls .agents/workspace/completed/{task-id}/task.md
|
|
|
79
79
|
- 按 issue-sync.md 移除所有 `in:` labels
|
|
80
80
|
- 按 issue-sync.md 移除 milestone
|
|
81
81
|
- 移除全部 assignees(无权限时直接跳过,不做替代)
|
|
82
|
-
- 发布取消评论,隐藏标记使用
|
|
83
|
-
- 使用 `.agents/rules/issue-sync.md` 的 task.md 评论同步规则创建或更新
|
|
82
|
+
- 发布取消评论,隐藏标记使用 `.agents/rules/issue-sync.md` 中定义的 cancel 评论标记
|
|
83
|
+
- 使用 `.agents/rules/issue-sync.md` 的 task.md 评论同步规则创建或更新 `.agents/rules/issue-sync.md` 中定义的 task 评论标记
|
|
84
84
|
- 关闭 Issue:按 `.agents/rules/issue-pr-commands.md` 中的“关闭 Issue”命令执行,关闭原因固定为 `not planned`
|
|
85
85
|
|
|
86
86
|
取消评论至少包含:
|
|
@@ -106,7 +106,7 @@ node .agents/scripts/validate-artifact.js gate cancel-task .agents/workspace/com
|
|
|
106
106
|
|
|
107
107
|
> 仅在校验通过后执行本步骤。
|
|
108
108
|
|
|
109
|
-
> **重要**:以下「下一步」中列出的所有 TUI 命令格式必须完整输出,不要只展示当前 AI
|
|
109
|
+
> **重要**:以下「下一步」中列出的所有 TUI 命令格式必须完整输出,不要只展示当前 AI 代理对应的格式。如果 `.agents/.airc.json` 中配置了自定义 TUI(`customTUIs`),读取每个工具的 `name` 和 `invoke`,按同样格式补充对应命令行(`${skillName}` 替换为技能名,`${projectName}` 替换为项目名)。
|
|
110
110
|
|
|
111
111
|
输出格式:
|
|
112
112
|
```
|
|
@@ -128,7 +128,7 @@ node .agents/scripts/validate-artifact.js gate cancel-task .agents/workspace/com
|
|
|
128
128
|
- [ ] 已将任务目录移动到 `.agents/workspace/completed/`
|
|
129
129
|
- [ ] 已在存在 Issue 时完成 Issue 同步
|
|
130
130
|
- [ ] 已运行 gate 校验并通过
|
|
131
|
-
- [ ]
|
|
131
|
+
- [ ] 已向用户展示完整的下一步命令(含自定义 TUI)
|
|
132
132
|
|
|
133
133
|
## 注意事项
|
|
134
134
|
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"platform-sync": {
|
|
25
25
|
"when": "issue_number_exists",
|
|
26
26
|
"expected_comment_marker": "<!-- sync-issue:{task-id}:cancel -->",
|
|
27
|
-
"verify_task_comment_content": true
|
|
27
|
+
"verify_task_comment_content": true,
|
|
28
|
+
"expected_comment_marker_key": "cancel"
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
}
|
|
@@ -100,7 +100,7 @@ Next step:
|
|
|
100
100
|
|
|
101
101
|
### 5. Recommend Next Action
|
|
102
102
|
|
|
103
|
-
Recommend the appropriate next skill based on the current workflow state. You must show command formats for all TUI columns in the table below, not just the current AI agent.
|
|
103
|
+
Recommend the appropriate next skill based on the current workflow state. You must show command formats for all TUI columns in the table below, not just the current AI agent. If `.agents/.airc.json` configures custom TUIs (via `customTUIs`), read each tool's `name` and `invoke`, then add the matching command line in the same format (`${skillName}` becomes the skill name and `${projectName}` becomes the project name).
|
|
104
104
|
|
|
105
105
|
> **⚠️ CONDITION CHECK — you must choose the single matching row in the table below based on `status`, `current_step`, the latest artifacts, and the latest review result:**
|
|
106
106
|
>
|
|
@@ -100,7 +100,7 @@ description: "查看任务的当前状态和进度"
|
|
|
100
100
|
|
|
101
101
|
### 5. 建议下一步操作
|
|
102
102
|
|
|
103
|
-
根据当前工作流状态,建议合适的下一个技能。必须展示下表中所有 TUI 列的命令格式,不要只展示当前 AI
|
|
103
|
+
根据当前工作流状态,建议合适的下一个技能。必须展示下表中所有 TUI 列的命令格式,不要只展示当前 AI 代理对应的列。如果 `.agents/.airc.json` 中配置了自定义 TUI(`customTUIs`),读取每个工具的 `name` 和 `invoke`,按同样格式补充对应命令行(`${skillName}` 替换为技能名,`${projectName}` 替换为项目名):
|
|
104
104
|
|
|
105
105
|
> **⚠️ 条件判断 — 你必须先根据 `status`、`current_step`、最新产物和最新审查结果,选择下表中唯一匹配的一行:**
|
|
106
106
|
>
|