@fitlab-ai/agent-infra 0.12.1 → 0.12.2

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 (303) hide show
  1. package/README.md +0 -2
  2. package/README.zh-CN.md +0 -2
  3. package/dist/bin/internal-cli.js +2 -17
  4. package/dist/lib/agent-clients/adapter.js +0 -13
  5. package/dist/lib/agent-clients/adapters/antigravity-cli.js +0 -5
  6. package/dist/lib/agent-clients/adapters/claude-code-credentials.js +0 -17
  7. package/dist/lib/agent-clients/adapters/claude-code.js +0 -9
  8. package/dist/lib/agent-clients/adapters/codex.js +0 -52
  9. package/dist/lib/agent-clients/adapters/opencode.js +0 -5
  10. package/dist/lib/agent-clients/adapters/traecli.js +0 -5
  11. package/dist/lib/agent-clients/config.js +19 -54
  12. package/dist/lib/agent-clients/registry.js +1 -12
  13. package/dist/lib/agent-clients/schema.js +0 -18
  14. package/dist/lib/agent-clients/tokens.js +1 -2
  15. package/dist/lib/agent-clients/types.js +0 -1
  16. package/dist/lib/decide.js +2 -0
  17. package/dist/lib/git/worktree-identity.js +1 -9
  18. package/dist/lib/internal/agent-client.js +2 -62
  19. package/dist/lib/internal/cli-route-inventory.js +1 -5
  20. package/dist/lib/internal/manual-validation.js +18 -10
  21. package/dist/lib/internal/task-create.js +1 -1
  22. package/dist/lib/internal/task-event.js +1 -8
  23. package/dist/lib/internal/task-finalization.js +0 -1
  24. package/dist/lib/internal/task-lifecycle.js +2 -2
  25. package/dist/lib/internal/task-operation-registry.js +4 -20
  26. package/dist/lib/internal/task-review.js +4 -4
  27. package/dist/lib/platform/comment-safety.js +1 -7
  28. package/dist/lib/platform/in-label-sync.js +1 -14
  29. package/dist/lib/platform/issue-comments.js +1 -16
  30. package/dist/lib/platform/issues.js +1 -1
  31. package/dist/lib/platform/operation-coordinator.js +4 -2
  32. package/dist/lib/platform/pr-change-report.js +1 -4
  33. package/dist/lib/platform/pr-checks.js +2 -8
  34. package/dist/lib/platform/provider-validation.js +0 -20
  35. package/dist/lib/platform/pull-requests.js +73 -84
  36. package/dist/lib/platform/releases.js +1 -43
  37. package/dist/lib/platform/verification-required.js +0 -2
  38. package/dist/lib/platform/verification-sync.js +1 -79
  39. package/dist/lib/process-data/normalize.js +1 -185
  40. package/dist/lib/process-data/privacy.js +1 -16
  41. package/dist/lib/process-data/sources.js +2 -279
  42. package/dist/lib/render.js +0 -12
  43. package/dist/lib/run/index.js +15 -10
  44. package/dist/lib/run/skills.js +0 -3
  45. package/dist/lib/sandbox/commands/create.js +40 -53
  46. package/dist/lib/sandbox/commands/list-running.js +0 -18
  47. package/dist/lib/sandbox/commands/start.js +7 -8
  48. package/dist/lib/sandbox/constants.js +0 -6
  49. package/dist/lib/sandbox/control/client.js +0 -1
  50. package/dist/lib/sandbox/control/container-identity.js +1 -16
  51. package/dist/lib/sandbox/control/executor.js +0 -4
  52. package/dist/lib/sandbox/control/identity-sentinel.js +0 -7
  53. package/dist/lib/sandbox/control/lifecycle.js +21 -37
  54. package/dist/lib/sandbox/control/native-file-lock.js +0 -3
  55. package/dist/lib/sandbox/control/server.js +18 -38
  56. package/dist/lib/sandbox/control/state.js +1 -9
  57. package/dist/lib/sandbox/dockerfile.js +0 -6
  58. package/dist/lib/sandbox/engine.js +0 -14
  59. package/dist/lib/sandbox/engines/docker-exact-discovery.js +1 -4
  60. package/dist/lib/sandbox/engines/wsl2-paths.js +0 -3
  61. package/dist/lib/sandbox/recovery.js +24 -26
  62. package/dist/lib/sandbox/removal.js +11 -519
  63. package/dist/lib/sandbox/task-resolver.js +0 -41
  64. package/dist/lib/sandbox/tools.js +1 -4
  65. package/dist/lib/sandbox/workspace-view.js +1 -2
  66. package/dist/lib/server/display.js +0 -6
  67. package/dist/lib/task/activity-intent.js +45 -40
  68. package/dist/lib/task/activity-log.js +9 -16
  69. package/dist/lib/task/artifact-command.js +1 -1
  70. package/dist/lib/task/artifact-lifecycle.js +61 -63
  71. package/dist/lib/task/artifact-name.js +0 -6
  72. package/dist/lib/task/artifact-operations.js +3 -3
  73. package/dist/lib/task/capabilities.js +4 -5
  74. package/dist/lib/task/commands/log.js +0 -6
  75. package/dist/lib/task/commands/status.js +17 -60
  76. package/dist/lib/task/commit-operation.js +28 -39
  77. package/dist/lib/task/completion-facts.js +56 -43
  78. package/dist/lib/task/control-authority.js +23 -256
  79. package/dist/lib/task/control-recovery.js +3 -5
  80. package/dist/lib/task/create.js +2 -4
  81. package/dist/lib/task/decision-intents.js +8 -9
  82. package/dist/lib/task/delivery-target.js +1 -40
  83. package/dist/lib/task/events.js +84 -107
  84. package/dist/lib/task/finalization.js +44 -8
  85. package/dist/lib/task/ledger-intents.js +1 -1
  86. package/dist/lib/task/lifecycle-execution.js +38 -33
  87. package/dist/lib/task/lifecycle.js +49 -41
  88. package/dist/lib/task/local-artifact-finalization.js +1 -4
  89. package/dist/lib/task/manual-validation-evidence.js +1 -37
  90. package/dist/lib/task/platform-operation-recovery.js +67 -24
  91. package/dist/lib/task/pr-delivery-fact.js +2 -5
  92. package/dist/lib/task/qualification-confirmation.js +5 -7
  93. package/dist/lib/task/resolve-ref.js +1 -25
  94. package/dist/lib/task/review-command.js +2 -2
  95. package/dist/lib/task/review-finalization.js +1 -21
  96. package/dist/lib/task/review-fingerprint.js +0 -4
  97. package/dist/lib/task/secure-fs.js +0 -56
  98. package/dist/lib/task/short-id.js +1 -39
  99. package/dist/lib/task/skill-scope.js +0 -1
  100. package/dist/lib/task/verification-engine.js +58 -282
  101. package/dist/lib/task/verification.js +6 -3
  102. package/dist/lib/task/write.js +11 -1
  103. package/lib/agent-clients/adapter.ts +0 -76
  104. package/lib/agent-clients/adapters/antigravity-cli.ts +0 -5
  105. package/lib/agent-clients/adapters/claude-code-credentials.ts +0 -19
  106. package/lib/agent-clients/adapters/claude-code.ts +0 -9
  107. package/lib/agent-clients/adapters/codex.ts +0 -56
  108. package/lib/agent-clients/adapters/opencode.ts +0 -5
  109. package/lib/agent-clients/adapters/traecli.ts +0 -5
  110. package/lib/agent-clients/config.ts +20 -61
  111. package/lib/agent-clients/registry.ts +1 -34
  112. package/lib/agent-clients/schema.ts +0 -18
  113. package/lib/agent-clients/tokens.ts +1 -2
  114. package/lib/agent-clients/types.ts +0 -15
  115. package/lib/decide.ts +1 -0
  116. package/lib/git/worktree-identity.ts +0 -10
  117. package/lib/internal/agent-client.ts +2 -70
  118. package/lib/internal/cli-route-inventory.ts +1 -4
  119. package/lib/internal/manual-validation.ts +16 -9
  120. package/lib/internal/task-create.ts +0 -1
  121. package/lib/internal/task-event.ts +1 -5
  122. package/lib/internal/task-finalization.ts +0 -1
  123. package/lib/internal/task-lifecycle.ts +3 -5
  124. package/lib/internal/task-operation-registry.ts +3 -19
  125. package/lib/internal/task-review.ts +4 -4
  126. package/lib/platform/comment-safety.ts +0 -10
  127. package/lib/platform/github-provider.ts +0 -2
  128. package/lib/platform/in-label-sync.ts +0 -16
  129. package/lib/platform/issue-comments.ts +0 -21
  130. package/lib/platform/issues.ts +0 -2
  131. package/lib/platform/operation-coordinator.ts +4 -2
  132. package/lib/platform/pr-change-report.ts +0 -5
  133. package/lib/platform/pr-checks.ts +1 -10
  134. package/lib/platform/pr-review.ts +1 -1
  135. package/lib/platform/provider-bridge.ts +0 -1
  136. package/lib/platform/provider-loader.ts +1 -5
  137. package/lib/platform/provider-validation.ts +1 -49
  138. package/lib/platform/pull-requests.ts +64 -99
  139. package/lib/platform/releases.ts +1 -40
  140. package/lib/platform/verification-required.ts +0 -2
  141. package/lib/platform/verification-sync.ts +0 -94
  142. package/lib/process-data/normalize.ts +1 -186
  143. package/lib/process-data/privacy.ts +2 -19
  144. package/lib/process-data/sources.ts +3 -283
  145. package/lib/render.ts +0 -15
  146. package/lib/run/index.ts +13 -7
  147. package/lib/run/skills.ts +0 -4
  148. package/lib/sandbox/commands/create.ts +37 -74
  149. package/lib/sandbox/commands/list-running.ts +0 -19
  150. package/lib/sandbox/commands/start.ts +7 -10
  151. package/lib/sandbox/constants.ts +0 -8
  152. package/lib/sandbox/control/client.ts +0 -1
  153. package/lib/sandbox/control/container-identity.ts +1 -16
  154. package/lib/sandbox/control/executor.ts +1 -5
  155. package/lib/sandbox/control/identity-sentinel.ts +0 -8
  156. package/lib/sandbox/control/lifecycle.ts +18 -51
  157. package/lib/sandbox/control/native-file-lock.ts +0 -8
  158. package/lib/sandbox/control/protocol.ts +0 -2
  159. package/lib/sandbox/control/server.ts +13 -39
  160. package/lib/sandbox/control/state.ts +1 -10
  161. package/lib/sandbox/dockerfile.ts +0 -11
  162. package/lib/sandbox/engine.ts +0 -17
  163. package/lib/sandbox/engines/docker-exact-discovery.ts +1 -5
  164. package/lib/sandbox/engines/wsl2-paths.ts +0 -4
  165. package/lib/sandbox/recovery.ts +24 -26
  166. package/lib/sandbox/removal.ts +11 -696
  167. package/lib/sandbox/shell.ts +1 -1
  168. package/lib/sandbox/task-resolver.ts +0 -48
  169. package/lib/sandbox/tools.ts +1 -5
  170. package/lib/sandbox/workspace-view.ts +2 -4
  171. package/lib/server/display.ts +0 -14
  172. package/lib/server/process-control.ts +1 -1
  173. package/lib/task/activity-intent.ts +36 -44
  174. package/lib/task/activity-log.ts +9 -22
  175. package/lib/task/artifact-command.ts +1 -1
  176. package/lib/task/artifact-lifecycle.ts +58 -67
  177. package/lib/task/artifact-name.ts +0 -7
  178. package/lib/task/artifact-operations.ts +3 -3
  179. package/lib/task/capabilities.ts +5 -6
  180. package/lib/task/commands/log.ts +0 -7
  181. package/lib/task/commands/status.ts +14 -79
  182. package/lib/task/commit-operation.ts +29 -51
  183. package/lib/task/completion-facts.ts +45 -42
  184. package/lib/task/control-authority.ts +27 -317
  185. package/lib/task/control-recovery.ts +2 -5
  186. package/lib/task/create.ts +2 -5
  187. package/lib/task/decision-intents.ts +5 -5
  188. package/lib/task/delivery-target.ts +0 -40
  189. package/lib/task/events.ts +89 -123
  190. package/lib/task/finalization.ts +41 -9
  191. package/lib/task/ledger-intents.ts +1 -1
  192. package/lib/task/lifecycle-execution.ts +37 -89
  193. package/lib/task/lifecycle.ts +48 -44
  194. package/lib/task/local-artifact-finalization.ts +0 -7
  195. package/lib/task/manual-validation-evidence.ts +1 -47
  196. package/lib/task/platform-operation-recovery.ts +50 -26
  197. package/lib/task/pr-delivery-fact.ts +2 -11
  198. package/lib/task/qualification-confirmation.ts +6 -6
  199. package/lib/task/resolve-ref.ts +0 -23
  200. package/lib/task/review-command.ts +2 -2
  201. package/lib/task/review-finalization.ts +1 -27
  202. package/lib/task/review-fingerprint.ts +0 -8
  203. package/lib/task/secure-fs.ts +0 -42
  204. package/lib/task/short-id.ts +0 -43
  205. package/lib/task/skill-scope.ts +0 -1
  206. package/lib/task/verification-engine.ts +56 -287
  207. package/lib/task/verification.ts +5 -5
  208. package/lib/task/write.ts +12 -1
  209. package/package.json +2 -2
  210. package/templates/.agents/README.en.md +1 -3
  211. package/templates/.agents/README.zh-CN.md +0 -2
  212. package/templates/.agents/rules/README.en.md +0 -1
  213. package/templates/.agents/rules/README.zh-CN.md +0 -1
  214. package/templates/.agents/rules/commit-and-pr.en.md +1 -1
  215. package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -1
  216. package/templates/.agents/rules/no-mid-flow-questions.en.md +0 -10
  217. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +0 -10
  218. package/templates/.agents/rules/pr-sync.en.md +1 -1
  219. package/templates/.agents/rules/pr-sync.zh-CN.md +1 -1
  220. package/templates/.agents/rules/task-management.en.md +3 -3
  221. package/templates/.agents/rules/task-management.zh-CN.md +3 -3
  222. package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
  223. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
  224. package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
  225. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
  226. package/templates/.agents/skills/code-task/SKILL.en.md +2 -2
  227. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +4 -4
  228. package/templates/.agents/skills/commit/SKILL.en.md +2 -2
  229. package/templates/.agents/skills/commit/SKILL.zh-CN.md +2 -2
  230. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +6 -6
  231. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +6 -6
  232. package/templates/.agents/skills/plan-task/SKILL.en.md +2 -2
  233. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -2
  234. package/templates/.agents/skills/review-analysis/SKILL.en.md +3 -3
  235. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +3 -3
  236. package/templates/.agents/skills/review-code/SKILL.en.md +5 -5
  237. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -5
  238. package/templates/.agents/skills/review-plan/SKILL.en.md +3 -3
  239. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +3 -3
  240. package/templates/.agents/skills/review-pr/SKILL.en.md +4 -4
  241. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +4 -4
  242. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -1
  243. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -1
  244. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +3 -75
  245. package/templates/.agents/templates/task.en.md +1 -0
  246. package/templates/.agents/templates/task.zh-CN.md +1 -0
  247. package/templates/.claude/settings.json +0 -24
  248. package/templates/.codex/hooks.json +0 -50
  249. package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +0 -582
  250. package/dist/lib/agent-clients/adapters/codex-lifecycle/binding.js +0 -114
  251. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +0 -237
  252. package/dist/lib/agent-clients/adapters/codex-lifecycle/cli.js +0 -443
  253. package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +0 -236
  254. package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +0 -292
  255. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +0 -267
  256. package/dist/lib/agent-clients/adapters/codex-orchestration.js +0 -466
  257. package/dist/lib/internal/task-orchestration.js +0 -71
  258. package/dist/lib/platform/verification.js +0 -6
  259. package/dist/lib/run/prompt.js +0 -2
  260. package/dist/lib/sandbox/engines/authority.js +0 -289
  261. package/dist/lib/task/delegation-receipts.js +0 -410
  262. package/dist/lib/task/orchestration.js +0 -1233
  263. package/dist/lib/task/verification-checks.js +0 -9
  264. package/dist/lib/task/workspace-snapshot.js +0 -121
  265. package/dist/lifecycle-build-manifest.json +0 -6
  266. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +0 -688
  267. package/lib/agent-clients/adapters/codex-lifecycle/binding.ts +0 -147
  268. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +0 -349
  269. package/lib/agent-clients/adapters/codex-lifecycle/cli.ts +0 -506
  270. package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +0 -385
  271. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +0 -41
  272. package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +0 -418
  273. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +0 -354
  274. package/lib/agent-clients/adapters/codex-orchestration.ts +0 -630
  275. package/lib/internal/task-orchestration.ts +0 -74
  276. package/lib/platform/verification.ts +0 -11
  277. package/lib/run/prompt.ts +0 -1
  278. package/lib/sandbox/engines/authority.ts +0 -365
  279. package/lib/task/delegation-receipts.ts +0 -547
  280. package/lib/task/orchestration.ts +0 -1651
  281. package/lib/task/verification-checks.ts +0 -10
  282. package/lib/task/workspace-snapshot.ts +0 -144
  283. package/templates/.agents/hooks/lifecycle-delegation.js +0 -140
  284. package/templates/.agents/rules/lifecycle-orchestration.en.md +0 -44
  285. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +0 -44
  286. package/templates/.agents/skills/run-task/SKILL.en.md +0 -29
  287. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +0 -29
  288. package/templates/.agents/skills/run-task/config/verify.en.json +0 -10
  289. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +0 -10
  290. package/templates/.agents/skills/run-task/reference/host-validation.en.md +0 -24
  291. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +0 -24
  292. package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +0 -6
  293. package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +0 -6
  294. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +0 -6
  295. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +0 -6
  296. package/templates/.claude/commands/run-task.en.md +0 -8
  297. package/templates/.claude/commands/run-task.zh-CN.md +0 -8
  298. package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +0 -3
  299. package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +0 -3
  300. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +0 -3
  301. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +0 -3
  302. package/templates/.opencode/commands/run-task.en.md +0 -11
  303. package/templates/.opencode/commands/run-task.zh-CN.md +0 -11
@@ -1,4 +1,3 @@
1
- import { normalizePullRequest, type RemotePullRequest } from './github-data.ts';
2
1
  import fs from 'node:fs';
3
2
  import path from 'node:path';
4
3
  import { createHash } from 'node:crypto';
@@ -6,7 +5,8 @@ import { execFileSync } from 'node:child_process';
6
5
 
7
6
  import { parseTypedTaskFrontmatter } from '../task/frontmatter.ts';
8
7
  import { resolveTaskRef } from '../task/resolve-ref.ts';
9
- import { extractSection } from '../task/sections.ts';
8
+ import { activityWarnings, locateActivityLog } from '../task/activity-log.ts';
9
+ import type { TaskMutation } from '../task/write.ts';
10
10
  import { captureTaskWriteMetadata, writeTask } from '../task/write.ts';
11
11
  import type { PlatformChangeRequestSnapshot } from './snapshots.ts';
12
12
  import { resolvePlatformProviderContext } from './context.ts';
@@ -77,7 +77,7 @@ type CreateOptions = SharedOptions & {
77
77
  dryRun?: boolean;
78
78
  phase?: { value: CreatePhase };
79
79
  };
80
- type BindOptions = SharedOptions & { agent: string; pr: string | number; dryRun?: boolean };
80
+ type BindOptions = SharedOptions & { agent: string; pr: string | number; dryRun?: boolean; expectedHeadSha?: string };
81
81
  type PullRequestPrimaryResult = 'pr_created' | 'pr_reused' | 'no_op';
82
82
  type SyncOptions = SharedOptions & { agent: string; metadata?: boolean; closingIssue?: boolean; dryRun?: boolean; primaryResult: PullRequestPrimaryResult };
83
83
  type ResolveExternalOptions = SharedOptions & { agent: string; pr?: string | number; dryRun?: boolean };
@@ -264,48 +264,6 @@ function expectedHead(repository: string, head: string): { repository: string; r
264
264
  return { repository: `${head.slice(0, colon)}/${repoName}`, ref: head.slice(colon + 1) };
265
265
  }
266
266
 
267
- function selectPullRequest(remotes: RemotePullRequest[], repository: string, head: string, base: string, expectedSha?: string):
268
- | { status: 'resolved'; pullRequest: PullRequestSnapshot }
269
- | { status: 'missing' | 'ambiguous' | 'head-mismatch'; pullRequest: null } {
270
- const wanted = expectedHead(repository, head);
271
- const matches = remotes.flatMap((remote) => {
272
- const normalized = normalizePullRequest(remote, repository);
273
- return normalized && normalized.state === 'open' && normalized.head.repository === wanted.repository &&
274
- normalized.head.ref === wanted.ref && normalized.base.repository === repository && normalized.base.ref === base
275
- ? [normalized] : [];
276
- });
277
- if (expectedSha && matches.some((match) => match.head.sha !== expectedSha)) {
278
- return { status: 'head-mismatch', pullRequest: null };
279
- }
280
- if (matches.length === 1) return { status: 'resolved', pullRequest: matches[0]! };
281
- return { status: matches.length === 0 ? 'missing' : 'ambiguous', pullRequest: null };
282
- }
283
-
284
- function validateBoundPullRequest(
285
- base: Awaited<ReturnType<typeof resolvedContext>> & { ok: true },
286
- pullRequest: PullRequestSnapshot | null,
287
- head: string,
288
- baseRef: string,
289
- expectedSha: string
290
- ): { ok: true } | { ok: false; error: { code: string; message: string; retryable: boolean } } {
291
- if (!pullRequest) return {
292
- ok: false,
293
- error: { code: 'PR_BIND_RECHECK_FAILED', message: 'Bound pull request identity is unavailable', retryable: false }
294
- };
295
- const wanted = expectedHead(base.context.platform.repository!, head);
296
- if (
297
- pullRequest.head.repository !== wanted.repository
298
- || pullRequest.head.ref !== wanted.ref
299
- || pullRequest.head.sha !== expectedSha
300
- || pullRequest.base.repository !== base.context.platform.repository
301
- || pullRequest.base.ref !== baseRef
302
- ) return {
303
- ok: false,
304
- error: { code: 'PR_BIND_IDENTITY_MISMATCH', message: 'Bound pull request identity does not match the current expected head/base', retryable: false }
305
- };
306
- return { ok: true };
307
- }
308
-
309
267
  type BindingIdentityOptions = {
310
268
  expectedHead?: string;
311
269
  expectedHeadSha?: string;
@@ -838,9 +796,11 @@ async function syncPlatformPullRequestInLabels(prToken: string | number, options
838
796
  });
839
797
  }
840
798
 
841
- function appendActivity(content: string, line: string): string {
842
- const body = extractSection(content, ['活动日志', 'Activity Log']);
843
- return `${body.replace(/\s+$/, '')}${body.trim() ? '\n' : ''}${line}`;
799
+ function activityMutation(content: string, line: string): TaskMutation[] {
800
+ const section = locateActivityLog(content);
801
+ if (!section) return [];
802
+ return [{ kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: section.heading,
803
+ body: `${section.body}${section.body ? '\n' : ''}${line}` }];
844
804
  }
845
805
 
846
806
  function deliveryIdentity(pullRequest: PullRequestSnapshot) {
@@ -875,16 +835,11 @@ function boundFactFor(
875
835
  }
876
836
 
877
837
  function writeCreateStarted(base: Awaited<ReturnType<typeof resolvedContext>> & { ok: true }, agent: string) {
878
- const starts = (base.content.match(/\*\*Create PR \[started\]\*\*/g) || []).length;
879
- const dones = (base.content.match(/\*\*Create PR\*\*/g) || []).length;
880
- if (starts > dones) return { status: 'no-op' as const };
881
838
  const metadata = captureTaskWriteMetadata();
882
839
  return writeTask({
883
840
  taskRef: base.resolved.taskId,
884
841
  expectedState: 'active',
885
- mutations: [{ kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: '活动日志', body: appendActivity(
886
- base.content, `- ${metadata.timestamp} — **Create PR [started]** by ${agent} — started`
887
- ) }]
842
+ mutations: activityMutation(base.content, `- ${metadata.timestamp} — **Create PR [started]** by ${agent} — started`)
888
843
  }, { repoRoot: base.resolved.repoRoot, metadataProvider: () => metadata });
889
844
  }
890
845
 
@@ -922,9 +877,7 @@ function bindIdentity(
922
877
  dryRun,
923
878
  mutations: [
924
879
  { kind: 'frontmatter', set: { ...factMutation.set, assigned_to: agent } },
925
- { kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: '活动日志', body: appendActivity(
926
- current, `- ${metadata.timestamp} — **Create PR** by ${agent} — PR #${pullRequest.number} created → ${pullRequest.url}`
927
- ) }
880
+ ...activityMutation(current, `- ${metadata.timestamp} — **Create PR** by ${agent} — PR #${pullRequest.number} created → ${pullRequest.url}`)
928
881
  ]
929
882
  }, { repoRoot: base.resolved.repoRoot, metadataProvider: () => metadata });
930
883
  }
@@ -946,12 +899,13 @@ async function bindPlatformPullRequestImpl(taskRef: string, options: BindOptions
946
899
  if (inspected.status === 'failed' || inspected.status === 'blocked' || !inspected.pullRequest) return inspected;
947
900
  const initialIdentity = validateWriterIdentity(base, inspected.pullRequest, {
948
901
  expectedHead: String(base.frontmatter.branch || ''),
902
+ expectedHeadSha: options.expectedHeadSha,
949
903
  errorCode: 'PR_BIND_IDENTITY_MISMATCH'
950
904
  });
951
905
  if (!initialIdentity.ok) return result('failed', base.resolved.taskId, base.issueNumber, requestedNumber, {
952
906
  pullRequest: inspected.pullRequest, error: initialIdentity.error
953
907
  });
954
- const written = bindIdentity(base, inspected.pullRequest, options.agent, 'explicit-bind', options.dryRun);
908
+ const written = bindIdentity(base, inspected.pullRequest, options.agent, 'explicit-bind', options.dryRun, undefined, options.expectedHeadSha);
955
909
  if (written.status === 'failed') return result('failed', base.resolved.taskId, base.issueNumber, requestedNumber, {
956
910
  pullRequest: inspected.pullRequest, error: { code: written.error.code, message: written.error.message, retryable: false }
957
911
  });
@@ -962,7 +916,7 @@ async function bindPlatformPullRequestImpl(taskRef: string, options: BindOptions
962
916
  });
963
917
  }
964
918
 
965
- async function bindPlatformPullRequest(taskRef: string, options: BindOptions): Promise<PullRequestResult> {
919
+ async function bindPlatformPullRequestWithProjection(taskRef: string, options: BindOptions): Promise<PullRequestResult> {
966
920
  const intent: PlatformPullRequestIntent = { action: 'bind', prToken: String(options.pr) };
967
921
  return journalPullRequestOperation(taskRef, options, intent, `pr:${options.pr}`, { pr: String(options.pr) },
968
922
  () => bindPlatformPullRequestImpl(taskRef, options));
@@ -1108,30 +1062,15 @@ async function resolveExternalPullRequest(taskRef: string, options: ResolveExter
1108
1062
  }), { candidates: selected.candidates, eligible: selected.eligible, selected: rechecked.value });
1109
1063
  const selectedPullRequest = rechecked.value;
1110
1064
  const note = externalEvidenceNote(base.issueIdentity, selected.source, selectedPullRequest);
1111
- const identityNote = externalIdentityEvidenceNote(base.issueIdentity, selectedPullRequest);
1112
1065
  const activityEntry = `**Bind External PR** by ${options.agent} — ${note}`;
1113
- const auditLines = base.content.split(/\r?\n/).filter((line) => line.includes('**Bind External PR**'));
1114
- const alreadyAudited = auditLines.some((line) => line.endsWith(identityNote));
1115
- if (auditLines.length > 0 && !alreadyAudited) return externalResult(result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
1116
- platform: base.context.platform,
1117
- capabilities: base.context.capabilities,
1118
- pullRequest: selectedPullRequest,
1119
- error: { code: 'PR_BIND_CONFLICT', message: 'Existing external PR audit evidence conflicts with the selected identity', retryable: false }
1120
- }), { candidates: selected.candidates, eligible: selected.eligible, selected: selectedPullRequest });
1121
- if (alreadyAudited && base.prIdentity && !resourceIdentityEquals(base.prIdentity, pullRequestIdentity(selectedPullRequest))) return externalResult(result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
1122
- platform: base.context.platform,
1123
- capabilities: base.context.capabilities,
1124
- pullRequest: selectedPullRequest,
1125
- error: { code: 'PR_BIND_CONFLICT', message: 'External PR audit evidence does not match the task binding', retryable: false }
1066
+ if (base.prIdentity && !resourceIdentityEquals(base.prIdentity, pullRequestIdentity(selectedPullRequest))) return externalResult(result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
1067
+ platform: base.context.platform, capabilities: base.context.capabilities, pullRequest: selectedPullRequest,
1068
+ error: { code: 'PR_BIND_CONFLICT', message: 'Selected identity does not match the task binding', retryable: false }
1126
1069
  }), { candidates: selected.candidates, eligible: selected.eligible, selected: selectedPullRequest });
1127
- if (base.prIdentity && resourceIdentityEquals(base.prIdentity, pullRequestIdentity(selectedPullRequest)) && alreadyAudited) {
1070
+ if (base.prIdentity && resourceIdentityEquals(base.prIdentity, pullRequestIdentity(selectedPullRequest)) && base.fact?.state === 'bound') {
1128
1071
  return externalResult(result('no-op', base.resolved.taskId, base.issueNumber, base.prNumber, {
1129
- platform: base.context.platform,
1130
- capabilities: base.context.capabilities,
1131
- resource: { kind: 'pull-request', number: selectedPullRequest.number },
1132
- pullRequest: selectedPullRequest,
1133
- operations: [{ name: 'task:bind-external-pr', status: 'no-op', reasonCode: 'EVIDENCE_ALREADY_RECORDED' }],
1134
- error: null
1072
+ platform: base.context.platform, capabilities: base.context.capabilities, pullRequest: selectedPullRequest,
1073
+ operations: [{ name: 'task:bind-external-pr', status: 'no-op', reasonCode: 'EVIDENCE_ALREADY_RECORDED' }], error: null
1135
1074
  }), { mode: 'external', authorization: selected.source, candidates: selected.candidates, eligible: selected.eligible, selected: selectedPullRequest });
1136
1075
  }
1137
1076
  const metadata = captureTaskWriteMetadata();
@@ -1141,9 +1080,7 @@ async function resolveExternalPullRequest(taskRef: string, options: ResolveExter
1141
1080
  dryRun: options.dryRun,
1142
1081
  mutations: [
1143
1082
  { kind: 'frontmatter', set: { ...factFrontmatterMutation(boundFactFor(selectedPullRequest, selected.source === 'unique' ? 'external-unique' : 'external-explicit', base.issueNumber, metadata.timestamp)).set, assigned_to: options.agent } },
1144
- { kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: '活动日志', body: appendActivity(
1145
- base.content, `- ${metadata.timestamp} — ${activityEntry}`
1146
- ) }
1083
+ ...activityMutation(base.content, `- ${metadata.timestamp} — ${activityEntry}`)
1147
1084
  ]
1148
1085
  }, { repoRoot: base.resolved.repoRoot, metadataProvider: () => metadata });
1149
1086
  if (write.status === 'failed') return externalResult(result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
@@ -1173,7 +1110,7 @@ async function createPlatformPullRequestImpl(taskRef: string, options: CreateOpt
1173
1110
  }), PRECONDITION_NOT_CREATED);
1174
1111
  }
1175
1112
  try {
1176
- return await createExternalPullRequest(taskRef, options, base);
1113
+ return await createExternalPullRequest(options, base);
1177
1114
  } catch (error) {
1178
1115
  return withCreation(result('failed', base.resolved.taskId, base.issueNumber, null, {
1179
1116
  platform: base.context.platform,
@@ -1196,16 +1133,23 @@ async function recoverCreatedPullRequest(
1196
1133
  if (!base.issueIdentity) return result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
1197
1134
  error: { code: 'PLATFORM_OPERATION_ISSUE_REQUIRED', message: 'Pull-request recovery requires a bound Issue identity', retryable: false }
1198
1135
  });
1199
- const head = base.provider.changeRequests?.verifyHead
1200
- ? await base.provider.changeRequests.verifyHead({ context: providerOperationContext(base.loadedContext), head: options.head })
1201
- : unsupportedProviderOperation(base.provider, 'changeRequests.verifyHead');
1202
- if (!head.ok) return providerPullRequestError(base, head.error, base.prNumber);
1136
+ let headSha: string;
1137
+ if (base.provider.changeRequests?.verifyHead) {
1138
+ const head = await base.provider.changeRequests.verifyHead({ context: providerOperationContext(base.loadedContext), head: options.head });
1139
+ if (!head.ok) return providerPullRequestError(base, head.error, base.prNumber);
1140
+ headSha = head.value.sha;
1141
+ } else {
1142
+ headSha = typeof base.frontmatter.delivery_remote_head === 'string' ? base.frontmatter.delivery_remote_head.trim() : '';
1143
+ if (!headSha) return result('blocked', base.resolved.taskId, base.issueNumber, base.prNumber, {
1144
+ error: { code: 'PR_HEAD_UNVERIFIED', message: 'Verify and record the delivered remote head before retrying pull-request recovery', retryable: true }
1145
+ });
1146
+ }
1203
1147
  if (base.prIdentity) {
1204
1148
  const inspected = await inspectExternalPullRequest(base, base.prIdentity);
1205
1149
  if (!inspected.pullRequest || inspected.status === 'failed' || inspected.status === 'blocked'
1206
1150
  || inspected.pullRequest.base.repository !== base.context.platform.repository
1207
1151
  || inspected.pullRequest.base.ref !== options.base || inspected.pullRequest.head.ref !== options.head
1208
- || inspected.pullRequest.head.sha !== head.value.sha) {
1152
+ || inspected.pullRequest.head.sha !== headSha) {
1209
1153
  return result('blocked', base.resolved.taskId, base.issueNumber, base.prNumber, {
1210
1154
  error: inspected.error ?? { code: 'PLATFORM_OPERATION_PR_NOT_CONFIRMED', message: 'Bound pull request does not match the pending create intent', retryable: true }
1211
1155
  });
@@ -1221,22 +1165,22 @@ async function recoverCreatedPullRequest(
1221
1165
  && candidate.base.ref === options.base
1222
1166
  && candidate.head.repository === base.context.platform.repository
1223
1167
  && candidate.head.ref === options.head
1224
- && candidate.head.sha === head.value.sha);
1168
+ && candidate.head.sha === headSha);
1225
1169
  if (matches.length !== 1 || !matches[0]?.number) return result('blocked', base.resolved.taskId, base.issueNumber, null, {
1226
1170
  error: { code: matches.length > 1 ? 'PLATFORM_OPERATION_PR_AMBIGUOUS' : 'PLATFORM_OPERATION_PR_NOT_CONFIRMED',
1227
1171
  message: 'Pending pull-request creation does not resolve to one exact repository/base/head identity', retryable: true }
1228
1172
  });
1229
- const bound = await bindPlatformPullRequest(base.resolved.taskId, { agent: options.agent, cwd: base.resolved.repoRoot, pr: matches[0].number });
1173
+ const bound = await bindPlatformPullRequest(base.resolved.taskId, { agent: options.agent, cwd: base.resolved.repoRoot, client: options.client, pr: matches[0].number, skipQueue: true, expectedHeadSha: headSha });
1230
1174
  if (!bound.pullRequest || (bound.status !== 'applied' && bound.status !== 'no-op') || bound.error) return bound;
1231
1175
  if (bound.pullRequest.base.repository !== base.context.platform.repository || bound.pullRequest.base.ref !== options.base
1232
1176
  || bound.pullRequest.head.repository !== base.context.platform.repository || bound.pullRequest.head.ref !== options.head
1233
- || bound.pullRequest.head.sha !== head.value.sha) return result('blocked', base.resolved.taskId, base.issueNumber, bound.task.prNumber, {
1177
+ || bound.pullRequest.head.sha !== headSha) return result('blocked', base.resolved.taskId, base.issueNumber, bound.task.prNumber, {
1234
1178
  error: { code: 'PLATFORM_OPERATION_PR_NOT_CONFIRMED', message: 'Bound pull request changed while recovering the create intent', retryable: true }
1235
1179
  });
1236
1180
  return bound;
1237
1181
  }
1238
1182
 
1239
- async function createPlatformPullRequest(taskRef: string, options: CreateOptions): Promise<PullRequestResult> {
1183
+ async function createPlatformPullRequestWithProjection(taskRef: string, options: CreateOptions): Promise<PullRequestResult> {
1240
1184
  const intent: PlatformPullRequestIntent = { action: 'create', baseRef: options.base, headRef: options.head };
1241
1185
  const identityInput = {
1242
1186
  title: createHash('sha256').update(options.title).digest('hex'),
@@ -1248,7 +1192,6 @@ async function createPlatformPullRequest(taskRef: string, options: CreateOptions
1248
1192
  }
1249
1193
 
1250
1194
  async function createExternalPullRequest(
1251
- taskRef: string,
1252
1195
  options: CreateOptions,
1253
1196
  base: Extract<Awaited<ReturnType<typeof resolvedContext>>, { ok: true }>
1254
1197
  ): Promise<PullRequestResult> {
@@ -1636,9 +1579,7 @@ function applySkippedPullRequestFact(
1636
1579
  dryRun: options.dryRun,
1637
1580
  mutations: [
1638
1581
  { kind: 'frontmatter', set: { ...factFrontmatterMutation(fact).set, assigned_to: options.agent } },
1639
- { kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: '活动日志', body: appendActivity(
1640
- content, `- ${metadata.timestamp} — **Skip PR** by ${options.agent} — PR delivery explicitly skipped`
1641
- ) }
1582
+ ...activityMutation(content, `- ${metadata.timestamp} — **Skip PR** by ${options.agent} — PR delivery explicitly skipped`)
1642
1583
  ]
1643
1584
  }, { repoRoot: resolved.repoRoot, metadataProvider: () => metadata });
1644
1585
  if (write.status === 'failed') return result('failed', resolved.taskId, issueNumber, null, {
@@ -1652,7 +1593,7 @@ function applySkippedPullRequestFact(
1652
1593
  });
1653
1594
  }
1654
1595
 
1655
- async function skipPlatformPullRequestFact(taskRef: string, options: SkipFactOptions): Promise<PullRequestResult> {
1596
+ async function skipPlatformPullRequestFactWithProjection(taskRef: string, options: SkipFactOptions): Promise<PullRequestResult> {
1656
1597
  const resolved = resolveTaskRef(taskRef, options.cwd ? { repoRoot: options.cwd } : {});
1657
1598
  if (!resolved.ok) return result('failed', resolved.taskId, null, null, {
1658
1599
  error: { code: resolved.code, message: resolved.message, retryable: false }
@@ -1669,6 +1610,30 @@ async function skipPlatformPullRequestFact(taskRef: string, options: SkipFactOpt
1669
1610
  }
1670
1611
  }
1671
1612
 
1672
- export { bindPlatformPullRequest, createPlatformPullRequest, inspectPlatformPullRequest, inspectPlatformPullRequestByNumber, recoverCreatedPullRequest, resolveExternalPullRequest, skipPlatformPullRequestFact, selectExternalPullRequest, selectPullRequest, syncPlatformPullRequest, syncPlatformPullRequestInLabels };
1613
+ function withActivityWarnings<T extends PullRequestResult>(taskRef: string, cwd: string | undefined, output: T): T {
1614
+ if (output.status === 'failed' || output.status === 'blocked') return output;
1615
+ const resolved = resolveTaskRef(taskRef, cwd ? { repoRoot: cwd } : {});
1616
+ if (!resolved.ok) return output;
1617
+ let logWarnings: ReturnType<typeof activityWarnings>;
1618
+ try { logWarnings = activityWarnings(fs.readFileSync(resolved.taskMdPath, 'utf8')); }
1619
+ catch { return output; }
1620
+ if (!logWarnings.length) return output;
1621
+ const warnings: OperationWarning[] = logWarnings.map((item) => ({ ...item, retryable: true, step: 'pr', target: resolved.taskId, severity: 'IMPORTANT' }));
1622
+ return { ...output, warnings: mergeOperationWarnings(output.warnings, warnings) };
1623
+ }
1624
+ async function bindPlatformPullRequest(taskRef: string, options: BindOptions): Promise<PullRequestResult> {
1625
+ return withActivityWarnings(taskRef, options.cwd, await bindPlatformPullRequestWithProjection(taskRef, options));
1626
+ }
1627
+ async function createPlatformPullRequest(taskRef: string, options: CreateOptions): Promise<PullRequestResult> {
1628
+ return withActivityWarnings(taskRef, options.cwd, await createPlatformPullRequestWithProjection(taskRef, options));
1629
+ }
1630
+ async function resolveExternalPullRequestWithWarnings(taskRef: string, options: ResolveExternalOptions): Promise<ExternalPullRequestResult> {
1631
+ return withActivityWarnings(taskRef, options.cwd, await resolveExternalPullRequest(taskRef, options));
1632
+ }
1633
+ async function skipPlatformPullRequestFact(taskRef: string, options: SkipFactOptions): Promise<PullRequestResult> {
1634
+ return withActivityWarnings(taskRef, options.cwd, await skipPlatformPullRequestFactWithProjection(taskRef, options));
1635
+ }
1636
+
1637
+ export { bindPlatformPullRequest, createPlatformPullRequest, inspectPlatformPullRequest, inspectPlatformPullRequestByNumber, recoverCreatedPullRequest, resolveExternalPullRequestWithWarnings as resolveExternalPullRequest, skipPlatformPullRequestFact, selectExternalPullRequest, syncPlatformPullRequest, syncPlatformPullRequestInLabels };
1673
1638
  export type { BindOptions, CreateOptions, ExternalPullRequestResult, ExternalPullRequestSelection, PullRequestPrimaryResult, PullRequestResult, PullRequestSnapshot, ResolveExternalOptions, SkipFactOptions, SyncOptions };
1674
1639
  export { warningResultForPrimary };
@@ -1,18 +1,10 @@
1
- import fs from 'node:fs';
2
- import crypto from 'node:crypto';
3
1
  import { resolvePlatformProviderContext } from './context.ts';
4
2
  import type { PlatformClient } from './context.ts';
5
3
  import { platformResult } from './types.ts';
6
4
  import { providerError, providerOperationContext, providerStatus, unsupportedProviderOperation } from './provider-bridge.ts';
7
5
 
8
- type ReleaseSnapshot = { tag: string; published: boolean; draft: boolean; url: string | null };
9
6
  type ReleaseOptions = { cwd?: string; client?: PlatformClient };
10
7
 
11
- function flattenPages(value: unknown): Array<Record<string, unknown>> {
12
- if (!Array.isArray(value)) return [];
13
- return value.flatMap((entry) => Array.isArray(entry) ? entry : [entry]).filter((entry): entry is Record<string, unknown> => Boolean(entry) && typeof entry === 'object');
14
- }
15
-
16
8
  async function inspectPlatformRelease(tag: string, options: ReleaseOptions = {}) {
17
9
  const loaded = await resolvePlatformProviderContext({ cwd: options.cwd, client: options.client });
18
10
  const context = loaded.ok ? loaded.value.context : loaded.context;
@@ -36,37 +28,6 @@ async function inspectPlatformRelease(tag: string, options: ReleaseOptions = {})
36
28
  return { ...platformResult('failed'), platform: context.platform, release: null, workflows: [], error: context.error };
37
29
  }
38
30
 
39
- async function upsertPlatformRelease(input: { tag: string; title?: string; notesFile?: string }, options: ReleaseOptions = {}) {
40
- const inspected = await inspectPlatformRelease(input.tag, options);
41
- if (inspected.release?.published) return { ...inspected, status: 'no-op' as const, changed: false, operations: [] };
42
- if (inspected.status === 'blocked' || inspected.status === 'failed') return { ...inspected, changed: false, operations: [] };
43
- if (!inspected.platform.repository) return { ...inspected, status: 'no-op' as const, changed: false, operations: [] };
44
- const loaded = await resolvePlatformProviderContext({ cwd: options.cwd, client: options.client });
45
- if (loaded.ok) {
46
- let notes: { text: string; sha256: string; byteLength: number } | undefined;
47
- if (input.notesFile) {
48
- try {
49
- const bytes = fs.readFileSync(input.notesFile);
50
- notes = { text: bytes.toString('utf8'), sha256: `sha256:${crypto.createHash('sha256').update(bytes).digest('hex')}`, byteLength: bytes.byteLength };
51
- } catch {
52
- return { ...inspected, status: 'failed' as const, changed: false, operations: [{ name: 'create-release', status: 'failed' }], error: { code: 'RELEASE_NOTES_FILE_UNREADABLE', message: 'notes-file could not be read', retryable: false } };
53
- }
54
- }
55
- const created = loaded.value.provider.releases?.create
56
- ? await loaded.value.provider.releases.create({
57
- context: providerOperationContext(loaded.value),
58
- tag: input.tag,
59
- title: input.title ?? input.tag,
60
- ...(notes ? { notes } : {}),
61
- mutation: { idempotencyKey: `release:create:${input.tag}` }
62
- })
63
- : unsupportedProviderOperation(loaded.value.provider, 'releases.create');
64
- if (!created.ok) return { ...inspected, status: providerStatus(created.error), changed: false, operations: [{ name: 'create-release', status: 'failed' }], error: providerError(created.error, 'PLATFORM_PROVIDER_OPERATION_FAILED') };
65
- return { ...inspected, status: 'applied' as const, changed: created.value.changed, operations: [{ name: 'create-release', status: 'applied' }], error: null };
66
- }
67
- return { ...inspected, status: 'failed' as const, changed: false, operations: [{ name: 'create-release', status: 'failed' }], error: { code: 'PLATFORM_PROVIDER_LOAD_FAILED', message: 'Selected provider failed to load', retryable: false } };
68
- }
69
-
70
31
  async function reconcileReleaseMilestones(version: string, options: ReleaseOptions = {}) {
71
32
  const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
72
33
  if (!match) return { status: 'failed' as const, changed: false, operations: [], error: { code: 'RELEASE_VERSION_INVALID', message: `Invalid version '${version}'` } };
@@ -114,4 +75,4 @@ async function reconcileReleaseMilestones(version: string, options: ReleaseOptio
114
75
  return { status: 'failed' as const, changed: false, operations: [], error: { code: 'PLATFORM_CAPABILITY_UNSUPPORTED', message: 'Release milestone reconciliation is unavailable', retryable: false } };
115
76
  }
116
77
 
117
- export { inspectPlatformRelease, reconcileReleaseMilestones, upsertPlatformRelease };
78
+ export { inspectPlatformRelease, reconcileReleaseMilestones };
@@ -6,7 +6,6 @@ import { inspectRequiredChecks } from "./pr-checks.ts";
6
6
  import { resolvePlatformProviderContext } from "./context.ts";
7
7
  import { resolveReviewedHeadRelation } from "./merged-pr-equivalence.ts";
8
8
  import { readPrDeliveryFact } from "../task/pr-delivery-fact.ts";
9
- import { resourceIdentityNumber } from "./resource-identity.ts";
10
9
 
11
10
  const CHECK_TYPE = "required-checks";
12
11
  const SHA_PATTERN = /^[0-9a-f]{7,40}$/i;
@@ -36,7 +35,6 @@ export function evaluateRequiredChecks(context: any, shared: any): any {
36
35
  }
37
36
  const fact = factRead.status === "valid" ? factRead.fact : null;
38
37
  const prIdentity = fact?.state === "bound" ? fact.identity.resource : null;
39
- const prNumber = resourceIdentityNumber(prIdentity);
40
38
  if (prFlow === "disabled" || fact?.state === "skipped" || !prIdentity) {
41
39
  return shared.passResult(CHECK_TYPE, "Skipped: required checks are not applicable to this task");
42
40
  }
@@ -17,10 +17,7 @@ import { providerError, providerOperationContext, resourceIdentityNumber, unsupp
17
17
  import { taskIssueIdentity } from "./task-identities.ts";
18
18
  import { MARKERS, renderTaskCommentResult } from "./issue-comments.ts";
19
19
  import {
20
- CONTROL_MARKER_PATTERN,
21
20
  canonicalizeCommentBody,
22
- renderSafeCodeFence,
23
- sanitizeMarkdownDocument
24
21
  } from "./comment-safety.ts";
25
22
 
26
23
  const CHECK_TYPE = "platform-sync";
@@ -58,11 +55,6 @@ export function getDefaults(): any {
58
55
  };
59
56
  }
60
57
 
61
- function sanitizeCommentContent(content: string): string | null {
62
- const result = sanitizeMarkdownDocument(content, { reservedMarkers: [CONTROL_MARKER_PATTERN] });
63
- return result.ok ? result.value : null;
64
- }
65
-
66
58
  function infoResult(message: string): any {
67
59
  return {
68
60
  type: CHECK_TYPE,
@@ -877,36 +869,6 @@ function extractCommentBody(commentBody: any): any {
877
869
  return lines.slice(start, end).join("\n");
878
870
  }
879
871
 
880
- function buildExpectedTaskBody(taskContent: any, shared: VerificationShared): any {
881
- const frontmatterMatch = taskContent.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
882
- if (!frontmatterMatch) {
883
- return sanitizeCommentContent(taskContent.trim());
884
- }
885
-
886
- const body = sanitizeCommentContent(taskContent.slice(frontmatterMatch[0].length).trim());
887
- if (body === null) {
888
- return null;
889
- }
890
- return [
891
- buildTaskFrontmatterSummary(shared),
892
- "",
893
- renderSafeCodeFence(frontmatterMatch[0].trim(), "yaml"),
894
- "",
895
- "</details>",
896
- "",
897
- body
898
- ].join("\n").trim();
899
- }
900
-
901
- function buildTaskFrontmatterSummary(shared: VerificationShared): any {
902
- const language = loadProjectLanguage(shared);
903
- if (language === "en" || language === "en-US") {
904
- return "<details><summary>Metadata (frontmatter)</summary>";
905
- }
906
-
907
- return "<details><summary>元数据 (frontmatter)</summary>";
908
- }
909
-
910
872
  function loadProjectLanguage(shared: VerificationShared): any {
911
873
  const override = process.env.VALIDATE_ARTIFACT_LANGUAGE;
912
874
  if (!shared.isBlank(override)) {
@@ -977,43 +939,6 @@ function mapTaskTypeToIssueType(taskType: any): any {
977
939
  return mapping[taskType] || "Task";
978
940
  }
979
941
 
980
- function normalizeIssueFields(payload: any): any {
981
- const issue = payload?.data?.repository?.issue;
982
- const pinnedFields = Array.isArray(issue?.issueType?.pinnedFields)
983
- ? issue.issueType.pinnedFields
984
- : [];
985
- const values = Array.isArray(issue?.issueFieldValues?.nodes)
986
- ? issue.issueFieldValues.nodes
987
- : [];
988
- const pinnedNames = new Set(
989
- pinnedFields
990
- .map((field: any) => typeof field?.name === "string" ? field.name : "")
991
- .filter(Boolean)
992
- );
993
- const normalizedValues = new Map();
994
-
995
- for (const value of values) {
996
- const fieldName = value?.field?.name;
997
- if (!fieldName) {
998
- continue;
999
- }
1000
-
1001
- if (value.__typename === "IssueFieldSingleSelectValue") {
1002
- normalizedValues.set(fieldName, {
1003
- kind: "single-select",
1004
- value: normalizeOptionName(value.name)
1005
- });
1006
- } else if (value.__typename === "IssueFieldDateValue") {
1007
- normalizedValues.set(fieldName, {
1008
- kind: "date",
1009
- value: normalizeDateValue(value.value)
1010
- });
1011
- }
1012
- }
1013
-
1014
- return { pinnedNames, values: normalizedValues };
1015
- }
1016
-
1017
942
  function normalizeExpectedIssueField(metadataKey: any, rawValue: any): any {
1018
943
  const value = String(rawValue || "").trim();
1019
944
  if (!value) {
@@ -1124,25 +1049,6 @@ function gitText(args: any, cwd: any): any {
1124
1049
  }
1125
1050
  }
1126
1051
 
1127
- function resolvePrHeadSha(context: any): any {
1128
- const fallback = () => gitText(["rev-parse", "HEAD"], context.taskDir);
1129
- const branch = String(context.task?.metadata?.branch || "").trim();
1130
- if (!branch) {
1131
- return fallback();
1132
- }
1133
-
1134
- const matchedWorktree = resolveBranchWorktree(context.taskDir, branch);
1135
- if (!matchedWorktree) {
1136
- return {
1137
- ok: false,
1138
- type: "check_failed",
1139
- message: `Task branch '${branch}' is not checked out in a usable worktree`
1140
- };
1141
- }
1142
-
1143
- return gitText(["rev-parse", "HEAD"], matchedWorktree);
1144
- }
1145
-
1146
1052
  function interpolate(template: any, taskDir: any, artifactFile: any): any {
1147
1053
  const artifactStem = artifactFile ? path.basename(artifactFile, path.extname(artifactFile)) : "";
1148
1054
  return template