feat(pwd): add rtk pwd for execution-context validation (#2148)#2990
Open
oluies wants to merge 5 commits into
Open
feat(pwd): add rtk pwd for execution-context validation (#2148)#2990oluies wants to merge 5 commits into
oluies wants to merge 5 commits into
Conversation
Author
|
Salut @aeppling ! Petit bonjour de Suède 🇸🇪 Tu peux jeter un œil à cette PR (et à l'analyse dans #2148) quand tu as un moment ? Question de fond : est-ce que cette dérive de cwd avec les worktrees est un problème déjà résolu ailleurs (un autre outil, une autre approche qu'on devrait reprendre), ou est-ce que c'est simplement — comme on dit en Suède, « skit bakom ratten » — de la merde derrière le volant, c'est-à-dire le conducteur (l'agent) qui se trompe de répertoire, et pas rtk ? Mon enquête penche pour la deuxième option : rtk ne touche jamais au cwd (audit du code + 14/14 checks sur un repro déterministe), d'où ce |
Agent harnesses track shell cwd out-of-band and can silently drift to the wrong checkout when git worktrees are involved (rtk-ai#2148). rtk pwd prints the physical cwd, branch, and worktree linkage in one compact block so agents/hooks can validate where commands will execute: /repo/.worktrees/feature branch: feature worktree of: /repo (branch develop) Also surfaces logical $PWD vs physical getcwd() mismatches (symlinked paths), the innocent explanation for pwd != rtk proxy pwd reports. Pure in-process FS walk (no child process, no git dependency): parses .git dir/file, gitdir pointer, commondir, and HEAD directly. Degrades to '(unknown)' on malformed metadata, never fails the user.
- Classify .git files pointing into .git/modules/ as submodules
('submodule of: <super>') instead of mislabeling them as worktrees
with an unresolved pointer.
- Make the branchless 'worktree of:' arm reachable: main_branch now
comes from read_branch_opt, so an unreadable main HEAD prints the
link without an awkward '(branch (unknown))' suffix.
- Parse HEAD honestly: non-heads symbolic refs print verbatim, detached
formatting only applies to plausible object hashes, anything else
degrades to '(unknown)' instead of 'detached @ ref: refs' garbage.
- Check worktree layout before submodule layout so a linked worktree of a submodule keeps its worktree linkage (the drift signal) and gains a 'submodule of:' attribution line instead of losing the linkage. - When the shared gitdir is not a checkout's .git (submodule gitdir), point 'worktree of:' at the gitdir itself rather than fabricating a checkout path from its parent. - Label nested submodules 'submodule (nested) of:' since attribution is always to the outermost superproject, and document that in the code.
- Require a commondir file for worktree classification unless the gitdir is provably not submodule-layout: a plain submodule at path 'worktrees/<name>' no longer gains a bogus 'worktree of:' line. - Document that the 'nested' submodule label is best-effort: the disk layout cannot distinguish a nested submodule from a submodule whose own path contains a 'modules' component.
develop's new classification test requires every Commands variant to be listed as meta or passthrough. rtk pwd is RTK-native (in-process, does not wrap /bin/pwd), so it fails closed instead of falling back to the system pwd on bad args.
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.
Summary
Adds
rtk pwd— a cheap execution-context validation command, motivated by #2148 (see my investigation comment).Agent harnesses (Claude Code, Cursor, …) track their shell cwd out-of-band and can silently drift to the wrong checkout when git worktrees are involved — commands the agent believes run in a linked worktree actually run in the main checkout, and rtk faithfully reports the "wrong" checkout's state (or commits there).
rtk pwdgives agents and hooks a one-shot way to assert where commands will actually execute before writing:It also surfaces logical
$PWDvs physicalgetcwd()mismatches — the innocent explanation behind "pwdandrtk proxy pwddisagree" reports (shell builtins print the symlink-preserving$PWD; child processes only ever see the physical cwd):Design
gitbinary; parses.gitdir/file, thegitdir:pointer,commondir(with a path-based fallback when absent), andHEAD(branch or detached short hash) directly. Keeps startup well within the <10ms budget.(unknown)/(unresolved gitdir pointer); only an unreadable cwd is an error.TimedExecutionlike other info commands.is_operational_command(diagnostic command, invoked explicitly — fail-open per the whitelist comment), and no hook rewrite rule (pwdbuiltin output must stay untouched).Tests
10 hermetic unit tests with hand-crafted
.gitfixtures (no git binary needed): main checkout, subdirectory, linked worktree, missingcommondirfallback, detached HEAD, malformedgitdirpointer, symlink note / differing-$PWDwarn / equal-paths cases.cargo fmt --all✓ ·cargo clippy --all-targets✓ (0 warnings) ·cargo test --all✓ 2006 passed, 0 failed.Verified end-to-end against the real binary in a linked worktree, main checkout, subdirectory, non-repo dir, and through a symlinked
cd.