@fitlab-ai/agent-infra 0.7.4 → 0.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/bin/cli.ts +13 -11
  2. package/dist/bin/cli.js +13 -11
  3. package/dist/lib/init.js +1 -1
  4. package/dist/lib/merge.js +1 -1
  5. package/dist/lib/sandbox/commands/create.js +26 -4
  6. package/dist/lib/sandbox/index.js +21 -21
  7. package/dist/lib/sandbox/tools.js +20 -1
  8. package/dist/lib/task/commands/log.js +56 -6
  9. package/dist/lib/task/index.js +13 -13
  10. package/dist/lib/update.js +1 -1
  11. package/lib/init.ts +1 -1
  12. package/lib/merge.ts +1 -1
  13. package/lib/sandbox/commands/create.ts +33 -4
  14. package/lib/sandbox/index.ts +21 -21
  15. package/lib/sandbox/tools.ts +28 -1
  16. package/lib/task/commands/log.ts +59 -6
  17. package/lib/task/index.ts +13 -13
  18. package/lib/update.ts +1 -1
  19. package/package.json +1 -1
  20. package/templates/.agents/rules/README.en.md +7 -3
  21. package/templates/.agents/rules/README.zh-CN.md +7 -3
  22. package/templates/.agents/rules/cli-help-format.en.md +49 -0
  23. package/templates/.agents/rules/cli-help-format.zh-CN.md +49 -0
  24. package/templates/.agents/rules/no-mid-flow-questions.en.md +25 -2
  25. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +25 -2
  26. package/templates/.agents/rules/pr-sync.github.en.md +8 -6
  27. package/templates/.agents/rules/pr-sync.github.zh-CN.md +8 -6
  28. package/templates/.agents/rules/review-handshake.en.md +97 -0
  29. package/templates/.agents/rules/review-handshake.zh-CN.md +97 -0
  30. package/templates/.agents/rules/task-management.en.md +25 -0
  31. package/templates/.agents/rules/task-management.zh-CN.md +29 -0
  32. package/templates/.agents/scripts/lib/post-review-commit.js +56 -0
  33. package/templates/.agents/scripts/lib/review-artifacts.js +117 -0
  34. package/templates/.agents/scripts/review-diff-fingerprint.js +99 -0
  35. package/templates/.agents/scripts/validate-artifact.js +251 -2
  36. package/templates/.agents/skills/analyze-task/SKILL.en.md +63 -6
  37. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +63 -6
  38. package/templates/.agents/skills/block-task/SKILL.en.md +10 -0
  39. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +10 -0
  40. package/templates/.agents/skills/cancel-task/SKILL.en.md +10 -0
  41. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +11 -1
  42. package/templates/.agents/skills/close-codescan/SKILL.en.md +10 -0
  43. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +10 -0
  44. package/templates/.agents/skills/close-dependabot/SKILL.en.md +10 -0
  45. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +10 -0
  46. package/templates/.agents/skills/code-task/SKILL.en.md +11 -0
  47. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +11 -0
  48. package/templates/.agents/skills/code-task/config/verify.en.json +3 -0
  49. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +3 -0
  50. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +5 -3
  51. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +5 -3
  52. package/templates/.agents/skills/code-task/reference/report-template.en.md +4 -4
  53. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +4 -4
  54. package/templates/.agents/skills/code-task/scripts/detect-mode.js +2 -107
  55. package/templates/.agents/skills/commit/SKILL.en.md +16 -0
  56. package/templates/.agents/skills/commit/SKILL.zh-CN.md +16 -0
  57. package/templates/.agents/skills/commit/reference/task-status-update.en.md +8 -0
  58. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +8 -0
  59. package/templates/.agents/skills/complete-task/SKILL.en.md +20 -0
  60. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +20 -0
  61. package/templates/.agents/skills/complete-task/config/verify.en.json +2 -0
  62. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +2 -0
  63. package/templates/.agents/skills/create-pr/SKILL.en.md +20 -1
  64. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +20 -1
  65. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +1 -1
  66. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +1 -1
  67. package/templates/.agents/skills/create-release-note/SKILL.en.md +16 -1
  68. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +16 -1
  69. package/templates/.agents/skills/create-task/SKILL.en.md +11 -0
  70. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +14 -3
  71. package/templates/.agents/skills/import-codescan/SKILL.en.md +11 -0
  72. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +11 -0
  73. package/templates/.agents/skills/import-dependabot/SKILL.en.md +11 -0
  74. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +11 -0
  75. package/templates/.agents/skills/import-issue/SKILL.en.md +16 -0
  76. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +16 -0
  77. package/templates/.agents/skills/plan-task/SKILL.en.md +13 -1
  78. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +13 -1
  79. package/templates/.agents/skills/plan-task/config/verify.en.json +3 -0
  80. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +3 -0
  81. package/templates/.agents/skills/restore-task/SKILL.en.md +10 -0
  82. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +10 -0
  83. package/templates/.agents/skills/review-analysis/SKILL.en.md +10 -0
  84. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +10 -0
  85. package/templates/.agents/skills/review-analysis/config/verify.en.json +2 -1
  86. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +2 -1
  87. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +5 -4
  88. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +5 -4
  89. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +4 -0
  90. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +4 -0
  91. package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +1 -0
  92. package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +1 -0
  93. package/templates/.agents/skills/review-code/SKILL.en.md +14 -1
  94. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +14 -1
  95. package/templates/.agents/skills/review-code/config/verify.en.json +5 -2
  96. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +5 -2
  97. package/templates/.agents/skills/review-code/reference/output-templates.en.md +5 -4
  98. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +5 -4
  99. package/templates/.agents/skills/review-code/reference/report-template.en.md +6 -0
  100. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +6 -0
  101. package/templates/.agents/skills/review-code/reference/review-criteria.en.md +1 -0
  102. package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +1 -0
  103. package/templates/.agents/skills/review-plan/SKILL.en.md +10 -0
  104. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +10 -0
  105. package/templates/.agents/skills/review-plan/config/verify.en.json +2 -1
  106. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +2 -1
  107. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +5 -4
  108. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +5 -4
  109. package/templates/.agents/skills/review-plan/reference/report-template.en.md +4 -0
  110. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +4 -0
  111. package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +1 -0
  112. package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +1 -0
  113. package/templates/.agents/skills/watch-pr/SKILL.en.md +10 -0
  114. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +10 -0
  115. package/templates/.agents/templates/task.en.md +12 -0
  116. package/templates/.agents/templates/task.zh-CN.md +12 -0
  117. package/templates/.github/workflows/metadata-sync.yml +1 -1
  118. package/templates/.github/workflows/pr-label.yml +1 -1
  119. package/templates/.github/workflows/status-label.yml +1 -1
@@ -1,8 +1,15 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import process from "node:process";
4
+ import { execFileSync } from "node:child_process";
4
5
  import { fileURLToPath } from "node:url";
5
6
 
7
+ import {
8
+ extractReviewBaseline,
9
+ findAuthoritativeReviewCodeArtifact,
10
+ resolvePostReviewGlobs
11
+ } from "./lib/post-review-commit.js";
12
+
6
13
  const EXIT_CODE = {
7
14
  pass: 0,
8
15
  fail: 1,
@@ -31,8 +38,30 @@ const DEFAULT_FRESHNESS_MINUTES = 30;
31
38
  const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?$/;
32
39
  const AGENT_INFRA_VERSION_PATTERN = /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
33
40
  const ACTIVITY_LOG_PATTERN = /^- (\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?) — \*\*(.+?)\*\* by (.+?) — (.+)$/;
41
+ // Start markers (action suffixed with ` [started]`) are excluded from the
42
+ // "latest action" / freshness computation so a step's in-flight marker never
43
+ // satisfies a skill's expected_action_pattern; the matching done entry does.
44
+ const ACTIVITY_LOG_STARTED_RE = /\s*\[started\]\s*$/;
34
45
  const BRANCH_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
35
46
 
47
+ // Review disagreement ledger (see .agents/rules/review-handshake.md).
48
+ const LEDGER_SECTION_NAMES = ["审查分歧账本", "Review Disagreement Ledger"];
49
+ const LEDGER_STATUSES = new Set([
50
+ "open",
51
+ "accepted",
52
+ "adjusted",
53
+ "refuted",
54
+ "cannot-judge",
55
+ "confirmed",
56
+ "needs-human-decision",
57
+ "closed",
58
+ "human-decided"
59
+ ]);
60
+ const LEDGER_TERMINAL_OK = new Set(["confirmed", "closed", "human-decided"]);
61
+ const DEFAULT_MAX_HANDSHAKE_ROUNDS = 3;
62
+ const POST_REVIEW_COMMIT_STAGE = "post-review-commit";
63
+ const SHA_PATTERN = /^[0-9a-f]{7,40}$/i;
64
+
36
65
  const scriptPath = fileURLToPath(import.meta.url);
37
66
  const repoRoot = path.resolve(path.dirname(scriptPath), "..", "..");
38
67
 
@@ -188,6 +217,10 @@ function runCheck(type, context) {
188
217
  return checkActivityLog(context);
189
218
  case "completion-checklist":
190
219
  return checkCompletionChecklist(context);
220
+ case "review-ledger":
221
+ return checkReviewLedger(context);
222
+ case "post-review-commit":
223
+ return checkPostReviewCommit(context);
191
224
  default: {
192
225
  const adapter = PLATFORM_ADAPTERS[type];
193
226
  if (!adapter) {
@@ -332,6 +365,20 @@ function loadProjectName() {
332
365
  }
333
366
  }
334
367
 
368
+ function loadReviewConfig() {
369
+ const configPath = path.join(repoRoot, ".agents", ".airc.json");
370
+ if (!fs.existsSync(configPath)) {
371
+ return {};
372
+ }
373
+
374
+ try {
375
+ const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
376
+ return config.review && typeof config.review === "object" ? config.review : {};
377
+ } catch {
378
+ return {};
379
+ }
380
+ }
381
+
335
382
  function checkArtifact({ taskDir, config, artifactFile }) {
336
383
  const resolvedArtifact = resolveArtifactPath(taskDir, config.file_pattern, artifactFile);
337
384
  if (!resolvedArtifact.ok) {
@@ -419,8 +466,13 @@ function checkActivityLog({ taskDir, config }) {
419
466
  }
420
467
 
421
468
  previousTimestamp = timestamp;
422
- latestTimestamp = timestamp;
423
- latestAction = action;
469
+ // Ascending order is checked over every entry, but a `[started]` marker is
470
+ // not a terminal action: keep latestAction/latestTimestamp on the most
471
+ // recent done entry so expected_action_pattern and freshness see it.
472
+ if (!ACTIVITY_LOG_STARTED_RE.test(action)) {
473
+ latestTimestamp = timestamp;
474
+ latestAction = action;
475
+ }
424
476
  }
425
477
 
426
478
  if (config.expected_action_pattern && !new RegExp(config.expected_action_pattern).test(latestAction)) {
@@ -481,6 +533,203 @@ function checkCompletionChecklist({ taskDir, config }) {
481
533
  return passResult("completion-checklist", `Completion Checklist valid (${items.length} items checked)`);
482
534
  }
483
535
 
536
+ function parseLedgerRows(section) {
537
+ const rows = [];
538
+ for (const rawLine of String(section || "").split(/\r?\n/)) {
539
+ const line = rawLine.trim();
540
+ if (!line.startsWith("|")) {
541
+ continue;
542
+ }
543
+ if (/^\|[\s:|-]+\|?$/.test(line)) {
544
+ continue; // separator row
545
+ }
546
+ const inner = line.replace(/^\|/, "").replace(/\|$/, "");
547
+ const cells = inner.split("|").map((cell) => cell.trim());
548
+ if ((cells[0] || "").toLowerCase() === "id") {
549
+ continue; // header row
550
+ }
551
+ rows.push(cells);
552
+ }
553
+ return rows;
554
+ }
555
+
556
+ function resolveReviewSetting(config, key, fallback) {
557
+ if (config && config[key] !== undefined && config[key] !== null) {
558
+ return config[key];
559
+ }
560
+ const reviewConfig = loadReviewConfig();
561
+ if (reviewConfig[key] !== undefined && reviewConfig[key] !== null) {
562
+ return reviewConfig[key];
563
+ }
564
+ return fallback;
565
+ }
566
+
567
+ function checkReviewLedger({ taskDir, config }) {
568
+ const task = loadTask(taskDir);
569
+ if (!task.ok) {
570
+ return failResult("review-ledger", task.message);
571
+ }
572
+
573
+ const section = getSectionContent(task.content, LEDGER_SECTION_NAMES);
574
+ if (!section.trim()) {
575
+ return passResult("review-ledger", "No disagreement ledger section; treated as no open disagreements");
576
+ }
577
+
578
+ const rows = parseLedgerRows(section);
579
+ if (rows.length === 0) {
580
+ return passResult("review-ledger", "Disagreement ledger has no entries");
581
+ }
582
+
583
+ const stageScope = Array.isArray(config.stage_scope) ? config.stage_scope : null;
584
+ const maxRounds = Number(resolveReviewSetting(config, "max_handshake_rounds", DEFAULT_MAX_HANDSHAKE_ROUNDS));
585
+ const problems = [];
586
+ let inScopeCount = 0;
587
+
588
+ for (const cells of rows) {
589
+ if (cells.length < 6) {
590
+ problems.push(`malformed row (expected 6 columns): ${cells.join(" | ")}`);
591
+ continue;
592
+ }
593
+
594
+ const [id, stage, roundRaw, , status, evidence] = cells;
595
+ const stageScoped = stageScope ? stageScope.includes(stage) : true;
596
+ // post-review-commit exemption rows are consumed by the post-review-commit
597
+ // check, not enforced here.
598
+ if (stage === POST_REVIEW_COMMIT_STAGE) {
599
+ continue;
600
+ }
601
+ if (!stageScoped) {
602
+ continue;
603
+ }
604
+ inScopeCount += 1;
605
+
606
+ if (!LEDGER_STATUSES.has(status)) {
607
+ problems.push(`${id}: illegal status '${status}'`);
608
+ continue;
609
+ }
610
+ if (status !== "open" && evidence === "") {
611
+ problems.push(`${id}: status '${status}' requires evidence`);
612
+ }
613
+ const round = Number.parseInt(roundRaw, 10);
614
+ if (
615
+ Number.isFinite(round) &&
616
+ round >= maxRounds &&
617
+ !LEDGER_TERMINAL_OK.has(status) &&
618
+ status !== "needs-human-decision"
619
+ ) {
620
+ problems.push(`${id}: round ${round} reached limit ${maxRounds} without convergence; escalate to needs-human-decision`);
621
+ }
622
+ if (!LEDGER_TERMINAL_OK.has(status)) {
623
+ problems.push(`${id}: unresolved (status '${status}')`);
624
+ }
625
+ }
626
+
627
+ if (problems.length > 0) {
628
+ return failResult("review-ledger", `Unclosed/invalid disagreements: ${problems.join("; ")}`);
629
+ }
630
+
631
+ const scopeLabel = stageScope ? ` for stages [${stageScope.join(", ")}]` : "";
632
+ return passResult("review-ledger", `Disagreement ledger clean (${inScopeCount} in-scope entries terminal${scopeLabel})`);
633
+ }
634
+
635
+ function checkPostReviewCommit({ taskDir, config }) {
636
+ const reviewArtifact = findAuthoritativeReviewCodeArtifact(taskDir);
637
+ if (!reviewArtifact.ok) {
638
+ return passResult("post-review-commit", "No review-code artifact; check inactive");
639
+ }
640
+
641
+ let gitRoot;
642
+ try {
643
+ gitRoot = execFileSync("git", ["-C", taskDir, "rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim();
644
+ } catch {
645
+ return blockedResult("post-review-commit", "git unavailable or task directory is not inside a git repository");
646
+ }
647
+
648
+ const task = loadTask(taskDir);
649
+ const content = fs.readFileSync(reviewArtifact.path, "utf8");
650
+ const reviewBaseline = extractReviewBaseline(content);
651
+ const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
652
+ const baselineSource = resolvePostReviewBaseline({
653
+ gitRoot,
654
+ lastReviewedCommit,
655
+ reviewBaseline,
656
+ reviewArtifact: reviewArtifact.fileName
657
+ });
658
+ if (!baselineSource.ok) {
659
+ return baselineSource.result;
660
+ }
661
+
662
+ const sha = baselineSource.sha;
663
+ const globs = resolvePostReviewGlobs(config, loadReviewConfig());
664
+ let commits;
665
+ try {
666
+ const out = execFileSync("git", ["-C", gitRoot, "rev-list", `${sha}..HEAD`, "--", ...globs], { encoding: "utf8" });
667
+ commits = out.split(/\r?\n/).filter((line) => line.trim() !== "");
668
+ } catch {
669
+ return blockedResult("post-review-commit", `git rev-list failed for baseline ${sha}; manual inspection required`);
670
+ }
671
+
672
+ if (commits.length === 0) {
673
+ return passResult("post-review-commit", `No post-review commits to code/rule paths since ${sha.slice(0, 8)}`);
674
+ }
675
+
676
+ const ledgerSection = task.ok ? getSectionContent(task.content, LEDGER_SECTION_NAMES) : "";
677
+ const exempt = parseLedgerRows(ledgerSection).some(
678
+ (cells) => cells[1] === POST_REVIEW_COMMIT_STAGE && cells[4] === "human-decided"
679
+ );
680
+ if (exempt) {
681
+ return passResult(
682
+ "post-review-commit",
683
+ `${commits.length} post-review commit(s) covered by a human-decided exemption`
684
+ );
685
+ }
686
+
687
+ return failResult(
688
+ "post-review-commit",
689
+ `${commits.length} commit(s) to code/rule paths after review baseline ${sha.slice(0, 8)}; re-run review-code or record a human-decided exemption`
690
+ );
691
+ }
692
+
693
+ function resolvePostReviewBaseline({ gitRoot, lastReviewedCommit, reviewBaseline, reviewArtifact }) {
694
+ if (lastReviewedCommit) {
695
+ if (SHA_PATTERN.test(lastReviewedCommit) && gitCommitExists(gitRoot, lastReviewedCommit)) {
696
+ return { ok: true, sha: lastReviewedCommit };
697
+ }
698
+ }
699
+
700
+ if (!reviewBaseline) {
701
+ return {
702
+ ok: false,
703
+ result: passResult(
704
+ "post-review-commit",
705
+ `${reviewArtifact} predates baseline-commit anchoring; skipped (legacy artifact)`,
706
+ [`${reviewArtifact} has no 审查基线提交 / Review Baseline Commit field`]
707
+ )
708
+ };
709
+ }
710
+
711
+ if (!SHA_PATTERN.test(reviewBaseline)) {
712
+ return {
713
+ ok: false,
714
+ result: blockedResult(
715
+ "post-review-commit",
716
+ `${reviewArtifact} has an empty or malformed 审查基线提交 SHA ('${reviewBaseline}'); manual remediation required`
717
+ )
718
+ };
719
+ }
720
+
721
+ return { ok: true, sha: reviewBaseline };
722
+ }
723
+
724
+ function gitCommitExists(gitRoot, sha) {
725
+ try {
726
+ execFileSync("git", ["-C", gitRoot, "cat-file", "-e", `${sha}^{commit}`], { encoding: "utf8" });
727
+ return true;
728
+ } catch {
729
+ return false;
730
+ }
731
+ }
732
+
484
733
  // === File & Config Loaders ===
485
734
 
486
735
  function loadVerifyConfig(skillName) {
@@ -31,6 +31,16 @@ Before the state check is complete, do not make external-state assertions such a
31
31
 
32
32
  > If `{task-id}` matches `^[#]?[0-9]+$` (bare numeric or `#`-prefixed), follow the "SKILL parameter resolver" section of `.agents/rules/task-short-id.md`; treat `{task-id}` as the resolved full `TASK-YYYYMMDD-HHMMSS` form for every downstream command.
33
33
 
34
+ ## Step Start: Write the started Marker
35
+
36
+ After prerequisites pass and before this round's first artifact action, append a started marker to task.md `## Activity Log` (same base action as this round's done entry plus a ` [started]` suffix, note `started`):
37
+
38
+ ```
39
+ - {YYYY-MM-DD HH:mm:ss±HH:MM} — **Analyze Task (Round {N}) [started]** by {agent} — started
40
+ ```
41
+
42
+ `ai task log` pairs it with the done entry written on completion (step 7) onto one row (in progress → done). Format and pairing rules: see the "Activity Log started / done dual-marker convention" in `.agents/rules/task-management.md`.
43
+
34
44
  ## Steps
35
45
 
36
46
  ### 1. Verify Prerequisites
@@ -65,9 +75,49 @@ If `task.md` contains these source fields, also read the corresponding source in
65
75
  - `codescan_alert_number` - Code Scanning alert
66
76
  - `security_alert_number` - Dependabot alert
67
77
 
68
- **Round ≥ 2: respond to the prior review (only when a review artifact exists)**: if the task directory contains `review-analysis.md` / `review-analysis-r{N}.md`, read the highest-round review report; add a `## Response to Prior Review` section to this round's analysis artifact, and for each finding verify it via Read/Grep before acting (holds accept and fix; judged hallucinated/unfounded rebut with counter-evidence rather than defaulting to compliance); record any open disagreement under `## Open Questions`. Round 1 has no review, so skip this section.
78
+ **Round ≥ 2: respond to the prior review (only when a review artifact exists)**: if the task directory contains `review-analysis.md` / `review-analysis-r{N}.md`, read the highest-round review report; add a `## Response to Prior Review` section to this round's analysis artifact, and for each finding verify it via Read/Grep, then dispose of it with one of the four states in `.agents/rules/review-handshake.md` (`accepted` / `adjusted` / `refuted` / `cannot-judge`) — every state needs commensurate evidence, never defaulting to compliance; write the disposition back to the matching row in the task.md disagreement ledger (stage=analysis, round +1). Record any open disagreement under `## Open Questions`. Round 1 has no review, so skip this section.
79
+
80
+ ### 4. Requirement Sufficiency Gate
81
+
82
+ > Questions in this step are authorized by `.agents/rules/no-mid-flow-questions.md` "Exemption 3: Entry-point requirement-sufficiency clarification": only at the analyze-task entry point, only to judge and fill requirement sufficiency, one question at a time, and **never** to solicit implementation / technical-choice preferences.
83
+
84
+ Runs after Step 0 state check and Step 3 (questioning is an external-state action and must come after the state-check hard gate; the judgment and state read/write need task.md first).
85
+
86
+ **4.1 Read cross-round state**: read the `## Brainstorming` section of task.md (treat as first time when absent, `question_count=0`). Section format:
69
87
 
70
- ### 4. Perform Requirements Analysis
88
+ ```
89
+ ## Brainstorming
90
+ - status: asking | done
91
+ - question_count: <int>
92
+ - pending_question: <text, may be empty>
93
+ - answered:
94
+ - Q: … / A: …
95
+ ```
96
+
97
+ **4.2 Receive the answer to the previous question**: if `pending_question` exists:
98
+ - the user's current message yields an answer → write the answer back into `## Description` / `## Requirements`, append that `Q/A` to `answered`, and clear `pending_question` (`question_count` unchanged).
99
+ - no answer carried → restate `pending_question` and take Scenario B early-exit below (do not increase `question_count`).
100
+
101
+ **4.3 Sufficiency judgment** (objective checklist; any gap hit means insufficient):
102
+ - description/requirements empty, or a single sentence with no verifiable acceptance criteria;
103
+ - missing goal or impact scope (unclear what to change / who is affected);
104
+ - requirement items contradict each other, or key terms are undefined and block analysis.
105
+
106
+ **4.4 Branch**:
107
+
108
+ - **Scenario A (sufficient / converged)** — any exit condition met: the checklist fully passes / the user explicitly says "just analyze / skip" / `question_count` reaches the cap (≤5). Set `## Brainstorming` `status: done` and continue the normal flow from step 5; write any remaining gaps into the analysis artifact `## Assumptions` / `## Open Questions`.
109
+ - **Scenario B (insufficient, ask and early-exit)** — close the loop within this step and STOP early:
110
+ 1. Decide this round's question (consistent with 4.2):
111
+ - if a `pending_question` already exists (the previous question is still unanswered) → restate that `pending_question`, do **not** modify it and do **not** increment `question_count`;
112
+ - otherwise (no pending question) → pick the single highest-value question (acceptance criteria > scope > ambiguity) and write `## Brainstorming`: `status: asking`, `pending_question: <question>`, `question_count += 1`.
113
+ 2. Update frontmatter: `current_step: requirement-analysis`, `assigned_to`, `updated_at`, `agent_infra_version` (read `.agents/rules/version-stamp.md` first).
114
+ 3. Append to Activity Log: `- {YYYY-MM-DD HH:mm:ss±HH:MM} — **Analyze Task (Brainstorming)** by {agent} — Asked Q{question_count}, awaiting answer`.
115
+ 4. Issue sync (when `issue_number` exists, skip on any failure): read `.agents/rules/issue-sync.md` first for upstream / permission detection; update only the **task comment** per the task.md comment sync rule; keep the `status` label at `pending-design-work`; do **not** publish an analysis artifact comment.
116
+ 5. Verification (replaces the step 8 artifact gate): `node .agents/scripts/validate-artifact.js check task-meta .agents/workspace/active/{task-id} --skill analyze-task --format text` (the early-exit set `current_step: requirement-analysis`, so it should pass); also keep `rg -n 'Analyze Task \(Brainstorming\)' .agents/workspace/active/{task-id}/task.md` and the task-comment sync evidence. Do **not** run the artifact gate, nor `check activity-log` / `check platform-sync` (both bind to the analysis artifact path).
117
+ 6. User output: show only the current **single question** plus how to answer/continue (re-trigger `analyze-task {task-ref}` with the answer), and append the `Completed at` line per `.agents/rules/next-step-output.md`.
118
+ 7. **STOP** and wait for the answer. The next trigger returns to this step.
119
+
120
+ ### 5. Perform Requirements Analysis
71
121
 
72
122
  Before analysis begins: if `start_date` in the frontmatter is empty, write today's date immediately (command: `date +%F`, format `YYYY-MM-DD`); keep any existing value. Before writing, read `.agents/rules/version-stamp.md` and refresh `updated_at` / `agent_infra_version` at the same time.
73
123
 
@@ -80,7 +130,9 @@ Follow the `analysis` step in `.agents/workflows/feature-development.yaml`:
80
130
  - [ ] Identify potential technical risks and dependencies
81
131
  - [ ] Assess effort and complexity
82
132
 
83
- ### 5. Output Analysis Document
133
+ ### 6. Output Analysis Document
134
+
135
+ > Steps 6–9 are the **Scenario A (normal output)** path. **Scenario B (ask and early-exit)** already finished its state update, task-comment sync, and verification inside step 4 and STOPped, so it does not enter these steps.
84
136
 
85
137
  Create `.agents/workspace/active/{task-id}/{analysis-artifact}`.
86
138
 
@@ -130,6 +182,7 @@ Create `.agents/workspace/active/{task-id}/{analysis-artifact}`.
130
182
  ## Open Questions
131
183
 
132
184
  > If there are unresolved questions for human review, list them here; omit this section if there are none.
185
+ > Mark key design decisions with `[needs-human-decision]` and write `HD-` ledger rows according to `.agents/rules/no-mid-flow-questions.md`.
133
186
 
134
187
  - {open question}
135
188
 
@@ -138,7 +191,7 @@ Create `.agents/workspace/active/{task-id}/{analysis-artifact}`.
138
191
  - Risk level: {High/Medium/Low}
139
192
  ```
140
193
 
141
- ### 6. Update Task Status
194
+ ### 7. Update Task Status
142
195
 
143
196
  Get the current time:
144
197
 
@@ -170,7 +223,9 @@ If task.md contains a valid `issue_number`, perform these sync actions (skip and
170
223
  - Publish the `{analysis-artifact}` comment
171
224
  - Read `.agents/rules/issue-fields.md` and follow Flow A to sync every non-empty Issue field (`priority`/`effort`/`start_date`/`target_date`) from `task.md` to the Issue (idempotent; skip without blocking when `has_push=false` or the fetch/write fails)
172
225
 
173
- ### 7. Verification Gate
226
+ ### 8. Verification Gate
227
+
228
+ > This artifact gate is for **Scenario A** only; Scenario B's verification is in step 4 (`check task-meta` + explicit evidence), not the artifact gate here.
174
229
 
175
230
  Run the verification gate to confirm the task artifact and sync state are valid:
176
231
 
@@ -185,7 +240,9 @@ Handle the result as follows:
185
240
 
186
241
  Keep the gate output in your reply as fresh evidence. Do not claim completion without output from this run.
187
242
 
188
- ### 8. Inform User
243
+ ### 9. Inform User
244
+
245
+ > This step is the **Scenario A** normal-completion output; Scenario B's single-question output is in step 4.
189
246
 
190
247
  > Execute this step only after the verification gate passes.
191
248
 
@@ -31,6 +31,16 @@ tail .agents/workspace/active/{task-id}/task.md
31
31
 
32
32
  > 如果 `{task-id}` 入参匹配 `^[#]?[0-9]+$`(裸数字或带 `#` 前缀),先读取 `.agents/rules/task-short-id.md` 的「SKILL 入参解析」段执行解析;后续命令视 `{task-id}` 为解析后的全长 `TASK-YYYYMMDD-HHMMSS` 形式。
33
33
 
34
+ ## 步骤开始:写入 started 标记
35
+
36
+ 确认前置条件后、本轮第一个产出动作之前,向 task.md `## 活动日志` 追加一条 started 标记(与本轮 done 条目同基名 + ` [started]` 后缀,note 用 `started`):
37
+
38
+ ```
39
+ - {YYYY-MM-DD HH:mm:ss±HH:MM} — **Analyze Task (Round {N}) [started]** by {agent} — started
40
+ ```
41
+
42
+ `ai task log` 会把它与步骤完成时(步骤 7)写入的 done 条目配对成一行(进行中 → 已完成)。格式与配对规则见 `.agents/rules/task-management.md` 的「Activity Log started / done 双标记约定」。
43
+
34
44
  ## 执行步骤
35
45
  ### 1. 验证前置条件
36
46
 
@@ -64,9 +74,49 @@ tail .agents/workspace/active/{task-id}/task.md
64
74
  - `codescan_alert_number` - Code Scanning 告警
65
75
  - `security_alert_number` - Dependabot 告警
66
76
 
67
- **Round ≥ 2:响应上一轮审查(仅当存在审查产物时)**:若任务目录存在 `review-analysis.md` / `review-analysis-r{N}.md`,读取最高轮次的审查报告;在本轮分析产物中新增 `## 对上一轮审查的响应` 段,对每条发现先 Read/Grep 核实再处置(成立 接受并修正;判定为幻觉/不成立 附反证反驳,不默认顺从),未决分歧写入 `## 未决问题`。Round 1 无审查,跳过本段。
77
+ **Round ≥ 2:响应上一轮审查(仅当存在审查产物时)**:若任务目录存在 `review-analysis.md` / `review-analysis-r{N}.md`,读取最高轮次的审查报告;在本轮分析产物中新增 `## 对上一轮审查的响应` 段,对每条发现先 Read/Grep 核实,再按 `.agents/rules/review-handshake.md` 的四态(`accepted` / `adjusted` / `refuted` / `cannot-judge`)处置——每态都要附相称证据,不默认顺从;并把处置回写 task.md `## 审查分歧账本` 对应行(stage=analysis,round +1)。未决分歧写入 `## 未决问题`。Round 1 无审查,跳过本段。
78
+
79
+ ### 4. 入口需求充分性闸门
80
+
81
+ > 本步骤的发问受 `.agents/rules/no-mid-flow-questions.md`「例外 3:入口式需求充分性澄清」授权:仅在 analyze-task 入口、仅用于判断并补齐需求充分性,一次只问一个问题,**绝不**借此征求实现 / 技术选型偏好。
82
+
83
+ 排在第 0 步状态核对与步骤 3 之后执行(提问属对外动作,须在状态核对硬闸门之后;判定与状态读写需先读到 task.md)。
84
+
85
+ **4.1 读取跨轮状态**:读取 task.md 的 `## Brainstorming` 段(不存在则视为首次,`question_count=0`)。段格式:
68
86
 
69
- ### 4. 执行需求分析
87
+ ```
88
+ ## Brainstorming
89
+ - status: asking | done
90
+ - question_count: <int>
91
+ - pending_question: <文本,可空>
92
+ - answered:
93
+ - Q: … / A: …
94
+ ```
95
+
96
+ **4.2 接收上一问的答案**:若存在 `pending_question`:
97
+ - 用户当轮消息可解析出答案 → 把答案回写 `## 描述` / `## 需求`,把该 `Q/A` 追加进 `answered`,清空 `pending_question`(`question_count` 不变)。
98
+ - 未携带答案 → 复述 `pending_question`,按下文场景 B 提问早退(不增加 `question_count`)。
99
+
100
+ **4.3 充分性判定**(客观清单,命中任一缺口即判为不足):
101
+ - 描述/需求为空,或仅一句话且无可验证的验收标准;
102
+ - 缺少目标或受影响范围(不知道要改什么 / 影响谁);
103
+ - 需求条目自相矛盾,或关键名词未定义而无法分析。
104
+
105
+ **4.4 分流**:
106
+
107
+ - **场景 A(充分 / 已收敛)**——满足任一退出条件:充分性清单全部通过 / 用户显式「直接分析 / skip」/ `question_count` 达上限(≤5)。置 `## Brainstorming` 的 `status: done`,继续步骤 5 起的正常流程;未补齐的缺口写入分析产物 `## 假设` / `## 未决问题`。
108
+ - **场景 B(不足,提问早退)**——在本步骤内闭环并提前 STOP:
109
+ 1. 确定本轮要问的问题(与 4.2 保持一致):
110
+ - 若已存在 `pending_question`(上一问尚未得到答案)→ 复述该 `pending_question`,**不**修改它、**不**增加 `question_count`;
111
+ - 否则(无待答问题)→ 选最高价值的一个问题(验收标准 > 范围 > 歧义),写入 `## Brainstorming`:`status: asking`、`pending_question: <问题>`、`question_count += 1`。
112
+ 2. 更新 frontmatter:`current_step: requirement-analysis`、`assigned_to`、`updated_at`、`agent_infra_version`(先读 `.agents/rules/version-stamp.md`)。
113
+ 3. 追加 Activity Log:`- {YYYY-MM-DD HH:mm:ss±HH:MM} — **Analyze Task (Brainstorming)** by {agent} — Asked Q{question_count}, awaiting answer`。
114
+ 4. Issue 同步(存在 `issue_number` 时,任一失败跳过):先读 `.agents/rules/issue-sync.md` 完成 upstream / 权限检测;仅按 task.md 评论同步规则更新 **task 评论**;`status` label 维持 `pending-design-work`;**不**发布分析产物评论。
115
+ 5. 校验(替代步骤 8 的 artifact gate):`node .agents/scripts/validate-artifact.js check task-meta .agents/workspace/active/{task-id} --skill analyze-task --format text`(早退已置 `current_step: requirement-analysis`,预期通过);并保留 `rg -n 'Analyze Task \(Brainstorming\)' .agents/workspace/active/{task-id}/task.md` 与 task 评论同步证据。**不**跑 artifact gate,也不跑 `check activity-log` / `check platform-sync`(二者绑定分析产物路径)。
116
+ 6. 用户输出:只展示当前**单个问题** + 如何回答/继续(再次触发 `analyze-task {task-ref}` 并附答案),并按 `.agents/rules/next-step-output.md` 在末行追加 `Completed at`。
117
+ 7. **STOP**,等待回答。下一次触发回到本步骤。
118
+
119
+ ### 5. 执行需求分析
70
120
 
71
121
  开始分析前:若 frontmatter 的 `start_date` 为空,立即写入当日日期(命令 `date +%F`,格式 `YYYY-MM-DD`);已有值则保留。写入前先读取 `.agents/rules/version-stamp.md`,并同步刷新 `updated_at` / `agent_infra_version`。
72
122
 
@@ -79,7 +129,9 @@ tail .agents/workspace/active/{task-id}/task.md
79
129
  - [ ] 识别潜在技术风险和依赖
80
130
  - [ ] 评估工作量和复杂度
81
131
 
82
- ### 5. 输出分析文档
132
+ ### 6. 输出分析文档
133
+
134
+ > 步骤 6–9 属**场景 A(正常产出)**路径。**场景 B(提问早退)**已在步骤 4 内完成状态更新、task 评论同步与校验并 STOP,不进入这些步骤。
83
135
 
84
136
  创建 `.agents/workspace/active/{task-id}/{analysis-artifact}`。
85
137
 
@@ -129,6 +181,7 @@ tail .agents/workspace/active/{task-id}/task.md
129
181
  ## 未决问题
130
182
 
131
183
  > 如有需要人工裁定的未决问题,列在此处;没有则可省略本段。
184
+ > 关键设计决策按 `.agents/rules/no-mid-flow-questions.md` 的判据标记 `[needs-human-decision]` 并回写 `HD-` 账本行。
132
185
 
133
186
  - {未决问题}
134
187
 
@@ -137,7 +190,7 @@ tail .agents/workspace/active/{task-id}/task.md
137
190
  - 风险等级:{高/中/低}
138
191
  ```
139
192
 
140
- ### 6. 更新任务状态
193
+ ### 7. 更新任务状态
141
194
 
142
195
  获取当前时间:
143
196
 
@@ -169,7 +222,9 @@ date "+%Y-%m-%d %H:%M:%S%:z"
169
222
  - 发布 `{analysis-artifact}` 评论
170
223
  - 读取 `.agents/rules/issue-fields.md`,按流程 A 把 `task.md` 中所有非空的 Issue 字段(`priority`/`effort`/`start_date`/`target_date`)同步到 Issue(幂等;`has_push=false` 或取数/写入失败时跳过,不阻断)
171
224
 
172
- ### 7. 完成校验
225
+ ### 8. 完成校验
226
+
227
+ > 本步骤的 artifact gate 仅用于**场景 A**;场景 B 的校验见步骤 4(`check task-meta` + 显式证据),不在此跑 artifact gate。
173
228
 
174
229
  运行完成校验,确认任务产物和同步状态符合规范:
175
230
 
@@ -184,7 +239,9 @@ node .agents/scripts/validate-artifact.js gate analyze-task .agents/workspace/ac
184
239
 
185
240
  将校验输出保留在回复中作为当次验证输出。没有当次校验输出,不得声明完成。
186
241
 
187
- ### 8. 告知用户
242
+ ### 9. 告知用户
243
+
244
+ > 本步骤为**场景 A** 正常完成输出;场景 B 的单问输出见步骤 4。
188
245
 
189
246
  > 仅在校验通过后执行本步骤。
190
247
 
@@ -23,6 +23,16 @@ Version stamp rule: when creating or updating `task.md` frontmatter, read `.agen
23
23
 
24
24
  > If `{task-id}` matches `^[#]?[0-9]+$` (bare numeric or `#`-prefixed), follow the "SKILL parameter resolver" section of `.agents/rules/task-short-id.md`; treat `{task-id}` as the resolved full `TASK-YYYYMMDD-HHMMSS` form for every downstream command.
25
25
 
26
+ ## Step Start: Write the started Marker
27
+
28
+ After prerequisites pass and before this step's first artifact action, append a started marker to task.md `## Activity Log` (same base action as this step's done entry plus a ` [started]` suffix, note `started`):
29
+
30
+ ```
31
+ - {YYYY-MM-DD HH:mm:ss±HH:MM} — **Block Task [started]** by {agent} — started
32
+ ```
33
+
34
+ `ai task log` pairs it with the done entry written on completion onto one row (in progress → done). See the "Activity Log started / done dual-marker convention" in `.agents/rules/task-management.md`.
35
+
26
36
  ## Steps
27
37
 
28
38
  ### 1. Verify Task Exists
@@ -23,6 +23,16 @@ description: "标记任务为阻塞状态并记录原因"
23
23
 
24
24
  > 如果 `{task-id}` 入参匹配 `^[#]?[0-9]+$`(裸数字或带 `#` 前缀),先读取 `.agents/rules/task-short-id.md` 的「SKILL 入参解析」段执行解析;后续命令视 `{task-id}` 为解析后的全长 `TASK-YYYYMMDD-HHMMSS` 形式。
25
25
 
26
+ ## 步骤开始:写入 started 标记
27
+
28
+ 确认前置条件后、本步骤第一个产出动作之前,向 task.md `## 活动日志` 追加一条 started 标记(与本步骤 done 条目同基名 + ` [started]` 后缀,note 用 `started`):
29
+
30
+ ```
31
+ - {YYYY-MM-DD HH:mm:ss±HH:MM} — **Block Task [started]** by {agent} — started
32
+ ```
33
+
34
+ `ai task log` 会把它与完成时写入的 done 条目配对成一行(进行中 → 已完成)。约定见 `.agents/rules/task-management.md` 的「Activity Log started / done 双标记约定」。
35
+
26
36
  ## 执行步骤
27
37
  ### 1. 验证任务存在
28
38
 
@@ -17,6 +17,16 @@ Version stamp rule: when creating or updating `task.md` frontmatter, read `.agen
17
17
 
18
18
  > If `{task-id}` matches `^[#]?[0-9]+$` (bare numeric or `#`-prefixed), follow the "SKILL parameter resolver" section of `.agents/rules/task-short-id.md`; treat `{task-id}` as the resolved full `TASK-YYYYMMDD-HHMMSS` form for every downstream command.
19
19
 
20
+ ## Step Start: Write the started Marker
21
+
22
+ After prerequisites pass and before this step's first artifact action, append a started marker to task.md `## Activity Log` (same base action as this step's done entry plus a ` [started]` suffix, note `started`):
23
+
24
+ ```
25
+ - {YYYY-MM-DD HH:mm:ss±HH:MM} — **Cancel Task [started]** by {agent} — started
26
+ ```
27
+
28
+ `ai task log` pairs it with the done entry written on completion onto one row (in progress → done). See the "Activity Log started / done dual-marker convention" in `.agents/rules/task-management.md`.
29
+
20
30
  ## Steps
21
31
 
22
32
  ### 1. Verify Task Exists
@@ -17,6 +17,16 @@ description: "取消不再需要的任务并转移"
17
17
 
18
18
  > 如果 `{task-id}` 入参匹配 `^[#]?[0-9]+$`(裸数字或带 `#` 前缀),先读取 `.agents/rules/task-short-id.md` 的「SKILL 入参解析」段执行解析;后续命令视 `{task-id}` 为解析后的全长 `TASK-YYYYMMDD-HHMMSS` 形式。
19
19
 
20
+ ## 步骤开始:写入 started 标记
21
+
22
+ 确认前置条件后、本步骤第一个产出动作之前,向 task.md `## 活动日志` 追加一条 started 标记(与本步骤 done 条目同基名 + ` [started]` 后缀,note 用 `started`):
23
+
24
+ ```
25
+ - {YYYY-MM-DD HH:mm:ss±HH:MM} — **Cancel Task [started]** by {agent} — started
26
+ ```
27
+
28
+ `ai task log` 会把它与完成时写入的 done 条目配对成一行(进行中 → 已完成)。约定见 `.agents/rules/task-management.md` 的「Activity Log started / done 双标记约定」。
29
+
20
30
  ## 执行步骤
21
31
  ### 1. 验证任务存在
22
32
 
@@ -137,7 +147,7 @@ ai sandbox rm {branch}
137
147
 
138
148
  下一步 - 查看已转移任务:
139
149
  - Claude Code / OpenCode:/check-task {task-ref}
140
- - Gemini CLI:/{{project}}:check-task {task-ref}
150
+ - Gemini CLI:/agent-infra:check-task {task-ref}
141
151
  - Codex CLI:$check-task {task-ref}
142
152
  ```
143
153
 
@@ -11,6 +11,16 @@ Dismiss the specified Code Scanning (CodeQL) alert and record a justified reason
11
11
 
12
12
  > If `{task-id}` matches `^[#]?[0-9]+$` (bare numeric or `#`-prefixed), follow the "SKILL parameter resolver" section of `.agents/rules/task-short-id.md`; treat `{task-id}` as the resolved full `TASK-YYYYMMDD-HHMMSS` form for every downstream command.
13
13
 
14
+ ## Step Start: Write the started Marker
15
+
16
+ After prerequisites pass and before this step's first artifact action, append a started marker to task.md `## Activity Log` (same base action as this step's done entry plus a ` [started]` suffix, note `started`):
17
+
18
+ ```
19
+ - {YYYY-MM-DD HH:mm:ss±HH:MM} — **Close Codescan [started]** by {agent} — started
20
+ ```
21
+
22
+ `ai task log` pairs it with the done entry written on completion onto one row (in progress → done). See the "Activity Log started / done dual-marker convention" in `.agents/rules/task-management.md`.
23
+
14
24
  ## Execution Flow
15
25
 
16
26
  ### 1. Retrieve Alert Information
@@ -11,6 +11,16 @@ description: "关闭 Code Scanning 告警并记录理由"
11
11
 
12
12
  > 如果 `{task-id}` 入参匹配 `^[#]?[0-9]+$`(裸数字或带 `#` 前缀),先读取 `.agents/rules/task-short-id.md` 的「SKILL 入参解析」段执行解析;后续命令视 `{task-id}` 为解析后的全长 `TASK-YYYYMMDD-HHMMSS` 形式。
13
13
 
14
+ ## 步骤开始:写入 started 标记
15
+
16
+ 确认前置条件后、本步骤第一个产出动作之前,向 task.md `## 活动日志` 追加一条 started 标记(与本步骤 done 条目同基名 + ` [started]` 后缀,note 用 `started`):
17
+
18
+ ```
19
+ - {YYYY-MM-DD HH:mm:ss±HH:MM} — **Close Codescan [started]** by {agent} — started
20
+ ```
21
+
22
+ `ai task log` 会把它与完成时写入的 done 条目配对成一行(进行中 → 已完成)。约定见 `.agents/rules/task-management.md` 的「Activity Log started / done 双标记约定」。
23
+
14
24
  ## 执行流程
15
25
 
16
26
  ### 1. 获取告警信息