@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.
- package/.next/standalone/apps/web/.next/BUILD_ID +1 -1
- package/.next/standalone/apps/web/.next/app-path-routes-manifest.json +1 -0
- package/.next/standalone/apps/web/.next/build-manifest.json +3 -3
- package/.next/standalone/apps/web/.next/prerender-manifest.json +3 -3
- package/.next/standalone/apps/web/.next/routes-manifest.json +6 -0
- package/.next/standalone/apps/web/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/health/route/app-paths-manifest.json +3 -0
- package/.next/standalone/apps/web/.next/server/app/health/route/build-manifest.json +9 -0
- package/.next/standalone/apps/web/.next/server/app/health/route/server-reference-manifest.json +4 -0
- package/.next/standalone/apps/web/.next/server/app/health/route.js +6 -0
- package/.next/standalone/apps/web/.next/server/app/health/route.js.map +5 -0
- package/.next/standalone/apps/web/.next/server/app/health/route.js.nft.json +1 -0
- package/.next/standalone/apps/web/.next/server/app/health/route_client-reference-manifest.js +3 -0
- package/.next/standalone/apps/web/.next/server/app/icon.png/route.js +2 -1
- package/.next/standalone/apps/web/.next/server/app/icon.png/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/index.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/index.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_full.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_index.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app-paths-manifest.json +1 -0
- package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__03yk.z3._.js +3 -0
- package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0op9af~._.js +3 -0
- package/.next/standalone/apps/web/.next/server/chunks/apps_web__next-internal_server_app_health_route_actions_08pjq78.js +3 -0
- package/.next/standalone/apps/web/.next/server/chunks/node_modules_next_06p.d_a._.js +13 -0
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0dg0i1g._.js → [root-of-the-server]__092mq4r._.js} +2 -2
- 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
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0qw6wy3._.js → [root-of-the-server]__12vhk8e._.js} +15 -15
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_0g.cd6a._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_src_app_tasks_[id]_page_tsx_0jshsm2._.js +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_07.c491._.js → node_modules_0-31hvv._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0t3_1om._.js → node_modules_00je7te._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_02~gcwc._.js → node_modules_08zu-qy._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0gpuu-x._.js → node_modules_0f5l4h2._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_12qdm6m._.js → node_modules_0m9gy6q._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0cphr_r._.js → node_modules_0o0.qfb._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_0-4t5u4._.js → node_modules_0yo5dp5._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/{node_modules_055srxz._.js → node_modules_0zdgon0._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/apps/web/.next/server/pages/404.html +1 -1
- package/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
- package/.next/standalone/apps/web/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/{0l0s3fn6xga.t.js → 06h0.7cz1a2pw.js} +13 -13
- package/.next/standalone/apps/web/.next/static/chunks/0g.gfve6-xixo.css +4 -0
- package/.next/standalone/apps/web/.next/static/chunks/{0hx_sdyz0yyfb.js → 0u1x2j.2fd983.js} +7 -7
- package/.next/standalone/apps/web/.next/static/chunks/0wd663tqvi2ts.js +3 -0
- package/.next/standalone/apps/web/.next/static/chunks/{0ew.-lnxoet~x.js → 0zi97fcrx3u_8.js} +13 -13
- package/dist/auto-migrate.js +6 -7
- package/dist/cli.js +195 -10
- package/dist/plugin-lifecycle.d.ts +4 -1
- package/dist/plugin-lifecycle.js +11 -4
- package/dist/server/generated/prisma/commonInputTypes.d.ts +36 -36
- package/dist/server/generated/prisma/internal/class.js +2 -2
- package/dist/server/generated/prisma/models/Tab.d.ts +0 -7
- package/dist/server/generated/prisma/models/Task.d.ts +32 -25
- package/dist/server/index.js +6 -1
- package/dist/server/lib/repositories/task.d.ts +4 -2
- package/dist/server/lib/repositories/task.js +8 -6
- package/dist/server/lib/services/task-service.js +27 -17
- package/dist/server/routes/hooks.js +24 -12
- package/dist/server/routes/tasks.js +2 -2
- package/dist/server/routes/terminal.js +3 -2
- package/package.json +2 -1
- package/prisma/migrations/20260410000000_clear_stale_tab_todos/migration.sql +4 -0
- package/prisma/migrations/20260413000000_make_task_order_non_nullable/migration.sql +47 -0
- package/prisma/schema.prisma +1 -1
- package/tsunagi-marketplace/plugins/tsunagi-plugin/skills/tsunagi-task/SKILL.md +21 -0
- package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0jam776._.js +0 -13
- package/.next/standalone/apps/web/.next/static/chunks/0b8.3al6nvw3d.css +0 -4
- package/.next/standalone/apps/web/.next/static/chunks/12r3ashx0krmo.js +0 -3
- /package/.next/standalone/apps/web/.next/static/{y1VVVedZfN-isLJKKaC_l → 3spyaOCz0ow4ijl7Dvjpb}/_buildManifest.js +0 -0
- /package/.next/standalone/apps/web/.next/static/{y1VVVedZfN-isLJKKaC_l → 3spyaOCz0ow4ijl7Dvjpb}/_clientMiddlewareManifest.js +0 -0
- /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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
990
|
+
order: number;
|
|
984
991
|
deletedAt: Date | null;
|
|
985
992
|
createdAt: Date;
|
|
986
993
|
updatedAt: Date;
|
package/dist/server/index.js
CHANGED
|
@@ -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({
|
|
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'
|
|
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: '
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 &&
|
|
104
|
+
if (tasks && taskId && newStatus) {
|
|
96
105
|
const entry = tasks.get(taskId);
|
|
97
106
|
if (entry) {
|
|
98
|
-
entry.status =
|
|
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
|
+
"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,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;
|
package/prisma/schema.prisma
CHANGED
|
@@ -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` のいずれかでタスクを指定する。
|