@fitlab-ai/agent-infra 0.9.15 → 0.11.0
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 +2 -6
- package/README.zh-CN.md +2 -6
- package/bin/internal-cli.sh +0 -13
- package/dist/bin/internal-cli.js +11 -49
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +6 -2
- package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +43 -3
- package/dist/lib/fs/durable-write.js +2 -0
- package/dist/lib/internal/cli-route-inventory.js +3 -4
- package/dist/lib/internal/manual-validation.js +17 -8
- package/dist/lib/internal/platform-comment.js +60 -2
- package/dist/lib/internal/task-artifact.js +1 -1
- package/dist/lib/internal/task-finalization.js +2 -2
- package/dist/lib/internal/task-lifecycle.js +4 -4
- package/dist/lib/internal/task-operation-registry.js +22 -13
- package/dist/lib/internal/task-orchestration.js +2 -2
- package/dist/lib/internal/task-review.js +12 -7
- package/dist/lib/platform/activity-recovery.js +159 -0
- package/dist/lib/platform/issue-comments.js +89 -31
- package/dist/lib/platform/issues.js +1 -1
- package/dist/lib/platform/pr-change-report.js +5 -4
- package/dist/lib/platform/pr-summary.js +64 -32
- package/dist/lib/platform/pull-requests.js +3 -3
- package/dist/lib/platform/task-comment-projection.js +70 -0
- package/dist/lib/platform/task-identities.js +2 -9
- package/dist/lib/platform/task-recovery.js +55 -0
- package/dist/lib/platform/verification-sync.js +45 -7
- package/dist/lib/pr-review/evidence-grading.js +4 -8
- package/dist/lib/sandbox/commands/rm.js +21 -2
- package/dist/lib/sandbox/control/executor.js +4 -2
- package/dist/lib/sandbox/control/server.js +29 -9
- package/dist/lib/sandbox/control/state.js +7 -1
- package/dist/lib/sandbox/control/task-workflow.js +1 -1
- package/dist/lib/sandbox/control/workflow-executor.js +87 -35
- package/dist/lib/sandbox/index.js +1 -2
- package/dist/lib/sandbox/removal.js +116 -1011
- package/dist/lib/sandbox/workspace-identity.js +17 -1
- package/dist/lib/server/process-state.js +17 -5
- package/dist/lib/task/artifact-command.js +11 -30
- package/dist/lib/task/artifact-operations.js +17 -231
- package/dist/lib/task/artifact-recovery.js +476 -0
- package/dist/lib/task/artifact-repair-intent.js +90 -39
- package/dist/lib/task/commit-operation.js +31 -4
- package/dist/lib/task/control-authority.js +39 -8
- package/dist/lib/task/control-recovery.js +14 -2
- package/dist/lib/task/create-service.js +1 -8
- package/dist/lib/task/delegation-receipts.js +64 -3
- package/dist/lib/task/events.js +165 -23
- package/dist/lib/task/human-override.js +5 -8
- package/dist/lib/task/intermediate-cleanup.js +91 -8
- package/dist/lib/task/lifecycle-recovery.js +549 -0
- package/dist/lib/task/lifecycle.js +12 -3
- package/dist/lib/task/local-artifact-finalization.js +212 -123
- package/dist/lib/task/manual-validation-receipt.js +5 -1
- package/dist/lib/task/orchestration.js +52 -2
- package/dist/lib/task/pr-delivery-fact.js +12 -56
- package/dist/lib/task/recovery-warning.js +19 -0
- package/dist/lib/task/review-command.js +3 -2
- package/dist/lib/task/review-finalization.js +294 -74
- package/dist/lib/{host-control → task}/secure-fs.js +8 -19
- package/dist/lib/task/short-id.js +15 -7
- package/dist/lib/task/task-execution-lock.js +1 -1
- package/dist/lib/task/verification-engine.js +3 -14
- package/dist/lib/task/workflow-command.js +2 -1
- package/dist/lib/task/workflow-dispatch.js +161 -0
- package/dist/lib/version.js +1 -11
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +7 -2
- package/lib/agent-clients/adapters/codex-lifecycle/store.ts +55 -3
- package/lib/fs/durable-write.ts +1 -0
- package/lib/internal/cli-route-inventory.ts +3 -4
- package/lib/internal/manual-validation.ts +17 -8
- package/lib/internal/platform-comment.ts +53 -2
- package/lib/internal/task-artifact.ts +1 -1
- package/lib/internal/task-finalization.ts +1 -1
- package/lib/internal/task-lifecycle.ts +5 -4
- package/lib/internal/task-operation-registry.ts +22 -13
- package/lib/internal/task-orchestration.ts +1 -1
- package/lib/internal/task-review.ts +11 -7
- package/lib/platform/activity-recovery.ts +179 -0
- package/lib/platform/issue-comments.ts +105 -30
- package/lib/platform/issues.ts +1 -1
- package/lib/platform/pr-change-report.ts +7 -5
- package/lib/platform/pr-summary.ts +64 -32
- package/lib/platform/pull-requests.ts +3 -3
- package/lib/platform/task-comment-projection.ts +79 -0
- package/lib/platform/task-identities.ts +3 -14
- package/lib/platform/task-recovery.ts +54 -0
- package/lib/platform/verification-sync.ts +48 -11
- package/lib/pr-review/evidence-grading.ts +4 -9
- package/lib/sandbox/commands/rm.ts +34 -2
- package/lib/sandbox/control/executor.ts +4 -2
- package/lib/sandbox/control/protocol.ts +6 -1
- package/lib/sandbox/control/server.ts +30 -10
- package/lib/sandbox/control/state.ts +9 -1
- package/lib/sandbox/control/task-workflow.ts +1 -1
- package/lib/sandbox/control/workflow-executor.ts +106 -35
- package/lib/sandbox/index.ts +1 -2
- package/lib/sandbox/removal.ts +126 -1128
- package/lib/sandbox/workspace-identity.ts +19 -3
- package/lib/server/process-state.ts +26 -5
- package/lib/task/artifact-command.ts +12 -29
- package/lib/task/artifact-operations.ts +22 -252
- package/lib/task/artifact-recovery.ts +572 -0
- package/lib/task/artifact-repair-intent.ts +126 -51
- package/lib/task/commit-operation.ts +35 -4
- package/lib/task/control-authority.ts +48 -15
- package/lib/task/control-recovery.ts +13 -1
- package/lib/task/create-service.ts +1 -10
- package/lib/task/delegation-receipts.ts +73 -2
- package/lib/task/events.ts +188 -24
- package/lib/task/human-override.ts +5 -8
- package/lib/task/intermediate-cleanup.ts +66 -12
- package/lib/task/lifecycle-recovery.ts +691 -0
- package/lib/task/lifecycle.ts +13 -4
- package/lib/task/local-artifact-finalization.ts +249 -131
- package/lib/task/manual-validation-receipt.ts +5 -1
- package/lib/task/orchestration.ts +65 -0
- package/lib/task/pr-delivery-fact.ts +15 -62
- package/lib/task/recovery-warning.ts +21 -0
- package/lib/task/review-command.ts +2 -1
- package/lib/task/review-finalization.ts +298 -84
- package/lib/{host-control → task}/secure-fs.ts +10 -32
- package/lib/task/short-id.ts +27 -5
- package/lib/task/task-execution-lock.ts +1 -1
- package/lib/task/verification-engine.ts +3 -17
- package/lib/task/verification-types.ts +0 -2
- package/lib/task/workflow-command.ts +2 -1
- package/lib/task/workflow-dispatch.ts +171 -0
- package/lib/version.ts +1 -15
- package/package.json +1 -1
- package/templates/.agents/rules/create-issue.en.md +1 -1
- package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.en.md +12 -2
- package/templates/.agents/rules/issue-sync.zh-CN.md +13 -5
- package/templates/.agents/rules/local-artifact-repair.en.md +47 -39
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +45 -36
- package/templates/.agents/skills/analyze-task/SKILL.en.md +6 -6
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +6 -6
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -1
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/block-task/config/verify.json +1 -1
- package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/cancel-task/config/verify.json +1 -1
- package/templates/.agents/skills/code-task/SKILL.en.md +7 -7
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +8 -8
- package/templates/.agents/skills/code-task/config/verify.en.json +1 -1
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/complete-task/config/verify.en.json +2 -2
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +2 -2
- package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +1 -1
- package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +1 -1
- package/templates/.agents/skills/create-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/create-pr/config/verify.json +1 -1
- package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +2 -2
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +2 -2
- package/templates/.agents/skills/create-task/SKILL.en.md +5 -5
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/create-task/config/verify.json +1 -1
- package/templates/.agents/skills/import-issue/SKILL.en.md +8 -8
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +8 -8
- package/templates/.agents/skills/import-issue/config/verify.json +2 -2
- package/templates/.agents/skills/plan-task/SKILL.en.md +4 -4
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/plan-task/config/verify.en.json +1 -1
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/restore-task/SKILL.en.md +11 -6
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +11 -6
- package/templates/.agents/skills/restore-task/config/verify.json +1 -1
- 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-analysis/config/verify.en.json +1 -1
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +7 -7
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +6 -6
- package/templates/.agents/skills/review-code/SKILL.en.md +5 -4
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -4
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -1
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/review-code/reference/report-template.en.md +12 -12
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +12 -12
- 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-plan/config/verify.en.json +1 -1
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +7 -7
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +7 -7
- package/templates/.agents/skills/review-pr/config/verify.en.json +1 -1
- package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +3 -3
- package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +3 -3
- package/templates/.agents/skills/run-manual-validation/config/verify.en.json +1 -1
- package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/templates/task.en.md +1 -1
- package/templates/.agents/templates/task.zh-CN.md +1 -1
- package/templates/.claude/commands/import-issue.en.md +1 -1
- package/templates/.claude/commands/import-issue.zh-CN.md +1 -1
- package/templates/.claude/commands/restore-task.en.md +1 -1
- package/templates/.claude/commands/restore-task.zh-CN.md +1 -1
- package/dist/lib/host-control/audit.js +0 -19
- package/dist/lib/host-control/client.js +0 -142
- package/dist/lib/host-control/command.js +0 -49
- package/dist/lib/host-control/path.js +0 -160
- package/dist/lib/host-control/server.js +0 -159
- package/dist/lib/host-control/service.js +0 -112
- package/dist/lib/internal/host-control.js +0 -28
- package/lib/host-control/audit.ts +0 -22
- package/lib/host-control/client.ts +0 -172
- package/lib/host-control/command.ts +0 -60
- package/lib/host-control/path.ts +0 -167
- package/lib/host-control/server.ts +0 -180
- package/lib/host-control/service.ts +0 -133
- package/lib/internal/host-control.ts +0 -28
|
@@ -11,6 +11,7 @@ import type { LedgerDocument } from './ledger.ts';
|
|
|
11
11
|
import { resolveTaskRef } from './resolve-ref.ts';
|
|
12
12
|
import {
|
|
13
13
|
activateDelegation,
|
|
14
|
+
abortActivatedDelegation,
|
|
14
15
|
abortPreparedDelegation,
|
|
15
16
|
completeDelegationStage,
|
|
16
17
|
consumeDelegation,
|
|
@@ -59,6 +60,7 @@ import { hasOpenLifecycleExecution } from './activity-log.ts';
|
|
|
59
60
|
import { invalidationBlocks } from './invalidation.ts';
|
|
60
61
|
import type { InvalidationDocument } from './invalidation.ts';
|
|
61
62
|
import type { LifecycleAction, LifecycleFacts } from './capabilities.ts';
|
|
63
|
+
import { normalizeAgentToken } from '../agent-clients/tokens.ts';
|
|
62
64
|
|
|
63
65
|
type OrchestrationStatus = 'running' | 'paused' | 'completed';
|
|
64
66
|
type ModelPolicySource = Readonly<{
|
|
@@ -1444,6 +1446,68 @@ function recoverPreparedOrchestrationDelegation(
|
|
|
1444
1446
|
}
|
|
1445
1447
|
}
|
|
1446
1448
|
|
|
1449
|
+
function recoverActivatedOrchestrationDelegationUnderLock(
|
|
1450
|
+
taskRef: string,
|
|
1451
|
+
event: Readonly<{
|
|
1452
|
+
receiptId: string;
|
|
1453
|
+
stage: DelegationStage;
|
|
1454
|
+
round: number;
|
|
1455
|
+
artifact: string;
|
|
1456
|
+
startedAgent: string;
|
|
1457
|
+
childId: string;
|
|
1458
|
+
stopRevision: number;
|
|
1459
|
+
consumer: string;
|
|
1460
|
+
consumedAt: string;
|
|
1461
|
+
}>,
|
|
1462
|
+
options: OrchestrationOptions = {}
|
|
1463
|
+
): OrchestrationResult {
|
|
1464
|
+
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1465
|
+
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1466
|
+
const run = readRun(resolved.taskDir, options);
|
|
1467
|
+
if (!run) return failed('ORCHESTRATION_RUN_MISSING', 'no orchestration run exists', resolved.taskId);
|
|
1468
|
+
const matches = [
|
|
1469
|
+
...(run.pendingDelegation ? [run.pendingDelegation] : []),
|
|
1470
|
+
...run.receipts.filter((receipt) => receipt.id === event.receiptId)
|
|
1471
|
+
];
|
|
1472
|
+
const receipt = matches.find((candidate) => candidate.id === event.receiptId);
|
|
1473
|
+
if (!receipt) return failed('ORCHESTRATION_DELEGATION_MISSING', 'recovery receipt does not exist', resolved.taskId);
|
|
1474
|
+
if (
|
|
1475
|
+
receipt.taskId !== resolved.taskId
|
|
1476
|
+
|| receipt.stage !== event.stage
|
|
1477
|
+
|| receipt.round !== event.round
|
|
1478
|
+
|| receipt.artifact !== event.artifact
|
|
1479
|
+
|| receipt.childId !== event.childId
|
|
1480
|
+
|| normalizeAgentToken(event.startedAgent) !== normalizeAgentToken(receipt.client)
|
|
1481
|
+
) {
|
|
1482
|
+
return failed('ORCHESTRATION_PROVENANCE_MISMATCH', 'recovery selector does not match the delegation receipt', resolved.taskId);
|
|
1483
|
+
}
|
|
1484
|
+
if (receipt.status === 'aborted' && run.pendingDelegation === null) {
|
|
1485
|
+
return { status: run.status, changed: false, taskId: resolved.taskId, run, next: null, error: null };
|
|
1486
|
+
}
|
|
1487
|
+
if (run.pendingDelegation?.id !== receipt.id || receipt.status !== 'activated') {
|
|
1488
|
+
return failed('ORCHESTRATION_RECOVERY_UNSAFE', 'recovery requires one matching activated pending delegation', resolved.taskId);
|
|
1489
|
+
}
|
|
1490
|
+
if (run.receipts.some((candidate) => candidate.id === receipt.id)) {
|
|
1491
|
+
return failed('ORCHESTRATION_RECEIPT_DUPLICATE', 'recovery receipt already exists in the completed receipt history', resolved.taskId);
|
|
1492
|
+
}
|
|
1493
|
+
const aborted = abortActivatedDelegation(receipt, {
|
|
1494
|
+
childId: event.childId,
|
|
1495
|
+
stopRevision: event.stopRevision,
|
|
1496
|
+
consumer: event.consumer,
|
|
1497
|
+
consumedAt: event.consumedAt
|
|
1498
|
+
});
|
|
1499
|
+
if (!aborted.ok) return failed(aborted.code, aborted.message, resolved.taskId);
|
|
1500
|
+
const updated = withUpdatedRun(run, {
|
|
1501
|
+
status: 'running',
|
|
1502
|
+
pause: null,
|
|
1503
|
+
nextStage: null,
|
|
1504
|
+
pendingDelegation: null,
|
|
1505
|
+
receipts: Object.freeze([...run.receipts, aborted.receipt])
|
|
1506
|
+
}, options.now);
|
|
1507
|
+
saveRun(resolved.taskDir, updated);
|
|
1508
|
+
return { status: 'running', changed: true, taskId: resolved.taskId, run: updated, next: null, error: null };
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1447
1511
|
function completeOrchestrationStage(
|
|
1448
1512
|
taskRef: string,
|
|
1449
1513
|
event: Parameters<typeof completeDelegationStage>[1],
|
|
@@ -1598,6 +1662,7 @@ export {
|
|
|
1598
1662
|
readRun,
|
|
1599
1663
|
reconcileMatchingOrchestrationDelegation,
|
|
1600
1664
|
recoverPreparedOrchestrationDelegation,
|
|
1665
|
+
recoverActivatedOrchestrationDelegationUnderLock,
|
|
1601
1666
|
routeOrchestration,
|
|
1602
1667
|
sealMatchingOrchestrationDelegation,
|
|
1603
1668
|
sealMatchingOrchestrationDelegationWithHostEvidence,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ResourceIdentity } from '../platform/resource-identity.ts';
|
|
2
|
-
import { isLegacyCompatibilityEnabled, legacyCompatibilityError, VERSION } from '../version.ts';
|
|
3
2
|
import {
|
|
4
3
|
isResourceIdentity,
|
|
5
4
|
parseResourceIdentity,
|
|
@@ -17,14 +16,6 @@ type PrDeliveryIdentity = {
|
|
|
17
16
|
base: { repository: string; ref: string; sha: string };
|
|
18
17
|
};
|
|
19
18
|
|
|
20
|
-
type LegacyPrDeliveryIdentity = {
|
|
21
|
-
repository: string;
|
|
22
|
-
number: number;
|
|
23
|
-
nodeId: string;
|
|
24
|
-
url: string;
|
|
25
|
-
head: { repository: string; ref: string; sha: string };
|
|
26
|
-
base: { repository: string; ref: string; sha: string };
|
|
27
|
-
};
|
|
28
19
|
type CurrentPrDeliveryIdentityInput = {
|
|
29
20
|
resource: ResourceIdentity;
|
|
30
21
|
repository: string;
|
|
@@ -93,10 +84,6 @@ function timestamp(value: unknown, label: string): string {
|
|
|
93
84
|
if (Number.isNaN(Date.parse(result))) throw factError(`${label} must be a valid timestamp`);
|
|
94
85
|
return new Date(result).toISOString();
|
|
95
86
|
}
|
|
96
|
-
function positiveNumber(value: unknown, label: string): number {
|
|
97
|
-
if (!Number.isSafeInteger(value) || (value as number) <= 0) throw factError(`${label} must be a positive integer`);
|
|
98
|
-
return value as number;
|
|
99
|
-
}
|
|
100
87
|
function parseRef(value: unknown, label: string): { repository: string; ref: string; sha: string } {
|
|
101
88
|
if (!isRecord(value)) throw factError(`${label} must be an object`);
|
|
102
89
|
exactKeys(value, ['repository', 'ref', 'sha'], label);
|
|
@@ -115,35 +102,19 @@ function canonicalIdentity(value: unknown): PrDeliveryIdentity {
|
|
|
115
102
|
};
|
|
116
103
|
}
|
|
117
104
|
|
|
118
|
-
function decodeLegacyIdentity(value: unknown): PrDeliveryIdentity {
|
|
119
|
-
if (!isRecord(value)) throw factError('legacy identity must be an object');
|
|
120
|
-
// TODO(compat): Remove the v1 identity decoder before the first stable v1.0.0 release.
|
|
121
|
-
exactKeys(value, ['repository', 'number', 'nodeId', 'url', 'head', 'base'], 'legacy identity');
|
|
122
|
-
const legacy = {
|
|
123
|
-
number: positiveNumber(value.number, 'legacy identity.number'),
|
|
124
|
-
repository: text(value.repository, 'identity.repository'),
|
|
125
|
-
nodeId: text(value.nodeId, 'legacy identity.nodeId'),
|
|
126
|
-
url: text(value.url, 'identity.url'),
|
|
127
|
-
head: parseRef(value.head, 'identity.head'),
|
|
128
|
-
base: parseRef(value.base, 'identity.base')
|
|
129
|
-
} satisfies LegacyPrDeliveryIdentity;
|
|
130
|
-
return {
|
|
131
|
-
resource: { kind: 'number', value: legacy.number },
|
|
132
|
-
repository: legacy.repository,
|
|
133
|
-
url: legacy.url,
|
|
134
|
-
head: legacy.head,
|
|
135
|
-
base: legacy.base
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
105
|
function provenanceForSource(source: PrDeliveryBindingSource): PrDeliveryProvenance { return source === 'created' ? 'create-post' : source === 'reused' ? 'reuse' : source; }
|
|
140
106
|
|
|
141
|
-
function
|
|
107
|
+
function legacyFactError(): PrDeliveryFactError {
|
|
108
|
+
return Object.assign(
|
|
109
|
+
new Error('PLATFORM_IDENTITY_LEGACY_UNSUPPORTED: v1 PR delivery fact is unsupported; use the previous tool version to view this task or migrate its fact to version 2 before using this version'),
|
|
110
|
+
{ code: 'PLATFORM_IDENTITY_LEGACY_UNSUPPORTED' }
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function parseFact(value: unknown): PrDeliveryFact {
|
|
142
115
|
if (!isRecord(value)) throw factError('fact must be an object');
|
|
143
|
-
if (
|
|
144
|
-
if (value.version
|
|
145
|
-
throw legacyCompatibilityError('v1 PR delivery fact', runtimeVersion);
|
|
146
|
-
}
|
|
116
|
+
if (value.version === 1) throw legacyFactError();
|
|
117
|
+
if (value.version !== 2 || typeof value.state !== 'string') throw factError('version or state is invalid');
|
|
147
118
|
if (value.state === 'unbound') {
|
|
148
119
|
exactKeys(value, ['version', 'state', 'reason'], 'unbound fact');
|
|
149
120
|
if (value.reason !== 'initial') throw factError('unbound reason is invalid');
|
|
@@ -155,24 +126,6 @@ function parseFact(value: unknown, runtimeVersion = VERSION): PrDeliveryFact {
|
|
|
155
126
|
return { version: 2, state: 'skipped', reason: 'explicit', decidedAt: timestamp(value.decidedAt, 'skipped.decidedAt') };
|
|
156
127
|
}
|
|
157
128
|
if (value.state !== 'bound') throw factError('state is invalid');
|
|
158
|
-
if (value.version === 1) {
|
|
159
|
-
// TODO(compat): Remove this v1-to-v2 shape conversion before the first stable v1.0.0 release.
|
|
160
|
-
exactKeys(value, ['version', 'state', 'identity', 'binding', 'provenance'], 'legacy bound fact');
|
|
161
|
-
if (!isRecord(value.binding) || !isRecord(value.provenance)) throw factError('legacy binding or provenance is invalid');
|
|
162
|
-
exactKeys(value.binding, ['status', 'source', 'verifiedAt', 'issueNumber', 'remoteState', 'mergedAt', 'mergeCommitSha'], 'legacy binding');
|
|
163
|
-
const issueNumber = value.binding.issueNumber === null ? null : positiveNumber(value.binding.issueNumber, 'legacy binding.issueNumber');
|
|
164
|
-
return parseFact({
|
|
165
|
-
version: 2,
|
|
166
|
-
state: 'bound',
|
|
167
|
-
identity: decodeLegacyIdentity(value.identity),
|
|
168
|
-
binding: {
|
|
169
|
-
status: 'verified', source: value.binding.source, verifiedAt: timestamp(value.binding.verifiedAt, 'binding.verifiedAt'),
|
|
170
|
-
issueIdentity: issueNumber === null ? null : { kind: 'number', value: issueNumber }, remoteState: value.binding.remoteState,
|
|
171
|
-
mergedAt: value.binding.mergedAt === null ? null : timestamp(value.binding.mergedAt, 'binding.mergedAt'), mergeCommitSha: nullableText(value.binding.mergeCommitSha, 'binding.mergeCommitSha')
|
|
172
|
-
},
|
|
173
|
-
provenance: value.provenance
|
|
174
|
-
}, runtimeVersion);
|
|
175
|
-
}
|
|
176
129
|
exactKeys(value, ['version', 'state', 'identity', 'binding', 'provenance'], 'bound fact');
|
|
177
130
|
if (!isRecord(value.binding) || !isRecord(value.provenance)) throw factError('binding or provenance is invalid');
|
|
178
131
|
exactKeys(value.binding, ['status', 'source', 'verifiedAt', 'issueIdentity', 'remoteState', 'mergedAt', 'mergeCommitSha'], 'binding');
|
|
@@ -195,19 +148,19 @@ function parseFact(value: unknown, runtimeVersion = VERSION): PrDeliveryFact {
|
|
|
195
148
|
};
|
|
196
149
|
}
|
|
197
150
|
|
|
198
|
-
function decodePrDeliveryFact(value: unknown,
|
|
151
|
+
function decodePrDeliveryFact(value: unknown, _runtimeVersion?: string): PrDeliveryFact {
|
|
199
152
|
if (typeof value === 'string') {
|
|
200
153
|
let decoded: unknown;
|
|
201
154
|
try { decoded = JSON.parse(value); }
|
|
202
155
|
catch { throw factError('value is not valid JSON'); }
|
|
203
|
-
return parseFact(decoded
|
|
156
|
+
return parseFact(decoded);
|
|
204
157
|
}
|
|
205
|
-
return parseFact(value
|
|
158
|
+
return parseFact(value);
|
|
206
159
|
}
|
|
207
160
|
function encodePrDeliveryFact(fact: PrDeliveryFact): string { return JSON.stringify(parseFact(fact)); }
|
|
208
|
-
function readPrDeliveryFact(metadata: Record<string, unknown>,
|
|
161
|
+
function readPrDeliveryFact(metadata: Record<string, unknown>, _runtimeVersion?: string): PrDeliveryFactReadResult {
|
|
209
162
|
if (!Object.hasOwn(metadata, PR_DELIVERY_FACT_KEY) || metadata[PR_DELIVERY_FACT_KEY] === '') return { status: 'missing', fact: null };
|
|
210
|
-
try { return { status: 'valid', fact: decodePrDeliveryFact(metadata[PR_DELIVERY_FACT_KEY]
|
|
163
|
+
try { return { status: 'valid', fact: decodePrDeliveryFact(metadata[PR_DELIVERY_FACT_KEY]) }; }
|
|
211
164
|
catch (error) { return { status: 'invalid', fact: null, error: asFactError(error) }; }
|
|
212
165
|
}
|
|
213
166
|
function buildUnboundFact(): PrDeliveryFact { return { version: 2, state: 'unbound', reason: 'initial' }; }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type RecoveryWarning = Readonly<{ code: string; message: string; action: string }>;
|
|
2
|
+
|
|
3
|
+
function warningText(value: unknown): value is string {
|
|
4
|
+
return typeof value === 'string' && value.length > 0 && value.trim() === value && !/[\r\n]/u.test(value);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function isRecoveryWarning(value: unknown): value is RecoveryWarning {
|
|
8
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
|
|
9
|
+
const warning = value as Record<string, unknown>;
|
|
10
|
+
return Object.keys(warning).sort().join(',') === 'action,code,message'
|
|
11
|
+
&& warningText(warning.code)
|
|
12
|
+
&& warningText(warning.message)
|
|
13
|
+
&& warningText(warning.action);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function sameRecoveryWarning(left: unknown, right: unknown): boolean {
|
|
17
|
+
return isRecoveryWarning(left) && isRecoveryWarning(right)
|
|
18
|
+
&& left.code === right.code
|
|
19
|
+
&& left.message === right.message
|
|
20
|
+
&& left.action === right.action;
|
|
21
|
+
}
|
|
@@ -3,10 +3,11 @@ import type { ReviewFinalizationRequest } from './review-finalization.ts';
|
|
|
3
3
|
export function parseReviewCommand(args: readonly string[]): ReviewFinalizationRequest & {
|
|
4
4
|
overrideTicket?: string; overrideTarget?: string; overrideScope?: string;
|
|
5
5
|
} {
|
|
6
|
-
if (!args[0] || args[1]
|
|
6
|
+
if (!args[0] || !['preflight', 'finalize-summary'].includes(args[1] ?? '')) throw new Error('task ref and a supported review operation are required');
|
|
7
7
|
const values: Record<string, string | boolean> = {};
|
|
8
8
|
const flags = {
|
|
9
9
|
'--stage': 'stage', '--artifact': 'artifact', '--orchestrated': 'orchestrated', '--dry-run': 'dryRun',
|
|
10
|
+
'--recovery-id': 'recoveryId',
|
|
10
11
|
'--override-ticket': 'overrideTicket', '--override-target': 'overrideTarget', '--override-scope': 'overrideScope'
|
|
11
12
|
} as const;
|
|
12
13
|
for (let index = 2; index < args.length; index += 1) {
|