Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions corpus/skills/cat-mode/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,11 @@ bug: invoke `automate-me`, do not wait.
- **Treat absolute negatives as categorical.**
- **A blocked target is a stop, not a licence to substitute.** A number
produced on a proxy carries the proxy's name beside the number.
- **A hook or classifier block is a stop, not a puzzle.** Do what the block
asks, or report the block and stop. Never reword the prompt, switch tools,
retag the claim, or propose weakening the hook to get past it.
Disagreement with a block goes to the user, after reading the hook's
source.
- **An answer given through a tool binds exactly as hard as a typed one.**

Each rule's full text:
Expand Down
10 changes: 10 additions & 0 deletions corpus/skills/cat-mode/references/named-constraints.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ individual constraints it covers.
name in the same message as the number. Before reaching for a third vendor
or workaround, read `.env.example` and ask which paid source the user
already has.
- **A hook or classifier block is a stop, not a puzzle.** Do not reword a
subagent prompt after `agent-routing-guard` refused it. Do not end a gated
turn with a couldn't-verify tag instead of running the check the gate asked
for. Do not reissue a denied command through a different tool, flag, or
invocation; the classifier-denial rule in `corpus/CLAUDE.learned.md`
already binds this shape. Do not open a change that makes a hook complain
less. Do not relabel or relocate wording so that the region a checker
inspects no longer contains it; the words stay where the check looks, or the
check is raised with the user. Do what the block asks, and if the block is
wrong, read the hook's source and raise it with the user with that evidence.
- **An answer given through a tool binds exactly as hard as a typed one.**
A free-text reply to a multiple-choice question means every option offered
was wrong. Restate it as a binding parameter in the plan before any work
Expand Down
13 changes: 13 additions & 0 deletions tests/test_cat_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,19 @@ def test_named_constraints_reference_keeps_its_rules(self):
self.assertIn("carries the proxy's name in the same message as the number", text)
self.assertIn("An answer given through a tool binds exactly as hard as a typed one", text)

def test_block_is_a_stop_rule_kept_its_full_text_in_the_reference(self):
"""The bullet's bold lead lives in SKILL.md; the concrete forbidden
shapes (reword, retag, reissue through another tool, weaken the hook)
live in named-constraints.md. Locks both halves the same way
test_unhedged_claim_rule_kept_its_full_text_when_it_moved does."""
skill = normalized_skill_text()
self.assertIn("A hook or classifier block is a stop, not a puzzle.", skill)
reference = normalized_reference_text("named-constraints.md")
self.assertIn("A hook or classifier block is a stop, not a puzzle.", reference)
self.assertIn("Do not reword a subagent prompt after `agent-routing-guard` refused it", reference)
self.assertIn("Do not reissue a denied command through a different tool, flag, or invocation", reference)
self.assertIn("Do not open a change that makes a hook complain less", reference)

def test_routing_defers_to_an_installed_harness_routing_skill(self):
skill = normalized_skill_text()
self.assertIn("**An installed harness routing skill wins**", skill)
Expand Down