mirror of
https://github.com/morluto/rea
synced 2026-10-25 14:01:13 -04:00
fix(config): expose native matching session repair
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
||||
import { expect, it } from "vitest";
|
||||
import { ConfigurationError } from "../domain/configurationErrors.js";
|
||||
import { parseEnvironment } from "./environment.js";
|
||||
@@ -76,3 +77,19 @@ it("refuses invalid launch values instead of falling back to the default", () =>
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it("advertises current-session repair for an invalid native matching launch seed", () => {
|
||||
const parsed = parseNativeMatchingAllowance({
|
||||
[NATIVE_MATCHING_ALLOWANCE_SETTING]: "0",
|
||||
});
|
||||
if (parsed.ok) throw new Error("Invalid seed was accepted");
|
||||
const projection = projectAnalysisError(parsed.error);
|
||||
expect(projection.code).toBe("configuration_invalid");
|
||||
expect(projection.remediation.action).toContain("update_analysis_settings");
|
||||
expect(projection.remediation.action).toContain(
|
||||
"native.matching_representation_bytes",
|
||||
);
|
||||
expect(projection.remediation.action).toContain(
|
||||
NATIVE_MATCHING_ALLOWANCE_SETTING,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -47,6 +47,7 @@ export const parseNativeMatchingAllowance = (
|
||||
? ok({ maximumBytes: parsed.data, source: "setting" })
|
||||
: err(
|
||||
new ConfigurationError(nativeMatchingRepresentationBytesConstraint, {
|
||||
remediationAction: `On a running MCP session, call update_analysis_settings with ${JSON.stringify({ changes: [{ setting: "native.matching_representation_bytes", action: "set", value: DEFAULT_NATIVE_MATCHING_REPRESENTATION_BYTES }] })}, then retry matching. This repairs the current session for the next operation. For CLI or future REA processes, correct ${NATIVE_MATCHING_ALLOWANCE_SETTING} in the launch environment.`,
|
||||
settings: [
|
||||
{
|
||||
setting: NATIVE_MATCHING_ALLOWANCE_SETTING,
|
||||
|
||||
@@ -158,8 +158,13 @@ export const analysisErrorRemediationAction = (
|
||||
return "Check the current process's read access to the selected path. Retry with a readable local file.";
|
||||
if (error instanceof AnalysisArtifactChangedError)
|
||||
return "Wait until the selected file is stable. For an active binary session, reopen the target with open_binary before retrying so REA acquires its current identity; for a CLI command or target-free tool, rerun the operation.";
|
||||
if (error instanceof ConfigurationError && error.settings.length > 0)
|
||||
return `Correct ${[...new Set(error.settings.map(({ setting }) => setting))].join(", ")} in the environment that starts REA (your shell or the MCP client's registration), then rerun.`;
|
||||
if (error instanceof ConfigurationError)
|
||||
return (
|
||||
error.remediationAction ??
|
||||
(error.settings.length > 0
|
||||
? `Correct ${[...new Set(error.settings.map(({ setting }) => setting))].join(", ")} in the environment that starts REA (your shell or the MCP client's registration), then rerun.`
|
||||
: analysisErrorUserMessage(error))
|
||||
);
|
||||
if (error instanceof AnalysisInputError)
|
||||
return (
|
||||
error.remediationAction ??
|
||||
|
||||
@@ -9,7 +9,10 @@ import {
|
||||
AnalysisResourceConstraintError,
|
||||
} from "./analysisErrorCore.js";
|
||||
import { ArtifactOperationError } from "./artifactOperationError.js";
|
||||
import { BinaryTargetError } from "./configurationErrors.js";
|
||||
import {
|
||||
BinaryTargetError,
|
||||
ConfigurationError,
|
||||
} from "./configurationErrors.js";
|
||||
import { BrowserObservationError } from "./browserObservationError.js";
|
||||
import { EvidenceFileError, EvidenceIntegrityError } from "./evidenceErrors.js";
|
||||
import {
|
||||
@@ -1170,3 +1173,24 @@ it("does not offer entry-policy retries for integrity refusals without a declare
|
||||
expect(native.message).not.toContain("record-and-continue");
|
||||
expect(native.remediation.action).not.toContain("record-and-continue");
|
||||
});
|
||||
|
||||
it("preserves ordinary configuration recovery and projects a producer-owned session repair", () => {
|
||||
const settings = [{ setting: "REA_EXAMPLE", constraint: "must be positive" }];
|
||||
const original = projectAnalysisError(
|
||||
new ConfigurationError("Invalid setting", { settings }),
|
||||
);
|
||||
const repairing = projectAnalysisError(
|
||||
new ConfigurationError("Invalid setting", {
|
||||
settings,
|
||||
remediationAction: "Repair the running session, then retry.",
|
||||
}),
|
||||
);
|
||||
expect(original.remediation.action).toBe(
|
||||
"Correct REA_EXAMPLE in the environment that starts REA (your shell or the MCP client's registration), then rerun.",
|
||||
);
|
||||
expect(repairing).toEqual({
|
||||
...original,
|
||||
remediation: { action: "Repair the running session, then retry." },
|
||||
});
|
||||
expect(repairing.code).toBe("configuration_invalid");
|
||||
});
|
||||
|
||||
@@ -12,14 +12,18 @@ export interface ConfigurationSettingIssue {
|
||||
/** Rejected settings retained for diagnostics; their values are not. */
|
||||
export interface ConfigurationErrorOptions extends AnalysisErrorOptions {
|
||||
readonly settings?: readonly ConfigurationSettingIssue[];
|
||||
/** Producer-owned recovery when this setting can be repaired in a running session. */
|
||||
readonly remediationAction?: string;
|
||||
}
|
||||
|
||||
/** Runtime configuration could not be parsed safely. */
|
||||
export class ConfigurationError extends AnalysisError {
|
||||
readonly _tag = "ConfigurationError";
|
||||
readonly settings: readonly ConfigurationSettingIssue[];
|
||||
readonly remediationAction: string | undefined;
|
||||
constructor(message: string, options?: ConfigurationErrorOptions) {
|
||||
super(message, options);
|
||||
this.remediationAction = options?.remediationAction;
|
||||
this.settings = (options?.settings ?? []).map(
|
||||
({ setting, constraint }) => ({ setting, constraint }),
|
||||
);
|
||||
|
||||
@@ -266,6 +266,9 @@ it("lowers, restores and seeds the native matching allowance over MCP", async ()
|
||||
if (text?.type !== "text") throw new Error("Missing projected error");
|
||||
expect(JSON.parse(text.text).error).toMatchObject({
|
||||
code: "configuration_invalid",
|
||||
remediation: {
|
||||
action: expect.stringContaining("update_analysis_settings"),
|
||||
},
|
||||
details: {
|
||||
settings: [{ setting: "REA_NATIVE_MATCHING_REPRESENTATION_BYTES" }],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user