@obsfx/trekker 1.7.2 → 1.8.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 (3) hide show
  1. package/README.md +30 -0
  2. package/dist/index.js +80 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -41,6 +41,7 @@ My concerns about the future and security of that project led me here. Trekker i
41
41
 
42
42
  What you get:
43
43
  - Task and epic tracking with dependencies
44
+ - Ready command to find unblocked tasks and see what they unblock
44
45
  - Full-text search across tasks, epics, subtasks, and comments
45
46
  - Unified list view with filtering by type, status, priority, and custom sorting
46
47
  - Optional kanban board UI available as a [separate package](https://github.com/obsfx/trekker-dashboard)
@@ -78,6 +79,12 @@ trekker dep add TREK-2 TREK-1
78
79
  trekker dep add TREK-3 TREK-1
79
80
  ```
80
81
 
82
+ See what is ready to work on:
83
+
84
+ ```bash
85
+ trekker ready
86
+ ```
87
+
81
88
  Update task status as you work:
82
89
 
83
90
  ```bash
@@ -142,6 +149,29 @@ trekker dep remove <task-id> <depends-on-id>
142
149
  trekker dep list <task-id>
143
150
  ```
144
151
 
152
+ ### Ready
153
+
154
+ Show tasks that are ready to work on — unblocked and in `todo` status. For each ready task, shows downstream dependents that will be unblocked once it is completed:
155
+
156
+ ```bash
157
+ trekker ready
158
+ ```
159
+
160
+ Example output:
161
+ ```
162
+ 2 ready task(s):
163
+
164
+ TREK-1 | P0 | Setup database
165
+ -> unblocks TREK-2 | todo | P1 | Build API layer
166
+ -> unblocks TREK-3 | todo | P1 | Build UI layer
167
+ TREK-4 | P2 | Write docs
168
+ ```
169
+
170
+ Tasks are sorted by priority (critical first). A task is considered ready when:
171
+ - Status is `todo`
172
+ - It is a top-level task (not a subtask)
173
+ - All its dependencies are resolved (`completed`, `wont_fix`, or `archived`)
174
+
145
175
  ### Search
146
176
 
147
177
  Full-text search across epics, tasks, subtasks, and comments using FTS5:
package/dist/index.js CHANGED
@@ -455,7 +455,7 @@ var require_customParseFormat = __commonJS((exports, module) => {
455
455
  });
456
456
 
457
457
  // src/index.ts
458
- import { Command as Command13 } from "commander";
458
+ import { Command as Command14 } from "commander";
459
459
 
460
460
  // src/commands/init.ts
461
461
  import { Command } from "commander";
@@ -3369,10 +3369,86 @@ function formatItem(item) {
3369
3369
  const parentLabel = item.parentId ? ` (${item.parentId})` : "";
3370
3370
  return `${typeLabel} ${item.id} | ${statusLabel} | ${priorityLabel} | ${item.title}${parentLabel}`;
3371
3371
  }
3372
+
3373
+ // src/commands/ready.ts
3374
+ import { Command as Command13 } from "commander";
3375
+
3376
+ // src/services/ready.ts
3377
+ function getReadyTasks() {
3378
+ const sqlite = requireSqliteInstance();
3379
+ const readyRows = sqlite.query(`
3380
+ SELECT t.id, t.title, t.description, t.priority, t.status,
3381
+ t.epic_id, t.tags, t.created_at, t.updated_at
3382
+ FROM tasks t
3383
+ WHERE t.status = 'todo'
3384
+ AND t.parent_task_id IS NULL
3385
+ AND NOT EXISTS (
3386
+ SELECT 1 FROM dependencies d
3387
+ JOIN tasks dt ON dt.id = d.depends_on_id
3388
+ WHERE d.task_id = t.id
3389
+ AND dt.status NOT IN ('completed', 'wont_fix', 'archived')
3390
+ )
3391
+ ORDER BY t.priority ASC, t.created_at ASC
3392
+ `).all();
3393
+ const dependentsQuery = sqlite.query(`
3394
+ SELECT t.id, t.title, t.status, t.priority
3395
+ FROM dependencies d
3396
+ JOIN tasks t ON t.id = d.task_id
3397
+ WHERE d.depends_on_id = ?
3398
+ ORDER BY t.priority ASC
3399
+ `);
3400
+ return readyRows.map((row) => ({
3401
+ id: row.id,
3402
+ title: row.title,
3403
+ description: row.description,
3404
+ priority: row.priority,
3405
+ status: row.status,
3406
+ epicId: row.epic_id,
3407
+ tags: row.tags,
3408
+ createdAt: new Date(row.created_at * 1000),
3409
+ updatedAt: new Date(row.updated_at * 1000),
3410
+ dependents: dependentsQuery.all(row.id).map((d) => ({
3411
+ id: d.id,
3412
+ title: d.title,
3413
+ status: d.status,
3414
+ priority: d.priority
3415
+ }))
3416
+ }));
3417
+ }
3418
+
3419
+ // src/commands/ready.ts
3420
+ var readyCommand = new Command13("ready").description("Show tasks that are ready to work on (unblocked, todo)").action(() => {
3421
+ try {
3422
+ const readyTasks = getReadyTasks();
3423
+ outputResult(readyTasks, formatReadyTasks);
3424
+ } catch (err) {
3425
+ handleCommandError(err);
3426
+ }
3427
+ });
3428
+ function formatReadyTasks(tasks2) {
3429
+ if (tasks2.length === 0) {
3430
+ return "No ready tasks found.";
3431
+ }
3432
+ const lines = [];
3433
+ lines.push(`${tasks2.length} ready task(s):
3434
+ `);
3435
+ for (const task of tasks2) {
3436
+ const epic = task.epicId ? ` (${task.epicId})` : "";
3437
+ const tags = task.tags ? ` [${task.tags}]` : "";
3438
+ lines.push(`${task.id} | P${task.priority} | ${task.title}${epic}${tags}`);
3439
+ if (task.dependents.length > 0) {
3440
+ for (const dep of task.dependents) {
3441
+ lines.push(` -> unblocks ${dep.id} | ${dep.status.padEnd(11)} | P${dep.priority} | ${dep.title}`);
3442
+ }
3443
+ }
3444
+ }
3445
+ return lines.join(`
3446
+ `);
3447
+ }
3372
3448
  // package.json
3373
3449
  var package_default = {
3374
3450
  name: "@obsfx/trekker",
3375
- version: "1.7.2",
3451
+ version: "1.8.0",
3376
3452
  description: "A CLI-based issue tracker built for AI coding agents. Stores tasks, epics, and dependencies in a local SQLite database.",
3377
3453
  type: "module",
3378
3454
  main: "dist/index.js",
@@ -3434,7 +3510,7 @@ var package_default = {
3434
3510
  };
3435
3511
 
3436
3512
  // src/index.ts
3437
- var program = new Command13;
3513
+ var program = new Command14;
3438
3514
  program.name("trekker").description("CLI-based issue tracker for coding agents").version(package_default.version).option("--toon", "Output in TOON format").hook("preAction", (thisCommand) => {
3439
3515
  const opts = thisCommand.opts();
3440
3516
  if (opts.toon) {
@@ -3453,4 +3529,5 @@ program.addCommand(seedCommand);
3453
3529
  program.addCommand(searchCommand);
3454
3530
  program.addCommand(historyCommand);
3455
3531
  program.addCommand(listCommand);
3532
+ program.addCommand(readyCommand);
3456
3533
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@obsfx/trekker",
3
- "version": "1.7.2",
3
+ "version": "1.8.0",
4
4
  "description": "A CLI-based issue tracker built for AI coding agents. Stores tasks, epics, and dependencies in a local SQLite database.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",