Compare commits

...
Author SHA1 Message Date
review50-r3andClaude Opus 5.5 30502566aa fix(cli): context-pressure refusal names the config-file pair it checks
The set and reset check is unchanged: the config file has to hold a valid
pair on its own, since each process applies its own environment overrides
when it resolves. The refusal now says so. It names the file's values, says
an unset value counts as its default (95/99), and says environment overrides
aren't part of the check because they aren't saved.

Refs #2529

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 05:15:13 +00:00
review50-r3andClaude Opus 5.5 7cf1a9b56d test(cli): context-pressure refusal says which pair it checked
Red first. `rig config set` and `reset` check the context-pressure pair as
the config file will hold it, with defaults where the file sets none, while
resolution applies environment overrides on top. With an environment
warning of 50, setting critical to 80 is refused as "warning (95) must be
less than critical (80)", which names a value the person doesn't see in
effect. These cells expect the refusal to say it checks the file's values
and that environment overrides aren't counted. A control keeps the refusal
itself and its no-write behaviour.

Refs #2529

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 05:15:13 +00:00
2 changed files with 88 additions and 2 deletions

No files matched your search

+11 -2
View File
@@ -1186,6 +1186,15 @@ function validateTypedFileValue(key: ValidKey, value: string | number | boolean)
check(raw, value);
}
// set and reset check the context-pressure pair as the config file will hold it. The file has to
// stand on its own: each process applies its own environment overrides on top when it resolves.
function invalidContextPressurePairError(warning: unknown, critical: unknown): Error {
return new Error(
`Invalid context-pressure policy: in the config file, warning (${warning}) must be less than critical (${critical}); ` +
"a value the file doesn't set counts as its default (95/99), and environment overrides aren't saved, so they don't count here",
);
}
export type SettingSource = "env" | "file" | "default";
export interface ResolvedSetting {
@@ -1551,7 +1560,7 @@ export class ConfigStore {
const critical = getNestedValue(fileConfig, KEY_TO_PATH["health.context_pressure.critical_percent"])
?? getDefaultValue("health.context_pressure.critical_percent", workspaceRoot);
if ((warning as number) >= (critical as number)) {
throw new Error(`Invalid context-pressure policy: warning (${warning}) must be less than critical (${critical})`);
throw invalidContextPressurePairError(warning, critical);
}
}
mkdirSync(dirname(this.configPath), { recursive: true });
@@ -1603,7 +1612,7 @@ export class ConfigStore {
const critical = getNestedValue(fileConfig, KEY_TO_PATH["health.context_pressure.critical_percent"])
?? getDefaultValue("health.context_pressure.critical_percent", workspaceRoot);
if ((warning as number) >= (critical as number)) {
throw new Error(`Invalid context-pressure policy: warning (${warning}) must be less than critical (${critical})`);
throw invalidContextPressurePairError(warning, critical);
}
}
pruneEmptyAncestors(fileConfig, parentParts);
@@ -0,0 +1,77 @@
// `rig config set` and `rig config reset` check the context-pressure pair as the config file will
// hold it: the file's values, with defaults where it sets none. Environment overrides aren't saved,
// so they aren't part of the check, and the refusal says so.
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import { configCommand } from "../src/commands/config.js";
const ENV_NAMES = [
"OPENRIG_HEALTH_CONTEXT_PRESSURE_WARNING_PERCENT",
"OPENRIG_HEALTH_CONTEXT_PRESSURE_CRITICAL_PERCENT",
];
let dir: string;
let configPath: string;
let savedEnv: Record<string, string | undefined>;
async function run(args: string[]): Promise<{ err: string; exitCode: number | undefined }> {
vi.spyOn(console, "log").mockImplementation(() => {});
vi.spyOn(process.stderr, "write").mockImplementation(() => true);
const error = vi.spyOn(console, "error").mockImplementation(() => {});
try {
await configCommand(configPath, { probeDaemonRunning: async () => false })
.parseAsync(["node", "rig", ...args]);
return { err: error.mock.calls.map((c) => c.join(" ")).join("\n"), exitCode: process.exitCode as number | undefined };
} finally {
vi.restoreAllMocks();
}
}
describe("rig config context-pressure pair check", () => {
beforeEach(() => {
dir = fs.mkdtempSync(path.join(os.tmpdir(), "config-pressure-pair-"));
configPath = path.join(dir, "config.json");
savedEnv = Object.fromEntries(ENV_NAMES.map((name) => [name, process.env[name]]));
for (const name of ENV_NAMES) delete process.env[name];
process.exitCode = undefined;
});
afterEach(() => {
for (const name of ENV_NAMES) {
if (savedEnv[name] === undefined) delete process.env[name];
else process.env[name] = savedEnv[name];
}
process.exitCode = undefined;
fs.rmSync(dir, { recursive: true, force: true });
});
it("still refuses a critical below the file's warning and saves nothing, whatever the environment says", async () => {
process.env["OPENRIG_HEALTH_CONTEXT_PRESSURE_WARNING_PERCENT"] = "50";
const { exitCode } = await run(["set", "health.context_pressure.critical_percent", "80"]);
expect(exitCode).toBe(1);
expect(fs.existsSync(configPath)).toBe(false);
});
it("the refusal says it checks the file's values and doesn't count environment overrides", async () => {
process.env["OPENRIG_HEALTH_CONTEXT_PRESSURE_WARNING_PERCENT"] = "50";
const { err } = await run(["set", "health.context_pressure.critical_percent", "80"]);
expect(err).toBe(
"Invalid context-pressure policy: in the config file, warning (95) must be less than critical (80); " +
"a value the file doesn't set counts as its default (95/99), and environment overrides aren't saved, so they don't count here",
);
});
it("a refused reset gives the same reason and leaves the file as it was", async () => {
const before = JSON.stringify({ health: { contextPressure: { warningPercent: 99, criticalPercent: 100 } } });
fs.writeFileSync(configPath, before);
const { err, exitCode } = await run(["reset", "health.context_pressure.critical_percent"]);
expect(exitCode).toBe(1);
expect(err).toBe(
"Invalid context-pressure policy: in the config file, warning (99) must be less than critical (99); " +
"a value the file doesn't set counts as its default (95/99), and environment overrides aren't saved, so they don't count here",
);
expect(fs.readFileSync(configPath, "utf8")).toBe(before);
});
});