@fitlab-ai/agent-infra 0.7.3 → 0.7.4

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 (41) hide show
  1. package/README.md +32 -790
  2. package/README.zh-CN.md +32 -763
  3. package/bin/cli.ts +1 -1
  4. package/dist/bin/cli.js +1 -1
  5. package/dist/lib/sandbox/commands/create.js +44 -3
  6. package/dist/lib/sandbox/commands/rm.js +99 -19
  7. package/dist/lib/sandbox/index.js +3 -1
  8. package/dist/lib/sandbox/readme-scaffold.js +6 -6
  9. package/dist/lib/task/artifacts.js +58 -0
  10. package/dist/lib/task/commands/cat.js +38 -0
  11. package/dist/lib/task/commands/files.js +47 -0
  12. package/dist/lib/task/commands/grep.js +143 -0
  13. package/dist/lib/task/commands/log.js +75 -0
  14. package/dist/lib/task/commands/show.js +5 -114
  15. package/dist/lib/task/commands/status.js +239 -0
  16. package/dist/lib/task/index.js +37 -0
  17. package/dist/lib/task/resolve-ref.js +150 -0
  18. package/lib/sandbox/commands/create.ts +47 -4
  19. package/lib/sandbox/commands/rm.ts +128 -19
  20. package/lib/sandbox/index.ts +3 -1
  21. package/lib/sandbox/readme-scaffold.ts +6 -6
  22. package/lib/task/artifacts.ts +72 -0
  23. package/lib/task/commands/cat.ts +39 -0
  24. package/lib/task/commands/files.ts +53 -0
  25. package/lib/task/commands/grep.ts +147 -0
  26. package/lib/task/commands/log.ts +80 -0
  27. package/lib/task/commands/show.ts +5 -117
  28. package/lib/task/commands/status.ts +302 -0
  29. package/lib/task/index.ts +37 -0
  30. package/lib/task/resolve-ref.ts +160 -0
  31. package/package.json +1 -1
  32. package/templates/.agents/README.en.md +1 -0
  33. package/templates/.agents/README.zh-CN.md +1 -0
  34. package/templates/.agents/rules/README.en.md +41 -0
  35. package/templates/.agents/rules/README.zh-CN.md +40 -0
  36. package/templates/.agents/rules/debugging-guide.en.md +25 -0
  37. package/templates/.agents/rules/debugging-guide.zh-CN.md +25 -0
  38. package/templates/.agents/skills/code-task/SKILL.en.md +2 -0
  39. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +2 -0
  40. package/templates/.agents/skills/watch-pr/SKILL.en.md +1 -1
  41. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +1 -1
@@ -0,0 +1,160 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { execFileSync, spawnSync } from 'node:child_process';
4
+ import { normalizeShortIdInput } from './short-id.ts';
5
+
6
+ const TASK_ID_RE = /^TASK-\d{8}-\d{6}$/;
7
+ // Flat-structured workspace dirs that hold tasks under `{dir}/{taskId}/task.md`.
8
+ // Note: `archive` uses a three-level YYYY/MM/DD layout and is handled separately.
9
+ const FLAT_WORKSPACE_DIRS = ['active', 'blocked', 'completed'] as const;
10
+
11
+ type ResolveRefResult =
12
+ | {
13
+ ok: true;
14
+ repoRoot: string;
15
+ taskId: string;
16
+ taskDir: string;
17
+ taskMdPath: string;
18
+ }
19
+ | { ok: false; message: string };
20
+
21
+ function detectRepoRoot(): string {
22
+ try {
23
+ return execFileSync('git', ['rev-parse', '--show-toplevel'], {
24
+ encoding: 'utf8',
25
+ stdio: ['pipe', 'pipe', 'pipe']
26
+ }).trim();
27
+ } catch {
28
+ throw new Error('ai task: current directory is not inside a git repository');
29
+ }
30
+ }
31
+
32
+ function readShortIdLength(repoRoot: string): number {
33
+ try {
34
+ const cfg = JSON.parse(fs.readFileSync(path.join(repoRoot, '.agents', '.airc.json'), 'utf8'));
35
+ const v = cfg?.task?.shortIdLength;
36
+ if (typeof v === 'number' && Number.isFinite(v) && v >= 1) return v;
37
+ } catch {
38
+ // fall through to default
39
+ }
40
+ return 2;
41
+ }
42
+
43
+ function resolveShortIdToTaskId(arg: string, repoRoot: string): string {
44
+ const scriptPath = path.join(repoRoot, '.agents', 'scripts', 'task-short-id.js');
45
+ if (!fs.existsSync(scriptPath)) {
46
+ throw new Error(`task-short-id.js not found at ${scriptPath}`);
47
+ }
48
+ const result = spawnSync('node', [scriptPath, 'resolve', arg], {
49
+ encoding: 'utf8',
50
+ cwd: repoRoot
51
+ });
52
+ if (result.status !== 0) {
53
+ throw new Error((result.stderr || '').trim() || `failed to resolve '${arg}'`);
54
+ }
55
+ return result.stdout.trim();
56
+ }
57
+
58
+ function listSortedNumeric(dir: string, width: number): string[] {
59
+ if (!fs.existsSync(dir)) return [];
60
+ const pattern = new RegExp(`^\\d{${width}}$`);
61
+ return fs
62
+ .readdirSync(dir)
63
+ .filter((entry) => pattern.test(entry))
64
+ .sort()
65
+ .reverse();
66
+ }
67
+
68
+ function findInArchive(repoRoot: string, taskId: string): string | null {
69
+ // archive-tasks SKILL writes to .agents/workspace/archive/YYYY/MM/DD/{taskId}/task.md
70
+ // where YYYY/MM/DD comes from completed_at (or updated_at fallback) — NOT from
71
+ // the task id's creation date. So we cannot derive the path from taskId alone;
72
+ // walk the bounded YYYY/MM/DD tree instead. Newest-first to favor recent archives.
73
+ const archiveDir = path.join(repoRoot, '.agents', 'workspace', 'archive');
74
+ for (const year of listSortedNumeric(archiveDir, 4)) {
75
+ const yearDir = path.join(archiveDir, year);
76
+ for (const month of listSortedNumeric(yearDir, 2)) {
77
+ const monthDir = path.join(yearDir, month);
78
+ for (const day of listSortedNumeric(monthDir, 2)) {
79
+ const candidate = path.join(monthDir, day, taskId, 'task.md');
80
+ if (fs.existsSync(candidate)) return candidate;
81
+ }
82
+ }
83
+ }
84
+ return null;
85
+ }
86
+
87
+ function findTaskMd(repoRoot: string, taskId: string): string | null {
88
+ for (const sub of FLAT_WORKSPACE_DIRS) {
89
+ const candidate = path.join(repoRoot, '.agents', 'workspace', sub, taskId, 'task.md');
90
+ if (fs.existsSync(candidate)) return candidate;
91
+ }
92
+ return findInArchive(repoRoot, taskId);
93
+ }
94
+
95
+ /**
96
+ * Enumerate every task directory under the flat workspace states
97
+ * (active / blocked / completed) — archive is intentionally excluded so a
98
+ * full-tree scan never pulls in cold data. Ordered by state, then task id
99
+ * ascending, giving callers a deterministic traversal.
100
+ */
101
+ function enumerateTaskDirs(repoRoot: string): { taskId: string; taskDir: string }[] {
102
+ const out: { taskId: string; taskDir: string }[] = [];
103
+ for (const sub of FLAT_WORKSPACE_DIRS) {
104
+ const base = path.join(repoRoot, '.agents', 'workspace', sub);
105
+ if (!fs.existsSync(base)) continue;
106
+ for (const entry of fs.readdirSync(base).sort()) {
107
+ if (!TASK_ID_RE.test(entry)) continue;
108
+ const taskDir = path.join(base, entry);
109
+ if (!fs.existsSync(path.join(taskDir, 'task.md'))) continue;
110
+ out.push({ taskId: entry, taskDir });
111
+ }
112
+ }
113
+ return out;
114
+ }
115
+
116
+ /**
117
+ * Resolve a task ref (bare short id, `#N`, or `TASK-YYYYMMDD-HHMMSS`) to its
118
+ * task directory across active / blocked / completed / archive.
119
+ *
120
+ * The returned `message` on failure is command-agnostic (no `ai task <cmd>:`
121
+ * prefix); callers prepend their own prefix so each command keeps its existing
122
+ * stderr wording byte-for-byte.
123
+ */
124
+ function resolveTaskRef(arg: string): ResolveRefResult {
125
+ const repoRoot = detectRepoRoot();
126
+ let taskId: string;
127
+ if (TASK_ID_RE.test(arg)) {
128
+ taskId = arg;
129
+ } else {
130
+ const shortIdLength = readShortIdLength(repoRoot);
131
+ const normalized = normalizeShortIdInput(arg, { shortIdLength });
132
+ if (normalized.kind === 'error') {
133
+ return { ok: false, message: normalized.message };
134
+ }
135
+ if (normalized.kind === 'pass') {
136
+ return {
137
+ ok: false,
138
+ message:
139
+ `'${arg}' is not a valid short id or TASK-id; ` +
140
+ `expected bare digits, '#N', or 'TASK-YYYYMMDD-HHMMSS'`
141
+ };
142
+ }
143
+ try {
144
+ taskId = resolveShortIdToTaskId(normalized.value, repoRoot);
145
+ } catch (e) {
146
+ return { ok: false, message: (e as Error).message };
147
+ }
148
+ }
149
+ const taskMdPath = findTaskMd(repoRoot, taskId);
150
+ if (!taskMdPath) {
151
+ return {
152
+ ok: false,
153
+ message: `task ${taskId} not found in active / blocked / completed / archive`
154
+ };
155
+ }
156
+ return { ok: true, repoRoot, taskId, taskDir: path.dirname(taskMdPath), taskMdPath };
157
+ }
158
+
159
+ export { resolveTaskRef, detectRepoRoot, enumerateTaskDirs, TASK_ID_RE };
160
+ export type { ResolveRefResult };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fitlab-ai/agent-infra",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "description": "Bootstrap tool for AI multi-tool collaboration infrastructure — works with Claude Code, Codex, Gemini CLI, and OpenCode",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -34,6 +34,7 @@ This dual-config approach ensures every AI tool receives appropriate project con
34
34
  bug-fix.yaml # Bug fix workflow
35
35
  code-review.yaml # Code review workflow
36
36
  refactoring.yaml # Refactoring workflow
37
+ rules/ # Collaboration rule index (see rules/README.md)
37
38
  workspace/ # Runtime workspace (git-ignored)
38
39
  active/ # Currently active tasks
39
40
  blocked/ # Blocked tasks
@@ -34,6 +34,7 @@
34
34
  bug-fix.yaml # 缺陷修复工作流
35
35
  code-review.yaml # 代码审查工作流
36
36
  refactoring.yaml # 重构工作流
37
+ rules/ # 协作规则索引(见 rules/README.md)
37
38
  workspace/ # 运行时工作区(已被 git ignore)
38
39
  active/ # 当前活跃任务
39
40
  blocked/ # 被阻塞的任务
@@ -0,0 +1,41 @@
1
+ # Rules Index
2
+
3
+ `.agents/rules/` holds every collaboration rule in this project. Each SKILL loads the
4
+ relevant few on demand; this index groups all rules by domain with a one-line purpose,
5
+ so you can quickly find "which ones to read" without opening each file.
6
+
7
+ > Maintenance note: when adding or removing `.agents/rules/*.md`, update this index too.
8
+
9
+ ## General Principles
10
+
11
+ - [`no-mid-flow-questions.md`](no-mid-flow-questions.md) — Silence during SKILL runs: no user questions by default, plus two exceptions.
12
+ - [`next-step-output.md`](next-step-output.md) — "Next step" output rules: task short-id rendering and the `Completed at` trailer.
13
+ - [`version-stamp.md`](version-stamp.md) — How and when to stamp `agent_infra_version`.
14
+ - [`debugging-guide.md`](debugging-guide.md) — Structured debugging flow: gather evidence → form hypothesis → verify hypothesis → fix the root cause; no blind patch-and-retry.
15
+
16
+ ## Issue / PR
17
+
18
+ - [`issue-pr-commands.md`](issue-pr-commands.md) — GitHub commands to verify auth and read/write Issues / PRs.
19
+ - [`pr-checks-commands.md`](pr-checks-commands.md) — Commands to watch PR required checks and pull failure logs (`watch-pr`).
20
+ - [`create-issue.md`](create-issue.md) — Cascading Issue creation after `create-task` writes `task.md`.
21
+ - [`issue-sync.md`](issue-sync.md) — Sync markers and flow for task artifacts ↔ Issue comments / labels / fields.
22
+ - [`issue-fields.md`](issue-fields.md) — Read/write flow for Issue Type pinned fields (Priority/Effort/dates).
23
+ - [`pr-sync.md`](pr-sync.md) — Sync rule for the single reviewer-facing PR summary comment.
24
+
25
+ ## Task Workflow
26
+
27
+ - [`task-management.md`](task-management.md) — Task intent detection and workflow-command mapping.
28
+ - [`task-short-id.md`](task-short-id.md) — Resolution, allocation and lifecycle of `#NN` / bare-number short ids.
29
+ - [`milestone-inference.md`](milestone-inference.md) — Milestone inference for create-task / code-task / create-pr.
30
+ - [`label-milestone-setup.md`](label-milestone-setup.md) — Platform commands to initialize labels / milestones.
31
+ - [`security-alerts.md`](security-alerts.md) — Commands to import / close Dependabot and Code Scanning alerts.
32
+
33
+ ## Commit & Release
34
+
35
+ - [`commit-and-pr.md`](commit-and-pr.md) — Conventional Commits message and PR conventions.
36
+ - [`release-commands.md`](release-commands.md) — Read past releases, query merged PRs, publish release notes.
37
+
38
+ ## Testing & Cross-platform
39
+
40
+ - [`testing-discipline.md`](testing-discipline.md) — Test-writing discipline: prefer structural asserts, no brittle wording matches.
41
+ - [`cross-platform-tests.md`](cross-platform-tests.md) — Cross-platform test guards: express platform skips via `onPlatforms()`.
@@ -0,0 +1,40 @@
1
+ # 规则索引
2
+
3
+ `.agents/rules/` 收录本项目所有协作规则。各 SKILL 执行时按需加载其中若干篇;
4
+ 本索引按业务域列出全部规则及其用途,便于快速定位「该读哪几篇」,无需逐文件翻阅。
5
+
6
+ > 维护提醒:新增或删除 `.agents/rules/*.md` 时,请同步更新本索引。
7
+
8
+ ## 通用准则
9
+
10
+ - [`no-mid-flow-questions.md`](no-mid-flow-questions.md) — SKILL 执行期禁言:默认不向用户提问,及两类例外。
11
+ - [`next-step-output.md`](next-step-output.md) — 「下一步」输出规则:任务短号渲染与 `Completed at` 收尾行。
12
+ - [`version-stamp.md`](version-stamp.md) — `agent_infra_version` 版本戳的取值命令与写入时机。
13
+ - [`debugging-guide.md`](debugging-guide.md) — 结构化调试流程:收集证据→形成假设→验证假设→修复根因,禁止盲目改代码重试。
14
+
15
+ ## Issue / PR
16
+
17
+ - [`issue-pr-commands.md`](issue-pr-commands.md) — 验证平台认证、读写 Issue / PR 的 GitHub 命令集。
18
+ - [`pr-checks-commands.md`](pr-checks-commands.md) — 监控 PR required checks、拉取失败日志的命令集(`watch-pr`)。
19
+ - [`create-issue.md`](create-issue.md) — `create-task` 落盘后级联创建 Issue 的规则。
20
+ - [`issue-sync.md`](issue-sync.md) — task 产物与 Issue 评论 / 标签 / 字段的同步标记与流程。
21
+ - [`issue-fields.md`](issue-fields.md) — Issue Type pinned 字段(Priority/Effort/日期)的读写流程。
22
+ - [`pr-sync.md`](pr-sync.md) — 面向 reviewer 的唯一 PR 摘要评论的同步规则。
23
+
24
+ ## 任务工作流
25
+
26
+ - [`task-management.md`](task-management.md) — 任务语义识别与工作流命令映射。
27
+ - [`task-short-id.md`](task-short-id.md) — 任务短号 `#NN` / 裸数字的解析、分配与生命周期。
28
+ - [`milestone-inference.md`](milestone-inference.md) — create-task / code-task / create-pr 的 milestone 推断。
29
+ - [`label-milestone-setup.md`](label-milestone-setup.md) — 初始化 label / milestone 的平台命令集。
30
+ - [`security-alerts.md`](security-alerts.md) — 导入 / 关闭 Dependabot 与 Code Scanning 告警的命令集。
31
+
32
+ ## 提交与发布
33
+
34
+ - [`commit-and-pr.md`](commit-and-pr.md) — Conventional Commits 提交信息与 PR 规范。
35
+ - [`release-commands.md`](release-commands.md) — 读取历史 release、查询已合并 PR、发布 Release notes。
36
+
37
+ ## 测试与跨平台
38
+
39
+ - [`testing-discipline.md`](testing-discipline.md) — 测试编写纪律:结构性断言优先,禁止脆弱的措辞匹配。
40
+ - [`cross-platform-tests.md`](cross-platform-tests.md) — 跨平台测试守卫:用 `onPlatforms()` 表达平台跳过。
@@ -0,0 +1,25 @@
1
+ # General Rule - Structured Debugging Guide
2
+
3
+ > This file defines the structured triage flow for "test failure / behavior not as expected"; SKILLs that modify code in response to failures (e.g. `code-task`, `watch-pr`) load it on demand before attempting a fix.
4
+
5
+ ## Triggers
6
+
7
+ When any of the following happens, run this flow before changing code:
8
+
9
+ - A test fails, or a build / type-check / lint error appears
10
+ - Runtime behavior differs from expectations (output, state, or side effects)
11
+
12
+ ## Core Anti-pattern: No Blind Patch-and-Retry
13
+
14
+ The "tweak one spot → rerun → still broken → guess another spot" loop hides the real root cause, introduces new defects, and wastes time. A change with no supporting evidence is not a fix.
15
+
16
+ ## Four-phase Flow
17
+
18
+ 1. **Gather evidence**: Read the full error message and stack trace (not just the last line) and pinpoint where it fails; reproduce minimally when needed, and record "actual vs expected behavior".
19
+ 2. **Form a hypothesis**: From the evidence, propose a root-cause hypothesis that explains **all** the symptoms rather than a surface symptom; if there are several, rank them by likelihood and testability.
20
+ 3. **Verify the hypothesis**: Before changing anything, confirm the hypothesis cheaply—add logging, add a breakpoint, shrink the input, or write a failing test that reproduces it; if it is disproven, return to phase 2.
21
+ 4. **Fix the root cause**: Change only the verified root cause (not the symptom), then rerun the relevant tests to confirm they pass; if they still fail, return to phase 1 with the new evidence instead of trial-and-error without evidence.
22
+
23
+ ## Relation to Project Principles
24
+
25
+ This flow is the debugging-specific form of AGENTS.md's "Think Before Coding" and "Goal-Driven Execution": pin the problem with a reproducible failing case first, then make the fix turn it green.
@@ -0,0 +1,25 @@
1
+ # 通用规则 - 结构化调试指导
2
+
3
+ > 本文件定义「测试失败 / 行为不符合预期」时的结构化排查流程;`code-task`、`watch-pr` 等会因失败而修改代码的 SKILL 在动手修复前按需加载。
4
+
5
+ ## 触发条件
6
+
7
+ 出现以下任一情况时,先按本流程排查,再改代码:
8
+
9
+ - 测试失败,或构建 / 类型检查 / lint 报错
10
+ - 运行结果与预期不符(输出、状态或副作用异常)
11
+
12
+ ## 核心反模式:禁止盲目改代码重试
13
+
14
+ 「改一处 → 重跑 → 还错 → 再猜一处」的循环会掩盖真实根因、引入新缺陷、浪费时间。没有证据支撑的修改不算修复。
15
+
16
+ ## 四阶段流程
17
+
18
+ 1. **收集证据**:完整读取错误信息与堆栈(不要只看最后一行),定位失败的具体位置;必要时最小化复现,记录「实际行为 vs 预期行为」。
19
+ 2. **形成假设**:基于证据提出能解释**全部**现象的根因假设,而不是停留在表层症状;若有多个假设,按可能性与可验证性排序。
20
+ 3. **验证假设**:动手改之前,用最小代价确认假设成立——加日志、加断点、缩小输入,或写一个能复现的失败用例;假设被证伪就回到阶段 2。
21
+ 4. **修复根因**:只针对已验证的根因修改(而非症状),改完重跑相关测试确认通过;仍失败则带着新证据回到阶段 1,不在无证据时反复试错。
22
+
23
+ ## 与项目准则的关系
24
+
25
+ 本流程是 AGENTS.md「先思考再动手」「目标驱动执行」在调试场景的具体化:先用可复现的失败用例锁定问题,再让修复使其通过。
@@ -88,6 +88,8 @@ Follow the plan in order.
88
88
 
89
89
  Use the project test commands from the `test` skill and iterate until all required tests pass.
90
90
 
91
+ When triaging a test failure or unexpected behavior, first read `.agents/rules/debugging-guide.md` and locate the root cause via its four-phase flow; do not blindly patch and retry.
92
+
91
93
  ### 9. Write the Code Report
92
94
 
93
95
  Create `.agents/workspace/active/{task-id}/{code-artifact}`.
@@ -130,6 +130,8 @@ echo "$result"
130
130
 
131
131
  如果测试失败,先尝试修复并重新运行测试。只有在确认存在外部阻塞、环境缺失或需求不明确且超出任务范围时,才可以停止。
132
132
 
133
+ 排查测试失败或行为不符合预期时,先读取 `.agents/rules/debugging-guide.md`,按其四阶段流程定位根因,禁止盲目改代码重试。
134
+
133
135
  ### 9. 编写实现报告
134
136
 
135
137
  创建 `.agents/workspace/active/{task-id}/{code-artifact}`。
@@ -42,7 +42,7 @@ Using the watch command in `.agents/rules/pr-checks-commands.md`, poll `{pr#}`'s
42
42
 
43
43
  Before running this step, read the "Self-Heal Decision Tree" of `reference/monitor-and-heal.md` and "Resolve a Failing Run id and Pull Logs" of `.agents/rules/pr-checks-commands.md`.
44
44
 
45
- For a failing check: first deterministically resolve its failing run and pull the failure logs per the rule, then classify the failure; only when it is a locatable code-layer failure, make a minimal local fix, run the relevant tests until they pass, then **stage, commit, and push the fix** (`git add` only the related files → `git commit` per `.agents/rules/commit-and-pr.md` → `git push` to the current PR branch, recording the commit SHA), and return to step 2 to re-watch. Count fix attempts; on reaching the hard cap (default 2) or when the run is unlocatable, go to step 4.
45
+ For a failing check: first deterministically resolve its failing run and pull the failure logs per the rule, then classify the failure; before making any local fix, read `.agents/rules/debugging-guide.md` and locate the root cause via its four-phase flow, never blindly patching and retrying; only when it is a locatable code-layer failure, make a minimal local fix, run the relevant tests until they pass, then **stage, commit, and push the fix** (`git add` only the related files → `git commit` per `.agents/rules/commit-and-pr.md` → `git push` to the current PR branch, recording the commit SHA), and return to step 2 to re-watch. Count fix attempts; on reaching the hard cap (default 2) or when the run is unlocatable, go to step 4.
46
46
 
47
47
  ### 4. Help Exit (Produce-Then-Stop)
48
48
 
@@ -42,7 +42,7 @@ description: "监控 PR 的 required checks 并在失败时自愈"
42
42
 
43
43
  执行此步骤前,先读取 `reference/monitor-and-heal.md` 的「自愈决策树」与 `.agents/rules/pr-checks-commands.md` 的「解析失败 run id 并拉日志」。
44
44
 
45
- 对失败 check:先按规则确定性解析其失败 run 并拉取失败日志、判定失败类别;仅当属可定位的代码层失败时,本地最小化修复、运行对应测试通过后**暂存并提交本次修复再推送**(`git add` 仅相关文件 → 按 `.agents/rules/commit-and-pr.md` `git commit` → `git push` 到当前 PR 分支,并记录 commit SHA),再回到步骤 2 重新监控。修复尝试计数,达硬上限(默认 2)或 run 不可定位 → 转步骤 4。
45
+ 对失败 check:先按规则确定性解析其失败 run 并拉取失败日志、判定失败类别;本地修复前先读取 `.agents/rules/debugging-guide.md`,按其四阶段流程定位根因,禁止盲目改代码重试;仅当属可定位的代码层失败时,本地最小化修复、运行对应测试通过后**暂存并提交本次修复再推送**(`git add` 仅相关文件 → 按 `.agents/rules/commit-and-pr.md` `git commit` → `git push` 到当前 PR 分支,并记录 commit SHA),再回到步骤 2 重新监控。修复尝试计数,达硬上限(默认 2)或 run 不可定位 → 转步骤 4。
46
46
 
47
47
  ### 4. 求助出口(产出后停止)
48
48