Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .surface
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ CMD basecamp help
CMD basecamp lineup
CMD basecamp lineup create
CMD basecamp lineup delete
CMD basecamp lineup list
CMD basecamp lineup update
CMD basecamp login
CMD basecamp logout
Expand Down Expand Up @@ -3606,6 +3607,26 @@ FLAG basecamp lineup delete --stats type=bool
FLAG basecamp lineup delete --styled type=bool
FLAG basecamp lineup delete --todolist type=string
FLAG basecamp lineup delete --verbose type=count
FLAG basecamp lineup list --account type=string
FLAG basecamp lineup list --agent type=bool
FLAG basecamp lineup list --cache-dir type=string
FLAG basecamp lineup list --count type=bool
FLAG basecamp lineup list --hints type=bool
FLAG basecamp lineup list --ids-only type=bool
FLAG basecamp lineup list --in type=string
FLAG basecamp lineup list --jq type=string
FLAG basecamp lineup list --json type=bool
FLAG basecamp lineup list --markdown type=bool
FLAG basecamp lineup list --md type=bool
FLAG basecamp lineup list --no-hints type=bool
FLAG basecamp lineup list --no-stats type=bool
FLAG basecamp lineup list --profile type=string
FLAG basecamp lineup list --project type=string
FLAG basecamp lineup list --quiet type=bool
FLAG basecamp lineup list --stats type=bool
FLAG basecamp lineup list --styled type=bool
FLAG basecamp lineup list --todolist type=string
FLAG basecamp lineup list --verbose type=count
FLAG basecamp lineup update --account type=string
FLAG basecamp lineup update --agent type=bool
FLAG basecamp lineup update --cache-dir type=string
Expand Down Expand Up @@ -7326,6 +7347,7 @@ SUB basecamp help
SUB basecamp lineup
SUB basecamp lineup create
SUB basecamp lineup delete
SUB basecamp lineup list
SUB basecamp lineup update
SUB basecamp login
SUB basecamp logout
Expand Down
10 changes: 5 additions & 5 deletions API-COVERAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ Coverage of Basecamp 3 API endpoints. Source: [bc3-api/sections](https://github.

| Status | Sections | Endpoints |
|--------|----------|-----------|
| ✅ Implemented | 37 | 136 |
| ✅ Implemented | 37 | 137 |
| ⏭️ Out of scope | 4 | 12 |
| **Total (docs)** | **41** | **148** |
| **Total (docs)** | **41** | **149** |

**100% coverage of in-scope API** (136/136 endpoints)
**100% coverage of in-scope API** (137/137 endpoints)

Out-of-scope sections are excluded from parity totals and scripts: chatbots (different auth), legacy Clientside (deprecated)

**SDK version:** v0.4.0 — uniform pagination (Limit/Page) on all List methods; `types.FlexibleTime` and `types.FlexInt` for wire format handling.
**SDK version:** v0.6.0 — uniform pagination (Limit/Page) on all List methods; `types.FlexibleTime` and `types.FlexInt` for wire format handling.

## Coverage by Section

Expand Down Expand Up @@ -77,7 +77,7 @@ Out-of-scope sections are excluded from parity totals and scripts: chatbots (dif
| **Chatbots** |
| chatbots | 10 | - | ⏭️ | skip | Requires chatbot key, not OAuth (see notes) |
| **Lineup** |
| lineup_markers | 3 | `lineup` | ✅ | - | create, update, delete markers |
| lineup_markers | 4 | `lineup` | ✅ | - | list, create, update, delete markers |
| **Reference Only** |
| basecamps | 0 | - | - | - | Documentation reference, no endpoints |
| rich_text | 0 | - | - | - | Documentation reference, no endpoints |
Expand Down
3 changes: 3 additions & 0 deletions e2e/smoke/.qa-allowlist
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ test_timesheet_item_returns_timesheet_item_detail # timesheets not enabled — s

# Lineup API may not exist on all environments
test_lineup_create_creates_a_lineup_marker # API not available on some servers — smoke
test_lineup_list_returns_markers # API not available on some servers — smoke
test_lineup_update_updates_a_lineup_marker # depends on lineup create — smoke
test_lineup_delete_removes_a_lineup_marker # depends on lineup create — smoke

# SDK bug: TodolistOrGroup0 union type expects wrapped JSON, API returns flat
test_todolists_show_returns_todolist_detail # SDK deserialization mismatch — smoke
Expand Down
10 changes: 0 additions & 10 deletions e2e/smoke/smoke_lifecycle.bats
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,6 @@ load smoke_helper
mark_out_of_scope "Bulk completion — destructive, no undo"
}

# --- Structurally untestable (API returns 204 No Content, no ID to chain) ---

@test "lineup update is out of scope" {
mark_out_of_scope "API returns 204 No Content — no ID to chain"
}

@test "lineup delete is out of scope" {
mark_out_of_scope "API returns 204 No Content — no ID to chain"
}

# --- Code-path equivalence: docs group shares implementation with files ---

@test "docs archive is out of scope" {
Expand Down
50 changes: 44 additions & 6 deletions e2e/smoke/smoke_lineup.bats
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
#!/usr/bin/env bats
# smoke_lineup.bats - Level 1: Lineup create
#
# Note: lineup update/delete are OOS — the API returns 204 No Content
# (no ID in response), making them structurally untestable without a
# fragile list-after-create workaround. See smoke_lifecycle.bats.
# smoke_lineup.bats - Level 1: Lineup CRUD lifecycle

load smoke_helper

Expand All @@ -15,8 +11,50 @@ setup_file() {
@test "lineup create creates a lineup marker" {
local future_date
future_date=$(date -v+7d +%Y-%m-%d 2>/dev/null || date -d "+7 days" +%Y-%m-%d)
run_smoke basecamp lineup create "Smoke lineup $(date +%s)" "$future_date" --json
local marker_name="Smoke lineup $(date +%s)"
run_smoke basecamp lineup create "$marker_name" "$future_date" --json
# Lineup API may not exist on all environments (404 → validation error)
[[ "$status" -ne 0 ]] && mark_unverifiable "Lineup API not available"
assert_json_value '.ok' 'true'
echo "$marker_name" > "$BATS_FILE_TMPDIR/marker_name"
}

@test "lineup list returns markers" {
run_smoke basecamp lineup list --json
[[ "$status" -ne 0 ]] && mark_unverifiable "Lineup API not available"
assert_json_value '.ok' 'true'
}

@test "lineup update updates a lineup marker" {
local name_file="$BATS_FILE_TMPDIR/marker_name"
[[ ! -f "$name_file" ]] && mark_unverifiable "No marker created by earlier test"
local marker_name
marker_name=$(cat "$name_file")
run_smoke basecamp lineup list --json
[[ "$status" -ne 0 ]] && mark_unverifiable "Lineup API not available"
assert_json_value '.ok' 'true'
local marker_id
marker_id=$(echo "$output" | jq -r --arg name "$marker_name" '[.data[] | select(.name == $name)][0].id // empty')
[[ -z "$marker_id" ]] && mark_unverifiable "No markers found to update"
local updated_name="Updated $marker_name"
run_smoke basecamp lineup update "$marker_id" "$updated_name" --json
assert_success
assert_json_value '.ok' 'true'
echo "$updated_name" > "$BATS_FILE_TMPDIR/marker_name"
}

@test "lineup delete removes a lineup marker" {
local name_file="$BATS_FILE_TMPDIR/marker_name"
[[ ! -f "$name_file" ]] && mark_unverifiable "No marker created by earlier test"
local marker_name
marker_name=$(cat "$name_file")
run_smoke basecamp lineup list --json
[[ "$status" -ne 0 ]] && mark_unverifiable "Lineup API not available"
assert_json_value '.ok' 'true'
local marker_id
marker_id=$(echo "$output" | jq -r --arg name "$marker_name" '[.data[] | select(.name == $name)][0].id // empty')
[[ -z "$marker_id" ]] && mark_unverifiable "No markers found to delete"
run_smoke basecamp lineup delete "$marker_id" --json
assert_success
assert_json_value '.ok' 'true'
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
charm.land/bubbles/v2 v2.0.0
charm.land/bubbletea/v2 v2.0.2
charm.land/lipgloss/v2 v2.0.2
github.com/basecamp/basecamp-sdk/go v0.6.1-0.20260318221909-49475983b9c8
github.com/basecamp/basecamp-sdk/go v0.6.1-0.20260319050216-1c33ce43c305
github.com/basecamp/cli v0.1.1
github.com/charmbracelet/bubbles v1.0.0
github.com/charmbracelet/glamour v1.0.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ
github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/basecamp/basecamp-sdk/go v0.6.1-0.20260318221909-49475983b9c8 h1:WsLan1O+1GWBSQEn+dTd63roBunjojffjaoKnQ4g33U=
github.com/basecamp/basecamp-sdk/go v0.6.1-0.20260318221909-49475983b9c8/go.mod h1:g05DM58QkUm4/mvBAvRiugPw+F4trliuGkRGg8y+Th4=
github.com/basecamp/basecamp-sdk/go v0.6.1-0.20260319050216-1c33ce43c305 h1:NuMRr9mXUhSZAxxxLLfOAhiCTeYDlt/h7HaoarRLGjk=
github.com/basecamp/basecamp-sdk/go v0.6.1-0.20260319050216-1c33ce43c305/go.mod h1:g05DM58QkUm4/mvBAvRiugPw+F4trliuGkRGg8y+Th4=
github.com/basecamp/cli v0.1.1 h1:FAF3M09xo1m7gJJXf38glCkT50ZUuvz+31f+c3R3zcc=
github.com/basecamp/cli v0.1.1/go.mod h1:NTHe+keCTGI2qM5sMXdkUN0QgU3zGbwnBxcmg8vD5QU=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func CommandCategories() []CommandCategory {
{Name: "people", Category: "organization", Description: "Manage people and access", Actions: []string{"list", "show", "pingable", "add", "remove"}},
{Name: "templates", Category: "organization", Description: "Manage project templates", Actions: []string{"list", "show", "create", "update", "delete", "construct"}},
{Name: "webhooks", Category: "organization", Description: "Manage webhooks", Actions: []string{"list", "show", "create", "update", "delete"}},
{Name: "lineup", Category: "organization", Description: "Manage lineup markers", Actions: []string{"create", "update", "delete"}},
{Name: "lineup", Category: "organization", Description: "Manage lineup markers", Actions: []string{"list", "create", "update", "delete"}},
},
},
{
Expand Down
31 changes: 31 additions & 0 deletions internal/commands/lineup.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ They apply to the entire Basecamp account.`,
}

cmd.AddCommand(
newLineupListCmd(),
newLineupCreateCmd(),
newLineupUpdateCmd(),
newLineupDeleteCmd(),
Expand All @@ -37,6 +38,36 @@ They apply to the entire Basecamp account.`,
return cmd
}

func newLineupListCmd() *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "List lineup markers",
RunE: func(cmd *cobra.Command, args []string) error {
app := appctx.FromContext(cmd.Context())

if err := ensureAccount(cmd, app); err != nil {
return err
}

result, err := app.Account().Lineup().ListMarkers(cmd.Context())
if err != nil {
return convertSDKError(err)
}

return app.OK(result.Markers,
output.WithSummary(fmt.Sprintf("%d lineup markers", len(result.Markers))),
output.WithBreadcrumbs(
output.Breadcrumb{
Action: "create",
Cmd: "basecamp lineup create <name> <date>",
Description: "Create new marker",
},
),
)
},
}
}

func newLineupCreateCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create <name> <date>",
Expand Down
6 changes: 3 additions & 3 deletions internal/version/sdk-provenance.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"sdk": {
"module": "github.com/basecamp/basecamp-sdk/go",
"version": "v0.6.1-0.20260318221909-49475983b9c8",
"revision": "49475983b9c8",
"updated_at": "2026-03-18T22:19:09Z"
"version": "v0.6.1-0.20260319050216-1c33ce43c305",
"revision": "1c33ce43c305",
"updated_at": "2026-03-19T05:02:16Z"
},
"api": {
"repo": "basecamp/bc3",
Expand Down
1 change: 1 addition & 0 deletions skills/basecamp/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ basecamp subscriptions remove <id> --people 1,2,3 # Remove people
### Lineup (Account-wide Markers)

```bash
basecamp lineup list # List all markers
basecamp lineup create "Milestone" "2024-03-15" # Create marker
basecamp lineup create "Launch" tomorrow # Natural date parsing
basecamp lineup update <id> "New Name" "+7"
Expand Down
Loading