work-items-to-linear
Turn a work-items.md file (produced by /plan-work-items) into Linear issues, one per slice, in a single target Linear team. Use when you want to publish work items as Linear issues, create implementation tickets to track in Linear, or push a broken-down plan into a Linear team. R
Install
npx skills add https://github.com/testdouble/han/tree/main/han-linear/skills/work-items-to-linear
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install testdouble-han@llmmart
git clone https://github.com/testdouble/han.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole testdouble/han collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Project Context
- personal config directory: !
bash "${CLAUDE_PLUGIN_ROOT}/scripts/han-config-dir.sh" 2>/dev/null || echo "$HOME/.claude" - project .han/config.md: !
cat .han/config.md 2>/dev/null || echo ""
As your first action, use the Read tool on .han/config.md inside the personal config directory path above. A read
that returns no file is no personal configuration: continue silently. When that file or the project .han/config.md
probe supplies content, apply it per config-rule.md, which governs precedence
between the two files, relative-path resolution, and what to do with a file that reads but cannot be used.
Work Items to Linear Issues
Take an already-broken-down work-items.md file (produced by /plan-work-items) and publish each slice as a Linear
issue in a single target team.
The breakdown work — drafting slices, assigning symbolic IDs, specifying dependencies, inventorying references — has already been done upstream. This skill validates the format, confirms the target against the live team, creates one issue per slice through the Linear MCP server, links the within-file dependencies as native "blocked by" relations, and reports.
Rules
- Every slice posts into one Linear team. This skill does not split work across teams or repos. A
work-items.mdthat names multiple code repos still produces issues in the single team you name; the repo prose is informational only. - Dependencies are within-file only. Every SYM named in a
Depends online must resolve to another slice in the same file. ADepends onthat names an unknown SYM, names the slice itself, or forms a cycle is a format error to surface for repair, never published. - Symbolic-ID prefixes: accept whatever the input uses. Any uppercase prefix shape is valid (
W-N,V2-N,EV-N, ...); the prefix has no effect on team placement. - Resolve against the live team before writing. Read the team's real workflow states, labels, Projects, and members, and resolve every named option against them before creating any issue. Nothing is assigned, categorized, grouped, or moved unless asked.
- No issue types. Linear has no issue-type concept. The skill never asks for or sets one. Categorization is via the team's real labels, chosen by the user.
- Every slice issue MUST carry the reference artifacts an implementer needs — API/event contracts, design references, schema docs, runbooks, ADRs, coding standards. Full include/exclude list in references/reference-artifact-inventory.md.
- NEVER include process artifacts in issue descriptions. Excluded: iteration histories, decision logs, review
findings, team findings, facilitation summaries, gap analyses, and anything under an
artifacts/subfolder of the plan that is not a contract or design reference. - No image upload or embedding. Design references are carried as links, not uploaded into Linear. See references/linear-issue-template.md.
Process
0. Linear MCP preflight (hard requirement)
This skill cannot run without a configured and connected Linear MCP server. Confirm it is reachable by calling
mcp__plugin_linear_linear__list_teams. If the tool is unavailable, the call errors, or no workspace is accessible,
stop immediately and tell the user the skill requires the Linear MCP server to be installed, configured, and
authenticated. Do not fall back to any other publishing target.
If the integration exposes more than one Linear workspace, note which are available and confirm which one to use before resolving the team.
1. Locate the work-items file
If the path is not provided, ask for it. The input is a single work-items.md produced by /plan-work-items. Read it.
Its format is described in references/work-items-file-format.md.
2. Gather the run options
Read these from the arguments and conversation; do not guess defaults the user did not ask for:
- Target team —
--team <name or key>. Required. If absent, ask for it in Step 3. - Project —
--project <name or ID>. Optional. Groups every created issue under a Linear Project. - Parent —
--parent <issue id>. Optional. Nests every created issue as a sub-issue under the named parent. - State —
--state <name>. Optional; defaults to the team's initial/default workflow state. - Labels —
--label <name>, repeatable. Optional; resolved against the team's real labels. - Assignee —
--assignee <name/email/me>. Optional; defaults to unassigned.
3. Resolve the target against the live team
Resolve everything concretely now so failures surface before any issue is created. This is a strict, fail-before-write sequence:
- Team (required). Confirm the named team with
mcp__plugin_linear_linear__list_teams. If none is named, ask. If the name matches more than one team, present the matches and ask which one. Do not proceed without exactly one team. - Read the team's configuration with
mcp__plugin_linear_linear__list_issue_statuses,mcp__plugin_linear_linear__list_issue_labels, andmcp__plugin_linear_linear__list_users. These reads are independent and may run together. - State. If
--statewas given, match it against the team's real states. The default is the team's initial/default state. If a named state does not exist, present the team's real states and ask. - Labels. If
--labels were given, match each against the team's labels. When categorization was not specified, present the team's real labels and let the user choose one, several, or none. If the team defines no labels, say so and proceed without categorization. - Assignee. If named, resolve it with
mcp__plugin_linear_linear__get_user: the literal tokenmeresolves to the authenticated Linear identity, and a name or email resolves to that member. If unset, leave issues unassigned. The creator is recorded automatically by Linear as the authenticated user; never set it. - Project (optional). Resolve a named Project at workspace scope with
mcp__plugin_linear_linear__list_projects(Projects are not strictly team-scoped), and confirm the target team participates in it. - Parent (optional). Resolve a named parent issue with
mcp__plugin_linear_linear__get_issueand confirm it belongs to the target team.
For any option that cannot be resolved, do not silently drop or invent it. Distinguish "no such option exists in the team" (present the team's real options for that field) from "it exists but belongs to a different team" (name that team). Ask the user to pick or correct before continuing.
4. Validate the format with evidence-based repair
Check the work-items file against the invariants in references/work-items-file-format.md and references/linear-issue-template.md:
- Heading shape. Every slice heading matches
## <SYM-N> — <title>with an em-dash separator (already-published headings annotated as## <SYM-N> (<LINEAR-ID>) — <title>are valid too). Depends online. Literal bold marker**Depends on.**, trailing period,None.or comma-separated SYMs.- Within-file blockers. Every SYM named in a
Depends online resolves to another slice in this file. A SYM that names the slice itself (self-block) or that forms a dependency cycle with other slices is a format error. - References block. Present whenever the slice consumes an HTTP endpoint, event payload, design frame, ADR, coding standard, or other named artifact.
- No process artifacts. No links to iteration histories, decision logs, review findings, team findings, facilitation
summaries, gap analyses, or anything under an
artifacts/subfolder that is not a contract or design reference.
When a check fails, attempt evidence-based repair. Pull evidence from the source work-items.md, the parent plan
referenced in its intro, the feature spec in the same folder, sibling files in the plan folder, and the relevant repo's
ADRs / coding standards / docs:
- Malformed heading — propose the corrected shape based on surrounding text. Cite the line number.
- Missing
Depends online — proposeNone.if no blockers are evident. Cite the absence. - Unknown-SYM, self-block, or cycle — propose the correct in-file SYM (if a typo is evident), or
None., or breaking the cycle. Cite the SYM list this file defines. - Missing References bullet for an HTTP-consuming or UI slice — propose the contract section or design frame from the parent plan or feature spec. Cite the anchor.
- Process-artifact link found — propose removing the link and, if the slice still needs the context, restating the decision in plain language with a Plan decisions References bullet naming the ID plus a one-sentence description. Cite the include/exclude list.
After validation, report findings in plain language. For each: (1) what is wrong — slice SYM, line reference, failing invariant; (2) the proposed fill — corrected line, new bullet, removed link; (3) the evidence — file path with line number, document section, or named source.
Then give the user three actions: Continue with fills (apply the repairs to the source work-items.md and proceed),
Correct the fills (user provides the right values; apply those and proceed), or Stop (exit without creating
issues). If validation passes with no findings, proceed to Step 5.
5. Show the plan for confirmation
Creating Linear issues writes to a shared system, so confirm before doing it. Present a summary and wait for an explicit yes:
- Destination: the Linear workspace, the target team, the Project (if any), the parent (if any, and that each item becomes a sub-issue under it), the workflow state, the labels (or "none"), and the assignee (or "unassigned").
- The issues to create: a table, in file order, of every slice that does not already carry a
(<LINEAR-ID>)annotation.
| SYM | Title | Depends on |
|---|---|---|
| W-1 | ... | None |
| W-2 | ... | W-1 |
State the total count of issues to create and how many slices are being skipped because they already carry an identifier. Do not create anything until the user confirms.
6. Create one issue per slice
Walk the slices in file order. Skip any slice whose heading already carries a (<LINEAR-ID>) annotation so a re-run
resumes cleanly. Creation order does not affect correctness, because dependency relations are made in Step 7 once every
issue exists. For each remaining slice, call mcp__plugin_linear_linear__save_issue with:
- team = the resolved team,
- title = the slice title (the text after
—in the heading), - description = the rendered slice body (Summary, Description, any notes, References, Tests, Acceptance criteria) as Markdown, passed through without conversion,
- state, labels, assignee, parentId, project = the values resolved in Step 3, applied as chosen,
- never
blockedByhere — relations are made in Step 7.
After each successful create, capture the returned Linear identifier and rewrite that slice's heading in place from
## <SYM-N> — <title> to ## <SYM-N> (<LINEAR-ID>) — <title> using Edit, so dependencies resolve and re-runs skip it.
Report each creation as created: <SYM-N> -> <LINEAR-ID>.
If a create succeeds but the heading annotation fails, stop. Report the orphaned Linear identifier so the user can annotate the heading by hand or delete the issue. Do not continue creating, and do not run the link pass — the file state is inconsistent until the user resolves it.
7. Link dependencies as native relations
Once every slice has a Linear identifier, build the SYM-to-identifier map from the annotated headings. This pass runs over the whole annotated file on every run (including identifiers carried over from a prior run), not only over newly created issues, so a link step interrupted earlier completes on the next run.
Relations are made after all issues exist because a blocked by relation needs both endpoints to exist, and file order
is not guaranteed to be blocker-first.
- Stale-annotation check. For each unique identifier in the map, confirm it resolves to an accessible issue in the
team with
mcp__plugin_linear_linear__get_issue. Surface any that do not resolve to the user before making any relation; never link to a missing or wrong issue. - Make the relations. For each slice's
**Depends on.**line (skipNone.), callmcp__plugin_linear_linear__save_issueon the dependent issue withblockedByset to each blocker's identifier. Relations are append-only and de-duplicated, so a re-run does not duplicate them; no per-relation pre-read is needed.
Report each as linked: <SYM-A>(<LINEAR-A>) blocked_by <SYM-B>(<LINEAR-B>).
8. Report
Summarize: the team, the Project and parent (if any), the workflow state, the labels and assignee (or "none" /
"unassigned"). List every created issue as <SYM-N> — <LINEAR-ID> with its URL, the count of native "blocked by"
relations created, and any slices skipped because they already carried an identifier. If any step failed, report the
error and confirm the source work-items.md annotations reflect exactly which issues were created, so the user can
re-run safely.
Files (han)
-
references
-
linear-issue-template.md 5.3 KB
# Slice issue format > Each slice in a `work-items.md` file follows this format. The skill's validation step checks it, and the create step > maps each field onto a Linear issue. This is the same slice format `/plan-work-items` emits; the mapping to Linear > fields is documented below. The format is what `/plan-work-items` emits. Required fields appear in the order shown. The `**References.**` block is required whenever the slice consumes any external artifact (HTTP endpoint, event payload, design frame, ADR, coding standard). Additional `**Bold paragraph.**` context blocks are allowed between required fields. ``` ## <SYM-N> — <short descriptive name> **Summary.** Three to five very short, plain-language sentences stating why the work is needed and what is being done. No technical detail and no ID references — plan references live in the References block, each with a one-sentence description. **Work to be done.** - Plain-language bullets stating the actual work, one to two short sentences each, every bullet supporting an acceptance criterion below. - Technical detail, when needed, nests under the plain-language bullet it belongs to: starting points (a file path, a contract, a boundary), never a prescribed edit list or implementation code. **References.** - **Plan decisions** — every plan decision or work unit this slice satisfies, one bullet each: the ID as a link (e.g., `[D-6](feature-implementation-plan.md#d-6-...)`) followed by one short plain sentence saying what it is. Never a bare ID list. Replaces any inline `See plan: ...` reference. - **API contract** — `[<file>#<anchor>](<relative-path>)`. Required when the slice produces or consumes an HTTP endpoint. - **Event contract** — `[<file>#<event-section>](<relative-path>)`. Required when the slice produces or consumes an event payload. - **Design** — design document path plus frame IDs. Carried as a link in the issue description; this skill does not upload or embed images into Linear (see "Design and images" below). - **Spec section** — `[feature-specification.md#<anchor>](feature-specification.md#<anchor>)` for the behavior this slice realizes. - **ADR / standard / repo doc** — links the implementer must honor. **Acceptance criteria.** - [ ] Each criterion is an observable, verifiable outcome of this slice's own behavior. Test expectations live here. Never standard operating procedure (commit pushed, CI green, PR opened), and never a prohibition without its validated reason stated alongside it. **Depends on.** `<SYM-N>` (within this file), comma-separated for multiple, or `None.` ``` ## Mapping a slice onto a Linear issue When the skill creates an issue for a slice, it maps the slice fields like this: - **Title (Linear) <- slice title.** The text after `— ` in the `## <SYM-N> — <title>` heading becomes the issue title. The `<SYM-N>` symbolic ID is not part of the title; it is preserved only in the source work-items file's heading annotation. - **Description (Linear) <- the entire slice body.** Everything below the heading (Summary, Work to be done, optional notes, References, Acceptance criteria) is rendered into the issue description and passed as **Markdown with no format conversion** (Linear accepts Markdown directly). - **Team <- the required target team.** Every slice posts into the one team you name. The skill resolves the team against the workspace before any create. - **Workflow state <- the team's initial state by default.** The skill defaults to the team's own default/initial state and applies a `--state` override only when given, resolved against the team's real workflow states. - **Labels <- discovery.** The skill never assumes a label exists. When categorization is not specified up front, it presents the team's real labels and lets the user choose, or proceed without one. Linear has no issue-type concept, so the skill never asks for or sets one. - **Parent issue <- optional sub-issue nesting.** A named parent issue (resolved against the target team) nests each created issue as a sub-issue. - **Project <- optional grouping.** A named Linear Project (resolved at workspace scope, confirming the target team participates) groups the created issues. - **Assignee <- none by default.** Set only when the user names one, resolved against the team's members. - **Creator <- the Linear MCP identity.** The skill never sets the creator; Linear records the authenticated user automatically. ## Dependencies (`**Depends on.**`) After every slice's issue exists and the SYM-to-identifier map is known, the skill resolves each `Depends on` line by creating a **native Linear "blocked by" relation** from the dependent issue to each blocker. Linear relations are reliably native, so no description rewrite is needed. Relations are append-only and de-duplicated, so a re-run does not create duplicates. Every SYM in a `Depends on` line must resolve to another slice in the same file; an unknown SYM is a format error to surface for repair, not a silent skip. ## Design and images This skill does not upload attachments to or embed images in Linear issues. For UI-bearing slices, the design reference (document path, frame IDs, any design-tool URL) is carried as a link in the issue's references. If a slice's design must be visible inside the issue, add the attachment in Linear by hand after the issue is created. -
reference-artifact-inventory.md 4.3 KB
# Reference artifact inventory The breakdown work upstream (`/plan-work-items`) inventories artifacts and embeds them in each slice's `**References.**` block. This skill's job is to **verify** those references are complete and correct before creating Linear issues, and to propose evidence-based fills when they are not. This file defines what belongs in slice References blocks (the include list), what never belongs (the exclude list), and how validation reasons about both. ## Include (these belong in slice References blocks and/or the source file's Shared reference artifacts) - **HTTP API contract files** and the specific endpoint sections that slices produce or consume. - **Event payload contract files** and the specific event sections. - **Feature specification** (`feature-specification.md`) — sections that define the behavior a slice realizes. - **Design assets** — design document paths plus specific frame IDs, design-tool URLs, mockup PDFs. Carried into the issue as links. This skill does not upload or embed images into Linear; the design reference is a link the implementer follows. - **Schema / migration references** when a slice depends on a not-yet-shipped schema. - **ADRs**, coding standards, and feature documentation that constrain the slice's implementation. - **Runbook skeletons or observability notes** when a slice's acceptance criteria require them. ## Exclude (these never belong in slice References blocks or the Shared reference artifacts section) - Iteration histories (`*-iteration-history.md`, `.evidence-roundN.md`, etc.) - Decision logs (`decision-log.md`, `implementation-decision-log.md`) - Review findings (`review-findings.md`, `implementation-review-findings.md`) - Team findings, facilitation summaries, gap analyses, security/UX round notes - Anything under an `artifacts/` subfolder of the plan **unless** it is a contract or design reference. These record how the plan was reached, not what the implementer needs to build. Plan-level decisions that survive into a slice are restated in plain language in the slice description, and cited in the slice's `**References.**` block as the decision ID plus a one-sentence description of what it is — never an inline ID-only breadcrumb, and never a link to the decision log itself. If validation finds a process-artifact link in a slice, the proposed repair is to remove the link and, when the context it held is load-bearing, restate the decision in plain language with a **Plan decisions** References bullet. ## Where each artifact should be cited - When a single artifact applies to **many slices**, it appears once in the source file's **Shared reference artifacts** section. Slices reference it by anchor instead of duplicating. - When an artifact applies to **a single slice**, it appears inline in that slice's `**References.**` block. ## What validation checks For each slice: - If the slice produces or consumes an HTTP endpoint, an **API contract** bullet must be present in `**References.**`. - If the slice produces or consumes an event payload, an **Event contract** bullet must be present. - If the slice has a UI surface, a **Design** bullet should be present (a link/path plus frame IDs). - A **Spec section** bullet should be present whenever the slice realizes a named behavior from the feature spec. - No process-artifact link is present anywhere in the slice body. ## Missing-artifact handling (evidence-based repair) When validation finds a missing or excluded artifact: - **Missing API contract link** — propose the parent plan's External Interfaces / API Contracts section by path and anchor, evidenced by the section's existence. - **Missing event contract link** — propose the parent plan's events section, evidenced by its existence. - **Missing Design link** — inspect the feature spec's Visual Reference table and inline design references; propose the design frame IDs and document path, cited by spec section. - **Process-artifact link found** — propose removal, evidenced by the exclude list above. If load-bearing, propose a plain-language restatement with a **Plan decisions** References bullet (ID plus a one-sentence description). Every proposed fill cites a concrete source: a file path with line number, a document section, or a named source. Fills without evidence are surfaced as gaps for the user to resolve, not silently applied. -
work-items-file-format.md 3.9 KB
# Work-items file format > This file describes the format the skill **reads** from `/plan-work-items`. Like the Jira `work-items-to-jira` skill, > this skill does **not** write per-repo split files: every slice becomes a Linear issue in a single target team, so > there is one input file and no derived files. There is one file shape to know: - **Source `work-items.md`** — one file emitted by `/plan-work-items`, covering every slice in the plan. The skill reads it, creates one Linear issue per slice, and annotates each slice heading in place with the created issue's identifier. ## Source file shape (input) The source file lives next to its parent plan (typically `<feature>/<phase>/work-items.md`) and contains, in order: ### 1. Title ``` # Work Items — <feature or phase name> ``` ### 2. Intro paragraph Links the parent implementation plan and feature spec, and notes that work-item SYMs are for cross-reference only. ### 3. Cross-repo work order prose _(may be present; informational only)_ A file spanning more than one code repo may name which SYMs ship to which repo. **This skill ignores the repo split for placement** — every slice posts into the one Linear team you name. The prose is carried into issue context where it clarifies ordering, but it never changes which team an issue lands in. ### 4. Shared reference artifacts _(required when an artifact applies to more than one slice)_ A flat list of artifacts more than one slice references — API contract sections, spec sections, schema docs, ADRs, coding standards. Each entry is a relative link plus the anchor or path an implementer jumps to. These are carried into each issue's references as links. ### 5. Slices One slice per `## <SYM-N> — <title>` heading. Slice bodies follow [linear-issue-template.md](linear-issue-template.md). Slices may appear in any order; the skill preserves source order. Creation order does not affect correctness, because dependency relations are made in a separate pass once every issue exists. ## Symbolic-ID prefixes Both shapes are valid input: - **Single prefix across the plan.** Every slice uses `W-N` (or any single prefix). This is what `/plan-work-items` currently emits. - **Per-area prefixes.** Different prefixes (`V2-N` backend, `W-N` frontend, `EV-N` events) are accepted as-is. They have no effect on team placement. The skill reads any `[A-Z][A-Z0-9]*-[0-9]+` heading. ## Heading annotation after creation After a slice's Linear issue is created, the skill rewrites that slice's heading in place from: ``` ## <SYM-N> — <title> ``` to: ``` ## <SYM-N> (<LINEAR-ID>) — <title> ``` The `(<LINEAR-ID>)` annotation (for example `(ENG-142)`) is the team-prefixed identifier Linear returns. It is how the skill resolves symbolic IDs to Linear issues when linking dependencies, and how a re-run knows to skip slices that already have an issue. A heading is treated as already published **if and only if** it matches the annotated form; any other form is unannotated and eligible for creation. Both shapes are valid input, so a partial run resumes cleanly. The annotation is written by a single edit of the heading line immediately after a successful create, so the file is never left in a partially-written state. ## What the dependency step depends on The `**Depends on.**` line in each slice uses the literal bold marker, comma-separates blocker SYMs, and ends with `.` (or is `None.`). Every SYM named in a `Depends on` line must resolve to another slice in this same file; the skill turns those into native Linear "blocked by" relations after all issues exist. There is no cross-file or cross-team dependency concept in this skill. Two `Depends on` shapes are **format errors**, surfaced for repair before any issue is created, never published: - **Self-block** — a slice that names its own SYM in `Depends on`. - **Dependency cycle** — a set of slices whose `Depends on` lines form a loop (A depends on B, B depends on A, and longer cycles).
-
-
SKILL.md 14.8 KB
--- name: work-items-to-linear description: > Turn a work-items.md file (produced by /plan-work-items) into Linear issues, one per slice, in a single target Linear team. Use when you want to publish work items as Linear issues, create implementation tickets to track in Linear, or push a broken-down plan into a Linear team. Requires a configured Linear MCP server and a target team. Reads the team's real workflow states, labels, Projects, and members and resolves every option against them before creating anything; defaults each issue to the team's initial state, unassigned, uncategorized, with no parent or Project unless you ask. Links within-file `Depends on` relationships as native Linear "blocked by" relations and annotates the source file so re-runs resume cleanly. Does not produce the work-items file itself — use plan-work-items first. Does not post to Jira — use work-items-to-jira. Does not post to GitHub — use work-items-to-issues. argument-hint: "[path to work-items.md] --team team [--project Linear project] [--parent issue id] [--state name] [--label name (repeatable)] [--assignee name, email, or me]" allowed-tools: Read, Write, Edit, Glob, Grep, Bash(find *), mcp__plugin_linear_linear__save_issue, mcp__plugin_linear_linear__get_issue, mcp__plugin_linear_linear__list_teams, mcp__plugin_linear_linear__list_issue_statuses, mcp__plugin_linear_linear__list_issue_labels, mcp__plugin_linear_linear__list_users, mcp__plugin_linear_linear__get_user, mcp__plugin_linear_linear__list_projects, Bash(bash "${CLAUDE_PLUGIN_ROOT}/scripts/han-config-dir.sh") --- ## Project Context - personal config directory: !`bash "${CLAUDE_PLUGIN_ROOT}/scripts/han-config-dir.sh" 2>/dev/null || echo "$HOME/.claude"` - project .han/config.md: !`cat .han/config.md 2>/dev/null || echo ""` As your first action, use the Read tool on `.han/config.md` inside the `personal config directory` path above. A read that returns no file is no personal configuration: continue silently. When that file or the `project .han/config.md` probe supplies content, apply it per [config-rule.md](../../references/config-rule.md), which governs precedence between the two files, relative-path resolution, and what to do with a file that reads but cannot be used. # Work Items to Linear Issues Take an already-broken-down `work-items.md` file (produced by `/plan-work-items`) and publish each slice as a Linear issue in a single target team. The breakdown work — drafting slices, assigning symbolic IDs, specifying dependencies, inventorying references — has already been done upstream. This skill validates the format, confirms the target against the live team, creates one issue per slice through the Linear MCP server, links the within-file dependencies as native "blocked by" relations, and reports. ## Rules - **Every slice posts into one Linear team.** This skill does not split work across teams or repos. A `work-items.md` that names multiple code repos still produces issues in the single team you name; the repo prose is informational only. - **Dependencies are within-file only.** Every SYM named in a `Depends on` line must resolve to another slice in the same file. A `Depends on` that names an unknown SYM, names the slice itself, or forms a cycle is a format error to surface for repair, never published. - **Symbolic-ID prefixes:** accept whatever the input uses. Any uppercase prefix shape is valid (`W-N`, `V2-N`, `EV-N`, ...); the prefix has no effect on team placement. - **Resolve against the live team before writing.** Read the team's real workflow states, labels, Projects, and members, and resolve every named option against them before creating any issue. Nothing is assigned, categorized, grouped, or moved unless asked. - **No issue types.** Linear has no issue-type concept. The skill never asks for or sets one. Categorization is via the team's real labels, chosen by the user. - **Every slice issue MUST carry the reference artifacts an implementer needs** — API/event contracts, design references, schema docs, runbooks, ADRs, coding standards. Full include/exclude list in [references/reference-artifact-inventory.md](references/reference-artifact-inventory.md). - **NEVER include process artifacts in issue descriptions.** Excluded: iteration histories, decision logs, review findings, team findings, facilitation summaries, gap analyses, and anything under an `artifacts/` subfolder of the plan that is not a contract or design reference. - **No image upload or embedding.** Design references are carried as links, not uploaded into Linear. See [references/linear-issue-template.md](references/linear-issue-template.md). ## Process ### 0. Linear MCP preflight (hard requirement) This skill cannot run without a configured and connected Linear MCP server. Confirm it is reachable by calling `mcp__plugin_linear_linear__list_teams`. If the tool is unavailable, the call errors, or no workspace is accessible, **stop immediately** and tell the user the skill requires the Linear MCP server to be installed, configured, and authenticated. Do not fall back to any other publishing target. If the integration exposes more than one Linear workspace, note which are available and confirm which one to use before resolving the team. ### 1. Locate the work-items file If the path is not provided, ask for it. The input is a single `work-items.md` produced by `/plan-work-items`. Read it. Its format is described in [references/work-items-file-format.md](references/work-items-file-format.md). ### 2. Gather the run options Read these from the arguments and conversation; do not guess defaults the user did not ask for: - **Target team** — `--team <name or key>`. **Required.** If absent, ask for it in Step 3. - **Project** — `--project <name or ID>`. Optional. Groups every created issue under a Linear Project. - **Parent** — `--parent <issue id>`. Optional. Nests every created issue as a sub-issue under the named parent. - **State** — `--state <name>`. Optional; defaults to the team's initial/default workflow state. - **Labels** — `--label <name>`, repeatable. Optional; resolved against the team's real labels. - **Assignee** — `--assignee <name/email/me>`. Optional; defaults to unassigned. ### 3. Resolve the target against the live team Resolve everything concretely now so failures surface before any issue is created. This is a strict, fail-before-write sequence: - **Team (required).** Confirm the named team with `mcp__plugin_linear_linear__list_teams`. If none is named, ask. If the name matches more than one team, present the matches and ask which one. Do not proceed without exactly one team. - **Read the team's configuration** with `mcp__plugin_linear_linear__list_issue_statuses`, `mcp__plugin_linear_linear__list_issue_labels`, and `mcp__plugin_linear_linear__list_users`. These reads are independent and may run together. - **State.** If `--state` was given, match it against the team's real states. The default is the team's initial/default state. If a named state does not exist, present the team's real states and ask. - **Labels.** If `--label`s were given, match each against the team's labels. When categorization was not specified, present the team's real labels and let the user choose one, several, or none. If the team defines no labels, say so and proceed without categorization. - **Assignee.** If named, resolve it with `mcp__plugin_linear_linear__get_user`: the literal token `me` resolves to the authenticated Linear identity, and a name or email resolves to that member. If unset, leave issues unassigned. The creator is recorded automatically by Linear as the authenticated user; never set it. - **Project (optional).** Resolve a named Project at **workspace scope** with `mcp__plugin_linear_linear__list_projects` (Projects are not strictly team-scoped), and confirm the target team participates in it. - **Parent (optional).** Resolve a named parent issue with `mcp__plugin_linear_linear__get_issue` and confirm it belongs to the target team. For any option that cannot be resolved, do not silently drop or invent it. Distinguish "no such option exists in the team" (present the team's real options for that field) from "it exists but belongs to a different team" (name that team). Ask the user to pick or correct before continuing. ### 4. Validate the format with evidence-based repair Check the work-items file against the invariants in [references/work-items-file-format.md](references/work-items-file-format.md) and [references/linear-issue-template.md](references/linear-issue-template.md): - **Heading shape.** Every slice heading matches `## <SYM-N> — <title>` with an em-dash separator (already-published headings annotated as `## <SYM-N> (<LINEAR-ID>) — <title>` are valid too). - **`Depends on` line.** Literal bold marker `**Depends on.**`, trailing period, `None.` or comma-separated SYMs. - **Within-file blockers.** Every SYM named in a `Depends on` line resolves to another slice in this file. A SYM that names the slice itself (self-block) or that forms a dependency cycle with other slices is a format error. - **References block.** Present whenever the slice consumes an HTTP endpoint, event payload, design frame, ADR, coding standard, or other named artifact. - **No process artifacts.** No links to iteration histories, decision logs, review findings, team findings, facilitation summaries, gap analyses, or anything under an `artifacts/` subfolder that is not a contract or design reference. When a check fails, attempt evidence-based repair. Pull evidence from the source `work-items.md`, the parent plan referenced in its intro, the feature spec in the same folder, sibling files in the plan folder, and the relevant repo's ADRs / coding standards / docs: - **Malformed heading** — propose the corrected shape based on surrounding text. Cite the line number. - **Missing `Depends on` line** — propose `None.` if no blockers are evident. Cite the absence. - **Unknown-SYM, self-block, or cycle** — propose the correct in-file SYM (if a typo is evident), or `None.`, or breaking the cycle. Cite the SYM list this file defines. - **Missing References bullet for an HTTP-consuming or UI slice** — propose the contract section or design frame from the parent plan or feature spec. Cite the anchor. - **Process-artifact link found** — propose removing the link and, if the slice still needs the context, restating the decision in plain language with a **Plan decisions** References bullet naming the ID plus a one-sentence description. Cite the include/exclude list. After validation, report findings in plain language. For each: (1) what is wrong — slice SYM, line reference, failing invariant; (2) the proposed fill — corrected line, new bullet, removed link; (3) the evidence — file path with line number, document section, or named source. Then give the user three actions: **Continue with fills** (apply the repairs to the source `work-items.md` and proceed), **Correct the fills** (user provides the right values; apply those and proceed), or **Stop** (exit without creating issues). If validation passes with no findings, proceed to Step 5. ### 5. Show the plan for confirmation Creating Linear issues writes to a shared system, so confirm before doing it. Present a summary and wait for an explicit yes: - **Destination:** the Linear workspace, the target team, the Project (if any), the parent (if any, and that each item becomes a sub-issue under it), the workflow state, the labels (or "none"), and the assignee (or "unassigned"). - **The issues to create:** a table, in file order, of every slice that does not already carry a `(<LINEAR-ID>)` annotation. | SYM | Title | Depends on | | --- | ----- | ---------- | | W-1 | ... | None | | W-2 | ... | W-1 | State the total count of issues to create and how many slices are being skipped because they already carry an identifier. Do not create anything until the user confirms. ### 6. Create one issue per slice Walk the slices in file order. Skip any slice whose heading already carries a `(<LINEAR-ID>)` annotation so a re-run resumes cleanly. Creation order does not affect correctness, because dependency relations are made in Step 7 once every issue exists. For each remaining slice, call `mcp__plugin_linear_linear__save_issue` with: - **team** = the resolved team, - **title** = the slice title (the text after `— ` in the heading), - **description** = the rendered slice body (Summary, Description, any notes, References, Tests, Acceptance criteria) as Markdown, passed through without conversion, - **state**, **labels**, **assignee**, **parentId**, **project** = the values resolved in Step 3, applied as chosen, - **never `blockedBy` here** — relations are made in Step 7. After each successful create, capture the returned Linear identifier and rewrite that slice's heading in place from `## <SYM-N> — <title>` to `## <SYM-N> (<LINEAR-ID>) — <title>` using Edit, so dependencies resolve and re-runs skip it. Report each creation as `created: <SYM-N> -> <LINEAR-ID>`. **If a create succeeds but the heading annotation fails**, stop. Report the orphaned Linear identifier so the user can annotate the heading by hand or delete the issue. Do not continue creating, and do not run the link pass — the file state is inconsistent until the user resolves it. ### 7. Link dependencies as native relations Once every slice has a Linear identifier, build the SYM-to-identifier map from the annotated headings. This pass runs over the whole annotated file on every run (including identifiers carried over from a prior run), not only over newly created issues, so a link step interrupted earlier completes on the next run. Relations are made after all issues exist because a `blocked by` relation needs both endpoints to exist, and file order is not guaranteed to be blocker-first. - **Stale-annotation check.** For each unique identifier in the map, confirm it resolves to an accessible issue in the team with `mcp__plugin_linear_linear__get_issue`. Surface any that do not resolve to the user before making any relation; never link to a missing or wrong issue. - **Make the relations.** For each slice's `**Depends on.**` line (skip `None.`), call `mcp__plugin_linear_linear__save_issue` on the dependent issue with `blockedBy` set to each blocker's identifier. Relations are append-only and de-duplicated, so a re-run does not duplicate them; no per-relation pre-read is needed. Report each as `linked: <SYM-A>(<LINEAR-A>) blocked_by <SYM-B>(<LINEAR-B>)`. ### 8. Report Summarize: the team, the Project and parent (if any), the workflow state, the labels and assignee (or "none" / "unassigned"). List every created issue as `<SYM-N> — <LINEAR-ID>` with its URL, the count of native "blocked by" relations created, and any slices skipped because they already carried an identifier. If any step failed, report the error and confirm the source `work-items.md` annotations reflect exactly which issues were created, so the user can re-run safely.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.