@fitlab-ai/agent-infra 0.9.8 → 0.9.10

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 (182) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/bin/internal-cli.js +11 -1
  4. package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +58 -21
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +25 -11
  6. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +173 -10
  7. package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-context.js +127 -0
  8. package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +14 -0
  9. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +63 -92
  10. package/dist/lib/agent-clients/adapters/codex-sandbox.js +72 -11
  11. package/dist/lib/agent-clients/adapters/index.js +3 -1
  12. package/dist/lib/agent-clients/adapters/traecli.js +66 -0
  13. package/dist/lib/agent-clients/tokens.js +2 -2
  14. package/dist/lib/agent-clients/types.js +2 -1
  15. package/dist/lib/defaults.json +5 -0
  16. package/dist/lib/git/workflow.js +10 -1
  17. package/dist/lib/internal/codex-lifecycle.js +20 -6
  18. package/dist/lib/internal/codex-sandbox-controller.js +9 -15
  19. package/dist/lib/internal/git-workflow.js +5 -7
  20. package/dist/lib/internal/platform-pr.js +20 -7
  21. package/dist/lib/internal/release-workflow.js +2 -1
  22. package/dist/lib/internal/sandbox-control.js +79 -2
  23. package/dist/lib/internal/task-finalization.js +54 -0
  24. package/dist/lib/internal/task-orchestration.js +156 -291
  25. package/dist/lib/{task/commands/validate.js → internal/task-validate.js} +75 -42
  26. package/dist/lib/platform/pr-summary.js +48 -10
  27. package/dist/lib/platform/pull-requests.js +205 -41
  28. package/dist/lib/run/tui.js +5 -2
  29. package/dist/lib/sandbox/commands/rm.js +316 -55
  30. package/dist/lib/sandbox/control/client.js +190 -6
  31. package/dist/lib/sandbox/control/controller-registration.js +275 -0
  32. package/dist/lib/sandbox/control/executor.js +140 -5
  33. package/dist/lib/sandbox/control/lifecycle.js +3 -1
  34. package/dist/lib/sandbox/control/protocol.js +67 -6
  35. package/dist/lib/sandbox/index.js +5 -3
  36. package/dist/lib/sandbox/managed-fs.js +5 -0
  37. package/dist/lib/sandbox/task-resolver.js +50 -6
  38. package/dist/lib/sandbox/workspace-identity.js +27 -0
  39. package/dist/lib/sandbox/worktree-safety.js +215 -2
  40. package/dist/lib/task/codex-orchestration.js +161 -39
  41. package/dist/lib/task/commands/status.js +59 -1
  42. package/dist/lib/task/commit-operation.js +335 -0
  43. package/dist/lib/task/commit-policy.js +18 -0
  44. package/dist/lib/task/delegation-receipts.js +248 -6
  45. package/dist/lib/task/finalization.js +593 -0
  46. package/dist/lib/task/index.js +0 -9
  47. package/dist/lib/task/operation-outcome.js +33 -0
  48. package/dist/lib/task/orchestration.js +187 -761
  49. package/dist/lib/task/short-id.js +59 -1
  50. package/dist/lib/task/task-execution-lock.js +6 -1
  51. package/dist/lib/task/verification-engine.js +110 -60
  52. package/dist/lib/task/verification.js +2 -1
  53. package/dist/lib/task/workflow-warning-intents.js +50 -1
  54. package/dist/lifecycle-build-manifest.json +3 -3
  55. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +61 -19
  56. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +37 -10
  57. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +276 -12
  58. package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +163 -0
  59. package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +19 -0
  60. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +9 -1
  61. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +91 -118
  62. package/lib/agent-clients/adapters/codex-sandbox.ts +89 -14
  63. package/lib/agent-clients/adapters/index.ts +3 -1
  64. package/lib/agent-clients/adapters/traecli.ts +67 -0
  65. package/lib/agent-clients/tokens.ts +2 -2
  66. package/lib/agent-clients/types.ts +2 -1
  67. package/lib/defaults.json +5 -0
  68. package/lib/git/workflow.ts +11 -2
  69. package/lib/internal/codex-lifecycle.ts +19 -6
  70. package/lib/internal/codex-sandbox-controller.ts +9 -14
  71. package/lib/internal/git-workflow.ts +5 -6
  72. package/lib/internal/platform-pr.ts +14 -7
  73. package/lib/internal/release-workflow.ts +2 -1
  74. package/lib/internal/sandbox-control.ts +92 -2
  75. package/lib/internal/task-finalization.ts +68 -0
  76. package/lib/internal/task-orchestration.ts +20 -103
  77. package/lib/{task/commands/validate.ts → internal/task-validate.ts} +75 -40
  78. package/lib/platform/pr-summary.ts +55 -11
  79. package/lib/platform/pull-requests.ts +211 -41
  80. package/lib/run/tui.ts +5 -3
  81. package/lib/sandbox/commands/rm.ts +413 -61
  82. package/lib/sandbox/control/client.ts +255 -6
  83. package/lib/sandbox/control/controller-registration.ts +352 -0
  84. package/lib/sandbox/control/executor.ts +169 -5
  85. package/lib/sandbox/control/lifecycle.ts +2 -1
  86. package/lib/sandbox/control/protocol.ts +80 -7
  87. package/lib/sandbox/index.ts +5 -3
  88. package/lib/sandbox/managed-fs.ts +5 -0
  89. package/lib/sandbox/task-resolver.ts +58 -7
  90. package/lib/sandbox/workspace-identity.ts +50 -2
  91. package/lib/sandbox/workspace-view.ts +3 -3
  92. package/lib/sandbox/worktree-safety.ts +236 -2
  93. package/lib/task/codex-orchestration.ts +168 -40
  94. package/lib/task/commands/status.ts +78 -1
  95. package/lib/task/commit-operation.ts +430 -0
  96. package/lib/task/commit-policy.ts +30 -0
  97. package/lib/task/delegation-receipts.ts +263 -4
  98. package/lib/task/finalization.ts +761 -0
  99. package/lib/task/index.ts +0 -8
  100. package/lib/task/operation-outcome.ts +48 -0
  101. package/lib/task/orchestration.ts +218 -982
  102. package/lib/task/short-id.ts +65 -1
  103. package/lib/task/task-execution-lock.ts +10 -1
  104. package/lib/task/verification-engine.ts +115 -63
  105. package/lib/task/verification.ts +3 -2
  106. package/lib/task/workflow-warning-intents.ts +57 -2
  107. package/package.json +2 -2
  108. package/templates/.agents/QUICKSTART.en.md +3 -4
  109. package/templates/.agents/QUICKSTART.zh-CN.md +3 -4
  110. package/templates/.agents/hooks/lifecycle-delegation.js +1 -21
  111. package/templates/.agents/rules/README.en.md +1 -0
  112. package/templates/.agents/rules/README.zh-CN.md +1 -0
  113. package/templates/.agents/rules/compatibility-policy.en.md +39 -0
  114. package/templates/.agents/rules/compatibility-policy.zh-CN.md +39 -0
  115. package/templates/.agents/rules/lifecycle-orchestration.en.md +4 -4
  116. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +4 -4
  117. package/templates/.agents/rules/pr-sync.en.md +1 -1
  118. package/templates/.agents/rules/pr-sync.github.en.md +2 -1
  119. package/templates/.agents/rules/pr-sync.github.zh-CN.md +2 -0
  120. package/templates/.agents/rules/pr-sync.zh-CN.md +1 -0
  121. package/templates/.agents/rules/review-method.en.md +1 -0
  122. package/templates/.agents/rules/review-method.zh-CN.md +1 -0
  123. package/templates/.agents/rules/task-management.en.md +2 -2
  124. package/templates/.agents/rules/task-management.zh-CN.md +2 -2
  125. package/templates/.agents/skills/analyze-task/SKILL.en.md +1 -0
  126. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +1 -0
  127. package/templates/.agents/skills/block-task/SKILL.en.md +2 -4
  128. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -4
  129. package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
  130. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +3 -3
  131. package/templates/.agents/skills/close-codescan/SKILL.en.md +6 -2
  132. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +6 -2
  133. package/templates/.agents/skills/close-dependabot/SKILL.en.md +6 -2
  134. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +6 -2
  135. package/templates/.agents/skills/code-task/SKILL.en.md +1 -0
  136. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +2 -0
  137. package/templates/.agents/skills/commit/SKILL.en.md +41 -125
  138. package/templates/.agents/skills/commit/SKILL.zh-CN.md +52 -123
  139. package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
  140. package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
  141. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +14 -43
  142. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +14 -49
  143. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  144. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  145. package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -35
  146. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -35
  147. package/templates/.agents/skills/complete-task/SKILL.en.md +31 -38
  148. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +31 -38
  149. package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
  150. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
  151. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +1 -1
  152. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +1 -1
  153. package/templates/.agents/skills/create-pr/SKILL.en.md +17 -9
  154. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +17 -9
  155. package/templates/.agents/skills/create-pr/reference/change-report.en.md +41 -0
  156. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +41 -0
  157. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +2 -2
  158. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +2 -2
  159. package/templates/.agents/skills/plan-task/SKILL.en.md +2 -1
  160. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -1
  161. package/templates/.agents/skills/review-code/reference/migration-risks.en.md +8 -6
  162. package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +8 -6
  163. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +3 -3
  164. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +3 -3
  165. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +1 -1
  166. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +1 -1
  167. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -2
  168. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -2
  169. package/templates/.agents/skills/run-task/SKILL.en.md +6 -6
  170. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +6 -6
  171. package/templates/.agents/skills/run-task/reference/host-validation.en.md +2 -2
  172. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +2 -2
  173. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +24 -0
  174. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +1 -1
  175. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +1 -1
  176. package/templates/.codex/hooks.json +4 -4
  177. package/templates/.trae/skills/update-agent-infra.en.md +8 -0
  178. package/templates/.trae/skills/update-agent-infra.zh-CN.md +8 -0
  179. package/dist/lib/task/commit-finalization.js +0 -305
  180. package/dist/lib/task/commit-intent.js +0 -165
  181. package/lib/task/commit-finalization.ts +0 -419
  182. package/lib/task/commit-intent.ts +0 -230
@@ -3,28 +3,28 @@ import fs from 'node:fs';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { randomUUID } from 'node:crypto';
6
- import { loadConfig } from '../../sandbox/config.ts';
7
- import { detectEngine } from '../../sandbox/engine.ts';
8
- import { runEngine } from '../../sandbox/shell.ts';
9
- import { sandboxBranchLabel, sandboxLabel } from '../../sandbox/constants.ts';
10
- import { fetchSandboxRows, selectSandboxContainer } from '../../sandbox/commands/list-running.ts';
11
- import { containerNameCandidates } from '../../sandbox/constants.ts';
12
- import { resolveSandboxTarget } from '../../sandbox/workspace-identity.ts';
13
- import { sandboxControlPaths } from '../../sandbox/workspace-view.ts';
6
+ import { loadConfig } from '../sandbox/config.ts';
7
+ import { detectEngine } from '../sandbox/engine.ts';
8
+ import { runEngine } from '../sandbox/shell.ts';
9
+ import { sandboxBranchLabel, sandboxLabel } from '../sandbox/constants.ts';
10
+ import { fetchSandboxRows, selectSandboxContainer } from '../sandbox/commands/list-running.ts';
11
+ import { containerNameCandidates } from '../sandbox/constants.ts';
12
+ import { resolveSandboxTarget } from '../sandbox/workspace-identity.ts';
13
+ import { sandboxControlPaths } from '../sandbox/workspace-view.ts';
14
14
  import {
15
15
  appendSandboxControlAudit,
16
16
  readActiveLease,
17
17
  readSandboxControlStatus
18
- } from '../../sandbox/control/state.ts';
19
- import type { SandboxControlLease, SandboxControlManifest } from '../../sandbox/control/protocol.ts';
18
+ } from '../sandbox/control/state.ts';
19
+ import type { SandboxControlLease, SandboxControlManifest } from '../sandbox/control/protocol.ts';
20
20
  import {
21
21
  SANDBOX_CONTROL_FUTURE_SKEW_MS,
22
22
  SANDBOX_CONTROL_STATUS_STALE_MS
23
- } from '../../sandbox/control/protocol.ts';
24
- import { getProcessStartTime } from '../../server/process-state.ts';
25
- import { assertGitWorktreeBinding } from '../../git/worktree-identity.ts';
23
+ } from '../sandbox/control/protocol.ts';
24
+ import { getProcessStartTime } from '../server/process-state.ts';
25
+ import { assertGitWorktreeBinding } from '../git/worktree-identity.ts';
26
26
 
27
- const USAGE = `Usage: ai task validate <branch | TASK-id | N> [--scope snapshot|inplace] [--timeout <ms>] [--format text|json] -- <command> [args...]`;
27
+ const USAGE = `Usage: agent-infra-internal task-validate <branch | TASK-id | N> [--scope snapshot|inplace] [--timeout <ms>] [--format text|json] -- <command> [args...]`;
28
28
  const MAX_TIMEOUT_MS = 60 * 60 * 1000;
29
29
  const RECOVERY_GRACE_MS = 30_000;
30
30
 
@@ -250,33 +250,68 @@ function inplaceValidation(config: ReturnType<typeof loadConfig>, target: Return
250
250
  }
251
251
  }
252
252
 
253
- export async function validate(args: string[]): Promise<number> {
254
- const options = parseValidateArgs(args);
253
+ function errorCode(message: string): string {
254
+ const match = message.match(/^([A-Z][A-Z0-9_]*)/);
255
+ return match && match[1]!.length >= 3 ? match[1]! : 'TASK_VALIDATE_FAILED';
256
+ }
257
+
258
+ function fail(format: 'text' | 'json', code: string, message: string): void {
259
+ if (format === 'json') {
260
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code, message } })}\n`);
261
+ } else {
262
+ process.stderr.write(`${message}\n`);
263
+ }
264
+ process.exitCode = 1;
265
+ }
266
+
267
+ function sniffFormat(args: string[]): 'text' | 'json' {
268
+ const index = args.indexOf('--format');
269
+ return index >= 0 && args[index + 1] === 'json' ? 'json' : 'text';
270
+ }
271
+
272
+ function taskValidate(args: string[]): void {
273
+ let options: ValidateOptions;
274
+ try {
275
+ options = parseValidateArgs(args);
276
+ } catch (error) {
277
+ fail(sniffFormat(args), 'TASK_VALIDATE_ARGS_INVALID', error instanceof Error ? error.message : String(error));
278
+ return;
279
+ }
255
280
  if (options.help) {
256
281
  process.stdout.write(`${USAGE}\n`);
257
- return 0;
282
+ return;
283
+ }
284
+ try {
285
+ const config = loadConfig();
286
+ const target = resolveSandboxTarget(options.target, config.repoRoot);
287
+ const commit = git(config.repoRoot, ['rev-parse', target.branch]);
288
+ const startedAt = new Date().toISOString();
289
+ const result = options.scope === 'snapshot'
290
+ ? snapshotValidation(config.repoRoot, commit, options)
291
+ : inplaceValidation(config, target, options);
292
+ const evidence = {
293
+ version: 1,
294
+ taskId: target.workspace.mode === 'task-bound' ? target.workspace.taskId : null,
295
+ branch: target.branch,
296
+ scope: options.scope,
297
+ commit,
298
+ command: path.basename(options.command[0]!),
299
+ startedAt,
300
+ completedAt: new Date().toISOString(),
301
+ exitCode: result.exitCode,
302
+ signal: result.signal,
303
+ cleanup: result.cleanup()
304
+ };
305
+ if (options.format === 'json') {
306
+ process.stdout.write(`${JSON.stringify({ status: 'applied', changed: false, evidence, error: null })}\n`);
307
+ } else {
308
+ process.stdout.write(`Validation ${result.exitCode === 0 ? 'passed' : 'failed'} (${options.scope}, ${evidence.command}, cleanup=${evidence.cleanup}).\n`);
309
+ }
310
+ process.exitCode = result.exitCode;
311
+ } catch (error) {
312
+ const message = error instanceof Error ? error.message : String(error);
313
+ fail(options.format, errorCode(message), message);
258
314
  }
259
- const config = loadConfig();
260
- const target = resolveSandboxTarget(options.target, config.repoRoot);
261
- const commit = git(config.repoRoot, ['rev-parse', target.branch]);
262
- const startedAt = new Date().toISOString();
263
- const result = options.scope === 'snapshot'
264
- ? snapshotValidation(config.repoRoot, commit, options)
265
- : inplaceValidation(config, target, options);
266
- const evidence = {
267
- version: 1,
268
- taskId: target.workspace.mode === 'task-bound' ? target.workspace.taskId : null,
269
- branch: target.branch,
270
- scope: options.scope,
271
- commit,
272
- command: path.basename(options.command[0]!),
273
- startedAt,
274
- completedAt: new Date().toISOString(),
275
- exitCode: result.exitCode,
276
- signal: result.signal,
277
- cleanup: result.cleanup()
278
- };
279
- if (options.format === 'json') process.stdout.write(`${JSON.stringify(evidence)}\n`);
280
- else process.stdout.write(`Validation ${result.exitCode === 0 ? 'passed' : 'failed'} (${options.scope}, ${evidence.command}, cleanup=${evidence.cleanup}).\n`);
281
- return result.exitCode;
282
315
  }
316
+
317
+ export { taskValidate };
@@ -11,12 +11,24 @@ import type { GitHubClient } from './github-client.ts';
11
11
  import { listRemoteComments, normalizeCommentContent, writeComment } from './issue-comments.ts';
12
12
  import { platformResult } from './types.ts';
13
13
  import type { PlatformResult } from './types.ts';
14
+ import type { OperationWarning } from '../task/operation-outcome.ts';
14
15
 
15
16
  type SummaryComment = { id: number; body: string };
16
17
  type SummaryContextResult = PlatformResult & {
17
18
  task: { id: string | null; prNumber: number | null };
18
19
  artifacts: Array<{ family: string; name: string; path: string }>;
19
20
  };
21
+ type PullRequestSummaryResult = PlatformResult & {
22
+ result: 'pr_created_with_warnings' | 'pr_reused_with_warnings' | 'no_op_with_warnings' | null;
23
+ warnings: readonly OperationWarning[];
24
+ };
25
+ type PullRequestPrimaryResult = 'pr_created' | 'pr_reused' | 'no_op';
26
+
27
+ function warningResultForPrimary(primaryResult: PullRequestPrimaryResult): NonNullable<PullRequestSummaryResult['result']> {
28
+ if (primaryResult === 'pr_created') return 'pr_created_with_warnings';
29
+ if (primaryResult === 'pr_reused') return 'pr_reused_with_warnings';
30
+ return 'no_op_with_warnings';
31
+ }
20
32
 
21
33
  function summaryMarker(taskId: string): string {
22
34
  return `<!-- sync-pr:${taskId}:summary -->`;
@@ -61,20 +73,50 @@ function summaryContext(taskRef: string, options: { cwd?: string; client?: GitHu
61
73
  return { ...platformResult('no-op'), task: { id: resolved.taskId, prNumber }, artifacts: canonicalArtifacts(resolved.taskDir) };
62
74
  }
63
75
 
64
- function syncPullRequestSummary(taskRef: string, options: { agent: string; body: string; cwd?: string; client?: GitHubClient; dryRun?: boolean }): PlatformResult {
76
+ function syncPullRequestSummary(taskRef: string, options: { agent: string; body: string; cwd?: string; client?: GitHubClient; dryRun?: boolean; primaryResult: PullRequestPrimaryResult }): PullRequestSummaryResult {
77
+ const warningResult = warningResultForPrimary(options.primaryResult);
78
+ let knownPrNumber: number | null = null;
79
+ const softenFailure = (output: PlatformResult): PullRequestSummaryResult => {
80
+ const prNumber = output.resource.kind === 'pull-request' && output.resource.number
81
+ ? output.resource.number
82
+ : knownPrNumber;
83
+ const warning = output.error && prNumber
84
+ && output.error.code !== 'PR_NOT_LINKED'
85
+ ? {
86
+ code: output.error.code,
87
+ message: output.error.message,
88
+ retryable: output.error.retryable,
89
+ step: 'pr-summary',
90
+ target: `pull-request:${prNumber}`,
91
+ severity: 'ACTION_REQUIRED' as const
92
+ }
93
+ : null;
94
+ return warning
95
+ ? {
96
+ ...output,
97
+ status: 'applied',
98
+ changed: false,
99
+ resource: { kind: 'pull-request', number: prNumber },
100
+ error: null,
101
+ result: warningResult,
102
+ warnings: [warning]
103
+ }
104
+ : { ...output, result: null, warnings: [] };
105
+ };
65
106
  const resolved = resolveTaskRef(taskRef, options.cwd ? { repoRoot: options.cwd } : {});
66
- if (!resolved.ok) return platformResult('failed', { error: { code: resolved.code, message: resolved.message, retryable: false } });
107
+ if (!resolved.ok) return softenFailure(platformResult('failed', { error: { code: resolved.code, message: resolved.message, retryable: false } }));
67
108
  const frontmatter = parseTaskFrontmatter(fs.readFileSync(resolved.taskMdPath, 'utf8'));
68
109
  const prNumber = Number(frontmatter.pr_number);
69
- if (!Number.isInteger(prNumber) || prNumber <= 0) return platformResult('failed', { error: { code: 'PR_NOT_LINKED', message: 'Task has no valid pr_number', retryable: false } });
110
+ if (!Number.isInteger(prNumber) || prNumber <= 0) return softenFailure(platformResult('failed', { error: { code: 'PR_NOT_LINKED', message: 'Task has no valid pr_number', retryable: false } }));
111
+ knownPrNumber = prNumber;
70
112
  const client = options.client || createGitHubClient();
71
113
  const context = resolvePlatformContext({ cwd: resolved.repoRoot, client });
72
- if (!context.platform.repository || !['no-op', 'degraded'].includes(context.status)) return context;
114
+ if (!context.platform.repository || !['no-op', 'degraded'].includes(context.status)) return softenFailure(context);
73
115
  let headSha: string;
74
116
  try {
75
117
  headSha = execFileSync('git', ['rev-parse', 'HEAD'], { cwd: resolved.repoRoot, encoding: 'utf8' }).trim();
76
118
  } catch (error) {
77
- return platformResult('failed', { platform: context.platform, capabilities: context.capabilities, error: { code: 'GIT_HEAD_UNRESOLVED', message: error instanceof Error ? error.message : String(error), retryable: false } });
119
+ return softenFailure(platformResult('failed', { platform: context.platform, capabilities: context.capabilities, error: { code: 'GIT_HEAD_UNRESOLVED', message: error instanceof Error ? error.message : String(error), retryable: false } }));
78
120
  }
79
121
  const desired = buildPullRequestSummary(
80
122
  resolved.taskId,
@@ -83,15 +125,17 @@ function syncPullRequestSummary(taskRef: string, options: { agent: string; body:
83
125
  renderHumanOverrideAudit(fs.readFileSync(resolved.taskMdPath, 'utf8'))
84
126
  );
85
127
  const listed = listRemoteComments(client, context.platform.repository, prNumber, resolved.repoRoot);
86
- if (!listed.ok) return platformResult(listed.error.retryable ? 'blocked' : 'failed', { platform: context.platform, capabilities: context.capabilities, resource: { kind: 'pull-request', number: prNumber }, error: listed.error });
128
+ if (!listed.ok) return softenFailure(platformResult(listed.error.retryable ? 'blocked' : 'failed', { platform: context.platform, capabilities: context.capabilities, resource: { kind: 'pull-request', number: prNumber }, error: listed.error }));
87
129
  const reconciliation = reconcileSummaryComment(listed.value, resolved.taskId, desired);
88
- if (reconciliation.action === 'conflict') return platformResult('failed', { platform: context.platform, capabilities: context.capabilities, resource: { kind: 'pull-request', number: prNumber }, error: { code: 'PR_SUMMARY_MARKER_AMBIGUOUS', message: 'Multiple PR comments contain the summary marker', retryable: false } });
89
- if (reconciliation.action === 'no-op') return platformResult('no-op', { platform: context.platform, capabilities: context.capabilities, resource: { kind: 'pull-request', number: prNumber }, comment: { kind: 'summary', marker: summaryMarker(resolved.taskId), ids: [reconciliation.commentId!], parts: 1 }, error: null });
90
- if (options.dryRun) return platformResult('planned', { platform: context.platform, capabilities: context.capabilities, resource: { kind: 'pull-request', number: prNumber }, operations: [{ name: `summary:${reconciliation.action}`, status: 'planned', reasonCode: null }], error: null });
130
+ if (reconciliation.action === 'conflict') return softenFailure(platformResult('failed', { platform: context.platform, capabilities: context.capabilities, resource: { kind: 'pull-request', number: prNumber }, error: { code: 'PR_SUMMARY_MARKER_AMBIGUOUS', message: 'Multiple PR comments contain the summary marker', retryable: false } }));
131
+ if (reconciliation.action === 'no-op') return softenFailure(platformResult('no-op', { platform: context.platform, capabilities: context.capabilities, resource: { kind: 'pull-request', number: prNumber }, comment: { kind: 'summary', marker: summaryMarker(resolved.taskId), ids: [reconciliation.commentId!], parts: 1 }, error: null }));
132
+ if (options.dryRun) return softenFailure(platformResult('planned', { platform: context.platform, capabilities: context.capabilities, resource: { kind: 'pull-request', number: prNumber }, operations: [{ name: `summary:${reconciliation.action}`, status: 'planned', reasonCode: null }], error: null }));
91
133
  const written = writeComment(client, context.platform.repository, prNumber, resolved.repoRoot, desired, reconciliation.commentId || undefined);
92
- if (!written.ok) return platformResult(written.error.retryable ? 'blocked' : 'failed', { platform: context.platform, capabilities: context.capabilities, resource: { kind: 'pull-request', number: prNumber }, error: written.error });
134
+ if (!written.ok) return softenFailure(platformResult(written.error.retryable ? 'blocked' : 'failed', { platform: context.platform, capabilities: context.capabilities, resource: { kind: 'pull-request', number: prNumber }, error: written.error }));
93
135
  const id = Number(written.value.id || reconciliation.commentId);
94
- return platformResult('applied', { platform: context.platform, capabilities: context.capabilities, resource: { kind: 'pull-request', number: prNumber }, comment: { kind: 'summary', marker: summaryMarker(resolved.taskId), ids: Number.isInteger(id) ? [id] : [], parts: 1 }, operations: [{ name: `summary:${reconciliation.action}`, status: 'applied', reasonCode: null }], error: null });
136
+ return softenFailure(platformResult('applied', { platform: context.platform, capabilities: context.capabilities, resource: { kind: 'pull-request', number: prNumber }, comment: { kind: 'summary', marker: summaryMarker(resolved.taskId), ids: Number.isInteger(id) ? [id] : [], parts: 1 }, operations: [{ name: `summary:${reconciliation.action}`, status: 'applied', reasonCode: null }], error: null }));
95
137
  }
96
138
 
97
139
  export { buildPullRequestSummary, reconcileSummaryComment, summaryContext, summaryMarker, syncPullRequestSummary };
140
+ export type { PullRequestSummaryResult, SummaryContextResult };
141
+ export { warningResultForPrimary };