mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 03:02:56 +00:00
* fix(process)!: retain observed cleanup intervention Process capture derived `settlement.cleanup_outcome` from the settlement state alone in three places, so a quiesced capture reported `not_required` even after final owned-process cleanup SIGKILLed a live token-owned descendant. `cleanupOwnedProcessGroup` already knew it had signaled, but the capture lifecycle discarded that fact. Carry the observed signal out of ownership cleanup (also on failure paths), accumulate it across cleanup retries as true/false/unknown, and derive settlement and the intervention residual unknown once in `processCaptureCleanupFacts` for full, partial and harness results. BREAKING CHANGE: a quiesced settlement may now report `cleanup_outcome: "cleaned"`. Saved captures stay valid; readers that accepted only `not_required` for quiesced settlements must accept `cleaned`. Fixes #8032 Squashed from #8043 and rebased onto main (adapted to the resource-scope release API and the inspection-failure cleanup path). Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(process): keep a sent signal when cleanup throws an inspection failure Final ownership verification can rethrow a typed inspection failure (for example cancellation) after SIGKILL succeeded. The capture owner then recorded the attempt as unknown and dropped the intervention fact. cleanupOwnedProcessGroup now marks a failure it throws after signaling, without changing the failure's identity, and the capture owner keeps the signal for such failures. Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: wunianze666-netizen <wunianze666@gmail.com> Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
79 lines
2.9 KiB
TypeScript
79 lines
2.9 KiB
TypeScript
import { Client, InMemoryTransport } from "@modelcontextprotocol/client";
|
|
import { afterAll, expect, it, onTestFinished } from "vitest";
|
|
import { createServer } from "../../../src/server/createServer.js";
|
|
import { createTestBinarySession } from "../../fixtures/binarySession.js";
|
|
import { advertisedMcpToolSchemas } from "../../fixtures/advertisedMcpTool.js";
|
|
import { createMcpSchemaValidation } from "../../fixtures/mcpSchemaValidation.js";
|
|
import { emptyProcessCapture } from "../../../src/domain/process/processCapture.fixture.js";
|
|
import { parseProcessCapture } from "../../../src/domain/process/processCaptureParsing.js";
|
|
import { createProcessCaptureEvidence } from "../../../src/application/process/ProcessEvidence.js";
|
|
import { processScenarioSchema } from "../../../src/domain/process/processScenario.js";
|
|
|
|
const validation = createMcpSchemaValidation();
|
|
afterAll(() => validation.clear());
|
|
|
|
it.each(["full", "compact"] as const)(
|
|
"advertises quiesced cleanup intervention without rejecting saved captures (%s)",
|
|
async (profile) => {
|
|
const session = createTestBinarySession(() => {
|
|
throw new Error("Schema discovery must not start a provider");
|
|
});
|
|
const server = createServer(
|
|
{ kind: "session", session },
|
|
{
|
|
environment: {
|
|
...process.env,
|
|
REA_MCP_INPUT_SCHEMA_PROFILE: profile,
|
|
REA_MCP_OUTPUT_SCHEMA_PROFILE: "full",
|
|
},
|
|
},
|
|
);
|
|
const client = new Client(
|
|
{ name: "capture-cleanup-schema", version: "1" },
|
|
{ jsonSchemaValidator: validation },
|
|
);
|
|
onTestFinished(async () => {
|
|
await client.close();
|
|
await server.close();
|
|
await session.close();
|
|
});
|
|
const [clientTransport, serverTransport] =
|
|
InMemoryTransport.createLinkedPair();
|
|
await server.connect(serverTransport);
|
|
await client.connect(clientTransport);
|
|
const schemas = await advertisedMcpToolSchemas(
|
|
client,
|
|
"capture_process_scenario",
|
|
validation.assertions,
|
|
);
|
|
const saved = emptyProcessCapture();
|
|
const scenario = processScenarioSchema.parse({
|
|
executable: "fixture-program",
|
|
});
|
|
const intervened = parseProcessCapture({
|
|
...saved,
|
|
settlement: { ...saved.settlement, cleanup_outcome: "cleaned" },
|
|
residual_unknowns: [
|
|
{ scope: "process", reason: "Fixture cleanup intervention" },
|
|
],
|
|
});
|
|
for (const capture of [saved, intervened]) {
|
|
const evidence = createProcessCaptureEvidence(scenario, capture);
|
|
expect(
|
|
schemas.ajv.validate(schemas.outputSchema, evidence),
|
|
JSON.stringify(schemas.ajv.errors),
|
|
).toBe(true);
|
|
}
|
|
const evidence = createProcessCaptureEvidence(scenario, intervened);
|
|
expect(
|
|
schemas.ajv.validate(schemas.outputSchema, {
|
|
...evidence,
|
|
normalized_result: {
|
|
...intervened,
|
|
settlement: { ...intervened.settlement, cleanup_outcome: "invented" },
|
|
},
|
|
}),
|
|
).toBe(false);
|
|
},
|
|
);
|