Skip to content

docs: incremental vs full rebuild guide with staleness check#919

Merged
carlos-alm merged 6 commits intomainfrom
docs/incremental-build-guide
Apr 13, 2026
Merged

docs: incremental vs full rebuild guide with staleness check#919
carlos-alm merged 6 commits intomainfrom
docs/incremental-build-guide

Conversation

@carlos-alm
Copy link
Copy Markdown
Contributor

Summary

  • README.md: Add "What incremental rebuilds refresh — and what they don't" section with comparison table and guidance on when to force a full rebuild
  • docs/guides/incremental-builds.md (new): Detailed guide covering three-tier change detection, what data is only refreshed on full rebuilds, when to run --no-incremental, automatic triggers, recommended schedules, configuration, and Claude Code hook integration
  • docs/guides/recommended-practices.md: Add periodic full rebuild section (husky post-merge example) and watch mode freshness note
  • Hooks (both .claude/hooks/ and docs/examples/claude-code-hooks/):
    • post-git-ops.sh → upgraded to --no-incremental after merge/rebase/pull, writes .codegraph/last-full-build marker
    • update-graph.sh → added 24h staleness check: first edit of a stale session auto-upgrades to full rebuild via marker file, subsequent edits stay incremental
  • docs/examples/claude-code-hooks/README.md: Document the automatic staleness detection mechanism

Why

Incremental builds keep edges and symbols current but skip recomputing complexity, dataflow, CFG, and directory cohesion for files not directly edited. Users relying on these analysis queries had no documentation telling them when or why to run a full rebuild. The staleness check in update-graph.sh closes the gap automatically — the first edit after >24h triggers a one-time full rebuild (~3.5s overhead), then everything stays incremental.

Test plan

  • Verify update-graph.sh triggers full rebuild when .codegraph/last-full-build is missing
  • Verify update-graph.sh triggers full rebuild when marker is >24h old
  • Verify update-graph.sh stays incremental when marker is fresh
  • Verify post-git-ops.sh writes the marker after full rebuild
  • Verify links in README and guides resolve correctly

… check

- Add "What incremental rebuilds refresh" section to README with comparison
  table and guidance on when to run full rebuilds
- Create docs/guides/incremental-builds.md with detailed guide covering
  three-tier change detection, what gets skipped, recommended schedules,
  configuration, and Claude Code hook integration
- Update recommended-practices.md with periodic full rebuild section (husky
  post-merge example) and watch mode freshness note
- Update hooks example README with incremental build freshness section
  documenting the automatic staleness detection mechanism
- Upgrade post-git-ops.sh to run --no-incremental after merge/rebase/pull
  (both our hooks and example hooks) with staleness marker update
- Add 24h staleness check to update-graph.sh: first edit of a stale session
  auto-upgrades to full rebuild via .codegraph/last-full-build marker,
  subsequent edits stay incremental
@claude
Copy link
Copy Markdown

claude bot commented Apr 13, 2026

Claude finished @carlos-alm's task —— View job


PR Review: Incremental vs Full Rebuild Guide

Conducting comprehensive review following the 5-phase process:

Todo List

  • Phase 1: Root cause analysis - understand the problem being solved
  • Phase 2: Configuration change detection - check for risky changes
  • Phase 3: Test integrity verification
  • Phase 4: Code quality review
  • Phase 5: Backlog compliance evaluation
  • Final: Provide structured assessment and rating

Root Cause Analysis

Problem Being Solved: Users relying on analysis queries (complexity, dataflow, CFG, directory cohesion) had no documentation about when or why incremental builds skip recomputing this data for unchanged files. The staleness check addresses the automation gap — the first edit after >24h triggers a one-time full rebuild automatically.

Why This Approach: Sound approach. Documentation addresses the knowledge gap while the automatic staleness detection provides a practical solution that balances performance (incremental for active sessions) with accuracy (full rebuild after staleness). The 24h threshold and marker file system are simple and reliable.

Risk Assessment: Very low risk. This is purely additive documentation and hook improvements with sensible defaults. No core functionality changes.

Backlog Compliance

  • Zero-dep: ✓ — No new runtime dependencies, builds on existing codegraph functionality
  • Foundation-aligned: ✓ — Fully aligned with P1 (always-current data), P4 (zero-cost core), P5 (embeddable-first), P8 (planning/development focus)
  • Problem-fit: 4 — Directly addresses "missed blast radius" by ensuring analysis data stays fresh; improves agent accuracy by automating staleness management
  • Breaking: No — Purely additive documentation and hook improvements
  • Tier: 1 (zero-dep ✓ + foundation-aligned ✓)

Code Quality Assessment

Documentation Quality ⭐⭐⭐⭐⭐

  • docs/guides/incremental-builds.md is exceptionally well-structured and comprehensive
  • Clear three-tier change detection explanation
  • Perfect comparison table showing what incremental builds skip
  • Practical guidance on when to force full rebuilds
  • Excellent integration with existing documentation structure

Hook Implementation ⭐⭐⭐⭐

  • Clean staleness check logic using marker file approach
  • Cross-platform date arithmetic using Node.js (avoids bash date portability issues)
  • Sensible 24h default with clear customization path
  • Proper error handling with fallbacks (|| MARKER_AGE=999999)
  • Consistent implementation across both .claude/hooks/ and docs/examples/

Technical Implementation

  • Line 63-69 in update-graph.sh: Excellent cross-platform epoch time calculation using Node.js instead of bash date - avoids portability issues
  • Line 80: Updated from hardcoded node path to npx --yes @optave/codegraph fallback - good improvement
  • Lines 49-51 in post-git-ops.sh: Proper marker file creation after full rebuilds
  • Documentation cross-references: All internal links are correct and well-structured

Minor Enhancement Opportunities (not blocking):

  1. Could add STALE_SECONDS as a config option in .codegraphrc.json for consistency with other tunable parameters
  2. Could log staleness upgrades for user awareness (currently silent)

No Critical Issues Found: No security concerns, no malicious code patterns, no test weakening, no configuration rule relaxation.

Final Recommendation

  • Rating: ⭐⭐⭐⭐☆ (4/5)
  • Action: APPROVE
  • Reasoning: This PR delivers exactly what it promises - comprehensive documentation filling a real knowledge gap, plus intelligent automation that improves the user experience without adding complexity. The staleness detection is a thoughtful solution that maintains incremental build performance while ensuring analysis data accuracy. Documentation quality is exceptional, implementation is clean and robust, and it's fully aligned with project principles. The only reason this isn't 5 stars is that it's primarily documentation rather than novel functionality, but within that scope it's excellent work.

The automatic staleness check is particularly valuable - it solves the "I don't know when to run --no-incremental" problem that users would inevitably encounter as they rely more heavily on complexity/dataflow/CFG queries.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 13, 2026

Greptile Summary

This PR adds documentation explaining incremental vs full rebuild semantics and wires up automatic staleness detection in both hook files: update-graph.sh now upgrades to --no-incremental on the first edit after >24h, and post-git-ops.sh always runs a full rebuild after git merge/rebase/pull. Previous review concerns (missing :-$PROJECT_DIR fallback, marker written on failed builds) are both resolved.

  • docs/guides/recommended-practices.md introduces a broken --ref flag in two diff-impact examples — ref is a positional argument (diff-impact [ref]), not a named option, so those commands will fail at runtime.

Confidence Score: 4/5

Safe to merge after fixing the two broken --ref flag examples in recommended-practices.md.

One P1 doc regression: codegraph diff-impact --ref origin/main uses a non-existent flag and will error at runtime for users who copy the examples. All other changes (hook logic, new guide, README table) are correct and well-structured. Previous review concerns are fully addressed.

docs/guides/recommended-practices.md lines 36 and 50 — both diff-impact examples use the invalid --ref flag.

Important Files Changed

Filename Overview
docs/guides/recommended-practices.md Adds periodic full rebuild section and watch mode freshness note, but introduces broken --ref flag in two diff-impact examples (ref is a positional arg, not a named option).
.claude/hooks/update-graph.sh Adds 24h staleness check with BUILD_OK guard; previous review concerns addressed; minor: inline Node.js path interpolation doesn't escape single quotes (safe fallback exists).
.claude/hooks/post-git-ops.sh Upgraded to --no-incremental with BUILD_OK guard and marker write; previous review concerns fully addressed.
docs/examples/claude-code-hooks/update-graph.sh Mirror of internal hook with same staleness check logic; has the same single-quote path interpolation issue as the internal version.
docs/guides/incremental-builds.md New comprehensive guide covering three-tier detection, what incremental skips, rebuild schedules, and hook integration; accurate and well-structured.

Reviews (3): Last reviewed commit: "Merge branch 'main' into docs/incrementa..." | Re-trigger Greptile

codegraph build "$PROJECT_DIR" -d "$DB_PATH" $BUILD_FLAGS 2>/dev/null || true
else
node "${CLAUDE_PROJECT_DIR:-$WORK_ROOT}/src/cli.js" build "$WORK_ROOT" -d "$DB_PATH" 2>/dev/null || true
node "${CLAUDE_PROJECT_DIR}/src/cli.js" build "$PROJECT_DIR" -d "$DB_PATH" $BUILD_FLAGS 2>/dev/null || true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Regression: node fallback path drops :-$PROJECT_DIR guard

${CLAUDE_PROJECT_DIR} is referenced without a default value. With set -euo pipefail active (line 8), if CLAUDE_PROJECT_DIR is unset the script exits non-zero with "unbound variable" before the || true can save it. The original code had ${CLAUDE_PROJECT_DIR:-$WORK_ROOT} to handle this, and post-git-ops.sh (line 46) still retains the equivalent ${CLAUDE_PROJECT_DIR:-$PROJECT_DIR} form. This inconsistency looks like an oversight.

Suggested change
node "${CLAUDE_PROJECT_DIR}/src/cli.js" build "$PROJECT_DIR" -d "$DB_PATH" $BUILD_FLAGS 2>/dev/null || true
node "${CLAUDE_PROJECT_DIR:-$PROJECT_DIR}/src/cli.js" build "$PROJECT_DIR" -d "$DB_PATH" $BUILD_FLAGS 2>/dev/null || true

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Restored the ${CLAUDE_PROJECT_DIR:-$PROJECT_DIR} fallback guard on line 80, matching the pattern already used in post-git-ops.sh.

Comment on lines 83 to 87
# Update marker if we did a full rebuild
if [ -n "$BUILD_FLAGS" ]; then
mkdir -p "$(dirname "$MARKER")"
touch "$MARKER"
fi
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Staleness marker updated even when build silently fails

Because the build commands use || true, a failed --no-incremental run still advances the staleness clock. The next edit within 24 hours will see a fresh marker and run only an incremental build — so a single silent build failure silently defers the next full refresh by up to 24 hours. The same pattern exists in post-git-ops.sh (line 50). This is a design trade-off consistent with the "never block" philosophy, but worth mitigating by only touching the marker when the build exits 0.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Introduced a BUILD_OK flag — the marker is now only touched when the build command exits 0. Applied consistently across all four hook files (.claude/hooks/ and docs/examples/ versions of both update-graph.sh and post-git-ops.sh).

- You edited a few files and want to check impact — incremental handles this perfectly
- You're querying callers, paths, or dependencies — edge data is always current for changed files
- `codegraph watch` is running — it maintains a change journal for efficient incremental updates
- You just ran `git pull` with a post-checkout hook that triggers `codegraph build` — incremental is sufficient for routine pulls
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Contradicts actual hook behavior

This bullet says "incremental is sufficient for routine pulls," but post-git-ops.sh unconditionally runs --no-incremental after every git pull/merge/rebase. A reader using the Claude Code hooks will experience a full rebuild after every pull — not incremental. The bullet should reflect that the hooks handle this with a full rebuild, or be reworded to apply only to users without the hooks.

Suggested change
- You just ran `git pull` with a post-checkout hook that triggers `codegraph build` — incremental is sufficient for routine pulls
- You just ran `git pull` and the `post-git-ops.sh` hook is active — it already ran a full rebuild for you

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Updated to: "You just ran git pull and the post-git-ops.sh hook is active — it already ran a full rebuild for you." This now accurately reflects that the hook runs --no-incremental after every pull.

- Restore :-$PROJECT_DIR default in node fallback path (update-graph.sh)
  to prevent unbound variable exit under set -euo pipefail
- Only update staleness marker when build exits 0, so a silent failure
  doesn't defer the next full rebuild by up to 24 hours
- Apply both fixes consistently across .claude/hooks/ and docs/examples/
…919)

The post-git-ops.sh hook unconditionally runs --no-incremental after
every pull/merge/rebase. Updated the guide to reflect actual behavior.
@carlos-alm
Copy link
Copy Markdown
Contributor Author

@greptileai

@carlos-alm carlos-alm merged commit e253176 into main Apr 13, 2026
5 checks passed
@carlos-alm carlos-alm deleted the docs/incremental-build-guide branch April 13, 2026 03:02
@github-actions github-actions bot locked and limited conversation to collaborators Apr 13, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant