test(managed): record which load path produced each post-crash entry

HostedProcessCrashIT fails on main with postFailureLoads.every(Boolean), but
the recorded sequence changes shape between runs (#15898: 9 vs 10 entries,
different true positions, one run with none), so the current message cannot
say which of the connector's load paths sent the offending request.

Record a compact origin discriminator per entry — cancellationTakeover,
passiveManagedRuntimeRecovery, driveRuntimeRecovery, mcpManagementOnly and
whether cancellationPromptId was present — and include it in both assertion
messages. The assertion itself is unchanged: 'no tool replay after a crash'
is the property it protects, and the next red run should name its own origin
instead of being guessed at.
This commit is contained in:
yiliang114 committed 2026-10-30 10:43:51 +08:00
1 parent 619a601b39
commit fad5d81aeb
1 file changed
+21 -3
@@ -50,6 +50,11 @@ const report = {
promptSubmissions: 0,
continuationsAfterFailure: 0,
postFailureLoads: [] as boolean[],
// Which caller produced each entry above. The boolean says a post-failure
// load was not cancellation-only; it does not say which of the connector's
// load paths sent it. #15898 shows the sequence changing shape between runs,
// so a failing entry has to name its own origin.
postFailureLoadOrigins: [] as string[],
lateCancelReplays: 0,
originalCancelBody: '',
};
@@ -156,8 +161,18 @@ const proxy = createServer(async (req, res) => {
`/session/${config.sessionId}/managed-runtime/continue`
)
report.continuationsAfterFailure++;
if (injected && target.pathname.endsWith('/load'))
if (injected && target.pathname.endsWith('/load')) {
report.postFailureLoads.push(fields.cancellationTakeover === true);
report.postFailureLoadOrigins.push(
[
`takeover=${fields.cancellationTakeover === true}`,
`passive=${fields.passiveManagedRuntimeRecovery === true}`,
`drive=${fields.driveRuntimeRecovery === true}`,
`mcpOnly=${fields.mcpManagementOnly === true}`,
`promptId=${typeof fields.cancellationPromptId === 'string'}`,
].join(' '),
);
}
const headers = Object.fromEntries(
Object.entries(req.headers)
.filter(
@@ -679,10 +694,13 @@ async function runRecoverySettlement() {
assert.equal(report.modelCalls, 1);
assert.equal(report.promptSubmissions, 1);
assert.equal(report.continuationsAfterFailure, 0);
assert(report.postFailureLoads.length > 0);
assert(
report.postFailureLoads.length > 0,
`no post-failure loads were recorded at all: ${JSON.stringify(report.postFailureLoadOrigins)}`,
);
assert(
report.postFailureLoads.every(Boolean),
'replacement must use cancellation-only loads',
`replacement must use cancellation-only loads: ${report.postFailureLoadOrigins.join(' | ')}`,
);
await unlink(`${proof}.read-gate`);
await waitUntil(async () => {