Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/add-review-impl-vs-plan-workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fission-ai/openspec": minor
---

Add an optional `/opsx:review` workflow for read-only implementation review against an OpenSpec change plan.
26 changes: 26 additions & 0 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ For workflow patterns and when to use each command, see [Workflows](workflows.md
| `/opsx:continue` | Create the next artifact based on dependencies |
| `/opsx:ff` | Fast-forward: create all planning artifacts at once |
| `/opsx:verify` | Validate implementation matches artifacts |
| `/opsx:review` | Read-only review of implementation against the change plan |
| `/opsx:bulk-archive` | Archive multiple changes at once |
| `/opsx:onboard` | Guided tutorial through the complete workflow |

Expand Down Expand Up @@ -385,6 +386,31 @@ AI: Verifying add-dark-mode...

---

### `/opsx:review`

Run a read-only implementation review against the OpenSpec change plan. This is stricter and more evidence-focused than `/opsx:verify`: it checks whether the default runtime path, producer/consumer wiring, tests, config, examples, and docs actually support the requirements and tasks.

**Syntax:**
```
/opsx:review [change-name]
```

**Arguments:**
| Argument | Required | Description |
|----------|----------|-------------|
| `change-name` | No | Which change to review (inferred from context if not provided) |

**What it does:**
- Reads proposal, tasks, design, and delta specs
- Builds a requirement/task/design-to-code review matrix
- Inspects implementation, tests, runtime wiring, config, and docs
- Reports BLOCKER, WARNING, and NOTE findings
- Does not edit code or artifacts

Use `/opsx:review` when you want a code-review style answer to "does the implementation really match the approved plan?" Use `/opsx:verify` when you want the lighter archive-readiness check.

---

### `/opsx:sync`

**Optional command.** Merge delta specs from a change into main specs. Archive will prompt to sync if needed, so you typically don't need to run this manually.
Expand Down
2 changes: 1 addition & 1 deletion docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Explore to think it through, propose to draft the plan, apply to build it, archi

### What are `core` and expanded profiles?

A profile decides which slash commands get installed. **Core** (the default) gives you `propose`, `explore`, `apply`, `sync`, `archive`. The **expanded** set adds `new`, `continue`, `ff`, `verify`, `bulk-archive`, and `onboard` for finer control. Switch with `openspec config profile`, then apply with `openspec update`.
A profile decides which slash commands get installed. **Core** (the default) gives you `propose`, `explore`, `apply`, `sync`, `archive`. The **expanded** set adds `new`, `continue`, `ff`, `verify`, `review`, `bulk-archive`, and `onboard` for finer control. Switch with `openspec config profile`, then apply with `openspec update`.

### Do I need to run `/opsx:sync`?

Expand Down
2 changes: 1 addition & 1 deletion docs/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Terms are grouped by topic, then alphabetized within each group.

**Command file.** A per-tool slash command file (`.../commands/opsx-*`). The older delivery mechanism, still supported alongside skills. You rarely touch these directly.

**Profile.** The set of slash commands installed in your project. **Core** (the default) is `propose`, `explore`, `apply`, `sync`, `archive`. The **expanded** set adds `new`, `continue`, `ff`, `verify`, `bulk-archive`, `onboard`. Change it with `openspec config profile`.
**Profile.** The set of slash commands installed in your project. **Core** (the default) is `propose`, `explore`, `apply`, `sync`, `archive`. The **expanded** set adds `new`, `continue`, `ff`, `verify`, `review`, `bulk-archive`, `onboard`. Change it with `openspec config profile`.

**Delivery.** Whether OpenSpec installs skills, command files, or both for your tools. Configured globally and applied with `openspec update`.

Expand Down
2 changes: 1 addition & 1 deletion docs/how-commands-work.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ By default, OpenSpec installs the **core** set of slash commands:

A good default rhythm: `explore` when you're figuring out what to do, then `propose`, `apply`, `archive`. The [Explore First](explore.md) guide explains why that opening step pays off.

There's also an **expanded** set for people who want finer control (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:bulk-archive`, `/opsx:onboard`). You turn it on with `openspec config profile`, then apply it with `openspec update`.
There's also an **expanded** set for people who want finer control (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:review`, `/opsx:bulk-archive`, `/opsx:onboard`). You turn it on with `openspec config profile`, then apply it with `openspec update`.

New to all of this? `/opsx:onboard` (in the expanded set) walks you through a complete change on your own codebase, narrating each step. It's the friendliest possible introduction.

Expand Down
1 change: 1 addition & 0 deletions docs/migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ Command availability is profile-dependent:
| `/opsx:continue` | Create the next artifact (one at a time) |
| `/opsx:ff` | Fast-forward—create planning artifacts at once |
| `/opsx:verify` | Validate implementation matches specs |
| `/opsx:review` | Read-only implementation review against the change plan |
| `/opsx:sync` | Merge delta specs into main specs |
| `/opsx:bulk-archive` | Archive multiple changes at once |
| `/opsx:onboard` | Guided end-to-end onboarding workflow |
Expand Down
3 changes: 2 additions & 1 deletion docs/opsx.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ openspec init

This creates skills in `.claude/skills/` (or equivalent) that AI coding assistants auto-detect.

By default, OpenSpec uses the `core` workflow profile (`propose`, `explore`, `apply`, `sync`, `archive`). If you want the expanded workflow commands (`new`, `continue`, `ff`, `verify`, `bulk-archive`, `onboard`), configure them with `openspec config profile` and apply with `openspec update`.
By default, OpenSpec uses the `core` workflow profile (`propose`, `explore`, `apply`, `sync`, `archive`). If you want the expanded workflow commands (`new`, `continue`, `ff`, `verify`, `review`, `bulk-archive`, `onboard`), configure them with `openspec config profile` and apply with `openspec update`.

During setup, you'll be prompted to create a **project config** (`openspec/config.yaml`). This is optional but recommended.

Expand Down Expand Up @@ -164,6 +164,7 @@ rules:
| `/opsx:ff` | Fast-forward planning artifacts (expanded workflow) |
| `/opsx:apply` | Implement tasks, updating artifacts as needed |
| `/opsx:verify` | Validate implementation against artifacts (expanded workflow) |
| `/opsx:review` | Read-only implementation review against the change plan (expanded workflow) |
| `/opsx:sync` | Sync delta specs to main (default workflow, optional) |
| `/opsx:archive` | Archive when done |
| `/opsx:bulk-archive` | Archive multiple completed changes (expanded workflow) |
Expand Down
5 changes: 3 additions & 2 deletions docs/supported-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ By default, OpenSpec uses the `core` profile, which includes:
- `sync`
- `archive`

You can enable expanded workflows (`new`, `continue`, `ff`, `verify`, `bulk-archive`, `onboard`) via `openspec config profile`, then run `openspec update`.
You can enable expanded workflows (`new`, `continue`, `ff`, `verify`, `review`, `bulk-archive`, `onboard`) via `openspec config profile`, then run `openspec update`.

## Tool Directory Reference

Expand Down Expand Up @@ -83,7 +83,7 @@ OpenSpec installs workflow artifacts based on selected workflows:

- **Core profile (default):** `propose`, `explore`, `apply`, `sync`, `archive`
- **Custom selection:** any subset of all workflow IDs:
`propose`, `explore`, `new`, `continue`, `apply`, `ff`, `sync`, `archive`, `bulk-archive`, `verify`, `onboard`
`propose`, `explore`, `new`, `continue`, `apply`, `ff`, `sync`, `archive`, `bulk-archive`, `verify`, `review`, `onboard`

In other words, skill/command counts are profile-dependent and delivery-dependent, not fixed.

Expand All @@ -101,6 +101,7 @@ When selected by profile/workflow config, OpenSpec generates these skills:
- `openspec-archive-change`
- `openspec-bulk-archive-change`
- `openspec-verify-change`
- `openspec-review-impl-vs-plan`
- `openspec-onboard`

See [Commands](commands.md) for command behavior and [CLI](cli.md) for `init`/`update` options.
Expand Down
15 changes: 14 additions & 1 deletion docs/workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Explore creates no artifacts and writes no code. It's a free, no-stakes conversa

### Expanded/Full Workflow (custom selection)

If you want explicit scaffold-and-build commands (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:bulk-archive`, `/opsx:onboard`), enable them with:
If you want explicit scaffold-and-build commands (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:review`, `/opsx:bulk-archive`, `/opsx:onboard`), enable them with:

```bash
openspec config profile
Expand Down Expand Up @@ -303,6 +303,18 @@ AI: Verifying add-auth...

Verify won't block archive, but it surfaces issues you might want to address first.

#### Review: Check the Implementation Against the Plan

`/opsx:review` is a read-only, code-review style check. It reads the change artifacts, extracts requirements, tasks, scenarios, and design decisions, then inspects the actual implementation path:

- enforcing code
- default runtime entry points
- producer/consumer wiring
- tests and smoke checks
- config, examples, and docs

Use it when "tasks are checked" is not enough and you need evidence that the shipped behavior matches the approved plan. It reports blockers first and does not edit files.

#### Archive: Finalize the Change

`/opsx:archive` completes the change and moves it to the archive:
Expand Down Expand Up @@ -468,6 +480,7 @@ For full command details and options, see [Commands](commands.md).
| `/opsx:ff` | Create all planning artifacts | Expanded mode, clear scope |
| `/opsx:apply` | Implement tasks | Ready to write code |
| `/opsx:verify` | Validate implementation | Expanded mode, before archiving |
| `/opsx:review` | Review implementation against plan | Expanded mode, before or after verify |
| `/opsx:sync` | Merge delta specs | Expanded mode, optional |
| `/opsx:archive` | Complete the change | All work finished |
| `/opsx:bulk-archive` | Archive multiple changes | Expanded mode, parallel work |
Expand Down
6 changes: 4 additions & 2 deletions openspec/specs/cli-init/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ The command SHALL generate Agent Skills for selected AI tools.
#### Scenario: Generating skills for a tool

- **WHEN** a tool is selected during initialization
- **THEN** create 9 skill directories under `.<tool>/skills/`:
- **THEN** create skill directories under `.<tool>/skills/` for the selected workflows:
- `openspec-explore/SKILL.md`
- `openspec-new-change/SKILL.md`
- `openspec-continue-change/SKILL.md`
Expand All @@ -195,6 +195,7 @@ The command SHALL generate Agent Skills for selected AI tools.
- `openspec-sync-specs/SKILL.md`
- `openspec-archive-change/SKILL.md`
- `openspec-bulk-archive-change/SKILL.md`
- `openspec-review-impl-vs-plan/SKILL.md`
- **AND** each SKILL.md SHALL contain YAML frontmatter with name and description
- **AND** each SKILL.md SHALL contain the skill instructions

Expand All @@ -205,7 +206,7 @@ The command SHALL generate opsx slash commands only for selected tools that have
#### Scenario: Generating slash commands for a tool with a registered adapter

- **WHEN** a tool with a registered command adapter is selected during initialization
- **THEN** create 9 slash command files using the tool's command adapter:
- **THEN** create slash command files using the tool's command adapter for the selected workflows:
- `/opsx:explore`
- `/opsx:new`
- `/opsx:continue`
Expand All @@ -215,6 +216,7 @@ The command SHALL generate opsx slash commands only for selected tools that have
- `/opsx:sync`
- `/opsx:archive`
- `/opsx:bulk-archive`
- `/opsx:review`
- **AND** use tool-specific path conventions (e.g., `.claude/commands/opsx/` for Claude)
- **AND** include tool-specific frontmatter format

Expand Down
4 changes: 4 additions & 0 deletions src/commands/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ const WORKFLOW_PROMPT_META: Record<string, WorkflowPromptMeta> = {
name: 'Verify change',
description: 'Run verification checks against a change',
},
review: {
name: 'Review implementation',
description: 'Read-only review of code against the change plan',
},
onboard: {
name: 'Onboard',
description: 'Guided onboarding flow for OpenSpec',
Expand Down
1 change: 1 addition & 0 deletions src/core/profile-sync-drift.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const WORKFLOW_TO_SKILL_DIR: Record<WorkflowId, string> = {
'archive': 'openspec-archive-change',
'bulk-archive': 'openspec-bulk-archive-change',
'verify': 'openspec-verify-change',
'review': 'openspec-review-impl-vs-plan',
'onboard': 'openspec-onboard',
'propose': 'openspec-propose',
};
Expand Down
1 change: 1 addition & 0 deletions src/core/profiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const ALL_WORKFLOWS = [
'archive',
'bulk-archive',
'verify',
'review',
'onboard',
] as const;

Expand Down
4 changes: 4 additions & 0 deletions src/core/shared/skill-generation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
getArchiveChangeSkillTemplate,
getBulkArchiveChangeSkillTemplate,
getVerifyChangeSkillTemplate,
getReviewImplVsPlanSkillTemplate,
getOnboardSkillTemplate,
getOpsxProposeSkillTemplate,
getOpsxExploreCommandTemplate,
Expand All @@ -25,6 +26,7 @@ import {
getOpsxArchiveCommandTemplate,
getOpsxBulkArchiveCommandTemplate,
getOpsxVerifyCommandTemplate,
getOpsxReviewCommandTemplate,
getOpsxOnboardCommandTemplate,
getOpsxProposeCommandTemplate,
type SkillTemplate,
Expand Down Expand Up @@ -64,6 +66,7 @@ export function getSkillTemplates(workflowFilter?: readonly string[]): SkillTemp
{ template: getArchiveChangeSkillTemplate(), dirName: 'openspec-archive-change', workflowId: 'archive' },
{ template: getBulkArchiveChangeSkillTemplate(), dirName: 'openspec-bulk-archive-change', workflowId: 'bulk-archive' },
{ template: getVerifyChangeSkillTemplate(), dirName: 'openspec-verify-change', workflowId: 'verify' },
{ template: getReviewImplVsPlanSkillTemplate(), dirName: 'openspec-review-impl-vs-plan', workflowId: 'review' },
{ template: getOnboardSkillTemplate(), dirName: 'openspec-onboard', workflowId: 'onboard' },
{ template: getOpsxProposeSkillTemplate(), dirName: 'openspec-propose', workflowId: 'propose' },
];
Expand All @@ -90,6 +93,7 @@ export function getCommandTemplates(workflowFilter?: readonly string[]): Command
{ template: getOpsxArchiveCommandTemplate(), id: 'archive' },
{ template: getOpsxBulkArchiveCommandTemplate(), id: 'bulk-archive' },
{ template: getOpsxVerifyCommandTemplate(), id: 'verify' },
{ template: getOpsxReviewCommandTemplate(), id: 'review' },
{ template: getOpsxOnboardCommandTemplate(), id: 'onboard' },
{ template: getOpsxProposeCommandTemplate(), id: 'propose' },
];
Expand Down
1 change: 1 addition & 0 deletions src/core/templates/skill-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export { getSyncSpecsSkillTemplate, getOpsxSyncCommandTemplate } from './workflo
export { getArchiveChangeSkillTemplate, getOpsxArchiveCommandTemplate } from './workflows/archive-change.js';
export { getBulkArchiveChangeSkillTemplate, getOpsxBulkArchiveCommandTemplate } from './workflows/bulk-archive-change.js';
export { getVerifyChangeSkillTemplate, getOpsxVerifyCommandTemplate } from './workflows/verify-change.js';
export { getReviewImplVsPlanSkillTemplate, getOpsxReviewCommandTemplate } from './workflows/review-impl-vs-plan.js';
export { getOnboardSkillTemplate, getOpsxOnboardCommandTemplate } from './workflows/onboard.js';
export { getOpsxProposeSkillTemplate, getOpsxProposeCommandTemplate } from './workflows/propose.js';
export { getFeedbackSkillTemplate } from './workflows/feedback.js';
116 changes: 116 additions & 0 deletions src/core/templates/workflows/review-impl-vs-plan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/**
* Skill Template Workflow Modules
*/
import type { SkillTemplate, CommandTemplate } from '../types.js';
import { STORE_SELECTION_GUIDANCE } from './store-selection.js';

const REVIEW_IMPL_VS_PLAN_INSTRUCTIONS = `Review real implementation against an OpenSpec change plan. This is a read-only review: inspect artifacts, code, tests, configuration, and documented runtime paths, then report gaps. Do not edit files.

${STORE_SELECTION_GUIDANCE}

**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.

**Steps**

1. **Resolve the change**

If a change name is provided, use it. Otherwise:
- Infer from conversation context if the user clearly mentioned one
- If ambiguous, run \`openspec list --json\` and ask the user to select

2. **Check status to understand scope**
\`\`\`bash
openspec status --change "<name>" --json
\`\`\`
Parse:
- \`schemaName\`: workflow schema
- \`planningHome\`, \`changeRoot\`, \`artifactPaths\`, and \`actionContext\`: path and scope context
- Existing artifacts and their concrete paths

3. **Load the plan artifacts**

Read every existing artifact path from the status JSON. For a spec-driven change this usually includes:
- \`proposal.md\`
- \`tasks.md\`
- \`design.md\`, if present
- \`specs/**/spec.md\`

4. **Extract implementation claims**

Build a review matrix from:
- Requirements and scenarios from delta specs
- Task checklist items
- Design decisions or constraints
- Proposal impact areas and named affected systems

5. **Inspect implementation evidence**

For each claim, inspect the actual codebase:
- enforcing code path
- default runtime or user-facing entry point
- producer/consumer wiring
- configuration, examples, and docs that users will actually follow
- tests or smoke checks proving the behavior

Do not accept checklist state or generated contracts as proof by themselves. Verify that the default path is wired end to end.

6. **Report blockers first**

Classify findings:
- **BLOCKER**: shipped behavior is missing, incorrectly wired, unsafe, or contradicts required specs/tasks
- **WARNING**: likely drift, missing scenario coverage, weak test evidence, or docs/config mismatch
- **NOTE**: minor follow-up or assumption

**Output Format**

\`\`\`markdown
## Review: <change-name>

### Verdict
<short pass/fail summary>

### Findings
- [BLOCKER] <file:line> <issue and impact>
- [WARNING] <file:line> <issue and impact>

### Requirement -> Code -> Test
| Plan item | Code evidence | Test evidence | Status |
|-----------|---------------|---------------|--------|

### Runtime Wiring
<default entry points, producer/consumer path, config/docs status>

### Questions
<only questions that block a correct review>
\`\`\`

**Guardrails**
- Stay read-only. Do not edit artifacts or implementation.
- Prioritize concrete bugs, regressions, missing wiring, missing tests, and spec contradictions.
- Cite files and line numbers for findings whenever possible.
- If no issues are found, say that clearly and list any residual test gaps or assumptions.
- Keep summaries brief; findings and evidence are the main output.`;

export function getReviewImplVsPlanSkillTemplate(): SkillTemplate {
return {
name: 'openspec-review-impl-vs-plan',
description: 'Review real implementation against an OpenSpec proposal, tasks, specs, and design. Use when the user wants a read-only check that shipped code matches the approved plan.',
instructions: REVIEW_IMPL_VS_PLAN_INSTRUCTIONS,
license: 'MIT',
compatibility: 'Requires openspec CLI.',
metadata: { author: 'openspec', version: '1.0' },
};
}

export function getOpsxReviewCommandTemplate(): CommandTemplate {
return {
name: 'OPSX: Review',
description: 'Read-only review of implementation against an OpenSpec change plan',
category: 'Workflow',
tags: ['workflow', 'review', 'experimental'],
content: REVIEW_IMPL_VS_PLAN_INSTRUCTIONS.replace(
'**Input**: Optionally specify a change name.',
'**Input**: Optionally specify a change name after `/opsx:review` (e.g., `/opsx:review add-auth`).'
),
};
}
6 changes: 3 additions & 3 deletions test/core/profiles.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ describe('profiles', () => {
});

describe('ALL_WORKFLOWS', () => {
it('should contain all 11 workflows', () => {
expect(ALL_WORKFLOWS).toHaveLength(11);
it('should contain all 12 workflows', () => {
expect(ALL_WORKFLOWS).toHaveLength(12);
});

it('should contain expected workflow IDs', () => {
const expected = [
'propose', 'explore', 'new', 'continue', 'apply',
'ff', 'sync', 'archive', 'bulk-archive', 'verify', 'onboard',
'ff', 'sync', 'archive', 'bulk-archive', 'verify', 'review', 'onboard',
];
expect([...ALL_WORKFLOWS]).toEqual(expected);
});
Expand Down
Loading