@compilr-dev/cli 0.4.0

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 (152) hide show
  1. package/README.md +110 -0
  2. package/dist/agent.d.ts +62 -0
  3. package/dist/agent.js +317 -0
  4. package/dist/agents/registry.d.ts +66 -0
  5. package/dist/agents/registry.js +238 -0
  6. package/dist/agents/types.d.ts +40 -0
  7. package/dist/agents/types.js +94 -0
  8. package/dist/commands/custom-registry.d.ts +69 -0
  9. package/dist/commands/custom-registry.js +246 -0
  10. package/dist/commands/index.d.ts +7 -0
  11. package/dist/commands/index.js +7 -0
  12. package/dist/commands/types.d.ts +31 -0
  13. package/dist/commands/types.js +26 -0
  14. package/dist/commands.d.ts +63 -0
  15. package/dist/commands.js +324 -0
  16. package/dist/db/index.d.ts +42 -0
  17. package/dist/db/index.js +146 -0
  18. package/dist/db/repositories/document-repository.d.ts +63 -0
  19. package/dist/db/repositories/document-repository.js +184 -0
  20. package/dist/db/repositories/index.d.ts +9 -0
  21. package/dist/db/repositories/index.js +6 -0
  22. package/dist/db/repositories/project-repository.d.ts +132 -0
  23. package/dist/db/repositories/project-repository.js +337 -0
  24. package/dist/db/repositories/work-item-repository.d.ts +115 -0
  25. package/dist/db/repositories/work-item-repository.js +389 -0
  26. package/dist/db/schema.d.ts +83 -0
  27. package/dist/db/schema.js +143 -0
  28. package/dist/debug.d.ts +8 -0
  29. package/dist/debug.js +48 -0
  30. package/dist/index.d.ts +2 -0
  31. package/dist/index.js +348 -0
  32. package/dist/index.old.d.ts +7 -0
  33. package/dist/index.old.js +1014 -0
  34. package/dist/repl.d.ts +121 -0
  35. package/dist/repl.js +1878 -0
  36. package/dist/settings/index.d.ts +80 -0
  37. package/dist/settings/index.js +195 -0
  38. package/dist/shared-handlers.d.ts +63 -0
  39. package/dist/shared-handlers.js +57 -0
  40. package/dist/slash-autocomplete.d.ts +41 -0
  41. package/dist/slash-autocomplete.js +638 -0
  42. package/dist/state.d.ts +75 -0
  43. package/dist/state.js +130 -0
  44. package/dist/tabbed-menu.d.ts +11 -0
  45. package/dist/tabbed-menu.js +328 -0
  46. package/dist/templates/backlog-md.d.ts +7 -0
  47. package/dist/templates/backlog-md.js +94 -0
  48. package/dist/templates/claude-md.d.ts +7 -0
  49. package/dist/templates/claude-md.js +189 -0
  50. package/dist/templates/coding-standards.d.ts +7 -0
  51. package/dist/templates/coding-standards.js +299 -0
  52. package/dist/templates/compilr-md.d.ts +7 -0
  53. package/dist/templates/compilr-md.js +189 -0
  54. package/dist/templates/config-json.d.ts +38 -0
  55. package/dist/templates/config-json.js +39 -0
  56. package/dist/templates/gitignore.d.ts +7 -0
  57. package/dist/templates/gitignore.js +85 -0
  58. package/dist/templates/index.d.ts +19 -0
  59. package/dist/templates/index.js +302 -0
  60. package/dist/templates/package-json.d.ts +7 -0
  61. package/dist/templates/package-json.js +111 -0
  62. package/dist/templates/readme-md.d.ts +7 -0
  63. package/dist/templates/readme-md.js +161 -0
  64. package/dist/templates/tsconfig.d.ts +7 -0
  65. package/dist/templates/tsconfig.js +61 -0
  66. package/dist/templates/types.d.ts +33 -0
  67. package/dist/templates/types.js +24 -0
  68. package/dist/test-autocomplete.d.ts +7 -0
  69. package/dist/test-autocomplete.js +85 -0
  70. package/dist/test-tabbed-menu.d.ts +7 -0
  71. package/dist/test-tabbed-menu.js +25 -0
  72. package/dist/themes/colors.d.ts +49 -0
  73. package/dist/themes/colors.js +135 -0
  74. package/dist/themes/index.d.ts +23 -0
  75. package/dist/themes/index.js +24 -0
  76. package/dist/themes/registry.d.ts +60 -0
  77. package/dist/themes/registry.js +195 -0
  78. package/dist/themes/types.d.ts +82 -0
  79. package/dist/themes/types.js +7 -0
  80. package/dist/tool-selector.d.ts +71 -0
  81. package/dist/tool-selector.js +184 -0
  82. package/dist/tools/ask-user-simple.d.ts +19 -0
  83. package/dist/tools/ask-user-simple.js +86 -0
  84. package/dist/tools/ask-user.d.ts +32 -0
  85. package/dist/tools/ask-user.js +113 -0
  86. package/dist/tools/backlog.d.ts +53 -0
  87. package/dist/tools/backlog.js +709 -0
  88. package/dist/tools.d.ts +15 -0
  89. package/dist/tools.js +121 -0
  90. package/dist/ui/agents-overlay.d.ts +12 -0
  91. package/dist/ui/agents-overlay.js +501 -0
  92. package/dist/ui/arch-type-overlay.d.ts +20 -0
  93. package/dist/ui/arch-type-overlay.js +229 -0
  94. package/dist/ui/ask-user-overlay.d.ts +26 -0
  95. package/dist/ui/ask-user-overlay.js +647 -0
  96. package/dist/ui/ask-user-simple-overlay.d.ts +25 -0
  97. package/dist/ui/ask-user-simple-overlay.js +242 -0
  98. package/dist/ui/backlog-overlay.d.ts +17 -0
  99. package/dist/ui/backlog-overlay.js +786 -0
  100. package/dist/ui/commands-overlay.d.ts +11 -0
  101. package/dist/ui/commands-overlay.js +410 -0
  102. package/dist/ui/config-overlay.d.ts +34 -0
  103. package/dist/ui/config-overlay.js +977 -0
  104. package/dist/ui/conversation.d.ts +82 -0
  105. package/dist/ui/conversation.js +508 -0
  106. package/dist/ui/diff.d.ts +38 -0
  107. package/dist/ui/diff.js +182 -0
  108. package/dist/ui/ephemeral.d.ts +111 -0
  109. package/dist/ui/ephemeral.js +413 -0
  110. package/dist/ui/file-autocomplete.d.ts +45 -0
  111. package/dist/ui/file-autocomplete.js +237 -0
  112. package/dist/ui/footer.d.ts +153 -0
  113. package/dist/ui/footer.js +422 -0
  114. package/dist/ui/index.d.ts +12 -0
  115. package/dist/ui/index.js +15 -0
  116. package/dist/ui/init-overlay.d.ts +24 -0
  117. package/dist/ui/init-overlay.js +525 -0
  118. package/dist/ui/input-prompt-v2.d.ts +179 -0
  119. package/dist/ui/input-prompt-v2.js +991 -0
  120. package/dist/ui/input-prompt.d.ts +97 -0
  121. package/dist/ui/input-prompt.js +800 -0
  122. package/dist/ui/iteration-limit-overlay.d.ts +21 -0
  123. package/dist/ui/iteration-limit-overlay.js +150 -0
  124. package/dist/ui/keys-overlay.d.ts +14 -0
  125. package/dist/ui/keys-overlay.js +181 -0
  126. package/dist/ui/model-warning-overlay.d.ts +30 -0
  127. package/dist/ui/model-warning-overlay.js +171 -0
  128. package/dist/ui/overlay-controller.d.ts +25 -0
  129. package/dist/ui/overlay-controller.js +35 -0
  130. package/dist/ui/overlays.d.ts +47 -0
  131. package/dist/ui/overlays.js +627 -0
  132. package/dist/ui/permission-overlay.d.ts +16 -0
  133. package/dist/ui/permission-overlay.js +494 -0
  134. package/dist/ui/terminal.d.ts +117 -0
  135. package/dist/ui/terminal.js +237 -0
  136. package/dist/ui/todo-zone.d.ts +112 -0
  137. package/dist/ui/todo-zone.js +353 -0
  138. package/dist/ui/tools-overlay.d.ts +26 -0
  139. package/dist/ui/tools-overlay.js +278 -0
  140. package/dist/ui/tutorial-overlay.d.ts +10 -0
  141. package/dist/ui/tutorial-overlay.js +936 -0
  142. package/dist/ui/types.d.ts +103 -0
  143. package/dist/ui/types.js +33 -0
  144. package/dist/utils/credentials.d.ts +55 -0
  145. package/dist/utils/credentials.js +268 -0
  146. package/dist/utils/model-tiers.d.ts +37 -0
  147. package/dist/utils/model-tiers.js +118 -0
  148. package/dist/utils/project-memory.d.ts +47 -0
  149. package/dist/utils/project-memory.js +117 -0
  150. package/dist/utils/project-status.d.ts +56 -0
  151. package/dist/utils/project-status.js +237 -0
  152. package/package.json +66 -0
@@ -0,0 +1,337 @@
1
+ /**
2
+ * Project Repository
3
+ *
4
+ * Handles all database operations for projects.
5
+ */
6
+ import { getDb } from '../index.js';
7
+ /**
8
+ * Convert database record to Project object
9
+ */
10
+ function recordToProject(record) {
11
+ return {
12
+ id: record.id,
13
+ name: record.name,
14
+ displayName: record.display_name,
15
+ description: record.description,
16
+ type: record.type,
17
+ status: record.status,
18
+ path: record.path,
19
+ docsPath: record.docs_path,
20
+ repoPattern: record.repo_pattern,
21
+ language: record.language,
22
+ framework: record.framework,
23
+ packageManager: record.package_manager,
24
+ runtimeVersion: record.runtime_version,
25
+ commands: record.commands ? JSON.parse(record.commands) : null,
26
+ gitRemote: record.git_remote,
27
+ gitBranch: record.git_branch,
28
+ workflowMode: record.workflow_mode,
29
+ lifecycleState: record.lifecycle_state,
30
+ currentItemId: record.current_item_id,
31
+ lastContext: record.last_context ? JSON.parse(record.last_context) : null,
32
+ metadata: record.metadata ? JSON.parse(record.metadata) : null,
33
+ createdAt: new Date(record.created_at),
34
+ updatedAt: new Date(record.updated_at),
35
+ lastActivityAt: record.last_activity_at
36
+ ? new Date(record.last_activity_at)
37
+ : null,
38
+ };
39
+ }
40
+ export const projectRepository = {
41
+ /**
42
+ * Create a new project
43
+ */
44
+ create(input) {
45
+ const db = getDb();
46
+ const now = new Date().toISOString();
47
+ const result = db
48
+ .prepare(`
49
+ INSERT INTO projects (
50
+ name, display_name, description, type, path, docs_path, repo_pattern,
51
+ language, framework, package_manager, runtime_version, commands,
52
+ git_remote, git_branch, workflow_mode, metadata,
53
+ created_at, updated_at, last_activity_at
54
+ ) VALUES (
55
+ @name, @display_name, @description, @type, @path, @docs_path, @repo_pattern,
56
+ @language, @framework, @package_manager, @runtime_version, @commands,
57
+ @git_remote, @git_branch, @workflow_mode, @metadata,
58
+ @created_at, @updated_at, @last_activity_at
59
+ )
60
+ `)
61
+ .run({
62
+ name: input.name,
63
+ display_name: input.display_name,
64
+ description: input.description ?? null,
65
+ type: input.type ?? 'general',
66
+ path: input.path,
67
+ docs_path: input.docs_path ?? null,
68
+ repo_pattern: input.repo_pattern ?? 'single',
69
+ language: input.language ?? null,
70
+ framework: input.framework ?? null,
71
+ package_manager: input.package_manager ?? null,
72
+ runtime_version: input.runtime_version ?? null,
73
+ commands: input.commands ? JSON.stringify(input.commands) : null,
74
+ git_remote: input.git_remote ?? null,
75
+ git_branch: input.git_branch ?? 'main',
76
+ workflow_mode: input.workflow_mode ?? 'flexible',
77
+ metadata: input.metadata ? JSON.stringify(input.metadata) : null,
78
+ created_at: now,
79
+ updated_at: now,
80
+ last_activity_at: now,
81
+ });
82
+ const project = this.getById(Number(result.lastInsertRowid));
83
+ if (!project)
84
+ throw new Error('Failed to create project');
85
+ return project;
86
+ },
87
+ /**
88
+ * Get project by ID
89
+ */
90
+ getById(id) {
91
+ const db = getDb();
92
+ const record = db
93
+ .prepare('SELECT * FROM projects WHERE id = ?')
94
+ .get(id);
95
+ return record ? recordToProject(record) : null;
96
+ },
97
+ /**
98
+ * Get project by name
99
+ */
100
+ getByName(name) {
101
+ const db = getDb();
102
+ const record = db
103
+ .prepare('SELECT * FROM projects WHERE name = ?')
104
+ .get(name);
105
+ return record ? recordToProject(record) : null;
106
+ },
107
+ /**
108
+ * Get project by path (code repo)
109
+ */
110
+ getByPath(projectPath) {
111
+ const db = getDb();
112
+ const record = db
113
+ .prepare('SELECT * FROM projects WHERE path = ?')
114
+ .get(projectPath);
115
+ return record ? recordToProject(record) : null;
116
+ },
117
+ /**
118
+ * Get project by docs path (for two-repo pattern)
119
+ */
120
+ getByDocsPath(docsPath) {
121
+ const db = getDb();
122
+ const record = db
123
+ .prepare('SELECT * FROM projects WHERE docs_path = ?')
124
+ .get(docsPath);
125
+ return record ? recordToProject(record) : null;
126
+ },
127
+ /**
128
+ * Find project by path (checks both path and docs_path, including parent directories)
129
+ */
130
+ findByPath(searchPath) {
131
+ // First try exact match on path
132
+ let project = this.getByPath(searchPath);
133
+ if (project)
134
+ return project;
135
+ // Try exact match on docs_path
136
+ project = this.getByDocsPath(searchPath);
137
+ if (project)
138
+ return project;
139
+ // Try parent directories
140
+ const parts = searchPath.split('/').filter(Boolean);
141
+ for (let i = parts.length - 1; i >= 0; i--) {
142
+ const parentPath = '/' + parts.slice(0, i).join('/');
143
+ if (!parentPath || parentPath === '/')
144
+ break;
145
+ project = this.getByPath(parentPath);
146
+ if (project)
147
+ return project;
148
+ project = this.getByDocsPath(parentPath);
149
+ if (project)
150
+ return project;
151
+ }
152
+ return null;
153
+ },
154
+ /**
155
+ * List projects with optional filters
156
+ */
157
+ list(options) {
158
+ const db = getDb();
159
+ const conditions = [];
160
+ const params = {};
161
+ if (options?.status && options.status !== 'all') {
162
+ conditions.push('status = @status');
163
+ params.status = options.status;
164
+ }
165
+ if (options?.type && options.type !== 'all') {
166
+ conditions.push('type = @type');
167
+ params.type = options.type;
168
+ }
169
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
170
+ // Get total count
171
+ const countResult = db
172
+ .prepare(`SELECT COUNT(*) as count FROM projects ${whereClause}`)
173
+ .get(params);
174
+ // Get projects with pagination
175
+ let query = `SELECT * FROM projects ${whereClause} ORDER BY last_activity_at DESC NULLS LAST, updated_at DESC`;
176
+ if (options?.limit) {
177
+ query += ` LIMIT @limit`;
178
+ params.limit = options.limit;
179
+ }
180
+ if (options?.offset) {
181
+ query += ` OFFSET @offset`;
182
+ params.offset = options.offset;
183
+ }
184
+ const records = db.prepare(query).all(params);
185
+ return {
186
+ projects: records.map(recordToProject),
187
+ total: countResult.count,
188
+ };
189
+ },
190
+ /**
191
+ * Update a project
192
+ */
193
+ update(id, input) {
194
+ const db = getDb();
195
+ const updates = [];
196
+ const params = { id };
197
+ // Build dynamic update query
198
+ if (input.display_name !== undefined) {
199
+ updates.push('display_name = @display_name');
200
+ params.display_name = input.display_name;
201
+ }
202
+ if (input.description !== undefined) {
203
+ updates.push('description = @description');
204
+ params.description = input.description;
205
+ }
206
+ if (input.type !== undefined) {
207
+ updates.push('type = @type');
208
+ params.type = input.type;
209
+ }
210
+ if (input.status !== undefined) {
211
+ updates.push('status = @status');
212
+ params.status = input.status;
213
+ }
214
+ if (input.docs_path !== undefined) {
215
+ updates.push('docs_path = @docs_path');
216
+ params.docs_path = input.docs_path;
217
+ }
218
+ if (input.repo_pattern !== undefined) {
219
+ updates.push('repo_pattern = @repo_pattern');
220
+ params.repo_pattern = input.repo_pattern;
221
+ }
222
+ if (input.language !== undefined) {
223
+ updates.push('language = @language');
224
+ params.language = input.language;
225
+ }
226
+ if (input.framework !== undefined) {
227
+ updates.push('framework = @framework');
228
+ params.framework = input.framework;
229
+ }
230
+ if (input.package_manager !== undefined) {
231
+ updates.push('package_manager = @package_manager');
232
+ params.package_manager = input.package_manager;
233
+ }
234
+ if (input.runtime_version !== undefined) {
235
+ updates.push('runtime_version = @runtime_version');
236
+ params.runtime_version = input.runtime_version;
237
+ }
238
+ if (input.commands !== undefined) {
239
+ updates.push('commands = @commands');
240
+ params.commands = JSON.stringify(input.commands);
241
+ }
242
+ if (input.git_remote !== undefined) {
243
+ updates.push('git_remote = @git_remote');
244
+ params.git_remote = input.git_remote;
245
+ }
246
+ if (input.git_branch !== undefined) {
247
+ updates.push('git_branch = @git_branch');
248
+ params.git_branch = input.git_branch;
249
+ }
250
+ if (input.workflow_mode !== undefined) {
251
+ updates.push('workflow_mode = @workflow_mode');
252
+ params.workflow_mode = input.workflow_mode;
253
+ }
254
+ if (input.lifecycle_state !== undefined) {
255
+ updates.push('lifecycle_state = @lifecycle_state');
256
+ params.lifecycle_state = input.lifecycle_state;
257
+ }
258
+ if (input.current_item_id !== undefined) {
259
+ updates.push('current_item_id = @current_item_id');
260
+ params.current_item_id = input.current_item_id;
261
+ }
262
+ if (input.last_context !== undefined) {
263
+ updates.push('last_context = @last_context');
264
+ params.last_context = JSON.stringify(input.last_context);
265
+ }
266
+ if (input.metadata !== undefined) {
267
+ updates.push('metadata = @metadata');
268
+ params.metadata = JSON.stringify(input.metadata);
269
+ }
270
+ if (updates.length === 0) {
271
+ return this.getById(id);
272
+ }
273
+ // Always update updated_at
274
+ updates.push('updated_at = @updated_at');
275
+ params.updated_at = new Date().toISOString();
276
+ const query = `UPDATE projects SET ${updates.join(', ')} WHERE id = @id`;
277
+ db.prepare(query).run(params);
278
+ return this.getById(id);
279
+ },
280
+ /**
281
+ * Update last activity timestamp
282
+ */
283
+ touch(id) {
284
+ const db = getDb();
285
+ const now = new Date().toISOString();
286
+ db.prepare('UPDATE projects SET last_activity_at = ?, updated_at = ? WHERE id = ?').run(now, now, id);
287
+ },
288
+ /**
289
+ * Delete a project (cascades to work_items, documents, history)
290
+ */
291
+ delete(id) {
292
+ const db = getDb();
293
+ const result = db.prepare('DELETE FROM projects WHERE id = ?').run(id);
294
+ return result.changes > 0;
295
+ },
296
+ /**
297
+ * Archive a project (set status to 'archived')
298
+ */
299
+ archive(id) {
300
+ return this.update(id, { status: 'archived' });
301
+ },
302
+ /**
303
+ * Check if a project name is available
304
+ */
305
+ isNameAvailable(name, excludeId) {
306
+ const db = getDb();
307
+ const query = excludeId
308
+ ? 'SELECT id FROM projects WHERE name = ? AND id != ?'
309
+ : 'SELECT id FROM projects WHERE name = ?';
310
+ const params = excludeId ? [name, excludeId] : [name];
311
+ const result = db.prepare(query).get(...params);
312
+ return !result;
313
+ },
314
+ /**
315
+ * Get project counts by status
316
+ */
317
+ getStatusCounts() {
318
+ const db = getDb();
319
+ const results = db
320
+ .prepare(`
321
+ SELECT status, COUNT(*) as count
322
+ FROM projects
323
+ GROUP BY status
324
+ `)
325
+ .all();
326
+ const counts = {
327
+ active: 0,
328
+ paused: 0,
329
+ completed: 0,
330
+ archived: 0,
331
+ };
332
+ for (const row of results) {
333
+ counts[row.status] = row.count;
334
+ }
335
+ return counts;
336
+ },
337
+ };
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Work Item Repository
3
+ *
4
+ * Handles all database operations for work items (backlog items, tasks, bugs).
5
+ */
6
+ import type { WorkItemType, WorkItemStatus, WorkItemPriority, GuidedStep } from '../schema.js';
7
+ export interface CreateWorkItemInput {
8
+ project_id: number;
9
+ type: WorkItemType;
10
+ title: string;
11
+ description?: string;
12
+ priority?: WorkItemPriority;
13
+ estimated_effort?: 'low' | 'medium' | 'high';
14
+ }
15
+ export interface UpdateWorkItemInput {
16
+ type?: WorkItemType;
17
+ status?: WorkItemStatus;
18
+ priority?: WorkItemPriority;
19
+ guided_step?: GuidedStep | null;
20
+ title?: string;
21
+ description?: string;
22
+ estimated_effort?: 'low' | 'medium' | 'high';
23
+ actual_minutes?: number;
24
+ commit_hash?: string;
25
+ }
26
+ export interface QueryWorkItemsInput {
27
+ project_id?: number;
28
+ status?: WorkItemStatus | 'all';
29
+ type?: WorkItemType | 'all';
30
+ priority?: WorkItemPriority | 'all';
31
+ search?: string;
32
+ limit?: number;
33
+ offset?: number;
34
+ }
35
+ export interface WorkItem {
36
+ id: number;
37
+ projectId: number;
38
+ itemNumber: number;
39
+ itemId: string;
40
+ type: WorkItemType;
41
+ status: WorkItemStatus;
42
+ priority: WorkItemPriority;
43
+ guidedStep: GuidedStep | null;
44
+ title: string;
45
+ description: string | null;
46
+ estimatedEffort: string | null;
47
+ actualMinutes: number | null;
48
+ completedAt: Date | null;
49
+ completedBy: string | null;
50
+ commitHash: string | null;
51
+ createdAt: Date;
52
+ updatedAt: Date;
53
+ }
54
+ export declare const workItemRepository: {
55
+ /**
56
+ * Create a new work item
57
+ */
58
+ create(input: CreateWorkItemInput): WorkItem;
59
+ /**
60
+ * Get work item by database ID
61
+ */
62
+ getById(id: number): WorkItem | null;
63
+ /**
64
+ * Get work item by item_id (e.g., "REQ-001")
65
+ */
66
+ getByItemId(projectId: number, itemId: string): WorkItem | null;
67
+ /**
68
+ * Query work items with filters
69
+ */
70
+ query(input: QueryWorkItemsInput): {
71
+ items: WorkItem[];
72
+ total: number;
73
+ hasMore: boolean;
74
+ };
75
+ /**
76
+ * Get next work item (highest priority backlog item)
77
+ */
78
+ getNext(projectId: number, type?: WorkItemType): WorkItem | null;
79
+ /**
80
+ * Update a work item
81
+ */
82
+ update(id: number, input: UpdateWorkItemInput): WorkItem | null;
83
+ /**
84
+ * Record change in history
85
+ */
86
+ recordHistory(workItemId: number, projectId: number, changes: UpdateWorkItemInput, oldItem: WorkItem): void;
87
+ /**
88
+ * Delete a work item
89
+ */
90
+ delete(id: number): boolean;
91
+ /**
92
+ * Get work item counts by status for a project
93
+ */
94
+ getStatusCounts(projectId: number): Record<WorkItemStatus, number>;
95
+ /**
96
+ * Get history for a work item
97
+ */
98
+ getHistory(workItemId: number): Array<{
99
+ action: string;
100
+ oldValue: string | null;
101
+ newValue: string | null;
102
+ notes: string | null;
103
+ changedBy: string | null;
104
+ changedAt: Date;
105
+ }>;
106
+ /**
107
+ * Bulk import work items (for /promote command)
108
+ */
109
+ bulkCreate(projectId: number, items: Array<{
110
+ type: WorkItemType;
111
+ title: string;
112
+ description?: string;
113
+ priority?: WorkItemPriority;
114
+ }>): WorkItem[];
115
+ };