intent-engine 0.11.1

A command-line database service for tracking strategic intent, tasks, and events
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
# Design: `ie task` CRUD Commands

**Version**: 0.11
**Date**: 2026-02-06
**Status**: Implemented — see `docs/spec-03-interface-current.md` for the authoritative reference
**Parent Task**: #175

---

## 1. Motivation

### Problem: ie plan is the only task mutation interface

Currently, **all** task creation/update/deletion in intent-engine goes through `ie plan`, which requires constructing JSON and piping it through stdin:

```bash
echo '{"tasks":[{"name":"Fix bug","status":"doing","spec":"..."}]}' | ie plan
```

This is:
- **Verbose** for single-task operations (most common case)
- **Error-prone** (JSON escaping, quoting)
- **Unfriendly** for both humans and AI tools

### Reference: Claude Code Task Management

Claude Code provides 4 simple tools for task management:

| Tool | Purpose | Interface |
|------|---------|-----------|
| `TaskCreate` | Create one task | `(subject, description, activeForm)` |
| `TaskGet` | Get one task | `(taskId)` → full details + deps |
| `TaskUpdate` | Update one task | `(taskId, status?, subject?, description?, owner?, metadata?, addBlocks?, addBlockedBy?)` |
| `TaskList` | List all tasks | `()` → summary array |

Key characteristics:
- **Individual operations** - one task per call
- **Simple parameters** - no JSON construction needed
- **Metadata support** - arbitrary key-value storage
- **Dependency management** - `addBlocks`/`addBlockedBy` by task ID
- **Flexible owner** - any agent name string

---

## 2. Gap Analysis

### What Claude Code has that ie lacks

| Feature | Claude Code | ie Current |
|---------|------------|------------|
| Single-task CRUD | Direct tool params | JSON stdin batch only |
| Metadata (KV store) | `metadata: {key: val}` | Not supported |
| Flexible owner | Any string (`"agent-1"`) | `human` or `ai` only |
| Deps by ID on update | `addBlocks: [id]` | `depends_on: ["name"]` at plan-time only |
| Delete by update | `status: "deleted"` | `delete: true` flag in plan |
| Simple list-all | `TaskList()` no params | `ie search "todo doing"` workaround |

### What ie has that Claude Code lacks

| Feature | ie | Claude Code |
|---------|------|------------|
| Hierarchical tasks | Parent/children nesting | Flat only |
| Spec (execution contract) | Goal + approach markdown | Just description |
| Event/decision logging | `ie log` 4 event types | None |
| Full-text search | `ie search` with FTS5 | None |
| Cross-session persistence | SQLite database | In-memory only |
| Priority levels | critical/high/medium/low | None |
| Web Dashboard | Real-time UI | None |
| Focus system | Current task per session | No concept |
| Rich context | Ancestors/siblings/descendants | blocks/blockedBy only |
| Lifecycle timestamps | first_todo_at/doing_at/done_at | None |
| Batch operations | `ie plan` atomic batch | Individual only |

---

## 3. Interface Design

### 3.1 New `ie task` Subcommands

All commands output JSON by default. Add `--format text` for human-readable output.

#### `ie task create <name>`

Create a single task.

```
ie task create <NAME> [OPTIONS]

Arguments:
  <NAME>                Task name (required)

Options:
  -d, --description <TEXT>    Task description/spec (markdown)
      --parent <ID>           Parent task ID (default: current focused task, use 0 for root)
      --priority <LEVEL>      Priority: critical|high|medium|low
      --active-form <TEXT>    Present continuous display text (e.g. "Fixing bug")
      --blocked-by <IDS>      Comma-separated IDs of blocking tasks
      --blocks <IDS>          Comma-separated IDs of tasks this blocks
      --metadata <KV>         Metadata as key=value pairs (comma-separated)
      --owner <NAME>          Task owner (default: "ai")
      --status <STATUS>       Initial status: todo|doing (default: todo)
      --format <FMT>          Output format: json|text (default: json)
```

**Output** (JSON):
```json
{
  "id": 42,
  "name": "Fix login bug",
  "status": "todo",
  "description": null,
  "parent_id": null,
  "priority": null,
  "active_form": null,
  "owner": "ai",
  "metadata": {},
  "blocked_by": [],
  "blocks": []
}
```

**Mapping to Claude Code**:
| Claude Code `TaskCreate` | `ie task create` |
|--------------------------|------------------|
| `subject` | `<NAME>` (positional) |
| `description` | `--description` / `-d` |
| `activeForm` | `--active-form` |
| (N/A - always pending) | `--status` (default: todo) |
| (N/A) | `--parent`, `--priority`, `--metadata`, `--owner`, `--blocked-by`, `--blocks` |

---

#### `ie task get <ID>`

Get full task details.

```
ie task get <ID> [OPTIONS]

Arguments:
  <ID>                  Task ID (required)

Options:
  -e, --with-events     Include event history
  -c, --with-context    Include family tree (ancestors/siblings/descendants)
      --format <FMT>    Output format: json|text (default: json)
```

**Output** (JSON):
```json
{
  "id": 42,
  "name": "Fix login bug",
  "status": "doing",
  "description": "Login fails with 500 error on expired sessions",
  "parent_id": 40,
  "priority": "high",
  "active_form": "Fixing login bug",
  "owner": "agent-1",
  "metadata": {"component": "auth", "severity": "P1"},
  "blocked_by": [{"id": 41, "name": "DB migration", "status": "done"}],
  "blocks": [{"id": 43, "name": "Deploy release", "status": "todo"}],
  "first_todo_at": "2026-02-06T10:00:00Z",
  "first_doing_at": "2026-02-06T10:05:00Z",
  "first_done_at": null,
  "events": [],
  "context": null
}
```

With `--with-events`:
```json
{
  ...
  "events": [
    {"id": 1, "log_type": "decision", "discussion_data": "Root cause: session TTL mismatch", "timestamp": "..."}
  ]
}
```

With `--with-context`:
```json
{
  ...
  "context": {
    "ancestors": [{"id": 40, "name": "Auth System", "status": "doing"}],
    "siblings": [{"id": 41, "name": "DB migration", "status": "done"}],
    "descendants": [{"id": 44, "name": "Add retry logic", "status": "todo"}]
  }
}
```

**Mapping to Claude Code**:
| Claude Code `TaskGet` | `ie task get` |
|----------------------|---------------|
| `taskId` | `<ID>` (positional) |
| Returns: blocks/blockedBy | `blocked_by`, `blocks` |
| (N/A) | `--with-events`, `--with-context` (ie power features) |

---

#### `ie task update <ID>`

Update a single task.

```
ie task update <ID> [OPTIONS]

Arguments:
  <ID>                        Task ID (required)

Options:
      --name <NAME>           New name
  -d, --description <TEXT>    New description/spec
      --status <STATUS>       New status: todo|doing|done
      --priority <LEVEL>      Priority: critical|high|medium|low
      --active-form <TEXT>    Present continuous display text
      --add-blocks <IDS>      Add task IDs this task blocks
      --add-blocked-by <IDS>  Add task IDs that block this task
      --rm-blocks <IDS>       Remove blocking relationships
      --rm-blocked-by <IDS>   Remove blocked-by relationships
      --metadata <KV>         Merge metadata (key=value, use key= to delete)
      --owner <NAME>          Change owner
      --parent <ID>           Move to new parent (0 for root)
      --format <FMT>          Output format: json|text (default: json)
```

**Output**: Same as `ie task get` (returns updated task).

**Setting status to `doing`**: Automatically sets task as current focus (same as `ie task start`).

**Setting status to `done`**: Validates all children are complete first.

**Mapping to Claude Code**:
| Claude Code `TaskUpdate` | `ie task update` |
|--------------------------|------------------|
| `taskId` | `<ID>` (positional) |
| `status` (pending/in_progress/completed/deleted) | `--status` (todo/doing/done) + delete via `ie task delete` |
| `subject` | `--name` |
| `description` | `--description` / `-d` |
| `activeForm` | `--active-form` |
| `owner` | `--owner` |
| `metadata` | `--metadata` |
| `addBlocks` | `--add-blocks` |
| `addBlockedBy` | `--add-blocked-by` |
| (N/A) | `--priority`, `--parent`, `--rm-blocks`, `--rm-blocked-by` |

---

#### `ie task list`

List tasks with filtering.

```
ie task list [OPTIONS]

Options:
      --status <STATUS>   Filter by status: todo|doing|done
      --parent <ID>       Filter by parent (0 for roots)
      --owner <NAME>      Filter by owner
      --tree              Tree view (hierarchical)
      --format <FMT>      Output format: json|text (default: json)
```

**Output** (JSON):
```json
[
  {
    "id": 42,
    "name": "Fix login bug",
    "status": "doing",
    "parent_id": 40,
    "owner": "agent-1",
    "blocked_by": [41]
  },
  ...
]
```

**Mapping to Claude Code**:
| Claude Code `TaskList` | `ie task list` |
|------------------------|----------------|
| (no params) | Filters: `--status`, `--parent`, `--owner` |
| Returns: id, subject, status, owner, blockedBy | Same + parent_id |

---

#### `ie task delete <ID>`

Delete a task.

```
ie task delete <ID> [OPTIONS]

Arguments:
  <ID>                  Task ID (required)

Options:
      --cascade         Also delete all descendants
      --format <FMT>    Output format: json|text (default: json)
```

**Note**: Claude Code uses `TaskUpdate(status: "deleted")`. ie provides a dedicated delete command for clarity.

---

#### `ie task start <ID>` (convenience)

Start working on a task (sets doing + focus).

```
ie task start <ID> [OPTIONS]

Arguments:
  <ID>                        Task ID (required)

Options:
  -d, --description <TEXT>    Set description when starting
      --format <FMT>          Output format: json|text (default: json)
```

Equivalent to: `ie task update <ID> --status doing`

---

#### `ie task done [ID]` (convenience)

Complete a task.

```
ie task done [ID] [OPTIONS]

Arguments:
  [ID]                  Task ID (default: current focused task)

Options:
      --format <FMT>    Output format: json|text (default: json)
```

**Output includes next task suggestion:**
```json
{
  "completed_task": {"id": 42, "name": "Fix login bug", "status": "done"},
  "next_suggestion": {"id": 43, "name": "Deploy release", "reason": "sibling_task"}
}
```

---

#### `ie task next` (convenience)

Pick next available task.

```
ie task next [OPTIONS]

Options:
      --format <FMT>    Output format: json|text (default: json)
```

Same behavior as existing `task pick-next`.

---

### 3.2 Status Mapping

| Claude Code | ie | Notes |
|------------|-----|-------|
| `pending` | `todo` | Initial state |
| `in_progress` | `doing` | Active work, sets focus |
| `completed` | `done` | Children must be done first |
| `deleted` | `ie task delete` | Separate command |

---

### 3.3 Metadata System

New `metadata` field on tasks for arbitrary key-value storage.

**Storage**: TEXT column containing JSON object.

**CLI Interface**:
```bash
# Set metadata
ie task create "My task" --metadata component=auth,severity=P1

# Update metadata (merge)
ie task update 42 --metadata priority=urgent

# Delete metadata key
ie task update 42 --metadata severity=

# Read metadata
ie task get 42   # metadata field in output
```

**Use Cases**:
- AI agent tagging (component, module, type)
- Priority annotations beyond the 4-level system
- Custom workflow fields

---

### 3.4 Owner System

Expanded `owner` field allowing any string identifier.

**Current**: `"human"` | `"ai"` (enum)
**New**: Any string (e.g., `"agent-1"`, `"david"`, `"ci-bot"`)

**Backward Compatible**: `"human"` and `"ai"` still work as before.

---

## 4. Data Model Changes

### 4.1 New Column: `metadata`

```sql
ALTER TABLE tasks ADD COLUMN metadata TEXT DEFAULT '{}';
```

### 4.2 Owner Field

No schema change needed - `owner` is already TEXT. Only need to remove the `human`/`ai` enum validation in Rust code.

### 4.3 Updated Task Struct

```rust
pub struct Task {
    pub id: i64,
    pub parent_id: Option<i64>,
    pub name: String,
    pub spec: Option<String>,          // description maps here
    pub status: String,
    pub complexity: Option<i32>,
    pub priority: Option<i32>,
    pub first_todo_at: Option<DateTime>,
    pub first_doing_at: Option<DateTime>,
    pub first_done_at: Option<DateTime>,
    pub active_form: Option<String>,
    pub owner: String,                 // Now accepts any string
    pub metadata: Option<String>,      // NEW: JSON string
}
```

---

## 5. Backward Compatibility

### `ie plan` continues to work

- `ie plan` is NOT removed, only deprecated as primary interface
- All existing `ie plan` JSON schemas remain valid
- `ie plan` can optionally gain `metadata` support in TaskTree

### Migration path

```
Before (ie plan):
  echo '{"tasks":[{"name":"Fix bug","status":"doing"}]}' | ie plan

After (ie task):
  ie task create "Fix bug" --status doing
```

### System prompt update

Recommend `ie task` commands in system prompts. Keep `ie plan` documented for batch operations.

---

## 6. Test Plan

### 6.1 Unit Tests

| Test Case | Command | Verify |
|-----------|---------|--------|
| Create minimal | `ie task create "Test"` | Returns id, status=todo |
| Create full | `ie task create "Test" -d "desc" --parent 1 --priority high` | All fields set |
| Create with metadata | `ie task create "Test" --metadata k=v` | metadata populated |
| Create with deps | `ie task create "Test" --blocked-by 1,2` | Dependencies created |
| Create with doing | `ie task create "Test" --status doing` | Sets as current focus |
| Get basic | `ie task get 1` | Full task returned |
| Get with events | `ie task get 1 -e` | Events included |
| Get with context | `ie task get 1 -c` | Family tree included |
| Update name | `ie task update 1 --name "New"` | Name changed |
| Update status | `ie task update 1 --status doing` | Status + focus set |
| Update metadata | `ie task update 1 --metadata k=v` | Metadata merged |
| Update deps | `ie task update 1 --add-blocked-by 2` | Dep added |
| List all | `ie task list` | All tasks returned |
| List filtered | `ie task list --status todo` | Only todo tasks |
| List tree | `ie task list --tree` | Hierarchical output |
| Delete basic | `ie task delete 1` | Task removed |
| Delete cascade | `ie task delete 1 --cascade` | Descendants removed |
| Start | `ie task start 1` | Status=doing, focus set |
| Done focused | `ie task done` | Current task completed |
| Done by id | `ie task done 1` | Specific task completed |
| Done blocked | `ie task done 1` (children undone) | Error returned |
| Next | `ie task next` | Suggestion returned |

### 6.2 Integration Tests

| Scenario | Steps | Verify |
|----------|-------|--------|
| Full workflow | create → start → done → next | Each step correct |
| Hierarchy | create parent, create child --parent, list --tree | Tree correct |
| Dependencies | create A, create B --blocked-by A, start B (blocked) | Block enforced |
| Metadata CRUD | create --metadata, update --metadata, get | KV correct |
| Owner flow | create --owner agent-1, list --owner agent-1 | Filter works |
| Mixed with plan | ie plan + ie task commands | Both work together |

### 6.3 Regression Tests

| Test | Verify |
|------|--------|
| ie plan still works | Existing JSON input processed correctly |
| ie status reflects task changes | Focus/context updated |
| ie search finds new tasks | FTS index updated |
| ie log works with task tasks | Events attached correctly |
| Dashboard notifications | Changes trigger dashboard updates |

---

## 7. Implementation Order

1. **Design doc** (this document) ← Current
2. **Data model**: Add `metadata` column, relax `owner` validation
3. **CLI definition**: Add `task` subcommand group to clap
4. **TaskManager enhancement**: New methods + metadata/owner support
5. **CLI handlers**: Connect CLI commands to TaskManager
6. **Tests**: Unit + integration + regression
7. **Documentation**: Spec update, system prompt, CLAUDE.md

---

## 8. Open Questions

1. **Should `--description` map to `spec` or a new field?**
   Decision: Map to `spec`. The field is the same concept - task description/specification.
   In output JSON, use `description` as alias for `spec` for Claude Code compatibility.

2. **Auto-parenting behavior for `ie task create`?**
   Decision: Default parent = current focused task (consistent with `ie plan`).
   Use `--parent 0` to explicitly create at root level.

3. **Should `ie plan` be formally deprecated?**
   Decision: Soft deprecation. Keep functional, add deprecation notice to help text,
   recommend `ie task` in documentation. No removal timeline.

---

*End of Design Document*