jettypod 4.1.2 → 4.1.4

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.
Files changed (179) hide show
  1. package/.nvmrc +1 -0
  2. package/docs/COMPLETE-TESTING-STRATEGY.md +970 -0
  3. package/docs/DECISIONS.md +10 -12
  4. package/docs/NODE_VERSION.md +83 -0
  5. package/docs/TDD-INFRASTRUCTURE-STRATEGY.md +1374 -0
  6. package/docs/TESTING-FOR-NON-ENGINEERS.md +1588 -0
  7. package/docs/TESTING-STRATEGY-AUDIT.md +698 -0
  8. package/hooks/post-checkout +17 -0
  9. package/hooks/post-merge +17 -0
  10. package/hooks/pre-commit +30 -0
  11. package/jettypod.js +259 -120
  12. package/lib/coverage-tracker.js +218 -0
  13. package/lib/database.js +2 -0
  14. package/lib/db-export.js +192 -0
  15. package/lib/db-import.js +193 -0
  16. package/lib/external-transition-handler.js +32 -0
  17. package/lib/git-hook-helpers.js +174 -0
  18. package/lib/git-root.js +90 -0
  19. package/lib/infrastructure-chore-generator.js +45 -0
  20. package/lib/install-hooks.js +52 -0
  21. package/lib/jettypod-backup.js +238 -0
  22. package/lib/merge-lock.js +193 -0
  23. package/lib/migrations/012-add-worktree-path.js +38 -0
  24. package/lib/migrations/013-worktrees-table.js +86 -0
  25. package/lib/migrations/014-migrate-worktree-data.js +161 -0
  26. package/lib/migrations/015-merge-locks-table.js +67 -0
  27. package/lib/pattern-finder.js +152 -0
  28. package/lib/process-manager.js +140 -0
  29. package/lib/production-standards-reader.js +13 -2
  30. package/lib/production-standards-writer.js +85 -0
  31. package/lib/skills/feature-planning/dry-run-validator.js +135 -0
  32. package/lib/skills/feature-planning/validation-formatter.js +160 -0
  33. package/lib/smart-conflict-detection.js +168 -0
  34. package/lib/smart-fetch-rebase.js +614 -0
  35. package/lib/step-definition-parser.js +76 -0
  36. package/lib/unit-test-generator.js +232 -0
  37. package/lib/verification-command-generator.js +66 -0
  38. package/lib/worktree-diagnostics.js +413 -0
  39. package/lib/worktree-facade.js +174 -0
  40. package/lib/worktree-manager.js +636 -0
  41. package/lib/worktree-reconciler.js +429 -0
  42. package/package.json +30 -3
  43. package/skills-templates/external-transition/SKILL.md +34 -3
  44. package/skills-templates/feature-planning/SKILL.md +190 -24
  45. package/skills-templates/production-mode/SKILL.md +127 -9
  46. package/skills-templates/speed-mode/SKILL.md +454 -51
  47. package/skills-templates/stable-mode/SKILL.md +285 -76
  48. package/.claude/PROTECT_SKILLS.md +0 -28
  49. package/.claude/settings.json +0 -24
  50. package/.claude/settings.local.json +0 -16
  51. package/.claude/skills/epic-planning/SKILL.md +0 -297
  52. package/.claude/skills/external-transition/SKILL.md +0 -384
  53. package/.claude/skills/feature-planning/SKILL.md +0 -464
  54. package/.claude/skills/production-mode/SKILL.md +0 -369
  55. package/.claude/skills/speed-mode/SKILL.md +0 -481
  56. package/.claude/skills/stable-mode/SKILL.md +0 -713
  57. package/.claude/skills.backup-2025-11-10T23-33-09-368Z/epic-planning/SKILL.md +0 -297
  58. package/.claude/skills.backup-2025-11-10T23-33-09-368Z/feature-planning/SKILL.md +0 -464
  59. package/.claude/skills.backup-2025-11-10T23-33-09-368Z/speed-mode/SKILL.md +0 -467
  60. package/.claude/skills.backup-2025-11-10T23-33-09-368Z/stable-mode/SKILL.md +0 -673
  61. package/.claude/skills.backup-2025-11-11T16-15-10-070Z/epic-discover/SKILL.md +0 -297
  62. package/.claude/skills.backup-2025-11-11T16-42-43-212Z/epic-planning/SKILL.md +0 -297
  63. package/.claude/skills.backup-2025-11-11T16-42-43-212Z/feature-planning/SKILL.md +0 -464
  64. package/.claude/skills.backup-2025-11-11T16-42-43-212Z/speed-mode/SKILL.md +0 -467
  65. package/.claude/skills.backup-2025-11-11T16-42-43-212Z/stable-mode/SKILL.md +0 -673
  66. package/.claude/skills.backup-2025-11-11T17-06-09-783Z/epic-planning/SKILL.md +0 -297
  67. package/.claude/skills.backup-2025-11-11T17-06-09-783Z/feature-planning/SKILL.md +0 -464
  68. package/.claude/skills.backup-2025-11-11T17-06-09-783Z/speed-mode/SKILL.md +0 -467
  69. package/.claude/skills.backup-2025-11-11T17-06-09-783Z/stable-mode/SKILL.md +0 -673
  70. package/.devpod/current-work.json +0 -10
  71. package/.devpod/work.db +0 -0
  72. package/.github/workflows/test-safety.yml +0 -85
  73. package/.jettypod/config.json +0 -5
  74. package/.jettypod/current-work.json +0 -10
  75. package/.jettypod/hooks/README.md +0 -77
  76. package/.jettypod/hooks/protect-claude-md.js +0 -338
  77. package/.jettypod/test-work.db +0 -0
  78. package/.jettypod/work.db +0 -0
  79. package/CLAUDE.md +0 -49
  80. package/SPEED-STABLE-AUDIT.md +0 -853
  81. package/SYSTEM-BEHAVIOR.md +0 -2199
  82. package/TEST_SAFETY_AUDIT.md +0 -314
  83. package/TEST_SAFETY_IMPLEMENTATION.md +0 -97
  84. package/cucumber-report.html +0 -45
  85. package/dist/devpod-linux +0 -0
  86. package/dist/devpod-macos +0 -0
  87. package/dist/devpod-win.exe +0 -0
  88. package/docs/features/jettypod-standards-explained.md +0 -543
  89. package/docs/features/standards-inventory.md +0 -257
  90. package/features/auto-generate-production-chores.feature +0 -13
  91. package/features/backlog-command.feature +0 -26
  92. package/features/backlog-filtering-production.feature +0 -10
  93. package/features/claude-md-protection/steps.js +0 -498
  94. package/features/decisions/index.js +0 -490
  95. package/features/decisions/index.test.js +0 -208
  96. package/features/fix-text-wrapping.feature +0 -42
  97. package/features/git-hooks/git-hooks.feature +0 -30
  98. package/features/git-hooks/index.js +0 -93
  99. package/features/git-hooks/index.test.js +0 -137
  100. package/features/git-hooks/post-commit +0 -56
  101. package/features/git-hooks/post-merge +0 -47
  102. package/features/git-hooks/pre-commit +0 -28
  103. package/features/git-hooks/simple-steps.js +0 -53
  104. package/features/git-hooks/simple-test.feature +0 -10
  105. package/features/git-hooks/steps.js +0 -196
  106. package/features/jettypod-update-command.feature +0 -46
  107. package/features/mode-prompts/index.js +0 -95
  108. package/features/mode-prompts/simple-steps.js +0 -44
  109. package/features/mode-prompts/simple-test.feature +0 -9
  110. package/features/mode-prompts/validation.test.js +0 -120
  111. package/features/multiple-claude-instances.feature +0 -121
  112. package/features/production-mode-skill.feature +0 -121
  113. package/features/refactor-mode/steps.js +0 -217
  114. package/features/refactor-mode.feature +0 -49
  115. package/features/simplify-external-transition.feature +0 -166
  116. package/features/skills-update/index.test.js +0 -216
  117. package/features/step_definitions/backlog-command.steps.js +0 -37
  118. package/features/step_definitions/fix-text-wrapping.steps.js +0 -271
  119. package/features/step_definitions/multiple-claude-instances.steps.js +0 -621
  120. package/features/step_definitions/production-mode-skill.steps.js +0 -862
  121. package/features/step_definitions/simplify-external-transition.steps.js +0 -370
  122. package/features/step_definitions/terminal-logo.steps.js +0 -145
  123. package/features/step_definitions/update-command.steps.js +0 -183
  124. package/features/support/hooks.js +0 -9
  125. package/features/terminal-logo/index.js +0 -39
  126. package/features/terminal-logo/terminal-logo.feature +0 -30
  127. package/features/update-command/index.js +0 -181
  128. package/features/update-command/index.test.js +0 -225
  129. package/features/work-commands/bug-workflow-display.feature +0 -22
  130. package/features/work-commands/index.js +0 -498
  131. package/features/work-commands/simple-steps.js +0 -69
  132. package/features/work-commands/stable-tests.feature +0 -57
  133. package/features/work-commands/steps.js +0 -1174
  134. package/features/work-commands/validation.test.js +0 -88
  135. package/features/work-commands/work-commands.feature +0 -13
  136. package/features/work-tracking/discovery-validation.test.js +0 -228
  137. package/features/work-tracking/index.js +0 -1921
  138. package/features/work-tracking/mode-required.feature +0 -112
  139. package/features/work-tracking/phase-tracking.test.js +0 -482
  140. package/features/work-tracking/prototype-tracking.test.js +0 -485
  141. package/features/work-tracking/tree-view.test.js +0 -310
  142. package/features/work-tracking/work-set-mode.feature +0 -71
  143. package/features/work-tracking/work-start-mode.feature +0 -88
  144. package/full-test.txt +0 -0
  145. package/lib/bug-workflow.test.js +0 -177
  146. package/lib/claudemd.test.js +0 -195
  147. package/lib/config.test.js +0 -511
  148. package/lib/constants.test.js +0 -164
  149. package/lib/current-work.test.js +0 -146
  150. package/lib/database-project-config.test.js +0 -111
  151. package/lib/database.test.js +0 -106
  152. package/lib/decisions-generator.test.js +0 -457
  153. package/lib/decisions-helpers.test.js +0 -310
  154. package/lib/git-coordinator.js +0 -167
  155. package/lib/git.test.js +0 -145
  156. package/lib/migrations/002-default-work-item-modes.test.js +0 -351
  157. package/lib/production-chore-generator.test.js +0 -432
  158. package/lib/production-context-detector.test.js +0 -277
  159. package/lib/production-scenario-appender.test.js +0 -235
  160. package/lib/production-scenario-validator.test.js +0 -246
  161. package/lib/production-standards-reader.test.js +0 -270
  162. package/lib/project-state.test.js +0 -92
  163. package/lib/push-queue.js +0 -417
  164. package/lib/queue-processor.js +0 -74
  165. package/lib/test-helpers.js +0 -202
  166. package/lib/test-helpers.test.js +0 -255
  167. package/prototypes/2025-01-11-production-mode-autonomous.js +0 -119
  168. package/prototypes/2025-01-11-production-mode-collaborative.js +0 -166
  169. package/prototypes/2025-01-11-production-mode-guided.js +0 -217
  170. package/prototypes/2025-01-11-production-mode-smart-context.js +0 -347
  171. package/prototypes/2025-01-11-production-standards-example.md +0 -204
  172. package/prototypes/2025-11-10-backlog-filtering-tree-aware.js +0 -242
  173. package/prototypes/test/index.html +0 -1
  174. package/setup-dist-repo.sh +0 -68
  175. package/test-production-standards-engine.js +0 -130
  176. package/test-results.json +0 -2195
  177. package/test-safety-check.sh +0 -80
  178. package/work-item-tracking-plan.md +0 -199
  179. /package/{.jettypod/devpod.db → jettypod.db} +0 -0
@@ -1,85 +0,0 @@
1
- name: Test Safety Verification
2
-
3
- on:
4
- push:
5
- branches: [ main ]
6
- pull_request:
7
- branches: [ main ]
8
-
9
- jobs:
10
- test-safety:
11
- runs-on: ubuntu-latest
12
-
13
- steps:
14
- - uses: actions/checkout@v3
15
-
16
- - name: Setup Node.js
17
- uses: actions/setup-node@v3
18
- with:
19
- node-version: '18'
20
-
21
- - name: Install dependencies
22
- run: npm install
23
-
24
- - name: Create production snapshot
25
- run: |
26
- echo "Creating MD5 checksums of all production files..."
27
- find . -type f \( -name "*.json" -o -name "*.js" -o -name "*.md" \) \
28
- -not -path "./node_modules/*" \
29
- -not -path "./.git/*" \
30
- -not -path "./tmp/*" \
31
- | xargs md5sum > before-tests.md5
32
-
33
- echo "Recording package.json state..."
34
- cp package.json package.json.backup
35
-
36
- echo "Recording directory structure..."
37
- ls -la > before-tests-ls.txt
38
-
39
- - name: Run tests
40
- run: npm test
41
- continue-on-error: true
42
-
43
- - name: Verify no production changes
44
- run: |
45
- echo "Checking for file modifications..."
46
- find . -type f \( -name "*.json" -o -name "*.js" -o -name "*.md" \) \
47
- -not -path "./node_modules/*" \
48
- -not -path "./.git/*" \
49
- -not -path "./tmp/*" \
50
- | xargs md5sum > after-tests.md5
51
-
52
- echo "Comparing checksums..."
53
- if ! diff before-tests.md5 after-tests.md5; then
54
- echo "❌ CRITICAL: Tests modified production files!"
55
- echo "Modified files:"
56
- diff before-tests.md5 after-tests.md5 | grep "^[<>]"
57
- exit 1
58
- fi
59
-
60
- echo "Checking package.json..."
61
- if ! diff package.json.backup package.json; then
62
- echo "❌ CRITICAL: package.json was modified!"
63
- diff package.json.backup package.json
64
- exit 1
65
- fi
66
-
67
- echo "Checking for leaked test files..."
68
- ls -la > after-tests-ls.txt
69
- NEW_FILES=$(diff before-tests-ls.txt after-tests-ls.txt | grep "^>" | grep -E "(temp_|actual_|main|server|utils|Calculator|helper|app)" || true)
70
- if [ ! -z "$NEW_FILES" ]; then
71
- echo "❌ CRITICAL: Tests leaked files to production!"
72
- echo "$NEW_FILES"
73
- exit 1
74
- fi
75
-
76
- echo "✅ All safety checks passed - production directory unchanged"
77
-
78
- - name: Check for temp directory cleanup
79
- run: |
80
- echo "Checking /tmp for leaked test directories..."
81
- LEAKED_DIRS=$(ls -la /tmp | grep "devpod-test-" || true)
82
- if [ ! -z "$LEAKED_DIRS" ]; then
83
- echo "⚠️ WARNING: Test directories not cleaned up in /tmp:"
84
- echo "$LEAKED_DIRS"
85
- fi
@@ -1,5 +0,0 @@
1
- {
2
- "name": "jettypod-source",
3
- "mode": "discovery",
4
- "project_state": "internal"
5
- }
@@ -1,10 +0,0 @@
1
- {
2
- "id": 2,
3
- "title": "Test Epic",
4
- "type": "epic",
5
- "status": "backlog",
6
- "parent_id": null,
7
- "parent_title": null,
8
- "epic_id": null,
9
- "epic_title": null
10
- }
@@ -1,77 +0,0 @@
1
- # JettyPod Hooks
2
-
3
- ## protect-claude-md.js
4
-
5
- **Purpose**: Prevents Claude Code from directly editing protected sections of CLAUDE.md
6
-
7
- **Status**: ✅ Shipped (integrated in jettypod init)
8
-
9
- **What it does**:
10
- - Intercepts Edit/Write operations via Claude Code's PreToolUse hook
11
- - Blocks direct edits to: `<mode>`, `<stage>`, `<current_work>`, work status
12
- - Returns helpful errors: "Use: jettypod speed" instead of "forbidden"
13
- - Allows all other CLAUDE.md edits (mission, standards, etc.)
14
- - Zero impact on non-CLAUDE.md files
15
-
16
- **Installation**:
17
- Automatically installed when you run `jettypod init`. Hook is configured in `.claude/settings.json`.
18
-
19
- **Manual installation**:
20
- ```bash
21
- # Hook is already in .jettypod/hooks/
22
- # Just configure Claude Code:
23
- cat > .claude/settings.json << 'EOF'
24
- {
25
- "hooks": {
26
- "PreToolUse": [
27
- {
28
- "matcher": "Edit",
29
- "hooks": [{ "type": "command", "command": ".jettypod/hooks/protect-claude-md.js" }]
30
- },
31
- {
32
- "matcher": "Write",
33
- "hooks": [{ "type": "command", "command": ".jettypod/hooks/protect-claude-md.js" }]
34
- }
35
- ]
36
- }
37
- }
38
- EOF
39
- ```
40
-
41
- **Testing**:
42
- ```bash
43
- # Run built-in tests
44
- node .jettypod/hooks/protect-claude-md.js test
45
-
46
- # Test with sample edit
47
- echo '{
48
- "tool_name": "Edit",
49
- "tool_input": {
50
- "file_path": "CLAUDE.md",
51
- "old_string": "<mode>discovery</mode>",
52
- "new_string": "<mode>speed</mode>"
53
- }
54
- }' | .jettypod/hooks/protect-claude-md.js
55
- ```
56
-
57
- **Expected behavior**:
58
- When Claude tries to edit CLAUDE.md directly:
59
- ```
60
- ❌ Cannot change <mode> tag directly
61
-
62
- 💡 Hint: Use: jettypod speed
63
- ```
64
-
65
- **Debugging**:
66
- If hook isn't working:
67
- 1. Check `.claude/settings.json` exists with hook config
68
- 2. Verify hook is executable: `chmod +x .jettypod/hooks/protect-claude-md.js`
69
- 3. Test hook directly (see Testing above)
70
- 4. Check Claude Code version supports PreToolUse hooks
71
-
72
- **Known limitations**:
73
- - Can be bypassed with Bash redirection (`echo > CLAUDE.md`)
74
- - Not a concern in practice - Claude uses Edit tool by default
75
- - Could add Bash hook if bypass becomes common
76
-
77
- **Performance**: <10ms per edit check
@@ -1,338 +0,0 @@
1
- #!/usr/bin/env node
2
- // Prototype: Enforce jettypod command usage - Balanced (Claude Code Protocol)
3
- // Created: 2025-10-16
4
- // Purpose: PreToolUse hook that blocks direct CLAUDE.md edits and suggests jettypod commands
5
- // Decision: Updated to match actual Claude Code hook protocol
6
-
7
- /**
8
- * Claude Code PreToolUse Hook
9
- *
10
- * Intercepts Edit/Write operations on CLAUDE.md and blocks
11
- * forbidden patterns like mode changes or current_work updates.
12
- *
13
- * Configuration (add to ~/.claude/settings.json or .claude/settings.json):
14
- * {
15
- * "hooks": {
16
- * "PreToolUse": [
17
- * {
18
- * "matcher": "Edit",
19
- * "hooks": [
20
- * {
21
- * "type": "command",
22
- * "command": "./prototypes/2025-10-16-enforce-jettypod-balanced-v2.js"
23
- * }
24
- * ]
25
- * },
26
- * {
27
- * "matcher": "Write",
28
- * "hooks": [
29
- * {
30
- * "type": "command",
31
- * "command": "./prototypes/2025-10-16-enforce-jettypod-balanced-v2.js"
32
- * }
33
- * ]
34
- * }
35
- * ]
36
- * }
37
- * }
38
- *
39
- * Hook Input (via stdin):
40
- * {
41
- * "session_id": "...",
42
- * "transcript_path": "...",
43
- * "cwd": "...",
44
- * "hook_event_name": "PreToolUse",
45
- * "tool_name": "Edit" | "Write",
46
- * "tool_input": {
47
- * "file_path": "/path/to/CLAUDE.md",
48
- * "old_string": "original content", // Edit only
49
- * "new_string": "proposed new content", // Edit only
50
- * "content": "file content" // Write only
51
- * }
52
- * }
53
- *
54
- * Hook Output (to stdout):
55
- * {
56
- * "hookSpecificOutput": {
57
- * "hookEventName": "PreToolUse",
58
- * "permissionDecision": "allow" | "deny" | "ask",
59
- * "permissionDecisionReason": "Explanation"
60
- * }
61
- * }
62
- */
63
-
64
- const fs = require('fs');
65
-
66
- // Read hook input from stdin
67
- let input = '';
68
- process.stdin.on('data', chunk => input += chunk);
69
- process.stdin.on('end', () => {
70
- try {
71
- const hookInput = JSON.parse(input);
72
- const { tool_name, tool_input, cwd } = hookInput;
73
-
74
- // Only check CLAUDE.md edits
75
- if (!tool_input.file_path || !tool_input.file_path.endsWith('CLAUDE.md')) {
76
- allowEdit();
77
- return;
78
- }
79
-
80
- let oldContent, newContent;
81
-
82
- if (tool_name === 'Edit') {
83
- oldContent = tool_input.old_string;
84
- newContent = tool_input.new_string;
85
- } else if (tool_name === 'Write') {
86
- // For Write, read the current file content (if exists) to compare
87
- try {
88
- oldContent = fs.readFileSync(tool_input.file_path, 'utf8');
89
- newContent = tool_input.content;
90
- } catch (err) {
91
- // File doesn't exist yet - allow new file creation
92
- allowEdit();
93
- return;
94
- }
95
- } else {
96
- // Unknown tool
97
- allowEdit();
98
- return;
99
- }
100
-
101
- const result = checkEdit(oldContent, newContent);
102
-
103
- if (result.blocked) {
104
- denyEdit(result.message, result.suggestion);
105
- } else {
106
- allowEdit();
107
- }
108
-
109
- } catch (err) {
110
- // If we can't parse input, allow the edit (fail open)
111
- console.error('Hook error:', err.message);
112
- allowEdit();
113
- }
114
- });
115
-
116
- /**
117
- * Allow the edit
118
- */
119
- function allowEdit() {
120
- console.log(JSON.stringify({
121
- hookSpecificOutput: {
122
- hookEventName: "PreToolUse",
123
- permissionDecision: "allow"
124
- }
125
- }));
126
- process.exit(0);
127
- }
128
-
129
- /**
130
- * Deny the edit with explanation
131
- */
132
- function denyEdit(message, suggestion) {
133
- const reason = `❌ ${message}\n\n💡 Hint: ${suggestion}`;
134
-
135
- console.log(JSON.stringify({
136
- hookSpecificOutput: {
137
- hookEventName: "PreToolUse",
138
- permissionDecision: "deny",
139
- permissionDecisionReason: reason
140
- }
141
- }));
142
- process.exit(0);
143
- }
144
-
145
- /**
146
- * Pattern definitions for forbidden edits
147
- */
148
- const FORBIDDEN_PATTERNS = [
149
- {
150
- name: 'mode_change',
151
- detect: (old, newStr) => {
152
- const oldMode = old.match(/<mode>(\w+)<\/mode>/);
153
- const newMode = newStr.match(/<mode>(\w+)<\/mode>/);
154
- return oldMode && newMode && oldMode[1] !== newMode[1];
155
- },
156
- message: 'Cannot change <mode> tag directly',
157
- suggestion: (old, newStr) => {
158
- const newMode = newStr.match(/<mode>(\w+)<\/mode>/)?.[1];
159
- return `Use: jettypod ${newMode}`;
160
- }
161
- },
162
- {
163
- name: 'current_work_change',
164
- detect: (old, newStr) => {
165
- const oldWork = old.match(/<current_work>[\s\S]*?<\/current_work>/);
166
- const newWork = newStr.match(/<current_work>[\s\S]*?<\/current_work>/);
167
-
168
- // Block if current_work section content changes
169
- if (oldWork && newWork && oldWork[0] !== newWork[0]) {
170
- return true;
171
- }
172
-
173
- // Block if adding/removing current_work section
174
- if ((!oldWork && newWork) || (oldWork && !newWork)) {
175
- return true;
176
- }
177
-
178
- return false;
179
- },
180
- message: 'Cannot modify <current_work> section directly',
181
- suggestion: (old, newStr) => {
182
- const workId = newStr.match(/Working on: \[#(\d+)\]/)?.[1];
183
- if (workId) {
184
- return `Use: jettypod work start ${workId}`;
185
- }
186
- return 'Use: jettypod work start <id> or jettypod work stop';
187
- }
188
- },
189
- {
190
- name: 'work_status_change',
191
- detect: (old, newStr) => {
192
- const oldStatus = old.match(/Status: (\w+)/);
193
- const newStatus = newStr.match(/Status: (\w+)/);
194
- return oldStatus && newStatus && oldStatus[1] !== newStatus[1];
195
- },
196
- message: 'Cannot change work status directly',
197
- suggestion: (old, newStr) => {
198
- const workId = newStr.match(/Working on: \[#(\d+)\]/)?.[1];
199
- const newStatus = newStr.match(/Status: (\w+)/)?.[1];
200
- if (workId && newStatus) {
201
- return `Use: jettypod work status ${workId} ${newStatus}`;
202
- }
203
- return 'Use: jettypod work status <id> <status>';
204
- }
205
- },
206
- {
207
- name: 'stage_change',
208
- detect: (old, newStr) => {
209
- const oldStage = old.match(/<stage>(\w+)<\/stage>/);
210
- const newStage = newStr.match(/<stage>(\w+)<\/stage>/);
211
- return oldStage && newStage && oldStage[1] !== newStage[1];
212
- },
213
- message: 'Cannot change <stage> tag directly',
214
- suggestion: (old, newStr) => {
215
- const newStage = newStr.match(/<stage>(\w+)<\/stage>/)?.[1];
216
- return `Use: jettypod stage ${newStage}`;
217
- }
218
- }
219
- ];
220
-
221
- /**
222
- * Check if an edit should be blocked
223
- */
224
- function checkEdit(oldStr, newStr) {
225
- for (const pattern of FORBIDDEN_PATTERNS) {
226
- if (pattern.detect(oldStr, newStr)) {
227
- return {
228
- blocked: true,
229
- pattern: pattern.name,
230
- message: pattern.message,
231
- suggestion: pattern.suggestion(oldStr, newStr)
232
- };
233
- }
234
- }
235
-
236
- return { blocked: false };
237
- }
238
-
239
- /**
240
- * Test cases (run with: node prototypes/2025-10-16-enforce-jettypod-balanced-v2.js test)
241
- */
242
- if (process.argv[2] === 'test') {
243
- console.log('Running tests...\n');
244
-
245
- const tests = [
246
- {
247
- name: 'Block mode change (Edit)',
248
- input: {
249
- tool_name: 'Edit',
250
- tool_input: {
251
- file_path: '/path/to/CLAUDE.md',
252
- old_string: '<mode>discovery</mode>',
253
- new_string: '<mode>speed</mode>'
254
- }
255
- },
256
- shouldBlock: true
257
- },
258
- {
259
- name: 'Block current_work addition (Edit)',
260
- input: {
261
- tool_name: 'Edit',
262
- tool_input: {
263
- file_path: '/path/to/CLAUDE.md',
264
- old_string: '<project_summary>test</project_summary>',
265
- new_string: '<current_work>Working on: [#75]</current_work>'
266
- }
267
- },
268
- shouldBlock: true
269
- },
270
- {
271
- name: 'Block status change (Edit)',
272
- input: {
273
- tool_name: 'Edit',
274
- tool_input: {
275
- file_path: '/path/to/CLAUDE.md',
276
- old_string: 'Status: in_progress',
277
- new_string: 'Status: done'
278
- }
279
- },
280
- shouldBlock: true
281
- },
282
- {
283
- name: 'Allow other edits (Edit)',
284
- input: {
285
- tool_name: 'Edit',
286
- tool_input: {
287
- file_path: '/path/to/CLAUDE.md',
288
- old_string: '<mission>Old mission</mission>',
289
- new_string: '<mission>New mission</mission>'
290
- }
291
- },
292
- shouldBlock: false
293
- },
294
- {
295
- name: 'Allow non-CLAUDE.md edits',
296
- input: {
297
- tool_name: 'Edit',
298
- tool_input: {
299
- file_path: '/path/to/src/index.js',
300
- old_string: 'const x = 1',
301
- new_string: 'const x = 2'
302
- }
303
- },
304
- shouldBlock: false
305
- }
306
- ];
307
-
308
- let passed = 0;
309
- let failed = 0;
310
-
311
- tests.forEach(test => {
312
- const toolInput = test.input.tool_input;
313
- const oldStr = toolInput.old_string || '';
314
- const newStr = toolInput.new_string || '';
315
-
316
- // Skip file check for testing
317
- const isClaudeMd = toolInput.file_path.endsWith('CLAUDE.md');
318
- const result = isClaudeMd ? checkEdit(oldStr, newStr) : { blocked: false };
319
- const matches = result.blocked === test.shouldBlock;
320
-
321
- if (matches) {
322
- console.log(`✅ ${test.name}`);
323
- if (result.blocked) {
324
- console.log(` Message: ${result.message}`);
325
- console.log(` Suggestion: ${result.suggestion}`);
326
- }
327
- passed++;
328
- } else {
329
- console.log(`❌ ${test.name}`);
330
- console.log(` Expected blocked=${test.shouldBlock}, got blocked=${result.blocked}`);
331
- failed++;
332
- }
333
- console.log();
334
- });
335
-
336
- console.log(`Results: ${passed} passed, ${failed} failed`);
337
- process.exit(failed > 0 ? 1 : 0);
338
- }
Binary file
package/.jettypod/work.db DELETED
Binary file
package/CLAUDE.md DELETED
@@ -1,49 +0,0 @@
1
- <claude_context project="jettypod-source">
2
-
3
- <current_work>
4
- Working on: [#2] Test Epic (epic)
5
- Status: backlog
6
- </current_work>
7
- <project_summary>
8
- Not yet set
9
- </project_summary>
10
- <project_state>
11
- internal - Internal (team only, staging/preview - no external users)
12
- </project_state>
13
- <mission>
14
- undefined
15
- </mission>
16
- <tech_stack>
17
- Node.js, Jest
18
- </tech_stack>
19
- </claude_context>
20
- <jettypod_essentials>
21
- JettyPod: Structured workflow system with skills that guide complex workflows.
22
-
23
- ## ⚠️ CRITICAL: Skills are MANDATORY for workflows
24
- Skills auto-activate and MUST complete their full workflow:
25
- - epic-planning: Guides architectural decisions
26
- - feature-planning: Guides UX discovery + BDD scenarios
27
- - speed-mode: Implements happy path, THEN auto-generates stable chores
28
- - stable-mode: Adds error handling to speed implementation
29
- - external-transition: Guides launch preparation
30
-
31
- ❌ DO NOT bypass skills by manually running commands halfway through
32
- ❌ DO NOT mark work complete until skill finishes its ENTIRE workflow
33
- ❌ DO NOT manually create chores when a skill should generate them
34
- ✅ ALWAYS let skills complete autonomously before taking manual actions
35
-
36
- ## Basic Commands (for non-workflow operations)
37
- jettypod work create epic "<title>"
38
- jettypod work create feature "<title>" --parent=<id>
39
- jettypod work start <id>
40
- jettypod work status <id> cancelled
41
- jettypod backlog
42
-
43
- ## Advanced Commands
44
- For mode management, decisions, project state: docs/COMMAND_REFERENCE.md
45
- </jettypod_essentials>
46
-
47
- <communication_style>
48
- Be direct and opinionated. Skip hedging, apologies, and excessive politeness. Lead with the main point, challenge flawed ideas, give honest assessments even if unwelcome. Respond to what's literally asked, not what's "helpful". Prioritize brevity and practical utility over comprehensiveness.
49
- </communication_style>