@zq-silk/yui 0.13.5 → 0.13.6

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/ARCHITECTURE.md CHANGED
@@ -254,21 +254,21 @@ Yui's current attachment, not exclusive ownership of the Provider thread. One
254
254
  Turn identifies one provider-native execution. Yui's authority epoch fences
255
255
  only Yui's own submissions and retries.
256
256
 
257
- Codex Task threads can be opened and used directly in Desktop as ordinary
258
- sessions; no Yui takeover is required. If a direct user Turn is active, Yui
259
- keeps its pending Run/message and retries after that Turn settles. The explicit
260
- tmux takeover gateway remains for providers whose managed conversation is
261
- attached to an independent process. Global interactive entry remains a native
262
- session-lifecycle operation outside the Task delivery contract.
263
-
264
- Codex uses `app-server proxy` to create or resume a normal thread on the shared
265
- App Server daemon. Role model, effort, permission, workspace, and shell settings are passed at
257
+ Codex Task threads remain ordinary native sessions and can be inspected in
258
+ Desktop. While their managed Role runtime is live, writes go through Yui's
259
+ view/takeover boundary; stop Task execution before resuming the thread from a
260
+ different client. If Yui observes a pre-existing active Turn during resume, it
261
+ keeps its pending Run/message until that Turn settles. Global interactive entry
262
+ remains a native session-lifecycle operation outside the Task delivery contract.
263
+
264
+ Codex uses a Yui-owned direct `app-server` child to create or resume a normal
265
+ thread. The process loads the selected native config profile; Role model,
266
+ effort, permission, workspace, and shell settings are passed at
266
267
  `thread/start`/`thread/resume`, while the ordinary Task message points to the
267
268
  Session Manifest and matching Role Skill. Yui does not write either to global
268
- Codex config and may only ensure that the daemon is running; it never restarts
269
- or stops it for a thread error. A Codex native config profile is rejected for
270
- Managed Codex because the protocol cannot isolate it to one thread; a Yui Agent
271
- Profile supplies the per-Role behavior, Skills, model, and effort instead.
269
+ Codex config. The Agent Host owns the Provider process group, so Task execution
270
+ stop can end the complete runtime and start can rebuild it without depending on
271
+ the shared Codex daemon.
272
272
  Claude uses a persistent stream-json
273
273
  transport with exact user-message replay acknowledgement. In both cases, Yui
274
274
  records Turn intent before writing, accepts only exact Provider evidence, and
package/README.md CHANGED
@@ -875,13 +875,13 @@ Provider conversations remain ordinary user conversations. Yui adds the Role
875
875
  Skill and Session Manifest pointer, then sends Task work through provider-native
876
876
  structured requests. Managed prompts are never delivered as terminal bytes.
877
877
 
878
- Codex uses `app-server proxy` to create or resume a normal thread on the shared
879
- App Server daemon. The thread is visible and directly usable in Desktop; Yui
880
- does not require takeover or install global Hook/config state. It may
881
- idempotently start an absent daemon, but never restarts or stops it for a thread
882
- error. When a user Turn is active, Yui keeps pending Task work and retries
883
- later. If Yui's proxy disconnects, the Host reattaches without ending the
884
- logical Activation and reconciles the exact owned Turn from native history.
878
+ Codex uses a direct, Yui-owned `app-server` child to create or resume a normal
879
+ thread. The thread remains visible in Codex, while Yui's view/takeover boundary
880
+ is the supported way to interact with a live managed Role. Task execution stop
881
+ terminates the Agent Host and its Provider process group; start creates a fresh
882
+ owned runtime without depending on the shared Codex daemon. If the child
883
+ disconnects, the Host may start a bounded replacement process and reconcile the
884
+ exact owned Turn from native history.
885
885
  Claude Code keeps its independent stream-json process with exact
886
886
  user-message replay acknowledgement. A timeout or uncertain write becomes
887
887
  `delivery-unknown` and is never automatically retried.
@@ -894,10 +894,9 @@ yui task role takeover <task-id> <role>
894
894
  yui task role release <task-id> <role>
895
895
  ```
896
896
 
897
- For Codex, open the Role's ordinary thread in Desktop for direct interaction;
898
- these commands are not required. `view`/`takeover`/`release` remain the explicit
899
- PTY gateway for providers whose managed conversation uses an independent
900
- process.
897
+ For a live managed Role, including Codex, these commands are the supported
898
+ human-control boundary. Its ordinary native thread remains inspectable in
899
+ Codex; stop Task execution before resuming it from a different client.
901
900
 
902
901
  Global Operator and global Role sessions remain native interactive CLIs:
903
902
 
@@ -962,7 +961,7 @@ movement cannot conceal a workflow that is not advancing.
962
961
 
963
962
  Stable Role context never creates a separate bootstrap Turn. Task execution Runs use the generic Leader or Worker Skill, while review Runs use the generic Reviewer Skill based on durable Run purpose rather than a configured Role name. The provider either carries the Skill through a safe additive native context channel or points to it from the ordinary Task delivery. These Yui-owned Role Skills define portable orchestration only. Project Skills remain ordinary versioned files in the Project and are discovered, selected, and loaded by the Agent through its native project mechanism; Yui does not scan, parse, copy, or inject them.
964
963
 
965
- Managed Codex keeps the user's native developer instructions unchanged. The ordinary Task message includes a compact absolute Session Manifest pointer, and the manifest identifies the matching Yui-owned Role Skill for Codex to read on demand. Model, effort, permission, workspace, and shell settings selected for the Role are supplied as thread-scoped `thread/start` or `thread/resume` configuration through the shared App Server daemon. A Codex native config profile cannot be isolated to one shared-daemon thread, so Managed Codex rejects that setting and directs callers to a Yui Agent Profile; ordinary non-Yui and interactive Codex sessions remain unaffected. Unrelated Codex threads keep their existing user, profile, project, and system configuration and the underlying config file is never mutated. App Server notifications are the managed thread's lifecycle authority; Yui installs no managed Codex Hook and does not claim `notify`. Interactive Codex Sessions may still use Yui's structured `notify` callback, and Doctor reports any effective configuration conflict. `skills.config` is not misused because it only enables or disables already-discovered Skills. Claude receives the same Yui-owned Role Skill content from a private `0600` managed context file rather than a large or sensitive argv value; retries and resumes reuse the purpose-specific Role path. Non-Operator global Roles stay neutral and receive no Task orchestration Skill. Operator therefore opens at an empty native composer, so the user's text remains its first user message. Leader wakeups and Worker or Reviewer Run assignments remain real mailbox-delivered work messages.
964
+ Managed Codex keeps the user's native developer instructions unchanged. The ordinary Task message includes a compact absolute Session Manifest pointer, and the manifest identifies the matching Yui-owned Role Skill for Codex to read on demand. Its Yui-owned App Server process loads any selected Codex native config profile; model, effort, permission, workspace, and shell settings are supplied to `thread/start` or `thread/resume`, and the underlying Codex config file is never mutated. App Server notifications are the managed thread's lifecycle authority; Yui installs no managed Codex Hook and does not claim `notify`. Interactive Codex Sessions may still use Yui's structured `notify` callback, and Doctor reports any effective configuration conflict. `skills.config` is not misused because it only enables or disables already-discovered Skills. Claude receives the same Yui-owned Role Skill content from a private `0600` managed context file rather than a large or sensitive argv value; retries and resumes reuse the purpose-specific Role path. Non-Operator global Roles stay neutral and receive no Task orchestration Skill. Operator therefore opens at an empty native composer, so the user's text remains its first user message. Leader wakeups and Worker or Reviewer Run assignments remain real mailbox-delivered work messages.
966
965
 
967
966
  ## Controller and failure handling
968
967
 
@@ -150,10 +150,6 @@ class CodexAdapter extends BaseAdapter {
150
150
  }
151
151
  compileManagedControl(input, _mode, _nativeSessionId) {
152
152
  const config = this.canonicalizeConfig(input.config);
153
- if (config.profile !== undefined) {
154
- throw new Error("Managed Codex does not accept a Codex config profile because it cannot be scoped to one "
155
- + "shared-daemon thread. Use a Yui Agent Profile for skills, model, and effort.");
156
- }
157
153
  const launch = this.compileNew(input);
158
154
  // A managed Codex thread is an ordinary user thread. Its Yui guidance is
159
155
  // part of the durable Task message, not a developer_instructions override
@@ -170,10 +166,9 @@ class CodexAdapter extends BaseAdapter {
170
166
  }
171
167
  return {
172
168
  ...launch,
173
- argv: [...argv, "app-server", "proxy"],
174
- transport: "codex-app-server-proxy",
175
- codexThread: codexThreadOptions(input, config),
176
- codexDaemonStartArgs: [...input.agent.baseArgs, "app-server", "daemon", "start"]
169
+ argv: [...argv, "app-server"],
170
+ transport: "codex-app-server",
171
+ codexThread: codexThreadOptions(input, config)
177
172
  };
178
173
  }
179
174
  }
@@ -420,7 +420,7 @@ export class FileRoleLaunchPlanner {
420
420
  if (owner.scope !== "task" || input.runId === undefined) {
421
421
  args = addCodexSessionNotify(args, launchMode, this.#cliPath);
422
422
  }
423
- // Managed Codex Runs are ordinary shared-daemon threads. Their Session
423
+ // Managed Codex Runs use Yui-owned App Server processes. Their Session
424
424
  // Manifest points at the Yui Skills; no Yui Hook config is installed.
425
425
  if (owner.scope === "task" && input.runId !== undefined) {
426
426
  if (managedRun === null || managedRun.status !== "active") {
@@ -516,9 +516,6 @@ export class FileRoleLaunchPlanner {
516
516
  ...(managedCompiled.codexThread === undefined
517
517
  ? {}
518
518
  : { codexThread: managedCompiled.codexThread }),
519
- ...(managedCompiled.codexDaemonStartArgs === undefined
520
- ? {}
521
- : { codexDaemonStartArgs: managedCompiled.codexDaemonStartArgs }),
522
519
  ...(providerOwnedTurn === undefined ? {} : { ownedTurn: providerOwnedTurn }),
523
520
  authority: providerAuthority
524
521
  }
@@ -536,9 +533,6 @@ export class FileRoleLaunchPlanner {
536
533
  ...(managedCompiled.codexThread === undefined
537
534
  ? {}
538
535
  : { codexThread: managedCompiled.codexThread }),
539
- ...(managedCompiled.codexDaemonStartArgs === undefined
540
- ? {}
541
- : { codexDaemonStartArgs: managedCompiled.codexDaemonStartArgs }),
542
536
  authority: providerAuthority,
543
537
  initialTurn
544
538
  }
@@ -553,9 +547,6 @@ export class FileRoleLaunchPlanner {
553
547
  ...(managedCompiled.codexThread === undefined
554
548
  ? {}
555
549
  : { codexThread: managedCompiled.codexThread }),
556
- ...(managedCompiled.codexDaemonStartArgs === undefined
557
- ? {}
558
- : { codexDaemonStartArgs: managedCompiled.codexDaemonStartArgs }),
559
550
  authority: providerAuthority,
560
551
  initialTurn
561
552
  };
@@ -145,7 +145,7 @@ export async function runAgentHost(input) {
145
145
  providerControl: {
146
146
  schemaVersion: 1,
147
147
  adapterId: "codex",
148
- transport: "codex-app-server-proxy",
148
+ transport: "codex-app-server",
149
149
  kind: "ensure",
150
150
  mode: "resume",
151
151
  nativeSessionId: disconnectedSession.nativeSessionId,
@@ -153,7 +153,6 @@ export async function runAgentHost(input) {
153
153
  ? {}
154
154
  : { sessionTitle: previousControl.sessionTitle }),
155
155
  codexThread: previousControl.codexThread,
156
- codexDaemonStartArgs: previousControl.codexDaemonStartArgs,
157
156
  ...(ownedTurn === undefined ? {} : { ownedTurn }),
158
157
  authority
159
158
  }
@@ -258,7 +257,7 @@ export async function runAgentHost(input) {
258
257
  ...(activeTurnAttemptId === undefined ? {} : { attemptId: activeTurnAttemptId }),
259
258
  ...(activeNativeTurnId === undefined ? {} : { nativeTurnId: activeNativeTurnId }),
260
259
  ...exitAuthority,
261
- detail: "Codex client disconnected; reattaching to the shared daemon."
260
+ detail: "Codex App Server disconnected; starting a replacement process."
262
261
  }));
263
262
  await reconnectCodexClient(providerSession, currentPayload);
264
263
  return;
@@ -121,7 +121,7 @@ export const BUILTIN_AGENT_DRIVERS = Object.freeze([
121
121
  }),
122
122
  observation: Object.freeze({
123
123
  ...STRUCTURED_CLI_CAPABILITIES.observation,
124
- // Managed Codex uses the ordinary shared App Server event stream.
124
+ // Managed Codex uses its Yui-owned App Server event stream.
125
125
  // Turn lifecycle is exact; Yui does not install per-thread Hooks merely
126
126
  // to manufacture tool/wait/usage observations.
127
127
  operations: Object.freeze([]),
@@ -86,25 +86,15 @@ function validateProviderControl(control) {
86
86
  if (control.adapterId !== "codex" && control.adapterId !== "claude") {
87
87
  throw new Error("Agent Host Provider control adapter is invalid.");
88
88
  }
89
- if ((control.adapterId === "codex" && control.transport !== "codex-app-server-proxy")
89
+ if ((control.adapterId === "codex" && control.transport !== "codex-app-server")
90
90
  || (control.adapterId === "claude" && control.transport !== "claude-stream-json")) {
91
91
  throw new Error("Agent Host Provider control transport does not match its adapter.");
92
92
  }
93
93
  if ((control.adapterId === "codex") !== (control.codexThread !== undefined)) {
94
94
  throw new Error("Agent Host Provider thread settings do not match its adapter.");
95
95
  }
96
- if ((control.adapterId === "codex") !== (control.codexDaemonStartArgs !== undefined)) {
97
- throw new Error("Agent Host Provider daemon bootstrap does not match its adapter.");
98
- }
99
96
  if (control.codexThread !== undefined)
100
97
  validateCodexThreadOptions(control.codexThread);
101
- if (control.codexDaemonStartArgs !== undefined) {
102
- if (!Array.isArray(control.codexDaemonStartArgs)
103
- || control.codexDaemonStartArgs.length === 0) {
104
- throw new Error("Agent Host Codex daemon bootstrap args are invalid.");
105
- }
106
- control.codexDaemonStartArgs.forEach((value) => text(value, "Codex daemon argument"));
107
- }
108
98
  if (control.mode !== "new" && control.mode !== "resume") {
109
99
  throw new Error("Agent Host Provider control mode is invalid.");
110
100
  }
@@ -4,8 +4,6 @@ import { CodexAppServerRequestError, CodexAppServerRuntime, codexAppServerErrorI
4
4
  import { PROVIDER_ACCEPT_TIMEOUT_MS } from "./runtimeDeadlines.js";
5
5
  import { YUI_VERSION } from "../version.js";
6
6
  const PROVIDER_MESSAGE_MAX_BYTES = 16 * 1024 * 1024;
7
- const CODEX_DAEMON_START_TIMEOUT_MS = 10_000;
8
- const CODEX_DAEMON_OUTPUT_MAX_BYTES = 64 * 1024;
9
7
  export class ProviderDeliveryUnknownError extends Error {
10
8
  attemptId;
11
9
  name = "ProviderDeliveryUnknownError";
@@ -46,9 +44,6 @@ export async function startStructuredProviderSession(payload, input = {}) {
46
44
  if (control === undefined) {
47
45
  throw new Error("Managed Agent Host launch requires Provider control metadata.");
48
46
  }
49
- if (control.adapterId === "codex") {
50
- await ensureCodexAppServerDaemon(payload, control);
51
- }
52
47
  const child = spawn(payload.command, [...payload.args], {
53
48
  cwd: payload.cwd,
54
49
  env: { ...payload.environment },
@@ -78,58 +73,6 @@ export async function startStructuredProviderSession(payload, input = {}) {
78
73
  throw error;
79
74
  }
80
75
  }
81
- async function ensureCodexAppServerDaemon(payload, control) {
82
- if (payload.args.at(-2) !== "app-server" || payload.args.at(-1) !== "proxy")
83
- return;
84
- if (control.adapterId !== "codex")
85
- return;
86
- const environment = Object.fromEntries(Object.entries(payload.environment).filter(([key]) => (!key.startsWith("YUI_")
87
- && key !== "CODEX_INTERNAL_ORIGINATOR_OVERRIDE"
88
- && !["TMPDIR", "XDG_CACHE_HOME", "XDG_DATA_HOME", "XDG_STATE_HOME", "XDG_RUNTIME_DIR"]
89
- .includes(key))));
90
- const child = spawn(payload.command, [...control.codexDaemonStartArgs], {
91
- cwd: payload.cwd,
92
- env: environment,
93
- stdio: ["ignore", "pipe", "pipe"]
94
- });
95
- await new Promise((resolvePromise, reject) => {
96
- let output = "";
97
- let settled = false;
98
- let timer;
99
- const settle = (error) => {
100
- if (settled)
101
- return;
102
- settled = true;
103
- if (timer !== undefined)
104
- clearTimeout(timer);
105
- if (error === undefined)
106
- resolvePromise();
107
- else
108
- reject(error);
109
- };
110
- const capture = (chunk) => {
111
- output += String(chunk);
112
- if (Buffer.byteLength(output, "utf8") <= CODEX_DAEMON_OUTPUT_MAX_BYTES)
113
- return;
114
- child.kill("SIGTERM");
115
- settle(new Error("Codex App Server daemon start output exceeded its bound."));
116
- };
117
- child.stdout.on("data", capture);
118
- child.stderr.on("data", capture);
119
- child.once("error", (error) => settle(error));
120
- child.once("close", (code, signal) => {
121
- if (code === 0)
122
- settle();
123
- else
124
- settle(new Error(`Codex App Server daemon start failed (${code ?? signal ?? "unknown"})${output.trim().length === 0 ? "" : `: ${output.trim()}`}`));
125
- });
126
- timer = setTimeout(() => {
127
- child.kill("SIGTERM");
128
- settle(new Error("Codex App Server daemon start timed out."));
129
- }, CODEX_DAEMON_START_TIMEOUT_MS);
130
- timer.unref();
131
- });
132
- }
133
76
  class JsonLineChannel {
134
77
  child;
135
78
  mirror;
@@ -510,9 +510,9 @@ Task 生命周期的交互选择只展示有效来源状态:activate 只展示
510
510
 
511
511
  ## Session 与 tmux
512
512
 
513
- 受管理的 Provider 会话仍然是普通用户会话。Yui 只添加对应的 Role Skill 与 Session Manifest 指针,并通过 Provider 原生结构化协议提交 Task 工作;Yui 不接管完整对话历史。受管理输入绝不会作为终端按键、粘贴文本或启动 argv 发送。Codex 通过 `app-server proxy` 在共享 App Server daemon 上创建或恢复普通 thread;proxy 断开时 Host 会保留逻辑 Activation,重新连接并用原生 thread 历史核对 Yui 已持有的 Turn。Claude 继续使用独立的持久 stream-json 进程,并以精确回放的 user message 作为接收确认。
513
+ 受管理的 Provider 会话仍然是普通用户会话。Yui 只添加对应的 Role Skill 与 Session Manifest 指针,并通过 Provider 原生结构化协议提交 Task 工作;Yui 不接管完整对话历史。受管理输入绝不会作为终端按键、粘贴文本或启动 argv 发送。Codex 由每个存活的 Role Runtime 启动并持有独立的 `app-server` 子进程;Task execution stop 会终止 Agent Host 及其 Provider 进程组,start 会创建新的受控运行时,不再依赖共享 Codex daemon。原生 thread 历史仍由 Codex 保留,Task、WorkItem、代码与持久消息仍由 Yui 保留。Claude 继续使用独立的持久 stream-json 进程,并以精确回放的 user message 作为接收确认。
514
514
 
515
- Run、Conversation、Activation 与 Turn 是四个独立身份。Conversation 可以跨多个 Run 和客户端连接;Activation 只代表 Yui 当前的连接,而不是对 Provider thread 的独占所有权;Turn 在写入前先持久化。写入超时或结果不明确会进入 `delivery-unknown`,不会自动重发。用户在 Desktop 直接发起的 active Turn 只会让 Yui 暂时等待,不会导致 Yui Run 失败。
515
+ Run、Conversation、Activation 与 Turn 是四个独立身份。Conversation 可以跨多个 Run 和客户端连接;Activation 只代表 Yui 当前的连接,而不是对 Provider thread 的独占所有权;Turn 在写入前先持久化。写入超时或结果不明确会进入 `delivery-unknown`,不会自动重发。已经存在的原生 active Turn 只会让 Yui 暂时等待,不会导致 Yui Run 失败;存活的受管理 Role 应通过 Yui 的 view/takeover 边界进行人工控制,避免其他客户端并发写入。
516
516
 
517
517
  Task Role 使用以下显式入口:
518
518
 
@@ -524,7 +524,7 @@ yui task role takeover <task-id> <role>
524
524
  yui task role release <task-id> <role>
525
525
  ```
526
526
 
527
- Codex Role thread 可以直接在 Desktop 中打开和交互,不需要执行 `takeover`;Yui 不写入全局 Hook/config。Yui 可以幂等启动尚未运行的共享 daemon,但不会因 thread 错误停止或重启它。`view`、`takeover`、`release` 继续作为独立进程型 Provider 的显式 PTY 输入网关。Global Operator 与 global Role 继续使用原生交互式 CLI,不属于受管理 Task Provider 协议。
527
+ Codex Role thread 仍可在 Desktop 中查看,但存活的受管理 Role 应通过 `view`、`takeover`、`release` 进行人工控制;若要从其他客户端恢复该 thread,应先停止 Task execution。Yui 不写入全局 Hook/config,也不依赖或控制共享 Codex daemon。Global Operator 与 global Role 继续使用原生交互式 CLI,不属于受管理 Task Provider 协议。
528
528
 
529
529
  当新版本需要离线迁移 Home 时,应等待当前 Turn/Run 完成,然后从普通 shell
530
530
  执行 `yui session stop --all`,再重新执行 `yui update`。停止命令会先整体预检:
@@ -560,7 +560,7 @@ state、receipt 与 pane fence。Yui 不会解析 prompt glyph、进度文本、
560
560
  或其他 Agent 终端输出来推断 ready 或 success。`captureRole()` 只用于显式的人类
561
561
  transcript 查看,不具备生命周期权威。
562
562
 
563
- 稳定的 Role 上下文不会创建额外的 bootstrap Turn。Task execution Run 按角色使用通用 Leader 或 Worker Skill,review Run 则按持久 Run purpose 使用通用 Reviewer Skill;Provider 可以通过安全的追加式原生上下文通道携带 Skill,也可以在普通 Task 投递中指向它。这些都只是 Yui 自己拥有的可移植编排规则。Project Skills 始终是 Project 中正常版本化的文件,由 Agent 通过自身项目机制发现、选择并按需加载;Yui 不扫描、不解析、不复制,也不注入 Project Skills。Managed Codex 保留用户原有的 developer instructions;普通 Task 消息会携带精简的 Session Manifest 绝对路径,Manifest 再指向对应的 Yui Role Skill,供 Codex 按需读取。Role 选择的 model、effort、permission、workspace 与 shell 设置通过共享 App Server daemon,作为线程级 `thread/start` 或 `thread/resume` 配置传入。Codex 原生 config profile 不能隔离到共享 daemon 的单个 thread,因此 Managed Codex 会拒绝这个设置并提示使用 Yui Agent Profile;其他非 Yui 或交互式 Codex 会话不受影响。其他 Codex 线程继续使用原有的用户、profile、Project 和 system 配置,Yui 不修改底层配置文件。App Server 原生通知是 Managed Codex 线程的生命周期权威;Yui 不为它安装 Hook,也不占用 `notify`。交互式 Codex Session 仍可使用 Yui 的结构化 `notify` callback,Doctor 会报告最终生效的配置冲突。`skills.config` 只负责启停已发现 Skill,Yui 不会误用它。Claude 从 Yui 管理的私有 `0600` context 文件读取同一份 Yui Role Skill 内容,不再把大段或敏感文本放进 argv;重试和 resume 会复用按 purpose 区分的稳定路径。非 Operator 的 global Role 保持中性,不会注入 Task 编排 Skill。因此 Operator 会停在空白的原生 composer,用户输入仍是第一条 user message;Leader wake、Worker 和 Reviewer Run assignment 仍是邮箱投递的真实工作消息。
563
+ 稳定的 Role 上下文不会创建额外的 bootstrap Turn。Task execution Run 按角色使用通用 Leader 或 Worker Skill,review Run 则按持久 Run purpose 使用通用 Reviewer Skill;Provider 可以通过安全的追加式原生上下文通道携带 Skill,也可以在普通 Task 投递中指向它。这些都只是 Yui 自己拥有的可移植编排规则。Project Skills 始终是 Project 中正常版本化的文件,由 Agent 通过自身项目机制发现、选择并按需加载;Yui 不扫描、不解析、不复制,也不注入 Project Skills。Managed Codex 保留用户原有的 developer instructions;普通 Task 消息会携带精简的 Session Manifest 绝对路径,Manifest 再指向对应的 Yui Role Skill,供 Codex 按需读取。每个存活 Role Yui-owned App Server 进程会加载所选 Codex 原生 config profile;model、effort、permission、workspace 与 shell 设置作为线程级 `thread/start` 或 `thread/resume` 配置传入,Yui 不修改底层 Codex 配置文件。App Server 原生通知是 Managed Codex 线程的生命周期权威;Yui 不为它安装 Hook,也不占用 `notify`。交互式 Codex Session 仍可使用 Yui 的结构化 `notify` callback,Doctor 会报告最终生效的配置冲突。`skills.config` 只负责启停已发现 Skill,Yui 不会误用它。Claude 从 Yui 管理的私有 `0600` context 文件读取同一份 Yui Role Skill 内容,不再把大段或敏感文本放进 argv;重试和 resume 会复用按 purpose 区分的稳定路径。非 Operator 的 global Role 保持中性,不会注入 Task 编排 Skill。因此 Operator 会停在空白的原生 composer,用户输入仍是第一条 user message;Leader wake、Worker 和 Reviewer Run assignment 仍是邮箱投递的真实工作消息。
564
564
 
565
565
  ## Controller 与失败处理
566
566
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zq-silk/yui",
3
- "version": "0.13.5",
3
+ "version": "0.13.6",
4
4
  "description": "Local control plane for long-running native agent CLI sessions backed by tmux.",
5
5
  "license": "MIT",
6
6
  "private": false,