docs(skills): scope rafter security skills by surface, not task label#195
Merged
Conversation
The rafter skill prompts were all-escalation with no scoping ("DO NOT
stop at local", "an un-evaluated 'done' is not done", "default: run
rafter run") and never said WHAT counts as security-relevant or when the
gate does NOT apply. Agents writing research/experimental code with zero
security surface (training scripts, data analysis, plotting, model eval,
notebooks, pure computation over trusted local data) kept getting the
gate in the way.
Fix (prompting only — no executable code changes): add a "When this
applies (and when it doesn't)" framing driven by the security SURFACE of
the diff, not the task's label.
- ENGAGE fully (unchanged, not weakened): auth, credentials/secrets/
tokens/sessions, user/untrusted input, SQL, shell/exec, file paths +
uploads, deserialization, crypto, network-facing endpoints, data
deletion, dependency/manifest changes.
- BACK OFF: research/experimental/local-only/throwaway code with NONE of
that surface — a quick surface check suffices, and with genuinely no
surface it is fine to proceed without the full rafter-code-review +
rafter run.
- Key rule landed in every edited skill: judge by the actual security
surface of the diff, not by whether the work is called "research."
Research code that touches secrets/shell/network/untrusted input still
fully engages.
Also surface-conditioned the overly-broad `description:` front-matter
(that string drives auto-invocation).
Files: node/resources/skills/{rafter,rafter-code-review,
rafter-secure-design}/SKILL.md and their byte-identical python mirrors
under python/rafter_cli/resources/skills/. rafter-skill-review is left
unchanged on purpose: vetting third-party executable context before
install is always a genuine security surface, so a back-off there would
weaken a real gate.
This REDUCES false engagement on no-surface code without removing or
softening protection for any genuine security surface.
Refs: sable-hjd3
AI-assisted (per repo AI Policy): authored with Claude Opus 4.8.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rome-1
added a commit
that referenced
this pull request
Jul 9, 2026
…el (sable-m9n6) (#196) `rafter agent init` injects RAFTER_INSTRUCTION_BLOCK into agents' instruction files (CLAUDE.md, and ~/.codex/AGENTS.md — a GLOBAL Codex instructions file). The block was a blanket gate ("A security-relevant task is not complete until reviewed... Stop and invoke before continuing") with no scoping. Because Codex reads ~/.codex/AGENTS.md as global instructions, every Codex session was ordered to treat its task as rafter-gated — agents went to read rafter's SKILL.md instead of doing the requested (often no-surface, research) work. Instruction-level hijacking. This applies the same surface-based scoping that PR #195 gave the skill prompts, to the injected block itself, so block and skills tell the same story: - Engage the gate when the change touches a real security surface (auth, secrets/ tokens, untrusted input, SQL/query, shell/exec, file paths, deserialization, crypto, network endpoints/SSRF, data deletion, dependencies). - Back off when NONE of those are present — research/experimental/local-only/ throwaway code (training scripts, analysis, plotting, model eval, notebooks, pure computation over trusted local data): a quick surface check is enough. - Decisive rule: judge by the diff's actual surface, not the "research" label — research code that reads a secret, shells out, hits the network, parses untrusted input, or bumps a dependency still gets the full gate. Guardrail: this reduces false engagement on no-surface code without removing or softening protection for any listed surface — the routing bullets were expanded (crypto, network/SSRF, data deletion, dependencies) so coverage strengthens, not weakens. node and python RAFTER_INSTRUCTION_BLOCK remain byte-identical. Also (sable-h0ah): narrow the Codex .codex/hooks.json PostToolUse matcher from `.*` to `Bash|apply_patch` so posttool stops firing on every Read/MCP call (log noise + latency), matching Codex's own PreToolUse surface and the claude-code posttool scoping. Applied in init.ts, components.ts, and the python mirror; the one test asserting the old value is updated. AI-assisted (Claude Opus 4.8) per repo AI Policy. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Rome-1
added a commit
that referenced
this pull request
Jul 12, 2026
#195 added the surface-scoping section and grew the rafter router SKILL.md from 118 -> 142 lines, blowing BOTH line budgets (node <120, python <130). With no CI, those two tests have been red on main since it merged. - Condense SKILL.md 142 -> 128 lines: the 11-bullet engage list becomes a compact inline list (every surface kept) and the tier section is tightened. No content dropped — the scoping rule stays in the router, since it decides whether the skill is entered at all and can't be pushed into a sub-doc. - Align the node budget 120 -> 130 to match python's. The limits had drifted: python was bumped 120 -> 130 for the scanner-scope section; node never was. Tests: node brief.test.ts 28 passed; python test_brief.py 35 passed. node/python SKILL.md byte-identical. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Rafter skills are a security review gate, but their prompts were all-escalation with no scoping: "DO NOT stop at local", "an un-evaluated 'done' on security-relevant work is not done", "Default expectation: run
rafter run" — and nowhere did they say what counts as security-relevant or when the gate does not apply.Result: agents writing research / experimental / exploratory code with zero security surface (training scripts, data analysis, plotting, model eval, notebooks, pure computation over trusted local data) kept getting the gate in the way. Direct feedback from the repo owner: Rafter should scope itself.
Fix (prompting only — no executable code changes)
Added a "When this applies (and when it doesn't)" framing to the three relevant skills, driven by the security SURFACE of the diff, not the task's label.
exec, file paths + uploads, deserialization, crypto, network-facing endpoints/outbound fetchers (SSRF), data deletion, dependency/manifest changes.rafter-code-review+rafter run.Also surface-conditioned the overly-broad
description:front-matter on each edited skill (that string drives auto-invocation), so auto-triggering follows the surface too.Guardrail: reduces false engagement WITHOUT weakening the gate
The back-off branch fires only when none of the engage surfaces are present; any presence of a real surface re-engages the full gate. No auth/secret/injection/SSRF/dependency surface can slip past. This narrows over-engagement on no-surface code without removing or softening protection for genuine security surface.
rafter-skill-reviewis left unchanged on purpose: vetting third-party executable context before install is always a genuine security surface, so adding a back-off there would weaken a real gate.Files changed / node ↔ python parity
Docs/prompt-only. Edited and kept byte-identical across both trees:
node/resources/skills/rafter/SKILL.md(router — scoping section near the top)node/resources/skills/rafter-code-review/SKILL.mdnode/resources/skills/rafter-secure-design/SKILL.mdpython/rafter_cli/resources/skills/<same-path>Confirmed node vs python identical before and after via
diff. Front-matter still parses cleanly through the existing registry parser (names/versions unchanged; descriptions remain single-line).Refs: sable-hjd3
AI-assisted (per repo AI Policy): authored with Claude Opus 4.8.
🤖 Generated with Claude Code