Skip to content

fix: remediate comprehensive repository review#17

Merged
jmagar merged 3 commits into
mainfrom
codex/full-review-20260718
Jul 18, 2026
Merged

fix: remediate comprehensive repository review#17
jmagar merged 3 commits into
mainfrom
codex/full-review-20260718

Conversation

@jmagar

@jmagar jmagar commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • remediate all 50 P0-P3 findings from the full-repository comprehensive review
  • make download, catalog, cache, storage, runtime, and notification outcomes fail-safe and truthful
  • add protected CI, verified release artifacts, supply-chain hardening, and rebuilt user/contributor documentation
  • add regression, race, request-budget, security, atomicity, and subprocess CLI coverage
  • raise the minimum toolchain to Go 1.25.12 to eliminate reachable standard-library vulnerabilities

Validation

  • mise x go@1.25.12 -- make verify
  • actionlint
  • zizmor --pedantic .
  • git diff --check

The full review artifacts are intentionally local under ignored .full-review/; all reconciled P0-P3 findings were remediated before this PR was opened.


Summary by cubic

Remediates all P0–P3 findings from the comprehensive repo review. Hardens CI/release, makes catalog/download/cache/storage/runtime/notifications fail-safe and truthful, and raises the minimum toolchain to Go 1.25.12.

  • Bug Fixes

    • Catalog: generation-based snapshots with a manifest; previous snapshot preserved on failure; warm analysis uses a durable local full index with zero API requests; coverage emits structured partial errors; status reads from the manifest.
    • Security: stricter path sanitization and root confinement (including Windows separators and reserved components); gotify requires HTTPS off loopback and never forwards tokens on redirects; runtime/API logs rotate safely with mode 0600.
    • Storage: rclone subprocess slots cap concurrency and preserve the last good bulk index; album uploads are skipped on partial failures; explicit error when rclone is enabled without a storage provider.
    • Networking/Resilience: api.WithHTTPClient scopes clients for tests; circuit breaker allows only one half-open probe.
    • Media/tooling: size pre-calc reuses HEAD on track URLs; ffmpeg resolution no longer trusts the current directory; explicit error for empty HLS masters; video variant selection supports context cancellation; audio downloads drain and close HTTP bodies.
    • Watch/systemd: degraded runs return a WatchOutcomeError so the unit fails while counts are preserved; unit sets PATH and quotes ExecStart.
  • Refactors

    • CLI: adds a version command; Makefile produces versioned binaries via -ldflags and installs a stable symlink; version printing works without config and accepts --version/-v; clearer process exit codes.
    • Releases/CI: protected multi-platform release assets with smoke tests; new CI “quality” job runs fmt/vet/race/tests and scripts/check-docs.py; actions pinned; workflows use concurrency groups; Dependabot cooldown added.
    • Cache/config/runtime: atomic writes with fsync across cache/config/runtime; Windows locks use LockFileEx; process-level cache lock; catalog artifacts resolve by generation; durable per-artist shards for the full catalog.
    • Docs: simplified and corrected user/config references; README.md and guides trimmed; Node 22 toolchain for openwiki with lockfile checked in.

Written for commit 84c1506. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Releases now provide native binaries for major operating systems and architectures, with checksums and provenance attestations.
    • The CLI displays version, commit, build date, runtime, and platform information.
    • Catalog analysis can reuse cached data, reducing repeated requests.
    • Watch automation now reports partial or degraded results more clearly.
  • Bug Fixes

    • Improved error reporting, cancellation, download failure handling, and cache recovery.
    • Enhanced path, notification URL, credential, and remote-storage safety.
  • Documentation

    • Updated installation, configuration, command, release, and development guidance.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The CLI now propagates structured errors, supports build metadata and version reporting, and uses context-aware HTTP, download, and storage operations. Catalog caching, watch outcomes, path handling, notifications, CI, release automation, and documentation contracts were also updated.

Changes

CLI reliability and repository operations

Layer / File(s) Summary
CI, release, and documentation contracts
.github/*, Makefile, README.md, docs/*, scripts/check-docs.py
CI, release packaging, build verification, documentation validation, and CLI references were added or updated.
CLI contracts and error propagation
cmd/nugs/*, internal/config/*, internal/download/*, internal/helpers/errors.go
Command execution now returns contextual and aggregated errors, configuration owns CLI arguments, and version output includes build identity and platform data.
API execution and response handling
internal/api/*, internal/list/list.go, internal/model/constants.go
HTTP clients can be scoped through context, API circuit breakers are domain-specific, responses are drained, and JSON decoding is centralized.
Cache generations and durable indexes
internal/cache/*, internal/runtime/status.go
Catalog writes use generation manifests and atomic swaps; artist metadata is pruned while full-catalog data remains durable.
Catalog analysis and watch outcomes
internal/catalog/*, internal/model/progress_box.go
Coverage and watch operations report partial or degraded results, reuse cached artist metadata, and roll back failed systemd unit changes.
Storage, path, and notification safeguards
internal/rclone/*, internal/helpers/paths.go, internal/notify/*, internal/download/deps.go
Rclone processes are throttled, cached results can be reused, traversal and URL leakage are constrained, and Gotify transport validation prevents unsafe redirects.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI as cmd/nugs
  participant API as internal/api
  participant Cache as internal/cache
  participant Download as internal/download
  participant Storage as internal/rclone

  CLI->>API: Execute context-scoped request
  API->>API: Apply domain circuit breaker and retry policy
  API-->>CLI: Return typed response or error
  CLI->>Cache: Read durable catalog or artist index
  Cache-->>CLI: Return cached metadata
  CLI->>Download: Run context-aware download
  Download->>Storage: Upload or verify through process slot
  Storage-->>Download: Return storage result
  Download-->>CLI: Return aggregated operation errors
Loading

Possibly related PRs

Poem

A rabbit hops through caches bright,
With errors gathered left and right.
CI builds on every shore,
Safe little paths guard every door.
“Version!” cries Bun, “the release is near!”

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.87% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the PR’s goal of remediating issues found in a comprehensive repository review.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/full-review-20260718

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7db44e5652

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/catalog/watch_systemd.go Outdated
Comment thread go.mod

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
cmd/nugs/main.go (1)

173-180: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve cancellation status for pre-dispatch commands.

A cancellation error returned by handleCatalogGapsFill or handleWatchCheckCommand leaves runCancelled false, so the defer records "failed". Check isCrawlCancelledErr(runErr) when finalizing.

Proposed fix
-		if runCancelled {
+		if runCancelled || isCrawlCancelledErr(runErr) {
 			finalizeRuntimeStatus("cancelled")
 			return
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/nugs/main.go` around lines 173 - 180, Update the finalization logic
around runCancelled and runErr to treat errors recognized by
isCrawlCancelledErr(runErr) as cancellation before recording failure. Ensure
cancellations returned by handleCatalogGapsFill or handleWatchCheckCommand
finalize with "cancelled", while other errors continue to finalize with
"failed".
internal/download/audio.go (1)

723-734: 🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

Delay context cancellation until the response body is closed.

Calling reqCancel() immediately after api.Do(req) returns aborts the request's context while the response body is still open. The net/http transport will forcefully tear down the underlying TCP connection instead of returning it to the idle pool. Move the cancellation to after the body is closed to preserve connection keep-alive behavior and drastically improve throughput for sequential/concurrent requests.

⚡ Proposed fix for keep-alive connection reuse
-					resp, err := api.Do(req)
-					reqCancel()
-					if err != nil {
-						continue
-					}
-					if resp.ContentLength > 0 {
-						mu.Lock()
-						totalSize += resp.ContentLength
-						mu.Unlock()
-					}
-					_, _ = io.Copy(io.Discard, io.LimitReader(resp.Body, 64<<10))
-					_ = resp.Body.Close()
+					resp, err := api.Do(req)
+					if err != nil {
+						reqCancel()
+						continue
+					}
+					if resp.ContentLength > 0 {
+						mu.Lock()
+						totalSize += resp.ContentLength
+						mu.Unlock()
+					}
+					_, _ = io.Copy(io.Discard, io.LimitReader(resp.Body, 64<<10))
+					_ = resp.Body.Close()
+					reqCancel()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/download/audio.go` around lines 723 - 734, In the request loop
around api.Do(req), defer reqCancel until after the response body has been fully
consumed and closed; retain immediate cancellation on the error path, and ensure
resp.Body.Close occurs before cancellation so connections remain reusable.
internal/api/client.go (1)

154-167: 🩺 Stability & Availability | 🔴 Critical | 🏗️ Heavy lift

Fix permanent circuit breaker deadlock on probe network errors.

If a network error (err != nil from Do) or a request construction error (makeReq failure) occurs during a half-open probe, retryDo returns without updating the circuit breaker. Because Allow() sets probeInFlight = true, the breaker leaks this state and permanently deadlocks in circuitHalfOpen. All subsequent requests to this domain will be continually rejected.

Treat these probe-time failures as circuit failures so the breaker transitions back to circuitOpen and clears the probeInFlight lock.

🔒️ Proposed fix to correctly trip the breaker on probe errors
 		// 3. Build and execute the request.
 		req, err := makeReq()
 		if err != nil {
+			if cbState == circuitHalfOpen {
+				breaker.RecordFailure()
+			}
 			return nil, err
 		}
 		start := time.Now()
 		resp, err := Do(req)
 		duration := time.Since(start)
 
 		if err != nil {
 			// Network-level error: log but do NOT trip the circuit breaker.
 			// Network hiccups are distinct from the API being overloaded.
 			LogRequest(label, 0, duration, attempt, cbState.String(), err)
+			if cbState == circuitHalfOpen {
+				breaker.RecordFailure()
+			}
 			return nil, err
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/api/client.go` around lines 154 - 167, Update retryDo’s makeReq and
Do error paths to detect when the request is a half-open circuit probe and
record a circuit failure through the existing circuit-breaker failure
transition, clearing probeInFlight and returning to circuitOpen. Preserve the
current behavior for non-probe errors, including logging and returning the
original error.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Line 81: Replace the direct go build invocation in the CI build step with the
repository’s make build target. Update the Makefile build target as needed so it
consumes the matrix’s BUILD_TARGET and output-related variables while preserving
the existing cross-build artifact path and build metadata contract.

In @.github/workflows/openwiki-update.yml:
- Around line 51-52: Update the shell validation around
OPENAI_COMPATIBLE_API_KEY to emit a clear error message before exiting when the
variable is missing, while preserving the existing non-empty key validation and
set -euo pipefail behavior.

In `@cmd/nugs/main.go`:
- Around line 493-512: Propagate validation failures as non-zero CLI errors
instead of printing messages and returning nil: in cmd/nugs/main.go lines
493-512, return errors for unknown catalog actions and subcommands; at lines
348-350, 437-439, and 467-469, return errors for non-positive list/catalog
limits and missing catalog artist IDs; in cmd/nugs/watch.go lines 68-83, return
errors when watch add or remove lacks an artist ID. Anchor the changes to the
existing command dispatch and validation functions, preserving successful paths.

In `@cmd/nugs/version_test.go`:
- Around line 9-21: The TestIsVersionRequest test currently groups multiple
cases in separate loops without subtests; refactor it into one table-driven case
list containing each input and expected result, then iterate with t.Run using
descriptive case names and assert isVersionRequest against the expected value.

In `@internal/cache/atomic.go`:
- Around line 33-43: Add a parent-directory fsync in the atomic publish flow
after os.Rename in internal/cache/atomic.go:33-43, before returning success.
Also fsync the catalog-generations directory in the generation
creation/population flow before writing catalog-current.json in
internal/cache/cache.go:197-228; preserve the existing error propagation style
and publish ordering.

In `@internal/cache/cache.go`:
- Around line 236-250: The pruneCatalogGenerations implementation must not
remove generations that an unlocked reader may still reference. Synchronize
generation reads and pruning, or introduce safe deferred reclamation so a
generation remains available from resolution through artifact opening; also stop
relying on sorted MkdirTemp names to identify the previous generation.

In `@internal/cache/full_catalog.go`:
- Around line 29-46: Update ReadFullCatalogArtist and the corresponding
full-catalog write paths to avoid unmarshalling and rewriting the entire
FullCatalogIndex for each artist. Use durable per-artist records, or load the
index once and batch all artist updates within a crawl or analysis operation,
while preserving existing lookup and persistence behavior.

In `@internal/catalog/watch_systemd.go`:
- Around line 224-246: Update snapshotUnitFiles to return the captured
unitSnapshot plus an error, propagating any os.ReadFile failure instead of
recording it as missing; update restoreUnitFiles to return errors from os.Remove
and cache.WriteFileAtomic. At each caller, handle snapshot errors before
proceeding and combine any restoration error with the original operation error
during rollback.
- Around line 86-103: Update the watch installation flow around
writeWatchUnitFiles and systemctlUser to capture the timer’s prior enabled and
active state, then restore both states in rollback when daemon-reload or enable
fails; also update the removal/disable flow at internal/catalog/watch_systemd.go
lines 183-213 to restore the captured state when unit removal or daemon reload
fails. Keep unit-file restoration and existing error propagation intact.

In `@internal/catalog/watch.go`:
- Around line 207-213: Update the catalogUpdateErr branch in the WatchOutcome
error handling to use %w for catalogUpdateErr instead of %v, preserving wrapping
of both outcome and the underlying catalog update error.

In `@internal/config/config.go`:
- Around line 273-281: Update the directory sync flow around dirFile.Sync in the
config synchronization function to skip Sync on Windows while retaining the
existing sync-and-close error handling on other platforms. Ensure dirFile.Close
still runs on every platform and preserves the current error propagation
behavior.

In `@internal/download/video.go`:
- Around line 226-228: Remove the context.Background()-based wrappers
GetSegUrls, GetDuration, and TsToMp4 from internal/download/video.go, then
update every caller to invoke the corresponding context-aware functions and pass
through its existing context. Apply this change at internal/download/video.go
lines 226-228, 404-406, and 517-519; callers should no longer use the removed
legacy APIs.

In `@internal/notify/gotify.go`:
- Around line 50-54: Update the URL construction following validateServerURL so
"/message" is added to the parsed URL's Path rather than concatenated onto
base.String(). Preserve or explicitly handle the existing query and fragment
components, then serialize the modified URL for requestURL.

In `@internal/rclone/concurrency_test.go`:
- Line 18: Update both command stubs assigned to adapter.commandContext to use
their supplied ctx with exec.CommandContext(ctx, "true") instead of
exec.Command("true"), preserving the injected factory contract and eliminating
no-context command creation.

In `@internal/rclone/storage_adapter.go`:
- Around line 39-41: The rclone package must propagate caller-provided contexts
instead of creating context.Background(). In internal/rclone/storage_adapter.go
lines 39-41, remove the WithProcessSlot fallback and require a valid context; in
internal/rclone/rclone.go lines 38-45, add ctx to CheckRcloneAvailable, use it
with exec.CommandContext and WithProcessSlot, and update callers such as
cmd/nugs/rclone.go. Apply the same propagation pattern to CheckRclonePathOnline
and Upload, removing their internal background contexts and updating downstream
callers accordingly.

In `@internal/runtime/detach_unix.go`:
- Line 28: Update the log file setup around os.OpenFile to explicitly apply 0600
via logFile.Chmod after opening, including existing files; if chmod fails, close
the file and return the existing safe error path rather than continuing.

In `@README.md`:
- Around line 194-213: Add a dedicated section to README.md documenting how the
project uses the Claude API and the applicable rate-limit considerations,
including any relevant handling or constraints. Keep the existing Development
and documentation references intact.

---

Outside diff comments:
In `@cmd/nugs/main.go`:
- Around line 173-180: Update the finalization logic around runCancelled and
runErr to treat errors recognized by isCrawlCancelledErr(runErr) as cancellation
before recording failure. Ensure cancellations returned by handleCatalogGapsFill
or handleWatchCheckCommand finalize with "cancelled", while other errors
continue to finalize with "failed".

In `@internal/api/client.go`:
- Around line 154-167: Update retryDo’s makeReq and Do error paths to detect
when the request is a half-open circuit probe and record a circuit failure
through the existing circuit-breaker failure transition, clearing probeInFlight
and returning to circuitOpen. Preserve the current behavior for non-probe
errors, including logging and returning the original error.

In `@internal/download/audio.go`:
- Around line 723-734: In the request loop around api.Do(req), defer reqCancel
until after the response body has been fully consumed and closed; retain
immediate cancellation on the error path, and ensure resp.Body.Close occurs
before cancellation so connections remain reusable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5ef7441c-ebe3-4573-9d9f-9b35c929bd57

📥 Commits

Reviewing files that changed from the base of the PR and between eb7562c and 7db44e5.

⛔ Files ignored due to path filters (1)
  • tools/openwiki/package-lock.json is excluded by !**/package-lock.json and included by **/*
📒 Files selected for processing (100)
  • .github/dependabot.yml
  • .github/workflows/ci.yml
  • .github/workflows/openwiki-update.yml
  • .github/workflows/release-please.yml
  • .github/workflows/release.yml
  • CHANGELOG.md
  • CLAUDE.md
  • INCREMENTAL_CATALOG_UPDATE.md
  • Makefile
  • README.md
  • cmd/nugs/api_client.go
  • cmd/nugs/batch.go
  • cmd/nugs/cache.go
  • cmd/nugs/cancel_unix.go
  • cmd/nugs/cancel_windows.go
  • cmd/nugs/catalog_analysis_mediaaware.go
  • cmd/nugs/catalog_autorefresh.go
  • cmd/nugs/catalog_handlers.go
  • cmd/nugs/cli_integration_test.go
  • cmd/nugs/completions.go
  • cmd/nugs/config.go
  • cmd/nugs/config_ffmpeg_test.go
  • cmd/nugs/detach_common.go
  • cmd/nugs/detach_unix.go
  • cmd/nugs/detach_windows.go
  • cmd/nugs/download.go
  • cmd/nugs/filelock.go
  • cmd/nugs/format.go
  • cmd/nugs/helpers.go
  • cmd/nugs/hotkey_input.go
  • cmd/nugs/list_commands.go
  • cmd/nugs/main.go
  • cmd/nugs/main_flow_test.go
  • cmd/nugs/model_aliases.go
  • cmd/nugs/output.go
  • cmd/nugs/rclone.go
  • cmd/nugs/runtime_status.go
  • cmd/nugs/signal_persistence.go
  • cmd/nugs/structs.go
  • cmd/nugs/url_parser.go
  • cmd/nugs/version.go
  • cmd/nugs/version_test.go
  • cmd/nugs/video.go
  • cmd/nugs/watch.go
  • docs/ARCHITECTURE.md
  • docs/COMMANDS.md
  • docs/CONFIG.md
  • docs/QUICK_REFERENCE.md
  • docs/nugs-api-endpoints.md
  • docs/nugs-client-README.md
  • go.mod
  • internal/api/apilog.go
  • internal/api/apilog_test.go
  • internal/api/circuit.go
  • internal/api/circuit_test.go
  • internal/api/client.go
  • internal/cache/artist_cache.go
  • internal/cache/atomic.go
  • internal/cache/cache.go
  • internal/cache/containers_index_test.go
  • internal/cache/filelock_windows.go
  • internal/cache/full_catalog.go
  • internal/cache/regression_test.go
  • internal/cache/remediation_test.go
  • internal/catalog/catalog_update_test.go
  • internal/catalog/handlers.go
  • internal/catalog/handlers_coverage_test.go
  • internal/catalog/helpers.go
  • internal/catalog/media_filter.go
  • internal/catalog/request_budget_test.go
  • internal/catalog/watch.go
  • internal/catalog/watch_systemd.go
  • internal/catalog/watch_test.go
  • internal/config/atomic_test.go
  • internal/config/config.go
  • internal/download/audio.go
  • internal/download/batch.go
  • internal/download/deps.go
  • internal/download/deps_test.go
  • internal/download/precalculate_test.go
  • internal/download/regression_test.go
  • internal/download/video.go
  • internal/helpers/errors.go
  • internal/helpers/paths.go
  • internal/helpers/paths_security_test.go
  • internal/list/list.go
  • internal/model/constants.go
  • internal/model/progress_box.go
  • internal/model/progress_box_test.go
  • internal/model/types.go
  • internal/notify/gotify.go
  • internal/notify/gotify_security_test.go
  • internal/rclone/concurrency_test.go
  • internal/rclone/rclone.go
  • internal/rclone/storage_adapter.go
  • internal/rclone/storage_adapter_test.go
  • internal/runtime/detach_unix.go
  • internal/runtime/status.go
  • scripts/check-docs.py
  • tools/openwiki/package.json
💤 Files with no reviewable changes (2)
  • docs/nugs-client-README.md
  • internal/model/types.go

Comment thread .github/workflows/ci.yml
Comment thread .github/workflows/openwiki-update.yml Outdated
Comment thread cmd/nugs/main.go Outdated
Comment thread cmd/nugs/version_test.go
Comment thread internal/cache/atomic.go
Comment thread internal/notify/gotify.go Outdated
Comment thread internal/rclone/concurrency_test.go Outdated
Comment thread internal/rclone/storage_adapter.go
Comment thread internal/runtime/detach_unix.go Outdated
Comment thread README.md
@jmagar

jmagar commented Jul 18, 2026

Copy link
Copy Markdown
Owner Author

Final outside-diff review findings are addressed in 84c1506:

  • Runtime finalization now classifies wrapped ErrCrawlCancelled results as cancelled, including pre-dispatch handlers.
  • HEAD request contexts are cancelled only after response bodies are drained and closed; error paths still cancel immediately.
  • Regression tests cover both behaviors.

The earlier half-open circuit-breaker cleanup finding was addressed in 4fe0b71. Full verification, actionlint, zizmor, govulncheck, and go test -race -shuffle=on -count=3 ./... are green.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

return qual, isHlsOnly, qual.Format, nil

P1 Badge Honor requested audio format when TrackURL is present

When album metadata includes track.TrackURL, this fast path returns that URL immediately and never compares qual.Format with wantFmt or runs the format probing/fallback logic below. For users requesting a different audio format (-f 1, -f 2, etc.) than the metadata URL, the download uses the metadata URL's quality and merely reports a fallback even when the requested quality is available through GetStreamMeta, so normal album downloads can ignore the configured format selection.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@jmagar
jmagar merged commit 7c41fd5 into main Jul 18, 2026
9 checks passed
@jmagar jmagar mentioned this pull request Jul 18, 2026
@jmagar
jmagar deleted the codex/full-review-20260718 branch July 18, 2026 11:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant