Data Safety Rules + Extensible Rule System (PR #131 Part 2)#157
Open
ahundt wants to merge 5 commits intortk-ai:masterfrom
Open
Data Safety Rules + Extensible Rule System (PR #131 Part 2)#157ahundt wants to merge 5 commits intortk-ai:masterfrom
ahundt wants to merge 5 commits intortk-ai:masterfrom
Conversation
Rust binary replaces 204-line bash script as Claude Code PreToolUse hook. Adds rtk hook claude, rtk run -c, and Windows support via cfg!(windows). Closes rtk-ai#112 (chained commands missed). Based on updated master (70c3786) which includes: - Hook audit mode (rtk-ai#151) - Claude Code agents and skills (d8f4659) - tee raw output feature (rtk-ai#134) Migrated from feat/rust-hooks (571bd86) with conflict resolution for: - src/main.rs: Commands enum (preserved both hook audit + our hook commands) - src/init.rs: Hook registration (integrated both approaches) New files (src/cmd/ module): - mod.rs: Module declarations (10 modules, excluding safety/trash/gemini for PR 1) - hook.rs: Shared hook decision logic (21 tests, 3 safety tests removed for PR 2) - claude_hook.rs: Claude Code JSON protocol handler (18 tests) - lexer.rs: Quote-aware tokenizer (28 tests) - analysis.rs: Chain parsing and shellism detection (10 tests) - builtins.rs: cd/export/pwd/echo/true/false (8 tests) - exec.rs: Command executor with recursion guard (22 tests, safety dispatch removed for PR 2) - filters.rs: Output filter registry (5 tests) - predicates.rs: Context predicates (4 tests) - test_helpers.rs: Test utilities Modified files: - src/main.rs: Added Commands::Run, Commands::Hook, HookCommands enum, routing - src/init.rs: Changed patch_settings_json to use rtk hook claude binary command - hooks/rtk-rewrite.sh: Replaced 204-line bash script with 4-line shim (exec rtk hook claude) - Cargo.toml: Added which = 7 for PATH resolution - INSTALL.md: Added Windows installation section Windows support: - exec.rs:175-176: cfg!(windows) selects cmd /C vs sh -c for shell passthrough - predicates.rs:26: USERPROFILE fallback for Windows home directory - No bash, node, or bun dependency - rtk hook claude is a compiled Rust binary Tests: All 541 tests pass
…commands Replaces stub check_for_hook_inner with full tokenize+native-path dispatch. Adds route_native_command() with replace_first_word/route_pnpm/route_npx helpers to route single parsed commands to optimized RTK subcommands. Chains (&&/||/;) and shellisms still use rtk run -c. No safety integration (PR rtk-ai#157 adds that). Mirrors ~/.claude/hooks/rtk-rewrite.sh routing table. Corrects shell script vitest double-run bug for pnpm vitest run flags.
fe612ca to
c4e9ec8
Compare
rtk has no `tail` subcommand — routing to "rtk tail" was silently broken (rtk would error "unrecognized subcommand"). Remove the Route entry so the command falls through to `rtk run -c '...'` correctly. Move the log-tailing test cases from test_routing_native_commands (which asserted the broken path) into test_routing_fallbacks_to_rtk_run where they correctly verify the rtk-run-c fallback behavior.
Port tests added during the ROUTES table integration that were missing from the v2 worktree: registry.rs: - 12 classify tests for Python/Go commands (pytest, go×4, ruff×2, pip×3, golangci-lint) that verify PATTERNS/RULES and ROUTES alignment - 11 lookup tests (test_lookup_*, test_no_duplicate_binaries_in_routes, test_lookup_is_o1_consistent) that verify O(1) HashMap routing hook.rs: - Extend test_routing_native_commands from 20 to 47 cases covering all ROUTES entries: docker, kubectl, curl, eslint, tsc, prettier, playwright, prisma, pytest, golangci-lint, ruff, pip, gh variants - Add test_routing_subcommand_filter_fallback (14 cases) verifying that Only[] subcommand filters correctly reject unmatched subcommands Total: 545 → 569 tests (+24)
Add 11 safety rules intercepting destructive commands: - rm → trash (cross-platform via trash crate) - git reset --hard/clean/checkout → stash first - cat/head/sed → blocked, suggest Read tool or Edit tool Extensible rtk.*.md rule files with YAML frontmatter loaded from .rtk/, .claude/, .gemini/ directories. Config system expanded from single config.rs to config/ module with rules.rs and discovery.rs. Env var opt-out: RTK_SAFE_COMMANDS=0 disables safety rules, RTK_BLOCK_TOKEN_WASTE=0 allows cat/head/sed. Config CLI expanded: rtk config get/set/list/unset/create/export-rules. New dependencies: trash = "5", serde_yaml = "0.9" Closes rtk-ai#115 Tests: 673 total (35 safety, 4 trash, 3 restored hook safety tests)
c4e9ec8 to
c1b7685
Compare
edsai
pushed a commit
to edsai/rtk
that referenced
this pull request
Feb 19, 2026
…commands Replaces stub check_for_hook_inner with full tokenize+native-path dispatch. Adds route_native_command() with replace_first_word/route_pnpm/route_npx helpers to route single parsed commands to optimized RTK subcommands. Chains (&&/||/;) and shellisms still use rtk run -c. No safety integration (PR rtk-ai#157 adds that). Mirrors ~/.claude/hooks/rtk-rewrite.sh routing table. Corrects shell script vitest double-run bug for pnpm vitest run flags.
edsai
pushed a commit
to edsai/rtk
that referenced
this pull request
Feb 19, 2026
…commands Replaces stub check_for_hook_inner with full tokenize+native-path dispatch. Adds route_native_command() with replace_first_word/route_pnpm/route_npx helpers to route single parsed commands to optimized RTK subcommands. Chains (&&/||/;) and shellisms still use rtk run -c. No safety integration (PR rtk-ai#157 adds that). Mirrors ~/.claude/hooks/rtk-rewrite.sh routing table. Corrects shell script vitest double-run bug for pnpm vitest run flags.
edsai
pushed a commit
to edsai/rtk
that referenced
this pull request
Feb 19, 2026
…commands Replaces stub check_for_hook_inner with full tokenize+native-path dispatch. Adds route_native_command() with replace_first_word/route_pnpm/route_npx helpers to route single parsed commands to optimized RTK subcommands. Chains (&&/||/;) and shellisms still use rtk run -c. No safety integration (PR rtk-ai#157 adds that). Mirrors ~/.claude/hooks/rtk-rewrite.sh routing table. Corrects shell script vitest double-run bug for pnpm vitest run flags.
Author
|
@pszymkowiak I saw a pending problem tag added to this one is there a particular technical issue? I've been running it without issue myself. |
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.
PR 131 Part 2: Data Safety Rules + Extensible Rule System
Branch:
feat/data-safety-rules-v2| Base:master(stacks on Part 1)Tests: 673 pass | Closes: #115
Split from: PR #131
New deps:
trash = "5",serde_yaml = "0.9"PR: #157
Context
Addresses item 2 from FlorianBruniaux's split request:
Depends on PR 1 for the hook engine (
safety.rsintegrates intohook.rsandexec.rs). Parallel to PR 3 (Gemini) -- zero file overlap.Merge Sequence
After PR 1 merges: retarget
feat/data-safety-rules-v2->master, then merge. Can merge before or after PR 3.Summary
11 safety rules intercept destructive commands and make them recoverable.
Impact: Prevents ~20-50K token costs per data loss incident (investigate damage → restore/rewrite → regenerate → debug differences).
Rules
rmgit reset --hardgit checkout ./git checkout --git clean -f/-fd/-dfgit stash dropgit stash pop(recoverable)cat/head/sedConditional rules (
git reset --hard,git checkout) usewhen: has_unstaged_changes-- only fire when uncommitted changes exist.Opt-out:
RTK_SAFE_COMMANDS=0disables safety rules.RTK_BLOCK_TOKEN_WASTE=0allows cat/head/sed.Extensible
rtk.*.mdrule filesRules are markdown with YAML frontmatter. 11 built-in rules compile into the binary via
include_str!(). Users override or extend by placing files in.rtk/,.claude/,.gemini/, or~/.config/rtk/:Priority: CLI paths > project-local dirs > global dirs > built-in defaults. Same-name rules override by priority.
User custom rule example --
~/.config/rtk/rtk.safety.chmod-777.md:Config system expansion
src/config.rs(125 lines) replaced bysrc/config/module (3 files, 2419 lines):mod.rs-- Config struct with precedence chain, CRUD operationsrules.rs-- Rule loading, regex matching,try_remap()alias expansiondiscovery.rs-- Walk-up ancestor directory discoveryNew commands:
rtk config list/get/set/unset/create/export-rulesChanges
24 files changed (+3535, -148)
New:
src/cmd/safety.rs(538 lines, 30 tests),src/cmd/trash_cmd.rs(76 lines, 4 tests),src/config/{mod,rules,discovery}.rs, 11 rule files insrc/rules/Modified:
src/cmd/mod.rs(+safety, +trash_cmd),src/cmd/hook.rs(restore safety integration),src/cmd/exec.rs(restore safety dispatch),src/main.rs(+Config commands),Cargo.toml(+trash, +serde_yaml)Deleted:
src/config.rs(replaced bysrc/config/module)Review Guide
Focus areas:
src/cmd/safety.rs+src/rules/*.md-- Rule matching and rewritingsrc/config/rules.rs+discovery.rs-- Rule loading, precedence, override semanticssrc/cmd/hook.rs+exec.rs-- Safety integration pointsNot Included (Future)
sudo rm,docker rm,kubectl deletewith confirmationsalwaysandhas_unstaged_changesTest Plan
cargo test-- 673 tests pass (safety:30, trash:4, rules:15, discovery:8, +3 restored hook tests)echo '{"tool_input":{"command":"rm file"}}' | cargo run -- hook claude-- rm rewrittenecho '{"tool_input":{"command":"cat file.txt"}}' | cargo run -- hook claude-- cat blocked (exit 2)cargo run -- hook check "git clean -fd"-- stash prependedRTK_SAFE_COMMANDS=0 cargo run -- hook check "rm file"-- opt-out workscargo run -- hook check "catalog show"-- NOT blocked (catalog != cat)cargo run -- config list-- CRUD worksRelated PRs (Split from PR #131)
Merge order: Part 1 first → retarget Parts 2 & 3 to
master→ merge in any order