@vinihcrosa/lumem-os 0.4.0 → 0.6.0

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 (48) hide show
  1. package/bin/lumem.mjs +46 -3
  2. package/dist/server/main.mjs +11659 -7544
  3. package/dist/web/assets/{codemirror-setup-u52h1pHp.js → codemirror-setup-JaVFPDhT.js} +1 -1
  4. package/dist/web/assets/index-BvSMeFFu.css +32 -0
  5. package/dist/web/assets/index-DML0Esam.js +101 -0
  6. package/dist/web/index.html +2 -2
  7. package/drizzle/0014_tarefa_como_entidade.sql +33 -0
  8. package/drizzle/0015_quadro_de_sete_colunas.sql +33 -0
  9. package/drizzle/0016_ordem_na_coluna.sql +13 -0
  10. package/drizzle/0017_relogio_do_encalhe.sql +10 -0
  11. package/drizzle/0018_tetos_do_workspace.sql +26 -0
  12. package/drizzle/0019_comentario_de_tarefa.sql +15 -0
  13. package/drizzle/0020_esteira_tentativa_e_autonomia.sql +51 -0
  14. package/drizzle/0021_catalogo_de_agentes.sql +27 -0
  15. package/drizzle/0022_interruptor_da_esteira.sql +30 -0
  16. package/drizzle/0023_prompt_preparado.sql +49 -0
  17. package/drizzle/0024_motivo_do_bloqueio.sql +1 -0
  18. package/drizzle/0025_aviso_uma_vez.sql +1 -0
  19. package/drizzle/0026_pr_mesclada_sempre_remove.sql +1 -0
  20. package/drizzle/0027_issue_como_identidade.sql +6 -0
  21. package/drizzle/0028_marcos_no_tracker.sql +1 -0
  22. package/drizzle/0029_parecer_do_revisor.sql +22 -0
  23. package/drizzle/0030_papel_da_sessao_e_vaivem.sql +56 -0
  24. package/drizzle/0031_recibo_do_parecer.sql +14 -0
  25. package/drizzle/0032_turno_do_consumo.sql +1 -0
  26. package/drizzle/meta/0014_snapshot.json +1895 -0
  27. package/drizzle/meta/0015_snapshot.json +1895 -0
  28. package/drizzle/meta/0016_snapshot.json +1912 -0
  29. package/drizzle/meta/0017_snapshot.json +1920 -0
  30. package/drizzle/meta/0018_snapshot.json +1945 -0
  31. package/drizzle/meta/0019_snapshot.json +2039 -0
  32. package/drizzle/meta/0020_snapshot.json +2063 -0
  33. package/drizzle/meta/0021_snapshot.json +2249 -0
  34. package/drizzle/meta/0022_snapshot.json +2273 -0
  35. package/drizzle/meta/0023_snapshot.json +2291 -0
  36. package/drizzle/meta/0024_snapshot.json +2298 -0
  37. package/drizzle/meta/0025_snapshot.json +2305 -0
  38. package/drizzle/meta/0026_snapshot.json +2313 -0
  39. package/drizzle/meta/0027_snapshot.json +2357 -0
  40. package/drizzle/meta/0028_snapshot.json +2365 -0
  41. package/drizzle/meta/0029_snapshot.json +2506 -0
  42. package/drizzle/meta/0030_snapshot.json +2525 -0
  43. package/drizzle/meta/0031_snapshot.json +2623 -0
  44. package/drizzle/meta/0032_snapshot.json +2631 -0
  45. package/drizzle/meta/_journal.json +133 -0
  46. package/package.json +1 -1
  47. package/dist/web/assets/index-CrtHjcbU.js +0 -101
  48. package/dist/web/assets/index-DliBP3a7.css +0 -32
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Lumem-OS</title>
7
- <script type="module" crossorigin src="/assets/index-CrtHjcbU.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-DliBP3a7.css">
7
+ <script type="module" crossorigin src="/assets/index-DML0Esam.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-BvSMeFFu.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
@@ -0,0 +1,33 @@
1
+ CREATE TABLE `task` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `workspace_id` text NOT NULL,
4
+ `project_id` text NOT NULL,
5
+ `title` text NOT NULL,
6
+ `body` text DEFAULT '' NOT NULL,
7
+ `status` text DEFAULT 'open' NOT NULL,
8
+ `created_by` text DEFAULT 'human' NOT NULL,
9
+ `created_by_session` text,
10
+ `worktree_id` text,
11
+ `links` text DEFAULT '[]' NOT NULL,
12
+ `reason` text,
13
+ `closed_at` integer,
14
+ `created_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
15
+ `updated_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
16
+ FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE no action ON DELETE restrict,
17
+ FOREIGN KEY (`project_id`) REFERENCES `project`(`id`) ON UPDATE no action ON DELETE restrict,
18
+ FOREIGN KEY (`worktree_id`) REFERENCES `worktree`(`id`) ON UPDATE no action ON DELETE set null,
19
+ CONSTRAINT "task_status" CHECK("task"."status" IN ('proposed', 'open', 'in_progress', 'review', 'done', 'dropped')),
20
+ CONSTRAINT "task_created_by" CHECK("task"."created_by" IN ('human', 'agent')),
21
+ CONSTRAINT "task_agent_provenance" CHECK(("task"."created_by" = 'agent' AND "task"."created_by_session" IS NOT NULL)
22
+ OR ("task"."created_by" = 'human' AND "task"."created_by_session" IS NULL)),
23
+ CONSTRAINT "task_closed_at" CHECK(("task"."status" IN ('done', 'dropped') AND "task"."closed_at" IS NOT NULL)
24
+ OR ("task"."status" NOT IN ('done', 'dropped') AND "task"."closed_at" IS NULL))
25
+ );
26
+ --> statement-breakpoint
27
+ CREATE INDEX `task_by_workspace` ON `task` (`workspace_id`,`status`);--> statement-breakpoint
28
+ CREATE INDEX `task_by_project` ON `task` (`project_id`);--> statement-breakpoint
29
+ -- `ON DELETE set null` escrito à mão: o `drizzle-kit` perde a ação do FK no
30
+ -- caminho de ALTER TABLE, e sem ela a coluna nasceria NO ACTION — ou seja,
31
+ -- apagar uma tarefa ficaria bloqueado por qualquer sessão que a serviu, que é
32
+ -- o oposto do que o schema declara.
33
+ ALTER TABLE `session` ADD `task_id` text REFERENCES `task`(`id`) ON UPDATE no action ON DELETE set null;
@@ -0,0 +1,33 @@
1
+ PRAGMA foreign_keys=OFF;--> statement-breakpoint
2
+ CREATE TABLE `__new_task` (
3
+ `id` text PRIMARY KEY NOT NULL,
4
+ `workspace_id` text NOT NULL,
5
+ `project_id` text NOT NULL,
6
+ `title` text NOT NULL,
7
+ `body` text DEFAULT '' NOT NULL,
8
+ `status` text DEFAULT 'open' NOT NULL,
9
+ `created_by` text DEFAULT 'human' NOT NULL,
10
+ `created_by_session` text,
11
+ `worktree_id` text,
12
+ `links` text DEFAULT '[]' NOT NULL,
13
+ `reason` text,
14
+ `closed_at` integer,
15
+ `created_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
16
+ `updated_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
17
+ FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE no action ON DELETE restrict,
18
+ FOREIGN KEY (`project_id`) REFERENCES `project`(`id`) ON UPDATE no action ON DELETE restrict,
19
+ FOREIGN KEY (`worktree_id`) REFERENCES `worktree`(`id`) ON UPDATE no action ON DELETE set null,
20
+ CONSTRAINT "task_status" CHECK("__new_task"."status" IN ('proposed', 'backlog', 'open', 'in_progress', 'review', 'testing', 'ready_to_merge', 'done', 'dropped')),
21
+ CONSTRAINT "task_created_by" CHECK("__new_task"."created_by" IN ('human', 'agent')),
22
+ CONSTRAINT "task_agent_provenance" CHECK(("__new_task"."created_by" = 'agent' AND "__new_task"."created_by_session" IS NOT NULL)
23
+ OR ("__new_task"."created_by" = 'human' AND "__new_task"."created_by_session" IS NULL)),
24
+ CONSTRAINT "task_closed_at" CHECK(("__new_task"."status" IN ('done', 'dropped') AND "__new_task"."closed_at" IS NOT NULL)
25
+ OR ("__new_task"."status" NOT IN ('done', 'dropped') AND "__new_task"."closed_at" IS NULL))
26
+ );
27
+ --> statement-breakpoint
28
+ INSERT INTO `__new_task`("id", "workspace_id", "project_id", "title", "body", "status", "created_by", "created_by_session", "worktree_id", "links", "reason", "closed_at", "created_at", "updated_at") SELECT "id", "workspace_id", "project_id", "title", "body", "status", "created_by", "created_by_session", "worktree_id", "links", "reason", "closed_at", "created_at", "updated_at" FROM `task`;--> statement-breakpoint
29
+ DROP TABLE `task`;--> statement-breakpoint
30
+ ALTER TABLE `__new_task` RENAME TO `task`;--> statement-breakpoint
31
+ PRAGMA foreign_keys=ON;--> statement-breakpoint
32
+ CREATE INDEX `task_by_workspace` ON `task` (`workspace_id`,`status`);--> statement-breakpoint
33
+ CREATE INDEX `task_by_project` ON `task` (`project_id`);
@@ -0,0 +1,13 @@
1
+ ALTER TABLE `task` ADD `position` integer DEFAULT 0 NOT NULL;--> statement-breakpoint
2
+ CREATE INDEX `task_by_position` ON `task` (`workspace_id`,`status`,`position`);--> statement-breakpoint
3
+ -- Backfill escrito à mão: o `drizzle-kit` só sabe o DEFAULT, e com todas as
4
+ -- linhas em zero a coluna do quadro nasceria numa ordem que o SQLite escolhe.
5
+ -- Ordem de chegada é a que o §4.3 declara para quem nunca arrastou, e
6
+ -- `created_at` é o único registro dela que existe.
7
+ UPDATE `task` SET `position` = (
8
+ SELECT COUNT(*) FROM `task` AS `earlier`
9
+ WHERE `earlier`.`workspace_id` = `task`.`workspace_id`
10
+ AND `earlier`.`status` = `task`.`status`
11
+ AND (`earlier`.`created_at` < `task`.`created_at`
12
+ OR (`earlier`.`created_at` = `task`.`created_at` AND `earlier`.`id` < `task`.`id`))
13
+ );
@@ -0,0 +1,10 @@
1
+ ALTER TABLE `task` ADD `status_changed_at` integer DEFAULT 0 NOT NULL;--> statement-breakpoint
2
+ -- Backfill à mão, e o `DEFAULT 0` acima é o motivo: o SQLite recusa
3
+ -- `ADD COLUMN` com default não-constante, então não dá para carimbar *agora* na
4
+ -- própria coluna — e carimbar *agora* seria errado de qualquer jeito. Toda
5
+ -- tarefa que já estava parada acordaria da migração dizendo "há 0 s", apagando
6
+ -- exatamente o encalhe que a coluna existe para mostrar. `updated_at` é o
7
+ -- melhor registro de quando alguém mexeu nela pela última vez: um limite
8
+ -- superior da verdade, que erra para o lado seguro — nunca inventa encalhe que
9
+ -- não houve.
10
+ UPDATE `task` SET `status_changed_at` = `updated_at`;
@@ -0,0 +1,26 @@
1
+ PRAGMA foreign_keys=OFF;--> statement-breakpoint
2
+ CREATE TABLE `__new_workspace` (
3
+ `id` text PRIMARY KEY NOT NULL,
4
+ `name` text NOT NULL,
5
+ `default_lumem_mode` text DEFAULT 'ask' NOT NULL,
6
+ `budget_cost_per_task` real,
7
+ `budget_cost_per_day` real,
8
+ `budget_turns_per_session` integer,
9
+ `created_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
10
+ `updated_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
11
+ CONSTRAINT "workspace_default_lumem_mode" CHECK("__new_workspace"."default_lumem_mode" IN ('ask', 'auto')),
12
+ CONSTRAINT "workspace_budget_not_negative" CHECK(("__new_workspace"."budget_cost_per_task" IS NULL OR "__new_workspace"."budget_cost_per_task" >= 0)
13
+ AND ("__new_workspace"."budget_cost_per_day" IS NULL OR "__new_workspace"."budget_cost_per_day" >= 0)
14
+ AND ("__new_workspace"."budget_turns_per_session" IS NULL OR "__new_workspace"."budget_turns_per_session" >= 0))
15
+ );
16
+ --> statement-breakpoint
17
+ -- A lista de colunas do SELECT foi reescrita à mão, e é a mesma armadilha que o
18
+ -- `0001` pagou: o `drizzle-kit` gera o SELECT com as colunas da tabela **nova**,
19
+ -- lendo da **velha** — `SELECT "budget_cost_per_task" FROM workspace` num banco
20
+ -- onde essa coluna, por definição, ainda não existe. Copia-se o que havia; as
21
+ -- três novas ficam `NULL`, que é o valor que quer dizer **sem teto**.
22
+ INSERT INTO `__new_workspace`("id", "name", "default_lumem_mode", "created_at", "updated_at") SELECT "id", "name", "default_lumem_mode", "created_at", "updated_at" FROM `workspace`;--> statement-breakpoint
23
+ DROP TABLE `workspace`;--> statement-breakpoint
24
+ ALTER TABLE `__new_workspace` RENAME TO `workspace`;--> statement-breakpoint
25
+ PRAGMA foreign_keys=ON;--> statement-breakpoint
26
+ CREATE UNIQUE INDEX `workspace_name_unique` ON `workspace` (`name`);
@@ -0,0 +1,15 @@
1
+ CREATE TABLE `task_comment` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `task_id` text NOT NULL,
4
+ `body` text NOT NULL,
5
+ `created_by` text DEFAULT 'human' NOT NULL,
6
+ `created_by_session` text,
7
+ `created_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
8
+ `updated_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
9
+ FOREIGN KEY (`task_id`) REFERENCES `task`(`id`) ON UPDATE no action ON DELETE cascade,
10
+ CONSTRAINT "task_comment_created_by" CHECK("task_comment"."created_by" IN ('human', 'agent')),
11
+ CONSTRAINT "task_comment_provenance" CHECK(("task_comment"."created_by" = 'agent' AND "task_comment"."created_by_session" IS NOT NULL)
12
+ OR ("task_comment"."created_by" = 'human' AND "task_comment"."created_by_session" IS NULL))
13
+ );
14
+ --> statement-breakpoint
15
+ CREATE INDEX `task_comment_by_task` ON `task_comment` (`task_id`,`created_at`);
@@ -0,0 +1,51 @@
1
+ PRAGMA foreign_keys=OFF;--> statement-breakpoint
2
+ CREATE TABLE `__new_task` (
3
+ `id` text PRIMARY KEY NOT NULL,
4
+ `workspace_id` text NOT NULL,
5
+ `project_id` text NOT NULL,
6
+ `title` text NOT NULL,
7
+ `body` text DEFAULT '' NOT NULL,
8
+ `status` text DEFAULT 'open' NOT NULL,
9
+ `created_by` text DEFAULT 'human' NOT NULL,
10
+ `created_by_session` text,
11
+ `worktree_id` text,
12
+ `position` integer DEFAULT 0 NOT NULL,
13
+ `links` text DEFAULT '[]' NOT NULL,
14
+ `reason` text,
15
+ `attempts` integer DEFAULT 0 NOT NULL,
16
+ `autonomy` text DEFAULT 'inherit' NOT NULL,
17
+ `status_changed_at` integer DEFAULT 0 NOT NULL,
18
+ `closed_at` integer,
19
+ `created_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
20
+ `updated_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
21
+ FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE no action ON DELETE restrict,
22
+ FOREIGN KEY (`project_id`) REFERENCES `project`(`id`) ON UPDATE no action ON DELETE restrict,
23
+ FOREIGN KEY (`worktree_id`) REFERENCES `worktree`(`id`) ON UPDATE no action ON DELETE set null,
24
+ CONSTRAINT "task_status" CHECK("__new_task"."status" IN ('proposed', 'backlog', 'open', 'in_progress', 'review', 'testing', 'ready_to_merge', 'done', 'dropped')),
25
+ CONSTRAINT "task_created_by" CHECK("__new_task"."created_by" IN ('human', 'agent')),
26
+ CONSTRAINT "task_autonomy" CHECK("__new_task"."autonomy" IN ('inherit', 'off')),
27
+ CONSTRAINT "task_attempts_not_negative" CHECK("__new_task"."attempts" >= 0),
28
+ CONSTRAINT "task_agent_provenance" CHECK(("__new_task"."created_by" = 'agent' AND "__new_task"."created_by_session" IS NOT NULL)
29
+ OR ("__new_task"."created_by" = 'human' AND "__new_task"."created_by_session" IS NULL)),
30
+ CONSTRAINT "task_closed_at" CHECK(("__new_task"."status" IN ('done', 'dropped') AND "__new_task"."closed_at" IS NOT NULL)
31
+ OR ("__new_task"."status" NOT IN ('done', 'dropped') AND "__new_task"."closed_at" IS NULL))
32
+ );
33
+ --> statement-breakpoint
34
+ -- A lista de colunas foi reescrita à mão, e é a TERCEIRA vez neste repositório:
35
+ -- o `drizzle-kit` gera o SELECT com as colunas da tabela **nova**, lendo da
36
+ -- **velha** — `SELECT "attempts", "autonomy" FROM task` num banco onde elas, por
37
+ -- definição, ainda não existem. O `0001` pagou por isso, o `0018` pagou cinco
38
+ -- migrações depois, e a lição já está no `testing.md`: **leia o SELECT de toda
39
+ -- migração gerada**. Nenhum teste que começa de banco vazio pega.
40
+ --
41
+ -- Copia-se o que havia. As duas novas ficam no DEFAULT: `attempts = 0`, que é a
42
+ -- verdade sobre toda tarefa que existia antes de a esteira existir, e
43
+ -- `autonomy = 'inherit'`, que não liga nada — o interruptor do workspace nasce
44
+ -- em `manual`.
45
+ INSERT INTO `__new_task`("id", "workspace_id", "project_id", "title", "body", "status", "created_by", "created_by_session", "worktree_id", "position", "links", "reason", "status_changed_at", "closed_at", "created_at", "updated_at") SELECT "id", "workspace_id", "project_id", "title", "body", "status", "created_by", "created_by_session", "worktree_id", "position", "links", "reason", "status_changed_at", "closed_at", "created_at", "updated_at" FROM `task`;--> statement-breakpoint
46
+ DROP TABLE `task`;--> statement-breakpoint
47
+ ALTER TABLE `__new_task` RENAME TO `task`;--> statement-breakpoint
48
+ PRAGMA foreign_keys=ON;--> statement-breakpoint
49
+ CREATE INDEX `task_by_workspace` ON `task` (`workspace_id`,`status`);--> statement-breakpoint
50
+ CREATE INDEX `task_by_position` ON `task` (`workspace_id`,`status`,`position`);--> statement-breakpoint
51
+ CREATE INDEX `task_by_project` ON `task` (`project_id`);
@@ -0,0 +1,27 @@
1
+ CREATE TABLE `named_agent` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `workspace_id` text NOT NULL,
4
+ `name` text NOT NULL,
5
+ `adapter` text NOT NULL,
6
+ `model` text,
7
+ `instructions` text DEFAULT '' NOT NULL,
8
+ `created_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
9
+ `updated_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
10
+ FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE no action ON DELETE restrict
11
+ );
12
+ --> statement-breakpoint
13
+ CREATE UNIQUE INDEX `named_agent_name_in_workspace` ON `named_agent` (`workspace_id`,`name`);--> statement-breakpoint
14
+ CREATE TABLE `role_binding` (
15
+ `id` text PRIMARY KEY NOT NULL,
16
+ `scope_type` text NOT NULL,
17
+ `scope_id` text NOT NULL,
18
+ `role` text NOT NULL,
19
+ `agent_id` text NOT NULL,
20
+ `created_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
21
+ `updated_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
22
+ FOREIGN KEY (`agent_id`) REFERENCES `named_agent`(`id`) ON UPDATE no action ON DELETE cascade,
23
+ CONSTRAINT "role_binding_scope_type" CHECK("role_binding"."scope_type" IN ('workspace', 'project', 'task')),
24
+ CONSTRAINT "role_binding_role" CHECK("role_binding"."role" IN ('implementador', 'revisor', 'testador'))
25
+ );
26
+ --> statement-breakpoint
27
+ CREATE UNIQUE INDEX `role_binding_one_per_scope` ON `role_binding` (`scope_type`,`scope_id`,`role`);
@@ -0,0 +1,30 @@
1
+ PRAGMA foreign_keys=OFF;--> statement-breakpoint
2
+ CREATE TABLE `__new_workspace` (
3
+ `id` text PRIMARY KEY NOT NULL,
4
+ `name` text NOT NULL,
5
+ `default_lumem_mode` text DEFAULT 'ask' NOT NULL,
6
+ `budget_cost_per_task` real,
7
+ `budget_cost_per_day` real,
8
+ `budget_turns_per_session` integer,
9
+ `autonomy` text DEFAULT 'manual' NOT NULL,
10
+ `autonomy_max_parallel` integer DEFAULT 2 NOT NULL,
11
+ `created_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
12
+ `updated_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
13
+ CONSTRAINT "workspace_default_lumem_mode" CHECK("__new_workspace"."default_lumem_mode" IN ('ask', 'auto')),
14
+ CONSTRAINT "workspace_autonomy" CHECK("__new_workspace"."autonomy" IN ('manual', 'assistido', 'autonomo')),
15
+ CONSTRAINT "workspace_autonomy_max_parallel" CHECK("__new_workspace"."autonomy_max_parallel" >= 0),
16
+ CONSTRAINT "workspace_budget_not_negative" CHECK(("__new_workspace"."budget_cost_per_task" IS NULL OR "__new_workspace"."budget_cost_per_task" >= 0)
17
+ AND ("__new_workspace"."budget_cost_per_day" IS NULL OR "__new_workspace"."budget_cost_per_day" >= 0)
18
+ AND ("__new_workspace"."budget_turns_per_session" IS NULL OR "__new_workspace"."budget_turns_per_session" >= 0))
19
+ );
20
+ --> statement-breakpoint
21
+ -- Reescrita à mão pela QUARTA vez: o `drizzle-kit` gera o SELECT com as colunas
22
+ -- da tabela nova lendo da velha, e `SELECT "autonomy" FROM workspace` não existe
23
+ -- num banco anterior a esta migração. O `0001`, o `0018` e o `0020` pagaram pelo
24
+ -- mesmo. Copia-se o que havia; as duas novas ficam no DEFAULT — `manual`, que é
25
+ -- o Lumem de hoje, e `2`, que é o número que a folha do Open Design desenha.
26
+ INSERT INTO `__new_workspace`("id", "name", "default_lumem_mode", "budget_cost_per_task", "budget_cost_per_day", "budget_turns_per_session", "created_at", "updated_at") SELECT "id", "name", "default_lumem_mode", "budget_cost_per_task", "budget_cost_per_day", "budget_turns_per_session", "created_at", "updated_at" FROM `workspace`;--> statement-breakpoint
27
+ DROP TABLE `workspace`;--> statement-breakpoint
28
+ ALTER TABLE `__new_workspace` RENAME TO `workspace`;--> statement-breakpoint
29
+ PRAGMA foreign_keys=ON;--> statement-breakpoint
30
+ CREATE UNIQUE INDEX `workspace_name_unique` ON `workspace` (`name`);
@@ -0,0 +1,49 @@
1
+ PRAGMA foreign_keys=OFF;--> statement-breakpoint
2
+ CREATE TABLE `__new_task` (
3
+ `id` text PRIMARY KEY NOT NULL,
4
+ `workspace_id` text NOT NULL,
5
+ `project_id` text NOT NULL,
6
+ `title` text NOT NULL,
7
+ `body` text DEFAULT '' NOT NULL,
8
+ `status` text DEFAULT 'open' NOT NULL,
9
+ `created_by` text DEFAULT 'human' NOT NULL,
10
+ `created_by_session` text,
11
+ `worktree_id` text,
12
+ `position` integer DEFAULT 0 NOT NULL,
13
+ `links` text DEFAULT '[]' NOT NULL,
14
+ `reason` text,
15
+ `attempts` integer DEFAULT 0 NOT NULL,
16
+ `autonomy` text DEFAULT 'inherit' NOT NULL,
17
+ `prepared_prompt` text,
18
+ `prepared_role` text,
19
+ `status_changed_at` integer DEFAULT 0 NOT NULL,
20
+ `closed_at` integer,
21
+ `created_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
22
+ `updated_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
23
+ FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE no action ON DELETE restrict,
24
+ FOREIGN KEY (`project_id`) REFERENCES `project`(`id`) ON UPDATE no action ON DELETE restrict,
25
+ FOREIGN KEY (`worktree_id`) REFERENCES `worktree`(`id`) ON UPDATE no action ON DELETE set null,
26
+ CONSTRAINT "task_status" CHECK("__new_task"."status" IN ('proposed', 'backlog', 'open', 'in_progress', 'review', 'testing', 'ready_to_merge', 'done', 'dropped')),
27
+ CONSTRAINT "task_created_by" CHECK("__new_task"."created_by" IN ('human', 'agent')),
28
+ CONSTRAINT "task_autonomy" CHECK("__new_task"."autonomy" IN ('inherit', 'off')),
29
+ CONSTRAINT "task_attempts_not_negative" CHECK("__new_task"."attempts" >= 0),
30
+ CONSTRAINT "task_prepared_pair" CHECK(("__new_task"."prepared_prompt" IS NULL AND "__new_task"."prepared_role" IS NULL)
31
+ OR ("__new_task"."prepared_prompt" IS NOT NULL AND "__new_task"."prepared_role" IS NOT NULL)),
32
+ CONSTRAINT "task_agent_provenance" CHECK(("__new_task"."created_by" = 'agent' AND "__new_task"."created_by_session" IS NOT NULL)
33
+ OR ("__new_task"."created_by" = 'human' AND "__new_task"."created_by_session" IS NULL)),
34
+ CONSTRAINT "task_closed_at" CHECK(("__new_task"."status" IN ('done', 'dropped') AND "__new_task"."closed_at" IS NOT NULL)
35
+ OR ("__new_task"."status" NOT IN ('done', 'dropped') AND "__new_task"."closed_at" IS NULL))
36
+ );
37
+ --> statement-breakpoint
38
+ -- Quinta vez, e a lição já tem endereço no `testing.md`: o `drizzle-kit` gera o
39
+ -- SELECT com as colunas da tabela nova lendo da velha. Aqui as duas que não
40
+ -- existem ainda são `prepared_prompt` e `prepared_role`; as duas ficam `NULL`,
41
+ -- que quer dizer *nada preparado* — a verdade sobre toda tarefa anterior ao
42
+ -- degrau `assistido`.
43
+ INSERT INTO `__new_task`("id", "workspace_id", "project_id", "title", "body", "status", "created_by", "created_by_session", "worktree_id", "position", "links", "reason", "attempts", "autonomy", "status_changed_at", "closed_at", "created_at", "updated_at") SELECT "id", "workspace_id", "project_id", "title", "body", "status", "created_by", "created_by_session", "worktree_id", "position", "links", "reason", "attempts", "autonomy", "status_changed_at", "closed_at", "created_at", "updated_at" FROM `task`;--> statement-breakpoint
44
+ DROP TABLE `task`;--> statement-breakpoint
45
+ ALTER TABLE `__new_task` RENAME TO `task`;--> statement-breakpoint
46
+ PRAGMA foreign_keys=ON;--> statement-breakpoint
47
+ CREATE INDEX `task_by_workspace` ON `task` (`workspace_id`,`status`);--> statement-breakpoint
48
+ CREATE INDEX `task_by_position` ON `task` (`workspace_id`,`status`,`position`);--> statement-breakpoint
49
+ CREATE INDEX `task_by_project` ON `task` (`project_id`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `task` ADD `blocked_reason` text;
@@ -0,0 +1 @@
1
+ ALTER TABLE `task` ADD `notified_at` integer;
@@ -0,0 +1 @@
1
+ ALTER TABLE `workspace` ADD `merged_always_removes` integer DEFAULT false NOT NULL;
@@ -0,0 +1,6 @@
1
+ ALTER TABLE `task` ADD `external_source` text;--> statement-breakpoint
2
+ ALTER TABLE `task` ADD `external_id` text;--> statement-breakpoint
3
+ ALTER TABLE `task` ADD `external_state` text;--> statement-breakpoint
4
+ ALTER TABLE `task` ADD `external_assignee` text;--> statement-breakpoint
5
+ ALTER TABLE `task` ADD `external_body_hash` text;--> statement-breakpoint
6
+ CREATE UNIQUE INDEX `task_external_in_workspace` ON `task` (`workspace_id`,`external_source`,`external_id`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `task` ADD `external_marks` text DEFAULT '[]' NOT NULL;
@@ -0,0 +1,22 @@
1
+ CREATE TABLE `task_finding` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `task_id` text NOT NULL,
4
+ `found_by_session` text NOT NULL,
5
+ `role` text NOT NULL,
6
+ `bucket` text NOT NULL,
7
+ `title` text NOT NULL,
8
+ `detail` text DEFAULT '' NOT NULL,
9
+ `command` text,
10
+ `expected` text,
11
+ `verification` text DEFAULT 'pending' NOT NULL,
12
+ `output` text,
13
+ `created_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
14
+ `updated_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
15
+ FOREIGN KEY (`task_id`) REFERENCES `task`(`id`) ON UPDATE no action ON DELETE cascade,
16
+ CONSTRAINT "task_finding_bucket" CHECK("task_finding"."bucket" IN ('blocks', 'notes')),
17
+ CONSTRAINT "task_finding_verification" CHECK("task_finding"."verification" IN ('pending', 'reproduced', 'refuted', 'skipped')),
18
+ CONSTRAINT "task_finding_reproduction" CHECK(("task_finding"."bucket" = 'blocks' AND "task_finding"."command" IS NOT NULL)
19
+ OR ("task_finding"."bucket" = 'notes' AND "task_finding"."command" IS NULL))
20
+ );
21
+ --> statement-breakpoint
22
+ CREATE INDEX `task_finding_by_task` ON `task_finding` (`task_id`,`created_at`);
@@ -0,0 +1,56 @@
1
+ ALTER TABLE `session` ADD `task_role` text;--> statement-breakpoint
2
+ PRAGMA foreign_keys=OFF;--> statement-breakpoint
3
+ CREATE TABLE `__new_task` (
4
+ `id` text PRIMARY KEY NOT NULL,
5
+ `workspace_id` text NOT NULL,
6
+ `project_id` text NOT NULL,
7
+ `title` text NOT NULL,
8
+ `body` text DEFAULT '' NOT NULL,
9
+ `status` text DEFAULT 'open' NOT NULL,
10
+ `created_by` text DEFAULT 'human' NOT NULL,
11
+ `created_by_session` text,
12
+ `worktree_id` text,
13
+ `position` integer DEFAULT 0 NOT NULL,
14
+ `links` text DEFAULT '[]' NOT NULL,
15
+ `reason` text,
16
+ `attempts` integer DEFAULT 0 NOT NULL,
17
+ `bounces` integer DEFAULT 0 NOT NULL,
18
+ `autonomy` text DEFAULT 'inherit' NOT NULL,
19
+ `prepared_prompt` text,
20
+ `prepared_role` text,
21
+ `blocked_reason` text,
22
+ `notified_at` integer,
23
+ `external_source` text,
24
+ `external_id` text,
25
+ `external_state` text,
26
+ `external_assignee` text,
27
+ `external_body_hash` text,
28
+ `external_marks` text DEFAULT '[]' NOT NULL,
29
+ `status_changed_at` integer DEFAULT 0 NOT NULL,
30
+ `closed_at` integer,
31
+ `created_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
32
+ `updated_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
33
+ FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE no action ON DELETE restrict,
34
+ FOREIGN KEY (`project_id`) REFERENCES `project`(`id`) ON UPDATE no action ON DELETE restrict,
35
+ FOREIGN KEY (`worktree_id`) REFERENCES `worktree`(`id`) ON UPDATE no action ON DELETE set null,
36
+ CONSTRAINT "task_status" CHECK("__new_task"."status" IN ('proposed', 'backlog', 'open', 'in_progress', 'review', 'testing', 'ready_to_merge', 'done', 'dropped')),
37
+ CONSTRAINT "task_created_by" CHECK("__new_task"."created_by" IN ('human', 'agent')),
38
+ CONSTRAINT "task_autonomy" CHECK("__new_task"."autonomy" IN ('inherit', 'off')),
39
+ CONSTRAINT "task_attempts_not_negative" CHECK("__new_task"."attempts" >= 0),
40
+ CONSTRAINT "task_bounces_not_negative" CHECK("__new_task"."bounces" >= 0),
41
+ CONSTRAINT "task_prepared_pair" CHECK(("__new_task"."prepared_prompt" IS NULL AND "__new_task"."prepared_role" IS NULL)
42
+ OR ("__new_task"."prepared_prompt" IS NOT NULL AND "__new_task"."prepared_role" IS NOT NULL)),
43
+ CONSTRAINT "task_agent_provenance" CHECK(("__new_task"."created_by" = 'agent' AND "__new_task"."created_by_session" IS NOT NULL)
44
+ OR ("__new_task"."created_by" = 'human' AND "__new_task"."created_by_session" IS NULL)),
45
+ CONSTRAINT "task_closed_at" CHECK(("__new_task"."status" IN ('done', 'dropped') AND "__new_task"."closed_at" IS NOT NULL)
46
+ OR ("__new_task"."status" NOT IN ('done', 'dropped') AND "__new_task"."closed_at" IS NULL))
47
+ );
48
+ --> statement-breakpoint
49
+ INSERT INTO `__new_task`("id", "workspace_id", "project_id", "title", "body", "status", "created_by", "created_by_session", "worktree_id", "position", "links", "reason", "attempts", "bounces", "autonomy", "prepared_prompt", "prepared_role", "blocked_reason", "notified_at", "external_source", "external_id", "external_state", "external_assignee", "external_body_hash", "external_marks", "status_changed_at", "closed_at", "created_at", "updated_at") SELECT "id", "workspace_id", "project_id", "title", "body", "status", "created_by", "created_by_session", "worktree_id", "position", "links", "reason", "attempts", 0, "autonomy", "prepared_prompt", "prepared_role", "blocked_reason", "notified_at", "external_source", "external_id", "external_state", "external_assignee", "external_body_hash", "external_marks", "status_changed_at", "closed_at", "created_at", "updated_at" FROM `task`;--> statement-breakpoint
50
+ DROP TABLE `task`;--> statement-breakpoint
51
+ ALTER TABLE `__new_task` RENAME TO `task`;--> statement-breakpoint
52
+ PRAGMA foreign_keys=ON;--> statement-breakpoint
53
+ CREATE INDEX `task_by_workspace` ON `task` (`workspace_id`,`status`);--> statement-breakpoint
54
+ CREATE INDEX `task_by_position` ON `task` (`workspace_id`,`status`,`position`);--> statement-breakpoint
55
+ CREATE INDEX `task_by_project` ON `task` (`project_id`);--> statement-breakpoint
56
+ CREATE UNIQUE INDEX `task_external_in_workspace` ON `task` (`workspace_id`,`external_source`,`external_id`);
@@ -0,0 +1,14 @@
1
+ CREATE TABLE `task_review` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `task_id` text NOT NULL,
4
+ `by_session` text NOT NULL,
5
+ `role` text NOT NULL,
6
+ `blocks` integer DEFAULT 0 NOT NULL,
7
+ `notes` integer DEFAULT 0 NOT NULL,
8
+ `created_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
9
+ `updated_at` integer DEFAULT (unixepoch('subsec') * 1000) NOT NULL,
10
+ FOREIGN KEY (`task_id`) REFERENCES `task`(`id`) ON UPDATE no action ON DELETE cascade,
11
+ CONSTRAINT "task_review_counts_not_negative" CHECK("task_review"."blocks" >= 0 AND "task_review"."notes" >= 0)
12
+ );
13
+ --> statement-breakpoint
14
+ CREATE INDEX `task_review_by_session` ON `task_review` (`by_session`,`created_at`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `session_usage` ADD `turn` integer DEFAULT 0 NOT NULL;