Skip to content

feat(forge): Linear provider (read + write, issues half) (RIG-2170) - #400

Merged
mattwilkinsonn merged 2 commits into
mainfrom
compass-server-rig-2209-linear-provider
Aug 19, 2026
Merged

feat(forge): Linear provider (read + write, issues half) (RIG-2170)#400
mattwilkinsonn merged 2 commits into
mainfrom
compass-server-rig-2209-linear-provider

Conversation

@rigel-mintaka

@rigel-mintaka rigel-mintaka commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Add go/internal/forge/linear.go: a hand-rolled net/http GraphQL client for Linear, a co-equal forge write target beside GitHub, per the frozen write-path design §5. Stdlib-only (no go-github/GraphQL library), mirroring github.go's posture and sharing its seams: a TokenSource for LINEAR_FORGE_TOKEN (DL-052), a mu-guarded fail-fast rate gate, and an injectable clock.

Linear is issues-only (DL-051): CreateIssue/CommentOnIssue/GetIssue/ListIssues implement the issues half; the PR/review family (CreatePullRequest, CommentOnPullRequest, SubmitReview, GetPullRequest, Checks) returns ErrUnsupported. repo is the Linear team key, resolved to a team UUID once and cached.

Attribution (design §5, OQ-5/OQ-8): writes set Linear's createAsUser/displayIconUrl to one constant shared Compass app identity, gated by a one-time actor-capability probe (viewer.app); a non-actor token degrades to stamp-only and emits the named log line. The fine-grained per-agent owner truth rides the Service's StampOwner header unchanged.

Rate limits map a 429 or a GraphQL RATELIMITED code to ErrBudgetExhausted with the reset instant from Retry-After / X-RateLimit-Requests-Reset; a GraphQL AUTHENTICATION_ERROR or HTTP 401 invalidates the token. 17 hermetic tests over a stubbed RoundTripper cover request goldens, team-cache, read mapping/filter/pagination, ErrUnsupported, the rate/auth/degrade paths.

Refs RIG-2209.

Co-authored-by: Matt Wilkinson matt@sealedsecurity.com

@linear-code

linear-code Bot commented Aug 19, 2026

Copy link
Copy Markdown

RIG-2170

RIG-2209

@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown

Compass engineering docs preview: https://compass-server-rig-2209-line.compass-eng-docs.pages.dev

Deployed from compass-server-rig-2209-linear-provider at 71941d7.

Base automatically changed from compass-server-rig-2208-submitreview to main August 19, 2026 03:06
Add go/internal/forge/linear.go: a hand-rolled net/http GraphQL client for Linear, a co-equal forge write target beside GitHub, per the frozen write-path design §5. Stdlib-only (no go-github/GraphQL library), mirroring github.go's posture and sharing its seams: a TokenSource for LINEAR_FORGE_TOKEN (DL-052), a mu-guarded fail-fast rate gate, and an injectable clock.

Linear is issues-only (DL-051): CreateIssue/CommentOnIssue/GetIssue/ListIssues implement the issues half; the PR/review family (CreatePullRequest, CommentOnPullRequest, SubmitReview, GetPullRequest, Checks) returns ErrUnsupported. repo is the Linear team key, resolved to a team UUID once and cached.

Attribution (design §5, OQ-5/OQ-8): writes set Linear's createAsUser/displayIconUrl to one constant shared Compass app identity, gated by a one-time actor-capability probe (viewer.app); a non-actor token degrades to stamp-only and emits the named log line. The fine-grained per-agent owner truth rides the Service's StampOwner header unchanged.

Rate limits map a 429 or a GraphQL RATELIMITED code to ErrBudgetExhausted with the reset instant from Retry-After / X-RateLimit-Requests-Reset; a GraphQL AUTHENTICATION_ERROR or HTTP 401 invalidates the token. 17 hermetic tests over a stubbed RoundTripper cover request goldens, team-cache, read mapping/filter/pagination, ErrUnsupported, the rate/auth/degrade paths.

Refs RIG-2209.

Co-authored-by: Matt Wilkinson <matt@sealedsecurity.com>
@mattwilkinsonn
mattwilkinsonn force-pushed the compass-server-rig-2209-linear-provider branch from 26370de to b8a25e8 Compare August 19, 2026 03:06
…e (RIG-2209 review)

Review M1: actorAttribution cached a TRANSIENT probe failure (a network blip, HTTP 5xx, or an already-armed rate gate) as a permanent not-capable, poisoning attribution to stamp-only for the whole process even after the token/budget recovered. The probe is meant to reflect the token's nature, not runtime state — so only cache an authoritative answer (probeErr == nil); a transient error degrades this one write and re-probes on the next.

Review M2/L2: add success-path budget-gate coverage (a 200 whose X-Ratelimit-Requests-Remaining equals the reserve arms the gate; above-reserve leaves it open) and both untested rateLimitReset branches (Retry-After HTTP-date, and the X-Ratelimit-Requests-Reset epoch-ms fallback).

Review L1: ListIssues could loop forever if Linear ever returned hasNextPage=true with an empty endCursor (advancing on an empty cursor drops the after variable and refetches page 1); terminate on a malformed page instead.

New M1 regression test is red-green verified (fails against the permanent-cache behavior, passes with the fix). All four gates green (gofmt/vet/-race/lint); 21 Linear tests pass race-clean.

Refs RIG-2209.

Co-authored-by: Matt Wilkinson <matt@sealedsecurity.com>
@mattwilkinsonn
mattwilkinsonn merged commit 068320d into main Aug 19, 2026
7 checks passed
@mattwilkinsonn
mattwilkinsonn deleted the compass-server-rig-2209-linear-provider branch August 19, 2026 03:38
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.

2 participants