@fitlab-ai/agent-infra 0.11.3 → 0.11.4
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 +17 -8
- package/README.zh-CN.md +17 -8
- package/dist/bin/internal-cli.js +1 -1
- package/dist/lib/internal/cli-route-inventory.js +1 -1
- package/dist/lib/internal/task-artifact.js +1 -1
- package/dist/lib/internal/task-finalization.js +41 -1
- package/dist/lib/internal/task-ledger.js +13 -5
- package/dist/lib/internal/task-operation-registry.js +1 -0
- package/dist/lib/platform/completion-backfill.js +63 -17
- package/dist/lib/sandbox/control/server.js +26 -143
- package/dist/lib/sandbox/task-cleanup.js +13 -20
- package/dist/lib/task/artifact-command.js +11 -4
- package/dist/lib/task/artifact-lifecycle.js +217 -85
- package/dist/lib/task/artifact-operations.js +1 -26
- package/dist/lib/task/artifact-receipts.js +4 -1
- package/dist/lib/task/artifact-schema.js +1 -0
- package/dist/lib/task/artifact-selection.js +25 -0
- package/dist/lib/task/capabilities.js +158 -39
- package/dist/lib/task/commands/status.js +9 -2
- package/dist/lib/task/control-authority.js +3 -2
- package/dist/lib/task/decision-intents.js +12 -0
- package/dist/lib/task/delivery.js +1 -43
- package/dist/lib/task/events.js +80 -64
- package/dist/lib/task/finalization.js +301 -143
- package/dist/lib/task/ledger-intents.js +157 -15
- package/dist/lib/task/lifecycle-path.js +75 -0
- package/dist/lib/task/lifecycle.js +10 -0
- package/dist/lib/task/local-artifact-finalization.js +1 -20
- package/dist/lib/task/orchestration.js +17 -7
- package/dist/lib/task/review-finalization.js +3 -16
- package/dist/lib/task/rework-intent.js +70 -4
- package/dist/lib/task/verification-engine.js +20 -30
- package/dist/lib/task/verification.js +1 -0
- package/dist/lib/task/workflow-warning-intents.js +21 -6
- package/dist/lib/task/workspace-snapshot.js +7 -2
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/internal/cli-route-inventory.ts +1 -1
- package/lib/internal/task-artifact.ts +1 -1
- package/lib/internal/task-finalization.ts +40 -1
- package/lib/internal/task-ledger.ts +12 -5
- package/lib/internal/task-operation-registry.ts +1 -0
- package/lib/platform/completion-backfill.ts +78 -16
- package/lib/sandbox/control/server.ts +21 -146
- package/lib/sandbox/task-cleanup.ts +12 -20
- package/lib/task/artifact-command.ts +14 -4
- package/lib/task/artifact-lifecycle.ts +236 -85
- package/lib/task/artifact-operations.ts +1 -26
- package/lib/task/artifact-receipts.ts +4 -1
- package/lib/task/artifact-schema.ts +1 -0
- package/lib/task/artifact-selection.ts +53 -0
- package/lib/task/capabilities.ts +154 -40
- package/lib/task/commands/status.ts +11 -2
- package/lib/task/control-authority.ts +3 -1
- package/lib/task/decision-intents.ts +9 -0
- package/lib/task/delivery.ts +1 -40
- package/lib/task/events.ts +82 -64
- package/lib/task/finalization.ts +269 -111
- package/lib/task/ledger-intents.ts +155 -15
- package/lib/task/lifecycle-path.ts +98 -0
- package/lib/task/lifecycle.ts +13 -0
- package/lib/task/local-artifact-finalization.ts +2 -25
- package/lib/task/orchestration.ts +26 -8
- package/lib/task/review-finalization.ts +3 -16
- package/lib/task/rework-intent.ts +75 -5
- package/lib/task/verification-engine.ts +19 -30
- package/lib/task/verification.ts +2 -1
- package/lib/task/workflow-warning-intents.ts +18 -6
- package/lib/task/workspace-snapshot.ts +3 -2
- package/package.json +1 -1
- package/templates/.agents/rules/review-handshake.en.md +4 -4
- package/templates/.agents/rules/review-handshake.zh-CN.md +4 -4
- package/templates/.agents/skills/analyze-task/SKILL.en.md +11 -4
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +11 -4
- package/templates/.agents/skills/code-task/SKILL.en.md +14 -8
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +18 -13
- package/templates/.agents/skills/code-task/reference/code-rules.en.md +2 -2
- package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +2 -2
- package/templates/.agents/skills/code-task/reference/dual-mode.en.md +4 -4
- package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +4 -4
- package/templates/.agents/skills/code-task/reference/report-template.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/plan-task/SKILL.en.md +13 -10
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +13 -10
- package/templates/.agents/skills/review-analysis/SKILL.en.md +5 -1
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/review-code/SKILL.en.md +5 -1
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/review-plan/SKILL.en.md +5 -1
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +18 -2
- package/templates/.agents/templates/task.en.md +2 -2
- package/templates/.agents/templates/task.zh-CN.md +2 -2
- package/templates/.agents/workflows/bug-fix.en.yaml +11 -6
- package/templates/.agents/workflows/bug-fix.zh-CN.yaml +11 -6
- package/templates/.agents/workflows/feature-development.en.yaml +11 -6
- package/templates/.agents/workflows/feature-development.zh-CN.yaml +11 -6
- package/templates/.agents/workflows/refactoring.en.yaml +11 -6
- package/templates/.agents/workflows/refactoring.zh-CN.yaml +11 -6
- package/dist/lib/sandbox/control/finalization-response.js +0 -33
- package/lib/sandbox/control/finalization-response.ts +0 -35
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { finalizationTerminalResponse } from './finalization-response.js';
|
|
2
1
|
import { completedReentryView } from './completed-reentry.js';
|
|
3
2
|
import fs from 'node:fs';
|
|
4
3
|
import path from 'node:path';
|
|
@@ -21,7 +20,7 @@ import { nextSandboxControlBackoff } from './timing.js';
|
|
|
21
20
|
import { readTaskFinalizationReceipt } from '../../task/finalization.js';
|
|
22
21
|
import { readCodexControllerRegistration } from './controller-registration.js';
|
|
23
22
|
import { validateSandboxControlIdentity } from './identity-sentinel.js';
|
|
24
|
-
import { mergeSandboxTaskView,
|
|
23
|
+
import { mergeSandboxTaskView, taskViewForManifest } from './task-view.js';
|
|
25
24
|
import { taskCreateOutputUnavailableResult } from '../../task/create-service.js';
|
|
26
25
|
function appendBrokerAudit(manifest, event, fields = {}) {
|
|
27
26
|
appendDiagnosticAudit(manifest, event, { source: 'broker', ...fields });
|
|
@@ -125,48 +124,6 @@ export function writeSandboxControlResponse(manifest, response) {
|
|
|
125
124
|
}
|
|
126
125
|
return true;
|
|
127
126
|
}
|
|
128
|
-
function finalizationRecoveryResponse(manifest, requestId, exitCode) {
|
|
129
|
-
if (!manifest.taskId || exitCode !== 0)
|
|
130
|
-
return { status: 'not-applicable' };
|
|
131
|
-
let receipt;
|
|
132
|
-
try {
|
|
133
|
-
receipt = readTaskFinalizationReceipt(manifest.repoRoot, manifest.taskId);
|
|
134
|
-
if (!receipt || !receipt.controlBinding
|
|
135
|
-
|| receipt.controlBinding.generation !== manifest.generation
|
|
136
|
-
|| receipt.controlBinding.requestId !== requestId)
|
|
137
|
-
return { status: 'deferred' };
|
|
138
|
-
const resolved = resolveTaskRef(manifest.taskId, { repoRoot: manifest.repoRoot });
|
|
139
|
-
if (!resolved.ok || resolved.state !== 'completed' || receipt.lifecycle !== 'done')
|
|
140
|
-
return { status: 'deferred' };
|
|
141
|
-
}
|
|
142
|
-
catch {
|
|
143
|
-
return { status: 'deferred' };
|
|
144
|
-
}
|
|
145
|
-
return { status: 'matched', response: finalizationTerminalResponse(manifest.taskId, requestId, receipt) };
|
|
146
|
-
}
|
|
147
|
-
function publishFinalizationTaskView(manifest, broker, requestId, state, reasonCode, activeRequestId) {
|
|
148
|
-
let view;
|
|
149
|
-
try {
|
|
150
|
-
const resolved = resolveTaskRef(manifest.taskId ?? '', { repoRoot: manifest.repoRoot });
|
|
151
|
-
const receipt = readTaskFinalizationReceipt(manifest.repoRoot, manifest.taskId ?? '');
|
|
152
|
-
view = resolved.ok && resolved.state === 'completed'
|
|
153
|
-
? taskViewAfterFinalization({
|
|
154
|
-
taskId: manifest.taskId ?? '', generation: manifest.generation, requestId, receipt
|
|
155
|
-
})
|
|
156
|
-
: {
|
|
157
|
-
state: 'unknown', taskId: manifest.taskId, observedSource: 'unknown', receipt: null,
|
|
158
|
-
reasonCode: 'SANDBOX_TASK_VIEW_SOURCE_UNCONFIRMED'
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
catch {
|
|
162
|
-
view = {
|
|
163
|
-
state: 'unknown', taskId: manifest.taskId, observedSource: 'unknown', receipt: null,
|
|
164
|
-
reasonCode: 'SANDBOX_TASK_VIEW_RECEIPT_INVALID'
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
writeSandboxControlStatus(manifest, broker, state, reasonCode, activeRequestId, Date.now(), view);
|
|
168
|
-
return view;
|
|
169
|
-
}
|
|
170
127
|
function payloadReference(payload) {
|
|
171
128
|
return {
|
|
172
129
|
version: payload.version,
|
|
@@ -329,12 +286,7 @@ export async function recoveryResponse(manifest, manifestPath, request, evidence
|
|
|
329
286
|
if (JSON.stringify(payloadTerminal) !== JSON.stringify(terminalResult))
|
|
330
287
|
return unknown(request.id);
|
|
331
288
|
}
|
|
332
|
-
const
|
|
333
|
-
if (evidence.exitCode === 0 && finalization?.status === 'deferred')
|
|
334
|
-
return null;
|
|
335
|
-
const recovery = finalization
|
|
336
|
-
? { domain: { consistent: finalization.status === 'matched' } }
|
|
337
|
-
: await readRecoveryDomain(manifest, manifestPath, request, operation, terminalResult, payload?.stdout ?? null);
|
|
289
|
+
const recovery = await readRecoveryDomain(manifest, manifestPath, request, operation, terminalResult, payload?.stdout ?? null);
|
|
338
290
|
const binding = operationRecoveryBinding(request.id, manifest.generation, manifest.taskId, request.family, operationName);
|
|
339
291
|
const decision = classifySandboxControlRecovery({
|
|
340
292
|
operation,
|
|
@@ -351,23 +303,9 @@ export async function recoveryResponse(manifest, manifestPath, request, evidence
|
|
|
351
303
|
return notExecuted(request.id);
|
|
352
304
|
if (decision.outcome !== 'success' && decision.outcome !== 'failure')
|
|
353
305
|
return null;
|
|
354
|
-
if (request.family === 'task-finalization' && evidence.exitCode === 0) {
|
|
355
|
-
if (finalization?.status !== 'matched')
|
|
356
|
-
return null;
|
|
357
|
-
return finalization.response ?? null;
|
|
358
|
-
}
|
|
359
306
|
return genericRecoveryResponse(request, evidence.exitCode, payload);
|
|
360
307
|
}
|
|
361
|
-
async function terminalMatchesEvidence(manifest,
|
|
362
|
-
if (request.family === 'task-finalization' && evidence.exitCode === 0) {
|
|
363
|
-
if (!terminalResult)
|
|
364
|
-
return { valid: false, payloadReferenced: false };
|
|
365
|
-
const expected = await recoveryResponse(manifest, manifestPath, request, evidence, payload, terminalResult);
|
|
366
|
-
return {
|
|
367
|
-
valid: expected !== null && JSON.stringify(response) === JSON.stringify(expected),
|
|
368
|
-
payloadReferenced: false
|
|
369
|
-
};
|
|
370
|
-
}
|
|
308
|
+
async function terminalMatchesEvidence(manifest, request, response, evidence, payload, payloadInvalid, terminalResult) {
|
|
371
309
|
if (response.version !== 2 || response.id !== request.id || response.phase !== 'completed'
|
|
372
310
|
|| response.exitCode !== evidence.exitCode || response.error !== null) {
|
|
373
311
|
return { valid: false, payloadReferenced: false };
|
|
@@ -401,7 +339,7 @@ async function terminalMatchesEvidence(manifest, manifestPath, request, response
|
|
|
401
339
|
payloadReferenced: false
|
|
402
340
|
};
|
|
403
341
|
}
|
|
404
|
-
function publishExecutionResult(manifest, request, result,
|
|
342
|
+
function publishExecutionResult(manifest, request, result, brokerOwns) {
|
|
405
343
|
const normalized = sanitizeSandboxControlResult(manifest, result);
|
|
406
344
|
const terminalResult = writeSandboxControlTerminalResult(manifest, {
|
|
407
345
|
id: request.id,
|
|
@@ -413,46 +351,29 @@ function publishExecutionResult(manifest, request, result, broker, brokerOwns) {
|
|
|
413
351
|
criticalRequestPhase(manifest, request, 'evidence-written', normalized.exitCode === 0 ? 'success' : 'failure');
|
|
414
352
|
criticalRequestPhase(manifest, request, 'publish-authorized', normalized.exitCode === 0 ? 'success' : 'failure');
|
|
415
353
|
}
|
|
416
|
-
let terminal =
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
terminal = finalization.response ?? null;
|
|
422
|
-
}
|
|
423
|
-
if (!terminal) {
|
|
424
|
-
const inline = {
|
|
425
|
-
version: 2, id: request.id, phase: 'completed', exitCode: normalized.exitCode,
|
|
426
|
-
stdout: normalized.stdout, stderr: normalized.stderr, error: null
|
|
427
|
-
};
|
|
428
|
-
if (sandboxControlEncodedJsonBytes(inline) <= SANDBOX_CONTROL_MAX_TERMINAL_RECORD_BYTES) {
|
|
429
|
-
terminal = inline;
|
|
430
|
-
}
|
|
354
|
+
let terminal = {
|
|
355
|
+
version: 2, id: request.id, phase: 'completed', exitCode: normalized.exitCode,
|
|
356
|
+
stdout: normalized.stdout, stderr: normalized.stderr, error: null
|
|
357
|
+
};
|
|
358
|
+
if (sandboxControlEncodedJsonBytes(terminal) > SANDBOX_CONTROL_MAX_TERMINAL_RECORD_BYTES) {
|
|
431
359
|
let payload = null;
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
writeSandboxControlPayload(manifest, request.id, normalized);
|
|
438
|
-
}
|
|
439
|
-
else {
|
|
440
|
-
payload = null;
|
|
441
|
-
}
|
|
360
|
+
try {
|
|
361
|
+
payload = createSandboxControlPayload(manifest, request.id, normalized);
|
|
362
|
+
const usage = sandboxControlGenerationUsage(manifest);
|
|
363
|
+
if (usage.bytes + sandboxControlEncodedJsonBytes(payload) <= SANDBOX_CONTROL_MAX_RESPONSE_BYTES) {
|
|
364
|
+
writeSandboxControlPayload(manifest, request.id, normalized);
|
|
442
365
|
}
|
|
443
|
-
|
|
366
|
+
else {
|
|
444
367
|
payload = null;
|
|
445
368
|
}
|
|
446
|
-
terminal = genericRecoveryResponse(request, normalized.exitCode, payload, 'publish');
|
|
447
369
|
}
|
|
370
|
+
catch {
|
|
371
|
+
payload = null;
|
|
372
|
+
}
|
|
373
|
+
terminal = genericRecoveryResponse(request, normalized.exitCode, payload, 'publish');
|
|
448
374
|
}
|
|
449
375
|
if (!brokerOwns())
|
|
450
376
|
return false;
|
|
451
|
-
if (request.family === 'task-finalization' && normalized.exitCode === 0) {
|
|
452
|
-
const view = publishFinalizationTaskView(manifest, broker, request.id, 'healthy', null, null);
|
|
453
|
-
if (view.state === 'unknown')
|
|
454
|
-
return false;
|
|
455
|
-
}
|
|
456
377
|
const committed = writeSandboxControlResponse(manifest, terminal);
|
|
457
378
|
if (committed && fs.existsSync(path.join(manifest.processingDir, request.id, 'transitions'))) {
|
|
458
379
|
criticalRequestPhase(manifest, request, 'published-committed', normalized.exitCode === 0 ? 'success' : 'failure');
|
|
@@ -652,16 +573,11 @@ async function recoverProcessing(manifest, manifestPath, broker, brokerOwns) {
|
|
|
652
573
|
if (terminal && request && resultEvidence) {
|
|
653
574
|
if (!terminalResult && request.family !== 'task-create')
|
|
654
575
|
continue;
|
|
655
|
-
const reconciliation = await terminalMatchesEvidence(manifest,
|
|
576
|
+
const reconciliation = await terminalMatchesEvidence(manifest, request, existingTerminalResponse, resultEvidence, payload, payloadInvalid, terminalResult);
|
|
656
577
|
if (!reconciliation.valid)
|
|
657
578
|
continue;
|
|
658
579
|
terminalReconciled = true;
|
|
659
580
|
payloadReferenced = reconciliation.payloadReferenced;
|
|
660
|
-
if (request.family === 'task-finalization' && resultEvidence.exitCode === 0) {
|
|
661
|
-
const view = publishFinalizationTaskView(manifest, broker, request.id, 'starting', null, null);
|
|
662
|
-
if (view.state === 'unknown')
|
|
663
|
-
continue;
|
|
664
|
-
}
|
|
665
581
|
}
|
|
666
582
|
if (!terminalResult && !terminalReconciled) {
|
|
667
583
|
if (terminal)
|
|
@@ -688,11 +604,6 @@ async function recoverProcessing(manifest, manifestPath, broker, brokerOwns) {
|
|
|
688
604
|
const recovered = await recoveryResponse(manifest, manifestPath, request, resultEvidence, payload, terminalResult);
|
|
689
605
|
if (!recovered)
|
|
690
606
|
continue;
|
|
691
|
-
if (request.family === 'task-finalization' && resultEvidence.exitCode === 0) {
|
|
692
|
-
const view = publishFinalizationTaskView(manifest, broker, request.id, 'starting', null, null);
|
|
693
|
-
if (view.state === 'unknown')
|
|
694
|
-
continue;
|
|
695
|
-
}
|
|
696
607
|
writeSandboxControlResponse(manifest, recovered);
|
|
697
608
|
const preserveRecoveryEvidence = recovered.error?.code === 'SANDBOX_CONTROL_RESULT_UNKNOWN';
|
|
698
609
|
if (transitionProtocolActive && !preserveRecoveryEvidence) {
|
|
@@ -700,7 +611,7 @@ async function recoverProcessing(manifest, manifestPath, broker, brokerOwns) {
|
|
|
700
611
|
}
|
|
701
612
|
if (preserveRecoveryEvidence)
|
|
702
613
|
continue;
|
|
703
|
-
payloadReferenced = Boolean(payload)
|
|
614
|
+
payloadReferenced = Boolean(payload);
|
|
704
615
|
}
|
|
705
616
|
}
|
|
706
617
|
else {
|
|
@@ -794,14 +705,10 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
|
|
|
794
705
|
startupReceipt = readTaskFinalizationReceipt(manifest.repoRoot, manifest.taskId);
|
|
795
706
|
}
|
|
796
707
|
catch {
|
|
797
|
-
// Preserve malformed receipt evidence as unknown rather than treating it as no receipt.
|
|
798
708
|
startupReceipt = {};
|
|
799
709
|
}
|
|
800
710
|
}
|
|
801
|
-
let taskView = taskViewForManifest({
|
|
802
|
-
...manifest,
|
|
803
|
-
receipt: startupReceipt
|
|
804
|
-
});
|
|
711
|
+
let taskView = taskViewForManifest({ ...manifest, receipt: startupReceipt });
|
|
805
712
|
try {
|
|
806
713
|
const previous = readSandboxControlStatus(manifest.publicStatusDir);
|
|
807
714
|
if (previous.generation === manifest.generation)
|
|
@@ -983,17 +890,7 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
|
|
|
983
890
|
break;
|
|
984
891
|
let terminalCommitted = false;
|
|
985
892
|
if (settledExecution.result && settledExecution.resultEvidenceWritten) {
|
|
986
|
-
terminalCommitted = publishExecutionResult(manifest, settledExecution.request, settledExecution.result,
|
|
987
|
-
if (terminalCommitted && settledExecution.request.family === 'task-finalization') {
|
|
988
|
-
try {
|
|
989
|
-
const published = readSandboxControlStatus(manifest.publicStatusDir);
|
|
990
|
-
if (published.generation === manifest.generation)
|
|
991
|
-
taskView = published.taskView;
|
|
992
|
-
}
|
|
993
|
-
catch {
|
|
994
|
-
taskView = { state: 'unknown', taskId: manifest.taskId, observedSource: 'unknown', receipt: null, reasonCode: 'SANDBOX_TASK_VIEW_STATUS_INVALID' };
|
|
995
|
-
}
|
|
996
|
-
}
|
|
893
|
+
terminalCommitted = publishExecutionResult(manifest, settledExecution.request, settledExecution.result, brokerOwns);
|
|
997
894
|
}
|
|
998
895
|
else {
|
|
999
896
|
terminalCommitted = writeSandboxControlResponse(manifest, unknown(settledExecution.request.id));
|
|
@@ -1255,7 +1152,7 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
|
|
|
1255
1152
|
}
|
|
1256
1153
|
}
|
|
1257
1154
|
if (owned && active.result && active.resultEvidenceWritten) {
|
|
1258
|
-
if (publishExecutionResult(manifest, active.request, active.result,
|
|
1155
|
+
if (publishExecutionResult(manifest, active.request, active.result, brokerOwns)) {
|
|
1259
1156
|
if (brokerOwns()) {
|
|
1260
1157
|
removeAcceptedResponse(manifest, active.request.id);
|
|
1261
1158
|
fs.rmSync(path.join(manifest.processingDir, active.request.id), { recursive: true, force: true });
|
|
@@ -1264,22 +1161,8 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
|
|
|
1264
1161
|
}
|
|
1265
1162
|
}
|
|
1266
1163
|
if (active) {
|
|
1267
|
-
|
|
1268
|
-
if (owned && brokerOwns() && active
|
|
1269
|
-
const recovered = finalizationRecoveryResponse(manifest, active.request.id, 0);
|
|
1270
|
-
const view = recovered.status === 'matched'
|
|
1271
|
-
? publishFinalizationTaskView(manifest, broker, active.request.id, 'healthy', null, null)
|
|
1272
|
-
: null;
|
|
1273
|
-
if (view?.state !== 'unknown' && recovered.status === 'matched' && recovered.response
|
|
1274
|
-
&& writeSandboxControlResponse(manifest, recovered.response)) {
|
|
1275
|
-
if (terminationConfirmed && brokerOwns()) {
|
|
1276
|
-
removeAcceptedResponse(manifest, active.request.id);
|
|
1277
|
-
fs.rmSync(path.join(manifest.processingDir, active.request.id), { recursive: true, force: true });
|
|
1278
|
-
active = null;
|
|
1279
|
-
}
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
if (owned && brokerOwns() && active && active.request.family !== 'task-finalization' && !active.resultEvidenceWritten) {
|
|
1164
|
+
active.prepared.terminate(owned);
|
|
1165
|
+
if (owned && brokerOwns() && active && !active.resultEvidenceWritten) {
|
|
1283
1166
|
writeSandboxControlResponse(manifest, unknown(active.request.id));
|
|
1284
1167
|
}
|
|
1285
1168
|
}
|
|
@@ -8,7 +8,6 @@ import { enumerateAllTaskDirs } from '../task/resolve-ref.js';
|
|
|
8
8
|
import { resolveSandboxCleanupTarget } from './workspace-identity.js';
|
|
9
9
|
import { readSandboxControlManifest } from './control/lifecycle.js';
|
|
10
10
|
import { readJsonFile, readSandboxControlStatus } from './control/state.js';
|
|
11
|
-
import { finalizationTerminalResponse } from './control/finalization-response.js';
|
|
12
11
|
const TASK_ID_RE = /^TASK-\d{8}-\d{6}$/;
|
|
13
12
|
function matchingControlManifest(repoRoot, controlRoot, taskId, binding) {
|
|
14
13
|
if (!controlRootIdentity(controlRoot))
|
|
@@ -77,11 +76,9 @@ function canonicalPath(input) {
|
|
|
77
76
|
return path.resolve(input);
|
|
78
77
|
}
|
|
79
78
|
}
|
|
80
|
-
function taskFinalizationReceiptComplete(receipt, taskId
|
|
79
|
+
function taskFinalizationReceiptComplete(receipt, taskId) {
|
|
81
80
|
return receipt.taskId === taskId
|
|
82
|
-
&& taskFinalizationReceiptState(receipt) === 'complete'
|
|
83
|
-
&& receipt.controlBinding?.generation === binding.generation
|
|
84
|
-
&& receipt.controlBinding.requestId === binding.requestId;
|
|
81
|
+
&& taskFinalizationReceiptState(receipt) === 'complete';
|
|
85
82
|
}
|
|
86
83
|
function terminalControlBindingEvidence(repoRootInput, controlRootInput, taskId, binding) {
|
|
87
84
|
const repoRoot = canonicalPath(repoRootInput);
|
|
@@ -105,26 +102,22 @@ function terminalControlBindingEvidence(repoRootInput, controlRootInput, taskId,
|
|
|
105
102
|
return false;
|
|
106
103
|
}
|
|
107
104
|
const receipt = readTaskFinalizationReceipt(repoRoot, taskId);
|
|
108
|
-
if (!receipt || !taskFinalizationReceiptComplete(receipt, taskId
|
|
105
|
+
if (!receipt || !taskFinalizationReceiptComplete(receipt, taskId)) {
|
|
109
106
|
return false;
|
|
110
107
|
}
|
|
111
|
-
const status = readSandboxControlStatus(manifest.publicStatusDir);
|
|
112
|
-
const viewReceipt = status.taskView.receipt;
|
|
113
|
-
const terminalTaskView = (status.taskView.state === 'current' && status.taskView.observedSource === 'completed')
|
|
114
|
-
|| (status.taskView.state === 'finalized-stale' && status.taskView.observedSource === 'active');
|
|
115
|
-
if (status.generation !== binding.generation || status.state !== 'healthy'
|
|
116
|
-
|| status.activeRequestId !== null || !terminalTaskView || status.taskView.taskId !== taskId
|
|
117
|
-
|| !viewReceipt || viewReceipt.generation !== binding.generation
|
|
118
|
-
|| viewReceipt.requestId !== binding.requestId
|
|
119
|
-
|| viewReceipt.receiptId !== receipt.receiptId
|
|
120
|
-
|| viewReceipt.revision !== receipt.revision)
|
|
121
|
-
return false;
|
|
122
108
|
const responsePath = path.join(manifest.channelDir, 'responses', `${binding.requestId}.json`);
|
|
123
109
|
if (!inspectOwnedPath(path.join(controlRoot, 'channel'), responsePath, 'file'))
|
|
124
110
|
return false;
|
|
125
111
|
const actual = readJsonFile(responsePath);
|
|
126
|
-
const
|
|
127
|
-
|
|
112
|
+
const response = actual;
|
|
113
|
+
if (response.version !== 2 || response.id !== binding.requestId || response.phase !== 'completed'
|
|
114
|
+
|| response.exitCode !== 0 || typeof response.stdout !== 'string')
|
|
115
|
+
return false;
|
|
116
|
+
const envelope = JSON.parse(response.stdout);
|
|
117
|
+
const result = envelope.result;
|
|
118
|
+
return envelope.status === 'completed' && envelope.accepted === true
|
|
119
|
+
&& result !== null && typeof result === 'object'
|
|
120
|
+
&& result.status === 'completed' && result.taskId === taskId;
|
|
128
121
|
}
|
|
129
122
|
catch {
|
|
130
123
|
return false;
|
|
@@ -153,7 +146,7 @@ function removedControlBindingEvidence(repoRootInput, journal, taskId, binding)
|
|
|
153
146
|
return false;
|
|
154
147
|
try {
|
|
155
148
|
const receipt = readTaskFinalizationReceipt(repoRoot, taskId);
|
|
156
|
-
return receipt !== null && taskFinalizationReceiptComplete(receipt, taskId
|
|
149
|
+
return receipt !== null && taskFinalizationReceiptComplete(receipt, taskId);
|
|
157
150
|
}
|
|
158
151
|
catch {
|
|
159
152
|
return false;
|
|
@@ -13,7 +13,7 @@ export function parseArtifactCommand(args) {
|
|
|
13
13
|
}
|
|
14
14
|
const fields = {};
|
|
15
15
|
const allowed = {
|
|
16
|
-
inspect: ['--family'],
|
|
16
|
+
inspect: ['--family', '--source-finding', '--source-artifact', '--source-sha256'],
|
|
17
17
|
init: ['--family', '--artifact', '--locale'],
|
|
18
18
|
'preflight': ['--family', '--artifact'],
|
|
19
19
|
'finalize-local': ['--family', '--artifact']
|
|
@@ -37,8 +37,10 @@ export function parseArtifactCommand(args) {
|
|
|
37
37
|
if (locale !== undefined && locale !== 'zh-CN' && locale !== 'en')
|
|
38
38
|
throw new Error("option '--locale' must be 'zh-CN' or 'en'");
|
|
39
39
|
return {
|
|
40
|
-
taskRef, operation: operation, family: fields['--family'],
|
|
41
|
-
artifact: fields['--artifact'] ?? '', locale
|
|
40
|
+
taskRef, operation: operation, family: fields['--family'] ?? '',
|
|
41
|
+
artifact: fields['--artifact'] ?? '', locale,
|
|
42
|
+
sourceFinding: fields['--source-finding'], sourceArtifact: fields['--source-artifact'],
|
|
43
|
+
sourceSha256: fields['--source-sha256']
|
|
42
44
|
};
|
|
43
45
|
}
|
|
44
46
|
/** Resolve authoritative task metadata separately from a trusted candidate directory. */
|
|
@@ -46,7 +48,12 @@ export function executeArtifactCommand(command, options = {}) {
|
|
|
46
48
|
const { taskRef, operation, family, artifact, locale } = command;
|
|
47
49
|
const fail = (code, message) => ({ status: 'failed', changed: false, error: { code, message } });
|
|
48
50
|
if (operation === 'inspect') {
|
|
49
|
-
const result = resolveArtifactContext(taskRef, family, {
|
|
51
|
+
const result = resolveArtifactContext(taskRef, family, {
|
|
52
|
+
repoRoot: options.repoRoot,
|
|
53
|
+
sourceFinding: command.sourceFinding,
|
|
54
|
+
sourceArtifact: command.sourceArtifact,
|
|
55
|
+
sourceSha256: command.sourceSha256
|
|
56
|
+
});
|
|
50
57
|
return family === 'code' && result.codeMode ? {
|
|
51
58
|
...result, mode: result.codeMode.mode, code_max: result.codeMode.codeMax, rev_max: result.codeMode.reviewMax,
|
|
52
59
|
verdict: result.codeMode.verdict, next_round: result.next?.round ?? null, next_artifact: result.next?.name ?? null,
|