@inetafrica/open-claudia 2.6.7 → 2.6.8

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/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Changelog
2
2
 
3
+ ## v2.6.8
4
+ - **Tasks: a plan can't be completed while subtasks are still open.** `task done` (and the loopback task-update path) now refuses to flip a parent to completed if any child is not yet completed — it returns a blocked result listing the open children, and the CLI prints a clean "Can't complete <id>: N subtask(s) still open" message instead of silently corrupting the tree. Standalone tasks and completing the last open child (which removes the whole plan) are unchanged. Prevents the inflated-count drift where parents showed done over still-open children.
5
+
3
6
  ## v2.6.6
4
7
  - **Recall: recent-turns window as judge-gated context.** v2.6.5 fixed quotes, but a bare follow-up like "Push" with no quote still recalled nothing — recall only ever saw the current message. The last ~6 user/assistant turns on this channel (read from the project transcript, current turn excluded) now feed recall the same way the quote does: keyword-matched as origin "context", kept only when the haiku judge confirms relevance, dropped on fail-open. A stale thread can never force-inject packs on keywords alone, but terse follow-ups finally inherit the topic of the conversation.
5
8
 
package/bin/task.js CHANGED
@@ -13,6 +13,7 @@ Per-channel todo list with optional plan/subtask hierarchy.
13
13
  open-claudia task list [--status pending|in_progress|completed]
14
14
  open-claudia task start <id>
15
15
  open-claudia task done <id> # completes AND removes; last subtask done removes the plan
16
+ # a plan won't complete while any subtask is still open
16
17
  open-claudia task remove <id> # removing a plan removes its subtasks
17
18
  open-claudia task clear-completed # prune any leftover completed entries
18
19
 
@@ -106,6 +107,12 @@ async function runUpdate(args, status) {
106
107
  if (!id) { console.error(`Usage: task ${status === "in_progress" ? "start" : "done"} <id>`); process.exit(2); }
107
108
  try {
108
109
  const res = await postJson("task-update", { id, status });
110
+ if (res.blocked) {
111
+ const kids = res.openChildren || [];
112
+ const names = kids.map((c) => ` - ${c.content} (${c.id})`).join("\n");
113
+ console.error(`Can't complete ${id}: ${kids.length} subtask${kids.length === 1 ? "" : "s"} still open. Finish or remove ${kids.length === 1 ? "it" : "them"} first:\n${names}`);
114
+ process.exit(1);
115
+ }
109
116
  if (!res.ok) { console.error(`Not found: ${id}`); process.exit(1); }
110
117
  if (status === "completed") {
111
118
  const n = res.removedCount || 0;
package/core/loopback.js CHANGED
@@ -226,7 +226,9 @@ async function handleJson(req, res, url, kind) {
226
226
  if (!payload.id) return reply(res, 400, { error: "missing id" });
227
227
  if (payload.status === "completed") {
228
228
  const result = tasksStore.complete(adapterId, channelId, payload.id);
229
- return reply(res, result ? 200 : 404, { ok: !!result, task: result ? result.task : null, removedCount: result ? result.removedCount : 0 });
229
+ if (!result) return reply(res, 404, { ok: false, task: null, removedCount: 0 });
230
+ if (result.blocked) return reply(res, 200, { ok: false, blocked: true, task: result.task, openChildren: result.openChildren });
231
+ return reply(res, 200, { ok: true, task: result.task, removedCount: result.removedCount });
230
232
  }
231
233
  const patch = {};
232
234
  if (payload.status) patch.status = payload.status;
package/core/tasks.js CHANGED
@@ -120,7 +120,20 @@ function prune(adapter, channelId) {
120
120
 
121
121
  // Mark a task completed, then prune. Reports how many entries left the
122
122
  // list so callers can tell the agent what disappeared.
123
+ //
124
+ // A plan can't be completed while any of its subtasks are still open:
125
+ // flipping the parent to [x] over [ ] children leaves a contradictory
126
+ // row that lingers (prune only drops a parent once all kids are done)
127
+ // and inflates the visible list. Refuse instead, naming the open kids
128
+ // so the caller finishes or removes them first.
123
129
  function complete(adapter, channelId, id) {
130
+ const list = load(adapter, channelId);
131
+ const target = list.find((t) => t.id === id);
132
+ if (!target) return null;
133
+ if (!target.parentId) {
134
+ const openChildren = list.filter((c) => c.parentId === id && c.status !== "completed");
135
+ if (openChildren.length > 0) return { blocked: true, task: target, openChildren };
136
+ }
124
137
  const t = update(adapter, channelId, id, { status: "completed" });
125
138
  if (!t) return null;
126
139
  const before = load(adapter, channelId).length;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inetafrica/open-claudia",
3
- "version": "2.6.7",
3
+ "version": "2.6.8",
4
4
  "description": "Your always-on AI coding assistant — Claude Code, Cursor Agent, and OpenAI Codex via Telegram or Kazee Chat",
5
5
  "main": "bot.js",
6
6
  "bin": {