@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
|
@@ -7,12 +7,12 @@ import { checkpointCommitMatches } from './commit-identity.js';
|
|
|
7
7
|
import { resolveTaskContext, resolveTaskRef } from './resolve-ref.js';
|
|
8
8
|
import { commitPushDecision } from './commit-policy.js';
|
|
9
9
|
import { mergeOperationWarnings } from './operation-outcome.js';
|
|
10
|
-
import { appendActivityEntry, locateActivityLog } from './activity-log.js';
|
|
10
|
+
import { activityWarnings, appendActivityEntry, locateActivityLog } from './activity-log.js';
|
|
11
11
|
import { captureTaskWriteMetadata, writeTask } from './write.js';
|
|
12
12
|
import { checkpointIntentDigest, readCheckpointIntent, removeCheckpointIntent, sameCheckpointIntent, updateCheckpointIntent, writeCheckpointIntent } from './commit-intent.js';
|
|
13
13
|
const HEAD_REF = /^refs\/heads\/(.+)$/;
|
|
14
14
|
function isCommitExecutionMode(value) {
|
|
15
|
-
return value === 'direct'
|
|
15
|
+
return value === 'direct';
|
|
16
16
|
}
|
|
17
17
|
function gitText(repoRoot, args) {
|
|
18
18
|
return execFileSync('git', [...args], {
|
|
@@ -117,50 +117,43 @@ function validateCommon(input, branch) {
|
|
|
117
117
|
}
|
|
118
118
|
return null;
|
|
119
119
|
}
|
|
120
|
-
|
|
120
|
+
// Log presentation only; checkpoint identity and recovery never depend on this projection.
|
|
121
|
+
function commitLogProjection(activity, timestamp, agent, commitNote) {
|
|
122
|
+
if (!activity)
|
|
123
|
+
return [];
|
|
124
|
+
let lastCommit = -1;
|
|
125
|
+
for (const [index, entry] of activity.entries.entries()) {
|
|
126
|
+
if (entry.step === 'Commit' && entry.note === commitNote)
|
|
127
|
+
lastCommit = index;
|
|
128
|
+
}
|
|
129
|
+
const reviewedAfter = activity.entries.slice(lastCommit + 1).some((entry) => /^Review Code \(Round \d+\)$/.test(entry.step));
|
|
130
|
+
if (lastCommit >= 0 && !reviewedAfter)
|
|
131
|
+
return [];
|
|
132
|
+
return [{ kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: activity.heading,
|
|
133
|
+
body: appendActivityEntry(activity, { time: timestamp, step: 'Commit', agent, note: commitNote }) }];
|
|
134
|
+
}
|
|
135
|
+
function syncTaskCommit(input, task, committedHead, writeOptions = {}) {
|
|
121
136
|
let content;
|
|
122
137
|
try {
|
|
123
138
|
content = fs.readFileSync(task.taskMdPath, 'utf8');
|
|
124
139
|
const activity = locateActivityLog(content);
|
|
125
|
-
if (!activity)
|
|
126
|
-
return warning('TASK_STATUS_SYNC_FAILED', 'task has no unique Activity Log section', true, 'task', task.taskId, 'ACTION_REQUIRED');
|
|
127
140
|
const metadata = captureTaskWriteMetadata();
|
|
128
141
|
const commitNote = gitText(task.repoRoot, ['show', '-s', '--format=%h %s', committedHead]);
|
|
129
|
-
|
|
130
|
-
for (let index = activity.entries.length - 1; index >= 0; index -= 1) {
|
|
131
|
-
const entry = activity.entries[index];
|
|
132
|
-
if (entry.step === 'Commit' && entry.note === commitNote) {
|
|
133
|
-
matchingCommitIndex = index;
|
|
134
|
-
break;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
const reviewedAfterCommit = matchingCommitIndex >= 0 && activity.entries
|
|
138
|
-
.slice(matchingCommitIndex + 1)
|
|
139
|
-
.some((entry) => /^Review Code \(Round \d+\)$/.test(entry.step));
|
|
140
|
-
const alreadyLogged = matchingCommitIndex >= 0 && !reviewedAfterCommit;
|
|
141
|
-
const mutations = [];
|
|
142
|
-
if (!alreadyLogged)
|
|
143
|
-
mutations.push({
|
|
144
|
-
kind: 'section',
|
|
145
|
-
aliases: ['活动日志', 'Activity Log'],
|
|
146
|
-
heading: activity.heading,
|
|
147
|
-
body: appendActivityEntry(activity, { time: metadata.timestamp, step: 'Commit', agent: input.agent, note: commitNote })
|
|
148
|
-
});
|
|
142
|
+
const mutations = commitLogProjection(activity, metadata.timestamp, input.agent, commitNote);
|
|
149
143
|
const frontmatter = {
|
|
150
144
|
assigned_to: input.agent,
|
|
151
145
|
checkpoint_commit: committedHead
|
|
152
146
|
};
|
|
153
147
|
mutations.push({ kind: 'frontmatter', set: frontmatter });
|
|
154
|
-
if (mutations.length === 0)
|
|
155
|
-
return null;
|
|
156
148
|
const written = writeTask({
|
|
157
149
|
taskRef: task.taskId,
|
|
158
150
|
expectedState: 'active',
|
|
159
151
|
mutations
|
|
160
|
-
}, { repoRoot: task.repoRoot, metadataProvider: () => metadata });
|
|
152
|
+
}, { ...writeOptions, repoRoot: task.repoRoot, metadataProvider: () => metadata });
|
|
161
153
|
if (written.status === 'failed')
|
|
162
154
|
return warning('TASK_STATUS_SYNC_FAILED', written.error.message, true, 'task', task.taskId, 'ACTION_REQUIRED');
|
|
163
|
-
|
|
155
|
+
const logWarning = activityWarnings(content)[0];
|
|
156
|
+
return logWarning ? warning(logWarning.code, logWarning.message, true, 'task', task.taskId, 'IMPORTANT') : null;
|
|
164
157
|
}
|
|
165
158
|
catch (error) {
|
|
166
159
|
return warning('TASK_STATUS_SYNC_FAILED', error instanceof Error ? error.message : String(error), true, 'task', task.taskId, 'ACTION_REQUIRED');
|
|
@@ -183,12 +176,10 @@ function checkpointIdentity(input, task, delivery) {
|
|
|
183
176
|
function checkpointTimestamp() {
|
|
184
177
|
return new Date().toISOString();
|
|
185
178
|
}
|
|
186
|
-
function executeCommitOperationCore(input, task, mode) {
|
|
179
|
+
function executeCommitOperationCore(input, task, mode, writeOptions) {
|
|
187
180
|
const inspected = inspectGitWorkflow(input.cwd);
|
|
188
181
|
if (!inspected.snapshot)
|
|
189
182
|
return failure(input, mode, task?.taskId ?? null, 'GIT_INSPECT_FAILED', 'Unable to inspect Git repository');
|
|
190
|
-
if (mode === 'orchestrated')
|
|
191
|
-
return failure(input, mode, task?.taskId ?? null, 'ORCHESTRATED_COMMIT_REMOVED', 'Orchestrated commit is no longer a lifecycle stage; use local checkpoint delivery from code-task', 'blocked', inspected.snapshot);
|
|
192
183
|
const branch = inspected.snapshot.branch;
|
|
193
184
|
const commonError = validateCommon(input, branch);
|
|
194
185
|
if (commonError)
|
|
@@ -380,13 +371,13 @@ function executeCommitOperationCore(input, task, mode) {
|
|
|
380
371
|
}
|
|
381
372
|
if (task && (committed.status === 'applied' || committed.status === 'no-op')) {
|
|
382
373
|
const committedHead = checkpointCommittedHead ?? committed.snapshot?.head ?? gitText(task.repoRoot, ['rev-parse', 'HEAD']);
|
|
383
|
-
const taskWarning = syncTaskCommit(input, task, committedHead);
|
|
374
|
+
const taskWarning = syncTaskCommit(input, task, committedHead, writeOptions);
|
|
384
375
|
if (taskWarning) {
|
|
385
376
|
warnings.push(taskWarning);
|
|
386
377
|
status = 'applied';
|
|
387
378
|
result = 'committed_with_warnings';
|
|
388
379
|
}
|
|
389
|
-
if (delivery.mode === 'local' &&
|
|
380
|
+
if (delivery.mode === 'local' && taskWarning?.code !== 'TASK_STATUS_SYNC_FAILED' && pendingIntent && checkpointCommittedHead) {
|
|
390
381
|
const synced = updateCheckpointIntent(pendingIntent, {
|
|
391
382
|
state: 'synced', committedHead: checkpointCommittedHead, updatedAt: checkpointTimestamp()
|
|
392
383
|
});
|
|
@@ -406,7 +397,7 @@ function executeCommitOperationCore(input, task, mode) {
|
|
|
406
397
|
error: null
|
|
407
398
|
};
|
|
408
399
|
}
|
|
409
|
-
function executeCommitOperation(input) {
|
|
400
|
+
function executeCommitOperation(input, writeOptions = {}) {
|
|
410
401
|
if (input.mode !== undefined && !isCommitExecutionMode(input.mode))
|
|
411
402
|
return {
|
|
412
403
|
status: 'blocked',
|
|
@@ -417,7 +408,7 @@ function executeCommitOperation(input) {
|
|
|
417
408
|
warnings: [],
|
|
418
409
|
snapshot: null,
|
|
419
410
|
operations: [],
|
|
420
|
-
error: { code: 'COMMIT_MODE_INVALID', message: 'commit mode must be direct
|
|
411
|
+
error: { code: 'COMMIT_MODE_INVALID', message: 'commit mode must be direct' }
|
|
421
412
|
};
|
|
422
413
|
const mode = input.mode ?? 'direct';
|
|
423
414
|
let normalizedInput;
|
|
@@ -431,10 +422,8 @@ function executeCommitOperation(input) {
|
|
|
431
422
|
if (resolved.kind === 'error')
|
|
432
423
|
return resolved.result;
|
|
433
424
|
const task = resolved.kind === 'bound' ? resolved.task : null;
|
|
434
|
-
if (mode === 'orchestrated' && !task)
|
|
435
|
-
return failure(normalizedInput, mode, null, 'ORCHESTRATION_TASK_REQUIRED', 'orchestrated commit requires a task context', 'blocked');
|
|
436
425
|
try {
|
|
437
|
-
return executeCommitOperationCore(normalizedInput, task, mode);
|
|
426
|
+
return executeCommitOperationCore(normalizedInput, task, mode, writeOptions);
|
|
438
427
|
}
|
|
439
428
|
catch (error) {
|
|
440
429
|
const code = 'COMMIT_OPERATION_FAILED';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
2
3
|
import { canonicalSemanticDigest } from './artifact-operations.js';
|
|
3
|
-
import { inspectActivityLog, pairEntries } from './activity-log.js';
|
|
4
4
|
import { parseTypedTaskFrontmatter } from './frontmatter.js';
|
|
5
5
|
import { parseArtifactName } from './artifact-name.js';
|
|
6
6
|
import { sha256File } from './artifact-receipts.js';
|
|
@@ -23,56 +23,69 @@ export function parseCompletionFacts(value) {
|
|
|
23
23
|
return [];
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
function completionEvent(family) {
|
|
27
|
+
if (family === 'validation-run')
|
|
28
|
+
return 'validation-run.completed';
|
|
29
|
+
if (family === 'analysis')
|
|
30
|
+
return 'analyze.completed';
|
|
31
|
+
if (family === 'review-analysis')
|
|
32
|
+
return 'review-analysis.completed';
|
|
33
|
+
if (family === 'plan')
|
|
34
|
+
return 'plan.completed';
|
|
35
|
+
if (family === 'review-plan')
|
|
36
|
+
return 'review-plan.completed';
|
|
37
|
+
if (family === 'code')
|
|
38
|
+
return 'code.completed';
|
|
39
|
+
if (family === 'review-code')
|
|
40
|
+
return 'review-code.completed';
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
/** Validates an artifact's own completion fact and output evidence. */
|
|
44
|
+
export function hasValidArtifactCompletion(taskContent, taskDir, artifact, event) {
|
|
27
45
|
try {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
const content = fs.readFileSync(artifactPath, 'utf8');
|
|
31
|
-
const outputSha256 = sha256File(artifactPath);
|
|
32
|
-
const semanticDigest = canonicalSemanticDigest(content);
|
|
33
|
-
return parseCompletionFacts(frontmatter.completion_facts).some((fact) => fact.event === event && fact.output === output
|
|
34
|
-
&& fact.outputSha256 === outputSha256 && fact.semanticDigest === semanticDigest
|
|
35
|
-
&& fact.requestId.length > 0);
|
|
46
|
+
const fact = findCompletionFact(taskContent, artifact, event);
|
|
47
|
+
return Boolean(fact && validateOutput(taskDir, artifact, fact));
|
|
36
48
|
}
|
|
37
49
|
catch {
|
|
38
50
|
return false;
|
|
39
51
|
}
|
|
40
52
|
}
|
|
41
|
-
|
|
42
|
-
|
|
53
|
+
/** Distinguishes an invalidated completion fact from a round that has never completed. */
|
|
54
|
+
export function hasArtifactCompletionRecord(taskContent, artifact, event) {
|
|
55
|
+
try {
|
|
56
|
+
const raw = parseTypedTaskFrontmatter(taskContent).completion_facts;
|
|
57
|
+
if (raw === undefined)
|
|
58
|
+
return false;
|
|
59
|
+
if (typeof raw !== 'string')
|
|
60
|
+
return true;
|
|
61
|
+
if (raw.trim() === '')
|
|
62
|
+
return false;
|
|
63
|
+
const parsed = JSON.parse(raw);
|
|
64
|
+
if (!Array.isArray(parsed))
|
|
65
|
+
return true;
|
|
66
|
+
return parsed.some((fact) => fact && typeof fact === 'object' && !Array.isArray(fact)
|
|
67
|
+
&& fact.event === event
|
|
68
|
+
&& fact.output === artifact);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
43
73
|
}
|
|
44
|
-
|
|
45
|
-
export function artifactCompletionOrder(taskContent, artifact, event) {
|
|
74
|
+
function findCompletionFact(taskContent, artifact, event) {
|
|
46
75
|
const identity = parseArtifactName(artifact);
|
|
47
|
-
if (!identity)
|
|
76
|
+
if (!identity || completionEvent(identity.family) !== event)
|
|
48
77
|
return null;
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
: family === 'code' ? 'Code Task' : 'Review Code';
|
|
62
|
-
const { section, invalidEntries } = inspectActivityLog(taskContent);
|
|
63
|
-
if (!section || invalidEntries.length > 0)
|
|
64
|
-
return null;
|
|
65
|
-
const ordered = section.entries.map((entry, sourceOrder) => ({ entry, sourceOrder }))
|
|
66
|
-
.sort((left, right) => Date.parse(left.entry.time.replace(' ', 'T')) - Date.parse(right.entry.time.replace(' ', 'T')) || left.sourceOrder - right.sourceOrder);
|
|
67
|
-
const entries = ordered.map(({ entry }) => entry);
|
|
68
|
-
const roundPattern = new RegExp(`^${action} \\(Round ${identity.round}(?:, [^)]+)?\\)$`);
|
|
69
|
-
const row = pairEntries(entries).find((candidate) => candidate.started !== ''
|
|
70
|
-
&& candidate.done !== '' && roundPattern.test(candidate.step)
|
|
71
|
-
&& candidate.note.includes(`→ ${artifact}`));
|
|
72
|
-
if (!row)
|
|
73
|
-
return null;
|
|
74
|
-
const doneIndex = ordered.findIndex(({ entry }) => entry.time === row.done
|
|
75
|
-
&& entry.step === row.step && entry.note === row.note);
|
|
76
|
-
return doneIndex < 0 ? null : doneIndex;
|
|
78
|
+
const fact = parseCompletionFacts(parseTypedTaskFrontmatter(taskContent).completion_facts)
|
|
79
|
+
.find((candidate) => candidate.event === event && candidate.output === artifact);
|
|
80
|
+
return fact && fact.requestId.length > 0 ? fact : null;
|
|
81
|
+
}
|
|
82
|
+
function validateOutput(taskDir, artifact, fact) {
|
|
83
|
+
const outputPath = path.join(taskDir, artifact);
|
|
84
|
+
const stat = fs.lstatSync(outputPath);
|
|
85
|
+
if (!stat.isFile() || stat.isSymbolicLink())
|
|
86
|
+
return false;
|
|
87
|
+
const content = fs.readFileSync(outputPath, 'utf8');
|
|
88
|
+
return sha256File(outputPath) === fact.outputSha256
|
|
89
|
+
&& canonicalSemanticDigest(content) === fact.semanticDigest;
|
|
77
90
|
}
|
|
78
91
|
//# sourceMappingURL=completion-facts.js.map
|
|
@@ -1,24 +1,12 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { normalizeAgentToken } from '../agent-clients/tokens.js';
|
|
4
|
-
import { isAgentClientId } from '../agent-clients/types.js';
|
|
5
4
|
import { sandboxControlPaths } from '../sandbox/workspace-view.js';
|
|
6
|
-
import { getAgentClientAdapter } from '../agent-clients/registry.js';
|
|
7
|
-
import { activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, advanceOrchestration, awaitOrchestrationDelegationActivation, beginOrResumeOrchestration, dispatchOrchestrationDelegation, OrchestrationStateError, pauseOrchestration, prepareOrchestrationDelegation, recoverPreparedOrchestrationDelegation, routeOrchestration, sealMatchingOrchestrationDelegation, sealOrchestrationDelegation, statusOrchestration } from './orchestration.js';
|
|
8
5
|
import { applyTaskFinalization } from './finalization.js';
|
|
9
6
|
import { applyTaskLifecycle } from './lifecycle.js';
|
|
10
|
-
import {
|
|
7
|
+
import { resolveTaskRef, TASK_ID_RE } from './resolve-ref.js';
|
|
11
8
|
import { verifyTaskEvent } from './verification.js';
|
|
12
9
|
import { releaseStaleShortIdRegistry } from './short-id.js';
|
|
13
|
-
export function taskControlOperationKey(operation) {
|
|
14
|
-
if (operation.family === 'task-finalization')
|
|
15
|
-
return 'complete';
|
|
16
|
-
if (operation.family === 'task-lifecycle')
|
|
17
|
-
return operation.request.intent;
|
|
18
|
-
return operation.intent === 'route'
|
|
19
|
-
? operation.input && operation.input.completed === true ? 'route.clean-completion' : 'route.read'
|
|
20
|
-
: operation.intent;
|
|
21
|
-
}
|
|
22
10
|
function invalidContext(message) {
|
|
23
11
|
throw new Error(`TASK_CONTROL_CONTEXT_INVALID: ${message}`);
|
|
24
12
|
}
|
|
@@ -85,20 +73,6 @@ export function assertTaskControlExecutionContext(context) {
|
|
|
85
73
|
function boundTaskRef(context, taskRef) {
|
|
86
74
|
return context.source === 'sandbox-executor' ? context.taskId : taskRef;
|
|
87
75
|
}
|
|
88
|
-
function autoTaskOptions(context, options) {
|
|
89
|
-
if (context.source === 'sandbox-executor')
|
|
90
|
-
return { ...options, taskId: context.taskId };
|
|
91
|
-
const resolved = resolveTaskContext(undefined, { repoRoot: context.repoRoot });
|
|
92
|
-
if (!resolved.ok)
|
|
93
|
-
throw new Error(`${resolved.code}: ${resolved.message}`);
|
|
94
|
-
return { ...options, taskId: resolved.taskId };
|
|
95
|
-
}
|
|
96
|
-
function domainOptions(context, options) {
|
|
97
|
-
return {
|
|
98
|
-
...options,
|
|
99
|
-
repoRoot: context.repoRoot
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
76
|
function lifecycleTaskId(request, repoRoot) {
|
|
103
77
|
if (request.intent === 'restore')
|
|
104
78
|
return TASK_ID_RE.test(request.taskRef) ? request.taskRef : null;
|
|
@@ -114,19 +88,6 @@ async function applyLifecycleWithAuthority(context, request) {
|
|
|
114
88
|
const taskId = lifecycleTaskId(request, context.repoRoot);
|
|
115
89
|
const controlRoot = taskId ? controlRootForTask(context, taskId) : undefined;
|
|
116
90
|
const execute = async () => {
|
|
117
|
-
if (request.intent === 'recover-started') {
|
|
118
|
-
const adapter = isAgentClientId(request.agent)
|
|
119
|
-
? getAgentClientAdapter(request.agent).orchestrationAdapter
|
|
120
|
-
: undefined;
|
|
121
|
-
if (!adapter?.recoverStarted) {
|
|
122
|
-
return {
|
|
123
|
-
status: 'no-op', changed: false, targetState: 'active',
|
|
124
|
-
requestRef: request.taskRef, intent: 'recover-started', taskId: null,
|
|
125
|
-
receiptId: null, childId: null, error: null
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
return adapter.recoverStarted(request, { repoRoot: context.repoRoot });
|
|
129
|
-
}
|
|
130
91
|
return applyTaskLifecycle(request, {
|
|
131
92
|
repoRoot: context.repoRoot,
|
|
132
93
|
...(controlRoot ? { controlRoot } : {}),
|
|
@@ -147,62 +108,6 @@ function controlRootForTask(context, taskId) {
|
|
|
147
108
|
identity: { mode: 'task-bound', taskId }
|
|
148
109
|
}).root;
|
|
149
110
|
}
|
|
150
|
-
function orchestration(context, operation) {
|
|
151
|
-
const taskRef = boundTaskRef(context, operation.taskRef);
|
|
152
|
-
const input = operation.input;
|
|
153
|
-
const options = domainOptions(context, operation.options);
|
|
154
|
-
switch (operation.intent) {
|
|
155
|
-
case 'begin-or-resume':
|
|
156
|
-
return beginOrResumeOrchestration(taskRef, {
|
|
157
|
-
...options,
|
|
158
|
-
client: input.client,
|
|
159
|
-
maxSteps: input.maxSteps,
|
|
160
|
-
modelPolicy: input.modelPolicy
|
|
161
|
-
});
|
|
162
|
-
case 'route': return routeOrchestration(taskRef, options);
|
|
163
|
-
case 'status': return statusOrchestration(taskRef, options);
|
|
164
|
-
case 'prepare': return prepareTaskOrchestration(context, { ...operation, taskRef }, options);
|
|
165
|
-
case 'dispatch': return dispatchOrchestrationDelegation(taskRef, options);
|
|
166
|
-
case 'await-activation':
|
|
167
|
-
return awaitOrchestrationDelegationActivation(taskRef, input.event, options);
|
|
168
|
-
case 'recover-prepared': return recoverPreparedOrchestrationDelegation(taskRef, options);
|
|
169
|
-
case 'hook-start':
|
|
170
|
-
return input.auto === true
|
|
171
|
-
? activateMatchingOrchestrationDelegation(input.client, input.event, autoTaskOptions(context, options))
|
|
172
|
-
: activateOrchestrationDelegation(taskRef, input.event, options);
|
|
173
|
-
case 'hook-stop':
|
|
174
|
-
return input.auto === true
|
|
175
|
-
? sealMatchingOrchestrationDelegation(input.client, input.event, autoTaskOptions(context, options))
|
|
176
|
-
: sealOrchestrationDelegation(taskRef, input.event, undefined, options);
|
|
177
|
-
case 'advance': return advanceOrchestration(taskRef, options);
|
|
178
|
-
case 'pause':
|
|
179
|
-
return pauseOrchestration(taskRef, input.code, input.message, input.recoverable, options);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
function prepareTaskOrchestration(context, operation, options) {
|
|
183
|
-
const input = operation.input;
|
|
184
|
-
const prepareInput = {
|
|
185
|
-
client: input.client,
|
|
186
|
-
requestedModel: input.requestedModel,
|
|
187
|
-
requestedReasoningEffort: input.requestedReasoningEffort,
|
|
188
|
-
};
|
|
189
|
-
const prepareDelegation = getAgentClientAdapter(prepareInput.client).orchestrationAdapter?.prepareDelegation;
|
|
190
|
-
return prepareDelegation
|
|
191
|
-
? prepareDelegation(operation.taskRef, prepareInput, {
|
|
192
|
-
repoRoot: context.repoRoot,
|
|
193
|
-
orchestrationOptions: options,
|
|
194
|
-
})
|
|
195
|
-
: prepareOrchestrationDelegation(operation.taskRef, prepareInput, options);
|
|
196
|
-
}
|
|
197
|
-
function orchestrationFailure(error) {
|
|
198
|
-
if (error instanceof OrchestrationStateError) {
|
|
199
|
-
return {
|
|
200
|
-
status: 'failed', changed: false, taskId: error.taskId, run: null, next: null,
|
|
201
|
-
error: { code: error.code, message: error.message }
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
throw error;
|
|
205
|
-
}
|
|
206
111
|
export function dispatchTaskControlOperation(context, operation) {
|
|
207
112
|
assertTaskControlExecutionContext(context);
|
|
208
113
|
assertTaskControlOperation(operation);
|
|
@@ -253,13 +158,7 @@ export function dispatchTaskControlOperation(context, operation) {
|
|
|
253
158
|
}
|
|
254
159
|
});
|
|
255
160
|
}
|
|
256
|
-
|
|
257
|
-
const result = orchestration(context, operation);
|
|
258
|
-
return result instanceof Promise ? result.catch(orchestrationFailure) : result;
|
|
259
|
-
}
|
|
260
|
-
catch (error) {
|
|
261
|
-
return orchestrationFailure(error);
|
|
262
|
-
}
|
|
161
|
+
throw new Error('TASK_CONTROL_OPERATION_INVALID: unsupported operation family');
|
|
263
162
|
}
|
|
264
163
|
export function assertTaskControlOperation(operation) {
|
|
265
164
|
if (operation.family === 'task-lifecycle') {
|
|
@@ -274,31 +173,20 @@ export function assertTaskControlOperation(operation) {
|
|
|
274
173
|
}
|
|
275
174
|
return;
|
|
276
175
|
}
|
|
277
|
-
if (!operation.taskRef || !operation.intent || !operation.input || typeof operation.input !== 'object' || Array.isArray(operation.input)) {
|
|
278
|
-
throw new Error('TASK_CONTROL_OPERATION_INVALID: orchestration operation is invalid');
|
|
279
|
-
}
|
|
280
176
|
}
|
|
281
177
|
function operationInvalid(message) {
|
|
282
178
|
throw new Error(`TASK_CONTROL_OPERATION_INVALID: ${message}`);
|
|
283
179
|
}
|
|
284
180
|
const LIFECYCLE_FLAGS = new Set([
|
|
285
181
|
'--agent', '--reason', '--unblock-condition', '--note', '--alert-number', '--staging-dir', '--issue-number',
|
|
286
|
-
'--
|
|
182
|
+
'--dry-run'
|
|
287
183
|
]);
|
|
288
184
|
const FINALIZATION_FLAGS = new Set(['--agent']);
|
|
289
|
-
const ORCHESTRATION_FLAGS = new Set([
|
|
290
|
-
'--agent', '--max-steps', '--executor-model', '--executor-reasoning-effort', '--reviewer-model',
|
|
291
|
-
'--reviewer-reasoning-effort', '--client', '--requested-model', '--requested-reasoning-effort',
|
|
292
|
-
'--parent-id', '--before-fingerprint', '--stage', '--round', '--artifact', '--role',
|
|
293
|
-
'--native-agent', '--child-id', '--spawn-mode', '--actual-model', '--actual-reasoning-effort',
|
|
294
|
-
'--model-fallback-reason', '--reasoning-effort-fallback-reason', '--exit-code', '--after-fingerprint',
|
|
295
|
-
'--changed-paths', '--code', '--message', '--recoverable'
|
|
296
|
-
]);
|
|
297
185
|
function parseValues(args, start, flags) {
|
|
298
186
|
const values = {};
|
|
299
187
|
for (let index = start; index < args.length; index += 1) {
|
|
300
188
|
const flag = args[index];
|
|
301
|
-
if (flag === '--dry-run'
|
|
189
|
+
if (flag === '--dry-run') {
|
|
302
190
|
if (!flags.has(flag))
|
|
303
191
|
operationInvalid(`unknown option '${flag}'`);
|
|
304
192
|
if (values[flag] !== undefined)
|
|
@@ -321,11 +209,6 @@ function value(values, flag) {
|
|
|
321
209
|
const current = values[flag];
|
|
322
210
|
return typeof current === 'string' ? current : undefined;
|
|
323
211
|
}
|
|
324
|
-
function required(values, flags) {
|
|
325
|
-
const missing = flags.find((flag) => value(values, flag) === undefined);
|
|
326
|
-
if (missing)
|
|
327
|
-
operationInvalid(`option '${missing}' is required`);
|
|
328
|
-
}
|
|
329
212
|
export function parseTaskControlOperation(family, args) {
|
|
330
213
|
if (family === 'task-finalization') {
|
|
331
214
|
if (args.length !== 4 || args[1] !== 'complete' || args[2] !== '--agent' || !args[0] || !args[3]) {
|
|
@@ -341,140 +224,24 @@ export function parseTaskControlOperation(family, args) {
|
|
|
341
224
|
operationInvalid('task ref and intent are required');
|
|
342
225
|
const taskRef = args[0];
|
|
343
226
|
const intent = args[1];
|
|
344
|
-
if (
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
};
|
|
364
|
-
if (intent === 'recover-started') {
|
|
365
|
-
const recoveryFlags = new Set(['--agent', '--auto']);
|
|
366
|
-
for (const flag of Object.keys(values)) {
|
|
367
|
-
if (!recoveryFlags.has(flag))
|
|
368
|
-
operationInvalid(`option '${flag}' is not supported for recover-started`);
|
|
369
|
-
}
|
|
370
|
-
if (values['--auto'] !== true)
|
|
371
|
-
operationInvalid('--auto is required for recover-started');
|
|
372
|
-
return { family, request: input };
|
|
373
|
-
}
|
|
374
|
-
else if (values['--auto'] !== undefined) {
|
|
375
|
-
operationInvalid('--auto is only supported for recover-started');
|
|
376
|
-
}
|
|
377
|
-
return { family, request: input };
|
|
378
|
-
}
|
|
379
|
-
const values = parseValues(args, 2, ORCHESTRATION_FLAGS);
|
|
380
|
-
const orchestrationIntents = new Set([
|
|
381
|
-
'begin-or-resume', 'route', 'prepare', 'dispatch', 'await-activation', 'recover-prepared',
|
|
382
|
-
'hook-start', 'hook-stop', 'advance', 'pause', 'status'
|
|
383
|
-
]);
|
|
384
|
-
if (!orchestrationIntents.has(intent)) {
|
|
385
|
-
operationInvalid(`unknown orchestration intent '${intent}'`);
|
|
386
|
-
}
|
|
387
|
-
const client = value(values, '--client');
|
|
388
|
-
if (client !== undefined && !isAgentClientId(client))
|
|
389
|
-
operationInvalid(`unknown client '${client}'`);
|
|
390
|
-
const parsedIntent = intent;
|
|
391
|
-
const input = {};
|
|
392
|
-
if (parsedIntent === 'begin-or-resume' || parsedIntent === 'prepare') {
|
|
393
|
-
required(values, ['--client']);
|
|
394
|
-
if (!client || !isAgentClientId(client))
|
|
395
|
-
operationInvalid(`unknown client '${client ?? ''}'`);
|
|
396
|
-
input.client = client;
|
|
397
|
-
}
|
|
398
|
-
if (parsedIntent === 'begin-or-resume') {
|
|
399
|
-
const maxSteps = value(values, '--max-steps');
|
|
400
|
-
if (maxSteps !== undefined) {
|
|
401
|
-
const parsed = Number(maxSteps);
|
|
402
|
-
if (!Number.isInteger(parsed) || parsed < 1)
|
|
403
|
-
operationInvalid('--max-steps must be a positive integer');
|
|
404
|
-
input.maxSteps = parsed;
|
|
405
|
-
}
|
|
406
|
-
const policyFlags = ['--executor-model', '--executor-reasoning-effort', '--reviewer-model', '--reviewer-reasoning-effort'];
|
|
407
|
-
const hasPolicy = policyFlags.some((flag) => value(values, flag) !== undefined);
|
|
408
|
-
if (hasPolicy && policyFlags.some((flag) => value(values, flag) === undefined)) {
|
|
409
|
-
operationInvalid('explicit model policy requires executor/reviewer model and reasoning effort');
|
|
410
|
-
}
|
|
411
|
-
if (hasPolicy) {
|
|
412
|
-
input.modelPolicy = {
|
|
413
|
-
executor: { model: value(values, '--executor-model'), reasoningEffort: value(values, '--executor-reasoning-effort') },
|
|
414
|
-
reviewer: { model: value(values, '--reviewer-model'), reasoningEffort: value(values, '--reviewer-reasoning-effort') }
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
if (parsedIntent === 'prepare') {
|
|
419
|
-
input.requestedModel = value(values, '--requested-model');
|
|
420
|
-
input.requestedReasoningEffort = value(values, '--requested-reasoning-effort');
|
|
421
|
-
}
|
|
422
|
-
if (parsedIntent === 'await-activation') {
|
|
423
|
-
required(values, ['--stage', '--round', '--artifact', '--role']);
|
|
424
|
-
const round = Number(value(values, '--round'));
|
|
425
|
-
if (!Number.isSafeInteger(round) || round < 1)
|
|
426
|
-
operationInvalid('--round must be a positive integer');
|
|
427
|
-
const role = value(values, '--role');
|
|
428
|
-
if (role !== 'executor' && role !== 'reviewer')
|
|
429
|
-
operationInvalid('--role must be executor or reviewer');
|
|
430
|
-
input.event = { stage: value(values, '--stage'), round, artifact: value(values, '--artifact'), role };
|
|
431
|
-
}
|
|
432
|
-
if (parsedIntent === 'hook-start') {
|
|
433
|
-
required(values, ['--native-agent', '--child-id', '--parent-id']);
|
|
434
|
-
if (taskRef === 'auto')
|
|
435
|
-
required(values, ['--client']);
|
|
436
|
-
input.auto = taskRef === 'auto';
|
|
437
|
-
input.client = value(values, '--client');
|
|
438
|
-
input.event = {
|
|
439
|
-
nativeAgent: value(values, '--native-agent'), childId: value(values, '--child-id'), parentId: value(values, '--parent-id'),
|
|
440
|
-
spawnMode: value(values, '--spawn-mode'), actualModel: value(values, '--actual-model'),
|
|
441
|
-
actualReasoningEffort: value(values, '--actual-reasoning-effort'), modelFallbackReason: value(values, '--model-fallback-reason'),
|
|
442
|
-
reasoningEffortFallbackReason: value(values, '--reasoning-effort-fallback-reason')
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
if (parsedIntent === 'hook-stop') {
|
|
446
|
-
input.auto = taskRef === 'auto';
|
|
447
|
-
if (input.auto) {
|
|
448
|
-
required(values, ['--client', '--native-agent', '--child-id']);
|
|
449
|
-
input.client = value(values, '--client');
|
|
450
|
-
input.event = {
|
|
451
|
-
nativeAgent: value(values, '--native-agent'), childId: value(values, '--child-id'), actualModel: value(values, '--actual-model'),
|
|
452
|
-
actualReasoningEffort: value(values, '--actual-reasoning-effort'), modelFallbackReason: value(values, '--model-fallback-reason'),
|
|
453
|
-
reasoningEffortFallbackReason: value(values, '--reasoning-effort-fallback-reason')
|
|
454
|
-
};
|
|
455
|
-
}
|
|
456
|
-
else {
|
|
457
|
-
required(values, ['--child-id', '--exit-code', '--after-fingerprint']);
|
|
458
|
-
const exitCode = Number(value(values, '--exit-code'));
|
|
459
|
-
if (!Number.isInteger(exitCode))
|
|
460
|
-
operationInvalid('--exit-code must be an integer');
|
|
461
|
-
input.event = {
|
|
462
|
-
childId: value(values, '--child-id'), exitCode, afterFingerprint: value(values, '--after-fingerprint'),
|
|
463
|
-
changedPaths: value(values, '--changed-paths')?.split(',').filter(Boolean) ?? [], actualModel: value(values, '--actual-model'),
|
|
464
|
-
actualReasoningEffort: value(values, '--actual-reasoning-effort'), modelFallbackReason: value(values, '--model-fallback-reason'),
|
|
465
|
-
reasoningEffortFallbackReason: value(values, '--reasoning-effort-fallback-reason')
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
if (parsedIntent === 'pause') {
|
|
470
|
-
required(values, ['--code', '--message', '--recoverable']);
|
|
471
|
-
const recoverable = value(values, '--recoverable');
|
|
472
|
-
if (recoverable !== 'true' && recoverable !== 'false')
|
|
473
|
-
operationInvalid('--recoverable must be true or false');
|
|
474
|
-
input.code = value(values, '--code');
|
|
475
|
-
input.message = value(values, '--message');
|
|
476
|
-
input.recoverable = recoverable === 'true';
|
|
477
|
-
}
|
|
478
|
-
return { family, taskRef, intent: parsedIntent, input };
|
|
227
|
+
if (intent === 'complete')
|
|
228
|
+
operationInvalid('complete must use task-finalization');
|
|
229
|
+
const values = parseValues(args, 2, LIFECYCLE_FLAGS);
|
|
230
|
+
const agent = normalizeAgentToken(value(values, '--agent') ?? '');
|
|
231
|
+
if (!agent)
|
|
232
|
+
operationInvalid('lifecycle agent is invalid');
|
|
233
|
+
const request = {
|
|
234
|
+
taskRef,
|
|
235
|
+
intent,
|
|
236
|
+
agent,
|
|
237
|
+
...(value(values, '--reason') ? { reason: value(values, '--reason') } : {}),
|
|
238
|
+
...(value(values, '--unblock-condition') ? { unblockCondition: value(values, '--unblock-condition') } : {}),
|
|
239
|
+
...(value(values, '--note') ? { note: value(values, '--note') } : {}),
|
|
240
|
+
...(value(values, '--staging-dir') ? { stagingDir: value(values, '--staging-dir') } : {}),
|
|
241
|
+
...(value(values, '--alert-number') ? { alertNumber: Number(value(values, '--alert-number')) } : {}),
|
|
242
|
+
...(value(values, '--issue-number') ? { issueNumber: Number(value(values, '--issue-number')) } : {}),
|
|
243
|
+
...(values['--dry-run'] === true ? { dryRun: true } : {})
|
|
244
|
+
};
|
|
245
|
+
return { family, request: request };
|
|
479
246
|
}
|
|
480
247
|
//# sourceMappingURL=control-authority.js.map
|
|
@@ -16,7 +16,7 @@ export function parseControlOutput(output) {
|
|
|
16
16
|
export const SANDBOX_CONTROL_REQUIRED_COMPLETION_PHASES = Object.freeze([
|
|
17
17
|
'completed', 'evidence-written', 'publish-authorized'
|
|
18
18
|
]);
|
|
19
|
-
const LIFECYCLE_INTENTS = ['block', 'activate', 'cancel', 'close-codescan', 'close-dependabot', 'restore'
|
|
19
|
+
const LIFECYCLE_INTENTS = ['block', 'activate', 'cancel', 'close-codescan', 'close-dependabot', 'restore'];
|
|
20
20
|
export const SANDBOX_CONTROL_RECOVERY_OPERATIONS = Object.freeze([
|
|
21
21
|
...LIFECYCLE_INTENTS.map((intent) => ({ family: 'task-lifecycle', intent, class: 'lifecycle-mutation' })),
|
|
22
22
|
{ family: 'task-create', intent: 'create', class: 'task-create' }
|
|
@@ -33,13 +33,11 @@ function bindingMatchesResult(binding, result) {
|
|
|
33
33
|
&& (result.taskId === undefined || result.taskId === binding.taskId)
|
|
34
34
|
&& (result.intentDigest === undefined || result.intentDigest === binding.intentDigest);
|
|
35
35
|
}
|
|
36
|
-
function domainEvidenceMatches(
|
|
36
|
+
function domainEvidenceMatches(domain) {
|
|
37
37
|
if (!domain)
|
|
38
38
|
return false;
|
|
39
39
|
if (domain.consistent !== true)
|
|
40
40
|
return false;
|
|
41
|
-
if (operation.family === 'task-lifecycle' && operation.intent === 'recover-started')
|
|
42
|
-
return false;
|
|
43
41
|
return true;
|
|
44
42
|
}
|
|
45
43
|
export function classifySandboxControlRecovery(input) {
|
|
@@ -71,7 +69,7 @@ export function classifySandboxControlRecovery(input) {
|
|
|
71
69
|
if (result.changed === null) {
|
|
72
70
|
return { outcome: 'unknown', responseReconstructable: false, reasonCode: 'RECOVERY_RESULT_CHANGE_FLAG_MISSING' };
|
|
73
71
|
}
|
|
74
|
-
if (!domainEvidenceMatches(input.
|
|
72
|
+
if (!domainEvidenceMatches(input.domain)) {
|
|
75
73
|
if (input.journal?.exists && (input.journal.completedSteps?.length ?? 0) > 0) {
|
|
76
74
|
return { outcome: 'in-progress', responseReconstructable: false, reasonCode: 'RECOVERY_DOMAIN_EVIDENCE_INCOMPLETE' };
|
|
77
75
|
}
|