Skip to content

chore(hooks): chain .githooks to global co-author stripping hooks - #521

Merged
chuks-qua merged 1 commit into
mainfrom
chore/git-hook
May 27, 2026
Merged

chuks-qua merged 1 commit into
mainfrom
chore/git-hook

Conversation

@chuks-qua

@chuks-qua chuks-qua commented May 27, 2026 •

Copy link
Copy Markdown
Contributor

What

Adds prepare-commit-msg and post-commit hooks to .githooks/ that chain to the user-level hooks at ~/.git-hooks/.

Why

This repo sets core.hooksPath = .githooks, which bypasses the global ~/.git-templates hooks directory. Without chaining hooks in place, the user-level co-author stripping hooks never run in this repo, and AI co-author lines leak into commits.

Key changes

  • .githooks/prepare-commit-msg - chains to ~/.git-hooks/prepare-commit-msg if executable
  • .githooks/post-commit - chains to ~/.git-hooks/post-commit if executable
  • Both hooks are safe to re-install (idempotent via # --- chained-to-global-hooks --- marker)

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.

Summary by CodeRabbit

  • Chores
    • Enhanced Git hooks configuration to enable custom global commit workflow integration for development processes.

Review Change Stack

Installs prepare-commit-msg and post-commit hooks in .githooks/ that
chain to ~/.git-hooks/ so the user-level co-author stripping hooks run
in this repo despite the local core.hooksPath override.
@coderabbitai

coderabbitai Bot commented May 27, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 66011790-247f-4714-8b0e-891e22a7d691

📥 Commits

Reviewing files that changed from the base of the PR and between c05b279 and bccb2e2.

📒 Files selected for processing (2)
  • .githooks/post-commit
  • .githooks/prepare-commit-msg

📝 Walkthrough

Walkthrough

Two Git hook scripts are added to the .githooks/ directory. Both post-commit and prepare-commit-msg implement a delegation pattern: each checks for a corresponding executable global hook in the user's home directory and invokes it with original arguments if present.

Changes

Git hook delegation to global hooks

Layer / File(s) Summary
Git hook delegation
.githooks/post-commit, .githooks/prepare-commit-msg
Both hooks implement the same pattern: check for an executable global hook at ~/.git-hooks/post-commit and $HOME/.git-hooks/prepare-commit-msg respectively, and invoke it with the original CLI arguments if it exists.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Poem

A rabbit hops through git's great hall,
Two hooks to catch them one and all—
Post-commit and prepare-msg dance,
Delegating with elegant prance. 🐰

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding Git hook chaining to global hooks for co-author stripping, matching the actual file additions and purpose.
Description check ✅ Passed The description includes all required template sections (What, Why, Key Changes) with clear explanations; Config Changes section appropriately marked as None.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

@chuks-qua
chuks-qua merged commit c1ce29d into main May 27, 2026
7 checks passed
@chuks-qua
chuks-qua deleted the chore/git-hook branch May 27, 2026 09:03
chuks-qua added a commit that referenced this pull request May 28, 2026
PR #521 added chain-to-global logic in .githooks/prepare-commit-msg and
.githooks/post-commit so that AI attribution stripping always runs.
But the global hooks already chain BACK to repo-local via
chain_repo_hook(), creating an infinite cycle:

  global prepare-commit-msg
    -> chain_repo_hook()
      -> .githooks/prepare-commit-msg
        -> $HOME/.git-hooks/prepare-commit-msg
          -> chain_repo_hook() ... (repeat until SHLVL=1000)

Fix: remove the chain-to-global calls. The hooks are now no-ops that
document the chaining direction and provide a place for future
repo-specific logic.
chuks-qua added a commit that referenced this pull request May 28, 2026
…aps into ThreadRecord (#524)

* refactor(threadStore): extract ThreadHydrator + collapse per-thread maps into ThreadRecord

Closes #522 (phases 1-4; phase 5 prefetch.ts deletion already complete).

## What
- Introduce `ThreadHydrator` as a single deep module owning the full "load this
  thread" flow: cache lookup, RPC fetch, record commit, auxiliary fanout, and
  narrative prefetch. Split into `SnapshotBuilder` (pure, no IO) and
  `AuxiliaryHydrator` (TTL-gated permissions/tasks/plans/file-changes fanout).
- Collapse ~30 parallel `Record<string, X>` maps into a canonical
  `ThreadRecord` keyed by threadId in a `Map<string, ThreadRecord>`. Add
  `thread-record.ts` (immutable patch helpers) and `thread-selectors.ts`
  (typed read paths). Active-thread mirrors removed.
- LRU cache (`record-cache.ts`, 15-thread capacity) stores evicted
  `ThreadRecord` directly. `MessageCacheSnapshot` / `ThreadSnapshot` types and
  adapter functions deleted - cache stores canonical records, not adapters.
- Delete `apps/web/src/lib/prefetch.ts` (collapsed to a single debounced
  call inside `prefetch-scheduler.ts`) and `apps/web/src/stores/messageCache.ts`
  (replaced by `record-cache.ts`).
- Add `thread-store-test-utils.ts` with `applyLegacyThreadStoreSeed` shim so
  legacy per-thread-map seeding continues to work in tests during the
  migration.

## Why
- Per the epic in #522: thread load and switch involved ~30 parallel maps and
  scattered side-effects, making both correctness and performance reasoning
  hard. The collapse trades surface for depth: one record-shaped state, one
  hydrator, one cache.

## Key changes
- `threadStore.ts` shrinks from ~1490 lines of state-mutation code to ~650;
  most behavior delegates to `ThreadHydrator` and its sub-modules.
- Restoring from cache preserves the live record's `permissions` and
  `lastHydratedAt` fields (auxiliary-owned). The auxiliary fanout that runs
  after restore refreshes them; this prevents stale cache values from
  clobbering in-flight async updates.
- `SnapshotBuilder.build()` returns `answeredPlanMessageIds: Set<string>`
  (was string[]) to match the canonical `ThreadRecord` shape.

## Verification
- `bun run verify`: 157 test files, 1389 tests passing.
- One flaky test (`sidebar-usage-panel-tokens.test.tsx`) had a one-off hook
  timeout under full suite load but passes in isolation; unrelated to this
  refactor.

* refactor(threadStore): drop applyLegacyThreadStoreSeed shim

Replace the 23 test consumers of the legacy flat-seed shim with canonical
resetThreadStoreForTests + patchThreadRecord helpers, then delete the shim itself.

The shim was the test-side compatibility seam during the per-thread record
collapse. Now that production code is on ThreadRecord and tests are migrated,
the shim's flat *ByThread input shape has no callers and its inline
field-mapping tables are dead weight.

resetThreadStoreForTests now accepts runningThreadIds and
recentlyAnsweredPlanMessageIds so single-call resets stay one expression.

Net -162 lines.

* fix(hooks): break infinite recursion between repo-local and global hooks

PR #521 added chain-to-global logic in .githooks/prepare-commit-msg and
.githooks/post-commit so that AI attribution stripping always runs.
But the global hooks already chain BACK to repo-local via
chain_repo_hook(), creating an infinite cycle:

  global prepare-commit-msg
    -> chain_repo_hook()
      -> .githooks/prepare-commit-msg
        -> $HOME/.git-hooks/prepare-commit-msg
          -> chain_repo_hook() ... (repeat until SHLVL=1000)

Fix: remove the chain-to-global calls. The hooks are now no-ops that
document the chaining direction and provide a place for future
repo-specific logic.

* chore(hooks): delete no-op repo-local commit hooks

The repo-local prepare-commit-msg and post-commit hooks were left as
empty placeholders after 011db21 broke the recursion loop with the
global hooks. Git treats missing hook files as no-op, so the
placeholders carried no behavior — just documentation.

post-checkout stays: it has real .env bootstrap logic.

* fix(threadHydrator): address review feedback — guards, test assertions, stale comment

- Add thread-existence guard in auxiliary-hydrator permissions writeback
  and thread-hydrator narrative prefetch to prevent resurrecting deleted
  threads via patchThreadRecord
- Add firstStart definedness assertion in running-session-signal idempotency
  test so it fails if turnStarted never recorded a start time
- Fix workspace-behavior test: check workspace loading state instead of
  thread loading after loadWorkspaces() failure
- Update stale "message-cache" comment to "record-cache" in App.tsx
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