Parent epic: #3180
Goal
Implement a LinearAdapter against the ProjectTrackerAdapter interface (introduced by #3183), so repos that track work in Linear instead of (or in addition to) GitHub Projects/Milestones get the same matching/suggestion/auto-apply behavior.
Requirements
- New
autoProjectMilestoneMatchBackend: "github" | "linear" setting (default "github").
- Auth: Linear personal API key, sent as raw
Authorization: <key> header (no Bearer prefix) — simplest single-workspace model, no OAuth needed for a self-host/single-org integration. Store as a per-repo or per-org secret, never committed.
- List open projects via Linear's GraphQL
projects(filter: { status: { type: { neq: "completed" } } }).
- Prefer reading Linear's own native GitHub auto-link result where the integration is already installed on that workspace (
Issue.attachments/GitHub-link metadata) over re-deriving a match, since Linear already auto-links PRs via its branch-name (<team-key>-<number>-<slug>) and magic-word conventions (linear.app/integrations/github) — only fall back to gittensory's own tokenize/termOverlap matching when Linear's integration isn't installed on that workspace.
Issue.project / Project.issues for the project link; Issue.projectMilestone for milestone-level grouping if the repo wants milestone-equivalent granularity.
Deliverables
Expected outcome
A repo can point auto-project/milestone matching at Linear instead of GitHub Projects without any change to the matching/suggestion/auto-apply orchestration — confirms the adapter boundary was real, not just theoretical.
References
Parent epic: #3180
Goal
Implement a
LinearAdapteragainst theProjectTrackerAdapterinterface (introduced by #3183), so repos that track work in Linear instead of (or in addition to) GitHub Projects/Milestones get the same matching/suggestion/auto-apply behavior.Requirements
autoProjectMilestoneMatchBackend: "github" | "linear"setting (default"github").Authorization: <key>header (noBearerprefix) — simplest single-workspace model, no OAuth needed for a self-host/single-org integration. Store as a per-repo or per-org secret, never committed.projects(filter: { status: { type: { neq: "completed" } } }).Issue.attachments/GitHub-link metadata) over re-deriving a match, since Linear already auto-links PRs via its branch-name (<team-key>-<number>-<slug>) and magic-word conventions (linear.app/integrations/github) — only fall back to gittensory's own tokenize/termOverlap matching when Linear's integration isn't installed on that workspace.Issue.project/Project.issuesfor the project link;Issue.projectMilestonefor milestone-level grouping if the repo wants milestone-equivalent granularity.Deliverables
LinearAdapterimplementingProjectTrackerAdapter.Expected outcome
A repo can point auto-project/milestone matching at Linear instead of GitHub Projects without any change to the matching/suggestion/auto-apply orchestration — confirms the adapter boundary was real, not just theoretical.
References