fix(state): key the session on the project, not the working directory - #43
Merged
Conversation
`sessionOwnershipError` blesses running from a package subdirectory, but `sessionPathFor` hashed `Directory.current.path`. A command from there missed its own session file, fell back to the shared pointer, and with two apps up was refused for driving somebody else's: a false refusal, and the defeat of the isolation 0.0.10 shipped. It only held for callers standing in the repo root. `projectRootFor` walks to the nearest ancestor holding a `pubspec.yaml`. Nearest rather than outermost, because that is the unit `artisan start` boots; two packages in one repository are two apps. No pubspec anywhere up the chain falls back to the directory itself, so a non-Dart caller does not end up sharing one session with every other. `start` records the same walked root, because a raw cwd there would make a start from a subdirectory record a root that the ownership check then measures every later command against, refusing the ones run from the package root.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
anilcancakir
added a commit
that referenced
this pull request
Aug 20, 2026
Patch release for #43: the session isolation 0.0.10 introduced only held for callers standing in the repo root, and a command run from a package subdirectory got a false refusal on exactly the layout the ownership guard was written to permit. All six version stamps bumped in one pass, using the list the 0.0.10 cut had to discover: pubspec, the MCP handshake string, both example pubspecs, the skill stamp, and the example lockfile. The two example pubspecs moved together, so pub resolved cleanly rather than failing with `version solving failed`, and the MCP guard test confirms the handshake string moved with the package.
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.
What
StateFile.projectRootForwalks from the working directory to the nearest ancestor holding apubspec.yaml, and both the session key and theprojectRootstartrecords use it.Why
The session isolation shipped in #40 only held for callers standing in the repo root.
sessionOwnershipErrordeliberately lets a command run frombackend/or a package subdirectory through. ButsessionPathForhashed the cwd, so from that same subdirectory the session FILE lookup missed, fell back to the shared~/.artisan/state.jsonpointer, and with two apps up the ownership guard then refused the command for driving somebody else's app. A false refusal, on exactly the layout the guard was written to permit.Design notes
artisan startboots; two packages in one repository are two apps and want two sessions. Pinned by a test.startrecords the walked root too. A raw cwd there would make a start from a subdirectory record a root the ownership check measures every later command against, refusing the ones run from the package root. That would have traded one false refusal for another.Testing
Three new cases in
test/state/state_file_session_test.dart(subdirectory resolves to the project session, nested package keeps its own, no-pubspec keys on itself). Verified red before the fix: the subdirectory hashed to a different session.dart formatzero diff,dart analyzezero issues, 1222 tests green.