fix(claude): remove unconditional always-mode return in claudeClassifierCompat (#9276)

This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-08-04 21:36:54 -03:00
committed by GitHub
parent 7d6a64b054
commit 6b531fbacd
3 changed files with 21 additions and 5 deletions

View File

@@ -0,0 +1 @@
- fix(claude): remove unconditional "always" return in claudeClassifierCompat so normal chat requests are not swallowed (#9276)

View File

@@ -41,8 +41,8 @@ function extractSystemTexts(body: Record<string, unknown> | null | undefined): s
* True when the inbound request should be default-allowed without calling upstream.
*
* - `mode === "off"` (default): never short-circuits.
* - `mode === "always"`: short-circuits every Claude-format request (operator has
* decided every `/v1/messages` call through this route is the classifier).
* - `mode === "always"`: short-circuits only when the request carries the classifier's
* system-prompt marker (same body-awareness as "auto").
* - `mode === "auto"`: only short-circuits when the request carries the classifier's
* system-prompt marker. `</block>` in `stop_sequences` is corroborating evidence but
* is never sufficient alone — the marker is the strong, classifier-unique signal;
@@ -56,7 +56,6 @@ export function shouldDefaultAllowClassifier(
): boolean {
if (mode !== "auto" && mode !== "always") return false;
if (sourceFormat !== FORMATS.CLAUDE) return false;
if (mode === "always") return true;
return extractSystemTexts(body).some((text) => text.includes(SECURITY_MONITOR_MARKER));
}

View File

@@ -112,9 +112,25 @@ test("detector: never fires for non-Claude source formats even in always mode",
assert.equal(shouldDefaultAllowClassifier(FORMATS.OPENAI, CLASSIFIER_BODY, "always"), false);
});
test("detector: always fires for every Claude-format request", () => {
test("detector: always does NOT fire for normal chat without classifier marker (#9276)", () => {
const plain = { system: [{ type: "text", text: "hi" }], stop_sequences: [] };
assert.equal(shouldDefaultAllowClassifier(FORMATS.CLAUDE, plain, "always"), true);
assert.equal(
shouldDefaultAllowClassifier(FORMATS.CLAUDE, plain, "always"),
false,
"always must NOT short-circuit a normal chat (no security-monitor marker)"
);
});
test("detector: always fires when classifier marker is present", () => {
const classifier = {
system: [{ type: "text", text: "You are a security monitor for autonomous AI coding agents. Evaluate the following action." }],
stop_sequences: ["</block>"],
};
assert.equal(
shouldDefaultAllowClassifier(FORMATS.CLAUDE, classifier, "always"),
true,
"always must short-circuit when the classifier marker is present"
);
});
// ─── Pure builder: buildDefaultAllowClaudeMessage ────────────────────────────