feat: archive zoo_backup for home sync
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
---
|
||||
name: code-review
|
||||
description: Structured code review against implementation plan.
|
||||
---
|
||||
|
||||
# Skill: code-review
|
||||
|
||||
Structured code review against implementation plan.
|
||||
|
||||
## Invoked by
|
||||
|
||||
🔍 Reviewer mode
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `PROJECT-123` |
|
||||
| `MODULE` | Module/component name | `auth`, `api`, `core` |
|
||||
|
||||
## Output
|
||||
|
||||
Markdown file: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-review.md`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Read the plan document
|
||||
|
||||
```bash
|
||||
cat docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-plan.md
|
||||
```
|
||||
|
||||
Extract: planned changes, affected files, expected patterns, acceptance criteria.
|
||||
|
||||
### 2. Read the test plan (if exists)
|
||||
|
||||
```bash
|
||||
cat docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-testplan.md
|
||||
```
|
||||
|
||||
Cross-reference: are all planned test cases implemented?
|
||||
|
||||
### 3. Get the diff
|
||||
|
||||
```bash
|
||||
cd <your-repo-path>-<TICKET_KEY>
|
||||
git diff origin/main --name-only
|
||||
git diff origin/main --stat
|
||||
git diff origin/main
|
||||
```
|
||||
|
||||
### 4. Read changed files
|
||||
|
||||
For each changed file, read the full file to understand context — not just the diff hunks.
|
||||
|
||||
### 5. Run the review checklist
|
||||
|
||||
For each changed file, verify:
|
||||
|
||||
| # | Check | What to look for |
|
||||
|---|-------|-----------------|
|
||||
| 1 | Plan compliance | All plan items implemented? Nothing missing, nothing extra? |
|
||||
| 2 | Pattern correctness | Correct project patterns used? |
|
||||
| 3 | No generated source changes | Generated sources must never be modified manually |
|
||||
| 4 | Logging | Parameterized messages (`log.debug("x: {}", v)`) — no string concatenation |
|
||||
| 5 | Error handling | Proper error responses checked before parsing? Null-safe patterns? |
|
||||
| 6 | Test coverage | Every new/modified public method has a test? Edge cases covered? |
|
||||
| 7 | Database migrations | Correct naming convention? Dual DB dialect support? |
|
||||
| 8 | No hardcoded values | No hardcoded IDs, instance names, or secrets? |
|
||||
| 9 | Field visibility | Appropriate access modifiers? |
|
||||
| 10 | Annotations | Correct use of framework annotations? |
|
||||
|
||||
### 6. Check test quality
|
||||
|
||||
For each test file:
|
||||
- Meaningful assertions (not just `assertNotNull`)?
|
||||
- Edge cases covered?
|
||||
- Mocking done correctly?
|
||||
- Test naming convention: `test<What>_<Scenario>_<Expected>()`?
|
||||
|
||||
### 7. Run tests
|
||||
|
||||
```bash
|
||||
cd <your-repo-path>-<TICKET_KEY>
|
||||
mvn test -pl <module-path> -f pom.xml
|
||||
```
|
||||
|
||||
### 8. Generate review document
|
||||
|
||||
```markdown
|
||||
# Code Review: <TICKET_KEY> — <Summary>
|
||||
|
||||
**Date:** <today>
|
||||
**Module:** <MODULE>
|
||||
**Reviewer:** Lumen (Reviewer)
|
||||
**Branch:** <branch name>
|
||||
**Status:** ✅ Approved / ⚠️ Approved with comments / ❌ Changes requested
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
<1-2 sentence summary of the review outcome>
|
||||
|
||||
## Reviewed Files
|
||||
|
||||
| File | Change | Assessment |
|
||||
|------|--------|-----------|
|
||||
| `<path>` | New/Modified | ✅ / ⚠️ / ❌ |
|
||||
|
||||
## Checklist
|
||||
|
||||
| # | Check | Result | Note |
|
||||
|---|-------|--------|------|
|
||||
| 1 | Plan compliance | ✅ | All planned changes implemented |
|
||||
| ... | ... | ... | ... |
|
||||
|
||||
## Findings
|
||||
|
||||
### ⚠️ Warnings (non-blocking)
|
||||
|
||||
1. **<file>:<line>** — <description>
|
||||
- Recommendation: <suggested fix>
|
||||
|
||||
### ❌ Blockers (must fix)
|
||||
|
||||
1. **<file>:<line>** — <description>
|
||||
- Reason: <why this must be fixed>
|
||||
|
||||
## Tests
|
||||
|
||||
- **Executed:** <N> tests
|
||||
- **Passed:** <N> ✅
|
||||
- **Failed:** <N> ❌
|
||||
- **Build:** ✅ Green / ❌ Red
|
||||
|
||||
## Recommendation
|
||||
|
||||
<Final recommendation: merge / fix and re-review / reject>
|
||||
```
|
||||
|
||||
### 9. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Code review completed — {status}. {findings_count} findings ({blockers} blockers)."
|
||||
)
|
||||
```
|
||||
|
||||
## Severity Levels
|
||||
|
||||
| Level | Symbol | Meaning | Action |
|
||||
|-------|--------|---------|--------|
|
||||
| Blocker | ❌ | Must fix before merge | Changes requested |
|
||||
| Warning | ⚠️ | Should fix, not blocking | Approved with comments |
|
||||
| Info | ℹ️ | Suggestion for improvement | Approved |
|
||||
| OK | ✅ | No issues | — |
|
||||
@@ -0,0 +1,143 @@
|
||||
---
|
||||
name: create-pr
|
||||
description: Create a Bitbucket pull request from a worktree branch.
|
||||
---
|
||||
|
||||
# Skill: create-pr
|
||||
|
||||
Create a Bitbucket (or GitHub) pull request from a worktree branch.
|
||||
|
||||
## Invoked by
|
||||
|
||||
🎫 JiraOps mode (or 🪃 Orchestrator)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `PROJECT-123` |
|
||||
| `MODULE` | Module/component name | `auth`, `api`, `core` |
|
||||
|
||||
## Output
|
||||
|
||||
- Pull request created targeting the main branch
|
||||
- Jira comment with PR link added
|
||||
- BigMind fact stored
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Get current branch
|
||||
|
||||
```bash
|
||||
cd <your-repo-path>-<TICKET_KEY>
|
||||
git branch --show-current
|
||||
```
|
||||
|
||||
### 2. Ensure all changes are committed
|
||||
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
|
||||
If uncommitted changes exist, warn the user before proceeding.
|
||||
|
||||
### 3. Push branch to origin
|
||||
|
||||
```bash
|
||||
git push -u origin <BRANCH>
|
||||
```
|
||||
|
||||
### 4. Gather diff statistics
|
||||
|
||||
```bash
|
||||
git diff origin/main --stat
|
||||
git diff origin/main --name-only
|
||||
```
|
||||
|
||||
### 5. Read Jira ticket for context
|
||||
|
||||
```python
|
||||
ticket = retrieve_ticket_details(TICKET_KEY)
|
||||
# Extract: summary, description for PR title/description
|
||||
```
|
||||
|
||||
### 6. Compose PR title and description
|
||||
|
||||
PR title format:
|
||||
```
|
||||
<TICKET_KEY>: <Jira summary>
|
||||
```
|
||||
|
||||
PR description template:
|
||||
```markdown
|
||||
## Jira
|
||||
|
||||
<TICKET_KEY>: <summary>
|
||||
|
||||
## Description
|
||||
|
||||
<Brief description of what was changed and why>
|
||||
|
||||
## Changes
|
||||
|
||||
<List of changed files grouped by component>
|
||||
|
||||
## Tests
|
||||
|
||||
- <N> Unit tests
|
||||
- <M> Integration tests
|
||||
- All tests passing ✅
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Code review completed
|
||||
- [ ] Tests passing
|
||||
- [ ] No generated source modifications
|
||||
```
|
||||
|
||||
### 7. Create the pull request
|
||||
|
||||
```python
|
||||
create_pull_request(
|
||||
project_key="<PROJECT>",
|
||||
repo_slug="<repo>",
|
||||
title=f"{TICKET_KEY}: {summary}",
|
||||
description=<composed description>,
|
||||
from_branch=<BRANCH>,
|
||||
to_branch="main"
|
||||
)
|
||||
```
|
||||
|
||||
### 8. Add Jira comment with PR link
|
||||
|
||||
```python
|
||||
add_comment_to_ticket(
|
||||
issue_key=TICKET_KEY,
|
||||
comment=f"*Pull Request created*\n\nBranch: {BRANCH}\nPR: [PR #{pr_id}|<pr_url>]"
|
||||
)
|
||||
```
|
||||
|
||||
### 9. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: PR #{pr_id} created — {BRANCH} → main. {N} files changed."
|
||||
)
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Branch not pushed | Run `git push -u origin <BRANCH>` first |
|
||||
| Uncommitted changes | Warn user, suggest `git add` + `git commit` |
|
||||
| PR already exists | Check `list_prs_for_repository` for existing PR from same branch |
|
||||
| Merge conflicts | Run `git fetch origin main && git merge origin/main` in worktree |
|
||||
| No diff (empty PR) | Branch is identical to `main` — nothing to merge |
|
||||
|
||||
## Conventions
|
||||
|
||||
- PR title: always starts with `TICKET_KEY:` for Jira auto-linking
|
||||
- Target branch: typically `main` (configure per project)
|
||||
- One PR per ticket — don't create multiple PRs for the same branch
|
||||
@@ -0,0 +1,154 @@
|
||||
---
|
||||
name: create-worktree
|
||||
description: Git worktree setup for a Jira ticket. Supports multi-branch strategy with automatic base branch selection. Use when asked to create a worktree, start work on a ticket, or set up a branch for a Jira issue.
|
||||
---
|
||||
|
||||
# Skill: create-worktree
|
||||
|
||||
Git worktree setup for a Jira ticket with correct base branch selection.
|
||||
|
||||
## When to use
|
||||
|
||||
- User asks to create a worktree for a Jira ticket
|
||||
- User asks to "start work on" or "set up" a ticket
|
||||
- Orchestrator delegates worktree creation for a new ticket
|
||||
|
||||
## When NOT to use
|
||||
|
||||
- Switching to an existing worktree → use `switch-worktree` skill
|
||||
- Removing a worktree after merge → see Cleanup section below
|
||||
|
||||
## Invoked by
|
||||
|
||||
🎫 JiraOps mode (or 🪃 Orchestrator)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_ID` | Jira issue key | `PROJECT-123` |
|
||||
| `MODULE` | Ticket context or user input | Module/component name |
|
||||
| `TYPE` | Ticket issue type (Story → feature, Bug → bugfix) | `feature` or `bugfix` |
|
||||
| `SHORT_DESC` | Kebab-case summary (2-4 words) | `fix-auth-timeout` |
|
||||
| `BASE_BRANCH` | (Optional) Long-lived branch to base work on | `main` (default) |
|
||||
|
||||
## Branch Strategy
|
||||
|
||||
| Branch | Purpose | Use as base when... |
|
||||
|--------|---------|-------------------|
|
||||
| `main` | Current development — **DEFAULT** | Standard features, bugs, tasks |
|
||||
| `release` | Current production release (hotfixes) | Urgent hotfixes for production |
|
||||
|
||||
### Base branch → worktree branch prefix mapping
|
||||
|
||||
| BASE_BRANCH | Allowed TYPE | Branch prefix |
|
||||
|-------------|-------------|---------------|
|
||||
| `main` | `feature` or `bugfix` | `feature/...` or `bugfix/...` |
|
||||
| `release` | `bugfix` only | `hotfix/...` |
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Parse ticket metadata
|
||||
|
||||
```
|
||||
TICKET_KEY = e.g. "PROJECT-123"
|
||||
```
|
||||
|
||||
If MODULE or TYPE are not provided, retrieve them from Jira:
|
||||
- `retrieve_ticket_details(TICKET_KEY)` → read `issuetype` and `summary`
|
||||
- Map issue type: `Story` / `Task` → `feature`, `Bug` → `bugfix`
|
||||
- Infer module from summary keywords or ask the user
|
||||
|
||||
### 2. Determine base branch
|
||||
|
||||
If `BASE_BRANCH` is not explicitly provided, apply this decision logic:
|
||||
|
||||
1. **Default:** `main`
|
||||
2. **If user says "hotfix" or ticket priority is Critical/Blocker:** suggest `release`
|
||||
|
||||
When suggesting a non-default base, confirm with the user before proceeding.
|
||||
|
||||
### 3. Determine branch name
|
||||
|
||||
```
|
||||
BRANCH = <TYPE>/<MODULE>/<TICKET_KEY>-<SHORT_DESC>
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `feature/auth/PROJECT-123-oauth2-timeout`
|
||||
- `bugfix/api/PROJECT-456-null-pointer`
|
||||
- `hotfix/api/PROJECT-789-critical-fix` (base: `release`)
|
||||
|
||||
### 4. Ensure base branch is up to date
|
||||
|
||||
```bash
|
||||
cd <your-repo-path>
|
||||
git fetch origin <BASE_BRANCH>
|
||||
```
|
||||
|
||||
### 5. Create worktree
|
||||
|
||||
```bash
|
||||
git worktree add <your-repo-path>-<TICKET_KEY> -b <BRANCH> origin/<BASE_BRANCH>
|
||||
```
|
||||
|
||||
This creates:
|
||||
- Worktree directory: `<your-repo-path>-<TICKET_KEY>`
|
||||
- New branch: `<BRANCH>` tracking `origin/<BASE_BRANCH>`
|
||||
|
||||
### 6. Verify
|
||||
|
||||
```bash
|
||||
cd <your-repo-path>-<TICKET_KEY> && git branch --show-current
|
||||
```
|
||||
|
||||
### 7. Switch VS Code workspace to worktree
|
||||
|
||||
```bash
|
||||
code --reuse-window <your-repo-path>-<TICKET_KEY>
|
||||
```
|
||||
|
||||
### 8. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Worktree at <path>, branch {BRANCH}, based on {BASE_BRANCH}"
|
||||
)
|
||||
```
|
||||
|
||||
### 9. Announce focus
|
||||
|
||||
```python
|
||||
memory_announce_focus(
|
||||
session_id=SESSION_ID,
|
||||
description=f"Working on {TICKET_KEY} in worktree",
|
||||
files=[target_path],
|
||||
ide_hint="Roo"
|
||||
)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
- Worktree directory exists
|
||||
- Branch is checked out, based on `origin/<BASE_BRANCH>`
|
||||
- VS Code workspace switched to worktree directory
|
||||
- BigMind fact stored with worktree path and base branch
|
||||
- Focus announced
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Worktree already exists | Check if branch matches. If yes, reuse. If no, ask user. |
|
||||
| Branch already exists | `git worktree add <path> <BRANCH>` (without `-b`) |
|
||||
| `origin/<BASE_BRANCH>` not found | Try `git fetch origin` first, then retry |
|
||||
| Directory already exists (not a worktree) | Ask user to remove or choose different path |
|
||||
|
||||
## Cleanup (when ticket is done)
|
||||
|
||||
```bash
|
||||
cd <your-repo-path>
|
||||
git worktree remove <your-repo-path>-<TICKET_KEY>
|
||||
git branch -d <BRANCH> # only after merge
|
||||
```
|
||||
@@ -0,0 +1,122 @@
|
||||
---
|
||||
name: expert-panel-review
|
||||
description: Multi-expert panel review that analyzes a plan or code from 3 specialized perspectives (Domain Expert, Architecture Expert, Risk/Compliance Expert). Produces a synthesized panel verdict with confidence level. Use when reviewing plans, assessments, or code changes that need high-confidence validation.
|
||||
---
|
||||
|
||||
# Skill: expert-panel-review
|
||||
|
||||
Multi-expert panel review for high-confidence validation of plans and code.
|
||||
|
||||
## When to use
|
||||
|
||||
- Reviewing plans that need multi-perspective validation
|
||||
- Complex architectural decisions requiring diverse expert input
|
||||
- Any change where confidence level matters before proceeding
|
||||
|
||||
## Invoked by
|
||||
|
||||
📋✅ Plan Reviewer mode (as part of plan review workflow)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `ARTIFACT_TYPE` | Type of artifact being reviewed | `plan`, `assessment`, `code` |
|
||||
| `ARTIFACT_PATH` | Path to the document/code | `docs/auth/PROJECT-123/PROJECT-123-plan.md` |
|
||||
|
||||
## Panel Composition
|
||||
|
||||
### 🏛️ Domain Expert
|
||||
- Validates business logic correctness
|
||||
- Checks domain terminology and workflows
|
||||
- Verifies requirements are fully addressed
|
||||
- Identifies missing business rules
|
||||
|
||||
### 🔧 Architecture Expert
|
||||
- Validates technical design patterns
|
||||
- Checks for scalability and maintainability concerns
|
||||
- Verifies integration points are handled correctly
|
||||
- Identifies missing error handling or edge cases
|
||||
|
||||
### 🛡️ Risk/Compliance Expert
|
||||
- Identifies security implications
|
||||
- Checks for data privacy concerns
|
||||
- Validates audit trail requirements
|
||||
- Flags regulatory compliance gaps
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Load the artifact
|
||||
|
||||
Read the document at `ARTIFACT_PATH` completely.
|
||||
|
||||
### 2. Domain Expert review
|
||||
|
||||
Analyze from the domain perspective:
|
||||
- Are all business requirements addressed?
|
||||
- Is domain terminology used correctly?
|
||||
- Are business rules complete and accurate?
|
||||
- Are there missing edge cases from a domain perspective?
|
||||
|
||||
Output: findings list + confidence score (0-100%)
|
||||
|
||||
### 3. Architecture Expert review
|
||||
|
||||
Analyze from the technical perspective:
|
||||
- Are design patterns appropriate?
|
||||
- Is the solution maintainable and testable?
|
||||
- Are integration points correctly handled?
|
||||
- Are failure modes addressed?
|
||||
|
||||
Output: findings list + confidence score (0-100%)
|
||||
|
||||
### 4. Risk/Compliance Expert review
|
||||
|
||||
Analyze from a risk perspective:
|
||||
- Are there security implications?
|
||||
- Is data handling appropriate?
|
||||
- Are there compliance requirements being missed?
|
||||
- What's the blast radius if something goes wrong?
|
||||
|
||||
Output: findings list + confidence score (0-100%)
|
||||
|
||||
### 5. Synthesize panel verdict
|
||||
|
||||
Combine all three perspectives:
|
||||
|
||||
```markdown
|
||||
## Panel Verdict
|
||||
|
||||
**Overall Confidence:** <avg of 3 scores>%
|
||||
- Domain: <score>% — <1-line summary>
|
||||
- Architecture: <score>% — <1-line summary>
|
||||
- Risk: <score>% — <1-line summary>
|
||||
|
||||
### Blockers (❌)
|
||||
<items all experts agree must be fixed>
|
||||
|
||||
### Warnings (⚠️)
|
||||
<items raised by 1-2 experts as concerns>
|
||||
|
||||
### Recommendations (ℹ️)
|
||||
<suggestions for improvement>
|
||||
```
|
||||
|
||||
### 6. Confidence interpretation
|
||||
|
||||
| Confidence | Meaning | Action |
|
||||
|-----------|---------|--------|
|
||||
| 90-100% | High confidence — safe to proceed | APPROVED |
|
||||
| 70-89% | Good confidence — minor concerns | APPROVED with warnings |
|
||||
| 50-69% | Mixed signals — significant concerns | REVISE recommended |
|
||||
| < 50% | Low confidence — major gaps | REVISE required |
|
||||
|
||||
## Output Format
|
||||
|
||||
The panel review is embedded in the parent review document (plan-review.md or code-review.md), not as a standalone file.
|
||||
|
||||
## Notes
|
||||
|
||||
- Panel confidence < 70% → parent review MUST be REVISE regardless of checklist
|
||||
- All three experts must produce findings — even if "no concerns" is the finding
|
||||
- Disagreements between experts should be highlighted explicitly
|
||||
@@ -0,0 +1,136 @@
|
||||
---
|
||||
name: generate-handover
|
||||
description: Generate handover document for session or person transfer.
|
||||
---
|
||||
|
||||
# Skill: generate-handover
|
||||
|
||||
Generate handover document for session or person transfer.
|
||||
|
||||
## Invoked by
|
||||
|
||||
📝 DocGen mode (or 🪃 Orchestrator)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `PROJECT-123` |
|
||||
| `MODULE` | Module/component name | `auth`, `api`, `core` |
|
||||
| `SESSION_ID` | BigMind session to hand over (optional) | `d8a0f4fa-...` |
|
||||
|
||||
## Output
|
||||
|
||||
Markdown file: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-handover-<date>.md`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Read BigMind session context
|
||||
|
||||
```python
|
||||
memory_get_session_detail(session_id=SESSION_ID)
|
||||
memory_search_facts("<TICKET_KEY>")
|
||||
memory_search_chunks("<TICKET_KEY>")
|
||||
```
|
||||
|
||||
### 2. Read git status
|
||||
|
||||
```bash
|
||||
cd <worktree-path>
|
||||
git branch --show-current
|
||||
git status
|
||||
git log origin/main..HEAD --oneline
|
||||
git diff origin/main --stat
|
||||
```
|
||||
|
||||
### 3. Read Jira ticket status
|
||||
|
||||
```python
|
||||
ticket = retrieve_ticket_details(TICKET_KEY)
|
||||
checklist = get_checklist(TICKET_KEY)
|
||||
```
|
||||
|
||||
### 4. Read existing documentation
|
||||
|
||||
Check `docs/<MODULE>/<TICKET_KEY>/` for assessment, plan, testplan, solution, review docs.
|
||||
|
||||
### 5. Analyze what's done vs. remaining
|
||||
|
||||
Cross-reference Jira checklist, git commits, test plan status, and plan steps.
|
||||
|
||||
### 6. Generate handover document
|
||||
|
||||
```markdown
|
||||
# Handover: <TICKET_KEY> — <Summary>
|
||||
|
||||
**Date:** <today>
|
||||
**Module:** <MODULE>
|
||||
**Author:** Lumen (DocGen)
|
||||
**BigMind Session:** `<SESSION_ID>`
|
||||
**Branch:** <current branch>
|
||||
|
||||
---
|
||||
|
||||
## 1. Current State
|
||||
|
||||
**Jira Status:** <status>
|
||||
**Progress:** <X>/<Y> checklist items complete
|
||||
|
||||
<1-3 sentence summary>
|
||||
|
||||
## 2. Completed Work
|
||||
|
||||
| # | Description | Files | Commit |
|
||||
|---|------------|-------|--------|
|
||||
| 1 | <what was done> | `<file1>`, `<file2>` | `<hash>` |
|
||||
|
||||
## 3. Remaining Work
|
||||
|
||||
| # | Description | Priority | Estimated Effort |
|
||||
|---|------------|----------|-----------------|
|
||||
| 1 | <what remains> | High/Medium/Low | <estimate> |
|
||||
|
||||
## 4. Open Questions / Blockers
|
||||
|
||||
| # | Question/Blocker | Context | Contact |
|
||||
|---|-----------------|---------|---------|
|
||||
| 1 | <question> | <context> | <who> |
|
||||
|
||||
## 5. Key Decisions
|
||||
|
||||
| Decision | Rationale | Date |
|
||||
|----------|----------|------|
|
||||
| <decision> | <why> | <date> |
|
||||
|
||||
## 6. Technical Notes
|
||||
|
||||
- <Important context the next person needs>
|
||||
- <Environment setup needed>
|
||||
- <Test data requirements>
|
||||
|
||||
## 7. Context Recovery
|
||||
|
||||
For continuing this work:
|
||||
- **Worktree:** `<path>`
|
||||
- **Branch:** `<branch name>`
|
||||
- **BigMind Session:** `<SESSION_ID>` — `memory_get_session_detail("<ID>")` for details
|
||||
- **Documentation:** `docs/<MODULE>/<TICKET_KEY>/`
|
||||
```
|
||||
|
||||
### 7. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Handover doc created. Status: {done}/{total} items done."
|
||||
)
|
||||
```
|
||||
|
||||
## When to Use
|
||||
|
||||
| Scenario | Trigger |
|
||||
|----------|---------|
|
||||
| End of day | Capture progress before stopping work |
|
||||
| Person transfer | Handing ticket to another developer |
|
||||
| Session recovery | After IDE crash, use to restore context |
|
||||
| Long pause | Before vacation or multi-day break |
|
||||
@@ -0,0 +1,135 @@
|
||||
---
|
||||
name: generate-solution-doc
|
||||
description: Solution documentation from implementation results.
|
||||
---
|
||||
|
||||
# Skill: generate-solution-doc
|
||||
|
||||
Solution documentation from implementation results.
|
||||
|
||||
## Invoked by
|
||||
|
||||
📝 DocGen mode
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `PROJECT-123` |
|
||||
| `MODULE` | Module/component name | `auth`, `api`, `core` |
|
||||
| `PLAN_PATH` | Path to plan.md | `docs/auth/PROJECT-123/PROJECT-123-plan.md` |
|
||||
| `TESTPLAN_PATH` | Path to testplan.md | `docs/auth/PROJECT-123/PROJECT-123-testplan.md` |
|
||||
|
||||
## Output
|
||||
|
||||
- Markdown: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-solution.md`
|
||||
- PDF: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-solution.pdf`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Read input documents
|
||||
|
||||
Read all available docs in `docs/<MODULE>/<TICKET_KEY>/`.
|
||||
|
||||
### 2. Analyze actual changes
|
||||
|
||||
```bash
|
||||
cd <worktree-path>
|
||||
git diff origin/main --stat
|
||||
git diff origin/main --name-only
|
||||
git log origin/main..HEAD --oneline
|
||||
```
|
||||
|
||||
### 3. Gather test results
|
||||
|
||||
Check surefire reports or reference the testplan status.
|
||||
|
||||
### 4. Generate solution document
|
||||
|
||||
```markdown
|
||||
# Solution Documentation: <TICKET_KEY>
|
||||
|
||||
**Date:** <today>
|
||||
**Module:** <MODULE>
|
||||
**Author:** <Your Name>
|
||||
**Jira:** <TICKET_KEY>
|
||||
**Branch:** <branch name>
|
||||
|
||||
---
|
||||
|
||||
## 1. Problem Statement
|
||||
|
||||
<What was the problem? Why did it need solving?>
|
||||
|
||||
## 2. Approach
|
||||
|
||||
<High-level approach chosen. Reference the plan document.>
|
||||
|
||||
## 3. Architecture Decisions
|
||||
|
||||
| Decision | Rationale | Alternatives |
|
||||
|----------|----------|--------------|
|
||||
| <decision> | <why> | <what was considered> |
|
||||
|
||||
## 4. Implemented Changes
|
||||
|
||||
### 4.1 <Component group>
|
||||
|
||||
| File | Change | Description |
|
||||
|------|--------|-------------|
|
||||
| `<path>` | New/Modified | <what changed> |
|
||||
|
||||
### 4.n Database Migrations
|
||||
|
||||
| Migration | Database | Description |
|
||||
|-----------|----------|-------------|
|
||||
| `V{timestamp}__...` | H2/Oracle | <what it does> |
|
||||
|
||||
## 5. Test Coverage
|
||||
|
||||
| ID | Description | Type | Result |
|
||||
|----|-------------|------|--------|
|
||||
| T-01 | <desc> | Unit | ✅ |
|
||||
| T-02 | <desc> | Integration | ✅ |
|
||||
|
||||
## 6. Open Items
|
||||
|
||||
| # | Description | Priority | Ticket |
|
||||
|---|-------------|----------|--------|
|
||||
| 1 | <open item> | High/Medium/Low | <linked ticket or "—"> |
|
||||
```
|
||||
|
||||
### 5. Ask for PDF color scheme
|
||||
|
||||
> "Which color scheme for the PDF? Available: adp (red), royal_purple, ocean, forest, sunset, slate, rose"
|
||||
|
||||
### 6. Generate PDF
|
||||
|
||||
```python
|
||||
generate_pdf(
|
||||
content=<markdown content>,
|
||||
title=f"Solution Documentation {TICKET_KEY}",
|
||||
author="Your Name",
|
||||
output_path=f"docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-solution.pdf",
|
||||
color_scheme=<chosen scheme>
|
||||
)
|
||||
```
|
||||
|
||||
### 7. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Solution doc created, PDF generated"
|
||||
)
|
||||
```
|
||||
|
||||
## Template Variants
|
||||
|
||||
### Minimal (for small bugfixes)
|
||||
|
||||
Skip sections 3 (Architecture Decisions) and 6 (Open Items). Keep 1, 2, 4, 5.
|
||||
|
||||
### Extended (for large features)
|
||||
|
||||
Add: Configuration Changes, Deployment Notes, Backward Compatibility, Performance Impact.
|
||||
@@ -0,0 +1,123 @@
|
||||
---
|
||||
name: generate-testplan
|
||||
description: Structured test plan from implementation plan / assessment.
|
||||
---
|
||||
|
||||
# Skill: generate-testplan
|
||||
|
||||
Structured test plan from implementation plan / assessment.
|
||||
|
||||
## Invoked by
|
||||
|
||||
📋 Planner mode
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `PROJECT-123` |
|
||||
| `MODULE` | Module/component name | `auth`, `api`, `core` |
|
||||
| `PLAN_PATH` | Path to plan.md | `docs/auth/PROJECT-123/PROJECT-123-plan.md` |
|
||||
|
||||
## Output
|
||||
|
||||
Markdown file: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-testplan.md`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Read the implementation plan
|
||||
|
||||
Understand which classes/methods are being added or modified, data flows affected, database changes, and integration points.
|
||||
|
||||
### 2. Identify testable units
|
||||
|
||||
| Category | What to test | Test type |
|
||||
|----------|-------------|-----------|
|
||||
| New methods | Input/output, edge cases, null handling | Unit |
|
||||
| Modified methods | Regression + new behavior | Unit |
|
||||
| Database changes | Migration up/down, data integrity | Integration |
|
||||
| Data flows | End-to-end processing | Integration |
|
||||
| Error paths | Invalid input, missing data, error responses | Unit |
|
||||
|
||||
### 3. Generate test plan document
|
||||
|
||||
```markdown
|
||||
# Test Plan: <TICKET_KEY> — <Summary>
|
||||
|
||||
**Date:** <today>
|
||||
**Module:** <MODULE>
|
||||
**Author:** Lumen (Planner)
|
||||
**Status:** Draft v1
|
||||
**Based on:** <TICKET_KEY>-plan.md
|
||||
|
||||
---
|
||||
|
||||
## Test Overview
|
||||
|
||||
| ID | Description | Type | Class | Status |
|
||||
|----|-------------|------|-------|--------|
|
||||
| T-01 | <short desc> | Unit | <TestClass> | ⬜ |
|
||||
| T-02 | <short desc> | Unit | <TestClass> | ⬜ |
|
||||
| T-03 | <short desc> | Integration | <TestClass> | ⬜ |
|
||||
|
||||
Status: ⬜ Open | ✅ Passed | ❌ Failed | ⏭️ Skipped
|
||||
|
||||
---
|
||||
|
||||
## Test Cases
|
||||
|
||||
### T-01: <Descriptive name>
|
||||
|
||||
**Type:** Unit
|
||||
**Class:** `<package>.<TestClassName>`
|
||||
**Method:** `test<MethodName>()`
|
||||
|
||||
**Preconditions:**
|
||||
- <setup requirements>
|
||||
|
||||
**Scenarios:**
|
||||
|
||||
| # | Input | Expected Result |
|
||||
|---|-------|----------------|
|
||||
| a | <input> | <expected> |
|
||||
| b | <input> | <expected> |
|
||||
| c | <edge case> | <expected> |
|
||||
|
||||
---
|
||||
|
||||
## Test Data
|
||||
|
||||
<Describe test data requirements, fixtures, or database setup needed.>
|
||||
|
||||
## Test Coverage
|
||||
|
||||
| Component | Unit | Integration | Total |
|
||||
|-----------|------|-------------|-------|
|
||||
| <Class1> | 3 | 1 | 4 |
|
||||
| <Class2> | 2 | 0 | 2 |
|
||||
| **Total** | **5** | **1** | **6** |
|
||||
```
|
||||
|
||||
### 4. Cross-reference with plan
|
||||
|
||||
Verify every implementation step has at least one test case. Flag gaps as warnings.
|
||||
|
||||
### 5. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Testplan with {N} test cases (Unit: {u}, Integration: {i})"
|
||||
)
|
||||
```
|
||||
|
||||
## Test Naming Conventions
|
||||
|
||||
- Test class: `<OriginalClass>Test.java` or `<Feature>Test.java`
|
||||
- Test method: `test<What>_<Scenario>_<Expected>()` or `test<What>()` for simple cases
|
||||
- Location: mirror source structure under `src/test/java/`
|
||||
|
||||
## Test ID Format
|
||||
|
||||
- Sequential: T-01, T-02, ..., T-nn
|
||||
- IDs are stable — don't renumber on revision, append new tests at the end
|
||||
@@ -0,0 +1,173 @@
|
||||
---
|
||||
name: mvn-test
|
||||
description: Run Maven tests in multi-module projects. Resolves module paths, builds dependencies, parses surefire XML reports, and returns structured pass/fail results. Use when asked to run tests, execute test classes, or verify a module build.
|
||||
---
|
||||
|
||||
# Maven Test & Build Runner
|
||||
|
||||
## When to use
|
||||
|
||||
- Running all tests for a module in a multi-module Maven project
|
||||
- Running a specific test class or method
|
||||
- Building a fat JAR for deployment
|
||||
- Verifying a build after code changes in a worktree
|
||||
- Troubleshooting Maven dependency/version issues
|
||||
|
||||
## When NOT to use
|
||||
|
||||
- SSH integration tests on remote instances → use a dedicated SSH test skill
|
||||
- Creating new test files → use Code mode directly
|
||||
- Running non-Maven tests (npm, etc.)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Issue key or task ID | `PROJECT-123` |
|
||||
| `MODULE` | Maven module name | `module-a`, `module-b`, `persistence` |
|
||||
| `TEST_CLASS` | Fully qualified test class (optional) | `com.example.service.MyServiceTest` |
|
||||
|
||||
## Module Path Resolution
|
||||
|
||||
| Module name | Maven `-pl` path |
|
||||
|------------|-----------------|
|
||||
| module-a | `java/modules/cs-modules/module-a` |
|
||||
| module-b | `java/modules/cs-modules/module-b` |
|
||||
| nested-module | `java/modules/cs-modules/parent-group/nested-module` |
|
||||
| persistence | `java/persistence` |
|
||||
| shared-lib | `java/modules/shared-lib` |
|
||||
|
||||
If the module is not in this table, search for it:
|
||||
```bash
|
||||
find java/modules -name "pom.xml" -path "*/<MODULE>/*" | head -3
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Determine worktree path
|
||||
|
||||
```bash
|
||||
WORKTREE="<your-repo-path>"
|
||||
# Verify it exists
|
||||
ls "$WORKTREE/java/pom.xml"
|
||||
```
|
||||
|
||||
If no worktree exists, fall back to the main repo path
|
||||
|
||||
### 2. Resolve module path
|
||||
|
||||
Look up `MODULE` in the path resolution table above. Store as `MODULE_PATH`.
|
||||
|
||||
### 3. Run tests
|
||||
|
||||
**All module tests:**
|
||||
```bash
|
||||
cd <WORKTREE> && mvn test -pl <MODULE_PATH> -am -f java/pom.xml
|
||||
```
|
||||
|
||||
**Specific test class:**
|
||||
```bash
|
||||
cd <WORKTREE> && mvn test -pl <MODULE_PATH> -am -Dtest="<TEST_CLASS>" -Dsurefire.failIfNoSpecifiedTests=false -f java/pom.xml
|
||||
```
|
||||
|
||||
**Specific test method:**
|
||||
```bash
|
||||
cd <WORKTREE> && mvn test -pl <MODULE_PATH> -am -Dtest="<TEST_CLASS>#<methodName>" -Dsurefire.failIfNoSpecifiedTests=false -f java/pom.xml
|
||||
```
|
||||
|
||||
### 4. Parse results
|
||||
|
||||
Look for these patterns in the output:
|
||||
|
||||
| Pattern | Meaning |
|
||||
|---------|---------|
|
||||
| `Tests run: N, Failures: F, Errors: E, Skipped: S` | Surefire summary |
|
||||
| `BUILD SUCCESS` | All tests passed |
|
||||
| `BUILD FAILURE` | At least one test failed or compilation error |
|
||||
| `There are test failures` | Link to surefire reports |
|
||||
|
||||
If tests fail, read the surefire report:
|
||||
```bash
|
||||
find <WORKTREE>/<MODULE_PATH>/target/surefire-reports -name "*.txt" -exec grep -l "FAILURE\|ERROR" {} \;
|
||||
```
|
||||
|
||||
### 5. Store results in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: mvn test {MODULE} — {tests_run} run, {failures} failures, {errors} errors. {'BUILD SUCCESS' or 'BUILD FAILURE'}"
|
||||
)
|
||||
```
|
||||
|
||||
## Building Fat JARs (for deployment)
|
||||
|
||||
### Package a module with all dependencies:
|
||||
```bash
|
||||
cd <WORKTREE> && mvn package -pl :<ARTIFACT_ID> -am -DskipTests -f java/pom.xml -Drevision=1.0.0-TEST -o -q
|
||||
```
|
||||
|
||||
### Locate the built JAR:
|
||||
```bash
|
||||
find <MODULE_PATH>/target -name "*-jar-with-dependencies.jar" | head -1
|
||||
```
|
||||
|
||||
### Module artifact IDs (for `-pl :NAME`):
|
||||
|
||||
| Module | Artifact ID | Fat JAR name |
|
||||
|--------|-------------|-------------|
|
||||
| module-a | `ModuleA` | `ModuleA-*-jar-with-dependencies.jar` |
|
||||
| module-b | `ModuleB` | `ModuleB-*-jar-with-dependencies.jar` |
|
||||
| persistence | `persistence` | (no fat JAR) |
|
||||
|
||||
Use `:ARTIFACT_ID` with `-pl` for single-module builds (faster than path-based).
|
||||
|
||||
## Critical: Version Timestamp Issue
|
||||
|
||||
If the project uses a Maven `${revision}` timestamp-based SNAPSHOT scheme (e.g. `1.0-DEV-SNAPSHOT-<timestamp>`), the snapshot changes every minute; ensure dependent modules are rebuilt in the same run.
|
||||
|
||||
**Problem:** If you `mvn install` at 07:55 and then `mvn test` at 07:56, the version changed and artifacts can't be found.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Always use `-am` (also-make)** — builds from source, no cached artifacts needed
|
||||
2. **Pin the version:** `-Drevision=1.0.0-TEST` — stable across commands
|
||||
3. **Use `-o` (offline)** — prevents remote lookups that fail on VPN/cert issues
|
||||
4. **Never use `-pl` without `-am`** for test runs — dependencies won't resolve
|
||||
|
||||
### Recommended command patterns:
|
||||
|
||||
```bash
|
||||
# Compile check (fast)
|
||||
mvn compile -pl :<ARTIFACT_ID> -am -f java/pom.xml -o -q
|
||||
|
||||
# Run specific test (reliable)
|
||||
mvn test -pl :<ARTIFACT_ID> -am -f java/pom.xml \
|
||||
-Dtest="com.example.MyTest" \
|
||||
-Dsurefire.failIfNoSpecifiedTests=false \
|
||||
-Dmaven.test.skip=false -DskipTests=false \
|
||||
-Drevision=1.0.0-TEST -o
|
||||
|
||||
# Build fat JAR for deployment
|
||||
mvn package -pl :<ARTIFACT_ID> -am -DskipTests -f java/pom.xml \
|
||||
-Drevision=1.0.0-TEST -o -q
|
||||
```
|
||||
|
||||
### Why `-Dmaven.test.skip=false -DskipTests=false`?
|
||||
|
||||
Some modules have `<skipTests>true</skipTests>` in their POM or parent POM. These flags override that to force test execution.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Problem | Solution |
|
||||
|---------|----------|
|
||||
| `Could not find artifact` | Add `-am` flag to build dependencies first |
|
||||
| `No tests were executed` | Check test class path — use package-relative path, not fully qualified with `src/test/java/` |
|
||||
| `Compilation failure` in dependency | Run `mvn compile -pl <MODULE_PATH> -am -f java/pom.xml` first to isolate |
|
||||
| OOM during tests | Add `-Xmx1g` via `MAVEN_OPTS`: `MAVEN_OPTS="-Xmx1g" mvn test ...` |
|
||||
| Test hangs | Add `-Dsurefire.timeout=120` to kill stuck tests after 120s |
|
||||
| `Tests are skipped` | Add `-Dmaven.test.skip=false -DskipTests=false` |
|
||||
| Version mismatch (timestamp) | Pin with `-Drevision=1.0.0-TEST` |
|
||||
| Certificate/SSL error on artifact download | Add `-o` (offline) — use local sources with `-am` |
|
||||
| `No tests matching pattern` in dependency modules | Add `-Dsurefire.failIfNoSpecifiedTests=false` |
|
||||
| Wrong module selected by `-pl` | Use artifact ID (`:ModuleA`) not path — check with `grep '<artifactId>' <MODULE_PATH>/pom.xml` |
|
||||
@@ -0,0 +1,160 @@
|
||||
---
|
||||
name: plan-review
|
||||
description: Plan and testplan quality review before implementation. Produces APPROVED/REVISE verdict.
|
||||
---
|
||||
|
||||
# Skill: plan-review
|
||||
|
||||
Plan and testplan quality review before implementation.
|
||||
|
||||
## Invoked by
|
||||
|
||||
📋✅ Plan Reviewer mode
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `TICKET_KEY` | Jira issue key | `PROJECT-123` |
|
||||
| `MODULE` | Module/component name | `auth`, `api`, `core` |
|
||||
|
||||
## Output
|
||||
|
||||
Markdown file: `docs/<MODULE>/<TICKET_KEY>/<TICKET_KEY>-plan-review.md`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Read the planning documents
|
||||
|
||||
- Assessment (`*-assessment.md`) — required
|
||||
- Implementation plan (`*-plan.md`) — required
|
||||
- Test plan (`*-testplan.md`) — required
|
||||
|
||||
If any required document is missing, flag as REVISE immediately.
|
||||
|
||||
### 2. Read the Jira ticket
|
||||
|
||||
Cross-reference: do the plan documents address ALL requirements from the ticket?
|
||||
|
||||
### 3. Read affected source code
|
||||
|
||||
For each file/class mentioned in the plan:
|
||||
- Verify the file exists at the stated path
|
||||
- Verify class/method names are correct
|
||||
- Verify patterns described match actual code
|
||||
- Check if the plan missed related files
|
||||
|
||||
### 4. Run the plan review checklist
|
||||
|
||||
#### Assessment Review
|
||||
|
||||
| # | Check |
|
||||
|---|-------|
|
||||
| 1 | Problem statement complete and matches Jira ticket |
|
||||
| 2 | Affected components identified — any missing? |
|
||||
| 3 | Current state description matches actual code |
|
||||
| 4 | Risk assessment realistic |
|
||||
| 5 | Solution options evaluated with justification |
|
||||
|
||||
#### Implementation Plan Review
|
||||
|
||||
| # | Check |
|
||||
|---|-------|
|
||||
| 6 | All requirements covered |
|
||||
| 7 | Correct project patterns referenced |
|
||||
| 8 | File paths correct and exist |
|
||||
| 9 | Implementation order logical (dependencies first) |
|
||||
| 10 | No gaps between steps |
|
||||
| 11 | Database migrations planned (if needed) |
|
||||
| 12 | Error handling planned (not just happy path) |
|
||||
| 13 | No scope creep beyond ticket requirements |
|
||||
|
||||
#### Test Plan Review
|
||||
|
||||
| # | Check |
|
||||
|---|-------|
|
||||
| 14 | Coverage complete — every plan step has a test |
|
||||
| 15 | Test types appropriate (unit vs integration) |
|
||||
| 16 | Edge cases covered (null, empty, boundary values) |
|
||||
| 17 | Test class naming correct |
|
||||
| 18 | Test method naming correct |
|
||||
| 19 | Test data defined |
|
||||
|
||||
### 5. Run expert-panel-review skill
|
||||
|
||||
Before generating the verdict, run the `expert-panel-review` skill for multi-perspective analysis. Panel confidence < 70% → verdict MUST be REVISE.
|
||||
|
||||
### 6. Generate plan review document
|
||||
|
||||
```markdown
|
||||
# Plan Review: <TICKET_KEY> — <Summary>
|
||||
|
||||
**Date:** <today>
|
||||
**Module:** <MODULE>
|
||||
**Reviewer:** Lumen (Plan Reviewer)
|
||||
**Documents:** assessment.md v<N>, plan.md v<N>, testplan.md v<N>
|
||||
**Verdict:** ✅ APPROVED / 🔄 REVISE
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
<1-2 sentence summary>
|
||||
|
||||
## Checklist
|
||||
|
||||
| # | Check | Result | Note |
|
||||
|---|-------|--------|------|
|
||||
| 1 | Problem statement complete | ✅/❌ | |
|
||||
| ... | ... | ... | ... |
|
||||
|
||||
## Findings
|
||||
|
||||
### ❌ Must revise (blocking)
|
||||
|
||||
1. **<document>** — <issue>
|
||||
|
||||
### ⚠️ Suggestions (non-blocking)
|
||||
|
||||
1. **<document>** — <suggestion>
|
||||
|
||||
## Traceability Matrix
|
||||
|
||||
| Requirement | Plan Step | Test Case | Status |
|
||||
|------------|-----------|-----------|--------|
|
||||
| <req 1> | Step <N> | T-<NN> | ✅ Covered |
|
||||
|
||||
## Verdict
|
||||
|
||||
**✅ APPROVED** — Plan is complete and ready for implementation.
|
||||
— or —
|
||||
**🔄 REVISE** — <N> items need rework. Back to Planner.
|
||||
**Panel Confidence:** <X>%
|
||||
```
|
||||
|
||||
### 7. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"{TICKET_KEY}: Plan review — {verdict}. {findings} findings ({blockers} blocking)."
|
||||
)
|
||||
```
|
||||
|
||||
## Verdict Criteria
|
||||
|
||||
| Verdict | Criteria |
|
||||
|---------|---------|
|
||||
| ✅ APPROVED | All checklist items pass. No blocking findings. Panel confidence ≥ 70%. |
|
||||
| 🔄 REVISE | Any checklist item fails, or panel confidence < 70%. |
|
||||
|
||||
## Review Loop
|
||||
|
||||
1. Planner produces v1 documents
|
||||
2. Plan Reviewer reviews → REVISE with findings
|
||||
3. Planner revises → v2 documents
|
||||
4. Plan Reviewer reviews → APPROVED
|
||||
5. User gives GO
|
||||
6. Pipeline proceeds
|
||||
|
||||
Max 3 iterations recommended.
|
||||
@@ -0,0 +1,460 @@
|
||||
---
|
||||
name: playwright-e2e
|
||||
description: Set up standardized Playwright E2E test infrastructure for Next.js + Spring Boot projects. Creates 3-project config (setup/authenticated/unauthenticated), auth flow, Docker test environment, accessibility tests, and seed data. Use when asked to set up Playwright tests, create E2E test infrastructure, add Playwright to a project, or create an integration test harness.
|
||||
---
|
||||
|
||||
# Playwright E2E Test Infrastructure
|
||||
|
||||
## When to use
|
||||
|
||||
- Setting up Playwright E2E tests for a Next.js + backend project
|
||||
- Creating test infrastructure from scratch
|
||||
- Adding authentication-aware E2E testing
|
||||
- Setting up accessibility testing with axe-core
|
||||
- Triggers: "set up Playwright tests", "create E2E test infrastructure", "add Playwright to this project", "E2E test suite", "create integration test harness"
|
||||
|
||||
## When NOT to use
|
||||
|
||||
- Unit testing (use Jest/Vitest instead)
|
||||
- API-only testing without a frontend (use Postman/REST client)
|
||||
- Projects without a web frontend
|
||||
- Adding individual test files to an existing Playwright setup (just write the test directly)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `PROJECT_DIR` | Current workspace | `/Users/pplate/git/personal/inspectflow` |
|
||||
| `FRONTEND_DIR` | Relative path to frontend | `frontend/` |
|
||||
| `BASE_URL` | Dev server URL | `http://localhost:3000` |
|
||||
| `API_URL` | Backend URL | `http://localhost:8080` |
|
||||
| `LOGIN_EMAIL` | Test user email | `admin@test.de` |
|
||||
| `LOGIN_PASSWORD` | Test user password | `test123` |
|
||||
|
||||
## Expected Output
|
||||
|
||||
- `playwright.config.ts` (3-project architecture)
|
||||
- `e2e/auth.setup.ts`
|
||||
- `e2e/auth-flow.unauth.spec.ts`
|
||||
- `e2e/crud-flow.spec.ts` (template)
|
||||
- `e2e/navigation.spec.ts` (template)
|
||||
- `e2e/accessibility.spec.ts`
|
||||
- `docker-compose.test.yml`
|
||||
- `scripts/seed.sql`
|
||||
- Updated `package.json` scripts
|
||||
- Updated `.gitignore`
|
||||
|
||||
---
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: Install dependencies
|
||||
|
||||
```bash
|
||||
cd <FRONTEND_DIR>
|
||||
pnpm add -D @playwright/test @axe-core/playwright
|
||||
npx playwright install chromium
|
||||
```
|
||||
|
||||
### Step 2: Create `playwright.config.ts`
|
||||
|
||||
Place in `<FRONTEND_DIR>/playwright.config.ts`:
|
||||
|
||||
```typescript
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './e2e',
|
||||
fullyParallel: true,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
reporter: [['html'], ['list']],
|
||||
|
||||
use: {
|
||||
baseURL: process.env.BASE_URL || '<BASE_URL>',
|
||||
trace: 'on-first-retry',
|
||||
screenshot: 'only-on-failure',
|
||||
video: 'retain-on-failure',
|
||||
},
|
||||
|
||||
projects: [
|
||||
{
|
||||
name: 'setup',
|
||||
testMatch: /.*\.setup\.ts/,
|
||||
},
|
||||
{
|
||||
name: 'authenticated',
|
||||
use: {
|
||||
...devices['Desktop Chrome'],
|
||||
storageState: '.auth/admin.json',
|
||||
},
|
||||
dependencies: ['setup'],
|
||||
testIgnore: /.*\.unauth\.spec\.ts/,
|
||||
},
|
||||
{
|
||||
name: 'unauthenticated',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
testMatch: /.*\.unauth\.spec\.ts/,
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
**Key architecture:**
|
||||
- `setup` project runs `auth.setup.ts` first — logs in once, saves session
|
||||
- `authenticated` project reuses saved `storageState` — no repeated logins
|
||||
- `unauthenticated` project has no auth state — tests public pages and login flows
|
||||
|
||||
### Step 3: Create `e2e/auth.setup.ts`
|
||||
|
||||
```typescript
|
||||
import { test as setup, expect } from '@playwright/test';
|
||||
|
||||
const authFile = '.auth/admin.json';
|
||||
|
||||
setup('authenticate', async ({ page }) => {
|
||||
const email = process.env.TEST_EMAIL || '<LOGIN_EMAIL>';
|
||||
const password = process.env.TEST_PASSWORD || '<LOGIN_PASSWORD>';
|
||||
|
||||
await page.goto('/login');
|
||||
await page.getByLabel('E-Mail').fill(email);
|
||||
await page.getByLabel('Passwort').fill(password);
|
||||
await page.getByRole('button', { name: /anmelden|login|sign in/i }).click();
|
||||
|
||||
// Wait for successful redirect to dashboard
|
||||
await page.waitForURL('**/dashboard');
|
||||
await expect(page.locator('body')).not.toContainText('Login');
|
||||
|
||||
// Save authentication state
|
||||
await page.context().storageState({ path: authFile });
|
||||
});
|
||||
```
|
||||
|
||||
### Step 4: Create `docker-compose.test.yml`
|
||||
|
||||
Place in `<PROJECT_DIR>/docker-compose.test.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
test-db:
|
||||
image: postgres:17-alpine
|
||||
environment:
|
||||
POSTGRES_DB: testdb
|
||||
POSTGRES_USER: test
|
||||
POSTGRES_PASSWORD: test
|
||||
ports:
|
||||
- "5433:5432"
|
||||
volumes:
|
||||
- ./scripts/seed.sql:/docker-entrypoint-initdb.d/01-seed.sql
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U test -d testdb"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
environment:
|
||||
SPRING_PROFILES_ACTIVE: test
|
||||
SPRING_DATASOURCE_URL: jdbc:postgresql://test-db:5432/testdb
|
||||
SPRING_DATASOURCE_USERNAME: test
|
||||
SPRING_DATASOURCE_PASSWORD: test
|
||||
JWT_SECRET: test-secret-key-for-e2e-testing-only
|
||||
ports:
|
||||
- "8080:8080"
|
||||
depends_on:
|
||||
test-db:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
```
|
||||
|
||||
### Step 5: Create `scripts/seed.sql`
|
||||
|
||||
```sql
|
||||
-- E2E Test Seed Data
|
||||
-- Password "test123" as BCrypt hash
|
||||
-- Verify with: echo -n "test123" | htpasswd -bnBC 10 "" - | cut -d: -f2
|
||||
|
||||
INSERT INTO users (email, password_hash, name, role, active)
|
||||
VALUES (
|
||||
'<LOGIN_EMAIL>',
|
||||
'$2a$10$/FgU1KyveJ7MaQ7Xv4kxD.5EIQUHujJfZI4K2E1H7pS6parMHJpeG',
|
||||
'Test Admin',
|
||||
'ADMIN',
|
||||
true
|
||||
) ON CONFLICT (email) DO NOTHING;
|
||||
|
||||
-- Sample data (adapt to your schema)
|
||||
-- INSERT INTO companies (name, created_by) VALUES ('Test GmbH', 1);
|
||||
```
|
||||
|
||||
⚠️ **CRITICAL**: The BCrypt hash `$2a$10$/FgU1KyveJ7MaQ7Xv4kxD.5EIQUHujJfZI4K2E1H7pS6parMHJpeG` is for the password `test123`. If you change the password, regenerate the hash. This was the #1 source of broken tests in CannaManage.
|
||||
|
||||
### Step 6: Create test file templates
|
||||
|
||||
#### `e2e/auth-flow.unauth.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Authentication Flow', () => {
|
||||
test('login page loads correctly', async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
await expect(page.getByRole('heading', { name: /anmelden|login/i })).toBeVisible();
|
||||
await expect(page.getByLabel('E-Mail')).toBeVisible();
|
||||
await expect(page.getByLabel('Passwort')).toBeVisible();
|
||||
});
|
||||
|
||||
test('shows validation errors for empty form', async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
await page.getByRole('button', { name: /anmelden|login|sign in/i }).click();
|
||||
// Expect validation messages
|
||||
await expect(page.locator('text=/required|pflichtfeld|eingeben/i')).toBeVisible();
|
||||
});
|
||||
|
||||
test('redirects unauthenticated users to login', async ({ page }) => {
|
||||
await page.goto('/dashboard');
|
||||
await page.waitForURL('**/login**');
|
||||
});
|
||||
|
||||
test('registration page loads', async ({ page }) => {
|
||||
await page.goto('/register');
|
||||
await expect(page.getByRole('heading', { name: /registr/i })).toBeVisible();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### `e2e/crud-flow.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('CRUD Operations', () => {
|
||||
test('can navigate to list page', async ({ page }) => {
|
||||
await page.goto('/dashboard');
|
||||
// Adapt: click sidebar link to your main entity
|
||||
// await page.getByRole('link', { name: 'Companies' }).click();
|
||||
// await expect(page.getByRole('heading', { name: 'Companies' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('can create a new item', async ({ page }) => {
|
||||
// Adapt: navigate to creation form
|
||||
// await page.goto('/companies/new');
|
||||
// await page.getByLabel('Name').fill('Test Company');
|
||||
// await page.getByRole('button', { name: /erstellen|create|save/i }).click();
|
||||
// await expect(page.locator('text=/erfolgreich|created|success/i')).toBeVisible();
|
||||
});
|
||||
|
||||
test('can edit an existing item', async ({ page }) => {
|
||||
// Adapt: navigate to edit form
|
||||
// await page.goto('/companies');
|
||||
// await page.getByRole('row').first().getByRole('link', { name: /edit|bearbeiten/i }).click();
|
||||
// await page.getByLabel('Name').fill('Updated Company');
|
||||
// await page.getByRole('button', { name: /speichern|save|update/i }).click();
|
||||
// await expect(page.locator('text=/aktualisiert|updated|success/i')).toBeVisible();
|
||||
});
|
||||
|
||||
test('can delete an item', async ({ page }) => {
|
||||
// Adapt: delete flow with confirmation dialog
|
||||
// await page.goto('/companies');
|
||||
// await page.getByRole('row').first().getByRole('button', { name: /löschen|delete/i }).click();
|
||||
// await page.getByRole('dialog').getByRole('button', { name: /bestätigen|confirm|delete/i }).click();
|
||||
// await expect(page.locator('text=/gelöscht|deleted|success/i')).toBeVisible();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### `e2e/navigation.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Navigation', () => {
|
||||
test('sidebar navigation works', async ({ page }) => {
|
||||
await page.goto('/dashboard');
|
||||
// Adapt: check your sidebar links exist
|
||||
const sidebar = page.locator('[data-sidebar]');
|
||||
await expect(sidebar).toBeVisible();
|
||||
});
|
||||
|
||||
test('breadcrumbs display correctly', async ({ page }) => {
|
||||
await page.goto('/dashboard');
|
||||
// Adapt: verify breadcrumb trail
|
||||
// await expect(page.locator('nav[aria-label="breadcrumb"]')).toBeVisible();
|
||||
});
|
||||
|
||||
test('mobile menu toggle works', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 375, height: 667 });
|
||||
await page.goto('/dashboard');
|
||||
// Adapt: check mobile menu behavior
|
||||
// await page.getByRole('button', { name: /menu/i }).click();
|
||||
// await expect(page.locator('[data-sidebar]')).toBeVisible();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### `e2e/accessibility.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test';
|
||||
import AxeBuilder from '@axe-core/playwright';
|
||||
|
||||
const pages = [
|
||||
{ name: 'Dashboard', path: '/dashboard' },
|
||||
// Add all pages to scan:
|
||||
// { name: 'Companies', path: '/companies' },
|
||||
// { name: 'New Company', path: '/companies/new' },
|
||||
];
|
||||
|
||||
test.describe('Accessibility', () => {
|
||||
for (const { name, path } of pages) {
|
||||
test(`${name} has no accessibility violations`, async ({ page }) => {
|
||||
await page.goto(path);
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
const results = await new AxeBuilder({ page }).analyze();
|
||||
|
||||
// Log violations for debugging
|
||||
if (results.violations.length > 0) {
|
||||
console.log(`Accessibility violations on ${name}:`);
|
||||
results.violations.forEach((v) => {
|
||||
console.log(` [${v.impact}] ${v.id}: ${v.description}`);
|
||||
v.nodes.forEach((n) => console.log(` ${n.html}`));
|
||||
});
|
||||
}
|
||||
|
||||
expect(results.violations).toEqual([]);
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Step 7: Add `package.json` scripts
|
||||
|
||||
Add to `<FRONTEND_DIR>/package.json` scripts section:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"e2e": "playwright test",
|
||||
"e2e:ui": "playwright test --ui",
|
||||
"e2e:headed": "playwright test --headed",
|
||||
"e2e:report": "playwright show-report"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 8: Update `.gitignore`
|
||||
|
||||
Append to `<FRONTEND_DIR>/.gitignore`:
|
||||
|
||||
```
|
||||
# Playwright
|
||||
.auth/
|
||||
playwright-report/
|
||||
test-results/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Lessons Learned & Gotchas
|
||||
|
||||
### 1. BCrypt hash MUST match the password
|
||||
|
||||
The #1 cause of broken E2E suites. If `seed.sql` has a hash that doesn't match the password in `auth.setup.ts`, all authenticated tests fail silently (login form rejects credentials).
|
||||
|
||||
**Verify with:**
|
||||
```bash
|
||||
echo -n "test123" | htpasswd -bnBC 10 "" - | cut -d: -f2
|
||||
```
|
||||
|
||||
### 2. waitForURL — use globs, not broad regex
|
||||
|
||||
```typescript
|
||||
// ❌ BAD — matches too broadly, causes flaky tests
|
||||
await page.waitForURL(/dashboard|\//)
|
||||
|
||||
// ✅ GOOD — specific glob pattern
|
||||
await page.waitForURL('**/dashboard')
|
||||
```
|
||||
|
||||
### 3. shadcn/ui selectors
|
||||
|
||||
Don't use generic CSS class selectors for shadcn components. They use dynamic Tailwind classes.
|
||||
|
||||
```typescript
|
||||
// ❌ BAD
|
||||
page.locator('.sidebar')
|
||||
|
||||
// ✅ GOOD
|
||||
page.locator('[data-sidebar]') // sidebar
|
||||
page.locator('[role="dialog"]') // modals/dialogs
|
||||
page.getByRole('button', { name: 'Save' }) // buttons
|
||||
page.getByLabel('Email') // form fields
|
||||
```
|
||||
|
||||
### 4. Console error filtering
|
||||
|
||||
Tests fail on unexpected console errors. Filter known/expected ones:
|
||||
|
||||
```typescript
|
||||
const errors: string[] = [];
|
||||
page.on('console', msg => {
|
||||
if (msg.type() === 'error' && !msg.text().includes('expected-error-pattern')) {
|
||||
errors.push(msg.text());
|
||||
}
|
||||
});
|
||||
// ... do test actions ...
|
||||
expect(errors).toEqual([]);
|
||||
```
|
||||
|
||||
### 5. Auth state caching = 10x speed
|
||||
|
||||
The `setup` project runs ONCE per test run. All `authenticated` tests reuse the saved `.auth/admin.json` session cookie. Never log in per-test unless testing auth specifically.
|
||||
|
||||
### 6. Accessibility scanning pattern
|
||||
|
||||
```typescript
|
||||
import AxeBuilder from '@axe-core/playwright';
|
||||
|
||||
const results = await new AxeBuilder({ page }).analyze();
|
||||
expect(results.violations).toEqual([]);
|
||||
```
|
||||
|
||||
Run on every page. Add new pages to the `pages` array in `accessibility.spec.ts`.
|
||||
|
||||
### 7. Visual regression (optional, add when ready)
|
||||
|
||||
```typescript
|
||||
await expect(page).toHaveScreenshot('page-name.png', { maxDiffPixels: 100 });
|
||||
```
|
||||
|
||||
First run creates baseline screenshots. Subsequent runs compare. Commit screenshots to git.
|
||||
|
||||
### 8. Docker test environment
|
||||
|
||||
Backend should have a `test` Spring profile that:
|
||||
- Uses the test PostgreSQL (port 5433 to avoid conflicts)
|
||||
- Runs Flyway migrations + seed on startup
|
||||
- Has shorter JWT expiry for faster test cycles
|
||||
- Disables rate limiting and email sending
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Problem | Cause | Fix |
|
||||
|---------|-------|-----|
|
||||
| All auth tests fail | Wrong BCrypt hash in seed.sql | Regenerate hash for your password |
|
||||
| `waitForURL` times out | URL doesn't match pattern | Use `page.url()` to print actual URL, adjust pattern |
|
||||
| Tests pass locally, fail in CI | Missing `npx playwright install` | Add to CI setup step |
|
||||
| `storageState` file not found | `.auth/` directory doesn't exist | Create `.auth/` dir or let setup create it |
|
||||
| Flaky navigation tests | Page not fully loaded | Add `await page.waitForLoadState('networkidle')` |
|
||||
| axe violations on shadcn | Missing aria labels | Add `aria-label` to interactive elements |
|
||||
@@ -0,0 +1,121 @@
|
||||
---
|
||||
name: sprint-report
|
||||
description: Generate sprint status report from Jira data.
|
||||
---
|
||||
|
||||
# Skill: sprint-report
|
||||
|
||||
Generate sprint status report from Jira data.
|
||||
|
||||
## Invoked by
|
||||
|
||||
🎫 JiraOps mode (or 🪃 Orchestrator)
|
||||
|
||||
## Required Inputs
|
||||
|
||||
| Input | Source | Example |
|
||||
|-------|--------|---------|
|
||||
| `PROJECT_KEY` | Jira project key | `PROJECT` |
|
||||
| `SPRINT_ID` | Sprint ID (optional — auto-detected) | `1234` |
|
||||
|
||||
## Output
|
||||
|
||||
Markdown report: `docs/sprint-reports/sprint-<sprint_name>-<date>.md`
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Get active sprint
|
||||
|
||||
```python
|
||||
boards = get_agile_boards(project_key=PROJECT_KEY)
|
||||
sprints = get_sprints_from_board(board_id=boards[0]["id"], states="active")
|
||||
sprint = sprints[0]
|
||||
```
|
||||
|
||||
### 2. Get sprint tickets
|
||||
|
||||
```python
|
||||
tickets = get_tickets_from_sprint(sprint_id=sprint["id"])
|
||||
```
|
||||
|
||||
### 3. Categorize by status
|
||||
|
||||
| Category | Statuses |
|
||||
|----------|----------|
|
||||
| To Do | `Open`, `Backlog`, `To Do` |
|
||||
| In Progress | `In Progress`, `In Development` |
|
||||
| In Review | `In Review`, `Code Review` |
|
||||
| Done | `Done`, `Accepted`, `Closed` |
|
||||
|
||||
### 4. Calculate metrics
|
||||
|
||||
```python
|
||||
total = len(tickets)
|
||||
done = len([t for t in tickets if t["status"] in DONE_STATUSES])
|
||||
completion_pct = round(done / total * 100) if total > 0 else 0
|
||||
```
|
||||
|
||||
### 5. Generate report
|
||||
|
||||
```markdown
|
||||
# Sprint Report: <sprint_name>
|
||||
|
||||
**Date:** <today>
|
||||
**Sprint:** <sprint_name>
|
||||
**Period:** <start> — <end>
|
||||
**Project:** <PROJECT_KEY>
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total tickets | <total> |
|
||||
| Done | <done> (<pct>%) |
|
||||
| In Progress | <wip> |
|
||||
| Open | <todo> |
|
||||
|
||||
## Progress
|
||||
|
||||
```
|
||||
[████████████░░░░░░░░] 60% (<done>/<total>)
|
||||
```
|
||||
|
||||
## By Status
|
||||
|
||||
### ✅ Done (<done>)
|
||||
|
||||
| Ticket | Type | Summary | Assignee |
|
||||
|--------|------|---------|----------|
|
||||
| <key> | Story | <summary> | <name> |
|
||||
|
||||
### 🔄 In Progress (<wip>)
|
||||
|
||||
| Ticket | Type | Summary | Assignee |
|
||||
|--------|------|---------|----------|
|
||||
|
||||
### ⏳ Open (<todo>)
|
||||
|
||||
| Ticket | Type | Summary | Assignee |
|
||||
|--------|------|---------|----------|
|
||||
|
||||
## By Assignee
|
||||
|
||||
| Assignee | Total | Done | In Progress | Open |
|
||||
|----------|-------|------|-------------|------|
|
||||
|
||||
## Blockers / Risks
|
||||
|
||||
| Ticket | Description | Since | Impact |
|
||||
|--------|-------------|-------|--------|
|
||||
```
|
||||
|
||||
### 6. Store in BigMind
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"Sprint report for {sprint_name}: {done}/{total} done ({pct}%)"
|
||||
)
|
||||
```
|
||||
@@ -0,0 +1,107 @@
|
||||
---
|
||||
name: switch-worktree
|
||||
description: Switch VS Code to an existing git worktree. Lists worktrees, replaces the current window (code -r), announces BigMind focus, and restores session context. Use when asked to switch worktree, open another ticket, change to a different branch/ticket, or activate a worktree.
|
||||
---
|
||||
|
||||
# Switch Worktree
|
||||
|
||||
## When to use
|
||||
|
||||
- User wants to switch to a different ticket worktree
|
||||
- User says "switch to PROJECT-XXX", "open worktree for ...", "go to ticket ..."
|
||||
- User wants to see available worktrees and pick one
|
||||
|
||||
## When NOT to use
|
||||
|
||||
- User wants to **create** a new worktree → use `create-worktree` skill instead
|
||||
- User wants to delete/remove a worktree
|
||||
- User just wants to see git history (no switch needed)
|
||||
|
||||
## Inputs
|
||||
|
||||
| Input | Required | Source | Example |
|
||||
|-------|----------|--------|---------|
|
||||
| `TICKET_KEY` | Optional | User or interactive selection | `PROJECT-123` |
|
||||
|
||||
If no ticket key is provided, list all worktrees and let the user pick.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. List available worktrees
|
||||
|
||||
```bash
|
||||
git -C <your-repo-path> worktree list
|
||||
```
|
||||
|
||||
Parse output to show available worktrees with their branches.
|
||||
|
||||
### 2. Match or select target
|
||||
|
||||
If `TICKET_KEY` provided:
|
||||
- Look for a worktree path containing the ticket key
|
||||
- If not found, report error and show available worktrees
|
||||
|
||||
If no `TICKET_KEY`:
|
||||
- Present the list and ask the user to pick
|
||||
|
||||
### 3. Show worktree status before switching
|
||||
|
||||
```bash
|
||||
cd <target_worktree_path>
|
||||
git branch --show-current
|
||||
git status --short
|
||||
git log --oneline -3
|
||||
```
|
||||
|
||||
Report: branch name, uncommitted changes (if any), last 3 commits.
|
||||
|
||||
### 4. Switch VS Code window
|
||||
|
||||
```bash
|
||||
code -r <target_worktree_path>
|
||||
```
|
||||
|
||||
This replaces the current VS Code window with the target worktree.
|
||||
|
||||
**Important:** After this command, the current Roo session ends because the workspace changes. The next Roo session will start in the new worktree.
|
||||
|
||||
### 5. Update BigMind focus
|
||||
|
||||
Before executing `code -r`, announce the switch:
|
||||
|
||||
```python
|
||||
memory_store_fact(
|
||||
category="codebase",
|
||||
fact=f"Switched worktree to {TICKET_KEY} at {target_path}, branch {branch_name}"
|
||||
)
|
||||
memory_announce_focus(
|
||||
session_id=SESSION_ID,
|
||||
description=f"Switching to {TICKET_KEY} worktree",
|
||||
files=[target_path],
|
||||
ide_hint="Roo"
|
||||
)
|
||||
```
|
||||
|
||||
### 6. Context recovery hint
|
||||
|
||||
After switching, the next session should:
|
||||
1. Run `memory_search_facts("<TICKET_KEY>")` to find prior work
|
||||
2. Run `memory_search_chunks("<TICKET_KEY>")` for detailed context
|
||||
3. Check `docs/<MODULE>/<TICKET_KEY>/` for existing documentation
|
||||
|
||||
This happens automatically via the BigMind session ritual.
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| No worktrees found | Only the main repo exists — suggest `create-worktree` |
|
||||
| Ticket worktree not found | Show available worktrees, ask user to pick or create |
|
||||
| Uncommitted changes in current worktree | Warn user before switching — suggest commit or stash |
|
||||
| `code` CLI not available | Run `Shell Command: Install 'code' command in PATH` from VS Code |
|
||||
|
||||
## Notes
|
||||
|
||||
- `code -r` replaces the current window — the Roo session will end after this
|
||||
- The new window starts fresh — BigMind provides continuity across the switch
|
||||
- If the user has uncommitted changes, always warn before switching
|
||||
@@ -0,0 +1,140 @@
|
||||
---
|
||||
name: visual-verify
|
||||
description: Verify a frontend page visually using Playwright. Takes screenshots (dark/light mode), extracts visible text, checks element positioning and responsive layout. Use when asked to verify a page, check how it looks, take a screenshot, or after building a new UI component.
|
||||
---
|
||||
|
||||
# Visual Verify
|
||||
|
||||
## When to use
|
||||
|
||||
- After creating or modifying a frontend page/component
|
||||
- When asked "how does it look", "verify the page", "take a screenshot"
|
||||
- To check dark/light mode rendering
|
||||
- To verify text content (i18n) renders correctly
|
||||
- To check centering, alignment, and responsive layout
|
||||
|
||||
## When NOT to use
|
||||
|
||||
- For unit tests or API testing (use test runners instead)
|
||||
- For full E2E test suites (use Playwright test framework directly)
|
||||
- When the dev server is not running
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Playwright installed in the frontend project: `pnpm add -D playwright`
|
||||
- Chromium browser installed: `npx playwright install chromium`
|
||||
- Dev server running (usually `pnpm dev` on localhost:3000)
|
||||
|
||||
## Inputs
|
||||
|
||||
| Input | Required | Default | Example |
|
||||
|-------|----------|---------|---------|
|
||||
| URL | Yes | — | `http://localhost:3000/login` |
|
||||
| Checks | No | all | `text`, `screenshot`, `position`, `responsive`, `interaction` |
|
||||
| Theme | No | both | `dark`, `light`, `both` |
|
||||
| Viewport | No | 1280x720 | `375x667` (mobile) |
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Launch browser and navigate
|
||||
|
||||
```javascript
|
||||
const { chromium } = require('playwright');
|
||||
const browser = await chromium.launch();
|
||||
const page = await browser.newPage({ viewport: { width: 1280, height: 720 } });
|
||||
await page.goto(URL);
|
||||
await page.waitForTimeout(2000); // Wait for hydration
|
||||
```
|
||||
|
||||
### 2. Extract visible text
|
||||
|
||||
```javascript
|
||||
const text = await page.locator('body').innerText();
|
||||
// Report: verify all expected text is present (i18n keys rendered)
|
||||
```
|
||||
|
||||
### 3. Check element positioning
|
||||
|
||||
```javascript
|
||||
// Verify centering of a key element
|
||||
const box = await page.locator('SELECTOR').boundingBox();
|
||||
const vp = page.viewportSize();
|
||||
const centerX = Math.round(box.x + box.width / 2);
|
||||
const centerY = Math.round(box.y + box.height / 2);
|
||||
// Report: distance from viewport center
|
||||
```
|
||||
|
||||
### 4. Take screenshots
|
||||
|
||||
```javascript
|
||||
// Dark mode (default)
|
||||
await page.screenshot({ path: '/tmp/verify-dark.png', fullPage: true });
|
||||
|
||||
// Light mode
|
||||
await page.evaluate(() => {
|
||||
document.documentElement.classList.remove('dark');
|
||||
document.documentElement.style.colorScheme = 'light';
|
||||
});
|
||||
await page.waitForTimeout(500);
|
||||
await page.screenshot({ path: '/tmp/verify-light.png', fullPage: true });
|
||||
```
|
||||
|
||||
### 5. Responsive check (optional)
|
||||
|
||||
```javascript
|
||||
// Mobile viewport
|
||||
await page.setViewportSize({ width: 375, height: 667 });
|
||||
await page.waitForTimeout(500);
|
||||
await page.screenshot({ path: '/tmp/verify-mobile.png', fullPage: true });
|
||||
|
||||
// Tablet
|
||||
await page.setViewportSize({ width: 768, height: 1024 });
|
||||
await page.waitForTimeout(500);
|
||||
await page.screenshot({ path: '/tmp/verify-tablet.png', fullPage: true });
|
||||
```
|
||||
|
||||
### 6. Interaction check (optional)
|
||||
|
||||
```javascript
|
||||
// Click a button and verify outcome
|
||||
await page.locator('button[type="submit"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
const errorText = await page.locator('body').innerText();
|
||||
// Report: what changed after interaction
|
||||
```
|
||||
|
||||
### 7. Report findings
|
||||
|
||||
Produce a summary:
|
||||
|
||||
```
|
||||
=== Visual Verification: <URL> ===
|
||||
✅ Text renders: <key phrases found>
|
||||
✅ Horizontally centered (X: 640/640)
|
||||
⚠️ Vertically offset (Y: 414 vs 360) — acceptable, content above pushes down
|
||||
✅ Dark mode: screenshot saved
|
||||
✅ Light mode: screenshot saved
|
||||
⚠️ Mobile: form overflows at 375px width
|
||||
```
|
||||
|
||||
### 8. Clean up
|
||||
|
||||
```javascript
|
||||
await browser.close();
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
- Console report with pass/fail per check
|
||||
- Screenshots at `/tmp/verify-*.png` (dark, light, mobile, tablet)
|
||||
- Actionable findings if issues detected
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Resolution |
|
||||
|-------|-----------|
|
||||
| Page blank / no text | Increase `waitForTimeout` — hydration may be slow |
|
||||
| Cannot find module 'playwright' | Run `pnpm add -D playwright` in the frontend project |
|
||||
| Browser not found | Run `npx playwright install chromium` |
|
||||
| Connection refused | Ensure dev server is running on the expected port |
|
||||
| Dark mode not toggling | Check if theme uses `class="dark"` on `<html>` or `data-theme` attribute |
|
||||
Reference in New Issue
Block a user