@fitlab-ai/agent-infra 0.9.11 → 0.9.12

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 (193) hide show
  1. package/README.md +6 -6
  2. package/README.zh-CN.md +6 -6
  3. package/dist/bin/internal-cli.js +5 -0
  4. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +71 -10
  5. package/dist/lib/defaults.json +4 -0
  6. package/dist/lib/git/workflow.js +43 -1
  7. package/dist/lib/init.js +1 -0
  8. package/dist/lib/internal/git-workflow.js +8 -1
  9. package/dist/lib/internal/platform-pr.js +8 -2
  10. package/dist/lib/internal/task-delivery.js +59 -0
  11. package/dist/lib/platform/github-client.js +7 -1
  12. package/dist/lib/platform/pr-checks.js +8 -5
  13. package/dist/lib/platform/pr-summary.js +12 -8
  14. package/dist/lib/platform/pull-requests.js +393 -91
  15. package/dist/lib/platform/verification-required.js +13 -2
  16. package/dist/lib/platform/verification-sync.js +9 -4
  17. package/dist/lib/pr-review/evidence-grading.js +12 -4
  18. package/dist/lib/sandbox/config.js +5 -0
  19. package/dist/lib/sandbox/control/lifecycle.js +29 -7
  20. package/dist/lib/server/process-state.js +2 -2
  21. package/dist/lib/task/artifact-lifecycle.js +2 -2
  22. package/dist/lib/task/commit-intent.js +100 -0
  23. package/dist/lib/task/commit-operation.js +195 -101
  24. package/dist/lib/task/create.js +33 -7
  25. package/dist/lib/task/decision-details.js +3 -48
  26. package/dist/lib/task/delivery-target.js +97 -0
  27. package/dist/lib/task/delivery.js +153 -0
  28. package/dist/lib/task/human-override.js +5 -2
  29. package/dist/lib/task/lifecycle.js +106 -9
  30. package/dist/lib/task/orchestration.js +55 -62
  31. package/dist/lib/task/pr-delivery-fact.js +182 -0
  32. package/dist/lib/task/review-finalization.js +4 -8
  33. package/dist/lib/task/review-fingerprint.js +8 -0
  34. package/dist/lib/task/verification-engine.js +48 -24
  35. package/dist/lib/task/verification-review.js +1 -1
  36. package/dist/lib/update.js +9 -0
  37. package/dist/lifecycle-build-manifest.json +3 -3
  38. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +105 -10
  39. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +12 -1
  40. package/lib/defaults.json +4 -0
  41. package/lib/git/workflow.ts +38 -1
  42. package/lib/init.ts +3 -0
  43. package/lib/internal/git-workflow.ts +7 -1
  44. package/lib/internal/platform-pr.ts +8 -1
  45. package/lib/internal/task-delivery.ts +53 -0
  46. package/lib/platform/github-client.ts +8 -1
  47. package/lib/platform/pr-checks.ts +7 -5
  48. package/lib/platform/pr-summary.ts +10 -7
  49. package/lib/platform/pull-requests.ts +425 -87
  50. package/lib/platform/verification-required.ts +12 -2
  51. package/lib/platform/verification-sync.ts +9 -4
  52. package/lib/pr-review/evidence-grading.ts +7 -4
  53. package/lib/sandbox/config.ts +7 -0
  54. package/lib/sandbox/control/lifecycle.ts +30 -8
  55. package/lib/server/process-state.ts +2 -2
  56. package/lib/task/artifact-lifecycle.ts +2 -2
  57. package/lib/task/commit-intent.ts +137 -0
  58. package/lib/task/commit-operation.ts +174 -87
  59. package/lib/task/create.ts +34 -9
  60. package/lib/task/decision-details.ts +2 -62
  61. package/lib/task/delivery-target.ts +130 -0
  62. package/lib/task/delivery.ts +160 -0
  63. package/lib/task/human-override.ts +5 -2
  64. package/lib/task/lifecycle.ts +93 -4
  65. package/lib/task/orchestration.ts +62 -65
  66. package/lib/task/pr-delivery-fact.ts +254 -0
  67. package/lib/task/review-finalization.ts +4 -14
  68. package/lib/task/review-fingerprint.ts +10 -0
  69. package/lib/task/verification-engine.ts +45 -28
  70. package/lib/task/verification-review.ts +2 -0
  71. package/lib/update.ts +10 -0
  72. package/package.json +1 -1
  73. package/templates/.agents/rules/README.en.md +4 -2
  74. package/templates/.agents/rules/README.zh-CN.md +4 -2
  75. package/templates/.agents/rules/create-issue.en.md +11 -2
  76. package/templates/.agents/rules/create-issue.zh-CN.md +24 -2
  77. package/templates/.agents/rules/issue-pr-commands.en.md +4 -17
  78. package/templates/.agents/rules/issue-sync.en.md +26 -5
  79. package/templates/.agents/rules/issue-sync.zh-CN.md +62 -5
  80. package/templates/.agents/rules/label-milestone-setup.en.md +15 -2
  81. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +15 -2
  82. package/templates/.agents/rules/local-artifact-repair.en.md +46 -0
  83. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +46 -0
  84. package/templates/.agents/rules/milestone-inference.en.md +12 -2
  85. package/templates/.agents/rules/milestone-inference.zh-CN.md +25 -3
  86. package/templates/.agents/rules/pr-sync.en.md +22 -13
  87. package/templates/.agents/rules/pr-sync.zh-CN.md +22 -1
  88. package/templates/.agents/rules/release-commands.en.md +42 -3
  89. package/templates/.agents/rules/release-commands.zh-CN.md +42 -3
  90. package/templates/.agents/rules/security-alerts.en.md +17 -2
  91. package/templates/.agents/rules/security-alerts.zh-CN.md +17 -2
  92. package/templates/.agents/rules/sync-content-generation.en.md +8 -0
  93. package/templates/.agents/rules/sync-content-generation.zh-CN.md +8 -0
  94. package/templates/.agents/rules/task-management.en.md +1 -1
  95. package/templates/.agents/rules/task-management.zh-CN.md +1 -1
  96. package/templates/.agents/scripts/security-alerts.github.sh +151 -0
  97. package/templates/.agents/scripts/security-alerts.sh +31 -0
  98. package/templates/.agents/skills/analyze-task/SKILL.en.md +1 -0
  99. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +1 -0
  100. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  101. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  102. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  103. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  104. package/templates/.agents/skills/code-task/SKILL.en.md +5 -2
  105. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +6 -3
  106. package/templates/.agents/skills/commit/SKILL.en.md +3 -3
  107. package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -3
  108. package/templates/.agents/skills/commit/config/verify.json +1 -1
  109. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +3 -3
  110. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +3 -3
  111. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  112. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  113. package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -2
  114. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -2
  115. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +2 -1
  116. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +2 -1
  117. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  118. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  119. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
  120. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
  121. package/templates/.agents/skills/complete-task/SKILL.en.md +10 -10
  122. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +10 -10
  123. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +2 -2
  124. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +2 -2
  125. package/templates/.agents/skills/create-pr/SKILL.en.md +4 -4
  126. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +4 -4
  127. package/templates/.agents/skills/create-task/SKILL.en.md +1 -0
  128. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -0
  129. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  130. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  131. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  132. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  133. package/templates/.agents/skills/init-labels/SKILL.en.md +9 -10
  134. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -10
  135. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +57 -1
  136. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +27 -1
  137. package/templates/.agents/skills/init-milestones/SKILL.en.md +3 -5
  138. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +3 -5
  139. package/templates/.agents/skills/plan-task/SKILL.en.md +1 -0
  140. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +1 -0
  141. package/templates/.agents/skills/review-analysis/SKILL.en.md +4 -3
  142. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +4 -3
  143. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +18 -0
  144. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +18 -0
  145. package/templates/.agents/skills/review-code/SKILL.en.md +7 -6
  146. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +7 -6
  147. package/templates/.agents/skills/review-code/reference/output-templates.en.md +19 -1
  148. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +19 -1
  149. package/templates/.agents/skills/review-code/reference/report-template.en.md +4 -2
  150. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +4 -2
  151. package/templates/.agents/skills/review-plan/SKILL.en.md +4 -3
  152. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +4 -3
  153. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +18 -0
  154. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +18 -0
  155. package/templates/.agents/skills/review-pr/SKILL.en.md +1 -0
  156. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +1 -0
  157. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +2 -2
  158. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +2 -2
  159. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -0
  160. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -0
  161. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  162. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  163. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +4 -0
  164. package/templates/.agents/skills/watch-pr/SKILL.en.md +4 -4
  165. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +4 -4
  166. package/templates/.agents/templates/task.en.md +5 -1
  167. package/templates/.agents/templates/task.zh-CN.md +5 -1
  168. package/templates/.agents/workflows/bug-fix.en.yaml +9 -8
  169. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +9 -8
  170. package/templates/.agents/workflows/feature-development.en.yaml +9 -8
  171. package/templates/.agents/workflows/feature-development.zh-CN.yaml +9 -8
  172. package/templates/.agents/workflows/refactoring.en.yaml +9 -8
  173. package/templates/.agents/workflows/refactoring.zh-CN.yaml +9 -8
  174. package/templates/.agents/rules/create-issue.github.en.md +0 -14
  175. package/templates/.agents/rules/create-issue.github.zh-CN.md +0 -27
  176. package/templates/.agents/rules/issue-pr-commands.github.en.md +0 -34
  177. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +0 -49
  178. package/templates/.agents/rules/issue-sync.github.en.md +0 -40
  179. package/templates/.agents/rules/issue-sync.github.zh-CN.md +0 -76
  180. package/templates/.agents/rules/label-milestone-setup.github.en.md +0 -60
  181. package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +0 -60
  182. package/templates/.agents/rules/milestone-inference.github.en.md +0 -15
  183. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +0 -27
  184. package/templates/.agents/rules/pr-checks-commands.github.en.md +0 -18
  185. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +0 -34
  186. package/templates/.agents/rules/pr-sync.github.en.md +0 -43
  187. package/templates/.agents/rules/pr-sync.github.zh-CN.md +0 -69
  188. package/templates/.agents/rules/release-commands.github.en.md +0 -44
  189. package/templates/.agents/rules/release-commands.github.zh-CN.md +0 -44
  190. package/templates/.agents/rules/security-alerts.github.en.md +0 -43
  191. package/templates/.agents/rules/security-alerts.github.zh-CN.md +0 -43
  192. /package/templates/.agents/rules/{issue-fields.github.en.md → issue-fields.en.md} +0 -0
  193. /package/templates/.agents/rules/{issue-fields.github.zh-CN.md → issue-fields.zh-CN.md} +0 -0
@@ -7,6 +7,8 @@ import { fileURLToPath } from "node:url";
7
7
 
8
8
  import {
9
9
  extractReviewBaseline,
10
+ extractReviewTargetHead,
11
+ extractReviewedHead,
10
12
  extractReviewDiffBase,
11
13
  extractReviewDiffFingerprint,
12
14
  extractReviewedSnapshotTree,
@@ -30,6 +32,8 @@ import { inspectDecisionDetailDuplicates } from "./decision-details.ts";
30
32
  import { loadVerificationConfig } from "./verification-config.ts";
31
33
  import { snapshotReview } from "../git/review-snapshot.ts";
32
34
  import { OrchestrationStateError, readRun } from "./orchestration.ts";
35
+ import { resolveDeliveryTarget } from "./delivery-target.ts";
36
+ import { readPrDeliveryFact } from "./pr-delivery-fact.ts";
33
37
 
34
38
  const TASK_ENUMS = {
35
39
  type: ["feature", "bugfix", "refactor", "docs", "chore"],
@@ -195,15 +199,14 @@ function validateCleanCompletionEvidence(run: any): string | null {
195
199
  || !shaPattern.test(evidence.headTree)
196
200
  || !shaPattern.test(evidence.worktreeTree)
197
201
  || !shaPattern.test(evidence.lastReviewedCommit)
198
- || !Number.isInteger(evidence.prNumber)
199
- || evidence.prNumber <= 0
200
- || !shaPattern.test(evidence.prHead)
202
+ || !(evidence.prNumber === null || (Number.isInteger(evidence.prNumber) && evidence.prNumber > 0))
203
+ || !(evidence.prHead === null || shaPattern.test(evidence.prHead))
201
204
  ) {
202
205
  return 'Clean completion evidence has an invalid structure';
203
206
  }
204
207
  if (
205
208
  evidence.head !== evidence.lastReviewedCommit
206
- || evidence.head !== evidence.prHead
209
+ || (evidence.prHead !== null && evidence.head !== evidence.prHead)
207
210
  || evidence.headTree !== evidence.worktreeTree
208
211
  ) {
209
212
  return 'Clean completion evidence does not bind matching commit and tree identities';
@@ -276,12 +279,8 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
276
279
  if (run.completionEvidence != null) {
277
280
  const evidenceError = validateCleanCompletionEvidence(run);
278
281
  if (evidenceError) return failResult('orchestration-evidence', evidenceError);
279
- } else if (run.status === 'completed' && (
280
- run.receipts.length === 0
281
- || run.receipts.at(-1)?.stage !== 'commit'
282
- || run.receipts.at(-1)?.status !== 'consumed'
283
- )) {
284
- return failResult('orchestration-evidence', 'Completed run requires a final consumed commit receipt');
282
+ } else if (run.status === 'completed') {
283
+ return failResult('orchestration-evidence', 'Completed run requires reviewed-head-clean completion evidence');
285
284
  }
286
285
  if (run.pendingDelegation && !['prepared', 'activated', 'stage-completed'].includes(run.pendingDelegation.status)) {
287
286
  return failResult('orchestration-evidence', `Pending receipt has unsafe status '${run.pendingDelegation.status}'`);
@@ -500,18 +499,18 @@ function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }: any): any {
500
499
  return failResult('required-pr-delivery', 'Project configuration is invalid');
501
500
  }
502
501
  const flow = projectConfig.prFlow;
503
- const status = String(task.metadata.pr_status || 'pending');
504
- const prNumber = parsePrNumber(task.metadata.pr_number);
502
+ const factRead = readPrDeliveryFact(task.metadata);
503
+ if (factRead.status === 'invalid') return failResult('required-pr-delivery', factRead.error.message);
504
+ const fact = factRead.status === 'valid' ? factRead.fact : null;
505
+ const status = fact?.state || 'unbound';
506
+ const prNumber = fact?.state === 'bound' ? fact.identity.number : null;
505
507
  if (flow === 'disabled') return passResult('required-pr-delivery', 'Pull request delivery is disabled by project policy');
506
- if (flow === 'required' && (status !== 'created' || prNumber === null)) {
508
+ if (flow === 'required' && (status !== 'bound' || prNumber === null)) {
507
509
  return failResult('required-pr-delivery', 'Project policy requires a bound pull request before completion');
508
510
  }
509
- if (flow !== 'required' && status === 'pending') {
511
+ if (flow !== 'required' && status === 'unbound') {
510
512
  return failResult('required-pr-delivery', 'Pull request delivery is pending; create a PR or explicitly skip it');
511
513
  }
512
- if (status === 'created' && prNumber === null) {
513
- return failResult('required-pr-delivery', 'Task claims a created pull request without a valid pr_number');
514
- }
515
514
  if (flow === 'required') {
516
515
  if (mode === 'gate') {
517
516
  return passResult('required-pr-delivery', 'Bound pull request shape is valid; merged-state inspection is reserved for hard preflight');
@@ -527,6 +526,7 @@ function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }: any): any {
527
526
  const pullRequest = inspected.pullRequest;
528
527
  const repository = inspected.platform.repository?.toLowerCase() || '';
529
528
  const taskBranch = String(task.metadata.branch || '').trim();
529
+ const deliveryBaseRef = String(task.metadata.delivery_base_ref || projectConfig.delivery?.baseRef || '').trim();
530
530
  if (inspected.status !== 'no-op' || !pullRequest || pullRequest.number !== prNumber) {
531
531
  return failResult('required-pr-delivery', 'Bound pull request identity could not be verified');
532
532
  }
@@ -535,6 +535,7 @@ function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }: any): any {
535
535
  || pullRequest.repository.toLowerCase() !== repository
536
536
  || pullRequest.base.repository.toLowerCase() !== repository
537
537
  || (taskBranch && pullRequest.head.ref !== taskBranch)
538
+ || (deliveryBaseRef && pullRequest.base.ref !== deliveryBaseRef)
538
539
  ) {
539
540
  return failResult('required-pr-delivery', 'Bound pull request identity does not match the task');
540
541
  }
@@ -1110,9 +1111,12 @@ function checkPostReviewCommit({ taskDir, config }: any): any {
1110
1111
 
1111
1112
  const task = loadTask(taskDir);
1112
1113
  if (!task.ok) return failResult("post-review-commit", task.message);
1114
+ const factRead = readPrDeliveryFact(task.metadata);
1115
+ if (factRead.status === 'invalid') return failResult("post-review-commit", factRead.error.message);
1116
+ const fact = factRead.status === 'valid' ? factRead.fact : null;
1113
1117
  const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
1114
1118
  const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repoRoot));
1115
- const hasPullRequest = Number(task.metadata.pr_number) > 0;
1119
+ const hasPullRequest = fact?.state === 'bound';
1116
1120
  let inspected: ReturnType<typeof inspectPlatformPullRequest> | null = null;
1117
1121
  if (hasPullRequest) {
1118
1122
  inspected = inspectPlatformPullRequest(task.metadata.id, { cwd: gitRoot });
@@ -1302,7 +1306,8 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
1302
1306
 
1303
1307
  const content = fs.readFileSync(resolvedArtifact.path, "utf8");
1304
1308
  const verdict = parseReviewVerdict(content);
1305
- const reviewBaseline = extractReviewBaseline(content);
1309
+ const reviewTargetHead = extractReviewTargetHead(content);
1310
+ const reviewReviewedHead = extractReviewedHead(content);
1306
1311
  const reviewDiffBase = extractReviewDiffBase(content);
1307
1312
  const reviewedFingerprint = extractReviewDiffFingerprint(content);
1308
1313
  const reviewedTree = extractReviewedSnapshotTree(content);
@@ -1311,30 +1316,42 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
1311
1316
  return failResult("review-fact", `Unsupported review verdict '${verdict}'`);
1312
1317
  }
1313
1318
 
1319
+ const deliveryRemote = String(task.metadata.delivery_remote || "").trim();
1320
+ const deliveryBaseRef = String(task.metadata.delivery_base_ref || "").trim();
1321
+ if (!deliveryRemote || !deliveryBaseRef) {
1322
+ return failResult("review-fact", "Task delivery target is not bound; re-run task branch preparation before review-code");
1323
+ }
1324
+ if (!reviewTargetHead || !reviewReviewedHead || !reviewDiffBase) {
1325
+ return failResult("review-fact", "Review fact must record target head, reviewed head, and diff base");
1326
+ }
1327
+
1314
1328
  let gitRoot;
1315
1329
  let head;
1316
1330
  let baseline;
1331
+ let targetHead;
1317
1332
  let diffBase;
1318
1333
  try {
1319
1334
  gitRoot = execFileSync("git", ["-C", taskDir, "rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim();
1320
1335
  head = execFileSync("git", ["-C", gitRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim();
1321
- baseline = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewBaseline}^{commit}`], { encoding: "utf8" }).trim();
1322
- diffBase = execFileSync(
1323
- "git",
1324
- ["-C", gitRoot, "rev-parse", `${reviewDiffBase || reviewBaseline}^{commit}`],
1325
- { encoding: "utf8" }
1326
- ).trim();
1336
+ const target = resolveDeliveryTarget(gitRoot, { remote: deliveryRemote, baseRef: deliveryBaseRef });
1337
+ if (!target.ok) throw new Error(target.message);
1338
+ const reviewedRef = reviewReviewedHead;
1339
+ baseline = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewedRef}^{commit}`], { encoding: "utf8" }).trim();
1340
+ targetHead = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewTargetHead}^{commit}`], { encoding: "utf8" }).trim();
1341
+ const computed = execFileSync("git", ["-C", gitRoot, "merge-base", baseline, targetHead], { encoding: "utf8" }).trim();
1342
+ diffBase = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewDiffBase}^{commit}`], { encoding: "utf8" }).trim();
1343
+ if (diffBase !== computed) throw new Error('saved review diff base does not match merge-base(reviewed head, target head)');
1327
1344
  } catch {
1328
1345
  return blockedResult(
1329
1346
  "review-fact",
1330
- `Unable to resolve review baseline '${reviewBaseline}' in the task repository; re-run review-code`
1347
+ `Unable to resolve saved review commits in the task repository; re-run review-code`
1331
1348
  );
1332
1349
  }
1333
1350
 
1334
1351
  if (baseline !== head) {
1335
1352
  return failResult(
1336
1353
  "review-fact",
1337
- `Review baseline ${baseline.slice(0, 8)} does not match current HEAD ${head.slice(0, 8)}; re-run review-code`
1354
+ `Reviewed head ${baseline.slice(0, 8)} does not match current HEAD ${head.slice(0, 8)}; re-run review-code`
1338
1355
  );
1339
1356
  }
1340
1357
 
@@ -1378,7 +1395,7 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
1378
1395
  if (cleanSnapshot && lastReviewedCommit !== baseline) {
1379
1396
  return failResult(
1380
1397
  "review-fact",
1381
- `Approved clean review must set task last_reviewed_commit to baseline ${baseline.slice(0, 8)}`
1398
+ `Approved clean review must set task last_reviewed_commit to reviewed head ${baseline.slice(0, 8)}`
1382
1399
  );
1383
1400
  }
1384
1401
  if (!cleanSnapshot && lastReviewedCommit) {
@@ -1,5 +1,7 @@
1
1
  export {
2
2
  extractReviewBaseline,
3
+ extractReviewTargetHead,
4
+ extractReviewedHead,
3
5
  extractReviewDiffBase,
4
6
  extractReviewDiffFingerprint,
5
7
  extractReviewedSnapshotTree,
package/lib/update.ts CHANGED
@@ -23,6 +23,7 @@ type UpdateConfig = {
23
23
  prFlow?: 'required' | 'disabled';
24
24
  sandbox?: Record<string, unknown>;
25
25
  task?: { shortIdLength: number };
26
+ delivery?: { remote?: string; baseRef?: string };
26
27
  labels?: Record<string, unknown>;
27
28
  files?: Partial<FileRegistry>;
28
29
  agentClients?: unknown;
@@ -33,6 +34,7 @@ type Defaults = {
33
34
  platform: { type: string };
34
35
  sandbox: Record<string, unknown>;
35
36
  task: { shortIdLength: number };
37
+ delivery: { remote: string; baseRef: string };
36
38
  labels: Record<string, unknown>;
37
39
  files: FileRegistry;
38
40
  };
@@ -83,10 +85,12 @@ async function cmdSync(): Promise<void> {
83
85
  const sandboxAdded = !config.sandbox;
84
86
  const taskAdded = !config.task;
85
87
  const labelsAdded = !config.labels;
88
+ const deliveryAdded = !config.delivery;
86
89
  if (platformAdded) config.platform = structuredClone(defaults.platform);
87
90
  if (sandboxAdded) config.sandbox = structuredClone(defaults.sandbox);
88
91
  if (taskAdded) config.task = structuredClone(defaults.task);
89
92
  if (labelsAdded) config.labels = structuredClone(defaults.labels);
93
+ if (deliveryAdded) config.delivery = structuredClone(defaults.delivery);
90
94
 
91
95
  const workflowPlan = planAgentClientReconciliation({
92
96
  config: config as unknown as Record<string, unknown>,
@@ -150,6 +154,9 @@ async function cmdSync(): Promise<void> {
150
154
  if (labelsAdded) {
151
155
  info(`Default labels.in config added to ${CONFIG_PATH}.`);
152
156
  }
157
+ if (deliveryAdded) {
158
+ info(`Default delivery target added to ${CONFIG_PATH}.`);
159
+ }
153
160
  } else {
154
161
  info(`File registry changed in ${CONFIG_PATH}.`);
155
162
  }
@@ -165,6 +172,9 @@ async function cmdSync(): Promise<void> {
165
172
  if (hasNewEntries && platformAdded) {
166
173
  info(`Default platform config added to ${CONFIG_PATH}.`);
167
174
  }
175
+ if (hasNewEntries && deliveryAdded) {
176
+ info(`Default delivery target added to ${CONFIG_PATH}.`);
177
+ }
168
178
  ok(`Updated ${CONFIG_PATH}`);
169
179
  }
170
180
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fitlab-ai/agent-infra",
3
- "version": "0.9.11",
3
+ "version": "0.9.12",
4
4
  "description": "Bootstrap tool for AI multi-tool collaboration infrastructure — works with Claude Code, Codex, Antigravity CLI, and OpenCode",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -13,6 +13,7 @@ so you can quickly find "which ones to read" without opening each file.
13
13
  - [`version-stamp.md`](version-stamp.md) — How and when to stamp `agent_infra_version`.
14
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
15
  - [`compatibility-policy.md`](compatibility-policy.md) — Compatibility by exception: admission evidence, implementation boundaries, exit conditions, and lifecycle review requirements.
16
+ - [`sync-content-generation.md`](sync-content-generation.md) — Producer-side Markdown constraints for task and lifecycle content synchronized to Issues.
16
17
 
17
18
  ## Issue / PR
18
19
 
@@ -29,11 +30,12 @@ so you can quickly find "which ones to read" without opening each file.
29
30
  - [`lifecycle-orchestration.md`](lifecycle-orchestration.md) — Fresh executor/reviewer, one-use receipt, pause/recovery, and safe endpoint rules for `run-task`.
30
31
  - [`review-handshake.md`](review-handshake.md) — Three-stage bidirectional review handshake: four-state disposition, symmetric evidence, disagreement ledger, convergence and post-review commit gate.
31
32
  - [`review-method.md`](review-method.md) — Shared three-stage review method: multi-pass review, risk lenses, traceability, and finding evidence.
33
+ - [`local-artifact-repair.md`](local-artifact-repair.md) — Model-per-case repair, mechanical safety gates, dynamic convergence, and result-output contract for failed review artifacts.
32
34
  - [`human-decision-context.md`](human-decision-context.md) — Self-contained context and canonical structure for new human-decision details.
33
35
  - [`task-short-id.md`](task-short-id.md) — Resolution, allocation and lifecycle of bare-number short ids.
34
36
  - [`milestone-inference.md`](milestone-inference.md) — Milestone inference for create-task / code-task / create-pr.
35
- - [`label-milestone-setup.md`](label-milestone-setup.md) — Platform commands to initialize labels / milestones.
36
- - [`security-alerts.md`](security-alerts.md) — Commands to import / close Dependabot and Code Scanning alerts.
37
+ - [`label-milestone-setup.md`](label-milestone-setup.md) — Shared entry points to initialize labels / milestones.
38
+ - [`security-alerts.md`](security-alerts.md) — Shared entry point to import / close dependency and code-scanning alerts.
37
39
 
38
40
  ## Commit & Release
39
41
 
@@ -12,6 +12,7 @@
12
12
  - [`version-stamp.md`](version-stamp.md) — `agent_infra_version` 版本戳的取值命令与写入时机。
13
13
  - [`debugging-guide.md`](debugging-guide.md) — 结构化调试流程:收集证据→形成假设→验证假设→修复根因,禁止盲目改代码重试。
14
14
  - [`compatibility-policy.md`](compatibility-policy.md) — 兼容性默认关闭:准入证据、实现边界、退出条件与生命周期审查要求。
15
+ - [`sync-content-generation.md`](sync-content-generation.md) — 同步到 Issue 的任务和生命周期 Markdown 生成约束。
15
16
 
16
17
  ## Issue / PR
17
18
 
@@ -28,11 +29,12 @@
28
29
  - [`lifecycle-orchestration.md`](lifecycle-orchestration.md) — `run-task` 的 fresh executor/reviewer、一次性 receipt、暂停恢复与安全终点规则。
29
30
  - [`review-handshake.md`](review-handshake.md) — 三阶段双向审查握手协议:四态处置、对称证据、分歧账本、收敛与 post-review commit 门禁。
30
31
  - [`review-method.md`](review-method.md) — 三阶段共享检视方法:多遍检视、风险镜头、追踪与 finding 证据契约。
32
+ - [`local-artifact-repair.md`](local-artifact-repair.md) — review artifact 失败后的模型逐例修复、机械安全门、动态收敛与结果输出契约。
31
33
  - [`human-decision-context.md`](human-decision-context.md) — 新建人工裁决详情的自足上下文与规范结构。
32
34
  - [`task-short-id.md`](task-short-id.md) — 裸数字任务短号的解析、分配与生命周期。
33
35
  - [`milestone-inference.md`](milestone-inference.md) — create-task / code-task / create-pr 的 milestone 推断。
34
- - [`label-milestone-setup.md`](label-milestone-setup.md) — 初始化 label / milestone 的平台命令集。
35
- - [`security-alerts.md`](security-alerts.md) — 导入 / 关闭 Dependabot 与 Code Scanning 告警的命令集。
36
+ - [`label-milestone-setup.md`](label-milestone-setup.md) — 初始化 label / milestone 的共享入口。
37
+ - [`security-alerts.md`](security-alerts.md) — 导入 / 关闭依赖与代码扫描告警的共享入口。
36
38
 
37
39
  ## 提交与发布
38
40
 
@@ -1,5 +1,14 @@
1
1
  # Issue Creation
2
2
 
3
- This code platform does not provide an Issue adapter. `platform-issue create` returns a structured no-op/degraded result.
3
+ > `--agent` values are defined in `.agents/rules/task-management.md` under “Collaborator Token Specification”.
4
4
 
5
- `create-task` skips the cascade Issue creation step on this platform; the local `task.md` remains a valid artifact. If you later want to bind the task to an Issue, manually write `issue_number` into `task.md` and the subsequent skills (`commit` / `code-task` / `complete-task`, etc.) will pick up Issue metadata syncing through the existing cascade rules.
5
+ After `create-task` writes task.md, create and initialize the Issue through declarative internal intents:
6
+
7
+ ```bash
8
+ agent-infra-internal platform-issue create {task-id} --agent {standard-agent-token}
9
+ agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} --status waiting-for-triage --assignees current --milestone initial --issue-type --fields
10
+ ```
11
+
12
+ The core reads only persisted task identity, title, type, description, and requirements, and reuses deterministic `ai task issue-body` rendering. It owns template selection, upstream/capabilities, duplicate prevention, POST outcome boundaries, response validation, and atomic `issue_number` binding.
13
+
14
+ `planned|applied|no-op|degraded` exit 0, `failed` exits 1, and `blocked` exits 2. Callers must not fall back to direct platform CLI or GraphQL orchestration.
@@ -1,5 +1,27 @@
1
1
  # Issue 创建
2
2
 
3
- 当前代码平台未提供 Issue 适配器;`platform-issue create` 返回结构化 no-op/degraded 结果。
3
+ > `--agent` 取值见 `.agents/rules/task-management.md`「合作者 token 规范」。
4
4
 
5
- `create-task` 在本平台上会跳过级联创建 Issue 步骤;本地 `task.md` 仍然是有效产物。如果将来需要把任务绑定到一个 Issue,可手动在 `task.md` 中写入 `issue_number`,后续技能(`commit` / `code-task` / `complete-task` 等)会按既有的级联同步规则自动接管 Issue 元数据更新。
5
+ 当 `create-task` 完成本地 `task.md` 落盘后,通过声明式内部命令创建 Issue:
6
+
7
+ ```bash
8
+ agent-infra-internal platform-issue create {task-id} --agent {standard-agent-token}
9
+ ```
10
+
11
+ 命令只从已落盘 task.md 读取身份、标题、类型、描述与需求,并复用 `ai task issue-body` 的确定性正文渲染。它负责模板选择、upstream/capability、已有绑定检查、非幂等 POST 边界、响应身份校验及通过任务写入内核回写 `issue_number`。
12
+
13
+ 创建后的初始元数据使用同一适配层同步:
14
+
15
+ ```bash
16
+ agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} \
17
+ --status waiting-for-triage --assignees current --milestone initial --issue-type --fields
18
+ ```
19
+
20
+ ## 结果处理
21
+
22
+ - `planned|applied|no-op|degraded`:exit 0;调用方按 operations 继续评论同步。
23
+ - `failed`:exit 1;调用方登记 `ISSUE_CREATE_FAILED` warning,不伪造绑定。
24
+ - `blocked`:exit 2;认证、网络或创建 outcome 不确定,调用方保留远端 identity 证据并停止盲目重试。
25
+ - 已绑定有效 Issue 时只验证绑定并返回 no-op,绝不重复创建。
26
+
27
+ 自定义或空平台返回 no-op/degraded;调用方不得回退到直接平台 CLI 或 GraphQL 编排。
@@ -12,36 +12,23 @@ agent-infra-internal platform-pr inspect {task-id}
12
12
 
13
13
  ## Create or recover
14
14
 
15
- Write the title and body to files, then run:
16
-
17
15
  ```bash
18
16
  agent-infra-internal platform-pr create {task-id} \
19
17
  --agent {standard-agent-token} --base {target-branch} --head {current-branch} \
20
18
  --title-file {title-file} --body-file {body-file}
21
19
  ```
22
20
 
23
- The core performs exact upstream/head/base lookup first. One match is reused, zero creates, and multiple matches fail closed. Unknown create outcomes are reconciled by the same exact identity rather than retried blindly. `--dry-run` returns only the plan.
21
+ The core performs exact upstream/head/base lookup. One match is reused, zero creates, and multiple matches fail closed. Unknown create outcomes are reconciled by exact identity. `--dry-run` returns only the plan.
24
22
 
25
- ## Bind
23
+ ## Bind and synchronize
26
24
 
27
25
  ```bash
28
26
  agent-infra-internal platform-pr bind {task-id} --pr {pr-number} --agent {standard-agent-token}
29
- ```
30
-
31
- Conflicting bindings fail without changing `task.md`.
32
27
 
33
- ## Synchronize metadata
34
-
35
- ```bash
36
28
  agent-infra-internal platform-pr sync {task-id} \
37
29
  --agent {standard-agent-token} --metadata --closing-issue
38
30
  ```
39
31
 
40
- The core copies type / `in:` labels, assignee, a specific milestone, and the closing association from the linked Issue. Permission-bound operations report `skipped` under top-level `degraded`; the Issue is never updated in reverse.
41
-
42
- ## Status contract
32
+ Conflicting bindings do not change `task.md`. Metadata comes from the linked Issue, permission-bound items degrade independently, and an already-created PR is never rolled back.
43
33
 
44
- - `planned|applied|no-op|degraded`: exit 0.
45
- - `failed`: exit 1.
46
- - `blocked`: exit 2 for authentication, network, or unknown outcome.
47
- - Metadata or summary failures never roll back an already-created PR.
34
+ Statuses `planned|applied|no-op|degraded` exit 0, `failed` exits 1, and `blocked` exits 2.
@@ -1,8 +1,8 @@
1
1
  # Issue Sync
2
2
 
3
- ## Marker Registry
3
+ > `--agent` values are defined in `.agents/rules/task-management.md` under “Collaborator Token Specification”.
4
4
 
5
- These hidden markers are the canonical registry for Issue synchronization:
5
+ ## Marker Registry
6
6
 
7
7
  | Key | Marker |
8
8
  |---|---|
@@ -12,8 +12,29 @@ These hidden markers are the canonical registry for Issue synchronization:
12
12
  | `summary` | `<!-- sync-issue:{task-id}:summary -->` |
13
13
  | `cancel` | `<!-- sync-issue:{task-id}:cancel -->` |
14
14
 
15
- Callers should refer to the marker key in skill prose and keep concrete marker strings in this rule or the platform adapter defaults.
15
+ `pr-review` content is synced only as an Issue artifact comment (via the `artifact` / `artifactChunk` markers) and is never a `restore-task` recovery source; restore still accepts only an Issue number and reads only registered Issue markers, with no PR source.
16
+
17
+ Comments use `platform-comment`; Issue resources use `platform-issue`:
18
+
19
+ ```bash
20
+ agent-infra-internal platform-issue inspect {task-id}
21
+ agent-infra-internal platform-issue create {task-id} --agent {standard-agent-token}
22
+ agent-infra-internal platform-issue bind {task-id} --issue {number} --agent {standard-agent-token}
23
+ agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} {desired-state-flags}
24
+ ```
25
+
26
+ The core owns status/in labels, assignees, milestones, Issue Type, pinned fields, requirements, state, capabilities, dry-run, retries, errors, and idempotency. Omitted flags preserve values; `none` explicitly clears them. Status labels converge to at most one, and ambiguous requirement identity fails closed.
27
+
28
+ `planned|applied|no-op|degraded` exit 0; `failed` exits 1; `blocked` exits 2.
29
+
30
+ Map material degraded/failed/blocked results to workflow warnings through the structured intent; callers must not edit warning rows directly:
31
+
32
+ ```bash
33
+ agent-infra-internal task-warning {task-id} add \
34
+ --step issue-sync --severity {severity} --code {code} \
35
+ --target {target} --message {message} --action {action}
36
+ ```
16
37
 
17
- This code platform does not provide an Issue adapter. `platform-issue` returns structured no-op/degraded operations.
38
+ ## Backfill
18
39
 
19
- Issue metadata, labels, milestones, assignees, and comments are skipped for custom platforms unless you provide matching `.{platform}.en.md` rule templates and platform adapters. Continue writing local task artifacts normally.
40
+ During completion, artifact comments are replayed with `--kind artifact --artifact <file> --backfill`. If the remote Issue has no matching marker, the core creates a comment with a historical-backfill notice. If a valid base or chunk marker set already exists, the core returns `no-op` and preserves the existing bodies and chunks. Marker conflicts still fail without writes.
@@ -1,8 +1,10 @@
1
- # Issue 同步
1
+ # Issue 同步规则
2
+
3
+ > `--agent` 取值见 `.agents/rules/task-management.md`「合作者 token 规范」。
2
4
 
3
5
  ## Marker 注册表
4
6
 
5
- 以下隐藏标记是 Issue 同步的唯一权威注册表:
7
+ 以下 key 及格式是 Issue 评论身份的兼容契约;调用方只传 key/资源,不自行拼 marker。
6
8
 
7
9
  | Key | Marker |
8
10
  |---|---|
@@ -12,8 +14,63 @@
12
14
  | `summary` | `<!-- sync-issue:{task-id}:summary -->` |
13
15
  | `cancel` | `<!-- sync-issue:{task-id}:cancel -->` |
14
16
 
15
- Skill 正文应引用 marker key,具体 marker 字符串只保留在本规则或平台适配器默认值中。
17
+ `prSummary` 属于 `.agents/rules/pr-sync.md`,本规则不实现 PR 聚合。
18
+
19
+ `pr-review` 原文只通过 `artifact` / `artifactChunk` marker 同步为 Issue artifact 评论,不作为 `restore-task` 恢复来源;恢复仍只接受 Issue 编号并只读注册的 Issue marker,不新增 PR 来源。
20
+
21
+ ## 平台 intent
22
+
23
+ 平台 upstream、认证、capability、分页、marker 查找、幂等 create/update、分片、重试与错误分类由 typed platform core 统一处理:
24
+
25
+ ```bash
26
+ agent-infra-internal platform-context resolve [--cwd <path>]
27
+ agent-infra-internal platform-comment list --issue <N> [--cwd <path>]
28
+ agent-infra-internal platform-comment owner <task-ref>
29
+ agent-infra-internal platform-comment sync <task-ref> \
30
+ --kind task|artifact|summary|cancel --agent {standard-agent-token} \
31
+ [--artifact <canonical.md>] [--body-file <path|->] [--backfill]
32
+ ```
33
+
34
+ - `applied|no-op|degraded` → exit 0;`failed` → exit 1;`blocked` → exit 2。
35
+ - task 评论保持 `<details>` frontmatter 可逆格式;artifact 原文内联并在超过 profile 上限时使用 `artifactChunk`。
36
+ - 相同 intent 重放必须收敛为 `no-op`;重复 marker 返回 `COMMENT_MARKER_CONFLICT` 且不写入。
37
+ - 外部贡献者锁定统一使用 `platform-comment owner`;不同作者且无 triage 时返回 `COMMENT_OWNER_CONFLICT`。
38
+
39
+ ## 降级与告警
40
+
41
+ 平台结果不直接写 task.md。调用方在有关联任务时把关键失败映射为 workflow warning:
42
+
43
+ - capability 不足:`IMPORTANT / PERMISSION_DEGRADED`
44
+ - 评论同步永久失败:`ACTION_REQUIRED / COMMENT_SYNC_FAILED`
45
+ - 网络重试耗尽:`ACTION_REQUIRED / NETWORK_RETRY_EXHAUSTED`
46
+
47
+ 使用 `agent-infra-internal task-warning {task-id} add ...` 登记;不得手写 warning 表。
48
+
49
+ ```bash
50
+ agent-infra-internal task-warning {task-id} add \
51
+ --step issue-sync --severity {severity} --code {code} \
52
+ --target {target} --message {message} --action {action}
53
+ ```
54
+
55
+ ## Issue 元数据 intent
56
+
57
+ 所有 Issue 元数据写入统一使用:
58
+
59
+ ```bash
60
+ agent-infra-internal platform-issue inspect {task-id}
61
+ agent-infra-internal platform-issue create {task-id} --agent {standard-agent-token}
62
+ agent-infra-internal platform-issue bind {task-id} --issue {number} --agent {standard-agent-token}
63
+ agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} {desired-state-flags}
64
+ ```
65
+
66
+ `sync` 支持 status/in labels、assignee、milestone、Issue Type、pinned fields、需求复选框与 Issue state。省略 flag 表示 preserve,`none` 表示显式清空。适配层统一处理集合差集、动态 schema、权限降级、dry-run、重试、错误分类与幂等重放;SKILL 不得拼装平台 CLI、GraphQL 或权限分支。
67
+
68
+ - `planned|applied|no-op|degraded` → exit 0
69
+ - `failed` → exit 1
70
+ - `blocked` → exit 2
71
+
72
+ status labels 始终至多一个;关闭后不保留 status label。`in:` labels 只从项目允许映射与仓库实际 labels 交集产生。需求复选框以 task.md 原文为身份,歧义时 fail closed。
16
73
 
17
- 当前代码平台未提供 Issue 适配器;`platform-issue` 返回结构化 no-op/degraded operations。
74
+ ## 补发
18
75
 
19
- 自定义平台会跳过 Issue 元数据、标签、里程碑、负责人和评论同步,除非你提供匹配的 `.{platform}.zh-CN.md` 规则模板和平台适配器。请继续正常写入本地任务产物。
76
+ complete-task 按 artifact catalog 时间线遍历本地已有产物:task 使用 `--kind task`,其余使用 `--kind artifact --artifact <file> --backfill`;最后用 `--kind summary --body-file <path>` 原地同步交付摘要。artifact backfill 在远端缺少 marker 时创建带“历史产物补发”提示的评论;已存在合法 marker 集合时保持原评论和分片不变并返回 `no-op`;marker 冲突仍失败。该判定由 core 完成,不由 Skill 扫描评论或拼标题。
@@ -1,5 +1,18 @@
1
1
  # Label and Milestone Setup
2
2
 
3
- This code platform does not provide built-in label or milestone setup.
3
+ Read this rule before initializing labels or milestones, or before changing milestone metadata during release work.
4
4
 
5
- Initialization of remote labels and milestones is skipped for custom platforms unless you provide matching `.{platform}.en.md` rule templates and scripts. Local task workflow files remain usable without remote metadata setup.
5
+ ## Entry points
6
+
7
+ Use the shared scripts rather than composing provider commands in a skill:
8
+
9
+ ```text
10
+ bash .agents/skills/init-labels/scripts/init-labels.sh [--cleanup-stale-in]
11
+ bash .agents/skills/init-milestones/scripts/init-milestones.sh "$ARGUMENTS"
12
+ ```
13
+
14
+ `init-labels.sh` reads the repository's `labels.in` configuration, creates or updates the declared `in:` labels, and preserves unrelated labels. `--cleanup-stale-in` is destructive and may only be passed after explicit confirmation; it removes stale `in:` labels that are no longer declared.
15
+
16
+ `init-milestones.sh` owns milestone inference and the provider-specific write path. Callers must pass the requested arguments through unchanged and must not rebuild milestone discovery, ordering, branch ancestry, or write logic.
17
+
18
+ Both scripts return a stable status. A successful no-op is still success; a degraded result must be reported without claiming that remote metadata was changed. Failed or cancelled operations must not be reported as completed.
@@ -1,5 +1,18 @@
1
1
  # Label 和 Milestone 初始化
2
2
 
3
- 当前代码平台未内置标签或里程碑初始化支持。
3
+ 在初始化 label、milestone,或在发布工作中修改 milestone 元数据前,先阅读本规则。
4
4
 
5
- 自定义平台会跳过远端标签和里程碑初始化,除非你提供匹配的 `.{platform}.zh-CN.md` 规则模板和脚本。即使没有远端元数据初始化,本地任务工作流文件仍可使用。
5
+ ## 入口
6
+
7
+ SKILL 应调用共享脚本,不得自行拼装 provider 命令:
8
+
9
+ ```text
10
+ bash .agents/skills/init-labels/scripts/init-labels.sh [--cleanup-stale-in]
11
+ bash .agents/skills/init-milestones/scripts/init-milestones.sh "$ARGUMENTS"
12
+ ```
13
+
14
+ `init-labels.sh` 读取仓库的 `labels.in` 配置,创建或更新声明的 `in:` label,并保留无关 label。`--cleanup-stale-in` 具有破坏性,只有在得到明确确认后才能传入;它会删除不再声明的过期 `in:` label。
15
+
16
+ `init-milestones.sh` 负责 milestone 推断和 provider 写入路径。调用方应原样传递请求参数,不得重新实现 milestone 发现、排序、分支祖先判断或写入逻辑。
17
+
18
+ 两个脚本都返回稳定状态。成功的 no-op 仍算成功;degraded 结果必须如实报告,不能声称远端元数据已变更。失败或取消的操作不得报告为已完成。
@@ -0,0 +1,46 @@
1
+ # General Rule - Model-Driven Local Artifact Repair
2
+
3
+ This rule applies only when `review-analysis`, `review-plan`, or `review-code` handles a finalizer failure for **the same controlled review artifact**. It does not apply to `task.md`, the ledger, receipts, source code, Git, platform resources, or lifecycle state.
4
+
5
+ ## Authorization Boundary
6
+
7
+ - The finalizer only reads facts, validates state, normalizes successful results, and performs atomic writes. It does not maintain a recoverable-error allowlist, infer repairability, or choose report content to delete.
8
+ - The initial finalizer call is not counted as a repair attempt. Editing is allowed only after the mechanical safety gates pass and the model explicitly determines that the current problem can be solved by a minimal, explainable artifact change.
9
+ - The model may edit only the one ordinary review artifact declared by the current review skill, and the file must be inside the current task directory. It must not edit `task.md`, the review disagreement ledger, receipts, source code, other reports, or remote resources.
10
+ - `changed=false`, an error code, or a format shape is diagnostic evidence, not automatic authorization. The model must judge each case using the complete diagnostic, artifact content, and context.
11
+
12
+ ## Non-bypassable Mechanical Safety Gates
13
+
14
+ Before every model edit, confirm that:
15
+
16
+ 1. the finalizer returned a failure and no artifact operation was committed;
17
+ 2. the task, stage, artifact, review round, identity, and provenance still match;
18
+ 3. the target is an ordinary file inside the current task directory, with no concurrency conflict, permission error, I/O uncertainty, or target replacement;
19
+ 4. the change does not alter human-decision semantics, decision-detail or ledger identity, and does not involve task state, receipts, Git, platform, or any other external side effect. A known and verifiable pending human decision may remain when the model proves the edit is unrelated to that decision.
20
+
21
+ If any condition fails, stop immediately without invoking a model edit. The model cannot bypass these gates.
22
+
23
+ ## Dynamic Convergence Loop
24
+
25
+ 1. Run the initial finalizer with the fixed task, stage, artifact, and orchestrated intent.
26
+ 2. On success, use that complete result for the existing completion gates; do not rescan the ledger or write summary fields manually.
27
+ 3. On failure with the safety gates passed, let the model read the structured diagnostic, current artifact, and required context, then decide whether to repair or stop. It must explain the scope and reason for the proposed change.
28
+ 4. If the model continues, perform one minimal edit to the artifact. Increment `repairAttempts` only when the file bytes actually change, then rerun the same finalizer intent completely.
29
+ 5. Re-run every safety check after each retry. A new, independent problem still limited to the same artifact may be offered to the model for another decision; the previous repairability decision must not be reused automatically.
30
+ 6. Stop immediately when the model cannot establish safety or identifies an environment, permission, concurrency, identity, provenance, unknown-state, uncertain human-decision semantics/details, or other non-local problem. A known human decision is not itself a stop condition.
31
+ 7. Stop when the diagnostic or artifact fingerprint repeats, no byte-level progress occurs, or the model cannot propose a verifiable minimal change.
32
+ 8. Allow at most 8 actual artifact edits per skill invocation as an emergency circuit breaker. This cap only prevents infinite loops and resource exhaustion; it is not a normal business stop condition and does not mean that at most eight problems may be repaired. Preserve the final structured diagnostic when the cap is reached.
33
+
34
+ The repair count exists only in the in-memory context of the current skill invocation. Do not write it to `task.md`, the ledger, or a public receipt. Do not create different normal budgets by error code, skill, or problem type.
35
+
36
+ ## Completion Events and User Output
37
+
38
+ - After the final complete finalizer result succeeds, publish the review completed event using that same result's provenance, ledger state, verdict, and counts. Generate cross-stage next-step commands only when `stageStatus.canAdvance=true` and the verdict is Approved; when `canAdvance=false`, still record the result and route to same-stage revision/review.
39
+ - On failure, model stop, lack of progress, repeated diagnostics, or the emergency cap, do not publish a completed event, advance the lifecycle, generate cross-stage commands, or fabricate an approval.
40
+ - Stopping advancement does not discard review results. User output must show the artifact path, the last safely readable summary/findings, actual `repairAttempts`, the last structured diagnostic, and the stop reason.
41
+ - If the summary cannot be safely parsed, show only the artifact path and the raw structured diagnostic; do not infer counts or add a conclusion, and state that lifecycle advancement stopped while the artifact remains available.
42
+ - A stop path may only suggest rerunning the current review skill or handling the issue manually. It must not invoke cross-stage helpers such as `code-task` or `complete-task`.
43
+
44
+ ## Lifecycle Isolation
45
+
46
+ `complete-task`, alert closing, task restoration, and other task-lifecycle/task-finalization entry points involve task state, receipts, remote results, or archival side effects and do not consume this rule. They retain their own hard-stop, same-intent retry, and unknown-state semantics.