diff --git a/.claude/commands/opsx/apply.md b/.claude/commands/opsx/apply.md index bf23721..dc7413e 100644 --- a/.claude/commands/opsx/apply.md +++ b/.claude/commands/opsx/apply.md @@ -1,5 +1,5 @@ --- -name: "OPSX: Apply" +name: 'OPSX: Apply' description: Implement tasks from an OpenSpec change (Experimental) category: Workflow tags: [workflow, artifacts, experimental] @@ -21,9 +21,11 @@ Implement tasks from an OpenSpec change. Always announce: "Using change: " and how to override (e.g., `/opsx:apply `). 2. **Check status to understand the schema** + ```bash openspec status --change "" --json ``` + Parse the JSON to understand: - `schemaName`: The workflow being used (e.g., "spec-driven") - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others) @@ -135,6 +137,7 @@ What would you like to do? ``` **Guardrails** + - Keep going through tasks until done or blocked - Always read context files before starting (from the apply instructions output) - If task is ambiguous, pause and ask before implementing diff --git a/.claude/commands/opsx/archive.md b/.claude/commands/opsx/archive.md index 5e91608..ceeb937 100644 --- a/.claude/commands/opsx/archive.md +++ b/.claude/commands/opsx/archive.md @@ -1,5 +1,5 @@ --- -name: "OPSX: Archive" +name: 'OPSX: Archive' description: Archive a completed change in the experimental workflow category: Workflow tags: [workflow, archive, experimental] @@ -64,6 +64,7 @@ Archive a completed change in the experimental workflow. 5. **Perform the archive** Create the archive directory if it doesn't exist: + ```bash mkdir -p openspec/changes/archive ``` @@ -148,6 +149,7 @@ Target archive directory already exists. ``` **Guardrails** + - Always prompt for change selection if not provided - Use artifact graph (openspec status --json) for completion checking - Don't block archive on warnings - just inform and confirm diff --git a/.claude/commands/opsx/bulk-archive.md b/.claude/commands/opsx/bulk-archive.md index a151410..e0b064e 100644 --- a/.claude/commands/opsx/bulk-archive.md +++ b/.claude/commands/opsx/bulk-archive.md @@ -1,5 +1,5 @@ --- -name: "OPSX: Bulk Archive" +name: 'OPSX: Bulk Archive' description: Archive multiple completed changes at once category: Workflow tags: [workflow, archive, experimental, bulk] @@ -33,16 +33,16 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig For each selected change, collect: a. **Artifact status** - Run `openspec status --change "" --json` - - Parse `schemaName` and `artifacts` list - - Note which artifacts are `done` vs other states + - Parse `schemaName` and `artifacts` list + - Note which artifacts are `done` vs other states b. **Task completion** - Read `openspec/changes//tasks.md` - - Count `- [ ]` (incomplete) vs `- [x]` (complete) - - If no tasks file exists, note as "No tasks" + - Count `- [ ]` (incomplete) vs `- [x]` (complete) + - If no tasks file exists, note as "No tasks" c. **Delta specs** - Check `openspec/changes//specs/` directory - - List which capability specs exist - - For each, extract requirement names (lines matching `### Requirement: `) + - List which capability specs exist + - For each, extract requirement names (lines matching `### Requirement: `) 4. **Detect spec conflicts** @@ -62,18 +62,18 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig a. **Read the delta specs** from each conflicting change to understand what each claims to add/modify b. **Search the codebase** for implementation evidence: - - Look for code implementing requirements from each delta spec - - Check for related files, functions, or tests + - Look for code implementing requirements from each delta spec + - Check for related files, functions, or tests c. **Determine resolution**: - - If only one change is actually implemented -> sync that one's specs - - If both implemented -> apply in chronological order (older first, newer overwrites) - - If neither implemented -> skip spec sync, warn user + - If only one change is actually implemented -> sync that one's specs + - If both implemented -> apply in chronological order (older first, newer overwrites) + - If neither implemented -> skip spec sync, warn user d. **Record resolution** for each conflict: - - Which change's specs to apply - - In what order (if both) - - Rationale (what was found in codebase) + - Which change's specs to apply + - In what order (if both) + - Rationale (what was found in codebase) 6. **Show consolidated status table** @@ -89,12 +89,14 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig ``` For conflicts, show the resolution: + ``` * Conflict resolution: - auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order) ``` For incomplete changes, show warnings: + ``` Warnings: - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks @@ -103,7 +105,6 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig 7. **Confirm batch operation** Use **AskUserQuestion tool** with a single confirmation: - - "Archive N changes?" with options based on status - Options might include: - "Archive all N changes" @@ -117,20 +118,21 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig Process changes in the determined order (respecting conflict resolution): a. **Sync specs** if delta specs exist: - - Use the openspec-sync-specs approach (agent-driven intelligent merge) - - For conflicts, apply in resolved order - - Track if sync was done + - Use the openspec-sync-specs approach (agent-driven intelligent merge) + - For conflicts, apply in resolved order + - Track if sync was done b. **Perform the archive**: - ```bash - mkdir -p openspec/changes/archive - mv openspec/changes/ openspec/changes/archive/YYYY-MM-DD- - ``` + + ```bash + mkdir -p openspec/changes/archive + mv openspec/changes/ openspec/changes/archive/YYYY-MM-DD- + ``` c. **Track outcome** for each change: - - Success: archived successfully - - Failed: error during archive (record error) - - Skipped: user chose not to archive (if applicable) + - Success: archived successfully + - Failed: error during archive (record error) + - Skipped: user chose not to archive (if applicable) 9. **Display summary** @@ -153,6 +155,7 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig ``` If any failures: + ``` Failed 1 change: - some-change: Archive directory already exists @@ -161,6 +164,7 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig **Conflict Resolution Examples** Example 1: Only one implemented + ``` Conflict: specs/auth/spec.md touched by [add-oauth, add-jwt] @@ -176,6 +180,7 @@ Resolution: Only add-oauth is implemented. Will sync add-oauth specs only. ``` Example 2: Both implemented + ``` Conflict: specs/api/spec.md touched by [add-rest-api, add-graphql] @@ -229,6 +234,7 @@ No active changes found. Create a new change to get started. ``` **Guardrails** + - Allow any number of changes (1+ is fine, 2+ is the typical use case) - Always prompt for selection, never auto-select - Detect spec conflicts early and resolve by checking codebase diff --git a/.claude/commands/opsx/continue.md b/.claude/commands/opsx/continue.md index af255c6..59e4c2a 100644 --- a/.claude/commands/opsx/continue.md +++ b/.claude/commands/opsx/continue.md @@ -1,5 +1,5 @@ --- -name: "OPSX: Continue" +name: 'OPSX: Continue' description: Continue working on a change - create the next artifact (Experimental) category: Workflow tags: [workflow, artifacts, experimental] @@ -26,9 +26,11 @@ Continue working on a change by creating the next artifact. **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose. 2. **Check current status** + ```bash openspec status --change "" --json ``` + Parse the JSON to understand current state. The response includes: - `schemaName`: The workflow schema being used (e.g., "spec-driven") - `artifacts`: Array of artifacts with their status ("done", "ready", "blocked") @@ -36,7 +38,7 @@ Continue working on a change by creating the next artifact. 3. **Act based on status**: - --- + *** **If all artifacts are complete (`isComplete: true`)**: - Congratulate the user @@ -44,7 +46,7 @@ Continue working on a change by creating the next artifact. - Suggest: "All artifacts created! You can now implement this change with `/opsx:apply` or archive it with `/opsx:archive`." - STOP - --- + *** **If artifacts are ready to create** (status shows artifacts with `status: "ready"`): - Pick the FIRST artifact with `status: "ready"` from the status output @@ -67,7 +69,7 @@ Continue working on a change by creating the next artifact. - Show what was created and what's now unlocked - STOP after creating ONE artifact - --- + *** **If no artifacts are ready (all blocked)**: - This shouldn't happen with a valid schema @@ -81,6 +83,7 @@ Continue working on a change by creating the next artifact. **Output** After each invocation, show: + - Which artifact was created - Schema workflow being used - Current progress (N/M complete) @@ -94,6 +97,7 @@ The artifact types and their purpose depend on the schema. Use the `instruction` Common artifact patterns: **spec-driven schema** (proposal → specs → design → tasks): + - **proposal.md**: Ask user about the change if not clear. Fill in Why, What Changes, Capabilities, Impact. - The Capabilities section is critical - each capability listed will need a spec file. - **specs//spec.md**: Create one spec per capability listed in the proposal's Capabilities section (use the capability name, not the change name). @@ -103,6 +107,7 @@ Common artifact patterns: For other schemas, follow the `instruction` field from the CLI output. **Guardrails** + - Create ONE artifact per invocation - Always read dependency artifacts before creating a new one - Never skip artifacts or create out of order diff --git a/.claude/commands/opsx/explore.md b/.claude/commands/opsx/explore.md index 30d9c57..ddc7f87 100644 --- a/.claude/commands/opsx/explore.md +++ b/.claude/commands/opsx/explore.md @@ -1,6 +1,6 @@ --- -name: "OPSX: Explore" -description: "Enter explore mode - think through ideas, investigate problems, clarify requirements" +name: 'OPSX: Explore' +description: 'Enter explore mode - think through ideas, investigate problems, clarify requirements' category: Workflow tags: [workflow, explore, experimental, thinking] --- @@ -12,6 +12,7 @@ Enter explore mode. Think deeply. Visualize freely. Follow the conversation wher **This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore. **Input**: The argument after `/opsx:explore` is whatever the user wants to think about. Could be: + - A vague idea: "real-time collaboration" - A specific problem: "the auth system is getting unwieldy" - A change name: "add-dark-mode" (to explore in context of that change) @@ -36,24 +37,28 @@ Enter explore mode. Think deeply. Visualize freely. Follow the conversation wher Depending on what the user brings, you might: **Explore the problem space** + - Ask clarifying questions that emerge from what they said - Challenge assumptions - Reframe the problem - Find analogies **Investigate the codebase** + - Map existing architecture relevant to the discussion - Find integration points - Identify patterns already in use - Surface hidden complexity **Compare options** + - Brainstorm multiple approaches - Build comparison tables - Sketch tradeoffs - Recommend a path (if asked) **Visualize** + ``` ┌─────────────────────────────────────────┐ │ Use ASCII diagrams liberally │ @@ -72,6 +77,7 @@ Depending on what the user brings, you might: ``` **Surface risks and unknowns** + - Identify what could go wrong - Find gaps in understanding - Suggest spikes or investigations @@ -85,11 +91,13 @@ You have full context of the OpenSpec system. Use it naturally, don't force it. ### Check for context At the start, quickly check what exists: + ```bash openspec list --json ``` This tells you: + - If there are active changes - Their names, schemas, and status - What the user might be working on @@ -119,14 +127,14 @@ If the user mentions a change or you detect one is relevant: 3. **Offer to capture when decisions are made** - | Insight Type | Where to Capture | - |--------------|------------------| + | Insight Type | Where to Capture | + | -------------------------- | ---------------------------- | | New requirement discovered | `specs//spec.md` | - | Requirement changed | `specs//spec.md` | - | Design decision made | `design.md` | - | Scope changed | `proposal.md` | - | New work identified | `tasks.md` | - | Assumption invalidated | Relevant artifact | + | Requirement changed | `specs//spec.md` | + | Design decision made | `design.md` | + | Scope changed | `proposal.md` | + | New work identified | `tasks.md` | + | Assumption invalidated | Relevant artifact | Example offers: - "That's a design decision. Capture it in design.md?" diff --git a/.claude/commands/opsx/ff.md b/.claude/commands/opsx/ff.md index 69f749c..6d09be9 100644 --- a/.claude/commands/opsx/ff.md +++ b/.claude/commands/opsx/ff.md @@ -1,5 +1,5 @@ --- -name: "OPSX: Fast Forward" +name: 'OPSX: Fast Forward' description: Create a change and generate all artifacts needed for implementation in one go category: Workflow tags: [workflow, artifacts, experimental] @@ -14,6 +14,7 @@ Fast-forward through artifact creation - generate everything needed to start imp 1. **If no input provided, ask what they want to build** Use the **AskUserQuestion tool** (open-ended, no preset options) to ask: + > "What change do you want to work on? Describe what you want to build or fix." From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). @@ -21,15 +22,19 @@ Fast-forward through artifact creation - generate everything needed to start imp **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. 2. **Create the change directory** + ```bash openspec new change "" ``` + This creates a scaffolded change at `openspec/changes//`. 3. **Get the artifact build order** + ```bash openspec status --change "" --json ``` + Parse the JSON to get: - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`) - `artifacts`: list of all artifacts with their status and dependencies @@ -41,30 +46,30 @@ Fast-forward through artifact creation - generate everything needed to start imp Loop through artifacts in dependency order (artifacts with no pending dependencies first): a. **For each artifact that is `ready` (dependencies satisfied)**: - - Get instructions: - ```bash - openspec instructions --change "" --json - ``` - - The instructions JSON includes: - - `context`: Project background (constraints for you - do NOT include in output) - - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) - - `template`: The structure to use for your output file - - `instruction`: Schema-specific guidance for this artifact type - - `outputPath`: Where to write the artifact - - `dependencies`: Completed artifacts to read for context - - Read any completed dependency files for context - - Create the artifact file using `template` as the structure - - Apply `context` and `rules` as constraints - but do NOT copy them into the file - - Show brief progress: "✓ Created " + - Get instructions: + ```bash + openspec instructions --change "" --json + ``` + - The instructions JSON includes: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance for this artifact type + - `outputPath`: Where to write the artifact + - `dependencies`: Completed artifacts to read for context + - Read any completed dependency files for context + - Create the artifact file using `template` as the structure + - Apply `context` and `rules` as constraints - but do NOT copy them into the file + - Show brief progress: "✓ Created " b. **Continue until all `applyRequires` artifacts are complete** - - After creating each artifact, re-run `openspec status --change "" --json` - - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array - - Stop when all `applyRequires` artifacts are done + - After creating each artifact, re-run `openspec status --change "" --json` + - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array + - Stop when all `applyRequires` artifacts are done c. **If an artifact requires user input** (unclear context): - - Use **AskUserQuestion tool** to clarify - - Then continue with creation + - Use **AskUserQuestion tool** to clarify + - Then continue with creation 5. **Show final status** ```bash @@ -74,6 +79,7 @@ Fast-forward through artifact creation - generate everything needed to start imp **Output** After completing all artifacts, summarize: + - Change name and location - List of artifacts created with brief descriptions - What's ready: "All artifacts created! Ready for implementation." @@ -90,6 +96,7 @@ After completing all artifacts, summarize: - These guide what you write, but should never appear in the output **Guardrails** + - Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`) - Always read dependency artifacts before creating a new one - If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum diff --git a/.claude/commands/opsx/new.md b/.claude/commands/opsx/new.md index ef26cfa..5ff0217 100644 --- a/.claude/commands/opsx/new.md +++ b/.claude/commands/opsx/new.md @@ -1,5 +1,5 @@ --- -name: "OPSX: New" +name: 'OPSX: New' description: Start a new change using the experimental artifact workflow (OPSX) category: Workflow tags: [workflow, artifacts, experimental] @@ -14,6 +14,7 @@ Start a new change using the experimental artifact-driven approach. 1. **If no input provided, ask what they want to build** Use the **AskUserQuestion tool** (open-ended, no preset options) to ask: + > "What change do you want to work on? Describe what you want to build or fix." From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). @@ -31,23 +32,29 @@ Start a new change using the experimental artifact-driven approach. **Otherwise**: Omit `--schema` to use the default. 3. **Create the change directory** + ```bash openspec new change "" ``` + Add `--schema ` only if the user requested a specific workflow. This creates a scaffolded change at `openspec/changes//` with the selected schema. 4. **Show the artifact status** + ```bash openspec status --change "" ``` + This shows which artifacts need to be created and which are ready (dependencies satisfied). 5. **Get instructions for the first artifact** The first artifact depends on the schema. Check the status output to find the first artifact with status "ready". + ```bash openspec instructions --change "" ``` + This outputs the template and context for creating the first artifact. 6. **STOP and wait for user direction** @@ -55,6 +62,7 @@ Start a new change using the experimental artifact-driven approach. **Output** After completing the steps, summarize: + - Change name and location - Schema/workflow being used and its artifact sequence - Current status (0/N artifacts complete) @@ -62,6 +70,7 @@ After completing the steps, summarize: - Prompt: "Ready to create the first artifact? Run `/opsx:continue` or just describe what this change is about and I'll draft it." **Guardrails** + - Do NOT create any artifacts yet - just show the instructions - Do NOT advance beyond showing the first artifact template - If the name is invalid (not kebab-case), ask for a valid name diff --git a/.claude/commands/opsx/onboard.md b/.claude/commands/opsx/onboard.md index 7df677c..67afb02 100644 --- a/.claude/commands/opsx/onboard.md +++ b/.claude/commands/opsx/onboard.md @@ -1,5 +1,5 @@ --- -name: "OPSX: Onboard" +name: 'OPSX: Onboard' description: Guided onboarding - walk through a complete OpenSpec workflow cycle with narration category: Workflow tags: [workflow, onboarding, tutorial, learning] @@ -21,6 +21,7 @@ openspec --version 2>&1 || echo "CLI_NOT_INSTALLED" ``` **If CLI not installed:** + > OpenSpec CLI is not installed. Install it first, then come back to `/opsx:onboard`. Stop here if not installed. @@ -65,6 +66,7 @@ Scan the codebase for small improvement opportunities. Look for: 6. **Missing validation** - User input handlers without validation Also check recent git activity: + ```bash # Unix/macOS git log --oneline -10 2>/dev/null || echo "No git history" @@ -103,6 +105,7 @@ Which task interests you? (Pick a number or describe your own) ``` **If nothing found:** Fall back to asking what the user wants to build: + > I didn't find obvious quick wins in your codebase. What's something small you've been meaning to add or fix? ### Scope Guardrail @@ -135,6 +138,7 @@ Before we create a change, let me quickly show you **explore mode**—it's how y ``` Spend 1-2 minutes investigating the relevant code: + - Read the file(s) involved - Draw a quick ASCII diagram if it helps - Note any considerations @@ -160,6 +164,7 @@ Now let's create a change to hold our work. ## Phase 4: Create the Change **EXPLAIN:** + ``` ## Creating a Change @@ -169,21 +174,25 @@ Let me create one for our task. ``` **DO:** Create the change with a derived kebab-case name: + ```bash openspec new change "" ``` **SHOW:** + ``` Created: `openspec/changes//` The folder structure: ``` + openspec/changes// -├── proposal.md ← Why we're doing this (empty, we'll fill it) -├── design.md ← How we'll build it (empty) -├── specs/ ← Detailed requirements (empty) -└── tasks.md ← Implementation checklist (empty) +├── proposal.md ← Why we're doing this (empty, we'll fill it) +├── design.md ← How we'll build it (empty) +├── specs/ ← Detailed requirements (empty) +└── tasks.md ← Implementation checklist (empty) + ``` Now let's fill in the first artifact—the proposal. @@ -194,6 +203,7 @@ Now let's fill in the first artifact—the proposal. ## Phase 5: Proposal **EXPLAIN:** + ``` ## The Proposal @@ -238,9 +248,11 @@ Does this capture the intent? I can adjust before we save it. **PAUSE** - Wait for user approval/feedback. After approval, save the proposal: + ```bash openspec instructions proposal --change "" --json ``` + Then write the content to `openspec/changes//proposal.md`. ``` @@ -254,6 +266,7 @@ Next up: specs. ## Phase 6: Specs **EXPLAIN:** + ``` ## Specs @@ -263,6 +276,7 @@ For a small task like this, we might only need one spec file. ``` **DO:** Create the spec file: + ```bash # Unix/macOS mkdir -p openspec/changes//specs/ @@ -301,6 +315,7 @@ Save to `openspec/changes//specs//spec.md`. ## Phase 7: Design **EXPLAIN:** + ``` ## Design @@ -346,6 +361,7 @@ Save to `openspec/changes//design.md`. ## Phase 8: Tasks **EXPLAIN:** + ``` ## Tasks @@ -384,6 +400,7 @@ Save to `openspec/changes//tasks.md`. ## Phase 9: Apply (Implementation) **EXPLAIN:** + ``` ## Implementation @@ -418,6 +435,7 @@ The change is implemented! One more step—let's archive it. ## Phase 10: Archive **EXPLAIN:** + ``` ## Archiving @@ -427,11 +445,13 @@ Archived changes become your project's decision history—you can always find th ``` **DO:** + ```bash openspec archive "" ``` **SHOW:** + ``` Archived to: `openspec/changes/archive/YYYY-MM-DD-/` diff --git a/.claude/commands/opsx/propose.md b/.claude/commands/opsx/propose.md index 05276f4..2df4c24 100644 --- a/.claude/commands/opsx/propose.md +++ b/.claude/commands/opsx/propose.md @@ -1,5 +1,5 @@ --- -name: "OPSX: Propose" +name: 'OPSX: Propose' description: Propose a new change - create it and generate all artifacts in one step category: Workflow tags: [workflow, artifacts, experimental] @@ -8,6 +8,7 @@ tags: [workflow, artifacts, experimental] Propose a new change - create the change and generate all artifacts in one step. I'll create a change with artifacts: + - proposal.md (what & why) - design.md (how) - tasks.md (implementation steps) @@ -23,6 +24,7 @@ When ready to implement, run /opsx:apply 1. **If no input provided, ask what they want to build** Use the **AskUserQuestion tool** (open-ended, no preset options) to ask: + > "What change do you want to work on? Describe what you want to build or fix." From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). @@ -30,15 +32,19 @@ When ready to implement, run /opsx:apply **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. 2. **Create the change directory** + ```bash openspec new change "" ``` + This creates a scaffolded change at `openspec/changes//` with `.openspec.yaml`. 3. **Get the artifact build order** + ```bash openspec status --change "" --json ``` + Parse the JSON to get: - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`) - `artifacts`: list of all artifacts with their status and dependencies @@ -50,30 +56,30 @@ When ready to implement, run /opsx:apply Loop through artifacts in dependency order (artifacts with no pending dependencies first): a. **For each artifact that is `ready` (dependencies satisfied)**: - - Get instructions: - ```bash - openspec instructions --change "" --json - ``` - - The instructions JSON includes: - - `context`: Project background (constraints for you - do NOT include in output) - - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) - - `template`: The structure to use for your output file - - `instruction`: Schema-specific guidance for this artifact type - - `outputPath`: Where to write the artifact - - `dependencies`: Completed artifacts to read for context - - Read any completed dependency files for context - - Create the artifact file using `template` as the structure - - Apply `context` and `rules` as constraints - but do NOT copy them into the file - - Show brief progress: "Created " + - Get instructions: + ```bash + openspec instructions --change "" --json + ``` + - The instructions JSON includes: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance for this artifact type + - `outputPath`: Where to write the artifact + - `dependencies`: Completed artifacts to read for context + - Read any completed dependency files for context + - Create the artifact file using `template` as the structure + - Apply `context` and `rules` as constraints - but do NOT copy them into the file + - Show brief progress: "Created " b. **Continue until all `applyRequires` artifacts are complete** - - After creating each artifact, re-run `openspec status --change "" --json` - - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array - - Stop when all `applyRequires` artifacts are done + - After creating each artifact, re-run `openspec status --change "" --json` + - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array + - Stop when all `applyRequires` artifacts are done c. **If an artifact requires user input** (unclear context): - - Use **AskUserQuestion tool** to clarify - - Then continue with creation + - Use **AskUserQuestion tool** to clarify + - Then continue with creation 5. **Show final status** ```bash @@ -83,6 +89,7 @@ When ready to implement, run /opsx:apply **Output** After completing all artifacts, summarize: + - Change name and location - List of artifacts created with brief descriptions - What's ready: "All artifacts created! Ready for implementation." @@ -99,6 +106,7 @@ After completing all artifacts, summarize: - These guide what you write, but should never appear in the output **Guardrails** + - Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`) - Always read dependency artifacts before creating a new one - If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum diff --git a/.claude/commands/opsx/sync.md b/.claude/commands/opsx/sync.md index 1571610..1f8171f 100644 --- a/.claude/commands/opsx/sync.md +++ b/.claude/commands/opsx/sync.md @@ -1,5 +1,5 @@ --- -name: "OPSX: Sync" +name: 'OPSX: Sync' description: Sync delta specs from a change to main specs category: Workflow tags: [workflow, specs, experimental] @@ -43,28 +43,28 @@ This is an **agent-driven** operation - you will read delta specs and directly e c. **Apply changes intelligently**: - **ADDED Requirements:** - - If requirement doesn't exist in main spec → add it - - If requirement already exists → update it to match (treat as implicit MODIFIED) + **ADDED Requirements:** + - If requirement doesn't exist in main spec → add it + - If requirement already exists → update it to match (treat as implicit MODIFIED) - **MODIFIED Requirements:** - - Find the requirement in main spec - - Apply the changes - this can be: - - Adding new scenarios (don't need to copy existing ones) - - Modifying existing scenarios - - Changing the requirement description - - Preserve scenarios/content not mentioned in the delta + **MODIFIED Requirements:** + - Find the requirement in main spec + - Apply the changes - this can be: + - Adding new scenarios (don't need to copy existing ones) + - Modifying existing scenarios + - Changing the requirement description + - Preserve scenarios/content not mentioned in the delta - **REMOVED Requirements:** - - Remove the entire requirement block from main spec + **REMOVED Requirements:** + - Remove the entire requirement block from main spec - **RENAMED Requirements:** - - Find the FROM requirement, rename to TO + **RENAMED Requirements:** + - Find the FROM requirement, rename to TO d. **Create new main spec** if capability doesn't exist yet: - - Create `openspec/specs//spec.md` - - Add Purpose section (can be brief, mark as TBD) - - Add Requirements section with the ADDED requirements + - Create `openspec/specs//spec.md` + - Add Purpose section (can be brief, mark as TBD) + - Add Requirements section with the ADDED requirements 4. **Show summary** @@ -78,16 +78,20 @@ This is an **agent-driven** operation - you will read delta specs and directly e ## ADDED Requirements ### Requirement: New Feature + The system SHALL do something new. #### Scenario: Basic case + - **WHEN** user does X - **THEN** system does Y ## MODIFIED Requirements ### Requirement: Existing Feature + #### Scenario: New scenario to add + - **WHEN** user does A - **THEN** system does B @@ -104,8 +108,9 @@ The system SHALL do something new. **Key Principle: Intelligent Merging** Unlike programmatic merging, you can apply **partial updates**: + - To add a scenario, just include that scenario under MODIFIED - don't copy existing scenarios -- The delta represents *intent*, not a wholesale replacement +- The delta represents _intent_, not a wholesale replacement - Use your judgment to merge changes sensibly **Output On Success** @@ -127,6 +132,7 @@ Main specs are now updated. The change remains active - archive when implementat ``` **Guardrails** + - Read both delta and main specs before making changes - Preserve existing content not mentioned in delta - If something is unclear, ask for clarification diff --git a/.claude/commands/opsx/verify.md b/.claude/commands/opsx/verify.md index 82ab63f..a84f933 100644 --- a/.claude/commands/opsx/verify.md +++ b/.claude/commands/opsx/verify.md @@ -1,5 +1,5 @@ --- -name: "OPSX: Verify" +name: 'OPSX: Verify' description: Verify implementation matches change artifacts before archiving category: Workflow tags: [workflow, verify, experimental] @@ -22,9 +22,11 @@ Verify that an implementation matches the change artifacts (specs, tasks, design **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose. 2. **Check status to understand the schema** + ```bash openspec status --change "" --json ``` + Parse the JSON to understand: - `schemaName`: The workflow being used (e.g., "spec-driven") - Which artifacts exist for this change @@ -106,6 +108,7 @@ Verify that an implementation matches the change artifacts (specs, tasks, design 8. **Generate Verification Report** **Summary Scorecard**: + ``` ## Verification Report: @@ -118,7 +121,6 @@ Verify that an implementation matches the change artifacts (specs, tasks, design ``` **Issues by Priority**: - 1. **CRITICAL** (Must fix before archive): - Incomplete tasks - Missing requirement implementations @@ -157,6 +159,7 @@ Verify that an implementation matches the change artifacts (specs, tasks, design **Output Format** Use clear markdown with: + - Table for summary scorecard - Grouped lists for issues (CRITICAL/WARNING/SUGGESTION) - Code references in format: `file.ts:123` diff --git a/.claude/skills/openspec-apply-change/SKILL.md b/.claude/skills/openspec-apply-change/SKILL.md index d474dc1..dd05a96 100644 --- a/.claude/skills/openspec-apply-change/SKILL.md +++ b/.claude/skills/openspec-apply-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Implement tasks from an OpenSpec change. @@ -25,9 +25,11 @@ Implement tasks from an OpenSpec change. Always announce: "Using change: " and how to override (e.g., `/opsx:apply `). 2. **Check status to understand the schema** + ```bash openspec status --change "" --json ``` + Parse the JSON to understand: - `schemaName`: The workflow being used (e.g., "spec-driven") - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others) @@ -139,6 +141,7 @@ What would you like to do? ``` **Guardrails** + - Keep going through tasks until done or blocked - Always read context files before starting (from the apply instructions output) - If task is ambiguous, pause and ask before implementing diff --git a/.claude/skills/openspec-archive-change/SKILL.md b/.claude/skills/openspec-archive-change/SKILL.md index 9b1f851..4163d13 100644 --- a/.claude/skills/openspec-archive-change/SKILL.md +++ b/.claude/skills/openspec-archive-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Archive a completed change in the experimental workflow. @@ -68,6 +68,7 @@ Archive a completed change in the experimental workflow. 5. **Perform the archive** Create the archive directory if it doesn't exist: + ```bash mkdir -p openspec/changes/archive ``` @@ -105,6 +106,7 @@ All artifacts complete. All tasks complete. ``` **Guardrails** + - Always prompt for change selection if not provided - Use artifact graph (openspec status --json) for completion checking - Don't block archive on warnings - just inform and confirm diff --git a/.claude/skills/openspec-bulk-archive-change/SKILL.md b/.claude/skills/openspec-bulk-archive-change/SKILL.md index d2f199a..db6cf21 100644 --- a/.claude/skills/openspec-bulk-archive-change/SKILL.md +++ b/.claude/skills/openspec-bulk-archive-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Archive multiple completed changes in a single operation. @@ -37,16 +37,16 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig For each selected change, collect: a. **Artifact status** - Run `openspec status --change "" --json` - - Parse `schemaName` and `artifacts` list - - Note which artifacts are `done` vs other states + - Parse `schemaName` and `artifacts` list + - Note which artifacts are `done` vs other states b. **Task completion** - Read `openspec/changes//tasks.md` - - Count `- [ ]` (incomplete) vs `- [x]` (complete) - - If no tasks file exists, note as "No tasks" + - Count `- [ ]` (incomplete) vs `- [x]` (complete) + - If no tasks file exists, note as "No tasks" c. **Delta specs** - Check `openspec/changes//specs/` directory - - List which capability specs exist - - For each, extract requirement names (lines matching `### Requirement: `) + - List which capability specs exist + - For each, extract requirement names (lines matching `### Requirement: `) 4. **Detect spec conflicts** @@ -66,18 +66,18 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig a. **Read the delta specs** from each conflicting change to understand what each claims to add/modify b. **Search the codebase** for implementation evidence: - - Look for code implementing requirements from each delta spec - - Check for related files, functions, or tests + - Look for code implementing requirements from each delta spec + - Check for related files, functions, or tests c. **Determine resolution**: - - If only one change is actually implemented -> sync that one's specs - - If both implemented -> apply in chronological order (older first, newer overwrites) - - If neither implemented -> skip spec sync, warn user + - If only one change is actually implemented -> sync that one's specs + - If both implemented -> apply in chronological order (older first, newer overwrites) + - If neither implemented -> skip spec sync, warn user d. **Record resolution** for each conflict: - - Which change's specs to apply - - In what order (if both) - - Rationale (what was found in codebase) + - Which change's specs to apply + - In what order (if both) + - Rationale (what was found in codebase) 6. **Show consolidated status table** @@ -93,12 +93,14 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig ``` For conflicts, show the resolution: + ``` * Conflict resolution: - auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order) ``` For incomplete changes, show warnings: + ``` Warnings: - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks @@ -107,7 +109,6 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig 7. **Confirm batch operation** Use **AskUserQuestion tool** with a single confirmation: - - "Archive N changes?" with options based on status - Options might include: - "Archive all N changes" @@ -121,20 +122,21 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig Process changes in the determined order (respecting conflict resolution): a. **Sync specs** if delta specs exist: - - Use the openspec-sync-specs approach (agent-driven intelligent merge) - - For conflicts, apply in resolved order - - Track if sync was done + - Use the openspec-sync-specs approach (agent-driven intelligent merge) + - For conflicts, apply in resolved order + - Track if sync was done b. **Perform the archive**: - ```bash - mkdir -p openspec/changes/archive - mv openspec/changes/ openspec/changes/archive/YYYY-MM-DD- - ``` + + ```bash + mkdir -p openspec/changes/archive + mv openspec/changes/ openspec/changes/archive/YYYY-MM-DD- + ``` c. **Track outcome** for each change: - - Success: archived successfully - - Failed: error during archive (record error) - - Skipped: user chose not to archive (if applicable) + - Success: archived successfully + - Failed: error during archive (record error) + - Skipped: user chose not to archive (if applicable) 9. **Display summary** @@ -157,6 +159,7 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig ``` If any failures: + ``` Failed 1 change: - some-change: Archive directory already exists @@ -165,6 +168,7 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig **Conflict Resolution Examples** Example 1: Only one implemented + ``` Conflict: specs/auth/spec.md touched by [add-oauth, add-jwt] @@ -180,6 +184,7 @@ Resolution: Only add-oauth is implemented. Will sync add-oauth specs only. ``` Example 2: Both implemented + ``` Conflict: specs/api/spec.md touched by [add-rest-api, add-graphql] @@ -233,6 +238,7 @@ No active changes found. Create a new change to get started. ``` **Guardrails** + - Allow any number of changes (1+ is fine, 2+ is the typical use case) - Always prompt for selection, never auto-select - Detect spec conflicts early and resolve by checking codebase diff --git a/.claude/skills/openspec-continue-change/SKILL.md b/.claude/skills/openspec-continue-change/SKILL.md index a2856f0..8f7f0ae 100644 --- a/.claude/skills/openspec-continue-change/SKILL.md +++ b/.claude/skills/openspec-continue-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Continue working on a change by creating the next artifact. @@ -30,9 +30,11 @@ Continue working on a change by creating the next artifact. **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose. 2. **Check current status** + ```bash openspec status --change "" --json ``` + Parse the JSON to understand current state. The response includes: - `schemaName`: The workflow schema being used (e.g., "spec-driven") - `artifacts`: Array of artifacts with their status ("done", "ready", "blocked") @@ -40,7 +42,7 @@ Continue working on a change by creating the next artifact. 3. **Act based on status**: - --- + *** **If all artifacts are complete (`isComplete: true`)**: - Congratulate the user @@ -48,7 +50,7 @@ Continue working on a change by creating the next artifact. - Suggest: "All artifacts created! You can now implement this change or archive it." - STOP - --- + *** **If artifacts are ready to create** (status shows artifacts with `status: "ready"`): - Pick the FIRST artifact with `status: "ready"` from the status output @@ -71,7 +73,7 @@ Continue working on a change by creating the next artifact. - Show what was created and what's now unlocked - STOP after creating ONE artifact - --- + *** **If no artifacts are ready (all blocked)**: - This shouldn't happen with a valid schema @@ -85,6 +87,7 @@ Continue working on a change by creating the next artifact. **Output** After each invocation, show: + - Which artifact was created - Schema workflow being used - Current progress (N/M complete) @@ -98,6 +101,7 @@ The artifact types and their purpose depend on the schema. Use the `instruction` Common artifact patterns: **spec-driven schema** (proposal → specs → design → tasks): + - **proposal.md**: Ask user about the change if not clear. Fill in Why, What Changes, Capabilities, Impact. - The Capabilities section is critical - each capability listed will need a spec file. - **specs//spec.md**: Create one spec per capability listed in the proposal's Capabilities section (use the capability name, not the change name). @@ -107,6 +111,7 @@ Common artifact patterns: For other schemas, follow the `instruction` field from the CLI output. **Guardrails** + - Create ONE artifact per invocation - Always read dependency artifacts before creating a new one - Never skip artifacts or create out of order diff --git a/.claude/skills/openspec-explore/SKILL.md b/.claude/skills/openspec-explore/SKILL.md index ffa10ca..84fbec0 100644 --- a/.claude/skills/openspec-explore/SKILL.md +++ b/.claude/skills/openspec-explore/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes. @@ -33,24 +33,28 @@ Enter explore mode. Think deeply. Visualize freely. Follow the conversation wher Depending on what the user brings, you might: **Explore the problem space** + - Ask clarifying questions that emerge from what they said - Challenge assumptions - Reframe the problem - Find analogies **Investigate the codebase** + - Map existing architecture relevant to the discussion - Find integration points - Identify patterns already in use - Surface hidden complexity **Compare options** + - Brainstorm multiple approaches - Build comparison tables - Sketch tradeoffs - Recommend a path (if asked) **Visualize** + ``` ┌─────────────────────────────────────────┐ │ Use ASCII diagrams liberally │ @@ -69,6 +73,7 @@ Depending on what the user brings, you might: ``` **Surface risks and unknowns** + - Identify what could go wrong - Find gaps in understanding - Suggest spikes or investigations @@ -82,11 +87,13 @@ You have full context of the OpenSpec system. Use it naturally, don't force it. ### Check for context At the start, quickly check what exists: + ```bash openspec list --json ``` This tells you: + - If there are active changes - Their names, schemas, and status - What the user might be working on @@ -114,14 +121,14 @@ If the user mentions a change or you detect one is relevant: 3. **Offer to capture when decisions are made** - | Insight Type | Where to Capture | - |--------------|------------------| + | Insight Type | Where to Capture | + | -------------------------- | ---------------------------- | | New requirement discovered | `specs//spec.md` | - | Requirement changed | `specs//spec.md` | - | Design decision made | `design.md` | - | Scope changed | `proposal.md` | - | New work identified | `tasks.md` | - | Assumption invalidated | Relevant artifact | + | Requirement changed | `specs//spec.md` | + | Design decision made | `design.md` | + | Scope changed | `proposal.md` | + | New work identified | `tasks.md` | + | Assumption invalidated | Relevant artifact | Example offers: - "That's a design decision. Capture it in design.md?" @@ -146,6 +153,7 @@ If the user mentions a change or you detect one is relevant: ## Handling Different Entry Points **User brings a vague idea:** + ``` User: I'm thinking about adding real-time collaboration @@ -169,6 +177,7 @@ You: Real-time collab is a big space. Let me think about this... ``` **User brings a specific problem:** + ``` User: The auth system is a mess @@ -200,6 +209,7 @@ You: [reads codebase] ``` **User is stuck mid-implementation:** + ``` User: /opsx:explore add-auth-system The OAuth integration is more complex than expected @@ -217,6 +227,7 @@ You: [reads change artifacts] ``` **User wants to compare options:** + ``` User: Should we use Postgres or SQLite? diff --git a/.claude/skills/openspec-ff-change/SKILL.md b/.claude/skills/openspec-ff-change/SKILL.md index d5f1204..48b7404 100644 --- a/.claude/skills/openspec-ff-change/SKILL.md +++ b/.claude/skills/openspec-ff-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Fast-forward through artifact creation - generate everything needed to start implementation in one go. @@ -18,6 +18,7 @@ Fast-forward through artifact creation - generate everything needed to start imp 1. **If no clear input provided, ask what they want to build** Use the **AskUserQuestion tool** (open-ended, no preset options) to ask: + > "What change do you want to work on? Describe what you want to build or fix." From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). @@ -25,15 +26,19 @@ Fast-forward through artifact creation - generate everything needed to start imp **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. 2. **Create the change directory** + ```bash openspec new change "" ``` + This creates a scaffolded change at `openspec/changes//`. 3. **Get the artifact build order** + ```bash openspec status --change "" --json ``` + Parse the JSON to get: - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`) - `artifacts`: list of all artifacts with their status and dependencies @@ -45,30 +50,30 @@ Fast-forward through artifact creation - generate everything needed to start imp Loop through artifacts in dependency order (artifacts with no pending dependencies first): a. **For each artifact that is `ready` (dependencies satisfied)**: - - Get instructions: - ```bash - openspec instructions --change "" --json - ``` - - The instructions JSON includes: - - `context`: Project background (constraints for you - do NOT include in output) - - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) - - `template`: The structure to use for your output file - - `instruction`: Schema-specific guidance for this artifact type - - `outputPath`: Where to write the artifact - - `dependencies`: Completed artifacts to read for context - - Read any completed dependency files for context - - Create the artifact file using `template` as the structure - - Apply `context` and `rules` as constraints - but do NOT copy them into the file - - Show brief progress: "✓ Created " + - Get instructions: + ```bash + openspec instructions --change "" --json + ``` + - The instructions JSON includes: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance for this artifact type + - `outputPath`: Where to write the artifact + - `dependencies`: Completed artifacts to read for context + - Read any completed dependency files for context + - Create the artifact file using `template` as the structure + - Apply `context` and `rules` as constraints - but do NOT copy them into the file + - Show brief progress: "✓ Created " b. **Continue until all `applyRequires` artifacts are complete** - - After creating each artifact, re-run `openspec status --change "" --json` - - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array - - Stop when all `applyRequires` artifacts are done + - After creating each artifact, re-run `openspec status --change "" --json` + - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array + - Stop when all `applyRequires` artifacts are done c. **If an artifact requires user input** (unclear context): - - Use **AskUserQuestion tool** to clarify - - Then continue with creation + - Use **AskUserQuestion tool** to clarify + - Then continue with creation 5. **Show final status** ```bash @@ -78,6 +83,7 @@ Fast-forward through artifact creation - generate everything needed to start imp **Output** After completing all artifacts, summarize: + - Change name and location - List of artifacts created with brief descriptions - What's ready: "All artifacts created! Ready for implementation." @@ -94,6 +100,7 @@ After completing all artifacts, summarize: - These guide what you write, but should never appear in the output **Guardrails** + - Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`) - Always read dependency artifacts before creating a new one - If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum diff --git a/.claude/skills/openspec-new-change/SKILL.md b/.claude/skills/openspec-new-change/SKILL.md index 607391a..179bb03 100644 --- a/.claude/skills/openspec-new-change/SKILL.md +++ b/.claude/skills/openspec-new-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Start a new change using the experimental artifact-driven approach. @@ -18,6 +18,7 @@ Start a new change using the experimental artifact-driven approach. 1. **If no clear input provided, ask what they want to build** Use the **AskUserQuestion tool** (open-ended, no preset options) to ask: + > "What change do you want to work on? Describe what you want to build or fix." From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). @@ -35,24 +36,30 @@ Start a new change using the experimental artifact-driven approach. **Otherwise**: Omit `--schema` to use the default. 3. **Create the change directory** + ```bash openspec new change "" ``` + Add `--schema ` only if the user requested a specific workflow. This creates a scaffolded change at `openspec/changes//` with the selected schema. 4. **Show the artifact status** + ```bash openspec status --change "" ``` + This shows which artifacts need to be created and which are ready (dependencies satisfied). 5. **Get instructions for the first artifact** The first artifact depends on the schema (e.g., `proposal` for spec-driven). Check the status output to find the first artifact with status "ready". + ```bash openspec instructions --change "" ``` + This outputs the template and context for creating the first artifact. 6. **STOP and wait for user direction** @@ -60,6 +67,7 @@ Start a new change using the experimental artifact-driven approach. **Output** After completing the steps, summarize: + - Change name and location - Schema/workflow being used and its artifact sequence - Current status (0/N artifacts complete) @@ -67,6 +75,7 @@ After completing the steps, summarize: - Prompt: "Ready to create the first artifact? Just describe what this change is about and I'll draft it, or ask me to continue." **Guardrails** + - Do NOT create any artifacts yet - just show the instructions - Do NOT advance beyond showing the first artifact template - If the name is invalid (not kebab-case), ask for a valid name diff --git a/.claude/skills/openspec-onboard/SKILL.md b/.claude/skills/openspec-onboard/SKILL.md index 9076b5d..9425535 100644 --- a/.claude/skills/openspec-onboard/SKILL.md +++ b/.claude/skills/openspec-onboard/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Guide the user through their first complete OpenSpec workflow cycle. This is a teaching experience—you'll do real work in their codebase while explaining each step. @@ -25,6 +25,7 @@ openspec --version 2>&1 || echo "CLI_NOT_INSTALLED" ``` **If CLI not installed:** + > OpenSpec CLI is not installed. Install it first, then come back to `/opsx:onboard`. Stop here if not installed. @@ -69,6 +70,7 @@ Scan the codebase for small improvement opportunities. Look for: 6. **Missing validation** - User input handlers without validation Also check recent git activity: + ```bash # Unix/macOS git log --oneline -10 2>/dev/null || echo "No git history" @@ -107,6 +109,7 @@ Which task interests you? (Pick a number or describe your own) ``` **If nothing found:** Fall back to asking what the user wants to build: + > I didn't find obvious quick wins in your codebase. What's something small you've been meaning to add or fix? ### Scope Guardrail @@ -139,6 +142,7 @@ Before we create a change, let me quickly show you **explore mode**—it's how y ``` Spend 1-2 minutes investigating the relevant code: + - Read the file(s) involved - Draw a quick ASCII diagram if it helps - Note any considerations @@ -164,6 +168,7 @@ Now let's create a change to hold our work. ## Phase 4: Create the Change **EXPLAIN:** + ``` ## Creating a Change @@ -173,21 +178,25 @@ Let me create one for our task. ``` **DO:** Create the change with a derived kebab-case name: + ```bash openspec new change "" ``` **SHOW:** + ``` Created: `openspec/changes//` The folder structure: ``` + openspec/changes// -├── proposal.md ← Why we're doing this (empty, we'll fill it) -├── design.md ← How we'll build it (empty) -├── specs/ ← Detailed requirements (empty) -└── tasks.md ← Implementation checklist (empty) +├── proposal.md ← Why we're doing this (empty, we'll fill it) +├── design.md ← How we'll build it (empty) +├── specs/ ← Detailed requirements (empty) +└── tasks.md ← Implementation checklist (empty) + ``` Now let's fill in the first artifact—the proposal. @@ -198,6 +207,7 @@ Now let's fill in the first artifact—the proposal. ## Phase 5: Proposal **EXPLAIN:** + ``` ## The Proposal @@ -242,9 +252,11 @@ Does this capture the intent? I can adjust before we save it. **PAUSE** - Wait for user approval/feedback. After approval, save the proposal: + ```bash openspec instructions proposal --change "" --json ``` + Then write the content to `openspec/changes//proposal.md`. ``` @@ -258,6 +270,7 @@ Next up: specs. ## Phase 6: Specs **EXPLAIN:** + ``` ## Specs @@ -267,6 +280,7 @@ For a small task like this, we might only need one spec file. ``` **DO:** Create the spec file: + ```bash # Unix/macOS mkdir -p openspec/changes//specs/ @@ -305,6 +319,7 @@ Save to `openspec/changes//specs//spec.md`. ## Phase 7: Design **EXPLAIN:** + ``` ## Design @@ -350,6 +365,7 @@ Save to `openspec/changes//design.md`. ## Phase 8: Tasks **EXPLAIN:** + ``` ## Tasks @@ -388,6 +404,7 @@ Save to `openspec/changes//tasks.md`. ## Phase 9: Apply (Implementation) **EXPLAIN:** + ``` ## Implementation @@ -422,6 +439,7 @@ The change is implemented! One more step—let's archive it. ## Phase 10: Archive **EXPLAIN:** + ``` ## Archiving @@ -431,11 +449,13 @@ Archived changes become your project's decision history—you can always find th ``` **DO:** + ```bash openspec archive "" ``` **SHOW:** + ``` Archived to: `openspec/changes/archive/YYYY-MM-DD-/` diff --git a/.claude/skills/openspec-propose/SKILL.md b/.claude/skills/openspec-propose/SKILL.md index d27bc53..5ceeeb4 100644 --- a/.claude/skills/openspec-propose/SKILL.md +++ b/.claude/skills/openspec-propose/SKILL.md @@ -5,13 +5,14 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Propose a new change - create the change and generate all artifacts in one step. I'll create a change with artifacts: + - proposal.md (what & why) - design.md (how) - tasks.md (implementation steps) @@ -27,6 +28,7 @@ When ready to implement, run /opsx:apply 1. **If no clear input provided, ask what they want to build** Use the **AskUserQuestion tool** (open-ended, no preset options) to ask: + > "What change do you want to work on? Describe what you want to build or fix." From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). @@ -34,15 +36,19 @@ When ready to implement, run /opsx:apply **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. 2. **Create the change directory** + ```bash openspec new change "" ``` + This creates a scaffolded change at `openspec/changes//` with `.openspec.yaml`. 3. **Get the artifact build order** + ```bash openspec status --change "" --json ``` + Parse the JSON to get: - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`) - `artifacts`: list of all artifacts with their status and dependencies @@ -54,30 +60,30 @@ When ready to implement, run /opsx:apply Loop through artifacts in dependency order (artifacts with no pending dependencies first): a. **For each artifact that is `ready` (dependencies satisfied)**: - - Get instructions: - ```bash - openspec instructions --change "" --json - ``` - - The instructions JSON includes: - - `context`: Project background (constraints for you - do NOT include in output) - - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) - - `template`: The structure to use for your output file - - `instruction`: Schema-specific guidance for this artifact type - - `outputPath`: Where to write the artifact - - `dependencies`: Completed artifacts to read for context - - Read any completed dependency files for context - - Create the artifact file using `template` as the structure - - Apply `context` and `rules` as constraints - but do NOT copy them into the file - - Show brief progress: "Created " + - Get instructions: + ```bash + openspec instructions --change "" --json + ``` + - The instructions JSON includes: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance for this artifact type + - `outputPath`: Where to write the artifact + - `dependencies`: Completed artifacts to read for context + - Read any completed dependency files for context + - Create the artifact file using `template` as the structure + - Apply `context` and `rules` as constraints - but do NOT copy them into the file + - Show brief progress: "Created " b. **Continue until all `applyRequires` artifacts are complete** - - After creating each artifact, re-run `openspec status --change "" --json` - - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array - - Stop when all `applyRequires` artifacts are done + - After creating each artifact, re-run `openspec status --change "" --json` + - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array + - Stop when all `applyRequires` artifacts are done c. **If an artifact requires user input** (unclear context): - - Use **AskUserQuestion tool** to clarify - - Then continue with creation + - Use **AskUserQuestion tool** to clarify + - Then continue with creation 5. **Show final status** ```bash @@ -87,6 +93,7 @@ When ready to implement, run /opsx:apply **Output** After completing all artifacts, summarize: + - Change name and location - List of artifacts created with brief descriptions - What's ready: "All artifacts created! Ready for implementation." @@ -103,6 +110,7 @@ After completing all artifacts, summarize: - These guide what you write, but should never appear in the output **Guardrails** + - Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`) - Always read dependency artifacts before creating a new one - If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum diff --git a/.claude/skills/openspec-sync-specs/SKILL.md b/.claude/skills/openspec-sync-specs/SKILL.md index 353bfac..a14f27d 100644 --- a/.claude/skills/openspec-sync-specs/SKILL.md +++ b/.claude/skills/openspec-sync-specs/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Sync delta specs from a change to main specs. @@ -47,28 +47,28 @@ This is an **agent-driven** operation - you will read delta specs and directly e c. **Apply changes intelligently**: - **ADDED Requirements:** - - If requirement doesn't exist in main spec → add it - - If requirement already exists → update it to match (treat as implicit MODIFIED) + **ADDED Requirements:** + - If requirement doesn't exist in main spec → add it + - If requirement already exists → update it to match (treat as implicit MODIFIED) - **MODIFIED Requirements:** - - Find the requirement in main spec - - Apply the changes - this can be: - - Adding new scenarios (don't need to copy existing ones) - - Modifying existing scenarios - - Changing the requirement description - - Preserve scenarios/content not mentioned in the delta + **MODIFIED Requirements:** + - Find the requirement in main spec + - Apply the changes - this can be: + - Adding new scenarios (don't need to copy existing ones) + - Modifying existing scenarios + - Changing the requirement description + - Preserve scenarios/content not mentioned in the delta - **REMOVED Requirements:** - - Remove the entire requirement block from main spec + **REMOVED Requirements:** + - Remove the entire requirement block from main spec - **RENAMED Requirements:** - - Find the FROM requirement, rename to TO + **RENAMED Requirements:** + - Find the FROM requirement, rename to TO d. **Create new main spec** if capability doesn't exist yet: - - Create `openspec/specs//spec.md` - - Add Purpose section (can be brief, mark as TBD) - - Add Requirements section with the ADDED requirements + - Create `openspec/specs//spec.md` + - Add Purpose section (can be brief, mark as TBD) + - Add Requirements section with the ADDED requirements 4. **Show summary** @@ -82,16 +82,20 @@ This is an **agent-driven** operation - you will read delta specs and directly e ## ADDED Requirements ### Requirement: New Feature + The system SHALL do something new. #### Scenario: Basic case + - **WHEN** user does X - **THEN** system does Y ## MODIFIED Requirements ### Requirement: Existing Feature + #### Scenario: New scenario to add + - **WHEN** user does A - **THEN** system does B @@ -108,8 +112,9 @@ The system SHALL do something new. **Key Principle: Intelligent Merging** Unlike programmatic merging, you can apply **partial updates**: + - To add a scenario, just include that scenario under MODIFIED - don't copy existing scenarios -- The delta represents *intent*, not a wholesale replacement +- The delta represents _intent_, not a wholesale replacement - Use your judgment to merge changes sensibly **Output On Success** @@ -131,6 +136,7 @@ Main specs are now updated. The change remains active - archive when implementat ``` **Guardrails** + - Read both delta and main specs before making changes - Preserve existing content not mentioned in delta - If something is unclear, ask for clarification diff --git a/.claude/skills/openspec-verify-change/SKILL.md b/.claude/skills/openspec-verify-change/SKILL.md index 744a088..051f4b1 100644 --- a/.claude/skills/openspec-verify-change/SKILL.md +++ b/.claude/skills/openspec-verify-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Verify that an implementation matches the change artifacts (specs, tasks, design). @@ -26,9 +26,11 @@ Verify that an implementation matches the change artifacts (specs, tasks, design **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose. 2. **Check status to understand the schema** + ```bash openspec status --change "" --json ``` + Parse the JSON to understand: - `schemaName`: The workflow being used (e.g., "spec-driven") - Which artifacts exist for this change @@ -110,6 +112,7 @@ Verify that an implementation matches the change artifacts (specs, tasks, design 8. **Generate Verification Report** **Summary Scorecard**: + ``` ## Verification Report: @@ -122,7 +125,6 @@ Verify that an implementation matches the change artifacts (specs, tasks, design ``` **Issues by Priority**: - 1. **CRITICAL** (Must fix before archive): - Incomplete tasks - Missing requirement implementations @@ -161,6 +163,7 @@ Verify that an implementation matches the change artifacts (specs, tasks, design **Output Format** Use clear markdown with: + - Table for summary scorecard - Grouped lists for issues (CRITICAL/WARNING/SUGGESTION) - Code references in format: `file.ts:123` diff --git a/.github/prompts/opsx-apply.prompt.md b/.github/prompts/opsx-apply.prompt.md index 494e10e..fa046f6 100644 --- a/.github/prompts/opsx-apply.prompt.md +++ b/.github/prompts/opsx-apply.prompt.md @@ -18,9 +18,11 @@ Implement tasks from an OpenSpec change. Always announce: "Using change: " and how to override (e.g., `/opsx:apply `). 2. **Check status to understand the schema** + ```bash openspec status --change "" --json ``` + Parse the JSON to understand: - `schemaName`: The workflow being used (e.g., "spec-driven") - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others) @@ -132,6 +134,7 @@ What would you like to do? ``` **Guardrails** + - Keep going through tasks until done or blocked - Always read context files before starting (from the apply instructions output) - If task is ambiguous, pause and ask before implementing diff --git a/.github/prompts/opsx-archive.prompt.md b/.github/prompts/opsx-archive.prompt.md index 1163776..c127905 100644 --- a/.github/prompts/opsx-archive.prompt.md +++ b/.github/prompts/opsx-archive.prompt.md @@ -61,6 +61,7 @@ Archive a completed change in the experimental workflow. 5. **Perform the archive** Create the archive directory if it doesn't exist: + ```bash mkdir -p openspec/changes/archive ``` @@ -145,6 +146,7 @@ Target archive directory already exists. ``` **Guardrails** + - Always prompt for change selection if not provided - Use artifact graph (openspec status --json) for completion checking - Don't block archive on warnings - just inform and confirm diff --git a/.github/prompts/opsx-bulk-archive.prompt.md b/.github/prompts/opsx-bulk-archive.prompt.md index be3f901..650d2c1 100644 --- a/.github/prompts/opsx-bulk-archive.prompt.md +++ b/.github/prompts/opsx-bulk-archive.prompt.md @@ -30,16 +30,16 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig For each selected change, collect: a. **Artifact status** - Run `openspec status --change "" --json` - - Parse `schemaName` and `artifacts` list - - Note which artifacts are `done` vs other states + - Parse `schemaName` and `artifacts` list + - Note which artifacts are `done` vs other states b. **Task completion** - Read `openspec/changes//tasks.md` - - Count `- [ ]` (incomplete) vs `- [x]` (complete) - - If no tasks file exists, note as "No tasks" + - Count `- [ ]` (incomplete) vs `- [x]` (complete) + - If no tasks file exists, note as "No tasks" c. **Delta specs** - Check `openspec/changes//specs/` directory - - List which capability specs exist - - For each, extract requirement names (lines matching `### Requirement: `) + - List which capability specs exist + - For each, extract requirement names (lines matching `### Requirement: `) 4. **Detect spec conflicts** @@ -59,18 +59,18 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig a. **Read the delta specs** from each conflicting change to understand what each claims to add/modify b. **Search the codebase** for implementation evidence: - - Look for code implementing requirements from each delta spec - - Check for related files, functions, or tests + - Look for code implementing requirements from each delta spec + - Check for related files, functions, or tests c. **Determine resolution**: - - If only one change is actually implemented -> sync that one's specs - - If both implemented -> apply in chronological order (older first, newer overwrites) - - If neither implemented -> skip spec sync, warn user + - If only one change is actually implemented -> sync that one's specs + - If both implemented -> apply in chronological order (older first, newer overwrites) + - If neither implemented -> skip spec sync, warn user d. **Record resolution** for each conflict: - - Which change's specs to apply - - In what order (if both) - - Rationale (what was found in codebase) + - Which change's specs to apply + - In what order (if both) + - Rationale (what was found in codebase) 6. **Show consolidated status table** @@ -86,12 +86,14 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig ``` For conflicts, show the resolution: + ``` * Conflict resolution: - auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order) ``` For incomplete changes, show warnings: + ``` Warnings: - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks @@ -100,7 +102,6 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig 7. **Confirm batch operation** Use **AskUserQuestion tool** with a single confirmation: - - "Archive N changes?" with options based on status - Options might include: - "Archive all N changes" @@ -114,20 +115,21 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig Process changes in the determined order (respecting conflict resolution): a. **Sync specs** if delta specs exist: - - Use the openspec-sync-specs approach (agent-driven intelligent merge) - - For conflicts, apply in resolved order - - Track if sync was done + - Use the openspec-sync-specs approach (agent-driven intelligent merge) + - For conflicts, apply in resolved order + - Track if sync was done b. **Perform the archive**: - ```bash - mkdir -p openspec/changes/archive - mv openspec/changes/ openspec/changes/archive/YYYY-MM-DD- - ``` + + ```bash + mkdir -p openspec/changes/archive + mv openspec/changes/ openspec/changes/archive/YYYY-MM-DD- + ``` c. **Track outcome** for each change: - - Success: archived successfully - - Failed: error during archive (record error) - - Skipped: user chose not to archive (if applicable) + - Success: archived successfully + - Failed: error during archive (record error) + - Skipped: user chose not to archive (if applicable) 9. **Display summary** @@ -150,6 +152,7 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig ``` If any failures: + ``` Failed 1 change: - some-change: Archive directory already exists @@ -158,6 +161,7 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig **Conflict Resolution Examples** Example 1: Only one implemented + ``` Conflict: specs/auth/spec.md touched by [add-oauth, add-jwt] @@ -173,6 +177,7 @@ Resolution: Only add-oauth is implemented. Will sync add-oauth specs only. ``` Example 2: Both implemented + ``` Conflict: specs/api/spec.md touched by [add-rest-api, add-graphql] @@ -226,6 +231,7 @@ No active changes found. Create a new change to get started. ``` **Guardrails** + - Allow any number of changes (1+ is fine, 2+ is the typical use case) - Always prompt for selection, never auto-select - Detect spec conflicts early and resolve by checking codebase diff --git a/.github/prompts/opsx-continue.prompt.md b/.github/prompts/opsx-continue.prompt.md index 24b480d..5a99e3a 100644 --- a/.github/prompts/opsx-continue.prompt.md +++ b/.github/prompts/opsx-continue.prompt.md @@ -23,9 +23,11 @@ Continue working on a change by creating the next artifact. **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose. 2. **Check current status** + ```bash openspec status --change "" --json ``` + Parse the JSON to understand current state. The response includes: - `schemaName`: The workflow schema being used (e.g., "spec-driven") - `artifacts`: Array of artifacts with their status ("done", "ready", "blocked") @@ -33,7 +35,7 @@ Continue working on a change by creating the next artifact. 3. **Act based on status**: - --- + *** **If all artifacts are complete (`isComplete: true`)**: - Congratulate the user @@ -41,7 +43,7 @@ Continue working on a change by creating the next artifact. - Suggest: "All artifacts created! You can now implement this change with `/opsx:apply` or archive it with `/opsx:archive`." - STOP - --- + *** **If artifacts are ready to create** (status shows artifacts with `status: "ready"`): - Pick the FIRST artifact with `status: "ready"` from the status output @@ -64,7 +66,7 @@ Continue working on a change by creating the next artifact. - Show what was created and what's now unlocked - STOP after creating ONE artifact - --- + *** **If no artifacts are ready (all blocked)**: - This shouldn't happen with a valid schema @@ -78,6 +80,7 @@ Continue working on a change by creating the next artifact. **Output** After each invocation, show: + - Which artifact was created - Schema workflow being used - Current progress (N/M complete) @@ -91,6 +94,7 @@ The artifact types and their purpose depend on the schema. Use the `instruction` Common artifact patterns: **spec-driven schema** (proposal → specs → design → tasks): + - **proposal.md**: Ask user about the change if not clear. Fill in Why, What Changes, Capabilities, Impact. - The Capabilities section is critical - each capability listed will need a spec file. - **specs//spec.md**: Create one spec per capability listed in the proposal's Capabilities section (use the capability name, not the change name). @@ -100,6 +104,7 @@ Common artifact patterns: For other schemas, follow the `instruction` field from the CLI output. **Guardrails** + - Create ONE artifact per invocation - Always read dependency artifacts before creating a new one - Never skip artifacts or create out of order diff --git a/.github/prompts/opsx-explore.prompt.md b/.github/prompts/opsx-explore.prompt.md index b21a226..d1bece5 100644 --- a/.github/prompts/opsx-explore.prompt.md +++ b/.github/prompts/opsx-explore.prompt.md @@ -9,6 +9,7 @@ Enter explore mode. Think deeply. Visualize freely. Follow the conversation wher **This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore. **Input**: The argument after `/opsx:explore` is whatever the user wants to think about. Could be: + - A vague idea: "real-time collaboration" - A specific problem: "the auth system is getting unwieldy" - A change name: "add-dark-mode" (to explore in context of that change) @@ -33,24 +34,28 @@ Enter explore mode. Think deeply. Visualize freely. Follow the conversation wher Depending on what the user brings, you might: **Explore the problem space** + - Ask clarifying questions that emerge from what they said - Challenge assumptions - Reframe the problem - Find analogies **Investigate the codebase** + - Map existing architecture relevant to the discussion - Find integration points - Identify patterns already in use - Surface hidden complexity **Compare options** + - Brainstorm multiple approaches - Build comparison tables - Sketch tradeoffs - Recommend a path (if asked) **Visualize** + ``` ┌─────────────────────────────────────────┐ │ Use ASCII diagrams liberally │ @@ -69,6 +74,7 @@ Depending on what the user brings, you might: ``` **Surface risks and unknowns** + - Identify what could go wrong - Find gaps in understanding - Suggest spikes or investigations @@ -82,11 +88,13 @@ You have full context of the OpenSpec system. Use it naturally, don't force it. ### Check for context At the start, quickly check what exists: + ```bash openspec list --json ``` This tells you: + - If there are active changes - Their names, schemas, and status - What the user might be working on @@ -116,14 +124,14 @@ If the user mentions a change or you detect one is relevant: 3. **Offer to capture when decisions are made** - | Insight Type | Where to Capture | - |--------------|------------------| + | Insight Type | Where to Capture | + | -------------------------- | ---------------------------- | | New requirement discovered | `specs//spec.md` | - | Requirement changed | `specs//spec.md` | - | Design decision made | `design.md` | - | Scope changed | `proposal.md` | - | New work identified | `tasks.md` | - | Assumption invalidated | Relevant artifact | + | Requirement changed | `specs//spec.md` | + | Design decision made | `design.md` | + | Scope changed | `proposal.md` | + | New work identified | `tasks.md` | + | Assumption invalidated | Relevant artifact | Example offers: - "That's a design decision. Capture it in design.md?" diff --git a/.github/prompts/opsx-ff.prompt.md b/.github/prompts/opsx-ff.prompt.md index 06cea28..e13102e 100644 --- a/.github/prompts/opsx-ff.prompt.md +++ b/.github/prompts/opsx-ff.prompt.md @@ -11,6 +11,7 @@ Fast-forward through artifact creation - generate everything needed to start imp 1. **If no input provided, ask what they want to build** Use the **AskUserQuestion tool** (open-ended, no preset options) to ask: + > "What change do you want to work on? Describe what you want to build or fix." From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). @@ -18,15 +19,19 @@ Fast-forward through artifact creation - generate everything needed to start imp **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. 2. **Create the change directory** + ```bash openspec new change "" ``` + This creates a scaffolded change at `openspec/changes//`. 3. **Get the artifact build order** + ```bash openspec status --change "" --json ``` + Parse the JSON to get: - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`) - `artifacts`: list of all artifacts with their status and dependencies @@ -38,30 +43,30 @@ Fast-forward through artifact creation - generate everything needed to start imp Loop through artifacts in dependency order (artifacts with no pending dependencies first): a. **For each artifact that is `ready` (dependencies satisfied)**: - - Get instructions: - ```bash - openspec instructions --change "" --json - ``` - - The instructions JSON includes: - - `context`: Project background (constraints for you - do NOT include in output) - - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) - - `template`: The structure to use for your output file - - `instruction`: Schema-specific guidance for this artifact type - - `outputPath`: Where to write the artifact - - `dependencies`: Completed artifacts to read for context - - Read any completed dependency files for context - - Create the artifact file using `template` as the structure - - Apply `context` and `rules` as constraints - but do NOT copy them into the file - - Show brief progress: "✓ Created " + - Get instructions: + ```bash + openspec instructions --change "" --json + ``` + - The instructions JSON includes: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance for this artifact type + - `outputPath`: Where to write the artifact + - `dependencies`: Completed artifacts to read for context + - Read any completed dependency files for context + - Create the artifact file using `template` as the structure + - Apply `context` and `rules` as constraints - but do NOT copy them into the file + - Show brief progress: "✓ Created " b. **Continue until all `applyRequires` artifacts are complete** - - After creating each artifact, re-run `openspec status --change "" --json` - - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array - - Stop when all `applyRequires` artifacts are done + - After creating each artifact, re-run `openspec status --change "" --json` + - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array + - Stop when all `applyRequires` artifacts are done c. **If an artifact requires user input** (unclear context): - - Use **AskUserQuestion tool** to clarify - - Then continue with creation + - Use **AskUserQuestion tool** to clarify + - Then continue with creation 5. **Show final status** ```bash @@ -71,6 +76,7 @@ Fast-forward through artifact creation - generate everything needed to start imp **Output** After completing all artifacts, summarize: + - Change name and location - List of artifacts created with brief descriptions - What's ready: "All artifacts created! Ready for implementation." @@ -87,6 +93,7 @@ After completing all artifacts, summarize: - These guide what you write, but should never appear in the output **Guardrails** + - Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`) - Always read dependency artifacts before creating a new one - If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum diff --git a/.github/prompts/opsx-new.prompt.md b/.github/prompts/opsx-new.prompt.md index ec2253d..eeb4aa7 100644 --- a/.github/prompts/opsx-new.prompt.md +++ b/.github/prompts/opsx-new.prompt.md @@ -11,6 +11,7 @@ Start a new change using the experimental artifact-driven approach. 1. **If no input provided, ask what they want to build** Use the **AskUserQuestion tool** (open-ended, no preset options) to ask: + > "What change do you want to work on? Describe what you want to build or fix." From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). @@ -28,23 +29,29 @@ Start a new change using the experimental artifact-driven approach. **Otherwise**: Omit `--schema` to use the default. 3. **Create the change directory** + ```bash openspec new change "" ``` + Add `--schema ` only if the user requested a specific workflow. This creates a scaffolded change at `openspec/changes//` with the selected schema. 4. **Show the artifact status** + ```bash openspec status --change "" ``` + This shows which artifacts need to be created and which are ready (dependencies satisfied). 5. **Get instructions for the first artifact** The first artifact depends on the schema. Check the status output to find the first artifact with status "ready". + ```bash openspec instructions --change "" ``` + This outputs the template and context for creating the first artifact. 6. **STOP and wait for user direction** @@ -52,6 +59,7 @@ Start a new change using the experimental artifact-driven approach. **Output** After completing the steps, summarize: + - Change name and location - Schema/workflow being used and its artifact sequence - Current status (0/N artifacts complete) @@ -59,6 +67,7 @@ After completing the steps, summarize: - Prompt: "Ready to create the first artifact? Run `/opsx:continue` or just describe what this change is about and I'll draft it." **Guardrails** + - Do NOT create any artifacts yet - just show the instructions - Do NOT advance beyond showing the first artifact template - If the name is invalid (not kebab-case), ask for a valid name diff --git a/.github/prompts/opsx-onboard.prompt.md b/.github/prompts/opsx-onboard.prompt.md index 8100b39..7ab2355 100644 --- a/.github/prompts/opsx-onboard.prompt.md +++ b/.github/prompts/opsx-onboard.prompt.md @@ -18,6 +18,7 @@ openspec --version 2>&1 || echo "CLI_NOT_INSTALLED" ``` **If CLI not installed:** + > OpenSpec CLI is not installed. Install it first, then come back to `/opsx:onboard`. Stop here if not installed. @@ -62,6 +63,7 @@ Scan the codebase for small improvement opportunities. Look for: 6. **Missing validation** - User input handlers without validation Also check recent git activity: + ```bash # Unix/macOS git log --oneline -10 2>/dev/null || echo "No git history" @@ -100,6 +102,7 @@ Which task interests you? (Pick a number or describe your own) ``` **If nothing found:** Fall back to asking what the user wants to build: + > I didn't find obvious quick wins in your codebase. What's something small you've been meaning to add or fix? ### Scope Guardrail @@ -132,6 +135,7 @@ Before we create a change, let me quickly show you **explore mode**—it's how y ``` Spend 1-2 minutes investigating the relevant code: + - Read the file(s) involved - Draw a quick ASCII diagram if it helps - Note any considerations @@ -157,6 +161,7 @@ Now let's create a change to hold our work. ## Phase 4: Create the Change **EXPLAIN:** + ``` ## Creating a Change @@ -166,21 +171,25 @@ Let me create one for our task. ``` **DO:** Create the change with a derived kebab-case name: + ```bash openspec new change "" ``` **SHOW:** + ``` Created: `openspec/changes//` The folder structure: ``` + openspec/changes// -├── proposal.md ← Why we're doing this (empty, we'll fill it) -├── design.md ← How we'll build it (empty) -├── specs/ ← Detailed requirements (empty) -└── tasks.md ← Implementation checklist (empty) +├── proposal.md ← Why we're doing this (empty, we'll fill it) +├── design.md ← How we'll build it (empty) +├── specs/ ← Detailed requirements (empty) +└── tasks.md ← Implementation checklist (empty) + ``` Now let's fill in the first artifact—the proposal. @@ -191,6 +200,7 @@ Now let's fill in the first artifact—the proposal. ## Phase 5: Proposal **EXPLAIN:** + ``` ## The Proposal @@ -235,9 +245,11 @@ Does this capture the intent? I can adjust before we save it. **PAUSE** - Wait for user approval/feedback. After approval, save the proposal: + ```bash openspec instructions proposal --change "" --json ``` + Then write the content to `openspec/changes//proposal.md`. ``` @@ -251,6 +263,7 @@ Next up: specs. ## Phase 6: Specs **EXPLAIN:** + ``` ## Specs @@ -260,6 +273,7 @@ For a small task like this, we might only need one spec file. ``` **DO:** Create the spec file: + ```bash # Unix/macOS mkdir -p openspec/changes//specs/ @@ -298,6 +312,7 @@ Save to `openspec/changes//specs//spec.md`. ## Phase 7: Design **EXPLAIN:** + ``` ## Design @@ -343,6 +358,7 @@ Save to `openspec/changes//design.md`. ## Phase 8: Tasks **EXPLAIN:** + ``` ## Tasks @@ -381,6 +397,7 @@ Save to `openspec/changes//tasks.md`. ## Phase 9: Apply (Implementation) **EXPLAIN:** + ``` ## Implementation @@ -415,6 +432,7 @@ The change is implemented! One more step—let's archive it. ## Phase 10: Archive **EXPLAIN:** + ``` ## Archiving @@ -424,11 +442,13 @@ Archived changes become your project's decision history—you can always find th ``` **DO:** + ```bash openspec archive "" ``` **SHOW:** + ``` Archived to: `openspec/changes/archive/YYYY-MM-DD-/` diff --git a/.github/prompts/opsx-propose.prompt.md b/.github/prompts/opsx-propose.prompt.md index cf30b2a..e6caba5 100644 --- a/.github/prompts/opsx-propose.prompt.md +++ b/.github/prompts/opsx-propose.prompt.md @@ -5,6 +5,7 @@ description: Propose a new change - create it and generate all artifacts in one Propose a new change - create the change and generate all artifacts in one step. I'll create a change with artifacts: + - proposal.md (what & why) - design.md (how) - tasks.md (implementation steps) @@ -20,6 +21,7 @@ When ready to implement, run /opsx:apply 1. **If no input provided, ask what they want to build** Use the **AskUserQuestion tool** (open-ended, no preset options) to ask: + > "What change do you want to work on? Describe what you want to build or fix." From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). @@ -27,15 +29,19 @@ When ready to implement, run /opsx:apply **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. 2. **Create the change directory** + ```bash openspec new change "" ``` + This creates a scaffolded change at `openspec/changes//` with `.openspec.yaml`. 3. **Get the artifact build order** + ```bash openspec status --change "" --json ``` + Parse the JSON to get: - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`) - `artifacts`: list of all artifacts with their status and dependencies @@ -47,30 +53,30 @@ When ready to implement, run /opsx:apply Loop through artifacts in dependency order (artifacts with no pending dependencies first): a. **For each artifact that is `ready` (dependencies satisfied)**: - - Get instructions: - ```bash - openspec instructions --change "" --json - ``` - - The instructions JSON includes: - - `context`: Project background (constraints for you - do NOT include in output) - - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) - - `template`: The structure to use for your output file - - `instruction`: Schema-specific guidance for this artifact type - - `outputPath`: Where to write the artifact - - `dependencies`: Completed artifacts to read for context - - Read any completed dependency files for context - - Create the artifact file using `template` as the structure - - Apply `context` and `rules` as constraints - but do NOT copy them into the file - - Show brief progress: "Created " + - Get instructions: + ```bash + openspec instructions --change "" --json + ``` + - The instructions JSON includes: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance for this artifact type + - `outputPath`: Where to write the artifact + - `dependencies`: Completed artifacts to read for context + - Read any completed dependency files for context + - Create the artifact file using `template` as the structure + - Apply `context` and `rules` as constraints - but do NOT copy them into the file + - Show brief progress: "Created " b. **Continue until all `applyRequires` artifacts are complete** - - After creating each artifact, re-run `openspec status --change "" --json` - - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array - - Stop when all `applyRequires` artifacts are done + - After creating each artifact, re-run `openspec status --change "" --json` + - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array + - Stop when all `applyRequires` artifacts are done c. **If an artifact requires user input** (unclear context): - - Use **AskUserQuestion tool** to clarify - - Then continue with creation + - Use **AskUserQuestion tool** to clarify + - Then continue with creation 5. **Show final status** ```bash @@ -80,6 +86,7 @@ When ready to implement, run /opsx:apply **Output** After completing all artifacts, summarize: + - Change name and location - List of artifacts created with brief descriptions - What's ready: "All artifacts created! Ready for implementation." @@ -96,6 +103,7 @@ After completing all artifacts, summarize: - These guide what you write, but should never appear in the output **Guardrails** + - Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`) - Always read dependency artifacts before creating a new one - If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum diff --git a/.github/prompts/opsx-sync.prompt.md b/.github/prompts/opsx-sync.prompt.md index 56b5b33..2cb5e8f 100644 --- a/.github/prompts/opsx-sync.prompt.md +++ b/.github/prompts/opsx-sync.prompt.md @@ -40,28 +40,28 @@ This is an **agent-driven** operation - you will read delta specs and directly e c. **Apply changes intelligently**: - **ADDED Requirements:** - - If requirement doesn't exist in main spec → add it - - If requirement already exists → update it to match (treat as implicit MODIFIED) + **ADDED Requirements:** + - If requirement doesn't exist in main spec → add it + - If requirement already exists → update it to match (treat as implicit MODIFIED) - **MODIFIED Requirements:** - - Find the requirement in main spec - - Apply the changes - this can be: - - Adding new scenarios (don't need to copy existing ones) - - Modifying existing scenarios - - Changing the requirement description - - Preserve scenarios/content not mentioned in the delta + **MODIFIED Requirements:** + - Find the requirement in main spec + - Apply the changes - this can be: + - Adding new scenarios (don't need to copy existing ones) + - Modifying existing scenarios + - Changing the requirement description + - Preserve scenarios/content not mentioned in the delta - **REMOVED Requirements:** - - Remove the entire requirement block from main spec + **REMOVED Requirements:** + - Remove the entire requirement block from main spec - **RENAMED Requirements:** - - Find the FROM requirement, rename to TO + **RENAMED Requirements:** + - Find the FROM requirement, rename to TO d. **Create new main spec** if capability doesn't exist yet: - - Create `openspec/specs//spec.md` - - Add Purpose section (can be brief, mark as TBD) - - Add Requirements section with the ADDED requirements + - Create `openspec/specs//spec.md` + - Add Purpose section (can be brief, mark as TBD) + - Add Requirements section with the ADDED requirements 4. **Show summary** @@ -75,16 +75,20 @@ This is an **agent-driven** operation - you will read delta specs and directly e ## ADDED Requirements ### Requirement: New Feature + The system SHALL do something new. #### Scenario: Basic case + - **WHEN** user does X - **THEN** system does Y ## MODIFIED Requirements ### Requirement: Existing Feature + #### Scenario: New scenario to add + - **WHEN** user does A - **THEN** system does B @@ -101,8 +105,9 @@ The system SHALL do something new. **Key Principle: Intelligent Merging** Unlike programmatic merging, you can apply **partial updates**: + - To add a scenario, just include that scenario under MODIFIED - don't copy existing scenarios -- The delta represents *intent*, not a wholesale replacement +- The delta represents _intent_, not a wholesale replacement - Use your judgment to merge changes sensibly **Output On Success** @@ -124,6 +129,7 @@ Main specs are now updated. The change remains active - archive when implementat ``` **Guardrails** + - Read both delta and main specs before making changes - Preserve existing content not mentioned in delta - If something is unclear, ask for clarification diff --git a/.github/prompts/opsx-verify.prompt.md b/.github/prompts/opsx-verify.prompt.md index 8111873..14ce70f 100644 --- a/.github/prompts/opsx-verify.prompt.md +++ b/.github/prompts/opsx-verify.prompt.md @@ -19,9 +19,11 @@ Verify that an implementation matches the change artifacts (specs, tasks, design **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose. 2. **Check status to understand the schema** + ```bash openspec status --change "" --json ``` + Parse the JSON to understand: - `schemaName`: The workflow being used (e.g., "spec-driven") - Which artifacts exist for this change @@ -103,6 +105,7 @@ Verify that an implementation matches the change artifacts (specs, tasks, design 8. **Generate Verification Report** **Summary Scorecard**: + ``` ## Verification Report: @@ -115,7 +118,6 @@ Verify that an implementation matches the change artifacts (specs, tasks, design ``` **Issues by Priority**: - 1. **CRITICAL** (Must fix before archive): - Incomplete tasks - Missing requirement implementations @@ -154,6 +156,7 @@ Verify that an implementation matches the change artifacts (specs, tasks, design **Output Format** Use clear markdown with: + - Table for summary scorecard - Grouped lists for issues (CRITICAL/WARNING/SUGGESTION) - Code references in format: `file.ts:123` diff --git a/.github/skills/openspec-apply-change/SKILL.md b/.github/skills/openspec-apply-change/SKILL.md index d474dc1..dd05a96 100644 --- a/.github/skills/openspec-apply-change/SKILL.md +++ b/.github/skills/openspec-apply-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Implement tasks from an OpenSpec change. @@ -25,9 +25,11 @@ Implement tasks from an OpenSpec change. Always announce: "Using change: " and how to override (e.g., `/opsx:apply `). 2. **Check status to understand the schema** + ```bash openspec status --change "" --json ``` + Parse the JSON to understand: - `schemaName`: The workflow being used (e.g., "spec-driven") - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others) @@ -139,6 +141,7 @@ What would you like to do? ``` **Guardrails** + - Keep going through tasks until done or blocked - Always read context files before starting (from the apply instructions output) - If task is ambiguous, pause and ask before implementing diff --git a/.github/skills/openspec-archive-change/SKILL.md b/.github/skills/openspec-archive-change/SKILL.md index 9b1f851..4163d13 100644 --- a/.github/skills/openspec-archive-change/SKILL.md +++ b/.github/skills/openspec-archive-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Archive a completed change in the experimental workflow. @@ -68,6 +68,7 @@ Archive a completed change in the experimental workflow. 5. **Perform the archive** Create the archive directory if it doesn't exist: + ```bash mkdir -p openspec/changes/archive ``` @@ -105,6 +106,7 @@ All artifacts complete. All tasks complete. ``` **Guardrails** + - Always prompt for change selection if not provided - Use artifact graph (openspec status --json) for completion checking - Don't block archive on warnings - just inform and confirm diff --git a/.github/skills/openspec-bulk-archive-change/SKILL.md b/.github/skills/openspec-bulk-archive-change/SKILL.md index d2f199a..db6cf21 100644 --- a/.github/skills/openspec-bulk-archive-change/SKILL.md +++ b/.github/skills/openspec-bulk-archive-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Archive multiple completed changes in a single operation. @@ -37,16 +37,16 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig For each selected change, collect: a. **Artifact status** - Run `openspec status --change "" --json` - - Parse `schemaName` and `artifacts` list - - Note which artifacts are `done` vs other states + - Parse `schemaName` and `artifacts` list + - Note which artifacts are `done` vs other states b. **Task completion** - Read `openspec/changes//tasks.md` - - Count `- [ ]` (incomplete) vs `- [x]` (complete) - - If no tasks file exists, note as "No tasks" + - Count `- [ ]` (incomplete) vs `- [x]` (complete) + - If no tasks file exists, note as "No tasks" c. **Delta specs** - Check `openspec/changes//specs/` directory - - List which capability specs exist - - For each, extract requirement names (lines matching `### Requirement: `) + - List which capability specs exist + - For each, extract requirement names (lines matching `### Requirement: `) 4. **Detect spec conflicts** @@ -66,18 +66,18 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig a. **Read the delta specs** from each conflicting change to understand what each claims to add/modify b. **Search the codebase** for implementation evidence: - - Look for code implementing requirements from each delta spec - - Check for related files, functions, or tests + - Look for code implementing requirements from each delta spec + - Check for related files, functions, or tests c. **Determine resolution**: - - If only one change is actually implemented -> sync that one's specs - - If both implemented -> apply in chronological order (older first, newer overwrites) - - If neither implemented -> skip spec sync, warn user + - If only one change is actually implemented -> sync that one's specs + - If both implemented -> apply in chronological order (older first, newer overwrites) + - If neither implemented -> skip spec sync, warn user d. **Record resolution** for each conflict: - - Which change's specs to apply - - In what order (if both) - - Rationale (what was found in codebase) + - Which change's specs to apply + - In what order (if both) + - Rationale (what was found in codebase) 6. **Show consolidated status table** @@ -93,12 +93,14 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig ``` For conflicts, show the resolution: + ``` * Conflict resolution: - auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order) ``` For incomplete changes, show warnings: + ``` Warnings: - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks @@ -107,7 +109,6 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig 7. **Confirm batch operation** Use **AskUserQuestion tool** with a single confirmation: - - "Archive N changes?" with options based on status - Options might include: - "Archive all N changes" @@ -121,20 +122,21 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig Process changes in the determined order (respecting conflict resolution): a. **Sync specs** if delta specs exist: - - Use the openspec-sync-specs approach (agent-driven intelligent merge) - - For conflicts, apply in resolved order - - Track if sync was done + - Use the openspec-sync-specs approach (agent-driven intelligent merge) + - For conflicts, apply in resolved order + - Track if sync was done b. **Perform the archive**: - ```bash - mkdir -p openspec/changes/archive - mv openspec/changes/ openspec/changes/archive/YYYY-MM-DD- - ``` + + ```bash + mkdir -p openspec/changes/archive + mv openspec/changes/ openspec/changes/archive/YYYY-MM-DD- + ``` c. **Track outcome** for each change: - - Success: archived successfully - - Failed: error during archive (record error) - - Skipped: user chose not to archive (if applicable) + - Success: archived successfully + - Failed: error during archive (record error) + - Skipped: user chose not to archive (if applicable) 9. **Display summary** @@ -157,6 +159,7 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig ``` If any failures: + ``` Failed 1 change: - some-change: Archive directory already exists @@ -165,6 +168,7 @@ This skill allows you to batch-archive changes, handling spec conflicts intellig **Conflict Resolution Examples** Example 1: Only one implemented + ``` Conflict: specs/auth/spec.md touched by [add-oauth, add-jwt] @@ -180,6 +184,7 @@ Resolution: Only add-oauth is implemented. Will sync add-oauth specs only. ``` Example 2: Both implemented + ``` Conflict: specs/api/spec.md touched by [add-rest-api, add-graphql] @@ -233,6 +238,7 @@ No active changes found. Create a new change to get started. ``` **Guardrails** + - Allow any number of changes (1+ is fine, 2+ is the typical use case) - Always prompt for selection, never auto-select - Detect spec conflicts early and resolve by checking codebase diff --git a/.github/skills/openspec-continue-change/SKILL.md b/.github/skills/openspec-continue-change/SKILL.md index a2856f0..8f7f0ae 100644 --- a/.github/skills/openspec-continue-change/SKILL.md +++ b/.github/skills/openspec-continue-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Continue working on a change by creating the next artifact. @@ -30,9 +30,11 @@ Continue working on a change by creating the next artifact. **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose. 2. **Check current status** + ```bash openspec status --change "" --json ``` + Parse the JSON to understand current state. The response includes: - `schemaName`: The workflow schema being used (e.g., "spec-driven") - `artifacts`: Array of artifacts with their status ("done", "ready", "blocked") @@ -40,7 +42,7 @@ Continue working on a change by creating the next artifact. 3. **Act based on status**: - --- + *** **If all artifacts are complete (`isComplete: true`)**: - Congratulate the user @@ -48,7 +50,7 @@ Continue working on a change by creating the next artifact. - Suggest: "All artifacts created! You can now implement this change or archive it." - STOP - --- + *** **If artifacts are ready to create** (status shows artifacts with `status: "ready"`): - Pick the FIRST artifact with `status: "ready"` from the status output @@ -71,7 +73,7 @@ Continue working on a change by creating the next artifact. - Show what was created and what's now unlocked - STOP after creating ONE artifact - --- + *** **If no artifacts are ready (all blocked)**: - This shouldn't happen with a valid schema @@ -85,6 +87,7 @@ Continue working on a change by creating the next artifact. **Output** After each invocation, show: + - Which artifact was created - Schema workflow being used - Current progress (N/M complete) @@ -98,6 +101,7 @@ The artifact types and their purpose depend on the schema. Use the `instruction` Common artifact patterns: **spec-driven schema** (proposal → specs → design → tasks): + - **proposal.md**: Ask user about the change if not clear. Fill in Why, What Changes, Capabilities, Impact. - The Capabilities section is critical - each capability listed will need a spec file. - **specs//spec.md**: Create one spec per capability listed in the proposal's Capabilities section (use the capability name, not the change name). @@ -107,6 +111,7 @@ Common artifact patterns: For other schemas, follow the `instruction` field from the CLI output. **Guardrails** + - Create ONE artifact per invocation - Always read dependency artifacts before creating a new one - Never skip artifacts or create out of order diff --git a/.github/skills/openspec-explore/SKILL.md b/.github/skills/openspec-explore/SKILL.md index ffa10ca..84fbec0 100644 --- a/.github/skills/openspec-explore/SKILL.md +++ b/.github/skills/openspec-explore/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes. @@ -33,24 +33,28 @@ Enter explore mode. Think deeply. Visualize freely. Follow the conversation wher Depending on what the user brings, you might: **Explore the problem space** + - Ask clarifying questions that emerge from what they said - Challenge assumptions - Reframe the problem - Find analogies **Investigate the codebase** + - Map existing architecture relevant to the discussion - Find integration points - Identify patterns already in use - Surface hidden complexity **Compare options** + - Brainstorm multiple approaches - Build comparison tables - Sketch tradeoffs - Recommend a path (if asked) **Visualize** + ``` ┌─────────────────────────────────────────┐ │ Use ASCII diagrams liberally │ @@ -69,6 +73,7 @@ Depending on what the user brings, you might: ``` **Surface risks and unknowns** + - Identify what could go wrong - Find gaps in understanding - Suggest spikes or investigations @@ -82,11 +87,13 @@ You have full context of the OpenSpec system. Use it naturally, don't force it. ### Check for context At the start, quickly check what exists: + ```bash openspec list --json ``` This tells you: + - If there are active changes - Their names, schemas, and status - What the user might be working on @@ -114,14 +121,14 @@ If the user mentions a change or you detect one is relevant: 3. **Offer to capture when decisions are made** - | Insight Type | Where to Capture | - |--------------|------------------| + | Insight Type | Where to Capture | + | -------------------------- | ---------------------------- | | New requirement discovered | `specs//spec.md` | - | Requirement changed | `specs//spec.md` | - | Design decision made | `design.md` | - | Scope changed | `proposal.md` | - | New work identified | `tasks.md` | - | Assumption invalidated | Relevant artifact | + | Requirement changed | `specs//spec.md` | + | Design decision made | `design.md` | + | Scope changed | `proposal.md` | + | New work identified | `tasks.md` | + | Assumption invalidated | Relevant artifact | Example offers: - "That's a design decision. Capture it in design.md?" @@ -146,6 +153,7 @@ If the user mentions a change or you detect one is relevant: ## Handling Different Entry Points **User brings a vague idea:** + ``` User: I'm thinking about adding real-time collaboration @@ -169,6 +177,7 @@ You: Real-time collab is a big space. Let me think about this... ``` **User brings a specific problem:** + ``` User: The auth system is a mess @@ -200,6 +209,7 @@ You: [reads codebase] ``` **User is stuck mid-implementation:** + ``` User: /opsx:explore add-auth-system The OAuth integration is more complex than expected @@ -217,6 +227,7 @@ You: [reads change artifacts] ``` **User wants to compare options:** + ``` User: Should we use Postgres or SQLite? diff --git a/.github/skills/openspec-ff-change/SKILL.md b/.github/skills/openspec-ff-change/SKILL.md index d5f1204..48b7404 100644 --- a/.github/skills/openspec-ff-change/SKILL.md +++ b/.github/skills/openspec-ff-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Fast-forward through artifact creation - generate everything needed to start implementation in one go. @@ -18,6 +18,7 @@ Fast-forward through artifact creation - generate everything needed to start imp 1. **If no clear input provided, ask what they want to build** Use the **AskUserQuestion tool** (open-ended, no preset options) to ask: + > "What change do you want to work on? Describe what you want to build or fix." From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). @@ -25,15 +26,19 @@ Fast-forward through artifact creation - generate everything needed to start imp **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. 2. **Create the change directory** + ```bash openspec new change "" ``` + This creates a scaffolded change at `openspec/changes//`. 3. **Get the artifact build order** + ```bash openspec status --change "" --json ``` + Parse the JSON to get: - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`) - `artifacts`: list of all artifacts with their status and dependencies @@ -45,30 +50,30 @@ Fast-forward through artifact creation - generate everything needed to start imp Loop through artifacts in dependency order (artifacts with no pending dependencies first): a. **For each artifact that is `ready` (dependencies satisfied)**: - - Get instructions: - ```bash - openspec instructions --change "" --json - ``` - - The instructions JSON includes: - - `context`: Project background (constraints for you - do NOT include in output) - - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) - - `template`: The structure to use for your output file - - `instruction`: Schema-specific guidance for this artifact type - - `outputPath`: Where to write the artifact - - `dependencies`: Completed artifacts to read for context - - Read any completed dependency files for context - - Create the artifact file using `template` as the structure - - Apply `context` and `rules` as constraints - but do NOT copy them into the file - - Show brief progress: "✓ Created " + - Get instructions: + ```bash + openspec instructions --change "" --json + ``` + - The instructions JSON includes: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance for this artifact type + - `outputPath`: Where to write the artifact + - `dependencies`: Completed artifacts to read for context + - Read any completed dependency files for context + - Create the artifact file using `template` as the structure + - Apply `context` and `rules` as constraints - but do NOT copy them into the file + - Show brief progress: "✓ Created " b. **Continue until all `applyRequires` artifacts are complete** - - After creating each artifact, re-run `openspec status --change "" --json` - - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array - - Stop when all `applyRequires` artifacts are done + - After creating each artifact, re-run `openspec status --change "" --json` + - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array + - Stop when all `applyRequires` artifacts are done c. **If an artifact requires user input** (unclear context): - - Use **AskUserQuestion tool** to clarify - - Then continue with creation + - Use **AskUserQuestion tool** to clarify + - Then continue with creation 5. **Show final status** ```bash @@ -78,6 +83,7 @@ Fast-forward through artifact creation - generate everything needed to start imp **Output** After completing all artifacts, summarize: + - Change name and location - List of artifacts created with brief descriptions - What's ready: "All artifacts created! Ready for implementation." @@ -94,6 +100,7 @@ After completing all artifacts, summarize: - These guide what you write, but should never appear in the output **Guardrails** + - Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`) - Always read dependency artifacts before creating a new one - If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum diff --git a/.github/skills/openspec-new-change/SKILL.md b/.github/skills/openspec-new-change/SKILL.md index 607391a..179bb03 100644 --- a/.github/skills/openspec-new-change/SKILL.md +++ b/.github/skills/openspec-new-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Start a new change using the experimental artifact-driven approach. @@ -18,6 +18,7 @@ Start a new change using the experimental artifact-driven approach. 1. **If no clear input provided, ask what they want to build** Use the **AskUserQuestion tool** (open-ended, no preset options) to ask: + > "What change do you want to work on? Describe what you want to build or fix." From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). @@ -35,24 +36,30 @@ Start a new change using the experimental artifact-driven approach. **Otherwise**: Omit `--schema` to use the default. 3. **Create the change directory** + ```bash openspec new change "" ``` + Add `--schema ` only if the user requested a specific workflow. This creates a scaffolded change at `openspec/changes//` with the selected schema. 4. **Show the artifact status** + ```bash openspec status --change "" ``` + This shows which artifacts need to be created and which are ready (dependencies satisfied). 5. **Get instructions for the first artifact** The first artifact depends on the schema (e.g., `proposal` for spec-driven). Check the status output to find the first artifact with status "ready". + ```bash openspec instructions --change "" ``` + This outputs the template and context for creating the first artifact. 6. **STOP and wait for user direction** @@ -60,6 +67,7 @@ Start a new change using the experimental artifact-driven approach. **Output** After completing the steps, summarize: + - Change name and location - Schema/workflow being used and its artifact sequence - Current status (0/N artifacts complete) @@ -67,6 +75,7 @@ After completing the steps, summarize: - Prompt: "Ready to create the first artifact? Just describe what this change is about and I'll draft it, or ask me to continue." **Guardrails** + - Do NOT create any artifacts yet - just show the instructions - Do NOT advance beyond showing the first artifact template - If the name is invalid (not kebab-case), ask for a valid name diff --git a/.github/skills/openspec-onboard/SKILL.md b/.github/skills/openspec-onboard/SKILL.md index 9076b5d..9425535 100644 --- a/.github/skills/openspec-onboard/SKILL.md +++ b/.github/skills/openspec-onboard/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Guide the user through their first complete OpenSpec workflow cycle. This is a teaching experience—you'll do real work in their codebase while explaining each step. @@ -25,6 +25,7 @@ openspec --version 2>&1 || echo "CLI_NOT_INSTALLED" ``` **If CLI not installed:** + > OpenSpec CLI is not installed. Install it first, then come back to `/opsx:onboard`. Stop here if not installed. @@ -69,6 +70,7 @@ Scan the codebase for small improvement opportunities. Look for: 6. **Missing validation** - User input handlers without validation Also check recent git activity: + ```bash # Unix/macOS git log --oneline -10 2>/dev/null || echo "No git history" @@ -107,6 +109,7 @@ Which task interests you? (Pick a number or describe your own) ``` **If nothing found:** Fall back to asking what the user wants to build: + > I didn't find obvious quick wins in your codebase. What's something small you've been meaning to add or fix? ### Scope Guardrail @@ -139,6 +142,7 @@ Before we create a change, let me quickly show you **explore mode**—it's how y ``` Spend 1-2 minutes investigating the relevant code: + - Read the file(s) involved - Draw a quick ASCII diagram if it helps - Note any considerations @@ -164,6 +168,7 @@ Now let's create a change to hold our work. ## Phase 4: Create the Change **EXPLAIN:** + ``` ## Creating a Change @@ -173,21 +178,25 @@ Let me create one for our task. ``` **DO:** Create the change with a derived kebab-case name: + ```bash openspec new change "" ``` **SHOW:** + ``` Created: `openspec/changes//` The folder structure: ``` + openspec/changes// -├── proposal.md ← Why we're doing this (empty, we'll fill it) -├── design.md ← How we'll build it (empty) -├── specs/ ← Detailed requirements (empty) -└── tasks.md ← Implementation checklist (empty) +├── proposal.md ← Why we're doing this (empty, we'll fill it) +├── design.md ← How we'll build it (empty) +├── specs/ ← Detailed requirements (empty) +└── tasks.md ← Implementation checklist (empty) + ``` Now let's fill in the first artifact—the proposal. @@ -198,6 +207,7 @@ Now let's fill in the first artifact—the proposal. ## Phase 5: Proposal **EXPLAIN:** + ``` ## The Proposal @@ -242,9 +252,11 @@ Does this capture the intent? I can adjust before we save it. **PAUSE** - Wait for user approval/feedback. After approval, save the proposal: + ```bash openspec instructions proposal --change "" --json ``` + Then write the content to `openspec/changes//proposal.md`. ``` @@ -258,6 +270,7 @@ Next up: specs. ## Phase 6: Specs **EXPLAIN:** + ``` ## Specs @@ -267,6 +280,7 @@ For a small task like this, we might only need one spec file. ``` **DO:** Create the spec file: + ```bash # Unix/macOS mkdir -p openspec/changes//specs/ @@ -305,6 +319,7 @@ Save to `openspec/changes//specs//spec.md`. ## Phase 7: Design **EXPLAIN:** + ``` ## Design @@ -350,6 +365,7 @@ Save to `openspec/changes//design.md`. ## Phase 8: Tasks **EXPLAIN:** + ``` ## Tasks @@ -388,6 +404,7 @@ Save to `openspec/changes//tasks.md`. ## Phase 9: Apply (Implementation) **EXPLAIN:** + ``` ## Implementation @@ -422,6 +439,7 @@ The change is implemented! One more step—let's archive it. ## Phase 10: Archive **EXPLAIN:** + ``` ## Archiving @@ -431,11 +449,13 @@ Archived changes become your project's decision history—you can always find th ``` **DO:** + ```bash openspec archive "" ``` **SHOW:** + ``` Archived to: `openspec/changes/archive/YYYY-MM-DD-/` diff --git a/.github/skills/openspec-propose/SKILL.md b/.github/skills/openspec-propose/SKILL.md index d27bc53..5ceeeb4 100644 --- a/.github/skills/openspec-propose/SKILL.md +++ b/.github/skills/openspec-propose/SKILL.md @@ -5,13 +5,14 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Propose a new change - create the change and generate all artifacts in one step. I'll create a change with artifacts: + - proposal.md (what & why) - design.md (how) - tasks.md (implementation steps) @@ -27,6 +28,7 @@ When ready to implement, run /opsx:apply 1. **If no clear input provided, ask what they want to build** Use the **AskUserQuestion tool** (open-ended, no preset options) to ask: + > "What change do you want to work on? Describe what you want to build or fix." From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`). @@ -34,15 +36,19 @@ When ready to implement, run /opsx:apply **IMPORTANT**: Do NOT proceed without understanding what the user wants to build. 2. **Create the change directory** + ```bash openspec new change "" ``` + This creates a scaffolded change at `openspec/changes//` with `.openspec.yaml`. 3. **Get the artifact build order** + ```bash openspec status --change "" --json ``` + Parse the JSON to get: - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`) - `artifacts`: list of all artifacts with their status and dependencies @@ -54,30 +60,30 @@ When ready to implement, run /opsx:apply Loop through artifacts in dependency order (artifacts with no pending dependencies first): a. **For each artifact that is `ready` (dependencies satisfied)**: - - Get instructions: - ```bash - openspec instructions --change "" --json - ``` - - The instructions JSON includes: - - `context`: Project background (constraints for you - do NOT include in output) - - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) - - `template`: The structure to use for your output file - - `instruction`: Schema-specific guidance for this artifact type - - `outputPath`: Where to write the artifact - - `dependencies`: Completed artifacts to read for context - - Read any completed dependency files for context - - Create the artifact file using `template` as the structure - - Apply `context` and `rules` as constraints - but do NOT copy them into the file - - Show brief progress: "Created " + - Get instructions: + ```bash + openspec instructions --change "" --json + ``` + - The instructions JSON includes: + - `context`: Project background (constraints for you - do NOT include in output) + - `rules`: Artifact-specific rules (constraints for you - do NOT include in output) + - `template`: The structure to use for your output file + - `instruction`: Schema-specific guidance for this artifact type + - `outputPath`: Where to write the artifact + - `dependencies`: Completed artifacts to read for context + - Read any completed dependency files for context + - Create the artifact file using `template` as the structure + - Apply `context` and `rules` as constraints - but do NOT copy them into the file + - Show brief progress: "Created " b. **Continue until all `applyRequires` artifacts are complete** - - After creating each artifact, re-run `openspec status --change "" --json` - - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array - - Stop when all `applyRequires` artifacts are done + - After creating each artifact, re-run `openspec status --change "" --json` + - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array + - Stop when all `applyRequires` artifacts are done c. **If an artifact requires user input** (unclear context): - - Use **AskUserQuestion tool** to clarify - - Then continue with creation + - Use **AskUserQuestion tool** to clarify + - Then continue with creation 5. **Show final status** ```bash @@ -87,6 +93,7 @@ When ready to implement, run /opsx:apply **Output** After completing all artifacts, summarize: + - Change name and location - List of artifacts created with brief descriptions - What's ready: "All artifacts created! Ready for implementation." @@ -103,6 +110,7 @@ After completing all artifacts, summarize: - These guide what you write, but should never appear in the output **Guardrails** + - Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`) - Always read dependency artifacts before creating a new one - If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum diff --git a/.github/skills/openspec-sync-specs/SKILL.md b/.github/skills/openspec-sync-specs/SKILL.md index 353bfac..a14f27d 100644 --- a/.github/skills/openspec-sync-specs/SKILL.md +++ b/.github/skills/openspec-sync-specs/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Sync delta specs from a change to main specs. @@ -47,28 +47,28 @@ This is an **agent-driven** operation - you will read delta specs and directly e c. **Apply changes intelligently**: - **ADDED Requirements:** - - If requirement doesn't exist in main spec → add it - - If requirement already exists → update it to match (treat as implicit MODIFIED) + **ADDED Requirements:** + - If requirement doesn't exist in main spec → add it + - If requirement already exists → update it to match (treat as implicit MODIFIED) - **MODIFIED Requirements:** - - Find the requirement in main spec - - Apply the changes - this can be: - - Adding new scenarios (don't need to copy existing ones) - - Modifying existing scenarios - - Changing the requirement description - - Preserve scenarios/content not mentioned in the delta + **MODIFIED Requirements:** + - Find the requirement in main spec + - Apply the changes - this can be: + - Adding new scenarios (don't need to copy existing ones) + - Modifying existing scenarios + - Changing the requirement description + - Preserve scenarios/content not mentioned in the delta - **REMOVED Requirements:** - - Remove the entire requirement block from main spec + **REMOVED Requirements:** + - Remove the entire requirement block from main spec - **RENAMED Requirements:** - - Find the FROM requirement, rename to TO + **RENAMED Requirements:** + - Find the FROM requirement, rename to TO d. **Create new main spec** if capability doesn't exist yet: - - Create `openspec/specs//spec.md` - - Add Purpose section (can be brief, mark as TBD) - - Add Requirements section with the ADDED requirements + - Create `openspec/specs//spec.md` + - Add Purpose section (can be brief, mark as TBD) + - Add Requirements section with the ADDED requirements 4. **Show summary** @@ -82,16 +82,20 @@ This is an **agent-driven** operation - you will read delta specs and directly e ## ADDED Requirements ### Requirement: New Feature + The system SHALL do something new. #### Scenario: Basic case + - **WHEN** user does X - **THEN** system does Y ## MODIFIED Requirements ### Requirement: Existing Feature + #### Scenario: New scenario to add + - **WHEN** user does A - **THEN** system does B @@ -108,8 +112,9 @@ The system SHALL do something new. **Key Principle: Intelligent Merging** Unlike programmatic merging, you can apply **partial updates**: + - To add a scenario, just include that scenario under MODIFIED - don't copy existing scenarios -- The delta represents *intent*, not a wholesale replacement +- The delta represents _intent_, not a wholesale replacement - Use your judgment to merge changes sensibly **Output On Success** @@ -131,6 +136,7 @@ Main specs are now updated. The change remains active - archive when implementat ``` **Guardrails** + - Read both delta and main specs before making changes - Preserve existing content not mentioned in delta - If something is unclear, ask for clarification diff --git a/.github/skills/openspec-verify-change/SKILL.md b/.github/skills/openspec-verify-change/SKILL.md index 744a088..051f4b1 100644 --- a/.github/skills/openspec-verify-change/SKILL.md +++ b/.github/skills/openspec-verify-change/SKILL.md @@ -5,8 +5,8 @@ license: MIT compatibility: Requires openspec CLI. metadata: author: openspec - version: "1.0" - generatedBy: "1.2.0" + version: '1.0' + generatedBy: '1.2.0' --- Verify that an implementation matches the change artifacts (specs, tasks, design). @@ -26,9 +26,11 @@ Verify that an implementation matches the change artifacts (specs, tasks, design **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose. 2. **Check status to understand the schema** + ```bash openspec status --change "" --json ``` + Parse the JSON to understand: - `schemaName`: The workflow being used (e.g., "spec-driven") - Which artifacts exist for this change @@ -110,6 +112,7 @@ Verify that an implementation matches the change artifacts (specs, tasks, design 8. **Generate Verification Report** **Summary Scorecard**: + ``` ## Verification Report: @@ -122,7 +125,6 @@ Verify that an implementation matches the change artifacts (specs, tasks, design ``` **Issues by Priority**: - 1. **CRITICAL** (Must fix before archive): - Incomplete tasks - Missing requirement implementations @@ -161,6 +163,7 @@ Verify that an implementation matches the change artifacts (specs, tasks, design **Output Format** Use clear markdown with: + - Table for summary scorecard - Grouped lists for issues (CRITICAL/WARNING/SUGGESTION) - Code references in format: `file.ts:123` diff --git a/PROJECT.md b/PROJECT.md index c77bad7..4098747 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -365,13 +365,13 @@ Single-metric display tile for KPI summaries (出勤数, 売上, 未処理件数 ```tsx interface StatCardProps { - label: string // e.g. "本日の出勤数" - value: string // pre-formatted by caller, e.g. "12" or "198,000" + label: string // e.g. "本日の出勤数" + value: string // pre-formatted by caller, e.g. "12" or "198,000" delta?: { - value: string // e.g. "+3" or "-5.2%" + value: string // e.g. "+3" or "-5.2%" direction: 'up' | 'down' } - format?: 'currency' | 'count' | 'percent' // ARIA hint only — does not format value + format?: 'currency' | 'count' | 'percent' // ARIA hint only — does not format value isLoading?: boolean } ``` @@ -406,8 +406,8 @@ interface DataTableProps { columns: ColumnDef[] data: T[] isLoading?: boolean - skeletonRowCount?: number // default 5 - emptyState?: ReactNode // falls back to "まだデータがありません" + skeletonRowCount?: number // default 5 + emptyState?: ReactNode // falls back to "まだデータがありません" } ``` @@ -434,9 +434,9 @@ interface TimelineEvent { interface ActivityTimelineProps { events: TimelineEvent[] - order?: 'desc' | 'asc' // default 'desc' (newest first) + order?: 'desc' | 'asc' // default 'desc' (newest first) isLoading?: boolean - skeletonCount?: number // default 4 + skeletonCount?: number // default 4 } ``` diff --git a/openspec/changes/archive/2026-04-04-design-token-expansion/.openspec.yaml b/openspec/changes/archive/2026-04-04-design-token-expansion/.openspec.yaml new file mode 100644 index 0000000..c54c137 --- /dev/null +++ b/openspec/changes/archive/2026-04-04-design-token-expansion/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-04-04 diff --git a/openspec/changes/archive/2026-04-04-design-token-expansion/design.md b/openspec/changes/archive/2026-04-04-design-token-expansion/design.md new file mode 100644 index 0000000..69dfc14 --- /dev/null +++ b/openspec/changes/archive/2026-04-04-design-token-expansion/design.md @@ -0,0 +1,76 @@ +## Context + +`src/tokens/globals.css` currently defines 60 tokens across six groups (colour, typography, spacing, radius, shadows, motion). As ShiftMate and FaxBridge move toward production, three recurring gaps appear in component work: + +1. **Focus visibility** — every interactive component duplicates an ad-hoc focus ring style. Browser defaults are ugly and inconsistent across macOS/iOS/Android. No shared token governs ring width or colour. +2. **Disabled states** — opacity values for disabled elements are hardcoded per-component (0.4, 0.5, 0.45). Inconsistent and impossible to update globally. +3. **Z-index collisions** — dropdowns, modals, toasts, and sticky headers fight for z-index supremacy with magic numbers (10, 100, 9999). No defined layering scale. +4. **Dark mode readiness** — Japanese mobile users expect dark mode (iOS and Android system preference). Without a structured token layer, adding dark mode later requires touching every component. + +All changes land exclusively in `globals.css`. No component API changes. Products consume dark mode via `data-theme="dark"` on ``. + +## Goals / Non-Goals + +**Goals:** + +- Add 3 focus-ring tokens, 1 disabled-opacity token, 1 surface-overlay token, and 6 z-index tokens to `:root` +- Add a complete `[data-theme="dark"]` block that redefines all colour tokens for dark mode +- Keep changes additive — no renames, no removals, no breaking changes +- Update the `design-tokens` spec to reflect new groups and updated token count +- Write specs for the three new capability areas + +**Non-Goals:** + +- Theme toggle UI — products implement their own toggle; Mori DS only defines the CSS contract +- System preference auto-detection (`prefers-color-scheme`) — intentionally deferred; products opt in when ready +- Dark mode for typography, spacing, radius, shadow, or motion tokens — only colour tokens have dark variants (the others are theme-agnostic) +- iOS / SwiftUI token mapping for dark mode — Phase 2 + +## Decisions + +### Decision 1: `data-theme` attribute over `prefers-color-scheme` media query + +**Choice:** Dark mode is activated via `[data-theme="dark"]` on ``, not `@media (prefers-color-scheme: dark)`. + +**Rationale:** Japanese SMB users often share devices (POS terminals, shared tablets at a restaurant). A user-controlled toggle is safer than inheriting the OS preference silently. Products can still wire the toggle to `prefers-color-scheme` on their own if they choose — the CSS contract is the same either way. Using an attribute also makes the theme deterministic in Playwright tests. + +**Alternative considered:** Media query only — rejected because it removes product-level control and complicates testing. + +### Decision 2: Single flat `[data-theme="dark"]` block, not a separate file + +**Choice:** All dark-mode overrides live in `globals.css` inside one `[data-theme="dark"]` selector block, not in a separate `dark.css`. + +**Rationale:** Products import one file. A separate file introduces import-order coupling and makes it easier for products to forget the second file. Keeping everything in `globals.css` mirrors how locale overrides (`[data-locale]`) are already handled in the same file — consistency reduces surprise. + +**Alternative considered:** Separate `dark-tokens.css` — rejected due to import fragility and inconsistency with existing locale pattern. + +### Decision 3: Focus ring colour anchored to `--color-brand`, not a separate hue + +**Choice:** `--focus-ring-color` is set to `--color-brand` (森緑 green) in light mode and adjusted slightly in dark mode. + +**Rationale:** Mori's brand green is already sufficiently distinct from all surface colours. Introducing a new hue (blue, purple) for focus would conflict with semantic colour meanings (info = blue). Japanese users associate the green ring with the product, not with a browser default. + +### Decision 4: Z-index scale anchored to named semantic layers, not a numeric sequence + +**Choice:** Six named layers — `--z-base`, `--z-dropdown`, `--z-sticky`, `--z-overlay`, `--z-modal`, `--z-toast` — with values 0, 100, 200, 300, 400, 500. + +**Rationale:** Semantic names communicate intent. Values spaced by 100 leave room for product-specific intermediate layers without forking the scale. Base at 0 (not 1) because `z-index: 0` is a valid stacking context reset. + +## Risks / Trade-offs + +- **Dark palette maintenance** — every new colour token added to `:root` in the future must also get a dark variant. This is a discipline cost. Mitigation: the `design-tokens` spec will encode a rule requiring dark variants for every colour token. +- **Tailwind v3 arbitrary-value syntax** — tokens like `--z-modal` require `z-[var(--z-modal)]` in Tailwind classes, which is verbose. Mitigation: document the pattern clearly; consider adding to Tailwind config as named utilities in a future change. +- **`data-theme` on `` during SSR** — Server Components render before the client knows the user's theme preference, causing a flash of light mode. Mitigation: products set `data-theme` via a blocking inline script in `` reading `localStorage`; this is a product-level concern documented in the spec. + +## Migration Plan + +1. Add new tokens to `globals.css` (additive — no migration of existing code required) +2. Update `design-tokens` spec with new group list and token count +3. Create new specs for `token-interactive-states`, `token-z-index`, and `token-dark-mode` +4. Existing components continue to work unchanged — adoption of new tokens is incremental, driven per-component as engineers touch them + +Rollback: remove the additive blocks from `globals.css`. No data migrations. No API changes. + +## Open Questions + +- Should `--opacity-disabled` be a standalone token or a CSS variable alias (e.g., `--color-ink-disabled: color-mix(in srgb, var(--color-ink) 45%, transparent)`)? A colour-mix alias would be more semantically precise but reduces compatibility with older Safari. Decision deferred to specs phase. diff --git a/openspec/changes/archive/2026-04-04-design-token-expansion/proposal.md b/openspec/changes/archive/2026-04-04-design-token-expansion/proposal.md new file mode 100644 index 0000000..a0d60ac --- /dev/null +++ b/openspec/changes/archive/2026-04-04-design-token-expansion/proposal.md @@ -0,0 +1,31 @@ +## Why + +The current Mori token set covers colour, typography, spacing, radius, shadows, and motion — but lacks tokens for interactive element states (focus rings, disabled opacity), z-index layering, and a dark-mode theme layer. As ShiftMate and FaxBridge approach production, these gaps force engineers to hardcode values in components, undermining the single-source-of-truth token contract. + +## What Changes + +- Add a **focus-ring token group** — `--focus-ring-color`, `--focus-ring-width`, `--focus-ring-offset` — used consistently by all interactive components (buttons, inputs, links) +- Add a **disabled-state token** — `--opacity-disabled: 0.45` — replaces ad-hoc opacity values scattered across components +- Add a **z-index scale** — `--z-base`, `--z-dropdown`, `--z-sticky`, `--z-overlay`, `--z-modal`, `--z-toast` — eliminates magic numbers in layering +- Add a **surface-overlay token** — `--color-surface-overlay: rgba(0, 0, 0, 0.4)` — standardises the modal/drawer backdrop colour +- Add a **dark-mode theme layer** — all colour tokens redefined under `[data-theme="dark"]` on `` — allows products to opt in to dark mode without rebuilding components +- Update `design-tokens` spec to reflect the new token groups and updated total count + +## Capabilities + +### New Capabilities + +- `token-interactive-states`: Focus ring, disabled opacity, and surface overlay tokens for interactive element states +- `token-z-index`: Z-index scale tokens for consistent layering across all components and overlays +- `token-dark-mode`: Dark-mode theme layer — full colour token set redefined under `[data-theme="dark"]`, mapped to Mori's dark palette while preserving brand identity + +### Modified Capabilities + +- `design-tokens`: Token count and group list change — spec's total (currently 60) grows to cover new groups; the "six groups" rule expands to nine + +## Impact + +- `src/tokens/globals.css` — new `:root` blocks and `[data-theme="dark"]` selector block +- All existing components consume focus-ring and disabled-opacity tokens via Tailwind arbitrary-value syntax; no component logic changes, only class references update +- Products (ShiftMate, FaxBridge) must add a theme toggle mechanism to set `data-theme` on `` — that work lives in product repos, not Mori DS +- No breaking changes to existing token names — additive only diff --git a/openspec/changes/archive/2026-04-04-design-token-expansion/specs/design-tokens/spec.md b/openspec/changes/archive/2026-04-04-design-token-expansion/specs/design-tokens/spec.md new file mode 100644 index 0000000..339ab23 --- /dev/null +++ b/openspec/changes/archive/2026-04-04-design-token-expansion/specs/design-tokens/spec.md @@ -0,0 +1,40 @@ +## MODIFIED Requirements + +### Requirement: Token file covers all six groups +`src/tokens/globals.css` SHALL define CSS custom properties on `:root` for all nine token groups specified in PROJECT.md: colour palette, typography scale, spacing scale, border radius, shadows, motion, interactive states, z-index, and surface overlay. The file SHALL additionally define locale-specific overrides for typography tokens (`--font-body`, `--font-heading`, `--leading-body`, `--leading-heading`) scoped to `[data-locale]` attribute selectors as specified in the `localisation-typography` spec. The file SHALL additionally define a `[data-theme="dark"]` block overriding all colour tokens as specified in the `token-dark-mode` spec. + +#### Scenario: All groups present +- **WHEN** the CSS file is parsed +- **THEN** it SHALL contain a custom property for every token listed in PROJECT.md across all nine groups — no group is missing, no token is omitted + +#### Scenario: Mobile viewport — tokens load +- **WHEN** a product imports `globals.css` on a 390px viewport +- **THEN** all `:root` custom properties are available and resolve correctly — no breakpoint or media query restricts token definitions + +#### Scenario: Locale typography overrides present +- **WHEN** `globals.css` is parsed +- **THEN** it SHALL contain `[data-locale="en"]` and `[data-locale="zh-Hans"]` blocks that override `--font-body`, `--font-heading`, `--leading-body`, and `--leading-heading` + +#### Scenario: Dark mode block present +- **WHEN** `globals.css` is parsed +- **THEN** it SHALL contain a `[data-theme="dark"]` block overriding all colour tokens defined in `:root` + +### Requirement: Token names match PROJECT.md exactly +Every CSS custom property name in `globals.css` SHALL match the name defined in PROJECT.md character-for-character (e.g., `--color-brand`, `--space-4`, `--radius-md`). + +#### Scenario: Name fidelity +- **WHEN** each token name in `globals.css` is compared against PROJECT.md +- **THEN** there SHALL be no typos, no added prefixes, no renamed variables — the names are identical + +#### Scenario: Token count matches specification +- **WHEN** the total token count per group is checked +- **THEN** it SHALL equal: colour 19 (light) + 19 (dark), typography 17, spacing 10, radius 5, shadows 3, motion 6, interactive-states 5 (`--focus-ring-color`, `--focus-ring-width`, `--focus-ring-offset`, `--opacity-disabled`, `--color-surface-overlay`), z-index 6 — 90 `:root` tokens total (not counting dark duplicates) + +## ADDED Requirements + +### Requirement: Every new colour token has a dark variant +For every colour token added to `:root` after this change (i.e., by future changes), a corresponding override SHALL be added simultaneously to the `[data-theme="dark"]` block. The token count MUST remain equal between the light and dark colour token sets. + +#### Scenario: New colour token paired with dark override +- **WHEN** a new `--color-*` token is added to `:root` +- **THEN** a corresponding override SHALL exist in `[data-theme="dark"]` in the same commit diff --git a/openspec/changes/archive/2026-04-04-design-token-expansion/specs/token-dark-mode/spec.md b/openspec/changes/archive/2026-04-04-design-token-expansion/specs/token-dark-mode/spec.md new file mode 100644 index 0000000..d33cfe2 --- /dev/null +++ b/openspec/changes/archive/2026-04-04-design-token-expansion/specs/token-dark-mode/spec.md @@ -0,0 +1,45 @@ +## ADDED Requirements + +### Requirement: Dark mode colour tokens defined under [data-theme="dark"] +`globals.css` SHALL define a `[data-theme="dark"]` selector block on the `` element that overrides every colour token defined in `:root`. Non-colour token groups (typography, spacing, radius, shadows, motion) SHALL NOT be overridden — they are theme-agnostic. + +#### Scenario: Dark mode block present +- **WHEN** `globals.css` is parsed +- **THEN** it SHALL contain a `[data-theme="dark"]` selector block with overrides for all colour tokens defined in `:root` + +#### Scenario: Every colour token has a dark variant +- **WHEN** the list of colour tokens in `:root` is compared to the list in `[data-theme="dark"]` +- **THEN** every token present in `:root` SHALL also be present in `[data-theme="dark"]` — no colour token is left without a dark override + +#### Scenario: Non-colour tokens are not duplicated in dark block +- **WHEN** the `[data-theme="dark"]` block is parsed +- **THEN** it SHALL contain only colour tokens (`--color-*`, `--focus-ring-color`) — no typography, spacing, radius, shadow, z-index, or motion tokens + +### Requirement: Dark mode activated via data-theme attribute, not media query +Dark mode SHALL be activated by setting `data-theme="dark"` on the `` element. The dark token block SHALL NOT rely on `@media (prefers-color-scheme: dark)` — products that wish to auto-detect OS preference may add the media query on their own, but the Mori DS contract is the attribute only. + +#### Scenario: Attribute activates dark tokens +- **WHEN** `` is rendered +- **THEN** all `--color-*` tokens resolve to their dark values + +#### Scenario: Light mode is default without attribute +- **WHEN** `` is rendered without a `data-theme` attribute +- **THEN** all `--color-*` tokens resolve to their `:root` light values + +### Requirement: Dark palette preserves brand identity and WCAG AA contrast +The dark palette SHALL use Mori's brand green (森緑 family) as the primary interactive colour. All text-on-background combinations SHALL meet WCAG AA contrast ratio (≥4.5:1 for normal text, ≥3:1 for large text and UI components). + +#### Scenario: Brand green used on dark surfaces +- **WHEN** a primary Button renders in dark mode +- **THEN** its background colour SHALL resolve to a value in the `--color-brand` family — not a generic blue or grey + +#### Scenario: Primary text meets contrast in dark mode +- **WHEN** `--color-ink` is checked against `--color-surface-raised` in dark mode +- **THEN** the contrast ratio SHALL be ≥4.5:1 + +### Requirement: Dark mode flash prevention documented +The `token-dark-mode` spec SHALL document (as a non-normative note) that products MUST inject a blocking inline script in `` to read the user's stored theme preference from `localStorage` and set `data-theme` on `` before first paint, preventing a flash of unstyled light mode. + +#### Scenario: Documentation note present in spec +- **WHEN** a product engineer reads the dark mode spec +- **THEN** they SHALL find a clear note explaining the blocking inline script pattern and why it is necessary diff --git a/openspec/changes/archive/2026-04-04-design-token-expansion/specs/token-interactive-states/spec.md b/openspec/changes/archive/2026-04-04-design-token-expansion/specs/token-interactive-states/spec.md new file mode 100644 index 0000000..799c9eb --- /dev/null +++ b/openspec/changes/archive/2026-04-04-design-token-expansion/specs/token-interactive-states/spec.md @@ -0,0 +1,38 @@ +## ADDED Requirements + +### Requirement: Focus ring tokens present on :root +`globals.css` SHALL define three focus-ring tokens on `:root`: `--focus-ring-color`, `--focus-ring-width`, and `--focus-ring-offset`. These tokens SHALL be used by all interactive components (Button, Input, links) to render a consistent focus indicator. + +#### Scenario: Focus ring tokens defined +- **WHEN** `globals.css` is parsed +- **THEN** `:root` SHALL contain `--focus-ring-color`, `--focus-ring-width`, and `--focus-ring-offset` custom properties + +#### Scenario: Focus ring colour matches brand token +- **WHEN** `--focus-ring-color` is resolved +- **THEN** its value SHALL reference `--color-brand` (森緑) — not a hardcoded hex value + +#### Scenario: Focus ring width and offset are consistent across components +- **WHEN** Button and Input components render their focus state +- **THEN** both SHALL use `var(--focus-ring-width)` and `var(--focus-ring-offset)` — no per-component overrides + +### Requirement: Disabled opacity token present on :root +`globals.css` SHALL define `--opacity-disabled: 0.45` on `:root`. All components that render a disabled state SHALL apply this token as their opacity value — no component SHALL hardcode a numeric opacity for disabled state. + +#### Scenario: Token defined with correct value +- **WHEN** `globals.css` is parsed +- **THEN** `:root` SHALL contain `--opacity-disabled` with a value of `0.45` + +#### Scenario: No hardcoded disabled opacity in components +- **WHEN** any component file is scanned for disabled state styling +- **THEN** it SHALL reference `var(--opacity-disabled)` — not `opacity-40`, `opacity-50`, or any other hardcoded fraction + +### Requirement: Surface overlay token present on :root +`globals.css` SHALL define `--color-surface-overlay` on `:root` for use as the backdrop colour behind modals, drawers, and sheets. + +#### Scenario: Token defined +- **WHEN** `globals.css` is parsed +- **THEN** `:root` SHALL contain `--color-surface-overlay` with a semi-transparent dark value (rgba or equivalent) + +#### Scenario: Modal and drawer backdrops use the token +- **WHEN** a Dialog or Sheet component renders its backdrop element +- **THEN** the backdrop background colour SHALL reference `var(--color-surface-overlay)` — not a hardcoded rgba value diff --git a/openspec/changes/archive/2026-04-04-design-token-expansion/specs/token-z-index/spec.md b/openspec/changes/archive/2026-04-04-design-token-expansion/specs/token-z-index/spec.md new file mode 100644 index 0000000..e890690 --- /dev/null +++ b/openspec/changes/archive/2026-04-04-design-token-expansion/specs/token-z-index/spec.md @@ -0,0 +1,27 @@ +## ADDED Requirements + +### Requirement: Z-index scale tokens present on :root +`globals.css` SHALL define six z-index tokens on `:root`, one per named semantic layer: `--z-base`, `--z-dropdown`, `--z-sticky`, `--z-overlay`, `--z-modal`, `--z-toast`. Values SHALL follow a scale of 0, 100, 200, 300, 400, 500 respectively. + +#### Scenario: All six z-index tokens defined +- **WHEN** `globals.css` is parsed +- **THEN** `:root` SHALL contain all six custom properties: `--z-base`, `--z-dropdown`, `--z-sticky`, `--z-overlay`, `--z-modal`, `--z-toast` + +#### Scenario: Layer values are ordered correctly +- **WHEN** token values are compared +- **THEN** `--z-toast` SHALL be greater than `--z-modal`, which SHALL be greater than `--z-overlay`, which SHALL be greater than `--z-sticky`, which SHALL be greater than `--z-dropdown`, which SHALL be greater than or equal to `--z-base` + +### Requirement: Components use z-index tokens, not magic numbers +All components and layout primitives that set a `z-index` property SHALL reference one of the six z-index tokens using `var(--z-)`. Hardcoded z-index integers are forbidden. + +#### Scenario: No hardcoded z-index in component files +- **WHEN** component source files are scanned for `z-index` CSS property usage +- **THEN** every instance SHALL use `var(--z-base)`, `var(--z-dropdown)`, `var(--z-sticky)`, `var(--z-overlay)`, `var(--z-modal)`, or `var(--z-toast)` — no integer literals + +#### Scenario: Dropdown renders above page content +- **WHEN** a dropdown menu is open +- **THEN** it SHALL render above sticky headers, using `var(--z-dropdown)` which exceeds `var(--z-sticky)` + +#### Scenario: Modal renders above overlays +- **WHEN** a Dialog component is open +- **THEN** its content panel SHALL use `var(--z-modal)` and its backdrop SHALL use `var(--z-overlay)`, ensuring the panel renders above the backdrop diff --git a/openspec/changes/archive/2026-04-04-design-token-expansion/tasks.md b/openspec/changes/archive/2026-04-04-design-token-expansion/tasks.md new file mode 100644 index 0000000..665ce3d --- /dev/null +++ b/openspec/changes/archive/2026-04-04-design-token-expansion/tasks.md @@ -0,0 +1,39 @@ +## 1. Interactive State Tokens + +- [x] 1.1 Add `--focus-ring-color`, `--focus-ring-width`, `--focus-ring-offset` to `:root` in `src/tokens/globals.css` +- [x] 1.2 Add `--opacity-disabled: 0.45` to `:root` in `src/tokens/globals.css` +- [x] 1.3 Add `--color-surface-overlay: rgba(0, 0, 0, 0.4)` to `:root` in `src/tokens/globals.css` +- [x] 1.4 Update Button component to use `var(--focus-ring-color)`, `var(--focus-ring-width)`, `var(--focus-ring-offset)` for its focus ring style +- [x] 1.5 Update Input component to use the same focus ring tokens +- [x] 1.6 Replace any hardcoded disabled opacity values in Button and Input with `var(--opacity-disabled)` +- [x] 1.7 Update Dialog/Sheet backdrop to use `var(--color-surface-overlay)` instead of any hardcoded rgba + +## 2. Z-Index Scale Tokens + +- [x] 2.1 Add `--z-base: 0`, `--z-dropdown: 100`, `--z-sticky: 200`, `--z-overlay: 300`, `--z-modal: 400`, `--z-toast: 500` to `:root` in `src/tokens/globals.css` +- [x] 2.2 Audit all component and layout files for hardcoded `z-index` integers — replace each with the appropriate `var(--z-*)` token +- [x] 2.3 Verify Navigation sticky header uses `var(--z-sticky)` (BottomTabBar uses `fixed` positioning — no explicit z-index; no sticky header component exists yet) +- [x] 2.4 Verify Dialog backdrop uses `var(--z-overlay)` and Dialog panel uses `var(--z-modal)` +- [x] 2.5 Verify any toast/notification component uses `var(--z-toast)` (no toast component exists yet — token is available for when it is built) + +## 3. Dark Mode Token Layer + +- [x] 3.1 Design the dark colour palette: map each of the 19 `:root` colour tokens to dark-mode equivalents (use WCAG AA contrast checker — target ≥4.5:1 for body text) +- [x] 3.2 Add `[data-theme="dark"]` block to `src/tokens/globals.css` overriding all 19 colour tokens plus `--focus-ring-color` and `--color-surface-overlay` +- [x] 3.3 Verify the dark block contains exactly the same colour token names as `:root` — no omissions, no extras (enforced by test 5.5) +- [ ] 3.4 Manually smoke-test dark mode by setting `data-theme="dark"` on `` in the browser and visually inspecting Button, Input, Card, Badge, and Navigation components + +## 4. Spec Sync + +- [x] 4.1 Sync the updated `design-tokens` delta spec into the main spec at `openspec/specs/design-tokens/spec.md` (update group count from 6→9 and token total) +- [x] 4.2 Promote `token-interactive-states` spec to `openspec/specs/token-interactive-states/spec.md` +- [x] 4.3 Promote `token-z-index` spec to `openspec/specs/token-z-index/spec.md` +- [x] 4.4 Promote `token-dark-mode` spec to `openspec/specs/token-dark-mode/spec.md` + +## 5. Tests and Verification + +- [x] 5.1 Run `pnpm lint` — confirm no new lint errors +- [x] 5.2 Run `pnpm typecheck` — confirm no TypeScript errors (pre-existing failures in test files only, unchanged) +- [x] 5.3 Run `pnpm test` — confirm all existing tests pass +- [x] 5.4 Write a Vitest test that parses `globals.css` and asserts all 71 `:root` tokens are present by name +- [x] 5.5 Write a Vitest test that asserts all colour tokens in `:root` have a matching override in `[data-theme="dark"]` diff --git a/openspec/specs/design-tokens/spec.md b/openspec/specs/design-tokens/spec.md index dd0c1e2..1e026a4 100644 --- a/openspec/specs/design-tokens/spec.md +++ b/openspec/specs/design-tokens/spec.md @@ -1,16 +1,16 @@ # design-tokens Specification ## Purpose -Define the requirements for Mori design token files — ensuring all six token groups from PROJECT.md are present, correctly named, and importable by product repositories. +Define the requirements for Mori design token files — ensuring all nine token groups are present, correctly named, and importable by product repositories. ## Requirements -### Requirement: Token file covers all six groups -`src/tokens/globals.css` SHALL define CSS custom properties on `:root` for all six token groups specified in PROJECT.md: colour palette, typography scale, spacing scale, border radius, shadows, and motion. The file SHALL additionally define locale-specific overrides for typography tokens (`--font-body`, `--font-heading`, `--leading-body`, `--leading-heading`) scoped to `[data-locale]` attribute selectors as specified in the `localisation-typography` spec. +### Requirement: Token file covers all nine groups +`src/tokens/globals.css` SHALL define CSS custom properties on `:root` for all nine token groups: colour palette, typography scale, spacing scale, border radius, shadows, motion, interactive states, z-index, and surface overlay. The file SHALL additionally define locale-specific overrides for typography tokens (`--font-body`, `--font-heading`, `--leading-body`, `--leading-heading`) scoped to `[data-locale]` attribute selectors as specified in the `localisation-typography` spec. The file SHALL additionally define a `[data-theme="dark"]` block overriding all colour tokens as specified in the `token-dark-mode` spec. #### Scenario: All groups present - **WHEN** the CSS file is parsed -- **THEN** it SHALL contain a custom property for every token listed in PROJECT.md — no group is missing, no token is omitted +- **THEN** it SHALL contain a custom property for every token in all nine groups — no group is missing, no token is omitted #### Scenario: Mobile viewport — tokens load - **WHEN** a product imports `globals.css` on a 390px viewport @@ -20,6 +20,10 @@ Define the requirements for Mori design token files — ensuring all six token g - **WHEN** `globals.css` is parsed - **THEN** it SHALL contain `[data-locale="en"]` and `[data-locale="zh-Hans"]` blocks that override `--font-body`, `--font-heading`, `--leading-body`, and `--leading-heading` +#### Scenario: Dark mode block present +- **WHEN** `globals.css` is parsed +- **THEN** it SHALL contain a `[data-theme="dark"]` block overriding all colour tokens defined in `:root` + ### Requirement: Token names match PROJECT.md exactly Every CSS custom property name in `globals.css` SHALL match the name defined in PROJECT.md character-for-character (e.g., `--color-brand`, `--space-4`, `--radius-md`). @@ -28,5 +32,12 @@ Every CSS custom property name in `globals.css` SHALL match the name defined in - **THEN** there SHALL be no typos, no added prefixes, no renamed variables — the names are identical #### Scenario: Token count matches specification -- **WHEN** the total token count per group is checked -- **THEN** it SHALL equal: colour 19, typography 17, spacing 10, radius 5, shadows 3, motion 6 (60 tokens total) +- **WHEN** the total `:root` token count per group is checked +- **THEN** it SHALL equal: colour 19, typography 17, spacing 10, radius 5, shadows 3, motion 6, interactive-states 5, z-index 6 — 71 tokens total (dark mode overrides in `[data-theme="dark"]` are not counted separately) + +### Requirement: Every new colour token has a dark variant +For every colour token defined in `:root`, a corresponding override SHALL exist in `[data-theme="dark"]`. The set of colour token names in both blocks MUST be identical. + +#### Scenario: New colour token paired with dark override +- **WHEN** a new `--color-*` token is added to `:root` +- **THEN** a corresponding override SHALL exist in `[data-theme="dark"]` in the same commit diff --git a/openspec/specs/token-dark-mode/spec.md b/openspec/specs/token-dark-mode/spec.md new file mode 100644 index 0000000..6ae0295 --- /dev/null +++ b/openspec/specs/token-dark-mode/spec.md @@ -0,0 +1,53 @@ +# token-dark-mode Specification + +## Purpose +Define the requirements for the dark mode token layer — ensuring every colour token has a dark-mode override, the theme is activated predictably via a data attribute, and products can adopt dark mode without touching component code. + +> **Flash prevention (non-normative):** Products MUST inject a blocking inline script in `` that reads the user's stored theme preference from `localStorage` and sets `data-theme` on `` before first paint. Without this, users who prefer dark mode will see a flash of the light theme on every page load. Example: +> ```html +> +> ``` + +## Requirements + +### Requirement: Dark mode colour tokens defined under [data-theme="dark"] +`globals.css` SHALL define a `[data-theme="dark"]` selector block that overrides every colour token defined in `:root`. Non-colour token groups (typography, spacing, radius, shadows, motion, z-index) SHALL NOT be overridden — they are theme-agnostic. + +#### Scenario: Dark mode block present +- **WHEN** `globals.css` is parsed +- **THEN** it SHALL contain a `[data-theme="dark"]` selector block with overrides for all colour tokens defined in `:root` + +#### Scenario: Every colour token has a dark variant +- **WHEN** the list of colour tokens in `:root` is compared to the list in `[data-theme="dark"]` +- **THEN** every token present in `:root` SHALL also be present in `[data-theme="dark"]` — no colour token is left without a dark override + +#### Scenario: Non-colour tokens are not duplicated in dark block +- **WHEN** the `[data-theme="dark"]` block is parsed +- **THEN** it SHALL contain only colour tokens (`--color-*`, `--focus-ring-color`) — no typography, spacing, radius, shadow, z-index, or motion tokens + +### Requirement: Dark mode activated via data-theme attribute, not media query +Dark mode SHALL be activated by setting `data-theme="dark"` on the `` element. The dark token block SHALL NOT rely on `@media (prefers-color-scheme: dark)` — products that wish to auto-detect OS preference may add the media query on their own, but the Mori DS contract is the attribute only. + +#### Scenario: Attribute activates dark tokens +- **WHEN** `` is rendered +- **THEN** all `--color-*` tokens resolve to their dark values + +#### Scenario: Light mode is default without attribute +- **WHEN** `` is rendered without a `data-theme` attribute +- **THEN** all `--color-*` tokens resolve to their `:root` light values + +### Requirement: Dark palette preserves brand identity and WCAG AA contrast +The dark palette SHALL use Mori's brand green (森緑 family) as the primary interactive colour. All text-on-background combinations SHALL meet WCAG AA contrast ratio (≥4.5:1 for normal text, ≥3:1 for large text and UI components). + +#### Scenario: Brand green used on dark surfaces +- **WHEN** a primary Button renders in dark mode +- **THEN** its background colour SHALL resolve to a value in the `--color-brand` family — not a generic blue or grey + +#### Scenario: Primary text meets contrast in dark mode +- **WHEN** `--color-ink` is checked against `--color-surface-raised` in dark mode +- **THEN** the contrast ratio SHALL be ≥4.5:1 diff --git a/openspec/specs/token-interactive-states/spec.md b/openspec/specs/token-interactive-states/spec.md new file mode 100644 index 0000000..42711fc --- /dev/null +++ b/openspec/specs/token-interactive-states/spec.md @@ -0,0 +1,43 @@ +# token-interactive-states Specification + +## Purpose +Define the requirements for interactive-state design tokens — ensuring consistent focus ring appearance, disabled state opacity, and modal backdrop colour across all Mori components. + +## Requirements + +### Requirement: Focus ring tokens present on :root +`globals.css` SHALL define three focus-ring tokens on `:root`: `--focus-ring-color`, `--focus-ring-width`, and `--focus-ring-offset`. These tokens SHALL be used by all interactive components (Button, Input, links) to render a consistent focus indicator. + +#### Scenario: Focus ring tokens defined +- **WHEN** `globals.css` is parsed +- **THEN** `:root` SHALL contain `--focus-ring-color`, `--focus-ring-width`, and `--focus-ring-offset` custom properties + +#### Scenario: Focus ring colour matches brand token +- **WHEN** `--focus-ring-color` is resolved +- **THEN** its value SHALL reference `--color-brand` (森緑) — not a hardcoded hex value + +#### Scenario: Focus ring width and offset are consistent across components +- **WHEN** Button and Input components render their focus state +- **THEN** both SHALL use `var(--focus-ring-width)` and `var(--focus-ring-offset)` — no per-component overrides + +### Requirement: Disabled opacity token present on :root +`globals.css` SHALL define `--opacity-disabled: 0.45` on `:root`. All components that render a disabled state SHALL apply this token as their opacity value — no component SHALL hardcode a numeric opacity for disabled state. + +#### Scenario: Token defined with correct value +- **WHEN** `globals.css` is parsed +- **THEN** `:root` SHALL contain `--opacity-disabled` with a value of `0.45` + +#### Scenario: No hardcoded disabled opacity in components +- **WHEN** any component file is scanned for disabled state styling +- **THEN** it SHALL reference `var(--opacity-disabled)` — not `opacity-40`, `opacity-50`, or any other hardcoded fraction + +### Requirement: Surface overlay token present on :root +`globals.css` SHALL define `--color-surface-overlay` on `:root` for use as the backdrop colour behind modals, drawers, and sheets. + +#### Scenario: Token defined +- **WHEN** `globals.css` is parsed +- **THEN** `:root` SHALL contain `--color-surface-overlay` with a semi-transparent dark value (rgba or equivalent) + +#### Scenario: Modal and drawer backdrops use the token +- **WHEN** a Dialog or Sheet component renders its backdrop element +- **THEN** the backdrop background colour SHALL reference `var(--color-surface-overlay)` — not a hardcoded rgba value diff --git a/openspec/specs/token-z-index/spec.md b/openspec/specs/token-z-index/spec.md new file mode 100644 index 0000000..0041f15 --- /dev/null +++ b/openspec/specs/token-z-index/spec.md @@ -0,0 +1,32 @@ +# token-z-index Specification + +## Purpose +Define the requirements for the z-index scale design tokens — ensuring all components use named semantic layers instead of magic numbers, and that layer ordering is consistent across the system. + +## Requirements + +### Requirement: Z-index scale tokens present on :root +`globals.css` SHALL define six z-index tokens on `:root`, one per named semantic layer: `--z-base`, `--z-dropdown`, `--z-sticky`, `--z-overlay`, `--z-modal`, `--z-toast`. Values SHALL follow a scale of 0, 100, 200, 300, 400, 500 respectively. + +#### Scenario: All six z-index tokens defined +- **WHEN** `globals.css` is parsed +- **THEN** `:root` SHALL contain all six custom properties: `--z-base`, `--z-dropdown`, `--z-sticky`, `--z-overlay`, `--z-modal`, `--z-toast` + +#### Scenario: Layer values are ordered correctly +- **WHEN** token values are compared +- **THEN** `--z-toast` SHALL be greater than `--z-modal`, which SHALL be greater than `--z-overlay`, which SHALL be greater than `--z-sticky`, which SHALL be greater than `--z-dropdown`, which SHALL be greater than or equal to `--z-base` + +### Requirement: Components use z-index tokens, not magic numbers +All components and layout primitives that set a `z-index` property SHALL reference one of the six z-index tokens using `var(--z-)`. Hardcoded z-index integers are forbidden. + +#### Scenario: No hardcoded z-index in component files +- **WHEN** component source files are scanned for `z-index` CSS property usage +- **THEN** every instance SHALL use `var(--z-base)`, `var(--z-dropdown)`, `var(--z-sticky)`, `var(--z-overlay)`, `var(--z-modal)`, or `var(--z-toast)` — no integer literals + +#### Scenario: Dropdown renders above page content +- **WHEN** a dropdown menu is open +- **THEN** it SHALL render above sticky headers, using `var(--z-dropdown)` which exceeds `var(--z-sticky)` + +#### Scenario: Modal renders above overlays +- **WHEN** a Dialog component is open +- **THEN** its content panel SHALL use `var(--z-modal)` and its backdrop SHALL use `var(--z-overlay)`, ensuring the panel renders above the backdrop diff --git a/showcase/src/components/LocaleSwitcher.tsx b/showcase/src/components/LocaleSwitcher.tsx index a887212..69b1bfa 100644 --- a/showcase/src/components/LocaleSwitcher.tsx +++ b/showcase/src/components/LocaleSwitcher.tsx @@ -23,7 +23,9 @@ export function LocaleSwitcher(): JSX.Element { @@ -85,11 +87,17 @@ export function DialogSection(): JSX.Element { { setDefaultOpen(false) }} + onClose={() => { + setDefaultOpen(false) + }} title={t.dialogDefaultTitle} subtitle={t.dialogDefaultSubtitle} footer={ - } @@ -117,7 +125,9 @@ export function DialogSection(): JSX.Element { @@ -125,11 +135,15 @@ export function DialogSection(): JSX.Element { { setConfirmOpen(false) }} + onClose={() => { + setConfirmOpen(false) + }} variant="confirm" title={t.dialogConfirmTitle} actionLabel={t.dialogSave} - onAction={() => { setConfirmOpen(false) }} + onAction={() => { + setConfirmOpen(false) + }} > {t.dialogConfirmBody} @@ -159,7 +173,9 @@ export function DialogSection(): JSX.Element { @@ -167,12 +183,16 @@ export function DialogSection(): JSX.Element { { setDestructiveOpen(false) }} + onClose={() => { + setDestructiveOpen(false) + }} variant="confirm" title={t.dialogDestructiveTitle} actionLabel={t.dialogDelete} destructive - onAction={() => { setDestructiveOpen(false) }} + onAction={() => { + setDestructiveOpen(false) + }} > {t.dialogDestructiveBody} @@ -199,7 +219,9 @@ export function DialogSection(): JSX.Element { @@ -207,12 +229,16 @@ export function DialogSection(): JSX.Element { { setLoadingOpen(false) }} + onClose={() => { + setLoadingOpen(false) + }} variant="confirm" title={t.dialogLoadingTitle} actionLabel={t.dialogUpdate} isLoading - onAction={() => { setLoadingOpen(false) }} + onAction={() => { + setLoadingOpen(false) + }} > {t.dialogLoadingBody} diff --git a/showcase/src/sections/EmptyStateSection.tsx b/showcase/src/sections/EmptyStateSection.tsx index 39538c8..0704418 100644 --- a/showcase/src/sections/EmptyStateSection.tsx +++ b/showcase/src/sections/EmptyStateSection.tsx @@ -9,7 +9,12 @@ export function EmptyStateSection(): JSX.Element { const t = useT() return ( - + @@ -21,17 +26,15 @@ export function EmptyStateSection(): JSX.Element { description={t.emptyNoShiftDesc} action={{ label: t.emptyNoShiftCta, - onClick: () => { /* showcase only */ }, + onClick: () => { + /* showcase only */ + }, }} /> - + @@ -41,7 +44,9 @@ export function EmptyStateSection(): JSX.Element { description={t.emptyFaxDesc} action={{ label: t.emptyFaxCta, - onClick: () => { /* showcase only */ }, + onClick: () => { + /* showcase only */ + }, }} /> diff --git a/showcase/src/sections/NavigationSection.tsx b/showcase/src/sections/NavigationSection.tsx index 36cf23d..210c72e 100644 --- a/showcase/src/sections/NavigationSection.tsx +++ b/showcase/src/sections/NavigationSection.tsx @@ -12,35 +12,44 @@ export function NavigationSection(): JSX.Element { const [activeTab, setActiveTab] = useState('home') const SIDEBAR_ITEMS: SidebarNavItem[] = [ - { key: 'home', icon: Home, label: t.navHome }, - { key: 'shift', icon: Calendar, label: t.navShift }, - { key: 'staff', icon: Users, label: t.navStaff }, - { key: 'reports', icon: FileText, label: t.navReports }, - { key: 'notifications', icon: Bell, label: t.navNotifications }, - { key: 'settings', icon: Settings, label: t.navSettings }, + { key: 'home', icon: Home, label: t.navHome }, + { key: 'shift', icon: Calendar, label: t.navShift }, + { key: 'staff', icon: Users, label: t.navStaff }, + { key: 'reports', icon: FileText, label: t.navReports }, + { key: 'notifications', icon: Bell, label: t.navNotifications }, + { key: 'settings', icon: Settings, label: t.navSettings }, ] const TAB_ITEMS: Omit[] = [ - { key: 'home', icon: Home, label: t.navTabHome }, - { key: 'shift', icon: Calendar, label: t.navTabShift }, - { key: 'staff', icon: Users, label: t.navTabStaff }, + { key: 'home', icon: Home, label: t.navTabHome }, + { key: 'shift', icon: Calendar, label: t.navTabShift }, + { key: 'staff', icon: Users, label: t.navTabStaff }, { key: 'settings', icon: Settings, label: t.navTabSettings }, ] const sidebarItems = SIDEBAR_ITEMS.map((item) => ({ ...item, isActive: item.key === activeSidebar, - onClick: () => { setActiveSidebar(item.key) }, + onClick: () => { + setActiveSidebar(item.key) + }, })) const tabItems = TAB_ITEMS.map((item) => ({ ...item, isActive: item.key === activeTab, - onClick: () => { setActiveTab(item.key) }, + onClick: () => { + setActiveTab(item.key) + }, })) return ( - +
📄, - description: 'FAXを受信しました', - timestamp: fiveMinAgo, - }, - { - id: '2', - icon: , - description: 'データを抽出しました', - timestamp: twoHoursAgo, - }, -] +const eventFax: TimelineEvent = { + id: '1', + icon: 📄, + description: 'FAXを受信しました', + timestamp: fiveMinAgo, +} + +const eventExtract: TimelineEvent = { + id: '2', + icon: , + description: 'データを抽出しました', + timestamp: twoHoursAgo, +} + +const events: TimelineEvent[] = [eventFax, eventExtract] describe('ActivityTimeline', () => { describe('event render', () => { @@ -39,32 +40,34 @@ describe('ActivityTimeline', () => { describe('order', () => { it('desc order renders newest event first (default)', () => { render() - const items = screen.getAllByRole('listitem') - expect(items[0].textContent).toContain('FAXを受信しました') + const [first] = screen.getAllByRole('listitem') + if (!first) throw new Error('no listitem found') + expect(first.textContent).toContain('FAXを受信しました') }) it('asc order renders oldest event first', () => { render() - const items = screen.getAllByRole('listitem') - expect(items[0].textContent).toContain('データを抽出しました') + const [first] = screen.getAllByRole('listitem') + if (!first) throw new Error('no listitem found') + expect(first.textContent).toContain('データを抽出しました') }) }) describe('relative timestamp', () => { it('shows "5分前" for an event 5 minutes ago', () => { - render() + render() expect(screen.getByText('5分前')).toBeInTheDocument() }) it('shows "2時間前" for an event 2 hours ago', () => { - render() + render() expect(screen.getByText('2時間前')).toBeInTheDocument() }) }) describe('aria-label on timestamp', () => { it('includes absolute Japanese date/time in aria-label', () => { - render() + render() const timeEl = screen.getByRole('time') // aria-label should be the full formatted date string const ariaLabel = timeEl.getAttribute('aria-label') ?? '' @@ -73,7 +76,7 @@ describe('ActivityTimeline', () => { }) it('sets title attribute equal to aria-label', () => { - render() + render() const timeEl = screen.getByRole('time') expect(timeEl.getAttribute('title')).toBe(timeEl.getAttribute('aria-label')) }) diff --git a/src/components/ui/__tests__/data-table.test.tsx b/src/components/ui/__tests__/data-table.test.tsx index 66c1ebb..88f1ac4 100644 --- a/src/components/ui/__tests__/data-table.test.tsx +++ b/src/components/ui/__tests__/data-table.test.tsx @@ -55,10 +55,12 @@ describe('DataTable', () => { const th = screen.getByText('名前').closest('th') if (!th) throw new Error('th not found') fireEvent.click(th) - const cells = screen.getAllByRole('cell').filter((c) => - ['田中 花子', '山田 次郎', '鈴木 一郎'].includes(c.textContent ?? ''), - ) - expect(cells[0].textContent).toBe('山田 次郎') // ア行 + const cells = screen + .getAllByRole('cell') + .filter((c) => ['田中 花子', '山田 次郎', '鈴木 一郎'].includes(c.textContent ?? '')) + const [firstCell] = cells + if (!firstCell) throw new Error('cell not found') + expect(firstCell.textContent).toBe('山田 次郎') // ア行 }) it('sorts descending on second click', () => { @@ -67,10 +69,12 @@ describe('DataTable', () => { if (!th) throw new Error('th not found') fireEvent.click(th) // asc: 3, 5, 7 fireEvent.click(th) // desc: 7, 5, 3 - const cells = screen.getAllByRole('cell').filter((c) => - ['5', '3', '7'].includes(c.textContent ?? ''), - ) - expect(cells[0].textContent).toBe('7') + const cells = screen + .getAllByRole('cell') + .filter((c) => ['5', '3', '7'].includes(c.textContent ?? '')) + const [firstCell] = cells + if (!firstCell) throw new Error('cell not found') + expect(firstCell.textContent).toBe('7') }) it('clears sort on third click', () => { @@ -82,7 +86,9 @@ describe('DataTable', () => { fireEvent.click(th) // After clearing, original order: 田中, 鈴木, 山田 const rows = screen.getAllByRole('row').slice(1) // skip header - expect(rows[0].textContent).toContain('田中 花子') + const [firstRow] = rows + if (!firstRow) throw new Error('row not found') + expect(firstRow.textContent).toContain('田中 花子') }) it('sets aria-sort ascending after first click', () => { @@ -101,13 +107,7 @@ describe('DataTable', () => { }) it('shows custom emptyState slot when provided', () => { - render( - カスタム空状態} - />, - ) + render(カスタム空状態} />) expect(screen.getByText('カスタム空状態')).toBeInTheDocument() }) }) @@ -122,7 +122,7 @@ describe('DataTable', () => { it('respects skeletonRowCount prop', () => { const { container } = render( - , + ) const skeletons = container.querySelectorAll('.animate-pulse') expect(skeletons.length).toBe(3 * columns.length) diff --git a/src/components/ui/__tests__/stat-card.test.tsx b/src/components/ui/__tests__/stat-card.test.tsx index f596671..1be4c30 100644 --- a/src/components/ui/__tests__/stat-card.test.tsx +++ b/src/components/ui/__tests__/stat-card.test.tsx @@ -20,17 +20,13 @@ describe('StatCard', () => { describe('delta', () => { it('shows positive delta with success colour', () => { - render( - , - ) + render() const delta = screen.getByText('+3') expect(delta.closest('div')?.style.color).toContain('var(--color-success)') }) it('shows negative delta with error colour', () => { - render( - , - ) + render() const delta = screen.getByText('-2') expect(delta.closest('div')?.style.color).toContain('var(--color-error)') }) @@ -73,13 +69,7 @@ describe('StatCard', () => { }) it('includes delta direction in aria-label', () => { - render( - , - ) + render() expect(screen.getByLabelText(/増加/)).toBeInTheDocument() }) }) diff --git a/src/components/ui/activity-timeline.tsx b/src/components/ui/activity-timeline.tsx index 4dd7b7c..a6e7f3e 100644 --- a/src/components/ui/activity-timeline.tsx +++ b/src/components/ui/activity-timeline.tsx @@ -109,10 +109,7 @@ export function ActivityTimeline({ {/* Content */}
-

+

{event.description}