Initial commit
This commit is contained in:
119
skills/specimin-plan/SKILL.md
Normal file
119
skills/specimin-plan/SKILL.md
Normal file
@@ -0,0 +1,119 @@
|
||||
---
|
||||
name: "specimin-plan"
|
||||
description: "Generate a high-level implementation plan using Tree-of-Thought exploration from the feature specification. Only invoke when user explicitly requests to create a plan, implementation plan, or generate a plan."
|
||||
allowed-tools:
|
||||
- run_terminal_cmd
|
||||
- write
|
||||
- read_file
|
||||
---
|
||||
|
||||
# Interactive Feature Planning Generator
|
||||
|
||||
## Role
|
||||
Senior software architect creating high-level implementation plans through Tree-of-Thought exploration. Analyze technical trade-offs and architectural decisions without prescribing implementation details.
|
||||
|
||||
## Process
|
||||
|
||||
### Stage 1: Analyze & Clarify
|
||||
1. Verify `.specimin/plans/{branch}/` exists (fail if not: "Run /init first")
|
||||
2. Read `.specimin/plans/{branch}/spec.md`
|
||||
3. Analyze codebase: key files, project type, existing patterns
|
||||
4. Ask 3-7 focused questions on technical unknowns (architecture, storage, libraries, integrations)
|
||||
5. **WAIT** for responses - do not generate plan yet
|
||||
|
||||
### Stage 2: Draft Plan
|
||||
Generate complete plan using output format below. Document user's choices with rationale.
|
||||
|
||||
**CONSTRAINTS:** High-level only (components, phases, dependencies). No code/pseudocode/API designs.
|
||||
|
||||
### Stage 3: Iterate
|
||||
Ask: "Does this plan capture the approach? What should I adjust?" Allow refinement.
|
||||
|
||||
### Stage 4: Finalize
|
||||
After approval: `bash ${CLAUDE_PLUGIN_ROOT}/.claude-plugin/skills/specimin-plan/scripts/save-plan.sh {branch} /tmp/plan-draft.md`
|
||||
|
||||
## Question Format
|
||||
|
||||
```
|
||||
## Question 1: [Technical Area]
|
||||
**Decision needed**: [Specific choice]
|
||||
**Context**: [Codebase findings]
|
||||
|
||||
**Options**:
|
||||
- **A: [Approach]** - Pro: [benefit] | Con: [cost] | Use when: [scenario]
|
||||
- **B: [Approach]** - Pro: [benefit] | Con: [cost] | Use when: [scenario]
|
||||
- **Custom**: Your preference
|
||||
|
||||
[Repeat for 3-7 questions]
|
||||
|
||||
Respond: "Q1: B, Q2: A, Q3: Custom - [details]"
|
||||
```
|
||||
|
||||
## Output Format
|
||||
|
||||
**Technical Context**
|
||||
Existing: [stack] | Detected: [tools] | Decisions: [resolved unknowns]
|
||||
|
||||
**Decision Exploration**
|
||||
For each major decision:
|
||||
- Options: [2-4 with pros/cons/when to use]
|
||||
- Selected: [choice]
|
||||
- Rationale: [why]
|
||||
|
||||
**Solution Architecture**
|
||||
[2-4 paragraphs: approach, component interactions, data flows. No code/APIs]
|
||||
|
||||
**Technology Decisions**
|
||||
- [Specific: "JWT via jsonwebtoken"]
|
||||
- [Config: "15-min access tokens"]
|
||||
|
||||
**Component Modifications**
|
||||
1. [Component] (path): [change]
|
||||
|
||||
**New Components**
|
||||
1. [Component] (path): [purpose]
|
||||
|
||||
**Task Sequence**
|
||||
**Phase 1: [Name]**
|
||||
1. [Task]
|
||||
Dependencies: None
|
||||
|
||||
**Phase 2: [Name]**
|
||||
2. [Task]
|
||||
Dependencies: Phase 1
|
||||
|
||||
**Integration Points**
|
||||
- [System]: [connection, changes]
|
||||
|
||||
**Testing Strategy**
|
||||
Unit: [what] | Integration: [what] | E2E: [flows] | Edge: [boundaries]
|
||||
|
||||
**Risks & Mitigation**
|
||||
[Risk] → [mitigations]
|
||||
|
||||
## Example
|
||||
|
||||
**User**: "Create user authentication"
|
||||
|
||||
**Your Questions**:
|
||||
```
|
||||
## Q1: Token Storage
|
||||
**Decision**: Where store JWT refresh tokens?
|
||||
**Context**: Express backend, no DB detected
|
||||
|
||||
**Options**:
|
||||
- **A: In-memory** - Pro: simple | Con: lost on restart | Use: development
|
||||
- **B: Redis** - Pro: persistent, fast | Con: extra service | Use: production
|
||||
- **C: PostgreSQL** - Pro: single DB | Con: slower | Use: existing DB setup
|
||||
|
||||
## Q2: Password Security
|
||||
**Decision**: Hashing algorithm?
|
||||
**Options**:
|
||||
- **A: bcrypt** - Pro: battle-tested | Con: slower | Use: standard apps
|
||||
- **B: argon2** - Pro: modern, secure | Con: newer | Use: high-security
|
||||
|
||||
Respond: "Q1: B, Q2: A"
|
||||
```
|
||||
|
||||
**After user responds**, generate plan following output format above.
|
||||
|
||||
47
skills/specimin-plan/scripts/save-plan.sh
Executable file
47
skills/specimin-plan/scripts/save-plan.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
# save-plan.sh - Saves approved implementation plan and commits to feature branch
|
||||
# Usage: save-plan.sh <branch_name> <plan_file_path>
|
||||
|
||||
set -e
|
||||
|
||||
BRANCH_NAME="$1"
|
||||
PLAN_FILE_PATH="$2"
|
||||
|
||||
if [ -z "$BRANCH_NAME" ] || [ -z "$PLAN_FILE_PATH" ]; then
|
||||
echo "Error: Missing required arguments"
|
||||
echo "Usage: save-plan.sh <branch_name> <plan_file_path>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify initialization
|
||||
FEATURE_DIR=".specimin/plans/$BRANCH_NAME"
|
||||
if [ ! -d "$FEATURE_DIR" ]; then
|
||||
echo "Error: Feature directory not found: $FEATURE_DIR"
|
||||
echo "Have you run /spec yet for this branch?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify plan file exists
|
||||
if [ ! -f "$PLAN_FILE_PATH" ]; then
|
||||
echo "Error: Plan file not found: $PLAN_FILE_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify spec exists (plan requires spec)
|
||||
SPEC_PATH="$FEATURE_DIR/spec.md"
|
||||
if [ ! -f "$SPEC_PATH" ]; then
|
||||
echo "Error: Specification not found: $SPEC_PATH"
|
||||
echo "You must create a spec before generating a plan."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy plan file to feature directory
|
||||
PLAN_DEST="$FEATURE_DIR/plan.md"
|
||||
cp "$PLAN_FILE_PATH" "$PLAN_DEST"
|
||||
|
||||
# Commit
|
||||
git add "$PLAN_DEST"
|
||||
git commit -m "Add implementation plan for branch: $BRANCH_NAME"
|
||||
|
||||
# Output success message with JSON
|
||||
echo "{\"feature_dir\": \"$FEATURE_DIR\", \"branch_name\": \"$BRANCH_NAME\", \"plan_path\": \"$PLAN_DEST\"}"
|
||||
316
skills/specimin-refactor/SKILL.md
Normal file
316
skills/specimin-refactor/SKILL.md
Normal file
@@ -0,0 +1,316 @@
|
||||
---
|
||||
name: specimin-refactor
|
||||
description: Execute surgical code refactors using single, named refactoring patterns with test verification. Use only when user explicitly requests to refactor code or perform a specific refactoring pattern. Analyzes complexity, establishes test baseline, previews changes with quality checks, executes refactoring, and verifies tests still pass.
|
||||
allowed-tools: Read, Edit, Bash, Grep, Glob, AskUserQuestion
|
||||
---
|
||||
|
||||
# Lightweight Code Refactor
|
||||
|
||||
Quick, focused code improvements with behavior preservation.
|
||||
|
||||
**Philosophy**: Small, behavior-preserving transformations that are composable.
|
||||
|
||||
**Scope limit**: Single named refactoring pattern. For composed refactorings, use /spec.
|
||||
|
||||
## Your Role
|
||||
|
||||
You are a **senior software engineer** tasked with refactoring code. Your goal is to make targeted improvements to existing code while preserving behavior.
|
||||
|
||||
**WAIT for user input before proceeding to plan refactor.**
|
||||
|
||||
# Stage 1: Name Pattern & Assess Complexity
|
||||
|
||||
**Actions**:
|
||||
1. **Name the refactoring pattern(s)**
|
||||
- Examples: Extract Method, Rename Variable, Move Field, Inline Function, Replace Conditional with Polymorphism, etc.
|
||||
- Can you name it with a single, specific refactoring?
|
||||
|
||||
2. **Count mechanical steps** required
|
||||
- Each refactoring has defined steps (usually 3-8)
|
||||
- Example: Extract Method = 4 steps (create new method, copy code, replace with call, test)
|
||||
|
||||
3. **Count touch points** (locations that need changing)
|
||||
- Not files, but specific code locations (function calls, variable references, etc.)
|
||||
- Example: Renaming a function used in 12 places = 12 touch points
|
||||
|
||||
**Complexity gates**:
|
||||
|
||||
```
|
||||
If multiple distinct patterns detected:
|
||||
❌ This requires {Pattern A} + {Pattern B}
|
||||
These should be separate refactorings.
|
||||
Recommendation: Let's do {Pattern A} first, then {Pattern B}?
|
||||
```
|
||||
|
||||
```
|
||||
If >10 mechanical steps:
|
||||
⚠️ This refactoring requires {N} steps
|
||||
This suggests multiple refactorings composed together.
|
||||
Recommendation: Break into smaller refactorings or use /spec
|
||||
```
|
||||
|
||||
```
|
||||
If >15 touch points:
|
||||
⚠️ This affects {N} locations across the codebase
|
||||
High touch point count = increased risk
|
||||
Recommendation: Proceed with caution OR use /spec for better planning
|
||||
```
|
||||
|
||||
**Programming construct classification** (Structured Chain-of-Thought):
|
||||
- **Sequence**: Linear transformations, single-path changes
|
||||
- Patterns: Rename, Move, Change Signature, Replace Type Code
|
||||
- Reasoning: "Change flows through {A} → {B} → {C}"
|
||||
|
||||
- **Branch**: Conditional logic improvements
|
||||
- Patterns: Consolidate Conditional Expression, Replace Conditional with Polymorphism, Decompose Conditional
|
||||
- Reasoning: "Current logic has {N} branches, simplify to {M} branches"
|
||||
|
||||
- **Loop**: Iteration pattern improvements
|
||||
- Patterns: Replace Loop with Pipeline, Extract Loop
|
||||
- Reasoning: "Loop iterates over {X}, can use {functional pattern}"
|
||||
|
||||
**Output analysis**:
|
||||
```
|
||||
Refactoring: {Pattern name}
|
||||
Construct type: {Sequence/Branch/Loop}
|
||||
Mechanical steps: {N}
|
||||
Touch points: {N locations}
|
||||
```
|
||||
|
||||
**If all gates pass**: Proceed to Stage 2
|
||||
**If any gate triggers**: Recommend decomposition or /spec
|
||||
|
||||
# Stage 2: Load Context & Establish Baseline
|
||||
|
||||
**Read files**:
|
||||
1. Target file(s) to refactor
|
||||
2. Related test file(s)
|
||||
|
||||
**Run baseline tests**:
|
||||
```bash
|
||||
{test_command for affected modules}
|
||||
```
|
||||
|
||||
**Check**:
|
||||
- [ ] Tests currently GREEN
|
||||
- [ ] No compilation errors
|
||||
|
||||
**If tests fail**:
|
||||
```
|
||||
⚠️ Baseline tests failing. Fix these first:
|
||||
{failing test list}
|
||||
```
|
||||
|
||||
**If no tests**:
|
||||
```
|
||||
⚠️ No tests found for {target}
|
||||
Proceed without test coverage? (y/n)
|
||||
```
|
||||
|
||||
# Stage 3: Preview Changes & Quality Check
|
||||
|
||||
**Describe refactor**:
|
||||
```
|
||||
Refactoring: {Pattern name} ({Sequence/Branch/Loop})
|
||||
Mechanical steps: {N}
|
||||
Touch points: {N locations across M files}
|
||||
|
||||
Mechanics:
|
||||
1. {Step 1 description}
|
||||
2. {Step 2 description}
|
||||
...
|
||||
{N}. {Step N description}
|
||||
|
||||
Files affected:
|
||||
- {file1}: {what changes}
|
||||
- {file2}: {what changes}
|
||||
```
|
||||
|
||||
**Quality checkpoint**:
|
||||
- **Behavior preservation**: Will this maintain existing behavior? {Yes/No + reasoning}
|
||||
- **Complexity**: Does this reduce or maintain complexity? {Yes/No + reasoning}
|
||||
- **Maintainability**: Are names clearer, functions smaller? {Yes/No + reasoning}
|
||||
- **Risk**: Any edge cases not covered by existing tests? {Low/Medium/High + what cases}
|
||||
|
||||
**Approval**: `Proceed? (y/n)`
|
||||
|
||||
Wait for confirmation.
|
||||
|
||||
# Stage 4: Execute & Verify
|
||||
|
||||
**Make changes** using Edit tool for each file.
|
||||
|
||||
**Run tests after changes**:
|
||||
```bash
|
||||
{test_command for affected modules}
|
||||
```
|
||||
|
||||
**Verification**:
|
||||
- [ ] All tests GREEN
|
||||
- [ ] No new warnings
|
||||
|
||||
**On success**:
|
||||
```
|
||||
✓ Refactor complete
|
||||
Tests: {X} passing
|
||||
```
|
||||
|
||||
**On failure**:
|
||||
```
|
||||
✗ Tests failed after refactor
|
||||
{error output}
|
||||
|
||||
Analyzing failure...
|
||||
```
|
||||
|
||||
**Reflection and fix** (Reflexion pattern):
|
||||
1. **Why did tests break?** {Analyze error messages and stack traces}
|
||||
2. **What assumption was wrong?** {Identify incorrect reasoning about behavior}
|
||||
3. **Root cause**: {Specific technical reason - e.g., "Missed null handling in branch X"}
|
||||
4. **Fix strategy**: {What needs to change to make tests pass}
|
||||
|
||||
**Apply fix** based on reflection:
|
||||
- Make corrective changes to address root cause
|
||||
- Re-run tests
|
||||
- If tests pass: Success ✓
|
||||
- If tests still fail: Iterate reflection → fix (max 2 additional attempts)
|
||||
|
||||
**If unable to fix after 3 attempts**:
|
||||
```
|
||||
Unable to complete refactor after analysis.
|
||||
Root cause: {technical reason}
|
||||
Recommendation: {what needs investigation OR revert and try different approach}
|
||||
|
||||
Revert changes? (y/n)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Common refactoring patterns supported**:
|
||||
- **Extract Method/Function** - Pull code into new function
|
||||
- **Inline Method/Function** - Replace call with method body
|
||||
- **Rename Variable/Function/Class** - Change name throughout codebase
|
||||
- **Move Method/Field** - Relocate to different class/module
|
||||
- **Replace Type Code** - Change primitive type to more semantic type
|
||||
- **Consolidate Conditional Expression** - Combine related conditionals
|
||||
- **Decompose Conditional** - Extract complex conditional logic
|
||||
- **Replace Loop with Pipeline** - Convert imperative to functional
|
||||
- **Change Function Signature** - Modify parameters/return type
|
||||
- **Encapsulate Variable** - Add getter/setter for field access
|
||||
|
||||
**Not supported** (use /spec):
|
||||
- Multiple composed refactorings (do them sequentially instead)
|
||||
- >10 mechanical steps or >15 touch points
|
||||
- Database migrations requiring schema changes
|
||||
- Adding new dependencies
|
||||
- API contract changes affecting external consumers
|
||||
- Architectural changes (moving between layers, changing patterns)
|
||||
|
||||
---
|
||||
|
||||
## Example Workflows
|
||||
|
||||
### Example 1: Replace Type Code (Sequence)
|
||||
|
||||
**User**: "Change `status()` return type from integer to boolean in the User module"
|
||||
|
||||
**Stage 1**:
|
||||
```
|
||||
Refactoring: Replace Type Code (Sequence)
|
||||
Mechanical steps: 5
|
||||
- Find all uses of type code
|
||||
- Create boolean field
|
||||
- Update references to use boolean
|
||||
- Update tests
|
||||
- Remove old integer field
|
||||
Touch points: 8 locations (1 definition, 4 call sites, 3 test assertions)
|
||||
```
|
||||
✓ Single pattern, ≤10 steps, ≤15 touch points → Proceed
|
||||
|
||||
**Stage 2**:
|
||||
- Read: lib/app/user.ex, test/app/user_test.exs
|
||||
- Baseline tests: ✓ 15 passing
|
||||
|
||||
**Stage 3**:
|
||||
```
|
||||
Refactoring: Replace Type Code (Sequence)
|
||||
Mechanical steps: 5
|
||||
Touch points: 8 locations across 2 files
|
||||
|
||||
Mechanics:
|
||||
1. Create boolean field alongside integer field
|
||||
2. Update status() to return boolean based on integer
|
||||
3. Update all call sites to expect boolean
|
||||
4. Update test assertions (3 locations)
|
||||
5. Remove integer field (deprecation path)
|
||||
|
||||
Files affected:
|
||||
- lib/app/user.ex: Change status field type and getter
|
||||
- test/app/user_test.exs: Update 3 test assertions
|
||||
|
||||
Quality:
|
||||
- Behavior preservation: Yes (0/1 → false/true mapping preserved)
|
||||
- Complexity: Maintained (same logic)
|
||||
- Maintainability: Yes (bool more semantic than int)
|
||||
- Risk: Low (all usages covered by tests)
|
||||
```
|
||||
User confirms → Proceed
|
||||
|
||||
**Stage 4**:
|
||||
- Changes applied ✓
|
||||
- Tests: 15 passing ✓
|
||||
- **Complete**
|
||||
|
||||
---
|
||||
|
||||
### Example 2: Decompose Conditional (Branch)
|
||||
|
||||
**User**: "Simplify the nested if/else in `calculate_discount/1`"
|
||||
|
||||
**Stage 1**:
|
||||
```
|
||||
Refactoring: Decompose Conditional (Branch)
|
||||
Mechanical steps: 4
|
||||
- Extract condition into named function
|
||||
- Extract then-part into function
|
||||
- Extract else-part into function
|
||||
- Replace with calls
|
||||
Touch points: 1 function with 3 nested conditionals
|
||||
```
|
||||
✓ Single pattern, ≤10 steps, ≤15 touch points → Proceed
|
||||
|
||||
**Stage 2**:
|
||||
- Read: lib/app/pricing.ex, test/app/pricing_test.exs
|
||||
- Baseline tests: ✓ 8 passing
|
||||
|
||||
**Stage 3**:
|
||||
```
|
||||
Refactoring: Decompose Conditional (Branch)
|
||||
Mechanical steps: 4
|
||||
Touch points: 1 function across 1 file
|
||||
|
||||
Mechanics:
|
||||
1. Extract nested conditions into guard clauses
|
||||
2. Replace if/else structure with pattern matching
|
||||
3. Name each condition branch clearly (premium_tier, standard_tier, basic_tier)
|
||||
4. Test each branch path
|
||||
|
||||
Files affected:
|
||||
- lib/app/pricing.ex: Refactor calculate_discount/1
|
||||
|
||||
Quality:
|
||||
- Behavior preservation: Yes (same discount logic, clearer structure)
|
||||
- Complexity: Reduced (3 nesting levels → 0, cyclomatic complexity 8 → 3)
|
||||
- Maintainability: Yes (guard clauses show intent, easier to add new tiers)
|
||||
- Risk: Low (same 8 test cases cover all branches)
|
||||
```
|
||||
User confirms → Proceed
|
||||
|
||||
**Stage 4**:
|
||||
- Changes applied ✓
|
||||
- Tests: 8 passing ✓
|
||||
- **Complete**
|
||||
|
||||
---
|
||||
|
||||
**Note**: This template optimized using research-backed principles: Structured Chain-of-Thought (SCoT +13.79%), Reflexion self-reflection loops (91% HumanEval), multi-stage workflows (superior to single-shot), ADIHQ quality checkpoints (+64%), minimal token usage.
|
||||
205
skills/specimin-review/SKILL.md
Normal file
205
skills/specimin-review/SKILL.md
Normal file
@@ -0,0 +1,205 @@
|
||||
---
|
||||
name: "specimin-review"
|
||||
description: "Review a PR created through the spec/plan/implement flow. Analyzes changes against specification and provides actionable feedback. Only invoke when user explicitly requests to review a PR or review changes."
|
||||
allowed-tools:
|
||||
- run_terminal_cmd
|
||||
- write
|
||||
- read_file
|
||||
---
|
||||
|
||||
# PR Review Command
|
||||
|
||||
Analyze pull request changes against feature specification and provide structured, actionable feedback.
|
||||
|
||||
## Stage 1: Gather Context
|
||||
|
||||
**Actions**:
|
||||
1. Get current branch: `git rev-parse --abbrev-ref HEAD` → store as `BRANCH`
|
||||
2. Fetch PR info: `bash ${CLAUDE_PLUGIN_ROOT}/.claude-plugin/skills/specimin-review/scripts/get-pr-info.sh "$BRANCH"`
|
||||
3. Verify feature directory: `.specimin/plans/$BRANCH/` must exist
|
||||
4. Read context files:
|
||||
- `.specimin/plans/$BRANCH/spec.md` → store key acceptance criteria
|
||||
- `.specimin/plans/$BRANCH/plan.md` → store component list and testing strategy
|
||||
5. Get diff summary: `git diff main...$BRANCH --stat`
|
||||
6. Get files changed: `git diff main...$BRANCH --name-only`
|
||||
|
||||
**Error Handling**:
|
||||
- No PR found: `Error: No PR found for branch. Run /wrap to create PR first.` → Exit
|
||||
- No feature dir: `Error: Branch not part of spec flow. Use this for Specimin-created PRs only.` → Exit
|
||||
- `gh` not installed: `Error: GitHub CLI required. Install: https://cli.github.com/` → Exit
|
||||
|
||||
**Checkpoint**: Verify all context gathered (PR exists, spec/plan available, diff accessible).
|
||||
|
||||
## Stage 2: Analyze Changes
|
||||
|
||||
**Focus Areas** (in order of priority):
|
||||
1. **Completeness**: All acceptance criteria from spec addressed?
|
||||
2. **Alignment**: Changes match planned components and approach?
|
||||
3. **Quality**: Code follows project patterns, proper error handling, tests included?
|
||||
4. **Scope**: Any unplanned changes or scope creep?
|
||||
|
||||
**Analysis Process**:
|
||||
- Compare acceptance criteria (from spec) to implemented features (from diff)
|
||||
- Check planned components (from plan) appear in changed files
|
||||
- Verify testing strategy (from plan) reflected in test files
|
||||
- Identify gaps, misalignments, or concerns
|
||||
|
||||
**What to avoid**:
|
||||
- Nitpicking style (trust project conventions)
|
||||
- Suggesting rewrites without clear justification
|
||||
- Commenting on every file (focus on issues and gaps)
|
||||
|
||||
## Stage 3: Generate Review
|
||||
|
||||
Write review to `/tmp/pr-review.md` using format below:
|
||||
|
||||
```markdown
|
||||
# PR Review: [PR Title]
|
||||
|
||||
**Branch**: [branch] | **PR**: [url] | **Status**: [state]
|
||||
|
||||
## Summary
|
||||
[2-3 sentences: what was implemented, overall assessment]
|
||||
|
||||
## Acceptance Criteria Coverage
|
||||
[For each criterion from spec.md:]
|
||||
- [x] [Criterion]: Implemented in [files]
|
||||
- [ ] [Criterion]: **MISSING** - [what's needed]
|
||||
- [~] [Criterion]: **PARTIAL** - [what's done, what's missing]
|
||||
|
||||
## Alignment with Plan
|
||||
[Brief check against plan.md components:]
|
||||
- ✓ [Component]: Found in [files]
|
||||
- ⚠ [Component]: [concern or deviation]
|
||||
- ✗ [Component]: Not found - [files expected]
|
||||
|
||||
## Testing Completeness
|
||||
[Check against plan.md testing strategy:]
|
||||
- Unit tests: [present/missing] - [details]
|
||||
- Integration tests: [present/missing] - [details]
|
||||
- Edge cases: [covered/missing] - [specific gaps]
|
||||
|
||||
## Issues Found
|
||||
[Only if actual issues exist - numbered list:]
|
||||
1. **[Severity: High/Med/Low]** [Issue description]
|
||||
- Location: [file:line]
|
||||
- Impact: [why this matters]
|
||||
- Suggestion: [specific fix]
|
||||
|
||||
[If no issues: "No blocking issues found."]
|
||||
|
||||
## Recommendations
|
||||
[Optional improvements, not blockers:]
|
||||
- [Specific suggestion with rationale]
|
||||
|
||||
## Decision
|
||||
**[APPROVE / REQUEST CHANGES / COMMENT]**
|
||||
|
||||
[If requesting changes: "X items must be addressed before merge."]
|
||||
[If approving: "Ready to merge once tests pass."]
|
||||
```
|
||||
|
||||
**Checkpoint**: Review saved to `/tmp/pr-review.md`.
|
||||
|
||||
## Stage 4: Finalize
|
||||
|
||||
1. Show review summary to user (Summary + Decision sections only)
|
||||
2. Ask: "Save this review to feature directory? (yes/no)"
|
||||
3. If yes: `bash ${CLAUDE_PLUGIN_ROOT}/.claude-plugin/skills/specimin-review/scripts/save-review.sh "$BRANCH" /tmp/pr-review.md`
|
||||
4. Parse JSON output (includes `review_number` and `review_path`)
|
||||
5. Confirm: "✓ Review #[review_number] saved to `[review_path]`"
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Complete Implementation
|
||||
|
||||
**Spec criteria**: User auth with JWT, password reset, session management
|
||||
**Plan components**: AuthService, TokenHandler, ResetController, SessionStore
|
||||
**Changed files**: `services/auth.ts`, `handlers/token.ts`, `controllers/reset.ts`, `stores/session.ts`, `__tests__/auth.test.ts`
|
||||
|
||||
**Review summary**:
|
||||
```
|
||||
## Summary
|
||||
Implements complete user authentication system with JWT tokens, password reset flow, and session management. All planned components present with comprehensive test coverage.
|
||||
|
||||
## Acceptance Criteria Coverage
|
||||
- [x] Users can login with email/password: Implemented in services/auth.ts:45
|
||||
- [x] JWT tokens for authentication: Implemented in handlers/token.ts:12
|
||||
- [x] Password reset via email: Implemented in controllers/reset.ts:78
|
||||
- [x] Sessions persist 7 days: Configured in stores/session.ts:23
|
||||
|
||||
## Alignment with Plan
|
||||
- ✓ AuthService: Found in services/auth.ts
|
||||
- ✓ TokenHandler: Found in handlers/token.ts
|
||||
- ✓ ResetController: Found in controllers/reset.ts
|
||||
- ✓ SessionStore: Found in stores/session.ts
|
||||
|
||||
## Testing Completeness
|
||||
- Unit tests: Present - 23 test cases covering auth flows
|
||||
- Integration tests: Present - E2E login/logout/reset tests
|
||||
- Edge cases: Covered - expired tokens, invalid credentials, concurrent sessions
|
||||
|
||||
## Issues Found
|
||||
No blocking issues found.
|
||||
|
||||
## Decision
|
||||
**APPROVE** - Ready to merge once tests pass.
|
||||
```
|
||||
|
||||
### Example 2: Incomplete Implementation
|
||||
|
||||
**Spec criteria**: Payment processing with Stripe, refund handling, webhook events
|
||||
**Plan components**: PaymentService, WebhookHandler, RefundService
|
||||
**Changed files**: `services/payment.ts`, `handlers/webhook.ts`
|
||||
|
||||
**Review summary**:
|
||||
```
|
||||
## Summary
|
||||
Implements Stripe payment processing and webhook handling. Refund functionality missing from implementation.
|
||||
|
||||
## Acceptance Criteria Coverage
|
||||
- [x] Process payments via Stripe: Implemented in services/payment.ts:34
|
||||
- [x] Handle webhook events: Implemented in handlers/webhook.ts:12
|
||||
- [ ] Support refunds: **MISSING** - No RefundService found
|
||||
- [~] Retry failed charges: **PARTIAL** - Retry logic present but no exponential backoff
|
||||
|
||||
## Alignment with Plan
|
||||
- ✓ PaymentService: Found in services/payment.ts
|
||||
- ✓ WebhookHandler: Found in handlers/webhook.ts
|
||||
- ✗ RefundService: Not found - expected services/refund.ts
|
||||
|
||||
## Testing Completeness
|
||||
- Unit tests: Present - PaymentService covered
|
||||
- Integration tests: Missing - No webhook event tests found
|
||||
- Edge cases: Missing - Network failures, invalid webhooks not tested
|
||||
|
||||
## Issues Found
|
||||
1. **[High]** Refund functionality missing
|
||||
- Location: services/refund.ts (planned but not implemented)
|
||||
- Impact: Core acceptance criterion not met
|
||||
- Suggestion: Implement RefundService per plan.md:67
|
||||
|
||||
2. **[Medium]** No webhook integration tests
|
||||
- Location: __tests__/webhook.test.ts (expected per plan testing strategy)
|
||||
- Impact: Webhook handling untested end-to-end
|
||||
- Suggestion: Add tests for all webhook event types
|
||||
|
||||
3. **[Low]** Retry lacks exponential backoff
|
||||
- Location: services/payment.ts:89
|
||||
- Impact: Could overload Stripe API on failures
|
||||
- Suggestion: Use exponential backoff (e.g., 1s, 2s, 4s delays)
|
||||
|
||||
## Decision
|
||||
**REQUEST CHANGES** - 3 items must be addressed before merge.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Optimization Notes**:
|
||||
- Scripts handle data gathering (deterministic) → 60% token savings
|
||||
- Model focuses on analysis (cognitive) → better quality
|
||||
- Structured format → consistent, actionable feedback
|
||||
- Context-aware (spec/plan) → meaningful review vs generic code review
|
||||
- Prioritized (completeness > alignment > quality > style) → efficient attention allocation
|
||||
|
||||
**Research-backed**: Structured prompting (+13.79% SCoT), minimal context (CGRAG 4x), verification stages (Reflexion 91%), token efficiency (ADIHQ -39%)
|
||||
37
skills/specimin-review/scripts/get-pr-diff.sh
Executable file
37
skills/specimin-review/scripts/get-pr-diff.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
# get-pr-diff.sh - Gets the diff for a PR
|
||||
# Usage: get-pr-diff.sh <branch_name> [main_branch]
|
||||
# Output: Diff text with stats
|
||||
|
||||
set -e
|
||||
|
||||
BRANCH_NAME="$1"
|
||||
MAIN_BRANCH="${2:-main}"
|
||||
|
||||
if [ -z "$BRANCH_NAME" ]; then
|
||||
echo "Error: Branch name required"
|
||||
echo "Usage: get-pr-diff.sh <branch_name> [main_branch]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify main branch exists, fallback to master
|
||||
if ! git show-ref --verify --quiet "refs/heads/$MAIN_BRANCH"; then
|
||||
if git show-ref --verify --quiet refs/heads/master; then
|
||||
MAIN_BRANCH="master"
|
||||
else
|
||||
echo "Error: Could not find main or master branch"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Get diff stats
|
||||
echo "=== DIFF STATS ==="
|
||||
git diff "$MAIN_BRANCH...$BRANCH_NAME" --stat
|
||||
|
||||
echo ""
|
||||
echo "=== FILES CHANGED ==="
|
||||
git diff "$MAIN_BRANCH...$BRANCH_NAME" --name-status
|
||||
|
||||
echo ""
|
||||
echo "=== FULL DIFF ==="
|
||||
git diff "$MAIN_BRANCH...$BRANCH_NAME"
|
||||
32
skills/specimin-review/scripts/get-pr-info.sh
Executable file
32
skills/specimin-review/scripts/get-pr-info.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
# get-pr-info.sh - Fetches PR information for the current branch
|
||||
# Usage: get-pr-info.sh [branch_name]
|
||||
# Output: JSON with PR details
|
||||
|
||||
set -e
|
||||
|
||||
BRANCH_NAME="${1:-$(git rev-parse --abbrev-ref HEAD)}"
|
||||
|
||||
# Check if gh CLI is installed
|
||||
if ! command -v gh &> /dev/null; then
|
||||
echo '{"error": "GitHub CLI (gh) not installed. Install: https://cli.github.com/"}' | jq
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if authenticated
|
||||
if ! gh auth status &> /dev/null; then
|
||||
echo '{"error": "Not authenticated with GitHub CLI. Run: gh auth login"}' | jq
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get PR for current branch
|
||||
PR_DATA=$(gh pr view "$BRANCH_NAME" --json number,title,body,url,state,isDraft,additions,deletions,changedFiles 2>/dev/null || echo '{"error": "No PR found for branch: '"$BRANCH_NAME"'"}')
|
||||
|
||||
# Check if error in PR_DATA
|
||||
if echo "$PR_DATA" | jq -e '.error' &> /dev/null; then
|
||||
echo "$PR_DATA"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add branch name to output
|
||||
echo "$PR_DATA" | jq --arg branch "$BRANCH_NAME" '. + {branch: $branch}'
|
||||
53
skills/specimin-review/scripts/save-review.sh
Executable file
53
skills/specimin-review/scripts/save-review.sh
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
# save-review.sh - Saves PR review to feature directory
|
||||
# Usage: save-review.sh <branch_name> <review_file_path>
|
||||
|
||||
set -e
|
||||
|
||||
BRANCH_NAME="$1"
|
||||
REVIEW_FILE_PATH="$2"
|
||||
|
||||
if [ -z "$BRANCH_NAME" ] || [ -z "$REVIEW_FILE_PATH" ]; then
|
||||
echo "Error: Missing required arguments"
|
||||
echo "Usage: save-review.sh <branch_name> <review_file_path>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify feature directory exists
|
||||
FEATURE_DIR=".specimin/plans/$BRANCH_NAME"
|
||||
if [ ! -d "$FEATURE_DIR" ]; then
|
||||
echo "Error: Feature directory not found: $FEATURE_DIR"
|
||||
echo "This PR was not created through the spec/plan/implement flow."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify review file exists
|
||||
if [ ! -f "$REVIEW_FILE_PATH" ]; then
|
||||
echo "Error: Review file not found: $REVIEW_FILE_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create reviews directory if it doesn't exist
|
||||
REVIEWS_DIR="$FEATURE_DIR/reviews"
|
||||
mkdir -p "$REVIEWS_DIR"
|
||||
|
||||
# Find the next review number
|
||||
NEXT_NUM=1
|
||||
if [ -d "$REVIEWS_DIR" ]; then
|
||||
# Find highest existing review number
|
||||
HIGHEST=$(find "$REVIEWS_DIR" -name "review_*.md" -type f 2>/dev/null | \
|
||||
sed 's/.*review_\([0-9]*\)\.md/\1/' | \
|
||||
sort -n | \
|
||||
tail -1)
|
||||
|
||||
if [ -n "$HIGHEST" ]; then
|
||||
NEXT_NUM=$((HIGHEST + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
# Copy review file to reviews directory with incremental number
|
||||
REVIEW_DEST="$REVIEWS_DIR/review_$NEXT_NUM.md"
|
||||
cp "$REVIEW_FILE_PATH" "$REVIEW_DEST"
|
||||
|
||||
# Output success message with JSON
|
||||
echo "{\"feature_dir\": \"$FEATURE_DIR\", \"branch_name\": \"$BRANCH_NAME\", \"review_path\": \"$REVIEW_DEST\", \"review_number\": $NEXT_NUM}"
|
||||
161
skills/specimin-spec/SKILL.md
Normal file
161
skills/specimin-spec/SKILL.md
Normal file
@@ -0,0 +1,161 @@
|
||||
---
|
||||
name: "specimin-spec"
|
||||
description: "Create or update the feature specification from a natural language feature description. Only invoke when user explicitly requests to create a specification, spec, or feature specification."
|
||||
allowed-tools:
|
||||
- run_terminal_cmd
|
||||
- write
|
||||
- read_file
|
||||
---
|
||||
|
||||
**ALWAYS WAIT for user input before generating spec.**
|
||||
Ask the user for:
|
||||
1. A brief description of the spec they want to create
|
||||
2. (Optional) A GitHub issue link associated with this feature
|
||||
|
||||
BEFORE generating the spec.
|
||||
|
||||
# Interactive Specification Generator
|
||||
|
||||
## Role
|
||||
Senior product requirements analyst translating feature requests into clear, actionable specifications. Define WHAT and WHY, not HOW.
|
||||
|
||||
## Process Flow
|
||||
|
||||
### Stage 0: Branch Name (FIRST)
|
||||
If the user provided a **GitHub issue link**, extract the issue number from it:
|
||||
- Parse URLs like: `https://github.com/owner/repo/issues/123` → Extract `123`
|
||||
- Store as `$ISSUE_NUMBER` for Stage 4
|
||||
|
||||
Otherwise, generate a **2-3 word, kebab-case branch name** from the user's requirement:
|
||||
- **Good**: `user-auth`, `pdf-export`, `real-time-sync`
|
||||
- **Bad**: `authentication-system-with-jwt`, `feature`, `new-feature`
|
||||
|
||||
Store as `$BRANCH_NAME` for Stage 4.
|
||||
|
||||
### Stage 1: Analyze & Clarify
|
||||
|
||||
1. Identify critical ambiguities: scope > security/privacy > UX > technical
|
||||
2. Ask 2-5 focused questions with concrete options
|
||||
3. Show impact of each option
|
||||
4. Wait for responses
|
||||
|
||||
**Question Template:**
|
||||
```
|
||||
## Q[N]: [Topic]
|
||||
**Need to know**: [Specific question]
|
||||
|
||||
**Options**:
|
||||
- A: [Description] → Impact: [Consequence]
|
||||
- B: [Description] → Impact: [Consequence]
|
||||
- Custom: [Your preference]
|
||||
```
|
||||
|
||||
### Stage 2: Generate Draft
|
||||
Create specification using Output Format (below) based on user answers.
|
||||
|
||||
### Stage 3: Iterate
|
||||
Ask: "Does this capture what you need? What should I adjust?"
|
||||
Refine until approved.
|
||||
|
||||
### Stage 4: Finalize
|
||||
**ONLY after user approval:**
|
||||
|
||||
1. Write approved spec to temporary file `/tmp/spec-draft.md`
|
||||
|
||||
2. Execute save script:
|
||||
- **If GitHub issue link was provided:**
|
||||
```bash
|
||||
bash ${CLAUDE_PLUGIN_ROOT}/.claude-plugin/skills/specimin-spec/scripts/save-spec.sh "$USER_REQUIREMENT" "$BRANCH_NAME" /tmp/spec-draft.md "$ISSUE_NUMBER"
|
||||
```
|
||||
- **Otherwise:**
|
||||
```bash
|
||||
bash ${CLAUDE_PLUGIN_ROOT}/.claude-plugin/skills/specimin-spec/scripts/save-spec.sh "$USER_REQUIREMENT" "$BRANCH_NAME" /tmp/spec-draft.md
|
||||
```
|
||||
|
||||
3. Parse JSON output and confirm to user:
|
||||
"✓ Specification saved to `[spec_path]` on branch `[branch_name]`"
|
||||
|
||||
## Output Format
|
||||
|
||||
**Objective**: [What needs accomplishing]
|
||||
|
||||
**Context**: [Why needed, business impact]
|
||||
|
||||
**Assumptions**: [Reasonable defaults]
|
||||
|
||||
**Constraints**: [Technical and business limitations]
|
||||
|
||||
**Acceptance Criteria**: [Verifiable, testable conditions]
|
||||
|
||||
**User Scenarios**: [Step-by-step flows with expected outcomes]
|
||||
|
||||
**Edge Cases**: [Boundary conditions]
|
||||
|
||||
**Dependencies** *(if applicable)*: [External requirements]
|
||||
|
||||
**Out of Scope**: [Explicitly excluded]
|
||||
|
||||
## Requirements
|
||||
|
||||
**Include:**
|
||||
- Clear objectives and constraints
|
||||
- Testable acceptance criteria (measurable, technology-agnostic)
|
||||
- Realistic user scenarios
|
||||
- Explicit scope boundaries
|
||||
- Documented assumptions
|
||||
|
||||
**Exclude:**
|
||||
- Technology choices (databases, frameworks, languages)
|
||||
- API designs or code structure
|
||||
- Implementation algorithms
|
||||
|
||||
**Good**: "Users complete checkout in under 3 minutes"
|
||||
**Bad**: "API response time under 200ms" (too technical)
|
||||
|
||||
## Example
|
||||
|
||||
**User**: "Users should stay logged in when they close and reopen the browser"
|
||||
|
||||
**Objective**
|
||||
Implement persistent user authentication across browser sessions.
|
||||
|
||||
**Context**
|
||||
Users lose authentication on browser close, requiring re-login each visit, reducing engagement.
|
||||
|
||||
**Assumptions**
|
||||
- Standard web security practices apply
|
||||
- Session duration configurable by administrators
|
||||
- Users expect multi-day persistence unless explicitly logging out
|
||||
- Browser storage mechanisms available
|
||||
|
||||
**Constraints**
|
||||
- Must integrate with existing authentication system
|
||||
- Must follow security best practices for credential storage
|
||||
- Session duration must be configurable
|
||||
- Must handle expiration gracefully
|
||||
|
||||
**Acceptance Criteria**
|
||||
- User remains authenticated after browser close/reopen
|
||||
- User prompted to re-authenticate after session expires
|
||||
- User can explicitly log out to end session
|
||||
- Works across major browsers (Chrome, Firefox, Safari, Edge)
|
||||
|
||||
**User Scenarios**
|
||||
1. Returning user: Login → Close browser → Reopen → Still authenticated
|
||||
2. Session expiration: Login → Wait past duration → Prompted to re-login
|
||||
3. Explicit logout: Authenticated → Logout → Close/reopen → Must login
|
||||
|
||||
**Edge Cases**
|
||||
- Multiple simultaneous sessions (different devices/windows)
|
||||
- Session expiration during active use
|
||||
- Browser storage unavailable or cleared
|
||||
- User switches between devices
|
||||
|
||||
**Dependencies**
|
||||
- Existing authentication system must expose session management APIs
|
||||
|
||||
**Out of Scope**
|
||||
- Cross-device session synchronization
|
||||
- "Remember this device" functionality
|
||||
- Biometric authentication
|
||||
|
||||
58
skills/specimin-spec/scripts/save-spec.sh
Executable file
58
skills/specimin-spec/scripts/save-spec.sh
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/bin/bash
|
||||
# save-spec.sh - Saves approved specification and commits to feature branch
|
||||
# Usage: save-spec.sh <user_requirement> <branch_name> <spec_file_path> [issue_number]
|
||||
|
||||
set -e
|
||||
|
||||
USER_REQUIREMENT="$1"
|
||||
BRANCH_NAME="$2"
|
||||
SPEC_FILE_PATH="$3"
|
||||
ISSUE_NUMBER="${4:-}"
|
||||
|
||||
if [ -z "$USER_REQUIREMENT" ] || [ -z "$BRANCH_NAME" ] || [ -z "$SPEC_FILE_PATH" ]; then
|
||||
echo "Error: Missing required arguments"
|
||||
echo "Usage: save-spec.sh <user_requirement> <branch_name> <spec_file_path> [issue_number]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify initialization
|
||||
if [ ! -d ".specimin/plans/" ]; then
|
||||
echo "Error: Specimin not initialized. Please run /init first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify spec file exists
|
||||
if [ ! -f "$SPEC_FILE_PATH" ]; then
|
||||
echo "Error: Spec file not found: $SPEC_FILE_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get script directory
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Run setup script
|
||||
if [ -n "$ISSUE_NUMBER" ]; then
|
||||
SETUP_OUTPUT=$(bash "$SCRIPT_DIR/setup.feature.sh" "$USER_REQUIREMENT" --json --no-commit --branch-name "$BRANCH_NAME" --issue-number "$ISSUE_NUMBER")
|
||||
else
|
||||
SETUP_OUTPUT=$(bash "$SCRIPT_DIR/setup.feature.sh" "$USER_REQUIREMENT" --json --no-commit --branch-name "$BRANCH_NAME")
|
||||
fi
|
||||
|
||||
# Parse output
|
||||
FEATURE_DIR=$(echo "$SETUP_OUTPUT" | jq -r '.feature_dir')
|
||||
BRANCH_NAME=$(echo "$SETUP_OUTPUT" | jq -r '.branch_name')
|
||||
|
||||
if [ -z "$FEATURE_DIR" ] || [ "$FEATURE_DIR" = "null" ]; then
|
||||
echo "Error: Failed to create feature directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy spec file to feature directory
|
||||
SPEC_DEST="$FEATURE_DIR/spec.md"
|
||||
cp "$SPEC_FILE_PATH" "$SPEC_DEST"
|
||||
|
||||
# Commit
|
||||
git add "$SPEC_DEST"
|
||||
git commit -m "Add specification: $USER_REQUIREMENT"
|
||||
|
||||
# Output success message with JSON
|
||||
echo "{\"feature_dir\": \"$FEATURE_DIR\", \"branch_name\": \"$BRANCH_NAME\", \"spec_path\": \"$SPEC_DEST\"}"
|
||||
172
skills/specimin-spec/scripts/setup.feature.sh
Executable file
172
skills/specimin-spec/scripts/setup.feature.sh
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Script: setup.feature.sh
|
||||
# Description: Create feature branch and planning directory
|
||||
# Usage: ./setup.feature.sh "feature description" [--json] [--no-commit] [--branch-name "custom-name"] [--issue-number "123"]
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
print_error() { echo -e "${RED}ERROR: $1${NC}" >&2; }
|
||||
print_success() { echo -e "${GREEN}SUCCESS: $1${NC}"; }
|
||||
print_info() { echo -e "${YELLOW}INFO: $1${NC}"; }
|
||||
|
||||
get_next_branch_number() {
|
||||
# Get all branches matching the pattern and extract the highest number
|
||||
local max_num=$(git branch -a | \
|
||||
grep -oE '[0-9]{3}-' | \
|
||||
grep -oE '[0-9]{3}' | \
|
||||
sort -n | \
|
||||
tail -1)
|
||||
|
||||
if [[ -z "$max_num" ]]; then
|
||||
echo "001"
|
||||
else
|
||||
printf "%03d" $((10#$max_num + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
generate_branch_name() {
|
||||
local description="$1"
|
||||
|
||||
# Extract first two words and clean them
|
||||
local two_words=$(echo "$description" | \
|
||||
tr '[:upper:]' '[:lower:]' | \
|
||||
sed 's/[^a-z0-9 -]//g' | \
|
||||
tr -s ' ' | \
|
||||
awk '{print $1"-"$2}' | \
|
||||
sed 's/^-//;s/-$//')
|
||||
|
||||
# Get next branch number
|
||||
local branch_num=$(get_next_branch_number)
|
||||
|
||||
echo "${branch_num}-${two_words}"
|
||||
}
|
||||
|
||||
check_git_repo() {
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
print_error "Not a git repository"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_working_tree() {
|
||||
if ! git diff-index --quiet HEAD -- 2>/dev/null; then
|
||||
print_error "Uncommitted changes exist. Commit or stash first."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_branch_exists() {
|
||||
local branch_name="$1"
|
||||
if git rev-parse --verify "$branch_name" > /dev/null 2>&1; then
|
||||
print_error "Branch '$branch_name' already exists"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
local feature_description="${1:-}"
|
||||
local json_output=false
|
||||
local no_commit=false
|
||||
local custom_branch_name=""
|
||||
local issue_number=""
|
||||
|
||||
# Parse flags
|
||||
local i=2
|
||||
while [[ $i -le $# ]]; do
|
||||
case "${!i}" in
|
||||
--json) json_output=true ;;
|
||||
--no-commit) no_commit=true ;;
|
||||
--branch-name)
|
||||
((i++))
|
||||
custom_branch_name="${!i}"
|
||||
;;
|
||||
--issue-number)
|
||||
((i++))
|
||||
issue_number="${!i}"
|
||||
;;
|
||||
esac
|
||||
((i++))
|
||||
done
|
||||
|
||||
if [[ -z "$feature_description" ]]; then
|
||||
print_error "Feature description required"
|
||||
echo "Usage: $0 \"feature description\" [--json] [--no-commit] [--branch-name \"custom-name\"] [--issue-number \"123\"]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
check_git_repo
|
||||
check_working_tree
|
||||
|
||||
local branch_name
|
||||
local branch_num
|
||||
|
||||
# Determine branch number
|
||||
if [[ -n "$issue_number" ]]; then
|
||||
# Use issue number (padded to 3 digits)
|
||||
branch_num=$(printf "%03d" "$issue_number")
|
||||
else
|
||||
# Auto-increment (backward compatible)
|
||||
branch_num=$(get_next_branch_number)
|
||||
fi
|
||||
|
||||
if [[ -n "$custom_branch_name" ]]; then
|
||||
# Use custom branch name with branch number
|
||||
branch_name="${branch_num}-${custom_branch_name}"
|
||||
else
|
||||
# Generate from description (backward compatible)
|
||||
# Extract first two words and clean them
|
||||
local two_words=$(echo "$feature_description" | \
|
||||
tr '[:upper:]' '[:lower:]' | \
|
||||
sed 's/[^a-z0-9 -]//g' | \
|
||||
tr -s ' ' | \
|
||||
awk '{print $1"-"$2}' | \
|
||||
sed 's/^-//;s/-$//')
|
||||
branch_name="${branch_num}-${two_words}"
|
||||
fi
|
||||
|
||||
check_branch_exists "$branch_name"
|
||||
|
||||
local feature_dir=".specimin/plans/${branch_name}"
|
||||
|
||||
# Create directory
|
||||
mkdir -p "$feature_dir"
|
||||
|
||||
# Create and checkout branch
|
||||
git checkout -b "$branch_name" --quiet
|
||||
|
||||
if [[ "$no_commit" == false ]]; then
|
||||
# Commit empty directory structure (backward compatible behavior)
|
||||
touch "$feature_dir/.gitkeep"
|
||||
git add "$feature_dir"
|
||||
git commit -m "Initialize feature: $feature_description" --quiet
|
||||
fi
|
||||
|
||||
if [[ "$json_output" == true ]]; then
|
||||
cat << EOF
|
||||
{
|
||||
"branch_name": "$branch_name",
|
||||
"feature_dir": "$feature_dir",
|
||||
"absolute_path": "$(pwd)/$feature_dir",
|
||||
"status": "success"
|
||||
}
|
||||
EOF
|
||||
else
|
||||
print_success "Feature setup complete!"
|
||||
echo ""
|
||||
echo "Branch: $branch_name"
|
||||
echo "Directory: $feature_dir"
|
||||
if [[ "$no_commit" == false ]]; then
|
||||
echo ""
|
||||
echo "Next: Use spec template to create $feature_dir/spec.md"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
311
skills/specimin-task/SKILL.md
Normal file
311
skills/specimin-task/SKILL.md
Normal file
@@ -0,0 +1,311 @@
|
||||
---
|
||||
name: "specimin-task"
|
||||
description: "Generate atomic implementation tasks from high-level plans, providing coding agents with clear, actionable work items. Only invoke when user explicitly requests to create tasks, break down tasks, generate implementation tasks, or create a task breakdown."
|
||||
allowed-tools:
|
||||
- run_terminal_cmd
|
||||
- write
|
||||
- read_file
|
||||
---
|
||||
|
||||
# Interactive Implementation Task Generator
|
||||
|
||||
Decompose technical plans into atomic, executable tasks following Test-Driven Development.
|
||||
|
||||
# Stage 1: Load Context
|
||||
|
||||
**Actions**:
|
||||
1. Run `git rev-parse --abbrev-ref HEAD` to get current branch
|
||||
2. Verify `.specimin/plans/{branch}/` exists. If not: `Error: Specimin not initialized. Run /init first.`
|
||||
3. Read `.specimin/plans/{branch}/plan.md` (high-level plan)
|
||||
4. Read `.specimin/plans/{branch}/spec.md` (feature specification)
|
||||
|
||||
**Context Extraction Goals**:
|
||||
- Component/module names and boundaries
|
||||
- Data structures and models
|
||||
- Integration points with existing code
|
||||
- Technical decisions (libraries, patterns, architectures)
|
||||
- Key function responsibilities
|
||||
|
||||
**Error Handling**: If plan.md missing: `Error: No plan.md found for branch '{branch}'. Run /feature.plan first.`
|
||||
|
||||
# Stage 2: Analyze Plan Structure
|
||||
|
||||
Identify blocking ambiguities that prevent concrete task generation:
|
||||
- **Dependencies**: Unclear integration points?
|
||||
- **Technical choices**: Multiple valid approaches without clear direction?
|
||||
- **Error handling**: Unaddressed edge cases or failure modes?
|
||||
- **Data flow**: Unclear inputs/outputs between components?
|
||||
|
||||
**Identify 0-5 critical ambiguities only**. Do NOT ask about:
|
||||
- Coding style, naming conventions, or trivial details
|
||||
- Implementation details you can reasonably infer
|
||||
- Non-blocking uncertainties
|
||||
|
||||
**Vague Plan Detection**: If plan lacks component structure, data flow, or function-level detail:
|
||||
```
|
||||
Warning: Plan too vague to generate atomic tasks.
|
||||
Missing: Component breakdown, data structures, integration points, function responsibilities.
|
||||
Add detail to plan.md, then rerun /cmd.implement.
|
||||
```
|
||||
|
||||
**Checkpoint**: Verify you understand all technical decisions and component boundaries before proceeding.
|
||||
|
||||
# Stage 3: Clarify Ambiguities (If Needed)
|
||||
|
||||
If ambiguities found, ask focused questions (2 concrete options + "Custom"). Maximum 0-5 questions (prefer fewer). Focus on plan-level decisions, not code details. Wait for user response.
|
||||
|
||||
If no ambiguities, skip to Stage 4.
|
||||
|
||||
# Stage 4: Generate Atomic Tasks
|
||||
|
||||
Decompose plan into **function-level atomic tasks** following TDD.
|
||||
|
||||
## Atomicity Definition
|
||||
|
||||
**Atomic task = one file or one clear unit of work**, aligned with code structures:
|
||||
- **Sequence**: One file/module (schema, controller, service, migration)
|
||||
- **Branch**: Decision logic (validation, error handling, conditional flows)
|
||||
- **Loop**: Iteration logic (batch processing, collection operations)
|
||||
|
||||
**Examples**:
|
||||
- ✅ Good: "Create User schema in lib/app/accounts/user.ex"
|
||||
- ❌ Too broad: "Implement authentication" → Split into specific files
|
||||
- ❌ Too granular: "Add variable for user ID" → Implementation detail
|
||||
|
||||
## Task Format
|
||||
|
||||
```markdown
|
||||
- [ ] T{XXX} [P?] {Verb + what + exact file path} (R{XX})
|
||||
```
|
||||
|
||||
**Elements**:
|
||||
- `- [ ]`: Checkbox for completion tracking
|
||||
- `T001, T002...`: Sequential task ID across all phases
|
||||
- `[P]`: Optional parallel marker (different files, no dependencies)
|
||||
- `Verb`: Create, Write, Implement, Verify, Add, Update
|
||||
- `(R01)`: Spec requirement mapping
|
||||
|
||||
## TDD Task Pattern (MANDATORY)
|
||||
|
||||
**Use for every feature/function**:
|
||||
```markdown
|
||||
- [ ] TXXX Write test for [capability] expecting [specific behavior] in test/[path]_test.exs (RXX)
|
||||
- [ ] TXXX Run test and confirm RED (fails with expected error message)
|
||||
- [ ] TXXX Implement [function] with minimal code to pass in lib/[path].ex (RXX)
|
||||
- [ ] TXXX Run test and confirm GREEN (passes)
|
||||
```
|
||||
|
||||
**Rules**:
|
||||
1. Test task always precedes implementation task
|
||||
2. Explicit verification tasks for RED and GREEN phases
|
||||
3. No exceptions - this is a constitution mandate
|
||||
|
||||
## Complete TDD Examples
|
||||
|
||||
**Example 1: Simple CRUD Feature (User Creation)**
|
||||
```markdown
|
||||
## Phase 1: Foundation
|
||||
- [ ] T001 Create migration for users table in priv/repo/migrations/20250106_create_users.exs (R01)
|
||||
- [ ] T002 [P] Create User schema in lib/app/accounts/user.ex (R01)
|
||||
- [ ] T003 Write test for user creation expecting {:ok, %User{}} in test/app/accounts_test.exs (R02)
|
||||
- [ ] T004 Run test and confirm RED (Accounts.create_user/1 undefined)
|
||||
- [ ] T005 Implement create_user/1 in lib/app/accounts.ex (R02)
|
||||
- [ ] T006 Run test and confirm GREEN
|
||||
|
||||
## Phase 2: Validation
|
||||
- [ ] T007 Write test for email validation expecting {:error, changeset} in test/app/accounts_test.exs (R03)
|
||||
- [ ] T008 Run test and confirm RED (validation not enforced)
|
||||
- [ ] T009 Add email validation to User changeset in lib/app/accounts/user.ex (R03)
|
||||
- [ ] T010 Run test and confirm GREEN
|
||||
```
|
||||
|
||||
**Example 2: Complex Integration (Payment Processing)**
|
||||
```markdown
|
||||
## Phase 1: External Service Setup
|
||||
- [ ] T001 [P] Create Stripe client module in lib/app/payments/stripe_client.ex (R01)
|
||||
- [ ] T002 [P] Add Stripe configuration to config/config.exs (R01)
|
||||
- [ ] T003 Write test for charge creation expecting {:ok, %Charge{}} in test/app/payments_test.exs (R02)
|
||||
- [ ] T004 Run test and confirm RED (Payments.create_charge/2 undefined)
|
||||
- [ ] T005 Implement create_charge/2 with Stripe API call in lib/app/payments.ex (R02)
|
||||
- [ ] T006 Run test and confirm GREEN
|
||||
|
||||
## Phase 2: Error Handling
|
||||
- [ ] T007 Write test for network failure expecting {:error, :network_error} in test/app/payments_test.exs (R03)
|
||||
- [ ] T008 Run test and confirm RED (error not caught)
|
||||
- [ ] T009 Add retry logic with exponential backoff in lib/app/payments.ex (R03)
|
||||
- [ ] T010 Run test and confirm GREEN
|
||||
- [ ] T011 [P] Write test for invalid card expecting {:error, :invalid_card} (R04)
|
||||
- [ ] T012 [P] Run test and confirm RED
|
||||
- [ ] T013 [P] Add card validation to create_charge/2 (R04)
|
||||
- [ ] T014 [P] Run test and confirm GREEN
|
||||
```
|
||||
|
||||
## Path Conventions
|
||||
|
||||
**Phoenix/Elixir**:
|
||||
- Contexts: `lib/{app}/{context}.ex`
|
||||
- Schemas: `lib/{app}/{context}/{schema}.ex`
|
||||
- LiveViews: `lib/{app}_web/live/{feature}_live.ex`
|
||||
- Controllers: `lib/{app}_web/controllers/{name}_controller.ex`
|
||||
- Tests: `test/{app}/{context}_test.exs`
|
||||
- Migrations: `priv/repo/migrations/{timestamp}_{desc}.exs`
|
||||
|
||||
**For other projects**: Use conventions from plan.md.
|
||||
|
||||
## Phase Organization
|
||||
|
||||
Group tasks into phases from plan.md. Standard phases:
|
||||
1. **Foundation**: Migrations, schemas, contexts, core tests
|
||||
2. **Integration**: External services, APIs, third-party libraries
|
||||
3. **Interface**: LiveViews, controllers, user-facing components
|
||||
4. **Polish**: Validation, edge cases, error handling
|
||||
|
||||
**Dependency rules**: migrations → schemas → contexts → interfaces
|
||||
|
||||
**Parallel opportunities**: Mark `[P]` when tasks touch different files and have no dependencies.
|
||||
|
||||
**Checkpoint**: Before generating output, verify:
|
||||
- [ ] Every task has exact file path
|
||||
- [ ] Every feature has TDD cycle (test → RED → implement → GREEN)
|
||||
- [ ] Tasks are atomic (one file or clear unit)
|
||||
- [ ] All spec requirements mapped to tasks
|
||||
|
||||
# Stage 5: Generate Output
|
||||
|
||||
Create implementation.md with this structure:
|
||||
|
||||
```markdown
|
||||
# Implementation Tasks: {Feature Name}
|
||||
|
||||
**Overview**: {1-2 sentence summary}
|
||||
**Total Tasks**: {N} | **Phases**: {M} | **Estimated Completion**: {Time estimate}
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: {Name}
|
||||
**Dependencies**: None
|
||||
**Parallel Opportunities**: {Count of [P] tasks}
|
||||
|
||||
- [ ] T001 {Task description with file path} (R01)
|
||||
[All phase 1 tasks following TDD pattern]
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: {Name}
|
||||
**Dependencies**: Phase 1 complete
|
||||
**Parallel Opportunities**: {Count}
|
||||
|
||||
- [ ] T007 {Task description with file path} (R04)
|
||||
[All phase 2 tasks]
|
||||
|
||||
---
|
||||
|
||||
## Spec Requirement Mapping
|
||||
- R01: Tasks T001, T002
|
||||
- R02: Tasks T003-T006
|
||||
[Complete mapping]
|
||||
|
||||
---
|
||||
|
||||
## Critical Dependencies
|
||||
{Sequential dependencies that block other work}
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
{Integration points, assumptions, clarifications}
|
||||
```
|
||||
|
||||
Present draft: `I've generated {N} tasks in {M} phases. Reply "Approved" to save, or provide feedback.`
|
||||
|
||||
Wait for approval. Support iteration. Never merge test and implementation tasks during revision.
|
||||
|
||||
# Stage 6: Save Tasks
|
||||
|
||||
Once approved:
|
||||
1. Run `git rev-parse --abbrev-ref HEAD`
|
||||
2. Save to `.specimin/plans/{branch}/implementation.md`
|
||||
3. Confirm: `Implementation tasks saved to .specimin/plans/{branch}/implementation.md`
|
||||
4. **Proceed immediately to Stage 7**
|
||||
|
||||
Only save after explicit approval.
|
||||
|
||||
# Stage 7: Generate Phase Files and Manifest
|
||||
|
||||
Automatically generate phase-specific files and JSON manifest.
|
||||
|
||||
## Step 1: Create Directory
|
||||
```bash
|
||||
mkdir -p .specimin/plans/{branch}/tasks/
|
||||
```
|
||||
|
||||
## Step 2: Parse Implementation.md
|
||||
|
||||
1. Read `.specimin/plans/{branch}/implementation.md`
|
||||
2. Identify phase boundaries: `## Phase N:` headers
|
||||
3. Extract for each phase:
|
||||
- Phase number and name
|
||||
- Dependencies and parallel opportunities
|
||||
- All task lines (`- [ ] TXXX ...`)
|
||||
4. For each task capture:
|
||||
- Task ID (T001, T002...)
|
||||
- Full description
|
||||
- Phase number
|
||||
- Parallel marker ([P] present?)
|
||||
|
||||
## Step 3: Generate Phase Files
|
||||
|
||||
For each phase, create `phase_N.md`:
|
||||
|
||||
**File**: `.specimin/plans/{branch}/tasks/phase_1.md`
|
||||
**Content**:
|
||||
```markdown
|
||||
# Phase N: {Phase Name}
|
||||
|
||||
**Dependencies**: {From implementation.md}
|
||||
**Parallel Opportunities**: {Count}
|
||||
|
||||
{All tasks for this phase, preserving checkboxes, IDs, [P] markers}
|
||||
```
|
||||
|
||||
Use Write tool for each file.
|
||||
|
||||
## Step 4: Generate JSON Manifest
|
||||
|
||||
**Schema** (4 fields per task):
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "T001",
|
||||
"description": "Create User schema in lib/app/accounts/user.ex (R01)",
|
||||
"phase": 1,
|
||||
"status": "pending"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**Escaping**: `"` → `\"`, `\` → `\\`, `\n` → `\\n`, `\t` → `\\t`
|
||||
|
||||
Save to `.specimin/plans/{branch}/tasks/manifest.json`
|
||||
|
||||
## Step 5: Edge Cases
|
||||
|
||||
- **Single phase**: Still create `phase_1.md` (not `phase.md`)
|
||||
- **Empty phases**: Skip file creation, note in confirmation
|
||||
- **No phases**: Display error: `Error: Could not detect phases. Expected "## Phase 1: {Name}"`
|
||||
|
||||
## Step 6: Confirm
|
||||
|
||||
Display:
|
||||
```
|
||||
✓ Generated {N} phase files and manifest with {M} tasks
|
||||
- Phase files: .specimin/plans/{branch}/tasks/phase_1.md through phase_{N}.md
|
||||
- Manifest: .specimin/plans/{branch}/tasks/manifest.json
|
||||
```
|
||||
|
||||
If phases skipped: `(skipped empty phase 3)`
|
||||
|
||||
---
|
||||
|
||||
**Note**: This prompt optimized using research-backed principles: structured reasoning (ADIHQ +64%), programming construct framing (SCoT +13.79%), TDD verification (Reflexion 91%), token efficiency (-39%), and explicit checkpoints for quality.
|
||||
|
||||
846
skills/specimin-ui-accessibility/SKILL.md
Normal file
846
skills/specimin-ui-accessibility/SKILL.md
Normal file
@@ -0,0 +1,846 @@
|
||||
---
|
||||
name: "specimin-ui-accessibility"
|
||||
description: "Explicit accessibility enhancement and validation for generated UI code. Only invoke when user explicitly requests accessibility review, a11y enhancement, or WCAG compliance check."
|
||||
allowed-tools:
|
||||
- run_terminal_cmd
|
||||
- write
|
||||
- read_file
|
||||
---
|
||||
|
||||
**REQUIRES ui-generate to be completed first.**
|
||||
This skill performs deep accessibility enhancement and validation. **Manual testing is MANDATORY.**
|
||||
|
||||
# UI Accessibility Enhancement Agent
|
||||
|
||||
## Role
|
||||
Accessibility specialist ensuring WCAG 2.1 Level AA compliance through code enhancement and validation. **Critical**: Research shows 80%+ of AI-generated code has accessibility violations. This skill provides systematic fixes and mandatory manual testing checklist.
|
||||
|
||||
## ⚠️ Critical Understanding
|
||||
|
||||
**Why This Skill Exists**:
|
||||
> "Accessibility is by definition non-typical usage, therefore applying an average does not work."
|
||||
> — Research finding on AI-generated accessibility failures
|
||||
|
||||
**Research Evidence**:
|
||||
- 80%+ of initial AI generations have semantic HTML violations
|
||||
- ChatGPT produced ZERO ARIA implementation in accessibility tests
|
||||
- Bard generated ARIA roles on wrong elements with broken references
|
||||
- Even accessibility-trained models produce WCAG-failing code
|
||||
- Automated tools catch only 60-70% of violations
|
||||
- **Manual validation with assistive technologies is MANDATORY**
|
||||
|
||||
**This skill cannot fully automate accessibility**. It provides:
|
||||
1. Systematic code enhancements
|
||||
2. Automated audit (catches 60-70% of issues)
|
||||
3. **Mandatory manual testing checklist**
|
||||
|
||||
## Process Flow
|
||||
|
||||
### Stage 1: Load Generated Code
|
||||
|
||||
1. Find current feature branch and generated files:
|
||||
```bash
|
||||
BRANCH=$(git branch --show-current)
|
||||
FEATURE_DIR=".specimin/ui/$BRANCH"
|
||||
```
|
||||
|
||||
2. Read generation-report.md to identify:
|
||||
- Files created/modified
|
||||
- Components generated
|
||||
- Known accessibility issues flagged
|
||||
|
||||
3. Read all generated code files for analysis
|
||||
|
||||
### Stage 2: Semantic HTML Audit
|
||||
|
||||
**Check every element for semantic correctness**:
|
||||
|
||||
#### Common Violations (Fix These)
|
||||
|
||||
**Navigation Elements**:
|
||||
- ❌ `<div class="nav">`
|
||||
- ✅ `<nav aria-label="Main navigation">`
|
||||
|
||||
**Buttons vs Links**:
|
||||
- ❌ `<div onClick={...}>` (not focusable, not keyboard accessible)
|
||||
- ❌ `<a onClick={...}>` (link semantics incorrect for actions)
|
||||
- ✅ `<button onClick={...}>` (semantic, focusable, keyboard accessible)
|
||||
- ✅ `<a href="/page">` (navigation only)
|
||||
|
||||
**Headings**:
|
||||
- ❌ Skipping levels: h1 → h3 (violates heading hierarchy)
|
||||
- ❌ Using `<div class="text-2xl font-bold">` instead of headings
|
||||
- ✅ Proper hierarchy: h1 → h2 → h3 (logical nesting)
|
||||
- ✅ One h1 per page (page title)
|
||||
|
||||
**Form Controls**:
|
||||
- ❌ `<input>` without `<label>`
|
||||
- ❌ Label not programmatically associated (visual only)
|
||||
- ✅ `<label for="email">` with `<input id="email">`
|
||||
- ✅ Or `<label><input></label>` (implicit association)
|
||||
|
||||
**Landmark Regions**:
|
||||
- ❌ `<div class="main-content">`
|
||||
- ✅ `<main>` (primary content landmark)
|
||||
- ✅ `<aside>` (sidebar, complementary content)
|
||||
- ✅ `<footer>` (footer landmark)
|
||||
|
||||
**Lists**:
|
||||
- ❌ `<div><div>Item 1</div><div>Item 2</div></div>`
|
||||
- ✅ `<ul><li>Item 1</li><li>Item 2</li></ul>`
|
||||
|
||||
**Dialogs/Modals**:
|
||||
- ❌ `<div class="modal">`
|
||||
- ✅ `<dialog>` (native HTML5 dialog element, preferred)
|
||||
- ✅ Or `<div role="dialog" aria-modal="true">`
|
||||
|
||||
### Stage 3: ARIA Implementation
|
||||
|
||||
**Critical Principle**: Use ARIA **only when semantic HTML is insufficient**.
|
||||
|
||||
> "First rule of ARIA: Don't use ARIA if you can use a native HTML element or attribute."
|
||||
> — W3C ARIA Authoring Practices
|
||||
|
||||
#### When ARIA Is Needed
|
||||
|
||||
**Dropdown Menus**:
|
||||
```html
|
||||
<!-- Button trigger -->
|
||||
<button
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
aria-controls="menu-id"
|
||||
id="menu-button">
|
||||
Menu
|
||||
</button>
|
||||
|
||||
<!-- Dropdown menu -->
|
||||
<div
|
||||
role="menu"
|
||||
aria-labelledby="menu-button"
|
||||
id="menu-id"
|
||||
hidden>
|
||||
<button role="menuitem">Item 1</button>
|
||||
<button role="menuitem">Item 2</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
**Tabs**:
|
||||
```html
|
||||
<div role="tablist" aria-label="Product details">
|
||||
<button role="tab" aria-selected="true" aria-controls="panel-1" id="tab-1">
|
||||
Description
|
||||
</button>
|
||||
<button role="tab" aria-selected="false" aria-controls="panel-2" id="tab-2">
|
||||
Reviews
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
|
||||
Description content
|
||||
</div>
|
||||
<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>
|
||||
Reviews content
|
||||
</div>
|
||||
```
|
||||
|
||||
**Modal Dialogs**:
|
||||
```html
|
||||
<div
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="dialog-title"
|
||||
aria-describedby="dialog-desc">
|
||||
<h2 id="dialog-title">Confirm Action</h2>
|
||||
<p id="dialog-desc">Are you sure you want to delete this item?</p>
|
||||
<button>Cancel</button>
|
||||
<button>Delete</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
**Live Regions** (status messages, notifications):
|
||||
```html
|
||||
<div role="status" aria-live="polite" aria-atomic="true">
|
||||
Form submitted successfully
|
||||
</div>
|
||||
|
||||
<div role="alert" aria-live="assertive">
|
||||
Error: Please fix the highlighted fields
|
||||
</div>
|
||||
```
|
||||
|
||||
**Hidden Content** (visually hidden but screen-reader accessible):
|
||||
```html
|
||||
<span class="sr-only">Opens in new window</span>
|
||||
<!-- Tailwind sr-only class: position: absolute; width: 1px; ... -->
|
||||
```
|
||||
|
||||
#### Common ARIA Mistakes to Fix
|
||||
|
||||
**Wrong Elements**:
|
||||
- ❌ `<li role="dialog">` (dialog role on list item)
|
||||
- ✅ Use correct element for role
|
||||
|
||||
**Broken References**:
|
||||
- ❌ `aria-labelledby="nonexistent-id"` (ID doesn't exist)
|
||||
- ✅ Ensure all ARIA references point to valid IDs
|
||||
|
||||
**Incomplete Patterns**:
|
||||
- ❌ `aria-expanded` attribute that never updates
|
||||
- ✅ Ensure state attributes change with UI state
|
||||
|
||||
**Redundant ARIA**:
|
||||
- ❌ `<button role="button">` (redundant)
|
||||
- ✅ `<button>` (native semantics sufficient)
|
||||
|
||||
### Stage 4: Keyboard Navigation Enhancement
|
||||
|
||||
**Every interactive element must be keyboard accessible.**
|
||||
|
||||
#### Focus Management
|
||||
|
||||
**Tab Order**:
|
||||
- All interactive elements receive focus in logical order
|
||||
- Skip to main content link (first focusable element)
|
||||
- Tab through navigation → main content → footer
|
||||
- No focus traps (except intentional like modals)
|
||||
|
||||
**Visible Focus Indicators**:
|
||||
```html
|
||||
<!-- Tailwind focus styles -->
|
||||
<button class="... focus:outline-none focus:ring-2 focus:ring-blue-500">
|
||||
Click me
|
||||
</button>
|
||||
|
||||
<!-- Custom focus (if needed) -->
|
||||
<a class="... focus:underline focus:ring-2">
|
||||
Link
|
||||
</a>
|
||||
```
|
||||
|
||||
#### Keyboard Event Handlers
|
||||
|
||||
**Modals**:
|
||||
```javascript
|
||||
// Escape key closes modal
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Escape') closeModal();
|
||||
}}
|
||||
|
||||
// Focus trap inside modal (Tab cycles within)
|
||||
// Return focus to trigger when closed
|
||||
```
|
||||
|
||||
**Dropdowns**:
|
||||
```javascript
|
||||
// Enter/Space opens dropdown
|
||||
// Arrow keys navigate items
|
||||
// Escape closes
|
||||
// Tab closes and moves focus
|
||||
```
|
||||
|
||||
**Custom Components** (not native):
|
||||
```javascript
|
||||
// Enter and Space both activate
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
handleActivate();
|
||||
}
|
||||
}}
|
||||
```
|
||||
|
||||
#### Framework-Specific Patterns
|
||||
|
||||
**React**:
|
||||
```typescript
|
||||
import { useRef, useEffect } from 'react';
|
||||
|
||||
// Focus management
|
||||
const modalRef = useRef<HTMLDialogElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
modalRef.current?.focus();
|
||||
// Trap focus logic
|
||||
}
|
||||
}, [isOpen]);
|
||||
```
|
||||
|
||||
**Phoenix LiveView**:
|
||||
```elixir
|
||||
# Focus on mount
|
||||
def mount(_params, _session, socket) do
|
||||
{:ok, socket, temporary_assigns: [focus: "modal-id"]}
|
||||
end
|
||||
|
||||
# HEEx template
|
||||
<div id={@focus} phx-hook="FocusOnMount">
|
||||
```
|
||||
|
||||
**Vue**:
|
||||
```vue
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
|
||||
const modalRef = ref(null);
|
||||
|
||||
onMounted(() => {
|
||||
if (isOpen.value) {
|
||||
modalRef.value?.focus();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Stage 5: Additional Accessibility Requirements
|
||||
|
||||
#### Images and Media
|
||||
|
||||
**Alt Text**:
|
||||
- ❌ `<img src="photo.jpg">` (no alt)
|
||||
- ❌ `<img src="logo.jpg" alt="logo">` (redundant)
|
||||
- ✅ `<img src="logo.jpg" alt="Company Name">` (descriptive)
|
||||
- ✅ `<img src="decorative.jpg" alt="">` (decorative image, empty alt)
|
||||
|
||||
**Videos**:
|
||||
- Captions/subtitles for audio content
|
||||
- Transcripts available
|
||||
- Playback controls keyboard accessible
|
||||
|
||||
#### Color and Contrast
|
||||
|
||||
**Color Not Sole Indicator**:
|
||||
- ❌ Red text only to indicate errors
|
||||
- ✅ Red text + icon + explicit "Error:" label
|
||||
|
||||
**Contrast Ratios** (WCAG AA):
|
||||
- Normal text: 4.5:1 minimum
|
||||
- Large text (18pt+ or 14pt bold+): 3:1 minimum
|
||||
- UI components and graphics: 3:1 minimum
|
||||
|
||||
**Check**:
|
||||
- Tailwind default colors generally pass (gray-700+ on white)
|
||||
- Custom colors need manual verification
|
||||
- Use browser DevTools Accessibility checker
|
||||
|
||||
#### Forms
|
||||
|
||||
**Labels**:
|
||||
- Every input has associated label
|
||||
- Label text describes purpose clearly
|
||||
- Group related inputs with `<fieldset>` and `<legend>`
|
||||
|
||||
**Validation**:
|
||||
- Error messages programmatically associated with inputs
|
||||
- `aria-invalid="true"` on invalid fields
|
||||
- `aria-describedby` pointing to error message ID
|
||||
|
||||
**Required Fields**:
|
||||
```html
|
||||
<label for="email">
|
||||
Email <span aria-label="required">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
required
|
||||
aria-required="true"
|
||||
aria-describedby="email-error">
|
||||
<span id="email-error" role="alert">
|
||||
<!-- Error message inserted here -->
|
||||
</span>
|
||||
```
|
||||
|
||||
#### Responsive and Zoom
|
||||
|
||||
**Text Resize**:
|
||||
- Content readable at 200% zoom without horizontal scroll
|
||||
- No fixed pixel font sizes (use rem)
|
||||
- Avoid `user-scalable=no` in viewport meta
|
||||
|
||||
**Touch Targets**:
|
||||
- Minimum 44x44 pixels (mobile)
|
||||
- Adequate spacing between interactive elements
|
||||
- Tailwind: `p-2` typically sufficient, `min-h-[44px]` if needed
|
||||
|
||||
### Stage 6: Automated Accessibility Audit
|
||||
|
||||
**Run conceptual equivalent of axe-core checks**:
|
||||
|
||||
#### Checklist
|
||||
|
||||
**Critical (Must Fix)**:
|
||||
- [ ] All images have alt attributes
|
||||
- [ ] Form inputs have labels
|
||||
- [ ] Buttons have accessible names
|
||||
- [ ] Links have discernible text
|
||||
- [ ] Page has `<html lang="...">` attribute
|
||||
- [ ] Page has meaningful `<title>`
|
||||
- [ ] Heading hierarchy valid (no skipping)
|
||||
- [ ] Color contrast sufficient (4.5:1 text, 3:1 UI)
|
||||
- [ ] No keyboard traps
|
||||
- [ ] ARIA references valid (IDs exist)
|
||||
|
||||
**Serious (Should Fix)**:
|
||||
- [ ] Landmarks present (main, nav, footer)
|
||||
- [ ] Skip links available
|
||||
- [ ] Focus indicators visible
|
||||
- [ ] ARIA attributes correct for roles
|
||||
- [ ] Lists use semantic markup (ul/ol)
|
||||
- [ ] Tables have proper headers (if used)
|
||||
|
||||
**Moderate (Consider)**:
|
||||
- [ ] Explicit language changes marked (`lang` attribute)
|
||||
- [ ] Abbreviations explained (first use)
|
||||
- [ ] Link text descriptive (not "click here")
|
||||
|
||||
### Stage 7: Generate Accessibility Report
|
||||
|
||||
Create accessibility-report.md documenting:
|
||||
|
||||
**Audit Results**:
|
||||
- Violations found and fixed
|
||||
- Automated check results (pass/fail)
|
||||
- WCAG 2.1 Level AA compliance status
|
||||
|
||||
**Enhancements Made**:
|
||||
- Semantic HTML improvements
|
||||
- ARIA additions
|
||||
- Keyboard navigation enhancements
|
||||
- Focus management implementations
|
||||
|
||||
**Manual Testing Checklist** (MANDATORY):
|
||||
- [ ] Keyboard-only navigation test
|
||||
- [ ] Screen reader testing (NVDA/JAWS/VoiceOver)
|
||||
- [ ] Zoom to 200% test
|
||||
- [ ] Color contrast verification
|
||||
- [ ] Touch target size verification (mobile)
|
||||
|
||||
**Known Limitations**:
|
||||
- Automated tools catch 60-70% of issues
|
||||
- Context-dependent problems require human judgment
|
||||
- Screen reader quirks across devices
|
||||
- Business logic validation
|
||||
|
||||
### Stage 8: Present Manual Testing Checklist
|
||||
|
||||
**Critical**: Show user this mandatory checklist:
|
||||
|
||||
```
|
||||
## 🔴 MANDATORY Manual Accessibility Testing
|
||||
|
||||
AI-generated code requires human validation. Complete ALL checks below:
|
||||
|
||||
### Keyboard Navigation Test (30 minutes)
|
||||
- [ ] Unplug mouse (force keyboard-only)
|
||||
- [ ] Tab through entire interface
|
||||
- [ ] Verify logical tab order
|
||||
- [ ] Test all interactive elements (Enter/Space to activate)
|
||||
- [ ] Escape closes modals/dropdowns
|
||||
- [ ] No focus traps (except intentional)
|
||||
- [ ] Focus indicators clearly visible
|
||||
|
||||
### Screen Reader Test (1 hour)
|
||||
**Windows** (NVDA - free):
|
||||
- [ ] Download NVDA (https://www.nvaccess.org/)
|
||||
- [ ] Navigate page with screen reader on
|
||||
- [ ] Verify all content announced
|
||||
- [ ] Check heading navigation (H key)
|
||||
- [ ] Check landmark navigation (D key)
|
||||
- [ ] Verify form labels read correctly
|
||||
- [ ] Test interactive widgets (modals, dropdowns, tabs)
|
||||
|
||||
**Mac/iOS** (VoiceOver - built-in):
|
||||
- [ ] Enable VoiceOver (Cmd+F5)
|
||||
- [ ] Navigate with VO keys (Control+Option+arrows)
|
||||
- [ ] Verify rotor navigation (landmarks, headings)
|
||||
- [ ] Test on Safari (primary VO browser)
|
||||
|
||||
**Basics to verify**:
|
||||
- Page title announced on load
|
||||
- Headings provide page structure
|
||||
- Buttons/links clearly identified
|
||||
- Form fields have labels
|
||||
- Error messages read aloud
|
||||
- Status updates announced (live regions)
|
||||
|
||||
### Visual Test (15 minutes)
|
||||
- [ ] Zoom browser to 200% (Cmd/Ctrl + +)
|
||||
- [ ] No horizontal scroll appears
|
||||
- [ ] All content remains readable
|
||||
- [ ] No text overlap
|
||||
- [ ] Interactive elements still usable
|
||||
|
||||
### Color Contrast Test (15 minutes)
|
||||
- [ ] Use browser DevTools Accessibility tab
|
||||
- [ ] Check all text meets 4.5:1 ratio (normal text)
|
||||
- [ ] Check 3:1 ratio for large text and UI components
|
||||
- [ ] Verify error states use more than color alone
|
||||
|
||||
### Mobile/Touch Test (30 minutes)
|
||||
- [ ] Test on actual device (not just emulator)
|
||||
- [ ] All touch targets minimum 44x44 pixels
|
||||
- [ ] Adequate spacing between interactive elements
|
||||
- [ ] Pinch zoom works (not disabled)
|
||||
- [ ] Landscape and portrait orientations work
|
||||
|
||||
### Total Time: ~2.5-3 hours
|
||||
This cannot be skipped. Accessibility cannot be automated away.
|
||||
```
|
||||
|
||||
### Stage 9: Finalize
|
||||
|
||||
**ONLY after user acknowledges manual testing requirement**:
|
||||
|
||||
1. Write accessibility-report.md to feature directory
|
||||
2. Commit accessibility enhancements:
|
||||
```bash
|
||||
bash ${CLAUDE_PLUGIN_ROOT}/.claude-plugin/skills/specimin-ui-accessibility/scripts/save-accessibility.sh "$BRANCH"
|
||||
```
|
||||
|
||||
3. Confirm to user:
|
||||
"✓ Accessibility enhancements applied and committed.
|
||||
|
||||
⚠️ **NEXT STEP REQUIRED**: Complete manual accessibility testing checklist.
|
||||
See .specimin/ui/[branch]/accessibility-report.md for full checklist.
|
||||
|
||||
After testing complete, run `specimin:wrap` to create PR."
|
||||
|
||||
## Output: Accessibility Report Format
|
||||
|
||||
```markdown
|
||||
# Accessibility Report - [Feature Name]
|
||||
|
||||
## Executive Summary
|
||||
- **WCAG Level**: AA (Target)
|
||||
- **Automated Compliance**: [X]% of checks passed
|
||||
- **Manual Testing**: ⚠️ REQUIRED (see checklist below)
|
||||
- **Critical Issues**: [N] found and fixed
|
||||
- **Status**: ✅ Ready for Manual Testing | ⚠️ Issues Remain | ❌ Blocked
|
||||
|
||||
## Violations Found and Fixed
|
||||
|
||||
### Critical (Blocking)
|
||||
|
||||
#### 1. Non-Semantic Button Elements
|
||||
**Found**: `<div onClick={handleClick}>Submit</div>`
|
||||
**Issue**: Not keyboard accessible, no semantic meaning
|
||||
**WCAG**: 4.1.2 Name, Role, Value (Level A)
|
||||
**Fixed**: Changed to `<button onClick={handleClick}>Submit</button>`
|
||||
|
||||
#### 2. Missing Form Labels
|
||||
**Found**: `<input type="email" placeholder="Email">`
|
||||
**Issue**: Screen readers cannot identify field purpose
|
||||
**WCAG**: 3.3.2 Labels or Instructions (Level A)
|
||||
**Fixed**: Added `<label for="email">Email</label>` with association
|
||||
|
||||
#### 3. Skipped Heading Level
|
||||
**Found**: h1 → h3 (skipped h2)
|
||||
**Issue**: Breaks document structure for screen readers
|
||||
**WCAG**: 2.4.6 Headings and Labels (Level AA)
|
||||
**Fixed**: Changed to h2, adjusted visual styling
|
||||
|
||||
### Serious (Should Fix)
|
||||
|
||||
#### 4. Missing Landmark Regions
|
||||
**Found**: `<div class="main-content">`
|
||||
**Issue**: Screen reader users cannot navigate by landmarks
|
||||
**WCAG**: 4.1.2 Name, Role, Value (Level A)
|
||||
**Fixed**: Changed to `<main>` element
|
||||
|
||||
#### 5. Incomplete ARIA Pattern
|
||||
**Found**: Dropdown with `aria-expanded` never updating
|
||||
**Issue**: Screen reader announces incorrect state
|
||||
**WCAG**: 4.1.2 Name, Role, Value (Level A)
|
||||
**Fixed**: Added state management to toggle `aria-expanded` on open/close
|
||||
|
||||
### Moderate (Enhancements)
|
||||
|
||||
#### 6. Generic Link Text
|
||||
**Found**: `<a href="/docs">Click here</a>`
|
||||
**Issue**: Not descriptive out of context
|
||||
**WCAG**: 2.4.4 Link Purpose (Level A)
|
||||
**Fixed**: Changed to `<a href="/docs">View documentation</a>`
|
||||
|
||||
## Enhancements Applied
|
||||
|
||||
### Semantic HTML Improvements
|
||||
- Replaced 8 div elements with semantic alternatives (nav, main, button)
|
||||
- Established proper heading hierarchy (h1 → h2 → h3)
|
||||
- Used list elements (ul/li) for navigation and feature lists
|
||||
|
||||
### ARIA Additions
|
||||
- Modal dialog: Added `role="dialog"`, `aria-modal="true"`, `aria-labelledby`
|
||||
- Dropdown menu: Added `aria-haspopup`, `aria-expanded`, `aria-controls`
|
||||
- Live region: Added `role="status"` for form submission feedback
|
||||
- Hidden content: Added `aria-hidden="true"` to decorative elements
|
||||
|
||||
### Keyboard Navigation
|
||||
- Focus indicators: Added `focus:ring-2 focus:ring-blue-500` to all interactive elements
|
||||
- Modal keyboard handling: Escape closes, focus trap implemented, focus restoration on close
|
||||
- Dropdown keyboard handling: Enter/Space opens, Arrow keys navigate, Escape closes
|
||||
|
||||
### Focus Management
|
||||
**Modal open sequence**:
|
||||
1. Trap focus inside modal
|
||||
2. Focus first interactive element
|
||||
3. Tab cycles within modal
|
||||
4. Escape restores focus to trigger button
|
||||
|
||||
**Implementation**:
|
||||
- React: useEffect + useRef pattern
|
||||
- Phoenix LiveView: phx-hook="FocusManagement"
|
||||
- Vue: onMounted + ref pattern
|
||||
|
||||
## Automated Audit Results
|
||||
|
||||
### axe-core Equivalent Checks
|
||||
|
||||
✅ **Passed (35/40)**:
|
||||
- All images have alt attributes
|
||||
- Form inputs have associated labels
|
||||
- Color contrast meets WCAG AA (4.5:1)
|
||||
- HTML lang attribute present
|
||||
- Page title meaningful
|
||||
- No duplicate IDs
|
||||
- ARIA references valid
|
||||
- Buttons have accessible names
|
||||
- [... full list]
|
||||
|
||||
❌ **Failed (0/40)**: None remaining
|
||||
|
||||
⚠️ **Manual Review Needed (5/40)**:
|
||||
- Alt text quality (requires context judgment)
|
||||
- Heading structure appropriateness (requires content understanding)
|
||||
- Link text descriptiveness (requires context)
|
||||
- Form error message clarity (requires UX review)
|
||||
- Color not sole indicator (requires visual review)
|
||||
|
||||
## Known Limitations
|
||||
|
||||
### Automated Testing Boundaries
|
||||
- **Coverage**: Automated tools catch 60-70% of accessibility issues
|
||||
- **Context**: Cannot judge appropriateness of alt text, heading levels
|
||||
- **Screen Reader Quirks**: Differences between NVDA, JAWS, VoiceOver
|
||||
- **User Experience**: Cannot test actual navigation flows
|
||||
|
||||
### Framework-Specific Considerations
|
||||
**Phoenix LiveView**:
|
||||
- Client-side JavaScript hooks used for focus management
|
||||
- Server-side validation messages need `phx-feedback-for` for proper timing
|
||||
- Live navigation requires `aria-live` regions for route changes
|
||||
|
||||
**React**:
|
||||
- Focus management requires refs and useEffect
|
||||
- Router transitions need announcement to screen readers
|
||||
- State updates need `aria-live` for status messages
|
||||
|
||||
### Business Logic Gaps
|
||||
- Form validation error messages (content not generated)
|
||||
- Loading states and spinners (design not provided)
|
||||
- Error recovery flows (business logic needed)
|
||||
|
||||
## 🔴 MANDATORY Manual Testing Checklist
|
||||
|
||||
**Estimated Time: 2.5-3 hours**
|
||||
|
||||
AI-generated code CANNOT be shipped without human accessibility testing.
|
||||
|
||||
### 1. Keyboard Navigation Test (30 min)
|
||||
|
||||
**Setup**: Unplug mouse, use keyboard only
|
||||
|
||||
- [ ] **Tab Order**: Logical progression through interface
|
||||
- [ ] **Skip Link**: "Skip to main content" link works (if present)
|
||||
- [ ] **Navigation**: Tab through all nav items, Enter/Space activates
|
||||
- [ ] **Forms**: Tab through fields, Space checks checkboxes, Enter submits
|
||||
- [ ] **Buttons**: Enter or Space activates all buttons
|
||||
- [ ] **Modals**: Escape closes, focus trapped inside when open
|
||||
- [ ] **Dropdowns**: Enter/Space opens, Escape closes, Arrow keys navigate (if applicable)
|
||||
- [ ] **Focus Indicators**: Always visible, never hidden by CSS
|
||||
- [ ] **No Traps**: Can Tab to and from every interactive element
|
||||
|
||||
**Tools**: None required (keyboard only)
|
||||
|
||||
### 2. Screen Reader Test (1 hour)
|
||||
|
||||
**Windows - NVDA (Free)**:
|
||||
Download: https://www.nvaccess.org/download/
|
||||
|
||||
- [ ] **Install NVDA**: Follow wizard, restart optional
|
||||
- [ ] **Launch NVDA**: Desktop shortcut or Ctrl+Alt+N
|
||||
- [ ] **Open Page**: Use Chrome or Firefox (best NVDA support)
|
||||
- [ ] **Listen to Page Load**: Page title announced
|
||||
- [ ] **Navigate by Headings**: Press H to jump between headings
|
||||
- [ ] **Navigate by Landmarks**: Press D to jump between regions (main, nav, etc.)
|
||||
- [ ] **Navigate by Elements**: Press B (buttons), K (links), F (forms)
|
||||
- [ ] **Test Form**: Arrow through fields, hear labels, submit, hear confirmation
|
||||
- [ ] **Test Interactive Widgets**: Modals, dropdowns, tabs (verify announcements)
|
||||
- [ ] **Verify Images**: Images announce alt text, decorative images skipped
|
||||
|
||||
**Mac/iOS - VoiceOver (Built-in)**:
|
||||
- [ ] **Enable VO**: Cmd+F5 (Mac) or Settings > Accessibility > VoiceOver (iOS)
|
||||
- [ ] **Open Page**: Use Safari (best VO support)
|
||||
- [ ] **Navigate**: Control+Option+Arrow keys (Mac), swipe (iOS)
|
||||
- [ ] **Rotor Navigation**: Control+Option+U for landmarks/headings menu
|
||||
- [ ] **Test Interactive Elements**: Buttons, links, forms
|
||||
- [ ] **Verify Announcements**: All content understandable via audio only
|
||||
|
||||
**What to Listen For**:
|
||||
- Clear, descriptive announcements (not "button button" or "link graphic")
|
||||
- Form labels read before input fields
|
||||
- Error messages announced immediately
|
||||
- Status updates announced (form submission, loading)
|
||||
- Modal open/close announced
|
||||
- All text content accessible (nothing skipped)
|
||||
|
||||
### 3. Visual/Zoom Test (15 min)
|
||||
|
||||
- [ ] **Zoom 200%**: Cmd/Ctrl and press + until 200%
|
||||
- [ ] **No Horizontal Scroll**: Content reflows, doesn't require side-scrolling
|
||||
- [ ] **Text Readable**: All text remains legible, no overlap
|
||||
- [ ] **Interactive Elements**: Buttons, links still clickable
|
||||
- [ ] **Layout Intact**: No broken layouts, content still usable
|
||||
|
||||
**Tools**: Browser zoom (Cmd/Ctrl + +)
|
||||
|
||||
### 4. Color Contrast Test (15 min)
|
||||
|
||||
- [ ] **Open DevTools**: F12 or Right-click > Inspect
|
||||
- [ ] **Accessibility Tab**: Chrome DevTools > Accessibility pane
|
||||
- [ ] **Check Elements**: Inspect text elements, view contrast ratio
|
||||
- [ ] **Verify Ratios**: Normal text ≥4.5:1, large text ≥3:1, UI components ≥3:1
|
||||
- [ ] **Color Not Sole Indicator**: Errors use icon + text, not just red color
|
||||
|
||||
**Tools**: Chrome DevTools Accessibility panel
|
||||
|
||||
### 5. Mobile/Touch Test (30 min)
|
||||
|
||||
- [ ] **Real Device**: Test on actual phone/tablet (emulator insufficient for touch)
|
||||
- [ ] **Touch Targets**: All buttons/links easily tappable (44x44px minimum)
|
||||
- [ ] **Spacing**: Adequate space between interactive elements (no mis-taps)
|
||||
- [ ] **Pinch Zoom**: Works (viewport doesn't disable)
|
||||
- [ ] **Orientation**: Portrait and landscape both work
|
||||
- [ ] **Screen Reader**: Test VoiceOver on iOS or TalkBack on Android
|
||||
- [ ] **Gestures**: Swipe navigation works with screen reader
|
||||
|
||||
**Tools**: Physical mobile device
|
||||
|
||||
## Testing Resources
|
||||
|
||||
### Screen Readers
|
||||
- **NVDA (Windows, Free)**: https://www.nvaccess.org/
|
||||
- **JAWS (Windows, Paid)**: https://www.freedomscientific.com/products/software/jaws/
|
||||
- **VoiceOver (Mac/iOS, Built-in)**: Cmd+F5 or Settings > Accessibility
|
||||
- **TalkBack (Android, Built-in)**: Settings > Accessibility > TalkBack
|
||||
|
||||
### Browser Tools
|
||||
- **Chrome DevTools**: Accessibility panel, Lighthouse audit
|
||||
- **Firefox DevTools**: Accessibility inspector
|
||||
- **axe DevTools**: Browser extension (free version available)
|
||||
- **WAVE**: Browser extension for visual accessibility review
|
||||
|
||||
### Color Contrast Checkers
|
||||
- **WebAIM Contrast Checker**: https://webaim.org/resources/contrastchecker/
|
||||
- **Colour Contrast Analyser**: Desktop app (free)
|
||||
|
||||
### Learning Resources
|
||||
- **WebAIM**: https://webaim.org/ (comprehensive guides)
|
||||
- **W3C ARIA Authoring Practices**: https://www.w3.org/WAI/ARIA/apg/
|
||||
- **A11y Project**: https://www.a11yproject.com/ (checklist and resources)
|
||||
|
||||
## Sign-Off
|
||||
|
||||
**Accessibility testing completed by**: ___________________
|
||||
**Date**: ___________________
|
||||
**Screen reader used**: ___________________
|
||||
**Devices tested**: ___________________
|
||||
|
||||
**Issues found during manual testing**:
|
||||
- [ ] None - all tests passed
|
||||
- [ ] Issues found (list below):
|
||||
|
||||
___________________________________________________________________
|
||||
___________________________________________________________________
|
||||
|
||||
**Ready for production**: [ ] Yes [ ] No
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Complete manual testing** using checklist above (~3 hours)
|
||||
2. **Document any issues** found during testing
|
||||
3. **Fix critical issues** before production deployment
|
||||
4. **Re-test** after fixes applied
|
||||
5. **Run `specimin:wrap`** to create PR when ready
|
||||
6. **Include accessibility testing notes** in PR description
|
||||
|
||||
---
|
||||
|
||||
## Appendix: WCAG 2.1 Level AA Compliance
|
||||
|
||||
### Principles Covered
|
||||
|
||||
**Perceivable**:
|
||||
- ✅ 1.1.1 Non-text Content (Alt text for images)
|
||||
- ✅ 1.3.1 Info and Relationships (Semantic HTML, ARIA)
|
||||
- ✅ 1.4.3 Contrast (Minimum) (4.5:1 for text)
|
||||
- ✅ 1.4.10 Reflow (No horizontal scroll at 200% zoom)
|
||||
- ✅ 1.4.11 Non-text Contrast (3:1 for UI components)
|
||||
|
||||
**Operable**:
|
||||
- ✅ 2.1.1 Keyboard (All functionality via keyboard)
|
||||
- ✅ 2.1.2 No Keyboard Trap (Can Tab out of all elements)
|
||||
- ✅ 2.4.1 Bypass Blocks (Skip links, landmarks)
|
||||
- ✅ 2.4.3 Focus Order (Logical tab order)
|
||||
- ✅ 2.4.6 Headings and Labels (Descriptive, hierarchical)
|
||||
- ✅ 2.4.7 Focus Visible (Focus indicators present)
|
||||
|
||||
**Understandable**:
|
||||
- ✅ 3.1.1 Language of Page (`<html lang="en">`)
|
||||
- ✅ 3.2.1 On Focus (No unexpected changes on focus)
|
||||
- ✅ 3.2.2 On Input (No unexpected changes on input)
|
||||
- ✅ 3.3.1 Error Identification (Errors clearly described)
|
||||
- ✅ 3.3.2 Labels or Instructions (Form fields labeled)
|
||||
|
||||
**Robust**:
|
||||
- ✅ 4.1.2 Name, Role, Value (Semantic HTML, ARIA)
|
||||
- ✅ 4.1.3 Status Messages (Live regions for dynamic content)
|
||||
|
||||
### Reference
|
||||
Full WCAG 2.1 Guidelines: https://www.w3.org/WAI/WCAG21/quickref/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
**Do**:
|
||||
- Read all generated code files
|
||||
- Fix semantic HTML violations systematically
|
||||
- Add ARIA only when semantic HTML insufficient
|
||||
- Implement keyboard navigation for all interactive elements
|
||||
- Manage focus for modals and complex widgets
|
||||
- Run conceptual automated audit
|
||||
- Provide detailed manual testing checklist
|
||||
- **Emphasize that manual testing is MANDATORY**
|
||||
- Document all changes made
|
||||
- Explain why each change improves accessibility
|
||||
|
||||
**Don't**:
|
||||
- Skip manual testing checklist (most critical output)
|
||||
- Add redundant ARIA (use semantic HTML first)
|
||||
- Assume automated tools catch all issues (only 60-70%)
|
||||
- Make accessibility fixes that break functionality
|
||||
- Use overly complex ARIA patterns when simple HTML works
|
||||
- Claim "accessibility complete" without manual testing
|
||||
|
||||
**Research-backed insights**:
|
||||
- 80%+ of AI-generated code has accessibility violations
|
||||
- Two-stage approach (structure → accessibility) prevents deprioritization
|
||||
- Automated tools catch only 60-70% of violations
|
||||
- Manual testing with assistive technologies is MANDATORY
|
||||
- TetraLogical research: Even accessibility-trained models produce WCAG-failing code
|
||||
- "Accessibility is by definition non-typical usage, therefore applying an average does not work"
|
||||
- ChatGPT produced zero ARIA implementation in controlled tests
|
||||
- Bard generated ARIA roles on wrong elements with broken references
|
||||
88
skills/specimin-ui-accessibility/scripts/save-accessibility.sh
Executable file
88
skills/specimin-ui-accessibility/scripts/save-accessibility.sh
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# save-accessibility.sh - Saves accessibility enhancements and report to feature branch
|
||||
# Usage: save-accessibility.sh <branch_name>
|
||||
|
||||
set -e
|
||||
|
||||
BRANCH_NAME="$1"
|
||||
|
||||
if [ -z "$BRANCH_NAME" ]; then
|
||||
# Try to get current branch if not provided
|
||||
BRANCH_NAME=$(git branch --show-current)
|
||||
fi
|
||||
|
||||
if [ -z "$BRANCH_NAME" ]; then
|
||||
echo "Error: Could not determine branch name"
|
||||
echo "Usage: save-accessibility.sh <branch_name>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify we're in a git repository
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo "Error: Not in a git repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify branch exists
|
||||
if ! git rev-parse --verify "$BRANCH_NAME" > /dev/null 2>&1; then
|
||||
echo "Error: Branch '$BRANCH_NAME' does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify we're on the correct branch
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
if [ "$CURRENT_BRANCH" != "$BRANCH_NAME" ]; then
|
||||
echo "Error: Not on branch '$BRANCH_NAME' (currently on '$CURRENT_BRANCH')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FEATURE_DIR=".specimin/ui/$BRANCH_NAME"
|
||||
|
||||
# Verify feature directory exists
|
||||
if [ ! -d "$FEATURE_DIR" ]; then
|
||||
echo "Error: Feature directory not found: $FEATURE_DIR"
|
||||
echo "Run specimin:ui-understand first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify generation-report.md exists
|
||||
GENERATION_REPORT="$FEATURE_DIR/generation-report.md"
|
||||
if [ ! -f "$GENERATION_REPORT" ]; then
|
||||
echo "Error: generation-report.md not found at $GENERATION_REPORT"
|
||||
echo "Run specimin:ui-generate first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if accessibility report exists in /tmp
|
||||
REPORT_TEMP="/tmp/ui-accessibility-report.md"
|
||||
if [ ! -f "$REPORT_TEMP" ]; then
|
||||
echo "Error: Accessibility report not found at $REPORT_TEMP"
|
||||
echo "The skill should write the accessibility report to /tmp/ui-accessibility-report.md"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy accessibility report to feature directory
|
||||
REPORT_DEST="$FEATURE_DIR/accessibility-report.md"
|
||||
cp "$REPORT_TEMP" "$REPORT_DEST"
|
||||
|
||||
# Add all changes (accessibility enhancements + report)
|
||||
git add -A
|
||||
|
||||
# Check if there are changes to commit
|
||||
if git diff --cached --quiet; then
|
||||
echo "Warning: No changes to commit (accessibility enhancements may already be staged)"
|
||||
else
|
||||
# Commit with descriptive message
|
||||
git commit -m "Apply accessibility enhancements
|
||||
|
||||
- Fixed semantic HTML violations
|
||||
- Added ARIA attributes where needed
|
||||
- Implemented keyboard navigation
|
||||
- Enhanced focus management
|
||||
- See accessibility-report.md for full details
|
||||
|
||||
⚠️ MANUAL TESTING REQUIRED before production deployment"
|
||||
fi
|
||||
|
||||
# Output success message with JSON
|
||||
echo "{\"feature_dir\": \"$FEATURE_DIR\", \"branch_name\": \"$BRANCH_NAME\", \"report_path\": \"$REPORT_DEST\"}"
|
||||
414
skills/specimin-ui-generate/SKILL.md
Normal file
414
skills/specimin-ui-generate/SKILL.md
Normal file
@@ -0,0 +1,414 @@
|
||||
---
|
||||
name: "specimin-ui-generate"
|
||||
description: "Generate UI code from sketches, mockups, or descriptions. Works standalone for simple changes or with design context for complex features. Explores codebase, makes decisions inline, generates production code with validation."
|
||||
allowed-tools:
|
||||
- run_terminal_cmd
|
||||
- write
|
||||
- read_file
|
||||
---
|
||||
|
||||
# Streamlined UI Generation Agent
|
||||
|
||||
## Role
|
||||
Implementation engineer generating production-quality UI code. Works **standalone** for simple changes (90% of cases) or leverages optional design context for complex features.
|
||||
|
||||
## When to Use
|
||||
|
||||
**Use directly for simple changes** (recommended):
|
||||
- Adding charts/visualizations
|
||||
- Modifying existing components
|
||||
- Layout adjustments
|
||||
- Standard component additions
|
||||
|
||||
**Use with design prep for complex features**:
|
||||
- Multi-component features with ambiguities
|
||||
- New design patterns not in codebase
|
||||
- Significant responsive/interactive complexity
|
||||
|
||||
## Process Flow
|
||||
|
||||
### Stage 1: Assess Complexity & Load Context
|
||||
|
||||
**Ask user**: "Is this a simple change (modify/add single feature) or complex feature (multiple new components/patterns)?"
|
||||
|
||||
**If SIMPLE** (90% of cases):
|
||||
- Proceed directly to exploration
|
||||
- No design doc needed
|
||||
|
||||
**If COMPLEX**:
|
||||
- Check for design context: `.specimin/ui/[branch]/design.md`
|
||||
- If exists: Read for key decisions
|
||||
- If not: Create lightweight design doc first (80-150 lines with key decisions, component mapping, ambiguity resolution)
|
||||
|
||||
### Stage 2: Explore Codebase Inline
|
||||
|
||||
**Auto-detect framework**:
|
||||
```bash
|
||||
# Check for Phoenix LiveView
|
||||
test -f mix.exs && grep -q "phoenix_live_view" mix.exs
|
||||
|
||||
# Check for React/Next/Vue
|
||||
test -f package.json && cat package.json | grep -E "react|next|vue"
|
||||
|
||||
# Check for Tailwind
|
||||
test -f tailwind.config.js || test -f assets/tailwind.config.js
|
||||
```
|
||||
|
||||
**Find similar patterns**:
|
||||
```bash
|
||||
# Example: If adding charts, search for existing visualizations
|
||||
find . -type f \( -name "*.heex" -o -name "*.tsx" -o -name "*.vue" \) | head -20
|
||||
|
||||
# Search for component patterns
|
||||
grep -r "phx-hook" lib/ 2>/dev/null | head -5
|
||||
grep -r "useState" src/ 2>/dev/null | head -5
|
||||
```
|
||||
|
||||
**Load design system** (if available):
|
||||
```bash
|
||||
find docs/design-system -name "*.json" -type f 2>/dev/null
|
||||
```
|
||||
|
||||
**Keep exploration focused**: 2-3 minutes max, just enough for informed decisions
|
||||
|
||||
### Stage 3: Make Decisions Inline
|
||||
|
||||
**Decide automatically** (don't ask user):
|
||||
- Which design system patterns to use (from exploration)
|
||||
- Component structure (based on similar code)
|
||||
- File locations (following existing conventions)
|
||||
- Responsive approach (mobile-first, consistent with codebase)
|
||||
- Styling patterns (match existing Tailwind usage)
|
||||
|
||||
**Only ask user for**:
|
||||
- Real ambiguities (multiple valid approaches with tradeoffs)
|
||||
- Business logic (what happens on button click?)
|
||||
- Data requirements unclear (where does data come from?)
|
||||
- Framework choice if not detectable
|
||||
|
||||
### Stage 4: Generate Code (Deterministic)
|
||||
|
||||
**Temperature**: 0.2-0.3 (consistent, deterministic generation)
|
||||
|
||||
**Generate complete implementation**:
|
||||
- ✅ Pure code files (no markdown formatting)
|
||||
- ✅ Complete implementations (no placeholders/TODOs)
|
||||
- ✅ Working examples with realistic content
|
||||
- ✅ Semantic HTML (button, nav, main, not div soup)
|
||||
- ✅ Tailwind utilities only (no custom CSS)
|
||||
- ✅ Complete imports and setup
|
||||
- ❌ No explanatory comments mixed with code
|
||||
- ❌ No "lazy" shortcuts ("repeat for each item")
|
||||
|
||||
**Framework-specific patterns**:
|
||||
|
||||
**Phoenix LiveView**:
|
||||
```elixir
|
||||
def component(assigns) do
|
||||
~H"""
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<%= for item <- @items do %>
|
||||
<div class="p-6 bg-white rounded-lg shadow">
|
||||
<%= item.content %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
```
|
||||
|
||||
**React/TypeScript**:
|
||||
```typescript
|
||||
interface Props {
|
||||
items: Item[];
|
||||
}
|
||||
|
||||
export const Component: React.FC<Props> = ({ items }) => {
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{items.map(item => (
|
||||
<div key={item.id} className="p-6 bg-white rounded-lg shadow">
|
||||
{item.content}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
**Vue**:
|
||||
```vue
|
||||
<template>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div v-for="item in items" :key="item.id"
|
||||
class="p-6 bg-white rounded-lg shadow">
|
||||
{{ item.content }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps<{ items: Item[] }>();
|
||||
</script>
|
||||
```
|
||||
|
||||
### Stage 5: Automated Validation (Max 3 Iterations)
|
||||
|
||||
**Run validation cycle** (repeat up to 3 times):
|
||||
|
||||
#### 5.1: Compilation Check
|
||||
```bash
|
||||
# Phoenix: mix compile
|
||||
# React/TypeScript: npm run build or tsc --noEmit
|
||||
# Vue: npm run build
|
||||
```
|
||||
|
||||
**If errors**: Parse output, fix issues, regenerate
|
||||
**If success**: Continue to next check
|
||||
|
||||
#### 5.2: Structure Validation
|
||||
|
||||
Check:
|
||||
- ✅ Component hierarchy makes sense
|
||||
- ✅ Responsive breakpoints applied (mobile-first)
|
||||
- ✅ Semantic HTML used (not div soup)
|
||||
- ✅ Design system patterns applied
|
||||
|
||||
**If issues**: Note problems, regenerate with corrections
|
||||
|
||||
#### 5.3: Basic Accessibility Check
|
||||
|
||||
Check:
|
||||
- ✅ Semantic elements (`<button>` not `<div onClick>`)
|
||||
- ✅ Heading hierarchy correct (h1 → h2 → h3, no skips)
|
||||
- ✅ Interactive elements keyboard accessible
|
||||
- ✅ ARIA where needed (aria-expanded, aria-label)
|
||||
- ✅ Focus management for modals/dropdowns
|
||||
|
||||
**If violations**: List issues, regenerate with fixes
|
||||
|
||||
#### 5.4: Decide Next Step
|
||||
|
||||
- **Iteration 1-2**: Continue refining if issues found
|
||||
- **Iteration 3**: Last attempt, aggressive fixes
|
||||
- **All checks pass**: Proceed to report
|
||||
|
||||
**Refinement prompt pattern**:
|
||||
```
|
||||
Fix these specific issues:
|
||||
1. [Exact problem with line reference]
|
||||
2. [Exact fix needed]
|
||||
|
||||
Previous code context:
|
||||
[Include relevant previous output]
|
||||
```
|
||||
|
||||
### Stage 6: Generate Concise Report
|
||||
|
||||
Create **brief** generation-report.md (50-100 lines):
|
||||
|
||||
```markdown
|
||||
# Generation Report - [Feature]
|
||||
|
||||
## Summary
|
||||
- **Files**: [N created, M modified]
|
||||
- **Iterations**: [X/3]
|
||||
- **Status**: ✅ Complete | ⚠️ Manual review needed
|
||||
|
||||
## Changes
|
||||
|
||||
### Created
|
||||
- `[path]` - [Brief description]
|
||||
|
||||
### Modified
|
||||
- `[path]` (lines X-Y) - [What changed]
|
||||
|
||||
## Validation
|
||||
|
||||
**Compilation**: ✅ Pass
|
||||
**Structure**: ✅ Pass
|
||||
**Accessibility**: ✅ Basic checks passed
|
||||
|
||||
## Issues Resolved
|
||||
|
||||
1. **[Issue]**: [How fixed]
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [ ] Manual testing: [Brief checklist]
|
||||
- [ ] Visual validation against design
|
||||
- [ ] Run `ui-accessibility` for deep audit (if complex)
|
||||
|
||||
Generated: [Timestamp]
|
||||
```
|
||||
|
||||
**Target**: 50-100 lines total
|
||||
|
||||
### Stage 7: Save & Finalize
|
||||
|
||||
```bash
|
||||
# Save to feature directory
|
||||
BRANCH=$(git branch --show-current)
|
||||
mkdir -p ".specimin/ui/$BRANCH"
|
||||
|
||||
# Write report
|
||||
cat > ".specimin/ui/$BRANCH/generation-report.md" << 'EOF'
|
||||
[report content]
|
||||
EOF
|
||||
|
||||
# Commit
|
||||
git add .
|
||||
git commit -m "Implement UI: [feature name]
|
||||
|
||||
🤖 Generated with Claude Code
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
**Present to user**: Show summary, ask if adjustments needed, allow rapid iteration
|
||||
|
||||
## Lightweight Design Context (for Complex Features)
|
||||
|
||||
When complexity warrants it, create quick design.md first:
|
||||
|
||||
```markdown
|
||||
# UI Design - [Feature]
|
||||
|
||||
## Component Hierarchy (High-Level)
|
||||
[Simple semantic structure notation]
|
||||
|
||||
## Design System Mapping
|
||||
**Standard**: [Components from design system]
|
||||
**Custom**: [What needs implementation]
|
||||
|
||||
## Key Decisions
|
||||
- [Decision 1 with rationale]
|
||||
- [Decision 2 with rationale]
|
||||
|
||||
## Responsive Strategy
|
||||
Mobile: [Key changes]
|
||||
Desktop: [Key changes]
|
||||
|
||||
## Interactive States
|
||||
[Component]: [State needs, triggers]
|
||||
|
||||
## Resolved Ambiguities
|
||||
Q: [Question] → A: [Answer]
|
||||
```
|
||||
|
||||
**Target**: 80-150 lines (high-level decisions only, NOT implementation specs)
|
||||
|
||||
## Tiered Approach Summary
|
||||
|
||||
### Tier 1: Trivial (~2-3 min)
|
||||
**Example**: Add existing button to page
|
||||
|
||||
**Process**: Request → Explore → Generate → Validate → Report
|
||||
|
||||
**Docs**: ~50 lines (report only)
|
||||
|
||||
### Tier 2: Simple (~5-10 min)
|
||||
**Example**: Add charts to page
|
||||
|
||||
**Process**: Request → Explore → Decide inline → Generate → Validate → Report
|
||||
|
||||
**Docs**: ~75 lines (report only)
|
||||
|
||||
### Tier 3: Complex (~15-25 min)
|
||||
**Example**: New multi-component dashboard
|
||||
|
||||
**Process**: Create design context → Request → Explore → Generate → Validate → Report
|
||||
|
||||
**Docs**: ~120 line design + ~100 line report = ~220 lines total
|
||||
|
||||
## Code Generation Rules
|
||||
|
||||
**Prohibitions**:
|
||||
- ❌ Markdown formatting (no ```, no string delimiters)
|
||||
- ❌ Explanatory text mixed with code
|
||||
- ❌ Placeholder comments (`// TODO`, `<!-- Implement -->`)
|
||||
- ❌ "Lazy" shortcuts (`<!-- Repeat for each -->`)
|
||||
- ❌ Custom CSS (Tailwind utilities only)
|
||||
- ❌ Inline styles (`style="..."`)
|
||||
|
||||
**Requirements**:
|
||||
- ✅ Pure code files
|
||||
- ✅ Complete implementations
|
||||
- ✅ Realistic content (not Lorem ipsum)
|
||||
- ✅ Semantic HTML
|
||||
- ✅ Proper imports
|
||||
|
||||
## Exploration Strategies
|
||||
|
||||
**Find similar components**:
|
||||
```bash
|
||||
# Phoenix
|
||||
find lib -name "*.heex" -type f | xargs grep -l "chart\|graph\|visualization" | head -5
|
||||
|
||||
# React
|
||||
find src/components -name "*.tsx" -type f | head -20
|
||||
```
|
||||
|
||||
**Find styling patterns**:
|
||||
```bash
|
||||
# Check common Tailwind usage
|
||||
grep -roh "grid grid-cols-[0-9]" lib/ | sort | uniq -c
|
||||
grep -roh "bg-\w+-\d+" src/ | sort | uniq -c | head -10
|
||||
```
|
||||
|
||||
**Find interactive patterns**:
|
||||
```bash
|
||||
# Phoenix LiveView
|
||||
grep -r "phx-hook" lib/ | head -10
|
||||
grep -r "phx-click" lib/ | head -10
|
||||
|
||||
# React
|
||||
grep -r "useState\|useEffect" src/ | head -10
|
||||
```
|
||||
|
||||
**Time-box exploration**: 2-3 minutes max
|
||||
|
||||
## Known Limitations
|
||||
|
||||
**Complex spatial reasoning** (30-40% accuracy):
|
||||
- Precise geometric layouts, pixel-perfect positioning
|
||||
- **Action**: Best-effort implementation, flag for manual refinement
|
||||
|
||||
**Dynamic behavior from static designs**:
|
||||
- Animations not visible, multi-step flows
|
||||
- **Action**: Basic interactions, flag complex flows for manual work
|
||||
|
||||
**Subjective styling**:
|
||||
- Brand "feel", micro-interactions
|
||||
- **Action**: Follow design system, flag subjective refinements for designer
|
||||
|
||||
## Requirements
|
||||
|
||||
**Do**:
|
||||
- Explore codebase for patterns (2-3 min)
|
||||
- Make reasonable decisions inline
|
||||
- Generate complete, working code
|
||||
- Run automated validation (max 3 iterations)
|
||||
- Fix compilation errors immediately
|
||||
- Create concise reports (~75 lines)
|
||||
- Use realistic content
|
||||
|
||||
**Don't**:
|
||||
- Write incomplete/placeholder code
|
||||
- Skip validation checks
|
||||
- Iterate beyond 3 times
|
||||
- Generate code that doesn't compile
|
||||
- Create verbose documentation
|
||||
- Over-specify everything upfront
|
||||
- Ignore accessibility
|
||||
|
||||
## Research-Backed Optimizations
|
||||
|
||||
- **Temperature 0.2-0.3**: Deterministic generation
|
||||
- **3 iteration limit**: Diminishing returns after iteration 3 (80-90% quality)
|
||||
- **Automated feedback**: Improves compilation rate from <10% to 80%+
|
||||
- **Context engineering**: Design system patterns > verbose instructions
|
||||
- **Inline exploration**: Better than upfront analysis for simple changes
|
||||
|
||||
---
|
||||
|
||||
**Summary**: For 90% of UI work, just provide a sketch/description and this agent will explore, decide, generate, validate, and create working code with a brief report (~75 lines). For complex features, optionally create lightweight design context first (~120 lines) for total ~220 lines vs old workflow's 900+ lines.
|
||||
84
skills/specimin-ui-generate/scripts/save-generation.sh
Executable file
84
skills/specimin-ui-generate/scripts/save-generation.sh
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
# save-generation.sh - Saves generated UI code and commits to feature branch
|
||||
# Usage: save-generation.sh <branch_name>
|
||||
|
||||
set -e
|
||||
|
||||
BRANCH_NAME="$1"
|
||||
|
||||
if [ -z "$BRANCH_NAME" ]; then
|
||||
# Try to get current branch if not provided
|
||||
BRANCH_NAME=$(git branch --show-current)
|
||||
fi
|
||||
|
||||
if [ -z "$BRANCH_NAME" ]; then
|
||||
echo "Error: Could not determine branch name"
|
||||
echo "Usage: save-generation.sh <branch_name>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify we're in a git repository
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo "Error: Not in a git repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify branch exists
|
||||
if ! git rev-parse --verify "$BRANCH_NAME" > /dev/null 2>&1; then
|
||||
echo "Error: Branch '$BRANCH_NAME' does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify we're on the correct branch
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
if [ "$CURRENT_BRANCH" != "$BRANCH_NAME" ]; then
|
||||
echo "Error: Not on branch '$BRANCH_NAME' (currently on '$CURRENT_BRANCH')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FEATURE_DIR=".specimin/ui/$BRANCH_NAME"
|
||||
|
||||
# Verify feature directory exists
|
||||
if [ ! -d "$FEATURE_DIR" ]; then
|
||||
echo "Error: Feature directory not found: $FEATURE_DIR"
|
||||
echo "Run specimin:ui-understand first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify structure.md exists
|
||||
STRUCTURE_PATH="$FEATURE_DIR/structure.md"
|
||||
if [ ! -f "$STRUCTURE_PATH" ]; then
|
||||
echo "Error: structure.md not found at $STRUCTURE_PATH"
|
||||
echo "Run specimin:ui-structure first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if generation report exists in /tmp
|
||||
REPORT_TEMP="/tmp/ui-generation-report.md"
|
||||
if [ ! -f "$REPORT_TEMP" ]; then
|
||||
echo "Error: Generation report not found at $REPORT_TEMP"
|
||||
echo "The skill should write the generation report to /tmp/ui-generation-report.md"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy generation report to feature directory
|
||||
REPORT_DEST="$FEATURE_DIR/generation-report.md"
|
||||
cp "$REPORT_TEMP" "$REPORT_DEST"
|
||||
|
||||
# Add all changes (generated code files + report)
|
||||
git add -A
|
||||
|
||||
# Check if there are changes to commit
|
||||
if git diff --cached --quiet; then
|
||||
echo "Warning: No changes to commit (generated files may already be staged)"
|
||||
else
|
||||
# Commit with descriptive message
|
||||
git commit -m "Generate UI implementation
|
||||
|
||||
- Generated code files from structure specification
|
||||
- Completed validation loops (compilation, structure, accessibility)
|
||||
- See generation-report.md for details"
|
||||
fi
|
||||
|
||||
# Output success message with JSON
|
||||
echo "{\"feature_dir\": \"$FEATURE_DIR\", \"branch_name\": \"$BRANCH_NAME\", \"report_path\": \"$REPORT_DEST\"}"
|
||||
274
skills/specimin-wrap/SKILL.md
Normal file
274
skills/specimin-wrap/SKILL.md
Normal file
@@ -0,0 +1,274 @@
|
||||
---
|
||||
name: "specimin-wrap"
|
||||
description: "Squash commits and create a pull request after feature implementation is complete. Only invoke when user explicitly requests to wrap up, create a PR, prepare for review, or finish the feature."
|
||||
allowed-tools:
|
||||
- run_terminal_cmd
|
||||
- read_file
|
||||
---
|
||||
|
||||
# Feature Wrap-Up Command
|
||||
|
||||
Prepare completed work for code review: squash commits, generate PR description, create pull request.
|
||||
|
||||
# Stage 1: Validate Environment
|
||||
|
||||
**Actions**:
|
||||
1. Check uncommitted changes: `git status`
|
||||
2. Get current branch: `git rev-parse --abbrev-ref HEAD` → store as `CURRENT_BRANCH`
|
||||
3. Detect main branch (try in order):
|
||||
```bash
|
||||
git show-ref --verify --quiet refs/heads/main && echo "main" || \
|
||||
git show-ref --verify --quiet refs/heads/master && echo "master" || \
|
||||
echo "unknown"
|
||||
```
|
||||
Store as `MAIN_BRANCH`. If "unknown", ask user: "What is your main branch name?"
|
||||
4. Verify branch is not main: If `CURRENT_BRANCH == MAIN_BRANCH`, error and exit
|
||||
5. Check initialization: Verify `.specimin/plans/{CURRENT_BRANCH}/` exists
|
||||
6. Read feature context (for PR description generation):
|
||||
- `.specimin/plans/{CURRENT_BRANCH}/spec.md`
|
||||
- `.specimin/plans/{CURRENT_BRANCH}/plan.md`
|
||||
- `.specimin/plans/{CURRENT_BRANCH}/implementation.md`
|
||||
|
||||
**Context Extraction Goals** (from spec/plan):
|
||||
- Feature objective (1-2 sentence summary)
|
||||
- High-level changes by phase/component
|
||||
- Acceptance criteria
|
||||
- Testing approach
|
||||
|
||||
**Error Handling**:
|
||||
- Uncommitted changes: `Warning: Uncommitted changes detected. Commit or stash before wrapping up.` → Exit
|
||||
- On main branch: `Error: Cannot wrap up main branch. Switch to feature branch first.` → Exit
|
||||
- Not initialized: `Error: Specimin not initialized. Run /init first.` → Exit
|
||||
- No commits ahead: `Error: No commits to squash. Branch up to date with {MAIN_BRANCH}.` → Exit
|
||||
- `gh` not installed: `Error: GitHub CLI not installed. Install: https://cli.github.com/` → Exit
|
||||
- Not authenticated: `Error: Not authenticated with GitHub CLI. Run: gh auth login` → Exit
|
||||
|
||||
**Checkpoint**: Verify environment valid (no uncommitted changes, on feature branch, has commits to squash) before proceeding.
|
||||
|
||||
# Stage 2: Run Tests
|
||||
|
||||
**Actions**:
|
||||
1. Detect test framework and run appropriate test command:
|
||||
- Python: `python3 -m pytest` or `pytest`
|
||||
- JavaScript/TypeScript: `npm test` or `yarn test`
|
||||
- Ruby: `bundle exec rspec` or `rake test`
|
||||
- Go: `go test ./...`
|
||||
- Rust: `cargo test`
|
||||
- Java: `mvn test` or `gradle test`
|
||||
- Other: Check for `Makefile` with test target, or ask user
|
||||
|
||||
2. Run tests and capture output
|
||||
|
||||
3. **Error Handling**:
|
||||
- Tests fail: Display failure summary and exit with message:
|
||||
```
|
||||
✗ Tests failed. Fix failing tests before wrapping up.
|
||||
|
||||
{test failure summary}
|
||||
|
||||
Run tests again after fixes and retry wrap.
|
||||
```
|
||||
- Tests pass: Proceed to next stage
|
||||
- No tests found: Warn user but continue:
|
||||
```
|
||||
⚠ No tests detected. Consider adding tests before creating PR.
|
||||
Proceed anyway? (yes/no)
|
||||
```
|
||||
|
||||
**Checkpoint**: Verify all tests pass before proceeding to review changes.
|
||||
|
||||
# Stage 3: Review Changes
|
||||
|
||||
Show user what will be squashed:
|
||||
|
||||
1. **Commit history**:
|
||||
```bash
|
||||
git log {MAIN_BRANCH}..HEAD --oneline
|
||||
```
|
||||
|
||||
2. **Change summary**:
|
||||
```bash
|
||||
git diff {MAIN_BRANCH}...HEAD --stat
|
||||
```
|
||||
|
||||
3. **Files changed**:
|
||||
```bash
|
||||
git diff {MAIN_BRANCH}...HEAD --name-only
|
||||
```
|
||||
|
||||
Present:
|
||||
```
|
||||
I'll squash these commits into one:
|
||||
|
||||
[commit history]
|
||||
|
||||
Files changed:
|
||||
[file list]
|
||||
|
||||
Proceed with squash and PR creation? (yes/no)
|
||||
```
|
||||
|
||||
Wait for confirmation. If "no", exit gracefully.
|
||||
|
||||
# Stage 4: Squash Commits
|
||||
|
||||
Once confirmed:
|
||||
|
||||
1. **Generate commit message**:
|
||||
- Use feature objective from spec.md
|
||||
- Summarize WHAT changed (not HOW)
|
||||
- 1-2 sentences max
|
||||
- Follow conventional commits: `feat:`, `fix:`, `refactor:`, `docs:`
|
||||
|
||||
2. **Perform squash**:
|
||||
```bash
|
||||
git reset --soft {MAIN_BRANCH}
|
||||
git commit -m "{COMMIT_MESSAGE}"
|
||||
```
|
||||
|
||||
**CRITICAL**: No `--author`, no `Co-Authored-By:`, no co-authoring metadata. User authorship only.
|
||||
|
||||
3. **Verify squash**:
|
||||
```bash
|
||||
git log --oneline -1
|
||||
```
|
||||
Confirm only one commit since main branch.
|
||||
|
||||
**Checkpoint**: Verify squash succeeded (single commit, correct message) before creating PR.
|
||||
|
||||
# Stage 5: Create Pull Request
|
||||
|
||||
1. **Generate PR title**:
|
||||
- Use commit message or feature name from spec
|
||||
- Under 72 characters
|
||||
- Clear and descriptive
|
||||
|
||||
2. **Generate PR description** (use template below with extracted context):
|
||||
|
||||
```markdown
|
||||
## Summary
|
||||
|
||||
{1-2 sentence feature objective from spec.md}
|
||||
|
||||
## Changes
|
||||
|
||||
{Bulleted list of high-level changes from plan.md phases or implementation.md completed tasks}
|
||||
|
||||
## Testing
|
||||
|
||||
{Testing approach from plan.md, or manual test scenarios}
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
{Criteria from spec.md}
|
||||
```
|
||||
|
||||
3. **Create PR**:
|
||||
```bash
|
||||
gh pr create --title "{PR_TITLE}" --body "$(cat <<'EOF'
|
||||
{PR_DESCRIPTION}
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
4. **Display result**:
|
||||
```
|
||||
✓ Squashed {N} commits into 1 commit
|
||||
✓ Created pull request: {PR_URL}
|
||||
|
||||
Your feature is ready for review!
|
||||
```
|
||||
|
||||
**No upstream remote**: `gh pr create` will prompt to push if needed.
|
||||
|
||||
# Complete Examples
|
||||
|
||||
## Example 1: Simple CRUD Feature
|
||||
|
||||
**Spec objective**: "Add user profile management allowing users to update their name and email"
|
||||
|
||||
**Commit message**:
|
||||
```
|
||||
feat: add user profile management with update functionality
|
||||
```
|
||||
|
||||
**PR title**:
|
||||
```
|
||||
feat: add user profile management
|
||||
```
|
||||
|
||||
**PR description**:
|
||||
```markdown
|
||||
## Summary
|
||||
|
||||
Add user profile management allowing users to update their name and email through a settings page.
|
||||
|
||||
## Changes
|
||||
|
||||
- Added User schema with name and email fields
|
||||
- Implemented update_user/2 function with validation
|
||||
- Created ProfileLive page with edit form
|
||||
- Added integration tests for profile updates
|
||||
|
||||
## Testing
|
||||
|
||||
- Unit tests: Accounts.update_user/2 with valid/invalid inputs
|
||||
- Integration tests: ProfileLive form submission and validation errors
|
||||
- Manual: Navigate to /profile, update name/email, verify saved
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [x] Users can view current profile information
|
||||
- [x] Users can update name and email
|
||||
- [x] Invalid emails show validation errors
|
||||
- [x] Changes persist after page refresh
|
||||
```
|
||||
|
||||
## Example 2: Complex Integration Feature
|
||||
|
||||
**Spec objective**: "Integrate Stripe payment processing with retry logic and webhook handling for subscription management"
|
||||
|
||||
**Commit message**:
|
||||
```
|
||||
feat: integrate Stripe payment processing with webhook support
|
||||
```
|
||||
|
||||
**PR title**:
|
||||
```
|
||||
feat: integrate Stripe payment processing
|
||||
```
|
||||
|
||||
**PR description**:
|
||||
```markdown
|
||||
## Summary
|
||||
|
||||
Integrate Stripe payment processing with automatic retry logic for failed charges and webhook handlers for subscription lifecycle events.
|
||||
|
||||
## Changes
|
||||
|
||||
- Added Stripe client module with exponential backoff retry logic
|
||||
- Implemented payment processing functions (create_charge, refund_charge)
|
||||
- Created webhook handler for subscription events (created, updated, canceled)
|
||||
- Added Payment schema and database migrations
|
||||
- Implemented error handling for network failures and invalid cards
|
||||
|
||||
## Testing
|
||||
|
||||
- Unit tests: StripeClient module with mocked HTTP responses
|
||||
- Integration tests: Payment creation flow with test API keys
|
||||
- Webhook tests: Event handling for all subscription states
|
||||
- Manual: Create test charge in Stripe dashboard, verify webhook receipt
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [x] Charges created successfully with valid cards
|
||||
- [x] Network failures retry up to 3 times with backoff
|
||||
- [x] Invalid cards return clear error messages
|
||||
- [x] Webhooks update subscription status in database
|
||||
- [x] Payment history visible to users
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Note**: This prompt optimized using research-backed principles: token efficiency (-30%), verification checkpoints (Reflexion 91%), consolidated examples (2-5 optimal), explicit context extraction (CGRAG 4x improvement), and minimal preamble (GPT-5-Codex guidance).
|
||||
|
||||
Reference in New Issue
Block a user