Summary
rgctl currently requires manual rgctl discover to build or rebuild the code graph. Nothing automatically triggers re-extraction when source files change. This issue proposes two complementary approaches — git hooks (phase 1) and a file watcher (phase 2) — to keep the graph fresh automatically.
Existing infrastructure
~90% of the plumbing already exists:
| Component |
Location |
Status |
IncrementalUpdater |
crates/rgctl-incremental/src/updater.rs:72-148 |
Implemented — update() and update_files() |
FileTracker |
crates/rgctl-incremental/src/file_tracker.rs |
Implemented — blake3 hash-based change detection |
ChangeDetector |
crates/rgctl-incremental/src/changes/mod.rs:54-135 |
Implemented — blast-radius risk classification |
HooksConfig |
crates/rgctl-project-config/src/project.rs:38-76 |
Implemented — pre_commit, post_commit, post_checkout, block_on_risk, blast_radius_threshold |
WatchConfig |
crates/rgctl-project-config/src/project.rs:78-96 |
Implemented — debounce_ms (default 500ms) |
git_changed_files() |
crates/rgctl-incremental/src/file_tracker.rs:301 |
Implemented — git diff --name-only |
pipeline_watch_loop |
src/cli/http_serve.rs:310-320 |
Implemented — polls graph digest every 400ms, hot-reloads snapshot |
What is missing is the end-to-end wiring: CLI subcommands, hook scripts, and the OS-level file watcher.
Phase 1: Git Hooks
Approach
Shell scripts in .git/hooks/ invoke rgctl at git lifecycle points:
pre-commit — runs rgctl check --staged, blocks if risk exceeds threshold (exit 1)
post-commit — runs rgctl update --since HEAD~1 in background
post-checkout — runs rgctl update --since <prev-HEAD> on branch switch
post-merge — runs rgctl update after merge
Tasks
Why hooks first
- More infrastructure already exists (
HooksConfig, ChangeDetector, RiskLevel)
- Risk gating (blocking risky commits) is a unique capability only hooks provide
- No new crate dependencies needed
- CI parity — same
rgctl check works in hooks and pipelines
Phase 2: File Watcher
Approach
A background watcher using the notify crate detects file writes/renames/deletes, debounces events, filters to language-supported extensions, and invokes IncrementalUpdater::update_files().
Tasks
Comparison
| Dimension |
Git Hooks |
File Watcher |
| Latency |
Seconds (on git op) |
Sub-second |
| Trigger |
commit, checkout, merge |
Any file write |
| Resource cost |
Zero between operations |
Continuous (watcher thread) |
| Risk gating |
Yes (pre-commit) |
No |
| CI integration |
Direct (rgctl check) |
N/A |
| Setup |
rgctl install --hooks |
Automatic with serve --watch |
| Git dependency |
Yes |
No |
| New dependencies |
None |
notify crate |
| Unstaged files |
Invisible |
Visible |
Phase 3 (optional): Hybrid
rgctl serve --watch for real-time freshness + git hooks for risk gating
- Coordination lock to prevent watcher and hook from racing
- Dashboard indicator showing last-update source
References
Full analysis: .scratch/todo/FILE_WATCHER_VS_GIT_HOOKS.md
Summary
rgctl currently requires manual
rgctl discoverto build or rebuild the code graph. Nothing automatically triggers re-extraction when source files change. This issue proposes two complementary approaches — git hooks (phase 1) and a file watcher (phase 2) — to keep the graph fresh automatically.Existing infrastructure
~90% of the plumbing already exists:
IncrementalUpdatercrates/rgctl-incremental/src/updater.rs:72-148update()andupdate_files()FileTrackercrates/rgctl-incremental/src/file_tracker.rsChangeDetectorcrates/rgctl-incremental/src/changes/mod.rs:54-135HooksConfigcrates/rgctl-project-config/src/project.rs:38-76pre_commit,post_commit,post_checkout,block_on_risk,blast_radius_thresholdWatchConfigcrates/rgctl-project-config/src/project.rs:78-96debounce_ms(default 500ms)git_changed_files()crates/rgctl-incremental/src/file_tracker.rs:301git diff --name-onlypipeline_watch_loopsrc/cli/http_serve.rs:310-320What is missing is the end-to-end wiring: CLI subcommands, hook scripts, and the OS-level file watcher.
Phase 1: Git Hooks
Approach
Shell scripts in
.git/hooks/invokergctlat git lifecycle points:pre-commit— runsrgctl check --staged, blocks if risk exceeds threshold (exit 1)post-commit— runsrgctl update --since HEAD~1in backgroundpost-checkout— runsrgctl update --since <prev-HEAD>on branch switchpost-merge— runsrgctl updateafter mergeTasks
rgctl updateCLI subcommand wrappingIncrementalUpdater::update()/update_files()rgctl check --stagedflag to wireChangeDetectoragainstgit diff --cached --name-onlyrgctl install --hooksto generate and install hook scripts in.git/hooks/HooksConfigfromrgctl.tomlfor which hooks to install and risk thresholdsrgctl uninstall --hooksto remove installed hooksdocs/guides/git-hooks.mdWhy hooks first
HooksConfig,ChangeDetector,RiskLevel)rgctl checkworks in hooks and pipelinesPhase 2: File Watcher
Approach
A background watcher using the
notifycrate detects file writes/renames/deletes, debounces events, filters to language-supported extensions, and invokesIncrementalUpdater::update_files().Tasks
notifycrate dependency--watchflag torgctl serve(both HTTP and MCP modes)LanguageRegistryIncrementalUpdater::update_files()WatchConfig.debounce_msfromrgctl.toml.gitignore-aware path filtering to avoid indexing build artifactsdocs/guides/watch-mode.mdComparison
commit,checkout,mergepre-commit)rgctl check)rgctl install --hooksserve --watchnotifycratePhase 3 (optional): Hybrid
rgctl serve --watchfor real-time freshness + git hooks for risk gatingReferences
Full analysis:
.scratch/todo/FILE_WATCHER_VS_GIT_HOOKS.md