@zq-silk/yui 2.21.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 +85 -25
- package/dist/cli/dynamicCompletion.js +4 -1
- package/dist/cli/helpRenderer.js +12 -1
- package/dist/cli/interactionPolicy.js +2 -0
- package/dist/cli/invocationRouter.js +5 -5
- package/dist/cli/roleWizard.js +5 -1
- 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 +217 -64
- package/dist/commands/taskContextCommand.js +26 -4
- package/dist/commands/taskFactCommands.js +15 -2
- package/dist/commands/taskIntegrationCommands.js +3 -3
- package/dist/commands/taskRoleRuntimeStatus.js +15 -5
- 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/taskContext.js +100 -16
- package/dist/controlPlaneCli.js +17 -7
- 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/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/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/tmux/tmuxManager.js +4 -2
- package/dist/web/webSettings.js +2 -0
- package/docs/authorization.md +18 -3
- package/docs/cli-information-contract.md +228 -6
- package/docs/cli-information-contract.zh-CN.md +95 -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 +37 -0
- package/docs/release-workflow.zh-CN.md +28 -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/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 -193
- 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 -333
- 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 +1 -1
- package/skills/yui-operator/references/web-lifecycle.md +19 -0
- package/skills/yui-operator/scripts/verify-submission.mjs +37 -0
- package/skills/yui-runtime/SKILL.md +177 -531
- 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 -111
- 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
|
@@ -31,7 +31,7 @@ export async function startStructuredProviderSession(payload, input = {}) {
|
|
|
31
31
|
if (control.adapterId === "codex" && control.transport === "codex-app-server-proxy") {
|
|
32
32
|
const proxy = await connectCodexProxy(payload, mirror, true);
|
|
33
33
|
try {
|
|
34
|
-
const opened = await CodexStructuredProviderSession.open(proxy.child, proxy.exit, proxy.processInstanceId, payload, control, proxy.channel, input.onStarted, input.onTerminal, input.onGoal, input.onInput, input.onActivity,
|
|
34
|
+
const opened = await CodexStructuredProviderSession.open(proxy.child, proxy.exit, proxy.processInstanceId, payload, control, proxy.channel, input.onStarted, input.onTerminal, input.onGoal, input.onInput, input.onActivity, mirror);
|
|
35
35
|
return Object.freeze({
|
|
36
36
|
session: opened.session,
|
|
37
37
|
...(opened.recoveredTerminal === undefined
|
|
@@ -238,7 +238,10 @@ class CodexProxyWebSocketChannel {
|
|
|
238
238
|
this.#pending.delete(id);
|
|
239
239
|
reject(new Error(`Provider request timed out: ${method}.`));
|
|
240
240
|
}, PROVIDER_ACCEPT_TIMEOUT_MS);
|
|
241
|
-
this.#pending.set(id, {
|
|
241
|
+
this.#pending.set(id, {
|
|
242
|
+
resolve: resolvePromise, reject, timer, method,
|
|
243
|
+
requestBytes: Buffer.byteLength(JSON.stringify({ id, method, params }), "utf8")
|
|
244
|
+
});
|
|
242
245
|
});
|
|
243
246
|
try {
|
|
244
247
|
await this.send({ id, method, params });
|
|
@@ -282,7 +285,7 @@ class CodexProxyWebSocketChannel {
|
|
|
282
285
|
if (isBinary || encoded.byteLength > PROVIDER_MESSAGE_MAX_BYTES) {
|
|
283
286
|
this.#close(new Error(isBinary
|
|
284
287
|
? "Provider returned an unsupported binary WebSocket message."
|
|
285
|
-
:
|
|
288
|
+
: `Provider response message exceeds its bound (receivedBytes=${encoded.byteLength}).`));
|
|
286
289
|
terminateProcessGroup(this.child, "SIGTERM");
|
|
287
290
|
return;
|
|
288
291
|
}
|
|
@@ -320,6 +323,15 @@ class CodexProxyWebSocketChannel {
|
|
|
320
323
|
#close(error) {
|
|
321
324
|
if (this.#closedError !== undefined)
|
|
322
325
|
return;
|
|
326
|
+
// A rejected WebSocket frame has not reached #receive: its full size and
|
|
327
|
+
// response/notification identity are unknown. Record pending request
|
|
328
|
+
// metadata, not parameters or transcript bytes, and never blame a specific
|
|
329
|
+
// response just because that request was in flight.
|
|
330
|
+
const pendingMetadata = [...this.#pending].slice(0, 8).map(([id, pending]) => ({
|
|
331
|
+
id, method: pending.method, requestBytes: pending.requestBytes
|
|
332
|
+
}));
|
|
333
|
+
error = new Error(`Codex proxy transport closed: ${error.message}; messageLimitBytes=${PROVIDER_MESSAGE_MAX_BYTES}; `
|
|
334
|
+
+ `pendingRequests=${JSON.stringify(pendingMetadata)}; pendingCount=${this.#pending.size}.`, { cause: error });
|
|
323
335
|
this.#closedError = error;
|
|
324
336
|
if (!this.#ready)
|
|
325
337
|
this.#rejectReady(error);
|
|
@@ -410,7 +422,7 @@ class CodexStructuredProviderSession {
|
|
|
410
422
|
this.mirror = mirror;
|
|
411
423
|
this.nativeAccountHome = nativeAccountHome;
|
|
412
424
|
}
|
|
413
|
-
static async open(child, exit, processInstanceId, payload, control, channel, onStarted, onTerminal, onGoal, onInput, onActivity,
|
|
425
|
+
static async open(child, exit, processInstanceId, payload, control, channel, onStarted, onTerminal, onGoal, onInput, onActivity, mirror) {
|
|
414
426
|
const openingMessages = [];
|
|
415
427
|
const stopOpeningBuffer = channel.onMessage((message) => openingMessages.push(message));
|
|
416
428
|
const initialized = await channel.request("initialize", codexClientInitialization());
|
|
@@ -419,7 +431,6 @@ class CodexStructuredProviderSession {
|
|
|
419
431
|
let conversationId;
|
|
420
432
|
let nativeConfiguration;
|
|
421
433
|
let resumedActiveTurnId;
|
|
422
|
-
let resumedTurns = [];
|
|
423
434
|
if (control.mode === "new") {
|
|
424
435
|
const opened = await runtime.openConversation({
|
|
425
436
|
cwd: payload.cwd,
|
|
@@ -437,7 +448,6 @@ class CodexStructuredProviderSession {
|
|
|
437
448
|
conversationId = resumed.threadId;
|
|
438
449
|
nativeConfiguration = resumed.raw;
|
|
439
450
|
resumedActiveTurnId = resumed.activeTurnId;
|
|
440
|
-
resumedTurns = resumed.turns;
|
|
441
451
|
}
|
|
442
452
|
catch (error) {
|
|
443
453
|
if (codexAppServerErrorIsMissing(error)) {
|
|
@@ -446,37 +456,25 @@ class CodexStructuredProviderSession {
|
|
|
446
456
|
throw error;
|
|
447
457
|
}
|
|
448
458
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
await runtime.setConversationName({
|
|
459
|
-
conversationId,
|
|
460
|
-
name: control.sessionTitle
|
|
461
|
-
});
|
|
462
|
-
appliedGeneratedTitle = control.sessionTitle;
|
|
463
|
-
}
|
|
464
|
-
catch (error) {
|
|
465
|
-
onDiagnostic?.({
|
|
466
|
-
nativeSessionId: conversationId,
|
|
467
|
-
failure: providerDeliveryFailureFrom(error, {
|
|
468
|
-
phase: "session-start",
|
|
469
|
-
inputDisposition: "not-accepted",
|
|
470
|
-
sessionDisposition: "recoverable"
|
|
471
|
-
})
|
|
472
|
-
});
|
|
473
|
-
}
|
|
459
|
+
if (control.sessionTitle !== undefined) {
|
|
460
|
+
// The native title mutation can persist without replying and stall later
|
|
461
|
+
// Goal/Turn requests, even through a separate metadata connection. Keep
|
|
462
|
+
// Yui's launch title, but do not put that optional mutation on a managed
|
|
463
|
+
// Session's execution path. Reconnect must not replay it either.
|
|
464
|
+
// This is an intentional omission, not a failed delivery or unavailable
|
|
465
|
+
// observer. Keep it in the Host log without waking an Agent to recover
|
|
466
|
+
// an operation that was never attempted.
|
|
467
|
+
mirror("stderr", "Native title synchronization was not submitted; Yui retains its Session title without blocking native Goal/Turn control.\n");
|
|
474
468
|
}
|
|
469
|
+
const ownedTurn = control.kind === "restore" ? control.ownedTurn : undefined;
|
|
470
|
+
// Keep notifications buffered during paginated recovery. Otherwise a live
|
|
471
|
+
// terminal can be emitted before open returns and then returned again as a
|
|
472
|
+
// synthetic recovered terminal, or a newer start can be overwritten.
|
|
473
|
+
const recoveredOwnedTurn = ownedTurn !== undefined && resumedActiveTurnId !== ownedTurn.turnId
|
|
474
|
+
? await runtime.readTurn(conversationId, ownedTurn.turnId) : undefined;
|
|
475
475
|
const session = new CodexStructuredProviderSession(child, exit, processInstanceId, conversationId, runtime, onStarted, onTerminal, onGoal, onInput, onActivity, mirror, optionalId(initialized.codexHome));
|
|
476
476
|
session.nativeAccess = createCodexNativeAccess(conversationId, initialized, channel, openingMessages, nativeConfiguration);
|
|
477
|
-
session.appliedGeneratedTitle = appliedGeneratedTitle;
|
|
478
477
|
session.#activeTurnId = resumedActiveTurnId;
|
|
479
|
-
const ownedTurn = control.kind === "restore" ? control.ownedTurn : undefined;
|
|
480
478
|
session.#clientOwnedTurnId = ownedTurn?.turnId;
|
|
481
479
|
session.#clientOwnedAttemptId = ownedTurn?.attemptId;
|
|
482
480
|
if (ownedTurn !== undefined)
|
|
@@ -493,7 +491,7 @@ class CodexStructuredProviderSession {
|
|
|
493
491
|
});
|
|
494
492
|
if (ownedTurn !== undefined && recoveredTerminal === undefined
|
|
495
493
|
&& session.#activeTurnId !== ownedTurn.turnId) {
|
|
496
|
-
const recovered =
|
|
494
|
+
const recovered = recoveredOwnedTurn;
|
|
497
495
|
if (recovered?.status === "completed"
|
|
498
496
|
|| recovered?.status === "interrupted"
|
|
499
497
|
|| recovered?.status === "failed") {
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { enqueueWork } from "../coordination/workMailboxQueue.js";
|
|
2
2
|
/** The caller's TaskStore transaction owns this read/merge/write operation. */
|
|
3
3
|
export function queueLeaderWakeup(store, taskId, reason, now) {
|
|
4
4
|
if (store.getTask(taskId)?.status === "archived")
|
|
5
5
|
return null;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
// The scheduler's pending-wakeup projection may expose an already-owned
|
|
7
|
+
// processing prefix. Append to the actual suffix, never write that read
|
|
8
|
+
// projection back over independent inputs.
|
|
9
|
+
const pending = enqueueWork(store, { kind: "role", taskId, roleName: "leader" }, reason, now).pending;
|
|
10
|
+
return {
|
|
11
|
+
schemaVersion: 1, taskId, reasons: [...pending.reasons],
|
|
12
|
+
requestCount: pending.requestCount,
|
|
13
|
+
firstRequestedAt: pending.firstQueuedAt, lastRequestedAt: pending.lastQueuedAt
|
|
14
|
+
};
|
|
9
15
|
}
|
|
@@ -286,6 +286,15 @@ const MINOR_UPGRADES = Object.freeze([{
|
|
|
286
286
|
// Optional Role presentation and generated-title provenance. Never infer
|
|
287
287
|
// ownership of historical titles, rewrite frozen profiles, or fill defaults.
|
|
288
288
|
sql: ""
|
|
289
|
+
}, {
|
|
290
|
+
fromVersion: "1.25",
|
|
291
|
+
toVersion: "1.26",
|
|
292
|
+
name: "codex-workspace-temp-exclusions",
|
|
293
|
+
introducedIn: "next",
|
|
294
|
+
sourceChecksum: CURRENT_SCHEMA_CHECKSUM,
|
|
295
|
+
targetChecksum: CURRENT_SCHEMA_CHECKSUM,
|
|
296
|
+
// Optional workspace-write permission fields; preserve all existing payloads.
|
|
297
|
+
sql: ""
|
|
289
298
|
}]);
|
|
290
299
|
export function storageMinorUpgradePlan(from) {
|
|
291
300
|
if (from === CURRENT_STORAGE_VERSION)
|
package/dist/tmux/tmuxManager.js
CHANGED
|
@@ -62,7 +62,9 @@ export class TmuxManager {
|
|
|
62
62
|
this.#yuiHome = options.yuiHome ?? process.env.YUI_HOME ?? process.cwd();
|
|
63
63
|
this.#serverName = yuiTmuxServerName(this.#yuiHome);
|
|
64
64
|
this.#onRoleTargetRecorded = options.onRoleTargetRecorded;
|
|
65
|
-
|
|
65
|
+
// Creating Node's stdin stream can make piped fd 0 nonblocking. Commands
|
|
66
|
+
// may still need to read that pipe synchronously before any attach.
|
|
67
|
+
this.#terminalInput = options.terminalInput;
|
|
66
68
|
this.#terminalType = usableInteractiveTerminal(options.terminalType ?? process.env.TERM);
|
|
67
69
|
this.#closeInteractiveInput = options.closeInteractiveInput ?? (() => { });
|
|
68
70
|
this.#readinessTimeoutMs = positiveInteger(options.readinessTimeoutMs, DEFAULT_READINESS_TIMEOUT_MS, "readiness timeout");
|
|
@@ -228,7 +230,7 @@ export class TmuxManager {
|
|
|
228
230
|
}
|
|
229
231
|
if (resolvedAccess === "read-write")
|
|
230
232
|
options.revalidateWritableAttach?.();
|
|
231
|
-
handoffTerminal(this.#terminalInput, this.#closeInteractiveInput);
|
|
233
|
+
handoffTerminal(this.#terminalInput ?? process.stdin, this.#closeInteractiveInput);
|
|
232
234
|
this.run([
|
|
233
235
|
"attach-session",
|
|
234
236
|
...(resolvedAccess === "read-only" ? ["-r"] : []),
|
package/dist/web/webSettings.js
CHANGED
|
@@ -276,6 +276,8 @@ const ROLE_FIELDS = {
|
|
|
276
276
|
model: { set: "--model", clear: "--clear-model" }, effort: { set: "--effort", clear: "--clear-effort" },
|
|
277
277
|
"permission.strategy": { set: "--permission-strategy" }, "permission.sandbox": { set: "--sandbox" },
|
|
278
278
|
"permission.approval": { set: "--approval" }, "permission.mode": { set: "--permission-mode" },
|
|
279
|
+
"permission.excludeTmpdirEnvVar": { set: "--exclude-tmpdir-env-var", clear: "--clear-exclude-tmpdir-env-var" },
|
|
280
|
+
"permission.excludeSlashTmp": { set: "--exclude-slash-tmp", clear: "--clear-exclude-slash-tmp" },
|
|
279
281
|
"permission.allowedTools": { set: "--allowed-tool", clear: "--clear-allowed-tools", many: true },
|
|
280
282
|
"permission.disallowedTools": { set: "--disallowed-tool", clear: "--clear-disallowed-tools", many: true },
|
|
281
283
|
search: { set: "--search", clear: "--clear-search" },
|
package/docs/authorization.md
CHANGED
|
@@ -20,9 +20,24 @@ authorization for any external effect.
|
|
|
20
20
|
| May it access an additional resource or irreversible effect? | `CapabilityGrant`, `grant/taskAuthorization.ts`, resource/plugin/release consumers | Task activation does not authorize arbitrary resources |
|
|
21
21
|
|
|
22
22
|
The full command inventory is generated from the catalog, not maintained as a
|
|
23
|
-
second per-command permissions table
|
|
24
|
-
`yui --json help task
|
|
25
|
-
|
|
23
|
+
second per-command permissions table. `yui --json help` and scoped
|
|
24
|
+
`yui --json help task` return the selected command's full details and all its
|
|
25
|
+
immediate child **summaries**, not a recursively expanded tree. The `discovery`
|
|
26
|
+
field labels this boundary and gives the detail and full-tree commands. Follow
|
|
27
|
+
each child's `path` with `yui --json help <command ...>` for full usage, options,
|
|
28
|
+
values and examples, or use `yui --json help [command ...] --recursive` for the
|
|
29
|
+
complete caller-filtered tree in one call.
|
|
30
|
+
|
|
31
|
+
This changes the default JSON help shape: consumers that previously traversed
|
|
32
|
+
nested `children` must request `--recursive`; absence of child details in the
|
|
33
|
+
default view is not proof that the child has no options or descendants.
|
|
34
|
+
Focused leaf details are unchanged, with additive discovery metadata.
|
|
35
|
+
Text help still shows immediate children; `--recursive` requires `--json`.
|
|
36
|
+
`config describe --json` and the offline
|
|
37
|
+
`describeCommandTree(discoveryCommandTree(env))` API retain full recursive
|
|
38
|
+
descriptions. Native `yui agent` product help is a separate surface and unchanged.
|
|
39
|
+
|
|
40
|
+
Complete role hints retain an offline template even without
|
|
26
41
|
a running Home; that is not authentication. Native-ID-only callers are resolved
|
|
27
42
|
from read-only local storage for help/completion; if that read fails the CLI shows
|
|
28
43
|
the restricted `unbound` template. No Controller or provider is started for that
|
|
@@ -21,7 +21,7 @@ declared storage 1.10 → 1.11 transition; historical sources are never invented
|
|
|
21
21
|
| What changed? | `task context delta <task> --after <cursor>` | Immutable events with a fixed upper bound, not a snapshot of current mutable state |
|
|
22
22
|
| Which Global input? | `session context <role>` | Identity, Profile read pointer, authority, current native Turn/retry facts and a bounded pending Message page; history is opt-in |
|
|
23
23
|
| Read Global input | `role message list <role> [--pending]`, `role message show <role> <id>` | Scoped discovery, then exact original; queue acceptance never erases history |
|
|
24
|
-
| What arrived in this wake? | `task wake show <task> <wake>` | Fixed-window inputs/results,
|
|
24
|
+
| What arrived in this wake? | `task wake show <task> <wake>` | Fixed-window inputs/results, bounded complete ordinary inputs and exact original reads; `--history` expands diagnostics |
|
|
25
25
|
| What was assigned? | `task run context <task>/<run>` | Frozen authority, up to 16 `pointers`, sampled changed identities and live observations with totals; `--view refs` pages references, `--view full` reads the full pack |
|
|
26
26
|
| Which repeated failure? | `role message list <role> --diagnostics` | Derived classified groups with count, first/latest and recovery evidence; `--diagnostic <key>` pages original occurrences |
|
|
27
27
|
| Which configuration is real? | `task role session inspect <task> <role>` | Task/Role identity, desired binding, frozen Session, current Provider binding, retry and explicit Host observation; no full Task/Role copies or Provider conversation history |
|
|
@@ -32,11 +32,35 @@ Task Role-status and wake-history lists also page, with explicit detail commands
|
|
|
32
32
|
Role discovery reports `recordedHealth` and `hostObservation: "not-requested"`,
|
|
33
33
|
not live Host health. Even a normal recorded status cannot rule out a failed Host
|
|
34
34
|
or unacknowledged terminal; follow the row's `task role status` read to inspect it.
|
|
35
|
+
`task role status <task> <role>` defaults to `--view current`: the same computed
|
|
36
|
+
health, Host, delivery/retry, cleanup and drift observations, with Run/WorkItem
|
|
37
|
+
identities and exact detail commands instead of their input/report/history bodies.
|
|
38
|
+
Retry diagnostics remain available through the current retry read. Desired and
|
|
39
|
+
effective configuration remain visible; unknown evidence is not upgraded to success.
|
|
40
|
+
This changes the default nested JSON contract. Consumers needing the previous
|
|
41
|
+
complete records use `--view full` and retain that option on pagination.
|
|
42
|
+
The underlying runtime status projection and Web payload are unchanged.
|
|
35
43
|
Context lists additionally expose candidates, reviews, jobs, Project Knowledge,
|
|
36
44
|
workspaces and other authorized record families. `--status`, `--after` and
|
|
37
45
|
`--work-item` narrow Context discovery; every continuation must retain filters.
|
|
38
46
|
Run listing accepts a Task or `task/work` target.
|
|
39
47
|
|
|
48
|
+
`task run show <task>/<run> --view status` reads identity, record status,
|
|
49
|
+
delivery/retry observations, retirement and result availability without copying
|
|
50
|
+
input, launch or report bodies. It uses the same authorization as the default
|
|
51
|
+
`--view full`, which retains complete audit evidence and document pagination.
|
|
52
|
+
Its retry observation is the same current summary used in Task Context, with
|
|
53
|
+
an exact Session retry command for raw diagnostics and history, not their bodies.
|
|
54
|
+
`--view result` returns the complete original result (including failure/provider
|
|
55
|
+
fields), Run identity/status, retirement and execution observation without the
|
|
56
|
+
submitted input or launch configuration. An absent result is `null`, not success.
|
|
57
|
+
Long reports retain document pagination; continue with the same view. The full
|
|
58
|
+
audit command remains available in `reads.full`, and the default is still full.
|
|
59
|
+
Read the original result through its Message, result or full Run view before disposition;
|
|
60
|
+
status is neither a report nor acceptance. Once that exact original is available
|
|
61
|
+
in current context, use status for additional execution facts instead of loading
|
|
62
|
+
the report twice. No read receipt or model-memory cache is introduced.
|
|
63
|
+
|
|
40
64
|
Current Context's `attention.messages` excludes explicit acknowledgements and
|
|
41
65
|
retirements; delivery alone is not handling. The exact wake receipt and latest
|
|
42
66
|
Message revision determine coverage. `--view current` continues that view;
|
|
@@ -45,6 +69,28 @@ explicitly describe incomplete discovery. Samples are not proof that no older pe
|
|
|
45
69
|
relevant input exists. Read the relevant fixed wake and original Messages;
|
|
46
70
|
use family discovery when a broader requirement/history audit is needed.
|
|
47
71
|
|
|
72
|
+
Current Context is a working index, not a repeated configuration or requirements
|
|
73
|
+
dump. Task/Brief, Role, Project policy, workspace, delivery and decision records
|
|
74
|
+
return summaries and exact references even when their bodies are small. Lifecycle,
|
|
75
|
+
execution authority, attention counts and active execution/retry observations
|
|
76
|
+
remain inline. Read a relevant original through `context inspect` before acting
|
|
77
|
+
on its requirements or authority; `omitted: true` is not an empty original.
|
|
78
|
+
Fresh reads still compute current identities and enforce scope. There is no
|
|
79
|
+
model-memory cache, inferred handling receipt or automatic reuse of stale state.
|
|
80
|
+
Within the current workspace sample, the exact Run workspace overlay (when
|
|
81
|
+
authorized) precedes Task main, then other workspaces. Historical integration
|
|
82
|
+
directories cannot crowd Task main out of that sample. Full family discovery
|
|
83
|
+
retains its existing ordering, counts and original records; this priority neither
|
|
84
|
+
changes workspace authority nor grants access to another Assignment.
|
|
85
|
+
|
|
86
|
+
Message discovery can reuse an existing producer-authored `Yui-Summary:` from
|
|
87
|
+
the Message body or its matching terminal Run result. It labels the source as
|
|
88
|
+
an **author summary**, not a verified outcome or handling decision. The source
|
|
89
|
+
label counts toward the 512-byte summary budget; an otherwise valid summary
|
|
90
|
+
that no longer fits is omitted whole with an original-read hint, not clipped.
|
|
91
|
+
Missing, oversized or mismatched result summaries do not hide the Message or
|
|
92
|
+
change its exact original, digest, authorization or handling state.
|
|
93
|
+
|
|
48
94
|
## Budgets and continuations
|
|
49
95
|
|
|
50
96
|
- Discovery pages default to 20 items, accept 1–100, and enforce a 32 KiB
|
|
@@ -58,6 +104,11 @@ use family discovery when a broader requirement/history audit is needed.
|
|
|
58
104
|
uncertain ones. Historical missing receipts are a separate count and explicit
|
|
59
105
|
`inbox list --view history` read; absence of ACK is not proof of unexecuted work.
|
|
60
106
|
Continue its pending page with `role message list <role> --current --cursor`.
|
|
107
|
+
A managed self-read additionally includes `currentOriginals`: complete records
|
|
108
|
+
correlated to this exact Turn and present in that pending page, at most 4 KiB
|
|
109
|
+
each and 8 KiB combined. Available future inputs, history and oversized records
|
|
110
|
+
remain discovery-only; their exact reads are unchanged. Inspection callers get
|
|
111
|
+
no inline originals. This does not claim, deliver or acknowledge input.
|
|
61
112
|
It does not repeat recent history, Profile bodies, frozen Skill
|
|
62
113
|
packages or accumulated retry details. The Manifest is the Profile pointer;
|
|
63
114
|
explicit Message and Session retry reads retain history and original evidence.
|
|
@@ -75,14 +126,25 @@ use family discovery when a broader requirement/history audit is needed.
|
|
|
75
126
|
document continuation uses `--view full`. Neither changes the frozen authority.
|
|
76
127
|
Read `--view input` before acting when `input.directiveOmitted` is true: the
|
|
77
128
|
entry's bounded directive summary is not the assigned instruction body.
|
|
129
|
+
New frozen Task-message pointers include a literal `Excerpt:` preview in their
|
|
130
|
+
existing summary (at most 160 UTF-8 bytes), alongside the original revision
|
|
131
|
+
and digest. Use it to select relevant originals, not as their complete body or
|
|
132
|
+
authority. Later message edits cannot change that Run's frozen preview.
|
|
133
|
+
Existing snapshots are not regenerated.
|
|
134
|
+
When pointers are present, `reads.expand` exposes the existing selected-original
|
|
135
|
+
batch syntax directly. Replace the placeholders with relevant frozen pointers;
|
|
136
|
+
this is not a preselected read-all command. The existing 1–8 selection limit,
|
|
137
|
+
exact snapshot checks, complete original bodies and page budget are unchanged.
|
|
78
138
|
- `session skills [--cursor ...]` checks only current metadata/readability. It
|
|
79
139
|
does not read Skill bodies or historical packages, and uses document pagination
|
|
80
140
|
only when the configured metadata exceeds the inline budget.
|
|
81
141
|
- Detail documents up to 16 KiB remain ordinary JSON. Larger documents return
|
|
82
142
|
`contentPage`: exact source, SHA-256 digest, JSON-character offset, total bytes
|
|
83
|
-
and characters, text, completeness and a next cursor.
|
|
84
|
-
|
|
85
|
-
|
|
143
|
+
and characters, text, completeness and a next cursor. Chunk lengths adapt to
|
|
144
|
+
the complete encoded 32 KiB response budget, including identity and cursors,
|
|
145
|
+
with 256 bytes reserved for small command wrappers. Chunks never split
|
|
146
|
+
surrogate pairs; offsets remain UTF-16 units and previously issued cursors
|
|
147
|
+
remain readable. There is no 4 MiB cutoff that makes a legal original
|
|
86
148
|
permanently unreadable.
|
|
87
149
|
- Task metadata/next-action/remote-delivery, Brief, WorkItem, Message, Run,
|
|
88
150
|
decision/milestone/event, Role show/status/Session inspection, wake detail,
|
|
@@ -111,6 +173,93 @@ Use `--json` and read the top-level `data`. Run context and expansion use
|
|
|
111
173
|
the same source and digest, and parse the combined JSON once. Do not parse
|
|
112
174
|
chunks individually or treat a first chunk as the complete report.
|
|
113
175
|
|
|
176
|
+
### Copyable detail-reading example
|
|
177
|
+
|
|
178
|
+
For 1–8 already-known independent originals in the same Task, use
|
|
179
|
+
`task context inspect <task> --refs '<JSON array of discovery ref objects>'`.
|
|
180
|
+
For hand-written commands, repeated `--context-ref <store/refId@digest>` flags
|
|
181
|
+
avoid JSON quoting; they use the same exact-reference spelling as dispatch.
|
|
182
|
+
Do not combine the two selection formats or single-inspect selector flags.
|
|
183
|
+
Each object requires `store`, `refId`, and `digest`; optional `revision` is
|
|
184
|
+
discovery metadata, not a second freshness guard. The response contains
|
|
185
|
+
`{taskId, items}`, with each item identical to a single inspect result.
|
|
186
|
+
The entire batch shares the existing 32 KiB budget, not one budget per item.
|
|
187
|
+
Follow `contentPage` using the same ordered references and `--cursor`.
|
|
188
|
+
A stale, duplicate, unavailable or forbidden reference rejects the whole read.
|
|
189
|
+
Each original is independently digest-pinned; this does not create an atomic
|
|
190
|
+
cross-record snapshot, select sources, claim inputs, or grant broader access.
|
|
191
|
+
Use single inspect unchanged when only one original is needed.
|
|
192
|
+
|
|
193
|
+
For `task context inspect`, the following Node.js example consumes the outer
|
|
194
|
+
`data` envelope. Supply the authorized CLI path and exact discovery arguments;
|
|
195
|
+
keep the current Session environment. It only reads that record, does not claim
|
|
196
|
+
or acknowledge input, and does not prove that an Agent has read its contents.
|
|
197
|
+
Save as a local `.mjs` file and invoke
|
|
198
|
+
`node reader.mjs /absolute/path/to/yui task-1 task-message message-1 <digest>`.
|
|
199
|
+
The final stdout is the reconstructed record; capture it in your owned scratch
|
|
200
|
+
directory and read it in bounded portions if it exceeds the tool output limit.
|
|
201
|
+
Do not re-fetch earlier pages just to inspect metadata.
|
|
202
|
+
|
|
203
|
+
```js
|
|
204
|
+
import { spawnSync } from "node:child_process";
|
|
205
|
+
|
|
206
|
+
function readDocument(read) {
|
|
207
|
+
let cursor, source, digest, total, offset = 0;
|
|
208
|
+
const chunks = [];
|
|
209
|
+
for (;;) {
|
|
210
|
+
const data = read(cursor);
|
|
211
|
+
const page = data.contentPage;
|
|
212
|
+
if (!page) {
|
|
213
|
+
if (chunks.length) throw Error("Detail changed shape during pagination");
|
|
214
|
+
return data;
|
|
215
|
+
}
|
|
216
|
+
if (!chunks.length) {
|
|
217
|
+
({ source, digest, totalCharacters: total } = page);
|
|
218
|
+
}
|
|
219
|
+
if (page.source !== source || page.digest !== digest ||
|
|
220
|
+
page.totalCharacters !== total || page.offset !== offset ||
|
|
221
|
+
typeof page.text !== "string" || !page.text.length) {
|
|
222
|
+
throw Error(`Detail identity/offset mismatch at ${offset}`);
|
|
223
|
+
}
|
|
224
|
+
chunks.push(page.text);
|
|
225
|
+
offset += page.text.length; // UTF-16 units, not UTF-8 bytes.
|
|
226
|
+
if (page.complete === true && page.nextCursor === null && offset === total) {
|
|
227
|
+
try { return JSON.parse(chunks.join("")); }
|
|
228
|
+
catch { throw Error(`Invalid completed detail at ${offset}`); }
|
|
229
|
+
}
|
|
230
|
+
if (page.complete !== false || offset >= total ||
|
|
231
|
+
typeof page.nextCursor !== "string" || !page.nextCursor.length) {
|
|
232
|
+
throw Error(`Invalid continuation at ${offset}`);
|
|
233
|
+
}
|
|
234
|
+
cursor = page.nextCursor;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const [cli, task, store, ref, digest] = process.argv.slice(2);
|
|
239
|
+
if (![cli, task, store, ref, digest].every(Boolean)) throw Error("Five arguments required");
|
|
240
|
+
const args = ["task", "context", "inspect", task, "--store", store,
|
|
241
|
+
"--ref", ref, "--digest", digest, "--json"];
|
|
242
|
+
const record = readDocument(cursor => {
|
|
243
|
+
const result = spawnSync(cli, [...args, ...(cursor ? ["--cursor", cursor] : [])],
|
|
244
|
+
{ encoding: "utf8", maxBuffer: 1024 * 1024 });
|
|
245
|
+
if (result.error || result.status !== 0) throw Error("Detail command failed; stop without replay");
|
|
246
|
+
let reply;
|
|
247
|
+
try { reply = JSON.parse(result.stdout); }
|
|
248
|
+
catch { throw Error("Invalid CLI envelope"); }
|
|
249
|
+
if (reply.ok !== true || !reply.data) throw Error("Detail read refused");
|
|
250
|
+
return reply.data;
|
|
251
|
+
});
|
|
252
|
+
console.log(JSON.stringify(record));
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
This is a detail consumer, not a list paginator or a mutation retry helper.
|
|
256
|
+
On a changed source or refusal, stop and reassess the original read; do not
|
|
257
|
+
silently restart or mix versions. Errors deliberately exclude document text:
|
|
258
|
+
passing a partial `contentPage.text` to `jq fromjson` can echo the entire
|
|
259
|
+
fragment on failure. To inspect one already-fetched page without parsing it,
|
|
260
|
+
use `.data.contentPage | {offset,len:(.text|length),complete,nextCursor}`.
|
|
261
|
+
Two pages are not a completion condition; only the returned metadata is.
|
|
262
|
+
|
|
114
263
|
List responses carry `items`, `total`, `complete`, and `nextCursor`. Counts,
|
|
115
264
|
items and cursor validation occur inside the same authorized scope. Cursors
|
|
116
265
|
are opaque positions, not access tokens: every page reauthorizes. A changed
|
|
@@ -163,6 +312,16 @@ timestamps overlap; `--history` retains timestamp-window discovery.
|
|
|
163
312
|
|
|
164
313
|
## Runtime diagnostics
|
|
165
314
|
|
|
315
|
+
CLI JSON failures keep `ok`, `code`, `message` and `details`. `message` contains
|
|
316
|
+
the primary error, effect uncertainty, safe recovery guidance and focused help;
|
|
317
|
+
`details.diagnostic` retains the complete sanitized cause chain, operation,
|
|
318
|
+
Home, CLI entry, targets and any Controller request/delivery/timing facts.
|
|
319
|
+
Those identity lines and nested causes are not repeated as prose in `message`.
|
|
320
|
+
Consumers needing them must read `details.diagnostic`, not parse the human
|
|
321
|
+
message. Text-mode diagnostics remain unchanged. This is presentation only:
|
|
322
|
+
exit codes, redaction, partial receipts and no-replay/recovery boundaries do
|
|
323
|
+
not change; no probe, retry or repair is performed.
|
|
324
|
+
|
|
166
325
|
Global failure evidence remains ordinary record-only Messages; no aggregate
|
|
167
326
|
table, Message envelope change, memory store or recovery state machine is added.
|
|
168
327
|
Grouping is a derived view of new evidence documents. Older documents remain
|
|
@@ -183,6 +342,42 @@ Discovery and every evidence page retain the existing Role read boundary.
|
|
|
183
342
|
|
|
184
343
|
Message send/queue/steer receipts preserve identity, digest, body byte count and
|
|
185
344
|
the original submission/delivery/control states without echoing the body.
|
|
345
|
+
`bodySha256` is the lowercase SHA-256 of the saved body's raw UTF-8 bytes;
|
|
346
|
+
`bodyBytes` counts those same bytes. Callers may compare them with the exact
|
|
347
|
+
submitted file to verify transport without fetching the body again. Do not trim
|
|
348
|
+
or JSON-encode the body before hashing. The separate `digest` covers the entire
|
|
349
|
+
record and is not a body checksum. These fields are derived from the saved
|
|
350
|
+
Message, including idempotent replay; they neither add persistent state nor
|
|
351
|
+
replace required original reads, authorization, ACK or downstream acceptance.
|
|
352
|
+
`operator submit --json` uses that same structured shape:
|
|
353
|
+
`data.taskId`, `data.message` (the bounded Message receipt), and `data.submission`
|
|
354
|
+
(the recorded save, phase, planning, activation, delivery and next-step facts).
|
|
355
|
+
It no longer returns only an `output` string for JSON consumers; ordinary text
|
|
356
|
+
output is unchanged. A same-key retry reproduces the saved submission feedback,
|
|
357
|
+
not a fresh interpretation of the Task's later state. The receipt is not the
|
|
358
|
+
original body or proof that the Leader finished.
|
|
359
|
+
Message `--body-file <path|->` inputs preserve their UTF-8 text, including leading
|
|
360
|
+
and trailing whitespace, through Operator submission and Task/Global message
|
|
361
|
+
send, update, queue and steer paths. Blank-only or NUL-containing input remains
|
|
362
|
+
invalid. Inline text and summary/note file normalization are unchanged. This fixes
|
|
363
|
+
the earlier file-input trim; an old request saved after trimming must be inspected,
|
|
364
|
+
not replayed with newly different bytes under the same request ID.
|
|
365
|
+
Operator's optional `scripts/verify-submission.mjs` compares a local receipt with
|
|
366
|
+
the payload and expected Task/intent/request ID. It performs no Yui operation,
|
|
367
|
+
write, cleanup or ACK; a missing checksum is a failed local check, never success.
|
|
368
|
+
`task decision record|supersede --json` also returns a bounded save receipt:
|
|
369
|
+
`data.taskId`, `effect: "saved"`, `data.decision` (identity, state, timestamps,
|
|
370
|
+
complete-record digest and rationale byte count). When the complete
|
|
371
|
+
saved record is at most 2048 UTF-8 bytes in JSON, `decision` also contains all
|
|
372
|
+
its fields and `contentOmitted` is false: callers can inspect the actual short
|
|
373
|
+
saved value directly, without a `read` follow-up pointer. Larger records set
|
|
374
|
+
`contentOmitted: true`, include an exact `read` command, and omit title,
|
|
375
|
+
rationale and supersede-reason bodies rather than truncate them. The digest
|
|
376
|
+
always covers the complete original record, excluding receipt-added fields;
|
|
377
|
+
`decision show` remains the complete read when needed. Human text is unchanged.
|
|
378
|
+
JSON callers must consume `data`
|
|
379
|
+
instead of parsing the previous `output` string. This confirms the saved state,
|
|
380
|
+
not semantic acceptance; a missing response never authorizes repeating a record.
|
|
186
381
|
Brief updates return a saved reference. No new wait, retry, acknowledgement or
|
|
187
382
|
approval phase is added. Repeating a read cursor must never repeat a mutation.
|
|
188
383
|
|
|
@@ -201,8 +396,35 @@ document does not claim a universal 32 KiB cap for them. Full-detail Web
|
|
|
201
396
|
projections are separate consumers, not silently replaced with CLI summaries.
|
|
202
397
|
Use targeted Context discovery for large Project Knowledge and Task evidence.
|
|
203
398
|
|
|
204
|
-
For a typical notification, read current Context
|
|
205
|
-
|
|
399
|
+
For a typical notification, read current Context and the fixed wake, then obtain
|
|
400
|
+
only relevant originals not already returned in full (including their complete pages).
|
|
401
|
+
The focused wake JSON includes complete ordinary Message values up to 4 KiB
|
|
402
|
+
each and 8 KiB combined, marked `contentOmitted: false` with their current
|
|
403
|
+
versioned `ref`. Use those bodies directly. Larger messages and result reports
|
|
404
|
+
retain explicit reads; a completion notice never substitutes for its report.
|
|
405
|
+
For an inline complete value, `refreshRead` is an optional current-source refresh,
|
|
406
|
+
not a required next read; `read` is present only when the original is omitted.
|
|
407
|
+
Consumers that previously followed every `messages[].read` must first inspect
|
|
408
|
+
`contentOmitted` and use `value` for complete originals. Text output still links
|
|
409
|
+
to the original because it presents only a summary, not the inline JSON value.
|
|
410
|
+
The fixed window selects identities, not a historical snapshot of mutable
|
|
411
|
+
message bodies. Later revisions remain distinguishable by their exact reference.
|
|
412
|
+
History mode does not inline bodies. This changes no claim or ACK semantics.
|
|
413
|
+
The current Leader's `inbox show <wake>` also returns that focused view as
|
|
414
|
+
`originalContext`, with the existing wake metadata at the top level. It uses
|
|
415
|
+
the same identity selection, inline limits and exact original pointers as
|
|
416
|
+
`task wake show`; reuse the included complete bodies instead of making a second
|
|
417
|
+
read. Own-inbox authorization still applies, and the outer read retains
|
|
418
|
+
`contentPage` pagination. An unclaimed `pending-*` window has no fixed wake yet;
|
|
419
|
+
its claim receipt still supplies the durable wake and original-read command.
|
|
420
|
+
Claim/ACK mutations themselves are unchanged and do not perform extra reads.
|
|
421
|
+
For mutations addressed to an existing `wake-*`, the receipt now calls that
|
|
422
|
+
navigation `refreshOriginals`, not `originals`: use it when the focused originals
|
|
423
|
+
are missing, incomplete or need refreshing, not merely because a claim occurred.
|
|
424
|
+
Mutations addressed to `pending-*` retain `originals`, including idempotent claim
|
|
425
|
+
retries, because their initial inspection did not provide fixed originals.
|
|
426
|
+
This is a JSON navigation-field change; consumers must handle both entry types.
|
|
427
|
+
It records no read history and does not waive complete relevant-original reads.
|
|
206
428
|
Do not reread an aggregate to obtain a detail it intentionally omits.
|
|
207
429
|
Full-original reading costs additional calls only when the original exceeds
|
|
208
430
|
the inline budget; it is never replaced by a summary.
|