chore(deps): bump actions/cache from 4.3.0 to 6.1.0 - #266
dependabot[bot] wants to merge 556 commits into
Conversation
🐛 fix: raise LMDB mapsize cap 8GB→16GB + PersistentEmbeddingCache auto-resize on MDB_MAP_FULL (#189)
…ed error messages
When the LMDB mapsize auto-resize cap is reached (7 sites: 4 in
vectordb/store.rs, 3 in embed/cache.rs), the error/warn messages said
'already at max size {}MB' or 'exceeds MAX_LMDB_MAP_SIZE_MB {}MB' but
never told the operator how to raise the cap. Appended '(set
CODESEARCH_MAX_LMDB_MAP_SIZE_MB to raise this cap)' to all 7 messages,
using backslash line-continuation per the repo's caller-facing-literal
convention (validated by tests/caller_facing_literals.rs - all 4 pass).
- CHANGELOG: renamed unreleased section 1.2.1 -> 1.2.4 (current pending version) and added the #189 fix entry (cap raise + cache auto-resize + error-message hint), alongside the existing build.ps1 entry. - README: documented the new CODESEARCH_MAX_LMDB_MAP_SIZE_MB env var in the Environment Variables table. PRs #187 and #176 (also merged since v1.2.0) were docs/AGENTS.md-only changes with no user-facing code impact, so intentionally have no CHANGELOG entries.
…remove dead PR trigger - test-linux: remove `cargo build --release` (nothing consumes it; release.yml builds isolated per-platform artifacts at tag time). Was pure wasted CI minutes on every feature/develop push. - Add `master` to push triggers: the develop->master release squash-merge previously got ZERO CI build/test coverage (protect-master.yml only checks the source-branch name, not code quality). - Remove the pull_request: branches: [main] trigger: this repo has no `main` branch (default is `master`), and PRs target develop/master anyway — the trigger was permanently dead. push already covers every commit that matters.
master only ever advances via a squash-merged release PR (develop/release/* -> master, per RELEASING.md). A direct git push to master is always either a mistake or should go through that same PR path anyway. GitHub's branch ruleset already blocks non-admin pushes, but the repo owner's own bypass privilege makes that toothless against exactly this kind of accidental local push -- which happened this session (a commit landed on master while HEAD was there for the release flow, caught only by manual inspection). Adds scripts/pre-push (tracked) with the master-push guard + QC gate, and installs the equivalent (hand-maintained superset, customer-ref-leak check stays local-only per existing convention) to .git/hooks/pre-push. Verified: simulated stdin push to refs/heads/master exits 1 with the guard message; refs/heads/develop passes through unaffected.
…s path gate
Two changes to .github/workflows/ci.yml, both reducing wasted CI minutes
without losing coverage:
1. concurrency: ci-${{ github.ref }}, cancel-in-progress: true — a stale
in-flight run on the same branch (e.g. a stage commit immediately
followed by a review-fix amend + re-push, which happened repeatedly
this session) now gets cancelled instead of running to completion for
a commit that is already superseded.
2. csharp-integration-tests now checks (via git diff on the pushed range,
not a fragile commit-message convention) whether helpers/csharp/**
actually changed before running its dotnet publish + cargo test cycle.
That job was previously running unconditionally on every single push
regardless of relevance — a full self-contained dotnet publish plus a
cargo test compile for code nobody touched.
Not changed (deliberately): test-lib running on both linux and windows is
cross-platform coverage, not duplication — kept as-is. fmt/clippy running
both locally (pre-push hook) and in CI is intentional defense-in-depth
(CI cannot trust a hook that can be bypassed via --no-verify).
Diagnosed a user report: a local 'codesearch serve' instance was silently keeping a mounted cloud federation peer warm, defeating its scale-to-zero, with zero trace in the logs. Traced and ruled out TUI federated polling (correctly gated behind --no-tui already) and explicit federated tool calls (none logged). Root cause: the cloud keep-warm task (CODESEARCH_KEEP_WARM_URL / --keep-warm-url) is not gated by --no-tui at all, has no restriction that its target must be 'self', and every ping was completely silent (success and failure both discarded with zero log line) -- so a keep-warm URL accidentally pointing at another peer (e.g. copy-pasted from a cloud deployment env into a local shell profile) would silently generate periodic outbound traffic every KEEP_WARM_INTERVAL_SECS (120s -- matches the reported 'every 2 minutes') with no way to see it in the local logs. Fixes: - Per-ping logging: debug! on success, warn! on failure (was: silently discarded). - Startup sanity check: new extract_host_from_url() helper (no new crate dependency) compares the keep-warm target's host against this server's own effective bind host; a mismatch (and not localhost/127.0.0.1/::1) now fires a loud warn! naming both hosts, explicit that keep-warm exists to self-ping THIS replica, not another peer. Tests: 6 new cases for extract_host_from_url (plain http, https with real hostname, no-scheme input, IPv6 literal bracket-preserving, query/fragment stripping, empty-host edge case). Full serve:: suite green (104 passed). Diagnosis write-up: docs/diagnose-federated-keep-warm.md
The embedded serve TUI ran a background `/status` fan-out to every mounted federated peer on a cadence equal to the LOCAL serve's idle-suspend window (2h by default). Each such poll WOKE the peer's scale-to-zero replica, which then held itself warm for its own full idle window (~1h on the cloud deploy) — roughly a 50% duty cycle on a peer nobody had queried. Ground truth from Azure Log Analytics: wakes exactly 120/121/120 minutes apart, each warm period ~67 min, with zero federated searches. The design spec was that background polling of LOCAL repos is fine but a FEDERATED peer must never be polled in the background. "Cannot keep a peer awake past the host's own suspend term" is a strictly weaker property than "never wakes it", and the two windows were unrelated values besides (local host vs. remote peer). - tui.rs: `spawn_remote_discovery` no longer polls on a timer. The periodic tick is now CONFIG-ONLY (`REMOTE_ROW_REFRESH_SECS` = 5s, zero HTTP): it rebuilds rows from the `remote_mounts` allowlist so mount/unmount edits and `l` reloads surface promptly. The activity poke (a real federated tool call landed on that peer) remains the only thing that ever contacts a peer, plus the explicit `i` info-overlay keypress. The `initial_cycle` startup gate is gone — every cycle is now config-only, so it had nothing left to gate. - serve/mod.rs: drop `ServeState::idle_suspend_secs` (field, env init, getter and the `--idle-suspend-secs` override). It existed solely to feed the TUI poll cadence and is now write-only. The keep-warm task reads the flag/env directly, so `--idle-suspend-secs` behaviour is unchanged. - Doc comments record WHY there is no baseline poll, to stop the reasoning from being reintroduced. Local repos are entirely unaffected. Review-fixes: - [Important] tui_common.rs `activity_stale` doc still referenced "the slow baseline poll hasn't fired" as the reason a remote row goes stale → rewritten to state there is no background poll and that `-` on an idle mount is the normal steady state, not a fault. - [Important] AGENTS.md and CHANGELOG.md still asserted the removed `idle_suspend_secs` cadence as current design (and named a field this commit deletes) → corrected, but deliberately NOT folded in here: both files carry a large unrelated pending doc-cleanup rewrite that must not enter a source commit. They land in the docs commit later on this same unpushed branch. - [Pre-existing, fixed opportunistically] the discovery snapshot was gated on `!cfg.remotes.is_empty()`, so removing the last peer from repos.json left its rows rendered forever with no snapshot to clear them. The emit is now unconditional; with no peers `build_remote_rows` yields an empty vec, which clears them. Still zero HTTP. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Second half of the federated scale-to-zero defect. Removing the TUI's timer
poll (previous commit) stops the peer being woken; this stops a wake that
does happen from costing a full warm hour.
The keep-warm loop computed its idle check as:
let last = kw_state.most_recent_tool_call().unwrap_or(start);
`/status` and `/healthz` have their own handlers and never call
`record_tool_call`, so a replica woken by anything other than a genuine tool
call found no recorded call, fell back to the process start time, and
self-pinged its own ingress every 120s for the entire idle window.
The fallback was unreachable in the case it was written for ("a freshly
deployed replica stays warm for the full idle window before first use"): a
real tool call always records itself, so the fallback could ONLY ever fire
when the wake was not real work. Its entire practical effect was rewarding
spurious wakes — ~67 min warm instead of the ~6 min a bare wake costs,
roughly 11x amplification.
Keep-warm now requires a real recorded tool call; with none it does not ping
and lets the host suspend the replica, which the next real request wakes.
Verified this preserves the legitimate path: an inbound federated search hits
SEARCH_PATH -> crate::mcp::rest_search_handler -> the MultiStoreContext path
that calls record_tool_call, so after real use the peer keeps itself warm
exactly as before. A peer staying warm for an hour after real use is correct
behaviour and is unchanged.
Also fixes the startup "target isn't self" warning shipped in 55fa36b, which
false-positived on the ONLY deployment where keep-warm is correct: on Azure
Container Apps the process binds 0.0.0.0 while keep_warm_url is the ingress
FQDN, so the host comparison failed and the warning fired on every cold
start. A wildcard bind means our externally-visible host is genuinely
unknown, so the comparison cannot conclude anything and must stay silent — a
check that cries wolf on the correct configuration trains operators to ignore
the case that matters. The rule moved into a testable `keep_warm_foreign_target`
helper, covered by 5 new tests (wildcard binds, genuine foreign host, matching
host, loopback targets, unparseable URL).
cargo fmt / clippy -D warnings clean; 1134 passed, 42 ignored.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The diagnosis document's root cause was a hypothesis that turned out to be wrong, and two project docs still described the removed poll cadence as the current design — which is how this same behaviour got re-introduced twice (PR #181, #184). Corrected against the code now on this branch. DIAGNOSE_FEDERATED_KEEP_WARM.md (moved from docs/, rewritten): - The old root cause blamed a misconfigured local CODESEARCH_KEEP_WARM_URL. Disproven on four independent grounds, now recorded under "What was ruled out": the env var is set nowhere locally (process env, HKCU, HKLM, all shell profiles); the one-time "keep-warm enabled" line appears in zero logs from 2026-04-26 on; that absence is meaningful because init_serve_logger is always file-only in serve mode and those logs do carry other INFO lines; and no local process held a :443 connection. - Replaced with the confirmed two-defect root cause plus the Azure Log Analytics ground truth (wakes 120/121/120 min apart, ~67 min warm each, zero searches). - Records the requirement being violated ("poll LOCAL repos, never federated") and the rejected reasoning, so it is not re-litigated. - Notes one residual, not currently exploitable: the MCP `status` TOOL, when project-scoped, does record a tool call — unlike the HTTP /status endpoint that every known poller actually uses. CHANGELOG.md: - The consolidated fix entry goes under [1.2.4] (unreleased). An earlier draft wrongly rewrote the [1.2.0] section — v1.2.0 is a real tag and #181/#184 shipped in it, so editing it would have made released notes claim a fix that is not in that release. Both original 1.2.0 entries are restored verbatim as historical record, each marked superseded. - Older version entries compressed to one-liners (existing convention). AGENTS.md: - The "Scale-to-zero-safe federated polling" bullet asserted the removed cadence as current and named ServeState::idle_suspend_secs, a field that no longer exists. Rewritten as an explicit design constraint with the rejected reasoning attached. - Keep-warm bullet updated for the tool-call requirement and the wildcard-bind carve-out. - Completed TODO sections removed, Implemented Features compressed. README.md: - The grep-guard bullet still described the 5-minute retry-unblock that 1.2.0 replaced with a /healthz liveness probe. Rewritten to match. - Verified NOT stale and left alone: "17 languages" (supported_languages() returns 17 — the table's 18th row, Jupyter, is JSON-parsed rather than tree-sitter) and the web-guard's 5-minute retry, which still exists. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Per-feature work log covering the whole cycle: the disproven original hypothesis, the Azure Log Analytics ground truth, the two defects, the three stages with their commit SHAs and review outcomes, and the open follow-ups. Records why this behaviour took three attempts across PR #181, #184 and this branch, so the rejected reasoning is not re-litigated a fourth time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`ci.yml`'s push trigger is a prefix allowlist that never included `fix/**`, and there is no `pull_request` trigger. Every `fix/...` branch therefore merged into develop having never run fmt, clippy or a single test in CI. This is the repo's own documented naming convention — the comment directly above the branch list even says "feature/fix -> develop". Only the prefix was missing. It was invisible because CodeQL is a separate, pull_request-triggered workflow, so the PR still showed a green check. On PR #192, `gh pr checks` listed CodeQL and nothing else; the local pre-push QC gate was the only thing validating the branch. Adds `fix/**` and documents the footgun plus how to verify coverage (`gh pr checks <n>` should list the CI jobs, not just CodeQL). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
🐛 fix: stop waking the scale-to-zero federated peer (and stop it self-warming afterwards)
… duplicates
All hooks now live in .githooks/ and are enabled with a single
`git config core.hooksPath .githooks`. Removes the copy-into-.git/hooks step
that had let the tracked template and the installed hook drift apart.
Why this was broken:
- scripts/pre-push documented its own install as `cp scripts/pre-push
.git/hooks/pre-push`, but the tracked copy had no customer-reference leak
scan. Following the documented install silently removed that guard.
- .githooks/post-checkout documented `git config core.hooksPath .githooks`,
which would have made git look only in .githooks/ — a directory that held
neither pre-commit nor pre-push. Enabling one hook would have disabled the
two that matter. core.hooksPath was in fact unset, so post-checkout had
never run at all.
Changes:
- .githooks/{pre-commit,pre-push,post-checkout} + README.md; scripts/pre-commit
and scripts/pre-push deleted (scripts/qc.ps1 stays).
- Customer patterns move to untracked .githooks/customer-patterns.local. The
list is itself the thing being hidden, so it must never be tracked. When it
is missing, pre-push prints a loud "SKIPPED — nothing was checked" warning
instead of passing silently: a guard that quietly stops running is worse
than no guard, because it is still trusted.
- pre-push skips the Rust QC gate when the branch changes no .rs/Cargo.* files
vs origin/develop. Compared against origin/develop rather than the pushed
ref range because stdin is already consumed by the master guard, and this
avoids the all-zeros remote_sha case for a new branch. Every uncertain case
runs the gate rather than skipping it.
- Leak scan uses `git grep -lIE` instead of `git ls-files | xargs grep`:
space-safe paths, no argument-length limit, no stderr to suppress.
- ci.yml: add chore/** to the push branch allowlist — same prefix-allowlist
footgun that left fix/** with no CI at all until PR #192.
- .gitattributes: drop the now-dead scripts/pre-commit eol=lf rule.
Master-push guard is unchanged.
Verified by running the hook directly: master push blocked (exit 1); normal
push passes with QC correctly skipped (exit 0); missing pattern file warns
loudly and exits 0; a planted customer reference in a tracked file blocks
(exit 1); the Rust-path filter matches src/foo.rs and Cargo.toml and not
docs/x.md, proving the skip can actually un-skip.
Review-fixes:
- [Important] `|| true` on the leak scan turned a git grep *failure* into a
clean pass, and the comment-stripper could manufacture that failure: an
inline `#` in a valid pattern like `Acme(NV#|BV)` was truncated to `Acme(NV`,
producing an invalid ERE that exits 128. One bad line poisoned the whole
alternation, so a real leak sailed through with "No customer references
detected." Now: only whole-line comments are stripped (a mid-line `#` stays
part of the pattern), and the git grep exit status is branched on — 0 blocks,
1 is clean, anything else prints the loud SKIPPED banner. One rule overall:
configuration problems warn, actual leaks block.
- [Important] RELEASING.md still documented `cp scripts/pre-commit
.git/hooks/pre-commit` — a copy of a file this commit deletes, into a
directory core.hooksPath makes git ignore. Replaced with the single
`git config core.hooksPath .githooks` install.
- [Important] The QC-skip regex missed `rust-toolchain.toml` and `.cargo/`,
both tracked here: a toolchain bump changes no .rs file yet flips fmt,
clippy and tests, so the gate was skipped for exactly the change most likely
to need it. Widened to cover rust-toolchain, .cargo/, scripts/qc.*, and
rustfmt/clippy.toml (the latter two not tracked today, listed so adding one
later cannot silently reopen the gap).
- [doc] README.md said `hooks git install` writes to `.git/hooks/`. It resolves
the target with `git rev-parse --git-path hooks`, so it honours
core.hooksPath and chains into an existing hook as a marker-delimited block.
Corrected; no code change needed.
Re-verified after the fixes: master push blocked (exit 1); normal push passes
with QC skipped (exit 0); an invalid regex in the pattern file now warns
loudly and exits 0 instead of reporting clean; a mid-line `#` survives
parsing; rust-toolchain.toml, .cargo/config.toml, scripts/qc.ps1, src/a.rs and
Cargo.lock all trigger the gate while docs-only paths do not.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
🔧 chore: unify git hooks in .githooks/ — one location, no hand-copied duplicates
The worklog still said "Not pushed. Three commits sit locally" while the work was merged (PR #192) and running in production. A change record that is wrong is worse than none, so this brings it to ground truth. - Header: status is now shipped + verified, with the merge SHA and the deployed revision; test line records CI green, not just the local run. - Stage 4 added: the branch had no CI at all until `fix/**` was added to ci.yml's prefix allowlist, with the self-test that proved it. - Stage 5 added: deployment of both sides (local via copy-to-common, cloud as revision --0000024), config verified intact across the image update, and the scale-to-zero verification — replicas held at 0 across six consecutive checks with no traffic. Recorded as positive evidence: under the old binary the keep-warm fallback made reaching 0 at ten minutes impossible. - Build note: two az acr build runs failed at the identical step with "layer does not exist" on a byte-identical Dockerfile; a local docker build succeeded. Root cause is the ACR Tasks agent, not this repo. - Follow-ups: dropped the stale "not pushed" item; the production check is now a 24h Log Analytics sample rather than "unverified"; added the ACR Tasks failure as a blocker for any automated cloud deploy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
📝 docs: worklog — record merge, deploy and production verification
…e forever A repo whose database failed to open (typically a transient write lock - an indexing run holding the DB when a query arrived) was cached as RepoState::Conflicted, and the fast path in get_or_open_stores replayed that error on every later call without ever retrying the open. The state's only documented exit was idle eviction, and it was unreachable: evict_idle_repos iterates last_access, but both paths that mark a repo Conflicted (warmup_repo and the get_or_open_stores slow path) propagate the failure with `?` before reaching their touch_access call. A repo that conflicts on first open therefore never gets a last_access entry and is never considered for eviction, however long it sits idle. Querying it did not help either: the fast path replayed the cached error while calling touch_access on the way, so the only queries that would have registered it for eviction were also the ones resetting its idle timer. Net effect: a momentary lock was indistinguishable from permanent corruption and could only be cleared by restarting serve - while the error text promised "the next query will retry automatically". A cached conflict is now dropped on next access and the open genuinely retried. Retrying is cheap when it still fails (a refused file lock), and this mirrors the missing-DB path, which already refuses to cache Conflicted for the same reason (missing_db_not_cached_as_conflicted). Regression test asserts recovery without a restart and without an idle wait. It carries two preconditions so it cannot pass vacuously (the first open must genuinely fail, and that failure must actually be cached as Conflicted), and was confirmed to FAIL with the fix neutralised - reproducing the exact user-visible error string. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Review-fixes: - [Important] Non-atomic get()+remove() on the Conflicted cache entry could race with a concurrent insert (e.g. add_repo_handler or force-reindex installing a fresh RepoState::Write) and delete that live entry instead, dropping its cancel_token without cancelling it. Fixed by using DashMap::remove_if with a matches!(v, RepoState::Conflicted) predicate — same atomic check-and-remove primitive already used by is_indexing() in this file — so removal can only ever affect an entry still Conflicted at removal time.
…-retries 🐛 fix: retry a conflicted repo instead of replaying the cached failure forever
When an agent (or any non-MSYS caller, e.g. an MCP client) sent codesearch
a POSIX-style path like `/c/Users/foo`, Rust on Windows resolved the
leading `/` as "rooted on the current drive" — i.e. `<drive>:\c\Users\foo`,
silently creating junk directories like `C:\c\Users\...` and indexing the
wrong project. This is the path-pollution defect behind the orphan
`<repo>-propagate-tmp` indexes (diagnosed end-to-end: an agent-created
staging folder was indexed under a polluted `C:\c\...` mirror that nothing
ever cleaned up).
Fix: add `translate_msys_path()` to `cache/file_meta.rs`. It detects a
leading `/` + single ASCII letter (+ `/` or EOL) and rewrites it to
`<UPPER>:/...`. Idempotent on every other input; no-op on non-Windows.
Apply it at every user-supplied path boundary so existing AND not-yet-existing
paths are both caught:
- `safe_canonicalize` calls it before canonicalising (existing-path case)
- `ReposConfig::register` / `register_with_alias` fallbacks use it on the
raw path (non-existing-path case)
- `resolve_database_with_message` fallback uses it on the raw path too
Added tests:
- `translate_msys_path_converts_single_letter_drive` (table-driven, Windows)
- `translate_msys_path_leaves_non_drive_paths_untouched` (Windows)
- `translate_msys_path_leaves_existing_windows_paths_untouched` (Windows)
- `translate_msys_path_is_noop_on_unix` (non-Windows)
- `register_translates_msys_posix_path` — integration regression for the
exact defect (Windows)
- `register_leaves_unix_path_untouched` — guards against the fix leaking
to Unix where `/c/...` is legitimate
Validation: cargo check + cargo clippy -D warnings clean; cache:: + db_discovery::
tests = 101 passed, 7 ignored, 0 failed.
Review-fixes (round 1 → 2):
- [Critical] translate_msys_path missed a #[cfg(windows)] guard; the body
ran on Unix too, rewriting legitimate `/c/...` paths to `C:/...` and
breaking test-linux CI. Split into a Windows real impl + a Unix no-op.
- [Important] register_translates_msys_posix_path only pinned the
existing-path branch (safe_canonicalize success path); the actual defect
site — the non-existing-path fallback — was unpinned. Added a dedicated
test `register_translates_msys_posix_path_when_dir_does_not_exist` that
fails if the fallback is reverted to `strip_unc_prefix`.
- [Important] unregister_path and alias_for_path had the same fallback
pattern as register() but weren't updated → register stored `C:\Users\foo`
while unregister compared against the raw `/c/Users/foo`, leaving entries
stuck. Added register/unregister symmetry test. Fixed by introducing a
shared `normalize_user_path(path)` helper (translate_msys_path +
strip_unc_prefix) and routing all 5 fallback sites through it, per the
repo's "structural fix" rule for the warnings-channel class of defect.
…e_user_path Stage 1 introduced `normalize_user_path` and applied it to the 6 db_discovery fallback sites. Round-2 review flagged 5 more sites with the same pattern (`safe_canonicalize(...).unwrap_or_else(|_| <raw path>)`) elsewhere in the codebase that still leaked caller-supplied MSYS POSIX paths (`/c/...`) to Windows file APIs when canonicalize failed. Same defect class, same fix. Sites updated: - `try_delegate_reindex_to_serve` (src/index/mod.rs ~2064) - `try_delegate_add_to_serve` (src/index/mod.rs ~2296) - `try_delegate_rm_to_serve` (src/index/mod.rs ~2394) + its inner `normalize_for_cmp` closure (~2397) - `run_serve` `--register` loop (src/serve/mod.rs ~4745) All 5 now use `crate::cache::normalize_user_path(...)` on the fallback, so the `validate_path_within_allowed_roots` check and the eventual `config.register(...)` call both see the translated `C:/...` form, not the raw `/c/...`. Added tests for `normalize_user_path` itself (the helper shared across all fallback sites): - `normalize_user_path_translates_msys_and_strips_unc` (Windows) - `normalize_user_path_only_strips_unc_on_unix` (non-Windows) The 5 sites here are CLI-arg paths feeding serve-delegation flows; the register/unregister symmetry tests from stage 1 cover the integration guarantee indirectly (the delegation flows terminate in `register()`). Validation: cargo check + cargo clippy -D warnings clean; cache:: + db_discovery:: tests = 104 passed, 7 ignored, 0 failed.
…e_reindex_to_serve
Stage 2 swept 5 safe_canonicalize fallback sites for the MSYS path-pollution
defect, but missed the twin of the closure it fixed in try_delegate_rm_to_serve.
Stage-2 review round-1 flagged this site (src/index/mod.rs:2076) as the
identical pattern in the identical closure name in the sibling delegation
function. Same defect class, same one-line fix: route the fallback through
`crate::cache::normalize_user_path(p)`.
Post-fix detector sweep confirms every production `safe_canonicalize(...).
unwrap_or_else(_)` site now goes through `normalize_user_path`:
- db_discovery/repos.rs: register, register_with_alias, unregister_path,
alias_for_path, scan_for_remote (5 sites)
- index/mod.rs: try_delegate_reindex_to_serve outer + closure,
try_delegate_add_to_serve, try_delegate_rm_to_serve outer + closure (5 sites)
- serve/mod.rs: run_serve --register loop (1 site)
The only remaining hits are a test helper (repos_tests.rs:12) and the
vectordb mapsize-pin key (vectordb/store.rs:67, input is already canonical
by design — flagged by stage-2 review as out-of-scope).
Validation: cargo clippy -D warnings clean. No test changes needed — the
closure is private and the register/unregister symmetry tests from stage 1
cover the integration guarantee.
fix: translate MSYS POSIX paths at the path boundary (path-pollution defect)
… + rebuild Symbol-rebuild failures of the MDB_BAD_VALSIZE class (data written by an older storage-major, observed on all C# repos after the arroy 0.8/heed 0.22 upgrades) now queue the repo for automatic recovery: evict stores (remove_repo's sequence, minus unregister), wipe the DB dir with the bounded lock-retry, and force-reindex through the TUI machinery whose store-open path recreates fresh formats. Recoveries are processed strictly one repo at a time (single worker, flag+queue under one lock so no lost wake-up); read-only repos are skipped with a pointer to the owning writer. Detection helper is unit-tested; queue dedup + worker start pinned by test.
Serve: auto-recover LMDB format corruption (sequential wipe + rebuild)
…ting (todo #153) Two independent defects in remote chunk fetch: 1. The peer URL replaced '{id' without the closing brace, producing /chunk/2058%7D — axum's {id} param swallowed the stray '}' into the captured value, so mock-based tests passed while real peers answered 400. Replace the full '{id}' placeholder; pinned by a test whose route echoes the exact path it was hit on. 2. get_chunk(project=<peer>/<alias>, chunk_id) died with 'Unknown alias': mounted remote projects now route through the same federated fetch search uses (local aliases win name clashes). Hermetic routing test (temp config file — the in-memory config is reloaded from disk, which previously leaked the developer's real peers into the test).
|
@dependabot rebase |
|
The base commit for this pull request has not changed. |
Fix federated chunk fetch: URL residue + project-scope routing (todo #153)
dependabot: target develop (rebases were resetting the base to master)
|
@dependabot rebase |
0b4dc97 to
349a247
Compare
|
@dependabot recreate |
Bumps [actions/cache](https://github.com/actions/cache) from 4.3.0 to 6.1.0. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](actions/cache@0057852...55cc834) --- updated-dependencies: - dependency-name: actions/cache dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
349a247 to
4673fa2
Compare
|
Superseded by #275 (your bump, cherry-picked onto a real develop base and merged with full CI). This PR branch was recreated from a stale master fork, so its diff/CI could not validate against develop. Closing — dependabot will re-propose against develop next cycle now that |
|
OK, I won't notify you again about this release, but will get in touch when a new version is available. If you'd rather skip all updates until the next major or minor version, let me know by commenting If you change your mind, just re-open this PR and I'll resolve any conflicts on it. |
Bumps actions/cache from 4.3.0 to 6.1.0.
Release notes
Sourced from actions/cache's releases.
... (truncated)
Changelog
Sourced from actions/cache's changelog.
... (truncated)
Commits
55cc834Merge pull request #1768 from jasongin/readonly-cached8cd72fBump@actions/cacheto v6.1.0 - handle cache write error due to RO token2c8a9bdMerge pull request #1760 from actions/samirat/esm_migration_and_package_updatee9b91fdPrettier fixese4884b8Rebuild dist10baf01Fixed licensese39b386Fix test mock return orderb692820PR feedback6074912Rebuild dist bundles as ESM to match type:module5a912e8Fix lint and jest issues