Skip to content

Set, lay out and remove a project's wallpaper - #948

Merged
robzolkos merged 6 commits into
mainfrom
project-wallpaper
Oct 24, 2026
Merged

robzolkos merged 6 commits into
mainfrom
project-wallpaper

Conversation

@robzolkos

@robzolkos robzolkos commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

What

Adds basecamp projects wallpaper set|mode|remove:

basecamp projects wallpaper set skyline.jpg --mode tile --in "<project>"
basecamp projects wallpaper mode fill --in "<project>"
basecamp projects wallpaper remove --in "<project>"
  • Upload or replace PNG, JPEG, GIF, WebP, AVIF, HEIF or HEIC files up to 10 MB. Local checks use the file size and MIME hint; the server applies its existing shared image validations.
  • Change fill/tile through project update, resending the current name as required by the SDK. Omitted upload mode preserves the current setting, including a setting saved before an image exists.
  • Remove an image idempotently. Commands return the project; .data.wallpaper is {url, mode} when attached and otherwise absent. The URL requires authentication and redirects to the image; it is not a public image link.
  • Show the wallpaper mode in Markdown/styled project details. Update skill guidance, eval coverage, API coverage and command surface.
  • People and personal assistants follow project-edit permissions; shared agents are refused.

This covers the wallpaper half of #864. Project color and logo remain out of scope.

Dependencies and rebase

Rebased onto current main, replacing the obsolete SDK feature-branch pin with released SDK v0.28.0. BC3 #14062 is merged and deployed, and SDK #1037 is merged and released.

SDK provenance, the vendored MCP model/catalog snapshot and the Nix vendor hash are refreshed. MCP exposes remove_project_wallpaper; multipart upload remains excluded like the other binary uploads.

Verification

Updated head: ea21e610.

  • Full local bin/ci passes, including unit/e2e tests, linting, surface/skill drift, SDK provenance and dependency tidiness.
  • The Nix build succeeds with the updated vendor hash.
  • Built the local CLI against published Go SDK v0.28.0 and ran 28/28 production checks on the operator-supplied test project, sequentially:
    • upload/read-back in all seven supported image formats;
    • replacements, changed attachment URLs and omitted-mode preservation;
    • explicit fill/tile, mode without an image, and the next upload retaining that mode;
    • --in/--project selection and JSON/Markdown/styled output, plus executing the advertised scoped show command and checking every wallpaper breadcrumb preserves the explicit account;
    • local argument/type/size rejections and a server 422 for SVG mislabeled as PNG, preserving the previous image;
    • removal, re-read and repeated removal.
  • Cleanup verified the original mode with an omitted-mode upload, then restored wallpaper absence and confirmed the project name was unchanged. An independent installed-CLI read also confirmed absence.
  • The new seven-format regression test fails against the old implementation for GIF, HEIF and HEIC, then passes with the fix.
  • Fixed Copilot's scope finding using the existing newFollowUpScope pattern before account resolution. Twelve regression cases cover all three wallpaper commands across configured account, active profile, explicit account override and prompted account contexts; they fail before the fix and pass afterward.
  • Addressed Copilot's macOS portability finding: the oversized BATS fixture now uses portable dd, not GNU truncate. Its targeted test passes with truncate forced unavailable. No macOS execution is claimed; the full local gate ran on Linux.

The previous description's blanket claim that every mislabeled file is rejected was incorrect: existing image identification can accept plain text named .png. This PR deliberately retains the shared server policy rather than adding a stricter decoder/format policy in the CLI.

Cubic's neutral quota result is not a substantive code review. Copilot's earlier exhausted-credit response was not a review either; it subsequently reviewed the rebased code and found the scope issue fixed above. Fresh GitHub checks/reviews are tracked on this head; this update does not merge the PR.

@robzolkos
robzolkos requested a review from a team as a code owner October 23, 2026 01:06
Copilot AI balanced review requested due to automatic review settings October 23, 2026 01:06
@github-actions github-actions Bot added commands CLI command implementations sdk SDK wrapper and provenance tests Tests (unit and e2e) skills Agent skills output Output formatting and presentation docs deps labels Oct 23, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the organization has exhausted its available GitHub AI Credits or reached a budget that stops additional usage. An organization owner can increase the applicable AI Credits budget or wait for the usage allowance to reset. Learn about budgets for usage-based billing. Review the organization's AI Credits budgets.

@jeremy

jeremy commented Oct 23, 2026

Copy link
Copy Markdown
Member

🤖 Reviewed at 53a29b6. The code is clean. CI is green apart from Copilot's check, which failed because the organization's AI credits ran out, so no bot has reviewed this PR. I checked:

  • Every local refusal happens before the upload, and the tests assert that no request was sent.
  • The type check uses the file extension, with byte sniffing as a fallback. The server's own sniffing catches a mislabeled file, as the PR says.
  • mode sends back exactly {name, wallpaper_mode}, so the description isn't touched.
  • When the read-back fails, the command reports it as a diagnostic instead of failing a change that already happened.
  • The .surface entries, the skill section, and the eval case match the commands.

What's left is the merge state, not the code:

  • It conflicts with main in go.mod, go.sum and nix/package.nix, because main has moved both the SDK and basecamp/cli pins since this branch was cut.
  • It still pins an SDK branch pseudo-version and depends on bc3#14062, so if it merged today, `set` and `remove` would call an endpoint production doesn't have yet.

I'd mark it draft until basecamp-sdk#1037 and bc3#14062 land, then re-bump, re-sync the MCP model and refresh the Nix hash, as the description already plans.

@jeremy

jeremy commented Oct 23, 2026

Copy link
Copy Markdown
Member

🤖 Local review at 53a29b6 against main, in place of the Copilot pass that didn't run: no regressions found. The wallpaper tests, the presenter and MCP suites, and the 9 project e2e tests pass. Live API smoke tests weren't run.

What the earlier comment raised still stands: the conflicts with main in go.mod, go.sum and nix/package.nix, the pinned SDK branch, and the dependency on basecamp-sdk#1037 and bc3#14062.

basecamp projects wallpaper set <file> [--mode fill|tile]
basecamp projects wallpaper mode <fill|tile>
basecamp projects wallpaper remove

The project comes from --project/--in, then the configured default, as
for other project-scoped commands; the positional slot is the file or
the mode. Before anything is sent, set refuses a file that is not PNG,
JPEG, WebP or AVIF or is over 10 MB, and both set and mode refuse a mode
other than fill or tile. The formats and the cap are named once and feed
the help and the refusals. The server sniffs the bytes and holds the
web's rules (editors only, agents refused), and its 422 or 403 comes
back as the error.

mode goes through PUT /projects/:id.json with wallpaper_mode, sending the
current name the SDK requires and nothing else. Each command answers
with the project re-read, so the output shows wallpaper {url, mode}, or
no wallpaper after remove; a failed re-read falls back with a notice,
since the change has already happened.
The skill says which commands change a wallpaper and what an agent
cannot learn from leaf help in time: an agent profile is always refused,
so retrying or reaching for basecamp api is wrong. An eval case holds
that the agent uses wallpaper set rather than projects update.

API-COVERAGE gains a BC5 projects (wallpaper) row for the two new
endpoints, and the totals move from 209 to 211.
Styled and Markdown project output listed no wallpaper, so a person
running projects show or a wallpaper command saw nothing of it. Show
the mode under Info when one is attached. The URL is a signed-in
redirect, no use to read in a terminal, so it stays in JSON only.
Copilot AI balanced review requested due to automatic review settings October 24, 2026 02:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Wallpaper follow-up commands omit the selected profile and account, so copied commands can run in the wrong environment.

1 open issue

Review effort: Balanced

Comment thread internal/commands/projects.go Outdated
Copilot AI balanced review requested due to automatic review settings October 24, 2026 03:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The new size-limit test uses truncate, which breaks the documented macOS test setup without GNU coreutils.

1 open issue
1 previously missed issue

In code that hasn't changed since last review

Medium severity Use portable dd instead of truncate for macOS e2e fixture

e2e/​projects.bats:51

This adds a truncate dependency to make test-e2e, but macOS does not provide that command and the macOS setup documented in CONTRIBUTING.md does not install GNU coreutils. On that supported setup, this test fails while creating its fixture, so bin/ci cannot pass. Create the 10 MiB + 1 byte file with portable dd instead.

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 24, 2026 03:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approved

No unresolved blocking issues remain, and the prior scope issue is addressed with regression coverage.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@robzolkos

Copy link
Copy Markdown
Collaborator Author

Update for reviewers

Rebased and pushed ea21e610. The conflicts and dependency blockers raised in the earlier review and follow-up are resolved: the API is deployed, SDK v0.28.0 is released and pinned, and provenance/MCP/Nix metadata are refreshed.

  • Full local bin/ci passes. Nix build verified with the updated vendor hash.
  • 28/28 live checks pass with the locally built CLI, including all seven image formats, replacement/mode preservation, output, scoped follow-up execution, local/server rejections and idempotent removal. Original wallpaper absence/mode restored and name unchanged; an independent installed-CLI read confirmed absence.
  • Fixed the scope finding with the shared scope helper and 12 red/green regression cases; its thread is resolved.
  • Fixed the review-body portability finding with portable dd; the targeted BATS test also passes when truncate is forced unavailable. No macOS execution is claimed.
  • Current-head GitHub results: 36/41 successful, 4 skipped, 1 neutral; no failures or pending checks. Copilot reviewed this exact head and reports no open issues. 0/1 review threads unresolved; the review-body finding is answered above. Cubic is quota-limited: its neutral check is not a substantive review.

The old blanket claim about rejecting every mislabeled file has been removed. Local checks use a MIME hint and the deployed server keeps its shared image-identification/validation policy; this change does not introduce a stricter CLI decoder.

PR remains open, mergeable and unmerged; auto-merge is off.

@robzolkos
robzolkos merged commit 5b102e4 into main Oct 24, 2026
42 checks passed
@jeremy jeremy mentioned this pull request Oct 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commands CLI command implementations deps docs output Output formatting and presentation sdk SDK wrapper and provenance skills Agent skills tests Tests (unit and e2e)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants