add more opencode goodness
This commit is contained in:
parent
143b45999a
commit
8ccd91a459
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
**/node_modules/**
|
||||||
12
flake.lock
generated
12
flake.lock
generated
@ -98,11 +98,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-unstable": {
|
"nixpkgs-unstable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1760878510,
|
"lastModified": 1761373498,
|
||||||
"narHash": "sha256-K5Osef2qexezUfs0alLvZ7nQFTGS9DL2oTVsIXsqLgs=",
|
"narHash": "sha256-Q/uhWNvd7V7k1H1ZPMy/vkx3F8C13ZcdrKjO7Jv7v0c=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "5e2a59a5b1a82f89f2c7e598302a9cacebb72a67",
|
"rev": "6a08e6bb4e46ff7fcbb53d409b253f6bad8a28ce",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -114,11 +114,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1761016216,
|
"lastModified": 1761468971,
|
||||||
"narHash": "sha256-G/iC4t/9j/52i/nm+0/4ybBmAF4hzR8CNHC75qEhjHo=",
|
"narHash": "sha256-vY2OLVg5ZTobdroQKQQSipSIkHlxOTrIF1fsMzPh8w8=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "481cf557888e05d3128a76f14c76397b7d7cc869",
|
"rev": "78e34d1667d32d8a0ffc3eba4591ff256e80576e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@ -345,6 +345,7 @@
|
|||||||
"waybar".source = config.lib.file.mkOutOfStoreSymlink "/home/nate/nixos/nate-work/linked-dotfiles/waybar";
|
"waybar".source = config.lib.file.mkOutOfStoreSymlink "/home/nate/nixos/nate-work/linked-dotfiles/waybar";
|
||||||
# Shared
|
# Shared
|
||||||
"helix".source = config.lib.file.mkOutOfStoreSymlink "/home/nate/nixos/shared/linked-dotfiles/helix";
|
"helix".source = config.lib.file.mkOutOfStoreSymlink "/home/nate/nixos/shared/linked-dotfiles/helix";
|
||||||
|
"opencode".source = config.lib.file.mkOutOfStoreSymlink "/home/nate/nixos/shared/linked-dotfiles/opencode";
|
||||||
|
|
||||||
# Theme files
|
# Theme files
|
||||||
"gtk-4.0/assets".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/assets";
|
"gtk-4.0/assets".source = "${config.gtk.theme.package}/share/themes/${config.gtk.theme.name}/gtk-4.0/assets";
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
# Catppuccin Macchiato Minimal - Judicious Syntax Highlighting
|
# Catppuccin Macchiato Minimal - Judicious Syntax Highlighting
|
||||||
# Uses only 4 colors for syntax: lavender (keywords), green (strings), peach (numbers), mauve (comments)
|
# Uses only 4 colors for syntax
|
||||||
# Functions and variables remain plain text for reduced visual noise
|
# Functions and variables remain plain text for reduced visual noise
|
||||||
|
|
||||||
"ui.background" = { bg = "base" }
|
"ui.background" = { bg = "base" }
|
||||||
@ -98,7 +98,7 @@
|
|||||||
"variable.parameter" = "text"
|
"variable.parameter" = "text"
|
||||||
"variable.other.member" = "text"
|
"variable.other.member" = "text"
|
||||||
|
|
||||||
"type" = "lavender" # Types are slightly highlighted
|
"type" = { fg = "lavender", modifiers = ["italic"]} # Types are slightly highlighted
|
||||||
"type.builtin" = "lavender"
|
"type.builtin" = "lavender"
|
||||||
|
|
||||||
"constructor" = "text" # Constructors are plain text
|
"constructor" = "text" # Constructors are plain text
|
||||||
|
|||||||
59
shared/linked-dotfiles/opencode/agent/pr-reviewer.md
Normal file
59
shared/linked-dotfiles/opencode/agent/pr-reviewer.md
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
description: Reviews pull requests to verify work is ready for team review - runs comprehensive validation checks and provides approval or feedback
|
||||||
|
mode: subagent
|
||||||
|
model: anthropic/claude-sonnet-4-5
|
||||||
|
temperature: 0.1
|
||||||
|
tools:
|
||||||
|
write: false
|
||||||
|
edit: false
|
||||||
|
bash: true
|
||||||
|
permission:
|
||||||
|
bash:
|
||||||
|
"make *": allow
|
||||||
|
"gh pr *": allow
|
||||||
|
"rg *": allow
|
||||||
|
"test *": allow
|
||||||
|
"grep *": allow
|
||||||
|
"*": ask
|
||||||
|
---
|
||||||
|
|
||||||
|
You are a pull request reviewer. Your job is to verify that work is ready for human code review.
|
||||||
|
|
||||||
|
## Your Process
|
||||||
|
|
||||||
|
1. **Verify the work is ready for review**
|
||||||
|
- Check that the PR exists and is accessible
|
||||||
|
- Confirm changes are committed and pushed
|
||||||
|
- Ensure PR description is complete
|
||||||
|
|
||||||
|
2. **Use the go-pr-review skill**
|
||||||
|
- Invoke the `go-pr-review` skill to perform comprehensive validation
|
||||||
|
- The skill will check repository compatibility, run tests, validate code quality
|
||||||
|
- Trust the skill's validation results
|
||||||
|
|
||||||
|
3. **Provide your conclusion**
|
||||||
|
- If go-pr-review finds critical issues: Report "Needs work" with specific issues to fix
|
||||||
|
- If go-pr-review approves or has only minor suggestions: Report "Ready for review"
|
||||||
|
- Always include a brief summary of what was validated
|
||||||
|
|
||||||
|
## Important Guidelines
|
||||||
|
|
||||||
|
- Be thorough but efficient - rely on the go-pr-review skill for detailed checks
|
||||||
|
- Never modify code - you're reviewing only
|
||||||
|
- Provide actionable feedback if issues are found
|
||||||
|
- Be clear about whether work can proceed to human review or needs fixes first
|
||||||
|
|
||||||
|
## Response Format
|
||||||
|
|
||||||
|
Conclude your review with one of:
|
||||||
|
|
||||||
|
**✅ Ready for review**
|
||||||
|
- All validations passed
|
||||||
|
- Code quality meets standards
|
||||||
|
- Tests are passing
|
||||||
|
- Ready for human code review
|
||||||
|
|
||||||
|
**❌ Needs work**
|
||||||
|
- [List critical issues that must be fixed]
|
||||||
|
- [Provide specific guidance on what to address]
|
||||||
|
- Re-review after fixes are applied
|
||||||
17
shared/linked-dotfiles/opencode/bun.lock
Normal file
17
shared/linked-dotfiles/opencode/bun.lock
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"@opencode-ai/plugin": "0.15.2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@opencode-ai/plugin": ["@opencode-ai/plugin@0.15.2", "", { "dependencies": { "@opencode-ai/sdk": "0.15.2", "zod": "4.1.8" } }, "sha512-cCttqxDou+OPQzjc20cB4xxuSMMSowZMpvlioIgyzyhp8B7Gc5hh1kY796nly7vjaQfUcLg8pOmRJSLrbxj98g=="],
|
||||||
|
|
||||||
|
"@opencode-ai/sdk": ["@opencode-ai/sdk@0.15.2", "", {}, "sha512-m2aU0TiZj7/o1JvYmoqF7ichrKZcWi4UTx3WYlDXpRJvfZX0gnLKLJAlTKfHkisytGlrlgmST2kt/YQrAjc0wQ=="],
|
||||||
|
|
||||||
|
"zod": ["zod@4.1.8", "", {}, "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ=="],
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,11 +1,25 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://opencode.ai/config.json",
|
"$schema": "https://opencode.ai/config.json",
|
||||||
// Theme configuration
|
|
||||||
"theme": "catppuccin",
|
"theme": "catppuccin",
|
||||||
"model": "anthropic/claude-sonnet-4-5",
|
"model": "anthropic/claude-sonnet-4-5",
|
||||||
"autoupdate": false,
|
"autoupdate": false,
|
||||||
"plugin": [
|
"plugin": [], // local plugins do not need to be added here
|
||||||
// "skills"
|
"agent": {
|
||||||
// "swaync-notifications"
|
// "pr-reviewer": {
|
||||||
]
|
// "description": "Reviews pull requests to verify work is ready for team review",
|
||||||
|
// "mode": "subagent",
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
"mcp": {
|
||||||
|
"atlassian-mcp-server": {
|
||||||
|
"type": "local",
|
||||||
|
"command": [
|
||||||
|
"npx",
|
||||||
|
"-y",
|
||||||
|
"mcp-remote",
|
||||||
|
"https://mcp.atlassian.com/v1/sse"
|
||||||
|
],
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
6
shared/linked-dotfiles/opencode/package.json
Normal file
6
shared/linked-dotfiles/opencode/package.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@opencode-ai/plugin": "0.15.2",
|
||||||
|
"gray-matter": "^4.0.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
340
shared/linked-dotfiles/opencode/skills/do-job/SKILL.md
Normal file
340
shared/linked-dotfiles/opencode/skills/do-job/SKILL.md
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
---
|
||||||
|
name: do-job
|
||||||
|
description: Use when starting work on Jira tickets - fetches To Do tickets, creates git worktrees with proper PI-XXXXX naming, implements features using TDD (test-first), commits with ticket references, creates draft PRs, validates work with PR review, and transitions tickets through workflow to Testing
|
||||||
|
---
|
||||||
|
|
||||||
|
# Do Job
|
||||||
|
|
||||||
|
Complete developer workflow from ticket selection to validated draft PR using TDD and git worktrees.
|
||||||
|
|
||||||
|
## When to Use This Skill
|
||||||
|
|
||||||
|
Use when:
|
||||||
|
- Starting work on a new Jira ticket
|
||||||
|
- Need to set up development environment for ticket work
|
||||||
|
- Implementing features using test-driven development
|
||||||
|
- Creating PRs for Jira-tracked work
|
||||||
|
|
||||||
|
## Workflow Checklist
|
||||||
|
|
||||||
|
Copy and track progress:
|
||||||
|
|
||||||
|
```
|
||||||
|
Ticket Workflow Progress:
|
||||||
|
- [ ] Step 1: Fetch and select To Do ticket
|
||||||
|
- [ ] Step 2: Move ticket to In Progress
|
||||||
|
- [ ] Step 3: Set up git worktree
|
||||||
|
- [ ] Step 4: Write failing tests (TDD)
|
||||||
|
- [ ] Step 5: Implement feature/fix
|
||||||
|
- [ ] Step 6: Verify tests pass
|
||||||
|
- [ ] Step 7: Commit with PI-XXXXX reference
|
||||||
|
- [ ] Step 8: Push branch
|
||||||
|
- [ ] Step 9: Create draft PR
|
||||||
|
- [ ] Step 10: Review work with PR reviewer
|
||||||
|
- [ ] Step 11: Link PR to ticket
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Verify environment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check Jira access
|
||||||
|
atlassian-mcp-server_getAccessibleAtlassianResources
|
||||||
|
|
||||||
|
# Check GitHub CLI
|
||||||
|
gh auth status
|
||||||
|
|
||||||
|
# Verify in repos root directory
|
||||||
|
ls -d */
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 1: Fetch and Select Ticket
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get To Do tickets
|
||||||
|
atlassian-mcp-server_searchJiraIssuesUsingJql \
|
||||||
|
cloudId="<cloud-id>" \
|
||||||
|
jql="assignee = currentUser() AND status = 'To Do' ORDER BY priority DESC, updated DESC" \
|
||||||
|
fields='["summary", "description", "status", "priority"]'
|
||||||
|
```
|
||||||
|
|
||||||
|
Review tickets and select one based on priority and description.
|
||||||
|
|
||||||
|
## Step 2: Move Ticket to In Progress
|
||||||
|
|
||||||
|
```bash
|
||||||
|
atlassian-mcp-server_transitionJiraIssue \
|
||||||
|
cloudId="<cloud-id>" \
|
||||||
|
issueIdOrKey="PI-XXXXX" \
|
||||||
|
transition='{"id": "41"}' # In Progress transition ID
|
||||||
|
```
|
||||||
|
|
||||||
|
Add comment explaining work start:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
atlassian-mcp-server_addCommentToJiraIssue \
|
||||||
|
cloudId="<cloud-id>" \
|
||||||
|
issueIdOrKey="PI-XXXXX" \
|
||||||
|
commentBody="Starting work on this ticket using TDD approach"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 3: Set Up Git Worktree
|
||||||
|
|
||||||
|
**CRITICAL: All branches and commits MUST include PI-XXXXX ticket number**
|
||||||
|
|
||||||
|
### Identify Repository
|
||||||
|
|
||||||
|
From repos root directory, determine which repo based on ticket description and summary.
|
||||||
|
|
||||||
|
### Create Worktree
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Navigate to develop branch of target repo
|
||||||
|
cd <repo-name>/develop
|
||||||
|
|
||||||
|
# Pull latest changes
|
||||||
|
git pull
|
||||||
|
|
||||||
|
# Create worktree with proper naming
|
||||||
|
# Pattern: ../<descriptive-name> with branch nate/PI-XXXXX_descriptive-name
|
||||||
|
git worktree add ../<descriptive-name> -b nate/PI-XXXXX_descriptive-name
|
||||||
|
|
||||||
|
# Navigate to new worktree
|
||||||
|
cd ../<descriptive-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Naming conventions:**
|
||||||
|
- Directory: Short descriptive name (e.g., `rename-folder-fix`)
|
||||||
|
- Branch: `nate/PI-XXXXX_descriptive-name` (e.g., `nate/PI-70535_rename-folder-fix`)
|
||||||
|
- **MUST include PI-XXXXX** in branch name
|
||||||
|
|
||||||
|
## Step 4: Build Implementation Plan
|
||||||
|
|
||||||
|
Analyze ticket requirements and create TDD plan:
|
||||||
|
|
||||||
|
1. **Understand requirements** from ticket description
|
||||||
|
2. **Identify affected code** areas
|
||||||
|
3. **Plan test cases** covering:
|
||||||
|
- Happy path
|
||||||
|
- Edge cases
|
||||||
|
- Error conditions
|
||||||
|
4. **Plan implementation** approach
|
||||||
|
|
||||||
|
## Step 5: TDD Implementation
|
||||||
|
|
||||||
|
### Write Failing Tests First
|
||||||
|
|
||||||
|
**CRITICAL: Write tests BEFORE implementation**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Identify test framework from repo
|
||||||
|
ls *_test.* test/ tests/ __tests__/
|
||||||
|
|
||||||
|
# Create or modify test file
|
||||||
|
# Write test that validates missing functionality
|
||||||
|
```
|
||||||
|
|
||||||
|
Test should:
|
||||||
|
- Clearly describe expected behavior
|
||||||
|
- Cover the specific bug/feature from ticket
|
||||||
|
- **Fail initially** (validates test is working)
|
||||||
|
|
||||||
|
### Run Failing Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Verify test fails (proves test is valid)
|
||||||
|
<run-test-command>
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: Test fails with clear error showing missing functionality.
|
||||||
|
|
||||||
|
### Implement Feature/Fix
|
||||||
|
|
||||||
|
Write minimal code to make test pass:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Implement the feature or fix
|
||||||
|
# Focus on making test pass, not perfection
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run Tests Again
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Verify test now passes
|
||||||
|
<run-test-command>
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: All tests pass.
|
||||||
|
|
||||||
|
### Refactor (if needed)
|
||||||
|
|
||||||
|
Clean up implementation while keeping tests passing:
|
||||||
|
|
||||||
|
- Improve code clarity
|
||||||
|
- Remove duplication
|
||||||
|
- Follow project conventions
|
||||||
|
- **Keep tests passing**
|
||||||
|
|
||||||
|
## Step 6: Verify Complete Solution
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run full test suite
|
||||||
|
<full-test-command>
|
||||||
|
|
||||||
|
# Run linting (if available)
|
||||||
|
<lint-command>
|
||||||
|
|
||||||
|
# Run type checking (if available)
|
||||||
|
<typecheck-command>
|
||||||
|
```
|
||||||
|
|
||||||
|
All checks must pass before proceeding.
|
||||||
|
|
||||||
|
## Step 7: Commit Changes
|
||||||
|
|
||||||
|
**CRITICAL: Commit message MUST include PI-XXXXX**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stage changes
|
||||||
|
git add .
|
||||||
|
|
||||||
|
# Commit with ticket reference
|
||||||
|
git commit -m "PI-XXXXX: <concise description>
|
||||||
|
|
||||||
|
<detailed explanation of changes>
|
||||||
|
- What was changed
|
||||||
|
- Why it was changed
|
||||||
|
- How it addresses the ticket"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Commit message format:**
|
||||||
|
- First line: `PI-XXXXX: <summary>` (50 chars max)
|
||||||
|
- Blank line
|
||||||
|
- Detailed description explaining the why and how
|
||||||
|
- Reference ticket number (PI-XXXXX) in first line
|
||||||
|
|
||||||
|
## Step 8: Push Branch
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Push to remote
|
||||||
|
git push -u origin nate/PI-XXXXX_descriptive-name
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 9: Create Draft PR
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create draft PR with gh CLI
|
||||||
|
gh pr create \
|
||||||
|
--draft \
|
||||||
|
--title "PI-XXXXX: <descriptive title>" \
|
||||||
|
--body "$(cat <<'PRBODY'
|
||||||
|
## Summary
|
||||||
|
- Fixes issue described in PI-XXXXX
|
||||||
|
- Implements <feature/fix> using TDD approach
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
- Added tests for <functionality>
|
||||||
|
- Implemented <feature/fix>
|
||||||
|
- Verified all tests pass
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
- [x] Unit tests added and passing
|
||||||
|
- [x] Linting passes
|
||||||
|
- [x] Manual testing completed
|
||||||
|
|
||||||
|
## Jira
|
||||||
|
Related ticket: PI-XXXXX
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
Ready for review. Once approved, will move ticket to Pull Request status.
|
||||||
|
PRBODY
|
||||||
|
)"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Save PR URL** returned by command for next steps.
|
||||||
|
|
||||||
|
## Step 10: Review Work with PR Reviewer
|
||||||
|
|
||||||
|
**CRITICAL: Invoke @pr-reviewer subagent to validate work before linking to ticket**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Invoke the pr-reviewer subagent
|
||||||
|
@pr-reviewer please review the PR I just created
|
||||||
|
```
|
||||||
|
|
||||||
|
The pr-reviewer will:
|
||||||
|
- Verify the repository is compatible (Go with Makefile)
|
||||||
|
- Run all validation commands (tests, linting, type checking)
|
||||||
|
- Review code quality against project standards
|
||||||
|
- Check for security issues and best practices
|
||||||
|
- Provide verdict: Ready for review OR needs work
|
||||||
|
|
||||||
|
**If pr-reviewer finds issues:**
|
||||||
|
1. Address the critical issues identified
|
||||||
|
2. Re-run tests and validations
|
||||||
|
3. Commit fixes with `PI-XXXXX: Address PR review feedback`
|
||||||
|
4. Push updates
|
||||||
|
5. Invoke @pr-reviewer again to re-validate
|
||||||
|
|
||||||
|
**Only proceed to Step 11 when pr-reviewer gives approval.**
|
||||||
|
|
||||||
|
## Step 11: Link PR to Ticket
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Add PR link to Jira ticket
|
||||||
|
atlassian-mcp-server_addCommentToJiraIssue \
|
||||||
|
cloudId="<cloud-id>" \
|
||||||
|
issueIdOrKey="PI-XXXXX" \
|
||||||
|
commentBody="Draft PR created: <pr-url>
|
||||||
|
|
||||||
|
Implementation complete using TDD approach. Ready for code review."
|
||||||
|
```
|
||||||
|
|
||||||
|
## Post-Workflow Steps (Manual)
|
||||||
|
|
||||||
|
**After automated pr-reviewer approval and manual developer review:**
|
||||||
|
|
||||||
|
1. Remove draft status from PR
|
||||||
|
2. Request code review from team
|
||||||
|
3. Address any additional review comments
|
||||||
|
4. Get approval
|
||||||
|
5. **Manual:** Transition ticket to "Pull Request" status (transition ID: 381)
|
||||||
|
6. **Manual:** After merge, SDET moves to "Testing (Service Stack)" (transition ID: 201)
|
||||||
|
|
||||||
|
## Common Mistakes
|
||||||
|
|
||||||
|
### Branch Naming
|
||||||
|
- ❌ `fix-bug` (missing ticket number)
|
||||||
|
- ❌ `PI70535-fix` (missing hyphen, no username)
|
||||||
|
- ✅ `nate/PI-70535_rename-folder-fix`
|
||||||
|
|
||||||
|
### Commit Messages
|
||||||
|
- ❌ `fixed bug` (no ticket reference)
|
||||||
|
- ❌ `Updated code for PI-70535` (vague)
|
||||||
|
- ✅ `PI-70535: Fix shared folder rename permission check`
|
||||||
|
|
||||||
|
### TDD Order
|
||||||
|
- ❌ Write code first, then tests
|
||||||
|
- ❌ Skip tests entirely
|
||||||
|
- ✅ Write failing test → Implement → Verify passing → Refactor
|
||||||
|
|
||||||
|
### Worktree Location
|
||||||
|
- ❌ `git worktree add ./feature` (wrong location)
|
||||||
|
- ❌ `git worktree add ~/feature` (absolute path)
|
||||||
|
- ✅ `git worktree add ../feature-name` (parallel to develop)
|
||||||
|
|
||||||
|
## Jira Transition IDs
|
||||||
|
|
||||||
|
Reference for manual transitions:
|
||||||
|
|
||||||
|
- To Do: 11
|
||||||
|
- In Progress: 41
|
||||||
|
- Pull Request: 381
|
||||||
|
- Testing (Service Stack): 201
|
||||||
|
- Done: (varies by project)
|
||||||
|
|
||||||
|
## Reference Materials
|
||||||
|
|
||||||
|
See references/tdd-workflow.md for detailed TDD best practices.
|
||||||
|
See references/git-worktree.md for git worktree patterns and troubleshooting.
|
||||||
@ -0,0 +1,236 @@
|
|||||||
|
# Git Worktree Patterns
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Git worktrees allow multiple working directories from single repository, enabling parallel work on different branches without stashing or switching.
|
||||||
|
|
||||||
|
## Basic Commands
|
||||||
|
|
||||||
|
### Create Worktree
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From main/develop branch
|
||||||
|
cd <repo>/develop
|
||||||
|
git pull
|
||||||
|
|
||||||
|
# Create new worktree
|
||||||
|
git worktree add <path> -b <branch-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
### List Worktrees
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git worktree list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Remove Worktree
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From any location in repo
|
||||||
|
git worktree remove <path>
|
||||||
|
|
||||||
|
# Or manually
|
||||||
|
rm -rf <path>
|
||||||
|
git worktree prune
|
||||||
|
```
|
||||||
|
|
||||||
|
## Naming Patterns
|
||||||
|
|
||||||
|
### Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
repos/
|
||||||
|
├── document-api/
|
||||||
|
│ ├── develop/ # Main worktree
|
||||||
|
│ ├── fix-permissions/ # Feature worktree
|
||||||
|
│ └── add-tags/ # Another feature worktree
|
||||||
|
```
|
||||||
|
|
||||||
|
### Branch Naming
|
||||||
|
|
||||||
|
Format: `<username>/PI-XXXXX_<description>`
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
- `nate/PI-70535_rename-folder-fix`
|
||||||
|
- `nate/PI-70361_upload-permissions`
|
||||||
|
- `nate/PI-69924_delete-access-level`
|
||||||
|
|
||||||
|
## Workflow Patterns
|
||||||
|
|
||||||
|
### Starting Work
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Navigate to develop
|
||||||
|
cd document-api/develop
|
||||||
|
|
||||||
|
# Update develop
|
||||||
|
git pull
|
||||||
|
|
||||||
|
# Create worktree for ticket
|
||||||
|
git worktree add ../pi-70535-rename-fix -b nate/PI-70535_rename-folder-fix
|
||||||
|
|
||||||
|
# Move to worktree
|
||||||
|
cd ../pi-70535-rename-fix
|
||||||
|
```
|
||||||
|
|
||||||
|
### During Work
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Normal git operations work in worktree
|
||||||
|
git status
|
||||||
|
git add .
|
||||||
|
git commit -m "PI-70535: Fix folder rename permissions"
|
||||||
|
git push -u origin nate/PI-70535_rename-folder-fix
|
||||||
|
```
|
||||||
|
|
||||||
|
### After PR Merge
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From anywhere in repo
|
||||||
|
git worktree remove ../pi-70535-rename-fix
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
git worktree prune
|
||||||
|
git branch -d nate/PI-70535_rename-folder-fix
|
||||||
|
|
||||||
|
# Update develop
|
||||||
|
cd develop
|
||||||
|
git pull
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
### Worktree Already Exists
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Error: worktree already exists
|
||||||
|
# Solution: Remove old worktree first
|
||||||
|
git worktree remove <path>
|
||||||
|
git worktree prune
|
||||||
|
```
|
||||||
|
|
||||||
|
### Branch Already Exists
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Error: branch already exists
|
||||||
|
# Solution: Use existing branch or delete old one
|
||||||
|
git worktree add <path> <existing-branch>
|
||||||
|
|
||||||
|
# Or delete old branch
|
||||||
|
git branch -D <branch-name>
|
||||||
|
git worktree add <path> -b <branch-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Locked Worktree
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# If worktree shows as locked
|
||||||
|
git worktree unlock <path>
|
||||||
|
git worktree remove <path>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Orphaned Worktrees
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clean up references to deleted worktrees
|
||||||
|
git worktree prune
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### Keep Worktrees Short-Lived
|
||||||
|
|
||||||
|
- Create for specific ticket
|
||||||
|
- Remove after PR merged
|
||||||
|
- Don't accumulate many worktrees
|
||||||
|
|
||||||
|
### Use Descriptive Names
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ❌ Bad
|
||||||
|
git worktree add ../work -b fix
|
||||||
|
|
||||||
|
# ✅ Good
|
||||||
|
git worktree add ../rename-folder-fix -b nate/PI-70535_rename-folder-fix
|
||||||
|
```
|
||||||
|
|
||||||
|
### Always Branch from Latest
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Update base branch before creating worktree
|
||||||
|
cd develop
|
||||||
|
git pull
|
||||||
|
git worktree add ../feature -b username/PI-XXXXX_feature
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clean Up Regularly
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all worktrees
|
||||||
|
git worktree list
|
||||||
|
|
||||||
|
# Remove merged/abandoned worktrees
|
||||||
|
git worktree remove <path>
|
||||||
|
git worktree prune
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advantages Over Branch Switching
|
||||||
|
|
||||||
|
### Parallel Work
|
||||||
|
|
||||||
|
Work on multiple tickets simultaneously without switching contexts:
|
||||||
|
|
||||||
|
```
|
||||||
|
Terminal 1: cd document-api/develop # Review PRs
|
||||||
|
Terminal 2: cd document-api/feature-1 # Active development
|
||||||
|
Terminal 3: cd document-api/hotfix # Emergency fix
|
||||||
|
```
|
||||||
|
|
||||||
|
### Preserve State
|
||||||
|
|
||||||
|
Each worktree maintains its own:
|
||||||
|
- Working directory state
|
||||||
|
- Staged changes
|
||||||
|
- Build artifacts
|
||||||
|
- IDE configuration
|
||||||
|
|
||||||
|
### Avoid Stashing
|
||||||
|
|
||||||
|
No need to stash changes when switching tasks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Traditional flow (with stashing)
|
||||||
|
git stash
|
||||||
|
git checkout other-branch
|
||||||
|
# ... do work ...
|
||||||
|
git checkout original-branch
|
||||||
|
git stash pop
|
||||||
|
|
||||||
|
# Worktree flow (no stashing)
|
||||||
|
cd ../other-worktree
|
||||||
|
# ... do work ...
|
||||||
|
cd ../original-worktree
|
||||||
|
# Everything still there
|
||||||
|
```
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
### Shared References
|
||||||
|
|
||||||
|
All worktrees share:
|
||||||
|
- Git objects
|
||||||
|
- Remote configuration
|
||||||
|
- Git hooks
|
||||||
|
- Submodules
|
||||||
|
|
||||||
|
### Disk Space
|
||||||
|
|
||||||
|
Each worktree requires full working directory (but shares `.git` objects).
|
||||||
|
|
||||||
|
### Cannot Checkout Same Branch
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Error: branch already checked out
|
||||||
|
# One branch can only be checked out in one worktree at a time
|
||||||
|
git worktree add ../dup -b existing-branch # Fails if already checked out
|
||||||
|
```
|
||||||
@ -0,0 +1,173 @@
|
|||||||
|
# Test-Driven Development Workflow
|
||||||
|
|
||||||
|
## Core TDD Cycle
|
||||||
|
|
||||||
|
1. **Red** - Write failing test
|
||||||
|
2. **Green** - Make test pass
|
||||||
|
3. **Refactor** - Improve code while keeping tests passing
|
||||||
|
|
||||||
|
## Writing Effective Tests
|
||||||
|
|
||||||
|
### Test Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
# Arrange - Set up test data and conditions
|
||||||
|
# Act - Execute the code being tested
|
||||||
|
# Assert - Verify expected behavior
|
||||||
|
```
|
||||||
|
|
||||||
|
### Good Test Characteristics
|
||||||
|
|
||||||
|
- **Isolated** - Tests don't depend on each other
|
||||||
|
- **Repeatable** - Same input always produces same output
|
||||||
|
- **Fast** - Tests run quickly
|
||||||
|
- **Clear** - Test name describes what's being tested
|
||||||
|
- **Focused** - One concept per test
|
||||||
|
|
||||||
|
### Test Naming
|
||||||
|
|
||||||
|
```
|
||||||
|
test_<function>_<scenario>_<expected_result>
|
||||||
|
```
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
- `test_rename_folder_as_owner_succeeds`
|
||||||
|
- `test_rename_folder_without_permission_returns_403`
|
||||||
|
- `test_rename_folder_with_empty_name_returns_400`
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Testing Error Conditions
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Test expected errors
|
||||||
|
test('rename_folder_without_permission_returns_403', async () => {
|
||||||
|
// Arrange: Set up user without permissions
|
||||||
|
const user = createUserWithoutPermissions();
|
||||||
|
|
||||||
|
// Act: Attempt rename
|
||||||
|
const response = await renameFolder(user, folderId, newName);
|
||||||
|
|
||||||
|
// Assert: Verify 403 error
|
||||||
|
expect(response.status).toBe(403);
|
||||||
|
expect(response.error).toContain('forbidden');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing Happy Path
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
test('rename_folder_as_owner_succeeds', async () => {
|
||||||
|
// Arrange: Set up folder with owner
|
||||||
|
const owner = createOwner();
|
||||||
|
const folder = createFolder(owner);
|
||||||
|
|
||||||
|
// Act: Rename folder
|
||||||
|
const response = await renameFolder(owner, folder.id, 'NewName');
|
||||||
|
|
||||||
|
// Assert: Verify success
|
||||||
|
expect(response.status).toBe(200);
|
||||||
|
expect(response.data.name).toBe('NewName');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing Edge Cases
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
test('rename_folder_with_special_characters_sanitizes_name', async () => {
|
||||||
|
const owner = createOwner();
|
||||||
|
const folder = createFolder(owner);
|
||||||
|
|
||||||
|
const response = await renameFolder(owner, folder.id, '<script>alert(1)</script>');
|
||||||
|
|
||||||
|
expect(response.status).toBe(200);
|
||||||
|
expect(response.data.name).not.toContain('<script>');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## TDD Best Practices
|
||||||
|
|
||||||
|
### Start Simple
|
||||||
|
|
||||||
|
Write simplest test first, then add complexity:
|
||||||
|
|
||||||
|
1. Happy path with minimal data
|
||||||
|
2. Add edge cases
|
||||||
|
3. Add error conditions
|
||||||
|
4. Add integration scenarios
|
||||||
|
|
||||||
|
### One Test at a Time
|
||||||
|
|
||||||
|
- Write one test
|
||||||
|
- Watch it fail
|
||||||
|
- Make it pass
|
||||||
|
- Refactor if needed
|
||||||
|
- Repeat
|
||||||
|
|
||||||
|
### Keep Tests Independent
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// ❌ Bad - Tests depend on order
|
||||||
|
test('create_folder', () => { /* creates folder with id=1 */ });
|
||||||
|
test('rename_folder', () => { /* assumes folder id=1 exists */ });
|
||||||
|
|
||||||
|
// ✅ Good - Each test sets up own data
|
||||||
|
test('create_folder', () => {
|
||||||
|
const folder = createFolder();
|
||||||
|
expect(folder.id).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('rename_folder', () => {
|
||||||
|
const folder = createFolder(); // Own setup
|
||||||
|
const result = renameFolder(folder.id, 'NewName');
|
||||||
|
expect(result.name).toBe('NewName');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Behavior, Not Implementation
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// ❌ Bad - Tests internal implementation
|
||||||
|
test('uses_postgres_query', () => {
|
||||||
|
expect(mockDb.query).toHaveBeenCalledWith('UPDATE folders...');
|
||||||
|
});
|
||||||
|
|
||||||
|
// ✅ Good - Tests behavior
|
||||||
|
test('rename_updates_folder_name', () => {
|
||||||
|
renameFolder(folderId, 'NewName');
|
||||||
|
const folder = getFolder(folderId);
|
||||||
|
expect(folder.name).toBe('NewName');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to Refactor
|
||||||
|
|
||||||
|
Refactor when tests are green and you notice:
|
||||||
|
|
||||||
|
- Duplication
|
||||||
|
- Long functions
|
||||||
|
- Unclear variable names
|
||||||
|
- Complex conditionals
|
||||||
|
- Hard-coded values
|
||||||
|
|
||||||
|
**Always keep tests passing during refactoring**
|
||||||
|
|
||||||
|
## Handling Legacy Code
|
||||||
|
|
||||||
|
When adding tests to existing code without tests:
|
||||||
|
|
||||||
|
1. Write characterization tests (document current behavior)
|
||||||
|
2. Refactor to make code testable
|
||||||
|
3. Add tests for new functionality
|
||||||
|
4. Gradually improve test coverage
|
||||||
|
|
||||||
|
## Test Coverage
|
||||||
|
|
||||||
|
Aim for coverage of:
|
||||||
|
|
||||||
|
- All new code paths
|
||||||
|
- Bug fixes (test the bug scenario)
|
||||||
|
- Edge cases
|
||||||
|
- Error conditions
|
||||||
|
|
||||||
|
Not aiming for 100% - focus on meaningful coverage.
|
||||||
Loading…
Reference in New Issue
Block a user