@fitlab-ai/agent-infra 0.12.0 → 0.12.1

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 (46) hide show
  1. package/dist/lib/internal/manual-validation.js +11 -17
  2. package/dist/lib/internal/platform-comment.js +56 -7
  3. package/dist/lib/platform/issue-comments.js +373 -267
  4. package/dist/lib/platform/issue-summary-content.js +112 -0
  5. package/dist/lib/platform/pr-change-report.js +175 -26
  6. package/dist/lib/platform/pr-summary-content.js +54 -0
  7. package/dist/lib/platform/pr-summary.js +318 -284
  8. package/dist/lib/platform/summary-content-pipeline.js +18 -0
  9. package/dist/lib/sandbox/removal.js +59 -2
  10. package/dist/lib/task/finalization.js +16 -7
  11. package/dist/lib/task/platform-operation-recovery.js +87 -87
  12. package/dist/lifecycle-build-manifest.json +3 -3
  13. package/lib/internal/manual-validation.ts +12 -18
  14. package/lib/internal/platform-comment.ts +46 -4
  15. package/lib/platform/issue-comments.ts +478 -280
  16. package/lib/platform/issue-summary-content.ts +132 -0
  17. package/lib/platform/pr-change-report.ts +165 -20
  18. package/lib/platform/pr-summary-content.ts +60 -0
  19. package/lib/platform/pr-summary.ts +364 -257
  20. package/lib/platform/summary-content-pipeline.ts +23 -0
  21. package/lib/sandbox/removal.ts +57 -1
  22. package/lib/task/finalization.ts +11 -6
  23. package/lib/task/platform-operation-recovery.ts +70 -81
  24. package/package.json +1 -1
  25. package/templates/.agents/rules/pr-sync.en.md +4 -2
  26. package/templates/.agents/rules/pr-sync.zh-CN.md +6 -9
  27. package/templates/.agents/skills/cancel-task/SKILL.en.md +1 -1
  28. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +1 -1
  29. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  30. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  31. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +2 -2
  32. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +2 -2
  33. package/templates/.agents/skills/complete-task/SKILL.en.md +10 -25
  34. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +11 -26
  35. package/templates/.agents/skills/create-pr/SKILL.en.md +1 -1
  36. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +1 -1
  37. package/templates/.agents/skills/create-pr/reference/change-report.en.md +9 -2
  38. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +9 -2
  39. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +2 -2
  40. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +2 -2
  41. package/templates/.agents/skills/create-task/SKILL.en.md +0 -18
  42. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +0 -18
  43. package/templates/.agents/skills/watch-pr/SKILL.en.md +1 -1
  44. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +1 -1
  45. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +3 -3
  46. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +3 -3
@@ -2,9 +2,10 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { locateActivityLog, pairEntries } from '../task/activity-log.js';
4
4
  import { resolveTaskRef } from '../task/resolve-ref.js';
5
+ import { prepareAndRenderPrSummaryContent } from '../platform/pr-summary.js';
5
6
  import { applyTaskEvent } from '../task/events.js';
6
7
  import { normalizeAgentToken } from '../agent-clients/tokens.js';
7
- import { MANUAL_VALIDATION_RECEIPT_PLACEHOLDER, createManualValidationReceipt, manualValidationFinalSummaryDigest, manualValidationFinalSummaryProjectionMatches, readManualValidationReceipt, writeManualValidationReceiptAtomic } from '../task/manual-validation-receipt.js';
8
+ import { createManualValidationReceipt, manualValidationFinalSummaryDigest, manualValidationFinalSummaryProjectionMatches, readManualValidationReceipt, writeManualValidationReceiptAtomic } from '../task/manual-validation-receipt.js';
8
9
  import { archiveManualValidationGeneration, createManualValidationTransaction, readManualValidationTransaction, retryManualValidationTransaction, summaryPreimageDigest, transitionManualValidationTransaction, validateManualValidationGenerationArchive, writeManualValidationTransactionAtomic } from '../task/manual-validation-transaction.js';
9
10
  import { sha256File } from '../task/artifact-receipts.js';
10
11
  import { summaryCommentState, syncPullRequestSummary } from '../platform/pr-summary.js';
@@ -21,22 +22,14 @@ function printFailure(format, error) {
21
22
  process.stderr.write(`${error.code}: ${error.message}\n`);
22
23
  process.exitCode = 1;
23
24
  }
24
- const MANUAL_VALIDATION_STATUS_HEADING = /^###\s+(?:⚠️\s+(?:需人工校验|Manual Validation Required)|✅\s+(?:人工验证已通过|无需人工校验|Manual Validation Passed|No Manual Validation Required)|⏳\s+(?:人工验证待收尾|Manual Validation Pending))\s*$/mu;
25
25
  function manualSummaryBody(body, phase) {
26
- const chinese = /###\s+(?:⚠️\s+需人工校验|✅\s+(?:人工验证已通过|无需人工校验)|⏳\s+人工验证待收尾)\s*$/mu.test(body);
27
- const heading = phase === 'pending'
28
- ? chinese ? '### ⏳ 人工验证待收尾' : '### ⏳ Manual Validation Pending'
29
- : chinese ? '### ✅ 人工验证已通过' : '### ✅ Manual Validation Passed';
30
- const marker = phase === 'final'
31
- ? `\n\n${MANUAL_VALIDATION_RECEIPT_PLACEHOLDER}`
32
- : '';
33
- if (MANUAL_VALIDATION_STATUS_HEADING.test(body)) {
34
- return `${body.replace(MANUAL_VALIDATION_STATUS_HEADING, `${heading}${marker}`).replace(/\s+$/u, '')}\n`;
35
- }
36
- const fallback = phase === 'pending'
37
- ? chinese ? '人工验证正在等待最终完成。' : 'Manual validation is awaiting final promotion.'
38
- : chinese ? '人工验证已通过。' : 'Manual validation passed.';
39
- return `${body.replace(/\s+$/u, '')}\n\n${heading}${marker}\n\n${fallback}\n`;
26
+ const content = JSON.parse(body);
27
+ const manual = content.manualValidation;
28
+ manual.state = phase === 'pending' ? 'pending' : 'passed';
29
+ return JSON.stringify(content);
30
+ }
31
+ function renderedManualSummaryBody(body, phase, taskContent) {
32
+ return prepareAndRenderPrSummaryContent(JSON.parse(manualSummaryBody(body, phase)), taskContent).rendered;
40
33
  }
41
34
  function openManualValidationStarted(taskMdPath) {
42
35
  let content;
@@ -90,6 +83,7 @@ async function executeManualValidationTransactionAtResolvedTask(taskRef, values,
90
83
  const preimage = { commentId: currentState.comment?.id ?? null, body: preimageBody, digest: summaryPreimageDigest(preimageBody) };
91
84
  const summaryPath = path.resolve(cwd, values.summaryFile);
92
85
  const finalBodyWithoutReceipt = fs.readFileSync(summaryPath, 'utf8');
86
+ const taskContent = fs.readFileSync(resolved.taskMdPath, 'utf8');
93
87
  const evidenceDigest = sha256File(summaryPath);
94
88
  const archiveGeneration = options.archiveGeneration ?? archiveManualValidationGeneration;
95
89
  let transactionResult = readManualValidationTransaction(resolved.taskDir, { taskId: resolved.taskId, prNumber: pullRequest.number, prHeadSha: pullRequest.head.sha, evidenceDigest, artifact: values.artifact });
@@ -132,7 +126,7 @@ async function executeManualValidationTransactionAtResolvedTask(taskRef, values,
132
126
  evidenceDigest,
133
127
  summaryPreimage: preimage,
134
128
  pendingSummaryDigest: summaryPreimageDigest(pendingBody),
135
- finalSummaryDigest: manualValidationFinalSummaryDigest(manualSummaryBody(finalBodyWithoutReceipt, 'final')),
129
+ finalSummaryDigest: manualValidationFinalSummaryDigest(renderedManualSummaryBody(finalBodyWithoutReceipt, 'final', taskContent)),
136
130
  artifact: values.artifact,
137
131
  attempt: 1,
138
132
  createdAt: new Date().toISOString(),
@@ -10,6 +10,9 @@ import { recoverTaskFromComments } from '../platform/task-recovery.js';
10
10
  import { backfillCompletionComments } from '../platform/completion-backfill.js';
11
11
  import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.js';
12
12
  import { resolveTaskRef } from '../task/resolve-ref.js';
13
+ import { enumerateArtifacts } from '../task/artifacts.js';
14
+ import { parseTaskFrontmatter } from '../task/frontmatter.js';
15
+ import { prepareAndRenderCancelSummaryContent, prepareAndRenderDeliverySummaryContent } from '../platform/issue-summary-content.js';
13
16
  const USAGE = `Usage: agent-infra-internal platform-comment list --issue <token> [--cwd <path>]
14
17
  agent-infra-internal platform-comment recover --issue <token> --task-id <TASK-id> --output <staging-task.md> [--cwd <path>]
15
18
  agent-infra-internal platform-comment owner <task-ref> [--cwd <path>]
@@ -202,19 +205,34 @@ async function platformComment(args = []) {
202
205
  fail(`unable to read body file: ${error instanceof Error ? error.message : String(error)}`);
203
206
  return;
204
207
  }
205
- const canonical = canonicalizeSummaryBody(body);
206
- if (!canonical.ok) {
207
- fail(`unable to stage summary: ${canonical.error.code}: ${canonical.error.message}`);
208
- return;
209
- }
210
- body = canonical.value;
211
208
  const resolved = resolveTaskRef(taskRef, { repoRoot: cwd });
212
209
  if (!resolved.ok || resolved.state !== 'active') {
213
210
  fail('stage-summary requires an active task');
214
211
  return;
215
212
  }
216
213
  const target = path.join(resolved.taskDir, '.delivery-summary.json');
217
- const value = { taskId: resolved.taskId, body, sha256: createHash('sha256').update(body).digest('hex') };
214
+ let content;
215
+ try {
216
+ const supplied = JSON.parse(body);
217
+ const taskContent = fs.readFileSync(resolved.taskMdPath, 'utf8');
218
+ const title = /^#\s+(.+)$/mu.exec(taskContent)?.[1]?.trim();
219
+ const prepared = prepareAndRenderDeliverySummaryContent(supplied, {
220
+ taskId: resolved.taskId,
221
+ title: title || resolved.taskId,
222
+ artifacts: enumerateArtifacts(resolved.taskDir).filter((artifact) => artifact.name !== 'task.md').map((artifact) => artifact.name),
223
+ verificationFallback: { state: 'not-run', detail: 'Final verification has not run at summary staging.' }
224
+ });
225
+ content = prepared.content;
226
+ const canonical = canonicalizeSummaryBody(prepared.rendered);
227
+ if (!canonical.ok)
228
+ throw new Error(`${canonical.error.code}: ${canonical.error.message}`);
229
+ body = canonical.value;
230
+ }
231
+ catch (error) {
232
+ fail(`unable to stage summary: ${error instanceof Error ? error.message : String(error)}`);
233
+ return;
234
+ }
235
+ const value = { taskId: resolved.taskId, content, contentSha256: createHash('sha256').update(JSON.stringify(content)).digest('hex') };
218
236
  const previous = fs.existsSync(target) ? fs.readFileSync(target, 'utf8') : null;
219
237
  const next = `${JSON.stringify(value)}\n`;
220
238
  if (previous === next) {
@@ -273,6 +291,37 @@ async function platformComment(args = []) {
273
291
  fail(`unable to read body file: ${error instanceof Error ? error.message : String(error)}`);
274
292
  return;
275
293
  }
294
+ if (kind === 'summary' || kind === 'cancel') {
295
+ try {
296
+ const input = JSON.parse(body);
297
+ const resolved = resolveTaskRef(taskRef, { repoRoot: cwd });
298
+ if (!resolved.ok)
299
+ throw new Error(resolved.message);
300
+ const taskContent = fs.readFileSync(resolved.taskMdPath, 'utf8');
301
+ const taskFrontmatter = parseTaskFrontmatter(taskContent);
302
+ const title = /^#\s+(.+)$/mu.exec(taskContent)?.[1]?.trim();
303
+ const artifacts = enumerateArtifacts(resolved.taskDir).filter((artifact) => artifact.name !== 'task.md').map((artifact) => artifact.name);
304
+ const rendered = kind === 'summary'
305
+ ? prepareAndRenderDeliverySummaryContent(input, {
306
+ taskId: resolved.taskId,
307
+ title: title || resolved.taskId,
308
+ artifacts,
309
+ ...(resolved.state === 'active' ? { verificationFallback: { state: 'not-run', detail: 'Final verification has not run at summary staging.' } } : {})
310
+ }).rendered
311
+ : prepareAndRenderCancelSummaryContent(input, {
312
+ taskId: resolved.taskId,
313
+ title: title || resolved.taskId,
314
+ reason: typeof taskFrontmatter.cancel_reason === 'string' ? taskFrontmatter.cancel_reason : '',
315
+ cancelledAt: typeof taskFrontmatter.cancelled_at === 'string' ? taskFrontmatter.cancelled_at : '',
316
+ lastCompletedArtifact: artifacts.at(-1) ?? null
317
+ }).rendered;
318
+ body = rendered;
319
+ }
320
+ catch (error) {
321
+ fail(`invalid ${kind} summary structure: ${error instanceof Error ? error.message : String(error)}`);
322
+ return;
323
+ }
324
+ }
276
325
  finish(await syncPlatformComment(taskRef, {
277
326
  kind: kind,
278
327
  agent: normalizedAgent,