@zq-silk/yui 0.13.4 → 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.
- package/README.md +8 -8
- package/dist/cli/commandCatalog.js +22 -21
- package/dist/cli/interactionPolicy.js +0 -14
- package/dist/cli.js +42 -0
- package/dist/commands/executionAuditCommands.js +1 -1
- package/dist/commands/taskCommands.js +60 -326
- package/dist/commands/taskContextCommand.js +3 -14
- package/dist/commands/taskExecutionCommands.js +254 -0
- package/dist/commands/taskNextActionCommand.js +1 -3
- package/dist/commands/taskOverviewCommand.js +9 -2
- package/dist/commands/taskRoleRuntimeStatus.js +2 -25
- package/dist/controller/agentRuntimeObserver.js +4 -2
- package/dist/controller/clientRuntime.js +45 -2
- package/dist/controller/controller.js +6 -3
- package/dist/controller/fileSchedulerStoreAdapter.js +59 -188
- package/dist/controller/jobControl.js +3 -2
- package/dist/controller/runtime.js +6 -33
- package/dist/controller/runtimeEventProcessor.js +8 -4
- package/dist/controller/runtimeHookRunFence.js +4 -10
- package/dist/execution/executionHealth.js +8 -16
- package/dist/executor/agentExecutor.js +13 -14
- package/dist/executor/fileRoleLaunchPlanner.js +9 -16
- package/dist/lifecycle/exactRunTerminalization.js +24 -322
- package/dist/repository/taskWorkspaceCoordinator.js +0 -9
- package/dist/runtime/agentHost.js +20 -80
- package/dist/runtime/exactControlPlane.js +15 -9
- package/dist/runtime/providerContinuationReconciliationService.js +1 -1
- package/dist/runtime/providerRecoveryDecision.js +1 -1
- package/dist/runtime/providerRuntimeIdentity.js +25 -15
- package/dist/scheduler/activeRoleRunDelivery.js +1 -19
- package/dist/scheduler/leaderWakeupProcessor.js +12 -63
- package/dist/scheduler/ports.js +3 -2
- package/dist/scheduler/roleRunLiveness.js +4 -1
- package/dist/scheduler/roleRunStall.js +0 -2
- package/dist/scheduler/taskExecutionProjection.js +18 -1
- package/dist/scheduler/wakeupQueue.js +2 -1
- package/dist/storage/migration/productionRegistry.js +65 -0
- package/dist/storage/sqliteStore.js +10 -2
- package/dist/storage/taskStore.js +11 -3
- package/dist/task/completionReadiness.js +0 -67
- package/dist/task/nextAction.js +16 -32
- package/dist/task/task.js +38 -3
- package/dist/web/assets/client/i18n.js +0 -4
- package/dist/web/assets/client/view.js +0 -18
- package/dist/web/webSnapshot.js +7 -13
- package/package.json +1 -1
- package/dist/run/recoveryProjection.js +0 -252
- 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
|
-
|
|
553
|
-
|
|
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
|
|
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
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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",
|
|
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", "
|
|
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
|
|
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} ·
|
|
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`
|