Skip to content

fix(port): worktree audit counts subdirectory, profile and custom-dir sessions - #31

Merged
AlexNegrescu26 merged 14 commits into
mainfrom
fix/audit-subdir-buckets-live-probe
Oct 25, 2026
Merged

AlexNegrescu26 merged 14 commits into
mainfrom
fix/audit-subdir-buckets-live-probe

Conversation

@AlexNegrescu26

Copy link
Copy Markdown
Collaborator

Why

The worktree audit missed three places a chat can live. A merged worktree with a recent omp chat could land in safe, and the cleanup playbook offers that bucket for deletion.

What changed

  • It also scans the buckets of a worktree's subdirectories. omp names a session's bucket from the session's cwd, so a chat started in <worktree>/sub was invisible.
  • It counts sessions launched with --profile or --session-dir. It scans the worktree buckets in every profile and XDG store, and reads omp's custom-session-files lists for moved stores.
  • The live omp probe fails instead of skipping when OMP_AUDIT_LIVE_REQUIRED=1. The smoke CI job, which has a pinned omp, now runs the audit test that way.
  • session-store-on-omp.md records the subdirectory rule, the custom-session-files list, and the one store the audit cannot see.

Scope

  • A store moved at launch by PI_CODING_AGENT_DIR, PI_CONFIG_DIR, XDG_DATA_HOME or XDG_STATE_HOME leaves nothing on disk the audit can find. That is documented, with what to do: rerun the audit with those variables set, or read get_state.sessionFile from the live session.
  • The main worktree is skipped by the subdirectory scan, because a repo at $HOME would make the prefix match the whole store.

Tradeoffs

A plain "bucket plus -" prefix misses absolute subdirectories, so the scan uses the same encoder omp's bucket names use. A prefix like foo can also scan -foo-bar. That fails safe, because a transcript must still name <foo>/ to count.

Blast Radius

The audit can hold more rows than before and never fewer. Three existing tests that expected no chat for a profile or custom store now expect today's date, on purpose.

Verification

  • Each fix has a test commit that fails first. Subdirectory: FAIL [gh] subdir BUCKET: want 'verify-recent-chat', got 'safe'. Profile and --session-dir: FAIL [live-omp] probe profile LAST_CHAT: want '2026-10-25', got '-'. All three pass after the fix.
  • With OMP_AUDIT_LIVE_REQUIRED=1 and no omp on PATH, the test now fails with FAIL [live-omp] omp is not on PATH. It passes with the real omp 18.12.6.
  • check-port.sh, test-gate-mutations.sh, test-worktree-audit.sh and smoke-plugin.mjs pass locally. The new CI step has not yet run on a GitHub runner.

…ry (fails until the fix)

omp files a session under the bucket of its own cwd, so a chat started in <worktree>/src never reaches the audit and a merged worktree reads as safe. The live probe asks omp for that path from a home and an absolute subdirectory.
omp names a session's bucket after its own cwd, so a session started in <worktree>/src sits in <bucket>-src, or --<abs>-src-- outside home and temp. The audit now also scans every existing bucket that matches the worktree's encoded name with a subdirectory appended, built by the same encoder. A transcript must still name the worktree path, so a sibling such as foo-bar that shares foo's prefix costs one more grep and never a match. The main worktree is skipped, since a repo at $HOME would turn the prefix into the whole store.
…sion-dir (fails until the fix)

Both flags move a transcript out of the store the audit resolves from its own environment. Each leaves an on-disk trace: a profile writes under <config>/profiles/<name>, and omp records the absolute path of every transcript outside the bucket store in the agent dir's custom-session-files. The live probe launches omp with each flag. The stores the audit's environment replaces still count, so the RECENT assertions under an explicit dir, a profile and XDG_DATA_HOME flip.
Under a symlinked HOME omp lists every transcript, bucket ones included, in custom-session-files, so an audit that reads the index found the subdirectory and profile probes without scanning their buckets. The live probe drops that index before the bucket audit and runs the --session-dir probe after it, so each rule is proven alone.
…ion-dir

Neither flag is visible to the audit's environment, but both leave a bounded trace on disk. Each profile's store sits under <config>/profiles/<name>, and omp lists the absolute path of every transcript it writes outside the bucket store, from --session-dir, PI_CODING_AGENT_SESSION_DIR or a --resume of a moved file, in the agent dir's custom-session-files, or XDG_STATE_HOME/omp's when that exists. The audit now scans the worktree buckets of every store under the config root and the XDG roots and every transcript the indexes list, with its subagent directory. The store the environment resolves still has to exist. A listed transcript that is gone holds no chat, and an index that cannot be read makes LAST_CHAT ?.
…s, and the store no reader can see

A session's bucket follows its launch cwd, not the git root. omp lists every transcript it writes outside the buckets in the agent dir's custom-session-files. A store moved at launch by the process environment leaves no list entry a reader can find, so the worktree audit cannot see it, and the doc says what an operator does instead.
…P_AUDIT_LIVE_REQUIRED=1

Without omp the probe prints SKIPPED and the run passes, which is right on a developer machine and wrong in a job that installed omp to run it.
The gate job has no omp, so the live probe in test-worktree-audit.sh never ran in CI. The smoke job installs omp by sha256, and the new step runs the test there with OMP_AUDIT_LIVE_REQUIRED=1, so a missing omp fails the step.
…es note

The version-agnostic gate rejects a pinned omp version in owned prose. The note now tells the reader to list a real store after an upgrade, as the rest of the file does.
… bounded

Under a symlinked HOME omp lists every bucket transcript in custom-session-files, so each row grepped the whole store. A listed path whose directory's parent is a store's sessions directory is already covered by the bucket scan and is skipped. Each distinct parent is canonicalized once.
…a closed directory

[ -f ] cannot tell a deleted transcript from one the audit cannot reach, so a listed transcript under an unsearchable directory read as no chat and the row could be safe. The audit now walks up to the nearest existing directory and, when that directory cannot be searched, makes LAST_CHAT ? and holds every row at verify-recent-chat.
@AlexNegrescu26
AlexNegrescu26 merged commit 9890c87 into main Oct 25, 2026
2 checks passed
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.

1 participant