@zq-silk/yui 2.4.0 → 2.5.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/dist/cli/commandCatalog.js +1 -1
- package/dist/commands/taskCommands.js +40 -12
- package/dist/context/sessionBootstrapManifest.js +8 -2
- package/dist/controller/fileSchedulerStoreAdapter.js +7 -2
- package/dist/controller/globalInputDelivery.js +2 -4
- package/dist/controller/providerRetryDelivery.js +4 -2
- package/dist/executor/agentAdapter.js +3 -5
- package/dist/executor/fileRoleLaunchPlanner.js +2 -2
- package/dist/interaction/notificationPresentation.js +85 -0
- package/dist/interaction/operatorPresentation.js +1 -2
- package/dist/scheduler/leaderWakeupProcessor.js +1 -9
- package/dist/web/webConversation.js +2 -2
- package/docs/cli-information-contract.md +1 -1
- package/docs/cli-information-contract.zh-CN.md +1 -1
- package/docs/managed-turn-and-session-runtime.md +22 -0
- package/docs/managed-turn-and-session-runtime.zh-CN.md +15 -0
- package/docs/release-workflow.md +26 -0
- package/docs/release-workflow.zh-CN.md +18 -0
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +5 -4
- package/skills/yui-leader/references/execution.md +2 -1
- package/skills/yui-operator/SKILL.md +3 -0
- package/skills/yui-reviewer/SKILL.md +4 -2
- package/skills/yui-runtime/SKILL.md +43 -2
- package/skills/yui-worker/SKILL.md +3 -2
|
@@ -1096,7 +1096,7 @@ const taskChildren = [
|
|
|
1096
1096
|
sections: [{ id: "manage", title: "Commands", entries: ["list", "show", "retry", "resolve"] }],
|
|
1097
1097
|
children: [
|
|
1098
1098
|
{ name: "list", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "List recorded Leader wakes.", usage: "yui task wake list <task> [--limit <1..100>] [--cursor <cursor>]", options: ["--limit", "--cursor"] },
|
|
1099
|
-
{ name: "show", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Show
|
|
1099
|
+
{ name: "show", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Show fixed wake inputs/results; expand diagnostics with --history.", usage: "yui task wake show <task> <wake> [--history] [--cursor <cursor>]", options: ["--history", "--cursor"] },
|
|
1100
1100
|
{ name: "retry", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Retry a rejected notification after correcting its cause; preserve original input.",
|
|
1101
1101
|
usage: "yui task wake retry <task> <wake> --reason <correction>", options: ["--reason"] },
|
|
1102
1102
|
{ name: "resolve", discovery: { surface: "managed", audiences: ["operator", "leader"] }, summary: "Release an unknown notification claim after explicit quiescence evidence, without replay.",
|
|
@@ -13,6 +13,7 @@ import { assertContextRecordReadable, readTaskContextResource } from "../context
|
|
|
13
13
|
import { parseTaskSearchOptions, searchTaskBodies } from "../context/taskSearch.js";
|
|
14
14
|
import { boundedDocument, readOptions, messageReceipt, recordPage } from "../output/boundedRead.js";
|
|
15
15
|
import { referencedWakeRunIds } from "../context/wakeRunReferences.js";
|
|
16
|
+
import { taskMessagePresentation, wakeChangeLabels, wakeMessages } from "../interaction/notificationPresentation.js";
|
|
16
17
|
import { completeProcessing, releaseProcessing } from "../coordination/workMailbox.js";
|
|
17
18
|
import { enqueueRoleRunDispatch, enqueueWork, settleExactWorkExecution } from "../coordination/workMailboxQueue.js";
|
|
18
19
|
import { CliError, dataError, roleNotFound, runtimeError, taskNotFound, usageError } from "../errors/cliError.js";
|
|
@@ -51,7 +52,7 @@ import { runtimeObservationFromTaskEvent } from "../runtime/runtimeObservation.j
|
|
|
51
52
|
import { failureCapabilitiesCommand } from "../runtime/agentFailureContext.js";
|
|
52
53
|
import { enqueueOperatorEvent } from "../scheduler/operatorEvent.js";
|
|
53
54
|
import { isRoleRunStalled, RUN_PROGRESS_EVENT, RUN_RECOVERED_EVENT } from "../scheduler/roleRunStall.js";
|
|
54
|
-
import { renderWakeReason, wakeReason } from "../scheduler/wakeReason.js";
|
|
55
|
+
import { parseWakeReason, renderWakeReason, wakeReason } from "../scheduler/wakeReason.js";
|
|
55
56
|
import { queueLeaderWakeup } from "../scheduler/wakeupQueue.js";
|
|
56
57
|
import { planningRuntimeCwd } from "../storage/homeLayout.js";
|
|
57
58
|
import { StorageConflictError } from "../storage/taskStore.js";
|
|
@@ -6932,12 +6933,16 @@ function taskWakeInspectionCommand(args, store) {
|
|
|
6932
6933
|
return output(`${JSON.stringify(data)}\n`, data);
|
|
6933
6934
|
}
|
|
6934
6935
|
if (command === "show") {
|
|
6935
|
-
const usage = "Task wake show usage: yui task wake show <task> <wake
|
|
6936
|
-
|
|
6937
|
-
const
|
|
6938
|
-
|
|
6936
|
+
const usage = "Task wake show usage: yui task wake show <task> <wake> [--history].";
|
|
6937
|
+
const history = rest.includes("--history");
|
|
6938
|
+
const positional = history ? rest.filter(arg => arg !== "--history") : rest;
|
|
6939
|
+
exactPositionals(positional, 2, usage);
|
|
6940
|
+
if (rest.filter(arg => arg === "--history").length > 1)
|
|
6941
|
+
throw usageError(usage);
|
|
6942
|
+
const task = requireTask(store, positional[0]);
|
|
6943
|
+
const wake = store.getTaskWake(task.id, positional[1]);
|
|
6939
6944
|
if (wake === null)
|
|
6940
|
-
throw dataError(`Wake not found: ${
|
|
6945
|
+
throw dataError(`Wake not found: ${positional[1]}.`);
|
|
6941
6946
|
const timeZone = store.getConfig().timeZone;
|
|
6942
6947
|
const fromMs = Date.parse(wake.fromCursor);
|
|
6943
6948
|
const toMs = Date.parse(wake.toCursor);
|
|
@@ -6953,8 +6958,20 @@ function taskWakeInspectionCommand(args, store) {
|
|
|
6953
6958
|
const currentClaim = store.getWorkMailbox(leaderMailbox(task.id))?.processing;
|
|
6954
6959
|
const referenced = (type, id) => wake.refs?.some(ref => ref.type === type && ref.id === id
|
|
6955
6960
|
&& (!("taskId" in ref) || ref.taskId === task.id)) === true;
|
|
6956
|
-
|
|
6957
|
-
|
|
6961
|
+
// Some existing producers carry the exact source only in a reason tag
|
|
6962
|
+
// (e.g. input-timeout:<request>). Do not hide its decision behind --history.
|
|
6963
|
+
const reasonRefs = new Set(wake.reasons.flatMap(tag => {
|
|
6964
|
+
const reason = parseWakeReason(tag);
|
|
6965
|
+
return reason.kind !== "force-wake" && reason.ref !== undefined ? [reason.ref] : [];
|
|
6966
|
+
}));
|
|
6967
|
+
const reasonEvent = (event) => Date.parse(event.createdAt) <= toMs && [
|
|
6968
|
+
event.id, event.payload.runId, event.payload.requestId, event.payload.jobId,
|
|
6969
|
+
event.payload.workItemId, event.payload.reviewRoundId
|
|
6970
|
+
].some(id => id !== undefined && reasonRefs.has(id));
|
|
6971
|
+
const windowEvents = allEvents.filter((e) => inWindow(e.createdAt) || referenced("event", e.id) || reasonEvent(e));
|
|
6972
|
+
const events = history ? windowEvents : windowEvents.filter(e => referenced("event", e.id)
|
|
6973
|
+
|| reasonEvent(e) || ["run.completed", "run.failed", "run.cancelled"].includes(e.type));
|
|
6974
|
+
const messages = wakeMessages(wake, store.listMessages(task.id));
|
|
6958
6975
|
const allRuns = store.listRuns(task.id);
|
|
6959
6976
|
const referencedRunIds = new Set(referencedWakeRunIds(allRuns, allEvents, events));
|
|
6960
6977
|
for (const run of allRuns)
|
|
@@ -6963,7 +6980,7 @@ function taskWakeInspectionCommand(args, store) {
|
|
|
6963
6980
|
for (const message of messages)
|
|
6964
6981
|
if (message.resultRef?.type === "agent-run-result")
|
|
6965
6982
|
referencedRunIds.add(message.resultRef.runId);
|
|
6966
|
-
const runs = operationalTaskRecords(allRuns, allEvents, "run").filter((run) => (inWindow(run.createdAt) || referencedRunIds.has(run.id)));
|
|
6983
|
+
const runs = operationalTaskRecords(allRuns, allEvents, "run").filter((run) => (history && inWindow(run.createdAt) || referencedRunIds.has(run.id)));
|
|
6967
6984
|
const lines = [
|
|
6968
6985
|
`Wake: ${wake.id}`,
|
|
6969
6986
|
`Task: ${task.id}`,
|
|
@@ -6979,29 +6996,40 @@ function taskWakeInspectionCommand(args, store) {
|
|
|
6979
6996
|
`Recovery: correct the cause, then yui task wake retry ${task.id} ${wake.id} --reason <correction>.`
|
|
6980
6997
|
]),
|
|
6981
6998
|
`Reasons: ${wake.reasons.map(renderWakeReason).join(", ")}`,
|
|
6999
|
+
`Changes: ${wakeChangeLabels(wake.reasons).join("; ")}`,
|
|
6982
7000
|
`Delta window: ${wake.fromCursor} → ${wake.toCursor}`,
|
|
6983
7001
|
`Dispatched: ${presentTime(wake.createdAt, timeZone)}`,
|
|
6984
7002
|
...(wake.consumedAt === undefined
|
|
6985
7003
|
? []
|
|
6986
7004
|
: [`Consumed: ${presentTime(wake.consumedAt, timeZone)}`]),
|
|
6987
7005
|
`Events (${events.length}):`,
|
|
6988
|
-
...events.map((e) => ` ${e.id} ${e.type} ${presentTime(e.createdAt, timeZone)}`),
|
|
7006
|
+
...events.map((e) => ` ${e.id} ${e.type} ${presentTime(e.createdAt, timeZone)} → yui task event show ${task.id} ${e.id}`),
|
|
6989
7007
|
`Messages (${messages.length}):`,
|
|
6990
|
-
...messages.map((m) =>
|
|
7008
|
+
...messages.map((m) => {
|
|
7009
|
+
const item = taskMessagePresentation(m, (taskId, runId) => store.getRun(taskId, runId));
|
|
7010
|
+
return ` ${m.id} [${taskMessageAuthorLabel(m.author)}] ${item.fact}`
|
|
7011
|
+
+ (item.summary === undefined ? "" : `; author summary (${item.summarySource}): ${JSON.stringify(item.summary)}`)
|
|
7012
|
+
+ ` → yui task message show ${task.id}/${m.id}`;
|
|
7013
|
+
}),
|
|
6991
7014
|
`AgentRuns (${runs.length}):`,
|
|
6992
7015
|
...runs.map((run) => (` ${run.id} [${run.status}/${run.purpose}] ${run.roleName} `
|
|
6993
7016
|
+ `${presentTime(run.createdAt, timeZone)}`
|
|
6994
7017
|
+ `${referencedRunIds.has(run.id)
|
|
6995
7018
|
? ` → yui task run show ${task.id}/${run.id}`
|
|
6996
|
-
: ""}`))
|
|
7019
|
+
: ""}`)),
|
|
7020
|
+
...(!history ? [`History/diagnostics: yui task wake show ${task.id} ${wake.id} --history`,
|
|
7021
|
+
"Read relevant originals in full; follow contentPage.nextCursor when present."] : [])
|
|
6997
7022
|
];
|
|
6998
7023
|
return output(lines.join("\n").concat("\n"), {
|
|
6999
7024
|
taskId: task.id,
|
|
7000
7025
|
deliveryEvents,
|
|
7001
7026
|
wake,
|
|
7027
|
+
view: history ? "history" : "focus",
|
|
7028
|
+
historyRead: `task wake show ${task.id} ${wake.id} --history`,
|
|
7002
7029
|
events: events.map(event => ({ id: event.id, type: event.type, createdAt: event.createdAt,
|
|
7003
7030
|
read: `task event show ${task.id} ${event.id}` })),
|
|
7004
7031
|
messages: messages.map(message => ({ id: message.id, kind: message.kind, author: message.author,
|
|
7032
|
+
...taskMessagePresentation(message, (taskId, runId) => store.getRun(taskId, runId)),
|
|
7005
7033
|
resultRef: message.resultRef, read: `task message show ${task.id}/${message.id}` })),
|
|
7006
7034
|
runs: runs.map(run => ({ id: run.id, status: run.status, purpose: run.purpose, roleName: run.roleName,
|
|
7007
7035
|
read: `task run show ${task.id}/${run.id}` }))
|
|
@@ -12,12 +12,18 @@ export function withSessionContextPointer(text, environment) {
|
|
|
12
12
|
if (manifest === undefined)
|
|
13
13
|
return text;
|
|
14
14
|
return [
|
|
15
|
-
|
|
16
|
-
"Follow its referenced Role Skills and role profile. It gives the exact Context load command.",
|
|
15
|
+
sessionContextInstructions(manifest),
|
|
17
16
|
"",
|
|
18
17
|
text
|
|
19
18
|
].join("\n");
|
|
20
19
|
}
|
|
20
|
+
/** No remembered/sent flag can prove instructions survived context compaction. */
|
|
21
|
+
export function sessionContextInstructions(manifestPath, digest) {
|
|
22
|
+
return `Yui Session Manifest: ${manifestPath}${digest === undefined ? "" : ` (digest ${digest})`}. `
|
|
23
|
+
+ "Apply yui-runtime and its Role Skills/profile by exact manifest paths. "
|
|
24
|
+
+ "Load on first entry, version change or missing context; reuse only same-version instructions "
|
|
25
|
+
+ "fully available now, never infer availability from prior reads.";
|
|
26
|
+
}
|
|
21
27
|
/** Read back one immutable Session Manifest and verify its content digest. */
|
|
22
28
|
export function readSessionBootstrapManifest(path) {
|
|
23
29
|
const source = resolve(path);
|
|
@@ -2,6 +2,7 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { isDeepStrictEqual } from "node:util";
|
|
3
3
|
import { contextSnapshotRef } from "../context/contextSnapshot.js";
|
|
4
4
|
import { freezeRunContextSnapshot } from "../context/runContextPack.js";
|
|
5
|
+
import { taskNotificationPresentation } from "../interaction/notificationPresentation.js";
|
|
5
6
|
import { settleGlobalRetryInput } from "../message/globalProviderRetry.js";
|
|
6
7
|
import { interruptThenTerminalState, prepareMessageContinuations } from "../message/messageContinuation.js";
|
|
7
8
|
import { assertExecutionEnvironmentCurrent } from "../runtime/executionEnvironment.js";
|
|
@@ -1848,7 +1849,11 @@ export class FileSchedulerStoreAdapter {
|
|
|
1848
1849
|
}
|
|
1849
1850
|
const nextAttempt = `notification:${taskId}/${wakeId}/${randomUUID()}`;
|
|
1850
1851
|
store.saveWorkMailbox({ ...mailbox, processing: { ...processing, batchId: nextAttempt } });
|
|
1851
|
-
|
|
1852
|
+
const wake = store.getTaskWake(taskId, wakeId);
|
|
1853
|
+
if (wake === null)
|
|
1854
|
+
throw new Error(`Notification wake is unavailable: ${taskId}/${wakeId}.`);
|
|
1855
|
+
return { wakeId, attemptId: nextAttempt, disposition: "submit",
|
|
1856
|
+
presentation: taskNotificationPresentation(wake, store) };
|
|
1852
1857
|
}
|
|
1853
1858
|
if (mailbox.pending === null || (provider !== null && provider !== undefined
|
|
1854
1859
|
&& ["submitting", "accepted", "delivery-unknown"].includes(provider.status)))
|
|
@@ -1918,7 +1923,7 @@ export class FileSchedulerStoreAdapter {
|
|
|
1918
1923
|
// batch, rather than delivering them with the chosen immediate successor.
|
|
1919
1924
|
if (remainingRefs.length > 0)
|
|
1920
1925
|
enqueueWork(store, target, "user-message", now, remainingRefs, { source: "controller", dedupeKey: `then-remainder:${wakeId}` });
|
|
1921
|
-
return { wakeId, attemptId, disposition: "submit" };
|
|
1926
|
+
return { wakeId, attemptId, disposition: "submit", presentation: taskNotificationPresentation(wake, store) };
|
|
1922
1927
|
});
|
|
1923
1928
|
}
|
|
1924
1929
|
settleLeaderNotification(taskId, attemptId, outcome, now, detail, failure) {
|
|
@@ -4,6 +4,7 @@ import { hasRuntimeCleanupObligation, runtimeLifecycleTarget } from "../runtime/
|
|
|
4
4
|
import { markGlobalRoleMessageNotDelivered } from "../message/message.js";
|
|
5
5
|
import { providerRetryPending } from "../runtime/providerRetry.js";
|
|
6
6
|
import { settleGlobalRetryInput } from "../message/globalProviderRetry.js";
|
|
7
|
+
import { globalMessagePresentation } from "../interaction/notificationPresentation.js";
|
|
7
8
|
/** Messages are the only queue. Host's atomic begin arbitrates native writers. */
|
|
8
9
|
export async function deliverGlobalInputs(home, store, ensure, onError) {
|
|
9
10
|
for (const role of store.listGlobalRoles()) {
|
|
@@ -119,10 +120,7 @@ export async function deliverGlobalInputs(home, store, ensure, onError) {
|
|
|
119
120
|
protocol: AGENT_HOST_CONTROL_PROTOCOL, type: "submit-turn", nativeSessionId,
|
|
120
121
|
authority: { epoch: binding.authority.epoch, owner: "controller",
|
|
121
122
|
holderId: binding.authority.holderId },
|
|
122
|
-
run: { attemptId, boundedText:
|
|
123
|
-
`Yui Global Message: role=${role.name} message=${next.id}.`,
|
|
124
|
-
"Read your Session Context and the referenced Message in full, then act on its durable input."
|
|
125
|
-
].join("\n") }
|
|
123
|
+
run: { attemptId, boundedText: globalMessagePresentation(role.name, next.id, next) }
|
|
126
124
|
}
|
|
127
125
|
});
|
|
128
126
|
if (result.outcome === "rejected") {
|
|
@@ -10,6 +10,7 @@ import { cancelProviderRetry, providerRetryAttemptId, providerRetryPending, prov
|
|
|
10
10
|
import { currentProviderConversation } from "../runtime/providerRuntimeIdentity.js";
|
|
11
11
|
import { retryIntentBlocker } from "./providerRetryAdmission.js";
|
|
12
12
|
import { recordGlobalRuntimeAttention } from "./globalRuntimeAttention.js";
|
|
13
|
+
import { globalMessagePresentation, taskNotificationPresentation } from "../interaction/notificationPresentation.js";
|
|
13
14
|
/** Hooks in the existing Controller pass and nearest-deadline timer. SQLite's
|
|
14
15
|
* current Provider input is the only pending intent; nothing is queued here. */
|
|
15
16
|
export function createProviderRetryHooks(home, store, ports = {}) {
|
|
@@ -185,11 +186,12 @@ export function createProviderRetryHooks(home, store, ports = {}) {
|
|
|
185
186
|
});
|
|
186
187
|
}
|
|
187
188
|
else {
|
|
189
|
+
const wake = retry.input.kind === "wake" ? store.getTaskWake(retry.input.taskId, retry.input.wakeId) : null;
|
|
188
190
|
const original = retry.input.kind === "text" ? retry.input.text
|
|
189
191
|
: retry.input.kind === "wake"
|
|
190
|
-
?
|
|
192
|
+
? wake === null ? undefined : taskNotificationPresentation(wake, store)
|
|
191
193
|
: retry.input.kind === "message"
|
|
192
|
-
?
|
|
194
|
+
? globalMessagePresentation(retry.input.roleName, retry.input.messageId, store.listGlobalRoleMessages(retry.input.roleName).find(message => retry.input.kind === "message" && message.id === retry.input.messageId))
|
|
193
195
|
: undefined;
|
|
194
196
|
if (original === undefined) {
|
|
195
197
|
stop(set, "original-input-unavailable", at);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { realpathSync, statSync } from "node:fs";
|
|
3
3
|
import { isAbsolute, resolve } from "node:path";
|
|
4
|
+
import { sessionContextInstructions } from "../context/sessionBootstrapManifest.js";
|
|
4
5
|
import { isAgentAdapterId, supportedAgentAdapterIds } from "../agent/adapterCatalog.js";
|
|
5
6
|
import { ownedArgumentsForAdapter, validateAgentAdvancedArguments, validateAgentBaseArguments } from "../agent/argumentPolicy.js";
|
|
6
7
|
import { writeTextFileAtomically } from "../storage/durableFile.js";
|
|
@@ -434,10 +435,7 @@ function acpSessionBootstrap(input) {
|
|
|
434
435
|
])
|
|
435
436
|
]
|
|
436
437
|
: [
|
|
437
|
-
|
|
438
|
-
+ `${input.sessionManifestPath} (digest ${input.sessionManifestDigest ?? "unknown"}). `
|
|
439
|
-
+ "Load each Skill and Role Profile by its manifest path before acting; Task "
|
|
440
|
-
+ "content is available only through the manifest's exact Context API."
|
|
438
|
+
sessionContextInstructions(input.sessionManifestPath, input.sessionManifestDigest)
|
|
441
439
|
];
|
|
442
440
|
const bootstrap = sections
|
|
443
441
|
.filter((value) => value !== undefined && value.trim().length > 0)
|
|
@@ -500,7 +498,7 @@ function codexThreadOptions(input, config) {
|
|
|
500
498
|
}
|
|
501
499
|
function codexSessionInstructions(input) {
|
|
502
500
|
if (input.sessionManifestPath !== undefined) {
|
|
503
|
-
return
|
|
501
|
+
return sessionContextInstructions(input.sessionManifestPath, input.sessionManifestDigest);
|
|
504
502
|
}
|
|
505
503
|
const instructions = [
|
|
506
504
|
input.developerInstructions,
|
|
@@ -9,7 +9,7 @@ import { assertExecutionEnvironmentCurrent } from "../runtime/executionEnvironme
|
|
|
9
9
|
import { configuredAgentToDefinition, resolveAgentEnvironment } from "../agent/agent.js";
|
|
10
10
|
import { NATIVE_AGENT_ENVIRONMENT_NAMES, nativeAgentEnvironmentNames, operationalAgentEnvironment, selectEnvironment } from "../agent/launchEnvironment.js";
|
|
11
11
|
import { compileRoleSessionContext, roleSessionKind } from "../context/roleSessionContext.js";
|
|
12
|
-
import { materializeSessionBootstrap } from "../context/sessionBootstrapManifest.js";
|
|
12
|
+
import { materializeSessionBootstrap, sessionContextInstructions } from "../context/sessionBootstrapManifest.js";
|
|
13
13
|
import { ResourceRegistrar } from "../resources/resourceRegistrar.js";
|
|
14
14
|
import { activeRoleAgentBinding } from "../role/role.js";
|
|
15
15
|
import { managedRuntimeAdmission } from "../runtime/agentDriver.js";
|
|
@@ -358,7 +358,7 @@ export class FileRoleLaunchPlanner {
|
|
|
358
358
|
}
|
|
359
359
|
const sessionContext = {
|
|
360
360
|
...baseSessionContext,
|
|
361
|
-
developerInstructions:
|
|
361
|
+
developerInstructions: sessionContextInstructions(bootstrap.manifestPath, bootstrap.manifest.digest),
|
|
362
362
|
managedContextFile: bootstrap.manifestPath,
|
|
363
363
|
sessionManifestPath: bootstrap.manifestPath,
|
|
364
364
|
sessionManifestDigest: bootstrap.manifest.digest
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { parseWakeReason } from "../scheduler/wakeReason.js";
|
|
2
|
+
/** Optional producer-authored presentation, stored in the original text, not a
|
|
3
|
+
* parsed business outcome or a second fact store. Reject oversized summaries
|
|
4
|
+
* whole: clipping could remove a failure/authority qualifier. */
|
|
5
|
+
export function authoredNotificationSummary(text) {
|
|
6
|
+
const line = text?.trimStart().split(/\r?\n/u, 1)[0];
|
|
7
|
+
if (!line?.startsWith("Yui-Summary: "))
|
|
8
|
+
return undefined;
|
|
9
|
+
const summary = line.slice("Yui-Summary: ".length).trim();
|
|
10
|
+
return summary.length > 0 && Buffer.byteLength(summary) <= 512
|
|
11
|
+
&& !/[\u0000-\u001f\u007f]/u.test(summary) ? summary : undefined;
|
|
12
|
+
}
|
|
13
|
+
export function taskMessagePresentation(message, getRun) {
|
|
14
|
+
const run = message.resultRef?.type === "agent-run-result"
|
|
15
|
+
? getRun(message.taskId, message.resultRef.runId) : null;
|
|
16
|
+
const summary = authoredNotificationSummary(run?.result?.output ?? message.body);
|
|
17
|
+
const fact = run !== null
|
|
18
|
+
? `${run.purpose === "review" ? "Review" : "Execution"} result returned (${run.status}); disposition pending`
|
|
19
|
+
: message.kind === "role-result" ? "Role result returned; disposition pending"
|
|
20
|
+
: message.kind === "user" || message.kind === "operator" ? "Additional input received"
|
|
21
|
+
: "System message received";
|
|
22
|
+
return {
|
|
23
|
+
fact,
|
|
24
|
+
...(summary === undefined ? {} : {
|
|
25
|
+
summary, summarySource: run?.result?.output === undefined ? "message-body" : "agent-run-result"
|
|
26
|
+
})
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function wakeChangeLabels(reasons) {
|
|
30
|
+
return [...new Set(reasons.map(tag => {
|
|
31
|
+
const { kind } = parseWakeReason(tag);
|
|
32
|
+
switch (kind) {
|
|
33
|
+
case "operator-input":
|
|
34
|
+
case "user-message":
|
|
35
|
+
case "interrupt-then": return "Additional input received";
|
|
36
|
+
case "execution-started": return "Task execution enabled";
|
|
37
|
+
case "task-created": return "Task created";
|
|
38
|
+
case "task-reopened": return "Task reopened; check for scoped follow-up";
|
|
39
|
+
case "role-result": return "Role result returned; disposition pending";
|
|
40
|
+
case "review-failed": return "Review execution failed; inspect original failure";
|
|
41
|
+
case "agent-error":
|
|
42
|
+
case "leader-turn-failed":
|
|
43
|
+
case "role-turn-failed": return "Execution failure needs attention";
|
|
44
|
+
case "job-finished": return "Job ended; inspect outcome";
|
|
45
|
+
case "input-timeout": return "Input deadline reached; inspect recorded decision";
|
|
46
|
+
case "notification-retry": return "Notification retry after recorded correction";
|
|
47
|
+
default: return Buffer.byteLength(kind) <= 120 && !/[\u0000-\u001f\u007f]/u.test(kind)
|
|
48
|
+
? `Recorded update: ${kind}` : "Other recorded update; inspect wake";
|
|
49
|
+
}
|
|
50
|
+
}))];
|
|
51
|
+
}
|
|
52
|
+
export function wakeMessages(wake, messages) {
|
|
53
|
+
const ids = new Set(wake.refs?.filter(ref => ref.type === "message" && ref.taskId === wake.taskId).map(ref => ref.id));
|
|
54
|
+
const from = Date.parse(wake.fromCursor), to = Date.parse(wake.toCursor);
|
|
55
|
+
return messages.filter(message => ids.has(message.id)
|
|
56
|
+
|| Date.parse(message.createdAt) > from && Date.parse(message.createdAt) <= to);
|
|
57
|
+
}
|
|
58
|
+
export function taskNotificationPresentation(wake, store) {
|
|
59
|
+
const messages = wakeMessages(wake, store.listMessages(wake.taskId));
|
|
60
|
+
const labels = wakeChangeLabels(wake.reasons);
|
|
61
|
+
return [
|
|
62
|
+
`Yui Task notification: task=${wake.taskId} wake=${wake.id}.`,
|
|
63
|
+
`Changes: ${labels.slice(0, 4).join("; ")}${labels.length > 4 ? "; more in wake" : ""}.`,
|
|
64
|
+
...messages.slice(0, 4).map(message => {
|
|
65
|
+
const item = taskMessagePresentation(message, (task, run) => store.getRun(task, run));
|
|
66
|
+
return `- ${message.id} [${message.author.type}${message.author.type === "role" ? `:${message.author.roleName}` : ""}]: ${item.fact}.`
|
|
67
|
+
+ (item.summary === undefined ? "" : ` Author summary (${item.summarySource}): ${JSON.stringify(item.summary)}`);
|
|
68
|
+
}),
|
|
69
|
+
...(messages.length > 4 ? [`${messages.length - 4} more messages in the fixed wake.`] : []),
|
|
70
|
+
`Refresh: yui task context ${wake.taskId} --json`,
|
|
71
|
+
`Read inputs/results: yui task wake show ${wake.taskId} ${wake.id} --json`,
|
|
72
|
+
"Apply yui-leader (from the current Manifest); read relevant originals in full and advance authorized work."
|
|
73
|
+
].join("\n");
|
|
74
|
+
}
|
|
75
|
+
export function globalMessagePresentation(roleName, messageId, message) {
|
|
76
|
+
const summary = authoredNotificationSummary(message?.body);
|
|
77
|
+
return [
|
|
78
|
+
`Yui Global Message: role=${roleName} message=${messageId}.`,
|
|
79
|
+
`Changes: ${message?.author.type ?? "Recorded"} input received.`,
|
|
80
|
+
...(summary === undefined ? [] : [`Author summary (message-body): ${JSON.stringify(summary)}`]),
|
|
81
|
+
"Refresh Session Context using the current Manifest's loadCommand.",
|
|
82
|
+
`Read original: yui role message show ${roleName} ${messageId} --json`,
|
|
83
|
+
`Apply ${roleName === "operator" ? "yui-operator" : "yui-runtime"} from the current Manifest within existing authority.`
|
|
84
|
+
].join("\n");
|
|
85
|
+
}
|
|
@@ -10,8 +10,7 @@ export function createOperatorBatchPresentation(batchId, items) {
|
|
|
10
10
|
receiptId: `operator-batch:${batchId}`,
|
|
11
11
|
text: [
|
|
12
12
|
"[Yui updates]",
|
|
13
|
-
"
|
|
14
|
-
"This notification is not a new execution assignment or authorization to replay prior operations.",
|
|
13
|
+
"Apply yui-operator from the current Manifest: inspect these originals and present material changes or decisions.",
|
|
15
14
|
...items.flatMap(renderItem)
|
|
16
15
|
].join("\n")
|
|
17
16
|
};
|
|
@@ -86,15 +86,7 @@ export async function processLeaderWakeups(store, delivery, now, selection) {
|
|
|
86
86
|
attempted = true;
|
|
87
87
|
const outcome = await delivery.sendOnce({
|
|
88
88
|
delivery: ready, receiptId: notification.attemptId, notificationId: notification.wakeId,
|
|
89
|
-
text:
|
|
90
|
-
`Yui Task notification: task=${task.id} wake=${notification.wakeId}.`,
|
|
91
|
-
`Read current context: yui task context ${task.id} --json.`,
|
|
92
|
-
`Read the fixed notification window: yui task wake show ${task.id} ${notification.wakeId}.`,
|
|
93
|
-
"Read referenced result Messages in full before deciding their disposition.",
|
|
94
|
-
"Follow the Leader Skill to advance outstanding Task work from these durable facts, or record the exact decision/authority needed.",
|
|
95
|
-
"This is a notification, not an execution assignment. No separate final report is required.",
|
|
96
|
-
"Reading context is not an acknowledgement that its requirements have been implemented."
|
|
97
|
-
].join("\n")
|
|
89
|
+
text: notification.presentation
|
|
98
90
|
});
|
|
99
91
|
const accepted = outcome.status === "sent" || outcome.status === "already-sent";
|
|
100
92
|
const disposition = accepted ? "accepted"
|
|
@@ -170,7 +170,7 @@ export function createWebConversationSurface(store, surface, plan, readPage = re
|
|
|
170
170
|
return [item];
|
|
171
171
|
let messages = [];
|
|
172
172
|
if (owner.scope === "task") {
|
|
173
|
-
const ref = /^Yui Task notification: task=([A-Za-z0-9_-]+) wake=([A-Za-z0-9_-]+)
|
|
173
|
+
const ref = /^Yui Task notification: task=([A-Za-z0-9_-]+) wake=([A-Za-z0-9_-]+)\.$/m.exec(item.text);
|
|
174
174
|
if (ref?.[1] === owner.taskId) {
|
|
175
175
|
const wake = store.listTaskWakes(owner.taskId).find(w => w.id === ref[2] && w.status === "consumed");
|
|
176
176
|
const ids = new Set(wake?.refs?.filter(r => r.type === "message").map(r => r.id));
|
|
@@ -178,7 +178,7 @@ export function createWebConversationSurface(store, surface, plan, readPage = re
|
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
else {
|
|
181
|
-
const ref = /^Yui Global Message: role=([A-Za-z0-9_-]+) message=([A-Za-z0-9_-]+)
|
|
181
|
+
const ref = /^Yui Global Message: role=([A-Za-z0-9_-]+) message=([A-Za-z0-9_-]+)\.$/m.exec(item.text);
|
|
182
182
|
if (ref?.[1] === owner.roleName)
|
|
183
183
|
messages = store.listGlobalRoleMessages(owner.roleName)
|
|
184
184
|
.filter(m => m.id === ref[2] && m.delivery?.via === "provider" && m.deliveryTarget?.nativeSessionId === id);
|
|
@@ -20,7 +20,7 @@ schema migration or new snapshot/cache store is introduced.
|
|
|
20
20
|
| What changed? | `task context delta <task> --after <cursor>` | Immutable events with a fixed upper bound, not a snapshot of current mutable state |
|
|
21
21
|
| Which Global input? | `session context <role>` | Identity, profile, authority, current native Turn/retry and separate bounded pending/recent Message pages |
|
|
22
22
|
| Read Global input | `role message list <role> [--pending]`, `role message show <role> <id>` | Scoped discovery, then exact original; queue acceptance never erases history |
|
|
23
|
-
| What arrived in this wake? | `task wake show <task> <wake>` | Fixed
|
|
23
|
+
| What arrived in this wake? | `task wake show <task> <wake>` | Fixed-window inputs/results, attributed optional summaries and exact original reads; `--history` expands diagnostics |
|
|
24
24
|
| What was assigned? | `task run context <task>/<run>` | Frozen authority and a single `pointers` inventory with summaries; changed identities in `deltaRefs`; current observations remain separate |
|
|
25
25
|
| 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 |
|
|
26
26
|
|
|
@@ -18,7 +18,7 @@ CLI 调用成功,不代表 Task、原生 Turn 或远端投递完成。
|
|
|
18
18
|
| 发生了什么变化? | `task context delta <task> --after <cursor>` | 固定上界内的不可变事件,不是可变当前状态的快照 |
|
|
19
19
|
| Global 收到了什么? | `session context <role>` | 身份、Profile、权限、当前原生 Turn/retry,以及分别有界的 pending/recent Message 页 |
|
|
20
20
|
| 读取 Global 输入 | `role message list <role> [--pending]`、`role message show <role> <id>` | 在自身范围内发现,再读完整原文;队列接受不删除历史 |
|
|
21
|
-
| 本次唤醒带来什么? | `task wake show <task> <wake>` |
|
|
21
|
+
| 本次唤醒带来什么? | `task wake show <task> <wake>` | 固定窗口的输入/结果、标明来源的可选摘要和确切原文入口;`--history` 展开诊断历史 |
|
|
22
22
|
| 分配了什么? | `task run context <task>/<run>` | 冻结授权与一份带摘要的 `pointers` 目录;`deltaRefs` 表示变化身份;当前观察独立 |
|
|
23
23
|
| 实际配置是什么? | `task role session inspect <task> <role>` | Task/Role 身份、期望绑定、冻结 Session、当前 Provider 绑定、retry 与显式 Host 观察;不复制整个 Task/Role 或 Provider 会话历史 |
|
|
24
24
|
|
|
@@ -69,6 +69,14 @@ Run Pack is a reference directory: read the relevant requirement and message
|
|
|
69
69
|
bodies before acting, rather than treating a successful load as the deliverable.
|
|
70
70
|
Planning Packs expose no Project write scope or Task-completion permission.
|
|
71
71
|
|
|
72
|
+
The Manifest pointer is a recovery locator, not a read receipt. Load its exact
|
|
73
|
+
`yui-runtime`, Role Skills and profile on first entry, a new/version-changed
|
|
74
|
+
Session, or missing context after compaction/recovery. Reuse instructions only
|
|
75
|
+
when the same-version full content is still available; Yui stores no "already
|
|
76
|
+
read" state. Always refresh dynamic facts. Leader notifications use
|
|
77
|
+
`currentCommand`; dispatched AgentRuns use the actual Run ID with
|
|
78
|
+
`loadCommand`/`expandCommand`, never their placeholder templates.
|
|
79
|
+
|
|
72
80
|
Every new Run, including planning, Review and continuation, binds an explicit
|
|
73
81
|
frozen Snapshot before dispatch. Context reads validate its full identity and
|
|
74
82
|
content digest, then read its stored values without rebuilding current Task
|
|
@@ -123,6 +131,20 @@ Human input, explicit execution entry and activation failure are delivered
|
|
|
123
131
|
promptly through the existing wake mechanism. Worker results retain their
|
|
124
132
|
aggregation window. Busy native input still preserves pending messages.
|
|
125
133
|
|
|
134
|
+
Normal and retry notifications share the same bounded presentation: factual
|
|
135
|
+
change labels, attributed optional author summaries, and original read entries.
|
|
136
|
+
An author can begin a Message/report with `Yui-Summary: <one line>` (summary
|
|
137
|
+
at most 512 UTF-8 bytes). It remains in the original record; no schema migration,
|
|
138
|
+
summary store, read-acknowledgement or extra model call is involved. Missing or
|
|
139
|
+
oversized summaries fall back to facts without clipping qualifications.
|
|
140
|
+
Summaries never grant authority, accept results or mark reviews approved.
|
|
141
|
+
|
|
142
|
+
`task wake show <task> <wake>` now defaults to inputs/results and explicit
|
|
143
|
+
references, including older referenced originals. It omits unrelated diagnostic
|
|
144
|
+
events and merely started Runs; `--history` restores full fixed-window discovery.
|
|
145
|
+
Both views retain the fixed window, deduplication, exact detail commands and
|
|
146
|
+
bounded `contentPage` continuations. Read decision-relevant originals in full.
|
|
147
|
+
|
|
126
148
|
| Evidence | Disposition |
|
|
127
149
|
| --- | --- |
|
|
128
150
|
| Busy with proven non-acceptance | Preserve input; a new transport attempt may use the same Session |
|
|
@@ -55,6 +55,21 @@ Run Context 冻结 Assignment、来源引用、生效配置和工作区边界。
|
|
|
55
55
|
和消息正文,而不是把加载成功当成交付物。规划 Pack 不暴露 Project 写范围或 Task 完成
|
|
56
56
|
权限。
|
|
57
57
|
|
|
58
|
+
Manifest 指针是恢复定位入口,不是已读凭据。首次进入、新会话、版本变化、压缩或恢复后
|
|
59
|
+
说明缺失时,从其确切路径加载 `yui-runtime`、Role Skills 和 profile;仅当同版本全文仍在
|
|
60
|
+
当前可用上下文中,才复用而不机械重读。系统不保存“已经读过”状态。动态事实仍须刷新:
|
|
61
|
+
Leader 通知使用 `currentCommand`,显式 AgentRun 使用真实 Run ID 的
|
|
62
|
+
`loadCommand`/`expandCommand`,不可直接执行占位模板。
|
|
63
|
+
|
|
64
|
+
正常和重试通知共用有界呈现:流程事实、标明作者来源的可选摘要与原文入口。Agent 可在
|
|
65
|
+
Message/报告首行写 `Yui-Summary: <单行摘要>`(摘要最多 512 UTF-8 字节),保留失败、
|
|
66
|
+
未验证、待决定等限定。摘要存在原文本身,不新增数据格式、摘要存储、已读状态或模型调用;
|
|
67
|
+
缺失或超长时使用事实模板,不截断关键限定。摘要不是授权、验收或审查通过结论。
|
|
68
|
+
|
|
69
|
+
`task wake show <task> <wake>` 默认展示消息、结果与明确引用(包括窗口外原文),
|
|
70
|
+
不再枚举无关诊断事件和仅启动的 Run;`--history` 展开完整固定窗口历史。两个视图保留
|
|
71
|
+
去重、固定窗口、确切原文命令及 `contentPage` 续读。决策所依赖的原文仍须全文读取。
|
|
72
|
+
|
|
58
73
|
新 Run(包括规划、Review 和消息续接)必须在派发前绑定明确冻结的 Snapshot。
|
|
59
74
|
Context 读取校验完整身份与内容 digest,然后直接读取已保存的值,不重新收集当前
|
|
60
75
|
Task 记录。聚合执行从该 Snapshot 读取已选择的 Producer 结果;可写 Project 来自
|
package/docs/release-workflow.md
CHANGED
|
@@ -51,6 +51,32 @@ merely to avoid a version decision. Package versions remain distinct from protoc
|
|
|
51
51
|
and persistent-storage contracts: their compatibility checks and required migrations
|
|
52
52
|
are unchanged, and the storage rules below do not authorize a package release.
|
|
53
53
|
|
|
54
|
+
### 2.5.0 compatibility and migration notes
|
|
55
|
+
|
|
56
|
+
This minor includes Task110's notification and context-loading improvements.
|
|
57
|
+
Normal and recovery notifications share bounded facts, optional attributed
|
|
58
|
+
author summaries and exact action entries. A summary is not acceptance or
|
|
59
|
+
authority: relevant requirements, user messages and execution results must
|
|
60
|
+
still be read in full.
|
|
61
|
+
|
|
62
|
+
Session instructions name the required Skills explicitly. Reuse is conditional
|
|
63
|
+
on the complete same-version instructions remaining available in context;
|
|
64
|
+
first entry, changed instructions or missing/compacted content require loading
|
|
65
|
+
the exact Manifest and referenced files again. There is no persistent read
|
|
66
|
+
receipt, instruction cache or additional model call for summarization.
|
|
67
|
+
|
|
68
|
+
`task wake show` now focuses on relevant messages, results and referenced
|
|
69
|
+
evidence by default. Use `--history` for the broader fixed-window diagnostic
|
|
70
|
+
view and follow pagination when present. Consumers must not treat the focused
|
|
71
|
+
view as all history. Original records, exact older references, deduplication,
|
|
72
|
+
snapshot boundaries and unknown-input no-replay rules are preserved.
|
|
73
|
+
|
|
74
|
+
No storage migration is added; storage remains **1.6**. Deterministic tests and
|
|
75
|
+
package smoke do not prove real-model instruction reuse or compaction recovery.
|
|
76
|
+
Byte measurements are not token savings and can increase for a simple first
|
|
77
|
+
entry. Publishing this package does not upgrade a global CLI, migrate a Home
|
|
78
|
+
or restart a Controller.
|
|
79
|
+
|
|
54
80
|
### 2.4.0 compatibility and migration notes
|
|
55
81
|
|
|
56
82
|
This minor ships the unified Web Task/Operator conversations and same-thread
|
|
@@ -36,6 +36,24 @@ Agent 选择一个预先声明的计划,设施从持久状态驱动该计划
|
|
|
36
36
|
不能将不兼容冒称为兼容,也不为回避版本选择新增历史兼容机制。包版本与协议、
|
|
37
37
|
持久存储契约仍然独立:兼容性检查和必要迁移要求不变,下文存储规则不授予发版权限。
|
|
38
38
|
|
|
39
|
+
### 2.5.0 兼容性及迁移说明
|
|
40
|
+
|
|
41
|
+
本 minor 包含 Task110 的通知和上下文加载优化。正常与恢复通知共用有界事实、
|
|
42
|
+
可选且注明来源的作者摘要及精确行动入口。摘要不是验收或授权:相关需求、
|
|
43
|
+
用户消息和执行结果仍须全文读取。
|
|
44
|
+
|
|
45
|
+
会话说明显式列出所需 Skill。只有完整的同版本说明仍在可用上下文中时才能复用;
|
|
46
|
+
首次进入、说明变更或内容缺失/被压缩时,须重新加载精确 Manifest 及其引用文件。
|
|
47
|
+
没有新增持久已读回执、说明缓存或专用模型摘要调用。
|
|
48
|
+
|
|
49
|
+
`task wake show` 默认聚焦相关消息、结果及引用证据;如需更完整的固定窗口诊断,
|
|
50
|
+
使用 `--history`,有分页时继续读取。调用方不能将聚焦视图当作全部历史。
|
|
51
|
+
原始记录、精确旧引用、去重、快照边界及未知输入不得重放的规则保持不变。
|
|
52
|
+
|
|
53
|
+
本版不新增存储迁移,存储仍为 **1.6**。确定性测试及安装包冒烟不证明真实模型
|
|
54
|
+
会复用说明或在压缩后正确补读;字节测量不是 token 节省,简单首次进入的开销
|
|
55
|
+
可能增加。发布本包不会升级全局 CLI、迁移 Home 或重启 Controller。
|
|
56
|
+
|
|
39
57
|
### 2.4.0 兼容性及迁移说明
|
|
40
58
|
|
|
41
59
|
本 minor 发布统一 Web Task/Operator 对话及同 Thread Codex 终端、任务工作台、
|
package/package.json
CHANGED
|
@@ -14,10 +14,11 @@ their summaries. Resolve links relative to the file containing them.
|
|
|
14
14
|
|
|
15
15
|
Current Context is a bounded working set, not all Task history. Use
|
|
16
16
|
`task context list <task> --store <store>` or a domain list for discovery,
|
|
17
|
-
then an exact detail read. A wake contains
|
|
18
|
-
not
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
then an exact detail read. A wake contains attributed change summaries and
|
|
18
|
+
original Message/Run pointers, not complete reports. Follow `yui-runtime`'s
|
|
19
|
+
`nextCursor` and `contentPage` rules: read the complete focused wake view and
|
|
20
|
+
relevant originals before disposition; use `wake show --history` only when
|
|
21
|
+
window history/diagnostics matter. Summaries never decide completion.
|
|
21
22
|
|
|
22
23
|
Before WorkItem dispatch, put the complete bounded requirements in the WorkItem
|
|
23
24
|
or explicitly select up to 16 relevant readable materials with repeated
|
|
@@ -420,7 +420,8 @@ notification; no active AgentRun is required.
|
|
|
420
420
|
|
|
421
421
|
Before ending authorized execution:
|
|
422
422
|
|
|
423
|
-
1. Inspect the wake
|
|
423
|
+
1. Inspect the focused wake inputs/results (expand `--history` when needed),
|
|
424
|
+
resolve every referenced Worker or Reviewer AgentRun
|
|
424
425
|
with `yui task run show`, read each original result in full, and make the
|
|
425
426
|
next decision.
|
|
426
427
|
2. Persist actual WorkItem lifecycle and material Brief, Decision, Milestone,
|
|
@@ -30,6 +30,9 @@ another reader's understanding or action. Do not narrate dispatch, attach,
|
|
|
30
30
|
heartbeat, sampling, unchanged waiting, or routine recovery.
|
|
31
31
|
|
|
32
32
|
A `[Yui updates]` message is a wake envelope containing durable references.
|
|
33
|
+
Follow `yui-runtime`'s conditional instruction loading and attributed summary
|
|
34
|
+
contract for both Global Message inputs and these notices. Summaries locate
|
|
35
|
+
originals; they cannot grant user authority or prove result acceptance.
|
|
33
36
|
Read those exact records before responding and combine related updates into one
|
|
34
37
|
user-level summary. Do not create a Codex Goal, polling loop, private monitoring
|
|
35
38
|
task, or synthetic progress message; future durable events will wake the
|
|
@@ -110,8 +110,10 @@ frozen Review or its original report.
|
|
|
110
110
|
|
|
111
111
|
A helpful default result layout is Conclusion, Material findings, Verification,
|
|
112
112
|
Uncertainty, and Recommended next action. Markdown or JSON are both acceptable.
|
|
113
|
-
Yui preserves the original text and does not parse
|
|
114
|
-
missing headings, field names, or formatting.
|
|
113
|
+
Yui preserves the original text and does not parse a verdict or reject it for
|
|
114
|
+
missing headings, field names, or formatting. Follow `yui-runtime`'s optional
|
|
115
|
+
`Yui-Summary:` first-line convention for attributed notification text; retain
|
|
116
|
+
material findings and uncertainty rather than implying automatic approval.
|
|
115
117
|
|
|
116
118
|
For normal software delivery, follow the applicable Project Policy. The
|
|
117
119
|
Leader decides whether risk warrants one independent Task-final Review of the
|
|
@@ -16,6 +16,24 @@ workspace layout, native transcript, or an earlier AgentRun.
|
|
|
16
16
|
|
|
17
17
|
## Enter through the current context
|
|
18
18
|
|
|
19
|
+
Stable instructions and dynamic facts have different lifetimes. On first entry,
|
|
20
|
+
new Session, Manifest/version change, or missing instructions (including after
|
|
21
|
+
compaction/recovery), read the exact Session Manifest and fully load its profile
|
|
22
|
+
and named Skills: `yui-runtime` plus the referenced `yui-leader`, `yui-worker`,
|
|
23
|
+
`yui-reviewer`, `yui-operator`, or custom Role Skills. Resolve IDs to paths and
|
|
24
|
+
versions through that Manifest, never another installed namesake. If those exact
|
|
25
|
+
same-version instructions are already fully available in current context, apply
|
|
26
|
+
them without mechanically rereading. Same Session, prior delivery, and prior
|
|
27
|
+
reads do not prove availability. The short Manifest pointer remains a recovery
|
|
28
|
+
entry, not a cache or authority receipt.
|
|
29
|
+
|
|
30
|
+
Refresh dynamic Task/Session facts before the relevant decision regardless of
|
|
31
|
+
instruction reuse. Leader notifications use the Manifest's `currentCommand`;
|
|
32
|
+
explicit AgentRuns use `loadCommand`/`expandCommand` with the actual newest
|
|
33
|
+
dispatched Run identity. Never execute `<run-id>` placeholders or substitute a
|
|
34
|
+
notification's wake ID for a Run. CLI/Controller identity, scope, Snapshot and
|
|
35
|
+
permission checks remain authoritative on every operation.
|
|
36
|
+
|
|
19
37
|
There are two normal Task entry points. A user may continue directly with the
|
|
20
38
|
current, unrevoked Leader Session: read current context using
|
|
21
39
|
`yui task context <task-id> --json`. Do not request a self-wake, reopen a Task,
|
|
@@ -167,8 +185,13 @@ and digest. A source-change error requires a fresh read, not mixing old and
|
|
|
167
185
|
new chunks. Never use a read cursor to repeat a mutation.
|
|
168
186
|
|
|
169
187
|
Read all pages of a relevant original requirement, result, or authorization
|
|
170
|
-
before acting on it. For a wake, read its complete
|
|
171
|
-
|
|
188
|
+
before acting on it. For a wake, read its complete focused input/result view and
|
|
189
|
+
relevant original Messages. `task wake show <task> <wake>` preserves the fixed
|
|
190
|
+
window and explicit older refs, deduplicates inputs, and provides exact original
|
|
191
|
+
reads. Use `--history` when window history or diagnostics is needed; unrelated
|
|
192
|
+
events and merely started Runs are not required for ordinary result disposition.
|
|
193
|
+
Follow any `contentPage` continuation for either view. The wake contains pointers
|
|
194
|
+
and attributed summaries, not complete reports.
|
|
172
195
|
For unrelated discovery, stop once the necessary evidence is found. Task
|
|
173
196
|
event deltas retain their fixed upper bound and are history, not replacement
|
|
174
197
|
current state. No read acknowledges implementation or consumes a queue.
|
|
@@ -244,6 +267,24 @@ create an InputRequest merely to solicit permission for it.
|
|
|
244
267
|
|
|
245
268
|
## Return evidence and recover within scope
|
|
246
269
|
|
|
270
|
+
When authoring a durable Message or managed final report, put a concise
|
|
271
|
+
`Yui-Summary: <one line>` first when useful for notification readers. Keep the
|
|
272
|
+
summary itself at most 512 UTF-8 bytes, and preserve material failure,
|
|
273
|
+
unverified-result, pending-decision and authority qualifications. Do this as
|
|
274
|
+
part of producing the original, not a separate model call. The optional line
|
|
275
|
+
remains part of the original text; missing or oversized summaries use factual
|
|
276
|
+
templates without blocking delivery. Core may reuse that line as explicitly
|
|
277
|
+
attributed presentation, never parse it into acceptance, review verdict or
|
|
278
|
+
Task state. A returned execution result is not completed requirements; a
|
|
279
|
+
returned review is not approval. Summaries do not replace reading full
|
|
280
|
+
requirements, results or authorizations before decisions.
|
|
281
|
+
|
|
282
|
+
Ordinary Task/Global notifications grant no new Assignment or authority and
|
|
283
|
+
require no separate execution report. Read the referenced originals and advance
|
|
284
|
+
outstanding work within existing authority under the relevant Role Skill.
|
|
285
|
+
Reading context or accepting notification delivery does not implement input.
|
|
286
|
+
Unknown delivery must not be replayed; use the recovery contract below.
|
|
287
|
+
|
|
247
288
|
Provider acceptance, Context load, AgentRun completion, and Task completion are
|
|
248
289
|
separate facts. For an explicitly dispatched managed Task AgentRun, end with one truthful
|
|
249
290
|
final report. Yui automatically correlates that native terminal with the exact
|
|
@@ -104,8 +104,9 @@ once and stop without wrappers, permission broadening, or another AgentRun targe
|
|
|
104
104
|
|
|
105
105
|
Use clear prose. A helpful default is Outcome, Changes, Verification, Risks or
|
|
106
106
|
blockers, and Recommended next action. This is a communication convention, not
|
|
107
|
-
a protocol: Yui preserves the original text and does not
|
|
108
|
-
|
|
107
|
+
a disposition protocol: Yui preserves the original text and does not reject
|
|
108
|
+
missing headings or invalid JSON. The optional `Yui-Summary:` first line
|
|
109
|
+
described in `yui-runtime` is reused only as attributed notification text.
|
|
109
110
|
|
|
110
111
|
Leave managed workspaces intact after handoff. Their owner lifecycle and
|
|
111
112
|
cleanup belong to the Leader and Yui Core.
|