Repository navigation
Conversation
There was a problem hiding this comment.
All reported issues were addressed across 21 files
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
There was a problem hiding this comment.
🟢 Approved
No active review issues block the opt-in conflict-check changes.
No open issues 🎉
What changed in this PR
Adds opt-in conflict checks to supported Basecamp CLI replacement commands, using the caller’s saved updated_at timestamp to detect intervening edits before uploads or writes. Protection remains optional and non-atomic; Boost editing is unchanged.
Changes:
- Adds shared
--if-unmodified-sincevalidation and a--forceoverride for timestamp mismatches only. - Integrates checks across supported update commands, with regression tests and a comments smoke test.
- Documents coverage and limitations, updates agent guidance, and refreshes the CLI surface snapshot.
[!TIP]
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or rungh pr ready --undo.
Click "Ready for review" or rungh pr readyto reengage.
| File | Description |
|---|---|
skills/basecamp/SKILL.md |
Guides agents to retain timestamps and use guarded replacements. |
internal/commands/todos.go |
Guards to-do updates before edit processing. |
internal/commands/todolists.go |
Adds version checks to to-do list updates. |
internal/commands/timesheet_entries.go |
Guards timesheet entry updates. |
internal/commands/templates.go |
Adds version checks to template updates. |
internal/commands/schedule.go |
Guards schedule updates before attachment processing. |
internal/commands/projects.go |
Adds version checks to project updates. |
internal/commands/notes.go |
Guards note replacement, including missing-version handling. |
internal/commands/messages.go |
Adds version checks to message updates. |
internal/commands/gauges.go |
Guards gauge needle description updates. |
internal/commands/files.go |
Guards file replacement and document, upload, and vault updates. |
internal/commands/doors.go |
Adds version checks to Door updates. |
internal/commands/comment.go |
Guards comment replacement before content processing. |
internal/commands/checkins.go |
Guards check-in answer updates before image processing. |
internal/commands/chat.go |
Adds version checks to chat line updates. |
internal/commands/cards.go |
Guards card updates before mutation preparation. |
internal/commands/body_guard.go |
Implements shared flags, timestamp validation, and conflict checks. |
internal/commands/body_guard_test.go |
Covers refusals, overrides, matching timestamps, and exclusions. |
e2e/smoke/smoke_comments.bats |
Exercises matching updates, stale refusal, and explicit override. |
docs/body-conflict-guard.md |
Documents usage, exact coverage, and safety limitations. |
.surface |
Records guard flags on supported commands and aliases. |
Review effort: Balanced
|
🤖 Review follow-up on
Full local |
What
Adds optional
--if-unmodified-since <updated_at>and explicit--forceconflict override to the supported typed replacement commands. The caller must retain the timestamp from the representation used to prepare the edit. A server-revalidated GET requires equal parsed timestamp instants before uploads or writes; failed reads and missing, zero or invalid timestamps refuse even with force.Coverage: comments, messages, to-dos, cards, to-do lists, schedule entries, check-in answers, chat lines, documents/uploads/vaults, file replacement, Doors, projects, templates, notes, gauges and timesheet entries. See exact coverage and limitations.
Boost editing is explicitly excluded and unchanged. Its supported API/SDK representation has no
updated_atbaseline. Creation time, a parent timestamp and ETags are not substituted.Limits
Verification
mise exec golangci-lint@2.15.0 ruby@3.4.12 -- bin/ci, including Go regression and BATS integration suites. Zizmor ran in its default offline mode; platform/credential helper skips are not live-platform coverage.Safe reproduction
On a disposable record you own, read and keep its
updated_at, make an intervening edit, then try a replacement with the older timestamp:The command must refuse with a conflict and leave the record unchanged. Re-fetch, reconcile and use the timestamp belonging to the reconciled edit for a matching update. Only use
--forcedeliberately to overwrite a mismatch; it does not waive prerequisites.No production/beta validation, merge, release or deployment is claimed.
Summary by cubic
Adds an opt-in conflict guard to typed replacement commands so callers can refuse to overwrite records edited since their last read. When
--if-unmodified-since <updated_at>is set, the CLI runs a server-revalidated GET and requires the liveupdated_atto parse to the same instant before writing;--forceoverrides a version mismatch, while failed reads and missing, zero, or invalid timestamps refuse even with force.The guard covers comments, messages, todos and to-do lists, cards, schedule entries, check-in answers, chat lines, files/documents/uploads/vaults (including the
file,docs,documents,vault, andfoldersaliases), Doors, projects, templates, notes, gauges, and timesheet entries, and checks the whole record rather than only body edits. User and agent guidance now instructs reading the record'supdated_atand passing it unchanged as the baseline.Limits
--forcerequires a baseline and does not waive invalid input or unavailable live state.updated_at.Written for commit 36d89ea. Summary will update on new commits.