feat(skills/github): ticket-driven PR creation + branch-name helper (closes #70)#71
Merged
Merged
Conversation
…loses #70) Additive update to the existing github skill — no existing tool names, signatures, or behaviour change. Both new github_create_pr parameters (ticket_id, ticket_url) are optional; absent both → identical to today. SKILL.md - Frontmatter tags: add `ticket-driven` and `linear-compatible` - Replace the "complete entire workflow" rule with a version that carves out three explicit pause cases: 1. ticket-driven mode (post a linear_add_comment and wait) 2. code planning (high complexity / risks) 3. genuine ambiguity Outside those exceptions, complete the full sequence in one session. - New "Ticket-driven PR conventions" section after Branch safety rules: use github_branch_name_from_ticket first, pass ticket_id/ticket_url to github_create_pr, post the PR URL back on the originating ticket (not in the PR itself). - github_create_pr docs: new input table with the two new optional rows (ticket_id, ticket_url) and a one-line explanation that the skill auto-suffixes the title and appends a Tracks: back-link footer. - New ## Tool: github_branch_name_from_ticket section after github_checkout. github-create-pr.sh - Extract optional ticket_id and ticket_url from input. - When ticket_id is set: - Suffix title with [<ticket_id>] if not already present (case pattern matches the literal bracket form, so "ENG-123" embedded in prose without brackets is treated as missing). - Append a Tracks: footer to body — with markdown link if ticket_url is provided, plain ID otherwise. github-branch-name-from-ticket.sh (new) - Validates prefix against feat|fix|chore|docs|refactor allow-list (invalid → feat fallback). - Lowercases ticket ID. - Slugifies title: tr to lowercase, sed -E to collapse non-alnum runs to a single -, strip leading/trailing -. - Truncates to 60 chars cutting at the last hyphen boundary so we don't emit a half-word at the end. - Returns {"branch": "<prefix>/<lower-id>-<slug>"}. Verification (verbatim from #70): - ENG-123 happy path: in: {"ticket_id":"ENG-123","title":"Add invoice creation endpoint with validation"} out: {"branch":"feat/eng-123-add-invoice-creation-endpoint-with-validation"} - BUG-7 with garbage chars: in: {"ticket_id":"BUG-7","title":"Fix: !!! Refresh token rejects 0-length string @@@","prefix":"fix"} out: {"branch":"fix/bug-7-fix-refresh-token-rejects-0-length-string"} Additional edge cases tested: - Invalid prefix ("wip") → feat fallback. - Long title truncated at the last hyphen inside 60 chars. - Missing ticket_id or title → {"error":"..."} on stderr, exit 1. Out of scope per #70 anti-patterns: no Linear calls from github-skill scripts (the LLM is responsible for the post-PR ticket comment via the linear skill), no hardcoded linear.app references, no new tools beyond github_branch_name_from_ticket. The pre-existing SC2181 finding in github-create-pr.sh line 88 was left untouched because the "additive changes only" rule covers existing style. go test ./forge-skills/... — all green including TestEmbeddedRegistry_GitHubDetails. shellcheck clean on github-branch-name-from-ticket.sh.
2 tasks
Mirrors the SKILL.md updates from this PR into the user-facing index: - Tools table count "fourteen" → "fifteen" with a new row for github_branch_name_from_ticket (slugifier, no network call), and the github_create_pr row updated to mention the new optional ticket_id / ticket_url parameters and the auto-suffix / Tracks-footer behaviour. - New "Workflow-completion rule" paragraph below the existing Workflow one-liner — documents the three pause carve-outs (ticket-driven mode, code-plan high complexity, genuine ambiguity). - New "Ticket-driven PR conventions" paragraph — the four-step ticket workflow plus the title-format examples plus the branch-name-helper algorithm (prefix allow-list, lowercase id, slugify, 60-char hyphen-boundary truncation). All identical in spirit to the SKILL.md edits already in this PR — no new behaviour. Doc-link check (37 files) clean.
This was referenced May 20, 2026
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.
Summary
Additive update to the existing
githubembedded skill. No breaking changes — both newgithub_create_prparameters (ticket_id,ticket_url) are optional; absent both → byte-identical behaviour to today. Closes #70.Tools
github_create_prticket_id,ticket_url(both optional)ticket_idis set, auto-suffix the title with[<ticket_id>]if not already present; ifticket_urlis set, append aTracks: [<ticket_id>](<ticket_url>)footer to the body.github_branch_name_from_ticketticket_id,title, optionalprefix<prefix>/<lower-id>-<slug>, capped at 60 chars cut at the last hyphen boundary. No network call.github_clone,github_checkout,github_commit,github_push,github_status,github_create_issue,github_list_issues,github_list_prs,github_get_user,github_list_stargazers,github_list_forks,github_pr_author_profiles,github_stargazer_profiles)SKILL.md changes
ticket-drivenandlinear-compatible. Everything else preserved.linear_add_commentand waitcode_plan_createreturnscomplexity: \"high\"or non-emptyrisks→ present to userOutside those, the "complete the full sequence in one session" rule still applies verbatim.
github_branch_name_from_ticketfirst, passticket_id/ticket_urltogithub_create_pr, and post the PR URL back on the originating ticket using thelinearskill (not in the PR itself).github_branch_name_from_ticketand explicitly forbids inventing branch names likeclaude/fix-thing.github_create_prdocs rebuilt as a proper input table with the two new rows and a one-line explainer of the auto-suffix/auto-footer behaviour. The previous one-line input bullet is unchanged in semantics.## Tool: github_branch_name_from_ticketsection placed aftergithub_checkout.github-create-pr.shchangesExtract
ticket_id/ticket_url, then before thegh pr createinvocation:The literal-bracket pattern (
*\"[\$TICKET_ID]\"*) intentionally matches only the bracketed form, so a title like\"ENG-123 hotfix\"(no brackets) gets the suffix appended. This matches the documented convention.github-branch-name-from-ticket.sh(new)prefixagainstfeat|fix|chore|docs|refactor; falls back tofeatfor any other value.ENG-123→eng-123).tr [:upper:] → [:lower:],sed -E 's/[^a-z0-9]+/-/g', strip leading/trailing-.\${SLUG%-*}so we never emit a half-word.{\"branch\": \"<prefix>/<lower-id>-<slug>\"}.Verification (verbatim from #70)
Both match the issue's expected outputs exactly. Additional edge cases tested locally:
prefix: \"wip\"feat→feat/x-1-hellofeat/ops-999-this-is-a-really-really-really-really-really-really-longticket_id{\"error\":\"ticket_id is required\"}on stderr, exit 1Test plan
go test ./forge-skills/...— all green (incl.TestEmbeddedRegistry_GitHubDetails, which counts ongh/git/jq+ the egress domain set — none of which changed)go test ./forge-core/..../forge-cli/..../forge-plugins/...— no regressionsgofmt -w,golangci-lint run ./forge-skills/...— 0 issuesshellcheckclean ongithub-branch-name-from-ticket.shGH_TOKEN, verify the PR title ends with[ENG-DEMO-1]and the body containsTracks: [ENG-DEMO-1](https://...)Out of scope per #70
linearskill (PR feat(skills): add linear embedded skill (closes #66) #67)linear.appreferences —ticket_urlis an opaque URLgithub_link_issue/github_close_issue_on_merge— separate concernapi.github.com+github.comstill the only allowed pairPre-existing finding left untouched
shellcheck github-create-pr.shreports SC2181 on line 88 (thegh pr createexit check uses\$?instead ofif !). This exists verbatim onmainand is not introduced by this PR — the issue's "additive changes only" rule covers existing style. Happy to fix in a follow-up.Relation to PRs #67 and #69
This PR is independent of:
linear_get_issue/linear_add_commenttools the new system-prompt guidance referencescode_plan_createwhosecomplexity: \"high\"output is one of the workflow-pause carve-outsThe three together form the canonical ticket → plan → branch → commit → PR → comment flow. None of them touch the same files, so they can land in any order.