plugins/linear-orchestrator/skills/planner-bridge/SKILL.md
This skill should be used when implementing or debugging two-way sync between Linear issues and Microsoft Planner via Microsoft Graph delta queries. Activates on "planner sync", "planner bridge", "microsoft planner", "graph delta", "tasks.readwrite".
npx skillsauth add markus41/claude Microsoft Planner ↔ Linear BridgeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Reference: https://learn.microsoft.com/en-us/graph/api/resources/planner-overview
App-only (client credentials) flow:
GRAPH_CLIENT_ID, GRAPH_CLIENT_SECRET, GRAPH_TENANT_IDhttps://login.microsoftonline.com/{tenant}/oauth2/v2.0/tokenTasks.ReadWrite.All, Group.Read.All, User.Read.All, Files.ReadWrite.All (for attachment mirror)const tokenRes = await fetch(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`, {
method: "POST",
body: new URLSearchParams({
client_id, client_secret,
grant_type: "client_credentials",
scope: "https://graph.microsoft.com/.default"
})
});
Tokens expire at 60 min; refresh proactively at 50 min.
Initial bootstrap:
GET /planner/plans/{planId}/tasks/delta
Returns first batch + @odata.nextLink (for paging) and eventually @odata.deltaLink (the cursor).
Subsequent polls:
GET <deltaLink>
Returns only changed tasks since the last call.
The bridge stores deltaLink per plan in lib/state.ts. TTL is 30 days; on expiry, full re-bootstrap.
| Planner field | Linear field |
|---------------|--------------|
| title | title |
| details.description | description (markdown) |
| bucketId | state (via bucket → state map) |
| assignments (AAD user IDs) | assignee (via email) |
| dueDateTime | dueDate |
| percentComplete | state (0=Triage, 50=In Progress, 100=Done) |
| appliedCategories | priority + first label |
| details.checklist | sub-issues (mapped 1:1) |
| details.references | attachments (link-only) |
| Linear → Planner | Planner → Linear |
|------------------|------------------|
| Webhook on Issue create/update → POST/PATCH /planner/tasks/{id} | Delta poll → GraphQL mutations |
| Webhook on Comment create → no direct equivalent; appended to task description with timestamp | Task description change → re-fetch issue, reconcile |
| Webhook on Reaction → ignored | Task appliedCategories change → label add/remove |
By email (case-insensitive). If Linear user's email isn't in AAD, the bridge:
GET /users?$filter=mail eq '[email protected]' returns the AAD user. Cache in SQLite for 24h.
Planner has no real sub-tasks. Linear sub-issues map to entries in details.checklist (max 20 per task). The bridge:
customAttributes on the Planner sideisChecked: true), transitions the corresponding Linear sub-issue to "Done"Planner has 4 priority slots (1-10 mapped to "Urgent", "Important", "Medium", "Low"). Linear's 5 levels (None, Urgent, High, Medium, Low) collapse to:
Plus an appliedCategory for color coding (red/orange/yellow/green/blue).
Planner has no cycle concept. The bridge encodes cycle membership in the task title prefix:
[Cycle: Sprint 23] Fix login bugA bridge utility re-titles tasks on cycle transitions (updateCycle webhook).
Linear projects map to Planner plans: one Linear project ↔ one Planner plan. The mapping is stored in plugin state; users configure via /linear:planner-sync map.
When a Linear issue's attachment is uploaded:
Authorization: Bearer <linear_key>)PUT /drives/{driveId}/items/{path}:contentPATCH /planner/tasks/{id}/details setting references["<onedrive-url>"]For Planner → Linear, references are link-only attachments (no byte copy).
Microsoft Graph: 600 reqs / 30s per app per tenant. Bridge implements:
Retry-After header| Failure | Behaviour |
|---------|-----------|
| Graph 401 | Refresh token; on second 401, pause bridge + alert |
| Graph 403 | Likely missing admin consent on scope; alert with required scope name |
| Graph 429 | Honor Retry-After, backoff |
| Delta token expired | Re-bootstrap (full scan) |
| AAD user not found | Skip assignment, log warning |
| Planner plan deleted | Disable mapping; preserve historic links |
@emailtools
Build Teams-native agents with the Teams SDK (formerly Teams AI Library v2) — App class, activity routing, adaptive cards, streaming, AI-generated labels, feedback, message extensions, Teams-as-MCP-server, and the bring-your-own-AI pattern with Agent Framework.
tools
Run agents on Microsoft Foundry (formerly Azure AI Foundry) Agent Service — prompt agents vs hosted agents, threads/runs and the Responses API, built-in tools (Bing grounding, code interpreter, file search, MCP, OpenAPI, A2A), connected agents, Entra agent identity, SDKs, and observability/evaluations.
tools
Build and host custom engine agents with the Microsoft 365 Agents SDK — AgentApplication, the Activity protocol, channel reach via Azure Bot Service, hosting Agent Framework or Semantic Kernel engines, and the Agents Toolkit/Playground workflow. Successor to the Bot Framework SDK.
tools
Design, govern, and extend Microsoft Copilot Studio agents — topics, generative orchestration, knowledge, tools and MCP, agent flows, autonomous triggers, publishing channels, Copilot Credits pricing, and solution-based ALM on Power Platform.