gh-glance 0.11.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/index.mjs +20 -5
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.11.2] - 2026-08-31
11
+
12
+ ### Fixed
13
+
14
+ - **Unchanged Security checks no longer turn a known count red.** A conditional
15
+ alert-source response with no staged ETag write now contributes an empty
16
+ cache update instead of failing with `part.stagedEntities is not iterable`.
17
+
18
+ ## [0.11.1] - 2026-08-31
19
+
20
+ ### Fixed
21
+
22
+ - **Lagging GitHub rate-limit counters no longer leave REST-backed tabs paused.**
23
+ A same-window observer refresh now keeps the governor fresh while retaining
24
+ the more conservative used and remaining values.
25
+ - **Dead request owners no longer delay every shared budget probe.** Their
26
+ uncertain API cost remains reserved, but later probes do not wait 30 seconds
27
+ for requests that can no longer complete.
28
+
10
29
  ## [0.11.0] - 2026-08-30
11
30
 
12
31
  ### Fixed
@@ -776,7 +795,9 @@ engineering, security, QA and UX. What follows is what changed as a result.
776
795
  - The `main` field from `package.json`. It advertised the file as importable,
777
796
  but importing it took over the terminal or exited the host process.
778
797
 
779
- [Unreleased]: https://github.com/juan294/gh-glance/compare/v0.11.0...HEAD
798
+ [Unreleased]: https://github.com/juan294/gh-glance/compare/v0.11.2...HEAD
799
+ [0.11.2]: https://github.com/juan294/gh-glance/compare/v0.11.1...v0.11.2
800
+ [0.11.1]: https://github.com/juan294/gh-glance/compare/v0.11.0...v0.11.1
780
801
  [0.11.0]: https://github.com/juan294/gh-glance/compare/v0.10.0...v0.11.0
781
802
  [0.10.0]: https://github.com/juan294/gh-glance/compare/v0.9.1...v0.10.0
782
803
  [0.9.1]: https://github.com/juan294/gh-glance/compare/v0.9.0...v0.9.1
package/index.mjs CHANGED
@@ -2659,7 +2659,10 @@ function claimProbe(scope, leaseId, nowMs) {
2659
2659
  const resources = RATE_RESOURCES.filter((resource) => dueAt[resource] <= at);
2660
2660
  const nonce = randomUUID();
2661
2661
  const startedReservationIds = Object.entries(state.reservations)
2662
- .filter(([, reservation]) => reservation.status === "started")
2662
+ // An expired owner can no longer settle its request. Keep that uncertain
2663
+ // cost charged, but do not make every later probe wait for it to finish.
2664
+ .filter(([, reservation]) => reservation.status === "started" &&
2665
+ state.leases[reservation.leaseId]?.expiresAt > at)
2663
2666
  .map(([id]) => id);
2664
2667
  state.probeClaim = {
2665
2668
  ownerLeaseId: leaseId,
@@ -2707,7 +2710,7 @@ function budgetFromObservation(raw, previous, nowMs, {
2707
2710
  clearProvenBlock = false,
2708
2711
  allowEpochChange = false,
2709
2712
  } = {}) {
2710
- const normalized = normalizeBudgetResource({ ...raw, observedAt: receivedAt });
2713
+ let normalized = normalizeBudgetResource({ ...raw, observedAt: receivedAt });
2711
2714
  if (
2712
2715
  !normalized || normalized.resetMs <= nowMs || receivedAt > nowMs ||
2713
2716
  !RATE_RESOURCES.includes(resource) ||
@@ -2723,8 +2726,17 @@ function budgetFromObservation(raw, previous, nowMs, {
2723
2726
  }
2724
2727
  if (previous) {
2725
2728
  if (normalized.resetMs < previous.resetMs) return { status: "ignored" };
2726
- if (normalized.resetMs === previous.resetMs && normalized.used < previous.used) {
2727
- return { status: "ignored" };
2729
+ if (budgetEpoch(previous) === epoch && normalized.used < previous.used) {
2730
+ if (!allowEpochChange) return { status: "ignored" };
2731
+ // The claimed observer can lag a newer endpoint response within the
2732
+ // same GitHub window. Refresh its timestamp without giving that stale
2733
+ // counter any capacity: retain the higher used and lower remaining
2734
+ // values until the observer catches up.
2735
+ normalized = {
2736
+ ...normalized,
2737
+ used: previous.used,
2738
+ remaining: Math.min(normalized.remaining, previous.remaining),
2739
+ };
2728
2740
  }
2729
2741
  if (
2730
2742
  normalized.resetMs === previous.resetMs && normalized.used === previous.used &&
@@ -3503,7 +3515,10 @@ async function fetchAlertSource(source, signal, now, {
3503
3515
  completedCalls,
3504
3516
  verdict: "ok",
3505
3517
  allNotModified: batch.allNotModified,
3506
- stagedEntities: batch.stagedEntities,
3518
+ // Every other fetchAlertSource path returns a Map. An all-304 batch has
3519
+ // no staged writes, so conditionalBatchResult returns null; normalize it
3520
+ // here before fetchSecurity merges the independently fetched sources.
3521
+ stagedEntities: batch.stagedEntities ?? new Map(),
3507
3522
  observations,
3508
3523
  parse: () => {
3509
3524
  const rows = mergeAlertRows(groups);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gh-glance",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
4
4
  "description": "A live-refreshing GitHub dashboard for your terminal: Actions, Issues, Pull Requests, and Security alerts in one narrow pane",
5
5
  "type": "module",
6
6
  "bin": {