@awak-app/simy-cli 0.7.48 → 0.7.49

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awak-app/simy-cli",
3
- "version": "0.7.48",
3
+ "version": "0.7.49",
4
4
  "description": "Local SIMY executor for non-coding Local Tasks and Agentic Loop runs.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,7 +14,7 @@ import {
14
14
  } from "./durable-local-task-steps-contract.js";
15
15
  import { buildExecutionCapabilityContract } from "./execution-capability-contract.js";
16
16
 
17
- export const CLI_VERSION = "0.7.48";
17
+ export const CLI_VERSION = "0.7.49";
18
18
  export const CLI_API_CONTRACT_VERSION = 10;
19
19
 
20
20
  export function narrativeImageCapabilityMetadata() {
@@ -36,6 +36,14 @@ export async function worktreeEvidence(worktree) {
36
36
  }
37
37
  const stopped = new Set(['stopped','paused','paused_by_user','cancelled']);
38
38
  const terminal = new Set(['completed','reported_done','failed','succeeded']);
39
+ const terminalLocalTasks = new Set(['succeeded','failed','stopped']);
40
+ function hasPendingExecution(task, localTask = false) {
41
+ // Coding runs use operation for an async handle. Local Tasks persist their
42
+ // operation kind (for example "read") even after completion and restoration.
43
+ const operation = localTask ? task.operation != null && typeof task.operation !== 'string' : task.operation;
44
+ return Boolean(task.child || operation || task.operation_promise || task.pendingLedgerUpdate || task.ledgerUpdateRunning ||
45
+ (localTask ? !terminalLocalTasks.has(task.status) : ['queued','running','dispatching','coding'].includes(task.status)));
46
+ }
39
47
  const taskState = run => stopped.has(run.state) ? run.state : run.managed?.pendingApproval ? 'approval_wait' : ['blocked','waiting_human','recovery_required'].includes(run.state) ? 'needs_user' : 'active';
40
48
  const originalTaskId = record => record.run.managed?.taskId || record.run.id;
41
49
  const authority = record => digest([record.run?.id,record.run?.state,record.run?.managed,record.run?.deadline,record.run?.continuations,record.run?.failures,record.autoContinue,record.process,record.cwd,record.run?.executionCwd]);
@@ -167,7 +175,8 @@ export function createUpdateRuntime({ root, origin, readContext, listRecords, ob
167
175
  if(startingGate.connection!=='detaching')return {safe:false,liveExecutions:0,pendingWrites:0,unsettledPermissions:0};
168
176
  retainer?.assertSupported([]);
169
177
  const c=context(), execution=[...(c.runs||[]),...(c.localTasks||[])];
170
- const unowned=execution.filter(run=>run.child || run.operation || run.pendingLedgerUpdate || run.ledgerUpdateRunning || ['queued','running','dispatching','coding'].includes(run.status));
178
+ const unowned=[...(c.runs||[]).filter(run=>hasPendingExecution(run)),
179
+ ...(c.localTasks||[]).filter(task=>hasPendingExecution(task,true))];
171
180
  const workers=[];
172
181
  for(const task of c.directTasks || []) {
173
182
  if(!['queued','running','stopping'].includes(task.status)) continue;