@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.
- package/README.md +0 -2
- package/README.zh-CN.md +0 -2
- package/dist/bin/internal-cli.js +2 -17
- package/dist/lib/agent-clients/adapter.js +0 -13
- package/dist/lib/agent-clients/adapters/antigravity-cli.js +0 -5
- package/dist/lib/agent-clients/adapters/claude-code-credentials.js +0 -17
- package/dist/lib/agent-clients/adapters/claude-code.js +0 -9
- package/dist/lib/agent-clients/adapters/codex.js +0 -52
- package/dist/lib/agent-clients/adapters/opencode.js +0 -5
- package/dist/lib/agent-clients/adapters/traecli.js +0 -5
- package/dist/lib/agent-clients/config.js +19 -54
- package/dist/lib/agent-clients/registry.js +1 -12
- package/dist/lib/agent-clients/schema.js +0 -18
- package/dist/lib/agent-clients/tokens.js +1 -2
- package/dist/lib/agent-clients/types.js +0 -1
- package/dist/lib/decide.js +2 -0
- package/dist/lib/git/worktree-identity.js +1 -9
- package/dist/lib/internal/agent-client.js +2 -62
- package/dist/lib/internal/cli-route-inventory.js +1 -5
- package/dist/lib/internal/manual-validation.js +18 -10
- package/dist/lib/internal/task-create.js +1 -1
- package/dist/lib/internal/task-event.js +1 -8
- package/dist/lib/internal/task-finalization.js +0 -1
- package/dist/lib/internal/task-lifecycle.js +2 -2
- package/dist/lib/internal/task-operation-registry.js +4 -20
- package/dist/lib/internal/task-review.js +4 -4
- package/dist/lib/platform/comment-safety.js +1 -7
- package/dist/lib/platform/in-label-sync.js +1 -14
- package/dist/lib/platform/issue-comments.js +1 -16
- package/dist/lib/platform/issues.js +1 -1
- package/dist/lib/platform/operation-coordinator.js +4 -2
- package/dist/lib/platform/pr-change-report.js +1 -4
- package/dist/lib/platform/pr-checks.js +2 -8
- package/dist/lib/platform/provider-validation.js +0 -20
- package/dist/lib/platform/pull-requests.js +73 -84
- package/dist/lib/platform/releases.js +1 -43
- package/dist/lib/platform/verification-required.js +0 -2
- package/dist/lib/platform/verification-sync.js +1 -79
- package/dist/lib/process-data/normalize.js +1 -185
- package/dist/lib/process-data/privacy.js +1 -16
- package/dist/lib/process-data/sources.js +2 -279
- package/dist/lib/render.js +0 -12
- package/dist/lib/run/index.js +15 -10
- package/dist/lib/run/skills.js +0 -3
- package/dist/lib/sandbox/commands/create.js +40 -53
- package/dist/lib/sandbox/commands/list-running.js +0 -18
- package/dist/lib/sandbox/commands/start.js +7 -8
- package/dist/lib/sandbox/constants.js +0 -6
- package/dist/lib/sandbox/control/client.js +0 -1
- package/dist/lib/sandbox/control/container-identity.js +1 -16
- package/dist/lib/sandbox/control/executor.js +0 -4
- package/dist/lib/sandbox/control/identity-sentinel.js +0 -7
- package/dist/lib/sandbox/control/lifecycle.js +21 -37
- package/dist/lib/sandbox/control/native-file-lock.js +0 -3
- package/dist/lib/sandbox/control/server.js +18 -38
- package/dist/lib/sandbox/control/state.js +1 -9
- package/dist/lib/sandbox/dockerfile.js +0 -6
- package/dist/lib/sandbox/engine.js +0 -14
- package/dist/lib/sandbox/engines/docker-exact-discovery.js +1 -4
- package/dist/lib/sandbox/engines/wsl2-paths.js +0 -3
- package/dist/lib/sandbox/recovery.js +24 -26
- package/dist/lib/sandbox/removal.js +11 -519
- package/dist/lib/sandbox/task-resolver.js +0 -41
- package/dist/lib/sandbox/tools.js +1 -4
- package/dist/lib/sandbox/workspace-view.js +1 -2
- package/dist/lib/server/display.js +0 -6
- package/dist/lib/task/activity-intent.js +45 -40
- package/dist/lib/task/activity-log.js +9 -16
- package/dist/lib/task/artifact-command.js +1 -1
- package/dist/lib/task/artifact-lifecycle.js +61 -63
- package/dist/lib/task/artifact-name.js +0 -6
- package/dist/lib/task/artifact-operations.js +3 -3
- package/dist/lib/task/capabilities.js +4 -5
- package/dist/lib/task/commands/log.js +0 -6
- package/dist/lib/task/commands/status.js +17 -60
- package/dist/lib/task/commit-operation.js +28 -39
- package/dist/lib/task/completion-facts.js +56 -43
- package/dist/lib/task/control-authority.js +23 -256
- package/dist/lib/task/control-recovery.js +3 -5
- package/dist/lib/task/create.js +2 -4
- package/dist/lib/task/decision-intents.js +8 -9
- package/dist/lib/task/delivery-target.js +1 -40
- package/dist/lib/task/events.js +84 -107
- package/dist/lib/task/finalization.js +44 -8
- package/dist/lib/task/ledger-intents.js +1 -1
- package/dist/lib/task/lifecycle-execution.js +38 -33
- package/dist/lib/task/lifecycle.js +49 -41
- package/dist/lib/task/local-artifact-finalization.js +1 -4
- package/dist/lib/task/manual-validation-evidence.js +1 -37
- package/dist/lib/task/platform-operation-recovery.js +67 -24
- package/dist/lib/task/pr-delivery-fact.js +2 -5
- package/dist/lib/task/qualification-confirmation.js +5 -7
- package/dist/lib/task/resolve-ref.js +1 -25
- package/dist/lib/task/review-command.js +2 -2
- package/dist/lib/task/review-finalization.js +1 -21
- package/dist/lib/task/review-fingerprint.js +0 -4
- package/dist/lib/task/secure-fs.js +0 -56
- package/dist/lib/task/short-id.js +1 -39
- package/dist/lib/task/skill-scope.js +0 -1
- package/dist/lib/task/verification-engine.js +58 -282
- package/dist/lib/task/verification.js +6 -3
- package/dist/lib/task/write.js +11 -1
- package/lib/agent-clients/adapter.ts +0 -76
- package/lib/agent-clients/adapters/antigravity-cli.ts +0 -5
- package/lib/agent-clients/adapters/claude-code-credentials.ts +0 -19
- package/lib/agent-clients/adapters/claude-code.ts +0 -9
- package/lib/agent-clients/adapters/codex.ts +0 -56
- package/lib/agent-clients/adapters/opencode.ts +0 -5
- package/lib/agent-clients/adapters/traecli.ts +0 -5
- package/lib/agent-clients/config.ts +20 -61
- package/lib/agent-clients/registry.ts +1 -34
- package/lib/agent-clients/schema.ts +0 -18
- package/lib/agent-clients/tokens.ts +1 -2
- package/lib/agent-clients/types.ts +0 -15
- package/lib/decide.ts +1 -0
- package/lib/git/worktree-identity.ts +0 -10
- package/lib/internal/agent-client.ts +2 -70
- package/lib/internal/cli-route-inventory.ts +1 -4
- package/lib/internal/manual-validation.ts +16 -9
- package/lib/internal/task-create.ts +0 -1
- package/lib/internal/task-event.ts +1 -5
- package/lib/internal/task-finalization.ts +0 -1
- package/lib/internal/task-lifecycle.ts +3 -5
- package/lib/internal/task-operation-registry.ts +3 -19
- package/lib/internal/task-review.ts +4 -4
- package/lib/platform/comment-safety.ts +0 -10
- package/lib/platform/github-provider.ts +0 -2
- package/lib/platform/in-label-sync.ts +0 -16
- package/lib/platform/issue-comments.ts +0 -21
- package/lib/platform/issues.ts +0 -2
- package/lib/platform/operation-coordinator.ts +4 -2
- package/lib/platform/pr-change-report.ts +0 -5
- package/lib/platform/pr-checks.ts +1 -10
- package/lib/platform/pr-review.ts +1 -1
- package/lib/platform/provider-bridge.ts +0 -1
- package/lib/platform/provider-loader.ts +1 -5
- package/lib/platform/provider-validation.ts +1 -49
- package/lib/platform/pull-requests.ts +64 -99
- package/lib/platform/releases.ts +1 -40
- package/lib/platform/verification-required.ts +0 -2
- package/lib/platform/verification-sync.ts +0 -94
- package/lib/process-data/normalize.ts +1 -186
- package/lib/process-data/privacy.ts +2 -19
- package/lib/process-data/sources.ts +3 -283
- package/lib/render.ts +0 -15
- package/lib/run/index.ts +13 -7
- package/lib/run/skills.ts +0 -4
- package/lib/sandbox/commands/create.ts +37 -74
- package/lib/sandbox/commands/list-running.ts +0 -19
- package/lib/sandbox/commands/start.ts +7 -10
- package/lib/sandbox/constants.ts +0 -8
- package/lib/sandbox/control/client.ts +0 -1
- package/lib/sandbox/control/container-identity.ts +1 -16
- package/lib/sandbox/control/executor.ts +1 -5
- package/lib/sandbox/control/identity-sentinel.ts +0 -8
- package/lib/sandbox/control/lifecycle.ts +18 -51
- package/lib/sandbox/control/native-file-lock.ts +0 -8
- package/lib/sandbox/control/protocol.ts +0 -2
- package/lib/sandbox/control/server.ts +13 -39
- package/lib/sandbox/control/state.ts +1 -10
- package/lib/sandbox/dockerfile.ts +0 -11
- package/lib/sandbox/engine.ts +0 -17
- package/lib/sandbox/engines/docker-exact-discovery.ts +1 -5
- package/lib/sandbox/engines/wsl2-paths.ts +0 -4
- package/lib/sandbox/recovery.ts +24 -26
- package/lib/sandbox/removal.ts +11 -696
- package/lib/sandbox/shell.ts +1 -1
- package/lib/sandbox/task-resolver.ts +0 -48
- package/lib/sandbox/tools.ts +1 -5
- package/lib/sandbox/workspace-view.ts +2 -4
- package/lib/server/display.ts +0 -14
- package/lib/server/process-control.ts +1 -1
- package/lib/task/activity-intent.ts +36 -44
- package/lib/task/activity-log.ts +9 -22
- package/lib/task/artifact-command.ts +1 -1
- package/lib/task/artifact-lifecycle.ts +58 -67
- package/lib/task/artifact-name.ts +0 -7
- package/lib/task/artifact-operations.ts +3 -3
- package/lib/task/capabilities.ts +5 -6
- package/lib/task/commands/log.ts +0 -7
- package/lib/task/commands/status.ts +14 -79
- package/lib/task/commit-operation.ts +29 -51
- package/lib/task/completion-facts.ts +45 -42
- package/lib/task/control-authority.ts +27 -317
- package/lib/task/control-recovery.ts +2 -5
- package/lib/task/create.ts +2 -5
- package/lib/task/decision-intents.ts +5 -5
- package/lib/task/delivery-target.ts +0 -40
- package/lib/task/events.ts +89 -123
- package/lib/task/finalization.ts +41 -9
- package/lib/task/ledger-intents.ts +1 -1
- package/lib/task/lifecycle-execution.ts +37 -89
- package/lib/task/lifecycle.ts +48 -44
- package/lib/task/local-artifact-finalization.ts +0 -7
- package/lib/task/manual-validation-evidence.ts +1 -47
- package/lib/task/platform-operation-recovery.ts +50 -26
- package/lib/task/pr-delivery-fact.ts +2 -11
- package/lib/task/qualification-confirmation.ts +6 -6
- package/lib/task/resolve-ref.ts +0 -23
- package/lib/task/review-command.ts +2 -2
- package/lib/task/review-finalization.ts +1 -27
- package/lib/task/review-fingerprint.ts +0 -8
- package/lib/task/secure-fs.ts +0 -42
- package/lib/task/short-id.ts +0 -43
- package/lib/task/skill-scope.ts +0 -1
- package/lib/task/verification-engine.ts +56 -287
- package/lib/task/verification.ts +5 -5
- package/lib/task/write.ts +12 -1
- package/package.json +2 -2
- package/templates/.agents/README.en.md +1 -3
- package/templates/.agents/README.zh-CN.md +0 -2
- package/templates/.agents/rules/README.en.md +0 -1
- package/templates/.agents/rules/README.zh-CN.md +0 -1
- package/templates/.agents/rules/commit-and-pr.en.md +1 -1
- package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -1
- package/templates/.agents/rules/no-mid-flow-questions.en.md +0 -10
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +0 -10
- package/templates/.agents/rules/pr-sync.en.md +1 -1
- package/templates/.agents/rules/pr-sync.zh-CN.md +1 -1
- package/templates/.agents/rules/task-management.en.md +3 -3
- package/templates/.agents/rules/task-management.zh-CN.md +3 -3
- package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/code-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/commit/SKILL.en.md +2 -2
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +6 -6
- package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +6 -6
- package/templates/.agents/skills/plan-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-analysis/SKILL.en.md +3 -3
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/review-code/SKILL.en.md +5 -5
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/review-plan/SKILL.en.md +3 -3
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/review-pr/SKILL.en.md +4 -4
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -1
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +3 -75
- package/templates/.agents/templates/task.en.md +1 -0
- package/templates/.agents/templates/task.zh-CN.md +1 -0
- package/templates/.claude/settings.json +0 -24
- package/templates/.codex/hooks.json +0 -50
- package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +0 -582
- package/dist/lib/agent-clients/adapters/codex-lifecycle/binding.js +0 -114
- package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +0 -237
- package/dist/lib/agent-clients/adapters/codex-lifecycle/cli.js +0 -443
- package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +0 -236
- package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +0 -292
- package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +0 -267
- package/dist/lib/agent-clients/adapters/codex-orchestration.js +0 -466
- package/dist/lib/internal/task-orchestration.js +0 -71
- package/dist/lib/platform/verification.js +0 -6
- package/dist/lib/run/prompt.js +0 -2
- package/dist/lib/sandbox/engines/authority.js +0 -289
- package/dist/lib/task/delegation-receipts.js +0 -410
- package/dist/lib/task/orchestration.js +0 -1233
- package/dist/lib/task/verification-checks.js +0 -9
- package/dist/lib/task/workspace-snapshot.js +0 -121
- package/dist/lifecycle-build-manifest.json +0 -6
- package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +0 -688
- package/lib/agent-clients/adapters/codex-lifecycle/binding.ts +0 -147
- package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +0 -349
- package/lib/agent-clients/adapters/codex-lifecycle/cli.ts +0 -506
- package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +0 -385
- package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +0 -41
- package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +0 -418
- package/lib/agent-clients/adapters/codex-lifecycle/store.ts +0 -354
- package/lib/agent-clients/adapters/codex-orchestration.ts +0 -630
- package/lib/internal/task-orchestration.ts +0 -74
- package/lib/platform/verification.ts +0 -11
- package/lib/run/prompt.ts +0 -1
- package/lib/sandbox/engines/authority.ts +0 -365
- package/lib/task/delegation-receipts.ts +0 -547
- package/lib/task/orchestration.ts +0 -1651
- package/lib/task/verification-checks.ts +0 -10
- package/lib/task/workspace-snapshot.ts +0 -144
- package/templates/.agents/hooks/lifecycle-delegation.js +0 -140
- package/templates/.agents/rules/lifecycle-orchestration.en.md +0 -44
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +0 -44
- package/templates/.agents/skills/run-task/SKILL.en.md +0 -29
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +0 -29
- package/templates/.agents/skills/run-task/config/verify.en.json +0 -10
- package/templates/.agents/skills/run-task/config/verify.zh-CN.json +0 -10
- package/templates/.agents/skills/run-task/reference/host-validation.en.md +0 -24
- package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +0 -24
- package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +0 -6
- package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +0 -6
- package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +0 -6
- package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +0 -6
- package/templates/.claude/commands/run-task.en.md +0 -8
- package/templates/.claude/commands/run-task.zh-CN.md +0 -8
- package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +0 -3
- package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +0 -3
- package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +0 -3
- package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +0 -3
- package/templates/.opencode/commands/run-task.en.md +0 -11
- 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 {
|
|
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
|
|
842
|
-
const
|
|
843
|
-
|
|
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:
|
|
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
|
-
{
|
|
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
|
|
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
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
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)) &&
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
1200
|
-
|
|
1201
|
-
:
|
|
1202
|
-
|
|
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 !==
|
|
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 ===
|
|
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 !==
|
|
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
|
|
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
|
-
{
|
|
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
|
|
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
|
-
|
|
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 };
|
package/lib/platform/releases.ts
CHANGED
|
@@ -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
|
|
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
|