| name | tracker-linear |
| description | Linear adapter for flightplan's tracker contract. Implements the canonical operations API (`fetch_issue`, `list_comments`, `post_comment`, `apply_labels`, `set_status`) by delegating to the Linear MCP. Loaded by consumer skills (`/triage`, `/diagnose`) when `.afk/config.yml` declares `tracker: linear` (the default). Not invoked directly by users — this is the adapter the rest of flightplan reads from. |
| disable-model-invocation | true |
tracker-linear — Linear adapter
Implements the tracker adapter contract
for Linear. Consumer skills load this adapter when
.afk/config.yml declares tracker: linear (or omits the field — that
defaults to linear).
All Linear operations go through the
mcp__plugin_productivity_linear__*
toolset. Never use gh or other tracker CLIs from this adapter.
Capability declaration
capabilities:
customer_field: true
project_membership: true
cycle_membership: true
team_namespace: true
active_work_detection: reliable
Consumer skills query these flags before using vendor-specific features.
Operations table
The contract floor every adapter must implement. Inputs and outputs are
the canonical shapes consumer skills expect.
| Canonical operation | Linear MCP call | Notes |
|---|
fetch_issue(id) | get_issue(id) | id accepts VA-87 style. Returns body, status, labels, project, dates. |
list_comments(id) | list_comments(issue: id) | Returns each comment with author + ISO timestamp. |
post_comment(id, body) | save_comment(issue: id, body: <body>) | Body is markdown. Always passes through verbatim — disclaimer is the consumer's responsibility. |
apply_labels(id, names) | save_issue(issue: id, labelIds: [...]) | Resolve canonical names → label IDs via list_issue_labels(team). Cache within session. |
set_status(id, name) | save_issue(issue: id, stateId: <id>) | Resolve canonical status → Linear stateId via list_issue_statuses(team). See status mapping below. |
Optional operations (consumer skills must check capability first):
| Canonical operation | Linear MCP call | Capability flag |
|---|
get_customer(id) | get_issue(id) → .customer | customer_field |
list_team_issues(team, ...) | list_issues({team, ...}) | team_namespace |
list_project_issues(project, ...) | list_issues({project, ...}) | project_membership |
list_cycle_issues(cycle, ...) | list_issues({cycle, ...}) | cycle_membership |
is_active_work(id) | inspect get_issue(id).status against the In Progress / In Review / Reviewed set | active_work_detection: reliable |
Status mapping
Canonical → Linear-native. Resolve the right side to a stateId for the
issue's team via list_issue_statuses(team); cache per session.
| Canonical (consumer-facing) | Linear status (UI / API) | Linear type |
|---|
triage | Triage | triage |
backlog | Backlog | backlog |
todo | Todo | unstarted |
in-progress | In Progress | started |
in-review | In Review | started |
reviewed | Reviewed | started |
done | Done | completed |
canceled | Canceled | canceled |
duplicate | Duplicate | canceled |
Active-work detection: any status whose type is started is treated
as active work. is_active_work(id) returns true for In Progress,
In Review, Reviewed.
Label mapping
See labels.yml — Valesco repos use canonical names
directly in Linear, so the file is essentially the identity mapping.
Per-repo override goes in .afk/tracker-labels.yml if a repo has
nonstandard label strings.
Valesco workspace teams
| Team key | Team name | Typical repos |
|---|
VA | Valescoagency | valesco-platform, flightplan, runway, ffl-live-draft, styled-by-kb, etc. |
MREG | Mill Real Estate Group | millsreg-sanity |
FMF | FMF-Website | fmf-website |
Infer the team from git remote get-url origin when possible. If
unknown, ask once and cache for the session.
The maintainer is Jason Kennemer
(jason@valescoagency.com). Other Linear users (cursor, linear)
are bots — never assign to them, never @-mention them in briefs.
ID format
Linear issue IDs are <TEAM>-<N> — e.g., VA-87, MREG-12.
The pattern ^[A-Z]{2,6}-\d+$ matches.
This is the value consumer skills (and runway, downstream) use to
identify the issue across systems.
Linear MCP cheatsheet
When implementing an operation, prefer the Linear MCP
search_documentation tool over guessing. Common entry points:
- Teams:
list_teams()
- Statuses for a team:
list_issue_statuses(team)
- Labels:
list_issue_labels(team?) — workspace-wide if team omitted
- Issues:
list_issues({team, status, label, project, ...})
- One issue:
get_issue(<id-or-key>) (accepts VA-87 style)
- Comments:
list_comments(issue) / save_comment(issue, body)
- Update:
save_issue(issue, {...})
Self-validation checks
Consumer skills should NOT need to implement these — the adapter
guarantees them. If a downstream skill catches a violation, file a bug
against this adapter.
fetch_issue returns canonical status names (mapped through the
table above), never raw Linear strings.
list_comments returns timestamps as ISO 8601, regardless of how
Linear surfaces them.
apply_labels only modifies labels that map to canonical names.
Non-canonical labels (e.g., team-specific decoration like
priority-high) are preserved on read and untouched on write.
set_status("triage") always lands the issue in the team's Triage
state, never the team's Backlog (which is a separate canonical
status).
What this adapter does NOT do
- No tracker-side knowledge of downstream pipelines (runway,
sandcastle). The adapter just exposes the canonical operations.
- No tier inference. If a project tier is needed, it's read from
.afk/config.yml, not computed from Linear project metadata.
- No HITL / runway-eligibility decisions. Those are consumer-skill
concerns, owned by
/triage.
- No PR / commit creation. Linear has issue→PR linking; this
adapter doesn't touch GitHub.
- No Linear-native features beyond the contract. Linear has rich
things (sub-issues, project updates, customer requests). The adapter
exposes only what the canonical operations need; consumer skills
don't get to use Linear-specific richness through this surface.
References