jettypod 4.4.87 → 4.4.89

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.
@@ -223,10 +223,23 @@ function evaluateBashCommand(command, inputRef, cwd) {
223
223
  if (/jettypod\s+(work|tests)\s+merge\b/.test(strippedCommand)) {
224
224
  const isInWorktree = cwd && cwd.includes('.jettypod-work');
225
225
  if (isInWorktree) {
226
+ // Extract main repo path and work item ID for helpful error message
227
+ const mainRepoPath = cwd.split('.jettypod-work')[0].replace(/\/$/, '');
228
+ const workIdMatch = strippedCommand.match(/merge\s+(\d+)/);
229
+ const workId = workIdMatch ? workIdMatch[1] : '<id>';
230
+
226
231
  return {
227
232
  allowed: false,
228
233
  message: 'Cannot merge from inside a worktree',
229
- hint: 'Merging deletes the worktree. Run from main repo: cd <main-repo-path> && jettypod work merge\n\nNote: "cd path && jettypod work merge" won\'t work - hooks check CWD before cd runs. Run cd separately first.'
234
+ hint: `Current CWD: ${cwd}
235
+ Main repo: ${mainRepoPath}
236
+
237
+ Run these as TWO SEPARATE Bash calls:
238
+
239
+ 1. cd ${mainRepoPath}
240
+ 2. jettypod work merge ${workId}
241
+
242
+ Why: Hooks check CWD before 'cd &&' executes, so chained commands fail.`
230
243
  };
231
244
  }
232
245
  }
@@ -384,7 +397,7 @@ function evaluateWriteOperation(filePath, inputWorktreePath, cwd) {
384
397
  return {
385
398
  allowed: false,
386
399
  message: 'Cannot write to main repository',
387
- hint: 'Use jettypod work start to create a worktree first.'
400
+ hint: 'Invoke the request-routing skill first to plan and create work items properly.'
388
401
  };
389
402
  }
390
403
 
package/jettypod.js CHANGED
@@ -701,8 +701,29 @@ async function generateClaude(options = {}) {
701
701
  const currentConfig = config.read();
702
702
 
703
703
  const content = await claude.generate(currentConfig, options);
704
+
705
+ // Check if content actually changed
706
+ const existingContent = fs.existsSync('CLAUDE.md') ? fs.readFileSync('CLAUDE.md', 'utf-8') : '';
707
+ const contentChanged = content !== existingContent;
708
+
709
+ if (!contentChanged) {
710
+ return; // No changes needed
711
+ }
712
+
704
713
  fs.writeFileSync('CLAUDE.md', content);
705
714
  console.log('📝 CLAUDE.md generated');
715
+
716
+ // Auto-commit if requested (for commands that legitimately update CLAUDE.md)
717
+ if (options.autoCommit) {
718
+ try {
719
+ const { execSync } = require('child_process');
720
+ execSync('git add CLAUDE.md', { stdio: 'ignore' });
721
+ execSync('git commit -m "chore: update CLAUDE.md"', { stdio: 'ignore' });
722
+ console.log('✅ CLAUDE.md changes committed');
723
+ } catch (err) {
724
+ // Commit may fail if nothing staged or not in a git repo - that's ok
725
+ }
726
+ }
706
727
  }
707
728
 
708
729
  // Ensure Claude Code hooks are up to date (called on every jettypod launch)
@@ -767,9 +788,9 @@ function ensureClaudeHooks() {
767
788
  }
768
789
  }
769
790
 
770
- // Write updated settings
771
- fs.writeFileSync(claudeSettingsPath, JSON.stringify(claudeSettings, null, 2));
791
+ // Only write settings if hooks were actually updated (avoid untracked changes in main)
772
792
  if (hooksUpdated) {
793
+ fs.writeFileSync(claudeSettingsPath, JSON.stringify(claudeSettings, null, 2));
773
794
  console.log('⚙️ Claude Code hooks updated');
774
795
  }
775
796
 
@@ -1263,6 +1284,21 @@ switch (command) {
1263
1284
 
1264
1285
  // Ensure session.md is gitignored (fixes existing projects)
1265
1286
  ensureJettypodGitignores();
1287
+
1288
+ // Auto-commit any changes made by update (skills, hooks, gitignore, etc.)
1289
+ // This prevents untracked changes from breaking worktree merges
1290
+ try {
1291
+ const { execSync } = require('child_process');
1292
+ // Check if there are any changes to commit
1293
+ const status = execSync('git status --porcelain', { encoding: 'utf-8' });
1294
+ if (status.trim()) {
1295
+ execSync('git add -A', { stdio: 'ignore' });
1296
+ execSync('git commit -m "chore: jettypod update - refresh skills and hooks"', { stdio: 'ignore' });
1297
+ console.log('✅ Update changes committed');
1298
+ }
1299
+ } catch (err) {
1300
+ // Commit may fail if not in a git repo or nothing to commit - that's ok
1301
+ }
1266
1302
  }
1267
1303
 
1268
1304
  process.exit(success ? 0 : 1);
@@ -1282,12 +1318,12 @@ switch (command) {
1282
1318
  }
1283
1319
  config.update({ description });
1284
1320
  console.log('✅ Project description updated');
1285
- await generateClaude();
1321
+ await generateClaude({ autoCommit: true });
1286
1322
  break;
1287
1323
 
1288
1324
  case 'generate':
1289
1325
  // Show directive only when explicitly using generate command
1290
- await generateClaude({ showDirective: true });
1326
+ await generateClaude({ showDirective: true, autoCommit: true });
1291
1327
  break;
1292
1328
 
1293
1329
  case 'work':
@@ -1914,7 +1950,7 @@ switch (command) {
1914
1950
  console.log('⚠️ Remember: Customer-facing features MUST use Production mode');
1915
1951
  console.log('');
1916
1952
 
1917
- await generateClaude();
1953
+ await generateClaude({ autoCommit: true });
1918
1954
  } catch (err) {
1919
1955
  console.error(`Error: ${err.message}`);
1920
1956
  process.exit(1);
@@ -1977,7 +2013,7 @@ switch (command) {
1977
2013
  console.log(' 4. Run: jettypod project discover complete --winner=<path> --rationale="<reason>"');
1978
2014
  console.log('');
1979
2015
 
1980
- await generateClaude();
2016
+ await generateClaude({ autoCommit: true });
1981
2017
  console.log('📝 CLAUDE.md updated with discovery context');
1982
2018
 
1983
2019
  } catch (err) {
@@ -2062,7 +2098,7 @@ switch (command) {
2062
2098
  const checkpoint = require('./lib/discovery-checkpoint');
2063
2099
  checkpoint.clearCheckpoint();
2064
2100
 
2065
- await generateClaude();
2101
+ await generateClaude({ autoCommit: true });
2066
2102
 
2067
2103
  console.log('✅ Project discovery complete!');
2068
2104
  console.log('');
@@ -2070,7 +2106,7 @@ switch (command) {
2070
2106
  console.log(`Rationale: ${rationale}`);
2071
2107
  console.log('');
2072
2108
 
2073
- await generateClaude();
2109
+ // Note: duplicate call removed - generateClaude already called above
2074
2110
  console.log('📝 CLAUDE.md updated');
2075
2111
  console.log('');
2076
2112
 
@@ -2123,11 +2159,15 @@ switch (command) {
2123
2159
  // New project - auto-initialize
2124
2160
  await initializeProject();
2125
2161
  } else {
2126
- // Project exists - launch dashboard and regenerate CLAUDE.md
2162
+ // Project exists - launch dashboard
2127
2163
  const currentConfig = config.read();
2128
- await generateClaude();
2129
2164
 
2130
- // Ensure Claude Code hooks are up to date on every launch
2165
+ // Only generate CLAUDE.md if it doesn't exist (avoid untracked changes in main)
2166
+ if (!fs.existsSync('CLAUDE.md')) {
2167
+ await generateClaude();
2168
+ }
2169
+
2170
+ // Ensure Claude Code hooks are up to date on every launch (only writes if changed)
2131
2171
  ensureClaudeHooks();
2132
2172
 
2133
2173
  // Launch dashboard
@@ -2804,9 +2844,12 @@ Quick commands:
2804
2844
  'speed-mode': ['feature_planning_complete'],
2805
2845
  'stable-mode': ['speed_mode_complete'],
2806
2846
  'production-mode': ['stable_mode_complete'],
2847
+ 'chore-mode': ['chore_planning_complete'],
2848
+ 'bug-mode': ['bug_planning_complete'],
2807
2849
  'feature-planning': [],
2808
2850
  'epic-planning': [],
2809
- 'chore-planning': []
2851
+ 'chore-planning': [],
2852
+ 'bug-planning': []
2810
2853
  };
2811
2854
 
2812
2855
  // Validate skill name
@@ -3170,7 +3213,10 @@ Quick commands:
3170
3213
  } else {
3171
3214
  // Already initialized - show smart guidance
3172
3215
  const currentConfig = config.read();
3173
- await generateClaude();
3216
+ // Only generate CLAUDE.md if it doesn't exist (avoid untracked changes)
3217
+ if (!fs.existsSync('CLAUDE.md')) {
3218
+ await generateClaude();
3219
+ }
3174
3220
 
3175
3221
  const discovery = currentConfig.project_discovery;
3176
3222
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jettypod",
3
- "version": "4.4.87",
3
+ "version": "4.4.89",
4
4
  "description": "AI-powered development workflow manager with TDD, BDD, and automatic test generation",
5
5
  "main": "jettypod.js",
6
6
  "bin": {
@@ -235,10 +235,17 @@ git commit -m "fix: [brief description]
235
235
  Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>"
236
236
  ```
237
237
 
238
- **Then merge (from main repo):**
238
+ **Then merge (CRITICAL: run as separate Bash calls):**
239
+
240
+ ⚠️ Shell CWD persists. You MUST run `cd` as a SEPARATE Bash tool call before merge.
239
241
 
240
242
  ```bash
243
+ # Bash call 1: Change to main repo
241
244
  cd <main-repo-path>
245
+ ```
246
+
247
+ ```bash
248
+ # Bash call 2: Merge and cleanup
242
249
  jettypod work merge <chore-id>
243
250
  jettypod work cleanup <chore-id>
244
251
  ```
@@ -316,8 +323,9 @@ jettypod work create chore "<title>" "<description>" --parent=<feature-id>
316
323
  # Start chore
317
324
  jettypod work start <chore-id>
318
325
 
319
- # Merge (from main repo)
320
- cd <main-repo> && jettypod work merge <chore-id>
326
+ # Merge (CRITICAL: separate Bash calls - cd first, then merge)
327
+ cd <main-repo> # Bash call 1
328
+ jettypod work merge <chore-id> # Bash call 2
321
329
 
322
330
  # Cleanup
323
331
  jettypod work cleanup <chore-id>
@@ -855,10 +855,14 @@ jettypod work create chore "[Chore title]" "[Description with scenarios addresse
855
855
 
856
856
  Repeat for each confirmed chore. **Do NOT use `--mode` flag** - chores inherit mode from their parent feature.
857
857
 
858
- **3. Release merge lock:**
858
+ **3. Release merge lock (CRITICAL: separate Bash calls):**
859
859
 
860
860
  ```bash
861
- cd <main-repo> && jettypod work merge --release-lock
861
+ cd <main-repo> # Bash call 1
862
+ ```
863
+
864
+ ```bash
865
+ jettypod work merge --release-lock # Bash call 2
862
866
  ```
863
867
 
864
868
  **🔄 WORKFLOW COMPLETE: Speed mode finished**
@@ -957,12 +961,17 @@ Before ending speed-mode skill, ensure:
957
961
 
958
962
  ## Command Reference
959
963
 
960
- **Complete chores (CRITICAL: cd to main repo BEFORE merge - worktree will be deleted):**
964
+ **Complete chores (CRITICAL: run cd and merge as SEPARATE Bash calls):**
965
+ ```bash
966
+ # Bash call 1: Change to main repo
967
+ cd <main-repo>
968
+ ```
961
969
  ```bash
962
- cd <main-repo> && jettypod work merge <id> # Merge chore by ID (recommended)
963
- cd <main-repo> && jettypod work merge # Merge current chore
964
- cd <main-repo> && jettypod work merge --with-transition # Hold lock for transition
965
- cd <main-repo> && jettypod work merge --release-lock # Release held lock
970
+ # Bash call 2: Merge (pick one)
971
+ jettypod work merge <id> # Merge chore by ID (recommended)
972
+ jettypod work merge # Merge current chore
973
+ jettypod work merge --with-transition # Hold lock for transition
974
+ jettypod work merge --release-lock # Release held lock
966
975
  ```
967
976
 
968
977
  **Start chores:**
@@ -773,10 +773,15 @@ Before ending stable-mode skill, ensure:
773
773
 
774
774
  ## Command Reference
775
775
 
776
- **Complete chores (CRITICAL: cd to main repo BEFORE merge - worktree will be deleted):**
776
+ **Complete chores (CRITICAL: run cd and merge as SEPARATE Bash calls):**
777
777
  ```bash
778
- cd <main-repo> && jettypod work merge <id> # Merge chore by ID (recommended)
779
- cd <main-repo> && jettypod work merge # Merge current chore
778
+ # Bash call 1: Change to main repo
779
+ cd <main-repo>
780
+ ```
781
+ ```bash
782
+ # Bash call 2: Merge (pick one)
783
+ jettypod work merge <id> # Merge chore by ID (recommended)
784
+ jettypod work merge # Merge current chore
780
785
  ```
781
786
 
782
787
  **Start chores:**
@@ -806,7 +811,7 @@ jettypod work set-mode <feature-id> production # Set feature to production mode
806
811
  - Parallel worktrees branch from main independently
807
812
 
808
813
  **Process:**
809
- 1. Complete chore → `cd <main-repo> && jettypod work merge` (CRITICAL: cd first!)
814
+ 1. Complete chore → run `cd <main-repo>` then `jettypod work merge` as SEPARATE Bash calls
810
815
  2. Start next chore → `jettypod work start <next-id>`
811
816
  3. Repeat
812
817