Skip to content

GH-92: feat(linear): implement SyncCapable — cursor-followed delta, taxonomy StateGroup, field writes#94

Merged
alekspetrov merged 1 commit into
mainfrom
pilot/GH-92
Jul 13, 2026
Merged

GH-92: feat(linear): implement SyncCapable — cursor-followed delta, taxonomy StateGroup, field writes#94
alekspetrov merged 1 commit into
mainfrom
pilot/GH-92

Conversation

@alekspetrov

Copy link
Copy Markdown
Contributor

Summary

Automated PR created by Pilot for task GH-92.

Closes #92

Changes

GitHub Issue GH-92: feat(linear): implement SyncCapable — cursor-followed delta, taxonomy StateGroup, field writes

Context

SaaS pre-work S0.9. Implements the #83 SyncCapable contract for Linear, building on the cursor/delta work.

Depends on: #85

Implementation

In sdk/integrations/linear, implement core.SyncCapable:

  • ListUpdatedSince/ListAll: the fix(linear): follow GraphQL cursors past first:50 + add updatedAt delta filter #85 cursor-followed queries; map to IssueSnapshot (State = workflow state name; StateGroup = workflow state type — backlog/unstarted/started/completed/canceled; SequenceID = the PROJ-42 identifier; Priority via core.NormalizePriority).
  • GetIssue by Linear issue id.
  • UpdateFields: GraphQL issueUpdate for title/description/labels/priority.
  • TransitionState: existing UpdateIssueState (target = workflow state id/name).
  • AddComment with <!-- pilot-op:{idemKey} --> marker idempotency (scan before repost).
  • CreateIssue from IssueDraft (team derived from projectID param).

Acceptance

  • SyncCapable conformance compile check
  • Mocked GraphQL tests: snapshot mapping incl. StateGroup taxonomy; delta filter; idempotent comment; UpdateFields
  • Existing poller behavior unchanged

Refs

Adds SyncAdapter, a *Client-backed implementation of core.SyncCapable
(SyncSource + SyncWriter) for board sync: ListUpdatedSince/ListAll follow
the #85 cursor convention page-by-page and map to core.IssueSnapshot with
StateGroup carrying Linear's workflow-state type (backlog/unstarted/
started/completed/canceled); GetIssue, UpdateFields (title/description/
labels/priority via issueUpdate), TransitionState (existing
UpdateIssueState), AddComment (idempotent via a pilot-op:{idemKey} HTML
marker scanned before reposting), and CreateIssue (team resolved from the
projectID team-key param) round out the contract.

Also adds the "url" field to Issue/issueListItem and their GraphQL
selections, needed to populate IssueSnapshot.URL.
@alekspetrov
alekspetrov merged commit ccb4517 into main Jul 13, 2026
3 checks passed
@alekspetrov
alekspetrov deleted the pilot/GH-92 branch July 13, 2026 18:39
alekspetrov added a commit that referenced this pull request Jul 13, 2026
…ated idem comment scan, on-or-after delta (post-merge review of #94) (#99)

Post-merge review of #94 found four defects in sdk/integrations/linear/sync.go:
TransitionState sent a state NAME straight through as a GraphQL stateId
(round-trip broken); AddComment's idempotency scan only checked the first
comments page, letting retries duplicate-post once a marker fell off page 1;
ListUpdatedSince used gt+second-truncated timestamps, silently dropping issues
updated exactly at the watermark; and UpdateFields silently ignored unknown
keys and wrongly-typed values instead of rejecting the patch.
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.

feat(linear): implement SyncCapable — cursor-followed delta, taxonomy StateGroup, field writes

1 participant