Repository navigation
Attention: a mutating git command is an action, not read-only inspection - #87
Merged
blast-hardcheese merged 4 commits intoOct 20, 2026
Conversation
The read-only list named git subcommands, so the writing form of six of them counted as pure inspection and attention dropped every reminder for git stash, git tag v1, git branch feature, git config key value, git remote add and git reflog expire. Those subcommands are read-only only in their inspecting form.
There was a problem hiding this comment.
Confidence Score: 2/5
Summary
Score reconciled from 3/5 because the review includes a blocking finding.
Makes attention inspect arguments for branch/config/remote/stash/tag/reflog so their writing forms fire. Net safer, but -v/--verbose wrongly count as list flags, so git branch -v name (creates a branch) stays silent.
Important Files Changed
| File | Overview |
|---|---|
| src/kindex/attention.py | Argument-aware read-only check for six form-dependent git subcommands |
| src/kindex/config.py | Comment documenting form-dependent semantics of listed git subcommands |
| tests/test_attention.py | Regression test for reading vs writing forms; misses branch flag edge cases |
| CHANGELOG.md | Fixed entry under Unreleased |
Reviewed 23490c5...050a755 · ↻ Re-run review · View in Adapt
The read-only check for the form-dependent git subcommands still mis-read four forms: * `git branch -v feature/x` creates the branch — `-v` only makes a listing louder, it does not say that the command lists. * `git branch --set-upstream-to=<upstream>`, `--unset-upstream` and `--edit-description` write the branch configuration without naming a branch, so "no positional argument" did not mean "nothing was written". * `git config edit`, `git config -e` and `git config --edit` open the file for editing, while `git config get <key>` reads a single value. * `git branch --merged` / `--contains` / `--points-at` list filtered branches and their argument is a commit-ish, not a name to create. Adds a regression test for each form.
Collaborator
|
Thank you for your contribution! After additional reviews there were a few more of these edge cases, I'm pushing up a fix now! |
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.
Fixes #86.
What broke
kin's attention decides whether a Bash tool call is pure read-only inspection (not worth interrupting the agent for) or a real action (worth interrupting for). Forgitit matched only the subcommand name:The default list names
branch,config,remote,stash,tagandreflog— subcommands that write in their common form. Sogit stash,git tag v1.0.0,git branch feature/x,git config user.email a@b.c,git remote add origin <url>andgit reflog expire --allwere classified as inspection, the attention hook returned early (src/kindex/cli.py:5769), and no reminder was injected for them.The list's own comment states the opposite contract: "
gitandkinare read-only only for these subcommands; any other subcommand (push, commit, index, export, …) is an action and fires."Root cause
src/kindex/attention.py:324-325— the git check never looks at the arguments, so the reading form and the writing form of one subcommand cannot be told apart.src/kindex/config.py:526-530— the default list contains the six subcommands that have both forms.The change
A listed
gitsubcommand is now read-only only in its inspecting form:branch/taglist, unless they name something to create, move or delete (git tag -amakes an annotated tag, so it is not a listing flag);configreads a key, but writes when it is given a value or asked to unset one;remotereads withshow/get-urland writes withadd/remove/rename/set-url/prune/update;stashreads only withlist/show— a baregit stashsaves the working tree;reflogreads unless it is asked toexpireordeleteentries.A follow-up commit closes four forms the first one still got wrong:
git branch -v feature/xcreates the branch, and-vonly makes a listing louder, so it must not turn a creation into inspection;--list,--merged,--contains,--points-at,--remotes) take a pattern or a commit-ish, so their argument is never the name of a branch to create;git branch --set-upstream-to=<upstream>,--unset-upstreamand--edit-descriptionchange the branch configuration without naming a branch;git config edit,git config -eandgit config --editopen the file for editing, whilegit config get <key>reads a single value — the two were classified the wrong way round.Every other listed subcommand (
status,log,diff,show,blame, …) stays unconditionally read-only, so a subcommand added toattention.readonly_git_subcommandskeeps its previous meaning.How it was verified
Reproduced on the base commit
23490c5, before the change:Trueis "background", i.e. inspection. After the change the same three commands reportFalse, and the reading forms still reportTrue:Regression tests:
tests/test_attention.py::test_is_background_action_fires_on_mutating_git_subcommandsandtests/test_attention.py::test_is_background_action_separates_git_listing_from_creation. The second one was added after an external review flagged four forms this change still got wrong; it fails on the previous commit of this branch and passes on the current one.Full suite,
python -m pytest -q -n 4 --dist loadfile --timeout 300:The 199 failing test IDs are the same set before and after (0 added, 0 removed) — the pre-existing failures are unrelated to this change and unchanged by it. The two extra passes are the new regression tests. The local runs used Python 3.13.9; the repository's CI workflow runs the suite on Python 3.12.
CI status
gh pr checks 87currently reports no checks. The repository's ownCIworkflow is behind the fork approval gate, and the external review bot has not posted a check for the current head yet.The
CIworkflow does have a run on this PR's current head — run39362917061,status=completed,conclusion=action_required, 0 jobs. That is the fork approval gate: the workflow is waiting for a maintainer to approve running it, so the test suite has not run on the upstream runner for this PR. It is not a test failure — the sameCIworkflow on the base commit23490c5is green (run38674146331,conclusion=success).An earlier head of this branch (
050a755) carried one further check, Adapt Review — an external review bot (app.adapt.com), not this repository's CI. It completed with the conclusionfail. It is not a test run of this pull request, but its report is reproducible: all four findings it raised reproduce on this branch, and the follow-up commit fixes all four. They were:git branch -v feature/xcreates a branch, but-vwas treated as a listing flag, so the creation counted as inspection;git branch --set-upstream-to=<upstream>,--unset-upstreamand--edit-descriptionwrite the branch configuration without naming a branch, so they counted as inspection;git config edit,git config -eandgit config --editopen the file for editing, whilegit config get <key>reads a single value — the two were classified the wrong way round;git branch --merged,--containsand--points-atlist filtered branches, but their commit-ish argument was read as the name of a branch to create, so they fired as actions.This change was prepared with the assistance of an AI coding agent.