Repository navigation
fix(shell): count the reads in a shell command list - #1262
Conversation
A file a command list reads (pwd; cat X, test -f X && cat X, a newline list) is not a read today, so skill use and recall adoption miss it for every tool. Co-authored-by: 007Ghz <77567709+007Ghz@users.noreply.github.com>
classifyShellCommand now reads each pipeline of a list. A read after || credits nothing, error lines are filtered for any non-simple call, and a relative path stops counting after a command that may change the cwd. Co-authored-by: 007Ghz <77567709+007Ghz@users.noreply.github.com>
3fffbe3 to
5fc7e89
Compare
Testing documentation is sufficient: the description records representative built-CLI hook replays and targeted e2e runs. I only read the specified diff; nothing was run, built, or installed. |
…ostics Skip heredoc bodies, command substitutions, compound blocks, and function definitions when crediting shell list reads. Match command diagnostics by the invoked command spelling, basename with .exe, and basename without .exe, reading diagnostics only from stderr when separate or from merged output when exit status is unknown. Co-authored-by: 007Ghz <77567709+007Ghz@users.noreply.github.com>
All three earlier findings are resolved in the current diff. Testing documentation is sufficient: the description records representative built-CLI hook replays at the specified head. Only the specified diff was read; nothing was run, built, or installed. |
…commands, and nested substitutions Track delimiter and substitution nesting via a stack in simpleCommands so inner double quotes inside `$(...)` do not prematurely close outer double quotes. In classifyList, fail closed on commands following shell-terminating commands (`exit`, `exec`, `return`, `logout`, `break`, `continue`, `throw`), after `false &&`, or on `&&` links in non-final conditional chains where prior commands may fail. Co-authored-by: 007Ghz <77567709+007Ghz@users.noreply.github.com>
All six findings from the earlier passes are resolved in the current diff. Testing documentation is sufficient: the description records representative built-CLI hook replays. Its older recorded commit is a note, not a blocking finding. Only the specified diff was read; nothing was run, built, or installed. |
…andalone terminations Track left-to-right AND/OR pipeline execution states so skipped or conditional branches (including printf failures and negated commands) do not falsely credit unopened reads. Allow non-masking trailing delimiters (like semicolons) on final AND-chains, exclude subshell pipeline exits from parent termination, and detect shell termination commands inside compound bodies. Co-authored-by: 007Ghz <77567709+007Ghz@users.noreply.github.com>
All eleven findings from the earlier passes are resolved in the current diff. Testing documentation is sufficient: the description records representative built-CLI hook replays. The older recorded commit is a note, not a blocking finding. Only the specified diff was read; nothing was run, built, or installed. |
…ferred functions, and fallback states Disallow redirections on unconditional zero guards so failed stderr redirections fail closed. Reject assignments containing command substitutions from zero state. Treat compound commands as UNKNOWN condition state to allow valid subsequent guard executions, ignore argument tokens and function bodies when detecting shell termination, avoid shell termination for standalone exec without command arguments, and allow unconditional zero fallback commands after || to restore ZERO state. Co-authored-by: 007Ghz <77567709+007Ghz@users.noreply.github.com>
The previously reported scenarios are resolved in the current diff. Testing documentation is sufficient: the description records representative built-CLI hook replays. The older recorded commit is a note, not a blocking finding. Only the specified diff was read; nothing was run, built, or installed. |
Whether an item of a shell list ran cannot be known from its text and the final exit status without running the shell, so the list simulator is gone. A list is a read only when it is plain words joined by `;`, `&&` or newlines, each item a read or a guard that cannot end, replace or reconfigure the shell (pwd, true, :, echo, ls, a one-file test or [ ], cd). Only the reads of its last `&&` chain count; with no exit status, only the first one, after guards that cannot fail. Everything else is a plain shell call, as on main, and diagnostics are main's again. Co-authored-by: 007Ghz <77567709+007Ghz@users.noreply.github.com>
|
No new findings. The previously reported scenarios are resolved in the current diff. Testing documentation is sufficient: the description records representative built-CLI hook replays at Only the specified diff was read; nothing was run, built, or installed. |
Summary
A file read inside a shell command list (
pwd; cat …/SKILL.md,test -f X && cat X,cd d && cat a.md) now counts as a read for skill use and recall adoption. Whether an item of a list ran cannot be known without running the shell, so only lists in a small closed grammar count. Every other list stays a plainshellcall with no paths, as on main.shell|,||,&, an empty command, a final&&pwd,true,:(no arguments),echo …$(but a$HOME/or${HOME}/path prefix), a backtick,(,),{,},<,#, a line continuation, an unclosed quotels …,testor[ ]with one of-e -f -d -r -sand one operandeval,exec,exit,source,.,set,trap,alias, a function, a reserved word, a path (/bin/true),.execd <dir>, one literal operand: later relative reads in its&&chain move under it2>/dev/nullor2>&1Joined by
;,&&or newlines. A read before the last;counts for nothing, since it may have failed with the call still exiting 0. After acdin an earlier chain only absolute and~paths count.classifyToolCallkeeps main's failed-read rule: a counted read's failure fails the call, so error lines are read only when the status is unknown.Supersedes #1257, whose author (@007Ghz) is credited as co-author on the commits.
Evidence
Hook payloads replayed through the built
dist/cli.js hook-dispatch post-tool-use --bg-onlywith an isolatedHOMEandhello-skillinstalled. Skill uses recorded by main, the previous head45b10457, and this head85c906ac:One table test in
src/__tests__/tool-call.test.tsspecifies the grammar: the counted shapes, and every list raised against earlier heads of this PR reading nothing. Run against45b10457, 47 of the file's 218 tests fail. At85c906acall 218 pass.Gates at
85c906ac:npx tsc --noEmitandnpm run lintpass.npx vitest rungives 11565 passed and 1 failed. The failure ishooks-reconcile-scope.test.ts"fires inside the project … under a real shell" (ENOTDIR on.git/hooks, because the local checkout is a linked git worktree), and it fails the same way with main'ssrc. The diff-based e2e selection matched 0 of 141 e2e files.Merge Danger
Door: two-way. Reverting restores main's handling, where no list is a read.
Blast Radius: attribution
;, pipelines inside a list, and, with no exit status, a read aftertest,ls,cdor another read in its chain.cd dfollowsCDPATHwhen the shell has one set, so a relative read after it could be credited under the wrong directory.Co-authored-by: 007Ghz 77567709+007Ghz@users.noreply.github.com