Add OpenSpec workflow and open-pr skill (LS-3223) - #53
Conversation
OpenSpec integration - Initialize OpenSpec for Claude Code (openspec init --tools claude) - Add opsx:propose/apply/archive/explore/sync commands and skills Planning artifacts - Add proposal.md: why open-pr is moving from a personal command to a repo-committed skill - Add design.md: skill location, dual-invocation guard, content-carryover decisions - Add specs/pr-creation/spec.md: testable requirements for context-gathering, pre-flight checks, labels/assignee-in-same-command, changelog-after-PR - Add tasks.md: implementation checklist for building the open-pr skill Housekeeping - Gitignore .claude/settings.local.json (personal, machine-local permission grants)
Skill implementation - Add .claude/skills/open-pr/SKILL.md implementing the pr-creation spec - Port validated PR-creation instructions: context gathering, pre-flight checks, PR structure - Apply labels and assignee in the same gh pr create/edit call, not a follow-up step - Add CHANGELOG entry step that runs only after the PR exists and links back to it - Add branch/base confirmation guard for natural-language (non-/open-pr) invocation - Document the deliberate .claude/skills/ vs .agents/skills/ location choice inline Planning - Check off tasks.md sections 1-3 (scaffolding, instruction porting, dual invocation)
- Link the entry to PR #53, per this repo's per-PR changelog convention
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved moderate workflow and safety issues remain in the OpenSpec commands and open-pr skill.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds a version-controlled OpenSpec workflow and Claude Code open-pr skill for consistent, spec-driven PR creation.
Changes:
- Adds
/opsx:*commands and corresponding workflow skills. - Adds OpenSpec planning artefacts for
open-pr. - Adds PR creation/update guidance, changelog integration, and local settings exclusions.
File summaries
| File | Description |
|---|---|
openspec/changes/open-pr-skill/tasks.md |
Implementation and verification checklist |
openspec/changes/open-pr-skill/specs/pr-creation/spec.md |
PR creation requirements |
openspec/changes/open-pr-skill/proposal.md |
Change rationale and scope |
openspec/changes/open-pr-skill/design.md |
Architectural decisions and trade-offs |
openspec/changes/open-pr-skill/.openspec.yaml |
OpenSpec metadata |
CHANGELOG.md |
Documents the new workflow and skill |
.gitignore |
Excludes local Claude settings |
.claude/skills/openspec-sync-specs/SKILL.md |
Specification synchronisation workflow |
.claude/skills/openspec-propose/SKILL.md |
Proposal workflow |
.claude/skills/openspec-explore/SKILL.md |
Exploration workflow |
.claude/skills/openspec-archive-change/SKILL.md |
Archive workflow |
.claude/skills/openspec-apply-change/SKILL.md |
Implementation workflow |
.claude/skills/open-pr/SKILL.md |
PR creation and update workflow |
.claude/commands/opsx/sync.md |
Sync command |
.claude/commands/opsx/propose.md |
Propose command |
.claude/commands/opsx/explore.md |
Explore command |
.claude/commands/opsx/archive.md |
Archive command |
.claude/commands/opsx/apply.md |
Apply command |
Review details
Suppressed comments (9)
.claude/commands/opsx/archive.md:65
- The prompt includes
Cancelas an option when specs are already synced, but this sentence says to proceed to archive regardless of the choice. A user who cancels can therefore still have the change moved into the archive. Handle Cancel as a stop and only continue for the two archive choices.
If user chooses sync, use Task tool (subagent_type: "general-purpose", prompt: "Use Skill tool to invoke openspec-sync-specs for change '<name>'. Delta spec analysis: <include the analyzed delta spec summary>"). Proceed to archive regardless of choice.
.claude/commands/opsx/propose.md:19
- This input contract accepts a free-form description, but the command then passes
<name>straight toopenspec new changewithout deriving a kebab-case name. A request such asadd user authenticationcan therefore be rejected or create an invalid change name; add the derivation/ambiguity check here before step 2, as the paired skill already describes.
**Input**: The argument after `/opsx:propose` is the change name (kebab-case), OR a description of what the user wants to build.
.claude/skills/open-pr/SKILL.md:61
- This condition checks only whether the repository requires a changelog, not whether this branch already contains the required PR-linked entry. Re-running the skill for an existing PR after the first invocation will append and push a duplicate entry; gate this step on the current branch lacking that entry.
If Step 2.6 found this repo requires a changelog entry, add it now — only after the PR exists, never before:
.claude/skills/open-pr/SKILL.md:63
- On the existing-PR path, no
gh pr createoutput exists, so this step cannot provide the URL/number needed for a required changelog link. Use the existing PR returned bygh pr listorgh pr viewwhen updating instead.
1. Take the PR URL and/or number from the `gh pr create` output in the previous step.
.claude/skills/open-pr/SKILL.md:81
- This absolute prohibition conflicts with the spec's no-fit-label scenario: when
gh label listhas no accurate label, the skill must proceed without--label; requiring it here forces the agent either to invent a label or abort. Make the label flag conditional while keeping--assigneemandatory, and update the identical wording in the earlier creation section.
- Don't run `gh pr create` without `--label` and `--assignee` already in that same command.
.claude/skills/open-pr/SKILL.md:34
gh label listhas a default result limit, so this does not guarantee the “full current label set” required by the next step; this repository currently has 91 labels, and a valid match can be omitted before the agent chooses labels. Use an explicit high--limit(or paginate) here.
4. Check `gh label list` for the full current label set — never invent a label that doesn't exist in the repo.
.claude/skills/openspec-archive-change/SKILL.md:69
- The prompt includes
Cancelas an option when specs are already synced, but this sentence says to proceed to archive regardless of the choice. A user who cancels can therefore still have the change moved into the archive. Handle Cancel as a stop and only continue for the two archive choices.
If user chooses sync, use Task tool (subagent_type: "general-purpose", prompt: "Use Skill tool to invoke openspec-sync-specs for change '<name>'. Delta spec analysis: <include the analyzed delta spec summary>"). Proceed to archive regardless of choice.
openspec/changes/open-pr-skill/proposal.md:3
- The proposal describes OpenSpec as the required planning process for new skills, but the repository's canonical guidance (
AGENTS.md) is not updated to require or even point contributors to this workflow. Without that documentation, future agents can still follow the old ad-hoc process. Add the rule to the contributor/agent guidance or scope this claim explicitly.
PR creation currently relies on a personal, machine-local slash command (`~/.claude/commands/open-pr.md`) that isn't shared with the team, isn't discoverable by other agent tools, and has already shown a real failure mode: agents running it have skipped the labels/assignee step because it lived as trailing sections after the main "create the PR" action instead of being structurally part of it. LS-3223 also establishes OpenSpec as the required planning process for new skills going forward, and this is the first skill being planned through it — both problems are solved by converting `open-pr` into a proper, repo-committed agent skill with a spec-reviewed design instead of a hand-written command file.
openspec/changes/open-pr-skill/tasks.md:19
- The PR description says this PR was created through the natural-language path with the branch/base confirmation, which exercises task 4.2, but the OpenSpec task remains unchecked. Mark 4.2 complete if that verification claim is accurate, while leaving 4.1 pending unless the literal
/open-prpath was also exercised.
- [ ] 4.2 Trigger the skill with a natural-language prompt (e.g. "create the PR for me") and confirm the branch/base confirmation guard fires before any `gh pr create` call.
- Files reviewed: 17/18 changed files
- Comments generated: 4
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| - Dynamic instruction based on current state | ||
|
|
||
| **Handle states:** | ||
| - If `state: "blocked"` (missing artifacts): show message, suggest using `/opsx:continue` |
|
|
||
| Create a pull request for the current branch, following this repo's established conventions exactly. This skill only creates/updates a PR — it does not create branches, commit changes, or push to `develop`. Assume the branch and its commits already exist. | ||
|
|
||
| **Invocation guard**: if this skill was triggered by a natural-language request (e.g. "create the PR for me") rather than the explicit `/open-pr` command, confirm the target branch and base with the user before running `gh pr create`. Skip this confirmation when invoked via the literal `/open-pr` command. |
| - Dynamic instruction based on current state | ||
|
|
||
| **Handle states:** | ||
| - If `state: "blocked"` (missing artifacts): show message, suggest using openspec-continue-change |
| - *Alternative considered*: `.agents/skills/open-pr/` for consistency with the repo's stated skill convention. Rejected because it would silently break native `/open-pr` slash-command registration and auto-invocation, the two explicit requirements driving this work. | ||
|
|
||
| **2. Auto-invocation: omit `disable-model-invocation`, but add an explicit confirmation guard for implicit triggers.** | ||
| The user wants both explicit (`/open-pr`) and natural-language invocation to work. Claude Code's own best practice recommends `disable-model-invocation: true` for side-effect operations, but that would block natural-language triggering entirely, which is a stated requirement here. Decision: leave auto-invocation enabled, and add an instruction in the skill body requiring the agent to confirm target branch and base with the user before running `gh pr create` when the skill was triggered implicitly (i.e., not via the literal `/open-pr` command) — for `gh pr edit` are more common on updates. This preserves today's "just run it" convenience for the explicit command while adding a safety check only for the ambiguous-trigger path. |
Summary
New skills were being planned ad hoc, with no shared process and no version-controlled record of why a given skill was built the way it was. This adds OpenSpec as the repo's spec-driven planning workflow for new skills, and uses it end-to-end to build the first real skill under that process:
open-pr, replacing a personal, machine-local PR-creation command with a proper repo-committed agent skill.OpenSpec setup
openspec init --tools claude), adding the/opsx:propose,/opsx:apply,/opsx:archive,/opsx:explore,/opsx:synccommands and their corresponding skills under.claude/.openspec/specs/andopenspec/changes/archive/scaffolding.open-prskill — planned and built through OpenSpecopenspec/changes/open-pr-skill/proposal.md,design.md,specs/pr-creation/spec.md,tasks.md— the full planning trail: why the personal command is being replaced, the key design decisions (skill location, dual invocation with a confirmation guard, content carryover), and testable WHEN/THEN requirements..claude/skills/open-pr/SKILL.md— the implemented skill. Gathers PR context from the branch's own commits/diff rather than assumed conversation context, runs pre-flight checks (existing PR, real label set, base branch, changelog requirement), and applies labels and assignee in the samegh pr create/gh pr editcall rather than as a separate step that can be skipped. Adds aCHANGELOG.mdentry only after the PR exists, linking back to it. Works via the explicit/open-prcommand and via natural-language requests (e.g. "create the PR for me"), with a guard requiring branch/base confirmation before acting on an implicit trigger..claude/skills/rather than this repo's usual.agents/skills/portable-skill location, since it needs native Claude Code slash-command registration and natural-language auto-invocation, which Claude Code does not provide for.agents/skills/. Documented inline in the skill file and indesign.md(Decision 1) so it isn't mistaken for an oversight ofAGENTS.mdrule 11.Housekeeping
.claude/settings.local.json(personal, machine-local Claude Code permission grants) — this file is not meant to be shared and was about to be committed by accident.Investigated, not changed
open-prskill under.agents/skills/for consistency with this repo's stated portable-skill convention. Rejected: Claude Code only auto-discovers and slash-command-registers skills from.claude/skills/, and this skill has no near-term need for cross-tool portability (it's agh-CLI-specific workflow, not a shared WordPress convention). Full rationale inopenspec/changes/open-pr-skill/design.md.Test plan
openspec validate open-pr-skill→Change 'open-pr-skill' is validspecs/pr-creation/spec.mdagainst the shippedSKILL.mdbody — all represented.claude/settings.local.jsonis excluded viagit check-ignore -v/open-pr-equivalent skill (natural-language invocation, branch/base confirmed per the implicit-trigger guard) — a live, real-world test of task 4.1/4.2 intasks.mdgh pr edit --add-label/--add-assigneepath) — not yet exercised, since this PR didn't previously existopenspec/changes/open-pr-skill/via/opsx:archiveafter this PR is reviewedLS-3223
Closes LS-3223.