@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,11 +1,10 @@
|
|
|
1
|
-
import { normalizePullRequest } from './github-data.js';
|
|
2
1
|
import fs from 'node:fs';
|
|
3
2
|
import path from 'node:path';
|
|
4
3
|
import { createHash } from 'node:crypto';
|
|
5
4
|
import { execFileSync } from 'node:child_process';
|
|
6
5
|
import { parseTypedTaskFrontmatter } from '../task/frontmatter.js';
|
|
7
6
|
import { resolveTaskRef } from '../task/resolve-ref.js';
|
|
8
|
-
import {
|
|
7
|
+
import { activityWarnings, locateActivityLog } from '../task/activity-log.js';
|
|
9
8
|
import { captureTaskWriteMetadata, writeTask } from '../task/write.js';
|
|
10
9
|
import { resolvePlatformProviderContext } from './context.js';
|
|
11
10
|
import { inspectPlatformIssue } from './issues.js';
|
|
@@ -162,39 +161,6 @@ function expectedHead(repository, head) {
|
|
|
162
161
|
const repoName = repository.split('/')[1] || '';
|
|
163
162
|
return { repository: `${head.slice(0, colon)}/${repoName}`, ref: head.slice(colon + 1) };
|
|
164
163
|
}
|
|
165
|
-
function selectPullRequest(remotes, repository, head, base, expectedSha) {
|
|
166
|
-
const wanted = expectedHead(repository, head);
|
|
167
|
-
const matches = remotes.flatMap((remote) => {
|
|
168
|
-
const normalized = normalizePullRequest(remote, repository);
|
|
169
|
-
return normalized && normalized.state === 'open' && normalized.head.repository === wanted.repository &&
|
|
170
|
-
normalized.head.ref === wanted.ref && normalized.base.repository === repository && normalized.base.ref === base
|
|
171
|
-
? [normalized] : [];
|
|
172
|
-
});
|
|
173
|
-
if (expectedSha && matches.some((match) => match.head.sha !== expectedSha)) {
|
|
174
|
-
return { status: 'head-mismatch', pullRequest: null };
|
|
175
|
-
}
|
|
176
|
-
if (matches.length === 1)
|
|
177
|
-
return { status: 'resolved', pullRequest: matches[0] };
|
|
178
|
-
return { status: matches.length === 0 ? 'missing' : 'ambiguous', pullRequest: null };
|
|
179
|
-
}
|
|
180
|
-
function validateBoundPullRequest(base, pullRequest, head, baseRef, expectedSha) {
|
|
181
|
-
if (!pullRequest)
|
|
182
|
-
return {
|
|
183
|
-
ok: false,
|
|
184
|
-
error: { code: 'PR_BIND_RECHECK_FAILED', message: 'Bound pull request identity is unavailable', retryable: false }
|
|
185
|
-
};
|
|
186
|
-
const wanted = expectedHead(base.context.platform.repository, head);
|
|
187
|
-
if (pullRequest.head.repository !== wanted.repository
|
|
188
|
-
|| pullRequest.head.ref !== wanted.ref
|
|
189
|
-
|| pullRequest.head.sha !== expectedSha
|
|
190
|
-
|| pullRequest.base.repository !== base.context.platform.repository
|
|
191
|
-
|| pullRequest.base.ref !== baseRef)
|
|
192
|
-
return {
|
|
193
|
-
ok: false,
|
|
194
|
-
error: { code: 'PR_BIND_IDENTITY_MISMATCH', message: 'Bound pull request identity does not match the current expected head/base', retryable: false }
|
|
195
|
-
};
|
|
196
|
-
return { ok: true };
|
|
197
|
-
}
|
|
198
164
|
function resolveTaskDeliveryTarget(repoRoot, frontmatter) {
|
|
199
165
|
const existing = {
|
|
200
166
|
...(typeof frontmatter.delivery_remote === 'string' && frontmatter.delivery_remote
|
|
@@ -682,9 +648,12 @@ async function syncPlatformPullRequestInLabels(prToken, options = {}) {
|
|
|
682
648
|
resources: resourcesState, evidence: { kind: 'pull-request-files', pullRequestFiles: files.value, closingIssues: closingIssueIdentities }, error: null
|
|
683
649
|
});
|
|
684
650
|
}
|
|
685
|
-
function
|
|
686
|
-
const
|
|
687
|
-
|
|
651
|
+
function activityMutation(content, line) {
|
|
652
|
+
const section = locateActivityLog(content);
|
|
653
|
+
if (!section)
|
|
654
|
+
return [];
|
|
655
|
+
return [{ kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: section.heading,
|
|
656
|
+
body: `${section.body}${section.body ? '\n' : ''}${line}` }];
|
|
688
657
|
}
|
|
689
658
|
function deliveryIdentity(pullRequest) {
|
|
690
659
|
return {
|
|
@@ -710,15 +679,11 @@ function boundFactFor(pullRequest, source, issue, verifiedAt) {
|
|
|
710
679
|
});
|
|
711
680
|
}
|
|
712
681
|
function writeCreateStarted(base, agent) {
|
|
713
|
-
const starts = (base.content.match(/\*\*Create PR \[started\]\*\*/g) || []).length;
|
|
714
|
-
const dones = (base.content.match(/\*\*Create PR\*\*/g) || []).length;
|
|
715
|
-
if (starts > dones)
|
|
716
|
-
return { status: 'no-op' };
|
|
717
682
|
const metadata = captureTaskWriteMetadata();
|
|
718
683
|
return writeTask({
|
|
719
684
|
taskRef: base.resolved.taskId,
|
|
720
685
|
expectedState: 'active',
|
|
721
|
-
mutations:
|
|
686
|
+
mutations: activityMutation(base.content, `- ${metadata.timestamp} — **Create PR [started]** by ${agent} — started`)
|
|
722
687
|
}, { repoRoot: base.resolved.repoRoot, metadataProvider: () => metadata });
|
|
723
688
|
}
|
|
724
689
|
function bindIdentity(base, pullRequest, agent, source, dryRun = false, expectedHead, expectedHeadSha) {
|
|
@@ -750,7 +715,7 @@ function bindIdentity(base, pullRequest, agent, source, dryRun = false, expected
|
|
|
750
715
|
dryRun,
|
|
751
716
|
mutations: [
|
|
752
717
|
{ kind: 'frontmatter', set: { ...factMutation.set, assigned_to: agent } },
|
|
753
|
-
|
|
718
|
+
...activityMutation(current, `- ${metadata.timestamp} — **Create PR** by ${agent} — PR #${pullRequest.number} created → ${pullRequest.url}`)
|
|
754
719
|
]
|
|
755
720
|
}, { repoRoot: base.resolved.repoRoot, metadataProvider: () => metadata });
|
|
756
721
|
}
|
|
@@ -779,13 +744,14 @@ async function bindPlatformPullRequestImpl(taskRef, options) {
|
|
|
779
744
|
return inspected;
|
|
780
745
|
const initialIdentity = validateWriterIdentity(base, inspected.pullRequest, {
|
|
781
746
|
expectedHead: String(base.frontmatter.branch || ''),
|
|
747
|
+
expectedHeadSha: options.expectedHeadSha,
|
|
782
748
|
errorCode: 'PR_BIND_IDENTITY_MISMATCH'
|
|
783
749
|
});
|
|
784
750
|
if (!initialIdentity.ok)
|
|
785
751
|
return result('failed', base.resolved.taskId, base.issueNumber, requestedNumber, {
|
|
786
752
|
pullRequest: inspected.pullRequest, error: initialIdentity.error
|
|
787
753
|
});
|
|
788
|
-
const written = bindIdentity(base, inspected.pullRequest, options.agent, 'explicit-bind', options.dryRun);
|
|
754
|
+
const written = bindIdentity(base, inspected.pullRequest, options.agent, 'explicit-bind', options.dryRun, undefined, options.expectedHeadSha);
|
|
789
755
|
if (written.status === 'failed')
|
|
790
756
|
return result('failed', base.resolved.taskId, base.issueNumber, requestedNumber, {
|
|
791
757
|
pullRequest: inspected.pullRequest, error: { code: written.error.code, message: written.error.message, retryable: false }
|
|
@@ -796,7 +762,7 @@ async function bindPlatformPullRequestImpl(taskRef, options) {
|
|
|
796
762
|
operations: [{ name: 'task:bind-pr', status: options.dryRun ? 'planned' : written.status === 'no-op' ? 'no-op' : 'applied', reasonCode: null }], error: null
|
|
797
763
|
});
|
|
798
764
|
}
|
|
799
|
-
async function
|
|
765
|
+
async function bindPlatformPullRequestWithProjection(taskRef, options) {
|
|
800
766
|
const intent = { action: 'bind', prToken: String(options.pr) };
|
|
801
767
|
return journalPullRequestOperation(taskRef, options, intent, `pr:${options.pr}`, { pr: String(options.pr) }, () => bindPlatformPullRequestImpl(taskRef, options));
|
|
802
768
|
}
|
|
@@ -940,32 +906,16 @@ async function resolveExternalPullRequest(taskRef, options) {
|
|
|
940
906
|
}), { candidates: selected.candidates, eligible: selected.eligible, selected: rechecked.value });
|
|
941
907
|
const selectedPullRequest = rechecked.value;
|
|
942
908
|
const note = externalEvidenceNote(base.issueIdentity, selected.source, selectedPullRequest);
|
|
943
|
-
const identityNote = externalIdentityEvidenceNote(base.issueIdentity, selectedPullRequest);
|
|
944
909
|
const activityEntry = `**Bind External PR** by ${options.agent} — ${note}`;
|
|
945
|
-
|
|
946
|
-
const alreadyAudited = auditLines.some((line) => line.endsWith(identityNote));
|
|
947
|
-
if (auditLines.length > 0 && !alreadyAudited)
|
|
910
|
+
if (base.prIdentity && !resourceIdentityEquals(base.prIdentity, pullRequestIdentity(selectedPullRequest)))
|
|
948
911
|
return externalResult(result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
|
|
949
|
-
platform: base.context.platform,
|
|
950
|
-
|
|
951
|
-
pullRequest: selectedPullRequest,
|
|
952
|
-
error: { code: 'PR_BIND_CONFLICT', message: 'Existing external PR audit evidence conflicts with the selected identity', retryable: false }
|
|
912
|
+
platform: base.context.platform, capabilities: base.context.capabilities, pullRequest: selectedPullRequest,
|
|
913
|
+
error: { code: 'PR_BIND_CONFLICT', message: 'Selected identity does not match the task binding', retryable: false }
|
|
953
914
|
}), { candidates: selected.candidates, eligible: selected.eligible, selected: selectedPullRequest });
|
|
954
|
-
if (
|
|
955
|
-
return externalResult(result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
|
|
956
|
-
platform: base.context.platform,
|
|
957
|
-
capabilities: base.context.capabilities,
|
|
958
|
-
pullRequest: selectedPullRequest,
|
|
959
|
-
error: { code: 'PR_BIND_CONFLICT', message: 'External PR audit evidence does not match the task binding', retryable: false }
|
|
960
|
-
}), { candidates: selected.candidates, eligible: selected.eligible, selected: selectedPullRequest });
|
|
961
|
-
if (base.prIdentity && resourceIdentityEquals(base.prIdentity, pullRequestIdentity(selectedPullRequest)) && alreadyAudited) {
|
|
915
|
+
if (base.prIdentity && resourceIdentityEquals(base.prIdentity, pullRequestIdentity(selectedPullRequest)) && base.fact?.state === 'bound') {
|
|
962
916
|
return externalResult(result('no-op', base.resolved.taskId, base.issueNumber, base.prNumber, {
|
|
963
|
-
platform: base.context.platform,
|
|
964
|
-
|
|
965
|
-
resource: { kind: 'pull-request', number: selectedPullRequest.number },
|
|
966
|
-
pullRequest: selectedPullRequest,
|
|
967
|
-
operations: [{ name: 'task:bind-external-pr', status: 'no-op', reasonCode: 'EVIDENCE_ALREADY_RECORDED' }],
|
|
968
|
-
error: null
|
|
917
|
+
platform: base.context.platform, capabilities: base.context.capabilities, pullRequest: selectedPullRequest,
|
|
918
|
+
operations: [{ name: 'task:bind-external-pr', status: 'no-op', reasonCode: 'EVIDENCE_ALREADY_RECORDED' }], error: null
|
|
969
919
|
}), { mode: 'external', authorization: selected.source, candidates: selected.candidates, eligible: selected.eligible, selected: selectedPullRequest });
|
|
970
920
|
}
|
|
971
921
|
const metadata = captureTaskWriteMetadata();
|
|
@@ -975,7 +925,7 @@ async function resolveExternalPullRequest(taskRef, options) {
|
|
|
975
925
|
dryRun: options.dryRun,
|
|
976
926
|
mutations: [
|
|
977
927
|
{ kind: 'frontmatter', set: { ...factFrontmatterMutation(boundFactFor(selectedPullRequest, selected.source === 'unique' ? 'external-unique' : 'external-explicit', base.issueNumber, metadata.timestamp)).set, assigned_to: options.agent } },
|
|
978
|
-
|
|
928
|
+
...activityMutation(base.content, `- ${metadata.timestamp} — ${activityEntry}`)
|
|
979
929
|
]
|
|
980
930
|
}, { repoRoot: base.resolved.repoRoot, metadataProvider: () => metadata });
|
|
981
931
|
if (write.status === 'failed')
|
|
@@ -1006,7 +956,7 @@ async function createPlatformPullRequestImpl(taskRef, options) {
|
|
|
1006
956
|
}), PRECONDITION_NOT_CREATED);
|
|
1007
957
|
}
|
|
1008
958
|
try {
|
|
1009
|
-
return await createExternalPullRequest(
|
|
959
|
+
return await createExternalPullRequest(options, base);
|
|
1010
960
|
}
|
|
1011
961
|
catch (error) {
|
|
1012
962
|
return withCreation(result('failed', base.resolved.taskId, base.issueNumber, null, {
|
|
@@ -1028,17 +978,26 @@ async function recoverCreatedPullRequest(taskRef, options) {
|
|
|
1028
978
|
return result('failed', base.resolved.taskId, base.issueNumber, base.prNumber, {
|
|
1029
979
|
error: { code: 'PLATFORM_OPERATION_ISSUE_REQUIRED', message: 'Pull-request recovery requires a bound Issue identity', retryable: false }
|
|
1030
980
|
});
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
:
|
|
1034
|
-
|
|
1035
|
-
|
|
981
|
+
let headSha;
|
|
982
|
+
if (base.provider.changeRequests?.verifyHead) {
|
|
983
|
+
const head = await base.provider.changeRequests.verifyHead({ context: providerOperationContext(base.loadedContext), head: options.head });
|
|
984
|
+
if (!head.ok)
|
|
985
|
+
return providerPullRequestError(base, head.error, base.prNumber);
|
|
986
|
+
headSha = head.value.sha;
|
|
987
|
+
}
|
|
988
|
+
else {
|
|
989
|
+
headSha = typeof base.frontmatter.delivery_remote_head === 'string' ? base.frontmatter.delivery_remote_head.trim() : '';
|
|
990
|
+
if (!headSha)
|
|
991
|
+
return result('blocked', base.resolved.taskId, base.issueNumber, base.prNumber, {
|
|
992
|
+
error: { code: 'PR_HEAD_UNVERIFIED', message: 'Verify and record the delivered remote head before retrying pull-request recovery', retryable: true }
|
|
993
|
+
});
|
|
994
|
+
}
|
|
1036
995
|
if (base.prIdentity) {
|
|
1037
996
|
const inspected = await inspectExternalPullRequest(base, base.prIdentity);
|
|
1038
997
|
if (!inspected.pullRequest || inspected.status === 'failed' || inspected.status === 'blocked'
|
|
1039
998
|
|| inspected.pullRequest.base.repository !== base.context.platform.repository
|
|
1040
999
|
|| inspected.pullRequest.base.ref !== options.base || inspected.pullRequest.head.ref !== options.head
|
|
1041
|
-
|| inspected.pullRequest.head.sha !==
|
|
1000
|
+
|| inspected.pullRequest.head.sha !== headSha) {
|
|
1042
1001
|
return result('blocked', base.resolved.taskId, base.issueNumber, base.prNumber, {
|
|
1043
1002
|
error: inspected.error ?? { code: 'PLATFORM_OPERATION_PR_NOT_CONFIRMED', message: 'Bound pull request does not match the pending create intent', retryable: true }
|
|
1044
1003
|
});
|
|
@@ -1055,24 +1014,24 @@ async function recoverCreatedPullRequest(taskRef, options) {
|
|
|
1055
1014
|
&& candidate.base.ref === options.base
|
|
1056
1015
|
&& candidate.head.repository === base.context.platform.repository
|
|
1057
1016
|
&& candidate.head.ref === options.head
|
|
1058
|
-
&& candidate.head.sha ===
|
|
1017
|
+
&& candidate.head.sha === headSha);
|
|
1059
1018
|
if (matches.length !== 1 || !matches[0]?.number)
|
|
1060
1019
|
return result('blocked', base.resolved.taskId, base.issueNumber, null, {
|
|
1061
1020
|
error: { code: matches.length > 1 ? 'PLATFORM_OPERATION_PR_AMBIGUOUS' : 'PLATFORM_OPERATION_PR_NOT_CONFIRMED',
|
|
1062
1021
|
message: 'Pending pull-request creation does not resolve to one exact repository/base/head identity', retryable: true }
|
|
1063
1022
|
});
|
|
1064
|
-
const bound = await bindPlatformPullRequest(base.resolved.taskId, { agent: options.agent, cwd: base.resolved.repoRoot, pr: matches[0].number });
|
|
1023
|
+
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 });
|
|
1065
1024
|
if (!bound.pullRequest || (bound.status !== 'applied' && bound.status !== 'no-op') || bound.error)
|
|
1066
1025
|
return bound;
|
|
1067
1026
|
if (bound.pullRequest.base.repository !== base.context.platform.repository || bound.pullRequest.base.ref !== options.base
|
|
1068
1027
|
|| bound.pullRequest.head.repository !== base.context.platform.repository || bound.pullRequest.head.ref !== options.head
|
|
1069
|
-
|| bound.pullRequest.head.sha !==
|
|
1028
|
+
|| bound.pullRequest.head.sha !== headSha)
|
|
1070
1029
|
return result('blocked', base.resolved.taskId, base.issueNumber, bound.task.prNumber, {
|
|
1071
1030
|
error: { code: 'PLATFORM_OPERATION_PR_NOT_CONFIRMED', message: 'Bound pull request changed while recovering the create intent', retryable: true }
|
|
1072
1031
|
});
|
|
1073
1032
|
return bound;
|
|
1074
1033
|
}
|
|
1075
|
-
async function
|
|
1034
|
+
async function createPlatformPullRequestWithProjection(taskRef, options) {
|
|
1076
1035
|
const intent = { action: 'create', baseRef: options.base, headRef: options.head };
|
|
1077
1036
|
const identityInput = {
|
|
1078
1037
|
title: createHash('sha256').update(options.title).digest('hex'),
|
|
@@ -1081,7 +1040,7 @@ async function createPlatformPullRequest(taskRef, options) {
|
|
|
1081
1040
|
};
|
|
1082
1041
|
return journalPullRequestOperation(taskRef, options, intent, `head:${options.head}:base:${options.base}`, identityInput, () => createPlatformPullRequestImpl(taskRef, options));
|
|
1083
1042
|
}
|
|
1084
|
-
async function createExternalPullRequest(
|
|
1043
|
+
async function createExternalPullRequest(options, base) {
|
|
1085
1044
|
if (!base.fact)
|
|
1086
1045
|
return withCreation(result('failed', base.resolved.taskId, base.issueNumber, null, {
|
|
1087
1046
|
error: { code: 'PR_DELIVERY_FACT_MISSING', message: 'Task has no pr_delivery_fact; repair the task metadata or create a new task', retryable: false }
|
|
@@ -1500,7 +1459,7 @@ function applySkippedPullRequestFact(resolved, options) {
|
|
|
1500
1459
|
dryRun: options.dryRun,
|
|
1501
1460
|
mutations: [
|
|
1502
1461
|
{ kind: 'frontmatter', set: { ...factFrontmatterMutation(fact).set, assigned_to: options.agent } },
|
|
1503
|
-
|
|
1462
|
+
...activityMutation(content, `- ${metadata.timestamp} — **Skip PR** by ${options.agent} — PR delivery explicitly skipped`)
|
|
1504
1463
|
]
|
|
1505
1464
|
}, { repoRoot: resolved.repoRoot, metadataProvider: () => metadata });
|
|
1506
1465
|
if (write.status === 'failed')
|
|
@@ -1514,7 +1473,7 @@ function applySkippedPullRequestFact(resolved, options) {
|
|
|
1514
1473
|
error: null
|
|
1515
1474
|
});
|
|
1516
1475
|
}
|
|
1517
|
-
async function
|
|
1476
|
+
async function skipPlatformPullRequestFactWithProjection(taskRef, options) {
|
|
1518
1477
|
const resolved = resolveTaskRef(taskRef, options.cwd ? { repoRoot: options.cwd } : {});
|
|
1519
1478
|
if (!resolved.ok)
|
|
1520
1479
|
return result('failed', resolved.taskId, null, null, {
|
|
@@ -1533,6 +1492,36 @@ async function skipPlatformPullRequestFact(taskRef, options) {
|
|
|
1533
1492
|
});
|
|
1534
1493
|
}
|
|
1535
1494
|
}
|
|
1536
|
-
|
|
1495
|
+
function withActivityWarnings(taskRef, cwd, output) {
|
|
1496
|
+
if (output.status === 'failed' || output.status === 'blocked')
|
|
1497
|
+
return output;
|
|
1498
|
+
const resolved = resolveTaskRef(taskRef, cwd ? { repoRoot: cwd } : {});
|
|
1499
|
+
if (!resolved.ok)
|
|
1500
|
+
return output;
|
|
1501
|
+
let logWarnings;
|
|
1502
|
+
try {
|
|
1503
|
+
logWarnings = activityWarnings(fs.readFileSync(resolved.taskMdPath, 'utf8'));
|
|
1504
|
+
}
|
|
1505
|
+
catch {
|
|
1506
|
+
return output;
|
|
1507
|
+
}
|
|
1508
|
+
if (!logWarnings.length)
|
|
1509
|
+
return output;
|
|
1510
|
+
const warnings = logWarnings.map((item) => ({ ...item, retryable: true, step: 'pr', target: resolved.taskId, severity: 'IMPORTANT' }));
|
|
1511
|
+
return { ...output, warnings: mergeOperationWarnings(output.warnings, warnings) };
|
|
1512
|
+
}
|
|
1513
|
+
async function bindPlatformPullRequest(taskRef, options) {
|
|
1514
|
+
return withActivityWarnings(taskRef, options.cwd, await bindPlatformPullRequestWithProjection(taskRef, options));
|
|
1515
|
+
}
|
|
1516
|
+
async function createPlatformPullRequest(taskRef, options) {
|
|
1517
|
+
return withActivityWarnings(taskRef, options.cwd, await createPlatformPullRequestWithProjection(taskRef, options));
|
|
1518
|
+
}
|
|
1519
|
+
async function resolveExternalPullRequestWithWarnings(taskRef, options) {
|
|
1520
|
+
return withActivityWarnings(taskRef, options.cwd, await resolveExternalPullRequest(taskRef, options));
|
|
1521
|
+
}
|
|
1522
|
+
async function skipPlatformPullRequestFact(taskRef, options) {
|
|
1523
|
+
return withActivityWarnings(taskRef, options.cwd, await skipPlatformPullRequestFactWithProjection(taskRef, options));
|
|
1524
|
+
}
|
|
1525
|
+
export { bindPlatformPullRequest, createPlatformPullRequest, inspectPlatformPullRequest, inspectPlatformPullRequestByNumber, recoverCreatedPullRequest, resolveExternalPullRequestWithWarnings as resolveExternalPullRequest, skipPlatformPullRequestFact, selectExternalPullRequest, syncPlatformPullRequest, syncPlatformPullRequestInLabels };
|
|
1537
1526
|
export { warningResultForPrimary };
|
|
1538
1527
|
//# sourceMappingURL=pull-requests.js.map
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import crypto from 'node:crypto';
|
|
3
1
|
import { resolvePlatformProviderContext } from './context.js';
|
|
4
2
|
import { platformResult } from './types.js';
|
|
5
3
|
import { providerError, providerOperationContext, providerStatus, unsupportedProviderOperation } from './provider-bridge.js';
|
|
6
|
-
function flattenPages(value) {
|
|
7
|
-
if (!Array.isArray(value))
|
|
8
|
-
return [];
|
|
9
|
-
return value.flatMap((entry) => Array.isArray(entry) ? entry : [entry]).filter((entry) => Boolean(entry) && typeof entry === 'object');
|
|
10
|
-
}
|
|
11
4
|
async function inspectPlatformRelease(tag, options = {}) {
|
|
12
5
|
const loaded = await resolvePlatformProviderContext({ cwd: options.cwd, client: options.client });
|
|
13
6
|
const context = loaded.ok ? loaded.value.context : loaded.context;
|
|
@@ -32,41 +25,6 @@ async function inspectPlatformRelease(tag, options = {}) {
|
|
|
32
25
|
}
|
|
33
26
|
return { ...platformResult('failed'), platform: context.platform, release: null, workflows: [], error: context.error };
|
|
34
27
|
}
|
|
35
|
-
async function upsertPlatformRelease(input, options = {}) {
|
|
36
|
-
const inspected = await inspectPlatformRelease(input.tag, options);
|
|
37
|
-
if (inspected.release?.published)
|
|
38
|
-
return { ...inspected, status: 'no-op', changed: false, operations: [] };
|
|
39
|
-
if (inspected.status === 'blocked' || inspected.status === 'failed')
|
|
40
|
-
return { ...inspected, changed: false, operations: [] };
|
|
41
|
-
if (!inspected.platform.repository)
|
|
42
|
-
return { ...inspected, status: 'no-op', changed: false, operations: [] };
|
|
43
|
-
const loaded = await resolvePlatformProviderContext({ cwd: options.cwd, client: options.client });
|
|
44
|
-
if (loaded.ok) {
|
|
45
|
-
let notes;
|
|
46
|
-
if (input.notesFile) {
|
|
47
|
-
try {
|
|
48
|
-
const bytes = fs.readFileSync(input.notesFile);
|
|
49
|
-
notes = { text: bytes.toString('utf8'), sha256: `sha256:${crypto.createHash('sha256').update(bytes).digest('hex')}`, byteLength: bytes.byteLength };
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
return { ...inspected, status: 'failed', 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)
|
|
65
|
-
return { ...inspected, status: providerStatus(created.error), changed: false, operations: [{ name: 'create-release', status: 'failed' }], error: providerError(created.error, 'PLATFORM_PROVIDER_OPERATION_FAILED') };
|
|
66
|
-
return { ...inspected, status: 'applied', changed: created.value.changed, operations: [{ name: 'create-release', status: 'applied' }], error: null };
|
|
67
|
-
}
|
|
68
|
-
return { ...inspected, status: 'failed', changed: false, operations: [{ name: 'create-release', status: 'failed' }], error: { code: 'PLATFORM_PROVIDER_LOAD_FAILED', message: 'Selected provider failed to load', retryable: false } };
|
|
69
|
-
}
|
|
70
28
|
async function reconcileReleaseMilestones(version, options = {}) {
|
|
71
29
|
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
|
|
72
30
|
if (!match)
|
|
@@ -115,5 +73,5 @@ async function reconcileReleaseMilestones(version, options = {}) {
|
|
|
115
73
|
}
|
|
116
74
|
return { status: 'failed', changed: false, operations: [], error: { code: 'PLATFORM_CAPABILITY_UNSUPPORTED', message: 'Release milestone reconciliation is unavailable', retryable: false } };
|
|
117
75
|
}
|
|
118
|
-
export { inspectPlatformRelease, reconcileReleaseMilestones
|
|
76
|
+
export { inspectPlatformRelease, reconcileReleaseMilestones };
|
|
119
77
|
//# sourceMappingURL=releases.js.map
|
|
@@ -5,7 +5,6 @@ import { inspectRequiredChecks } from "./pr-checks.js";
|
|
|
5
5
|
import { resolvePlatformProviderContext } from "./context.js";
|
|
6
6
|
import { resolveReviewedHeadRelation } from "./merged-pr-equivalence.js";
|
|
7
7
|
import { readPrDeliveryFact } from "../task/pr-delivery-fact.js";
|
|
8
|
-
import { resourceIdentityNumber } from "./resource-identity.js";
|
|
9
8
|
const CHECK_TYPE = "required-checks";
|
|
10
9
|
const SHA_PATTERN = /^[0-9a-f]{7,40}$/i;
|
|
11
10
|
function readPrFlow(repoRoot) {
|
|
@@ -33,7 +32,6 @@ export function evaluateRequiredChecks(context, shared) {
|
|
|
33
32
|
}
|
|
34
33
|
const fact = factRead.status === "valid" ? factRead.fact : null;
|
|
35
34
|
const prIdentity = fact?.state === "bound" ? fact.identity.resource : null;
|
|
36
|
-
const prNumber = resourceIdentityNumber(prIdentity);
|
|
37
35
|
if (prFlow === "disabled" || fact?.state === "skipped" || !prIdentity) {
|
|
38
36
|
return shared.passResult(CHECK_TYPE, "Skipped: required checks are not applicable to this task");
|
|
39
37
|
}
|
|
@@ -13,7 +13,7 @@ import { readPrDeliveryFact } from "../task/pr-delivery-fact.js";
|
|
|
13
13
|
import { providerError, providerOperationContext, resourceIdentityNumber, unsupportedProviderOperation } from "./provider-bridge.js";
|
|
14
14
|
import { taskIssueIdentity } from "./task-identities.js";
|
|
15
15
|
import { MARKERS, renderTaskCommentResult } from "./issue-comments.js";
|
|
16
|
-
import {
|
|
16
|
+
import { canonicalizeCommentBody, } from "./comment-safety.js";
|
|
17
17
|
const CHECK_TYPE = "platform-sync";
|
|
18
18
|
const VERSION_LINE_REGEX = /^[0-9]+\.[0-9]+\.x$/;
|
|
19
19
|
const FRONTMATTER_FIELD_MAP = {
|
|
@@ -47,10 +47,6 @@ export function getDefaults() {
|
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
-
function sanitizeCommentContent(content) {
|
|
51
|
-
const result = sanitizeMarkdownDocument(content, { reservedMarkers: [CONTROL_MARKER_PATTERN] });
|
|
52
|
-
return result.ok ? result.value : null;
|
|
53
|
-
}
|
|
54
50
|
function infoResult(message) {
|
|
55
51
|
return {
|
|
56
52
|
type: CHECK_TYPE,
|
|
@@ -655,32 +651,6 @@ function extractCommentBody(commentBody) {
|
|
|
655
651
|
}
|
|
656
652
|
return lines.slice(start, end).join("\n");
|
|
657
653
|
}
|
|
658
|
-
function buildExpectedTaskBody(taskContent, shared) {
|
|
659
|
-
const frontmatterMatch = taskContent.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
|
|
660
|
-
if (!frontmatterMatch) {
|
|
661
|
-
return sanitizeCommentContent(taskContent.trim());
|
|
662
|
-
}
|
|
663
|
-
const body = sanitizeCommentContent(taskContent.slice(frontmatterMatch[0].length).trim());
|
|
664
|
-
if (body === null) {
|
|
665
|
-
return null;
|
|
666
|
-
}
|
|
667
|
-
return [
|
|
668
|
-
buildTaskFrontmatterSummary(shared),
|
|
669
|
-
"",
|
|
670
|
-
renderSafeCodeFence(frontmatterMatch[0].trim(), "yaml"),
|
|
671
|
-
"",
|
|
672
|
-
"</details>",
|
|
673
|
-
"",
|
|
674
|
-
body
|
|
675
|
-
].join("\n").trim();
|
|
676
|
-
}
|
|
677
|
-
function buildTaskFrontmatterSummary(shared) {
|
|
678
|
-
const language = loadProjectLanguage(shared);
|
|
679
|
-
if (language === "en" || language === "en-US") {
|
|
680
|
-
return "<details><summary>Metadata (frontmatter)</summary>";
|
|
681
|
-
}
|
|
682
|
-
return "<details><summary>元数据 (frontmatter)</summary>";
|
|
683
|
-
}
|
|
684
654
|
function loadProjectLanguage(shared) {
|
|
685
655
|
const override = process.env.VALIDATE_ARTIFACT_LANGUAGE;
|
|
686
656
|
if (!shared.isBlank(override)) {
|
|
@@ -741,38 +711,6 @@ function mapTaskTypeToIssueType(taskType) {
|
|
|
741
711
|
};
|
|
742
712
|
return mapping[taskType] || "Task";
|
|
743
713
|
}
|
|
744
|
-
function normalizeIssueFields(payload) {
|
|
745
|
-
const issue = payload?.data?.repository?.issue;
|
|
746
|
-
const pinnedFields = Array.isArray(issue?.issueType?.pinnedFields)
|
|
747
|
-
? issue.issueType.pinnedFields
|
|
748
|
-
: [];
|
|
749
|
-
const values = Array.isArray(issue?.issueFieldValues?.nodes)
|
|
750
|
-
? issue.issueFieldValues.nodes
|
|
751
|
-
: [];
|
|
752
|
-
const pinnedNames = new Set(pinnedFields
|
|
753
|
-
.map((field) => typeof field?.name === "string" ? field.name : "")
|
|
754
|
-
.filter(Boolean));
|
|
755
|
-
const normalizedValues = new Map();
|
|
756
|
-
for (const value of values) {
|
|
757
|
-
const fieldName = value?.field?.name;
|
|
758
|
-
if (!fieldName) {
|
|
759
|
-
continue;
|
|
760
|
-
}
|
|
761
|
-
if (value.__typename === "IssueFieldSingleSelectValue") {
|
|
762
|
-
normalizedValues.set(fieldName, {
|
|
763
|
-
kind: "single-select",
|
|
764
|
-
value: normalizeOptionName(value.name)
|
|
765
|
-
});
|
|
766
|
-
}
|
|
767
|
-
else if (value.__typename === "IssueFieldDateValue") {
|
|
768
|
-
normalizedValues.set(fieldName, {
|
|
769
|
-
kind: "date",
|
|
770
|
-
value: normalizeDateValue(value.value)
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
return { pinnedNames, values: normalizedValues };
|
|
775
|
-
}
|
|
776
714
|
function normalizeExpectedIssueField(metadataKey, rawValue) {
|
|
777
715
|
const value = String(rawValue || "").trim();
|
|
778
716
|
if (!value) {
|
|
@@ -869,22 +807,6 @@ function gitText(args, cwd) {
|
|
|
869
807
|
};
|
|
870
808
|
}
|
|
871
809
|
}
|
|
872
|
-
function resolvePrHeadSha(context) {
|
|
873
|
-
const fallback = () => gitText(["rev-parse", "HEAD"], context.taskDir);
|
|
874
|
-
const branch = String(context.task?.metadata?.branch || "").trim();
|
|
875
|
-
if (!branch) {
|
|
876
|
-
return fallback();
|
|
877
|
-
}
|
|
878
|
-
const matchedWorktree = resolveBranchWorktree(context.taskDir, branch);
|
|
879
|
-
if (!matchedWorktree) {
|
|
880
|
-
return {
|
|
881
|
-
ok: false,
|
|
882
|
-
type: "check_failed",
|
|
883
|
-
message: `Task branch '${branch}' is not checked out in a usable worktree`
|
|
884
|
-
};
|
|
885
|
-
}
|
|
886
|
-
return gitText(["rev-parse", "HEAD"], matchedWorktree);
|
|
887
|
-
}
|
|
888
810
|
function interpolate(template, taskDir, artifactFile) {
|
|
889
811
|
const artifactStem = artifactFile ? path.basename(artifactFile, path.extname(artifactFile)) : "";
|
|
890
812
|
return template
|