Files
Genarrative/apps/ai-game-creator-shell/scripts/agent-runtime-real-e2e/suites/goal.mjs
T
AIGameCreator App be89296492 拆分 AI 游戏创作客户端大型模块
拆分 App 认证、壳层、运行配置与项目摘要模块
拆分 Tauri 项目能力与 Rust 测试领域模块
拆分界面测试与 Agent Runtime 真实 E2E 套件
补充源码扫描和客户端模块化文档约定
2026-07-21 22:53:29 +08:00

2329 lines
82 KiB
JavaScript

import {
assert,
codedError,
hashValue,
isFailedTask,
sleep,
} from '../assertions/core.mjs';
import {
actionAuditIdentity,
assertNoPersistedImagePayload,
auditInputValue,
auditPatchsetPathsInclude,
auditPathEquals,
canonicalAuditInputSummary,
collectNativeRuntimeToolPlanProtocolEvidence,
countExactSecrets,
duplicateCount,
emptyToolPlanRepairCountsByProtocolErrorKind,
finalMessageId,
findSuccessfulToolExecution,
isNonEmptyString,
receiptAuditIdentity,
sumObjectValues,
validateNativeRuntimeToolPlanProtocolEvidence,
validateToolActionReplays,
} from '../assertions/runtime.mjs';
import { fs, path } from '../dependencies.mjs';
import {
claimOwnedRunner,
ensureOwnedRunnerStableKillSupport,
prepareIsolatedSuiteAppData,
} from '../harness/app-data.mjs';
import {
isLiveTask,
listFiles,
parseAssignedJson,
readJson,
readOptionalJsonl,
relativeProjectPath,
resolveProjectRelative,
} from '../harness/io.mjs';
import { prepareCliBinary, runCli, runProcess } from '../harness/process.mjs';
import {
assertResultOrientedDisposableTask,
seedDisposableProject,
} from '../harness/project.mjs';
import {
collectPartialRuntimeJsonlSurface,
readLatestJsonFile,
} from '../harness/reporting.mjs';
import {
agentConversationPath,
assertStructuredPlanAuditSnapshot,
buildTaskSnapshot,
confirmPendingActions,
countLureLeaks,
countMarkerOutsideRuntimeControl,
findPendingActions,
hasExpectedWorkspaceSandboxMetadata,
inspectStructuredPlanSnapshot,
killRunnerOnce,
mainContextBundlePath,
mainRuntimeStatePath,
readAllRuntimeEvents,
readRunnerStatus,
readTaskSnapshot,
runnerBootId,
validateProjectRootPublicLeakBoundary,
waitForCanonicalRuntime,
waitForRunnerBootChange,
} from '../harness/runtime.mjs';
import {
commandDiagnosticLineCount,
commandFailureMarker,
commandPassedMarker,
commandRootErrorLine,
commandRootErrorMarker,
goalDeliveryPath,
goalEditedPayload,
goalFailureEvidenceCanary,
goalFinalMarker,
goalInitialMarker,
goalInitialPayload,
goalProjectWriteTools,
goalRuntimeSuite,
goalSessionId,
mainAgentId,
patchedText,
patchsetCreatedContent,
patchsetCreatedMarker,
patchsetCreatedPath,
pollIntervalMs,
providerRequestLifecycleSchemaVersion,
requestedRunId,
runtimeContextBundleSchemaVersion,
runTimeoutMs,
state,
verificationCommand,
visibleText,
} from '../runtime-state.mjs';
export async function runGoalRuntimeE2e() {
await ensureOwnedRunnerStableKillSupport();
await seedDisposableProject();
await assertGoalInitialMarkerAbsent('goal-project-seeded');
state.cliBinary = await prepareCliBinary();
await prepareIsolatedSuiteAppData();
assertGoalPayloadUnscripted(goalInitialPayload, 'goal-initial');
assertGoalPayloadUnscripted(goalEditedPayload, 'goal-edited');
state.initialTask = {
chars: [...goalInitialPayload.outcome].length,
sha256: hashValue(goalInitialPayload.outcome),
};
state.isolatedRunner.launchAttempted = true;
const started = parseGoalMutation(
await runCli(
[
'--agent-goal-start',
'--init',
state.projectRoot,
mainAgentId,
goalSessionId,
requestedRunId,
'--stdin',
],
{
timeoutMs: 120_000,
stdin: `${JSON.stringify(goalInitialPayload)}\n`,
},
),
);
assertGoalMutationIdentity(started, 1, 'goal-start');
state.goal.goalId = started.goal.goalId;
state.goal.initialRevision = started.goal.revision;
state.initialRunId = started.goal.runId;
state.initialSessionId = started.goal.sessionId;
await claimOwnedRunner();
const canonicalRuntime = await waitForCanonicalRuntime();
assert(
canonicalRuntime.agentId === mainAgentId &&
canonicalRuntime.sessionId === state.initialSessionId &&
canonicalRuntime.runId === state.initialRunId &&
canonicalRuntime.goalId === state.goal.goalId &&
canonicalRuntime.goalRevision === state.goal.initialRevision &&
canonicalRuntime.goalStatus === 'active',
'goal-start-canonical-runtime-invalid',
);
const initialPending = await waitForGoalRevisionPendingAction({
revision: state.goal.initialRevision,
marker: goalInitialMarker,
codePrefix: 'goal-initial',
});
state.goal.initialCompletedStepHashes = [
...initialPending.plan.completedStepHashes,
];
state.goal.initialPending = summarizeGoalPending(initialPending.pending);
await assertGoalInitialMarkerAbsent(
'goal-initial-pending-before-edit',
initialPending.pending.actionId,
);
const [deliveryBeforeEdit, finalMarkerBeforeEdit] = await Promise.all([
fs.lstat(path.join(state.projectRoot, goalDeliveryPath)).catch((error) => {
if (error?.code === 'ENOENT') return null;
throw error;
}),
countMarkerOutsideRuntimeControl(goalFinalMarker),
]);
assert(
deliveryBeforeEdit === null && finalMarkerBeforeEdit === 0,
'goal-edited-evidence-present-before-edit',
);
state.goal.editedEvidenceAbsentBeforeEdit = true;
await assertGoalRevisionOneFixtureIsolation();
await injectGoalRevisionTwoFixtureAndProveFailure();
state.goal.revisionTwoEditAgentDbBoundary = (
await readOptionalJsonl(path.join(state.projectRoot, '.agent/agent.db'))
).length;
const edited = parseGoalMutation(
await runCli(
[
'--agent-goal-edit',
state.projectRoot,
mainAgentId,
state.initialSessionId,
state.goal.goalId,
String(state.goal.initialRevision),
'--stdin',
],
{
timeoutMs: 120_000,
stdin: `${JSON.stringify(goalEditedPayload)}\n`,
},
),
);
assertGoalMutationIdentity(edited, 2, 'goal-edit');
state.goal.editedRevision = edited.goal.revision;
state.goal.editProviderInterrupted = edited.providerInterrupted === true;
await waitForGoalOldActionBlocked(initialPending.pending);
await waitForGoalRevisionTwoAgentVerificationFailure();
const editedPending = await waitForGoalRevisionPendingAction({
revision: state.goal.editedRevision,
codePrefix: 'goal-edited',
minimumPlanRevision: initialPending.plan.revision + 1,
requiredCompletedStepHashes: state.goal.initialCompletedStepHashes,
pendingMatcher: goalPendingMatchesRevisionTwoRepair,
});
state.goal.editedPending = summarizeGoalPending(editedPending.pending);
const paused = parseGoalMutation(
await runCli(
[
'--agent-goal-pause',
state.projectRoot,
mainAgentId,
state.initialSessionId,
state.goal.goalId,
String(state.goal.editedRevision),
],
{ timeoutMs: 120_000 },
),
);
assertGoalMutationIdentity(paused, state.goal.editedRevision, 'goal-pause');
assert(
paused.goal.status === 'paused' &&
paused.runtime?.state?.status === 'paused' &&
paused.runtime?.state?.phase === 'paused',
'goal-pause-not-durable',
);
state.goal.pauseProviderInterrupted = paused.providerInterrupted === true;
const beforeKillRunner = await readRunnerStatus();
state.goal.oldRunnerBootId = runnerBootId(beforeKillRunner);
assert(
isNonEmptyString(state.goal.oldRunnerBootId),
'goal-runner-boot-before-kill-missing',
);
state.goal.pauseSnapshot = await captureGoalPausedSnapshot(
editedPending.pending,
'goal-paused-before-kill',
);
await killRunnerOnce();
await runCli(['--agent-resume', state.projectRoot], { timeoutMs: 120_000 });
state.resumed = true;
const restartedRunner = await waitForRunnerBootChange(
state.goal.oldRunnerBootId,
);
state.goal.newRunnerBootId = runnerBootId(restartedRunner);
assert(
isNonEmptyString(state.goal.newRunnerBootId) &&
state.goal.newRunnerBootId !== state.goal.oldRunnerBootId,
'goal-runner-boot-did-not-change',
);
await claimOwnedRunner(restartedRunner);
state.goal.executionOwnerRecovered =
await waitForGoalExecutionOwnerTakeover();
await assertGoalRemainsPausedAfterRestart(
state.goal.pauseSnapshot,
editedPending.pending,
);
const resumed = parseGoalMutation(
await runCli(
[
'--agent-goal-resume',
state.projectRoot,
mainAgentId,
state.initialSessionId,
state.goal.goalId,
String(state.goal.editedRevision),
],
{ timeoutMs: 120_000 },
),
);
assertGoalMutationIdentity(resumed, state.goal.editedRevision, 'goal-resume');
assert(
resumed.goal.status === 'active' &&
resumed.goal.runId === state.initialRunId &&
['pending', 'waiting-for-confirmation', 'running'].includes(
resumed.runtime?.state?.status,
),
'goal-explicit-resume-invalid',
);
state.identityStable = true;
await driveGoalRuntimeToQuiescence();
state.evidence = await validateGoalRuntimeEvidence();
assert(state.evidence.secretLeakCount === 0, 'loaded-key-leak-detected');
}
export function goalRevisionOneVerificationFixtureSource() {
return `import fs from 'node:fs';\nconst html = fs.readFileSync('game/index.html', 'utf8');\nconst agents = fs.readFileSync('AGENTS.md', 'utf8');\nconst passed = html.includes(${JSON.stringify(visibleText)}) && html.includes('<canvas') && html.includes('requestAnimationFrame') && agents.includes('REPOSITORY_CONTEXT_MARKER');\nif (!passed) process.exit(1);\nconsole.log(${JSON.stringify(commandPassedMarker)});\n`;
}
export function goalRevisionTwoVerificationFixtureSource() {
return `import fs from 'node:fs';\nconst html = fs.readFileSync('game/index.html', 'utf8');\nconst agents = fs.readFileSync('AGENTS.md', 'utf8');\nconst requiredCreatedContent = ${JSON.stringify(patchsetCreatedContent)};\nconst patchsetFile = fs.existsSync('${patchsetCreatedPath}') ? fs.readFileSync('${patchsetCreatedPath}', 'utf8') : '';\nconst passed = html.includes('${patchedText}') && html.includes('<canvas') && html.includes('requestAnimationFrame') && agents.includes('REPOSITORY_CONTEXT_MARKER') && patchsetFile === requiredCreatedContent;\nif (!passed) {\n const rootMarker = [${JSON.stringify(commandRootErrorMarker.slice(0, 20))}, ${JSON.stringify(commandRootErrorMarker.slice(20))}].join('');\n for (let line = 1; line <= ${commandDiagnosticLineCount}; line += 1) {\n if (line === 1) console.error('${commandFailureMarker}');\n if (line === ${commandRootErrorLine}) {\n console.error(\`ROOT_CAUSE marker=\${rootMarker} repairPath=game/index.html old=REAL_E2E_TARGET:before new=${patchedText} createPath=${patchsetCreatedPath} createContentJson=\${JSON.stringify(requiredCreatedContent)}\`);\n } else {\n console.error(\`diagnostic-line-\${String(line).padStart(3, '0')} ${'x'.repeat(72)}\`);\n }\n }\n process.exit(1);\n}\nconsole.log('${commandPassedMarker}');\n`;
}
export async function assertGoalRevisionOneFixtureIsolation() {
const fixturePath = path.join(state.projectRoot, 'verify-e2e.mjs');
const fixture = await fs.readFile(fixturePath, 'utf8');
for (const forbidden of [
commandFailureMarker,
commandRootErrorMarker,
patchedText,
patchsetCreatedPath,
patchsetCreatedMarker,
]) {
assert(
!fixture.includes(forbidden),
'goal-revision-two-clue-visible-in-revision-one',
);
}
const verification = await runProcess(process.execPath, ['verify-e2e.mjs'], {
cwd: state.projectRoot,
timeoutMs: 120_000,
});
assert(
verification.stdout.includes(commandPassedMarker),
'goal-revision-one-fixture-not-passing',
);
state.goal.revisionOneFixtureIsolated = true;
}
export async function injectGoalRevisionTwoFixtureAndProveFailure() {
assert(
state.goal.revisionOneFixtureIsolated,
'goal-revision-one-isolation-not-proven',
);
const gameHtml = await fs.readFile(
path.join(state.projectRoot, 'game/index.html'),
'utf8',
);
const patchsetMetadata = await fs
.lstat(path.join(state.projectRoot, patchsetCreatedPath))
.catch((error) => {
if (error?.code === 'ENOENT') return null;
throw error;
});
assert(
gameHtml.includes('REAL_E2E_TARGET:before') &&
!gameHtml.includes(patchedText) &&
patchsetMetadata === null,
'goal-revision-two-failure-precondition-missing',
);
await assertGoalInitialMarkerAbsent('goal-revision-two-fixture-before-write');
await fs.writeFile(
path.join(state.projectRoot, 'verify-e2e.mjs'),
goalRevisionTwoVerificationFixtureSource(),
);
await assertGoalInitialMarkerAbsent('goal-revision-two-fixture-after-write');
state.goal.revisionTwoFixtureInjected = true;
const verification = await runProcess(process.execPath, ['verify-e2e.mjs'], {
cwd: state.projectRoot,
timeoutMs: 120_000,
allowNonZero: true,
});
const exactRootCause = `ROOT_CAUSE marker=${commandRootErrorMarker} repairPath=game/index.html old=REAL_E2E_TARGET:before new=${patchedText} createPath=${patchsetCreatedPath} createContentJson=${JSON.stringify(patchsetCreatedContent)}`;
assert(
verification.code === 1 &&
verification.signal === null &&
verification.stderr.includes(commandFailureMarker) &&
verification.stderr.includes(exactRootCause),
'goal-revision-two-real-failure-not-observed',
);
state.goal.revisionTwoHostFailureObserved = true;
}
export function assertGoalPayloadUnscripted(payload, codePrefix) {
assert(
payload &&
isNonEmptyString(payload.outcome) &&
Array.isArray(payload.constraints) &&
payload.constraints.length > 0 &&
Array.isArray(payload.verification) &&
payload.verification.length > 0,
`${codePrefix}-payload-invalid`,
);
assertResultOrientedDisposableTask(
[payload.outcome, ...payload.constraints, ...payload.verification].join(
'\n',
),
codePrefix,
);
}
export function goalPrivateBodyValues() {
return [
goalInitialPayload.outcome,
...goalInitialPayload.constraints,
...goalInitialPayload.verification,
goalEditedPayload.outcome,
...goalEditedPayload.constraints,
...goalEditedPayload.verification,
goalInitialMarker,
goalFinalMarker,
goalFailureEvidenceCanary,
];
}
export function goalPublicBodyValues() {
return [
goalInitialPayload.outcome,
...goalInitialPayload.constraints,
...goalInitialPayload.verification,
goalEditedPayload.outcome,
...goalEditedPayload.constraints,
...goalEditedPayload.verification,
goalInitialMarker,
goalFinalMarker,
goalFailureEvidenceCanary,
];
}
export function parseGoalMutation(result) {
const mutation = parseAssignedJson(result.stdout, ['goalMutationJson']);
assert(
mutation?.goal &&
mutation?.runtime?.state &&
typeof mutation.providerInterrupted === 'boolean',
'goal-mutation-json-invalid',
);
return mutation;
}
export function assertGoalMutationIdentity(
mutation,
expectedRevision,
codePrefix,
) {
const goal = mutation.goal;
const runtime = mutation.runtime.state;
const payload =
expectedRevision === state.goal.initialRevision || expectedRevision === 1
? goalInitialPayload
: goalEditedPayload;
const runtimeIdentityMatches =
runtime.runId === goal.runId &&
runtime.agentId === goal.agentId &&
runtime.sessionId === goal.sessionId &&
runtime.goalId === goal.goalId &&
runtime.goalRevision === goal.revision &&
runtime.goalStatus === goal.status;
const queuedStartMatches =
codePrefix === 'goal-start' &&
mutation.runtime.recentTasks?.some(
(task) =>
task.agentId === goal.agentId &&
task.sessionId === goal.sessionId &&
task.runId === goal.runId &&
task.goalId === goal.goalId &&
task.goalRevision === goal.revision &&
task.goalStatus === goal.status &&
task.status === 'pending',
);
assert(
goal.schemaVersion === 'game-creator-agent-goal.v1' &&
isNonEmptyString(goal.projectId) &&
goal.agentId === mainAgentId &&
goal.sessionId === goalSessionId &&
goal.runId === requestedRunId &&
goal.revision === expectedRevision &&
goal.outcome === payload.outcome &&
JSON.stringify(goal.constraints) ===
JSON.stringify(payload.constraints) &&
JSON.stringify(goal.verification) ===
JSON.stringify(payload.verification) &&
(runtimeIdentityMatches || queuedStartMatches),
`${codePrefix}-identity-invalid`,
);
}
export function goalSnapshotFingerprint(goal) {
// serde_json::Map uses lexicographically sorted keys without preserve_order.
return hashValue(
JSON.stringify({
agentId: goal.agentId,
constraints: goal.constraints,
goalId: goal.goalId,
outcome: goal.outcome,
projectId: goal.projectId,
revision: goal.revision,
runId: goal.runId,
sessionId: goal.sessionId,
verification: goal.verification,
}),
);
}
export async function readGoalStatus() {
const result = await runCli(
[
'--agent-goal-status',
state.projectRoot,
mainAgentId,
state.initialSessionId,
],
{ timeoutMs: 60_000 },
);
const goal = parseAssignedJson(result.stdout, ['goalJson']);
assert(goal && typeof goal === 'object', 'goal-status-json-invalid');
return goal;
}
export async function assertGoalRuntimeCanProgress(codePrefix) {
const [taskSnapshot, runtime] = await Promise.all([
readTaskSnapshot(),
readJson(mainRuntimeStatePath()).catch(() => null),
]);
const current = taskSnapshot.latest.find(
(task) => task.agentId === mainAgentId && task.runId === state.initialRunId,
);
if (current && isFailedTask(current)) {
throw codedError(`${codePrefix}-runtime-failed`);
}
if (
runtime?.status === 'needs-reconciliation' ||
runtime?.phase === 'needs-reconciliation'
) {
throw codedError(`${codePrefix}-runtime-needs-reconciliation`);
}
}
export function assertGoalContextSnapshot(
runtime,
contextBundle,
goal,
codePrefix,
) {
const expectedGoalSnapshotFingerprint = goalSnapshotFingerprint(goal);
assert(
contextBundle.schemaVersion === runtimeContextBundleSchemaVersion &&
contextBundle.projectId === goal.projectId &&
contextBundle.agentId === runtime.agentId &&
contextBundle.taskId === runtime.taskId &&
contextBundle.sessionId === runtime.sessionId &&
contextBundle.runId === runtime.runId &&
contextBundle.goalId === goal.goalId &&
contextBundle.goalRevision === goal.revision &&
contextBundle.goalStatus === 'active' &&
contextBundle.goalSnapshotFingerprint ===
expectedGoalSnapshotFingerprint &&
runtime.goalId === goal.goalId &&
runtime.goalRevision === goal.revision &&
runtime.goalStatus === goal.status &&
runtime.goalOutcome === goal.outcome &&
JSON.stringify(runtime.goalConstraints) ===
JSON.stringify(goal.constraints) &&
JSON.stringify(runtime.goalVerification) ===
JSON.stringify(goal.verification) &&
contextBundle.planRevision === runtime.planRevision &&
contextBundle.planExplanation === runtime.planExplanation &&
JSON.stringify(contextBundle.planSteps) ===
JSON.stringify(runtime.planSteps) &&
contextBundle.activePlanStepIndex === runtime.activePlanStepIndex,
`${codePrefix}-context-snapshot-mismatch`,
);
}
export async function readVerifiedGoalPlanSnapshot(codePrefix) {
const [runtime, contextBundle, records, goal] = await Promise.all([
readJson(mainRuntimeStatePath()),
readJson(mainContextBundlePath()),
readOptionalJsonl(path.join(state.projectRoot, '.agent/agent.db')),
readGoalStatus(),
]);
assert(goal.status === 'active', `${codePrefix}-goal-not-active`);
const snapshot = inspectStructuredPlanSnapshot(runtime, codePrefix);
assertGoalContextSnapshot(runtime, contextBundle, goal, codePrefix);
assertStructuredPlanAuditSnapshot(runtime, records, `${codePrefix}-audit`);
return { ...snapshot, runtime, contextBundle, goal, records };
}
export function goalPendingDeliveryMutation(pending) {
const action = pending?.record?.action ?? pending?.action;
const input = action?.input;
if (!action || !input || typeof input !== 'object') return null;
if (action.tool === 'file.write') {
return {
tool: action.tool,
path: input.path,
content: input.content,
};
}
if (action.tool !== 'project.patchset' || !Array.isArray(input.changes)) {
return null;
}
const matchingChanges = input.changes.filter(
(change) =>
change?.operation === 'create' && change?.path === goalDeliveryPath,
);
if (matchingChanges.length !== 1) return null;
return {
tool: action.tool,
path: matchingChanges[0].path,
content: matchingChanges[0].content,
};
}
export function goalPendingMatchesDelivery(pending, marker) {
const mutation = goalPendingDeliveryMutation(pending);
return (
mutation?.path === goalDeliveryPath && mutation.content === `${marker}\n`
);
}
export function goalPendingIsStandaloneDeliveryMutation(pending, marker) {
if (!goalPendingMatchesDelivery(pending, marker)) return false;
const action = pending?.record?.action ?? pending?.action;
return (
action?.tool === 'file.write' ||
(action?.tool === 'project.patchset' && action.input?.changes?.length === 1)
);
}
export function goalPendingMatchesRevisionTwoRepair(pending) {
const action = pending?.record?.action ?? pending?.action;
const input = action?.input;
if (!action || !input || typeof input !== 'object') return false;
if (action.tool === 'file.patch') {
return input.path === 'game/index.html';
}
if (action.tool === 'file.write') {
return (
input.path === 'game/index.html' || input.path === patchsetCreatedPath
);
}
return (
action.tool === 'project.patchset' &&
Array.isArray(input.changes) &&
input.changes.some(
(change) =>
change?.path === 'game/index.html' ||
change?.path === patchsetCreatedPath,
)
);
}
export function validateGoalPendingAction(pending, plan, revision, codePrefix) {
const record = pending.record;
const expectedGoalSnapshotFingerprint = goalSnapshotFingerprint(plan.goal);
assert(
record?.schemaVersion === 'game-creator-pending-action.v5' &&
record.agentId === mainAgentId &&
record.taskId === plan.runtime.taskId &&
record.sessionId === state.initialSessionId &&
record.runId === state.initialRunId &&
record.goalId === state.goal.goalId &&
record.goalRevision === revision &&
record.goalSnapshotFingerprint === expectedGoalSnapshotFingerprint &&
plan.contextBundle.goalSnapshotFingerprint ===
expectedGoalSnapshotFingerprint &&
isNonEmptyString(record.actionId) &&
isNonEmptyString(record.actionFingerprint) &&
record.actionId === pending.actionId &&
record.action?.tool === pending.tool &&
['pending', 'pending-confirmation'].includes(record.status) &&
Number.isSafeInteger(record.plannedSteerCursor),
`${codePrefix}-pending-action-invalid`,
);
if (revision === state.goal.initialRevision) {
assert(
state.goal.initialGoalSnapshotFingerprint == null ||
state.goal.initialGoalSnapshotFingerprint ===
expectedGoalSnapshotFingerprint,
`${codePrefix}-initial-goal-fingerprint-changed`,
);
state.goal.initialGoalSnapshotFingerprint = expectedGoalSnapshotFingerprint;
} else if (revision === state.goal.editedRevision) {
assert(
isNonEmptyString(state.goal.initialGoalSnapshotFingerprint) &&
expectedGoalSnapshotFingerprint !==
state.goal.initialGoalSnapshotFingerprint,
`${codePrefix}-goal-fingerprint-did-not-change`,
);
state.goal.editedGoalSnapshotFingerprint = expectedGoalSnapshotFingerprint;
}
}
export async function waitForGoalRevisionPendingAction({
revision,
codePrefix,
minimumPlanRevision = 1,
requiredCompletedStepHashes = [],
marker = null,
pendingMatcher = null,
}) {
const matchesPending =
pendingMatcher ??
((pending) => goalPendingMatchesDelivery(pending, marker));
assert(
typeof matchesPending === 'function' &&
(pendingMatcher || isNonEmptyString(marker)),
`${codePrefix}-pending-matcher-invalid`,
);
const deadline = Date.now() + runTimeoutMs;
let lastError = null;
while (Date.now() < deadline) {
await assertGoalInitialMarkerAbsent(`${codePrefix}-poll`);
const taskSnapshot = await readTaskSnapshot();
const initial = taskSnapshot.latest.find(
(task) =>
task.agentId === mainAgentId && task.runId === state.initialRunId,
);
if (initial && isFailedTask(initial)) {
throw codedError(`${codePrefix}-runtime-failed-before-pending`);
}
if (initial && !isLiveTask(initial)) {
throw codedError(`${codePrefix}-runtime-terminal-before-pending`);
}
let plan = null;
let targetPending = null;
try {
const pendingActions = (await findPendingActions()).filter(
(pending) =>
pending.agentId === mainAgentId &&
pending.runId === state.initialRunId,
);
targetPending = pendingActions.find(matchesPending);
plan = await readVerifiedGoalPlanSnapshot(`${codePrefix}-plan`);
} catch (error) {
if (targetPending) {
throw codedError(`${codePrefix}-pending-contract-invalid`, error);
}
lastError = error;
}
if (targetPending) {
validateGoalPendingAction(targetPending, plan, revision, codePrefix);
assert(
plan.revision >= minimumPlanRevision &&
plan.completedStepHashes.length > 0 &&
plan.incompleteStepCount > 0 &&
requiredCompletedStepHashes.every((stepHash) =>
plan.completedStepHashes.includes(stepHash),
),
`${codePrefix}-partial-plan-missing`,
);
const messages = await readOptionalJsonl(
agentConversationPath(mainAgentId, state.initialSessionId),
);
assert(
messages.filter((message) => message.role === 'assistant').length === 0,
`${codePrefix}-assistant-before-control-point`,
);
return { pending: targetPending, plan };
}
await confirmPendingActions(null, (pending) => !matchesPending(pending));
await sleep(pollIntervalMs);
}
throw codedError(`${codePrefix}-pending-action-timeout`, lastError);
}
export function summarizeGoalPending(pending) {
return {
actionId: pending.actionId,
actionFingerprint: pending.record.actionFingerprint,
goalRevision: pending.record.goalRevision,
schemaVersion: pending.record.schemaVersion,
tool: pending.tool,
};
}
export function goalOldActionExecutionEvidence(records, actionId) {
const executing = records.filter(
(record) =>
record.actionId === actionId &&
[
'agent.runtime.tool_action.executing',
'agent.runtime.tool_confirmation.approved',
].includes(record.recordType),
);
const successfulReceipts = records.filter(
(record) =>
record.recordType === 'agent.runtime.action_receipt' &&
record.actionId === actionId &&
['ok', 'command-failed'].includes(record.status),
);
return {
executionCount: executing.length,
successfulReceiptCount: successfulReceipts.length,
};
}
export async function waitForGoalOldActionBlocked(initialPending) {
const deadline = Date.now() + 120_000;
let lastError = null;
while (Date.now() < deadline) {
await assertGoalRuntimeCanProgress('goal-old-action-block');
await assertGoalInitialMarkerAbsent(
'goal-old-action-block-poll',
initialPending.actionId,
);
try {
const [runtime, contextBundle, records, goal, oldMarkerCount] =
await Promise.all([
readJson(mainRuntimeStatePath()),
readJson(mainContextBundlePath()),
readOptionalJsonl(path.join(state.projectRoot, '.agent/agent.db')),
readGoalStatus(),
countMarkerOutsideRuntimeControl(goalInitialMarker),
]);
const execution = goalOldActionExecutionEvidence(
records,
initialPending.actionId,
);
assert(
execution.executionCount === 0 &&
execution.successfulReceiptCount === 0 &&
oldMarkerCount === 0,
'goal-old-action-executed',
);
const blocked = (contextBundle.observations ?? []).filter(
(observation) =>
observation?.tool === 'runtime.goal' &&
observation?.status === 'blocked',
);
const blockedReceipts = records.filter(
(record) =>
record.recordType === 'agent.runtime.action_receipt' &&
record.agentId === mainAgentId &&
record.runId === state.initialRunId &&
record.actionId === initialPending.actionId &&
record.tool === 'runtime.goal' &&
record.status === 'blocked',
);
if (
goal.revision === state.goal.editedRevision &&
goal.status === 'active' &&
runtime.runId === state.initialRunId &&
runtime.sessionId === state.initialSessionId &&
runtime.goalId === state.goal.goalId &&
runtime.goalRevision === state.goal.editedRevision &&
contextBundle.schemaVersion === runtimeContextBundleSchemaVersion &&
contextBundle.goalId === state.goal.goalId &&
contextBundle.goalRevision === state.goal.editedRevision &&
contextBundle.goalSnapshotFingerprint ===
goalSnapshotFingerprint(goal) &&
contextBundle.goalSnapshotFingerprint !==
state.goal.initialGoalSnapshotFingerprint &&
blocked.length >= 1 &&
blockedReceipts.length === 1
) {
state.goal.initialPending.blockedObservationCount = blocked.length;
state.goal.initialPending.blockedReceiptCount = blockedReceipts.length;
return;
}
lastError = codedError('goal-old-action-block-not-yet-observed');
} catch (error) {
lastError = error;
}
await sleep(pollIntervalMs);
}
throw codedError('goal-old-action-block-timeout', lastError);
}
export async function waitForGoalRevisionTwoAgentVerificationFailure() {
assert(
state.goal.revisionTwoFixtureInjected === true &&
state.goal.revisionTwoHostFailureObserved === true &&
Number.isSafeInteger(state.goal.revisionTwoEditAgentDbBoundary),
'goal-revision-two-agent-failure-precondition-invalid',
);
const deadline = Date.now() + runTimeoutMs;
let lastError = null;
while (Date.now() < deadline) {
await assertGoalRuntimeCanProgress('goal-revision-two-agent-failure');
await assertGoalInitialMarkerAbsent('goal-revision-two-verify-poll');
const records = await readOptionalJsonl(
path.join(state.projectRoot, '.agent/agent.db'),
);
const failure = findGoalRevisionTwoAgentVerificationFailure(records);
if (failure) {
const contextBundle = await readJson(mainContextBundlePath());
const failedObservations = (contextBundle.observations ?? []).filter(
(observation) =>
observation?.tool === 'project.verify' &&
observation?.status === 'failed',
);
if (failedObservations.length === 0) {
lastError = codedError(
'goal-revision-two-failed-observation-not-checkpointed',
);
await sleep(pollIntervalMs);
continue;
}
const logPath = resolveProjectRelative(failure.audit.logPath);
assert(
relativeProjectPath(logPath).startsWith('.agent/') &&
failure.audit.exitCode === 1 &&
failure.audit.timedOut === false,
'goal-revision-two-failed-verification-audit-invalid',
);
const log = await fs.readFile(logPath);
assert(
countExactSecrets(log, [commandRootErrorMarker]) === 1 &&
log.includes(Buffer.from(commandFailureMarker)),
'goal-revision-two-failed-verification-log-invalid',
);
state.goal.revisionTwoFailureObserved = true;
state.goal.revisionTwoFailureExitCode = failure.audit.exitCode;
state.goal.revisionTwoFailureFingerprint = hashValue(
Buffer.concat([
Buffer.from(
`${failure.audit.actionId}\0${failure.audit.actionFingerprint}\0`,
),
log,
]),
);
state.goal.revisionTwoAgentDbBoundary = failure.observationIndex + 1;
return;
}
const pendingActions = (await findPendingActions()).filter(
(pending) =>
pending.agentId === mainAgentId && pending.runId === state.initialRunId,
);
const unsupportedEarlyWrite = pendingActions.find(
(pending) =>
goalProjectWriteTools.has(pending.tool) &&
!goalPendingIsStandaloneDeliveryMutation(pending, goalFinalMarker),
);
assert(
!unsupportedEarlyWrite,
'goal-revision-two-repair-before-failed-verification',
);
await confirmPendingActions(
new Set([
'project.checkpoint',
'project.verify',
'file.write',
'project.patchset',
]),
(pending) =>
pending.tool === 'project.checkpoint' ||
pending.tool === 'project.verify' ||
goalPendingIsStandaloneDeliveryMutation(pending, goalFinalMarker),
);
lastError = codedError('goal-revision-two-agent-failure-not-yet-observed');
await sleep(pollIntervalMs);
}
throw codedError('goal-revision-two-agent-failure-timeout', lastError);
}
export function findGoalRevisionTwoAgentVerificationFailure(records) {
for (
let auditIndex = state.goal.revisionTwoEditAgentDbBoundary;
auditIndex < records.length;
auditIndex += 1
) {
const audit = records[auditIndex];
if (
audit.recordType !== 'agent.runtime.project.verify' ||
audit.agentId !== mainAgentId ||
audit.runId !== state.initialRunId ||
audit.status !== 'failed' ||
audit.exitCode !== 1 ||
audit.timedOut !== false ||
!['test', 'check:e2e'].includes(audit.script) ||
audit.expectedCommand !== verificationCommand ||
!isNonEmptyString(audit.actionId) ||
!isNonEmptyString(audit.actionFingerprint) ||
!isNonEmptyString(audit.logPath) ||
!hasExpectedWorkspaceSandboxMetadata(audit)
) {
continue;
}
let startIndex = -1;
for (let index = auditIndex - 1; index >= 0; index -= 1) {
const record = records[index];
if (
record.agentId === mainAgentId &&
record.runId === state.initialRunId &&
record.tool === 'project.verify' &&
record.actionId === audit.actionId &&
record.actionFingerprint === audit.actionFingerprint &&
[
'agent.runtime.tool_action.executing',
'agent.runtime.tool_confirmation.approved',
].includes(record.recordType)
) {
startIndex = index;
break;
}
}
const observationIndex = records.findIndex(
(record, index) =>
index > auditIndex &&
record.recordType === 'agent.runtime.tool_observation' &&
record.agentId === mainAgentId &&
record.runId === state.initialRunId &&
record.tool === 'project.verify' &&
record.actionId === audit.actionId &&
record.status === 'failed',
);
if (
startIndex < state.goal.revisionTwoEditAgentDbBoundary ||
observationIndex < 0
) {
continue;
}
const unsupportedEarlyWrite = records
.slice(state.goal.revisionTwoEditAgentDbBoundary, observationIndex + 1)
.some(
(record) =>
goalProjectWriteTools.has(record.tool) &&
!state.goal.preFailureDeliveryActionIds.has(record.actionId) &&
[
'agent.runtime.tool_action.executing',
'agent.runtime.tool_confirmation.approved',
].includes(record.recordType),
);
assert(
!unsupportedEarlyWrite,
'goal-revision-two-repair-executed-before-failure',
);
return { audit, auditIndex, observationIndex, startIndex };
}
return null;
}
export async function readGoalRuntimePersistence() {
const taskSnapshot = await readTaskSnapshot();
const events = await readAllRuntimeEvents();
const [
agentDb,
conversations,
activity,
output,
runtimeState,
contextBundle,
goal,
] = await Promise.all([
readOptionalJsonl(path.join(state.projectRoot, '.agent/agent.db')),
readOptionalJsonl(
agentConversationPath(mainAgentId, state.initialSessionId),
),
readOptionalJsonl(path.join(state.projectRoot, '.agent/activity.jsonl')),
readOptionalJsonl(path.join(state.projectRoot, '.agent/output.jsonl')),
readJson(mainRuntimeStatePath()),
readJson(mainContextBundlePath()),
readGoalStatus(),
]);
const pendingActions = (await findPendingActions()).filter(
(pending) =>
pending.agentId === mainAgentId && pending.runId === state.initialRunId,
);
return {
taskSnapshot,
events,
agentDb,
conversations,
activity,
output,
runtimeState,
contextBundle,
goal,
pendingActions,
};
}
export async function captureGoalPausedSnapshot(expectedPending, codePrefix) {
await assertGoalInitialMarkerAbsent(`${codePrefix}-marker-check`);
const persistence = await readGoalRuntimePersistence();
const {
taskSnapshot,
events,
agentDb,
conversations,
runtimeState,
contextBundle,
goal,
pendingActions,
} = persistence;
const latest = taskSnapshot.latest.find(
(task) => task.agentId === mainAgentId && task.runId === state.initialRunId,
);
const targetRuns = [
...new Set(
taskSnapshot.all
.filter((task) => task.agentId === mainAgentId)
.map((task) => task.runId),
),
].sort();
const pending = pendingActions.find(
(candidate) => candidate.actionId === expectedPending.actionId,
);
assert(
goal.goalId === state.goal.goalId &&
goal.revision === state.goal.editedRevision &&
goal.status === 'paused' &&
runtimeState.agentId === mainAgentId &&
runtimeState.sessionId === state.initialSessionId &&
runtimeState.runId === state.initialRunId &&
runtimeState.goalId === state.goal.goalId &&
runtimeState.goalRevision === state.goal.editedRevision &&
runtimeState.goalStatus === 'paused' &&
runtimeState.status === 'paused' &&
runtimeState.phase === 'paused' &&
latest?.status === 'paused' &&
latest?.phase === 'paused' &&
JSON.stringify(targetRuns) === JSON.stringify([state.initialRunId]) &&
contextBundle.schemaVersion === runtimeContextBundleSchemaVersion &&
contextBundle.goalId === state.goal.goalId &&
contextBundle.goalRevision === state.goal.editedRevision &&
contextBundle.goalStatus === 'active' &&
pending?.record?.schemaVersion === 'game-creator-pending-action.v5' &&
pending.record.goalId === state.goal.goalId &&
pending.record.goalRevision === state.goal.editedRevision &&
pending.record.goalSnapshotFingerprint ===
contextBundle.goalSnapshotFingerprint &&
contextBundle.goalSnapshotFingerprint === goalSnapshotFingerprint(goal) &&
contextBundle.goalSnapshotFingerprint ===
state.goal.editedGoalSnapshotFingerprint &&
contextBundle.goalSnapshotFingerprint !==
state.goal.initialGoalSnapshotFingerprint &&
conversations.filter((message) => message.role === 'assistant').length ===
0,
`${codePrefix}-state-invalid`,
);
const planProtocolCount = agentDb.filter(
(record) =>
record.recordType === 'agent.runtime.tool_plan.protocol' &&
record.agentId === mainAgentId &&
record.runId === state.initialRunId,
).length;
const actionProgressCount = agentDb.filter(
(record) =>
record.agentId === mainAgentId &&
record.runId === state.initialRunId &&
[
'agent.runtime.tool_action.executing',
'agent.runtime.tool_action.observed',
'agent.runtime.tool_confirmation.approved',
'agent.runtime.action_receipt',
].includes(record.recordType),
).length;
const providerRequestStartedCount = agentDb.filter(
(record) =>
record.recordType === 'agent.runtime.provider_request.lifecycle' &&
record.agentId === mainAgentId &&
record.runId === state.initialRunId &&
record.status === 'started',
).length;
const signaturePayload = {
goalSha256: hashValue(JSON.stringify(goal)),
runtimeSha256: hashValue(JSON.stringify(runtimeState)),
contextSha256: hashValue(JSON.stringify(contextBundle)),
pendingSha256: hashValue(JSON.stringify(pending.record)),
taskCount: taskSnapshot.all.filter(
(task) =>
task.agentId === mainAgentId && task.runId === state.initialRunId,
).length,
eventCount: events.filter(
(event) =>
event.agentId === mainAgentId && event.runId === state.initialRunId,
).length,
agentDbCount: agentDb.filter(
(record) =>
record.agentId === mainAgentId && record.runId === state.initialRunId,
).length,
conversationCount: conversations.length,
assistantCount: conversations.filter(
(message) => message.role === 'assistant',
).length,
planProtocolCount,
providerRequestStartedCount,
actionProgressCount,
planRevision: runtimeState.planRevision,
pendingActionIdHash: hashValue(pending.actionId),
};
return {
...signaturePayload,
signature: hashValue(JSON.stringify(signaturePayload)),
};
}
export async function assertGoalRemainsPausedAfterRestart(
baseline,
expectedPending,
) {
let latest = null;
for (let poll = 0; poll < 4; poll += 1) {
latest = await captureGoalPausedSnapshot(
expectedPending,
'goal-paused-after-restart',
);
assert(
latest.signature === baseline.signature,
'goal-paused-evidence-progressed-after-restart',
);
await sleep(1_000);
}
state.goal.pausedAfterRestart = latest;
}
export async function waitForGoalExecutionOwnerTakeover() {
const ownerPath = path.join(
state.projectRoot,
'.agent/runtime/execution-owner.json',
);
const deadline = Date.now() + 30_000;
while (Date.now() < deadline) {
const owner = await readJson(ownerPath).catch(() => null);
if (
Number.isSafeInteger(owner?.protocolVersion) &&
owner.protocolVersion > 0 &&
Number.isSafeInteger(owner.pid) &&
owner.pid > 1 &&
owner.bootId === state.goal.newRunnerBootId &&
owner.recoveredFromBootId === state.goal.oldRunnerBootId
) {
return true;
}
await sleep(100);
}
throw codedError('goal-execution-owner-takeover-timeout');
}
export async function driveGoalRuntimeToQuiescence() {
const deadline = Date.now() + runTimeoutMs;
let quietPolls = 0;
while (Date.now() < deadline) {
await assertGoalInitialMarkerAbsent('goal-quiescence-poll');
await confirmPendingActions();
const [snapshot, goal] = await Promise.all([
readTaskSnapshot(),
readGoalStatus(),
]);
const initial = snapshot.latest.find(
(task) =>
task.agentId === mainAgentId && task.runId === state.initialRunId,
);
if (initial && isFailedTask(initial)) {
throw codedError('goal-runtime-failed');
}
if (goal.status === 'needs-reconciliation') {
throw codedError('goal-runtime-needs-reconciliation');
}
const pending = await findPendingActions();
const completed =
initial?.status === 'completed' &&
initial?.phase === 'completed' &&
goal.status === 'completed';
const hasLive = snapshot.latest.some(isLiveTask);
if (completed && !hasLive && pending.length === 0) {
quietPolls += 1;
if (quietPolls >= 3) return;
} else {
quietPolls = 0;
}
await sleep(pollIntervalMs);
}
throw codedError('goal-runtime-e2e-timeout');
}
export async function monitorGoalWriteActionUntilSettled(pending) {
state.goal.monitoredWriteActionIds.add(pending.actionId);
const deadline = Date.now() + 120_000;
while (Date.now() < deadline) {
await assertGoalRuntimeCanProgress('goal-write-action-settle');
await assertGoalInitialMarkerAbsent(
'goal-write-after-confirm',
pending.actionId,
);
const records = await readOptionalJsonl(
path.join(state.projectRoot, '.agent/agent.db'),
);
const settled = records.some(
(record) =>
record.agentId === pending.agentId &&
record.runId === pending.runId &&
record.actionId === pending.actionId &&
record.tool === pending.tool &&
[
'agent.runtime.action_receipt',
'agent.runtime.tool_action.observed',
'agent.runtime.tool_observation',
].includes(record.recordType),
);
if (settled) {
await assertGoalInitialMarkerAbsent(
'goal-write-settled',
pending.actionId,
);
return;
}
await sleep(100);
}
throw codedError('goal-write-action-settle-timeout');
}
export async function validateGoalRuntimeEvidence() {
const persistence = await readGoalRuntimePersistence();
const {
taskSnapshot,
events,
agentDb,
conversations,
activity,
output,
runtimeState,
contextBundle,
goal,
pendingActions,
} = persistence;
assert(taskSnapshot.all.length > 0, 'goal-task-evidence-missing');
assert(events.length > 0, 'goal-event-evidence-missing');
assert(agentDb.length > 0, 'goal-agent-db-evidence-missing');
assertNoPersistedImagePayload('goal-task', taskSnapshot.all);
assertNoPersistedImagePayload('goal-event', events);
assertNoPersistedImagePayload('goal-agent-db', agentDb);
const plan = inspectStructuredPlanSnapshot(runtimeState, 'goal-final-plan');
const verificationExecution =
findFinalSuccessfulGoalVerificationExecution(agentDb);
const projectRevision = await readJson(
path.join(state.projectRoot, '.agent/runtime/project-revision.json'),
);
const verificationGate = await readGoalVerificationGate(
projectRevision,
verificationExecution,
goal,
);
const expectedCompletionEvidence = [
`goalRevision=${state.goal.editedRevision}`,
`planRevision=${runtimeState.planRevision} completedSteps=${plan.completedStepHashes.length}`,
`verificationRequired=true verifiedRevision=${projectRevision.revision}`,
`runId=${state.initialRunId} sessionId=${state.initialSessionId}`,
];
assert(
plan.incompleteStepCount === 0 &&
plan.completedStepHashes.length === runtimeState.planSteps.length &&
state.goal.initialCompletedStepHashes.every((stepHash) =>
plan.completedStepHashes.includes(stepHash),
),
'goal-final-plan-incomplete',
);
assertGoalContextSnapshot(runtimeState, contextBundle, goal, 'goal-final');
assertStructuredPlanAuditSnapshot(
runtimeState,
agentDb,
'goal-final-plan-audit',
);
assert(
goal.schemaVersion === 'game-creator-agent-goal.v1' &&
goal.goalId === state.goal.goalId &&
goal.agentId === mainAgentId &&
goal.sessionId === state.initialSessionId &&
goal.runId === state.initialRunId &&
goal.revision === state.goal.editedRevision &&
goalSnapshotFingerprint(goal) ===
state.goal.editedGoalSnapshotFingerprint &&
state.goal.editedGoalSnapshotFingerprint !==
state.goal.initialGoalSnapshotFingerprint &&
goal.status === 'completed' &&
Number.isSafeInteger(goal.completedAt) &&
goal.completedAt > 0 &&
projectRevision.updatedAt <= goal.completedAt &&
verificationGate.updatedAt <= goal.completedAt &&
/^[0-9a-f]{64}$/u.test(goal.responseFingerprint) &&
Array.isArray(goal.completionEvidence) &&
JSON.stringify(goal.completionEvidence) ===
JSON.stringify(expectedCompletionEvidence) &&
runtimeState.status === 'idle' &&
runtimeState.phase === 'completed' &&
runtimeState.goalId === goal.goalId &&
runtimeState.goalRevision === goal.revision &&
runtimeState.goalStatus === 'completed',
'goal-final-state-invalid',
);
const targetTasks = taskSnapshot.all.filter(
(task) => task.agentId === mainAgentId && task.runId === state.initialRunId,
);
const targetRunIds = [
...new Set(
taskSnapshot.all
.filter((task) => task.agentId === mainAgentId)
.map((task) => task.runId),
),
].sort();
const completedTasks = targetTasks.filter(
(task) => task.status === 'completed' && task.phase === 'completed',
);
const latest = taskSnapshot.latest.find(
(task) => task.agentId === mainAgentId && task.runId === state.initialRunId,
);
assert(
JSON.stringify(targetRunIds) === JSON.stringify([state.initialRunId]) &&
completedTasks.length === 2 &&
completedTasks.filter((task) => task.goalStatus === 'active').length ===
1 &&
completedTasks.filter((task) => task.goalStatus === 'completed')
.length === 1 &&
latest?.goalStatus === 'completed',
'goal-finalization-projection-invalid',
);
const finalMessage = finalMessageId(
mainAgentId,
state.initialSessionId,
state.initialRunId,
);
const userMessages = conversations.filter(
(message) => message.role === 'user',
);
const assistantMessages = conversations.filter(
(message) => message.role === 'assistant',
);
const finalAssistant = assistantMessages.find(
(message) => message.messageId === finalMessage,
);
const assistantAudits = agentDb.filter(
(record) =>
record.recordType === 'conversation.message' &&
record.role === 'assistant' &&
record.agentId === mainAgentId &&
record.sessionId === state.initialSessionId &&
record.messageId === finalMessage,
);
const responseEvents = events.filter(
(event) =>
event.agentId === mainAgentId &&
event.runId === state.initialRunId &&
event.eventType === 'response' &&
event.phase === 'completed',
);
const completedEvents = events.filter(
(event) =>
event.agentId === mainAgentId &&
event.runId === state.initialRunId &&
event.eventType === 'turn.completed' &&
event.phase === 'completed',
);
assert(
userMessages.length === 2 &&
assistantMessages.length === 1 &&
finalAssistant?.agentId === mainAgentId &&
hashValue(finalAssistant.content.trim()) === goal.responseFingerprint &&
assistantAudits.length === 1 &&
responseEvents.length === 1 &&
completedEvents.length === 1,
'goal-final-assistant-invalid',
);
const providerLifecycle = validateGoalProviderRequestLifecycle(agentDb);
const finalizationLifecycle = validateGoalFinalizationLifecycle(
agentDb,
goal,
runtimeState,
);
assert(
verificationExecution.completionIndex <
finalizationLifecycle.firstStageIndex,
'goal-completed-before-verification-gate-passed',
);
const oldExecution = goalOldActionExecutionEvidence(
agentDb,
state.goal.initialPending.actionId,
);
const editedActionRecords = agentDb.filter(
(record) => record.actionId === state.goal.editedPending.actionId,
);
const editedExecutionCount = editedActionRecords.filter((record) =>
[
'agent.runtime.tool_action.executing',
'agent.runtime.tool_confirmation.approved',
].includes(record.recordType),
).length;
const editedReceipts = editedActionRecords.filter(
(record) =>
record.recordType === 'agent.runtime.action_receipt' &&
record.status === 'ok',
);
assert(
state.goal.initialPending.blockedObservationCount >= 1 &&
state.goal.initialPending.blockedReceiptCount === 1 &&
oldExecution.executionCount === 0 &&
oldExecution.successfulReceiptCount === 0 &&
editedExecutionCount >= 1 &&
editedReceipts.length === 1 &&
pendingActions.length === 0,
'goal-action-transition-invalid',
);
const executedGoalWriteActionIds = new Set(
agentDb
.filter(
(record) =>
record.agentId === mainAgentId &&
record.runId === state.initialRunId &&
goalProjectWriteTools.has(record.tool) &&
[
'agent.runtime.tool_action.executing',
'agent.runtime.tool_confirmation.approved',
].includes(record.recordType),
)
.map((record) => record.actionId)
.filter(isNonEmptyString),
);
assert(
[...executedGoalWriteActionIds].every((actionId) =>
state.goal.monitoredWriteActionIds.has(actionId),
) && state.goal.initialMarkerAbsenceCheckCount > 0,
'goal-write-action-marker-monitoring-incomplete',
);
assert(
state.goal.runner.pidfdClaimCount >= 2 &&
state.goal.runner.pidfdSignalCount >= 1,
'goal-runner-pidfd-evidence-invalid',
);
const repairEvidence = validateGoalRevisionTwoRepairEvidence(
agentDb,
verificationExecution,
);
const verification = await runProcess(process.execPath, ['verify-e2e.mjs'], {
cwd: state.projectRoot,
timeoutMs: 120_000,
});
assert(
verification.stdout.includes(commandPassedMarker),
'goal-final-project-verification-failed',
);
const goalDelivery = await fs.readFile(
path.join(state.projectRoot, goalDeliveryPath),
'utf8',
);
const oldMarkerProjectCount =
await countMarkerOutsideRuntimeControl(goalInitialMarker);
assert(
goalDelivery === `${goalFinalMarker}\n` && oldMarkerProjectCount === 0,
'goal-final-delivery-invalid',
);
const finalizationFiles = await listFiles(
path.join(state.projectRoot, '.agent/runtime/finalizations'),
);
const finalizationJournalCount = finalizationFiles.filter((file) =>
file.endsWith('.json'),
).length;
assert(finalizationJournalCount === 0, 'goal-finalization-journal-present');
const replayEvidence = validateToolActionReplays(agentDb);
const duplicateActionCount = duplicateCount(
agentDb.filter((record) => record.actionId).map(actionAuditIdentity),
);
const duplicateMessageCount = duplicateCount(
conversations.map((message) => message.messageId).filter(Boolean),
);
const receipts = agentDb.filter(
(record) => record.recordType === 'agent.runtime.action_receipt',
);
const duplicateReceiptCount = duplicateCount(
receipts.map(receiptAuditIdentity),
);
assert(
duplicateActionCount === 0 &&
duplicateMessageCount === 0 &&
duplicateReceiptCount === 0 &&
replayEvidence.sideEffectReplayCount === 0,
'goal-duplicate-or-replay-detected',
);
const publicSurfaces = {
event: events,
agentDb,
receipt: receipts,
activity,
output,
};
const goalPublicBodyLeakCounts = {};
for (const [surface, records] of Object.entries(publicSurfaces)) {
goalPublicBodyLeakCounts[surface] = countExactSecrets(
Buffer.from(JSON.stringify(records)),
goalPublicBodyValues(),
);
assert(
goalPublicBodyLeakCounts[surface] === 0,
`goal-body-public-${surface}-leak-detected`,
);
}
const goalPublicBodyLeakCount = sumObjectValues(goalPublicBodyLeakCounts);
const projectPathPublicLeakCounts = validateProjectRootPublicLeakBoundary(
publicSurfaces,
'goal-public',
);
const projectPathPublicLeakCount = sumObjectValues(
projectPathPublicLeakCounts,
);
state.lureLeakCount = await countLureLeaks();
assert(state.lureLeakCount === 0, 'sensitive-lure-leak-detected');
const nativeToolPlanProtocolEvidence =
validateNativeRuntimeToolPlanProtocolEvidence(agentDb);
const successfulToolExecutionCount = receipts.filter(
(record) =>
record.agentId === mainAgentId &&
record.runId === state.initialRunId &&
record.status === 'ok',
).length;
return {
scenario: 'goal-edit-pause-runner-restart-resume',
taskCount: taskSnapshot.all.length,
eventCount: events.length,
agentDbRecordCount: agentDb.length,
conversationMessageCount: conversations.length,
successfulToolExecutionCount,
...nativeToolPlanProtocolEvidence,
structuredPlanRevision: plan.revision,
structuredPlanCompletedStepCount: plan.completedStepHashes.length,
goalInitialCompletedStepCount: state.goal.initialCompletedStepHashes.length,
goalRetainedInitialCompletedStepCount:
state.goal.initialCompletedStepHashes.filter((stepHash) =>
plan.completedStepHashes.includes(stepHash),
).length,
goalEditedEvidenceAbsentBeforeEdit:
state.goal.editedEvidenceAbsentBeforeEdit,
goalRevisionOneFixtureIsolated: state.goal.revisionOneFixtureIsolated,
goalRevisionTwoFixtureInjected: state.goal.revisionTwoFixtureInjected,
goalRevisionTwoHostFailureObserved:
state.goal.revisionTwoHostFailureObserved,
goalRevisionTwoFailureObserved: state.goal.revisionTwoFailureObserved,
goalRevisionTwoFailureExitCode: state.goal.revisionTwoFailureExitCode,
goalRevisionTwoFailureFingerprint: state.goal.revisionTwoFailureFingerprint,
goalRevisionTwoRepairActionCount: repairEvidence.actionCount,
goalRevisionTwoRepairFileWriteCount: repairEvidence.fileWriteCount,
goalRevisionTwoRepairPatchsetCount: repairEvidence.patchsetCount,
goalIdHash: hashValue(goal.goalId),
goalInitialRevision: state.goal.initialRevision,
goalEditedRevision: state.goal.editedRevision,
goalSnapshotFingerprintChanged:
state.goal.initialGoalSnapshotFingerprint !==
state.goal.editedGoalSnapshotFingerprint,
goalInitialMarkerAbsenceCheckCount:
state.goal.initialMarkerAbsenceCheckCount,
goalMonitoredWriteActionCount: state.goal.monitoredWriteActionIds.size,
goalPreFailureDeliveryActionCount:
state.goal.preFailureDeliveryActionIds.size,
goalFinalStatus: goal.status,
goalEditProviderInterrupted: state.goal.editProviderInterrupted,
goalPauseProviderInterrupted: state.goal.pauseProviderInterrupted,
goalPausedBeforeKill: true,
goalPausedAfterRestart: true,
goalRunnerBootChanged:
state.goal.oldRunnerBootId !== state.goal.newRunnerBootId,
goalRunnerKillMethod: 'linux-pidfd',
goalRunnerPidfdClaimCount: state.goal.runner.pidfdClaimCount,
goalRunnerPidfdSignalCount: state.goal.runner.pidfdSignalCount,
goalExecutionOwnerRecovered: state.goal.executionOwnerRecovered === true,
goalExplicitResumeSameRun: true,
goalTargetRunCount: targetRunIds.length,
goalUnexpectedRunCount: targetRunIds.length - 1,
goalOldActionCount: 1,
goalOldActionBlockedReceiptCount:
state.goal.initialPending.blockedReceiptCount,
goalOldActionExecutionCount: oldExecution.executionCount,
goalOldActionReplayCount: oldExecution.successfulReceiptCount,
goalEditedActionExecutionCount: editedExecutionCount,
goalPausedTaskDelta:
state.goal.pausedAfterRestart.taskCount -
state.goal.pauseSnapshot.taskCount,
goalPausedPlanDelta:
state.goal.pausedAfterRestart.planRevision -
state.goal.pauseSnapshot.planRevision,
goalPausedConversationDelta:
state.goal.pausedAfterRestart.conversationCount -
state.goal.pauseSnapshot.conversationCount,
goalPausedProviderPlanDelta:
state.goal.pausedAfterRestart.planProtocolCount -
state.goal.pauseSnapshot.planProtocolCount,
goalPausedProviderRequestStartedDelta:
state.goal.pausedAfterRestart.providerRequestStartedCount -
state.goal.pauseSnapshot.providerRequestStartedCount,
goalPausedActionProgressDelta:
state.goal.pausedAfterRestart.actionProgressCount -
state.goal.pauseSnapshot.actionProgressCount,
goalContextSchemaVersion: contextBundle.schemaVersion,
goalPendingSchemaVersion: state.goal.editedPending.schemaVersion,
projectRevision: projectRevision.revision,
verificationPassed: true,
verificationActionIdentityBound: true,
verificationActionIdHash: hashValue(verificationExecution.actionId),
goalProviderRequestStartedCount: providerLifecycle.startedCount,
goalProviderRequestTerminalCount: providerLifecycle.terminalCount,
goalFinalizationSchemaVersion: finalizationLifecycle.schemaVersion,
goalFinalizationObserved: true,
goalFinalizationStageCount: finalizationLifecycle.stageCount,
goalFinalizationIdHash: finalizationLifecycle.finalizationIdHash,
goalFinalizationJournalCount: finalizationJournalCount,
goalCompletedProjectionCount: completedTasks.length,
goalAssistantCount: assistantMessages.length,
goalPublicBodyLeakCount,
goalBodyReportLeakCount: state.goalBodyReportLeakCount,
sideEffectActionCount: replayEvidence.sideEffectActionCount,
sideEffectReplayCount: replayEvidence.sideEffectReplayCount,
idempotentReplayActionCount: replayEvidence.idempotentReplayActionCount,
actionReceiptReplayRecordCount:
replayEvidence.actionReceiptReplayRecordCount,
finalAssistantCount: assistantMessages.length,
finalAssistantAuditCount: assistantAudits.length,
duplicateActionCount,
duplicateMessageCount,
duplicateReceiptCount,
confirmedActionCount: state.confirmedActionIds.size,
projectPathPublicLeakCount,
projectPathPublicSurfaceCount: Object.keys(projectPathPublicLeakCounts)
.length,
secretLeakCount: state.transcriptLeakCount + state.projectLeakCount,
lureLeakCount: state.lureLeakCount,
paths: [
'.agent/runtime/tasks',
'.agent/runtime/events',
'.agent/agent.db',
relativeProjectPath(mainContextBundlePath()),
relativeProjectPath(mainRuntimeStatePath()),
'.agent/runtime/goals/current',
'.agent/conversations',
goalDeliveryPath,
],
};
}
export async function readGoalVerificationGate(
projectRevision,
verificationExecution,
goal,
) {
const manifest = await readJson(
path.join(state.projectRoot, '.agent/manifest.json'),
);
assert(
projectRevision?.schemaVersion === 'game-creator-project-revision.v1' &&
isNonEmptyString(projectRevision.projectId) &&
manifest?.projectId === projectRevision.projectId &&
goal.projectId === manifest.projectId &&
Number.isSafeInteger(projectRevision.revision) &&
projectRevision.revision > 0 &&
Number.isSafeInteger(projectRevision.updatedAt) &&
projectRevision.updatedAt > 0,
'goal-project-revision-invalid',
);
const verificationFiles = await listFiles(
path.join(state.projectRoot, '.agent/runtime/verification'),
);
const matching = [];
for (const file of verificationFiles.filter((entry) =>
entry.endsWith('.json'),
)) {
const value = await readJson(file);
if (value.agentId === mainAgentId && value.runId === state.initialRunId) {
matching.push(value);
}
}
assert(matching.length === 1, 'goal-verification-gate-count-invalid');
const gate = matching[0];
assert(
gate.schemaVersion === 'game-creator-verification-gate.v1' &&
gate.projectId === projectRevision.projectId &&
gate.agentId === mainAgentId &&
gate.runId === state.initialRunId &&
gate.requiresVerification === true &&
gate.mutationRevision === projectRevision.revision &&
gate.verifiedRevision === projectRevision.revision &&
['file.write', 'project.patchset'].includes(gate.lastMutationTool) &&
gate.lastVerificationTool === verificationExecution.tool &&
gate.lastVerificationStatus === 'passed' &&
Number.isSafeInteger(gate.updatedAt) &&
gate.updatedAt >= projectRevision.updatedAt &&
gate.updatedAt >= verificationExecution.verificationAudit.updatedAt &&
verificationExecution.verificationAudit.actionId ===
verificationExecution.actionId &&
verificationExecution.verificationAudit.actionFingerprint ===
verificationExecution.actionFingerprint,
'goal-verification-credential-invalid',
);
return gate;
}
export function findFinalSuccessfulGoalVerificationExecution(agentDb) {
let auditIndex = -1;
for (let index = agentDb.length - 1; index >= 0; index -= 1) {
const record = agentDb[index];
if (
record.recordType === 'agent.runtime.project.verify' &&
record.agentId === mainAgentId &&
record.runId === state.initialRunId
) {
auditIndex = index;
break;
}
}
assert(auditIndex >= 0, 'goal-project-verification-missing');
const verificationAudit = agentDb[auditIndex];
assert(
verificationAudit.status === 'completed' &&
verificationAudit.exitCode === 0 &&
verificationAudit.timedOut === false &&
['test', 'check:e2e'].includes(verificationAudit.script) &&
verificationAudit.expectedCommand === verificationCommand &&
isNonEmptyString(verificationAudit.actionId) &&
isNonEmptyString(verificationAudit.actionFingerprint) &&
Number.isSafeInteger(verificationAudit.updatedAt) &&
hasExpectedWorkspaceSandboxMetadata(verificationAudit),
'goal-final-project-verification-audit-invalid',
);
const execution = findSuccessfulToolExecution(
agentDb,
'project.verify',
state.initialRunId,
(candidate) =>
candidate.actionId === verificationAudit.actionId &&
candidate.actionFingerprint === verificationAudit.actionFingerprint &&
['test', 'check:e2e'].includes(
auditInputValue(candidate.inputSummary, 'script'),
),
);
assert(
execution &&
execution.startIndex < auditIndex &&
auditIndex < execution.resultIndex,
'goal-final-project-verification-action-identity-invalid',
);
return { ...execution, auditIndex, verificationAudit };
}
export function validateGoalRevisionTwoRepairEvidence(
agentDb,
verificationExecution,
) {
assert(
state.goal.revisionTwoFixtureInjected === true &&
state.goal.revisionTwoHostFailureObserved === true &&
state.goal.revisionTwoFailureObserved === true &&
Number.isSafeInteger(state.goal.revisionTwoAgentDbBoundary) &&
state.goal.revisionTwoAgentDbBoundary > 0,
'goal-revision-two-failure-boundary-invalid',
);
const afterFailureBoundary = (execution) =>
execution.startIndex >= state.goal.revisionTwoAgentDbBoundary &&
execution.completionIndex < verificationExecution.startIndex;
const gamePatchset = findSuccessfulToolExecution(
agentDb,
'project.patchset',
state.initialRunId,
(execution) =>
afterFailureBoundary(execution) &&
auditPatchsetPathsInclude(execution.inputSummary, [
'update:game/index.html',
]),
);
const createdPatchset = findSuccessfulToolExecution(
agentDb,
'project.patchset',
state.initialRunId,
(execution) =>
afterFailureBoundary(execution) &&
auditPatchsetPathsInclude(execution.inputSummary, [
`create:${patchsetCreatedPath}`,
]),
);
const gameWrite = findSuccessfulToolExecution(
agentDb,
'file.write',
state.initialRunId,
(execution) =>
afterFailureBoundary(execution) &&
auditPathEquals(execution.inputSummary, 'game/index.html'),
);
const createdWrite = findSuccessfulToolExecution(
agentDb,
'file.write',
state.initialRunId,
(execution) =>
afterFailureBoundary(execution) &&
auditPathEquals(execution.inputSummary, patchsetCreatedPath),
);
assert(
Boolean(gamePatchset || gameWrite) &&
Boolean(createdPatchset || createdWrite),
'goal-revision-two-agent-repair-evidence-missing',
);
const executions = [
gamePatchset ?? gameWrite,
createdPatchset ?? createdWrite,
];
const byAction = new Map(
executions.map((execution) => [execution.actionId, execution]),
);
return {
actionCount: byAction.size,
fileWriteCount: [...byAction.values()].filter(
(execution) => execution.tool === 'file.write',
).length,
patchsetCount: [...byAction.values()].filter(
(execution) => execution.tool === 'project.patchset',
).length,
};
}
export function validateGoalProviderRequestLifecycle(agentDb) {
const records = agentDb.filter(
(record) =>
record.recordType === 'agent.runtime.provider_request.lifecycle' &&
record.agentId === mainAgentId &&
record.runId === state.initialRunId,
);
const byRequest = new Map();
for (const record of records) {
assert(
record.auditSchemaVersion === providerRequestLifecycleSchemaVersion &&
record.taskId &&
record.sessionId === state.initialSessionId &&
['tool-plan', 'final-reply'].includes(record.requestKind) &&
typeof record.requestSlot === 'string' &&
typeof record.webSearchEnabled === 'boolean' &&
(record.requestKind !== 'final-reply' ||
record.webSearchEnabled === false) &&
!['prompt', 'response', 'error', 'baseUrl', 'model'].some((key) =>
Object.hasOwn(record, key),
),
'goal-provider-request-lifecycle-invalid',
);
const group = byRequest.get(record.requestId) ?? [];
group.push(record);
byRequest.set(record.requestId, group);
}
assert(byRequest.size > 0, 'goal-provider-request-lifecycle-missing');
for (const group of byRequest.values()) {
assert(
group.length === 2 &&
group[0].status === 'started' &&
['completed', 'failed', 'interrupted'].includes(group[1].status) &&
group[0].requestKind === group[1].requestKind &&
group[0].requestSlot === group[1].requestSlot,
'goal-provider-request-lifecycle-incomplete',
);
}
return {
startedCount: byRequest.size,
terminalCount: byRequest.size,
};
}
export function validateGoalFinalizationLifecycle(agentDb, goal, runtimeState) {
const records = agentDb.filter(
(record) =>
record.recordType === 'agent.runtime.finalization.lifecycle' &&
record.agentId === mainAgentId &&
record.runId === state.initialRunId,
);
const expectedStages = [
'prepared',
'assistant-persisted',
'runtime-completed',
'goal-completed',
];
assert(
records.length === expectedStages.length,
'goal-finalization-audit-count-invalid',
);
const finalizationId = records[0]?.finalizationId;
const messageId = records[0]?.messageId;
const expectedGoalSnapshotFingerprint = goalSnapshotFingerprint(goal);
for (const [index, record] of records.entries()) {
assert(
record.auditSchemaVersion === 'game-creator-finalization-lifecycle.v1' &&
record.journalSchemaVersion ===
'game-creator-runtime-finalization.v4' &&
record.finalizationId === finalizationId &&
record.messageId === messageId &&
record.taskId === runtimeState.taskId &&
record.sessionId === state.initialSessionId &&
record.stage === expectedStages[index] &&
record.stageOrdinal === index + 1 &&
record.previousStage ===
(index === 0 ? null : expectedStages[index - 1]) &&
record.goalId === goal.goalId &&
record.goalRevision === goal.revision &&
record.goalSnapshotFingerprint === expectedGoalSnapshotFingerprint &&
record.planRevision === runtimeState.planRevision &&
record.responseFingerprint === goal.responseFingerprint &&
Number.isSafeInteger(record.stageAt) &&
record.stageAt > 0 &&
!['task', 'response', 'prompt', 'observation'].some((key) =>
Object.hasOwn(record, key),
),
'goal-finalization-audit-invalid',
);
if (index > 0) {
assert(
record.stageAt >= records[index - 1].stageAt,
'goal-finalization-audit-time-regressed',
);
}
}
const assistantAuditIndex = agentDb.findIndex(
(record) =>
record.recordType === 'conversation.message' &&
record.messageId === messageId &&
record.role === 'assistant',
);
const assistantStageIndex = agentDb.findIndex(
(record) =>
record.recordType === 'agent.runtime.finalization.lifecycle' &&
record.finalizationId === finalizationId &&
record.stage === 'assistant-persisted',
);
assert(
assistantAuditIndex >= 0 && assistantAuditIndex < assistantStageIndex,
'goal-finalization-assistant-order-invalid',
);
return {
schemaVersion: records[0].journalSchemaVersion,
stageCount: records.length,
finalizationIdHash: hashValue(finalizationId),
firstStageIndex: agentDb.findIndex((record) => record === records[0]),
};
}
export async function assertGoalInitialMarkerAbsent(code, actionId = null) {
if (!isGoalRuntimeSuite() || !state.projectRoot) return;
const count = await countMarkerOutsideRuntimeControl(goalInitialMarker);
state.goal.initialMarkerAbsenceCheckCount += 1;
if (isNonEmptyString(actionId)) {
state.goal.monitoredWriteActionIds.add(actionId);
}
assert(count === 0, `${code}-revision-one-marker-landed`);
}
export function emptyGoalEvidence() {
return {
scenario: 'goal-edit-pause-runner-restart-resume',
taskCount: 0,
eventCount: 0,
agentDbRecordCount: 0,
conversationMessageCount: 0,
successfulToolExecutionCount: 0,
toolPlanProtocolCount: 0,
nativeRuntimeToolPlanCount: 0,
toolPlanRepairCount: 0,
nativeRuntimeToolPlanRepairCount: 0,
toolPlanRepairedLoopCount: 0,
toolPlanSecondRepairCount: 0,
toolPlanRepairCountsByProtocolErrorKind:
emptyToolPlanRepairCountsByProtocolErrorKind(),
wrapperToolPlanFallbackCount: 0,
textJsonToolPlanFallbackCount: 0,
toolPlanAuditPayloadLeakCount: 0,
structuredPlanRevision: 0,
structuredPlanCompletedStepCount: 0,
goalInitialCompletedStepCount: 0,
goalRetainedInitialCompletedStepCount: 0,
goalEditedEvidenceAbsentBeforeEdit: false,
goalRevisionOneFixtureIsolated: false,
goalRevisionTwoFixtureInjected: false,
goalRevisionTwoHostFailureObserved: false,
goalRevisionTwoFailureObserved: false,
goalRevisionTwoFailureExitCode: null,
goalRevisionTwoFailureFingerprint: null,
goalRevisionTwoRepairActionCount: 0,
goalRevisionTwoRepairFileWriteCount: 0,
goalRevisionTwoRepairPatchsetCount: 0,
goalIdHash: null,
goalInitialRevision: 0,
goalEditedRevision: 0,
goalSnapshotFingerprintChanged: false,
goalInitialMarkerAbsenceCheckCount: 0,
goalMonitoredWriteActionCount: 0,
goalPreFailureDeliveryActionCount: 0,
goalFinalStatus: null,
goalEditProviderInterrupted: false,
goalPauseProviderInterrupted: false,
goalPausedBeforeKill: false,
goalPausedAfterRestart: false,
goalRunnerBootChanged: false,
goalRunnerKillMethod: null,
goalRunnerPidfdClaimCount: 0,
goalRunnerPidfdSignalCount: 0,
goalRunnerStopped: false,
goalAppDataCleanupPerformed: false,
goalExecutionOwnerRecovered: false,
goalExplicitResumeSameRun: false,
goalTargetRunCount: 0,
goalUnexpectedRunCount: 0,
goalOldActionCount: 0,
goalOldActionBlockedReceiptCount: 0,
goalOldActionExecutionCount: 0,
goalOldActionReplayCount: 0,
goalEditedActionExecutionCount: 0,
goalPausedTaskDelta: 0,
goalPausedPlanDelta: 0,
goalPausedConversationDelta: 0,
goalPausedProviderPlanDelta: 0,
goalPausedProviderRequestStartedDelta: 0,
goalPausedActionProgressDelta: 0,
goalContextSchemaVersion: null,
goalPendingSchemaVersion: null,
projectRevision: 0,
verificationPassed: false,
verificationActionIdentityBound: false,
verificationActionIdHash: null,
goalProviderRequestStartedCount: 0,
goalProviderRequestTerminalCount: 0,
goalFinalizationSchemaVersion: null,
goalFinalizationObserved: false,
goalFinalizationStageCount: 0,
goalFinalizationIdHash: null,
goalFinalizationJournalCount: 0,
goalCompletedProjectionCount: 0,
goalAssistantCount: 0,
goalPublicBodyLeakCount: 0,
goalBodyReportLeakCount: 0,
sideEffectActionCount: 0,
sideEffectReplayCount: 0,
idempotentReplayActionCount: 0,
actionReceiptReplayRecordCount: 0,
finalAssistantCount: 0,
finalAssistantAuditCount: 0,
duplicateActionCount: 0,
duplicateMessageCount: 0,
duplicateReceiptCount: 0,
confirmedActionCount: 0,
projectPathPublicLeakCount: 0,
projectPathPublicSurfaceCount: 0,
projectPathTranscriptLeakCount: 0,
projectPathReportLeakCount: 0,
secretLeakCount: 0,
lureLeakCount: 0,
failureEvidenceErrors: {
task: [],
event: [],
agentDb: [],
conversation: [],
},
paths: [],
};
}
export async function collectPartialGoalEvidence() {
const [taskSurface, eventSurface, agentDbSurface, conversationSurface] =
await Promise.all([
collectPartialRuntimeJsonlSurface('goal', 'task', async () =>
(
await listFiles(path.join(state.projectRoot, '.agent/runtime/tasks'))
).filter((file) => file.endsWith('.jsonl')),
),
collectPartialRuntimeJsonlSurface('goal', 'event', async () =>
(
await listFiles(path.join(state.projectRoot, '.agent/runtime/events'))
).filter((file) => file.endsWith('.jsonl')),
),
collectPartialRuntimeJsonlSurface('goal', 'agent-db', async () => [
path.join(state.projectRoot, '.agent/agent.db'),
]),
collectPartialRuntimeJsonlSurface('goal', 'conversation', async () =>
(
await listFiles(path.join(state.projectRoot, '.agent/conversations'))
).filter((file) => file.endsWith('.jsonl')),
),
]);
const taskSnapshot = buildTaskSnapshot(taskSurface.records);
const events = eventSurface.records;
const agentDb = agentDbSurface.records;
const conversations = conversationSurface.records;
const runtime = await readJson(mainRuntimeStatePath()).catch(() => null);
const contextFiles = await listFiles(
path.join(state.projectRoot, '.agent/runtime/context-bundles', mainAgentId),
).catch(() => []);
const context = await readLatestJsonFile(contextFiles);
const goalFiles = await listFiles(
path.join(state.projectRoot, '.agent/runtime/goals/current'),
).catch(() => []);
const goals = await Promise.all(
goalFiles
.filter((file) => file.endsWith('.json'))
.map((file) => readJson(file).catch(() => null)),
);
const goal = goals.find(
(candidate) =>
candidate?.agentId === mainAgentId &&
(!state.initialRunId || candidate.runId === state.initialRunId),
);
const targetRunIds = [
...new Set(
taskSnapshot.all
.filter((task) => task.agentId === mainAgentId)
.map((task) => task.runId),
),
];
const receipts = agentDb.filter(
(record) => record.recordType === 'agent.runtime.action_receipt',
);
const providerLifecycle = agentDb.filter(
(record) =>
record.recordType === 'agent.runtime.provider_request.lifecycle' &&
record.agentId === mainAgentId,
);
const finalizationLifecycle = agentDb.filter(
(record) =>
record.recordType === 'agent.runtime.finalization.lifecycle' &&
record.agentId === mainAgentId,
);
const completedStepCount = Array.isArray(runtime?.planSteps)
? runtime.planSteps.filter((step) => step.status === 'completed').length
: 0;
const nativeToolPlanProtocolEvidence =
collectNativeRuntimeToolPlanProtocolEvidence(agentDb);
return {
taskCount: taskSnapshot.all.length,
eventCount: events.length,
agentDbRecordCount: agentDb.length,
conversationMessageCount: conversations.length,
successfulToolExecutionCount: receipts.filter(
(record) => record.status === 'ok',
).length,
...nativeToolPlanProtocolEvidence,
structuredPlanRevision: runtime?.planRevision ?? 0,
structuredPlanCompletedStepCount: completedStepCount,
goalEditedEvidenceAbsentBeforeEdit:
state.goal.editedEvidenceAbsentBeforeEdit,
goalRevisionOneFixtureIsolated: state.goal.revisionOneFixtureIsolated,
goalRevisionTwoFixtureInjected: state.goal.revisionTwoFixtureInjected,
goalRevisionTwoHostFailureObserved:
state.goal.revisionTwoHostFailureObserved,
goalRevisionTwoFailureObserved: state.goal.revisionTwoFailureObserved,
goalRevisionTwoFailureExitCode: state.goal.revisionTwoFailureExitCode,
goalRevisionTwoFailureFingerprint: state.goal.revisionTwoFailureFingerprint,
goalIdHash: isNonEmptyString(goal?.goalId) ? hashValue(goal.goalId) : null,
goalInitialRevision: state.goal.initialRevision || goal?.revision || 0,
goalEditedRevision: state.goal.editedRevision,
goalSnapshotFingerprintChanged:
isNonEmptyString(state.goal.initialGoalSnapshotFingerprint) &&
isNonEmptyString(state.goal.editedGoalSnapshotFingerprint) &&
state.goal.initialGoalSnapshotFingerprint !==
state.goal.editedGoalSnapshotFingerprint,
goalInitialMarkerAbsenceCheckCount:
state.goal.initialMarkerAbsenceCheckCount,
goalMonitoredWriteActionCount: state.goal.monitoredWriteActionIds.size,
goalPreFailureDeliveryActionCount:
state.goal.preFailureDeliveryActionIds.size,
goalFinalStatus: goal?.status ?? runtime?.goalStatus ?? null,
goalRunnerKillMethod:
state.goal.runner.pidfdClaimCount > 0 ? 'linux-pidfd' : null,
goalRunnerPidfdClaimCount: state.goal.runner.pidfdClaimCount,
goalRunnerPidfdSignalCount: state.goal.runner.pidfdSignalCount,
goalTargetRunCount: targetRunIds.length,
goalUnexpectedRunCount: Math.max(0, targetRunIds.length - 1),
goalContextSchemaVersion: context?.schemaVersion ?? null,
goalProviderRequestStartedCount: providerLifecycle.filter(
(record) => record.status === 'started',
).length,
goalProviderRequestTerminalCount: providerLifecycle.filter((record) =>
['completed', 'failed', 'interrupted'].includes(record.status),
).length,
goalFinalizationSchemaVersion:
finalizationLifecycle.at(-1)?.journalSchemaVersion ?? null,
goalFinalizationObserved: finalizationLifecycle.length > 0,
goalFinalizationStageCount: finalizationLifecycle.length,
goalFinalizationIdHash: isNonEmptyString(
finalizationLifecycle.at(-1)?.finalizationId,
)
? hashValue(finalizationLifecycle.at(-1).finalizationId)
: null,
goalAssistantCount: conversations.filter(
(message) => message.role === 'assistant',
).length,
finalAssistantCount:
goal?.status === 'completed'
? conversations.filter((message) => message.role === 'assistant').length
: 0,
finalAssistantAuditCount:
goal?.status === 'completed'
? agentDb.filter(
(record) =>
record.recordType === 'conversation.message' &&
record.role === 'assistant',
).length
: 0,
duplicateMessageCount: duplicateCount(
conversations.map((message) => message.messageId).filter(Boolean),
),
duplicateReceiptCount: duplicateCount(receipts.map(receiptAuditIdentity)),
failureEvidenceErrors: {
task: taskSurface.errors,
event: eventSurface.errors,
agentDb: agentDbSurface.errors,
conversation: conversationSurface.errors,
},
paths: [
'.agent/runtime/tasks',
'.agent/runtime/events',
'.agent/agent.db',
'.agent/runtime/context-bundles',
'.agent/runtime/goals/current',
'.agent/conversations',
],
};
}
export function isGoalRuntimeSuite() {
return state.suite === goalRuntimeSuite;
}
export function goalStaleActionReceiptMatchesOriginalAction(original, receipt) {
if (
!isGoalRuntimeSuite() ||
receipt.recordType !== 'agent.runtime.action_receipt' ||
receipt.tool !== 'runtime.goal' ||
receipt.status !== 'blocked' ||
!goalProjectWriteTools.has(original.tool) ||
!isNonEmptyString(original.rawInputSummary) ||
original.agentId !== receipt.agentId ||
original.runId !== receipt.runId ||
original.actionFingerprint !== receipt.actionFingerprint
) {
return false;
}
const expectedReceiptSummary = canonicalAuditInputSummary(
`inputSummarySha256=${hashValue(original.rawInputSummary)} · inputSummaryChars=${[...original.rawInputSummary].length}`,
);
return receipt.inputSummary === expectedReceiptSummary;
}