Skip to content

feat(log): per-line cwd + source-aware emit label#33

Merged
justi merged 4 commits intomainfrom
feat/log-cwd-and-source
Apr 27, 2026
Merged

feat(log): per-line cwd + source-aware emit label#33
justi merged 4 commits intomainfrom
feat/log-cwd-and-source

Conversation

@justi
Copy link
Copy Markdown
Owner

@justi justi commented Apr 27, 2026

Summary

Two small annoyances surfaced while dogfooding v0.2.0 across multiple projects:

1. Per-line [cwd] field in the log

~/.context-revive/hook.log is global. With revive wired in 5+ repos, the same post-compact: forcing emit line could be from any of them — un-debuggable. Now:

[2026-04-27T23:38:55] [~/Projects/context-revive] post-clear: forcing emit (counter=74)

$HOME-prefixed paths get tilde-shortened so the message body still has room.

2. Source-aware forcing-emit label

The forcing-emit log line said post-compact: even when triggered by /clear, because both paths shared one signal file and cadence_gate had no idea which command wrote it.

mark-compact and mark-clear now write compact / clear to the signal payload (was: a never-read unix timestamp). cadence_gate reads, sanitizes via tr -cd '[:lower:]', and emits the matching label. Unknown / malformed content falls back to a neutral post-context-loss: label rather than crashing.

The signal filename stays revive-compact.signal to keep the on-disk path stable across upgrades.

Bash gotcha worth noting

${VAR/old/\~} leaks the backslash — bash does NOT tilde-expand inside parameter-substitution replacements, so the literal ~ is correct (caught in smoke test before commit).

Test plan

  • 4 new tests: cwd field present, compact label, clear label, malformed payload → neutral label without crash
  • bats tests/ — 143/143 pass
  • shellcheck bin/revive install.sh clean
  • Live smoke on this repo: hook log now shows [~/Projects/context-revive] post-clear: forcing emit (counter=74) after mark-clear; refresh

🤖 Generated with Claude Code

Two annoyances surfaced when dogfooding v0.2.0 across multiple
projects:

1. Lines in the global `~/.context-revive/hook.log` did not carry
   any project context. With revive wired in 5+ repos, the same
   `post-compact: forcing emit` message could be from any of them
   — un-debuggable.
2. The forcing-emit log line said `post-compact:` even when the
   trigger was `/clear`, because both paths shared one signal file
   and `cadence_gate` had no idea which command wrote it.

Fixes:

- `log()` now prepends `[<cwd>]` after the timestamp, with a
  tilde substitution for paths under $HOME. A subtle bash gotcha:
  `${VAR/old/\~}` leaks the backslash; bash does NOT tilde-expand
  inside parameter-substitution replacements, so the literal `~`
  is correct (and was wrong on my first attempt — caught in
  smoke before commit).

- `cmd_mark_compact` and `cmd_mark_clear` write `compact` / `clear`
  to the signal file (was: a unix timestamp, never read). The
  signal filename stays `revive-compact.signal` to keep the
  on-disk path stable across upgrades.

- `cadence_gate` reads the payload, sanitizes via
  `tr -cd '[:lower:]'`, and emits either `post-compact:` or
  `post-clear:` accordingly. Unknown / malformed content falls
  back to a neutral `post-context-loss:` label.

4 new tests cover: cwd field present in log, compact label,
clear label, malformed payload → neutral label without crashing.
Copilot AI review requested due to automatic review settings April 27, 2026 14:40
The inline `[[ "$output" =~ \[[^]]+\]\ \[[^]]+\]\ post-compact ]]`
passed on macOS bats but failed on Ubuntu bats in CI — bash 3.2 vs
5.x differ on how literal `\[` inside the pattern is parsed. The
canonical workaround is to bind the pattern to a local variable
and reference it as `$re`. No content change to the assertion.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves revive hook logging ergonomics when used across multiple repositories by enriching each log line with a per-line working directory and by making the “forcing emit” label reflect whether the trigger was a compact or a /clear.

Changes:

  • Add a per-line [cwd] field to ~/.context-revive/hook.log output, with $HOME paths shortened to ~.
  • Encode the trigger source (compact vs clear) in the signal file payload and use it to emit a source-aware post-…: forcing emit log label (fallback to post-context-loss).
  • Add Bats coverage for the new log format and source-aware labels, including malformed payload handling.

Reviewed changes

Copilot reviewed 1 out of 2 changed files in this pull request and generated 1 comment.

File Description
bin/revive Enriches log() output with cwd, and makes cadence_gate() log label depend on sanitized signal payload (compact/clear/fallback).
tests/revive.bats Adds tests validating the new [cwd] log field and the compact/clear/neutral forcing-emit labels.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/revive.bats Outdated
}

@test "refresh log message reflects compact source" {
printf 'compact\n' > .claude/revive-compact.signal 2>/dev/null || mkdir -p .claude && printf 'compact\n' > .claude/revive-compact.signal
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

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

This test uses printf ... || mkdir -p .claude && printf ... which is hard to reason about due to &&/|| precedence, and it can still print a redirection error when .claude/ is missing (the failure happens before 2>/dev/null is applied). Prefer an explicit mkdir -p .claude first, then a single printf write.

Suggested change
printf 'compact\n' > .claude/revive-compact.signal 2>/dev/null || mkdir -p .claude && printf 'compact\n' > .claude/revive-compact.signal
mkdir -p .claude
printf 'compact\n' > .claude/revive-compact.signal

Copilot uses AI. Check for mistakes.
justi added 2 commits April 28, 2026 00:18
`${PWD/#$HOME/~}` did a string-prefix rewrite without a path
boundary check, so a checkout in `$HOME-something/...` (e.g.
HOME=/Users/alice and PWD=/Users/alice-work/project) would log
as `~-work/project` — wrong project name in a feature that
exists specifically to disambiguate projects.

Replace with a case statement that fires only on the exact
$HOME match or the `$HOME/` prefix; falls through to the
absolute path otherwise.

New test pins this: stages a sibling worktree at `$WORKDIR-other`
with HOME=$WORKDIR, runs mark-compact, and asserts the log line
does NOT contain the `~-other` splice artefact.
Replaced the convoluted `printf > .claude/... 2>/dev/null
|| mkdir -p .claude && printf > .claude/...` with the same
two-line pattern the sibling clear-source and garbage-payload
tests already use. Bash redirect failures land on the original
stderr before `2>/dev/null` is applied, so the old form would
have leaked an error noise even when functionally correct.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 2 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@justi justi merged commit 8b6bb09 into main Apr 27, 2026
7 checks passed
@justi justi deleted the feat/log-cwd-and-source branch April 27, 2026 15:40
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