mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-11 14:10:50 +02:00
Reject Cursor mode drift in native configuration updates
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
5013666821
commit
f5546efbaa
2 files changed
+28
No files matched your search
@@ -60,6 +60,24 @@ describe("Cursor native mode admission", () => {
|
||||
const other = opened("plan").guard;
|
||||
expect(() => other("outbound", { id: 3, method: "session/set_config_option", params: { sessionId: "other", configId: "mode", value: "plan" } })).toThrow(/different session/);
|
||||
});
|
||||
it.each([false, true])("rejects config-option mode drift with active prompt=%s", active => {
|
||||
const { admission, guard } = opened("plan");
|
||||
if (active) guard("outbound", prompt);
|
||||
expect(() => guard("inbound", { method: "session/update", params: { sessionId: "native", update: { sessionUpdate: "config_option_update", configOptions: config("agent") } } })).toThrow(/drifted/);
|
||||
expect(admission.assertReady).toThrow(/drifted/);
|
||||
});
|
||||
it.each(["foreign", "duplicate", "invalid"])("rejects %s mode configuration notifications", kind => {
|
||||
const { guard } = opened("plan");
|
||||
const options = kind === "duplicate" ? [...config("plan"), ...config("plan")] : config(kind === "invalid" ? "architect" : "plan");
|
||||
expect(() => guard("inbound", { method: "session/update", params: { sessionId: kind === "foreign" ? "other" : "native", update: { sessionUpdate: "config_option_update", configOptions: options } } })).toThrow(/mode admission/);
|
||||
});
|
||||
it("ignores model-only partial updates and cannot admit from a mode notification", () => {
|
||||
const { admission, guard } = opened("plan", "agent");
|
||||
for (const options of [[{ id: "model", currentValue: "fixture" }], config("plan")]) {
|
||||
guard("inbound", { method: "session/update", params: { sessionId: "native", update: { sessionUpdate: "config_option_update", configOptions: options } } });
|
||||
expect(admission.isReady()).toBe(false);
|
||||
}
|
||||
});
|
||||
it("does not mistake a bare set_mode response for configuration proof", () => {
|
||||
const { admission, guard } = opened("plan", "agent");
|
||||
guard("outbound", { id: 4, method: "session/set_mode", params: { sessionId: "native", modeId: "plan" } });
|
||||
|
||||
@@ -69,6 +69,16 @@ export function createCursorModeAdmission(expected: CursorSessionMode) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (message.method === "session/update" && object(params.update).sessionUpdate === "config_option_update") {
|
||||
const update = object(params.update);
|
||||
// Config updates may contain only model options. A mode entry is
|
||||
// authoritative observation, but never an admission acknowledgement.
|
||||
if (Array.isArray(update.configOptions) && update.configOptions.some(value => object(value).id === "mode")) {
|
||||
if (!state.sessionId || params.sessionId !== state.sessionId) throw failure("mode update belongs to a different session");
|
||||
if (readMode(update, false) !== expected) throw failure("native mode drifted from the selected mode");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (message.method === "session/update" && object(params.update).sessionUpdate === "current_mode_update") {
|
||||
if (!state.sessionId || params.sessionId !== state.sessionId) throw failure("mode update belongs to a different session");
|
||||
if (object(params.update).currentModeId !== expected) throw failure("native mode drifted from the selected mode");
|
||||
|
||||
Reference in new issue
Block a user