Migrate to basecamp-sdk TodoListOptions.Completed#456
Merged
Conversation
Bump basecamp-sdk to v0.7.4-0.20260423230153-f54589f0924a (merge-commit
pseudo-version; no tag past v0.7.3 yet) and migrate the CLI to its new
TodoListOptions shape. The SDK now uses Status for lifecycle only
("archived"/"trashed") and a separate Completed bool for the completion
filter; unsupported Status values ErrUsage at the wrapper boundary, and
omitting Status no longer returns all todos — it returns incomplete only.
Add resolveStatusFilter in internal/commands/todos.go to map --status
{completed,incomplete,archived,trashed} to (sdkStatus, sdkCompleted).
Thread the pair through runTodosList → listTodosInList / listAllTodos →
fetchTodosIncludingGroups; drop the old "incomplete→pending" coercion
and the cross-list client-side status filter (the server is now the
single source of truth on both paths).
In the TUI data layer, switch Hub.CompletedTodos to {Completed: true}.
Hub.Todos's empty {} now correctly returns only incomplete todos —
behavior fix: the active pool no longer leaks completed todos into the
active todos pane.
User-facing breaking change: --status pending is no longer accepted and
returns ErrUsage. Drop the dead "pending" alias from the empty-state
context switch.
Sweep WithMaxRetries(0) → (1) across test setups; the new SDK enforces
a minimum of 1 attempt (1 still means "no retries").
Review carefully before merging. Consider a major version bump. |
There was a problem hiding this comment.
Pull request overview
Migrates the CLI (and a small TUI path) to the basecamp-sdk TodoListOptions restructure by replacing legacy Status completion filtering with the new Completed flag, and updating validation + tests accordingly.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Changes:
- Bumps
github.com/basecamp/basecamp-sdk/gotov0.7.4-0...and updates provenance/go.sumaccordingly. - Updates
todos listto translate--statusinto the SDK’s(Status, Completed)pair (rejecting unsupported values likepending) and threads those options through single-list and cross-list fetch paths. - Adjusts TUI completed-todos fetch to use
Completed: true, updates empty-state messaging, and expands/rewrites todo status tests to assert query params + server-side filtering behavior.
Reviewed changes
Copilot reviewed 19 out of 20 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| skills/basecamp/SKILL.md | Updates documented --status values to include archived/trashed and drop legacy assumptions. |
| internal/version/sdk-provenance.json | Records the new SDK pseudo-version, revision, and update timestamp. |
| internal/tui/workspace/data/hub_test.go | Updates tests to comply with SDK retry minimum (WithMaxRetries(1)). |
| internal/tui/workspace/data/hub.go | Switches completed-todos listing to TodoListOptions{Completed: true}. |
| internal/tui/resolve/account_test.go | Updates tests to use WithMaxRetries(1). |
| internal/tui/empty/messages.go | Removes the dead "pending" alias from todo empty-state messaging. |
| internal/names/resolver_test.go | Updates tests to use WithMaxRetries(1). |
| internal/completion/refresh_test.go | Updates tests to use WithMaxRetries(1). |
| internal/commands/todos_test.go | Expands status filter test harness to capture query params and validates new (status, completed) behavior + usage errors. |
| internal/commands/todos.go | Adds resolveStatusFilter, threads (sdkStatus, sdkCompleted) through listing paths, and removes client-side completion filtering. |
| internal/commands/search_test.go | Updates tests to use WithMaxRetries(1). |
| internal/commands/recordings_test.go | Updates tests to use WithMaxRetries(1). |
| internal/commands/quickstart_test.go | Updates tests to use WithMaxRetries(1). |
| internal/commands/profile_test.go | Updates tests to use WithMaxRetries(1). |
| internal/commands/people_test.go | Updates tests to use WithMaxRetries(1). |
| internal/commands/messages_test.go | Updates tests to use WithMaxRetries(1). |
| internal/commands/doctor_test.go | Updates tests to use WithMaxRetries(1). |
| internal/commands/cards_test.go | Updates tests to use WithMaxRetries(1). |
| go.sum | Updates dependency checksums for the SDK bump and related transitive upgrades. |
| go.mod | Bumps SDK and a few indirect deps pulled along by the upgrade. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
Summary
basecamp-sdk PR #279 (merged 2026-04-23, unreleased — no tag past v0.7.3) restructures
TodoListOptions:Statusbecomes lifecycle-only ("archived","trashed", or empty).Completed boolfield handles the completion filter.Statusvalues are rejected at the wrapper boundary.Status: ""no longer returns all todos — it now returns incomplete only.The CLI today encodes the completion filter via
Status: "completed"/Status: "pending"and relies onStatus: ""returning all todos solistAllTodoscan filter client-side. Both assumptions break under the new SDK.This PR ships the SDK bump and the CLI migration together.
What changed
go.mod/go.sum/internal/version/sdk-provenance.jsontov0.7.4-0.20260423230153-f54589f0924a(merge-commit pseudo-version).internal/commands/todos.go— newresolveStatusFilterhelper maps--status {completed,incomplete,archived,trashed}to(sdkStatus, sdkCompleted)and rejects everything else (including legacypending) withErrUsage. Threaded the pair throughrunTodosList→listTodosInList/listAllTodos→fetchTodosIncludingGroups. Deleted theincomplete→pendingcoercion and the cross-list client-side status filter — the server is now the single source of truth on both paths.internal/tui/workspace/data/hub.go—CompletedTodosswitches to{Completed: true}. Behavior fix inHub.Todos: the empty{}now correctly returns only incomplete todos, so the active pane no longer leaks completed ones.internal/tui/empty/messages.go— drop the dead"pending"alias from the empty-state context switch.skills/basecamp/SKILL.md—--statusflag values updated to(completed/incomplete/archived/trashed).todos_test.goextendedstatusCapturingTransportto capture every/todos.jsonrequest's query params and to simulate server-side filtering. Rewrote 3 existing tests, added 8 new ones covering the matrix (single-list × cross-list × completed/archived/trashed, plus bogus andpendingrejection assertingoutput.CodeUsageandtotalCount == 0).WithMaxRetries(0) → (1)sweep — the new SDK enforces a minimum of 1 attempt;(1)still means "no retries."Breaking change
--status pendingis no longer accepted and now returnsErrUsage. This is option A from the migration handoff (droppendingas a synonym forincomplete). Option B (keeppendingas an alias mapped to the API default) is a one-line addition toresolveStatusFilter. Flag the choice if you'd prefer B before merge.Test plan
bin/cigreen (formatting, vet, lint, unit + e2e BATS, surface, skill drift, provenance, tidy)--status completed,--status archived,--status trashedall send the expected query params on both single-list and cross-list paths (covered by new tests)--status pendingand bogus values returnErrUsagebefore any HTTP firesreplacedirective ingo.mod; no legacyStatus: "completed"/Status: "pending"strings remain ininternal/./bin/basecamp tui→ project → completed-todos pane populates; active pane no longer mixes in completed todosSummary by cubic
Migrates to
github.com/basecamp/basecamp-sdk/go’s newTodoListOptions(lifecycle-onlyStatus+Completedbool) and updates CLI/TUI filtering to use the server as the source of truth. Fixes the TUI active todos pane showing completed items and rejects--status pending.Refactors
--status {completed,incomplete,archived,trashed}to(Status, Completed)via a new resolver; invalid values returnErrUsage.{Completed: true}for completed panes; empty options now return only incomplete todos.WithMaxRetries(1)per new SDK requirement; bump SDK tov0.7.4-0.20260423230153-f54589f0924a.Migration
--status pendingwith--status incomplete.completed,incomplete,archived,trashed.Written for commit 6f24cb9. Summary will update on new commits. Review in cubic