mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 19:23:24 +00:00
* refactor(application): build application cancellations with a required reason Migrate every AnalysisCancelledError construction under src/application to cancelledBy and lower the guard baseline from 671 to 442. Shutdown refusals in BinarySession report OwnerCancellation.ownerClosed when the caller did not abort, instead of an undefined reason. ReverseEngineeringService and DesktopBuildOwnedWork close their work with the typed owner reason. SharedStartupAttempt returns the departing caller's reason with a cancelled wait. One shared isAborted predicate replaces eleven local copies and narrows a checked signal for cancelledBy. * refactor(desktop): drop an unused cancellation import from desktop capture state
109 lines
3.6 KiB
TypeScript
109 lines
3.6 KiB
TypeScript
import type { ExecutionOptions } from "./AnalysisProvider.js";
|
|
import type { BrowserScenarioCapturePort } from "./BrowserScenarioCapturePort.js";
|
|
import { createBrowserScenarioEvidence } from "./BrowserScenarioEvidence.js";
|
|
import {
|
|
AnalysisCapabilityUnavailableError,
|
|
AnalysisOutputError,
|
|
cancelledBy,
|
|
} from "../domain/analysisErrorCore.js";
|
|
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
|
import type { Evidence } from "../domain/evidence.js";
|
|
import type { BrowserScenario } from "../domain/browserScenario.js";
|
|
import { err, type Result } from "../domain/result.js";
|
|
import { browserScenarioCaptureSchema } from "../domain/browserScenarioCapture.js";
|
|
import {
|
|
completeProviderEvidence,
|
|
keepIncompleteObservation,
|
|
} from "./ProviderOperationExecution.js";
|
|
|
|
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
|
|
const OPERATION = "capture_browser_scenario" as const;
|
|
const PROVIDER_ID = "rea-playwright-browser-scenario";
|
|
|
|
/** Execute one controlled browser scenario using its explicit request scope. */
|
|
export const captureBrowserScenario = async (
|
|
provider: BrowserScenarioCapturePort | undefined,
|
|
scenario: BrowserScenario,
|
|
options: ExecutionOptions = {},
|
|
): Promise<Result<Evidence, AnalysisError>> => {
|
|
if (provider === undefined)
|
|
return err(
|
|
new AnalysisCapabilityUnavailableError(
|
|
PROVIDER_ID,
|
|
OPERATION,
|
|
"browser scenario provider is not configured",
|
|
),
|
|
);
|
|
if (options.signal?.aborted)
|
|
return err(cancelledBy(OPERATION, options.signal));
|
|
const captured = await provider.captureScenario(scenario, options);
|
|
if (!captured.ok) {
|
|
keepIncompleteObservation(
|
|
captured.error,
|
|
OPERATION,
|
|
"Browser scenario provider retained a non-JSON incomplete observation.",
|
|
);
|
|
const seen = new Set<AnalysisError>();
|
|
const promoted = new Map<object, Evidence>();
|
|
let owner: AnalysisError | undefined = captured.error;
|
|
while (owner !== undefined && !seen.has(owner)) {
|
|
seen.add(owner);
|
|
const partial = owner.partialObservation;
|
|
if (
|
|
partial !== undefined &&
|
|
"kind" in partial &&
|
|
partial.kind === "browser-scenario-observation"
|
|
) {
|
|
const report = browserScenarioCaptureSchema.safeParse(partial.capture);
|
|
// Every cleanup primary may become the selected error after release.
|
|
if (
|
|
report.success &&
|
|
report.data.steps.every(({ status }) => status === "completed")
|
|
) {
|
|
const evidence =
|
|
promoted.get(partial) ??
|
|
createBrowserScenarioEvidence(
|
|
scenario,
|
|
{
|
|
source: jsonValueSchema.parse(partial.capture),
|
|
facts: report.data,
|
|
},
|
|
provider.identity(),
|
|
);
|
|
promoted.set(partial, evidence);
|
|
owner.partialObservation = evidence;
|
|
}
|
|
}
|
|
owner = owner.cleanupPrimary;
|
|
}
|
|
return captured;
|
|
}
|
|
const json = jsonValueSchema.safeParse(captured.value);
|
|
if (!json.success)
|
|
return err(
|
|
new AnalysisOutputError(
|
|
OPERATION,
|
|
"Browser scenario provider returned non-JSON capture data.",
|
|
{ cause: json.error },
|
|
),
|
|
);
|
|
const report = browserScenarioCaptureSchema.safeParse(json.data);
|
|
if (!report.success)
|
|
return err(
|
|
new AnalysisOutputError(
|
|
OPERATION,
|
|
"Browser scenario provider returned a malformed completed capture.",
|
|
{ cause: report.error },
|
|
),
|
|
);
|
|
return completeProviderEvidence(
|
|
createBrowserScenarioEvidence(
|
|
scenario,
|
|
{ source: json.data, facts: report.data },
|
|
provider.identity(),
|
|
),
|
|
options.signal,
|
|
);
|
|
};
|