@galda/cli 0.10.77 → 0.10.78

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/engine/lib.mjs CHANGED
@@ -2843,7 +2843,7 @@ export function replayQueueLog(rawText, reviewDefinitions = {}) {
2843
2843
  try {
2844
2844
  const e = JSON.parse(line);
2845
2845
  if (e.kind === 'goal') { goals = goals.filter((g) => g.id !== e.id); if (!e.deleted) goals.push(e); }
2846
- else { tasks = tasks.filter((t) => t.id !== e.id); tasks.push(e); }
2846
+ else if (e.kind === 'task') { tasks = tasks.filter((t) => t.id !== e.id); if (!e.deleted) tasks.push(e); }
2847
2847
  } catch { /* skip a corrupt line rather than lose the whole log */ }
2848
2848
  }
2849
2849
  for (const t of tasks) {
package/engine/server.mjs CHANGED
@@ -2589,6 +2589,12 @@ function installPreviewReaper() {
2589
2589
  async function startPreview(task) {
2590
2590
  installPreviewReaper();
2591
2591
  const { cmd, url, dir } = task.run;
2592
+ // Attached static artifacts are already served by this Manager at /upload.
2593
+ // They never need a child process; treating them like a Manager app made
2594
+ // "Open it" fail even though the HTML artifact was ready to view.
2595
+ if (!cmd && typeof url === 'string' && url.startsWith('/upload/')) {
2596
+ return { url, reused: false, started: false };
2597
+ }
2592
2598
  const live = previews.get(task.id);
2593
2599
  if (live && live.proc.exitCode === null) {
2594
2600
  live.expires = Date.now() + PREVIEW_IDLE_MS;
@@ -4159,6 +4165,16 @@ const server = createServer(async (req, res) => {
4159
4165
  || tasks.some((t) => t.projectId === project.id && ['running', 'queued'].includes(t.status));
4160
4166
  if (active) return json(res, 409, { error: 'cannot delete a project with active work' });
4161
4167
  const idx = projects.findIndex((p) => p.id === project.id);
4168
+ // A project id can be reused after deletion (for example "New project").
4169
+ // Remove its complete history before freeing that id, otherwise its old
4170
+ // Review cards appear in the newly created project.
4171
+ const removedGoals = goals.filter((g) => g.projectId === project.id);
4172
+ const removedGoalIds = new Set(removedGoals.map((g) => g.id));
4173
+ const removedTasks = tasks.filter((t) => t.projectId === project.id || removedGoalIds.has(t.goalId));
4174
+ goals = goals.filter((g) => g.projectId !== project.id);
4175
+ tasks = tasks.filter((t) => t.projectId !== project.id && !removedGoalIds.has(t.goalId));
4176
+ for (const g of removedGoals) logAppend(JSON.stringify({ kind: 'goal', id: g.id, deleted: true }));
4177
+ for (const t of removedTasks) logAppend(JSON.stringify({ kind: 'task', id: t.id, deleted: true }));
4162
4178
  projects.splice(idx, 1);
4163
4179
  queues.delete(project.id);
4164
4180
  saveProjects();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@galda/cli",
3
- "version": "0.10.77",
3
+ "version": "0.10.78",
4
4
  "type": "module",
5
5
  "description": "Galda - hand off work to Claude Code or Codex, get proof back. Runs on your existing subscription, no extra API cost.",
6
6
  "scripts": {