Repository navigation
feat(devmap-store): latest_symbols_for_file (recover code vendored from an unpushed commit) - #14
Merged
Merged
Conversation
…its generation GitPulse's code-intel panel (cmd_codeintel_symbols_for_file) reads the symbols a single file declares and compares the generation's head_sha with the commit it is showing. That reader was written against an unpushed local commit (c55d479) and vendored into GitPulse from it, so the vendored devmap-store carried FileSymbolsPage and Store::latest_symbols_for_file while DevCouncil did not, and GitPulse could not re-vendor without losing the feature. This lands the same code upstream. The rows and the head_sha are read from one pinned snapshot, like SearchPage: a second "latest" read could describe another generation. `None` means no generation; `Some` with no rows means the path has no indexed symbols. Corrupt spans go through checked_span, as every other symbol reader does. Tests in tests/symbols_for_file.rs cover the empty store, file scoping and source order, an unindexed path, the latest generation winning, and a corrupt span being refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS
The v1.3.5 release bumped the workspace version, but rust/gusset-engine/Cargo.lock (outside the workspace) still named dc-glob 0.2.3, so every job that builds the umbrella staticlib with `cargo build --locked` failed before any test ran. Regenerated with `cargo update -p dc-glob --offline` against the pinned gusset 7a56c3c; gusset stays 0.0.1. The same change is on claude/zealous-faraday-56lcrv. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS
cc 1.2.67 does not compile against find-msvc-tools 0.1.13, which re-exports FILE_ATTRIBUTE_TEMPORARY as i32 where std wants u32; 0.1.14 restores u32. Every Windows leg that builds the workspace failed on it, main included. Same lockfile change as b6e9673 on claude/zealous-faraday-56lcrv, via `cargo update -p find-msvc-tools --precise 0.1.14`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS
devmap-resolve's LSP client spawned its server with a raw Command::new, which devmap-extract's every_child_process_in_the_kernel_goes_through_the_runner guard rejects: a child outside the subprocess runner has no deadline and no output cap. That test failed on main and on every Rust leg of this PR. This is the lsp.rs and dc-proc part of e3bcb6b from claude/zealous-faraday-56lcrv, unchanged. Its rust.yml hunk (a static-musl step that builds on earlier workflow commits there) is left out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS
The clients jobs run `gofmt -l .` and failed on this file, on main as well. Byte-identical to the file on claude/zealous-faraday-56lcrv (from f0ec3e2). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS
devmap-cli's every_integration_test_is_classified_against_the_parse_feature requires each integration test to be either feature-off safe or gated on `parse`. symbols_for_file builds its generations with extract_file and the resolver, so it is gated like retention_churn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS
The umbrella and gussetfn were a startup health check with gaps at the boundary. This closes the ones found by auditing it end to end: - Stale links: Go's build and test caches key a cgo package on its flag text, not on the archive bytes, so after a Rust rebuild `go build` linked the old archive and `go test` could replay a cached "ok" (demonstrated with a marker string: invisible without -a). rust/gusset-engine/cgo-env.sh always runs the incremental cargo build and folds the archive's sha256 into CGO_CFLAGS. verify.sh (which built only when the archive was missing), ci-local.mjs and the setup-gusset action now use it. - Poison: the shared handle lived in a sync.Once, so one poisoned handle failed every later Match for the life of the process. A poisoned handle is now retired and the next call opens a new one; a failed Open is retried instead of latched. Close() shuts the engine for servers. - Allocator blindness: no archive declared a global allocator, so gusset.Stats() read zero and AdviseMemoryLimit subtracted nothing. The umbrella installs gusset's Counting allocator; a test pins that a Rust buffer is counted once. - MatchAny made one crossing per pattern. Opcode 1 carries a whole list, split into frames under the 4 KiB inline limit, validating every pattern before matching so the answer cannot depend on order. - The firewall was only ever proven against gusset's diagnostic engine. SelfTest panics inside this archive (opcode 0x7fff0001, header-only) on a throwaway handle and requires ErrPanic, ErrPoisoned, and a clean match on the shared handle. Check stays panic-free: Manvi runs it in serve. - DrainLogs forwards gusset's Rust log ring, which nothing read. - The lockfile named gusset 0.0.1 / dc-glob 0.2.3, so `cargo build --locked` failed against current gusset; the setup-gusset pin moves from 7a56c3c to b6f5200 (gusset main, 0.0.2) to match it. Tests: the CPython fixture through the boundary, MatchAny against Go across frame splits, poison recovery under 64-way concurrency, 200 micro-deadlines without poison, and FuzzMatchParity. Against a checkout of gusset at the pin (b6f5200), with the archive built by cgo-env.sh: race detector with GOGC=1 -count=15 clean, a 90 s fuzz clean, gusset-check ok with non-zero Rust stats. An earlier 4 min fuzz (1.94M execs) against the pre-allocator archive also found no divergence. Protects I2 (panic firewall), I3 (cancellation), I4 (bounded handles) and I6 (the archive under test is the archive linked). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FUNo5WZs78gWyCSXf2nRhm (cherry picked from commit 3197897)
…ation An adversarial review of 3197897 found these; each fix has a test that fails without it (reverted and run): - Match obeyed an opcode already on the caller's context: opcode 1 decoded a match frame as a match-any frame, and the self-test opcode panicked the shared handle. Match now pins opcode 0. (TestMatchIgnoresAnOpcodeOnTheContext) - A call landing on a handle a sibling had just poisoned or retired got ErrPoisoned or an unclassified "handle is closed" while a healthy handle was one call away (457 + 64 such errors in the review's probe). call() retries once on the replacement; a frame's own ErrPanic is never retried. After Close, the retry reaches engine() and answers ErrClosed, as Close documents. (TestPoisonUnderConcurrencyRecovers now requires every call to succeed and exactly one replacement per poisoning; TestZZCloseRacingCallsSeeErrClosed; TestOwnPanicIsNotRetried) - Close joins workers without a bound, so wiring it into a server's exit would hang on a stuck engine. Shutdown(drain) runs gusset.Shutdown first and returns its error without joining when the drain expires. (TestShutdownIsBoundedAndRefusesLaterCalls, in a child process) - MatchAny validated UTF-8 per frame, so a bad pattern in frame 2 went unreported when frame 1 matched. Every field is checked up front. (TestMatchAnyValidatesAcrossFrames) - TestStatsCountBuffersOnce passed with the global allocator removed: gusset counts buffers by hand regardless. TestCountingIsTheGlobalAllocator asserts AllocCount grows across Matches (0 -> 0 without Counting). - verify.sh: `eval "$(cgo-env.sh)" || fail` could never fail — eval of empty output succeeds — so a failed engine build linked a stale archive. The output is captured first. - cgo-env.sh and ci-local hashed target/release while an inherited CARGO_TARGET_DIR sent the fresh archive elsewhere; both now pass --target-dir. Base CFLAGS come from `go env` (process env, `go env -w`, or default) instead of the process env alone. A path with a space is refused by name. - check-release now requires rust/gusset-engine/Cargo.lock's dc-glob to match the product version; the next bump would otherwise break `cargo build --locked` of the umbrella exactly as 0.2.3-at-1.3.5 did. - Doc: the self-test opcode is sent by SelfTest, not Check. Race detector with GOGC=1 -count=5 clean; gusset-check ok. Protects I2 (panic firewall), I3 (bounded shutdown), I4 (bounded handles) and I6 (the archive under test is the one linked). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FUNo5WZs78gWyCSXf2nRhm (cherry picked from commit 876ace2)
gussetfn.DrainLogs stopped on a short read, treating it as "ring empty". gusset's second-pass audit (80c6468) makes gusset_drain_logs hand over whole lines and never split a UTF-8 character, so a short read can leave lines behind; only 0 means empty. Looping until 0 is correct under both the pinned gusset and the new one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FUNo5WZs78gWyCSXf2nRhm (cherry picked from commit f8866c7)
b6f5200 -> 709c2b7: gusset's second audit fixed a use-after-free where a waiter returned freed Rust memory as its result, a double-Wait park, drain exit admitting unreadable work, a queue lost-wakeup, phantom ring overflow, failure codes lost with a NULL status, unbounded engine error text and split log drains, and added a chaos hammer. Verified against it before pinning: umbrella cargo test, gussetfn race suite, gusset-check. Protects I1, I2 and I4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FUNo5WZs78gWyCSXf2nRhm (cherry picked from commit 663b998)
A third audit found the gusset gates in DevCouncil CI could not run:
- analysis-plane's clients job stopped at its gofmt step on
policy/zfix_split_test.go (already on main), so Set up Gusset, vet,
go test (which includes gussetfn) and -race never ran. gofmt applied.
- A pin-only bump triggered nothing: neither workflow's path filter named
.github/actions/setup-gusset/**, and rust.yml also omitted
rust/gusset-engine/** and gussetfn. Added.
- The Windows components leg could never build: gusset refuses non-unix
targets with compile_error!, yet the action built it for
x86_64-pc-windows-gnu through MinGW, and gussetfn plus gusset-check
imported gusset unconditionally, so the host (which dc-verify's json
contract needs) could not build there either. gussetfn and gusset-check
are now build-tagged unix; elsewhere gussetfn answers ErrUnsupported and
`devcouncil gusset-check` exits 2 ("could not run", never a pass). The
action still checks out and links the sibling on Windows (go.mod's
replace must resolve) and skips the Rust toolchain and archive build;
the MinGW and gnu-target steps are gone. Verified: GOOS=windows
CGO_ENABLED=0 go build and go vet of the host and gussetfn succeed.
- TestStatsCountBuffersOnce had no downward slack on a process-wide
counter; a concurrent free from an earlier test's cleanup could fail it.
It allows n-n/16; double-counting still fails near 2n.
actionlint clean; check-workflows tests pass; gussetfn -race and policy
tests pass; gusset-check ok on linux.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FUNo5WZs78gWyCSXf2nRhm
(cherry picked from commit f0ec3e2)
b6e9673) serve_stress's ten_thousand_pipelined_stdio_requests_stay_inside_the_ceiling failed on this PR with "MCP response write exceeded 5s": the 5 s RESPONSE_WRITE_TIMEOUT covered the wait for the writer mutex as well as the write, so on a loaded runner a reply queued behind other in-flight replies to a peer that was reading fine ran out of time. The bound now covers write+flush once the writer is held. This is the devmap-serve half of b6e9673 on claude/zealous-faraday-56lcrv, unchanged; its find-msvc-tools lockfile half is already here as a2c364e. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS
… the scan detector room - safe_fs: check_unchanged and check_appended_only compared the held handle with the file now at the name by dev/ino under cfg(unix) only. On Windows a managed file swapped for another between open and use went unnoticed, and the name's metadata was computed and dropped, which is the unused-variable clippy error that failed the Windows leg once cc compiled again. same_identity compares volume serial and file index from the handles on Windows (windows_information, already used here), dev/ino on unix. Clippy is clean on linux; the Windows build is checked by CI (the vendored C grammars cannot be cross-built here). - repomap: TestAnAreaIsFoundWithoutWalkingEveryIndexedFile failed on macOS runners at 3.4x and 7.4x against a bound of 3x for an 8x larger map, though AreaForPath never touches the file table. The map is now 32x larger and the bound 8x: the lookup passes 5/5 here, and putting the old per-level scan back reads 39.7x and fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FUNo5WZs78gWyCSXf2nRhm (cherry picked from commit c7563cf)
Checked locally with the windows-gnu target and mingw-w64, the same workspace set rust.yml's Windows Clippy step lints; it is clean now: - same_identity (added in c7563cf) named a File and a Metadata `held` and `_held`; clippy::similar_names. Renamed to held_file / named_file. - dc-regress owners_and_test_signal: two tests drive a /bin/sh stub standing in for git and returned early on non-unix, which passed without testing anything and is unreachable_code under -D warnings. They are #[cfg(unix)] now, since the mechanism cannot exist on Windows. The other three tests in the file still run everywhere. Linux clippy and the file's tests (5/5) pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FUNo5WZs78gWyCSXf2nRhm (cherry picked from commit a21ee78)
…aring-violation retries The Windows leg compiled for the first time in b6e9673 and showed 28 failing tests across 12 targets. Taken by cause: Production - repo_path / MCP roots (devmap-serve root_resolve): the unix rule ran on every host, so a Windows server refused every native path ("this server only opens unix filesystem paths"). Validation is now the host's own: unix still refuses C:\... and /C:/..., Windows refuses a drive-less /... instead of resolving it against the current drive, and takes only file:///<drive>:/... URIs. Neither side reinterprets the other's spelling. Unit tests for both directions; the unix URI test is unix-only. - Hook background builds (devmap-cli hook): they ran under `sh -c`, which Windows does not guarantee, and the lock-owner liveness check answered "alive" for every pid on non-unix, so a dead build's lock stood for the full 30-minute ceiling. On Windows the build is now spawned directly as a detached process, removes its own lock on exit (OwnedLock, only when the lock's pid file names it, so the variable cannot direct any other removal), and OpenProcess/GetExitCodeProcess answers liveness. The hook's own std handles are made non-inheritable first; otherwise the build held the host's pipe and the host waited on the hook until the build ended. unix behaviour is unchanged. - write_atomic (devmap-query): the snapshot comparison did not retry os error 32 while another writer's rename was replacing the target, which failed concurrent artifact and `devmap claude` bundle writes. It now waits within a 5 s deadline, and the rename retry drops its 100-attempt cap (about 0.5 s) for the same deadline. - Store::open (devmap-store): SQLITE_PROTOCOL, a WAL-index lock race lost after SQLite's own retries, is retried from the top for up to 20 s with backoff; open is re-entrant because migrate re-reads the version under the write lock. All eight concurrent openers of a legacy store failed on it. - paths: state paths are joined per component, so doctor no longer prints `.\.devmap\codeintel/devmap.sqlite`. Tests (the code was right, the fixture was not) - Canonical paths on Windows are `\\?\` verbatim with long names where the temp dir used 8.3 (`RUNNER~1`). Assertions that a message names a path accept it as written or canonical without the prefix (`names`); the `paths` db_path comparison ignores the prefix on both sides. - Root URIs were `format!("file://{}", path)`, which is `file://C:\...` on Windows; `file_uri` builds the platform's form. - Host configs were JSON built by format!, so a Windows path was an invalid escape and the config registered nothing; now serde_json. - A repository name containing `"` cannot exist on Windows; there the fixture keeps the other hostile characters. - make_undetachable set the read-only attribute, which Windows ignores on directories; it now denies writes with icacls. - A mid-session store deletion cannot happen on Windows while the server holds the file; the test asserts the refused delete and that the store still serves. - fanout.sh runs only on unix, where its consumers (verify.sh, the memory probe) run; a bare `bash` on a Windows runner is the WSL launcher. The rusqlite half of the test still runs everywhere. Verified: clippy -D warnings clean for x86_64-pc-windows-gnu (mingw-w64) and linux across the rust.yml workspace set; linux tests for every touched binary pass. Three tests that rely on permission denials fail identically before and after this change here because the container runs as root (claude_integration an_unwritable_output_directory..., kernel_defects k1_..., hook an_unremovable_stale_lock..., pinned_root_disables_discovery); CI runs them as a normal user. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FUNo5WZs78gWyCSXf2nRhm (cherry picked from commit 38c4d29)
…ss_reach 38c4d29 took the Windows leg from 28 failures to 3, all in its own test changes, and one file it edited after formatting failed Format on every OS (verify.sh gates too, which runs the same check): - pinned_root_disables_discovery: the refusal names the pinned root canonically (`\\?\C:\...`), and the assertion compared the raw spelling; it uses `names`, like the other path assertions. - parse_roots_list_caps_at_max_and_reports_overflow built drive-less `file:///tmp/...` URIs, which a Windows server now correctly refuses, so there was nothing to cap; it builds them in the host's spelling. - windows_file_uri_is_rejected_not_reinterpreted asserts the unix rule and is unix-only; its Windows twin asserts that `file:///Users/...` does not become a root there. cargo fmt --all --check clean; clippy -D warnings clean for linux and x86_64-pc-windows-gnu; mcp_repo_scope 24/24 and phase1_freshness_reach 9/9 on linux (hook_conformance's pinned-root test needs a non-root user, as before). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FUNo5WZs78gWyCSXf2nRhm (cherry picked from commit 241b018)
runInThrowawayTree ran `sh -c <command>` and snapshotted the tree as soon as sh exited. For a corpus entry that backgrounds its write (`echo hi > .env &`), sh exits first: the write landed after the snapshot, so the test recorded `would have written []` instead of `.env`, and on macOS it raced t.TempDir's RemoveAll, failing TestCommandVerdictIsNeverLooserThanTheWritesItPerforms with "directory not empty". Appending `wait` on its own line makes sh reap the job first. main never reached this on macOS: its clients job stopped at gofmt. Passes 30/30 with -count=30; the backgrounded entry now records [.env]. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS
bharathvbcr
pushed a commit
to bharathvbcr/GitPulse
that referenced
this pull request
Sep 28, 2026
Re-vendored from bharathvbcr/DevCouncil#14 at 485a2a6, which now also carries DevCouncil's Windows fixes: file identity checks on Windows in devmap-extract's safe_fs, native path validation, and sharing-violation retries in devmap-query's artifact writes and devmap-store. Behaviour on unix is unchanged (safe_fs keeps the same dev/ino check behind a helper). `vendor-crates.mjs --check` reports every DevCouncil crate local: clean, upstream: matches. clippy -D warnings is clean, and the Rust suite passes apart from tests this sandbox cannot run as-is (two permission tests that root bypasses, which pass unprivileged). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS
…le atomic writes; test(gate): wait for backgrounded writes The last two Windows failures at 3b58dd7, and a macOS flake at 241b018: - concurrent_readers_cannot_enqueue_writer_work: eight threads opening one store read-only lost the WAL-index race (SQLITE_PROTOCOL) as the migrators had; only Store::open retried it. Both opens now go through one retrying_lost_races helper. - concurrent_emission_leaves_one_valid_bundle: os error 32 still escaped write_atomic, from a step outside the comparison and the rename (a different bundle file each run). Every step of write_atomic is safe to repeat from the top, so on Windows the whole write retries a sharing violation within the same 5 s deadline. - gate: runInThrowawayTree ran `sh -c command` and read the tree when sh exited, so `echo hi > .env &` was recorded as writing nothing and its write landed during t.TempDir cleanup ("directory not empty", macOS). The shell now waits for its background jobs. If the gate had allowed that command, the old harness would have missed its write. TestThrowawayTreeSeesABackgroundedWrite fails without the wait (run 4: saw [], want [.env]). fmt --check clean; clippy -D warnings clean for linux and windows-gnu; migration_ladder 12/12, artifacts 7/7, gate passes. embedded_reader's a_filesystem_read_only_open... fails here identically without this change (root ignores the read-only fixture); CI runs it as a normal user. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FUNo5WZs78gWyCSXf2nRhm (cherry picked from commit ebd2a8f)
…in a process concurrent_readers_cannot_enqueue_writer_work still failed on Windows at ebd2a8f: eight threads opening one store read-only all got SQLITE_PROTOCOL for the whole 20 s retry deadline. Retrying cannot help. Reproduced locally under Wine with a windows-gnu build: a single reader opens fine and creates the -wal/-shm pair, the storm is intermittent and leaves the file healthy, and even plain opens with no further reads fail. It is contention between read-only connections in one process setting up the WAL index together, with no read-write connection there to finish it. A read-only connection now opens and makes its first read, the moment it maps the WAL index, under a process-wide lock (READ_ONLY_SETUP); reads after that run concurrently. Under Wine the test fails 3/3 without the lock (21-33 s) and passes 4/4 with it (about 2.7 s); the whole embedded_reader suite passes there, 11/11. Linux: migration_ladder 12/12, embedded_reader unchanged (its read-only-fixture test needs a non-root user). fmt and clippy clean for linux and windows-gnu. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FUNo5WZs78gWyCSXf2nRhm (cherry picked from commit 9248cc6)
bharathvbcr
pushed a commit
to bharathvbcr/GitPulse
that referenced
this pull request
Sep 28, 2026
Re-vendored from bharathvbcr/DevCouncil#14 at 975a79b, which adds two Windows fixes from the same upstream series: - devmap-query: on Windows, write_atomic retries the whole write when a sharing violation (os error 32) escapes any step, within its 5 s deadline. Unchanged on unix. - devmap-store: read-only opens retry lost SQLite races like Store::open, and a process-wide lock covers a read-only connection's open and first read, so concurrent read-only connections cannot livelock setting up the WAL index. Reads after that still run concurrently. `vendor-crates.mjs --check` reports every DevCouncil crate local: clean, upstream: matches. clippy -D warnings is clean, and the Rust suite passes apart from the permission tests root bypasses (they pass unprivileged). process_admission_stress's substitution test fails its own "race was exercised" guard intermittently on this 4-CPU sandbox: in one full run the test passed and an identical copy of it failed, every refusal being the storm renaming the directory away, so the vendored crates are not involved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS
At 975a79b the Windows leg failed concurrent_v19_openers_keep_pending_work_and_one_durable_identity: sixteen threads calling Store::open on one v19 store all got SQLITE_PROTOCOL for the whole 20 s retry deadline (the test ran 19.5 s). It is the livelock 9248cc6 fixed for read-only connections, between read-write ones: connections in one process setting the WAL index up together, each losing to the others, with retrying unable to help. The process-wide lock (renamed READ_ONLY_SETUP -> CONNECTION_SETUP, since it now covers both) is also held across open_once, from Connection::open through enable_wal and migrate. Migration was already serialised by SQLite's write lock, so this costs in-process openers nothing they were not already waiting for. Other processes still coordinate through SQLite, and everything after the open runs concurrently. Nothing inside an open opens another store, so the lock cannot be re-entered. Linux: fmt and clippy -D warnings clean; every devmap-store test binary passes as an unprivileged user (migration_ladder 12/12, embedded_reader 14/14, store_hardening 53/53, ...); the two concurrent-open tests pass 10/10 repeated; all 144 devmap-serve, devmap-query and devmap-cli test binaries pass, so the wider lock deadlocks nothing there. Not reproduced on Windows here; the next Windows leg is the check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS
bharathvbcr
pushed a commit
to bharathvbcr/GitPulse
that referenced
this pull request
Sep 29, 2026
Re-vendored from bharathvbcr/DevCouncil#14 at 4efeecf. devmap-store's process-wide setup lock (now CONNECTION_SETUP) also covers a read-write Store::open, from Connection::open through migration, so concurrent opens in one process cannot livelock setting up the WAL index on Windows. Reads after an open still run concurrently. `vendor-crates.mjs --check` reports every DevCouncil crate local: clean, upstream: matches. clippy -D warnings is clean. The full Rust suite (2798 passed) hits no deadlock from the wider lock. It fails only the two permission tests root bypasses (they pass unprivileged) and process_admission_stress's intermittent "race was exercised" guard, which, as in 79107bb, is unrelated to the vendored crates. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
GitPulse vendors DevCouncil crates into
src-tauri/vendored/, and itsVENDOR.jsongives origin commitc55d479for all of them. That commit was never pushed. I diffed each vendored crate'ssrc/againstrust/<crate>onmainand found exactly one difference in devmap-store:FileSymbolsPageandStore::latest_symbols_for_fileinsrc/db.rssrc/lib.rsGitPulse's
cmd_codeintel_symbols_for_file(thecodeintel::symbols_for_filepath) calls this method. Without it here, re-vendoring GitPulse from DevCouncil would drop the feature. Every other vendored crate was byte-identical tomain.GitPulse is re-vendored from this PR's head (
4efeecf) on itsclaude/friendly-lamport-60dj43branch. There,vendor-crates.mjs --checkreports all 12 crates asupstream: matches.What
The port itself:
a429fdelands the vendored code, verbatim apart fromcargo fmton thelib.rsre-export list.head_shacome from one pinned snapshot.Nonemeans the store has no generation.Somewith empty rows means the path has no indexed symbols. Spans go throughchecked_span.rust/devmap-store/tests/symbols_for_file.rs, 5 tests: an empty store, file scoping and source order (checked againstall_symbols), an unindexed path, the latest generation winning, and a corrupt span being refused.fba2df5declares that test'sparserequirement, as devmap-cli'severy_integration_test_is_classified_against_the_parse_featurerequires.mainhas been red since v1.3.5. The rest make this PR green. All but the last one are fixes that already exist onclaude/zealous-faraday-56lcrv.Lockfiles, formatting and timeouts:
e63f184updatesrust/gusset-engine/Cargo.lockto dc-glob1.3.5.a2c364eandc3c5f4dportb6e9673, split into two commits.a2c364epins find-msvc-tools to0.1.14, becausecc1.2.67 does not compile against 0.1.13 on Windows.c3c5f4dmakesdevmap-serve's 5 s reply bound cover the write, not the wait for the writer. This fixesserve_stress.92e5f8dports thelsp.rsanddc-procparts ofe3bcb6b, which bound every wait on a language server. This fixesevery_child_process_in_the_kernel_goes_through_the_runner.dd7695cappliesgofmttopolicy/zfix_split_test.go.Windows, cherry-picked unchanged with
-x:fea3992←3197897,62331b3←876ace2,e88cdb3←f8866c7harden the engine integration.0b389c4←663b998pins Gusset709c2b7.d5ef7eb←f0ec3e2: Gusset is unix-only (compile_error!elsewhere), so the MinGW/gnu-target build could never pass.gussetfnandgusset-checkare now build-tagged unix, and Windows skips the engine build.b30b477←c7563cf:safe_fschecks file identity on Windows too.b031491←a21ee78: the last two Windows clippy errors.9a1d8d2←38c4d29: native Windows path validation in MCP root resolution, a shell-free detached build, and sharing-violation retries in artifact writes and the store.58760dc←241b018: the last three Windows tests. After it,test (windows-latest)fell from 12 failing targets to 1.f9083a7←ebd2a8f:write_atomicretries the whole write on a sharing violation. That fixesconcurrent_emission_leaves_one_valid_bundle.975a79b←9248cc6: a process-wide lock covers a read-only connection's open and first read. Concurrent read-only connections could livelock on Windows setting up the WAL index (concurrent_readers_cannot_enqueue_writer_work).819944ais left out. It updates a workflow test for arust.ymljob this branch does not carry, andscripts/check-workflows.test.mjspasses 7/7 without it.Mine, not on
zealous-faraday:4efeecfextends9248cc6's lock, renamedCONNECTION_SETUP, to read-write opens, fromConnection::openthroughmigrate.975a79b,concurrent_v19_openers_keep_pending_work_and_one_durable_identityfailed on Windows. Sixteen threads callingStore::openall gotSQLITE_PROTOCOLfor the whole 20 s retry deadline. It is the same livelock, between read-write connections.zealous-faradaywill want the same change.The gate test,
485a2a6thenf9083a7:runInThrowawayTreeread the tree as soon asshexited. A backgrounded write (echo hi > .env &) therefore went unrecorded, and landed duringt.TempDircleanup. That failedTestCommandVerdictIsNeverLooserThanTheWritesItPerformson macOS.485a2a6andebd2a8fmade the samecommand+"\nwait"change independently, and the file takesebd2a8f's version with its regression test.CI
Green on
4efeecf: every workflow, includingtest (windows-latest)twice andtest (macos-15)twice.Two Windows failures on earlier heads were intermittent and did not recur:
git committhat git itself failed to write (unable to create temporary file).concurrent_readers_cannot_enqueue_writer_work, which975a79bfixes.Verification (Linux, rustc 1.98.1, go 1.26.6)
Rust:
cargo fmt --all --checkandcargo clippy --workspace --all-targets --locked -- -D warnings: clean.migration_ladder12/12,embedded_reader14/14,store_hardening53/53,symbols_for_file5/5, and the rest. As root, the tests that rely on read-only fixtures fail, because root ignores file permissions.4efeecf.serve_stress: 10/10, three runs in a row.Gusset engine, Go and scripts:
rust/gusset-engineagainst Gusset709c2b7: build--locked, 12/12 tests, clippy clean.gofmtandgo vetare clean.go test ./gate ./gussetfn ./policy ./cmd/devcouncil ./repomappasses, and-race ./gussetfnpasses.GOOS=windows CGO_ENABLED=0 go build ./...andgo vetpass.check-release.test.mjs: 32/32.check-workflows.test.mjs: 7/7.🤖 Generated with Claude Code
https://claude.ai/code/session_01WQJD75wFPY52ckToQTu9FS