safeword 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{check-J6DFVBCE.js → check-US6EQLNS.js} +3 -3
- package/dist/check-US6EQLNS.js.map +1 -0
- package/dist/chunk-2XWIUEQK.js +190 -0
- package/dist/chunk-2XWIUEQK.js.map +1 -0
- package/dist/{chunk-UQMQ64CB.js → chunk-GZRQL3SX.js} +41 -2
- package/dist/chunk-GZRQL3SX.js.map +1 -0
- package/dist/chunk-Z2SOGTNJ.js +7 -0
- package/dist/{chunk-WWQ4YRZN.js.map → chunk-Z2SOGTNJ.js.map} +1 -1
- package/dist/cli.js +6 -6
- package/dist/{diff-U4IELWRL.js → diff-72ZUEZ6A.js} +32 -29
- package/dist/diff-72ZUEZ6A.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{reset-XETOHTCK.js → reset-3ACTIYYE.js} +44 -27
- package/dist/reset-3ACTIYYE.js.map +1 -0
- package/dist/{setup-CLDCHROZ.js → setup-TSFCHD2D.js} +77 -48
- package/dist/setup-TSFCHD2D.js.map +1 -0
- package/dist/{upgrade-DOKWRK7J.js → upgrade-XDPQFSMC.js} +38 -50
- package/dist/upgrade-XDPQFSMC.js.map +1 -0
- package/package.json +1 -1
- package/templates/SAFEWORD.md +776 -0
- package/templates/commands/arch-review.md +24 -0
- package/templates/commands/lint.md +11 -0
- package/templates/commands/quality-review.md +23 -0
- package/templates/doc-templates/architecture-template.md +136 -0
- package/templates/doc-templates/design-doc-template.md +134 -0
- package/templates/doc-templates/test-definitions-feature.md +131 -0
- package/templates/doc-templates/user-stories-template.md +92 -0
- package/templates/guides/architecture-guide.md +423 -0
- package/templates/guides/code-philosophy.md +195 -0
- package/templates/guides/context-files-guide.md +457 -0
- package/templates/guides/data-architecture-guide.md +200 -0
- package/templates/guides/design-doc-guide.md +171 -0
- package/templates/guides/learning-extraction.md +552 -0
- package/templates/guides/llm-instruction-design.md +248 -0
- package/templates/guides/llm-prompting.md +102 -0
- package/templates/guides/tdd-best-practices.md +615 -0
- package/templates/guides/test-definitions-guide.md +334 -0
- package/templates/guides/testing-methodology.md +618 -0
- package/templates/guides/user-story-guide.md +256 -0
- package/templates/guides/zombie-process-cleanup.md +219 -0
- package/templates/hooks/agents-md-check.sh +27 -0
- package/templates/hooks/inject-timestamp.sh +2 -3
- package/templates/hooks/post-tool.sh +4 -0
- package/templates/hooks/pre-commit.sh +10 -0
- package/templates/lib/common.sh +26 -0
- package/templates/lib/jq-fallback.sh +20 -0
- package/templates/markdownlint.jsonc +25 -0
- package/templates/prompts/arch-review.md +43 -0
- package/templates/prompts/quality-review.md +10 -0
- package/templates/skills/safeword-quality-reviewer/SKILL.md +207 -0
- package/dist/check-J6DFVBCE.js.map +0 -1
- package/dist/chunk-24OB57NJ.js +0 -78
- package/dist/chunk-24OB57NJ.js.map +0 -1
- package/dist/chunk-DB4CMUFD.js +0 -157
- package/dist/chunk-DB4CMUFD.js.map +0 -1
- package/dist/chunk-UQMQ64CB.js.map +0 -1
- package/dist/chunk-WWQ4YRZN.js +0 -7
- package/dist/diff-U4IELWRL.js.map +0 -1
- package/dist/reset-XETOHTCK.js.map +0 -1
- package/dist/setup-CLDCHROZ.js.map +0 -1
- package/dist/upgrade-DOKWRK7J.js.map +0 -1
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# User Story Guide for Claude Code
|
|
2
|
+
|
|
3
|
+
## How to Fill Out Feature User Stories
|
|
4
|
+
|
|
5
|
+
**Template:** `@.safeword/templates/user-stories-template.md`
|
|
6
|
+
|
|
7
|
+
**When user asks:** "Create user stories for issue #N" or "Create user stories for [feature]"
|
|
8
|
+
|
|
9
|
+
**What you do:**
|
|
10
|
+
|
|
11
|
+
1. Read `@.safeword/templates/user-stories-template.md`
|
|
12
|
+
2. Fill in feature name, issue number, status
|
|
13
|
+
3. Create numbered stories (Story 1, Story 2, etc.)
|
|
14
|
+
4. Add acceptance criteria with ✅/❌ checkboxes for tracking
|
|
15
|
+
5. Include test file references
|
|
16
|
+
6. Add summary with completion % and phases
|
|
17
|
+
7. Save to project location (e.g., `planning/user-stories/45-feature-name.md`)
|
|
18
|
+
|
|
19
|
+
**DO include:**
|
|
20
|
+
|
|
21
|
+
- Status tracking (✅/❌ per story and AC)
|
|
22
|
+
- Test file references
|
|
23
|
+
- Implementation status
|
|
24
|
+
- Completion percentage
|
|
25
|
+
- Phase tracking
|
|
26
|
+
- Next steps
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## INVEST Validation (Do This Before Saving)
|
|
31
|
+
|
|
32
|
+
After filling out story, mentally check:
|
|
33
|
+
|
|
34
|
+
✅ **Independent** - Can be done without other stories?
|
|
35
|
+
✅ **Negotiable** - Are details left for conversation?
|
|
36
|
+
✅ **Valuable** - Does "So that" clearly state value?
|
|
37
|
+
✅ **Estimable** - Can team estimate this (1-5 days)?
|
|
38
|
+
✅ **Small** - Completable in one sprint?
|
|
39
|
+
✅ **Testable** - Are acceptance criteria specific?
|
|
40
|
+
|
|
41
|
+
**If ANY check fails → Refine or split the story**
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Writing Good Acceptance Criteria
|
|
46
|
+
|
|
47
|
+
**✅ GOOD - Specific, user-facing, testable:**
|
|
48
|
+
|
|
49
|
+
- User can switch campaigns without page reload
|
|
50
|
+
- Response time is under 200ms
|
|
51
|
+
- Current campaign is visually highlighted
|
|
52
|
+
- Error message explains what went wrong
|
|
53
|
+
|
|
54
|
+
**❌ BAD - Vague, technical, or implementation:**
|
|
55
|
+
|
|
56
|
+
- Campaign switching works ← Too vague
|
|
57
|
+
- Use Zustand for state ← Implementation detail
|
|
58
|
+
- Database is fast ← Not user-facing
|
|
59
|
+
- Code is clean ← Not testable
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Size Guidelines
|
|
64
|
+
|
|
65
|
+
| Indicator | Too Big | Just Right | Too Small |
|
|
66
|
+
| ------------------- | ------- | ---------- | --------- |
|
|
67
|
+
| Acceptance Criteria | 6+ | 1-5 | 0 |
|
|
68
|
+
| Personas/Screens | 3+ | 1-2 | N/A |
|
|
69
|
+
| Duration | 6+ days | 1-5 days | <1 hour |
|
|
70
|
+
| **Action** | Split | ✅ Ship | Combine |
|
|
71
|
+
|
|
72
|
+
**Decision rule:** When borderline (e.g., 5 AC but 2 personas), err on the side of splitting. Smaller stories are easier to estimate and complete.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Examples
|
|
77
|
+
|
|
78
|
+
### ✅ GOOD Story
|
|
79
|
+
|
|
80
|
+
**As a** player with multiple campaigns
|
|
81
|
+
**I want** to switch between campaigns from the sidebar
|
|
82
|
+
**So that** I can quickly resume different games
|
|
83
|
+
|
|
84
|
+
**Acceptance Criteria:**
|
|
85
|
+
|
|
86
|
+
- [ ] Sidebar shows all campaigns with last-played date
|
|
87
|
+
- [ ] Clicking campaign loads it within 200ms
|
|
88
|
+
- [ ] Current campaign is highlighted
|
|
89
|
+
|
|
90
|
+
### ❌ BAD Story (Too Big)
|
|
91
|
+
|
|
92
|
+
**As a** user
|
|
93
|
+
**I want** a complete campaign management system
|
|
94
|
+
**So that** I can organize my games
|
|
95
|
+
|
|
96
|
+
**Acceptance Criteria:**
|
|
97
|
+
|
|
98
|
+
- [ ] Create, edit, delete campaigns
|
|
99
|
+
- [ ] Share campaigns with other players
|
|
100
|
+
- [ ] Export/import campaign data
|
|
101
|
+
- [ ] Search and filter campaigns
|
|
102
|
+
- [ ] Tag campaigns by theme
|
|
103
|
+
|
|
104
|
+
**Problem:** This is 5+ separate stories. Split it.
|
|
105
|
+
|
|
106
|
+
### ❌ BAD Story (No Value)
|
|
107
|
+
|
|
108
|
+
**As a** developer
|
|
109
|
+
**I want** to refactor the GameStore
|
|
110
|
+
**So that** code is cleaner
|
|
111
|
+
|
|
112
|
+
**Problem:**
|
|
113
|
+
|
|
114
|
+
- Developer is not a user
|
|
115
|
+
- "Cleaner code" is not user-facing value
|
|
116
|
+
- This is a technical task, not a user story
|
|
117
|
+
|
|
118
|
+
### ✅ BETTER (Technical Story)
|
|
119
|
+
|
|
120
|
+
**Technical Task:** Refactor GameStore to use Immer
|
|
121
|
+
|
|
122
|
+
**Why:** Prevent state mutation bugs (3 bugs in last sprint)
|
|
123
|
+
**Effort:** 2-3 hours
|
|
124
|
+
**Test:** All existing tests pass, no new mutations
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Conversation Starter, Not Contract
|
|
129
|
+
|
|
130
|
+
**Remember:** User story is a placeholder for conversation.
|
|
131
|
+
|
|
132
|
+
**During planning, discuss:**
|
|
133
|
+
|
|
134
|
+
- Edge cases not in acceptance criteria
|
|
135
|
+
- Technical approach (but don't document it in story)
|
|
136
|
+
- Open questions or dependencies
|
|
137
|
+
- How to split if too big
|
|
138
|
+
|
|
139
|
+
**The story should NOT contain:**
|
|
140
|
+
|
|
141
|
+
- Technical implementation details
|
|
142
|
+
- Test strategies
|
|
143
|
+
- UI mockups (link to them instead)
|
|
144
|
+
- Definition of done (that's team-wide)
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Technical Constraints Section
|
|
149
|
+
|
|
150
|
+
**Purpose:** Capture non-functional requirements that inform test definitions. These are NOT user stories but constrain how stories are implemented.
|
|
151
|
+
|
|
152
|
+
**When to use:** Fill in constraints BEFORE writing test definitions. Delete sections that don't apply—keep it lean.
|
|
153
|
+
|
|
154
|
+
### Categories
|
|
155
|
+
|
|
156
|
+
| Category | What It Captures | Examples |
|
|
157
|
+
| -------------- | -------------------------------- | ----------------------------------------------- |
|
|
158
|
+
| Performance | Speed, throughput, capacity | Response time < 200ms, 1000 concurrent users |
|
|
159
|
+
| Security | Auth, validation, rate limiting | Sanitized inputs, session required, 100 req/min |
|
|
160
|
+
| Compatibility | Browsers, devices, accessibility | Chrome 100+, iOS 14+, WCAG 2.1 AA |
|
|
161
|
+
| Data | Privacy, retention, compliance | GDPR delete in 72h, 90-day log retention |
|
|
162
|
+
| Dependencies | Existing systems, restrictions | Use AuthService, no new packages |
|
|
163
|
+
| Infrastructure | Resources, offline, deployment | < 512MB memory, offline-capable |
|
|
164
|
+
|
|
165
|
+
### ✅ GOOD Constraints (Specific, Testable)
|
|
166
|
+
|
|
167
|
+
```markdown
|
|
168
|
+
### Performance
|
|
169
|
+
|
|
170
|
+
- [ ] API response < 200ms at P95 under 100 concurrent users
|
|
171
|
+
- [ ] Initial page load < 3s on simulated 3G
|
|
172
|
+
|
|
173
|
+
### Security
|
|
174
|
+
|
|
175
|
+
- [ ] All user inputs sanitized via DOMPurify
|
|
176
|
+
- [ ] Rate limited: 100 requests/min per IP
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### ❌ BAD Constraints (Vague, Untestable)
|
|
180
|
+
|
|
181
|
+
```markdown
|
|
182
|
+
### Performance
|
|
183
|
+
|
|
184
|
+
- [ ] Should be fast ← How fast? Under what conditions?
|
|
185
|
+
- [ ] Good performance ← Not measurable
|
|
186
|
+
|
|
187
|
+
### Security
|
|
188
|
+
|
|
189
|
+
- [ ] Secure ← What does this mean?
|
|
190
|
+
- [ ] Protected from hackers ← Not specific
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Decision Rule
|
|
194
|
+
|
|
195
|
+
**Include a constraint if:**
|
|
196
|
+
|
|
197
|
+
- It affects how you write tests (performance tests, security tests)
|
|
198
|
+
- It limits implementation choices (must use X, can't use Y)
|
|
199
|
+
- Violating it would fail an audit or break SLAs
|
|
200
|
+
|
|
201
|
+
**Skip if:**
|
|
202
|
+
|
|
203
|
+
- It's a project-wide standard already in ARCHITECTURE.md
|
|
204
|
+
- It's obvious (don't document "code must compile")
|
|
205
|
+
|
|
206
|
+
### Tie-Breaking
|
|
207
|
+
|
|
208
|
+
**If constraint fits multiple categories:** Choose the most specific one.
|
|
209
|
+
|
|
210
|
+
| Constraint | Could Fit | Best Category | Why |
|
|
211
|
+
| -------------------------- | ----------------------------- | -------------- | ------------------------------- |
|
|
212
|
+
| API rate limit 100 req/min | Security, Performance | Security | Rate limiting is access control |
|
|
213
|
+
| Page load < 3s on 3G | Performance, Compatibility | Performance | Speed is primary concern |
|
|
214
|
+
| Must work offline | Infrastructure, Compatibility | Infrastructure | Offline is deployment concern |
|
|
215
|
+
|
|
216
|
+
**Edge case:** If truly cross-cutting (e.g., "GDPR compliance" spans Data + Security), pick one and add a note: "See also: Security constraints"
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## LLM Optimization Tips
|
|
221
|
+
|
|
222
|
+
**Core principle:** User stories are instructions that LLMs read and follow. Apply LLM instruction design best practices.
|
|
223
|
+
|
|
224
|
+
**See:** `@.safeword/guides/llm-instruction-design.md` for comprehensive framework on writing LLM-consumable documentation.
|
|
225
|
+
|
|
226
|
+
**When filling templates:**
|
|
227
|
+
|
|
228
|
+
- Use specific, concrete language (not vague)
|
|
229
|
+
- Avoid generic phrases ("improve UX", "make better")
|
|
230
|
+
- Include numbers where relevant (200ms, 3 items, under 5 clicks)
|
|
231
|
+
- Use concrete examples over abstract rules
|
|
232
|
+
- Define all terms explicitly
|
|
233
|
+
- Write for humans, not robots
|
|
234
|
+
|
|
235
|
+
**Token efficiency:**
|
|
236
|
+
|
|
237
|
+
- Template is 9 lines (minimal prompt caching cost)
|
|
238
|
+
- No nested sections (flat structure)
|
|
239
|
+
- No validation metadata in file
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## File Naming Convention
|
|
244
|
+
|
|
245
|
+
Save stories as: `.safeword/planning/user-stories/[slug].md`
|
|
246
|
+
|
|
247
|
+
**Good filenames:**
|
|
248
|
+
|
|
249
|
+
- `campaign-switching.md`
|
|
250
|
+
- `export-character-pdf.md`
|
|
251
|
+
- `stress-tracking.md`
|
|
252
|
+
|
|
253
|
+
**Bad filenames:**
|
|
254
|
+
|
|
255
|
+
- `user-story-1.md` ← Not descriptive
|
|
256
|
+
- `STORY_CAMPAIGN_SWITCHING_FINAL_v2.md` ← Bloated
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Zombie Process Cleanup (Multi-Project Environments)
|
|
2
|
+
|
|
3
|
+
**When to use:** Working on multiple projects simultaneously, especially when they share tech stacks (Next.js, Playwright, etc.)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## The Problem
|
|
8
|
+
|
|
9
|
+
When running dev servers and E2E tests across multiple projects, zombie processes accumulate:
|
|
10
|
+
|
|
11
|
+
- Dev servers holding ports
|
|
12
|
+
- Playwright browser instances
|
|
13
|
+
- Test runners stuck in background
|
|
14
|
+
- Build processes from previous sessions
|
|
15
|
+
|
|
16
|
+
**CRITICAL:** NEVER use `killall node` or `pkill -9 node` when working on multiple projects - this kills processes from ALL projects.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Port-Based Cleanup (Safest for Multi-Project)
|
|
21
|
+
|
|
22
|
+
**Prerequisite:** Each project must use a different port (e.g., Project A: 3000, Project B: 3001)
|
|
23
|
+
|
|
24
|
+
**Port convention:** Dev and test instances use different ports within the same project:
|
|
25
|
+
|
|
26
|
+
- **Dev port**: Project's configured port (e.g., 3000, 5173, 8080) - manual testing
|
|
27
|
+
- **Test port**: Dev port + 1000 (e.g., 4000, 6173, 9080) - Playwright managed
|
|
28
|
+
|
|
29
|
+
See `testing-methodology.md` → "E2E Testing with Persistent Dev Servers" for full port isolation strategy.
|
|
30
|
+
|
|
31
|
+
**Decision rule:** If unsure which cleanup method to use → port-based first (safest), then project script, then tmux.
|
|
32
|
+
|
|
33
|
+
**Recommended cleanup pattern** (replace ports with your project's ports):
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Kill both dev server AND test server ports
|
|
37
|
+
# Example: Next.js (3000/4000), Vite (5173/6173), or your project's ports
|
|
38
|
+
lsof -ti:3000 -ti:4000 | xargs kill -9 2>/dev/null
|
|
39
|
+
|
|
40
|
+
# Kill Playwright processes launched from THIS directory
|
|
41
|
+
pkill -f "playwright.*$(pwd)" 2>/dev/null
|
|
42
|
+
|
|
43
|
+
# Wait for cleanup
|
|
44
|
+
sleep 2
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Why this works:**
|
|
48
|
+
|
|
49
|
+
- ✅ Dev + test ports are unique to this project → safe to kill
|
|
50
|
+
- ✅ `$(pwd)` ensures only THIS project's tests are killed
|
|
51
|
+
- ✅ Other projects completely untouched
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Project-Specific Cleanup Script
|
|
56
|
+
|
|
57
|
+
For frequent cleanup needs, create `scripts/cleanup.sh` in each project:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
#!/bin/bash
|
|
61
|
+
# scripts/cleanup.sh - Kill only THIS project's processes
|
|
62
|
+
|
|
63
|
+
DEV_PORT=3000 # Dev server port (change per project)
|
|
64
|
+
TEST_PORT=$((DEV_PORT + 1000)) # Test server port (Playwright managed)
|
|
65
|
+
PROJECT_DIR="$(pwd)"
|
|
66
|
+
|
|
67
|
+
echo "Cleaning up $PROJECT_DIR (dev: $DEV_PORT, test: $TEST_PORT)..."
|
|
68
|
+
|
|
69
|
+
# Kill both dev and test servers by port
|
|
70
|
+
lsof -ti:$DEV_PORT -ti:$TEST_PORT | xargs kill -9 2>/dev/null
|
|
71
|
+
|
|
72
|
+
# Kill Playwright browsers for this project
|
|
73
|
+
ps aux | grep -E "(playwright|chromium)" | grep "$PROJECT_DIR" | grep -v grep | awk '{print $2}' | xargs kill -9 2>/dev/null
|
|
74
|
+
|
|
75
|
+
# Kill test runners
|
|
76
|
+
pgrep -f "playwright test.*$(basename $PROJECT_DIR)" | xargs kill -9 2>/dev/null
|
|
77
|
+
|
|
78
|
+
echo "Cleanup complete!"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Make executable:** `chmod +x scripts/cleanup.sh`
|
|
82
|
+
|
|
83
|
+
**Usage:** `./scripts/cleanup.sh`
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Common Patterns by Tech Stack
|
|
88
|
+
|
|
89
|
+
### Next.js Projects
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Kill Next.js dev server (port 3000)
|
|
93
|
+
lsof -ti:3000 | xargs kill -9 2>/dev/null
|
|
94
|
+
|
|
95
|
+
# Kill Next.js build processes for this project
|
|
96
|
+
ps aux | grep "next dev" | grep "$(pwd)" | grep -v grep | awk '{print $2}' | xargs kill -9 2>/dev/null
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Playwright E2E Tests
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Kill Playwright browsers and test runners
|
|
103
|
+
pkill -f "playwright.*$(pwd)" 2>/dev/null
|
|
104
|
+
|
|
105
|
+
# Or more specific (by project name)
|
|
106
|
+
pkill -f "playwright.*my-project-name" 2>/dev/null
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Vite Projects
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Kill Vite dev server (typically port 5173)
|
|
113
|
+
lsof -ti:5173 | xargs kill -9 2>/dev/null
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### React Native / Expo
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Kill Metro bundler (port 8081)
|
|
120
|
+
lsof -ti:8081 | xargs kill -9 2>/dev/null
|
|
121
|
+
|
|
122
|
+
# Kill Expo dev tools (port 19000-19006)
|
|
123
|
+
lsof -ti:19000-19006 | xargs kill -9 2>/dev/null
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Alternative: tmux/Screen Sessions
|
|
129
|
+
|
|
130
|
+
For complete isolation, run each project in its own terminal session:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Start project in named session
|
|
134
|
+
tmux new -s project-name
|
|
135
|
+
# Run dev server here
|
|
136
|
+
|
|
137
|
+
# Kill everything in this session only
|
|
138
|
+
tmux kill-session -t project-name
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Pros:**
|
|
142
|
+
|
|
143
|
+
- ✅ Complete isolation between projects
|
|
144
|
+
- ✅ One command kills everything
|
|
145
|
+
- ✅ Can detach/reattach sessions
|
|
146
|
+
|
|
147
|
+
**Cons:**
|
|
148
|
+
|
|
149
|
+
- ⚠️ Requires learning tmux
|
|
150
|
+
- ⚠️ Different workflow
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Best Practices
|
|
155
|
+
|
|
156
|
+
1. **Assign unique ports** - Set `PORT=3000` in one project, `PORT=3001` in another
|
|
157
|
+
2. **Use port-based cleanup first** - Simplest and safest
|
|
158
|
+
3. **Create project cleanup scripts** - Reusable, documented
|
|
159
|
+
4. **Never `killall node`** - Too broad when working on multiple projects
|
|
160
|
+
5. **Clean up before starting** - Run cleanup script before `npm run dev`
|
|
161
|
+
6. **Check what's running** - Use `lsof -i:PORT` to see what's using a port
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Debugging Zombie Processes
|
|
166
|
+
|
|
167
|
+
### Find What's Using a Port
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# Check what's on port 3000
|
|
171
|
+
lsof -i:3000
|
|
172
|
+
|
|
173
|
+
# More details
|
|
174
|
+
lsof -i:3000 -P -n
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Find All Node Processes
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# List all node processes
|
|
181
|
+
ps aux | grep -E "(node|playwright|chromium)"
|
|
182
|
+
|
|
183
|
+
# More detailed (with working directory)
|
|
184
|
+
lsof -p $(pgrep node) | grep cwd
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Find Processes by Project Directory
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Find processes running in specific directory
|
|
191
|
+
ps aux | grep "/Users/alex/projects/my-project"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Quick Reference
|
|
197
|
+
|
|
198
|
+
| Situation | Command |
|
|
199
|
+
| ---------------------------------------- | ---------------------------------------------------------------- |
|
|
200
|
+
| Kill dev + test servers (use your ports) | `lsof -ti:$DEV_PORT -ti:$TEST_PORT \| xargs kill -9 2>/dev/null` |
|
|
201
|
+
| Kill Playwright (this project) | `pkill -f "playwright.*$(pwd)"` |
|
|
202
|
+
| Kill all for this project | `./scripts/cleanup.sh` |
|
|
203
|
+
| Check what's on port | `lsof -i:3000` |
|
|
204
|
+
| Find zombie processes | `ps aux \| grep -E "(node\|playwright\|chromium)"` |
|
|
205
|
+
| Kill by process ID | `kill -9 <PID>` |
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## What NOT to Do
|
|
210
|
+
|
|
211
|
+
❌ **DON'T:** `killall node` (kills all projects)
|
|
212
|
+
❌ **DON'T:** `pkill -9 node` (kills all projects)
|
|
213
|
+
❌ **DON'T:** Kill processes without checking working directory
|
|
214
|
+
❌ **DON'T:** Assume zombie browsers will clean themselves up (they won't)
|
|
215
|
+
|
|
216
|
+
✅ **DO:** Use port-based cleanup
|
|
217
|
+
✅ **DO:** Filter by project directory with `$(pwd)`
|
|
218
|
+
✅ **DO:** Create project-specific cleanup scripts
|
|
219
|
+
✅ **DO:** Clean up before AND after development sessions
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Safeword AGENTS.md self-healing hook
|
|
3
|
+
# Ensures the AGENTS.md link is always present
|
|
4
|
+
|
|
5
|
+
LINK='**⚠️ ALWAYS READ FIRST: @./.safeword/SAFEWORD.md**'
|
|
6
|
+
|
|
7
|
+
if [ ! -d ".safeword" ]; then
|
|
8
|
+
# Not a safeword project, skip
|
|
9
|
+
exit 0
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
if [ ! -f "AGENTS.md" ]; then
|
|
13
|
+
# AGENTS.md doesn't exist, create it
|
|
14
|
+
echo "$LINK" > AGENTS.md
|
|
15
|
+
echo "SAFEWORD: Created AGENTS.md with safeword link"
|
|
16
|
+
exit 0
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# Check if link is present
|
|
20
|
+
if ! grep -q "@./.safeword/SAFEWORD.md" AGENTS.md; then
|
|
21
|
+
# Link missing, prepend it
|
|
22
|
+
CONTENT=$(cat AGENTS.md)
|
|
23
|
+
echo -e "$LINK\n\n$CONTENT" > AGENTS.md
|
|
24
|
+
echo "SAFEWORD: Restored AGENTS.md link (was removed)"
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
exit 0
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# Inject Timestamp -
|
|
3
|
-
# Outputs current Unix timestamp
|
|
2
|
+
# Inject Timestamp - UserPromptSubmit Hook
|
|
3
|
+
# Outputs current Unix timestamp for Claude's context awareness
|
|
4
4
|
# Helps with accurate ticket timestamps and time-based reasoning
|
|
5
5
|
|
|
6
6
|
echo "Current time: $(date +%s) ($(date -u +%Y-%m-%dT%H:%M:%SZ))"
|
|
7
|
-
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Safeword common utilities for hook scripts
|
|
3
|
+
|
|
4
|
+
# Output JSON response for Claude Code hooks
|
|
5
|
+
# Usage: json_response '{"key": "value"}'
|
|
6
|
+
json_response() {
|
|
7
|
+
echo "$1"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
# Check if running in a safeword project
|
|
11
|
+
is_safeword_project() {
|
|
12
|
+
[ -d ".safeword" ]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# Get project root (directory containing .safeword)
|
|
16
|
+
get_project_root() {
|
|
17
|
+
local dir="$PWD"
|
|
18
|
+
while [ "$dir" != "/" ]; do
|
|
19
|
+
if [ -d "$dir/.safeword" ]; then
|
|
20
|
+
echo "$dir"
|
|
21
|
+
return 0
|
|
22
|
+
fi
|
|
23
|
+
dir=$(dirname "$dir")
|
|
24
|
+
done
|
|
25
|
+
return 1
|
|
26
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Fallback JSON output when jq is not available
|
|
3
|
+
# Uses printf for safe JSON string escaping
|
|
4
|
+
|
|
5
|
+
# Escape a string for JSON output
|
|
6
|
+
json_escape() {
|
|
7
|
+
local str="$1"
|
|
8
|
+
str="${str//\\/\\\\}"
|
|
9
|
+
str="${str//\"/\\\"}"
|
|
10
|
+
str="${str//$'\n'/\\n}"
|
|
11
|
+
str="${str//$'\t'/\\t}"
|
|
12
|
+
echo "$str"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# Output a simple JSON object with one key-value pair
|
|
16
|
+
json_kv() {
|
|
17
|
+
local key="$1"
|
|
18
|
+
local value="$2"
|
|
19
|
+
printf '{"proposedChanges": false, "madeChanges": false, "askedQuestion": false, "%s": "%s"}\n' "$key" "$(json_escape "$value")"
|
|
20
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Safeword markdownlint configuration
|
|
3
|
+
"default": true,
|
|
4
|
+
|
|
5
|
+
// Allow inline HTML (needed for some markdown features)
|
|
6
|
+
"MD033": false,
|
|
7
|
+
|
|
8
|
+
// Allow multiple headings with same content
|
|
9
|
+
"MD024": {
|
|
10
|
+
"siblings_only": true
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
// Line length - be lenient
|
|
14
|
+
"MD013": {
|
|
15
|
+
"line_length": 120,
|
|
16
|
+
"code_blocks": false,
|
|
17
|
+
"tables": false
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
// Allow trailing punctuation in headings
|
|
21
|
+
"MD026": false,
|
|
22
|
+
|
|
23
|
+
// Allow emphasis as heading
|
|
24
|
+
"MD036": false
|
|
25
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Architecture Review Prompt
|
|
2
|
+
|
|
3
|
+
Review the following code changes for architectural issues.
|
|
4
|
+
|
|
5
|
+
## Check for:
|
|
6
|
+
|
|
7
|
+
1. **Misplaced logic** - Business rules in wrong layer?
|
|
8
|
+
2. **God module** - Too many responsibilities (>10 dependents or >500 lines)?
|
|
9
|
+
3. **Leaky abstraction** - Implementation details exposed to callers?
|
|
10
|
+
4. **Tight coupling** - Changes would cascade unnecessarily?
|
|
11
|
+
5. **Boundary violation** - Import from disallowed layer?
|
|
12
|
+
|
|
13
|
+
## Context
|
|
14
|
+
|
|
15
|
+
Read the project's ARCHITECTURE.md for:
|
|
16
|
+
|
|
17
|
+
- Defined layers and their responsibilities
|
|
18
|
+
- Allowed dependencies between layers
|
|
19
|
+
- Project-specific patterns and conventions
|
|
20
|
+
|
|
21
|
+
## Response Format
|
|
22
|
+
|
|
23
|
+
Return JSON:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"issues": [
|
|
28
|
+
{
|
|
29
|
+
"type": "misplaced_logic | god_module | leaky_abstraction | tight_coupling | boundary_violation",
|
|
30
|
+
"location": "file:line or module name",
|
|
31
|
+
"description": "What's wrong",
|
|
32
|
+
"fix": "How to fix it"
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"verdict": "clean | minor | refactor_needed"
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Verdict definitions:
|
|
40
|
+
|
|
41
|
+
- **clean**: No issues found
|
|
42
|
+
- **minor**: Small issues that should be noted but don't block commit
|
|
43
|
+
- **refactor_needed**: Significant issues that should be addressed before commit
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Quality Review Prompt
|
|
2
|
+
|
|
3
|
+
Double check and critique your work just in case.
|
|
4
|
+
|
|
5
|
+
- Is it correct?
|
|
6
|
+
- Is it elegant?
|
|
7
|
+
- Does it adhere to the latest documentation and best practices for the relevant stack items, UX principles, domain requirements, and testing practices?
|
|
8
|
+
- Ask me any non-obvious questions you can't research yourself in the codebase or online.
|
|
9
|
+
- Think hard.
|
|
10
|
+
- Avoid bloat.
|