From fb499cfcbe176d2139b4d44297bd43db2516fe76 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Tue, 27 Oct 2026 12:36:19 -0700 Subject: [PATCH 1/2] Match the Guard's Model Alias Boundaries Regardless of Case The alias inside a workflow script's model value was matched ignoring case while its boundaries excluded only lowercase letters, so a value such as `fableX` or `Xfable` matched `fable` and was denied. Both boundaries now exclude any ASCII letter or digit, and a test covers the uppercase-adjacent values. Co-Authored-By: Claude Opus 5.5 --- host-setup/agent-safety/claude/model-tier-guard.py | 2 +- host-setup/agent-safety/claude/test_model_tier_guard.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/host-setup/agent-safety/claude/model-tier-guard.py b/host-setup/agent-safety/claude/model-tier-guard.py index 2e3a53571..15915d7c8 100755 --- a/host-setup/agent-safety/claude/model-tier-guard.py +++ b/host-setup/agent-safety/claude/model-tier-guard.py @@ -85,7 +85,7 @@ def names_model(text, model): """Whether a script text carries a `model: ''` option naming `model`.""" # A JavaScript key may be bare or quoted, so `{"model": "x"}` is the same option as `{model: "x"}`. # The value may be a full model id rather than the alias, so the alias is matched as a word inside it. - value = r"[^'\"`]*(? Date: Tue, 27 Oct 2026 12:37:49 -0700 Subject: [PATCH 2/2] Cover a Mixed-Case Workflow Model and an Uppercase-Adjacent Alias Co-Authored-By: Claude Opus 5.5 --- host-setup/agent-safety/claude/test_model_tier_guard.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/host-setup/agent-safety/claude/test_model_tier_guard.py b/host-setup/agent-safety/claude/test_model_tier_guard.py index 169d8cd00..0995ea867 100755 --- a/host-setup/agent-safety/claude/test_model_tier_guard.py +++ b/host-setup/agent-safety/claude/test_model_tier_guard.py @@ -108,6 +108,7 @@ def test_a_workflow_script_naming_the_blocked_model_is_denied(self): 'agent("x", {"model": "fable"})', "agent('x', {'model': 'fable'})", "agent('x', { model: 'claude-fable-5-1' })", + "agent('x', { model: 'claude-Fable-5-1' })", ): with self.subTest(script=script): self.assertDenied(self.run_hook("Workflow", {"script": script})) @@ -135,7 +136,7 @@ def test_a_workflow_model_merely_containing_the_blocked_alias_is_allowed(self): for script in ( "agent('x', { model: 'fableX' })", "agent('x', { model: 'Xfable' })", - "agent('x', { model: 'FABLE2' })", + "agent('x', { model: 'FABLEX' })", ): with self.subTest(script=script): self.assertIsNone(self.run_hook("Workflow", {"script": script}))