trak_flow 0.1.3

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 (95) hide show
  1. checksums.yaml +7 -0
  2. data/.envrc +3 -0
  3. data/CHANGELOG.md +69 -0
  4. data/COMMITS.md +196 -0
  5. data/Gemfile +8 -0
  6. data/Gemfile.lock +281 -0
  7. data/README.md +479 -0
  8. data/Rakefile +16 -0
  9. data/bin/tf +6 -0
  10. data/bin/tf_mcp +81 -0
  11. data/docs/.keep +0 -0
  12. data/docs/api/database.md +434 -0
  13. data/docs/api/ruby-library.md +349 -0
  14. data/docs/api/task-model.md +341 -0
  15. data/docs/assets/stylesheets/extra.css +53 -0
  16. data/docs/assets/trak_flow.jpg +0 -0
  17. data/docs/cli/admin-commands.md +369 -0
  18. data/docs/cli/dependency-commands.md +321 -0
  19. data/docs/cli/label-commands.md +222 -0
  20. data/docs/cli/overview.md +163 -0
  21. data/docs/cli/plan-commands.md +344 -0
  22. data/docs/cli/task-commands.md +333 -0
  23. data/docs/core-concepts/dependencies.md +232 -0
  24. data/docs/core-concepts/labels.md +217 -0
  25. data/docs/core-concepts/overview.md +178 -0
  26. data/docs/core-concepts/plans-workflows.md +264 -0
  27. data/docs/core-concepts/tasks.md +205 -0
  28. data/docs/getting-started/configuration.md +120 -0
  29. data/docs/getting-started/installation.md +79 -0
  30. data/docs/getting-started/quick-start.md +245 -0
  31. data/docs/index.md +169 -0
  32. data/docs/mcp/integration.md +302 -0
  33. data/docs/mcp/overview.md +206 -0
  34. data/docs/mcp/resources.md +284 -0
  35. data/docs/mcp/tools.md +457 -0
  36. data/examples/basic_usage.rb +365 -0
  37. data/examples/cli_demo.sh +314 -0
  38. data/examples/mcp/Gemfile +9 -0
  39. data/examples/mcp/Gemfile.lock +226 -0
  40. data/examples/mcp/http_demo.rb +232 -0
  41. data/examples/mcp/stdio_demo.rb +146 -0
  42. data/lib/trak_flow/cli/admin_commands.rb +136 -0
  43. data/lib/trak_flow/cli/config_commands.rb +260 -0
  44. data/lib/trak_flow/cli/dep_commands.rb +71 -0
  45. data/lib/trak_flow/cli/label_commands.rb +76 -0
  46. data/lib/trak_flow/cli/main_commands.rb +386 -0
  47. data/lib/trak_flow/cli/plan_commands.rb +185 -0
  48. data/lib/trak_flow/cli/workflow_commands.rb +133 -0
  49. data/lib/trak_flow/cli.rb +110 -0
  50. data/lib/trak_flow/config/defaults.yml +114 -0
  51. data/lib/trak_flow/config/section.rb +74 -0
  52. data/lib/trak_flow/config.rb +276 -0
  53. data/lib/trak_flow/graph/dependency_graph.rb +288 -0
  54. data/lib/trak_flow/id_generator.rb +52 -0
  55. data/lib/trak_flow/mcp/resources/base_resource.rb +25 -0
  56. data/lib/trak_flow/mcp/resources/dependency_graph.rb +31 -0
  57. data/lib/trak_flow/mcp/resources/label_list.rb +21 -0
  58. data/lib/trak_flow/mcp/resources/plan_by_id.rb +27 -0
  59. data/lib/trak_flow/mcp/resources/plan_list.rb +21 -0
  60. data/lib/trak_flow/mcp/resources/task_by_id.rb +31 -0
  61. data/lib/trak_flow/mcp/resources/task_list.rb +21 -0
  62. data/lib/trak_flow/mcp/resources/task_next.rb +30 -0
  63. data/lib/trak_flow/mcp/resources/workflow_by_id.rb +27 -0
  64. data/lib/trak_flow/mcp/resources/workflow_list.rb +21 -0
  65. data/lib/trak_flow/mcp/server.rb +140 -0
  66. data/lib/trak_flow/mcp/tools/base_tool.rb +29 -0
  67. data/lib/trak_flow/mcp/tools/comment_add.rb +33 -0
  68. data/lib/trak_flow/mcp/tools/dep_add.rb +34 -0
  69. data/lib/trak_flow/mcp/tools/dep_remove.rb +25 -0
  70. data/lib/trak_flow/mcp/tools/label_add.rb +28 -0
  71. data/lib/trak_flow/mcp/tools/label_remove.rb +25 -0
  72. data/lib/trak_flow/mcp/tools/plan_add_step.rb +35 -0
  73. data/lib/trak_flow/mcp/tools/plan_create.rb +33 -0
  74. data/lib/trak_flow/mcp/tools/plan_run.rb +58 -0
  75. data/lib/trak_flow/mcp/tools/plan_start.rb +58 -0
  76. data/lib/trak_flow/mcp/tools/task_block.rb +27 -0
  77. data/lib/trak_flow/mcp/tools/task_close.rb +26 -0
  78. data/lib/trak_flow/mcp/tools/task_create.rb +51 -0
  79. data/lib/trak_flow/mcp/tools/task_defer.rb +27 -0
  80. data/lib/trak_flow/mcp/tools/task_start.rb +25 -0
  81. data/lib/trak_flow/mcp/tools/task_update.rb +36 -0
  82. data/lib/trak_flow/mcp/tools/workflow_discard.rb +28 -0
  83. data/lib/trak_flow/mcp/tools/workflow_summarize.rb +34 -0
  84. data/lib/trak_flow/mcp.rb +38 -0
  85. data/lib/trak_flow/models/comment.rb +71 -0
  86. data/lib/trak_flow/models/dependency.rb +96 -0
  87. data/lib/trak_flow/models/label.rb +90 -0
  88. data/lib/trak_flow/models/task.rb +188 -0
  89. data/lib/trak_flow/storage/database.rb +638 -0
  90. data/lib/trak_flow/storage/jsonl.rb +259 -0
  91. data/lib/trak_flow/time_parser.rb +15 -0
  92. data/lib/trak_flow/version.rb +5 -0
  93. data/lib/trak_flow.rb +100 -0
  94. data/mkdocs.yml +143 -0
  95. metadata +392 -0
@@ -0,0 +1,434 @@
1
+ # Database API Reference
2
+
3
+ TrakFlow uses SQLite for fast querying with JSONL as the persistent source of truth.
4
+
5
+ ## Class: TrakFlow::Storage::Database
6
+
7
+ ### Initialization
8
+
9
+ ```ruby
10
+ db = TrakFlow::Storage::Database.new(path)
11
+ ```
12
+
13
+ | Parameter | Type | Description |
14
+ |-----------|------|-------------|
15
+ | `path` | String | Path to SQLite database file |
16
+
17
+ ### Task Methods
18
+
19
+ #### find_task
20
+
21
+ Find a task by ID.
22
+
23
+ ```ruby
24
+ task = db.find_task("tf-abc123")
25
+ # Returns: TrakFlow::Models::Task or nil
26
+ ```
27
+
28
+ #### list_tasks
29
+
30
+ List tasks with optional filters.
31
+
32
+ ```ruby
33
+ tasks = db.list_tasks(
34
+ status: "open",
35
+ type: "bug",
36
+ priority: [0, 1],
37
+ assignee: "claude",
38
+ parent_id: nil,
39
+ label: "frontend",
40
+ include_closed: false,
41
+ include_ephemeral: false,
42
+ limit: 100,
43
+ offset: 0
44
+ )
45
+ # Returns: Array<TrakFlow::Models::Task>
46
+ ```
47
+
48
+ | Filter | Type | Description |
49
+ |--------|------|-------------|
50
+ | `status` | String/Array | Filter by status(es) |
51
+ | `type` | String/Array | Filter by type(s) |
52
+ | `priority` | Integer/Array | Filter by priority(ies) |
53
+ | `assignee` | String | Filter by assignee |
54
+ | `parent_id` | String | Filter by parent |
55
+ | `label` | String/Array | Filter by label(s) |
56
+ | `include_closed` | Boolean | Include closed tasks |
57
+ | `include_ephemeral` | Boolean | Include ephemeral tasks |
58
+ | `limit` | Integer | Max results |
59
+ | `offset` | Integer | Skip results |
60
+
61
+ #### insert_task
62
+
63
+ Insert a new task.
64
+
65
+ ```ruby
66
+ db.insert_task(task)
67
+ # Returns: TrakFlow::Models::Task
68
+ ```
69
+
70
+ #### update_task
71
+
72
+ Update an existing task.
73
+
74
+ ```ruby
75
+ db.update_task(task)
76
+ # Returns: TrakFlow::Models::Task
77
+ ```
78
+
79
+ #### delete_task
80
+
81
+ Delete a task.
82
+
83
+ ```ruby
84
+ db.delete_task("tf-abc123")
85
+ # Returns: true
86
+ ```
87
+
88
+ ### Ready Tasks
89
+
90
+ #### find_ready_tasks
91
+
92
+ Find tasks with no open blocking dependencies.
93
+
94
+ ```ruby
95
+ tasks = db.find_ready_tasks(
96
+ type: "bug",
97
+ priority: [0, 1],
98
+ limit: 10
99
+ )
100
+ # Returns: Array<TrakFlow::Models::Task>
101
+ ```
102
+
103
+ #### is_ready?
104
+
105
+ Check if a task is ready.
106
+
107
+ ```ruby
108
+ db.is_ready?("tf-abc123")
109
+ # Returns: Boolean
110
+ ```
111
+
112
+ ### Plan & Workflow Methods
113
+
114
+ #### find_plans
115
+
116
+ Find all Plan blueprints.
117
+
118
+ ```ruby
119
+ plans = db.find_plans
120
+ # Returns: Array<TrakFlow::Models::Task> where plan? == true
121
+ ```
122
+
123
+ #### find_workflows
124
+
125
+ Find Workflows, optionally filtered by source Plan.
126
+
127
+ ```ruby
128
+ workflows = db.find_workflows(plan_id: "tf-plan1")
129
+ # Returns: Array<TrakFlow::Models::Task> where workflow? == true
130
+ ```
131
+
132
+ #### find_ephemeral_workflows
133
+
134
+ Find ephemeral Workflows.
135
+
136
+ ```ruby
137
+ workflows = db.find_ephemeral_workflows
138
+ # Returns: Array<TrakFlow::Models::Task> where ephemeral? == true
139
+ ```
140
+
141
+ #### mark_as_plan
142
+
143
+ Convert a task to a Plan.
144
+
145
+ ```ruby
146
+ db.mark_as_plan("tf-abc123")
147
+ # Returns: TrakFlow::Models::Task
148
+ ```
149
+
150
+ ### Dependency Methods
151
+
152
+ #### add_dependency
153
+
154
+ Add a dependency between tasks.
155
+
156
+ ```ruby
157
+ db.add_dependency(
158
+ source_id: "tf-design",
159
+ target_id: "tf-implement",
160
+ type: "blocks"
161
+ )
162
+ # Returns: TrakFlow::Models::Dependency
163
+ ```
164
+
165
+ #### remove_dependency
166
+
167
+ Remove a dependency.
168
+
169
+ ```ruby
170
+ db.remove_dependency(
171
+ source_id: "tf-design",
172
+ target_id: "tf-implement"
173
+ )
174
+ # Returns: true
175
+ ```
176
+
177
+ #### dependencies_for
178
+
179
+ Get dependencies for a task.
180
+
181
+ ```ruby
182
+ deps = db.dependencies_for("tf-abc123")
183
+ # Returns: {
184
+ # blocked_by: Array<Dependency>,
185
+ # blocks: Array<Dependency>,
186
+ # related: Array<Dependency>
187
+ # }
188
+ ```
189
+
190
+ #### all_dependencies
191
+
192
+ Get all dependencies.
193
+
194
+ ```ruby
195
+ deps = db.all_dependencies
196
+ # Returns: Array<TrakFlow::Models::Dependency>
197
+ ```
198
+
199
+ #### would_create_cycle?
200
+
201
+ Check if adding a dependency would create a cycle.
202
+
203
+ ```ruby
204
+ db.would_create_cycle?("tf-a", "tf-b")
205
+ # Returns: Boolean
206
+ ```
207
+
208
+ ### Label Methods
209
+
210
+ #### add_label
211
+
212
+ Add a label to a task.
213
+
214
+ ```ruby
215
+ db.add_label("tf-abc123", "frontend")
216
+ # Returns: TrakFlow::Models::Label
217
+ ```
218
+
219
+ #### remove_label
220
+
221
+ Remove a label from a task.
222
+
223
+ ```ruby
224
+ db.remove_label("tf-abc123", "frontend")
225
+ # Returns: true
226
+ ```
227
+
228
+ #### labels_for
229
+
230
+ Get labels for a task.
231
+
232
+ ```ruby
233
+ labels = db.labels_for("tf-abc123")
234
+ # Returns: Array<String>
235
+ ```
236
+
237
+ #### all_labels
238
+
239
+ Get all labels with task counts.
240
+
241
+ ```ruby
242
+ labels = db.all_labels
243
+ # Returns: Hash<String, Integer>
244
+ # Example: {"frontend" => 5, "backend" => 3}
245
+ ```
246
+
247
+ #### tasks_with_label
248
+
249
+ Find tasks with a label.
250
+
251
+ ```ruby
252
+ tasks = db.tasks_with_label("frontend")
253
+ # Returns: Array<TrakFlow::Models::Task>
254
+ ```
255
+
256
+ ### Comment Methods
257
+
258
+ #### add_comment
259
+
260
+ Add a comment to a task.
261
+
262
+ ```ruby
263
+ db.add_comment(
264
+ task_id: "tf-abc123",
265
+ author: "claude",
266
+ content: "Working on this now"
267
+ )
268
+ # Returns: TrakFlow::Models::Comment
269
+ ```
270
+
271
+ #### comments_for
272
+
273
+ Get comments for a task.
274
+
275
+ ```ruby
276
+ comments = db.comments_for("tf-abc123")
277
+ # Returns: Array<TrakFlow::Models::Comment>
278
+ ```
279
+
280
+ ### Maintenance Methods
281
+
282
+ #### rebuild!
283
+
284
+ Rebuild the database from JSONL.
285
+
286
+ ```ruby
287
+ db.rebuild!(jsonl_path)
288
+ # Returns: Integer (number of tasks loaded)
289
+ ```
290
+
291
+ #### garbage_collect!
292
+
293
+ Remove old ephemeral Workflows.
294
+
295
+ ```ruby
296
+ count = db.garbage_collect!(older_than: 7.days.ago)
297
+ # Returns: Integer (number deleted)
298
+ ```
299
+
300
+ #### vacuum!
301
+
302
+ Optimize database storage.
303
+
304
+ ```ruby
305
+ db.vacuum!
306
+ ```
307
+
308
+ ### Statistics Methods
309
+
310
+ #### stats
311
+
312
+ Get database statistics.
313
+
314
+ ```ruby
315
+ stats = db.stats
316
+ # Returns: {
317
+ # total_tasks: 47,
318
+ # by_status: {"open" => 12, "closed" => 27, ...},
319
+ # by_type: {"task" => 30, "bug" => 8, ...},
320
+ # by_priority: {0 => 2, 1 => 8, ...},
321
+ # plans: 3,
322
+ # workflows: 5,
323
+ # dependencies: 34,
324
+ # labels: 12
325
+ # }
326
+ ```
327
+
328
+ ## Schema
329
+
330
+ ### tasks Table
331
+
332
+ ```sql
333
+ CREATE TABLE tasks (
334
+ id TEXT PRIMARY KEY,
335
+ title TEXT NOT NULL,
336
+ description TEXT,
337
+ status TEXT DEFAULT 'open',
338
+ priority INTEGER DEFAULT 2,
339
+ type TEXT DEFAULT 'task',
340
+ assignee TEXT,
341
+ parent_id TEXT,
342
+ created_at TEXT,
343
+ updated_at TEXT,
344
+ closed_at TEXT,
345
+ content_hash TEXT,
346
+ plan BOOLEAN DEFAULT 0,
347
+ source_plan_id TEXT,
348
+ ephemeral BOOLEAN DEFAULT 0,
349
+ notes TEXT
350
+ );
351
+
352
+ CREATE INDEX idx_tasks_status ON tasks(status);
353
+ CREATE INDEX idx_tasks_priority ON tasks(priority);
354
+ CREATE INDEX idx_tasks_type ON tasks(type);
355
+ CREATE INDEX idx_tasks_parent_id ON tasks(parent_id);
356
+ CREATE INDEX idx_tasks_plan ON tasks(plan);
357
+ CREATE INDEX idx_tasks_source_plan_id ON tasks(source_plan_id);
358
+ ```
359
+
360
+ ### dependencies Table
361
+
362
+ ```sql
363
+ CREATE TABLE dependencies (
364
+ id TEXT PRIMARY KEY,
365
+ source_id TEXT NOT NULL,
366
+ target_id TEXT NOT NULL,
367
+ type TEXT DEFAULT 'blocks',
368
+ created_at TEXT,
369
+ FOREIGN KEY (source_id) REFERENCES tasks(id),
370
+ FOREIGN KEY (target_id) REFERENCES tasks(id),
371
+ UNIQUE(source_id, target_id)
372
+ );
373
+
374
+ CREATE INDEX idx_deps_source ON dependencies(source_id);
375
+ CREATE INDEX idx_deps_target ON dependencies(target_id);
376
+ ```
377
+
378
+ ### labels Table
379
+
380
+ ```sql
381
+ CREATE TABLE labels (
382
+ id TEXT PRIMARY KEY,
383
+ task_id TEXT NOT NULL,
384
+ name TEXT NOT NULL,
385
+ created_at TEXT,
386
+ FOREIGN KEY (task_id) REFERENCES tasks(id),
387
+ UNIQUE(task_id, name)
388
+ );
389
+
390
+ CREATE INDEX idx_labels_task_id ON labels(task_id);
391
+ CREATE INDEX idx_labels_name ON labels(name);
392
+ ```
393
+
394
+ ### comments Table
395
+
396
+ ```sql
397
+ CREATE TABLE comments (
398
+ id TEXT PRIMARY KEY,
399
+ task_id TEXT NOT NULL,
400
+ author TEXT,
401
+ content TEXT NOT NULL,
402
+ created_at TEXT,
403
+ FOREIGN KEY (task_id) REFERENCES tasks(id)
404
+ );
405
+
406
+ CREATE INDEX idx_comments_task_id ON comments(task_id);
407
+ ```
408
+
409
+ ## Transaction Support
410
+
411
+ ```ruby
412
+ db.transaction do
413
+ task1 = db.insert_task(task1)
414
+ task2 = db.insert_task(task2)
415
+ db.add_dependency(task1.id, task2.id)
416
+ end
417
+ # All operations succeed or all fail
418
+ ```
419
+
420
+ ## Error Handling
421
+
422
+ ```ruby
423
+ begin
424
+ db.find_task("invalid-id")
425
+ rescue TrakFlow::Storage::NotFoundError => e
426
+ puts "Not found: #{e.message}"
427
+ end
428
+
429
+ begin
430
+ db.add_dependency("tf-a", "tf-a")
431
+ rescue TrakFlow::Storage::ValidationError => e
432
+ puts "Invalid: #{e.message}"
433
+ end
434
+ ```