@zq-silk/yui 0.13.3 → 0.13.5

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/README.md +8 -8
  2. package/dist/cli/commandCatalog.js +22 -21
  3. package/dist/cli/interactionPolicy.js +0 -14
  4. package/dist/cli.js +42 -0
  5. package/dist/commands/executionAuditCommands.js +1 -1
  6. package/dist/commands/taskCommands.js +60 -326
  7. package/dist/commands/taskContextCommand.js +3 -14
  8. package/dist/commands/taskExecutionCommands.js +254 -0
  9. package/dist/commands/taskNextActionCommand.js +1 -3
  10. package/dist/commands/taskOverviewCommand.js +9 -2
  11. package/dist/commands/taskRoleRuntimeStatus.js +2 -25
  12. package/dist/controller/agentRuntimeObserver.js +4 -2
  13. package/dist/controller/clientRuntime.js +45 -2
  14. package/dist/controller/controller.js +6 -3
  15. package/dist/controller/fileSchedulerStoreAdapter.js +70 -188
  16. package/dist/controller/jobControl.js +3 -2
  17. package/dist/controller/runtime.js +6 -33
  18. package/dist/controller/runtimeEventProcessor.js +8 -4
  19. package/dist/controller/runtimeHookRunFence.js +4 -10
  20. package/dist/execution/executionHealth.js +8 -16
  21. package/dist/executor/agentExecutor.js +13 -14
  22. package/dist/executor/fileRoleLaunchPlanner.js +9 -16
  23. package/dist/lifecycle/exactRunTerminalization.js +24 -322
  24. package/dist/repository/taskWorkspaceCoordinator.js +0 -9
  25. package/dist/runtime/agentHost.js +20 -80
  26. package/dist/runtime/exactControlPlane.js +15 -9
  27. package/dist/runtime/providerContinuationReconciliationService.js +1 -1
  28. package/dist/runtime/providerRecoveryDecision.js +1 -1
  29. package/dist/runtime/providerRuntimeIdentity.js +25 -15
  30. package/dist/scheduler/activeRoleRunDelivery.js +1 -19
  31. package/dist/scheduler/leaderWakeupProcessor.js +12 -63
  32. package/dist/scheduler/ports.js +3 -2
  33. package/dist/scheduler/roleRunLiveness.js +4 -1
  34. package/dist/scheduler/roleRunStall.js +0 -2
  35. package/dist/scheduler/taskExecutionProjection.js +18 -1
  36. package/dist/scheduler/wakeupQueue.js +2 -1
  37. package/dist/storage/migration/productionRegistry.js +65 -0
  38. package/dist/storage/sqliteStore.js +10 -2
  39. package/dist/storage/taskStore.js +11 -3
  40. package/dist/task/completionReadiness.js +0 -67
  41. package/dist/task/nextAction.js +16 -32
  42. package/dist/task/task.js +38 -3
  43. package/dist/web/assets/client/i18n.js +0 -4
  44. package/dist/web/assets/client/view.js +0 -18
  45. package/dist/web/webSnapshot.js +7 -13
  46. package/package.json +1 -1
  47. package/dist/run/recoveryProjection.js +0 -252
  48. package/dist/runtime/conversationSwitch.js +0 -277
package/README.md CHANGED
@@ -549,18 +549,18 @@ yui operator new
549
549
  yui operator enter
550
550
  ```
551
551
 
552
- When a Task Role's current Provider Conversation cannot continue, request a
553
- bounded switch with an audited reason:
552
+ If current execution cannot be settled normally, fence the Task and restart
553
+ from its durable progress:
554
554
 
555
555
  ```sh
556
- yui task role session switch <task-id> <role> --reason "<why this conversation cannot continue>"
556
+ yui task execution stop <task-id> --force --reason "<why execution must be fenced>"
557
+ yui task execution start <task-id>
557
558
  ```
558
559
 
559
- The command records intent only. It does not fail active work, stop a live
560
- runtime, or forget the current Conversation. Once the Role has ready work and
561
- the current writer/Turn is settled, Yui creates and binds the replacement; a
562
- failure before that bind leaves the old Conversation authoritative. Existing
563
- messages, reviews, and delivery history remain durable.
560
+ `stop` terminates disposable Runs and Sessions while preserving WorkItems,
561
+ repository changes, Messages, reviews, and other Task progress. `start` admits
562
+ one new Leader attempt from those durable records; it does not recover an old
563
+ Agent conversation.
564
564
 
565
565
  Without `--task`, `operator submit` creates a new Draft. Drafts accept planning changes but must be activated before Agent execution.
566
566
  Operator resolves every request against the Project catalog and existing Task
@@ -282,6 +282,24 @@ const taskChildren = [
282
282
  }
283
283
  },
284
284
  { name: "activate", summary: "Activate a Draft Task.", usage: "yui task activate <id>" },
285
+ {
286
+ name: "execution",
287
+ summary: "Fence or resume all execution for a Task.",
288
+ sections: [{ id: "manage", title: "Commands", entries: ["stop", "start"] }],
289
+ children: [
290
+ {
291
+ name: "stop",
292
+ summary: "Stop all Task execution while preserving durable progress.",
293
+ usage: "yui task execution stop <task> --force --reason <text>",
294
+ options: ["--force", "--reason"]
295
+ },
296
+ {
297
+ name: "start",
298
+ summary: "Resume the Leader from durable Task progress.",
299
+ usage: "yui task execution start <task>"
300
+ }
301
+ ]
302
+ },
285
303
  {
286
304
  name: "complete",
287
305
  summary: "Complete an active Task and stop automatic wakeups.",
@@ -540,7 +558,7 @@ const taskChildren = [
540
558
  name: "role",
541
559
  summary: "Manage Roles within a Task.",
542
560
  sections: [{ id: "manage", title: "Commands", entries: [
543
- "add", "list", "status", "show", "update", "remove", "bind", "unbind", "session",
561
+ "add", "list", "status", "show", "update", "remove", "bind", "unbind",
544
562
  "view", "takeover", "release"
545
563
  ] }],
546
564
  children: [
@@ -569,17 +587,6 @@ const taskChildren = [
569
587
  { name: "remove", summary: "Remove a Task Role.", usage: "yui task role remove <task> <role>" },
570
588
  { name: "bind", summary: "Bind and activate an Agent for a Task Role.", usage: "yui task role bind <task> <role> <agent-id>" },
571
589
  { name: "unbind", summary: "Unbind a dormant Agent from a Task Role.", usage: "yui task role unbind <task> <role> <agent-id>" },
572
- {
573
- name: "session",
574
- summary: "Manage the Provider Conversation bound to a Task Role.",
575
- sections: [{ id: "manage", title: "Commands", entries: ["switch"] }],
576
- children: [{
577
- name: "switch",
578
- summary: "Request a fresh Conversation after the current one reaches a safe boundary.",
579
- usage: "yui task role session switch <task> <role> --reason <text>",
580
- options: ["--reason"]
581
- }]
582
- },
583
590
  {
584
591
  name: "view",
585
592
  summary: "Attach read-only to an independent Provider presentation surface.",
@@ -720,12 +727,12 @@ const taskChildren = [
720
727
  {
721
728
  name: "run",
722
729
  summary: "Inspect and control Task Role Agent Runs.",
723
- sections: [{ id: "manage", title: "Commands", entries: ["list", "show", "retry", "settle", "recover", "yield", "context", "checkpoint", "retire"] }],
730
+ sections: [{ id: "manage", title: "Commands", entries: ["list", "show", "retry", "settle", "yield", "context", "checkpoint", "retire"] }],
724
731
  children: [
725
732
  { name: "list", summary: "List Runs for a work item.", usage: "yui task run list <task>/<work>" },
726
733
  {
727
734
  name: "show",
728
- summary: "Show one Run with its canonical recovery fence and exact recovery actions.",
735
+ summary: "Show one Run and its retained audit evidence.",
729
736
  usage: "yui task run show <task>/<run> [--json]"
730
737
  },
731
738
  {
@@ -738,12 +745,6 @@ const taskChildren = [
738
745
  summary: "Close an obsolete stranded final Review Run without requesting a retry Round.",
739
746
  usage: "yui task run settle <task>/<run>"
740
747
  },
741
- {
742
- name: "recover",
743
- summary: "Record one exact Leader-controlled Run recovery decision.",
744
- usage: "yui task run recover <task>/<run> --action <diagnose|retry|terminate> (--expected-progress-at <timestamp>|--from-next-action <fingerprint>) --provider-acceptance <accepted|rejected|ambiguous> --reason <text>",
745
- options: ["--action", "--expected-progress-at", "--progress-at", "--from-next-action", "--provider-acceptance", "--reason", "--role", "--agent-id", "--adapter-id", "--native-session-id", "--launch-id"]
746
- },
747
748
  {
748
749
  name: "yield",
749
750
  summary: "Complete an active Run and wake the Leader.",
@@ -1432,7 +1433,7 @@ export const ROOT_COMMAND = buildNode({
1432
1433
  name: "task",
1433
1434
  summary: "Manage Tasks, WorkItems, Agent Runs, and integration.",
1434
1435
  sections: [
1435
- { id: "lifecycle", title: "Lifecycle", entries: ["create", "project", "base", "update", "activate", "complete", "reopen", "retire", "list", "show", "context", "next-action", "archive", "rebuild", "history", "replace", "reconcile", "upstream"] },
1436
+ { id: "lifecycle", title: "Lifecycle", entries: ["create", "project", "base", "update", "activate", "execution", "complete", "reopen", "retire", "list", "show", "context", "next-action", "archive", "rebuild", "history", "replace", "reconcile", "upstream"] },
1436
1437
  { id: "collaboration", title: "Collaboration", entries: ["message", "input", "grant", "workflow", "publication", "work", "run", "review", "integration", "role", "overlap", "change-set"] },
1437
1438
  { id: "knowledge", title: "Task Knowledge", entries: ["brief", "decision", "milestone", "event", "continuation", "wake"] }
1438
1439
  ],
@@ -346,20 +346,6 @@ export const INTERACTION_POLICIES = Object.freeze([
346
346
  { argumentIndex: 5, entity: "agent", provider: "configured-agents", actionTarget: false }
347
347
  ]
348
348
  })),
349
- {
350
- commandPath: ["task", "role", "session", "switch"],
351
- selectors: [
352
- { argumentIndex: 4, entity: "task", provider: "tasks", actionTarget: true, statuses: ["active"] },
353
- {
354
- argumentIndex: 5,
355
- entity: "task-role",
356
- provider: "task-roles",
357
- dependsOn: 4,
358
- actionTarget: true
359
- }
360
- ],
361
- trailingOptions: { "--reason": "value" }
362
- },
363
349
  ...["view", "takeover", "release"].map((command) => ({
364
350
  commandPath: ["task", "role", command],
365
351
  selectors: [
package/dist/cli.js CHANGED
@@ -39,6 +39,7 @@ import { runProjectCommand } from "./commands/projectCommands.js";
39
39
  import { runProfileCommand } from "./commands/profileCommands.js";
40
40
  import { dispatchPreparedReviewRound, failPendingReviewRound, preserveReviewRoundWorkspace, parseTaskCompletionRequest, parseTaskFinalReviewContractRebindRequest, preflightTaskCompletion, runTaskCommand, normalizedExecutionLanePlan, resolvedExecutionStageRetryGroup, validateTaskArchiveRequest } from "./commands/taskCommands.js";
41
41
  import { taskActor } from "./commands/taskActor.js";
42
+ import { parseTaskExecutionStartRequest, parseTaskExecutionStopRequest, finalizeStoppedTaskExecution, startTaskExecutionCommand, stopTaskExecutionCommand } from "./commands/taskExecutionCommands.js";
42
43
  import { isCurrentGlobalOperator } from "./commands/taskInputCommands.js";
43
44
  import { runTaskIntegrationCommand } from "./commands/taskIntegrationCommands.js";
44
45
  import { runTaskChangeSetCommand } from "./commands/taskChangeSetCommands.js";
@@ -808,6 +809,47 @@ export async function main() {
808
809
  return;
809
810
  }
810
811
  if (resolved[0] === "task") {
812
+ if (resolved[1] === "execution") {
813
+ if (resolved[2] === "stop") {
814
+ const request = parseTaskExecutionStopRequest(resolved.slice(3));
815
+ const result = stopTaskExecutionCommand(request, store, { environment: process.env });
816
+ try {
817
+ await ensureFileTaskController(home, { environment: process.env });
818
+ await runtime.stopTaskDurableJobs(result.taskId);
819
+ await runtime.stopTaskRoleSessions(result.taskId, result.roleNames);
820
+ await runtime.assertTaskPhysicalResourcesReleased(result.taskId);
821
+ finalizeStoppedTaskExecution(result.taskId, store);
822
+ }
823
+ catch (error) {
824
+ const message = error instanceof Error ? error.message : String(error);
825
+ throw runtimeError(`Task execution is stopped and durable progress is preserved, but physical runtime cleanup failed: ${message}`);
826
+ }
827
+ emit(result.output, false, result);
828
+ return;
829
+ }
830
+ if (resolved[2] === "start") {
831
+ const taskId = parseTaskExecutionStartRequest(resolved.slice(3));
832
+ const task = store.getTask(taskId);
833
+ if (task === null)
834
+ throw usageError(`Task not found: ${taskId}.`);
835
+ // Reject managed Task callers before inspecting or starting runtime resources.
836
+ if (taskActor(process.env, taskId) === "leader") {
837
+ throw usageError("Task execution stop/start requires the global Operator or a human user.");
838
+ }
839
+ if (task.executionGate.state === "stopped") {
840
+ await runtime.assertTaskPhysicalResourcesReleased(taskId);
841
+ }
842
+ await ensureFileTaskController(home, { environment: process.env });
843
+ const result = startTaskExecutionCommand(taskId, store, { environment: process.env });
844
+ // Idempotent start is also a reliable kick: if an earlier caller
845
+ // committed the gate but lost its Controller acknowledgement, retrying
846
+ // start re-signals the same durable wake without creating another one.
847
+ await runtime.notifyMailboxChanged?.({ kind: "role", taskId, roleName: "leader" });
848
+ emit(result.output, false, result);
849
+ return;
850
+ }
851
+ throw usageError("Task execution usage: yui task execution <stop|start> ...");
852
+ }
811
853
  if (resolved[1] === "integration") {
812
854
  const result = await runTaskIntegrationCommand(resolved.slice(2), store, home, {
813
855
  environment: process.env,
@@ -139,7 +139,7 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
139
139
  }
140
140
  if (report.sessions.status === "ok" && report.sessions.data !== undefined) {
141
141
  const sessions = report.sessions.data;
142
- lines.push("", `Sessions: ${sessions.generations} generations · ${sessions.broken} broken · ${sessions.stopped} stopped · ${sessions.other} other`, `Resets: ${sessions.resets} · Conversation switches ${sessions.conversationSwitches}`
142
+ lines.push("", `Sessions: ${sessions.generations} generations · ${sessions.broken} broken · ${sessions.stopped} stopped · ${sessions.other} other`, `Resets: ${sessions.resets} · Historical conversation switches ${sessions.conversationSwitches}`
143
143
  + ` · lifecycle events ${sessions.lifecycleEvents} · stop failures ${sessions.stopFailures}`, `Terminal by Run relation: ${sessions.terminalByRunRelation.postRunYielded} post-run-yielded`
144
144
  + ` · ${sessions.terminalByRunRelation.runFailed} run-failed`
145
145
  + ` · ${sessions.terminalByRunRelation.activeRun} active-run`