Repository navigation
v0.4.0
Breaking
- Library API:
query::validate_select_only,
storage::sync_state_repository::acquire_lockandrelease_lockare
removed, andfetch::GhCommandLineis built withGhCommandLine::new().
CLI flags and MCP tool inputs are unchanged. prs_mergednow counts by merge date, so metric values change.
Changed
prs_merged(user, repo and group metrics, and thetop_mergers
leaderboard) now counts pull requests merged in the window, by
merged_date_key. It used to count pull requests opened in the window that
are merged now, so period-over-period deltas ran low. Expect different
numbers after upgrading.query::validate_select_onlyis removed;raw_querynow asks SQLite whether
the prepared statement is read-only.
Fixed
-
query --group <name>for a group with no members returned every pull
request; it now returns none, matchingmetrics.QueryBuilder::authors
andreposdo the same for an empty list. -
raw_queryrefused nothing but a non-SELECT/WITHfirst word, so
WITH x AS (SELECT 1) DELETE FROM ...ran. It also rejected a;inside a
string literal. -
gh api graphqlexits 1 when a response carries partialerrorsbut
still prints the data. That data is now kept, so a search with one
SAML-protected or missing node stores the rest instead of failing.
Rate-limited responses still go through retry and backoff. -
A hung
ghis killed after 120 seconds with a clear error
(GITHUBDW_GH_DEADLINE_SECSchanges the limit).ghnow runs with
GH_PROMPT_DISABLED=1and withoutGH_DEBUG/DEBUG, so request headers
never reach stored error text. -
A permanent HTTP 403 (SAML, permissions, blocked repository) fails on the
first attempt instead of seven. Only rate-limit 403s and specific
transient network errors are retried. -
GraphQL string variables are passed with
-f, so a login or repository
named123,trueornullreaches GitHub as a string and@xis never
read as a file. Only variables the query declaresIntorBooleanuse
-F. -
sync: run-level errors (cancellation, a spent rate limit or quota reserve,
an unusablegh, a failing database) now stop the repository and user walks
at once instead of being recorded as a failure for every remaining item.
Constraint errors on one item's rows are still recorded per item. Page size
halves only for 502/504, timeout and resource-limit failures; any other
error returns immediately. -
sync: the per-entity sync lock is now an owned lease. Recording progress
renews it, so a walk that runs past 30 minutes (search pacing, rate-limit
sleeps) no longer lets a second process start the same sync. A run releases
only the lock it holds, so a stale holder finishing cannot delete its
successor's lock. A lock with an unparsablestarted_atis reclaimable
instead of blocking forever, and a failure while recording the job outcome
releases the lock and no longer replaces the sync's own error. -
sync watch: the reported start time stays the job's real start instead of
following lock renewals. -
mcp:trigger_syncno longer blocks the server. It runs on a blocking
thread with its own database connection, so other tool calls, pings and
cancellation are answered while it works. A call processes at most 500
pull requests and returnspartial: true(statusPartial) when it stops
at that budget; calling again resumes. A rate-limit wait over 30 seconds
is not slept: the call returns statusRateLimitedwith
rate_limited_until. The result also carriesnotes. Input is unchanged.
Removed
- The unused
live-testsCargo feature. storage::sync_state_repository::acquire_lockandrelease_lock; use
SyncLease(oracquire_owned_lock).