Repository navigation
feat(status): answer pending changes from git's candidates when git sees every change (#1878) - #289
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e2a1fa48e1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let capture = Self { | ||
| repo, | ||
| status, | ||
| submodules: flags.submodules, |
There was a problem hiding this comment.
Preserve hidden-index state in the capture
When a source is marked assume-unchanged or skip-worktree during a full build, begin detects flags.hidden_changes but this initializer discards it. If the build indexes hidden working-tree content, then the user clears the flag and restores the file to the clean HEAD version, the later flag check passes, both Git candidate queries are empty, and the file was never added to dirty; status consequently reports no pending change even though the full inventory reports the file as modified. Persist this state to force a fallback, or add the hidden paths to the recorded dirty set.
Useful? React with 👍 / 👎.
| } | ||
| stored_paths.insert(file.path); | ||
| } | ||
| let fresh = scan_project(root, options)? |
There was a problem hiding this comment.
Fall back when the post-build verification scan fails
If the source tree changes during this second scan—for example, a build process removes a directory after the initial indexing scan—scan_project can return an I/O error here, which propagates out of record. Because every full index and full sync calls this after writing all graph rows, optional fast-path bookkeeping can now fail an otherwise completed indexing operation and prevent finalization. Treat a failed verification scan like the already-tolerated Git failures: omit/delete the metadata record and let later status calls use the full inventory.
Useful? React with 👍 / 👎.
Codecov Report❌ Patch coverage is @@ Coverage Diff @@
## main #289 +/- ##
========================================
Coverage 95.28% 95.29%
========================================
Files 160 161 +1
Lines 98419 99084 +665
========================================
+ Hits 93781 94423 +642
- Misses 4638 4661 +23
... and 1 file with indirect coverage changes 🚀 New features to boost your workflow:
|
…he unreleased landings
Summary
This ports upstream #1878's git-stamped fast path for pending status (#1829), as the owner decided on 2026-10-01. The design passed the kirocodex plan-convergence review in round 4 (blocking items 6 → 1 → 2 → 0).
The full inventory stays the reference answer and the fallback. The fast path only ever returns what the inventory would.
Record (
crates/codegraph-watch/src/git_pending.rs)project_metadatavalue,git_pending_state:{v, commit, dirty, scope, links, submodules}. No DDL.dirtyis the status set before and after the build, every row whose stat moved while the build ran, and every path where a fresh scan and the database disagree. The last two cover a file read in a transient state and restored, and a file the scan missed while it was briefly gone or excluded.scopefingerprints everything that decides scan membership: the config scan fields, extension overrides, root.gitignore, reserved index roots, extraction version, and binary version. A scope that changes during the build writes no record.dirtybefore it writes, or forgets the record if the scope moved.Reader
git diff <commit> HEAD, plusgit status -uall, plusdirty. They are classified by the scan's own membership (scan_membership) and the inventory's stat-then-hash rules. Git supplies candidates, never the verdict.core.autocrlf, any gitattributes source (resolved throughgit var GIT_ATTR_SYSTEM/GIT_ATTR_GLOBAL, plusinfo/attributesand.gitattributes),core.ignorecase,core.precomposeunicode. Windows CI caught the first: a revert rewrote LF as CRLF whilegit statusstayed clean. So on macOS and Windows defaults the full inventory answers;assume-unchanged/skip-worktreeentry is present (this last check was added beyond the plan);--no-optional-locks, so it never rewrites.git/index.GIT_DIRand its siblings are stripped. Paths are pinned to repo-root coordinates (--no-relative,--full-name) and rebased by--show-prefix.Scan membership (
crates/codegraph-extract/src/engine.rs)The walk's per-entry decision moves into
ScanRules(prunes_by_name,decide), which both the walk and the newscan_membershipuse. Single-path membership therefore cannot drift from the walk. Every symlink component returnsUnknown, which declines.Measured (code at
742bcb4, release build, warm cache, 5 runs after a warm-up,codegraph status . --json, generated 40,000-file TypeScript repo, ext4, 32-CPU Linux)Both columns reported identical pending changes in every run. The final head differs from the measured
742bcb4only by filesystem existence checks for.gitattributesabove a subdirectory project; no git process is added.Verification
crates/codegraph-watch/tests/git_pending_fast_path.rs(25 tests, real git, run withGIT_ATTR_NOSYSTEMand an emptyXDG_CONFIG_HOME), plus a unit test for a system attributes file through a stand-in git: every case compares withpending_full_inventoryand asserts which source answered..cache(scanned but not watched), and a project in a work-tree subdirectory.assume-unchanged, and a submodule withignore = all;.gitignore, and symlinks;core.autocrlfwith a revert,.gitattributes, andcore.ignorecase;CODEGRAPH_DIRindex root, and a submodule below a subdirectory project.forgetand no incremental extension: both interruption tests fail.crates/codegraph-extract/tests/scan_membership.rs: for every file of a tree mixing.gitignorenegation,ignore_dirs, the JVMbuildexception, reserved and nested.codegraph,.git, include and exclude,scan_membershipagrees withscan_project. It also checks directories, missing paths and symlinks.make pre-ci): see the PR checks; CI runs the full matrix, including macOS.BEGIN_COMMIT_OVERRIDE
feat(status): answer pending changes from git's candidates when git sees every change (#1878)
END_COMMIT_OVERRIDE
🤖 Generated with Claude Code