feat(init): auto-update .gitignore + tighter tagline#31
Conversation
"Your side project died at 80%. Bring it back in one prompt." was cryptic — readers had to guess what 80% referred to (project abandonment? completion?), and nothing in the line connected to the actual problem the tool solves (agent context rot in long sessions). Replace with the literal failure mode users hit in practice: "Your agent forgot the ADR you wrote 30 prompts ago." Names the pain directly, no metaphor decoding required. The next paragraph already explains the mechanism, so the tagline can stay terse.
A common onboarding stumble: user follows the README, runs
`revive init`, then `git add .revive/static.md` — git silently
skips the file because their .gitignore has `.revive/*` (or
similar) and no exception. The "checked in" workflow the README
documents quietly fails.
`cmd_init` now calls `maybe_update_gitignore` after writing
static.md. Logic:
- Skip silently if not in a git repo, no .gitignore exists, or
`git check-ignore` says the file is already trackable.
- Otherwise append a small canonical block:
.revive/*
!.revive/static.md
with a header comment explaining what gets tracked vs not.
- Re-run `git check-ignore`. If a directory-level `.revive/`
rule still suppresses the un-ignore (git semantics: `!`
cannot rescue a file inside a fully-ignored directory), print
a warning telling the user how to fix it.
4 new tests cover: no .gitignore (no-op), `.revive/*` (append +
verify trackable), already-correct (idempotent — line count
unchanged), `.revive/` directory rule (warning emitted, exit 0
preserved).
There was a problem hiding this comment.
Pull request overview
This PR improves onboarding and messaging by updating the project tagline and making revive init proactively fix a common .gitignore misconfiguration that prevents .revive/static.md from being tracked as intended.
Changes:
- Update README tagline to a clearer, failure-mode-based statement.
- Add
maybe_update_gitignoretorevive initto append a canonical.revive/*+!.revive/static.mdblock whenstatic.mdis currently ignored (and warn when directory-level ignore rules prevent the fix from taking effect). - Add Bats tests covering the
.gitignoreupdate behavior (no-op, append, idempotent when already correct, warn-on-directory-rule).
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
bin/revive |
Calls a new helper from cmd_init to update .gitignore so .revive/static.md becomes trackable; warns when un-ignore can’t work due to directory-level rules. |
tests/revive.bats |
Adds tests for revive init’s .gitignore auto-update and warning behavior. |
README.md |
Replaces the tagline with a clearer, more literal description of the problem the tool solves. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Two issues codex flagged on the original gitignore-auto patch: [P2] Broad dot-dir rules left static.md untrackable - A repo with `.revive/`, `.revive`, or even `.*` / `.*/` already ignores the parent directory. Git semantics: `!` cannot rescue a file inside a fully-ignored directory. - The canonical block now leads with `!.revive/` to un-ignore the parent first, then re-ignores contents with `.revive/*`, then re-includes static.md with `!.revive/static.md`. - The "warns when a directory-level .revive/ rule blocks" test flipped to "un-ignores even with a directory-level rule" — the former failure mode no longer happens. Added a parallel test for `.*` to cover the broad-rule case. [P3] Read-only .gitignore aborted `revive init` - Under `set -e`, `cat >> .gitignore` on a read-only file killed cmd_init even though the gitignore update is best-effort. - Pre-check writability with `[[ -w .gitignore ]]`. If not writable, print the exact lines the user needs to add and return 0 — static.md is already created at this point. - New test exercises the read-only path: chmod -w .gitignore, trap restores write perm so teardown doesn't break.
There was a problem hiding this comment.
Pull request overview
This PR improves the revive init onboarding flow by making .revive/static.md reliably trackable in git (via a best-effort .gitignore auto-update) and updates the README tagline to a more literal/clear failure mode description.
Changes:
- Add
maybe_update_gitignoreto append a canonical.reviveignore/un-ignore block whenstatic.mdis currently gitignored. - Add Bats coverage for
.gitignoreupdate behavior across common ignore patterns and failure modes. - Update the README tagline.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
bin/revive |
Calls new maybe_update_gitignore from cmd_init and appends a canonical .gitignore block to un-ignore .revive/static.md when needed. |
tests/revive.bats |
Adds tests validating .gitignore no-op/idempotency/update behavior and read-only warning behavior. |
README.md |
Replaces the top-level tagline. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
* docs(readme): document the post-compact refresh trigger Cadence section now lists four triggers (was three): first prompt, every-N counter, time-gap, and the new post-compact override. Quick start mentions install-hook now wires both UserPromptSubmit and PostCompact. * feat: refresh trigger after `/clear` Sibling to the post-compact trigger from #30. `/clear` wipes more than `/compact` (full conversation reset), but the recovery path is identical — re-inject the brief on the next prompt, bypassing cadence. Wired through Claude Code's `SessionStart` hook with `matcher: "clear"`, the documented dedicated signal. Implementation: - New `cmd_mark_clear` writes the same `.claude/revive-compact.signal` as `cmd_mark_compact`. Two commands so settings.json reads naturally and hook.log distinguishes the source. - `cmd_install_hook` now wires three hooks. Refactored the upsert helper to take an optional `matcher`, so SessionStart{clear} stays distinct from any user-added SessionStart{startup} or {resume} entry (idempotency key: event + matcher + command). - `cmd_doctor` adds a third hook check via the existing `_doctor_check_hook` helper (`SessionStart` + `revive mark-clear`). - README cadence section gains trigger #5; install-hook line now lists all three events. 6 new tests cover: signal write, help-text surface, settings.json shape (matcher field present), 3-hook idempotency, doctor warn on missing SessionStart, doctor green path with all three hooks. * release: v0.2.0 Headline: context-loss recovery. Refresh now fires immediately after `/compact` (#30) and `/clear` — the two moments when an agent has just lost most of its working memory and the brief gives the highest ROI. Three hook events wired by `install-hook`: UserPromptSubmit, PostCompact, SessionStart(matcher=clear). Also since v0.1.19: - `revive init` auto-fixes `.gitignore` so static.md is trackable (#31) - README tagline rewrite (#31) * fix(doctor): validate SessionStart matcher (codex P3) `_doctor_check_hook` accepted any SessionStart entry pointing at `revive mark-clear` regardless of its `matcher` value. A user who hand-wired SessionStart{startup} → mark-clear (or no matcher at all) would pass doctor, but `/clear` would never trigger that hook. Codex flagged the false-positive on the v0.2.0 PR. Two changes: 1. The helper takes an optional 3rd arg `matcher`. When set, the jq query also asserts `(.matcher // "") == $m` so only the intended entry counts. Doctor labels include the matcher in parens — `SessionStart(clear) hook installed`. 2. The grep fallback used to override a legitimate "no match" from jq because it ran on any non-zero jq exit. Distinguish jq's exit codes: - 0 → match; - 1 → legitimate no-match (trust it, skip grep); - ≥2 → jq error or absent → grep fallback (best-effort, can't tie matcher to command across JSON lines). Without that, the matcher check would have been silently defeated whenever jq returned 1 and grep happened to find the command string anywhere in the file. Also: `set -e` interaction. The naive `jq ...; rc=$?` pattern would abort the function on jq's non-zero exit before the assignment. Wrapping in `if jq ...; then rc=0; else rc=$?; fi` preserves the code. Tests: - "doctor warns when SessionStart entry has wrong matcher" — new regression test for codex P3, hand-crafts settings.json with matcher=startup pointing at mark-clear, asserts the warning. - Existing missing-SessionStart and all-three-hooks tests updated to expect the `(clear)` label.
Summary
Two small but unrelated wins, bundled because they're both single-commit and low-risk:
1. Tagline rewrite
The cryptic
Your side project died at 80%. Bring it back in one prompt.got swapped forYour agent forgot the ADR you wrote 30 prompts ago.— the literal failure mode users hit. No metaphor decoding required.2.
revive initauto-updates.gitignoreA common onboarding stumble: user runs
revive init, thengit add .revive/static.md— git silently skips it because the user's.gitignorehas.revive/*(or similar) and no exception. The "checked in" workflow that README documents quietly fails.cmd_initnow calls a newmaybe_update_gitignorehelper:.gitignoreexists, orstatic.mdis already trackable..revive/*+!.revive/static.md) with an explanatory header comment..revive/rule blocks the un-ignore — git semantics don't let!rescue a file inside a fully-ignored directory; user needs to manually fix.Test plan
.gitignore(no-op),.revive/*(append + verify trackable), already-correct (idempotent),.revive/directory rule (warning emitted, exit 0 preserved)git check-ignoreconfirmsstatic.mdis now trackedbats tests/— 130/130 passshellcheck bin/revive install.shclean🤖 Generated with Claude Code