@masslessai/push-todo 3.4.6 → 3.4.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.
package/SKILL.md CHANGED
@@ -32,9 +32,11 @@ When this command is invoked:
32
32
  push-todo
33
33
  ```
34
34
 
35
- 4. Present the tasks and ask which one to work on
35
+ 4. **Present ALL tasks** - Do NOT summarize or truncate the list. Show every active task in a table format. Users want to see their complete task list, not a curated subset. If there are 35 tasks, show all 35.
36
36
 
37
- 5. When user selects a task, mark it as started and begin working
37
+ 5. Ask which task the user wants to work on
38
+
39
+ 6. When user selects a task, mark it as started and begin working
38
40
 
39
41
  ## Review Mode
40
42
 
@@ -91,6 +93,27 @@ Should I mark #701 and #427 as completed?
91
93
  push-todo --mark-completed TASK_UUID --completion-comment "Completed in Claude Code session"
92
94
  ```
93
95
 
96
+ ### Step 6: Learn Vocabulary (After Each Completion)
97
+
98
+ After marking a task complete, contribute vocabulary terms to improve future task routing:
99
+
100
+ 1. **Extract 3-8 keywords from the session context:**
101
+ - File names / class names touched (e.g., `SyncService`, `RealtimeManager`)
102
+ - Technical concepts implemented (e.g., `WebSocket`, `reconnection`, `caching`)
103
+ - Domain-specific terms from the conversation
104
+
105
+ 2. **Call learn-vocabulary:**
106
+ ```bash
107
+ push-todo --learn-vocabulary TASK_UUID --keywords 'term1,term2,term3'
108
+ ```
109
+
110
+ **Example:** After fixing a sync bug:
111
+ ```bash
112
+ push-todo --learn-vocabulary abc123 --keywords 'SyncService,RealtimeManager,WebSocket,reconnection,realtime'
113
+ ```
114
+
115
+ **Why this matters:** These keywords help the AI route future voice todos to the correct project. The more specific the terms, the better the matching.
116
+
94
117
  ### Key Principle
95
118
 
96
119
  **Session context is primary** - don't grep the entire codebase for every task. Use conversation history to identify what was actually worked on, then match against tasks semantically. This catches both:
package/lib/cli.js CHANGED
@@ -15,7 +15,7 @@ import { ensureDaemonRunning, getDaemonStatus, startDaemon, stopDaemon } from '.
15
15
  import { getScreenshotPath, screenshotExists, openScreenshot } from './utils/screenshots.js';
16
16
  import { bold, red, cyan, dim, green } from './utils/colors.js';
17
17
 
18
- const VERSION = '3.4.5';
18
+ const VERSION = '3.4.7';
19
19
 
20
20
  const HELP_TEXT = `
21
21
  ${bold('push-todo')} - Voice tasks from Push iOS app for Claude Code
package/lib/fetch.js CHANGED
@@ -8,7 +8,7 @@ import * as api from './api.js';
8
8
  import { getMachineId, getMachineName } from './machine-id.js';
9
9
  import { getRegistry } from './project-registry.js';
10
10
  import { getGitRemote, isGitRepo } from './utils/git.js';
11
- import { formatTaskForDisplay, formatTaskTable, formatSearchResult, formatBatchOffer } from './utils/format.js';
11
+ import { formatTaskForDisplay, formatSearchResult } from './utils/format.js';
12
12
  import { bold, green, yellow, red, cyan, dim, muted } from './utils/colors.js';
13
13
  import { decryptTodoField, isE2EEAvailable } from './encryption.js';
14
14
  import { getAutoCommitEnabled, getMaxBatchSize } from './config.js';
@@ -92,34 +92,52 @@ export async function listTasks(options = {}) {
92
92
  const backlog = decryptedTasks.filter(t => !t.isCompleted && !t.is_completed && (t.isBacklog || t.is_backlog));
93
93
  const completed = decryptedTasks.filter(t => t.isCompleted || t.is_completed);
94
94
 
95
- // Header
96
- const scope = gitRemote ? gitRemote : 'All Projects';
97
- console.log(bold(`\nPush Tasks - ${scope}\n`));
98
-
99
- // Active tasks
100
- if (active.length > 0) {
101
- console.log(green(`Active (${active.length}):`));
102
- console.log(formatTaskTable(active));
103
- console.log('');
95
+ // Build scope description
96
+ const scope = gitRemote ? 'this project' : 'all projects';
97
+ const backlogSuffix = options.backlog ? ', backlog only' : '';
98
+ const includeSuffix = options.includeBacklog ? ', including backlog' : '';
99
+
100
+ // Determine which tasks to show
101
+ let tasksToShow = [];
102
+ if (options.backlog) {
103
+ tasksToShow = backlog;
104
+ } else if (options.completed) {
105
+ tasksToShow = completed;
106
+ } else {
107
+ tasksToShow = active;
108
+ if (options.includeBacklog) {
109
+ tasksToShow = [...active, ...backlog];
110
+ }
104
111
  }
105
112
 
106
- // Backlog tasks (if requested)
107
- if (backlog.length > 0 && (options.backlog || options.includeBacklog)) {
108
- console.log(yellow(`Backlog (${backlog.length}):`));
109
- console.log(formatTaskTable(backlog));
110
- console.log('');
111
- }
113
+ // Header
114
+ console.log(`# ${tasksToShow.length} Active Tasks (${scope}${backlogSuffix}${includeSuffix})\n`);
112
115
 
113
- // Completed tasks (if requested)
114
- if (completed.length > 0 && (options.completed || options.includeCompleted)) {
115
- console.log(dim(`Completed (${completed.length}):`));
116
- console.log(formatTaskTable(completed));
116
+ // Show full details for each task (matching Python behavior)
117
+ for (const task of tasksToShow) {
118
+ const displayNum = task.displayNumber || task.display_number;
119
+ console.log(`---\n### #${displayNum}\n`);
120
+ console.log(formatTaskForDisplay(task));
117
121
  console.log('');
118
122
  }
119
123
 
120
- // Summary
121
- const total = active.length + (options.includeBacklog ? backlog.length : 0);
122
- console.log(muted(`Showing ${total} task(s). Use --include-backlog or --completed for more.`));
124
+ // Batch queue offer (only for active tasks, not backlog view)
125
+ if (!options.backlog && tasksToShow.length > 0) {
126
+ const maxBatch = 5; // Default batch size
127
+ const batchCount = Math.min(tasksToShow.length, maxBatch);
128
+ const batchTasks = tasksToShow.slice(0, batchCount);
129
+ const batchNumbers = batchTasks.map(t => String(t.displayNumber || t.display_number));
130
+
131
+ console.log('='.repeat(50));
132
+ console.log(`BATCH_OFFER: ${batchCount}`);
133
+ console.log(`BATCH_TASKS: ${batchNumbers.join(',')}`);
134
+ for (const t of batchTasks) {
135
+ const num = t.displayNumber || t.display_number;
136
+ const summary = (t.summary || 'No summary').slice(0, 50);
137
+ console.log(` #${num} - ${summary}`);
138
+ }
139
+ console.log('='.repeat(50));
140
+ }
123
141
  }
124
142
 
125
143
  /**
@@ -353,7 +371,17 @@ export async function offerBatch(options = {}) {
353
371
  return;
354
372
  }
355
373
 
356
- console.log(formatBatchOffer(batch));
374
+ // Format batch offer inline (matching Python style)
375
+ const batchNumbers = batch.map(t => String(t.displayNumber || t.display_number));
376
+ console.log('='.repeat(50));
377
+ console.log(`BATCH_OFFER: ${batch.length}`);
378
+ console.log(`BATCH_TASKS: ${batchNumbers.join(',')}`);
379
+ for (const t of batch) {
380
+ const num = t.displayNumber || t.display_number;
381
+ const summary = (t.summary || 'No summary').slice(0, 50);
382
+ console.log(` #${num} - ${summary}`);
383
+ }
384
+ console.log('='.repeat(50));
357
385
  }
358
386
 
359
387
  /**
@@ -381,6 +409,13 @@ export async function runReview(options = {}) {
381
409
  return;
382
410
  }
383
411
 
384
- console.log(bold(`\nCompleted Tasks for Review (${decrypted.length}):\n`));
385
- console.log(formatTaskTable(decrypted));
412
+ console.log(`# ${decrypted.length} Completed Tasks for Review\n`);
413
+
414
+ // Show full details for each task (matching Python behavior)
415
+ for (const task of decrypted) {
416
+ const displayNum = task.displayNumber || task.display_number;
417
+ console.log(`---\n### #${displayNum}\n`);
418
+ console.log(formatTaskForDisplay(task));
419
+ console.log('');
420
+ }
386
421
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@masslessai/push-todo",
3
- "version": "3.4.6",
3
+ "version": "3.4.8",
4
4
  "description": "Voice tasks from Push iOS app for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {