Fix #1306: github capture: an observedRepos.list() failure during a session_repos tick still aborts the whole tick - #1310
Conversation
…e whole tick (#1306) `runCaptureTick` awaited `runtime.observedRepos.list()` outside any guard, so a failing local inventory read escaped into the `tick()` catch in `source.js`: the tick recorded `github.poll_tick_failed` having captured nothing, and the source's `backlogPending` was left at whatever the previous tick set. Catch it, log `github.inventory_resolve_failed` with the error's `error_kind`, and return it as a tick error with `pending` read off the durable cursors, so one unresolved inventory no longer aborts the tick or retires saved continuations it never touched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ill contradicting the reported cause The inventory-failure guard read `pending` off the durable cursors alone. The bounded revalidation slice runs inside the same `list()` call, so a throw from it leaves the pass unfinished while the index keeps reporting it as pending (state is only swapped after a completed `update()`). On an install whose repos all completed, `pending` came back `false`, cleared the source's backlog flag, and deferred the retry a full `poll_interval` while capture ran against the truncated inventory an incomplete revalidation returns. Fold `revalidationPending()` into the returned `pending`, with a regression test that fails without it. `hyp github backfill owner/repo` now reaches the `repos === 0` branch instead of throwing, so it told the user none of their repos are in the active inventory one line after `reportErrors` printed the real cause. Guard that message on there being no error to explain the zero. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review record - head
|
…kfill advising a next step after a failed run The failure-path comment claimed `revalidationPending()` stays true because the bounded slice runs inside the same `list()`. It does not: `update()` builds a local `next` and swaps `state = next` only on success, so a pass started by the very call that throws is discarded and reports nothing (and `writeState` never runs either). Only a pass an earlier tick already persisted keeps reporting pending. Corrected the comment in `tick.js` and the matching rationale in the regression test; the code is unchanged. `hyp github backfill owner/repo` also printed "run 'hyp graph project'" after a run that captured nothing because the inventory never resolved, dressing a failure up as progress. Guarded on the run having captured something or having no errors. Pinned that CLI branch with the first test to exercise `runGithubBackfill` (via the exported `setGithubRuntime`), covering both this guard and the earlier `errors.length === 0` guard: it asserts the real cause reaches stderr, that the inventory is not blamed on the configured selection, and that no next-step advice follows. It fails without the guard. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review record - head
|
|
Triage at head
Worst case verified as a bounded, self-healing local retry-cadence inefficiency: the tick aborts before any GitHub call, nothing is written or lost, and it clears on the first successful inventory read. All three round-2 fixes were verified present at this head. |
Ship risk:
|
Feature or issue
When
inventory: "session_repos"is configured,runCaptureTickawaitedruntime.observedRepos.list()outside any guard, before the per-repotry/catchthat exists precisely so one failure cannot kill a tick. A failing local inventory read (an unreadable cache partition, a sidecar rewrite) therefore escapedrunCaptureTickinto thetick()catch insource.js: the tick recordedgithub.poll_tick_failedhaving captured nothing, no per-failureerrorsentry reachedhyp github sync/backfill, and the source'sbacklogPendingwas left at whatever the previous tick happened to set. Deferred hardening finding 2 from PR #1302, which fixed only theall_visiblehalf of the same shape.Solution
runCaptureTicknow guards theobservedRepos.list()call: on a throw it logsgithub.inventory_resolve_failedwith the error'serror_kind, and resolves with the failure as a single{ repo: '(inventory)' }entry inerrorsinstead of throwing, so the tick completes attributably and the CLI reports the real cause.pendingon that path is read off the durable cursors rather than reported flatfalse: the failure itself is not backlog (LLP 0360#cadence), but a tick that never resolved its inventory retired none either, and clearing the flag would push a saved continuation back to a full poll interval (LLP 0361#budget).test/plugins/github-observed-repos.test.js, where the existingrunCaptureTick+observedReposcases live (the issue namedgithub-capture.test.jsalongside theall_visiblecase, but that case is in unmerged PR Fix #1298: github capture: a foreign Link during all_visible enumeration aborts the whole tick instead of one repo #1302 andcaptureReposnever callsobservedRepos.list()). Both fail on master with the throw escaping attick.js:28and pass after. Full suite 5990 pass / 0 fail;npm run typecheckclean. No lint or build check is defined beyondbuild:types.Code: +25 / -5 lines
Fixes #1306