Repository navigation
feat: add sub-issue support (--parent, children in issue view) - #46
Closed
seraph-pixelperfect wants to merge 1 commit into
Closed
seraph-pixelperfect wants to merge 1 commit into
seraph-pixelperfect wants to merge 1 commit into
Conversation
This was referenced Aug 19, 2026
Collaborator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #26
Depends on #45
What
issue create --parent <IDENTIFIER|UUID>— creates the new issue as a sub-issue of the referenced parent. The parent ref is resolved to its id (viafetchIssue, which accepts identifier or UUID) before the mutation, failing loud withParent issue "X" not found(NOT_FOUND) on a miss — the same resolve-loud-before-write convention as--project/--cyclefrom Support project and cycle assignment on issue create/update #25.parentIdrides throughcreateIssue's omit-null input builder (parentId: $parentId,$parentId: String), so the default create document is unchanged without the flag. A blank--parentfails loud before any network request.issue view --full— additionally selects the issue's children connection and renders asub-issues[N]:block after the description, oneidentifier | title | stateline per child in server order. Without--full, neither the selection nor the block appears (the default detail document stays byte-identical — the same opt-in principle as--fields). An issue with no children renders a baresub-issues[0]:header under--full("no sub-issues" is information, not noise).ISSUE_HELP) and the generatedskills/linear-axi/SKILL.mddocument the new flag and listing (pnpm run build:skill,--checkclean).Schema verification (mandatory per the issue)
Inspected the generated documents in
@linear/sdk@90.0.0(npm pack, thendist/index-zxW4m1xd.d.mtsfor types anddist/index.mjs/dist/chunk-DPPnyiuk.mjsfor the runtime documents):IssueCreateInput.parentId?index-zxW4m1xd.d.mts:9698-9699(insidetype IssueCreateInputstarting at line 9668)subIssueCreatemutation?subIssueCreate/SubIssueCreateacross the type declarations and the runtime documents. Sub-issues are created throughissueCreate+parentId; the relatedIssueCreateInput.subIssueSortOrder("The position of the issue in parent's sub-issue list", line 9730) corroborates thatissueCreateis the sub-issue path.index-zxW4m1xd.d.mts,index.mjs,chunk-DPPnyiuk.mjs— 0 hitschildren(notsubIssues):children: IssueConnection— "Children of the issue."IssueConnection = { nodes: Array<Issue>, ... }, sochildren { nodes { ... } }is the selection.index-zxW4m1xd.d.mts:9061(ontype Issue, line 9021, whose docstring reads "Issues support sub-issues (parent-child hierarchy up to 10 levels deep)")Mechanism choice:
parentIdonissueCreate— it is the only mechanism the schema exposes, and it is also the simpler route (one input field vs a separate mutation). Bonus finding for future work:IssueUpdateInput.parentIdalso exists (line 11578), so re-parenting viaissue update --parentis schema-supported but intentionally out of scope here (the issue only asks for create + view).Before / after (stubbed endpoint, real CLI code)
issue create --title "Review the copy" --team LIN --parent LIN-42— captured mutation document and variables:issue view LIN-42 --full— newsub-issuesblock after the description (absent without--full):Local gates (real output)
New
test/sub-issues.test.ts(10 tests, network-freevi.stubGlobal('fetch', ...)per the established pattern) covers: parent resolution round trip (identifier and UUID) withparentIdin the mutation variables; parent not found (loud error, no mutation); blank--parentrejected before any request; cross-team parent NOT pre-rejected (mutation still sent — Linear decides); create without--parentsends noparentId;--fullselectschildren { nodes { identifier title state { name } } }and renders ordered child lines; default view document/output untouched without--full; empty-children header; help documentation.pnpm run format:checkremains RED on the same pre-existing 18-file set as the base branch (CI does not run it); the new/edited files passpnpm exec prettier --check.Stacked PR note
Stacked on #45 (stack: #37→#38→#39→#40→#41→#42→#43→#44→#45→this). No CI checks appear on this PR —
ci.ymlonly triggers on PRs targetingmain. CI runs when retargeted tomainafter the stack merges; local gates above are the evidence. Not retargeting.CI caveat: if checks do appear and fail suspiciously fast (~3-4s, empty
steps), checkgh run view <run-id>/ the jobs API for a billing/spending-limit annotation — quota-block rejections look like check failures. If quota-blocked, this PR relies on the local output above; no retry.Decisions & ambiguities flagged
parentIdonissueCreate(notsubIssueCreate, which does not exist in the schema). Not actually ambiguous after verification; documented with evidence above.IssueCreateInput.parentIdaccepts any issue ref), so rejecting client-side would break legitimate use; any workspace-level rejection surfaces through the normal API error mapping. A test pins this behavior.--full(conditional selection). Alternative considered: always select, render only with--full. Conditional won becauseISSUE_DETAIL_FIELDSis shared by everyfetchIssuecaller (update no-op detection, delete, state resolution) which would otherwise fetch a children page it never reads, and because the repo's stated opt-in principle is that default documents stay byte-identical without the flag.sub-issues[N]:block with oneidentifier | title | stateline per child (echoing thehelp[N]:bracket convention) rather thanrenderListTOON objects: one line per child vs three, carrying exactly the three fields the acceptance criteria name. Empty children still render the bare header under--full.parentIdaccepted raw — the API would acceptLIN-42directly asparentId, but the CLI pre-resolves to the UUID id for a clean loudNOT_FOUNDinstead of an opaque mutation error (and the resolved id is what the schema documents as canonical).Identity note
Automated agent dispatch authenticated as
seraph-pixelperfect, submitted for human review — not self-approved; merge is a human decision.