@fitlab-ai/agent-infra 0.9.5 → 0.9.7
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/dist/bin/internal-cli.js +8 -3
- package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +171 -20
- package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +162 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +244 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +14 -2
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +370 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +68 -8
- package/dist/lib/agent-clients/adapters/codex.js +1 -1
- package/dist/lib/defaults.json +10 -2
- package/dist/lib/git/workflow.js +30 -4
- package/dist/lib/internal/codex-lifecycle.js +169 -3
- package/dist/lib/internal/codex-sandbox-controller.js +106 -0
- package/dist/lib/internal/release-workflow.js +108 -11
- package/dist/lib/internal/sandbox-control.js +43 -6
- package/dist/lib/internal/task-create.js +12 -4
- package/dist/lib/internal/task-orchestration.js +40 -7
- package/dist/lib/platform/context.js +6 -4
- package/dist/lib/platform/github-client.js +55 -2
- package/dist/lib/platform/issue-comments.js +2 -1
- package/dist/lib/process-data/checkpoint.js +319 -0
- package/dist/lib/process-data/index.js +128 -60
- package/dist/lib/process-data/materialize.js +84 -0
- package/dist/lib/process-data/normalize.js +34 -1
- package/dist/lib/process-data/reconcile.js +55 -1
- package/dist/lib/process-data/sources.js +422 -1
- package/dist/lib/process-data/store.js +341 -11
- package/dist/lib/release/workflow.js +29 -21
- package/dist/lib/sandbox/commands/create.js +111 -60
- package/dist/lib/sandbox/commands/prune.js +40 -16
- package/dist/lib/sandbox/commands/rm.js +372 -94
- package/dist/lib/sandbox/commands/start.js +4 -3
- package/dist/lib/sandbox/control/client.js +138 -22
- package/dist/lib/sandbox/control/container-identity.js +64 -0
- package/dist/lib/sandbox/control/executor.js +142 -0
- package/dist/lib/sandbox/control/lifecycle.js +557 -0
- package/dist/lib/sandbox/control/protocol.js +69 -26
- package/dist/lib/sandbox/control/server.js +395 -99
- package/dist/lib/sandbox/control/state.js +191 -0
- package/dist/lib/sandbox/control/timing.js +8 -0
- package/dist/lib/sandbox/index.js +2 -2
- package/dist/lib/sandbox/managed-fs.js +14 -2
- package/dist/lib/sandbox/mounts.js +22 -19
- package/dist/lib/sandbox/recovery.js +284 -50
- package/dist/lib/sandbox/workspace-view.js +90 -10
- package/dist/lib/sandbox/worktree-safety.js +196 -0
- package/dist/lib/server/daemon.js +1 -1
- package/dist/lib/server/process-control.js +17 -1
- package/dist/lib/server/process-state.js +57 -20
- package/dist/lib/task/artifact-lifecycle.js +87 -15
- package/dist/lib/task/artifact-receipts.js +128 -0
- package/dist/lib/task/codex-orchestration.js +236 -0
- package/dist/lib/task/commands/status.js +3 -0
- package/dist/lib/task/commands/validate.js +289 -0
- package/dist/lib/task/commit-finalization.js +36 -9
- package/dist/lib/task/create.js +10 -2
- package/dist/lib/task/delegation-receipts.js +109 -2
- package/dist/lib/task/events.js +149 -6
- package/dist/lib/task/finalization-artifacts.js +2 -1
- package/dist/lib/task/implementation-inputs.js +1 -7
- package/dist/lib/task/index.js +9 -0
- package/dist/lib/task/ledger.js +13 -1
- package/dist/lib/task/orchestration.js +365 -15
- package/dist/lib/task/sections.js +5 -1
- package/dist/lib/task/task-execution-lock.js +5 -4
- package/dist/lib/task/verification-engine.js +78 -14
- package/dist/lib/task/verification.js +1 -0
- package/dist/lifecycle-build-manifest.json +6 -0
- package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +202 -18
- package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +227 -0
- package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +321 -0
- package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +19 -3
- package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +26 -0
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +453 -0
- package/lib/agent-clients/adapters/codex-lifecycle/store.ts +83 -6
- package/lib/agent-clients/adapters/codex.ts +1 -1
- package/lib/defaults.json +10 -2
- package/lib/git/workflow.ts +25 -3
- package/lib/internal/codex-lifecycle.ts +175 -4
- package/lib/internal/codex-sandbox-controller.ts +109 -0
- package/lib/internal/release-workflow.ts +107 -11
- package/lib/internal/sandbox-control.ts +38 -6
- package/lib/internal/task-create.ts +16 -4
- package/lib/internal/task-orchestration.ts +34 -7
- package/lib/platform/context.ts +8 -5
- package/lib/platform/github-client.ts +61 -3
- package/lib/platform/issue-comments.ts +2 -1
- package/lib/process-data/checkpoint.ts +335 -0
- package/lib/process-data/index.ts +112 -60
- package/lib/process-data/materialize.ts +83 -0
- package/lib/process-data/normalize.ts +29 -1
- package/lib/process-data/reconcile.ts +64 -2
- package/lib/process-data/sources.ts +449 -2
- package/lib/process-data/store.ts +304 -11
- package/lib/process-data/types.ts +124 -2
- package/lib/release/workflow.ts +69 -20
- package/lib/sandbox/commands/create.ts +70 -25
- package/lib/sandbox/commands/prune.ts +53 -15
- package/lib/sandbox/commands/rm.ts +423 -108
- package/lib/sandbox/commands/start.ts +4 -3
- package/lib/sandbox/control/client.ts +152 -28
- package/lib/sandbox/control/container-identity.ts +93 -0
- package/lib/sandbox/control/executor.ts +167 -0
- package/lib/sandbox/control/lifecycle.ts +573 -0
- package/lib/sandbox/control/protocol.ts +121 -68
- package/lib/sandbox/control/server.ts +398 -109
- package/lib/sandbox/control/state.ts +213 -0
- package/lib/sandbox/control/timing.ts +12 -0
- package/lib/sandbox/index.ts +2 -2
- package/lib/sandbox/managed-fs.ts +17 -2
- package/lib/sandbox/mounts.ts +16 -8
- package/lib/sandbox/recovery.ts +335 -65
- package/lib/sandbox/workspace-view.ts +102 -11
- package/lib/sandbox/worktree-safety.ts +234 -0
- package/lib/server/daemon.ts +1 -1
- package/lib/server/process-control.ts +24 -3
- package/lib/server/process-state.ts +82 -27
- package/lib/task/artifact-lifecycle.ts +78 -14
- package/lib/task/artifact-receipts.ts +161 -0
- package/lib/task/codex-orchestration.ts +319 -0
- package/lib/task/commands/status.ts +2 -0
- package/lib/task/commands/validate.ts +282 -0
- package/lib/task/commit-finalization.ts +52 -9
- package/lib/task/create.ts +11 -2
- package/lib/task/delegation-receipts.ts +208 -7
- package/lib/task/events.ts +131 -5
- package/lib/task/finalization-artifacts.ts +2 -1
- package/lib/task/implementation-inputs.ts +1 -5
- package/lib/task/index.ts +8 -0
- package/lib/task/ledger.ts +16 -1
- package/lib/task/orchestration.ts +552 -18
- package/lib/task/sections.ts +6 -2
- package/lib/task/task-execution-lock.ts +11 -9
- package/lib/task/verification-engine.ts +93 -24
- package/lib/task/verification.ts +2 -1
- package/package.json +1 -1
- package/templates/.agents/README.en.md +7 -0
- package/templates/.agents/README.zh-CN.md +5 -0
- package/templates/.agents/hooks/lifecycle-delegation.js +72 -12
- package/templates/.agents/rules/lifecycle-orchestration.en.md +8 -2
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +8 -2
- package/templates/.agents/rules/no-mid-flow-questions.en.md +1 -0
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +1 -0
- package/templates/.agents/rules/pr-checks-commands.github.en.md +1 -1
- package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +1 -1
- package/templates/.agents/rules/review-handshake.en.md +3 -1
- package/templates/.agents/rules/review-handshake.zh-CN.md +3 -1
- package/templates/.agents/skills/code-task/reference/dual-mode.en.md +3 -1
- package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +3 -1
- package/templates/.agents/skills/complete-task/SKILL.en.md +4 -0
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +4 -0
- package/templates/.agents/skills/post-release/SKILL.en.md +32 -6
- package/templates/.agents/skills/post-release/SKILL.zh-CN.md +32 -6
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +42 -0
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +42 -0
- package/templates/.agents/skills/run-manual-validation/config/verify.en.json +25 -0
- package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +25 -0
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +67 -0
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +67 -0
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +69 -0
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +69 -0
- package/templates/.agents/skills/run-task/SKILL.en.md +9 -7
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +9 -7
- package/templates/.agents/skills/run-task/reference/host-validation.en.md +5 -3
- package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +5 -3
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +75 -3
- package/templates/.claude/commands/run-manual-validation.en.md +9 -0
- package/templates/.claude/commands/run-manual-validation.zh-CN.md +9 -0
- package/templates/.codex/hooks.json +8 -8
- package/templates/.opencode/commands/run-manual-validation.en.md +11 -0
- package/templates/.opencode/commands/run-manual-validation.zh-CN.md +11 -0
- package/templates/.agents/workspace/README.en.md +0 -26
- package/templates/.agents/workspace/README.zh-CN.md +0 -26
|
@@ -154,11 +154,47 @@ function inspectLocalReleaseFacts(cwd, version, run = command) {
|
|
|
154
154
|
const localTagConflict = Boolean(tagCommit && !localTag && !localTagAncestor);
|
|
155
155
|
const postSubject = `chore: prepare next dev iteration after v${version}`;
|
|
156
156
|
const postLog = localTag || localTagAncestor
|
|
157
|
-
? git(cwd, ['log', '--format=%s', `${tag}..HEAD`], run) ?? ''
|
|
157
|
+
? git(cwd, ['log', '--format=%H%x00%s', `${tag}..HEAD`], run) ?? ''
|
|
158
158
|
: '';
|
|
159
|
-
const postCommit = postLog.split('\n').
|
|
159
|
+
const postCommit = postLog.split('\n').map((line) => line.split('\0'))
|
|
160
|
+
.find(([, subject]) => subject === postSubject)?.[0] ?? null;
|
|
160
161
|
return { localTag, localTagAncestor, localTagConflict, postCommit };
|
|
161
162
|
}
|
|
163
|
+
function inspectPostReleaseFacts(cwd, commit, run = command) {
|
|
164
|
+
const inspected = inspectGitWorkflow(cwd);
|
|
165
|
+
const snapshot = inspected.snapshot;
|
|
166
|
+
const branch = snapshot?.branch ?? '';
|
|
167
|
+
const remoteLine = branch ? git(cwd, ['ls-remote', '--heads', 'origin', `refs/heads/${branch}`], run) : null;
|
|
168
|
+
const remoteHead = remoteLine?.split(/\s+/)[0] ?? null;
|
|
169
|
+
const packageJson = commit ? git(cwd, ['show', `${commit}:package.json`], run, false) : null;
|
|
170
|
+
let newVersion = null;
|
|
171
|
+
if (packageJson) {
|
|
172
|
+
try {
|
|
173
|
+
const version = JSON.parse(packageJson).version;
|
|
174
|
+
newVersion = typeof version === 'string' ? version : null;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
newVersion = null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const paths = commit ? git(cwd, ['diff-tree', '--root', '--no-commit-id', '--name-only', '-r', '-z', commit], run, false) : null;
|
|
181
|
+
const changedPaths = paths ? paths.split('\0').filter(Boolean)
|
|
182
|
+
.sort((left, right) => Buffer.from(left).compare(Buffer.from(right))) : [];
|
|
183
|
+
const digest = commit ? git(cwd, ['show', `${commit}:${DEMO_DIGEST_PATH}`], run) : null;
|
|
184
|
+
return {
|
|
185
|
+
commit,
|
|
186
|
+
isHead: Boolean(commit && snapshot?.head === commit),
|
|
187
|
+
published: Boolean(commit && remoteHead === commit),
|
|
188
|
+
branch,
|
|
189
|
+
upstream: snapshot?.upstream ?? null,
|
|
190
|
+
remoteHead,
|
|
191
|
+
newVersion,
|
|
192
|
+
changedPaths,
|
|
193
|
+
demoInputSha256: digest && /^[0-9a-f]{64}$/.test(digest) ? digest : null,
|
|
194
|
+
worktree: snapshot?.worktree ?? [],
|
|
195
|
+
staged: snapshot?.staged ?? []
|
|
196
|
+
};
|
|
197
|
+
}
|
|
162
198
|
function releaseSmokeStatus(workflows, version, tagCommit) {
|
|
163
199
|
const manualTitle = `Post-Release Smoke v${version}`;
|
|
164
200
|
const targets = workflows.filter((run) => {
|
|
@@ -209,12 +245,15 @@ async function inspectFacts(cwd, version) {
|
|
|
209
245
|
const workflows = platform.workflows;
|
|
210
246
|
const smoke = releaseSmokeStatus(workflows, version, localTagTarget);
|
|
211
247
|
return {
|
|
212
|
-
|
|
248
|
+
localTag: local.localTag,
|
|
249
|
+
localTagAncestor: local.localTagAncestor,
|
|
250
|
+
localTagConflict: local.localTagConflict,
|
|
213
251
|
remoteBranch: Boolean(remoteBranch && remoteBranch.split(/\s+/)[0] === head), remoteTag: Boolean(remoteTag),
|
|
214
252
|
githubRelease: platform.platform.type !== 'github'
|
|
215
253
|
? true
|
|
216
254
|
: platform.status === 'blocked' ? null : Boolean(platform.release?.published),
|
|
217
|
-
npm: npm.published, homebrew: homebrew.published, smoke
|
|
255
|
+
npm: npm.published, homebrew: homebrew.published, smoke,
|
|
256
|
+
post: inspectPostReleaseFacts(cwd, local.postCommit)
|
|
218
257
|
};
|
|
219
258
|
}
|
|
220
259
|
function parsePorcelainPath(record) {
|
|
@@ -245,13 +284,21 @@ function updateReleaseMetadata(cwd, version) {
|
|
|
245
284
|
fs.writeFileSync(filePath, content);
|
|
246
285
|
}
|
|
247
286
|
}
|
|
287
|
+
function optionValues(args, name) {
|
|
288
|
+
const values = [];
|
|
289
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
290
|
+
if (args[index] === name)
|
|
291
|
+
values.push(args[index + 1] ?? '');
|
|
292
|
+
}
|
|
293
|
+
return values;
|
|
294
|
+
}
|
|
248
295
|
async function releaseWorkflow(args = []) {
|
|
249
296
|
const [action, rawVersion, ...rest] = args;
|
|
250
297
|
const version = String(rawVersion || '').replace(/^v/, '');
|
|
251
298
|
const cwdIndex = rest.indexOf('--cwd');
|
|
252
299
|
const cwd = path.resolve(cwdIndex >= 0 && rest[cwdIndex + 1] ? rest[cwdIndex + 1] : process.cwd());
|
|
253
|
-
if (!['inspect', 'prepare', 'publish', 'post'].includes(action || '') || !semver.valid(version)) {
|
|
254
|
-
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'RELEASE_INPUT_INVALID', message: 'Usage: release-workflow inspect|prepare|publish|post <version>' } })}\n`);
|
|
300
|
+
if (!['inspect', 'prepare', 'publish', 'post-prepare', 'post-publish'].includes(action || '') || !semver.valid(version)) {
|
|
301
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'RELEASE_INPUT_INVALID', message: 'Usage: release-workflow inspect|prepare|publish|post-prepare|post-publish <version>' } })}\n`);
|
|
255
302
|
process.exitCode = 1;
|
|
256
303
|
return;
|
|
257
304
|
}
|
|
@@ -331,10 +378,56 @@ async function releaseWorkflow(args = []) {
|
|
|
331
378
|
process.exitCode = result.status === 'failed' ? 1 : result.status === 'degraded' ? 2 : 0;
|
|
332
379
|
return;
|
|
333
380
|
}
|
|
381
|
+
if (action === 'post-publish') {
|
|
382
|
+
const expectedValues = optionValues(rest, '--expected-sha256');
|
|
383
|
+
if (expectedValues.length !== 1 || !/^sha256:[0-9a-f]{64}$/.test(expectedValues[0])) {
|
|
384
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, snapshot: before, error: { code: 'RELEASE_INPUT_INVALID', message: 'post-publish requires one --expected-sha256 sha256:<64 hex>' } })}\n`);
|
|
385
|
+
process.exitCode = 1;
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
if (before.phase === 'complete') {
|
|
389
|
+
process.stdout.write(`${JSON.stringify({ status: 'no-op', changed: false, snapshot: before, error: null })}\n`);
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
const confirmation = 'postConfirmation' in before ? before.postConfirmation : null;
|
|
393
|
+
if (before.phase !== 'post-prepared' || !confirmation) {
|
|
394
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, snapshot: before, error: { code: confirmation ? 'RELEASE_PHASE_INVALID' : 'RELEASE_POST_CONFIRMATION_UNAVAILABLE', message: 'Post-release facts cannot authorize publish' } })}\n`);
|
|
395
|
+
process.exitCode = 1;
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
if (confirmation.sha256 !== expectedValues[0]) {
|
|
399
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, snapshot: before, error: { code: 'RELEASE_POST_SNAPSHOT_MISMATCH', message: 'Post-release confirmation snapshot changed' } })}\n`);
|
|
400
|
+
process.exitCode = 1;
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
const channelsComplete = before.facts.githubRelease === true && before.facts.npm === true && before.facts.homebrew === true;
|
|
404
|
+
if (!channelsComplete || before.facts.smoke !== 'success') {
|
|
405
|
+
process.stdout.write(`${JSON.stringify({ status: before.facts.smoke === 'failed' ? 'failed' : 'blocked', changed: false, snapshot: before, error: { code: 'RELEASE_CHANNELS_PENDING', message: 'Release channels or smoke workflow are not complete' } })}\n`);
|
|
406
|
+
process.exitCode = before.facts.smoke === 'failed' ? 1 : 2;
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
const pushed = pushGitRefs({ cwd, remote: 'origin', refs: [before.facts.post.branch] });
|
|
410
|
+
const snapshot = releaseSnapshot(version, await inspectFacts(cwd, version));
|
|
411
|
+
if (snapshot.phase === 'complete') {
|
|
412
|
+
process.stdout.write(`${JSON.stringify({ ...pushed, status: 'applied', changed: true, snapshot, error: null })}\n`);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
const blocked = pushed.status !== 'failed';
|
|
416
|
+
process.stdout.write(`${JSON.stringify({ ...pushed, status: blocked ? 'blocked' : 'failed', snapshot, error: pushed.error ?? { code: 'RELEASE_PROGRESS_PENDING', message: 'Post-release push is not visible at the expected remote head' } })}\n`);
|
|
417
|
+
process.exitCode = blocked ? 2 : 1;
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
334
420
|
if (before.phase === 'complete') {
|
|
335
421
|
process.stdout.write(`${JSON.stringify({ status: 'no-op', changed: false, snapshot: before, error: null })}\n`);
|
|
336
422
|
return;
|
|
337
423
|
}
|
|
424
|
+
if (before.phase === 'post-prepared') {
|
|
425
|
+
const confirmation = 'postConfirmation' in before ? before.postConfirmation : null;
|
|
426
|
+
const status = confirmation ? 'no-op' : 'blocked';
|
|
427
|
+
process.stdout.write(`${JSON.stringify({ status, changed: false, snapshot: before, error: confirmation ? null : { code: 'RELEASE_POST_CONFIRMATION_UNAVAILABLE', message: 'Post commit is not the clean current HEAD' } })}\n`);
|
|
428
|
+
process.exitCode = confirmation ? 0 : 2;
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
338
431
|
const channelsComplete = before.facts.githubRelease === true && before.facts.npm === true && before.facts.homebrew === true;
|
|
339
432
|
if (!['published', 'post-pending'].includes(before.phase) || !channelsComplete || before.facts.smoke !== 'success') {
|
|
340
433
|
process.stdout.write(`${JSON.stringify({ status: before.facts.smoke === 'failed' ? 'failed' : 'blocked', changed: false, snapshot: before, error: { code: 'RELEASE_CHANNELS_PENDING', message: 'Release channels or smoke workflow are not complete' } })}\n`);
|
|
@@ -373,10 +466,14 @@ async function releaseWorkflow(args = []) {
|
|
|
373
466
|
process.exitCode = 1;
|
|
374
467
|
return;
|
|
375
468
|
}
|
|
376
|
-
const
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
469
|
+
const snapshot = releaseSnapshot(version, await inspectFacts(cwd, version));
|
|
470
|
+
const confirmation = 'postConfirmation' in snapshot ? snapshot.postConfirmation : null;
|
|
471
|
+
if (snapshot.phase !== 'post-prepared' || !confirmation) {
|
|
472
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: true, demo, snapshot, error: { code: 'RELEASE_POST_CONFIRMATION_UNAVAILABLE', message: 'Prepared post commit did not produce a confirmation snapshot' } })}\n`);
|
|
473
|
+
process.exitCode = 1;
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
process.stdout.write(`${JSON.stringify({ status: 'applied', changed: true, demo, snapshot, error: null })}\n`);
|
|
380
477
|
}
|
|
381
|
-
export { changedPaths, computeDemoInputDigest, inspectFacts, inspectLocalReleaseFacts, inspectPostWorktree, releaseSmokeStatus, releaseWorkflow, runOptionalDemo };
|
|
478
|
+
export { changedPaths, computeDemoInputDigest, inspectFacts, inspectLocalReleaseFacts, inspectPostReleaseFacts, inspectPostWorktree, releaseSmokeStatus, releaseWorkflow, runOptionalDemo };
|
|
382
479
|
//# sourceMappingURL=release-workflow.js.map
|
|
@@ -1,24 +1,61 @@
|
|
|
1
|
-
import { requestSandboxControl } from '../sandbox/control/client.js';
|
|
1
|
+
import { requestSandboxControl, SandboxControlClientError } from '../sandbox/control/client.js';
|
|
2
2
|
import { serveSandboxControl } from '../sandbox/control/server.js';
|
|
3
|
-
|
|
3
|
+
import { runSandboxControlExecutor } from '../sandbox/control/executor.js';
|
|
4
|
+
async function sandboxControl(args) {
|
|
4
5
|
const [operation, ...rest] = args;
|
|
5
6
|
if (operation === 'serve') {
|
|
6
7
|
const manifestIndex = rest.indexOf('--manifest');
|
|
7
8
|
const manifest = manifestIndex >= 0 ? rest[manifestIndex + 1] : undefined;
|
|
8
9
|
if (!manifest)
|
|
9
10
|
throw new Error('sandbox-control serve requires --manifest');
|
|
10
|
-
|
|
11
|
+
const controller = new AbortController();
|
|
12
|
+
const abort = () => controller.abort();
|
|
13
|
+
process.once('SIGINT', abort);
|
|
14
|
+
process.once('SIGTERM', abort);
|
|
15
|
+
try {
|
|
16
|
+
await serveSandboxControl(manifest, controller.signal);
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
process.off('SIGINT', abort);
|
|
20
|
+
process.off('SIGTERM', abort);
|
|
21
|
+
}
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (operation === 'execute') {
|
|
25
|
+
const requestIndex = rest.indexOf('--request');
|
|
26
|
+
const nonceIndex = rest.indexOf('--nonce');
|
|
27
|
+
const request = requestIndex >= 0 ? rest[requestIndex + 1] : undefined;
|
|
28
|
+
const nonce = nonceIndex >= 0 ? rest[nonceIndex + 1] : undefined;
|
|
29
|
+
if (!request || !nonce)
|
|
30
|
+
throw new Error('sandbox-control execute requires --request and --nonce');
|
|
31
|
+
await runSandboxControlExecutor(request, nonce);
|
|
11
32
|
return;
|
|
12
33
|
}
|
|
13
34
|
if (operation === 'client') {
|
|
14
35
|
const [family = '', ...commandArgs] = rest;
|
|
15
|
-
|
|
36
|
+
let response;
|
|
37
|
+
try {
|
|
38
|
+
response = requestSandboxControl({ family, args: commandArgs });
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (!(error instanceof SandboxControlClientError))
|
|
42
|
+
throw error;
|
|
43
|
+
process.stderr.write(`${error.detail.message}\n`);
|
|
44
|
+
process.exitCode = error.detail.retryable ? 75 : 1;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
16
47
|
process.stdout.write(response.stdout);
|
|
17
48
|
process.stderr.write(response.stderr);
|
|
18
|
-
|
|
49
|
+
if (response.phase === 'rejected') {
|
|
50
|
+
process.stderr.write(response.error?.message ?? response.stderr);
|
|
51
|
+
process.exitCode = response.error?.retryable ? 75 : 1;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
process.exitCode = response.exitCode ?? 1;
|
|
55
|
+
}
|
|
19
56
|
return;
|
|
20
57
|
}
|
|
21
|
-
throw new Error('Usage: agent-infra-internal sandbox-control serve --manifest <path> | client <family> [args...]');
|
|
58
|
+
throw new Error('Usage: agent-infra-internal sandbox-control serve --manifest <path> | execute --request <path> --nonce <nonce> | client <family> [args...]');
|
|
22
59
|
}
|
|
23
60
|
export { sandboxControl };
|
|
24
61
|
//# sourceMappingURL=sandbox-control.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { requestSandboxTaskCreate } from '../sandbox/control/client.js';
|
|
3
|
+
import { requestSandboxTaskCreate, SandboxControlClientError } from '../sandbox/control/client.js';
|
|
4
4
|
import { SANDBOX_CONTROL_MAX_BYTES } from '../sandbox/control/protocol.js';
|
|
5
5
|
import { validateTaskCreateCandidate } from '../task/create.js';
|
|
6
6
|
import { createTask } from '../task/create-service.js';
|
|
7
|
-
function failed(code, message) {
|
|
7
|
+
function failed(code, message, retryable = false) {
|
|
8
8
|
return {
|
|
9
|
-
status: 'failed', changed: false, task: { id: null, shortId: null }, issue: null,
|
|
10
|
-
operations: [], warnings: [], error: { code, message, retryable
|
|
9
|
+
status: retryable ? 'blocked' : 'failed', changed: false, task: { id: null, shortId: null }, issue: null,
|
|
10
|
+
operations: [], warnings: [], error: { code, message, retryable }
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
function output(result) {
|
|
@@ -31,6 +31,10 @@ function taskCreate(args) {
|
|
|
31
31
|
const candidate = validateTaskCreateCandidate(JSON.parse(fs.readFileSync(inputPath, 'utf8')));
|
|
32
32
|
if (process.env.AGENT_INFRA_CONTROL_TOKEN) {
|
|
33
33
|
const response = requestSandboxTaskCreate({ candidate });
|
|
34
|
+
if (response.phase === 'rejected') {
|
|
35
|
+
output(failed(response.error?.code ?? 'SANDBOX_CONTROL_REJECTED', response.error?.message ?? response.stderr, response.error?.retryable ?? false));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
34
38
|
process.stdout.write(response.stdout);
|
|
35
39
|
process.stderr.write(response.stderr);
|
|
36
40
|
process.exitCode = response.exitCode;
|
|
@@ -39,6 +43,10 @@ function taskCreate(args) {
|
|
|
39
43
|
output(createTask(candidate, { repoRoot: process.cwd() }));
|
|
40
44
|
}
|
|
41
45
|
catch (error) {
|
|
46
|
+
if (error instanceof SandboxControlClientError) {
|
|
47
|
+
output(failed(error.detail.code, error.detail.message, error.detail.retryable));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
42
50
|
const message = error instanceof Error ? error.message : String(error);
|
|
43
51
|
const code = /^([A-Z][A-Z0-9_]+)/.exec(message)?.[1] ?? 'TASK_CREATE_INPUT_INVALID';
|
|
44
52
|
output(failed(code, message));
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.js';
|
|
2
|
-
import { abortCommitIntent, activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, advanceOrchestration, beginCommitIntent, beginOrResumeOrchestration, checkpointCommitIntent, completeCommitIntent,
|
|
2
|
+
import { abortCommitIntent, activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, advanceOrchestration, awaitOrchestrationDelegationActivation, beginCommitIntent, beginOrResumeOrchestration, checkpointCommitIntent, completeCommitIntent, dispatchOrchestrationDelegation, pauseOrchestration, recoverCommitIntent, recoverPreparedOrchestrationDelegation, routeOrchestration, sealMatchingOrchestrationDelegation, sealOrchestrationDelegation, startCommitAttempt, statusCommitIntent, statusOrchestration, terminateCommitAttempt } from '../task/orchestration.js';
|
|
3
|
+
import { prepareCodexOrchestrationDelegation } from '../task/codex-orchestration.js';
|
|
3
4
|
import { isAgentClientId } from '../agent-clients/types.js';
|
|
4
|
-
const USAGE = 'Usage: agent-infra-internal task-orchestration <task-ref|auto> <begin-or-resume|route|prepare|hook-start|hook-stop|advance|pause|status|commit-start|commit-begin|commit-checkpoint|commit-complete|commit-recover|commit-abort|commit-terminate|commit-status> [options]\n';
|
|
5
|
+
const USAGE = 'Usage: agent-infra-internal task-orchestration <task-ref|auto> <begin-or-resume|route|prepare|dispatch|await-activation|recover-prepared|hook-start|hook-stop|advance|pause|status|commit-start|commit-begin|commit-checkpoint|commit-complete|commit-recover|commit-abort|commit-terminate|commit-status> [options]\n';
|
|
5
6
|
function usageFailure(message) {
|
|
6
7
|
process.stdout.write(`${JSON.stringify({
|
|
7
8
|
status: 'failed', changed: false,
|
|
@@ -10,7 +11,7 @@ function usageFailure(message) {
|
|
|
10
11
|
process.stderr.write(USAGE);
|
|
11
12
|
process.exitCode = 2;
|
|
12
13
|
}
|
|
13
|
-
function taskOrchestration(args = []) {
|
|
14
|
+
async function taskOrchestration(args = []) {
|
|
14
15
|
if (args[0] === '--help' || args[0] === '-h') {
|
|
15
16
|
process.stdout.write(USAGE);
|
|
16
17
|
return;
|
|
@@ -21,7 +22,8 @@ function taskOrchestration(args = []) {
|
|
|
21
22
|
}
|
|
22
23
|
const [taskRef, intent] = args;
|
|
23
24
|
if (![
|
|
24
|
-
'begin-or-resume', 'route', 'prepare', '
|
|
25
|
+
'begin-or-resume', 'route', 'prepare', 'dispatch', 'await-activation', 'recover-prepared',
|
|
26
|
+
'hook-start', 'hook-stop', 'advance', 'pause', 'status',
|
|
25
27
|
'commit-start', 'commit-begin', 'commit-checkpoint', 'commit-complete', 'commit-recover', 'commit-abort', 'commit-terminate', 'commit-status'
|
|
26
28
|
].includes(intent)) {
|
|
27
29
|
usageFailure(`unknown intent '${intent}'`);
|
|
@@ -44,7 +46,9 @@ function taskOrchestration(args = []) {
|
|
|
44
46
|
if (![
|
|
45
47
|
'--max-steps', '--executor-model', '--executor-reasoning-effort',
|
|
46
48
|
'--reviewer-model', '--reviewer-reasoning-effort',
|
|
47
|
-
'--client', '--requested-model', '--requested-reasoning-effort', '--
|
|
49
|
+
'--client', '--requested-model', '--requested-reasoning-effort', '--capability-token',
|
|
50
|
+
'--parent-id', '--before-fingerprint',
|
|
51
|
+
'--stage', '--round', '--artifact', '--role',
|
|
48
52
|
'--native-agent', '--child-id', '--spawn-mode', '--actual-model', '--actual-reasoning-effort',
|
|
49
53
|
'--model-fallback-reason', '--reasoning-effort-fallback-reason',
|
|
50
54
|
'--exit-code', '--after-fingerprint', '--changed-paths', '--code', '--message', '--recoverable', '--agent',
|
|
@@ -260,12 +264,41 @@ function taskOrchestration(args = []) {
|
|
|
260
264
|
usageFailure(`intent 'prepare' requires '${missing}'`);
|
|
261
265
|
return;
|
|
262
266
|
}
|
|
263
|
-
result =
|
|
267
|
+
result = await prepareCodexOrchestrationDelegation(taskRef, {
|
|
264
268
|
client: values['--client'],
|
|
265
269
|
requestedModel: values['--requested-model'],
|
|
266
|
-
requestedReasoningEffort: values['--requested-reasoning-effort']
|
|
270
|
+
requestedReasoningEffort: values['--requested-reasoning-effort'],
|
|
271
|
+
capabilityToken: values['--capability-token']
|
|
272
|
+
}, { orchestrationOptions: coreOptions });
|
|
273
|
+
}
|
|
274
|
+
else if (intent === 'dispatch') {
|
|
275
|
+
result = dispatchOrchestrationDelegation(taskRef, coreOptions);
|
|
276
|
+
}
|
|
277
|
+
else if (intent === 'await-activation') {
|
|
278
|
+
const missing = requireValues(['--stage', '--round', '--artifact', '--role']);
|
|
279
|
+
if (missing) {
|
|
280
|
+
usageFailure(`intent 'await-activation' requires '${missing}'`);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const round = Number(values['--round']);
|
|
284
|
+
if (!Number.isSafeInteger(round) || round < 1) {
|
|
285
|
+
usageFailure('--round must be a positive integer');
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (!['executor', 'reviewer'].includes(values['--role'])) {
|
|
289
|
+
usageFailure('--role must be executor or reviewer');
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
result = await awaitOrchestrationDelegationActivation(taskRef, {
|
|
293
|
+
stage: values['--stage'],
|
|
294
|
+
round,
|
|
295
|
+
artifact: values['--artifact'],
|
|
296
|
+
role: values['--role']
|
|
267
297
|
}, coreOptions);
|
|
268
298
|
}
|
|
299
|
+
else if (intent === 'recover-prepared') {
|
|
300
|
+
result = recoverPreparedOrchestrationDelegation(taskRef, coreOptions);
|
|
301
|
+
}
|
|
269
302
|
else if (intent === 'hook-start') {
|
|
270
303
|
const missing = requireValues([
|
|
271
304
|
...(taskRef === 'auto' ? ['--client'] : []),
|
|
@@ -5,6 +5,7 @@ import semver from 'semver';
|
|
|
5
5
|
import { getPlatformAdapter, registerPlatformAdapter } from './adapters.js';
|
|
6
6
|
import { createGitHubClient, MINIMUM_GITHUB_CLI_VERSION } from './github-client.js';
|
|
7
7
|
import { platformResult } from './types.js';
|
|
8
|
+
const CURRENT_USER_QUERY = 'query { viewer { login } }';
|
|
8
9
|
function findRepoRoot(cwd) {
|
|
9
10
|
try {
|
|
10
11
|
return execFileSync('git', ['rev-parse', '--show-toplevel'], {
|
|
@@ -89,18 +90,19 @@ function resolveGitHubContext(options) {
|
|
|
89
90
|
error: { code: 'UPSTREAM_UNRESOLVED', message: 'Unable to resolve the upstream repository', retryable: false }
|
|
90
91
|
});
|
|
91
92
|
}
|
|
92
|
-
const user = client.json(['api', '
|
|
93
|
+
const user = client.json(['api', 'graphql', '-f', `query=${CURRENT_USER_QUERY}`], { cwd });
|
|
93
94
|
if (!user.ok)
|
|
94
95
|
return failure(user.error, upstream);
|
|
95
96
|
const userValue = user.value;
|
|
97
|
+
const currentUser = userValue?.data?.viewer?.login || null;
|
|
96
98
|
const permissions = client.json(['api', `repos/${upstream}`], { cwd });
|
|
97
99
|
if (!permissions.ok)
|
|
98
100
|
return failure(permissions.error, upstream);
|
|
99
101
|
const permissionValue = permissions.value;
|
|
100
102
|
const values = permissionValue?.permissions || {};
|
|
101
103
|
const capabilities = {
|
|
102
|
-
authenticated: Boolean(
|
|
103
|
-
comment: Boolean(
|
|
104
|
+
authenticated: Boolean(currentUser),
|
|
105
|
+
comment: Boolean(currentUser),
|
|
104
106
|
triage: Boolean(values.triage || values.push || values.admin),
|
|
105
107
|
push: Boolean(values.push || values.admin),
|
|
106
108
|
admin: Boolean(values.admin)
|
|
@@ -108,7 +110,7 @@ function resolveGitHubContext(options) {
|
|
|
108
110
|
const status = Object.values(capabilities).every(Boolean) ? 'no-op' : 'degraded';
|
|
109
111
|
return platformResult(status, {
|
|
110
112
|
changed: false,
|
|
111
|
-
platform: { type: platform, repository: upstream, currentUser
|
|
113
|
+
platform: { type: platform, repository: upstream, currentUser },
|
|
112
114
|
resource: { kind: 'repository', number: null },
|
|
113
115
|
capabilities,
|
|
114
116
|
operations: [{ name: 'resolve', status: 'no-op', reasonCode: null }]
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import spawn from 'cross-spawn';
|
|
3
3
|
import semver from 'semver';
|
|
4
|
-
|
|
4
|
+
// closingIssuesReferences (introduced in gh 2.72.0) is the highest-versioned gh feature
|
|
5
|
+
// the platform layer depends on; see github-release-notes.ts:102.
|
|
6
|
+
const MINIMUM_GITHUB_CLI_VERSION = '2.72.0';
|
|
5
7
|
const GITHUB_CLI_MAX_BUFFER = 64 * 1024 * 1024;
|
|
6
8
|
const ERROR_DETAIL_LIMIT = 4096;
|
|
7
9
|
function boundedFailureDetail(result) {
|
|
@@ -76,6 +78,41 @@ function classifyGitHubFailure(result) {
|
|
|
76
78
|
}
|
|
77
79
|
return { code: 'PLATFORM_REQUEST_FAILED', message: detail || 'GitHub request failed', retryable: false };
|
|
78
80
|
}
|
|
81
|
+
function responseUrl(args) {
|
|
82
|
+
const endpoint = args.find((arg, index) => index > 0 && !arg.startsWith('-')) || '';
|
|
83
|
+
return endpoint.startsWith('http') ? endpoint : `https://api.github.com/${endpoint.replace(/^\//, '')}`;
|
|
84
|
+
}
|
|
85
|
+
function parseIncludedResponse(stdout, args) {
|
|
86
|
+
const statusBlocks = [...stdout.matchAll(/^HTTP\/[^\r\n]+/gim)];
|
|
87
|
+
const headerStart = statusBlocks.at(-1)?.index;
|
|
88
|
+
if (headerStart === undefined)
|
|
89
|
+
return null;
|
|
90
|
+
const response = stdout.slice(headerStart);
|
|
91
|
+
const separator = response.match(/\r?\n\r?\n/);
|
|
92
|
+
if (!separator || separator.index === undefined)
|
|
93
|
+
return null;
|
|
94
|
+
const header = response.slice(0, separator.index);
|
|
95
|
+
const body = response.slice(separator.index + separator[0].length);
|
|
96
|
+
const status = header.match(/^HTTP\/[^ ]+\s+(\d{3})/mi)?.[1];
|
|
97
|
+
if (!status)
|
|
98
|
+
return null;
|
|
99
|
+
const date = header.match(/^Date:\s*(.+)$/mi)?.[1]?.trim();
|
|
100
|
+
const links = [...header.matchAll(/^Link:\s*(.+)$/gim)].flatMap((match) => match[1].split(',').map((value) => value.trim()));
|
|
101
|
+
try {
|
|
102
|
+
return {
|
|
103
|
+
value: JSON.parse(body || 'null'),
|
|
104
|
+
metadata: {
|
|
105
|
+
status: Number(status),
|
|
106
|
+
requestUrl: responseUrl(args),
|
|
107
|
+
...(date ? { date } : {}),
|
|
108
|
+
links
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
79
116
|
function createGitHubClient(options = {}) {
|
|
80
117
|
const runner = options.runner || defaultRunner;
|
|
81
118
|
const delays = options.retryDelaysMs || retryDelaysFromEnvironment();
|
|
@@ -134,8 +171,24 @@ function createGitHubClient(options = {}) {
|
|
|
134
171
|
error: { code: 'INVALID_PLATFORM_RESPONSE', message: 'GitHub returned invalid JSON', retryable: true }
|
|
135
172
|
};
|
|
136
173
|
}
|
|
174
|
+
},
|
|
175
|
+
jsonWithMetadata(args, request = {}) {
|
|
176
|
+
const includeArgs = args[0] === 'api' && args[1] !== '--include'
|
|
177
|
+
? [args[0], '--include', ...args.slice(1)]
|
|
178
|
+
: args;
|
|
179
|
+
const result = run(includeArgs, request);
|
|
180
|
+
if (!result.ok)
|
|
181
|
+
return result;
|
|
182
|
+
const parsed = parseIncludedResponse(result.value, args);
|
|
183
|
+
if (!parsed) {
|
|
184
|
+
return {
|
|
185
|
+
ok: false,
|
|
186
|
+
error: { code: 'INVALID_PLATFORM_RESPONSE', message: 'GitHub response metadata or JSON is invalid', retryable: true }
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return { ok: true, value: parsed };
|
|
137
190
|
}
|
|
138
191
|
};
|
|
139
192
|
}
|
|
140
|
-
export { classifyGitHubFailure, createGitHubClient, MINIMUM_GITHUB_CLI_VERSION };
|
|
193
|
+
export { classifyGitHubFailure, createGitHubClient, MINIMUM_GITHUB_CLI_VERSION, parseIncludedResponse };
|
|
141
194
|
//# sourceMappingURL=github-client.js.map
|
|
@@ -20,6 +20,7 @@ const ARTIFACT_TITLES = {
|
|
|
20
20
|
code: '实现报告',
|
|
21
21
|
'review-code': '代码审查',
|
|
22
22
|
'manual-validation': '人工验证报告',
|
|
23
|
+
'validation-run': '验证运行证据',
|
|
23
24
|
'pr-review': 'PR 审查报告'
|
|
24
25
|
};
|
|
25
26
|
function normalizeCommentContent(content) {
|
|
@@ -52,7 +53,7 @@ function renderTaskComment(content, taskId, agent) {
|
|
|
52
53
|
}
|
|
53
54
|
function artifactIdentity(artifact) {
|
|
54
55
|
const stem = path.basename(artifact, '.md');
|
|
55
|
-
const match = stem.match(/^(analysis|review-analysis|plan|review-plan|code|review-code|manual-validation|pr-review)(?:-r(\d+))?$/);
|
|
56
|
+
const match = stem.match(/^(analysis|review-analysis|plan|review-plan|code|review-code|manual-validation|validation-run|pr-review)(?:-r(\d+))?$/);
|
|
56
57
|
if (!match)
|
|
57
58
|
throw new Error(`unsupported artifact '${artifact}'`);
|
|
58
59
|
const base = ARTIFACT_TITLES[match[1]];
|