claudeboard 1.1.0 → 1.3.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.
@@ -77,6 +77,33 @@ export async function createTask({ epicId, title, description, priority = "mediu
77
77
  return data;
78
78
  }
79
79
 
80
+ /**
81
+ * Check if this project already has tasks in the board
82
+ * Used to detect resume vs fresh start
83
+ */
84
+ export async function hasTasks() {
85
+ const { data, error } = await supabase
86
+ .from("cb_tasks")
87
+ .select("id")
88
+ .eq("project", PROJECT)
89
+ .limit(1);
90
+ return Array.isArray(data) && data.length > 0;
91
+ }
92
+
93
+ /**
94
+ * Reset any stuck "in_progress" tasks back to "todo"
95
+ * Called on resume so the agent re-picks them up
96
+ */
97
+ export async function resetStuckTasks() {
98
+ const { data } = await supabase
99
+ .from("cb_tasks")
100
+ .update({ status: "todo", started_at: null })
101
+ .eq("project", PROJECT)
102
+ .eq("status", "in_progress")
103
+ .select();
104
+ return data?.length || 0;
105
+ }
106
+
80
107
  export async function getStats() {
81
108
  const tasks = await getAllTasks();
82
109
  return {
@@ -13,6 +13,8 @@ import {
13
13
  addLog,
14
14
  createTask,
15
15
  createEpic,
16
+ hasTasks,
17
+ resetStuckTasks,
16
18
  } from "./board-client.js";
17
19
  import { initSupabaseReader } from "../tools/supabase-reader.js";
18
20
  import { runCommand, startProcess, waitForPort } from "../tools/terminal.js";
@@ -49,15 +51,31 @@ export async function runOrchestrator(config) {
49
51
  console.log(chalk.dim(` Project: ${projectPath}\n`));
50
52
 
51
53
  let techStack = {};
54
+ let isResume = false;
52
55
 
53
- // ── PHASE 1: ARCHITECTURE ──────────────────────────────────────────────────
54
- if (!skipArchitect) {
56
+ // ── DETECT: RESUME or FRESH START ─────────────────────────────────────────
57
+ const existingTasks = await hasTasks();
58
+
59
+ if (existingTasks && !config.forceRestart) {
60
+ isResume = true;
61
+ const stuck = await resetStuckTasks();
62
+ const stats = await getStats();
63
+
64
+ console.log(chalk.yellow(" ↩️ Resuming existing session\n"));
65
+ console.log(chalk.dim(` Found ${stats.total} tasks — ${stats.done} done, ${stats.todo} todo, ${stats.error} failed`));
66
+ if (stuck > 0) {
67
+ console.log(chalk.dim(` Reset ${stuck} stuck task(s) back to todo`));
68
+ }
69
+ console.log();
70
+ } else {
71
+ // ── PHASE 1: ARCHITECTURE ────────────────────────────────────────────────
72
+ if (config.forceRestart) {
73
+ console.log(chalk.dim(" Force restart — skipping existing tasks (they remain in board)\n"));
74
+ }
55
75
  console.log(chalk.bold.cyan("[ PHASE 1: ARCHITECTURE ]\n"));
56
76
  const archResult = await runArchitectAgent(prdContent, projectName);
57
77
  techStack = archResult.techStack;
58
78
  console.log(chalk.green(`\n ✓ ${archResult.totalTasks} tasks created across ${archResult.epics.length} epics\n`));
59
- } else {
60
- console.log(chalk.dim(" Skipping architect (tasks already exist)\n"));
61
79
  }
62
80
 
63
81
  // ── START EXPO ─────────────────────────────────────────────────────────────
package/bin/cli.js CHANGED
@@ -129,7 +129,7 @@ program
129
129
  .description("Run the AI engineering team on your project")
130
130
  .requiredOption("--prd <path>", "Path to PRD markdown file")
131
131
  .requiredOption("--project <path>", "Path to your app project directory")
132
- .option("--skip-architect", "Skip architecture phase (tasks already exist)")
132
+ .option("--restart", "Force restart from scratch (ignore existing tasks in board)")
133
133
  .option("--expo-port <port>", "Expo Web port for QA screenshots", "8081")
134
134
  .action(async (opts) => {
135
135
  console.log(LOGO);
@@ -145,7 +145,9 @@ program
145
145
  console.log(chalk.bold(` AI Team starting for: ${chalk.cyan(config.projectName)}\n`));
146
146
  console.log(chalk.dim(` Dashboard → http://localhost:${config.port}`));
147
147
  console.log(chalk.dim(` PRD → ${opts.prd}`));
148
- console.log(chalk.dim(` Project → ${opts.project}\n`));
148
+ console.log(chalk.dim(` Project → ${opts.project}`));
149
+ if (opts.restart) console.log(chalk.yellow(` Mode → FORCE RESTART\n`));
150
+ else console.log(chalk.dim(` Mode → auto-resume if tasks exist\n`));
149
151
 
150
152
  const { runOrchestrator } = await import("../agents/orchestrator.js");
151
153
 
@@ -156,7 +158,7 @@ program
156
158
  supabaseKey: config.supabaseKey,
157
159
  projectName: config.projectName,
158
160
  expoPort: parseInt(opts.expoPort),
159
- skipArchitect: !!opts.skipArchitect,
161
+ forceRestart: !!opts.restart,
160
162
  });
161
163
  });
162
164