@zq-silk/yui 2.20.0 → 2.22.0
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 +5 -0
- package/dist/cli/commandCatalog.js +88 -28
- package/dist/cli/dynamicCompletion.js +4 -1
- package/dist/cli/helpRenderer.js +12 -1
- package/dist/cli/interactionPolicy.js +2 -0
- package/dist/cli/invocationAuthority.js +2 -6
- package/dist/cli/invocationRouter.js +5 -5
- package/dist/cli/managedDiagnostics.js +24 -16
- package/dist/cli/roleWizard.js +5 -1
- package/dist/commands/durableJobCommands.js +2 -3
- package/dist/commands/globalRoleCommands.js +33 -8
- package/dist/commands/inboxCommands.js +39 -12
- package/dist/commands/operatorCommands.js +2 -5
- package/dist/commands/releaseCommands.js +16 -2
- package/dist/commands/roleConfiguration.js +25 -2
- package/dist/commands/sessionCommands.js +5 -2
- package/dist/commands/taskCommands.js +225 -99
- package/dist/commands/taskContextCommand.js +26 -4
- package/dist/commands/taskFactCommands.js +20 -7
- package/dist/commands/taskIntegrationCommands.js +3 -3
- package/dist/commands/taskRoleRuntimeStatus.js +15 -5
- package/dist/commands/taskUsageCommand.js +2 -6
- package/dist/commands/textInput.js +2 -2
- package/dist/context/contextFamilies.js +10 -0
- package/dist/context/currentSkills.js +6 -4
- package/dist/context/runContextPack.js +44 -5
- package/dist/context/runInputContract.js +1 -1
- package/dist/context/sessionBootstrapManifest.js +7 -5
- package/dist/context/sessionSkillNotice.js +53 -0
- package/dist/context/taskCatalog.js +4 -13
- package/dist/context/taskContext.js +135 -103
- package/dist/context/taskSearch.js +3 -7
- package/dist/controlPlaneCli.js +23 -25
- package/dist/controller/agentRuntimeObserver.js +57 -12
- package/dist/controller/clientRuntime.js +37 -8
- package/dist/controller/controller.js +3 -1
- package/dist/controller/diagnosticJournal.js +10 -2
- package/dist/controller/fileSchedulerStoreAdapter.js +72 -24
- package/dist/controller/jobClient.js +2 -2
- package/dist/controller/jobControl.js +2 -2
- package/dist/controller/jobDefinitionControl.js +5 -1
- package/dist/controller/messageHealth.js +4 -3
- package/dist/controller/providerRetryAdmission.js +15 -1
- package/dist/controller/providerRetryDelivery.js +18 -2
- package/dist/controller/runtime.js +15 -5
- package/dist/controller/runtimeEventInbox.js +107 -13
- package/dist/controller/runtimeEventProcessor.js +3 -3
- package/dist/controller/taskRunRecovery.js +153 -0
- package/dist/core/controllerClient.js +16 -2
- package/dist/core/controllerServer.js +14 -5
- package/dist/core/controllerTelemetry.js +51 -5
- package/dist/errors/cliFailure.js +14 -5
- package/dist/executor/agentAdapter.js +32 -4
- package/dist/executor/agentConfigurationFields.js +2 -0
- package/dist/executor/taskAgentCapabilities.js +2 -2
- package/dist/integration/gitIntegrationService.js +3 -2
- package/dist/integration/integrationSourceApplication.js +12 -1
- package/dist/interaction/notificationPresentation.js +11 -16
- package/dist/interaction/operatorPresentation.js +1 -1
- package/dist/message/messageContinuation.js +3 -1
- package/dist/output/boundedRead.js +36 -7
- package/dist/output/rolePresentation.js +3 -1
- package/dist/runtime/agentHost.js +12 -3
- package/dist/runtime/codexAppServerRuntime.js +110 -24
- package/dist/runtime/codexInteractiveHost.js +46 -0
- package/dist/runtime/providerRetry.js +5 -2
- package/dist/runtime/providerRuntimeIdentity.js +1 -1
- package/dist/runtime/structuredProviderHost.js +32 -34
- package/dist/scheduler/wakeupQueue.js +10 -4
- package/dist/storage/sqliteSchema.js +9 -0
- package/dist/storage/storageVersions.js +1 -1
- package/dist/task/taskAuthority.js +7 -3
- package/dist/tmux/tmuxManager.js +4 -2
- package/dist/web/webSettings.js +2 -0
- package/docs/authorization.md +18 -3
- package/docs/cli-information-contract.md +245 -6
- package/docs/cli-information-contract.zh-CN.md +107 -5
- package/docs/managed-turn-and-session-runtime.md +82 -21
- package/docs/managed-turn-and-session-runtime.zh-CN.md +56 -13
- package/docs/provider-retry.md +11 -0
- package/docs/release-workflow.md +62 -0
- package/docs/release-workflow.zh-CN.md +46 -0
- package/docs/roles-and-configuration.md +28 -0
- package/docs/roles-and-configuration.zh-CN.md +21 -0
- package/docs/storage-baseline.md +4 -1
- package/docs/storage-baseline.zh-CN.md +1 -1
- package/docs/task-delivery.md +7 -0
- package/docs/task-delivery.zh-CN.md +5 -0
- package/docs/task-discovery.md +5 -5
- package/docs/task-discovery.zh-CN.md +4 -4
- package/docs/testing/review-evaluation.md +7 -7
- package/docs/testing/review-evaluation.zh-CN.md +7 -7
- package/docs/testing/verification-levels.md +45 -2
- package/docs/testing/verification-levels.zh-CN.md +21 -2
- package/i18n/README.zh-CN.md +6 -0
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +98 -189
- package/skills/yui-leader/VERSION +1 -1
- package/skills/yui-leader/references/artifacts.md +41 -0
- package/skills/yui-leader/references/assignment-execution.md +140 -0
- package/skills/yui-leader/references/completion.md +79 -0
- package/skills/yui-leader/references/delivery-scope.md +26 -0
- package/skills/yui-leader/references/execution.md +16 -487
- package/skills/yui-leader/references/implementation.md +81 -0
- package/skills/yui-leader/references/planning.md +7 -45
- package/skills/yui-leader/references/review.md +90 -0
- package/skills/yui-leader/references/task-progress.md +23 -0
- package/skills/yui-leader/references/work-allocation.md +118 -0
- package/skills/yui-operator/SKILL.md +77 -331
- package/skills/yui-operator/VERSION +1 -1
- package/skills/yui-operator/references/body-transport.md +62 -0
- package/skills/yui-operator/references/configuration.md +47 -0
- package/skills/yui-operator/references/lifecycle.md +41 -0
- package/skills/yui-operator/references/progress.md +39 -0
- package/skills/yui-operator/references/routing.md +57 -0
- package/skills/yui-operator/references/submission.md +56 -0
- package/skills/yui-operator/references/task-delivery.md +5 -2
- package/skills/yui-operator/references/web-lifecycle.md +19 -0
- package/skills/yui-operator/scripts/verify-submission.mjs +37 -0
- package/skills/yui-reviewer/SKILL.md +4 -2
- package/skills/yui-reviewer/VERSION +1 -1
- package/skills/yui-runtime/SKILL.md +177 -505
- package/skills/yui-runtime/VERSION +1 -1
- package/skills/yui-runtime/references/archive.md +51 -0
- package/skills/yui-runtime/references/command-discovery.md +41 -0
- package/skills/yui-runtime/references/completed-followup.md +65 -0
- package/skills/yui-runtime/references/context-ordering.md +3 -34
- package/skills/yui-runtime/references/context-reads.md +61 -0
- package/skills/yui-runtime/references/dispatched-run.md +61 -0
- package/skills/yui-runtime/references/execution-failure.md +105 -0
- package/skills/yui-runtime/references/global-context.md +18 -0
- package/skills/yui-runtime/references/global-input-controls.md +44 -0
- package/skills/yui-runtime/references/host-custody.md +30 -0
- package/skills/yui-runtime/references/inbox-recovery.md +77 -0
- package/skills/yui-runtime/references/incremental-context.md +40 -0
- package/skills/yui-runtime/references/publication.md +4 -104
- package/skills/yui-runtime/references/recovery.md +32 -192
- package/skills/yui-runtime/references/session-identity.md +18 -0
- package/skills/yui-runtime/references/session-replacement.md +45 -0
- package/skills/yui-runtime/references/uncertain-execution.md +29 -0
- package/skills/yui-worker/SKILL.md +7 -4
- package/skills/yui-worker/VERSION +1 -1
|
@@ -8,12 +8,12 @@ import { createRun, runExecutionObservation, runPurposeAdmitsTaskState } from ".
|
|
|
8
8
|
import { isGitArtifactRefString, parseGitArtifactRef } from "../artifacts/gitArtifactRef.js";
|
|
9
9
|
import { contextContentDigest, contextSnapshotRef } from "../context/contextSnapshot.js";
|
|
10
10
|
import { sourceRunContextValue } from "../context/sourceRunContext.js";
|
|
11
|
-
import { buildRunContextDelta, buildRunContextPack, runContextEntry, runContextPointerPage, contextSnapshotDeltaRefIds, expandRunContextRef, freezeReviewStageContextSnapshot, freezeRunContextSnapshot, freezeWorkItemExecutionAssignmentContextSnapshot, freezeCandidateContextSnapshot, readRunContextSnapshot, synthesisSourceRunIds } from "../context/runContextPack.js";
|
|
11
|
+
import { buildRunContextDelta, buildRunContextPack, runContextEntry, runContextPointerPage, contextSnapshotDeltaRefIds, expandRunContextRef, expandRunContextRefs, freezeReviewStageContextSnapshot, freezeRunContextSnapshot, freezeWorkItemExecutionAssignmentContextSnapshot, freezeCandidateContextSnapshot, readRunContextSnapshot, synthesisSourceRunIds } from "../context/runContextPack.js";
|
|
12
12
|
import { createRunInput } from "../context/runInputContract.js";
|
|
13
13
|
import { parseTaskCatalogOptions, readTaskCatalog, renderTaskCatalog } from "../context/taskCatalog.js";
|
|
14
|
-
import {
|
|
14
|
+
import { assertTaskReadable, materialize, parseExactContextRef, readTaskContextResource, resolveContextReader } from "../context/taskContext.js";
|
|
15
15
|
import { parseTaskSearchOptions, searchTaskBodies } from "../context/taskSearch.js";
|
|
16
|
-
import { boundedDocument, readOptions, messageReceipt, recordPage } from "../output/boundedRead.js";
|
|
16
|
+
import { boundedDocument, readOptions, messageReceipt, recordPage, summaryText } from "../output/boundedRead.js";
|
|
17
17
|
import { referencedWakeRunIds } from "../context/wakeRunReferences.js";
|
|
18
18
|
import { taskMessagePresentation, wakeChangeLabels, wakeMessages } from "../interaction/notificationPresentation.js";
|
|
19
19
|
import { completeProcessing, releaseProcessing } from "../coordination/workMailbox.js";
|
|
@@ -23,7 +23,7 @@ import { dispatchReviewSynthesis, selectedReviewSynthesisProducers } from "../ex
|
|
|
23
23
|
import { createExecutionGroup, createReviewExecutionAssignment, createWorkItemExecutionAssignment, createWorkItemExecutionGroup, updateExecutionLane as updateUnifiedExecutionLane, updateWorkItemExecutionLane, workItemExecutionGroupSettled } from "../execution/workItemExecution.js";
|
|
24
24
|
import { projectWorkItemExecution } from "../execution/workItemExecutionProjection.js";
|
|
25
25
|
import { dispatchWorkItemSynthesis, selectedWorkItemSynthesisProducers } from "../execution/workItemMainRun.js";
|
|
26
|
-
import { createRoleSessionSet, roleAgentSessionResumeMode, roleSessionControlTarget, updateTaskRoleProviderRuntime } from "../executor/agentExecutor.js";
|
|
26
|
+
import { activeRoleAgentSession, createRoleSessionSet, roleAgentSessionResumeMode, roleSessionControlTarget, updateTaskRoleProviderRuntime } from "../executor/agentExecutor.js";
|
|
27
27
|
import { resolveEffectiveLaunch, effectiveLaunchWithTaskMainWorkspace } from "../executor/effectiveLaunch.js";
|
|
28
28
|
import { cancelInputRequest } from "../input/inputRequest.js";
|
|
29
29
|
import { retireExactActiveRun, terminalizeExactTaskRun, validateExactRunReviewRound } from "../lifecycle/exactRunTerminalization.js";
|
|
@@ -46,8 +46,9 @@ import { resolveRecordedTaskFinalReviewContract } from "../review/taskFinalRevie
|
|
|
46
46
|
import { copyGlobalRoleToTaskRole, activeRoleAgentBinding, createRole, createRoleAgentBinding, switchActiveRoleAgent, unbindRoleAgent, updateRole } from "../role/role.js";
|
|
47
47
|
import { roleLaunchEventPayload, saveTaskRoleUpdate } from "../role/taskRoleUpdate.js";
|
|
48
48
|
import { RUNTIME_SESSION_REPLACE_REQUIRED_REASON, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
|
|
49
|
-
import { currentManagedRuntime
|
|
50
|
-
import { controlProviderRetry, providerRunRetry, providerRetryProjection, renderProviderRetry } from "../runtime/providerRetry.js";
|
|
49
|
+
import { currentManagedRuntime } from "../runtime/managedCaller.js";
|
|
50
|
+
import { controlProviderRetry, providerRunRetry, providerRetryProjection, providerRetrySummary, renderProviderRetry } from "../runtime/providerRetry.js";
|
|
51
|
+
import { taskRunRecovery } from "../controller/taskRunRecovery.js";
|
|
51
52
|
import { currentProviderConversation, transferProviderAuthority } from "../runtime/providerRuntimeIdentity.js";
|
|
52
53
|
import { projectProviderContinuations } from "../runtime/runtimeContinuationProjection.js";
|
|
53
54
|
import { runtimeObservationFromTaskEvent } from "../runtime/runtimeObservation.js";
|
|
@@ -67,7 +68,7 @@ import { addTaskProjectBinding, archiveTask, completeTask, createTask, reopenTas
|
|
|
67
68
|
import { recordTaskActivationRequestInTransaction, taskActivationOperationRef } from "../task/taskActivationService.js";
|
|
68
69
|
import { assertTaskDeliveryAuthority, assertTaskInputControlAuthority } from "../task/taskAuthority.js";
|
|
69
70
|
import { resolveTaskRecordReference } from "../task/taskRecordReference.js";
|
|
70
|
-
import { createTaskRecordRetirement, isTaskRecordRetired, operationalTaskRecords, taskRecordRetirement } from "../task/taskRecordRetirement.js";
|
|
71
|
+
import { createTaskRecordRetirement, isTaskRecordRetired, operationalTaskRecords, taskRecordRetirement, TASK_RECORD_RETIRED_EVENT } from "../task/taskRecordRetirement.js";
|
|
71
72
|
import { decideSubmissionRouting, describeSubmissionFeedback, draftActivationState, draftHasEnteredPlanning, normalizeSubmissionIntent, sameSubmissionTarget, TASK_PLANNING_ENTERED_EVENT } from "../task/taskSubmission.js";
|
|
72
73
|
import { assertWorkItemDependenciesCompleted as assertWorkItemDependencyGate, WorkItemDependencyGateError } from "../workItem/dependencyGate.js";
|
|
73
74
|
import { attachWorkItemExecutionGroup, createWorkItem, currentWorkItemCandidate, currentWorkItemExecutionGroup, editWorkItemDefinition, prepareWorkItemDispatch, retireWorkItem, submitWorkItemCandidate, updateWorkItemExecutionGroup, updateWorkItemStatus, updateWorkItemWriteProjects, workItemExecutionGroupById } from "../workItem/workItem.js";
|
|
@@ -318,7 +319,8 @@ export function runTaskCommand(args, store, options = {}) {
|
|
|
318
319
|
|| (["brief", "decision", "milestone", "event", "work", "wake", "review", "change-set"].includes(args[0] ?? "")
|
|
319
320
|
&& args[1] === "show")
|
|
320
321
|
|| (args[0] === "role" && (["show", "status"].includes(args[1] ?? "")
|
|
321
|
-
|| args[1] === "session" && args[2] === "inspect"
|
|
322
|
+
|| args[1] === "session" && (args[2] === "inspect"
|
|
323
|
+
|| args[2] === "retry" && (args[5] === undefined || args[5] === "show" || args[5] === "--cursor"))));
|
|
322
324
|
if (!detail)
|
|
323
325
|
return executeTaskCommand(args, store, options);
|
|
324
326
|
const cursorIndex = args.indexOf("--cursor");
|
|
@@ -851,7 +853,15 @@ export function submitOperatorMessage(body, taskId, store, options = {}, intent,
|
|
|
851
853
|
const header = result.created
|
|
852
854
|
? `Created Draft task ${result.task.id}: ${result.task.title}\n`
|
|
853
855
|
: "";
|
|
854
|
-
return
|
|
856
|
+
return {
|
|
857
|
+
kind: "output",
|
|
858
|
+
output: `${header}${renderSubmissionFeedback(result.feedback)}`,
|
|
859
|
+
data: {
|
|
860
|
+
taskId: result.task.id,
|
|
861
|
+
message: messageReceipt(result.message),
|
|
862
|
+
submission: result.feedback
|
|
863
|
+
}
|
|
864
|
+
};
|
|
855
865
|
}
|
|
856
866
|
function findSubmissionKeyCreate(store, submissionKey) {
|
|
857
867
|
let otherTarget = false;
|
|
@@ -1684,7 +1694,7 @@ function taskMessageCommand(args, store, options) {
|
|
|
1684
1694
|
const parsed = readOptions(rest, ["--cursor"]);
|
|
1685
1695
|
exactPositionals(parsed.positionals, 1, usage);
|
|
1686
1696
|
const ref = taskRecordReference(parsed.positionals[0], "message", "Message reference", options);
|
|
1687
|
-
|
|
1697
|
+
assertTaskReadable(store, ref.taskId, options.environment);
|
|
1688
1698
|
const message = store.queryContextRecords(ref.taskId, {
|
|
1689
1699
|
family: "task-message", ids: [ref.localId], limit: 1
|
|
1690
1700
|
}).records[0]?.value;
|
|
@@ -1702,7 +1712,7 @@ function taskMessageCommand(args, store, options) {
|
|
|
1702
1712
|
const parsed = parseTail(rest, new Set(["--body-file", "--intent", "--request-id", "--to", "--work-item", "--review-round"]), usage);
|
|
1703
1713
|
if (parsed.positionals.length < 1 || parsed.positionals.length > 2)
|
|
1704
1714
|
throw usageError(usage);
|
|
1705
|
-
const body = readCommandText(parsed.positionals[1], parsed.options.get("--body-file"), "--body", usage);
|
|
1715
|
+
const body = readCommandText(parsed.positionals[1], parsed.options.get("--body-file"), "--body", usage, { preserveFileWhitespace: true });
|
|
1706
1716
|
const intent = parseSubmissionIntentOption(parsed.options.get("--intent"), usage);
|
|
1707
1717
|
const submissionKey = parsed.options.get("--request-id");
|
|
1708
1718
|
if (submissionKey !== undefined && submissionKey.trim().length === 0) {
|
|
@@ -1771,7 +1781,7 @@ function queueTaskMessage(args, store, options) {
|
|
|
1771
1781
|
const parsed = parseTail(args, new Set(["--body-file", "--request-id", "--to", "--work-item", "--review-round"]), usage);
|
|
1772
1782
|
if (parsed.positionals.length < 1 || parsed.positionals.length > 2)
|
|
1773
1783
|
throw usageError(usage);
|
|
1774
|
-
const body = readCommandText(parsed.positionals[1], parsed.options.get("--body-file"), "--body", usage);
|
|
1784
|
+
const body = readCommandText(parsed.positionals[1], parsed.options.get("--body-file"), "--body", usage, { preserveFileWhitespace: true });
|
|
1775
1785
|
const requestId = requiredOption(parsed.options, "--request-id");
|
|
1776
1786
|
const recipientRole = parsed.options.get("--to");
|
|
1777
1787
|
const workItemId = parsed.options.get("--work-item");
|
|
@@ -1808,7 +1818,7 @@ function steerTaskMessage(args, store, options) {
|
|
|
1808
1818
|
const parsed = parseTail(args, new Set(["--body-file", "--request-id", "--expected-target", "--to", "--work-item", "--review-round"]), usage);
|
|
1809
1819
|
if (parsed.positionals.length < 1 || parsed.positionals.length > 2)
|
|
1810
1820
|
throw usageError(usage);
|
|
1811
|
-
const body = readCommandText(parsed.positionals[1], parsed.options.get("--body-file"), "--body", usage);
|
|
1821
|
+
const body = readCommandText(parsed.positionals[1], parsed.options.get("--body-file"), "--body", usage, { preserveFileWhitespace: true });
|
|
1812
1822
|
const requestId = requiredOption(parsed.options, "--request-id");
|
|
1813
1823
|
const expectedTarget = requiredOption(parsed.options, "--expected-target");
|
|
1814
1824
|
const recipientRole = parsed.options.get("--to");
|
|
@@ -2084,7 +2094,7 @@ function updateMessage(args, store, options) {
|
|
|
2084
2094
|
const parsed = parseTail(args, new Set(["--body-file"]), usage);
|
|
2085
2095
|
if (parsed.positionals.length < 1 || parsed.positionals.length > 2)
|
|
2086
2096
|
throw usageError(usage);
|
|
2087
|
-
const body = readCommandText(parsed.positionals[1], parsed.options.get("--body-file"), "--body", usage);
|
|
2097
|
+
const body = readCommandText(parsed.positionals[1], parsed.options.get("--body-file"), "--body", usage, { preserveFileWhitespace: true });
|
|
2088
2098
|
const reference = taskRecordReference(parsed.positionals[0], "message", "Message reference", options);
|
|
2089
2099
|
const now = clock(options);
|
|
2090
2100
|
const result = store.transaction((tx) => {
|
|
@@ -2507,19 +2517,13 @@ function taskRoleSessionCommand(args, store, options) {
|
|
|
2507
2517
|
if (extra.length > 0 || !["show", "cancel", "disable", "enable"].includes(action)) {
|
|
2508
2518
|
throw usageError("Usage: yui task role session retry <task> <role> [show|cancel|disable|enable]");
|
|
2509
2519
|
}
|
|
2510
|
-
return store
|
|
2520
|
+
return store[action === "show" ? "readTransaction" : "transaction"](tx => {
|
|
2511
2521
|
const task = requireTask(tx, taskId);
|
|
2512
2522
|
const role = requireRole(tx, task.id, roleName);
|
|
2513
2523
|
if (action !== "show")
|
|
2514
2524
|
taskActor(tx, options, task.id);
|
|
2515
|
-
else
|
|
2516
|
-
|
|
2517
|
-
if (reader === undefined)
|
|
2518
|
-
taskActor(tx, options, task.id);
|
|
2519
|
-
else if (reader.taskId !== task.id || reader.roleName !== "leader" && reader.roleName !== role.name) {
|
|
2520
|
-
throw usageError("Provider retry read is outside the caller's Task/Role.");
|
|
2521
|
-
}
|
|
2522
|
-
}
|
|
2525
|
+
else
|
|
2526
|
+
resolveContextReader(tx, options.environment ?? {});
|
|
2523
2527
|
const sessions = tx.getTaskRoleSessionSet(task.id, role.name);
|
|
2524
2528
|
let binding = sessions?.providerBinding ?? null;
|
|
2525
2529
|
if (action !== "show") {
|
|
@@ -2538,12 +2542,7 @@ function taskRoleSessionCommand(args, store, options) {
|
|
|
2538
2542
|
exactPositionals(rest, 2, "Task Role Session inspect usage: yui task role session inspect <task> <role>.");
|
|
2539
2543
|
const task = requireTask(store, rest[0]);
|
|
2540
2544
|
const role = requireRole(store, task.id, rest[1]);
|
|
2541
|
-
|
|
2542
|
-
if (reader === undefined)
|
|
2543
|
-
taskActor(store, options, task.id);
|
|
2544
|
-
else if (reader.taskId !== task.id || (reader.roleName !== "leader" && reader.roleName !== role.name)) {
|
|
2545
|
-
throw usageError("Session inspection is outside the caller's Task/Role.");
|
|
2546
|
-
}
|
|
2545
|
+
resolveContextReader(store, options.environment ?? {});
|
|
2547
2546
|
const sessions = store.getTaskRoleSessionSet(task.id, role.name);
|
|
2548
2547
|
const active = sessions?.sessions[sessions.activeAgentId] ?? null;
|
|
2549
2548
|
const binding = sessions?.providerBinding ?? null;
|
|
@@ -2767,28 +2766,93 @@ function listTaskRoles(args, store, options) {
|
|
|
2767
2766
|
return output(`${JSON.stringify(data)}\n`, data);
|
|
2768
2767
|
}
|
|
2769
2768
|
function taskRoleStatus(args, store, options) {
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
const
|
|
2769
|
+
const parsed = readOptions(args, ["--view"]);
|
|
2770
|
+
exactPositionals(parsed.positionals, 2, "Task role status usage: yui task role status <task> <role> [--view current|full].");
|
|
2771
|
+
const view = parsed.values.get("--view") ?? "current";
|
|
2772
|
+
if (!["current", "full"].includes(view))
|
|
2773
|
+
throw usageError("Task role status --view must be current or full.");
|
|
2774
|
+
const task = requireTask(store, parsed.positionals[0]);
|
|
2775
|
+
const role = requireRole(store, task.id, parsed.positionals[1]);
|
|
2773
2776
|
const [status] = inspectTaskRoleRuntimeStatuses(task.id, [role], store, options.runtime?.inspectTaskRolePanes?.(task.id) ?? [], options.now?.() ?? new Date());
|
|
2774
2777
|
if (status === undefined)
|
|
2775
2778
|
throw roleNotFound(role.name);
|
|
2776
2779
|
const observed = withTaskRoleHostObservation(status, options.liveHostObservations?.[role.name]);
|
|
2777
|
-
|
|
2780
|
+
if (view === "full")
|
|
2781
|
+
return output(renderTaskRoleRuntimeStatus(observed), { role: observed });
|
|
2782
|
+
// Presentation only: retain the already-computed health, live Host and
|
|
2783
|
+
// uncertain delivery facts. Run/WorkItem originals are not status fields.
|
|
2784
|
+
const currentRun = (run) => run === null ? null : ({
|
|
2785
|
+
id: run.id, taskId: run.taskId, roleName: run.roleName,
|
|
2786
|
+
purpose: run.purpose, mode: run.mode, status: run.status,
|
|
2787
|
+
workItemId: run.workItemId, reviewRoundId: run.reviewRoundId,
|
|
2788
|
+
executionGroupId: run.executionGroupId, executionLaneId: run.executionLaneId,
|
|
2789
|
+
sourceExecutionGroupId: run.sourceExecutionGroupId,
|
|
2790
|
+
createdAt: run.createdAt, updatedAt: run.updatedAt,
|
|
2791
|
+
result: run.result === undefined ? null : {
|
|
2792
|
+
available: run.result.output !== undefined,
|
|
2793
|
+
bytes: run.result.output === undefined ? 0 : Buffer.byteLength(run.result.output),
|
|
2794
|
+
completedAt: run.result.completedAt, failureReason: run.result.failureReason,
|
|
2795
|
+
diagnostic: run.result.diagnostic, provider: run.result.provider,
|
|
2796
|
+
read: `yui task run show ${run.taskId}/${run.id} --view result --json`
|
|
2797
|
+
},
|
|
2798
|
+
read: `yui task run show ${run.taskId}/${run.id} --view full --json`
|
|
2799
|
+
});
|
|
2800
|
+
const session = observed.nativeSession;
|
|
2801
|
+
const work = observed.activeWork;
|
|
2802
|
+
return output(renderTaskRoleRuntimeStatus(observed), { role: {
|
|
2803
|
+
...observed,
|
|
2804
|
+
activeRun: currentRun(observed.activeRun), lastRun: currentRun(observed.lastRun),
|
|
2805
|
+
activeWork: work === null ? null : {
|
|
2806
|
+
id: work.id, taskId: work.taskId, title: work.title, status: work.status,
|
|
2807
|
+
revision: work.revision, updatedAt: work.updatedAt,
|
|
2808
|
+
read: `yui task work show ${work.taskId}/${work.id} --json`
|
|
2809
|
+
},
|
|
2810
|
+
nativeSession: session === null ? null : {
|
|
2811
|
+
agentId: session.agentId, adapterId: session.adapterId,
|
|
2812
|
+
nativeSessionId: session.nativeSessionId, status: session.status,
|
|
2813
|
+
endReason: session.endReason, policy: session.policy, effective: session.effective,
|
|
2814
|
+
createdAt: session.createdAt, updatedAt: session.updatedAt,
|
|
2815
|
+
read: `yui task role session inspect ${task.id} ${role.name} --json`
|
|
2816
|
+
},
|
|
2817
|
+
execution: observed.execution === undefined ? undefined : {
|
|
2818
|
+
...observed.execution,
|
|
2819
|
+
retry: observed.execution.retry === null ? null : providerRetrySummary(store.getTaskRoleSessionSet(task.id, role.name)?.providerBinding, `yui task role session retry ${task.id} ${role.name} show --json`)
|
|
2820
|
+
}
|
|
2821
|
+
}, reads: { full: `yui task role status ${task.id} ${role.name} --view full --json` } });
|
|
2778
2822
|
}
|
|
2779
2823
|
function showTaskRole(args, store) {
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
const
|
|
2824
|
+
const parsed = readOptions(args, ["--view"]);
|
|
2825
|
+
exactPositionals(parsed.positionals, 2, "Task role show usage: yui task role show <task> <role> [--view current|full].");
|
|
2826
|
+
const view = parsed.values.get("--view") ?? "current";
|
|
2827
|
+
if (!["current", "full"].includes(view))
|
|
2828
|
+
throw usageError("Task role show --view must be current or full.");
|
|
2829
|
+
const task = requireTask(store, parsed.positionals[0]);
|
|
2830
|
+
const role = requireRole(store, task.id, parsed.positionals[1]);
|
|
2783
2831
|
const sessions = store.getTaskRoleSessionSet(task.id, role.name);
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2832
|
+
const text = renderRoleDetails(`Task Role: ${role.name}`, role, { kind: "task", sessions });
|
|
2833
|
+
if (view === "full")
|
|
2834
|
+
return output(text, {
|
|
2835
|
+
role,
|
|
2836
|
+
sessions,
|
|
2837
|
+
runs: store.listRuns(task.id).filter((run) => run.roleName === role.name)
|
|
2838
|
+
.map((run) => ({ id: run.id, status: run.status, effective: run.effective }))
|
|
2839
|
+
});
|
|
2840
|
+
const active = activeRoleAgentSession(sessions);
|
|
2841
|
+
return output(text + `\nFull history: yui task role show ${task.id} ${role.name} --view full\n`, {
|
|
2788
2842
|
role,
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2843
|
+
observation: "recorded-configuration-not-live-state",
|
|
2844
|
+
session: active === null ? null : {
|
|
2845
|
+
agentId: active.agentId, adapterId: active.adapterId, nativeSessionId: active.nativeSessionId,
|
|
2846
|
+
status: active.status, endReason: active.endReason, policy: active.policy, effective: active.effective,
|
|
2847
|
+
createdAt: active.createdAt, updatedAt: active.updatedAt
|
|
2848
|
+
},
|
|
2849
|
+
// A missing/ended cached Session does not prove retained execution stopped.
|
|
2850
|
+
controlTarget: roleSessionControlTarget(sessions) ?? null,
|
|
2851
|
+
reads: {
|
|
2852
|
+
full: `yui task role show ${task.id} ${role.name} --view full`,
|
|
2853
|
+
session: `yui task role session inspect ${task.id} ${role.name}`,
|
|
2854
|
+
status: `yui task role status ${task.id} ${role.name}`
|
|
2855
|
+
}
|
|
2792
2856
|
});
|
|
2793
2857
|
}
|
|
2794
2858
|
function updateTaskRole(args, store, options) {
|
|
@@ -3745,22 +3809,19 @@ export function readDispatchContextRefs(store, taskId, selectors, environment =
|
|
|
3745
3809
|
throw usageError("Dispatch requires at most 16 distinct --context-ref values.");
|
|
3746
3810
|
}
|
|
3747
3811
|
return selectors.flatMap(selector => {
|
|
3748
|
-
const
|
|
3749
|
-
if (match === null) {
|
|
3750
|
-
throw usageError(`Invalid required Context reference: ${selector}. Use store/refId@digest from task context list/inspect.`);
|
|
3751
|
-
}
|
|
3752
|
-
const [, family, refId, digest] = match;
|
|
3812
|
+
const ref = parseExactContextRef(selector);
|
|
3753
3813
|
try {
|
|
3754
|
-
const entry = readTaskContextResource(store, taskId,
|
|
3755
|
-
store: family, refId: refId, digest: digest
|
|
3756
|
-
}, environment);
|
|
3814
|
+
const entry = readTaskContextResource(store, taskId, ref, environment);
|
|
3757
3815
|
const resources = [{
|
|
3758
|
-
ref: { ...entry.ref, layer: "L4", evidenceOf: "dispatch-required"
|
|
3816
|
+
ref: { ...entry.ref, layer: "L4", evidenceOf: "dispatch-required",
|
|
3817
|
+
...(ref.store === "task-message" ? {
|
|
3818
|
+
summary: summaryText(`Excerpt: ${entry.value.body}`, 160)
|
|
3819
|
+
} : {}) },
|
|
3759
3820
|
value: entry.value
|
|
3760
3821
|
}];
|
|
3761
3822
|
// Selecting a result Message selects its already-authorized original
|
|
3762
3823
|
// result too, not just a pointer the receiving Assignment cannot expand.
|
|
3763
|
-
if (
|
|
3824
|
+
if (ref.store === "task-message" && "result" in entry) {
|
|
3764
3825
|
const message = entry.value;
|
|
3765
3826
|
const source = store.getRun(taskId, message.resultRef.runId);
|
|
3766
3827
|
const value = sourceRunContextValue(source);
|
|
@@ -4776,18 +4837,34 @@ function retireRun(args, store, options) {
|
|
|
4776
4837
|
function runContextCommand(args, store, options) {
|
|
4777
4838
|
const [first, ...rest] = args;
|
|
4778
4839
|
if (first === "expand") {
|
|
4779
|
-
const usage = "Task run context expand usage: yui task run context expand <task>/<run> <ref-id> --store <store> [--mode full].";
|
|
4780
|
-
const parsed =
|
|
4781
|
-
|
|
4782
|
-
|
|
4840
|
+
const usage = "Task run context expand usage: yui task run context expand <task>/<run> (<ref-id> --store <store> | --context-ref <store/refId[@digest]> ...) [--mode full] [--cursor <cursor>].";
|
|
4841
|
+
const parsed = parseMultiValueTail(rest, new Set(["--store", "--mode", "--cursor"]), new Set(["--context-ref"]), usage);
|
|
4842
|
+
const batch = parsed.multiOptions.get("--context-ref");
|
|
4843
|
+
if (batch !== undefined && (parsed.positionals.length !== 1 || parsed.options.has("--store")))
|
|
4844
|
+
throw usageError("Do not combine --context-ref with a positional ref-id or --store.", usage);
|
|
4845
|
+
exactPositionals(parsed.positionals, batch === undefined ? 2 : 1, usage);
|
|
4846
|
+
const refStore = batch === undefined ? requiredOption(parsed.options, "--store") : undefined;
|
|
4847
|
+
const refs = batch?.map(selector => {
|
|
4848
|
+
if (/@[0-9a-f]{64}$/u.test(selector))
|
|
4849
|
+
return parseExactContextRef(selector);
|
|
4850
|
+
const match = /^([^/]+)\/(.+)$/u.exec(selector);
|
|
4851
|
+
if (match === null)
|
|
4852
|
+
throw usageError("Run Context reference requires store/refId, optionally followed by @digest.", usage);
|
|
4853
|
+
return { store: match[1], refId: match[2] };
|
|
4854
|
+
});
|
|
4783
4855
|
const mode = parsed.options.get("--mode");
|
|
4784
4856
|
if (mode !== undefined && mode !== "full") {
|
|
4785
4857
|
throw usageError("AgentRun Context expansion mode must be full.", usage);
|
|
4786
4858
|
}
|
|
4787
4859
|
const { taskId, runId } = parseRunContextReference(parsed.positionals[0]);
|
|
4788
4860
|
authorizeRunContext(store, taskId, runId, options.environment);
|
|
4789
|
-
const expanded = store.
|
|
4790
|
-
|
|
4861
|
+
const expanded = store.readTransaction((tx) => refs === undefined
|
|
4862
|
+
? expandRunContextRef(tx, taskId, runId, parsed.positionals[1], refStore)
|
|
4863
|
+
: expandRunContextRefs(tx, taskId, runId, refs));
|
|
4864
|
+
const source = refs === undefined
|
|
4865
|
+
? `run:${taskId}/${runId}/${refStore}/${parsed.positionals[1]}`
|
|
4866
|
+
: `run:${taskId}/${runId}/context-batch:${contextContentDigest(refs)}`;
|
|
4867
|
+
const data = boundedDocument(expanded, source, parsed.options.get("--cursor"));
|
|
4791
4868
|
return output(`${JSON.stringify(data, null, 2)}\n`, { context: data });
|
|
4792
4869
|
}
|
|
4793
4870
|
if (first === "delta") {
|
|
@@ -4797,7 +4874,7 @@ function runContextCommand(args, store, options) {
|
|
|
4797
4874
|
}
|
|
4798
4875
|
const { taskId, runId } = parseRunContextReference(parsed.positionals[0]);
|
|
4799
4876
|
authorizeRunContext(store, taskId, runId, options.environment);
|
|
4800
|
-
const delta = store.
|
|
4877
|
+
const delta = store.readTransaction((tx) => (buildRunContextDelta(tx, taskId, runId, parsed.values.get("--after"))));
|
|
4801
4878
|
const data = boundedDocument(delta, `run:${taskId}/${runId}/delta/${parsed.values.get("--after")}`, parsed.cursor);
|
|
4802
4879
|
return output(`${JSON.stringify(data)}\n`, { contextDelta: data });
|
|
4803
4880
|
}
|
|
@@ -4807,7 +4884,7 @@ function runContextCommand(args, store, options) {
|
|
|
4807
4884
|
}
|
|
4808
4885
|
const { taskId, runId } = parseRunContextReference(first);
|
|
4809
4886
|
authorizeRunContext(store, taskId, runId, options.environment);
|
|
4810
|
-
const pack = store.
|
|
4887
|
+
const pack = store.readTransaction((tx) => buildRunContextPack(tx, taskId, runId));
|
|
4811
4888
|
const view = parsed.values.get("--view") ?? "current";
|
|
4812
4889
|
if (!["current", "full", "refs", "input"].includes(view))
|
|
4813
4890
|
throw usageError("Run Context view must be current, refs, input or full.");
|
|
@@ -4823,30 +4900,14 @@ function parseRunContextReference(value) {
|
|
|
4823
4900
|
}
|
|
4824
4901
|
return { taskId, runId };
|
|
4825
4902
|
}
|
|
4826
|
-
/**
|
|
4827
|
-
*
|
|
4828
|
-
* work. Authorization is therefore scope-shaped, not schedule-shaped: the
|
|
4829
|
-
* caller must be the current runtime of the Task Role that owns the AgentRun,
|
|
4830
|
-
* proven by its per-Session caller key against durable state.
|
|
4831
|
-
*
|
|
4832
|
-
* It deliberately does not require the AgentRun to still be the active one. An
|
|
4833
|
-
* Agent whose AgentRun has advanced must still be able to read the context it was
|
|
4834
|
-
* given; losing read access to its own Role's history is what forces an
|
|
4835
|
-
* otherwise healthy Agent to stop and escalate to a human.
|
|
4836
|
-
*/
|
|
4903
|
+
/** Frozen packs are readable evidence. Their execution authority still belongs
|
|
4904
|
+
* exclusively to the dispatched Run; reading does not adopt that identity. */
|
|
4837
4905
|
function authorizeRunContext(store, taskId, runId, environment) {
|
|
4838
|
-
|
|
4839
|
-
|| environment?.YUI_TASK_ID !== undefined
|
|
4840
|
-
|| environment?.YUI_ROLE !== undefined;
|
|
4841
|
-
if (!managed)
|
|
4842
|
-
return;
|
|
4906
|
+
resolveContextReader(store, environment ?? {});
|
|
4843
4907
|
const run = store.getRun(taskId, runId);
|
|
4844
4908
|
if (run === null) {
|
|
4845
4909
|
throw usageError(`AgentRun Context access is not authorized: ${taskId}/${runId}.`);
|
|
4846
4910
|
}
|
|
4847
|
-
if (currentManagedRuntime(store, environment, taskId, run.roleName) === undefined) {
|
|
4848
|
-
throw usageError(`AgentRun Context access requires the current runtime of ${taskId}/${run.roleName}.`);
|
|
4849
|
-
}
|
|
4850
4911
|
}
|
|
4851
4912
|
function listRuns(args, store, options) {
|
|
4852
4913
|
const reference = args[0];
|
|
@@ -4955,7 +5016,8 @@ function retryRun(args, store, options) {
|
|
|
4955
5016
|
const sessions = tx.getTaskRoleSessionSet(previous.taskId, previous.roleName);
|
|
4956
5017
|
const retry = options.providerRetryChainId !== undefined ? sessions?.providerBinding?.retry
|
|
4957
5018
|
: sessions?.providerBinding == null ? undefined
|
|
4958
|
-
: providerRunRetry(sessions.providerBinding, previous.id, clock(options).getTime())
|
|
5019
|
+
: providerRunRetry(sessions.providerBinding, previous.id, clock(options).getTime())
|
|
5020
|
+
?? taskRunRecovery(tx, sessions.providerBinding, previous);
|
|
4959
5021
|
if (options.providerRetryChainId !== undefined
|
|
4960
5022
|
&& (retry?.chainId !== options.providerRetryChainId || retry.status !== "waiting"
|
|
4961
5023
|
|| retry.previousRunId !== previous.id || clock(options).getTime() < Date.parse(retry.nextEligibleAt)
|
|
@@ -5789,17 +5851,49 @@ function retryFailedReviewRun(previous, store, options, now) {
|
|
|
5789
5851
|
}
|
|
5790
5852
|
/** AgentRun details are retained audit evidence; continuation uses durable Task state. */
|
|
5791
5853
|
function showRun(args, store, options) {
|
|
5792
|
-
const usage = "Task run show usage: yui task run show <task>/<run> [--json].";
|
|
5793
|
-
const parsed = readOptions(args.filter((arg) => arg !== "--json"), ["--cursor"]);
|
|
5854
|
+
const usage = "Task run show usage: yui task run show <task>/<run> [--view full|status|result] [--cursor <cursor>] [--json].";
|
|
5855
|
+
const parsed = readOptions(args.filter((arg) => arg !== "--json"), ["--cursor", "--view"]);
|
|
5856
|
+
const view = parsed.values.get("--view") ?? "full";
|
|
5857
|
+
if (!["full", "status", "result"].includes(view))
|
|
5858
|
+
throw usageError(usage);
|
|
5794
5859
|
const positionals = parsed.positionals;
|
|
5795
5860
|
exactPositionals(positionals, 1, usage);
|
|
5796
|
-
const data = store.
|
|
5861
|
+
const data = store.readTransaction((tx) => {
|
|
5797
5862
|
const run = requireRun(tx, positionals[0], options);
|
|
5798
|
-
const
|
|
5863
|
+
const events = tx.listEventsByType(run.taskId, [TASK_RECORD_RETIRED_EVENT, "runtime.agent-error"]);
|
|
5864
|
+
const retirement = events
|
|
5799
5865
|
.map(taskRecordRetirement)
|
|
5800
5866
|
.find((entry) => entry?.recordKind === "run" && entry.recordId === run.id) ?? null;
|
|
5801
|
-
|
|
5867
|
+
const binding = tx.getTaskRoleSessionSet(run.taskId, run.roleName)?.providerBinding;
|
|
5868
|
+
const execution = runExecutionObservation(run, binding, events);
|
|
5869
|
+
return { run, retirement, execution: view === "full" ? execution : {
|
|
5870
|
+
...execution, retry: execution.retry === null ? null : providerRetrySummary(binding, `yui task role session retry ${run.taskId} ${run.roleName} show --json`)
|
|
5871
|
+
} };
|
|
5802
5872
|
});
|
|
5873
|
+
if (view !== "full") {
|
|
5874
|
+
const { run } = data;
|
|
5875
|
+
const status = {
|
|
5876
|
+
run: {
|
|
5877
|
+
id: run.id, taskId: run.taskId, roleName: run.roleName,
|
|
5878
|
+
purpose: run.purpose, mode: run.mode, status: run.status,
|
|
5879
|
+
workItemId: run.workItemId, reviewRoundId: run.reviewRoundId,
|
|
5880
|
+
createdAt: run.createdAt, updatedAt: run.updatedAt
|
|
5881
|
+
},
|
|
5882
|
+
retirement: data.retirement,
|
|
5883
|
+
execution: data.execution,
|
|
5884
|
+
result: view === "result" ? run.result ?? null : {
|
|
5885
|
+
available: run.result?.output !== undefined,
|
|
5886
|
+
bytes: run.result?.output === undefined ? 0 : Buffer.byteLength(run.result.output),
|
|
5887
|
+
completedAt: run.result?.completedAt,
|
|
5888
|
+
failureReason: run.result?.failureReason,
|
|
5889
|
+
diagnostic: run.result?.diagnostic,
|
|
5890
|
+
read: `yui task run show ${run.taskId}/${run.id} --view result --json`
|
|
5891
|
+
},
|
|
5892
|
+
reads: { full: `yui task run show ${run.taskId}/${run.id} --view full --json` }
|
|
5893
|
+
};
|
|
5894
|
+
const bounded = boundedDocument(status, `run:${run.taskId}/${run.id}:${view}`, parsed.cursor);
|
|
5895
|
+
return output(`${JSON.stringify(bounded, null, 2)}\n`, bounded);
|
|
5896
|
+
}
|
|
5803
5897
|
const bounded = boundedDocument(data, `run:${data.run.taskId}/${data.run.id}`, parsed.cursor);
|
|
5804
5898
|
if ("contentPage" in bounded)
|
|
5805
5899
|
return output(`${JSON.stringify(bounded, null, 2)}\n`, bounded);
|
|
@@ -6941,31 +7035,45 @@ function taskWakeDispatch(args, store, options) {
|
|
|
6941
7035
|
const target = leaderMailbox(task.id);
|
|
6942
7036
|
const mailbox = tx.getWorkMailbox(target);
|
|
6943
7037
|
const claim = mailbox?.processing;
|
|
6944
|
-
|
|
6945
|
-
|
|
7038
|
+
const ownsClaim = claim?.owner === `leader-notification:${wake.id}`;
|
|
7039
|
+
const events = tx.listEvents(task.id);
|
|
7040
|
+
const resolved = events.find(event => event.type === "notification.resolved"
|
|
7041
|
+
&& event.payload.wakeId === wake.id && event.payload.outcome === "released-without-replay");
|
|
7042
|
+
if (resolved !== undefined) {
|
|
7043
|
+
return { taskId: task.id, wakeId: wake.id, outcome: "released-without-replay" };
|
|
7044
|
+
}
|
|
7045
|
+
if (wake.status === "consumed")
|
|
7046
|
+
throw usageError("An accepted notification uses ordinary inbox handling.");
|
|
7047
|
+
// Operational mailboxes may disappear on execution stop. Resolve only
|
|
7048
|
+
// the original durable delivery attempt, using the same exact wake
|
|
7049
|
+
// identity as wake inspection; missing evidence is not an unknown result.
|
|
7050
|
+
const previous = events.filter(event => event.type === "notification.delivery"
|
|
7051
|
+
&& (ownsClaim ? event.payload.attemptId === claim.batchId
|
|
7052
|
+
: event.payload.attemptId?.startsWith(`notification:${task.id}/${wake.id}/`))).at(-1);
|
|
7053
|
+
if (previous?.payload.outcome !== "unknown" && previous?.payload.outcome !== "rejected") {
|
|
7054
|
+
throw usageError("Only an unknown or rejected notification can be resolved without replay.");
|
|
6946
7055
|
}
|
|
6947
|
-
const previous = tx.listEvents(task.id).filter((event) => event.type === "notification.delivery" && event.payload.attemptId === claim.batchId).at(-1);
|
|
6948
7056
|
const sessions = tx.getTaskRoleSessionSet(task.id, "leader");
|
|
6949
7057
|
const provider = sessions?.providerBinding;
|
|
6950
|
-
if (previous?.payload.outcome !== "unknown")
|
|
6951
|
-
throw usageError("Only an unknown notification can be resolved.");
|
|
6952
7058
|
if (tx.getActiveRun(task.id, "leader") !== null
|
|
6953
7059
|
|| provider?.authority.owner === "human" || provider?.authority.owner === "unknown"
|
|
6954
7060
|
|| (provider?.run !== undefined && provider.run !== null
|
|
6955
7061
|
&& ["submitting", "accepted", "delivery-unknown"].includes(provider.run.status))) {
|
|
6956
7062
|
throw usageError("Shared native execution is not proven quiescent; resolve that exact runtime boundary first.");
|
|
6957
7063
|
}
|
|
6958
|
-
//
|
|
7064
|
+
// Rejection is not quiescence. Preserve every original delivery outcome
|
|
7065
|
+
// (including unknown followed by rejected) and the unconsumed fixed wake.
|
|
6959
7066
|
// This releases only the scheduling claim; it never replays, claims
|
|
6960
7067
|
// acceptance, or asserts that Message requirements were implemented.
|
|
6961
7068
|
recordTaskEvent(tx, task.id, "notification.resolved", {
|
|
6962
|
-
wakeId: wake.id, attemptId:
|
|
7069
|
+
wakeId: wake.id, attemptId: previous.payload.attemptId, reason, outcome: "released-without-replay"
|
|
6963
7070
|
}, now);
|
|
6964
|
-
|
|
7071
|
+
if (ownsClaim)
|
|
7072
|
+
tx.saveWorkMailbox(completeProcessing(mailbox, claim.batchId));
|
|
6965
7073
|
return { taskId: task.id, wakeId: wake.id, outcome: "released-without-replay" };
|
|
6966
7074
|
});
|
|
6967
7075
|
notifyMailbox(options.runtime, leaderMailbox(result.taskId));
|
|
6968
|
-
return output(`Released ${result.wakeId} without replay; original
|
|
7076
|
+
return output(`Released ${result.wakeId} without replay; original delivery evidence is unchanged.\n`, result);
|
|
6969
7077
|
}
|
|
6970
7078
|
if (subcommand === "list" || subcommand === "show") {
|
|
6971
7079
|
return taskWakeInspectionCommand(args, store);
|
|
@@ -6980,7 +7088,7 @@ function taskWakeDispatch(args, store, options) {
|
|
|
6980
7088
|
* wake — the on-demand read the Agent uses instead of a context dump in the
|
|
6981
7089
|
* wake envelope.
|
|
6982
7090
|
*/
|
|
6983
|
-
function taskWakeInspectionCommand(args, store) {
|
|
7091
|
+
export function taskWakeInspectionCommand(args, store) {
|
|
6984
7092
|
const [command, ...rest] = args;
|
|
6985
7093
|
if (command === "list") {
|
|
6986
7094
|
const usage = "Task wake list usage: yui task wake list <task> [--limit <n>] [--cursor <cursor>].";
|
|
@@ -7043,6 +7151,26 @@ function taskWakeInspectionCommand(args, store) {
|
|
|
7043
7151
|
if (message.resultRef?.type === "agent-run-result")
|
|
7044
7152
|
referencedRunIds.add(message.resultRef.runId);
|
|
7045
7153
|
const runs = operationalTaskRecords(allRuns, allEvents, "run").filter((run) => (history && inWindow(run.createdAt) || referencedRunIds.has(run.id)));
|
|
7154
|
+
// The focused read is an action working set, not merely another directory.
|
|
7155
|
+
// Include small ordinary originals whole, with their current exact identity.
|
|
7156
|
+
// Reports still require their terminal-result read; a completion notice is
|
|
7157
|
+
// not the original report. Do not amplify diagnostic history into bodies.
|
|
7158
|
+
let originalBytesRemaining = 8 * 1024;
|
|
7159
|
+
const messageDetails = messages.map(message => {
|
|
7160
|
+
const original = materialize("task-message", message.id, message);
|
|
7161
|
+
const bytes = Buffer.byteLength(JSON.stringify(message));
|
|
7162
|
+
const include = !history && message.resultRef === undefined
|
|
7163
|
+
&& bytes <= 4 * 1024 && bytes <= originalBytesRemaining;
|
|
7164
|
+
if (include)
|
|
7165
|
+
originalBytesRemaining -= bytes;
|
|
7166
|
+
return { id: message.id, kind: message.kind, author: message.author,
|
|
7167
|
+
...taskMessagePresentation(message, (taskId, runId) => store.getRun(taskId, runId)),
|
|
7168
|
+
resultRef: message.resultRef,
|
|
7169
|
+
...(include ? { refreshRead: `task message show ${task.id}/${message.id}` }
|
|
7170
|
+
: { read: `task message show ${task.id}/${message.id}` }),
|
|
7171
|
+
ref: original.ref, contentOmitted: !include,
|
|
7172
|
+
...(include ? { value: original.value } : {}) };
|
|
7173
|
+
});
|
|
7046
7174
|
const lines = [
|
|
7047
7175
|
`Wake: ${wake.id}`,
|
|
7048
7176
|
`Task: ${task.id}`,
|
|
@@ -7090,9 +7218,7 @@ function taskWakeInspectionCommand(args, store) {
|
|
|
7090
7218
|
historyRead: `task wake show ${task.id} ${wake.id} --history`,
|
|
7091
7219
|
events: events.map(event => ({ id: event.id, type: event.type, createdAt: event.createdAt,
|
|
7092
7220
|
read: `task event show ${task.id} ${event.id}` })),
|
|
7093
|
-
messages:
|
|
7094
|
-
...taskMessagePresentation(message, (taskId, runId) => store.getRun(taskId, runId)),
|
|
7095
|
-
resultRef: message.resultRef, read: `task message show ${task.id}/${message.id}` })),
|
|
7221
|
+
messages: messageDetails,
|
|
7096
7222
|
runs: runs.map(run => ({ id: run.id, status: run.status, purpose: run.purpose, roleName: run.roleName,
|
|
7097
7223
|
read: `task run show ${task.id}/${run.id}` }))
|
|
7098
7224
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { usageError } from "../errors/cliError.js";
|
|
2
|
-
import { inspectTaskContext, listTaskContext, readTaskContext, readTaskContextDelta } from "../context/taskContext.js";
|
|
2
|
+
import { inspectTaskContext, inspectTaskContextBatch, listTaskContext, parseExactContextRef, readTaskContext, readTaskContextDelta } from "../context/taskContext.js";
|
|
3
3
|
import { readOptions } from "../output/boundedRead.js";
|
|
4
4
|
export function taskRecordList(args, store, family, environment = {}) {
|
|
5
5
|
const parsed = readOptions(args, ["--cursor", "--limit", "--status", "--after", "--work-item"]);
|
|
@@ -17,19 +17,23 @@ export function runTaskContextCommand(args, store, environment = {}) {
|
|
|
17
17
|
const action = explicit ? args[0] : "read";
|
|
18
18
|
const taskId = args[explicit ? 1 : 0];
|
|
19
19
|
if (!taskId || taskId.startsWith("--"))
|
|
20
|
-
throw usageError("Task context usage: yui task context [read|list|delta|inspect] <task> [--after <cursor|timestamp>] [--continuation <cursor>] [--cursor <cursor>] [--limit <1..100>] [--store <store> --ref <id> --digest <digest>] [--view <current|all>] [--status <status>] [--work-item <id>].");
|
|
20
|
+
throw usageError("Task context usage: yui task context [read|list|delta|inspect] <task> [--after <cursor|timestamp>] [--continuation <cursor>] [--cursor <cursor>] [--limit <1..100>] [--store <store> --ref <id> --digest <digest> | --refs <JSON-array> | --context-ref <store/refId@digest> ...] [--view <current|all>] [--status <status>] [--work-item <id>].");
|
|
21
21
|
const options = new Map();
|
|
22
|
+
const contextRefs = [];
|
|
22
23
|
const rest = args.slice(explicit ? 2 : 1);
|
|
23
24
|
const allowed = action === "read" ? [] : action === "delta"
|
|
24
25
|
? ["--after", "--continuation", "--limit"] : action === "list"
|
|
25
|
-
? ["--store", "--cursor", "--limit", "--status", "--after", "--work-item", "--view"] : ["--store", "--ref", "--digest", "--cursor"];
|
|
26
|
+
? ["--store", "--cursor", "--limit", "--status", "--after", "--work-item", "--view"] : ["--store", "--ref", "--digest", "--refs", "--context-ref", "--cursor"];
|
|
26
27
|
for (let i = 0; i < rest.length; i += 2) {
|
|
27
28
|
const flag = rest[i];
|
|
28
29
|
const value = rest[i + 1];
|
|
29
30
|
if (!allowed.includes(flag) || options.has(flag) || value === undefined || value.startsWith("--")) {
|
|
30
31
|
throw usageError(`Invalid Context option: ${flag}.`);
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
+
if (flag === "--context-ref")
|
|
34
|
+
contextRefs.push(value);
|
|
35
|
+
else
|
|
36
|
+
options.set(flag, value);
|
|
33
37
|
}
|
|
34
38
|
let data;
|
|
35
39
|
if (action === "read")
|
|
@@ -54,6 +58,24 @@ export function runTaskContextCommand(args, store, environment = {}) {
|
|
|
54
58
|
...(options.has("--limit") ? { limit: Number(options.get("--limit")) } : {})
|
|
55
59
|
}, environment);
|
|
56
60
|
}
|
|
61
|
+
else if (options.has("--refs") || contextRefs.length > 0) {
|
|
62
|
+
if (["--store", "--ref", "--digest"].some(flag => options.has(flag)))
|
|
63
|
+
throw usageError("Do not combine batch references with --store, --ref or --digest.");
|
|
64
|
+
if (options.has("--refs") && contextRefs.length > 0)
|
|
65
|
+
throw usageError("Do not combine --refs with --context-ref.");
|
|
66
|
+
let refs;
|
|
67
|
+
if (contextRefs.length > 0)
|
|
68
|
+
refs = contextRefs.map(parseExactContextRef);
|
|
69
|
+
else {
|
|
70
|
+
try {
|
|
71
|
+
refs = JSON.parse(options.get("--refs"));
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
throw usageError("--refs must be a JSON array of exact Context references.");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
data = inspectTaskContextBatch(store, taskId, refs, options.get("--cursor"), environment);
|
|
78
|
+
}
|
|
57
79
|
else {
|
|
58
80
|
const family = options.get("--store");
|
|
59
81
|
const refId = options.get("--ref");
|