fix: add Copilot toolArgs/modifiedArgs support to rtk-rewrite hook#1795
Conversation
Tests added in #1788 check that rtk-rewrite.sh reads Copilot-format input (.toolArgs as object or stringified JSON) and emits .modifiedArgs output, but the hook itself was never updated, so the Shell workflow has been failing on every push to main. #1794 then added two new copilot hook files without updating the coverage list, adding a 5th failure. - Read CMD from .tool_input.command OR .toolArgs.command (object) OR .toolArgs | fromjson | .command (string). - Emit modifiedArgs alongside hookSpecificOutput when input used toolArgs, preserving original fields (e.g. timeout). - Mirror to claude/codex/copilot copies (sync_rtk_rewrite_spec.sh enforces byte equality between claude and codex). - Add config/copilot/hooks/{rtk-rewrite,security}.sh to coverage_spec.sh. Note: scripts/sync-rtk-rewrite.sh fetches from upstream and overwrites all three local copies — next sync will wipe this fix. Documented inline.
|
📝 WalkthroughWalkthroughThree RTK rewrite hook scripts (Claude, Codex, Copilot) are updated to extract commands from Copilot ChangesRTK Rewrite Copilot Support
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
1 issue found across 4 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="config/claude/hooks/rtk-rewrite.sh">
<violation number="1" location="config/claude/hooks/rtk-rewrite.sh:103">
P2: Use tolerant JSON parsing for string `toolArgs` when building `modifiedArgs`; strict `fromjson` can abort the hook under `set -e` on malformed input.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Re-trigger cubic
There was a problem hiding this comment.
Code Review
This pull request updates the rtk-rewrite.sh hooks for Claude, Codex, and Copilot to support Copilot's .toolArgs format, enabling command extraction and modification from both object and stringified JSON inputs. Feedback focuses on improving the robustness of jq parsing by adding type checks after fromjson to prevent errors on non-object values and optimizing performance by consolidating multiple jq process forks into a single call.
| # Build the updated tool_input with all original fields preserved, only command changed. | ||
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input') | ||
| # `// {}` handles pure-Copilot payloads that have no `.tool_input` field. | ||
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // {}') | ||
| UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd') | ||
|
|
||
| # Build Copilot-format `modifiedArgs` when input used `.toolArgs`. Preserves the | ||
| # original toolArgs structure (e.g. `timeout`) with `command` replaced. | ||
| TOOL_ARGS_KIND=$(echo "$INPUT" | jq -r '.toolArgs | type') | ||
| case "$TOOL_ARGS_KIND" in | ||
| object) MODIFIED_ARGS=$(echo "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.toolArgs | .command = $cmd') ;; | ||
| string) MODIFIED_ARGS=$(echo "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.toolArgs | fromjson | .command = $cmd') ;; | ||
| *) MODIFIED_ARGS="null" ;; | ||
| esac | ||
|
|
||
| if [ "$EXIT_CODE" -eq 3 ]; then | ||
| # Ask: rewrite the command, omit permissionDecision so Claude Code prompts. | ||
| jq -n \ | ||
| --argjson updated "$UPDATED_INPUT" \ | ||
| '{ | ||
| "hookSpecificOutput": { | ||
| "hookEventName": "PreToolUse", | ||
| "updatedInput": $updated | ||
| } | ||
| }' | ||
| DECISION="" | ||
| else | ||
| # Allow: output the rewrite instruction in Claude Code hook format. | ||
| jq -n \ | ||
| --argjson updated "$UPDATED_INPUT" \ | ||
| '{ | ||
| "hookSpecificOutput": { | ||
| "hookEventName": "PreToolUse", | ||
| "permissionDecision": "allow", | ||
| "permissionDecisionReason": "RTK auto-rewrite", | ||
| "updatedInput": $updated | ||
| } | ||
| }' | ||
| DECISION="allow" | ||
| fi | ||
|
|
||
| jq -n \ | ||
| --argjson updated "$UPDATED_INPUT" \ | ||
| --argjson modified "$MODIFIED_ARGS" \ | ||
| --arg decision "$DECISION" \ | ||
| ' | ||
| ({ | ||
| hookSpecificOutput: ( | ||
| {hookEventName: "PreToolUse", updatedInput: $updated} | ||
| + (if $decision != "" then | ||
| {permissionDecision: $decision, permissionDecisionReason: "RTK auto-rewrite"} | ||
| else {} end) | ||
| ) | ||
| }) | ||
| + (if $modified != null then {modifiedArgs: $modified} else {} end) | ||
| ' |
There was a problem hiding this comment.
The current implementation uses multiple jq calls to construct the output JSON, which is inefficient in a shell script due to process forking. Additionally, the fromjson call on line 103 is potentially unsafe if .toolArgs is a string but not valid JSON.
Consolidating these into a single jq call improves performance and simplifies the logic while adding robustness to the JSON parsing.
| # Build the updated tool_input with all original fields preserved, only command changed. | |
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input') | |
| # `// {}` handles pure-Copilot payloads that have no `.tool_input` field. | |
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // {}') | |
| UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd') | |
| # Build Copilot-format `modifiedArgs` when input used `.toolArgs`. Preserves the | |
| # original toolArgs structure (e.g. `timeout`) with `command` replaced. | |
| TOOL_ARGS_KIND=$(echo "$INPUT" | jq -r '.toolArgs | type') | |
| case "$TOOL_ARGS_KIND" in | |
| object) MODIFIED_ARGS=$(echo "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.toolArgs | .command = $cmd') ;; | |
| string) MODIFIED_ARGS=$(echo "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.toolArgs | fromjson | .command = $cmd') ;; | |
| *) MODIFIED_ARGS="null" ;; | |
| esac | |
| if [ "$EXIT_CODE" -eq 3 ]; then | |
| # Ask: rewrite the command, omit permissionDecision so Claude Code prompts. | |
| jq -n \ | |
| --argjson updated "$UPDATED_INPUT" \ | |
| '{ | |
| "hookSpecificOutput": { | |
| "hookEventName": "PreToolUse", | |
| "updatedInput": $updated | |
| } | |
| }' | |
| DECISION="" | |
| else | |
| # Allow: output the rewrite instruction in Claude Code hook format. | |
| jq -n \ | |
| --argjson updated "$UPDATED_INPUT" \ | |
| '{ | |
| "hookSpecificOutput": { | |
| "hookEventName": "PreToolUse", | |
| "permissionDecision": "allow", | |
| "permissionDecisionReason": "RTK auto-rewrite", | |
| "updatedInput": $updated | |
| } | |
| }' | |
| DECISION="allow" | |
| fi | |
| jq -n \ | |
| --argjson updated "$UPDATED_INPUT" \ | |
| --argjson modified "$MODIFIED_ARGS" \ | |
| --arg decision "$DECISION" \ | |
| ' | |
| ({ | |
| hookSpecificOutput: ( | |
| {hookEventName: "PreToolUse", updatedInput: $updated} | |
| + (if $decision != "" then | |
| {permissionDecision: $decision, permissionDecisionReason: "RTK auto-rewrite"} | |
| else {} end) | |
| ) | |
| }) | |
| + (if $modified != null then {modifiedArgs: $modified} else {} end) | |
| ' | |
| # Build the final output JSON, consolidating Claude and Copilot formats. | |
| jq -n \ | |
| --argjson input "$INPUT" \ | |
| --arg rewritten "$REWRITTEN" \ | |
| --argjson is_ask "$([ "$EXIT_CODE" -eq 3 ] && echo true || echo false)" \ | |
| ' | |
| ($input.tool_input // {} | .command = $rewritten) as $updated | | |
| ($input.toolArgs | if type == "object" then .command = $rewritten elif type == "string" then (fromjson? | if type == "object" then .command = $rewritten else null end) else null end) as $modified | | |
| { | |
| hookSpecificOutput: ( | |
| {hookEventName: "PreToolUse", updatedInput: $updated} | |
| + (if $is_ask then {} else {permissionDecision: "allow", permissionDecisionReason: "RTK auto-rewrite"} end) | |
| ) | |
| } | |
| + (if $modified != null then {modifiedArgs: $modified} else {} end) | |
| ' |
| # Build the updated tool_input with all original fields preserved, only command changed. | ||
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input') | ||
| # `// {}` handles pure-Copilot payloads that have no `.tool_input` field. | ||
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // {}') | ||
| UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd') | ||
|
|
||
| # Build Copilot-format `modifiedArgs` when input used `.toolArgs`. Preserves the | ||
| # original toolArgs structure (e.g. `timeout`) with `command` replaced. | ||
| TOOL_ARGS_KIND=$(echo "$INPUT" | jq -r '.toolArgs | type') | ||
| case "$TOOL_ARGS_KIND" in | ||
| object) MODIFIED_ARGS=$(echo "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.toolArgs | .command = $cmd') ;; | ||
| string) MODIFIED_ARGS=$(echo "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.toolArgs | fromjson | .command = $cmd') ;; | ||
| *) MODIFIED_ARGS="null" ;; | ||
| esac | ||
|
|
||
| if [ "$EXIT_CODE" -eq 3 ]; then | ||
| # Ask: rewrite the command, omit permissionDecision so Claude Code prompts. | ||
| jq -n \ | ||
| --argjson updated "$UPDATED_INPUT" \ | ||
| '{ | ||
| "hookSpecificOutput": { | ||
| "hookEventName": "PreToolUse", | ||
| "updatedInput": $updated | ||
| } | ||
| }' | ||
| DECISION="" | ||
| else | ||
| # Allow: output the rewrite instruction in Claude Code hook format. | ||
| jq -n \ | ||
| --argjson updated "$UPDATED_INPUT" \ | ||
| '{ | ||
| "hookSpecificOutput": { | ||
| "hookEventName": "PreToolUse", | ||
| "permissionDecision": "allow", | ||
| "permissionDecisionReason": "RTK auto-rewrite", | ||
| "updatedInput": $updated | ||
| } | ||
| }' | ||
| DECISION="allow" | ||
| fi | ||
|
|
||
| jq -n \ | ||
| --argjson updated "$UPDATED_INPUT" \ | ||
| --argjson modified "$MODIFIED_ARGS" \ | ||
| --arg decision "$DECISION" \ | ||
| ' | ||
| ({ | ||
| hookSpecificOutput: ( | ||
| {hookEventName: "PreToolUse", updatedInput: $updated} | ||
| + (if $decision != "" then | ||
| {permissionDecision: $decision, permissionDecisionReason: "RTK auto-rewrite"} | ||
| else {} end) | ||
| ) | ||
| }) | ||
| + (if $modified != null then {modifiedArgs: $modified} else {} end) | ||
| ' |
There was a problem hiding this comment.
The current implementation uses multiple jq calls to construct the output JSON, which is inefficient in a shell script due to process forking. Additionally, the fromjson call on line 103 is potentially unsafe if .toolArgs is a string but not valid JSON.
Consolidating these into a single jq call improves performance and simplifies the logic while adding robustness to the JSON parsing.
| # Build the updated tool_input with all original fields preserved, only command changed. | |
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input') | |
| # `// {}` handles pure-Copilot payloads that have no `.tool_input` field. | |
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // {}') | |
| UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd') | |
| # Build Copilot-format `modifiedArgs` when input used `.toolArgs`. Preserves the | |
| # original toolArgs structure (e.g. `timeout`) with `command` replaced. | |
| TOOL_ARGS_KIND=$(echo "$INPUT" | jq -r '.toolArgs | type') | |
| case "$TOOL_ARGS_KIND" in | |
| object) MODIFIED_ARGS=$(echo "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.toolArgs | .command = $cmd') ;; | |
| string) MODIFIED_ARGS=$(echo "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.toolArgs | fromjson | .command = $cmd') ;; | |
| *) MODIFIED_ARGS="null" ;; | |
| esac | |
| if [ "$EXIT_CODE" -eq 3 ]; then | |
| # Ask: rewrite the command, omit permissionDecision so Claude Code prompts. | |
| jq -n \ | |
| --argjson updated "$UPDATED_INPUT" \ | |
| '{ | |
| "hookSpecificOutput": { | |
| "hookEventName": "PreToolUse", | |
| "updatedInput": $updated | |
| } | |
| }' | |
| DECISION="" | |
| else | |
| # Allow: output the rewrite instruction in Claude Code hook format. | |
| jq -n \ | |
| --argjson updated "$UPDATED_INPUT" \ | |
| '{ | |
| "hookSpecificOutput": { | |
| "hookEventName": "PreToolUse", | |
| "permissionDecision": "allow", | |
| "permissionDecisionReason": "RTK auto-rewrite", | |
| "updatedInput": $updated | |
| } | |
| }' | |
| DECISION="allow" | |
| fi | |
| jq -n \ | |
| --argjson updated "$UPDATED_INPUT" \ | |
| --argjson modified "$MODIFIED_ARGS" \ | |
| --arg decision "$DECISION" \ | |
| ' | |
| ({ | |
| hookSpecificOutput: ( | |
| {hookEventName: "PreToolUse", updatedInput: $updated} | |
| + (if $decision != "" then | |
| {permissionDecision: $decision, permissionDecisionReason: "RTK auto-rewrite"} | |
| else {} end) | |
| ) | |
| }) | |
| + (if $modified != null then {modifiedArgs: $modified} else {} end) | |
| ' | |
| # Build the final output JSON, consolidating Claude and Copilot formats. | |
| jq -n \ | |
| --argjson input "$INPUT" \ | |
| --arg rewritten "$REWRITTEN" \ | |
| --argjson is_ask "$([ "$EXIT_CODE" -eq 3 ] && echo true || echo false)" \ | |
| ' | |
| ($input.tool_input // {} | .command = $rewritten) as $updated | | |
| ($input.toolArgs | if type == "object" then .command = $rewritten elif type == "string" then (fromjson? | if type == "object" then .command = $rewritten else null end) else null end) as $modified | | |
| { | |
| hookSpecificOutput: ( | |
| {hookEventName: "PreToolUse", updatedInput: $updated} | |
| + (if $is_ask then {} else {permissionDecision: "allow", permissionDecisionReason: "RTK auto-rewrite"} end) | |
| ) | |
| } | |
| + (if $modified != null then {modifiedArgs: $modified} else {} end) | |
| ' |
| # Build the updated tool_input with all original fields preserved, only command changed. | ||
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input') | ||
| # `// {}` handles pure-Copilot payloads that have no `.tool_input` field. | ||
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // {}') | ||
| UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd') | ||
|
|
||
| # Build Copilot-format `modifiedArgs` when input used `.toolArgs`. Preserves the | ||
| # original toolArgs structure (e.g. `timeout`) with `command` replaced. | ||
| TOOL_ARGS_KIND=$(echo "$INPUT" | jq -r '.toolArgs | type') | ||
| case "$TOOL_ARGS_KIND" in | ||
| object) MODIFIED_ARGS=$(echo "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.toolArgs | .command = $cmd') ;; | ||
| string) MODIFIED_ARGS=$(echo "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.toolArgs | fromjson | .command = $cmd') ;; | ||
| *) MODIFIED_ARGS="null" ;; | ||
| esac | ||
|
|
||
| if [ "$EXIT_CODE" -eq 3 ]; then | ||
| # Ask: rewrite the command, omit permissionDecision so Claude Code prompts. | ||
| jq -n \ | ||
| --argjson updated "$UPDATED_INPUT" \ | ||
| '{ | ||
| "hookSpecificOutput": { | ||
| "hookEventName": "PreToolUse", | ||
| "updatedInput": $updated | ||
| } | ||
| }' | ||
| DECISION="" | ||
| else | ||
| # Allow: output the rewrite instruction in Claude Code hook format. | ||
| jq -n \ | ||
| --argjson updated "$UPDATED_INPUT" \ | ||
| '{ | ||
| "hookSpecificOutput": { | ||
| "hookEventName": "PreToolUse", | ||
| "permissionDecision": "allow", | ||
| "permissionDecisionReason": "RTK auto-rewrite", | ||
| "updatedInput": $updated | ||
| } | ||
| }' | ||
| DECISION="allow" | ||
| fi | ||
|
|
||
| jq -n \ | ||
| --argjson updated "$UPDATED_INPUT" \ | ||
| --argjson modified "$MODIFIED_ARGS" \ | ||
| --arg decision "$DECISION" \ | ||
| ' | ||
| ({ | ||
| hookSpecificOutput: ( | ||
| {hookEventName: "PreToolUse", updatedInput: $updated} | ||
| + (if $decision != "" then | ||
| {permissionDecision: $decision, permissionDecisionReason: "RTK auto-rewrite"} | ||
| else {} end) | ||
| ) | ||
| }) | ||
| + (if $modified != null then {modifiedArgs: $modified} else {} end) | ||
| ' |
There was a problem hiding this comment.
The current implementation uses multiple jq calls to construct the output JSON, which is inefficient in a shell script due to process forking. Additionally, the fromjson call on line 103 is potentially unsafe if .toolArgs is a string but not valid JSON.
Consolidating these into a single jq call improves performance and simplifies the logic while adding robustness to the JSON parsing.
| # Build the updated tool_input with all original fields preserved, only command changed. | |
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input') | |
| # `// {}` handles pure-Copilot payloads that have no `.tool_input` field. | |
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // {}') | |
| UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd') | |
| # Build Copilot-format `modifiedArgs` when input used `.toolArgs`. Preserves the | |
| # original toolArgs structure (e.g. `timeout`) with `command` replaced. | |
| TOOL_ARGS_KIND=$(echo "$INPUT" | jq -r '.toolArgs | type') | |
| case "$TOOL_ARGS_KIND" in | |
| object) MODIFIED_ARGS=$(echo "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.toolArgs | .command = $cmd') ;; | |
| string) MODIFIED_ARGS=$(echo "$INPUT" | jq -c --arg cmd "$REWRITTEN" '.toolArgs | fromjson | .command = $cmd') ;; | |
| *) MODIFIED_ARGS="null" ;; | |
| esac | |
| if [ "$EXIT_CODE" -eq 3 ]; then | |
| # Ask: rewrite the command, omit permissionDecision so Claude Code prompts. | |
| jq -n \ | |
| --argjson updated "$UPDATED_INPUT" \ | |
| '{ | |
| "hookSpecificOutput": { | |
| "hookEventName": "PreToolUse", | |
| "updatedInput": $updated | |
| } | |
| }' | |
| DECISION="" | |
| else | |
| # Allow: output the rewrite instruction in Claude Code hook format. | |
| jq -n \ | |
| --argjson updated "$UPDATED_INPUT" \ | |
| '{ | |
| "hookSpecificOutput": { | |
| "hookEventName": "PreToolUse", | |
| "permissionDecision": "allow", | |
| "permissionDecisionReason": "RTK auto-rewrite", | |
| "updatedInput": $updated | |
| } | |
| }' | |
| DECISION="allow" | |
| fi | |
| jq -n \ | |
| --argjson updated "$UPDATED_INPUT" \ | |
| --argjson modified "$MODIFIED_ARGS" \ | |
| --arg decision "$DECISION" \ | |
| ' | |
| ({ | |
| hookSpecificOutput: ( | |
| {hookEventName: "PreToolUse", updatedInput: $updated} | |
| + (if $decision != "" then | |
| {permissionDecision: $decision, permissionDecisionReason: "RTK auto-rewrite"} | |
| else {} end) | |
| ) | |
| }) | |
| + (if $modified != null then {modifiedArgs: $modified} else {} end) | |
| ' | |
| # Build the final output JSON, consolidating Claude and Copilot formats. | |
| jq -n \ | |
| --argjson input "$INPUT" \ | |
| --arg rewritten "$REWRITTEN" \ | |
| --argjson is_ask "$([ "$EXIT_CODE" -eq 3 ] && echo true || echo false)" \ | |
| ' | |
| ($input.tool_input // {} | .command = $rewritten) as $updated | | |
| ($input.toolArgs | if type == "object" then .command = $rewritten elif type == "string" then (fromjson? | if type == "object" then .command = $rewritten else null end) else null end) as $modified | | |
| { | |
| hookSpecificOutput: ( | |
| {hookEventName: "PreToolUse", updatedInput: $updated} | |
| + (if $is_ask then {} else {permissionDecision: "allow", permissionDecisionReason: "RTK auto-rewrite"} end) | |
| ) | |
| } | |
| + (if $modified != null then {modifiedArgs: $modified} else {} end) | |
| ' |
Entire-Checkpoint: 9d826b214b88
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/sync-rtk-rewrite.sh`:
- Around line 19-21: The patch invocation using the variables PATCH and tmpfile
can prompt and hang CI; update the patch command in the block that checks [ -f
"$PATCH" ] to run non-interactively by adding the --batch and --forward flags
(so already-applied or reversed hunks are skipped without prompting) and
preserve the use of "<\"$PATCH\"" input redirection; ensure the surrounding
logic still checks the exit status of patch and fails fast if needed (refer to
the PATCH variable and tmpfile usage and the existing if [ -f "$PATCH" ]
conditional).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c101a2f3-34e2-437c-96a2-79ecaf432043
📒 Files selected for processing (8)
config/claude/hooks/rtk-rewrite.shconfig/codex/hooks/rtk-rewrite.shconfig/copilot/hooks/rtk-rewrite.shscripts/rtk-rewrite.copilot.patchscripts/sync-rtk-rewrite.shspec/coverage_spec.shspec/sync_rtk_rewrite_spec.shtreefmt.toml
Entire-Checkpoint: 8c976510b69a
| # LOCAL DIVERGENCE FROM UPSTREAM (rtk-ai/rtk @ master): this copy also reads | ||
| # commands from Copilot's `.toolArgs` (object or string) and emits a top-level | ||
| # `modifiedArgs` alongside `hookSpecificOutput`. scripts/sync-rtk-rewrite.sh will | ||
| # OVERWRITE these additions on next run — re-apply or upstream after syncing. |
There was a problem hiding this comment.
Stale warning after the sync refactor: this banner still says scripts/sync-rtk-rewrite.sh will OVERWRITE these additions on next run, but after 5e79309 the sync script no longer overwrites — it only curls upstream and prints a diff. Worth updating the wording (e.g. “Run scripts/sync-rtk-rewrite.sh to diff against upstream and port any non-Copilot changes in manually”) so future readers don't think their local edits are fragile. Remember to mirror the edit byte-for-byte into the codex and copilot copies so spec/sync_rtk_rewrite_spec.sh stays green.
Summary
The
Shellworkflow has been failing on every push tomainsince #1788 (4 failures) and #1794 added a 5th. Both are pre-existing parity gaps from those merges, not regressions in main code — but they block the green-PR signal for unrelated work.What was broken
modifiedArgstests in spec/rtk_rewrite_spec.sh and spec/codex_rtk_rewrite_spec.sh that check the hook reads Copilot's.toolArgsinput and emits.modifiedArgsoutput, but the hook was never updated.config/copilot/hooks/rtk-rewrite.shandconfig/copilot/hooks/security.shbut didn't register them inspec/coverage_spec.sh'scovered_scriptslist, so the coverage diff test failed.What this PR changes
.tool_input.commandOR.toolArgs.command(object) OR.toolArgs | fromjson | .command(string), reusing the multi-format jq pattern already present inconfig/copilot/hooks/security.sh.modifiedArgsfield alongsidehookSpecificOutputwhen input usedtoolArgs, preserving original fields liketimeout. Claude/Codex output unchanged.claude/codex/copilotcopies (sync_rtk_rewrite_spec.shenforces this between claude and codex).config/copilot/hooks/{rtk-rewrite,security}.shto the coverage list.Caveat (out of scope)
scripts/sync-rtk-rewrite.shfetches fromrtk-ai/rtk@master/.claude/hooks/rtk-rewrite.shand overwrites all three local copies — next manual sync will wipe this patch. Documented inline in the hook header. Follow-up options: upstream the patch, post-process the sync, or pin a fork.Test plan
shellspec spec/rtk_rewrite_spec.sh spec/codex_rtk_rewrite_spec.sh spec/coverage_spec.sh spec/sync_rtk_rewrite_spec.sh→ 102/102 pass locally (was 5 failures on main).shellspec→ 1496/1496 pass (no other suites regressed).Shellworkflow turns green on this PR.🤖 Generated with Claude Code
Summary by cubic
Adds Copilot
toolArgs/modifiedArgssupport tortk-rewrite, makes parsing tolerant, and updates sync/coverage so Shell workflow failures are resolved.Bug Fixes
.tool_input.commandor.toolArgs.command(object or JSON string via tolerantfromjson?).modifiedArgswhen input usedtoolArgs, preserving fields liketimeout.claude,codex, andcopilothook copies and add Copilot hooks to coverage.Tooling
scripts/sync-rtk-rewrite.shdrift-check-only (no overwrites); drop the patch step and print diffs to manually port upstream changes, preserving local Copilot support.claudeandcopilothook files in sync viaspec/sync_rtk_rewrite_spec.sh.config/copilot/hooks/rtk-rewrite.shfromshfmtintreefmt.toml.Written for commit 5e79309. Summary will update on new commits. Review in cubic