@fitlab-ai/agent-infra 0.12.0 → 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 +29 -27
- package/dist/lib/internal/platform-comment.js +56 -7
- 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 +373 -282
- package/dist/lib/platform/issue-summary-content.js +112 -0
- 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 +176 -30
- package/dist/lib/platform/pr-checks.js +2 -8
- package/dist/lib/platform/pr-summary-content.js +54 -0
- package/dist/lib/platform/pr-summary.js +318 -284
- 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/summary-content-pipeline.js +18 -0
- 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 +67 -518
- 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 +60 -15
- 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 +151 -108
- 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 +28 -27
- package/lib/internal/platform-comment.ts +46 -4
- 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 +478 -301
- package/lib/platform/issue-summary-content.ts +132 -0
- package/lib/platform/issues.ts +0 -2
- package/lib/platform/operation-coordinator.ts +4 -2
- package/lib/platform/pr-change-report.ts +165 -25
- package/lib/platform/pr-checks.ts +1 -10
- package/lib/platform/pr-review.ts +1 -1
- package/lib/platform/pr-summary-content.ts +60 -0
- package/lib/platform/pr-summary.ts +364 -257
- 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/summary-content-pipeline.ts +23 -0
- 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 +58 -687
- 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 +52 -15
- 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 +117 -104
- 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 +4 -2
- package/templates/.agents/rules/pr-sync.zh-CN.md +6 -9
- 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/commit/reference/pr-summary-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +2 -2
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +2 -2
- package/templates/.agents/skills/complete-task/SKILL.en.md +10 -25
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +11 -26
- package/templates/.agents/skills/create-pr/SKILL.en.md +1 -1
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/create-pr/reference/change-report.en.md +9 -2
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +9 -2
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +2 -2
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +2 -2
- package/templates/.agents/skills/create-task/SKILL.en.md +0 -18
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +0 -18
- 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/skills/watch-pr/SKILL.en.md +1 -1
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +3 -3
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +3 -3
- 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,95 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
inspectOrchestrationStage,
|
|
3
|
-
pauseOrchestration,
|
|
4
|
-
planOrchestrationStageCompletion
|
|
5
|
-
} from './orchestration.ts';
|
|
6
|
-
import type {
|
|
7
|
-
OrchestrationStageCompletion,
|
|
8
|
-
OrchestrationStageIdentity
|
|
9
|
-
} from './orchestration.ts';
|
|
10
|
-
import { resolveTaskRef } from './resolve-ref.ts';
|
|
1
|
+
import { parseTypedTaskFrontmatter } from './frontmatter.ts';
|
|
11
2
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
completionPlan: OrchestrationStageCompletion | null;
|
|
23
|
-
error: Readonly<{ code: string; message: string }> | null;
|
|
24
|
-
}>;
|
|
3
|
+
const labels = {
|
|
4
|
+
'Analyze Task': 'analyze', 'Review Analysis': 'review-analysis', 'Plan Task': 'plan',
|
|
5
|
+
'Review Plan': 'review-plan', 'Code Task': 'code', 'Review Code': 'review-code',
|
|
6
|
+
'Run Manual Validation': 'validation-run'
|
|
7
|
+
} as const;
|
|
8
|
+
export type ExecutionFamily = typeof labels[keyof typeof labels] | 'manual-validation' | 'other';
|
|
9
|
+
export type LifecycleExecution = {
|
|
10
|
+
family: ExecutionFamily; agent: string; startedAt: string; round?: number;
|
|
11
|
+
fixFor?: string; implementationInput?: string; transactionId?: string;
|
|
12
|
+
};
|
|
25
13
|
|
|
26
|
-
function
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}> = {}
|
|
37
|
-
): LifecycleExecutionResult {
|
|
38
|
-
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
39
|
-
if (!resolved.ok) return failure(request.mode, resolved.code, resolved.message);
|
|
40
|
-
if (request.mode === 'standalone') {
|
|
41
|
-
return { ok: true, mode: request.mode, completionPlan: null, error: null };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (request.agent) {
|
|
45
|
-
const planned = planOrchestrationStageCompletion(taskRef, {
|
|
46
|
-
...request.identity,
|
|
47
|
-
agent: request.agent
|
|
48
|
-
}, options);
|
|
49
|
-
if (planned.plan) {
|
|
50
|
-
return { ok: true, mode: request.mode, completionPlan: planned.plan, error: null };
|
|
51
|
-
}
|
|
52
|
-
return failure(
|
|
53
|
-
request.mode,
|
|
54
|
-
planned.result.error?.code ?? 'ORCHESTRATION_PROVENANCE_MISMATCH',
|
|
55
|
-
planned.result.error?.message ?? 'orchestration provenance validation failed'
|
|
56
|
-
);
|
|
14
|
+
export function lifecycleExecutions(content: string): LifecycleExecution[] {
|
|
15
|
+
const value = parseTypedTaskFrontmatter(content).lifecycle_execution;
|
|
16
|
+
if (value !== undefined) {
|
|
17
|
+
if (typeof value !== 'string') throw new Error('invalid lifecycle execution state');
|
|
18
|
+
const state: unknown = JSON.parse(value);
|
|
19
|
+
if (!state || typeof state !== 'object' || !('version' in state) || state.version !== 1 || !('open' in state) || !Array.isArray(state.open)) throw new Error('invalid lifecycle execution state');
|
|
20
|
+
return state.open.map((item: unknown) => {
|
|
21
|
+
if (!item || typeof item !== 'object' || !('family' in item) || typeof item.family !== 'string' || ![...Object.values(labels), 'manual-validation', 'other'].includes(item.family as ExecutionFamily) || !('agent' in item) || typeof item.agent !== 'string' || !('startedAt' in item) || typeof item.startedAt !== 'string') throw new Error('invalid lifecycle execution identity');
|
|
22
|
+
return item as LifecycleExecution;
|
|
23
|
+
});
|
|
57
24
|
}
|
|
58
|
-
|
|
59
|
-
const inspected = inspectOrchestrationStage(taskRef, request.identity, options);
|
|
60
|
-
if (inspected.status !== 'failed') {
|
|
61
|
-
return { ok: true, mode: request.mode, completionPlan: null, error: null };
|
|
62
|
-
}
|
|
63
|
-
return failure(
|
|
64
|
-
request.mode,
|
|
65
|
-
inspected.error?.code ?? 'ORCHESTRATION_PROVENANCE_MISMATCH',
|
|
66
|
-
inspected.error?.message ?? 'orchestration provenance validation failed'
|
|
67
|
-
);
|
|
25
|
+
return [];
|
|
68
26
|
}
|
|
69
27
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
options
|
|
86
|
-
);
|
|
87
|
-
return failure(
|
|
88
|
-
request.mode,
|
|
89
|
-
paused.run?.pause?.code ?? inspected.error?.code ?? 'ORCHESTRATION_PROVENANCE_MISMATCH',
|
|
90
|
-
paused.run?.pause?.message ?? inspected.error?.message ?? 'orchestration provenance validation failed'
|
|
91
|
-
);
|
|
28
|
+
export type PrReviewExecution = { open: { artifact: string; head: string; agent: string; startedAt: string } | null; terminals: Array<{ artifact: string; head: string; agent: string; note: string }> };
|
|
29
|
+
export function prReviewExecution(content: string): PrReviewExecution {
|
|
30
|
+
const value = parseTypedTaskFrontmatter(content).lifecycle_execution;
|
|
31
|
+
if (value === undefined) return { open: null, terminals: [] };
|
|
32
|
+
if (typeof value !== 'string') throw new Error('invalid lifecycle execution state');
|
|
33
|
+
const state = JSON.parse(value);
|
|
34
|
+
if (state.version !== 1 || !Array.isArray(state.open)) throw new Error('invalid lifecycle execution state');
|
|
35
|
+
const pr = state.prReview ?? { open: null, terminals: [] };
|
|
36
|
+
const valid = (item: any) => item && typeof item.artifact === 'string' && typeof item.head === 'string' && typeof item.agent === 'string';
|
|
37
|
+
if (!Array.isArray(pr.terminals) || (pr.open !== null && (!valid(pr.open) || typeof pr.open.startedAt !== 'string')) || !pr.terminals.every((item: any) => valid(item) && typeof item.note === 'string')) throw new Error('invalid PR review execution state');
|
|
38
|
+
return pr;
|
|
39
|
+
}
|
|
40
|
+
export function serializeLifecycleExecution(open: readonly LifecycleExecution[], content?: string, prReview?: PrReviewExecution): string {
|
|
41
|
+
const pr = prReview ?? (content ? prReviewExecution(content) : { open: null, terminals: [] });
|
|
42
|
+
return JSON.stringify({ version: 1, open, prReview: pr });
|
|
92
43
|
}
|
|
93
|
-
|
|
94
|
-
export { inspectLifecycleExecution, validateLifecycleExecution };
|
|
95
|
-
export type { LifecycleExecutionMode, LifecycleExecutionRequest, LifecycleExecutionResult };
|
package/lib/task/lifecycle.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
|
|
5
|
-
import { appendActivityEntry, locateActivityLog } from './activity-log.ts';
|
|
5
|
+
import { activityWarnings, appendActivityEntry, locateActivityLog } from './activity-log.ts';
|
|
6
6
|
import { artifactFamilyCatalog, inspectArtifactDirectory } from './artifact-lifecycle.ts';
|
|
7
7
|
import { parseArtifactName } from './artifact-name.ts';
|
|
8
8
|
import { parseTypedTaskFrontmatter, updateTaskFrontmatter } from './frontmatter.ts';
|
|
@@ -21,7 +21,7 @@ import { resourceIdentityEquals } from '../platform/resource-identity.ts';
|
|
|
21
21
|
import { resolveProjectTaskWorkspaceRoot } from './workspace-root.ts';
|
|
22
22
|
|
|
23
23
|
const lifecycleIntentCatalog = [
|
|
24
|
-
'block', 'activate', 'cancel', 'complete', 'close-codescan', 'close-dependabot', 'restore'
|
|
24
|
+
'block', 'activate', 'cancel', 'complete', 'close-codescan', 'close-dependabot', 'restore'
|
|
25
25
|
] as const;
|
|
26
26
|
const lifecycleFailureCatalog = [
|
|
27
27
|
'LIFECYCLE_DIRECTORY_TRANSFER_FAILED',
|
|
@@ -60,8 +60,7 @@ type TaskLifecycleRequest =
|
|
|
60
60
|
| { taskRef: string; intent: 'complete'; agent: string; dryRun?: boolean }
|
|
61
61
|
| { taskRef: string; intent: 'close-codescan'; agent: string; alertNumber: number; reason: string; dryRun?: boolean }
|
|
62
62
|
| { taskRef: string; intent: 'close-dependabot'; agent: string; alertNumber: number; reason: string; dryRun?: boolean }
|
|
63
|
-
| { taskRef: string; intent: 'restore'; agent: string; stagingDir: string; issueNumber: number; dryRun?: boolean }
|
|
64
|
-
| { taskRef: string; intent: 'recover-started'; agent: string; auto: true; dryRun?: boolean };
|
|
63
|
+
| { taskRef: string; intent: 'restore'; agent: string; stagingDir: string; issueNumber: number; dryRun?: boolean };
|
|
65
64
|
|
|
66
65
|
type HotState = 'active' | 'blocked' | 'completed';
|
|
67
66
|
type SourceState = HotState | 'staging';
|
|
@@ -97,6 +96,7 @@ type TaskLifecycleResult = {
|
|
|
97
96
|
completedSteps: readonly LifecycleStep[];
|
|
98
97
|
pendingSteps: readonly LifecycleStep[];
|
|
99
98
|
error: LifecycleError | null;
|
|
99
|
+
warnings?: readonly { code: string; message: string }[];
|
|
100
100
|
};
|
|
101
101
|
type LifecycleFileSystem = {
|
|
102
102
|
renameSync: (source: string, target: string) => void;
|
|
@@ -160,14 +160,6 @@ function failed(request: Pick<TaskLifecycleRequest, 'taskRef' | 'intent'>, error
|
|
|
160
160
|
};
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
export function taskLifecycleFailure(
|
|
164
|
-
request: Pick<TaskLifecycleRequest, 'taskRef' | 'intent'>,
|
|
165
|
-
error: LifecycleError,
|
|
166
|
-
taskId: string | null = null
|
|
167
|
-
): TaskLifecycleResult {
|
|
168
|
-
return failed(request, error, { taskId });
|
|
169
|
-
}
|
|
170
|
-
|
|
171
163
|
function normalizedRequest(request: TaskLifecycleRequest): TaskLifecycleRequest | LifecycleError {
|
|
172
164
|
if (!request || typeof request !== 'object' || !lifecycleIntentCatalog.includes(request.intent as TaskLifecycleIntent)) {
|
|
173
165
|
return { code: 'LIFECYCLE_PAYLOAD_INVALID', message: 'intent is not in the lifecycle catalog' };
|
|
@@ -368,32 +360,17 @@ function taskBoundControlMoveSafety(
|
|
|
368
360
|
return null;
|
|
369
361
|
}
|
|
370
362
|
|
|
371
|
-
function orchestrationMoveSafety(sourcePath: string): LifecycleError | null {
|
|
372
|
-
const orchestrationPath = path.join(sourcePath, '.runtime', 'orchestration.json');
|
|
373
|
-
if (!pathExists(orchestrationPath)) return null;
|
|
374
|
-
try {
|
|
375
|
-
const run = JSON.parse(fs.readFileSync(orchestrationPath, 'utf8')) as { status?: unknown; pendingDelegation?: unknown };
|
|
376
|
-
if (run.status === 'running' || run.pendingDelegation !== null && run.pendingDelegation !== undefined) {
|
|
377
|
-
return { code: 'LIFECYCLE_RUNTIME_MOVE_UNSAFE', message: 'task orchestration has an active or pending delegation; settle it before moving the task directory' };
|
|
378
|
-
}
|
|
379
|
-
} catch {
|
|
380
|
-
return { code: 'LIFECYCLE_RUNTIME_MOVE_UNSAFE', message: 'task orchestration state is unreadable; refusing to move the task directory' };
|
|
381
|
-
}
|
|
382
|
-
return null;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
363
|
function runtimeMoveSafety(
|
|
386
364
|
request: TaskLifecycleRequest,
|
|
387
365
|
movingTaskDirectory: boolean,
|
|
388
366
|
options: TaskLifecycleOptions,
|
|
389
367
|
taskId: string,
|
|
390
368
|
repoRoot: string,
|
|
391
|
-
sourcePath: string,
|
|
392
369
|
validateControlManifestIdentity: boolean
|
|
393
370
|
): LifecycleError | null {
|
|
394
371
|
if (!movingTaskDirectory) return null;
|
|
395
372
|
const controlSafety = taskBoundControlMoveSafety(request, options.controlRoot, options, taskId, repoRoot, validateControlManifestIdentity);
|
|
396
|
-
return controlSafety
|
|
373
|
+
return controlSafety;
|
|
397
374
|
}
|
|
398
375
|
|
|
399
376
|
function targetContainsTask(targetPath: string, taskId: string, request: TaskLifecycleRequest): boolean {
|
|
@@ -422,15 +399,26 @@ function actionAndNote(request: TaskLifecycleRequest, restoredFiles = 0): { acti
|
|
|
422
399
|
if (request.intent === 'complete') return { action: 'Complete Task', note: 'Task moved to completed/' };
|
|
423
400
|
if (request.intent === 'close-codescan') return { action: 'Close Codescan', note: `Code Scanning alert #${request.alertNumber} dismissed: ${request.reason}` };
|
|
424
401
|
if (request.intent === 'close-dependabot') return { action: 'Close Dependabot', note: `Dependabot alert #${request.alertNumber} dismissed: ${request.reason}` };
|
|
425
|
-
if (request.intent === 'recover-started') return { action: 'Recover Started', note: 'automatic recovery' };
|
|
426
402
|
return { action: 'Restore Task', note: `Restored ${restoredFiles} files from Issue #${request.issueNumber}` };
|
|
427
403
|
}
|
|
428
404
|
|
|
405
|
+
type LifecycleCompletionKey = { action: string; agent: string; note: string };
|
|
406
|
+
|
|
407
|
+
function completionKeys(content: string): LifecycleCompletionKey[] {
|
|
408
|
+
const value = parseTypedTaskFrontmatter(content).lifecycle_transition;
|
|
409
|
+
if (value === undefined) return [];
|
|
410
|
+
if (typeof value !== 'string') throw new Error('invalid lifecycle transition');
|
|
411
|
+
const state: unknown = JSON.parse(value);
|
|
412
|
+
if (!state || typeof state !== 'object' || !('completedKeys' in state) || !Array.isArray(state.completedKeys)) throw new Error('invalid lifecycle transition');
|
|
413
|
+
return state.completedKeys.map((key: unknown) => {
|
|
414
|
+
if (!key || typeof key !== 'object' || !('action' in key) || typeof key.action !== 'string' || !('agent' in key) || typeof key.agent !== 'string' || !('note' in key) || typeof key.note !== 'string') throw new Error('invalid lifecycle completion identity');
|
|
415
|
+
return key as LifecycleCompletionKey;
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
|
|
429
419
|
function matchingCompletion(content: string, request: TaskLifecycleRequest, restoredFiles = 0): boolean {
|
|
430
|
-
const section = locateActivityLog(content);
|
|
431
|
-
if (!section) return false;
|
|
432
420
|
const identity = actionAndNote(request, restoredFiles);
|
|
433
|
-
return
|
|
421
|
+
return completionKeys(content).some((entry) => entry.action === identity.action && entry.agent === request.agent && entry.note === identity.note);
|
|
434
422
|
}
|
|
435
423
|
|
|
436
424
|
function validateRestoreStaging(request: Extract<TaskLifecycleRequest, { intent: 'restore' }>, repoRoot: string, taskId: string): LifecycleError | { stagingDir: string; fileCount: number } {
|
|
@@ -483,12 +471,17 @@ function validateRestoreStaging(request: Extract<TaskLifecycleRequest, { intent:
|
|
|
483
471
|
return { stagingDir, fileCount: entries.filter((entry) => !entry.name.startsWith('.')).length };
|
|
484
472
|
}
|
|
485
473
|
|
|
486
|
-
function
|
|
487
|
-
const section = locateActivityLog(content) ?? (
|
|
488
|
-
if (!section) return
|
|
489
|
-
const identity = actionAndNote(request, restoredFiles);
|
|
474
|
+
function lifecycleActivityMutation(content: string, request: TaskLifecycleRequest, metadata: TaskWriteMetadata, identity: { action: string; note: string }, allowMissing: boolean): TaskMutation[] {
|
|
475
|
+
const section = locateActivityLog(content) ?? (allowMissing ? { heading: 'Activity Log', body: '', entries: [] } : null);
|
|
476
|
+
if (!section) return [];
|
|
490
477
|
let body = appendActivityEntry(section, { time: metadata.timestamp, step: `${identity.action} [started]`, agent: request.agent, note: 'started' });
|
|
491
478
|
body = appendActivityEntry({ ...section, body }, { time: metadata.timestamp, step: identity.action, agent: request.agent, note: identity.note });
|
|
479
|
+
return [{ kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: section.heading, body }];
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function mutationsFor(request: TaskLifecycleRequest, content: string, metadata: TaskWriteMetadata, restoredFiles: number, allowMissingActivityLog = false): TaskMutation[] | LifecycleError {
|
|
483
|
+
const identity = actionAndNote(request, restoredFiles);
|
|
484
|
+
const activityMutation = lifecycleActivityMutation(content, request, metadata, identity, allowMissingActivityLog);
|
|
492
485
|
const set: Record<string, string> = {};
|
|
493
486
|
const remove: string[] = [];
|
|
494
487
|
if (request.intent === 'block') {
|
|
@@ -506,9 +499,12 @@ function mutationsFor(request: TaskLifecycleRequest, content: string, metadata:
|
|
|
506
499
|
const frontmatter = parseTypedTaskFrontmatter(content);
|
|
507
500
|
if (frontmatter.target_date === '') set.target_date = metadata.timestamp.slice(0, 10);
|
|
508
501
|
}
|
|
502
|
+
const completedKeys = completionKeys(content);
|
|
503
|
+
if (!matchingCompletion(content, request, restoredFiles)) completedKeys.push({ ...identity, agent: request.agent });
|
|
504
|
+
set.lifecycle_transition = JSON.stringify({ completedKeys });
|
|
509
505
|
const mutations: TaskMutation[] = [
|
|
510
506
|
{ kind: 'frontmatter', set, remove: [...new Set(remove)] },
|
|
511
|
-
|
|
507
|
+
...activityMutation
|
|
512
508
|
];
|
|
513
509
|
if (request.intent === 'block') {
|
|
514
510
|
mutations.splice(1, 0, {
|
|
@@ -630,9 +626,6 @@ export function inspectTaskLifecycleProgress(
|
|
|
630
626
|
}
|
|
631
627
|
|
|
632
628
|
function applyTaskLifecycle(requestInput: TaskLifecycleRequest, options: TaskLifecycleOptions = {}): TaskLifecycleResult {
|
|
633
|
-
if (requestInput.intent === 'recover-started') {
|
|
634
|
-
return failed(requestInput, { code: 'LIFECYCLE_RECOVERY_REQUIRES_AUTHORITY', message: 'recover-started must be dispatched through task control authority' });
|
|
635
|
-
}
|
|
636
629
|
const normalized = normalizedRequest(requestInput);
|
|
637
630
|
if ('code' in normalized) return failed(requestInput, normalized);
|
|
638
631
|
const request = normalized;
|
|
@@ -696,14 +689,13 @@ function applyTaskLifecycle(requestInput: TaskLifecycleRequest, options: TaskLif
|
|
|
696
689
|
&& !(request.intent === 'complete' && targetContainsTask(targetPath, taskId, request))) {
|
|
697
690
|
return failed(request, { code: 'LIFECYCLE_TARGET_CONFLICT', message: `target directory already exists: ${targetPath}` }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
|
|
698
691
|
}
|
|
699
|
-
const moveSafety = runtimeMoveSafety(request, movingTaskDirectory, options, taskId, repoRoot,
|
|
692
|
+
const moveSafety = runtimeMoveSafety(request, movingTaskDirectory, options, taskId, repoRoot, true);
|
|
700
693
|
if (moveSafety) return failed(request, moveSafety, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
|
|
701
694
|
const content = io.readFileSync(currentTaskFile);
|
|
702
695
|
let frontmatter;
|
|
703
696
|
try { frontmatter = parseTypedTaskFrontmatter(content); }
|
|
704
697
|
catch (error) { return failed(request, { code: 'LIFECYCLE_DOCUMENT_INVALID', message: error instanceof Error ? error.message : String(error) }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath }); }
|
|
705
698
|
if (frontmatter.id !== taskId) return failed(request, { code: 'LIFECYCLE_IDENTITY_INVALID', message: 'task.md id does not match its lifecycle task id' }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
|
|
706
|
-
if (!locateActivityLog(content)) return failed(request, { code: 'LIFECYCLE_LOG_MISSING', message: 'task has no unique Activity Log section' }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
|
|
707
699
|
if (spec.target === 'active') {
|
|
708
700
|
const contract = validateCurrentTaskContract(content);
|
|
709
701
|
if (!contract.ok) return failed(request, { code: 'LIFECYCLE_DOCUMENT_INVALID', message: contract.message }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
|
|
@@ -823,7 +815,7 @@ function applyTaskLifecycle(requestInput: TaskLifecycleRequest, options: TaskLif
|
|
|
823
815
|
}
|
|
824
816
|
if (fs.existsSync(targetPath) && !fs.existsSync(path.join(sourcePath, 'task.md'))) completed.add('directory-moved');
|
|
825
817
|
if (!completed.has('directory-moved')) {
|
|
826
|
-
const moveSafety = runtimeMoveSafety(request, movingTaskDirectory, options, taskId, repoRoot,
|
|
818
|
+
const moveSafety = runtimeMoveSafety(request, movingTaskDirectory, options, taskId, repoRoot, false);
|
|
827
819
|
if (moveSafety) return failed(request, moveSafety, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath, journalPath, completedSteps: [...completed], changed: completed.size > 0, timestamp: journal.metadata.timestamp, agentInfraVersion: journal.metadata.agentInfraVersion });
|
|
828
820
|
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
829
821
|
if (request.intent === 'complete') {
|
|
@@ -925,9 +917,21 @@ function applyTaskLifecycle(requestInput: TaskLifecycleRequest, options: TaskLif
|
|
|
925
917
|
};
|
|
926
918
|
}
|
|
927
919
|
|
|
920
|
+
function applyTaskLifecycleWithWarnings(request: TaskLifecycleRequest, options: TaskLifecycleOptions = {}): TaskLifecycleResult {
|
|
921
|
+
const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
|
|
922
|
+
const taskFile = resolved.ok ? resolved.taskMdPath : request.intent === 'restore' ? path.join(request.stagingDir, 'task.md') : null;
|
|
923
|
+
let warnings: ReturnType<typeof activityWarnings> = [];
|
|
924
|
+
if (taskFile) {
|
|
925
|
+
try { warnings = activityWarnings(fs.readFileSync(taskFile, 'utf8')); }
|
|
926
|
+
catch { /* The lifecycle operation reports its own read failure. */ }
|
|
927
|
+
}
|
|
928
|
+
const result = applyTaskLifecycle(request, options);
|
|
929
|
+
return result.status === 'failed' || !warnings.length ? result : { ...result, warnings };
|
|
930
|
+
}
|
|
931
|
+
|
|
928
932
|
export {
|
|
929
933
|
lifecycleIntentCatalog, lifecycleFailureCatalog, lifecycleProducerCatalog,
|
|
930
|
-
applyTaskLifecycle, previewTaskCompletion
|
|
934
|
+
applyTaskLifecycleWithWarnings as applyTaskLifecycle, previewTaskCompletion
|
|
931
935
|
};
|
|
932
936
|
export type {
|
|
933
937
|
TaskLifecycleIntent, TaskLifecycleRequest, TaskLifecycleResult, TaskLifecycleOptions,
|
|
@@ -183,12 +183,6 @@ function prepareLocalArtifact(
|
|
|
183
183
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
function commitLocalArtifactProvenance(
|
|
187
|
-
prepared: LocalArtifactPreparation
|
|
188
|
-
): LocalArtifactFinalizationResult {
|
|
189
|
-
return prepared.result;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
186
|
function finalizeLocalArtifact(
|
|
193
187
|
request: LocalArtifactFinalizationRequest
|
|
194
188
|
): LocalArtifactFinalizationResult {
|
|
@@ -208,7 +202,6 @@ export {
|
|
|
208
202
|
finalizeLocalArtifact,
|
|
209
203
|
preflightLocalArtifact,
|
|
210
204
|
prepareLocalArtifact,
|
|
211
|
-
commitLocalArtifactProvenance,
|
|
212
205
|
canonicalSemanticDigest as semanticDigest,
|
|
213
206
|
sha256Content,
|
|
214
207
|
validateLocalArtifact
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import { createHash } from 'node:crypto';
|
|
3
1
|
import {
|
|
4
2
|
MANUAL_VALIDATION_SHA40 as SHA40,
|
|
5
3
|
MANUAL_VALIDATION_TASK_ID as TASK_ID,
|
|
@@ -47,11 +45,6 @@ type ManualValidationEvidenceInput = {
|
|
|
47
45
|
signal: string | null;
|
|
48
46
|
cleanup: ManualValidationCleanup;
|
|
49
47
|
};
|
|
50
|
-
type ManualValidationEvidenceIdentity = {
|
|
51
|
-
taskId: string | null;
|
|
52
|
-
branch: string;
|
|
53
|
-
commit?: string;
|
|
54
|
-
};
|
|
55
48
|
type ManualValidationEvidenceErrorCode =
|
|
56
49
|
| 'MANUAL_VALIDATION_EVIDENCE_MISSING'
|
|
57
50
|
| 'MANUAL_VALIDATION_EVIDENCE_INVALID'
|
|
@@ -151,56 +144,17 @@ function manualValidationEvidenceSummary(evidence: ManualValidationEvidence): Ma
|
|
|
151
144
|
};
|
|
152
145
|
}
|
|
153
146
|
|
|
154
|
-
function validateManualValidationEvidence(value: unknown, expected?: ManualValidationEvidenceIdentity): ManualValidationEvidenceResult {
|
|
155
|
-
const shape = validateShape(value);
|
|
156
|
-
if (!shape.ok) return shape;
|
|
157
|
-
const evidence = shape.value;
|
|
158
|
-
if (evidence.result.exitCode !== 0 || evidence.result.signal !== null || evidence.result.cleanup !== 'completed') {
|
|
159
|
-
return { ok: false, error: { code: 'MANUAL_VALIDATION_EVIDENCE_UNSUCCESSFUL', message: 'validation must exit 0 without a signal and complete cleanup' } };
|
|
160
|
-
}
|
|
161
|
-
if (expected) {
|
|
162
|
-
if (evidence.taskId !== expected.taskId || evidence.branch !== expected.branch) {
|
|
163
|
-
return { ok: false, error: { code: 'MANUAL_VALIDATION_EVIDENCE_IDENTITY_MISMATCH', message: 'evidence task or branch does not match the expected identity' } };
|
|
164
|
-
}
|
|
165
|
-
if (expected.commit !== undefined && evidence.commit !== expected.commit) {
|
|
166
|
-
return { ok: false, error: { code: 'MANUAL_VALIDATION_EVIDENCE_STALE', message: 'evidence commit does not match the current head' } };
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return shape;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function readManualValidationEvidence(file: string, expected?: ManualValidationEvidenceIdentity): ManualValidationEvidenceResult {
|
|
173
|
-
let parsed: unknown;
|
|
174
|
-
try {
|
|
175
|
-
parsed = JSON.parse(fs.readFileSync(file, 'utf8')) as unknown;
|
|
176
|
-
} catch (error) {
|
|
177
|
-
const code = (error as NodeJS.ErrnoException).code === 'ENOENT'
|
|
178
|
-
? 'MANUAL_VALIDATION_EVIDENCE_MISSING'
|
|
179
|
-
: 'MANUAL_VALIDATION_EVIDENCE_INVALID';
|
|
180
|
-
return { ok: false, error: { code, message: error instanceof Error ? error.message : String(error) } };
|
|
181
|
-
}
|
|
182
|
-
return validateManualValidationEvidence(parsed, expected);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function manualValidationEvidenceDigest(evidence: ManualValidationEvidence): string {
|
|
186
|
-
return createHash('sha256').update(JSON.stringify(evidence), 'utf8').digest('hex');
|
|
187
|
-
}
|
|
188
|
-
|
|
189
147
|
export {
|
|
190
148
|
MANUAL_VALIDATION_EVIDENCE_SCHEMA,
|
|
191
149
|
MANUAL_VALIDATION_EVIDENCE_VERSION,
|
|
192
150
|
createManualValidationEvidence,
|
|
193
|
-
manualValidationEvidenceSummary
|
|
194
|
-
manualValidationEvidenceDigest,
|
|
195
|
-
readManualValidationEvidence,
|
|
196
|
-
validateManualValidationEvidence
|
|
151
|
+
manualValidationEvidenceSummary
|
|
197
152
|
};
|
|
198
153
|
export type {
|
|
199
154
|
ManualValidationCleanup,
|
|
200
155
|
ManualValidationEvidence,
|
|
201
156
|
ManualValidationEvidenceError,
|
|
202
157
|
ManualValidationEvidenceErrorCode,
|
|
203
|
-
ManualValidationEvidenceIdentity,
|
|
204
158
|
ManualValidationEvidenceInput,
|
|
205
159
|
ManualValidationEvidenceResult,
|
|
206
160
|
ManualValidationEvidenceSummary,
|