Adopt GitHub Spec Kit, retire OpenSpec active tooling (LS-4126) - #20
Conversation
Installs Spec Kit for Claude Code and GitHub Copilot as the repo's active spec-driven workflow, ratifies a project constitution derived from AGENTS.md, and removes OpenSpec's now-superseded skills/prompts/ commands for both agents. openspec/ (specs + archived changes) is left untouched as a frozen historical record. See LS-4126. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical and moderate findings block approval.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
This PR adopts GitHub Spec Kit for Claude Code and GitHub Copilot, while preserving OpenSpec as historical material and retiring its active tooling.
Changes:
- Adds Spec Kit configuration, workflows, templates, scripts, and constitution.
- Adds mirrored agent skills and updates repository guidance and changelog.
- Removes active OpenSpec prompts, skills, and commands.
- Reported lint and theme validation checks pass.
Review findings: A critical path-containment issue remains in common.ps1; moderate findings cover branch enforcement, issue-creation capabilities, integration state, plan failure handling, and workflow review gates; nit findings cover constitution cleanup, exact validation commands, and the PowerShell prerequisite. These retain their supplied severities and vote counts.
File summaries
| File | Summary |
|---|---|
CHANGELOG.md |
Records Spec Kit adoption and OpenSpec tooling retirement. |
AGENTS.md |
Documents Spec Kit workflow and repository conventions. |
.specify/workflows/workflow-registry.json |
Registers Spec Kit workflows. |
.specify/workflows/speckit/workflow.yml |
Defines the full Spec-Driven Development workflow. |
.specify/templates/spec-template.md |
Provides the specification template. |
.specify/templates/plan-template.md |
Provides the implementation plan template. |
.specify/templates/constitution-template.md |
Provides the constitution template. |
.specify/templates/checklist-template.md |
Provides the review checklist template. |
.specify/scripts/powershell/setup-tasks.ps1 |
Sets up generated task files. |
.specify/scripts/powershell/setup-plan.ps1 |
Sets up generated plan files. |
.specify/scripts/powershell/resolve-template.ps1 |
Resolves workflow templates. |
.specify/scripts/powershell/check-prerequisites.ps1 |
Checks Spec Kit prerequisites. |
.specify/memory/constitution.md |
Defines project principles and governance. |
.specify/memory/.constitution-template.json |
Stores constitution template metadata. |
.specify/integrations/speckit.manifest.json |
Describes Spec Kit integration files. |
.specify/integrations/copilot.manifest.json |
Describes Copilot integration files. |
.specify/integrations/claude.manifest.json |
Describes Claude integration files. |
.specify/integration.json |
Stores installed integration state. |
.specify/init-options.json |
Stores Spec Kit initialization options. |
.specify/.gitignore |
Ignores local Spec Kit state. |
.github/skills/speckit-taskstoissues/SKILL.md |
Defines task-to-issue generation for Copilot. |
.github/skills/speckit-plan/SKILL.md |
Defines Copilot planning workflow. |
.github/skills/speckit-constitution/SKILL.md |
Defines Copilot constitution workflow. |
.github/skills/openspec-update-change/SKILL.md |
Removes retired OpenSpec update skill. |
.github/skills/openspec-sync-specs/SKILL.md |
Removes retired OpenSpec sync skill. |
.github/skills/openspec-propose/SKILL.md |
Removes retired OpenSpec proposal skill. |
.github/skills/openspec-explore/SKILL.md |
Removes retired OpenSpec exploration skill. |
.github/skills/openspec-archive-change/SKILL.md |
Removes retired OpenSpec archive skill. |
.github/skills/openspec-apply-change/SKILL.md |
Removes retired OpenSpec apply skill. |
.github/prompts/opsx-update.prompt.md |
Removes retired OpenSpec update prompt. |
.github/prompts/opsx-sync.prompt.md |
Removes retired OpenSpec sync prompt. |
.github/prompts/opsx-propose.prompt.md |
Removes retired OpenSpec proposal prompt. |
.github/prompts/opsx-explore.prompt.md |
Removes retired OpenSpec exploration prompt. |
.github/prompts/opsx-archive.prompt.md |
Removes retired OpenSpec archive prompt. |
.github/prompts/opsx-apply.prompt.md |
Removes retired OpenSpec apply prompt. |
.claude/skills/speckit-taskstoissues/SKILL.md |
Defines task-to-issue generation for Claude. |
.claude/skills/speckit-plan/SKILL.md |
Defines Claude planning workflow. |
.claude/skills/speckit-constitution/SKILL.md |
Defines Claude constitution workflow. |
.claude/skills/openspec-update-change/SKILL.md |
Removes retired OpenSpec update skill. |
.claude/skills/openspec-sync-specs/SKILL.md |
Removes retired OpenSpec sync skill. |
.claude/skills/openspec-propose/SKILL.md |
Removes retired OpenSpec proposal skill. |
.claude/skills/openspec-archive-change/SKILL.md |
Removes retired OpenSpec archive skill. |
.claude/skills/openspec-apply-change/SKILL.md |
Removes retired OpenSpec apply skill. |
.claude/commands/opsx/update.md |
Removes retired OpenSpec update command. |
.claude/commands/opsx/sync.md |
Removes retired OpenSpec sync command. |
.claude/commands/opsx/propose.md |
Removes retired OpenSpec proposal command. |
.claude/commands/opsx/explore.md |
Removes retired OpenSpec exploration command. |
.claude/commands/opsx/archive.md |
Removes retired OpenSpec archive command. |
.claude/commands/opsx/apply.md |
Removes retired OpenSpec apply command. |
Review details
Suppressed comments (7)
.claude/skills/speckit-specify/SKILL.md:78
- This is the mandatory branch-before-specify rule, but branch creation is optional here and the command proceeds when no hook exists. In this repository
create-new-feature.ps1only computes/printsBRANCH_NAME; it does not switch branches, so/speckit-specifycan writespecs/directly onmainordevelop, contradictingAGENTS.mdand the constitution. Require or verify a feature branch before creatingSPECIFY_FEATURE_DIRECTORY.
2. **Branch creation** (optional, via hook):
If a `before_specify` hook ran successfully in the Pre-Execution Checks above, it will have created/switched to a git branch and output JSON containing `BRANCH_NAME` and `FEATURE_NUM`. Note these values for reference, but the branch name does **not** dictate the spec directory name.
.github/skills/speckit-specify/SKILL.md:75
- This is the mandatory branch-before-specify rule, but branch creation is optional here and the command proceeds when no hook exists. In this repository
create-new-feature.ps1only computes/printsBRANCH_NAME; it does not switch branches, so/speckit-specifycan writespecs/directly onmainordevelop, contradictingAGENTS.mdand the constitution. Require or verify a feature branch before creatingSPECIFY_FEATURE_DIRECTORY.
.github/skills/speckit-taskstoissues/SKILL.md:72 - This skill instructs the agent to create GitHub issues through the MCP server, but the configured
github-mcp-serverexposes only read/list/search issue operations and no issue-creation operation. Following/speckit-taskstoissuestherefore cannot produce its advertised output and risks an agent claiming writes it could not perform. Make a write-capable tool an explicit prerequisite and provide a safe payload-only fallback when it is unavailable.
.specify/memory/constitution.md:100 - These are written as bare names (
schema:validate,theme:validate, etc.), butAGENTS.mddocuments them as npm scripts (npm run ...), so copying this mandatory gate into a shell will fail;composer run lint:phpis also omitted. Use the exact runnable commands and include the PHP syntax check.
.specify/scripts/powershell/setup-plan.ps1:70 - When
plan-templatecannot be resolved, this branch creates a zero-byteplan.mdand continues successfully. The plan skill then loads that file, whilesetup-tasks.ps1only checks for a file's existence, so the workflow can generate tasks from an empty plan instead of stopping on a broken installation. Fail with an error here, assetup-tasks.ps1already does for its required template.
.specify/workflows/speckit/workflow.yml:74 - The registered “Full SDD Cycle” goes directly from task generation to implementation, so the task list produced in the preceding step has no review gate. This conflicts with the new constitution's guidance to check every
/speckit-tasksoutput before implementation, and approving the plan cannot review tasks generated afterward. Add a human approval or/speckit-analyzegate betweentasksandimplement.
AGENTS.md:242 - The documented workflow has no runtime prerequisite note, but every command implementation invokes the checked-in
.specify/scripts/powershell/*.ps1scripts. On environments without PowerShell 7 (pwsh), all/speckit-*commands fail even though this is presented as the supported workflow. Document the prerequisite here or add a portable runner.
- Files reviewed: 67/67 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Fix a path-containment gap in .specify/scripts/powershell/common.ps1: Get-FeaturePathsEnv resolved SPECIFY_FEATURE_DIRECTORY (env var or feature.json) without checking the result stayed inside the repo, so a "../.." value or an absolute path elsewhere would be used as-is for reads/writes. Canonicalises the path and rejects anything outside $repoRoot, mirroring the existing Resolve-SpecifyInitDir pattern. Verified: a traversal value is now rejected, a legitimate relative path still resolves correctly. Also: drop the leftover Sync Impact Report scratch comment from constitution.md (was left in by mistake), correct its validation commands to the exact runnable npm/composer scripts and add the missing composer run lint:php (v1.0.0 -> v1.0.1); document the PowerShell 7 (pwsh) prerequisite in AGENTS.md for every /speckit-* command; and persist claude alongside copilot in .specify/integration.json's installed_integrations, which only recorded the most recently installed agent.
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved comments remain for path safety, branch and prerequisite enforcement, integration manifests, and metadata consistency.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (10)
Previously missed (1) — in code that hasn't changed since the last review.
.specify/memory/constitution.md:106
- The committed constitution declares version
1.0.1, while the PR description and the new changelog entry describe this as the initial ratification at1.0.0. With no prior committed constitution, this should use the initial1.0.0version (or the PR metadata/changelog must be updated consistently).
.claude/skills/speckit-checklist/SKILL.md:89
check-prerequisites.ps1always requiresplan.md(lines 104–109), so this command exits before reaching the documented context-loading behaviour whereplan.mdis optional. A checklist cannot be generated afterspec.mdbut before planning, despite this skill presenting that state as supported; either make the plan prerequisite explicit or use a setup path that only requires the feature/spec files needed here.
## Execution Steps
.claude/skills/speckit-specify/SKILL.md:80
- This copy has the same bypass: branch creation is optional, and the command proceeds to write the feature directory without verifying a
develop-based feature branch. Because this repository has no branch hook configured, Claude users can run/speckit-specifyonmaindespite the new governance rule; enforce the branch check before any write.
2. **Branch creation** (optional, via hook):
If a `before_specify` hook ran successfully in the Pre-Execution Checks above, it will have created/switched to a git branch and output JSON containing `BRANCH_NAME` and `FEATURE_NUM`. Note these values for reference, but the branch name does **not** dictate the spec directory name.
If the user explicitly provided `GIT_BRANCH_NAME`, pass it through to the hook so the branch script uses the exact value as the branch name (bypassing all prefix/suffix generation).
.github/skills/speckit-checklist/SKILL.md:92
check-prerequisites.ps1always requiresplan.md(lines 104–109), so this command exits before reaching the documented context-loading behaviour whereplan.mdis optional. A checklist cannot be generated afterspec.mdbut before planning, despite this skill presenting that state as supported; either make the plan prerequisite explicit or use a setup path that only requires the feature/spec files needed here.
.github/skills/speckit-specify/SKILL.md:77- The repository guidance and constitution require creating or switching to a feature branch from
developbefore every/speckit-*command, but this step makes branch creation optional and then proceeds to createspec.mdwhen no hook exists. There is no.specify/extensions.ymlor git hook in this checkout, so a fresh invocation can write feature artefacts onmain; make branch verification a mandatory precondition, with hooks only as an automation path.
.specify/scripts/powershell/check-prerequisites.ps1:27 - The script advertises
-has an alias in both help blocks, but[switch]$Helphas no alias declaration, socheck-prerequisites.ps1 -hfails with an unknown-parameter error instead of showing help. Add the alias to keep the documented interface functional.
.specify/scripts/powershell/common.ps1:187 - This persists the raw
SPECIFY_FEATURE_DIRECTORYbefore the containment check below. An invalid value such as../../outsideis therefore written to.specify/feature.jsoneven though the command then exits, poisoning subsequent commands that rely on the persisted feature state; validate the canonical path first and persist only after it is accepted.
AGENTS.md:245 - The new
speckit-specifyskill does not invoke any PowerShell helper; its directory creation and template/state writes are model-executed steps, as shown in.github/skills/speckit-specify/SKILL.md:93-104. Therefore the unconditional statement that every/speckit-*command shells out to PowerShell is inaccurate and makes thepwshrequirement misleading. Qualify this statement to commands that use the repository helper scripts.
AGENTS.md:255 - The PR description says
git grepfound no references to the retired OpenSpec tooling anywhere, but this change intentionally adds or retains OpenSpec references in this section,CHANGELOG.md, and the preservedopenspec/history. Please narrow that claim to active tooling references so the stated verification matches the repository.
CHANGELOG.md:44 - This entry calls the constitution ratified v1.0.0, but the committed
.specify/memory/constitution.mddeclaresVersion: 1.0.1at line 106. Please make the changelog and constitution metadata agree so the repository's governance history is unambiguous.
- Files reviewed: 67/67 changed files
- Comments generated: 5
- Review effort level: Lite
common.ps1's fix didn't cover this: the /speckit-specify skill's prose instructions tell the agent to take SPECIFY_FEATURE_DIRECTORY "as-is" and mkdir/write into it directly, with no containment check of their own, for both the Claude and Copilot copies of the skill. Adds the same validate-before-create step in both.
There was a problem hiding this comment.
🔵 Needs a closer look
Unresolved moderate findings remain in branch enforcement, issue creation, and path containment.
Review details
Suppressed comments (7)
Previously missed (3) — in code that hasn't changed since the last review.
.claude/skills/speckit-specify/SKILL.md:80
- This workflow makes branch creation optional and only relies on a
before_specifyhook, but the canonical rule inAGENTS.md:296(also.specify/memory/constitution.md:82-84) requires a feature branch before every/speckit-*command and forbids usingmain/developdirectly. With no hook configured, this skill can createspec.mdon the current shared branch. Make the branch precondition mandatory (or fail before writing) rather than treating the hook as optional.
.github/skills/speckit-specify/SKILL.md:77 - This workflow makes branch creation optional and only relies on a
before_specifyhook, but the canonical rule inAGENTS.md:296(also.specify/memory/constitution.md:82-84) requires a feature branch before every/speckit-*command and forbids usingmain/developdirectly. With no hook configured, this skill can createspec.mdon the current shared branch. Make the branch precondition mandatory (or fail before writing) rather than treating the hook as optional.
CHANGELOG.md:44 - This entry records the constitution as ratified at v1.0.0, but
.specify/memory/constitution.mddeclares version 1.0.1. Please align this changelog entry with the committed constitution so the adoption record is accurate.
.claude/skills/speckit-taskstoissues/SKILL.md:73
- This step requires creating GitHub issues, but the skill only names a generic GitHub MCP server and provides no write-capable issue-creation operation or fallback command. An agent can perform the deduplication read but cannot complete the advertised task-to-issues conversion. Add an explicit supported issue-creation API/CLI path (with its authentication and remote checks), or mark this skill unavailable for integrations without one.
1. For each task in the list, use the GitHub MCP server to create a new issue in the repository that is representative of the Git remote. Task lines in `tasks.md` start with a markdown checkbox, so first strip the leading `- [ ]` (and any `[P]` / `[US#]` markers) to recover the task ID and its description. Create the issue with a single canonical title of the form `T001: <description>`, with the ID written once followed by the task description (for example, the line `- [ ] T001 Create project structure` becomes the title `T001: Create project structure`).
.github/skills/speckit-taskstoissues/SKILL.md:70
- This step requires creating GitHub issues, but the skill only names a generic GitHub MCP server and provides no write-capable issue-creation operation or fallback command. An agent can perform the deduplication read but cannot complete the advertised task-to-issues conversion. Add an explicit supported issue-creation API/CLI path (with its authentication and remote checks), or mark this skill unavailable for integrations without one.
.specify/scripts/powershell/common.ps1:224 - This containment check compares
GetFullPathstrings only; it normalises..but does not resolve directory symlinks or junctions. An existingspecs/linkpointing outside the repository therefore makesspecs/link/newpass this check, after which the feature writers can create files outside the repository. Resolve the real path of existing components (or reject reparse points) before accepting the feature directory.
AGENTS.md:43 - The updated repository tree documents the new Claude integration under
.claude/, but it does not document the equally new Copilot skill tree under.github/skills/. Please add that path to the tree (and the folder-conventions table if it is intended to be exhaustive) so the new dual-agent layout is discoverable from the canonical guide.
- Files reviewed: 67/67 changed files
- Comments generated: 0 new
- Review effort level: Lite
- CHANGELOG.md: fix a stale "ratified v1.0.0" reference — the security-fix commit already bumped the constitution to v1.0.1. - AGENTS.md: add the missing .github/skills/ entry to the repo tree and the AI Folder Expectations table (only .claude/ was documented before), plus a .claude/skills/ row for the same reason. - common.ps1: document the known, accepted limitation that the containment check is a lexical path comparison, not symlink/junction -aware. Not fixing further: this tool only runs against a trusted local checkout, and exploiting it needs a symlink someone already planted on their own machine — no external input reaches this path.
Description
Adopts GitHub Spec Kit (
/speckit-*) as this repo's active spec-driven workflow for both Claude Code and GitHub Copilot, replacing OpenSpec's active tooling — which stays in place only as a frozen historical record inopenspec/. Investigated the official Spec Kit docs and LightSpeed's internal adoption guide first, installed and verified both agent integrations, ratified a project constitution derived fromAGENTS.md, then retired OpenSpec's now-superseded skills, prompts, and commands for both agents.Changes
specify initviauvxfor--integration claudeand--integration copilot; verified withgit status/git diffafter each step that no existing files were overwritten (clean merge into a non-empty repo)..specify/memory/constitution.mdv1.0.0, derived entirely fromAGENTS.md— 7 core principles (theme-first architecture, PHP minimalism, accessibility baseline, security by default, small-diffs/dependency discipline, verify-before-implementing WordPress core behavior, fixed folder conventions), plus governance sections covering site identity constraints and the new spec-driven workflow/branching rules.AGENTS.mdupdated: new "Spec-Driven Workflow" section documenting the/speckit-*command sequence and branch-before-specify rule, expanded "AI Folder Expectations" table (.specify/,specs/,openspec/), 2 new numbered rules, and a corrected repo-structure tree (previously missingopenspec/entirely)..github/prompts/opsx-*.prompt.md,.claude/skills/openspec-*/,.github/skills/openspec-*/, and.claude/commands/opsx/*.md(24 files total, all unmodified since their original 2026-08-03 commit) — confirmed viagit grepthat no other location referenced them.openspec/left untouched:openspec/specs/andopenspec/changes/archive/remain exactly as-is, now documented inAGENTS.mdas a frozen historical record, not active guidance.CHANGELOG.mdupdated under[Unreleased]for both the addition (Spec Kit) and the removal (OpenSpec tooling).Files Modified
Source files:
AGENTS.mdCHANGELOG.mdNew files:
.specify/(config, templates, scripts,memory/constitution.md).claude/skills/speckit-*/,.github/skills/speckit-*/(10 skills each, for Claude Code and Copilot)Removed files:
.github/prompts/opsx-*.prompt.md(6).claude/skills/openspec-*/(6).github/skills/openspec-*/(6).claude/commands/opsx/*.md(6)Key Improvements
/speckit-plan//speckit-tasksrun something concrete to check against, instead of relying on agents re-readingAGENTS.mdfrom scratch each timeopenspec/— nothing archived was rewritten or deletedgit grep)Related Issues
Closes LS-4126 — Adopt GitHub Spec Kit, retire OpenSpec tooling
Testing
npm run lint— passesnpm run theme:validate— passesgit status/git diff --statafter each install step that no existing tracked file was modified or overwrittenDeployment Notes
theme.json)uv/uvxinstalled locally to run any future/speckit-*command that shells out to the PowerShell scripts in.specify/scripts/powershell/Checklist
develop)npm run lintandnpm run theme:validateboth passAGENTS.mdandCHANGELOG.md