Skip to content

store project-relative paths for cross-environment portability - #59

Open
lshgdut wants to merge 1 commit into
cytostack:mainfrom
lshgdut:main
Open

store project-relative paths for cross-environment portability#59
lshgdut wants to merge 1 commit into
cytostack:mainfrom
lshgdut:main

Conversation

@lshgdut

@lshgdut lshgdut commented Jul 15, 2026

Copy link
Copy Markdown

Summary

sessions[].reads[].file and sessions[].writes[].file in token-ledger.json previously recorded absolute paths (e.g. /Users/hua/Desktop/01github/openwolf/src/hooks/stop.ts). This made the ledger non-portable across environments — when a user switches machines, clones the project to a different location, or runs inside a container/devcontainer, historical session paths immediately become invalid.

This change converts absolute paths to project-relative paths when writing the ledger, so the data remains reproducible in any environment.

What Changed

  • src/hooks/stop.ts:3 — imports the existing getProjectDir() helper (which handles the CLAUDE_PROJECT_DIR / CODEX_PROJECT_ROOT / OPENWOLF_PROJECT_ROOT / process.cwd() priority chain)
  • src/hooks/stop.ts:100-122 — converts the file field via path.relative() when building sessionEntry; introduces a small toRelative() helper

Design Decisions

  1. Reused getProjectDir() — no reimplementation of project-root resolution; the existing env-var priority chain is preserved (other hooks already depend on it).
  2. Conversion happens only at the ledger boundary — the in-memory session.files_read / session.files_written keep absolute paths unchanged, because downstream checks in the same function (checkForMissingBugLogs, checkStatusFreshness, checkSemanticSummaries, etc.) rely on absolute paths for fs.statSync and includes() matching. Minimal blast radius.
  3. Files outside the project fall back to absolute paths — detected by inspecting the result of path.relative(): if the result starts with .. or is still absolute (cross-drive / different root on Windows), the file lives outside the project and we keep the absolute path rather than losing the information. Rare, but robust.
  4. Zero behavior change for running codesessionEntry is still the last step before disk; downstream consumers (dashboard tables, token stats) only care about file existence and token counts, not full paths.

Compatibility & Migration

  • Forward compatible — historical ledger entries with absolute paths remain readable; consumers that want to normalize on read can add a path.isAbsolute() heuristic (out of scope for this change).
  • Backward compatible — new ledger entries are valid on any machine, container, or clone location, because relative paths are decoupled from the concrete filesystem location.

Testing

Manually verified scenarios:

  • Files inside the project → stored as src/hooks/stop.ts
  • Files outside the project (e.g. ~/.zshrc) → fall back to absolute path
  • Cross-drive / Windows-style paths → fall back to absolute path
  • path.relative() behavior matches the documented contract (a non-empty .. prefix indicates outside-the-project)

Checklist

  • Change is scoped to the last step before ledger persistence
  • No mutation of intermediate state (session.files_read / session.files_written)
  • No new runtime dependencies
  • TypeScript compiles cleanly (getProjectDir is already exported, no lint warnings)
  • Commit message follows the existing Conventional Commits style

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