release: v1.4.3 - #276
Merged
Merged
release: v1.4.3#276
Conversation
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)
…nners PR #196's two existing-path MSYS tests failed on Windows CI: - db_discovery::repos::tests::register_translates_msys_posix_path - db_discovery::repos::tests::unregister_path_matches_msys_posix_form Root cause: Windows CI runners use a temp root under `C:\Users\RUNNER~1\...` (8.3 short name for `runneradmin`). The tests built the expected path from the raw `tmp.path()` (short-name form) but `safe_canonicalize` inside `register()` resolves 8.3 names to their long form, so the stored path had `runneradmin` while the expected had `RUNNER~1` → string mismatch. For `unregister_path_matches_msys_posix_form` the same asymmetry hits the fallback branch: after the dir is deleted, `safe_canonicalize` fails and `normalize_user_path` returns the input verbatim (no short-name resolution), so unregister's comparison ran short-form input against long-form stored entry and returned false. Fix: pre-canonicalize the fixture with `safe_canonicalize(&win_repo)` BEFORE building both the MSYS input and the expected value. Both sides then use the long form regardless of which branch (success or fallback) executes. The non-existing-path sibling test passed on CI by luck (both sides bypass canonicalize), but its assertion is correct and untouched. Local: all 3 MSYS register/unregister tests green.
fix(tests): pre-canonicalize MSYS test fixtures for 8.3 short-name runners
Investigated a reproducible bug where a `search` chunk_id for the
federated cloud/custom-kb project does not reliably resolve to the
same content via `get_chunk`. Root-cause hypothesis and fix options
are documented in AGENTS.md under Open TODOs; no code changes yet.
Review-fixes:
- [Important] Root cause section stated an unlabelled conclusion
("two id spaces/generations exist") that the code contradicts;
literal-mode search results have no real chunk_id (Option<u32>,
None for literal hits per src/federation/mod.rs) and get rendered
as a fabricated chunk_id: 0 via .unwrap_or(0) in src/mcp/mod.rs.
That alone fully explains the reproduced symptom. -> Rewrote the
section: primary hypothesis is now the fabricated chunk_id: 0 for
literal hits (with a concrete fix: stop defaulting to 0, keep it
Option/omitted), and the cross-generation id-drift theory is
demoted to an explicitly unconfirmed secondary hypothesis with its
own "reproduce before fixing" TODO.
…son unregister (todo #48) `remove_from_index` unregistered the repo from repos.json (and saved it) before deleting `.codesearch.db`. When the delete failed — typically LMDB files still held by a serve instance the delegation probe could not see — the command returned Err with the config entry already gone: the registry claimed the repo did not exist while its still-locked database sat on disk, and re-running the command did nothing because there was no entry left to remove. The database directory is now deleted first and repos.json is only mutated once that succeeds, so a failed delete leaves the config untouched and the identical command finishes the job after the lock is cleared. A save failure after a successful delete now returns Err instead of printing a warning and reporting Ok. Also folds the pre-existing double-unregister in the global-only path and drops the "(Global index remains)" line, which printed after the global entry had already been removed. Review-fixes (round 1): - [Important] CHANGELOG.md had two `(unreleased)` sections and no [1.2.10] heading — renamed to `## [1.2.10] - 2026-08-12` and restored the missing MSYS path-translation entry; develop's [1.2.10] section is byte-identical to master's. - [Important] `--keep-config` printed "Global index removed!" after "Config entry preserved." in the global-only case — guarded with `&& !keep_config`. - [Coverage] Added keep_config_global_only_preserves_entry for the one untested quadrant. Review-fixes (round 2 — test hermeticity + CI correctness): - [Important] Tests issued live HTTP against a real serve: the delegation probe now points at an in-test reset-server (accepted-then-closed TCP listener => instant RST => ServeProbe::Down on first attempt). No test can fire a live DELETE at a developer's running serve, and the Windows loopback hang (3 retries x 3s per delegating test) is gone too. - [Important] Env-var race with doctor tests: remove_order_tests + doctor's repos.json readers are now #[serial] (serial_test) with panic-safe restore via new crate::testing::EnvRestore. Rule recorded in AGENTS.md. - [Important] changelog-check.yml diffed two-dot against the raw base SHA — a rebase or develop-merge into the branch false-passed the check with develop's own changelog commits. Now diffs from the merge base. - [Added] Global-config canary in remove_order_tests: snapshot of the developer's real ~/.codesearch/repos.json asserted byte-identical at every test end — a mis-ordered seed save (which once overwrote the real registry during development of this very test) fails the test instead of destroying data. Seed now sets the env override BEFORE saving. Adds .github/workflows/changelog-check.yml: visible-not-blocking PR check that CHANGELOG.md was touched, bypassable via `no-changelog` label; AGENTS.md documents it in the PR workflow section. Positive control: restoring the old operation order makes failed_delete_leaves_repos_json_untouched fail with "repos.json must be untouched after a failed delete, got: []".
Two follow-up hardenings from the live incident during this session's test work (a mis-ordered test seed briefly overwrote the developer's real ~/.codesearch/repos.json — 17 repos, groups, remotes, all replaced by a one-entry fixture, recovered from serve startup logs). repos.rs: - `ReposConfig::save()` now refuses, under cargo test, to write the real global repos.json unless CODESEARCH_REPOS_CONFIG is set to an override (or CODESEARCH_TEST_ALLOW_GLOBAL_SAVE is explicitly set). This is the guard that would have turned today's incident into an instant panic instead of silent data loss. - `ReposConfig::save_to()` was a bare `fs::write` — neither atomic nor recoverable. Now: (1) keeps one generation of the previous file as `<path>.bak`, best-effort; (2) writes to a sibling `.new` temp file and renames it into place, with a bounded retry (5 attempts / 20ms) on transient Windows rename errors (AV / search-indexer handle races), mirroring `vectordb::store::atomic_write_json`'s classification. logger/mod.rs (unrelated discovery while investigating the incident): - `cleanup_old_logs` was only ever invoked from standalone-MCP-mode (src/mcp/mod.rs). Neither the CLI logger init nor the serve logger init called it, so `~/.codesearch/logs/` grew forever — found at 299MB / 183 files spanning back to April, despite `DEFAULT_LOG_MAX_FILES=5` / `DEFAULT_LOG_RETENTION_DAYS=5`. - `parse_log_date` only recognized the CLI prefix (`codesearch.log.`), so even a cleanup call over the shared global log dir would silently skip every `serve.log.*` file. Now recognizes both prefixes. - Both `init_logger` (CLI) and `init_serve_logger` (serve) now call `cleanup_old_logs` on their log dir before wiring the appender. Validation: cargo fmt --check clean; targeted suites green (repos: 55, logger: 9, remove_order_tests: 5, doctor: 13).
fix: codesearch index rm reorders file-delete before repos.json unregister (todo #48)
SearchResultItem.chunk_id is now Option<u32>, omitted from JSON when absent. Literal-mode hits (local serve-delegation parse and federated convert_remote_item) carry no chunk id; the old .unwrap_or(0) rendered a real-looking chunk_id: 0 that callers could combine into a bogus "<peer>/<alias>:0" chunk_ref, which get_chunk then silently resolved to an unrelated chunk — a confident wrong answer (reproduced against cloud/custom-kb, see AGENTS.md Open TODOs). Semantic/similar paths wrap their real store ids in Some. Both fixed sites carry a regression pin asserting a literal hit has no chunk_id AND the key is absent from the JSON (not null); each pin verified red under a temporarily reintroduced unwrap_or(0). Review-fixes: - [Important] parse_search_items_from_call_result had zero test coverage, so its fix had no pin (the class-not-a-site reship mode AGENTS.md warns about) → added table-driven tests: literal payload without chunk_id (None + absent key + snippet->content mapping), explicit chunk_id preserved as Some, semantic keeps real ids, unparseable payload still yields empty list (pinned as-is).
…te TODOs/changelog Store-level repro of the secondary hypothesis from AGENTS.md Open TODOs (todo #51): next_id = max_key + 1 is recomputed on every open, so deleting the chunks holding the HIGHEST ids lowers max_key and the next reopen reassigns those ids to unrelated content — get_chunk returns the wrong file with no error. Boundary control proves a low-range delete is safe (surviving ids stable, next insert beyond the range). Mechanism confirmed locally; production two-cold-start comparison still owed before any content-keyed-id/generation-stamp fix is spent on (per the TODO's reproduce-first gate). AGENTS.md: primary fix marked DONE (branch reference, red-verified pins, live before/after repro still owed); secondary hypothesis upgraded from unconfirmed to mechanism-confirmed-at-store-level with test names. CHANGELOG entry added under 1.2.11 (unreleased). Review-fixes: - [Important] drift_chunk helper had two no-op 'as usize' casts -> clippy -D warnings failed at HEAD (missed because the post-recovery re-apply of these tests was only cargo-tested, not re-linted) -> casts removed; clippy clean, 1172 tests pass.
…sites A broken vector store rendered as an ordinary empty/short result with zero signal to the caller — the "search errors must not become empty results" class. Sites fixed (all in src/mcp/mod.rs): - single-store literal search: .ok()?? in filter_map -> Err propagates via ? to the existing "Error resolving search results" exit - hybrid semantic+literal fusion: closure mapped Err -> Ok(None) and the caller did .ok() on top -> Err noted into single_warnings, loop stops - find (definitions) + find (usages), multi-store branches: bind the lookup, note Err via note_store_failure into the existing find_warnings channel (same pattern as resolve_chunk_from_stores) - find (definitions) + find (usages), single-store branches: pre-resolve with ? so Err reaches the "Error opening database" exit Pinned by tests/store_err_swallow_detector.rs: source-scanning test in the caller_facing_literals.rs style — fails the build on a direct get_chunk(..).ok() or an if-let scrutinee on store.get_chunk(..) anywhere under src/mcp/. Red/green proof: reintroducing the if-let form on two sites made it fail with exactly those two violations; restored, it passes. Validation: cargo check --all-targets, cargo clippy --all-targets -D warnings, cargo test --lib --bins (1160 passed, 42 ignored), cargo test --test store_err_swallow_detector (1 passed). Ref: todo #57 full-review findings.
`serve --model X` was used as the query fallback for a repo whose `metadata.json` records no model. That overrode a legacy index the moment the flag was set: a 384-dim index queried with a 768-dim model failed every search with "Query embedding dimension mismatch: expected 384, got 768", and a same-dimension model compared incomparable vector spaces without erroring. Resolve such an index to the built-in default instead: that is both the historical behaviour and the value every other reader assumes for metadata without a `model_short_name`. `serve --model` keeps doing what its name says, selecting the model for newly created indexes. Surface the assumption to the caller as a search warning naming the repo, the assumed model and the re-index command, and log it once per repo so a busy hub does not repeat the same line. The scope-free status summary still reports the serve default.
fix: resolve each index's own embedding model (serve queries, CLI index/stats/status)
… + 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).
Fix federated chunk fetch: URL residue + project-scope routing (todo #153)
dependabot: target develop (rebases were resetting the base to master)
Bumps [criterion](https://github.com/criterion-rs/criterion.rs) from 0.5.1 to 0.8.2. - [Release notes](https://github.com/criterion-rs/criterion.rs/releases) - [Changelog](https://github.com/criterion-rs/criterion.rs/blob/master/CHANGELOG.md) - [Commits](criterion-rs/criterion.rs@0.5.1...criterion-v0.8.2) --- updated-dependencies: - dependency-name: criterion dependency-version: 0.8.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [serial_test](https://github.com/palfrey/serial_test) from 3.5.0 to 4.0.1. - [Release notes](https://github.com/palfrey/serial_test/releases) - [Commits](palfrey/serial_test@v3.5.0...v4.0.1) --- updated-dependencies: - dependency-name: serial_test dependency-version: 4.0.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [indicatif](https://github.com/console-rs/indicatif) from 0.17.11 to 0.18.6. - [Release notes](https://github.com/console-rs/indicatif/releases) - [Commits](console-rs/indicatif@0.17.11...0.18.6) --- updated-dependencies: - dependency-name: indicatif dependency-version: 0.18.6 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [colored](https://github.com/mackwic/colored) from 2.2.0 to 3.1.1. - [Release notes](https://github.com/mackwic/colored/releases) - [Changelog](https://github.com/colored-rs/colored/blob/master/CHANGELOG.md) - [Commits](colored-rs/colored@v2.2.0...v3.1.1) --- updated-dependencies: - dependency-name: colored dependency-version: 3.1.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 7.0.1. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](actions/upload-artifact@ea165f8...043fb46) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.6.2 to 3.0.3. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](softprops/action-gh-release@3bb1273...efb3536) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: 3.0.3 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.3.0 to 8.0.1. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](actions/download-artifact@d3f86a1...3e5f45b) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 8.0.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4.3.1 to 6.0.0. - [Release notes](https://github.com/actions/setup-dotnet/releases) - [Commits](actions/setup-dotnet@67a3573...a98b568) --- updated-dependencies: - dependency-name: actions/setup-dotnet dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
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>
Dependency batch 2: cargo majors (criterion/serial_test/indicatif/colored) + CI actions refresh
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.
Release v1.4.3 — squashed delta from develop (v1.3.14 → v1.4.3).
Highlights (full details in CHANGELOG.md, section [1.4.3]):
Behavior-identical MCP protocol (legacy lifecycle preserved).