@zq-silk/yui 2.22.0 → 2.23.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.
Files changed (47) hide show
  1. package/dist/cli/commandCatalog.js +2 -2
  2. package/dist/cli/updateCommand.js +20 -3
  3. package/dist/cli/updateOrchestrator.js +13 -0
  4. package/dist/cli/updatePorts.js +27 -0
  5. package/dist/commands/taskRoleRuntimeStatus.js +4 -0
  6. package/dist/context/currentSkills.js +32 -1
  7. package/dist/context/sessionBootstrapManifest.js +17 -4
  8. package/dist/context/sessionSkillNotice.js +33 -12
  9. package/dist/controller/clientRuntime.js +37 -18
  10. package/dist/controller/controller.js +16 -1
  11. package/dist/controller/fileSchedulerStoreAdapter.js +2 -0
  12. package/dist/controller/hostLifecycle.js +153 -0
  13. package/dist/controller/hostLifecycleChecks.js +27 -0
  14. package/dist/controller/hostUpgrade.js +344 -0
  15. package/dist/controller/runtime.js +67 -16
  16. package/dist/controller/sessionNotify.js +5 -46
  17. package/dist/execution/codexThreadNaming.js +54 -43
  18. package/dist/executor/fileRoleLaunchPlanner.js +18 -3
  19. package/dist/runtime/agentEndpoint.js +11 -1
  20. package/dist/runtime/agentEndpointIdentity.js +2 -0
  21. package/dist/runtime/agentHost.js +167 -42
  22. package/dist/runtime/agentHostImplementation.js +3 -1
  23. package/dist/runtime/codexAppServerRuntime.js +3 -0
  24. package/dist/runtime/codexInteractiveHost.js +62 -17
  25. package/dist/runtime/codexNativeAccess.js +1 -1
  26. package/dist/runtime/contextRecovery.js +15 -0
  27. package/dist/runtime/hostSessionLifecycle.js +83 -0
  28. package/dist/runtime/hostUpgradeGate.js +43 -0
  29. package/dist/runtime/lifecycleChecks.js +47 -0
  30. package/dist/runtime/lifecycleReservation.js +9 -1
  31. package/dist/runtime/nativeTitleReceipt.js +31 -0
  32. package/dist/runtime/nativeTitleSync.js +192 -0
  33. package/dist/runtime/providerRetry.js +4 -4
  34. package/dist/runtime/structuredProviderHost.js +42 -10
  35. package/dist/storage/sqliteSchema.js +20 -0
  36. package/dist/storage/storageVersions.js +1 -1
  37. package/docs/managed-turn-and-session-runtime.md +96 -1
  38. package/docs/managed-turn-and-session-runtime.zh-CN.md +70 -1
  39. package/docs/release-workflow.md +28 -0
  40. package/docs/release-workflow.zh-CN.md +20 -0
  41. package/docs/storage-baseline.md +10 -1
  42. package/docs/storage-baseline.zh-CN.md +5 -1
  43. package/docs/testing/verification-levels.md +2 -2
  44. package/docs/testing/verification-levels.zh-CN.md +2 -2
  45. package/package.json +1 -1
  46. package/skills/yui-runtime/SKILL.md +7 -2
  47. package/skills/yui-runtime/VERSION +1 -1
@@ -1,5 +1,6 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { randomUUID } from "node:crypto";
3
+ import { createNativeTitleSync } from "./nativeTitleSync.js";
3
4
  import { Duplex } from "node:stream";
4
5
  import { nativeExecutable } from "./nativeExecutable.js";
5
6
  import { startMissingCodexSharedDaemon } from "./codexSharedDaemon.js";
@@ -15,6 +16,7 @@ import { JsonLineChannel, PROVIDER_MESSAGE_MAX_BYTES, terminateProcessGroup } fr
15
16
  import { PROVIDER_ACCEPT_TIMEOUT_MS } from "./runtimeDeadlines.js";
16
17
  import { foldPublicReply } from "./publicReply.js";
17
18
  import { createCodexNativeAccess } from "./codexNativeAccess.js";
19
+ import { isNativeContextRecovery } from "./contextRecovery.js";
18
20
  const CODEX_PROXY_HANDSHAKE_TIMEOUT_MS = 10_000;
19
21
  /**
20
22
  * These Session implementations do not expose run-configuration observations.
@@ -396,7 +398,22 @@ class CodexStructuredProviderSession {
396
398
  onActivity;
397
399
  mirror;
398
400
  nativeAccountHome;
401
+ contextEpoch = 0;
402
+ async checkQuiescent() {
403
+ const snapshot = await this.runtime.readConversation(this.conversationId, { includeTurns: false });
404
+ if (snapshot.threadId !== this.conversationId || snapshot.status !== "idle"
405
+ || snapshot.activeTurnId !== undefined)
406
+ return false;
407
+ const backgrounds = await this.nativeAccess.read("thread/backgroundTerminals/list", {
408
+ threadId: this.conversationId, limit: 1
409
+ });
410
+ if (!Array.isArray(backgrounds.data) || !("nextCursor" in backgrounds)) {
411
+ throw new Error("Native background execution response is invalid.");
412
+ }
413
+ return backgrounds.data.length === 0 && backgrounds.nextCursor === null;
414
+ }
399
415
  appliedGeneratedTitle;
416
+ #titleSync;
400
417
  nativeAccess;
401
418
  #turnAttempts = new Map();
402
419
  adapterId = "codex";
@@ -456,16 +473,6 @@ class CodexStructuredProviderSession {
456
473
  throw error;
457
474
  }
458
475
  }
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");
468
- }
469
476
  const ownedTurn = control.kind === "restore" ? control.ownedTurn : undefined;
470
477
  // Keep notifications buffered during paginated recovery. Otherwise a live
471
478
  // terminal can be emitted before open returns and then returned again as a
@@ -521,6 +528,15 @@ class CodexStructuredProviderSession {
521
528
  }
522
529
  }
523
530
  const goal = await runtime.readGoal(conversationId);
531
+ session.#titleSync = createNativeTitleSync(payload, conversationId, session.nativeAccountHome, result => {
532
+ if (result.status === "confirmed")
533
+ session.appliedGeneratedTitle = result.title;
534
+ mirror("stderr", `Native title: ${JSON.stringify(result)}\n`);
535
+ });
536
+ void exit.then(() => session.#titleSync?.close());
537
+ // Fresh Threads may not be persisted until their first accepted input.
538
+ if (control.mode === "resume")
539
+ session.#titleSync.notify();
524
540
  return Object.freeze({
525
541
  session,
526
542
  ...(recoveredTerminal === undefined ? {} : { recoveredTerminal }),
@@ -530,6 +546,8 @@ class CodexStructuredProviderSession {
530
546
  #observeMessage(message, emit) {
531
547
  const method = typeof message.method === "string" ? message.method : "";
532
548
  const params = object(message.params) ?? {};
549
+ if (isNativeContextRecovery("codex", this.conversationId, message))
550
+ this.contextEpoch += 1;
533
551
  const threadId = optionalId(params.threadId);
534
552
  if (emit)
535
553
  this.publicReply = foldPublicReply(this.publicReply, this.conversationId, method, params);
@@ -539,6 +557,13 @@ class CodexStructuredProviderSession {
539
557
  }
540
558
  return undefined;
541
559
  }
560
+ if (method === "thread/name/updated") {
561
+ this.#titleSync?.close();
562
+ if (params.threadName !== this.appliedGeneratedTitle)
563
+ this.appliedGeneratedTitle = undefined;
564
+ }
565
+ if (method === "turn/started")
566
+ this.#titleSync?.notify();
542
567
  let goal;
543
568
  try {
544
569
  goal = codexGoalNotification({ method, params });
@@ -663,6 +688,7 @@ class CodexStructuredProviderSession {
663
688
  conversationId: this.conversationId,
664
689
  attemptId: turn.attemptId,
665
690
  text: turn.boundedText,
691
+ ...(turn.additionalContext === undefined ? {} : { additionalContext: turn.additionalContext }),
666
692
  expectedNoActiveTurn: true,
667
693
  ...(turn.requireQuiescent ? { requireQuiescent: true } : {}),
668
694
  ...(turn.expectedFailedNativeTurnId === undefined ? {} : {
@@ -682,6 +708,7 @@ class CodexStructuredProviderSession {
682
708
  this.#clientOwnedTurnId = acceptance.turnId;
683
709
  this.#clientOwnedAttemptId = turn.attemptId;
684
710
  this.#turnAttempts.set(acceptance.turnId, turn.attemptId);
711
+ this.#titleSync?.notify();
685
712
  return Object.freeze({
686
713
  attemptId: turn.attemptId,
687
714
  conversationId: this.conversationId,
@@ -712,6 +739,7 @@ class CodexStructuredProviderSession {
712
739
  conversationId: this.conversationId,
713
740
  expectedTurnId: nativeTurnId,
714
741
  text: turn.boundedText,
742
+ ...(turn.additionalContext === undefined ? {} : { additionalContext: turn.additionalContext }),
715
743
  clientUserMessageId: turn.attemptId
716
744
  });
717
745
  if (acceptance.status === "unknown") {
@@ -776,6 +804,7 @@ class CodexStructuredProviderSession {
776
804
  return result === "interrupted" ? "requested" : result;
777
805
  }
778
806
  terminate(signal) {
807
+ this.#titleSync?.close();
779
808
  terminateProcessGroup(this.child, signal);
780
809
  }
781
810
  }
@@ -787,6 +816,7 @@ class ClaudeStructuredProviderSession {
787
816
  channel;
788
817
  onGoal;
789
818
  mirror;
819
+ contextEpoch = 0;
790
820
  adapterId = "claude";
791
821
  get ownedProcessId() { return this.child.pid; }
792
822
  #activeAttemptId;
@@ -903,6 +933,8 @@ class ClaudeStructuredProviderSession {
903
933
  terminateProcessGroup(this.child, signal);
904
934
  }
905
935
  #receive(message, onTerminal, onAccepted, onActivity) {
936
+ if (isNativeContextRecovery("claude", this.conversationId, message))
937
+ this.contextEpoch += 1;
906
938
  const goal = claudeActiveGoal(message, this.conversationId);
907
939
  if (goal !== undefined) {
908
940
  const key = JSON.stringify(goal === null ? null : {
@@ -295,6 +295,26 @@ const MINOR_UPGRADES = Object.freeze([{
295
295
  targetChecksum: CURRENT_SCHEMA_CHECKSUM,
296
296
  // Optional workspace-write permission fields; preserve all existing payloads.
297
297
  sql: ""
298
+ }, {
299
+ fromVersion: "1.26",
300
+ toVersion: "1.27",
301
+ name: "host-upgrade-lifecycle-signals",
302
+ introducedIn: "next",
303
+ sourceChecksum: CURRENT_SCHEMA_CHECKSUM,
304
+ targetChecksum: CURRENT_SCHEMA_CHECKSUM,
305
+ // New versioned signal sources in the existing role-runtime mailbox. No
306
+ // historical requests are inferred and existing records remain unchanged.
307
+ sql: ""
308
+ }, {
309
+ fromVersion: "1.27",
310
+ toVersion: "1.28",
311
+ name: "native-title-effect-receipts",
312
+ introducedIn: "next",
313
+ sourceChecksum: CURRENT_SCHEMA_CHECKSUM,
314
+ targetChecksum: CURRENT_SCHEMA_CHECKSUM,
315
+ // Additive exact-identity intent/confirmation files under runtime/native-titles.
316
+ // Never invent native ownership or replay history during migration.
317
+ sql: ""
298
318
  }]);
299
319
  export function storageMinorUpgradePlan(from) {
300
320
  if (from === CURRENT_STORAGE_VERSION)
@@ -1,4 +1,4 @@
1
- export const CURRENT_STORAGE_VERSION = "1.26";
1
+ export const CURRENT_STORAGE_VERSION = "1.28";
2
2
  export const MIN_SUPPORTED_STORAGE_VERSION = "1.0";
3
3
  export const STORAGE_FORMAT = "yui-home";
4
4
  export function isStorageVersion(value) {
@@ -2,6 +2,99 @@
2
2
 
3
3
  # Session, AgentRun and notifications
4
4
 
5
+ ## Two lifecycle layers and nonblocking checks
6
+
7
+ Controller custody of a Host and the Host's native Session lifecycle have
8
+ separate event/guard/transition tables. Neither is an upgrade workflow.
9
+
10
+ | Layer | Events and transitions | Authority and correlation |
11
+ | --- | --- | --- |
12
+ | Controller → Host | Fresh physical observations recover `unavailable`/`stopped`/`starting`/`running`. Authorized launch enters `starting`; matching launch handshake enters `running`. Stop or graceful-exit request enters `stopping`; sending exit does not prove `stopped`. Physical absence confirms `stopped`; unknown effects enter `unavailable`. | Owner, local operation/revision, returned binding and native Session ID. Durable Role/Task intent, launch reservations and exact process custody remain authoritative. |
13
+ | Host → native Session | Launch, attachment, input acceptance, native activity, terminal, persistence, disconnect and exit drive the native states described below. | Native Session, proxy process, attempt and Turn identity; existing writer/resource fences still authorize effects. |
14
+
15
+ The Controller wraps the shared Host port for launch/restore, observation and
16
+ stop, including graceful-upgrade exit. A competing physical operation is
17
+ rejected before its side effect, not queued or replayed by this FSM. Late
18
+ reads and old bindings cannot overwrite newer custody; identical observations
19
+ produce no hook feedback loop. A Controller restart reconstructs by observation,
20
+ never by replaying the process-local state. Native completion/attachment exit
21
+ does not prove Host process exit. Legal same-conversation resume correlates the
22
+ layers without sharing their state enums or inventing another durable authority.
23
+
24
+ Host-side native Session lifecycle state is owned by an explicit transition table, not
25
+ by version detection. Launch/submit enters `starting`; attachment facts select
26
+ `idle`, `busy`, `ready` (owned input), or `delivery-unknown`; acceptance enters
27
+ `ready`; native execution enters `busy`; terminal handling enters `settling`;
28
+ persisted settlement returns to observed `idle`/`busy`. Disconnect enters
29
+ `starting`, classified failures retain their failure outcome, and exit enters
30
+ `exited`. Only an explicit launch can leave `exited`. Native-TUI attachment
31
+ readiness has its own event: `ready` there is not proof of native quiescence.
32
+ Illegal edges do not mutate state; stale process, attempt and terminal-Turn
33
+ facts are ignored. Exact writer/resource guards remain at command admission.
34
+ This process-local reducer reconstructs from existing launch and native facts;
35
+ it adds no persisted Session authority or upgrade workflow state machine.
36
+
37
+ Optional before/after observations are immutable, deferred and independently
38
+ coalesced (at most one running and one latest pending observation per check).
39
+ “Before” describes the transition's source, not an awaited precondition.
40
+ A slow or failing check cannot veto a transition or hold event folding/input
41
+ delivery; checks must yield for I/O and honour cancellation before effects.
42
+ They may recommend work to the separate fenced upgrade coordinator.
43
+ Controller Host-state hooks suggest version reconciliation. Host Session-state
44
+ hooks asynchronously observe current Skill metadata on attachment/settlement,
45
+ without reading Skill bodies, committing a notice or assuming model memory.
46
+ The exact per-input integrity check remains an ingress safeguard: invalid
47
+ Skills can reject that input, but an optional check cannot stall lifecycle.
48
+ Only accepted input advances the existing notice baseline; unchanged input
49
+ is passed through without any extra content.
50
+
51
+ Controller startup, Host connection/exit observations, Host state-change
52
+ signals and event persistence trigger version checks without an explicit
53
+ `update` request. Existing periodic reconciliation covers missed hints,
54
+ including providers without reliable background-execution-end events and
55
+ graceful exits that cannot emit a post-exit hint. Checks
56
+ compare actual loaded Host/Endpoint implementations with this Controller's
57
+ loaded target, never npm `latest`. Incomplete readiness on matching versions
58
+ is not an upgrade reason. Checks stop on shutdown; already-admitted work
59
+ retains the existing durable mailbox. A request pinned to a different target
60
+ stays waiting for explicit recovery, not silent retargeting. An explicitly
61
+ stopped Session is never restarted by a check.
62
+
63
+ ## Host upgrade and context checks
64
+
65
+ `update` reports package installation, verified Controller startup and each
66
+ Host separately. `update --hosts-status` reads current per-Host evidence without
67
+ installing, starting or advancing a switch. Supported controlled Codex Hosts fence new input immediately,
68
+ wait for the current native Turn and event persistence, inspect native background
69
+ execution, and release their owned Endpoint before exiting gracefully. The
70
+ existing role-runtime mailbox retains the exact generation, native Session,
71
+ configuration digest and drain receipt across Controller restarts. A successor
72
+ uses the recorded effective configuration and resumes that same conversation;
73
+ only its loaded Host/Endpoint and control/event handshake confirm success.
74
+ Queued Messages remain original and accepted/unknown inputs are never replayed.
75
+
76
+ Paused Roles stay paused. Older Hosts, native-TUI-only attachments and Endpoints
77
+ without a quiescence capability are retained with an unsupported diagnosis; no
78
+ unsupported drain command is sent. A busy/unknown native execution has no
79
+ bounded upgrade-completion promise. An uncertain launch is not automatically
80
+ repeated; a later exact successful handshake can settle the retained request.
81
+ This fence covers Host-controlled ingress, not arbitrary external native clients;
82
+ it never terminates a shared daemon or native conversation.
83
+
84
+ Host Skill checks still run before every input. Unchanged inputs are passed
85
+ through exactly, with no notice, marker, separator or extra native input part.
86
+ The attachment's loading guidance explains this managed-input contract; no
87
+ notice is not a reason to repeat the check. Unmediated clients or uncertain
88
+ current input routing retain the explicit Manifest check fallback; reusing a
89
+ conversation alone does not establish Host mediation. Cold attachment,
90
+ affected Skill changes and observed native compaction supply loading guidance;
91
+ compaction invalidates the next input's metadata baseline. Without a reliable
92
+ native event, the Agent must still recover any missing instructions using the
93
+ Manifest. Neither a version nor an accepted notice proves model memory.
94
+ Routine checks and empty inboxes are not user-facing progress.
95
+
96
+ ## Session stop and runtime observations
97
+
5
98
  Global Session stop/replacement uses the same exact native-execution quiescence
6
99
  boundary as Task Sessions. A departed Host or archived Session alone is not
7
100
  proof that an accepted input ended: its retained Provider binding is inspected
@@ -31,7 +124,9 @@ Samples use a process-monotonic clock and hashed target/request labels, with
31
124
  at most 16 recent and 16 active samples plus the slowest completed sample.
32
125
  In-flight request count is not queue depth; total client-to-route wait is not
33
126
  measured by the server alone. These observations neither identify an old incident
34
- retroactively nor establish quiescence; restarting a Controller does not refresh live Hosts.
127
+ retroactively nor establish quiescence. A Controller restart does not itself
128
+ prove Host replacement; asynchronous lifecycle checks still require a safe
129
+ drain and the successor's actual handshake.
35
130
 
36
131
  `observations.commands.routes.transport` correlates socket accept-to-route,
37
132
  complete-frame receive-to-route and route-to-local-flush stages by the same
@@ -2,6 +2,74 @@
2
2
 
3
3
  # Session、AgentRun 与通知
4
4
 
5
+ ## 两层生命周期与非阻塞检查
6
+
7
+ Controller 对 Host 的管理状态、Host 对原生 Session 的生命周期分别拥有自己的
8
+ 事件、guard 和转换表,都不是升级流程状态机。
9
+
10
+ | 层级 | 事件与转换 | 权限及关联 |
11
+ | --- | --- | --- |
12
+ | Controller → Host | 新鲜物理观测恢复 `unavailable`/`stopped`/`starting`/`running`;合法 launch 进入 `starting`,匹配启动握手进入 `running`。停止或优雅退出请求进入 `stopping`,发送退出不证明 `stopped`;物理不存在才确认 `stopped`,未知效果进入 `unavailable`。 | owner、本地操作/观测 revision、返回 binding 和原生 Session ID;持久 Role/Task 意图、启动 reservation 和精确进程权属仍是权威。 |
13
+ | Host → 原生 Session | launch、附件、输入接受、原生活动、终态、持久化、断连和退出驱动下述原生状态。 | 原生 Session、proxy 进程、attempt 和 Turn 身份;原有 writer/资源栅栏继续授权副作用。 |
14
+
15
+ Controller 在共享 Host port 处统一管理启动/恢复、观测与停止(含安全升级的优雅退出)。
16
+ 冲突物理操作在副作用前拒绝,不由状态机另建队列或重放。迟到读取和旧 binding 不能覆盖
17
+ 新管理状态;相同观测不重复触发检查反馈循环。Controller 重启后从观测重建,
18
+ 不重放进程内状态。原生轮次完成或附件退出不能证明 Host 进程已退出;
19
+ 合法恢复通过同一原生对话关联两层,不共用状态枚举或新增持久权威。
20
+
21
+ Host 内的原生 Session 生命周期由明确的转换表管理,不由版本检查管理。
22
+ launch/submit 进入 `starting`;附件事实选择 `idle`、`busy`、
23
+ `ready`(持有输入)或 `delivery-unknown`;接受输入进入 `ready`;
24
+ 原生执行进入 `busy`;终态处理进入 `settling`;持久化结清后回到观测到的
25
+ `idle`/`busy`。断连进入 `starting`,分类失败保留对应失败状态,退出进入
26
+ `exited`,只有显式 launch 可离开它。原生 TUI 附件就绪有独立事件,
27
+ 其 `ready` 不证明原生执行静止。非法边不改变状态;过期的进程、attempt、
28
+ 终态 Turn 事实被忽略。精确 writer/资源 guard 仍在命令准入处执行。
29
+ 状态机仅在进程内从现有 launch 和原生事实恢复,不新增持久 Session 权威或升级流程状态机。
30
+
31
+ 可组合的前/后检查接收不可变观测,各自异步执行并合并重复提示
32
+ (每项最多一个执行中和一个最新待处理观测)。“前”表示转换来源,不是等待完成的前置条件。
33
+ 慢检查或失败不能否决转换、阻塞事件折叠或输入投递;检查回调必须异步等待 I/O,
34
+ 并在请求副作用前响应取消。它们只能向独立的、受精确栅栏保护的升级协调器提出请求。
35
+ Controller 的 Host 状态 hook 提议版本对账;Host 的 Session 状态 hook 在附件和结清时
36
+ 异步观测当前 Skill 元数据,不读正文、不提交通知基线、不假定模型记忆。
37
+ 逐输入完整性核验仍是投递安全门:无效 Skill 可以拒绝该次输入,但可选检查不能卡住生命周期。
38
+ 仍只有被接受的输入推进通知基线,未变化输入原样通过,不额外注入内容。
39
+
40
+ Controller 启动、Host 连接/退出观测、Host 状态变化 signal 和事件持久化均可触发版本检查,
41
+ 不依赖显式 `update`。现有周期对账覆盖丢失提示、无法可靠提供后台执行结束事件的提供方,
42
+ 以及无法在退出后发出提示的优雅退出。
43
+ 比较对象是实际加载的 Host/Endpoint 实现与当前 Controller 已加载的目标,不查询 npm `latest`。
44
+ 版本匹配但就绪证据未齐不是升级理由。关闭时停止检查,已准入工作仍保留现有持久 mailbox;
45
+ 请求固定的目标与当前 Controller 不同时保持等待,交由显式恢复,不静默改目标。
46
+ 检查不会复活明确停止的 Session。
47
+
48
+ ## Host 升级与上下文检查
49
+
50
+ `update` 分别报告程序安装、Controller 启动核验及逐 Host 的状态。
51
+ `update --hosts-status` 只读查询逐 Host 证据,不安装、启动或推进切换。支持此能力的
52
+ 受控 Codex Host 先关闭新输入准入,等待当前原生轮次和事件持久化、核验后台执行,
53
+ 释放自己持有的 Endpoint 后优雅退出。现有 role-runtime mailbox 保存精确实现代际、
54
+ native Session、配置摘要和排空回执,Controller 重启后仍可继续。
55
+ 后继使用原 effective 配置接回同一对话;实际加载的 Host/Endpoint、控制与事件能力
56
+ 握手通过后才确认成功。队列中的 Message 原文不变,不重放 accepted 或 unknown 输入。
57
+
58
+ 暂停角色保持暂停。旧 Host、仅有原生 TUI 的附件及不能证明静止的 Endpoint
59
+ 保留并报告不支持,不反复发送不支持的排空命令。忙碌或未知执行不承诺限时升级。
60
+ 启动结果未知不自动重放;后续精确成功握手可结清原请求。
61
+ 准入栅栏覆盖 Host 控制的入口,不控制任意外部原生客户端,也不会终止共享 daemon 或原生对话。
62
+
63
+ Host 仍逐输入机械检查 Skills。未变化时原文原样通过,不添加检查通知、隐藏标记、
64
+ 分隔换行或原生输入片段。附件加载指引说明这一托管输入约定,不因没有通知而重复检查。
65
+ 绕过 Host 的客户端或当前输入路由不明时仍通过 Manifest 显式检查;复用同一对话
66
+ 本身不证明当前输入受 Host 托管。首次附件、局部 Skill 变化、已观测到的原生压缩
67
+ 提供相应加载指引;压缩使下一次输入的元数据基线失效。
68
+ 提供方无法可靠暴露事件时,Agent 仍须通过 Manifest 恢复缺失指令。
69
+ 版本和已接受的通知都不能证明模型记忆;例行检查、角色版本和空 inbox 不作为用户进度播报。
70
+
71
+ ## 会话停止与运行时观测
72
+
5
73
  局部停止等待自身的持久清理义务完成,不等待整个 Home 的 `scheduler.scan`
6
74
  循环排空。signal 只请求调度;完成仍以现有物理停止证明及清理事务为准。
7
75
  超时保留义务并阻止替换;选择失败和新会话启动未确认分别报告,不允许重放未知效果。
@@ -16,7 +84,8 @@ interrupt-owned 输入仍保留原处理路径。
16
84
  目标/请求标签仅保存哈希;每组最多保留 16 个近期样本、16 个活动样本及最慢完成样本。
17
85
  in-flight 请求数不是排队数,服务端不能独自测量客户端到路由的完整等待。
18
86
  观测不能反推旧事故的唯一根因,
19
- 也不构成静止证明;重启 Controller 不会刷新存活 Host。
87
+ 也不构成静止证明;Controller 重启本身不证明 Host 已替换,
88
+ 异步生命周期检查仍须经过安全排空和后继实际握手。
20
89
 
21
90
  `observations.commands.routes.transport` 使用与 route service time 相同的请求哈希,
22
91
  分别关联 socket accept→route、完整帧 receive→route、route→本地 flush。
@@ -51,6 +51,34 @@ 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.23.0 compatibility and migration notes
55
+
56
+ Host upgrades use explicit lifecycle signals and safe drain/reattachment
57
+ boundaries without replaying business input or replacing native identity.
58
+ Routine Skill checks remain inside the Host; unchanged Turns carry no Skill
59
+ notice. Cold attachment, explicit context loss/compaction and changed Skills
60
+ provide only the current loading pointers.
61
+
62
+ Codex keeps original user input separate from application context on start and
63
+ steer. Failed-Turn recovery does not duplicate the original input or imply lost
64
+ Skill context. This requires the native `additionalContext` contract verified
65
+ against Codex CLI 0.159.2; older native implementations are not covered and there
66
+ is no fallback that reinserts metadata into user input.
67
+
68
+ Native titles reuse the Role/Task/Draft/instance format through an independent,
69
+ bounded metadata process, never blocking Startup, Goal or Turn. Exact identity,
70
+ persisted intent and native readback distinguish confirmed naming from unknown
71
+ effects. Observed manual names are preserved; unknown writes are not replayed.
72
+ Historical polluted names without ownership evidence are diagnosed, not renamed.
73
+ The native naming API has no compare-and-swap, so a final concurrent external
74
+ rename cannot be protected atomically.
75
+
76
+ Storage advances to **1.28**, preserving **1.26 → 1.27** Host-upgrade signals and
77
+ adding **1.27 → 1.28** native-title receipts without rewriting history. Back up
78
+ the Home and use the normal upgrade/migration path; do not open a migrated Home
79
+ with an older binary. Controller/Host protocols remain v1. Publishing does not
80
+ update the global CLI, migrate production data or restart shared services.
81
+
54
82
  ### 2.22.0 compatibility and migration notes
55
83
 
56
84
  Context reads now support bounded discovery, precise batched original retrieval,
@@ -36,6 +36,26 @@ Agent 选择一个预先声明的计划,设施从持久状态驱动该计划
36
36
  不能将不兼容冒称为兼容,也不为回避版本选择新增历史兼容机制。包版本与协议、
37
37
  持久存储契约仍然独立:兼容性检查和必要迁移要求不变,下文存储规则不授予发版权限。
38
38
 
39
+ ### 2.23.0 兼容性及迁移说明
40
+
41
+ Host 升级使用明确的生命周期信号及安全排空/重新挂接边界,不重放业务输入、
42
+ 不替换原生会话身份。常规 Skill 检查保留在 Host 内,未变化的 Turn 不携带
43
+ Skill 提示;仅首次挂接、明确上下文丢失/压缩及 Skill 变化提供当前加载指针。
44
+
45
+ Codex 的 start/steer 将用户原文与应用上下文分离。失败 Turn 恢复不复制原文,
46
+ 也不视为 Skill 上下文丢失。此路径要求原生 `additionalContext` 契约,已核对
47
+ Codex CLI 0.159.2;旧原生实现不在验证范围内,不提供把元信息塞回用户输入的回退。
48
+
49
+ 原生标题复用 Role/Task/Draft/实例格式,通过独立、有界的元数据进程同步,
50
+ 不阻塞 Startup、Goal 或 Turn。精确身份、持久化意图和原生读回区分成功与未知效果。
51
+ 保留已观测到的手动命名,未知写入不重放;缺乏归属证据的历史污染标题只诊断、不改名。
52
+ 原生命名 API 没有 compare-and-swap,无法原子保护最后读写窗口内的外部并发改名。
53
+
54
+ 存储升级至 **1.28**:保留 **1.26 → 1.27** Host 升级信号迁移,追加
55
+ **1.27 → 1.28** 原生标题回执,不改写历史。升级前备份 Home,使用正常升级/迁移
56
+ 路径,不要用旧二进制打开已迁移的 Home。Controller/Host 协议仍为 v1。
57
+ 发布本身不更新全局 CLI、不迁移生产数据,也不重启共享服务。
58
+
39
59
  ### 2.22.0 兼容性及迁移说明
40
60
 
41
61
  上下文读取增加有界发现、精确批量原文读取、正文传输回执及聚焦通知。
@@ -2,7 +2,16 @@
2
2
 
3
3
  # Storage baseline 1.0
4
4
 
5
- Current storage is 1.26. The 1.25 → 1.26 transition admits optional Codex
5
+ Current storage is 1.28. The 1.27 → 1.28 transition admits exact-identity native
6
+ title effect receipts under `runtime/native-titles`. It does not infer historical
7
+ title ownership, rename conversations, or change existing database payloads.
8
+ Unconfirmed naming intents remain non-replayable across Host replacement.
9
+
10
+ The 1.26 → 1.27 transition admits versioned Host-upgrade
11
+ signals in the existing role-runtime mailbox. It adds no table, infers no past
12
+ upgrade request, and preserves existing payloads. Drain receipts precede Host
13
+ exit; a Controller restart resumes the exact request, not business input.
14
+ The 1.25 → 1.26 transition admits optional Codex
6
15
  workspace-write temporary-directory exclusions without changing historical
7
16
  permission payloads. The published 1.24 → 1.25 transition remains unchanged
8
17
  and admits optional Role
@@ -2,7 +2,11 @@
2
2
 
3
3
  # 存储基线 1.0
4
4
 
5
- 当前存储为 1.26。1.25 → 1.26 增加 Codex workspace-write 可选临时目录排除字段,不改写历史权限 payload。已发布的 1.24 → 1.25 定义保持不变:增加可选 Role `instanceCode` 和 Session `generatedTitle` 展示字段,不回填历史标题来源或实例码,不改写既有记录。1.23 → 1.24 为调度器的九类来源表增加事务维护的 Task 读取缓存修订号。插入、更新和删除只使对应 Task 的缓存失效,回滚同时回滚修订号。该值仅是派生缓存标识,不是 Task 权限或 Home revision CAS 的替代。历史 payload 不变,旧 Task 在首次修改前使用隐含的零修订号。
5
+ 当前存储为 1.28。1.27 → 1.28 声明 `runtime/native-titles` 下绑定精确会话身份的原生标题意图与回执;迁移不认领历史标题、不改名、不改写既有数据库 payload。未确认改名意图在 Host 替换后也不得重放。
6
+
7
+ 1.26 → 1.27 允许现有 role-runtime mailbox 保存版本化 Host 升级信号,不新增表、不推断历史升级请求、不改写既有 payload。排空回执先于 Host 退出持久化;Controller 重启继续精确升级请求,不重放业务输入。
8
+
9
+ 1.25 → 1.26 增加 Codex workspace-write 可选临时目录排除字段,不改写历史权限 payload。已发布的 1.24 → 1.25 定义保持不变:增加可选 Role `instanceCode` 和 Session `generatedTitle` 展示字段,不回填历史标题来源或实例码,不改写既有记录。1.23 → 1.24 为调度器的九类来源表增加事务维护的 Task 读取缓存修订号。插入、更新和删除只使对应 Task 的缓存失效,回滚同时回滚修订号。该值仅是派生缓存标识,不是 Task 权限或 Home revision CAS 的替代。历史 payload 不变,旧 Task 在首次修改前使用隐含的零修订号。
6
10
  同时增加两个局部索引,支持按精确运行观测身份查找,不再扫描或反序列化历史观测集合。
7
11
 
8
12
  1.22 → 1.23 新增全局 Shell Job、版本化脚本文件及每次运行的配置快照,不改写已有 Job、计划和历史记录。
@@ -53,12 +53,12 @@ is required.
53
53
  Both include `test/core` and `test/platform`. For an already built checkout,
54
54
  `npm run test:business` runs only `test/core` and `npm run test:platform` runs
55
55
  only `test/platform`; neither rebuilds. CI owns one explicit build per job.
56
- The stable suite owns current storage 1.26 and its declared 1.0 through 1.25 minor
56
+ The stable suite owns current storage 1.28 and its declared 1.0 through 1.27 minor
57
57
  transition. It contains no undeclared historical format compatibility path.
58
58
 
59
59
  Current coverage includes:
60
60
 
61
- 1. Fresh storage 1.26, exact schema/record validation, no initialization over
61
+ 1. Fresh storage 1.28, exact schema/record validation, no initialization over
62
62
  unknown data, and rejection of old integer formats without mutation.
63
63
  2. Exact-version staging, mismatched-target refusal, same-major contiguous
64
64
  minor preflight, explicit maintenance-owner identity across handover, and
@@ -39,12 +39,12 @@ Yui 是一个单用户本地产品。永久验证保护关键的 happy path 和
39
39
  两者均包含 `test/core` 和 `test/platform`。已构建的 checkout 可分别运行
40
40
  `npm run test:business` 与 `npm run test:platform`,它们不会再次构建。
41
41
  CI 每个作业只显式构建一次。
42
- 稳定套件维护当前存储 1.26 和明确声明的 1.0 至 1.25 连续小版本迁移,
42
+ 稳定套件维护当前存储 1.28 和明确声明的 1.0 至 1.27 连续小版本迁移,
43
43
  不包含未声明的历史格式兼容路径。
44
44
 
45
45
  当前覆盖包括:
46
46
 
47
- 1. 新建存储 1.26、精确结构与记录校验、禁止覆盖未知数据库、无修改拒绝旧整数格式。
47
+ 1. 新建存储 1.28、精确结构与记录校验、禁止覆盖未知数据库、无修改拒绝旧整数格式。
48
48
  2. 精确版本暂存、目标不匹配拒绝、同主版本连续小版本预检、交接锁显式所有者,
49
49
  以及恢复时核对捕获的协议和存储身份,不接受缺失字段。
50
50
  3. 持久 Task/Message/Decision 上下文、Draft 激活权威、mailbox 认领、
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zq-silk/yui",
3
- "version": "2.22.0",
3
+ "version": "2.23.0",
4
4
  "description": "Local control plane for long-running native agent CLI sessions backed by tmux.",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -13,9 +13,14 @@ Resolve links relative to their containing file.
13
13
  ## Keep the current working set
14
14
 
15
15
  The managed Host mechanically checks current Skill VERSION/readability for each
16
- input. Use its short check result/current pointers; do not duplicate that check.
17
- Without a Host check, run the Manifest's `contextProtocol.skillCheckCommand`
16
+ input. It injects guidance only when loading is needed; unchanged inputs carry
17
+ no notice or marker. Do not duplicate the Host's check merely because no notice
18
+ appears. For unmediated clients or uncertain current input routing, run the
19
+ Manifest's `contextProtocol.skillCheckCommand`
18
20
  (older Manifests: `yui session skills --json`) through the intended CLI/Home.
21
+ Conversation reuse alone does not establish Host mediation. Keep routine
22
+ role/Skill checks and empty-inbox observations internal; only report business
23
+ progress or actionable failures.
19
24
  Global `loadCommand` includes the check. Recheck after repair/relevant change.
20
25
 
21
26
  A check is metadata, not bodies, remembered instructions, a loading receipt or
@@ -1 +1 @@
1
- 44
1
+ 46