@damper/cli 0.9.6 → 0.9.8

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.
@@ -23,10 +23,15 @@ export async function releaseCommand() {
23
23
  process.exit(1);
24
24
  }
25
25
  const api = createDamperApi(apiKey);
26
- // Get tasks that are in_progress (locked)
27
- const { tasks, project } = await api.listTasks({ status: 'in_progress' });
26
+ // Get tasks that are in_progress or in_review (locked)
27
+ const [ipResult, irResult] = await Promise.all([
28
+ api.listTasks({ status: 'in_progress' }),
29
+ api.listTasks({ status: 'in_review' }),
30
+ ]);
31
+ const tasks = [...ipResult.tasks, ...irResult.tasks];
32
+ const project = ipResult.project;
28
33
  if (tasks.length === 0) {
29
- console.log(pc.yellow('\nNo in-progress tasks to release.\n'));
34
+ console.log(pc.yellow('\nNo in-progress or in-review tasks to release.\n'));
30
35
  return;
31
36
  }
32
37
  console.log(pc.bold(`\nProject: ${project}`));
@@ -1,7 +1,7 @@
1
1
  export interface StartOptions {
2
2
  taskId?: string;
3
3
  type?: 'bug' | 'feature' | 'improvement' | 'task';
4
- status?: 'planned' | 'in_progress' | 'done' | 'all';
4
+ status?: 'planned' | 'in_progress' | 'in_review' | 'done' | 'all';
5
5
  yolo?: boolean;
6
6
  force?: boolean;
7
7
  }
@@ -243,7 +243,7 @@ export async function postTaskFlow(options) {
243
243
  }
244
244
  // Show status
245
245
  if (taskStatus) {
246
- const statusColor = taskStatus === 'done' ? pc.green : taskStatus === 'in_progress' ? pc.yellow : pc.dim;
246
+ const statusColor = taskStatus === 'done' ? pc.green : (taskStatus === 'in_progress' || taskStatus === 'in_review') ? pc.yellow : pc.dim;
247
247
  console.log(`Task status: ${statusColor(taskStatus)}`);
248
248
  }
249
249
  if (currentBranch) {
@@ -256,8 +256,8 @@ export async function postTaskFlow(options) {
256
256
  console.log(pc.yellow('⚠ Unpushed commits detected'));
257
257
  }
258
258
  console.log();
259
- // Offer to add to changelog if task is completed
260
- if (taskStatus === 'done') {
259
+ // Offer to add to changelog if task is completed (done or in_review)
260
+ if (taskStatus === 'done' || taskStatus === 'in_review') {
261
261
  await offerChangelogFlow({ taskId, taskTitle, apiKey, isPublic: isPublicTask, confirm, select });
262
262
  }
263
263
  // Offer actions based on state
@@ -352,9 +352,9 @@ export async function postTaskFlow(options) {
352
352
  }
353
353
  }
354
354
  }
355
- // Offer cleanup if task is done or abandoned
356
- if (taskStatus === 'done' || taskStatus === 'planned') {
357
- const statusText = taskStatus === 'done' ? 'completed' : 'not started/abandoned';
355
+ // Offer cleanup if task is done, in_review, or abandoned
356
+ if (taskStatus === 'done' || taskStatus === 'in_review' || taskStatus === 'planned') {
357
+ const statusText = taskStatus === 'done' ? 'completed' : taskStatus === 'in_review' ? 'in review' : 'not started/abandoned';
358
358
  const shouldCleanup = await confirm({
359
359
  message: `Task is ${statusText}. Remove worktree and branch?`,
360
360
  default: taskStatus === 'done',
@@ -435,7 +435,7 @@ export async function postTaskFlow(options) {
435
435
  console.log(pc.dim(`\n Task removed. No changes saved.\n`));
436
436
  }
437
437
  else {
438
- const statusColor = taskStatus === 'done' ? pc.green : taskStatus === 'in_progress' ? pc.yellow : pc.dim;
438
+ const statusColor = taskStatus === 'done' ? pc.green : (taskStatus === 'in_progress' || taskStatus === 'in_review') ? pc.yellow : pc.dim;
439
439
  const statusLabel = taskStatus || 'unknown';
440
440
  console.log(pc.bold(`\n #${shortIdRaw(taskId)} ${taskTitle || 'Unknown task'}`) + ` ${statusColor(statusLabel)}`);
441
441
  if (!worktreeRemoved) {
@@ -111,7 +111,7 @@ export declare class DamperApi {
111
111
  constructor(apiKey: string);
112
112
  private request;
113
113
  listTasks(filters?: {
114
- status?: 'planned' | 'in_progress' | 'done' | 'all';
114
+ status?: 'planned' | 'in_progress' | 'in_review' | 'done' | 'all';
115
115
  type?: 'bug' | 'feature' | 'improvement' | 'task';
116
116
  quarter?: string;
117
117
  sort?: 'importance' | 'newest' | 'votes';
@@ -123,7 +123,7 @@ export declare class DamperApi {
123
123
  total: number;
124
124
  }>;
125
125
  listAllTasks(filters?: {
126
- status?: 'planned' | 'in_progress' | 'done' | 'all';
126
+ status?: 'planned' | 'in_progress' | 'in_review' | 'done' | 'all';
127
127
  type?: 'bug' | 'feature' | 'improvement' | 'task';
128
128
  quarter?: string;
129
129
  sort?: 'importance' | 'newest' | 'votes';
@@ -4,7 +4,7 @@ interface TaskPickerOptions {
4
4
  api: DamperApi;
5
5
  worktrees: WorktreeState[];
6
6
  typeFilter?: 'bug' | 'feature' | 'improvement' | 'task';
7
- statusFilter?: 'planned' | 'in_progress' | 'done' | 'all';
7
+ statusFilter?: 'planned' | 'in_progress' | 'in_review' | 'done' | 'all';
8
8
  }
9
9
  interface TaskPickerResult {
10
10
  task: Task;
@@ -126,7 +126,7 @@ export async function pickTask(options) {
126
126
  });
127
127
  // Filter out completed tasks unless specifically requested
128
128
  const availableTasks = tasks.filter(t => statusFilter === 'done' || statusFilter === 'all' ||
129
- (t.status === 'planned' || t.status === 'in_progress'));
129
+ (t.status === 'planned' || t.status === 'in_progress' || t.status === 'in_review'));
130
130
  // Match worktrees with tasks
131
131
  const inProgressChoices = [];
132
132
  const worktreeTaskIds = new Set();
@@ -155,7 +155,7 @@ export async function pickTask(options) {
155
155
  lockedBy: taskAny.lockedBy,
156
156
  });
157
157
  }
158
- else if (task.status === 'planned' || task.status === 'in_progress') {
158
+ else if (task.status === 'planned' || task.status === 'in_progress' || task.status === 'in_review') {
159
159
  availableChoices.push({ type: 'available', task });
160
160
  }
161
161
  }
@@ -293,6 +293,9 @@ async function handleCreateNewTask(api) {
293
293
  message: 'What needs to be done?',
294
294
  validate: (value) => value.trim().length > 0 || 'Instructions are required',
295
295
  });
296
+ const details = await input({
297
+ message: 'Additional details (optional, press Enter to skip):',
298
+ });
296
299
  const type = await select({
297
300
  message: 'Task type:',
298
301
  choices: [
@@ -303,9 +306,11 @@ async function handleCreateNewTask(api) {
303
306
  ],
304
307
  });
305
308
  const trimmed = instructions.trim();
309
+ const trimmedDetails = details.trim();
310
+ const fullInput = trimmedDetails ? `${trimmed}\n\n${trimmedDetails}` : trimmed;
306
311
  // Generate title with Claude, fall back to truncation
307
312
  console.log(pc.dim('\nGenerating title...'));
308
- const generatedTitle = await generateTaskTitle(trimmed, type);
313
+ const generatedTitle = await generateTaskTitle(fullInput, type);
309
314
  let title;
310
315
  if (generatedTitle) {
311
316
  title = generatedTitle;
@@ -317,7 +322,7 @@ async function handleCreateNewTask(api) {
317
322
  : trimmed.slice(0, trimmed.lastIndexOf(' ', maxTitleLen) || maxTitleLen) + '…';
318
323
  }
319
324
  console.log(pc.dim('Creating task in Damper...'));
320
- const task = await api.createTask(title, type, trimmed);
325
+ const task = await api.createTask(title, type, fullInput);
321
326
  console.log(pc.green(`✓ Created task #${shortIdRaw(task.id)}: ${task.title}`));
322
327
  return {
323
328
  task,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@damper/cli",
3
- "version": "0.9.6",
3
+ "version": "0.9.8",
4
4
  "description": "CLI tool for orchestrating Damper task workflows with Claude Code",
5
5
  "author": "Damper <hello@usedamper.com>",
6
6
  "repository": {