@minimalcorp/tsunagi 0.1.3 → 0.1.5

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 (104) hide show
  1. package/.next/standalone/apps/web/.next/BUILD_ID +1 -1
  2. package/.next/standalone/apps/web/.next/app-path-routes-manifest.json +1 -0
  3. package/.next/standalone/apps/web/.next/build-manifest.json +3 -3
  4. package/.next/standalone/apps/web/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/apps/web/.next/routes-manifest.json +6 -0
  6. package/.next/standalone/apps/web/.next/server/app/_global-error.html +1 -1
  7. package/.next/standalone/apps/web/.next/server/app/_global-error.rsc +1 -1
  8. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  11. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  12. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/apps/web/.next/server/app/_not-found.html +1 -1
  15. package/.next/standalone/apps/web/.next/server/app/_not-found.rsc +2 -2
  16. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  17. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  18. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  19. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  20. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  21. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  22. package/.next/standalone/apps/web/.next/server/app/health/route/app-paths-manifest.json +3 -0
  23. package/.next/standalone/apps/web/.next/server/app/health/route/build-manifest.json +9 -0
  24. package/.next/standalone/apps/web/.next/server/app/health/route/server-reference-manifest.json +4 -0
  25. package/.next/standalone/apps/web/.next/server/app/health/route.js +6 -0
  26. package/.next/standalone/apps/web/.next/server/app/health/route.js.map +5 -0
  27. package/.next/standalone/apps/web/.next/server/app/health/route.js.nft.json +1 -0
  28. package/.next/standalone/apps/web/.next/server/app/health/route_client-reference-manifest.js +3 -0
  29. package/.next/standalone/apps/web/.next/server/app/icon.png/route.js +2 -1
  30. package/.next/standalone/apps/web/.next/server/app/icon.png/route.js.nft.json +1 -1
  31. package/.next/standalone/apps/web/.next/server/app/index.html +1 -1
  32. package/.next/standalone/apps/web/.next/server/app/index.rsc +3 -3
  33. package/.next/standalone/apps/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  34. package/.next/standalone/apps/web/.next/server/app/index.segments/_full.segment.rsc +3 -3
  35. package/.next/standalone/apps/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  36. package/.next/standalone/apps/web/.next/server/app/index.segments/_index.segment.rsc +2 -2
  37. package/.next/standalone/apps/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  38. package/.next/standalone/apps/web/.next/server/app/page.js.nft.json +1 -1
  39. package/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  40. package/.next/standalone/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  41. package/.next/standalone/apps/web/.next/server/app/settings.html +1 -1
  42. package/.next/standalone/apps/web/.next/server/app/settings.rsc +2 -2
  43. package/.next/standalone/apps/web/.next/server/app/settings.segments/_full.segment.rsc +2 -2
  44. package/.next/standalone/apps/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  45. package/.next/standalone/apps/web/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  46. package/.next/standalone/apps/web/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  47. package/.next/standalone/apps/web/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
  48. package/.next/standalone/apps/web/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  49. package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page.js.nft.json +1 -1
  50. package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  51. package/.next/standalone/apps/web/.next/server/app-paths-manifest.json +1 -0
  52. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__03yk.z3._.js +3 -0
  53. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0op9af~._.js +3 -0
  54. package/.next/standalone/apps/web/.next/server/chunks/apps_web__next-internal_server_app_health_route_actions_08pjq78.js +3 -0
  55. package/.next/standalone/apps/web/.next/server/chunks/node_modules_next_06p.d_a._.js +13 -0
  56. package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0dg0i1g._.js → [root-of-the-server]__092mq4r._.js} +2 -2
  57. package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__12yece_._.js → [root-of-the-server]__0_p.e.m._.js} +15 -15
  58. package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0qw6wy3._.js → [root-of-the-server]__12vhk8e._.js} +15 -15
  59. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0g.cd6a._.js +1 -1
  60. package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_src_app_tasks_[id]_page_tsx_0jshsm2._.js +2 -2
  61. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_07.c491._.js → node_modules_0-31hvv._.js} +1 -1
  62. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0t3_1om._.js → node_modules_00je7te._.js} +1 -1
  63. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_02~gcwc._.js → node_modules_08zu-qy._.js} +1 -1
  64. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0gpuu-x._.js → node_modules_0f5l4h2._.js} +1 -1
  65. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_12qdm6m._.js → node_modules_0m9gy6q._.js} +1 -1
  66. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0cphr_r._.js → node_modules_0o0.qfb._.js} +1 -1
  67. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0-4t5u4._.js → node_modules_0yo5dp5._.js} +1 -1
  68. package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_055srxz._.js → node_modules_0zdgon0._.js} +1 -1
  69. package/.next/standalone/apps/web/.next/server/middleware-build-manifest.js +3 -3
  70. package/.next/standalone/apps/web/.next/server/pages/404.html +1 -1
  71. package/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
  72. package/.next/standalone/apps/web/.next/server/server-reference-manifest.js +1 -1
  73. package/.next/standalone/apps/web/.next/server/server-reference-manifest.json +1 -1
  74. package/.next/standalone/apps/web/.next/static/chunks/{0l0s3fn6xga.t.js → 06h0.7cz1a2pw.js} +13 -13
  75. package/.next/standalone/apps/web/.next/static/chunks/0g.gfve6-xixo.css +4 -0
  76. package/.next/standalone/apps/web/.next/static/chunks/{0hx_sdyz0yyfb.js → 0u1x2j.2fd983.js} +7 -7
  77. package/.next/standalone/apps/web/.next/static/chunks/0wd663tqvi2ts.js +3 -0
  78. package/.next/standalone/apps/web/.next/static/chunks/{0ew.-lnxoet~x.js → 0zi97fcrx3u_8.js} +13 -13
  79. package/dist/auto-migrate.js +6 -7
  80. package/dist/cli.js +195 -10
  81. package/dist/plugin-lifecycle.d.ts +4 -1
  82. package/dist/plugin-lifecycle.js +11 -4
  83. package/dist/server/generated/prisma/commonInputTypes.d.ts +36 -36
  84. package/dist/server/generated/prisma/internal/class.js +2 -2
  85. package/dist/server/generated/prisma/models/Tab.d.ts +0 -7
  86. package/dist/server/generated/prisma/models/Task.d.ts +32 -25
  87. package/dist/server/index.js +6 -1
  88. package/dist/server/lib/repositories/task.d.ts +4 -2
  89. package/dist/server/lib/repositories/task.js +8 -6
  90. package/dist/server/lib/services/task-service.js +27 -17
  91. package/dist/server/routes/hooks.js +24 -12
  92. package/dist/server/routes/tasks.js +2 -2
  93. package/dist/server/routes/terminal.js +3 -2
  94. package/package.json +2 -1
  95. package/prisma/migrations/20260410000000_clear_stale_tab_todos/migration.sql +4 -0
  96. package/prisma/migrations/20260413000000_make_task_order_non_nullable/migration.sql +47 -0
  97. package/prisma/schema.prisma +1 -1
  98. package/tsunagi-marketplace/plugins/tsunagi-plugin/skills/tsunagi-task/SKILL.md +21 -0
  99. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0jam776._.js +0 -13
  100. package/.next/standalone/apps/web/.next/static/chunks/0b8.3al6nvw3d.css +0 -4
  101. package/.next/standalone/apps/web/.next/static/chunks/12r3ashx0krmo.js +0 -3
  102. /package/.next/standalone/apps/web/.next/static/{y1VVVedZfN-isLJKKaC_l → 3spyaOCz0ow4ijl7Dvjpb}/_buildManifest.js +0 -0
  103. /package/.next/standalone/apps/web/.next/static/{y1VVVedZfN-isLJKKaC_l → 3spyaOCz0ow4ijl7Dvjpb}/_clientMiddlewareManifest.js +0 -0
  104. /package/.next/standalone/apps/web/.next/static/{y1VVVedZfN-isLJKKaC_l → 3spyaOCz0ow4ijl7Dvjpb}/_ssgManifest.js +0 -0
@@ -227,7 +227,7 @@ export type TaskGroupByOutputType = {
227
227
  worktreeStatus: string;
228
228
  pullRequestUrl: string | null;
229
229
  effort: number | null;
230
- order: number | null;
230
+ order: number;
231
231
  deletedAt: Date | null;
232
232
  createdAt: Date;
233
233
  updatedAt: Date;
@@ -256,7 +256,7 @@ export type TaskWhereInput = {
256
256
  worktreeStatus?: Prisma.StringFilter<"Task"> | string;
257
257
  pullRequestUrl?: Prisma.StringNullableFilter<"Task"> | string | null;
258
258
  effort?: Prisma.IntNullableFilter<"Task"> | number | null;
259
- order?: Prisma.IntNullableFilter<"Task"> | number | null;
259
+ order?: Prisma.IntFilter<"Task"> | number;
260
260
  deletedAt?: Prisma.DateTimeNullableFilter<"Task"> | Date | string | null;
261
261
  createdAt?: Prisma.DateTimeFilter<"Task"> | Date | string;
262
262
  updatedAt?: Prisma.DateTimeFilter<"Task"> | Date | string;
@@ -276,7 +276,7 @@ export type TaskOrderByWithRelationInput = {
276
276
  worktreeStatus?: Prisma.SortOrder;
277
277
  pullRequestUrl?: Prisma.SortOrderInput | Prisma.SortOrder;
278
278
  effort?: Prisma.SortOrderInput | Prisma.SortOrder;
279
- order?: Prisma.SortOrderInput | Prisma.SortOrder;
279
+ order?: Prisma.SortOrder;
280
280
  deletedAt?: Prisma.SortOrderInput | Prisma.SortOrder;
281
281
  createdAt?: Prisma.SortOrder;
282
282
  updatedAt?: Prisma.SortOrder;
@@ -299,7 +299,7 @@ export type TaskWhereUniqueInput = Prisma.AtLeast<{
299
299
  worktreeStatus?: Prisma.StringFilter<"Task"> | string;
300
300
  pullRequestUrl?: Prisma.StringNullableFilter<"Task"> | string | null;
301
301
  effort?: Prisma.IntNullableFilter<"Task"> | number | null;
302
- order?: Prisma.IntNullableFilter<"Task"> | number | null;
302
+ order?: Prisma.IntFilter<"Task"> | number;
303
303
  deletedAt?: Prisma.DateTimeNullableFilter<"Task"> | Date | string | null;
304
304
  createdAt?: Prisma.DateTimeFilter<"Task"> | Date | string;
305
305
  updatedAt?: Prisma.DateTimeFilter<"Task"> | Date | string;
@@ -319,7 +319,7 @@ export type TaskOrderByWithAggregationInput = {
319
319
  worktreeStatus?: Prisma.SortOrder;
320
320
  pullRequestUrl?: Prisma.SortOrderInput | Prisma.SortOrder;
321
321
  effort?: Prisma.SortOrderInput | Prisma.SortOrder;
322
- order?: Prisma.SortOrderInput | Prisma.SortOrder;
322
+ order?: Prisma.SortOrder;
323
323
  deletedAt?: Prisma.SortOrderInput | Prisma.SortOrder;
324
324
  createdAt?: Prisma.SortOrder;
325
325
  updatedAt?: Prisma.SortOrder;
@@ -345,7 +345,7 @@ export type TaskScalarWhereWithAggregatesInput = {
345
345
  worktreeStatus?: Prisma.StringWithAggregatesFilter<"Task"> | string;
346
346
  pullRequestUrl?: Prisma.StringNullableWithAggregatesFilter<"Task"> | string | null;
347
347
  effort?: Prisma.IntNullableWithAggregatesFilter<"Task"> | number | null;
348
- order?: Prisma.IntNullableWithAggregatesFilter<"Task"> | number | null;
348
+ order?: Prisma.IntWithAggregatesFilter<"Task"> | number;
349
349
  deletedAt?: Prisma.DateTimeNullableWithAggregatesFilter<"Task"> | Date | string | null;
350
350
  createdAt?: Prisma.DateTimeWithAggregatesFilter<"Task"> | Date | string;
351
351
  updatedAt?: Prisma.DateTimeWithAggregatesFilter<"Task"> | Date | string;
@@ -362,7 +362,7 @@ export type TaskCreateInput = {
362
362
  worktreeStatus: string;
363
363
  pullRequestUrl?: string | null;
364
364
  effort?: number | null;
365
- order?: number | null;
365
+ order?: number;
366
366
  deletedAt?: Date | string | null;
367
367
  createdAt?: Date | string;
368
368
  updatedAt?: Date | string;
@@ -382,7 +382,7 @@ export type TaskUncheckedCreateInput = {
382
382
  worktreeStatus: string;
383
383
  pullRequestUrl?: string | null;
384
384
  effort?: number | null;
385
- order?: number | null;
385
+ order?: number;
386
386
  deletedAt?: Date | string | null;
387
387
  createdAt?: Date | string;
388
388
  updatedAt?: Date | string;
@@ -400,7 +400,7 @@ export type TaskUpdateInput = {
400
400
  worktreeStatus?: Prisma.StringFieldUpdateOperationsInput | string;
401
401
  pullRequestUrl?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
402
402
  effort?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
403
- order?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
403
+ order?: Prisma.IntFieldUpdateOperationsInput | number;
404
404
  deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
405
405
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
406
406
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
@@ -420,7 +420,7 @@ export type TaskUncheckedUpdateInput = {
420
420
  worktreeStatus?: Prisma.StringFieldUpdateOperationsInput | string;
421
421
  pullRequestUrl?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
422
422
  effort?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
423
- order?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
423
+ order?: Prisma.IntFieldUpdateOperationsInput | number;
424
424
  deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
425
425
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
426
426
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
@@ -439,7 +439,7 @@ export type TaskCreateManyInput = {
439
439
  worktreeStatus: string;
440
440
  pullRequestUrl?: string | null;
441
441
  effort?: number | null;
442
- order?: number | null;
442
+ order?: number;
443
443
  deletedAt?: Date | string | null;
444
444
  createdAt?: Date | string;
445
445
  updatedAt?: Date | string;
@@ -456,7 +456,7 @@ export type TaskUpdateManyMutationInput = {
456
456
  worktreeStatus?: Prisma.StringFieldUpdateOperationsInput | string;
457
457
  pullRequestUrl?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
458
458
  effort?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
459
- order?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
459
+ order?: Prisma.IntFieldUpdateOperationsInput | number;
460
460
  deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
461
461
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
462
462
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
@@ -474,7 +474,7 @@ export type TaskUncheckedUpdateManyInput = {
474
474
  worktreeStatus?: Prisma.StringFieldUpdateOperationsInput | string;
475
475
  pullRequestUrl?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
476
476
  effort?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
477
- order?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
477
+ order?: Prisma.IntFieldUpdateOperationsInput | number;
478
478
  deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
479
479
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
480
480
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
@@ -601,6 +601,13 @@ export type NullableIntFieldUpdateOperationsInput = {
601
601
  multiply?: number;
602
602
  divide?: number;
603
603
  };
604
+ export type IntFieldUpdateOperationsInput = {
605
+ set?: number;
606
+ increment?: number;
607
+ decrement?: number;
608
+ multiply?: number;
609
+ divide?: number;
610
+ };
604
611
  export type NullableDateTimeFieldUpdateOperationsInput = {
605
612
  set?: Date | string | null;
606
613
  };
@@ -628,7 +635,7 @@ export type TaskCreateWithoutRepositoryInput = {
628
635
  worktreeStatus: string;
629
636
  pullRequestUrl?: string | null;
630
637
  effort?: number | null;
631
- order?: number | null;
638
+ order?: number;
632
639
  deletedAt?: Date | string | null;
633
640
  createdAt?: Date | string;
634
641
  updatedAt?: Date | string;
@@ -646,7 +653,7 @@ export type TaskUncheckedCreateWithoutRepositoryInput = {
646
653
  worktreeStatus: string;
647
654
  pullRequestUrl?: string | null;
648
655
  effort?: number | null;
649
- order?: number | null;
656
+ order?: number;
650
657
  deletedAt?: Date | string | null;
651
658
  createdAt?: Date | string;
652
659
  updatedAt?: Date | string;
@@ -688,7 +695,7 @@ export type TaskScalarWhereInput = {
688
695
  worktreeStatus?: Prisma.StringFilter<"Task"> | string;
689
696
  pullRequestUrl?: Prisma.StringNullableFilter<"Task"> | string | null;
690
697
  effort?: Prisma.IntNullableFilter<"Task"> | number | null;
691
- order?: Prisma.IntNullableFilter<"Task"> | number | null;
698
+ order?: Prisma.IntFilter<"Task"> | number;
692
699
  deletedAt?: Prisma.DateTimeNullableFilter<"Task"> | Date | string | null;
693
700
  createdAt?: Prisma.DateTimeFilter<"Task"> | Date | string;
694
701
  updatedAt?: Prisma.DateTimeFilter<"Task"> | Date | string;
@@ -705,7 +712,7 @@ export type TaskCreateWithoutTabsInput = {
705
712
  worktreeStatus: string;
706
713
  pullRequestUrl?: string | null;
707
714
  effort?: number | null;
708
- order?: number | null;
715
+ order?: number;
709
716
  deletedAt?: Date | string | null;
710
717
  createdAt?: Date | string;
711
718
  updatedAt?: Date | string;
@@ -724,7 +731,7 @@ export type TaskUncheckedCreateWithoutTabsInput = {
724
731
  worktreeStatus: string;
725
732
  pullRequestUrl?: string | null;
726
733
  effort?: number | null;
727
- order?: number | null;
734
+ order?: number;
728
735
  deletedAt?: Date | string | null;
729
736
  createdAt?: Date | string;
730
737
  updatedAt?: Date | string;
@@ -754,7 +761,7 @@ export type TaskUpdateWithoutTabsInput = {
754
761
  worktreeStatus?: Prisma.StringFieldUpdateOperationsInput | string;
755
762
  pullRequestUrl?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
756
763
  effort?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
757
- order?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
764
+ order?: Prisma.IntFieldUpdateOperationsInput | number;
758
765
  deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
759
766
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
760
767
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
@@ -773,7 +780,7 @@ export type TaskUncheckedUpdateWithoutTabsInput = {
773
780
  worktreeStatus?: Prisma.StringFieldUpdateOperationsInput | string;
774
781
  pullRequestUrl?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
775
782
  effort?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
776
- order?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
783
+ order?: Prisma.IntFieldUpdateOperationsInput | number;
777
784
  deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
778
785
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
779
786
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
@@ -790,7 +797,7 @@ export type TaskCreateManyRepositoryInput = {
790
797
  worktreeStatus: string;
791
798
  pullRequestUrl?: string | null;
792
799
  effort?: number | null;
793
- order?: number | null;
800
+ order?: number;
794
801
  deletedAt?: Date | string | null;
795
802
  createdAt?: Date | string;
796
803
  updatedAt?: Date | string;
@@ -807,7 +814,7 @@ export type TaskUpdateWithoutRepositoryInput = {
807
814
  worktreeStatus?: Prisma.StringFieldUpdateOperationsInput | string;
808
815
  pullRequestUrl?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
809
816
  effort?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
810
- order?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
817
+ order?: Prisma.IntFieldUpdateOperationsInput | number;
811
818
  deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
812
819
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
813
820
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
@@ -825,7 +832,7 @@ export type TaskUncheckedUpdateWithoutRepositoryInput = {
825
832
  worktreeStatus?: Prisma.StringFieldUpdateOperationsInput | string;
826
833
  pullRequestUrl?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
827
834
  effort?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
828
- order?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
835
+ order?: Prisma.IntFieldUpdateOperationsInput | number;
829
836
  deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
830
837
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
831
838
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
@@ -843,7 +850,7 @@ export type TaskUncheckedUpdateManyWithoutRepositoryInput = {
843
850
  worktreeStatus?: Prisma.StringFieldUpdateOperationsInput | string;
844
851
  pullRequestUrl?: Prisma.NullableStringFieldUpdateOperationsInput | string | null;
845
852
  effort?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
846
- order?: Prisma.NullableIntFieldUpdateOperationsInput | number | null;
853
+ order?: Prisma.IntFieldUpdateOperationsInput | number;
847
854
  deletedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null;
848
855
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
849
856
  updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string;
@@ -980,7 +987,7 @@ export type $TaskPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs =
980
987
  worktreeStatus: string;
981
988
  pullRequestUrl: string | null;
982
989
  effort: number | null;
983
- order: number | null;
990
+ order: number;
984
991
  deletedAt: Date | null;
985
992
  createdAt: Date;
986
993
  updatedAt: Date;
@@ -20,7 +20,11 @@ const extraOrigins = (process.env.TSUNAGI_EXTRA_CORS_ORIGINS ?? '')
20
20
  .filter(Boolean);
21
21
  const corsOrigins = ['http://localhost:2791', ...extraOrigins];
22
22
  async function start() {
23
- const fastify = Fastify({ logger: true });
23
+ const fastify = Fastify({
24
+ logger: {
25
+ level: process.env.LOG_LEVEL || (process.env.NODE_ENV === 'production' ? 'error' : 'info'),
26
+ },
27
+ });
24
28
  await fastify.register(fastifyCors, {
25
29
  origin: corsOrigins,
26
30
  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
@@ -30,6 +34,7 @@ async function start() {
30
34
  cors: { origin: corsOrigins },
31
35
  });
32
36
  fastify.decorate('io', io);
37
+ fastify.get('/health', async () => ({ status: 'ok' }));
33
38
  await fastify.register(tasksRoutes, { prefix: '/api' });
34
39
  await fastify.register(reposRoutes, { prefix: '/api' });
35
40
  await fastify.register(envRoutes, { prefix: '/api' });
@@ -1,4 +1,6 @@
1
+ import { prisma } from '../db.js';
1
2
  import type { Task, Tab } from '@minimalcorp/tsunagi-shared';
3
+ export type TxClient = Parameters<Parameters<(typeof prisma)['$transaction']>[0]>[0];
2
4
  export declare function getTasks(filter?: {
3
5
  includeDeleted?: boolean;
4
6
  status?: Task['status'] | Task['status'][];
@@ -7,9 +9,9 @@ export declare function getTasks(filter?: {
7
9
  updatedBefore?: Date;
8
10
  }): Promise<Task[]>;
9
11
  export declare function getTask(id: string): Promise<Task | null>;
10
- export declare function createTask(task: Omit<Task, 'id' | 'deleted' | 'deletedAt' | 'createdAt' | 'updatedAt' | 'tabs'>): Promise<Task>;
12
+ export declare function createTask(task: Omit<Task, 'id' | 'deleted' | 'deletedAt' | 'createdAt' | 'updatedAt' | 'tabs'>, tx?: TxClient): Promise<Task>;
11
13
  export declare function updateTask(id: string, updates: Partial<Omit<Task, 'id' | 'createdAt'>>): Promise<Task | null>;
12
- export declare function bumpOrder(targetOrder: number, excludeTaskId?: string): Promise<void>;
14
+ export declare function bumpOrder(targetOrder: number, excludeTaskId?: string, tx?: TxClient): Promise<void>;
13
15
  export declare function deleteTask(id: string): Promise<boolean>;
14
16
  export declare function createTab(taskId: string): Promise<Tab | null>;
15
17
  export declare function getTab(taskId: string, tab_id: string): Promise<Tab | null>;
@@ -16,7 +16,7 @@ export async function getTasks(filter) {
16
16
  orderBy: { order: 'asc' },
17
17
  },
18
18
  },
19
- orderBy: { createdAt: 'desc' },
19
+ orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],
20
20
  });
21
21
  return tasks.map((task) => mapTask(task));
22
22
  }
@@ -35,8 +35,9 @@ export async function getTask(id) {
35
35
  return mapTask(task);
36
36
  }
37
37
  // タスク作成
38
- export async function createTask(task) {
39
- const newTask = await prisma.task.create({
38
+ export async function createTask(task, tx) {
39
+ const client = tx ?? prisma;
40
+ const newTask = await client.task.create({
40
41
  data: {
41
42
  status: task.status,
42
43
  title: task.title,
@@ -84,8 +85,9 @@ export async function updateTask(id, updates) {
84
85
  return mapTask(updatedTask);
85
86
  }
86
87
  // 指定order以上のタスクを+1ずらす(玉突き)
87
- export async function bumpOrder(targetOrder, excludeTaskId) {
88
- await prisma.task.updateMany({
88
+ export async function bumpOrder(targetOrder, excludeTaskId, tx) {
89
+ const client = tx ?? prisma;
90
+ await client.task.updateMany({
89
91
  where: {
90
92
  order: { gte: targetOrder },
91
93
  deletedAt: null,
@@ -213,7 +215,7 @@ function mapTask(task) {
213
215
  worktreeStatus: task.worktreeStatus,
214
216
  pullRequestUrl: task.pullRequestUrl ?? undefined,
215
217
  effort: task.effort ?? undefined,
216
- order: task.order ?? undefined,
218
+ order: task.order,
217
219
  deletedAt: task.deletedAt?.toISOString(),
218
220
  createdAt: task.createdAt.toISOString(),
219
221
  updatedAt: task.updatedAt.toISOString(),
@@ -112,23 +112,33 @@ export async function createTask(params, options) {
112
112
  if (duplicateTask) {
113
113
  throw new TaskServiceError(`Branch "${branch}" already exists. Task "${duplicateTask.title}" (ID: ${duplicateTask.id}) is already using this branch.`, 'BRANCH_DUPLICATE');
114
114
  }
115
- // 1. order指定時は玉突き処理
116
- if (order !== undefined) {
117
- await taskRepo.bumpOrder(order);
118
- }
119
- // 2. DBにタスク登録
120
- const newTask = await taskRepo.createTask({
121
- title,
122
- description,
123
- status,
124
- owner,
125
- repo,
126
- branch,
127
- baseBranch,
128
- repoId: repository.id,
129
- worktreeStatus: 'pending',
130
- effort,
131
- order,
115
+ // 1. order解決 + bumpOrder + DB登録をアトミックに実行
116
+ const newTask = await prisma.$transaction(async (tx) => {
117
+ let resolvedOrder;
118
+ if (order !== undefined) {
119
+ resolvedOrder = order;
120
+ await taskRepo.bumpOrder(resolvedOrder, undefined, tx);
121
+ }
122
+ else {
123
+ const result = await tx.task.aggregate({
124
+ where: { owner, repo, deletedAt: null },
125
+ _max: { order: true },
126
+ });
127
+ resolvedOrder = (result._max.order ?? -1) + 1;
128
+ }
129
+ return await taskRepo.createTask({
130
+ title,
131
+ description,
132
+ status,
133
+ owner,
134
+ repo,
135
+ branch,
136
+ baseBranch,
137
+ repoId: repository.id,
138
+ worktreeStatus: 'pending',
139
+ effort,
140
+ order: resolvedOrder,
141
+ }, tx);
132
142
  });
133
143
  // 3. worktree作成
134
144
  try {
@@ -1,26 +1,31 @@
1
1
  import { prisma } from '../lib/db.js';
2
2
  export const hookEvents = [];
3
3
  const sessionTasks = new Map();
4
- /** TaskEntryリストをTodo形式に変換 */
4
+ /**
5
+ * TaskEntryリストをTodo形式に変換。
6
+ * 'deleted' を含めて全 status を pass-through し、表示時のフィルタは frontend 側に任せる。
7
+ */
5
8
  function tasksToTodos(tasks) {
6
9
  return Array.from(tasks.values()).map((t) => ({
7
10
  content: t.subject,
8
- status: t.status === 'in_progress' ? 'in_progress' : t.status,
11
+ status: t.status,
9
12
  }));
10
13
  }
11
14
  /** DBでタブのステータス(+ todos)を直接更新する */
12
15
  async function updateTabStatus(sessionId, status, todos) {
13
16
  try {
14
- await prisma.tab.updateMany({
17
+ const result = await prisma.tab.updateMany({
15
18
  where: { tabId: sessionId },
16
19
  data: {
17
20
  status,
18
21
  ...(todos !== undefined && { todos: JSON.stringify(todos) }),
19
22
  },
20
23
  });
24
+ return { count: result.count };
21
25
  }
22
26
  catch (err) {
23
27
  console.warn(`[hooks] Failed to update tab status in DB:`, err);
28
+ return { count: 0 };
24
29
  }
25
30
  }
26
31
  export async function hooksRoutes(fastify) {
@@ -64,7 +69,9 @@ export async function hooksRoutes(fastify) {
64
69
  if (body.tool_name === 'TodoWrite' && body.tool_input) {
65
70
  const todos = body.tool_input.todos;
66
71
  if (Array.isArray(todos)) {
67
- await updateTabStatus(sessionId, 'running', todos);
72
+ fastify.log.info({ sessionId, todosCount: todos.length }, '[hooks] TodoWrite received');
73
+ const { count } = await updateTabStatus(sessionId, 'running', todos);
74
+ fastify.log.info({ sessionId, updatedTabCount: count }, '[hooks] TodoWrite tab updated');
68
75
  io.to(room).emit('todos-updated', { sessionId, todos });
69
76
  todosUpdated = true;
70
77
  }
@@ -87,16 +94,19 @@ export async function hooksRoutes(fastify) {
87
94
  todosUpdated = true;
88
95
  }
89
96
  }
90
- // TaskUpdate: タスクのステータスを更新
97
+ // TaskUpdate: タスクのステータスを更新('deleted' 含む。Mapからは除去せず保持し、表示層で除外)
91
98
  if (body.tool_name === 'TaskUpdate' && body.tool_response && body.tool_input) {
92
99
  const taskId = body.tool_input.taskId;
93
- const statusChange = body.tool_response.statusChange;
100
+ // tool_input.status を優先(直接入力なので確実)、フォールバックで tool_response.statusChange.to
101
+ const newStatus = body.tool_input.status ??
102
+ body.tool_response.statusChange?.to;
94
103
  const tasks = sessionTasks.get(sessionId);
95
- if (tasks && taskId && statusChange?.to) {
104
+ if (tasks && taskId && newStatus) {
96
105
  const entry = tasks.get(taskId);
97
106
  if (entry) {
98
- entry.status = statusChange.to;
107
+ entry.status = newStatus;
99
108
  const todos = tasksToTodos(tasks);
109
+ fastify.log.info({ sessionId, taskId, newStatus, mapSize: tasks.size }, '[hooks] TaskUpdate processed');
100
110
  await updateTabStatus(sessionId, 'running', todos);
101
111
  io.to(room).emit('todos-updated', { sessionId, todos });
102
112
  todosUpdated = true;
@@ -118,16 +128,18 @@ export async function hooksRoutes(fastify) {
118
128
  io.to(room).emit('status-changed', { sessionId, status: 'success' });
119
129
  break;
120
130
  case 'StopFailure':
121
- // APIエラーでターン終了 → failure状態に更新
122
- await updateTabStatus(sessionId, 'error');
131
+ // APIエラーでターン終了 → failure状態に更新、todosをクリア
132
+ await updateTabStatus(sessionId, 'error', []);
123
133
  io.to(room).emit('status-changed', { sessionId, status: 'failure' });
134
+ io.to(room).emit('todos-updated', { sessionId, todos: [] });
124
135
  break;
125
136
  case 'SessionEnd':
126
- // セッション終了(Escキー中断・Ctrl+C・/exit等)→ idle状態に更新
137
+ // セッション終了(Escキー中断・Ctrl+C・/exit等)→ idle状態に更新、todosをクリア
127
138
  // reason: "prompt_input_exit" = ユーザー中断、"other" = プロセスkill等
128
139
  fastify.log.info({ sessionId, reason: body.reason }, 'SessionEnd received');
129
- await updateTabStatus(sessionId, 'idle');
140
+ await updateTabStatus(sessionId, 'idle', []);
130
141
  io.to(room).emit('status-changed', { sessionId, status: 'idle' });
142
+ io.to(room).emit('todos-updated', { sessionId, todos: [] });
131
143
  break;
132
144
  default:
133
145
  fastify.log.debug({ eventName }, 'Unhandled hook event');
@@ -159,7 +159,7 @@ export async function tasksRoutes(fastify) {
159
159
  fastify.put('/tasks/:id', async (request, reply) => {
160
160
  try {
161
161
  const { id } = request.params;
162
- const updatedTask = await updateTask({ id }, request.body);
162
+ const updatedTask = await updateTask({ id }, request.body, { io });
163
163
  return reply.status(200).send({ data: { task: updatedTask } });
164
164
  }
165
165
  catch (error) {
@@ -174,7 +174,7 @@ export async function tasksRoutes(fastify) {
174
174
  fastify.delete('/tasks/:id', async (request, reply) => {
175
175
  try {
176
176
  const { id } = request.params;
177
- await deleteTask({ id });
177
+ await deleteTask({ id }, { io });
178
178
  return reply.status(200).send({ data: { success: true } });
179
179
  }
180
180
  catch (error) {
@@ -48,12 +48,13 @@ export async function terminalRoutes(fastify) {
48
48
  // PTYプロセス終了 → room全体に通知(全接続クライアントに終了を伝える)+ セッション削除
49
49
  const exitHandler = ptyProcess.onExit(({ exitCode }) => {
50
50
  io.to(room).emit('exit', { exitCode });
51
- // Ctrl+C等でClaudeが強制終了した場合にclaudeStatusをidleにリセット
51
+ // Ctrl+C等でClaudeが強制終了した場合にclaudeStatusをidleにリセット、todosをクリア
52
52
  io.to(room).emit('status-changed', { sessionId, status: 'idle' });
53
+ io.to(room).emit('todos-updated', { sessionId, todos: [] });
53
54
  prisma.tab
54
55
  .updateMany({
55
56
  where: { tabId: sessionId },
56
- data: { status: 'idle' },
57
+ data: { status: 'idle', todos: '[]' },
57
58
  })
58
59
  .catch(() => {
59
60
  /* DB更新失敗は無視 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minimalcorp/tsunagi",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Multi-repo GitHub project management with Claude AI integration, designed for visualizing and controlling AI-driven development locally.",
5
5
  "keywords": [
6
6
  "tsunagi",
@@ -36,6 +36,7 @@
36
36
  },
37
37
  "files": [
38
38
  "dist/**/*",
39
+ "docs/**/*",
39
40
  "prisma/schema.prisma",
40
41
  "prisma/migrations/**/*",
41
42
  "prisma.config.ts",
@@ -0,0 +1,4 @@
1
+ -- session 終了時の todos クリア漏れで蓄積した stale データを一括リセット
2
+ -- idle/error 状態のタブは次回セッション開始まで参照されないため安全にクリアできる
3
+ -- success 状態(Stop 正常完了)のタブは累積プログレス表示のため意図的に残す
4
+ UPDATE "tabs" SET todos = '[]' WHERE status IN ('idle', 'error');
@@ -0,0 +1,47 @@
1
+ -- BackfillNullOrders
2
+ -- 既存の NULL order を createdAt 昇順で連番付与(既存の最大値の後ろから)
3
+ WITH ranked AS (
4
+ SELECT id,
5
+ ROW_NUMBER() OVER (ORDER BY created_at ASC) AS rn
6
+ FROM tasks
7
+ WHERE "order" IS NULL AND deleted_at IS NULL
8
+ )
9
+ UPDATE tasks
10
+ SET "order" = (
11
+ SELECT COALESCE(MAX("order"), -1) FROM tasks WHERE "order" IS NOT NULL AND deleted_at IS NULL
12
+ ) + (SELECT rn FROM ranked WHERE ranked.id = tasks.id)
13
+ WHERE id IN (SELECT id FROM ranked);
14
+
15
+ -- 論理削除済みタスクにも 0 を入れておく(NOT NULL 制約のため)
16
+ UPDATE tasks SET "order" = 0 WHERE "order" IS NULL;
17
+
18
+ -- RedefineTables
19
+ PRAGMA defer_foreign_keys=ON;
20
+ PRAGMA foreign_keys=OFF;
21
+ CREATE TABLE "new_tasks" (
22
+ "id" TEXT NOT NULL PRIMARY KEY,
23
+ "title" TEXT NOT NULL,
24
+ "description" TEXT NOT NULL,
25
+ "status" TEXT NOT NULL,
26
+ "owner" TEXT NOT NULL,
27
+ "repo" TEXT NOT NULL,
28
+ "branch" TEXT NOT NULL,
29
+ "base_branch" TEXT NOT NULL,
30
+ "repo_id" TEXT NOT NULL,
31
+ "worktree_status" TEXT NOT NULL,
32
+ "pull_request_url" TEXT,
33
+ "effort" INTEGER,
34
+ "order" INTEGER NOT NULL DEFAULT 0,
35
+ "deleted_at" DATETIME,
36
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
37
+ "updated_at" DATETIME NOT NULL,
38
+ CONSTRAINT "tasks_repo_id_fkey" FOREIGN KEY ("repo_id") REFERENCES "repositories" ("id") ON DELETE CASCADE ON UPDATE CASCADE
39
+ );
40
+ INSERT INTO "new_tasks" ("id", "title", "description", "status", "owner", "repo", "branch", "base_branch", "repo_id", "worktree_status", "pull_request_url", "effort", "order", "deleted_at", "created_at", "updated_at") SELECT "id", "title", "description", "status", "owner", "repo", "branch", "base_branch", "repo_id", "worktree_status", "pull_request_url", "effort", "order", "deleted_at", "created_at", "updated_at" FROM "tasks";
41
+ DROP TABLE "tasks";
42
+ ALTER TABLE "new_tasks" RENAME TO "tasks";
43
+ CREATE INDEX "tasks_owner_repo_idx" ON "tasks"("owner", "repo");
44
+ CREATE INDEX "tasks_status_idx" ON "tasks"("status");
45
+ CREATE INDEX "tasks_deleted_at_idx" ON "tasks"("deleted_at");
46
+ PRAGMA foreign_keys=ON;
47
+ PRAGMA defer_foreign_keys=OFF;
@@ -39,7 +39,7 @@ model Task {
39
39
  pullRequestUrl String? @map("pull_request_url")
40
40
 
41
41
  effort Int?
42
- order Int?
42
+ order Int @default(0)
43
43
  deletedAt DateTime? @map("deleted_at")
44
44
  createdAt DateTime @default(now()) @map("created_at")
45
45
  updatedAt DateTime @updatedAt @map("updated_at")
@@ -17,6 +17,27 @@ description: プロジェクトのタスク管理ツール。タスクの検索
17
17
 
18
18
  遷移は必ず順方向: backlog → planning → coding → reviewing → done
19
19
 
20
+ ## 実装開始時の TODO 作成(必須)
21
+
22
+ `coding` に遷移したら、**即座に** Claude Code 組み込みの `TodoWrite` ツールで実装ステップを TODO として登録する。これにより tsunagi UI にプログレスバーが表示される。
23
+
24
+ ### 手順
25
+
26
+ 1. `tsunagi_update_task(status: "coding")` の直後に `TodoWrite` を呼ぶ
27
+ 2. 各 TODO は完了判断が明確な作業単位にする
28
+ - 例: 「○○ファイルを修正」「マイグレーション作成・適用」「lint/type-check を通す」「動作確認」
29
+ 3. ステップ完了ごとに `TodoWrite` で該当項目の status を `in_progress` → `completed` に更新する
30
+ 4. 作業中に追加ステップが判明した場合、既存 TODO に追記して `TodoWrite` で再登録する
31
+
32
+ ### 語彙の使い分け(混同注意)
33
+
34
+ | 対象 | 使うツール | status 語彙 |
35
+ | --------------- | ---------------------- | -------------------------------------- |
36
+ | tsunagi タスク | `tsunagi_update_task` | backlog/planning/coding/reviewing/done |
37
+ | tab TODO (進捗) | `TodoWrite` (組み込み) | pending/in_progress/completed |
38
+
39
+ tsunagi タスクの status に `in_progress` を渡してはいけない(「よくある間違い」表参照)。逆に TODO の進捗管理は組み込み `TodoWrite` で行う。
40
+
20
41
  ## 現在のタスクを特定する
21
42
 
22
43
  タスク操作には `id`, `session_id`, `cwd` のいずれかでタスクを指定する。