fix(hooks): keep a removed worktree's hook events in its project (#810) - #824
Merged
Merged
Conversation
SaulMoro
force-pushed
the
fix-810-deleted-cwd-scope
branch
from
September 24, 2026 20:49
3dec2ed to
50a5bf9
Compare
|
No findings. The PR description provides sufficient testing evidence, including a representative real-CLI end-to-end run for the runtime behavior change. Per instruction, I reviewed the diff only and did not execute tests or PR code. |
…cent#810) A hook resolves its scope from the payload's cwd, and resolveConfigForDir answers the user scope for a directory that no longer exists. So once a session's worktree was removed, its remaining events (tool_use, SessionEnd, Stop) and skill uses were recorded under the user scope, which then counted the session and reported the skills to its team, or were dropped when there was no user scope. The project lost the session's last snapshot. resolveHookConfig (dashboard-collector.ts) is the one resolver for the hook dispatcher and the legacy dashboard-report, track and track-slash entry points. For an existing (or absent) cwd it is resolveConfigForDir, as before, and reads nothing else. For a cwd that is gone it reads this session's last event that recorded a dataHomeKey, once per process, preferring the events recorded at that same cwd (a detached Stop can run after the session moved on to another repo), and resolves the config at that event's projectAnchor, the main checkout, which still exists (for a bare repo, whose anchor is the git directory, at one of its worktrees that still exists). It uses that config only when it is still the scope the recorded dataHomeKey names, so a worktree's own legacy .teamai never becomes the main checkout's scope. If that config exists but cannot be read, the event is dropped rather than given to the user scope (Tencent#748). With nothing to match (no events, events from before Tencent#809 without an anchor), it is today's answer. The dispatcher's track and track-slash handlers now use the dispatcher's config instead of resolving their own, and eventProjectAnchor gives an event whose cwd is gone the session's last anchor, as process_exit does. The legacy track-slash looks skills up under the resolved scope's tool roots before the cwd's. The share reminder's gates (contribute-check on Stop, pending-hint on the next prompt) ask about hookScopeDir, the directory resolveHookConfig resolves from, so a removed worktree's session gets the project's reminder settings, not the user scope's. The legacy `teamai contribute-check` command gates the same way. The hook session id has one implementation, deriveDispatchSessionId in utils/session-id.ts, shared by the dispatcher and the event writers.
SaulMoro
force-pushed
the
fix-810-deleted-cwd-scope
branch
from
September 25, 2026 03:05
50a5bf9 to
df5d0f8
Compare
|
No findings. The PR description includes sufficient testing evidence, including a representative real-CLI end-to-end run for the runtime behavior change. The earlier review reported no findings, so there are none to mark resolved. I reviewed only the specified diff and did not execute PR code or tests. |
jeff-r2026
approved these changes
Sep 25, 2026
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
Once a session's worktree was removed, its later hook events and skill uses were recorded under the user scope, which counted the session, or were dropped when there was no user scope. They now keep the scope the session last recorded.
git worktree remove bStop,SessionEnd,tool_use(user scope exists)dataHomeKey, no anchordataHomeKey,projectAnchor/skill)~/.teamai/user-usage.jsonlusage.jsonlteamai statsSessions: 1,team-skill 1 usesNo usage data yet.bafter the session moved to another repob's project and anchorType of Change
Test Plan
npx tsc --noEmitpassesnpx vitest runpasses: 308 files, 4865 passed, 1 skippeddeleted-worktree-scope-810.test.ts(12 cases); unithook-config-810.test.ts(2)report-scope-reuse,report-timeout,dashboard-scoping,dashboard-unified,repo-attribution-worktrees-809: 6 files, 43 passed. The fullnpm run test:e2eruns in CI.The e2e test drives the built CLI: sandbox HOME, local team repo, a project in its partition, a worktree
boutside the checkout, hook payloads on stdin.origin/mainexpected [] to deeply equal [ 'prompt_submit', …(4) ](no user scope: events dropped) and userstatsshowsSessions: 1I removed each of 16 parts alone, rebuilt and re-ran the tests. Every removal made a test fail. The parts cover each entry point, the dispatcher's two track handlers, the three reminder gates, the anchor reuse, the same-cwd preference (scope and anchor), the unreadable-config rule, the data home check, the bare-repo checkout and the legacy tool-roots lookup.
Two existing tests changed, and neither assertion was loosened. The track handlers now take the dispatcher's scope, so
hook-handlers.test.tspasses them the file'sscopefixture instead ofnull, andgit-kind-reports.test.tsresolves the scope throughresolveHookConfig.Reproduced with the real CLI (git mode, sandbox HOME)
From reading the code, not reproduced with the real CLI:
.teamai/installs fall back to today's answer (unit test), because their recordeddataHomeKeyis not the main checkout's scope.session_idgets the pid-based id its events carry (same host process).Related Issues
Closes #810
Notes for Reviewers
usage-tracker.ts:31means that the legacy~/.teamai/usage.jsonlis never read.~/.teamai/user-usage.jsonlis the user scope's own usage and is reported, so the skill uses reached the user-scope team.events.jsonl, once per process.data-directory-layout.md,usage-guide{,.zh-CN}.mdandteam-intelligence-platform.md.dataHomeKey(a hash of the realpath'd data home) in place of thedataHomepath, so the recorded scope matches ondataHomeKey(getDataHome(config)). The e2e and unit tests assert and record the key. The real-CLI transcript above predates the rebase, when events recorded the path; the rebased build passes the same e2e (12 of 12).