Skip to content

Commit ce811b0

Browse files
Copilotneongreen
andcommitted
tak: Support short task IDs and fix event ordering
Bug fixes: 1. Allow short task IDs (e.g., "tak-2") in all commands - Added ResolveTaskID() to resolve short IDs to full IDs - Validates task existence before creating events - Returns error if task doesn't exist or ID is ambiguous 2. Fix event ordering to use created_at instead of Lamport timestamp - Lamport counter resets on each run, causing incorrect ordering - Now use actual created_at timestamp for chronological ordering - Ensures events are always processed in correct order Changes: - Add DB.ResolveTaskID() method to handle short ID resolution - Update status, note, and view commands to resolve IDs - Change GetEvents() and GetEventsByTaskID() to ORDER BY created_at - Add strings import to db.go for ID parsing Co-authored-by: neongreen <1523306+neongreen@users.noreply.github.com>
1 parent ad5cefd commit ce811b0

3 files changed

Lines changed: 87 additions & 6 deletions

File tree

tak/db.go

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"math/big"
99
"os"
1010
"path/filepath"
11+
"strings"
1112
"time"
1213

1314
_ "modernc.org/sqlite"
@@ -117,7 +118,7 @@ func (d *DB) InsertEvent(e Event) error {
117118
// GetEvents retrieves all events in chronological order
118119
func (d *DB) GetEvents() ([]Event, error) {
119120
query := `SELECT id, ts, created_at, actor, role, kind, payload, ctx, repo_uuid, branch, commit_sha, jj_op_id
120-
FROM events ORDER BY ts, id`
121+
FROM events ORDER BY created_at, id`
121122

122123
rows, err := d.db.Query(query)
123124
if err != nil {
@@ -165,7 +166,7 @@ func (d *DB) GetEventsByTaskID(taskID string) ([]Event, error) {
165166
SELECT id, ts, created_at, actor, role, kind, payload, ctx, repo_uuid, branch, commit_sha, jj_op_id
166167
FROM events
167168
WHERE json_extract(payload, '$.task_id') = ?
168-
ORDER BY ts, id
169+
ORDER BY created_at, id
169170
`
170171

171172
rows, err := d.db.Query(query, taskID)
@@ -294,3 +295,65 @@ func generateRandomSuffix(length int) string {
294295
}
295296
return string(b)
296297
}
298+
299+
// ResolveTaskID resolves a short task ID (e.g., "tak-2") to a full task ID (e.g., "tak-2-abc123")
300+
// If the input is already a full ID, it validates that it exists
301+
// Returns an error if the ID is ambiguous or doesn't exist
302+
func (d *DB) ResolveTaskID(shortID string) (string, error) {
303+
// Get all task IDs from the database
304+
query := `
305+
SELECT DISTINCT json_extract(payload, '$.task_id') as task_id
306+
FROM events
307+
WHERE kind = 'task.created'
308+
`
309+
310+
rows, err := d.db.Query(query)
311+
if err != nil {
312+
return "", fmt.Errorf("failed to query task IDs: %w", err)
313+
}
314+
defer rows.Close()
315+
316+
var taskIDs []string
317+
for rows.Next() {
318+
var taskID string
319+
if err := rows.Scan(&taskID); err != nil {
320+
return "", fmt.Errorf("failed to scan task ID: %w", err)
321+
}
322+
taskIDs = append(taskIDs, taskID)
323+
}
324+
325+
if err := rows.Err(); err != nil {
326+
return "", fmt.Errorf("failed to iterate task IDs: %w", err)
327+
}
328+
329+
// Check if shortID is already a full ID
330+
for _, fullID := range taskIDs {
331+
if fullID == shortID {
332+
return fullID, nil
333+
}
334+
}
335+
336+
// Try to match as a short ID (without suffix)
337+
var matches []string
338+
for _, fullID := range taskIDs {
339+
// Extract the numeric part (e.g., "tak-2" from "tak-2-abc123")
340+
// Format is tak-<number>-<suffix>
341+
parts := strings.Split(fullID, "-")
342+
if len(parts) >= 2 {
343+
shortForm := strings.Join(parts[:2], "-") // tak-<number>
344+
if shortForm == shortID {
345+
matches = append(matches, fullID)
346+
}
347+
}
348+
}
349+
350+
if len(matches) == 0 {
351+
return "", fmt.Errorf("task not found: %s", shortID)
352+
}
353+
354+
if len(matches) > 1 {
355+
return "", fmt.Errorf("ambiguous task ID %s, matches: %v", shortID, matches)
356+
}
357+
358+
return matches[0], nil
359+
}

tak/main.go

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ var statusSetCmd = &cobra.Command{
145145
}
146146
defer db.Close()
147147

148+
// Resolve short task ID to full ID
149+
fullTaskID, err := db.ResolveTaskID(taskID)
150+
if err != nil {
151+
return err
152+
}
153+
148154
currentUser, err := getCurrentUser()
149155
if err != nil {
150156
return err
@@ -153,7 +159,7 @@ var statusSetCmd = &cobra.Command{
153159
eventID := GenerateEventID()
154160

155161
payload := TaskStatusSetPayload{
156-
TaskID: taskID,
162+
TaskID: fullTaskID,
157163
Axis: axis,
158164
State: state,
159165
Role: role,
@@ -197,6 +203,12 @@ var noteCmd = &cobra.Command{
197203
}
198204
defer db.Close()
199205

206+
// Resolve short task ID to full ID
207+
fullTaskID, err := db.ResolveTaskID(taskID)
208+
if err != nil {
209+
return err
210+
}
211+
200212
currentUser, err := getCurrentUser()
201213
if err != nil {
202214
return err
@@ -205,7 +217,7 @@ var noteCmd = &cobra.Command{
205217
eventID := GenerateEventID()
206218

207219
payload := TaskNoteAddPayload{
208-
TaskID: taskID,
220+
TaskID: fullTaskID,
209221
Markdown: text,
210222
}
211223
payloadJSON, err := json.Marshal(payload)
@@ -246,7 +258,13 @@ var viewCmd = &cobra.Command{
246258
}
247259
defer db.Close()
248260

249-
events, err := db.GetEventsByTaskID(taskID)
261+
// Resolve short task ID to full ID
262+
fullTaskID, err := db.ResolveTaskID(taskID)
263+
if err != nil {
264+
return err
265+
}
266+
267+
events, err := db.GetEventsByTaskID(fullTaskID)
250268
if err != nil {
251269
return err
252270
}
@@ -260,7 +278,7 @@ var viewCmd = &cobra.Command{
260278
return err
261279
}
262280

263-
task, ok := reducer.GetTask(taskID)
281+
task, ok := reducer.GetTask(fullTaskID)
264282
if !ok {
265283
return fmt.Errorf("task not found: %s", taskID)
266284
}

tak/tak

6.23 KB
Binary file not shown.

0 commit comments

Comments
 (0)