jettypod 4.4.113 → 4.4.115

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.
@@ -151,14 +151,6 @@ function initializeJettypod(projectPath) {
151
151
  // The database (work.db) will be created automatically when getDb() is called
152
152
  // runMigrations() in getDb() will create all necessary tables
153
153
 
154
- // Seed onboarding epic for blank projects
155
- if (isBlankProject(projectPath)) {
156
- try {
157
- seedOnboardingEpic(projectPath);
158
- } catch (e) {
159
- console.error('Could not seed onboarding:', e.message);
160
- }
161
- }
162
154
  }
163
155
 
164
156
  /**
@@ -778,6 +770,15 @@ function registerIpcHandlers() {
778
770
  cachedDb = null;
779
771
  projectRoot = selectedPath;
780
772
 
773
+ // Seed onboarding epic for blank projects (safe to call every open - has dupe check)
774
+ if (isBlankProject(selectedPath)) {
775
+ try {
776
+ seedOnboardingEpic(selectedPath);
777
+ } catch (e) {
778
+ console.error('Could not seed onboarding:', e.message);
779
+ }
780
+ }
781
+
781
782
  // Add to recent projects list
782
783
  addRecentProject(selectedPath);
783
784
 
@@ -826,6 +827,15 @@ function registerIpcHandlers() {
826
827
  cachedDb = null;
827
828
  projectRoot = projectPath;
828
829
 
830
+ // Seed onboarding epic for blank projects (safe to call every open - has dupe check)
831
+ if (isBlankProject(projectPath)) {
832
+ try {
833
+ seedOnboardingEpic(projectPath);
834
+ } catch (e) {
835
+ console.error('Could not seed onboarding:', e.message);
836
+ }
837
+ }
838
+
829
839
  // Update recent projects (move to top)
830
840
  addRecentProject(projectPath);
831
841
 
@@ -94,22 +94,49 @@ export function getProjectName(): string {
94
94
  }
95
95
 
96
96
  // Ensure critical columns exist via ALTER TABLE, catching "duplicate column" errors.
97
- // Handles databases where migrations were falsely recorded as applied.
97
+ // Handles databases where migrations were falsely recorded as applied
98
+ // (the shim was missing db.serialize(), so migrations using it silently failed).
98
99
  function ensureColumns(db: Database.Database): void {
99
- const tryAdd = (col: string, type: string) => {
100
+ const tryAddTo = (table: string, col: string, type: string) => {
100
101
  try {
101
- db.exec(`ALTER TABLE work_items ADD COLUMN ${col} ${type}`);
102
+ db.exec(`ALTER TABLE ${table} ADD COLUMN ${col} ${type}`);
102
103
  } catch {
103
104
  // Column already exists - expected for healthy databases
104
105
  }
105
106
  };
106
107
  try {
107
- tryAdd('display_order', 'INTEGER DEFAULT NULL');
108
- tryAdd('rejection_reason', 'TEXT');
109
- tryAdd('rejected_at', 'TEXT');
108
+ tryAddTo('work_items', 'display_order', 'INTEGER DEFAULT NULL');
109
+ tryAddTo('work_items', 'rejection_reason', 'TEXT');
110
+ tryAddTo('work_items', 'rejected_at', 'TEXT');
110
111
  } catch {
111
112
  // Table might not exist yet - ensureSchema will handle it
112
113
  }
114
+
115
+ // claude_sessions columns from migrations 022-024 (used db.serialize which was missing)
116
+ try {
117
+ tryAddTo('claude_sessions', 'session_title', 'TEXT');
118
+ tryAddTo('claude_sessions', 'content', 'TEXT');
119
+ } catch {
120
+ // Table might not exist yet - migration 021 will create it
121
+ }
122
+
123
+ // Clear falsely-recorded migrations that used db.serialize() so they re-run properly.
124
+ // Only clear if we detect the column was actually missing (i.e. we just added it).
125
+ try {
126
+ const cols = db.prepare("PRAGMA table_info(claude_sessions)").all() as Array<{ name: string }>;
127
+ const hasSessionTitle = cols.some(c => c.name === 'session_title');
128
+ if (hasSessionTitle) {
129
+ // Check if work_item_id is still NOT NULL (migration 022 should make it nullable)
130
+ const workItemCol = cols.find(c => c.name === 'work_item_id') as { name: string; notnull: number } | undefined;
131
+ if (workItemCol && workItemCol.notnull === 1) {
132
+ // Column was added by our ALTER TABLE but migration 022 didn't actually run
133
+ // (it recreates the table with nullable work_item_id). Clear so it re-runs.
134
+ db.exec("DELETE FROM migrations WHERE id IN ('022-independent-sessions', '023-session-content-column', '024-session-orphaned-status')");
135
+ }
136
+ }
137
+ } catch {
138
+ // migrations table might not exist yet
139
+ }
113
140
  }
114
141
 
115
142
  // Singleton database connection - reused across all operations
@@ -49,6 +49,13 @@ function createDbShim(betterDb) {
49
49
  if (callback) callback(err);
50
50
  else throw err;
51
51
  }
52
+ },
53
+
54
+ // better-sqlite3 is synchronous, so serialize is a no-op — just call the function.
55
+ // Without this, migrations using db.serialize() silently fail inside their Promise
56
+ // constructor, get falsely recorded as applied, and never actually run.
57
+ serialize(fn) {
58
+ fn();
52
59
  }
53
60
  };
54
61
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jettypod",
3
- "version": "4.4.113",
3
+ "version": "4.4.115",
4
4
  "description": "AI-powered development workflow manager with TDD, BDD, and automatic test generation",
5
5
  "main": "jettypod.js",
6
6
  "bin": {