Skip to content

Record a Per-Fetch Token in hub.owned So a Menu Removes Only the Hub It Fetched - #2542

Merged
ptr727 merged 3 commits into
developfrom
feature/menu-ps1-fetch-token
Oct 8, 2026
Merged

ptr727 merged 3 commits into
developfrom
feature/menu-ps1-fetch-token

Conversation

@ptr727

@ptr727 ptr727 commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Summary

Refs #1093.

menu.ps1 and menu.sh share a hub cache, $DIR/hub, marked by $DIR/hub.owned. A session's exit cleanup removed that tree whenever its own process-local HUB_FETCHED was true and the marker existed. A session that fetched earlier could therefore delete a tree another session sharing the directory fetched since, a -Keep / --keep session's included.

  • Each fetch now writes a token unique to that fetch into the marker: a GUID in menu.ps1 and 16 bytes of /dev/urandom as hex in menu.sh.
  • The exit cleanup, once it holds the hub lock, removes the tree only when the marker still holds this session's own token (Test-HubFetchedHere / hub_fetched_here). A session that has no token, or finds an empty marker, removes nothing.
  • The issue says menu.sh lacks this shape. It does not: it has the same marker and the same cleanup gate, and both menus can share one --dir, so both are fixed here.

Known limit

An older copy of either menu, one fetched before this lands, still deletes whenever any marker exists. Until it is replaced, it can remove a tree a new session fetched. Nothing here can close that, since an old copy never reads the token.

Verification (Windows host)

  • New TestMenuHubCleanup (bash, run under Git Bash with flock stubbed) and TestPowerShellMenuHubCleanup (pwsh, under the real lock) share one set of cases. Two of them run a real fetch with git stubbed: a session's own fetch is removed at exit, and a fetch by another session made since survives the first session's exit.
  • Mutation-checked in both menus. Disabling the token gate fails 3 cases per menu, and writing an empty marker fails the own-fetch case per menu.
  • Full suite under Git Bash: 2270 tests, OK, 100 skipped.
  • ruff, mypy, the prose gate and the EOL gate pass, and so do shellcheck, shfmt and PSScriptAnalyzer through scripts/docker_lint.py.
  • Two local strict-review passes. The first raised one finding, a test name claiming a cross-menu match that cannot occur, which is fixed in e921ba5. The second raised none.
  • Not run on Linux locally. CI's Linux run covers menu.sh under real bash and menu.ps1 under Linux pwsh.

The review also found one pre-existing defect, filed as #2541: the freshness check ignores --ref.

🤖 Generated with Claude Code

ptr727 and others added 2 commits October 8, 2026 08:07
…It Fetched

Each fetch in menu.ps1 and menu.sh now writes a token unique to that
fetch into the shared hub.owned marker, and the exit cleanup removes the
cached hub only when the marker still holds this session's own token,
checked under the hub lock. A session that fetched earlier no longer
deletes a tree another session sharing the same cache directory fetched
since, a -Keep session's included.

menu.sh had the same gap as menu.ps1, and both menus share one marker
through a common cache directory, so both write the same form: the token
text, which each side compares after trimming the trailing newline.

Closes #1093

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…und Trip

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings October 8, 2026 15:15
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Repository: ptr727/ProjectTemplate/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 0bc5e99a-9284-40e7-8632-2716b84c4de3
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Resolve the two outstanding menu.sh token-generation and cross-menu CRLF cleanup findings.

0 open findings

What changed in this PR

This PR adds per-fetch ownership tokens so shared hub-cache cleanup removes only the cache fetched by the current session.

Changes:

  • Adds token recording and validation to both menu implementations.
  • Adds cleanup tests covering ownership, refetches, empty markers, and line endings.
  • menu.sh still requires token-generation failure handling and CRLF normalization.
File Reviewed changes
tests/​test_bootstrap.py Adds shared cleanup ownership tests for both menus.
host-setup/​menu.sh Adds random fetch tokens and ownership-gated cleanup.
host-setup/​menu.ps1 Adds GUID fetch tokens and ownership validation.

🧠 Review effort: Lite


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

@codecov

codecov Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 58.40%. Comparing base (382c0cc) to head (912b557).

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #2542   +/-   ##
========================================
  Coverage    58.40%   58.40%           
========================================
  Files           16       16           
  Lines         8090     8090           
========================================
  Hits          4725     4725           
  Misses        3365     3365           
Flag Coverage Δ
python-3.13 58.40% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…nges the Cache

fetch_hub_locked runs with errexit suspended, so a failed /dev/urandom read would otherwise mark the fetch with an empty token that no cleanup ever matches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Oct 8, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head 912b557ff2ccd0a6e072906d252e15c1abda780b, the content this pull request carries at that commit against develop, and it recorded 0 findings.

@ptr727

ptr727 commented Oct 8, 2026

Copy link
Copy Markdown
Owner Author

Copilot's round on e921ba5 opened no thread, but its headline named two outstanding menu.sh findings. They are answered here, and the reader gap that let the digest pass them is filed as #2544.

  1. Token-generation failure handling: fixed in 912b557. fetch_hub_locked runs as fetch_hub_locked || rc=$?, so errexit is suspended inside it. A failed /dev/urandom read would have marked the fetch with an empty token that no cleanup ever matches. The read now comes first, before remove_unowned_hub_check and rm -rf, and a failure or an empty result fails the fetch with nothing in the cache changed. test_a_token_that_cannot_be_read_fails_the_fetch_before_it_changes_anything stubs od to fail, and a mutation check confirms the test fails without the guard. menu.ps1 has no counterpart: [guid]::NewGuid() cannot fail, and a Set-Content failure throws under $ErrorActionPreference = 'Stop', as the New-Item it replaced did.
  2. Cross-menu CRLF normalization: declined, since nothing compares one menu's token against a marker the other menu wrote. Each session compares the marker only with HUB_FETCH_TOKEN, the token its own fetch generated: hub_fetched_here in menu.sh, Test-HubFetchedHere in menu.ps1. A marker written by the other menu holds that menu's token, never this session's, so it reads as a mismatch whatever its line ending, and a mismatch is the correct answer, because that tree belongs to the other session. Each menu does read back its own line ending: $(<file) strips menu.sh's LF, and .Trim() strips the CRLF Set-Content writes on Windows. test_a_marker_ending_in_the_line_break_its_menu_writes_still_matches covers both.

@ptr727
ptr727 merged commit 9d8937b into develop Oct 8, 2026
12 checks passed
@ptr727
ptr727 deleted the feature/menu-ps1-fetch-token branch October 8, 2026 15:43
ptr727 added a commit that referenced this pull request Oct 8, 2026
## Summary

Promotes one change from `develop`.

- #2542: `menu.ps1` and `menu.sh` each write a token unique to the fetch
into the shared `hub.owned` marker. The exit cleanup, holding the hub
lock, removes the cached hub only when the marker still holds the
session's own token. A session that fetched earlier no longer deletes a
tree another session sharing the cache directory fetched since, a
`-Keep` / `--keep` session's included. In `menu.sh` the token is read
before the fetch changes anything, and a failed read fails the fetch,
since errexit is suspended there.

Closes #1093.

## Verification

- The new `TestMenuHubCleanup` (bash) and `TestPowerShellMenuHubCleanup`
(pwsh, real lock) cases pass on Windows, and the full suite passes under
Git Bash (2270 tests, 100 skipped). Mutation checks fail the new cases
in both menus. CI covers the Linux side.
- #2542 took three recorded local strict-review passes, and the last two
raised nothing. Copilot ran one round, which opened no thread. Its
headline named two `menu.sh` findings. The token-read failure was fixed
in 912b557, and cross-menu CRLF was declined with evidence, since a
session only ever compares the marker with its own token. The reader gap
that let the digest pass that headline is filed as #2544.
- Pre-existing and out of scope: #2541, the freshness check ignoring
`--ref`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants