trekoon 0.4.0 → 0.4.1

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/README.md CHANGED
@@ -14,12 +14,6 @@ accounts. The database lives in `.trekoon/` inside your repo.
14
14
  bun add -g trekoon
15
15
  ```
16
16
 
17
- Or via npm (Bun still needs to be installed as the runtime):
18
-
19
- ```bash
20
- npm i -g trekoon
21
- ```
22
-
23
17
  ```bash
24
18
  trekoon init # set up .trekoon/ in your repo
25
19
  trekoon quickstart # walkthrough of the basics
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trekoon",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "AI-first task tracking that lives in your repo. You describe what to build, your agent plans it as a dependency graph, then executes it task by task",
5
5
  "keywords": [
6
6
  "ai",
@@ -365,7 +365,8 @@ export async function bootLegacyBoard(options = {}) {
365
365
  const screen = boardState.screen;
366
366
  const selectedTask = boardState.selectedTask;
367
367
  const selectedSubtask = boardState.selectedSubtask;
368
- const currentNav = selectedTask ? "detail" : screen === "tasks" ? "board" : "epics";
368
+ const taskModalOpen = Boolean(boardState.taskModalOpen && selectedTask);
369
+ const currentNav = taskModalOpen ? "detail" : screen === "tasks" ? "board" : "epics";
369
370
 
370
371
  // Layout toggles
371
372
  const showTasks = screen === "tasks" && boardState.selectedEpic;
@@ -381,11 +382,11 @@ export async function bootLegacyBoard(options = {}) {
381
382
  confirmDialog.update(null);
382
383
  }
383
384
 
384
- if (!showTasks || !selectedTask) {
385
+ if (!showTasks || !taskModalOpen) {
385
386
  taskModal.update(null);
386
387
  }
387
388
 
388
- if (!showTasks || !selectedTask || !selectedSubtask) {
389
+ if (!showTasks || !taskModalOpen || !selectedSubtask) {
389
390
  subtaskModal.update(null);
390
391
  }
391
392
 
@@ -428,7 +429,7 @@ export async function bootLegacyBoard(options = {}) {
428
429
  visibleTasks: boardState.visibleTasks,
429
430
  });
430
431
 
431
- taskModal.update(selectedTask ? {
432
+ taskModal.update(taskModalOpen ? {
432
433
  task: selectedTask,
433
434
  epics: store.snapshot.epics,
434
435
  snapshot: store.snapshot,
@@ -442,7 +443,7 @@ export async function bootLegacyBoard(options = {}) {
442
443
  });
443
444
  }
444
445
 
445
- subtaskModal.update(showTasks && selectedTask && selectedSubtask ? {
446
+ subtaskModal.update(showTasks && taskModalOpen && selectedSubtask ? {
446
447
  subtask: selectedSubtask,
447
448
  isMutating: store.isMutating,
448
449
  } : null);
@@ -252,7 +252,7 @@ export function isCompactViewport() {
252
252
  }
253
253
 
254
254
  export function shouldUseTaskModal(boardState, store) {
255
- return Boolean(boardState?.selectedTask);
255
+ return Boolean(boardState?.taskModalOpen && boardState?.selectedTask);
256
256
  }
257
257
 
258
258
  export function lookupNode(snapshot, id) {
@@ -263,6 +263,7 @@ export function createBoardActions(options) {
263
263
  selectedEpicId: epicId || null,
264
264
  selectedTaskId: null,
265
265
  selectedSubtaskId: null,
266
+ taskModalOpen: false,
266
267
  });
267
268
  },
268
269
  selectEpic(epicId) {
@@ -271,6 +272,7 @@ export function createBoardActions(options) {
271
272
  selectedEpicId: epicId || null,
272
273
  selectedTaskId: null,
273
274
  selectedSubtaskId: null,
275
+ taskModalOpen: false,
274
276
  });
275
277
  },
276
278
  showEpics() {
@@ -278,6 +280,7 @@ export function createBoardActions(options) {
278
280
  screen: "epics",
279
281
  selectedTaskId: null,
280
282
  selectedSubtaskId: null,
283
+ taskModalOpen: false,
281
284
  });
282
285
  },
283
286
  showBoard() {
@@ -295,6 +298,7 @@ export function createBoardActions(options) {
295
298
  selectedEpicId: fallbackEpicId,
296
299
  selectedTaskId: null,
297
300
  selectedSubtaskId: null,
301
+ taskModalOpen: false,
298
302
  });
299
303
  },
300
304
  setView(view) {
@@ -340,10 +344,11 @@ export function createBoardActions(options) {
340
344
  screen: "tasks",
341
345
  selectedEpicId: task.epicId,
342
346
  selectedTaskId: taskId,
347
+ taskModalOpen: true,
343
348
  });
344
349
  },
345
350
  closeTask() {
346
- transition({ selectedTaskId: null, selectedSubtaskId: null });
351
+ transition({ selectedTaskId: null, selectedSubtaskId: null, taskModalOpen: false });
347
352
  },
348
353
  openSubtask(subtaskId) {
349
354
  transition({ selectedSubtaskId: subtaskId || null }, { persistState: false });
@@ -413,7 +418,7 @@ export function createBoardActions(options) {
413
418
  if (!task || !nextStatus || task.status === nextStatus) {
414
419
  return;
415
420
  }
416
- transition({ selectedTaskId: taskId }, { rerenderBoard: false });
421
+ transition({ selectedTaskId: taskId, taskModalOpen: false }, { rerenderBoard: false });
417
422
  api.patchTask(taskId, { status: nextStatus }, (snapshot) => updateTaskInSnapshot(snapshot, taskId, { status: nextStatus }, normalizeSnapshot));
418
423
  },
419
424
  changeEpicStatus(epicId, newStatus) {
@@ -224,6 +224,7 @@ function selectSearchScope(state) {
224
224
  * @property {object|null} selectedTask
225
225
  * @property {string|null} selectedSubtaskId
226
226
  * @property {object|null} selectedSubtask
227
+ * @property {boolean} taskModalOpen
227
228
  * @property {string} search
228
229
  * @property {string} searchQuery
229
230
  * @property {object} searchScope
@@ -264,6 +265,8 @@ function deriveBoardState(state) {
264
265
  : stateWithScreen;
265
266
  const selectedSubtask = selectedTaskId ? selectSelectedSubtask(stateWithTaskSelection) : null;
266
267
 
268
+ const taskModalOpen = state.taskModalOpen === true;
269
+
267
270
  return {
268
271
  screen,
269
272
  selectedEpicId: selectedEpic?.id ?? null,
@@ -272,6 +275,7 @@ function deriveBoardState(state) {
272
275
  selectedTask: selectedTaskId ? selectedTask : null,
273
276
  selectedSubtaskId: selectedSubtask?.id ?? null,
274
277
  selectedSubtask,
278
+ taskModalOpen,
275
279
  search: stateWithScreen.search,
276
280
  searchQuery: stateWithScreen.searchQuery,
277
281
  searchScope: selectSearchScope(stateWithScreen),
@@ -289,6 +293,7 @@ function reconcileBoardState(state) {
289
293
  view: VIEW_MODES.includes(state.view) ? state.view : "kanban",
290
294
  selectedTaskId: derived.selectedTaskId,
291
295
  selectedSubtaskId: derived.selectedSubtaskId,
296
+ taskModalOpen: derived.taskModalOpen,
292
297
  };
293
298
  }
294
299
 
@@ -331,6 +336,7 @@ export function createStore(initialSnapshot, options = {}) {
331
336
  view: VIEW_MODES.includes(storedState.view) ? storedState.view : "kanban",
332
337
  selectedTaskId: typeof storedState.selectedTaskId === "string" ? storedState.selectedTaskId : null,
333
338
  selectedSubtaskId: null,
339
+ taskModalOpen: false,
334
340
  theme: readThemePreference(),
335
341
  focusedEpicIndex: 0,
336
342
  copyFeedback: null,
@@ -375,7 +381,8 @@ export function createStore(initialSnapshot, options = {}) {
375
381
  || state.search !== reconciled.search
376
382
  || state.view !== reconciled.view
377
383
  || state.selectedTaskId !== reconciled.selectedTaskId
378
- || state.selectedSubtaskId !== reconciled.selectedSubtaskId;
384
+ || state.selectedSubtaskId !== reconciled.selectedSubtaskId
385
+ || state.taskModalOpen !== reconciled.taskModalOpen;
379
386
 
380
387
  state.screen = reconciled.screen;
381
388
  state.selectedEpicId = reconciled.selectedEpicId;
@@ -384,6 +391,7 @@ export function createStore(initialSnapshot, options = {}) {
384
391
  state.view = reconciled.view;
385
392
  state.selectedTaskId = reconciled.selectedTaskId;
386
393
  state.selectedSubtaskId = reconciled.selectedSubtaskId;
394
+ state.taskModalOpen = reconciled.taskModalOpen;
387
395
  if (changed) {
388
396
  notify();
389
397
  }