jettypod 4.4.97 → 4.4.99

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/jettypod.js CHANGED
@@ -1310,12 +1310,19 @@ switch (command) {
1310
1310
  // Check if there are any changes to commit
1311
1311
  const status = execSync('git status --porcelain', { encoding: 'utf-8' });
1312
1312
  if (status.trim()) {
1313
- execSync('git add -A', { stdio: 'ignore' });
1314
- execSync('git commit -m "chore: jettypod update - refresh skills and hooks"', { stdio: 'ignore' });
1313
+ execSync('git add -A');
1314
+ // Use --no-verify to bypass pre-commit hooks - this is an automated system update
1315
+ execSync('git commit --no-verify -m "chore: jettypod update - refresh skills and hooks"');
1315
1316
  console.log('✅ Update changes committed');
1316
1317
  }
1317
1318
  } catch (err) {
1318
- // Commit may fail if not in a git repo or nothing to commit - that's ok
1319
+ // Log the error so users know what happened
1320
+ console.log('');
1321
+ console.log('⚠️ Could not auto-commit skill updates');
1322
+ console.log(' Reason:', err.message.split('\n')[0]);
1323
+ console.log('');
1324
+ console.log(' You may have untracked changes in .claude/skills/');
1325
+ console.log(' Run: git add .claude && git commit -m "chore: update skills"');
1319
1326
  }
1320
1327
  }
1321
1328
 
@@ -59,6 +59,12 @@ if (!checkBranchRestriction()) {
59
59
 
60
60
  // Export database snapshots (runs for all commits where .jettypod exists)
61
61
  async function exportSnapshots() {
62
+ // Skip in worktrees - snapshots only matter for commits on main
63
+ // Worktrees can't git add files from main repo ("outside repository" error)
64
+ if (process.cwd().includes('.jettypod-work')) {
65
+ return;
66
+ }
67
+
62
68
  const jettypodDir = path.join(process.cwd(), '.jettypod');
63
69
  if (!fs.existsSync(jettypodDir)) {
64
70
  return; // No JettyPod directory, skip export
@@ -1508,9 +1508,20 @@ async function mergeWork(options = {}) {
1508
1508
  return Promise.reject(new Error(`Failed to check git status: ${err.message}`));
1509
1509
  }
1510
1510
 
1511
+ // Validate work item type BEFORE git operations
1512
+ // Only chores, bugs, and test worktrees can be merged directly
1513
+ const isTestWorktree = currentBranch.startsWith('tests/');
1514
+ if (!isTestWorktree && !['chore', 'bug'].includes(currentWork.type)) {
1515
+ return Promise.reject(new Error(
1516
+ `Cannot merge ${currentWork.type} #${currentWork.id} directly.\n\n` +
1517
+ `Only chores and bugs can be merged. Features complete when all their chores are done.\n` +
1518
+ `Test worktrees (tests/* branches) merge BDD scenarios without completing the feature.`
1519
+ ));
1520
+ }
1521
+
1511
1522
  console.log(`Merging work item #${currentWork.id}: ${currentWork.title}`);
1512
1523
  console.log(`Branch: ${currentBranch}`);
1513
-
1524
+
1514
1525
  // Step 1: Push feature branch to remote
1515
1526
  // NOTE: Use ['pipe', 'inherit', 'inherit'] instead of 'inherit' to avoid stealing stdin
1516
1527
  // from Claude Code's shell. Using 'inherit' for stdin breaks the shell when run interactively.
@@ -1724,10 +1735,8 @@ async function mergeWork(options = {}) {
1724
1735
 
1725
1736
  console.log(`✓ Successfully merged work item #${currentWork.id}`);
1726
1737
 
1727
- // Check if this is a test worktree (tests/ prefix) - only set scenario_file, don't mark done
1728
- const isTestWorktree = currentBranch.startsWith('tests/');
1729
-
1730
1738
  // Get worktree info from database (needed for cleanup message)
1739
+ // Note: isTestWorktree was already set before git operations for early validation
1731
1740
  const worktree = await new Promise((resolve, reject) => {
1732
1741
  db.get(
1733
1742
  `SELECT id, worktree_path, branch_name FROM worktrees WHERE work_item_id = ? AND status = 'active'`,
@@ -1775,16 +1784,17 @@ async function mergeWork(options = {}) {
1775
1784
 
1776
1785
  console.log(`✅ BDD tests merged for feature #${currentWork.id}`);
1777
1786
  console.log(' Feature remains in discovery phase - create chores to continue');
1778
- } else if (currentWork.type !== 'chore') {
1779
- // Non-test branch for a non-chore - this shouldn't happen
1787
+ } else if (!['chore', 'bug'].includes(currentWork.type)) {
1788
+ // Non-test branch for a non-mergeable type - should have been caught by early validation
1789
+ // but kept as defensive check
1780
1790
  return Promise.reject(new Error(
1781
1791
  `Cannot merge ${currentWork.type} #${currentWork.id} directly.\n\n` +
1782
- `Only chores can be merged. Features complete when all their chores are done.\n` +
1792
+ `Only chores and bugs can be merged. Features complete when all their chores are done.\n` +
1783
1793
  `Test worktrees (tests/* branches) merge BDD scenarios without completing the feature.`
1784
1794
  ));
1785
1795
  } else {
1786
- // Chore worktree: mark as done (existing behavior)
1787
- console.log('Marking chore as done...');
1796
+ // Chore or bug worktree: mark as done
1797
+ console.log(`Marking ${currentWork.type} as done...`);
1788
1798
  const completedAt = new Date().toISOString();
1789
1799
  await new Promise((resolve, reject) => {
1790
1800
  db.run(
@@ -1796,7 +1806,7 @@ async function mergeWork(options = {}) {
1796
1806
  }
1797
1807
  );
1798
1808
  });
1799
- console.log(`✅ Chore #${currentWork.id} marked as done`);
1809
+ console.log(`✅ ${currentWork.type.charAt(0).toUpperCase() + currentWork.type.slice(1)} #${currentWork.id} marked as done`);
1800
1810
  }
1801
1811
 
1802
1812
  // Mark worktree as merged but DON'T delete it yet
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jettypod",
3
- "version": "4.4.97",
3
+ "version": "4.4.99",
4
4
  "description": "AI-powered development workflow manager with TDD, BDD, and automatic test generation",
5
5
  "main": "jettypod.js",
6
6
  "bin": {
@@ -13,16 +13,20 @@ When this skill is activated, you are helping discover the best approach for a f
13
13
 
14
14
  ## 🔑 Critical Command Distinction
15
15
 
16
- **Four different commands, four different purposes:**
16
+ **Six commands in workflow order:**
17
17
 
18
18
  | Command | Used For | When | Phase |
19
19
  |---------|----------|------|-------|
20
+ | `work prototype start <feature-id> [approach]` | Create worktree for UX prototyping | After UX approaches proposed (Step 4) | Feature Planning |
21
+ | `work prototype merge <feature-id>` | Merge prototype to main | After user tests prototype (Step 4) | Feature Planning |
20
22
  | `work tests start <feature-id>` | Create worktree for test authoring | After Integration Contract (Step 7) | Feature Planning |
21
- | `work tests merge` → `cd` → `work cleanup` | Merge tests to main, then cleanup worktree | After chores created (Step 12) | Feature Planning |
22
23
  | `work implement <feature-id>` | Transition feature to implementation phase | After chores created (Step 11) | Feature Planning |
24
+ | `work tests merge` → `cd` → `work cleanup` | Merge tests to main, then cleanup worktree | After transition (Step 12) | Feature Planning |
23
25
  | `work start <chore-id>` | Start implementing a specific chore | After tests merged (Step 13) | Speed Mode |
24
26
 
25
27
  **CRITICAL:** All commands are run by **Claude**, not the user. The distinction is:
28
+ - `work prototype start` = Creates isolated worktree for UX prototyping (Step 4, optional)
29
+ - `work prototype merge` = Land prototype files on main (Step 4)
26
30
  - `work tests start` = Creates isolated worktree for BDD test authoring (Step 7)
27
31
  - `work implement` = Ends feature planning, transitions to implementation phase
28
32
  - `work tests merge` = Land BDD tests on main
@@ -192,10 +192,34 @@ Do NOT proceed to Step 3 until chore is successfully created.
192
192
  jettypod work start <chore-id>
193
193
  ```
194
194
 
195
+ **🛑 STOP AND CHECK:** Verify worktree was created successfully before proceeding.
196
+
197
+ ```bash
198
+ sqlite3 .jettypod/work.db "SELECT worktree_path FROM worktrees WHERE work_item_id = <chore-id> AND status = 'active'"
199
+ ```
200
+
201
+ **If empty or error:** Stop and investigate. Do NOT proceed without a valid worktree.
202
+
203
+ **Capture the worktree path:**
204
+ - `WORKTREE_PATH` - the absolute path from the query result (e.g., `/path/to/.jettypod-work/42-fix-button-text`)
205
+
206
+ **Display confirmation:**
207
+
208
+ ```
209
+ 📁 Worktree created: ${WORKTREE_PATH}
210
+
211
+ From this point forward, ALL file operations MUST use paths starting with:
212
+ ${WORKTREE_PATH}/
213
+ ```
214
+
215
+ **🔒 WORKTREE PATH LOCK:** Store `WORKTREE_PATH` - all file operations in this skill MUST use this path prefix.
216
+
217
+ ---
218
+
195
219
  **Then implement the change directly:**
196
220
 
197
- 1. Read the file(s) that need modification
198
- 2. Make the specific change requested
221
+ 1. Read the file(s) that need modification (using `${WORKTREE_PATH}/...`)
222
+ 2. Make the specific change requested (using `${WORKTREE_PATH}/...`)
199
223
  3. Verify the change looks correct
200
224
 
201
225
  **Display progress:**
@@ -203,7 +227,7 @@ jettypod work start <chore-id>
203
227
  ```
204
228
  📝 Implementing change...
205
229
 
206
- Modified: [file path]
230
+ Modified: ${WORKTREE_PATH}/[relative path]
207
231
  Change: [what was changed]
208
232
 
209
233
  Verifying...
@@ -224,9 +248,11 @@ Verifying...
224
248
 
225
249
  **If verification passes:**
226
250
 
251
+ **🔒 WORKTREE PATH REQUIRED:** Use the `WORKTREE_PATH` captured in Step 3.
252
+
227
253
  ```bash
228
254
  # Commit the change
229
- cd <worktree-path>
255
+ cd ${WORKTREE_PATH}
230
256
  git add .
231
257
  git commit -m "fix: [brief description]
232
258