@zq-silk/yui 2.7.1 → 2.8.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 (90) hide show
  1. package/dist/cli/commandCatalog.js +8 -7
  2. package/dist/cli/updateCommand.js +3 -0
  3. package/dist/commands/configCommands.js +1 -0
  4. package/dist/commands/globalRoleCommands.js +42 -35
  5. package/dist/commands/inboxCommands.js +60 -40
  6. package/dist/commands/taskCommands.js +7 -3
  7. package/dist/commands/taskRoleRuntimeStatus.js +2 -0
  8. package/dist/context/runContextPack.js +48 -3
  9. package/dist/context/taskContext.js +36 -12
  10. package/dist/controlPlaneCli.js +46 -12
  11. package/dist/controller/controller.js +5 -0
  12. package/dist/controller/fileSchedulerStoreAdapter.js +9 -4
  13. package/dist/controller/globalInputDelivery.js +17 -5
  14. package/dist/controller/globalRuntimeAttention.js +135 -5
  15. package/dist/controller/runtime.js +4 -0
  16. package/dist/controller/structuredProviderObservation.js +51 -15
  17. package/dist/controller/taskHostTerminalRecovery.js +33 -0
  18. package/dist/executor/fileRoleLaunchPlanner.js +4 -9
  19. package/dist/message/inboxReceipt.js +30 -0
  20. package/dist/message/taskInboxOwnership.js +25 -3
  21. package/dist/models/modelManagement.js +469 -0
  22. package/dist/models/modelManagementConfig.js +46 -0
  23. package/dist/models/modelManagementFiles.js +90 -0
  24. package/dist/models/modelManagementHttp.js +90 -0
  25. package/dist/models/modelManagementTypes.js +1 -0
  26. package/dist/output/boundedRead.js +43 -14
  27. package/dist/runtime/agentEndpointIdentity.js +8 -4
  28. package/dist/runtime/agentEndpointOwnership.js +5 -6
  29. package/dist/runtime/agentHost.js +62 -10
  30. package/dist/runtime/agentHostImplementation.js +18 -0
  31. package/dist/runtime/managedCaller.js +25 -1
  32. package/dist/runtime/managedIdentity.js +1 -1
  33. package/dist/runtime/providerRetry.js +19 -1
  34. package/dist/runtime/sessionCaller.js +53 -0
  35. package/dist/storage/contextRecords.js +28 -0
  36. package/dist/storage/sqliteSchema.js +10 -0
  37. package/dist/storage/sqliteStore.js +9 -5
  38. package/dist/storage/storageVersions.js +1 -1
  39. package/dist/storage/taskStore.js +4 -0
  40. package/dist/task/completionReadiness.js +3 -3
  41. package/dist/web/assets/assetManifest.js +28 -2
  42. package/dist/web/assets/client/app/manage.js +6 -0
  43. package/dist/web/assets/client/app/models.js +20 -0
  44. package/dist/web/assets/client/app/settings.js +41 -9
  45. package/dist/web/assets/client/i18n/en.js +180 -2
  46. package/dist/web/assets/client/i18n/zh-CN.js +178 -2
  47. package/dist/web/assets/client/index.js +8 -0
  48. package/dist/web/assets/client/layout/manageShell.js +94 -0
  49. package/dist/web/assets/client/lib/api.js +13 -1
  50. package/dist/web/assets/client/lib/i18n.js +5 -3
  51. package/dist/web/assets/client/views/dock/conversation.js +231 -80
  52. package/dist/web/assets/client/views/models.js +777 -0
  53. package/dist/web/assets/client/views/skills.js +22 -15
  54. package/dist/web/assets/shared/icons.js +2 -0
  55. package/dist/web/assets/shared/manageNav.js +13 -0
  56. package/dist/web/assets/shell/manage.js +54 -0
  57. package/dist/web/assets/shell/models.js +7 -0
  58. package/dist/web/assets/shell/settings.js +1 -35
  59. package/dist/web/assets/shell/settingsContent.js +30 -0
  60. package/dist/web/assets/shell/sidebar.js +1 -0
  61. package/dist/web/assets/styles/index.js +6 -0
  62. package/dist/web/assets/styles/views/conversation.js +133 -0
  63. package/dist/web/assets/styles/views/manage.js +71 -0
  64. package/dist/web/assets/styles/views/models.js +129 -0
  65. package/dist/web/assets/styles/views/settings.js +28 -14
  66. package/dist/web/assets/styles/views/sidebar.js +1 -0
  67. package/dist/web/webServer.js +59 -9
  68. package/docs/cli-information-contract.md +42 -11
  69. package/docs/cli-information-contract.zh-CN.md +28 -7
  70. package/docs/managed-turn-and-session-runtime.md +47 -1
  71. package/docs/managed-turn-and-session-runtime.zh-CN.md +32 -0
  72. package/docs/release-workflow.md +58 -7
  73. package/docs/release-workflow.zh-CN.md +39 -4
  74. package/docs/storage-baseline.md +6 -1
  75. package/docs/storage-baseline.zh-CN.md +4 -1
  76. package/docs/testing/review-evaluation.md +148 -0
  77. package/docs/testing/review-evaluation.zh-CN.md +117 -0
  78. package/docs/testing/verification-levels.md +6 -2
  79. package/docs/testing/verification-levels.zh-CN.md +3 -0
  80. package/package.json +1 -1
  81. package/skills/yui-leader/VERSION +1 -1
  82. package/skills/yui-leader/references/execution.md +29 -0
  83. package/skills/yui-leader/references/replicated-execution.md +7 -0
  84. package/skills/yui-operator/SKILL.md +5 -1
  85. package/skills/yui-operator/VERSION +1 -1
  86. package/skills/yui-reviewer/SKILL.md +35 -0
  87. package/skills/yui-reviewer/VERSION +1 -1
  88. package/skills/yui-runtime/SKILL.md +53 -7
  89. package/skills/yui-runtime/VERSION +1 -1
  90. package/skills/yui-runtime/references/recovery.md +24 -5
@@ -0,0 +1,129 @@
1
+ import { BREAKPOINTS } from "../../shared/geometry.js";
2
+ /*
3
+ * MODELS VIEW — the content of the /models sections. The rail, reading column
4
+ * and section headings come from views/manage; cards, badges, chips,
5
+ * segmented controls and fields from the shared ui stylesheets. These rules
6
+ * add the provider table, the catalog list and the quota meters. On phones
7
+ * the provider table becomes stacked rows.
8
+ */
9
+ export const MODELS_STYLES = `
10
+ /* Heading first, as on every management page: the page scope and the shared
11
+ connection status sit under the current section's heading. The wrappers
12
+ flatten into one column so only order changes, never the DOM. */
13
+ .models-body .manage-main{display:flex;flex-direction:column;gap:14px}
14
+ .models-body .models-root,.models-body .models-section:not([hidden]){display:contents}
15
+ .models-body .manage-main>*,.models-root>*,.models-section>*{width:100%;max-width:1120px;margin-left:auto;margin-right:auto}
16
+ .models-section>.manage-head{order:-1}
17
+ .models-body .manage-scope{margin-bottom:0}
18
+ .models-root .seg-btn[aria-pressed="true"]{background:var(--surface-2);color:var(--ink);box-shadow:var(--shadow-1),0 0 0 1px var(--line-2)}
19
+ .models-root{display:grid;gap:16px;min-width:0}
20
+ .models-section p:not(.kicker){color:var(--ink-2);font-size:var(--fs-sm);line-height:1.55;overflow-wrap:anywhere}
21
+ .models-section .manage-heading p:not(.kicker){color:var(--ink-3)}
22
+ .models-card{overflow:hidden}
23
+ .models-card>.card-body{gap:12px}
24
+ .models-status{display:grid;gap:8px;min-width:0}
25
+ .models-status:empty{display:none}
26
+ .models-facts{display:flex;flex-wrap:wrap;gap:6px 8px;align-items:center;min-width:0}
27
+ .models-facts small{overflow-wrap:anywhere}
28
+ .models-facts .badge[hidden]{display:none}
29
+ .models-notice{flex:1 1 280px;min-width:0}
30
+ .models-alert{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;padding:10px 14px;border:1px solid var(--bad-soft);border-radius:var(--r-md);background:var(--bad-soft)}
31
+ .models-alert>.icon{width:16px;height:16px;color:var(--bad);flex:none}
32
+ .models-alert p{flex:1 1 240px;min-width:0}
33
+ .models-note{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:9px 12px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-2)}
34
+ .models-note>.icon{width:15px;height:15px;color:var(--info);flex:none}
35
+ .models-empty{color:var(--ink-3)!important;font-size:var(--fs-sm)}
36
+ .models-count{color:var(--ink-4);font-size:var(--fs-xs)!important;font-variant-numeric:tabular-nums}
37
+ .models-receipt{white-space:pre-wrap;overflow-wrap:anywhere}
38
+ .models-receipt-group .settings-actions{margin-top:8px}
39
+
40
+ /* Toolbars: search plus segmented filters */
41
+ .models-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;padding:12px 16px;border-bottom:1px solid var(--line);min-width:0}
42
+ .models-toolbar-flat{padding:0;border:0}
43
+ .models-toolbar .seg{flex-wrap:wrap}
44
+ .models-search{position:relative;display:flex;align-items:center;flex:1 1 240px;min-width:0;max-width:420px}
45
+ .models-search>.icon{position:absolute;left:10px;width:15px;height:15px;color:var(--ink-4);pointer-events:none}
46
+ .models-search input{width:100%;height:32px;padding:0 10px 0 32px;border-radius:var(--r-md);background:var(--surface-2)}
47
+ .models-results{display:grid;gap:0;min-width:0}
48
+ .models-results>.models-count{padding:8px 16px 0}
49
+ .models-results>.models-empty{padding:12px 16px 16px}
50
+ .models-catalog-results>.models-count{padding:0 0 8px}
51
+ .models-catalog-results>.models-empty{padding:0}
52
+
53
+ /* Provider table */
54
+ .models-table-wrap{min-width:0;overflow-x:auto}
55
+ .models-table{width:100%;border-collapse:collapse;font-size:var(--fs-sm)}
56
+ .models-table th{padding:10px 12px;color:var(--ink-4);font-size:var(--fs-2xs);font-weight:600;letter-spacing:.04em;text-align:left;text-transform:uppercase;border-bottom:1px solid var(--line);white-space:nowrap}
57
+ .models-table td{padding:11px 12px;border-bottom:1px solid var(--line);vertical-align:top;min-width:0}
58
+ .models-table tr:last-child td{border-bottom:0}
59
+ .models-table th:first-child,.models-table td:first-child{padding-left:16px}
60
+ .models-table th:last-child,.models-table td:last-child{padding-right:16px}
61
+ .models-table tbody tr:hover{background:var(--surface-2)}
62
+ .models-table tbody tr[aria-current="true"]{background:var(--accent-soft);box-shadow:inset 3px 0 0 var(--accent)}
63
+ .models-cell-main{display:grid;gap:3px;justify-items:start;min-width:0}
64
+ .models-cell-main strong{font-weight:600;color:var(--ink);overflow-wrap:anywhere}
65
+ .models-cell-main code{white-space:normal;overflow-wrap:anywhere}
66
+ .models-url{display:block;max-width:280px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink-2)}
67
+ .models-row-actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:6px;min-width:0}
68
+ .models-row-actions .btn{height:28px;padding:0 10px;font-size:var(--fs-xs)}
69
+ .models-reason{flex-basis:100%;max-width:260px;text-align:right;line-height:1.4;overflow-wrap:anywhere}
70
+ .models-danger{color:var(--bad)}
71
+ .models-danger:hover:not(:disabled){color:var(--bad);background:var(--bad-soft)}
72
+
73
+ /* Provider editor */
74
+ .models-editor{border-color:var(--accent-line)}
75
+ .models-form-head{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;min-width:0}
76
+ .models-form-head h2{font-size:var(--fs-md);font-weight:600;overflow-wrap:anywhere;min-width:0}
77
+ .models-provider-form .settings-grid{gap:14px 20px;align-items:start}
78
+ .models-provider-form input:not([type=checkbox]),.models-provider-form select,.models-connection-form input{width:100%;min-width:0}
79
+ .models-provider-form .settings-actions{margin-top:4px}
80
+
81
+ /* Connection settings */
82
+ .models-connection-form{display:grid;gap:16px;min-width:0}
83
+ .models-connection-form{grid-template-columns:repeat(2,minmax(0,1fr))}
84
+ .models-connection-form>.settings-actions,.models-connection-form>.receipt,.models-connection-form>.models-receipt-group{grid-column:1/-1;margin-top:0}
85
+ .models-fieldset{display:grid;align-content:start;gap:14px;min-width:0;margin:0;padding:0;border:0}
86
+ .models-fieldset legend{margin-bottom:12px;padding:0;color:var(--ink);font-size:var(--fs-sm);font-weight:600}
87
+ .models-explain h2{font-size:var(--fs-sm);font-weight:600}
88
+
89
+ /* Catalog */
90
+ .models-catalog{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:0 20px;min-width:0}
91
+ .models-catalog-item{display:flex;align-items:center;justify-content:space-between;gap:10px;min-width:0;padding:7px 2px;border-bottom:1px solid var(--line)}
92
+ .models-catalog-item code{font-family:var(--font-mono);font-size:var(--fs-xs);color:var(--ink);overflow-wrap:anywhere;min-width:0}
93
+
94
+ /* Quota accounts, groups and meters */
95
+ .models-accounts{list-style:none;margin:0 auto;padding:0;display:grid;gap:14px;min-width:0}
96
+ .models-account .card-title>span:first-child{font-family:var(--font-mono);font-size:var(--fs-sm)}
97
+ .models-groups{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:18px 28px;min-width:0}
98
+ .models-group{display:grid;align-content:start;gap:10px;min-width:0}
99
+ .models-group h3{font-size:var(--fs-sm);font-weight:600;color:var(--ink)}
100
+ .models-windows{list-style:none;margin:0;padding:0;display:grid;gap:12px;min-width:0}
101
+ .models-window{display:grid;gap:5px;min-width:0}
102
+ .models-window-line{display:flex;justify-content:space-between;gap:12px;font-size:var(--fs-sm);min-width:0}
103
+ .models-window-name{color:var(--ink-2);overflow-wrap:anywhere;min-width:0}
104
+ .models-window-value{color:var(--ink);font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap}
105
+ .models-meter{position:relative;height:6px;border-radius:var(--r-pill);background:var(--surface-3);overflow:hidden}
106
+ .models-meter>span{position:absolute;inset:0 auto 0 0;border-radius:inherit;background:var(--tone)}
107
+ .models-meter.is-unknown{background:repeating-linear-gradient(90deg,var(--surface-3) 0 6px,transparent 6px 10px)}
108
+ .models-window small{font-size:var(--fs-xs);overflow-wrap:anywhere}
109
+ .models-balances{display:flex;flex-wrap:wrap;gap:8px 28px;margin:0;padding-top:12px;border-top:1px solid var(--line);font-size:var(--fs-sm)}
110
+ .models-balances div{display:grid;gap:2px;min-width:0}
111
+ .models-balances dt{color:var(--ink-3);font-size:var(--fs-xs)}
112
+ .models-balances dd{margin:0;color:var(--ink);font-weight:500;font-variant-numeric:tabular-nums}
113
+
114
+ @media(max-width:${BREAKPOINTS.small}px){
115
+ .models-connection-form{grid-template-columns:minmax(0,1fr)}
116
+ .models-provider-form .settings-grid{grid-template-columns:minmax(0,1fr)}
117
+ .models-search{max-width:none;flex-basis:100%}
118
+ .models-table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
119
+ .models-table,.models-table tbody,.models-table tr,.models-table td{display:block;width:100%}
120
+ .models-table tr{padding:10px 14px;border-bottom:1px solid var(--line)}
121
+ .models-table tr:last-child{border-bottom:0}
122
+ .models-table td{display:grid;grid-template-columns:84px minmax(0,1fr);gap:8px;align-items:start;padding:4px 0!important;border:0}
123
+ .models-table td::before{content:attr(data-label);color:var(--ink-4);font-size:var(--fs-2xs);font-weight:600;letter-spacing:.04em;text-transform:uppercase;padding-top:3px}
124
+ .models-url{max-width:none;white-space:normal;overflow-wrap:anywhere}
125
+ .models-row-actions{justify-content:flex-start}
126
+ .models-reason{text-align:left;max-width:none}
127
+ .models-catalog{grid-template-columns:minmax(0,1fr)}
128
+ }
129
+ `;
@@ -1,26 +1,40 @@
1
+ import { BREAKPOINTS } from "../../shared/geometry.js";
2
+ /*
3
+ * SETTINGS VIEW — the content of the /settings sections (preferences, Skills,
4
+ * Agents & server). The rail, reading column and section headings come from
5
+ * views/manage. Settings panels share the card surface of the model pages:
6
+ * the same border, radius, padding and title scale; nested panels (a Skill in
7
+ * the catalog) sit one surface step lower instead of nesting full cards.
8
+ */
1
9
  export const SETTINGS_STYLES = `
2
- .settings-body{display:block;overflow:auto;height:auto;min-height:100dvh}
3
- .settings-page{max-width:1040px;margin:auto;padding:32px 24px 80px;display:grid;gap:22px}
4
- .settings-page p{color:var(--ink-2);font-size:var(--fs-sm);line-height:1.6;overflow-wrap:anywhere}
5
- .settings-header{display:flex;gap:20px;align-items:center}
6
- .settings-card{padding:22px;border:1px solid var(--line-2);border-radius:var(--r-lg);background:var(--surface);min-width:0}
7
- .settings-card>summary{font-size:var(--fs-md);font-weight:600;cursor:pointer}
8
- .settings-card h2{font-size:var(--fs-md);margin-bottom:16px}
9
- .settings-card[open]>summary{margin-bottom:16px}
10
+ .settings-card{display:block;padding:16px;border:1px solid var(--line);border-radius:var(--r-lg);background:var(--surface);min-width:0}
11
+ .settings-card .settings-card{padding:14px;background:var(--surface-2)}
12
+ .settings-card>summary{display:flex;align-items:center;gap:8px;min-height:24px;font-size:var(--fs-md);font-weight:600;color:var(--ink);cursor:pointer;overflow-wrap:anywhere}
13
+ .settings-card h2{font-size:var(--fs-md);font-weight:600;color:var(--ink);margin-bottom:14px}
14
+ .settings-card h3{font-size:var(--fs-sm);font-weight:600;color:var(--ink);overflow-wrap:anywhere}
15
+ .settings-card[open]>summary{margin-bottom:14px;padding-bottom:12px;border-bottom:1px solid var(--line)}
16
+ .manage-section[data-section] .settings-card p,.settings-stack>p{color:var(--ink-2);font-size:var(--fs-sm);line-height:1.6;overflow-wrap:anywhere}
10
17
  .settings-stack{display:grid;gap:16px;min-width:0}
11
- .settings-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px}
18
+ .settings-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px 24px;min-width:0}
12
19
  .settings-field{padding:14px 0;border-bottom:1px solid var(--line);display:grid;gap:8px;min-width:0}
13
20
  .settings-field small{color:var(--ink-3);overflow-wrap:anywhere}
14
21
  .settings-field small:empty,.settings-field .settings-actions:empty{display:none}
15
22
  .settings-field textarea{width:100%;min-height:88px;resize:vertical}
16
23
  .settings-field input,.settings-field select{width:100%;min-width:0}
17
24
  .settings-field .settings-reset{display:flex;gap:8px;align-items:center;font-size:var(--fs-xs)}
18
- .settings-reset input{width:auto}
19
- .settings-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:16px;align-items:center}
25
+ .settings-reset{display:flex;gap:8px;align-items:center;font-size:var(--fs-sm);color:var(--ink-2)}
26
+ .settings-reset input{width:auto;flex:none}
27
+ .settings-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:16px;align-items:center;min-width:0}
28
+ .settings-actions code{overflow-wrap:anywhere;min-width:0}
20
29
  .settings-receipt{white-space:pre-wrap;overflow-wrap:anywhere}
21
30
  .settings-error{color:var(--bad)!important}
22
31
  .settings-observation{max-height:260px;overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere;font-size:var(--fs-xs)}
23
- .settings-search{position:sticky;top:0;background:var(--canvas);padding:12px 0;z-index:1}
24
- .settings-page input[type=checkbox]{width:16px;height:16px;padding:0;accent-color:var(--accent)}
25
- @media(max-width:640px){.settings-page{padding:18px 12px 48px}.settings-grid{grid-template-columns:1fr}.settings-card{padding:16px}}
32
+ .settings-search{position:sticky;top:0;z-index:1;padding:10px 0;background:var(--canvas)}
33
+ .settings-search input{width:100%;max-width:520px}
34
+ #settings-status:empty,#browser-receipt:empty{display:none}
35
+ .mono-line{overflow-wrap:anywhere}
36
+ @media(max-width:${BREAKPOINTS.small}px){
37
+ .settings-grid{grid-template-columns:minmax(0,1fr)}
38
+ .settings-card{padding:14px}
39
+ }
26
40
  `;
@@ -71,4 +71,5 @@ export const SIDEBAR_STYLES = `
71
71
  .foot-btn[aria-pressed="true"]{color:var(--accent);border-color:var(--accent-line);background:var(--accent-soft)}
72
72
  .foot-btn kbd{margin-left:2px}
73
73
  .side-foot .icon-btn{margin-left:auto}
74
+ .side-foot .icon-btn+.icon-btn{margin-left:0}
74
75
  `;
@@ -7,9 +7,9 @@ import { parseTaskSearchOptions, searchTaskBodies } from "../context/taskSearch.
7
7
  import { readTaskUsage } from "../runtime/taskUsageQuery.js";
8
8
  import { readWebTaskActivity } from "./webTaskActivity.js";
9
9
  import { WebRequestRejected } from "./webMutation.js";
10
- import { SETTINGS_HTML } from "./assets/shell/settings.js";
10
+ import { MODELS_HTML } from "./assets/shell/models.js";
11
11
  import { TASK_SUBMISSION_INTENTS } from "../message/message.js";
12
- import { DASHBOARD_HTML, findWebAsset } from "./assets/assetManifest.js";
12
+ import { DASHBOARD_HTML, findWebAsset, prepareWebDocument, WEB_ASSET_VERSION } from "./assets/assetManifest.js";
13
13
  import { buildWebTaskCatalog, buildWebPageSessions, buildWebTaskDetail } from "./webSnapshot.js";
14
14
  const MAX_JSON_BODY_BYTES = 16 * 1024;
15
15
  const MAX_TERMINAL_MESSAGE_BYTES = 64 * 1024;
@@ -204,6 +204,54 @@ async function handleHttpRequest(request, response, store, dependencies, token,
204
204
  }
205
205
  return;
206
206
  }
207
+ if (pathname === "/api/models" || pathname.startsWith("/api/models/")) {
208
+ try {
209
+ const service = dependencies.models;
210
+ if (!service)
211
+ throw new WebRequestRejected("Model management unavailable.");
212
+ const query = new URL(request.url, "http://localhost").searchParams;
213
+ if ([...query.keys()].some(k => !["cursor", "source"].includes(k) || query.getAll(k).length !== 1)) {
214
+ throw new WebRequestRejected("Unknown Model query.");
215
+ }
216
+ let value;
217
+ if (method === "GET" && pathname === "/api/models")
218
+ value = service.read();
219
+ else if (method === "GET" && pathname === "/api/models/catalog")
220
+ value = service.readCatalog(query.get("cursor") ?? "0");
221
+ else if (method === "GET" && pathname === "/api/models/quota")
222
+ value = service.readQuota(query.get("source") ?? "factory");
223
+ else if (method === "POST") {
224
+ // Credential-bearing forms require an exact same-origin browser request.
225
+ if (headerValue(request, "origin") !== `http://${headerValue(request, "host")}`) {
226
+ throw new WebRequestRejected("Model changes require a same-origin request.");
227
+ }
228
+ if (headerValue(request, "content-type")?.split(";")[0]?.trim() !== "application/json") {
229
+ throw new WebRequestRejected("Model changes require JSON.");
230
+ }
231
+ const body = await readMutationBody(request);
232
+ if (pathname === "/api/models/connection")
233
+ value = service.saveConnection(body);
234
+ else if (pathname === "/api/models/provider")
235
+ value = service.saveProvider(body);
236
+ else if (pathname === "/api/models/refresh")
237
+ value = await service.refresh(body);
238
+ else
239
+ throw new WebRequestRejected("Unknown Model operation.");
240
+ }
241
+ else {
242
+ sendJson(response, 405, { error: "Method not allowed.", disposition: "not-submitted" }, false);
243
+ return;
244
+ }
245
+ sendJson(response, 200, value, false);
246
+ }
247
+ catch (error) {
248
+ sendJson(response, 409, {
249
+ error: error instanceof WebRequestRejected ? error.message : "Model operation failed. Inspect the current state before retrying.",
250
+ disposition: method === "GET" || error instanceof WebRequestRejected ? "not-submitted" : "unknown"
251
+ }, false);
252
+ }
253
+ return;
254
+ }
207
255
  if (pathname === "/api/settings" || pathname === "/api/settings/group" || pathname === "/api/settings/capabilities") {
208
256
  try {
209
257
  if (!dependencies.settings)
@@ -529,12 +577,14 @@ async function handleHttpRequest(request, response, store, dependencies, token,
529
577
  }
530
578
  if (method === "GET" || method === "HEAD") {
531
579
  try {
532
- const asset = findWebAsset(pathname);
533
- if (pathname === "/" || pathname === "/index.html" || pathname === "/settings") {
534
- sendText(response, 200, "text/html; charset=utf-8", pathname === "/settings" ? SETTINGS_HTML.replace("__YUI_WEB_TOKEN__", token) : dashboardHtml(token), method === "HEAD");
580
+ const assetVersion = new URL(request.url, "http://localhost").searchParams.get("v");
581
+ const asset = findWebAsset(pathname, assetVersion);
582
+ const managementPage = /^\/(?:models(?:\/(?:providers|catalog|quota))?|settings(?:\/(?:preferences|skills|server|connection))?)\/?$/.test(pathname);
583
+ if (pathname === "/" || pathname === "/index.html" || managementPage) {
584
+ sendText(response, 200, "text/html; charset=utf-8", prepareWebDocument(managementPage ? MODELS_HTML.replace("__YUI_WEB_TOKEN__", token) : dashboardHtml(token), managementPage ? "/assets/js/app/manage.js" : "/assets/app.js"), method === "HEAD");
535
585
  }
536
586
  else if (asset !== null) {
537
- sendAsset(response, asset, method === "HEAD");
587
+ sendAsset(response, asset, method === "HEAD", assetVersion === WEB_ASSET_VERSION);
538
588
  }
539
589
  else if (pathname === "/api/search") {
540
590
  const query = new URL(request.url, "http://localhost").searchParams;
@@ -960,12 +1010,12 @@ function sendText(response, status, contentType, body, head) {
960
1010
  response.setHeader("content-length", Buffer.byteLength(body));
961
1011
  response.end(head ? undefined : body);
962
1012
  }
963
- function sendAsset(response, asset, head) {
1013
+ function sendAsset(response, asset, head, versioned = false) {
964
1014
  const payload = asset.encoding === "base64"
965
1015
  ? Buffer.from(asset.body, "base64")
966
1016
  : Buffer.from(asset.body, "utf-8");
967
- if (asset.contentType.startsWith("font/") || asset.contentType.startsWith("image/")) {
968
- response.setHeader("cache-control", "public, max-age=31536000, immutable");
1017
+ if (versioned) {
1018
+ response.setHeader("cache-control", "private, max-age=31536000, immutable");
969
1019
  }
970
1020
  response.statusCode = 200;
971
1021
  response.setHeader("content-type", asset.contentType);
@@ -14,14 +14,15 @@ schema migration or new snapshot/cache store is introduced.
14
14
  | Question | Entry | Default information / further reading |
15
15
  | --- | --- | --- |
16
16
  | Which Task? | `task list` | Existing bounded catalog, filters, attention and cursor |
17
- | What is current? | `task context <task>` | Current Task/Brief/Role/Project/workspace facts, active work and Runs, open inputs, active decisions, unresolved jobs, recent Message references; no event or terminal-Run dump |
17
+ | What is current? | `task context <task>` | Current facts, active work, open inputs, active decisions, unresolved jobs and unacknowledged Message references; no event or terminal-Run dump |
18
18
  | What records exist? | `task context list <task> --store <family>` | One authorized family, summaries and exact digest-bearing references |
19
19
  | What does it actually say? | `task context inspect <task> --store <family> --ref <id> --digest <digest>` | Exact current record, including original result expansion; long documents are paged |
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
- | Which Global input? | `session context <role>` | Identity, profile, authority, current native Turn/retry and separate bounded pending/recent Message pages |
21
+ | Which Global input? | `session context <role>` | Identity, Profile read pointer, authority, current native Turn/retry facts and a bounded pending Message page; history is opt-in |
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
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
- | 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 |
24
+ | What was assigned? | `task run context <task>/<run>` | Frozen authority, up to 16 `pointers`, sampled changed identities and live observations with totals; `--view refs` pages references, `--view full` reads the full pack |
25
+ | Which repeated failure? | `role message list <role> --diagnostics` | Derived classified groups with count, first/latest and recovery evidence; `--diagnostic <key>` pages original occurrences |
25
26
  | 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
27
 
27
28
  Domain lists for Task Messages, events, WorkItems, Runs, decisions, milestones,
@@ -35,23 +36,35 @@ workspaces and other authorized record families. `--status`, `--after` and
35
36
  `--work-item` narrow Context discovery; every continuation must retain filters.
36
37
  Run listing accepts a Task or `task/work` target.
37
38
 
38
- Current Context's `attention.messages` counts all authorized Messages, not only
39
- undelivered input. `collections` counts and `omitted` explicitly describe
40
- incomplete discovery. Recent samples are not proof that no older pending or
39
+ Current Context's `attention.messages` excludes explicit acknowledgements and
40
+ retirements; delivery alone is not handling. The exact wake receipt and latest
41
+ Message revision determine coverage. `--view current` continues that view;
42
+ the default family list still includes history. `collections` counts and `omitted`
43
+ explicitly describe incomplete discovery. Samples are not proof that no older pending or
41
44
  relevant input exists. Read the relevant fixed wake and original Messages;
42
45
  use family discovery when a broader requirement/history audit is needed.
43
46
 
44
47
  ## Budgets and continuations
45
48
 
46
- - Discovery pages default to 20 items, accept 1–100, and reserve a 32 KiB
47
- compact-JSON budget. Items contain summaries, never full Message/report bodies.
49
+ - Discovery pages default to 20 items, accept 1–100, and enforce a 32 KiB
50
+ compact-JSON budget including the success envelope, escaped identities,
51
+ continuation and nested structure. Summaries are at most 512 UTF-8 bytes.
48
52
  - Current Task Context has at most 64 records, with a 24 KiB record/attention
49
53
  budget inside a 32 KiB response budget. Single inline values are at most
50
54
  2 KiB; large values and Message/Run/WorkItem/Knowledge bodies use references.
51
55
  Each collection contributes at most eight sampled records at entry.
52
- - Global entry samples up to eight pending and eight recent Messages separately.
53
- They have independent continuations, so a long historical list cannot crowd
54
- pending input out of the entry view.
56
+ - Global entry samples up to eight unacknowledged inputs, including claimed or
57
+ uncertain ones. It does not repeat recent history, Profile bodies, frozen Skill
58
+ packages or accumulated retry details. The Manifest is the Profile pointer;
59
+ explicit Message and Session retry reads retain history and original evidence.
60
+ - Run entry samples up to eight records per live category and 16 frozen refs.
61
+ Pointer continuation uses `--view refs` and `pointerPage.nextCursor`; full pack
62
+ document continuation uses `--view full`. Neither changes the frozen authority.
63
+ Read `--view input` before acting when `input.directiveOmitted` is true: the
64
+ entry's bounded directive summary is not the assigned instruction body.
65
+ - `session skills [--cursor ...]` checks only current metadata/readability. It
66
+ does not read Skill bodies or historical packages, and uses document pagination
67
+ only when the configured metadata exceeds the inline budget.
55
68
  - Detail documents up to 16 KiB remain ordinary JSON. Larger documents return
56
69
  `contentPage`: exact source, SHA-256 digest, JSON-character offset, total bytes
57
70
  and characters, text, completeness and a next cursor. Chunks contain at most
@@ -78,6 +91,24 @@ concurrent writes. For append-only event traversal use fixed-bound Context delta
78
91
  Discovery currently scans the selected authorized family to fingerprint it;
79
92
  its output, not total storage-reading cost, is bounded.
80
93
 
94
+ ## Runtime diagnostics
95
+
96
+ Global failure evidence remains ordinary record-only Messages; no aggregate
97
+ table, Message envelope change, memory store or recovery state machine is added.
98
+ Grouping is a derived view of new evidence documents. Older documents remain
99
+ readable in ordinary history, not heuristically reclassified. Classified source,
100
+ Host/Session, error category/code and explicit effect distinctions determine
101
+ equivalence; unclassified faults are not merged. Original affected IDs and raw
102
+ evidence remain in exact documents, never a growing array in one notification.
103
+ Counts represent distinct observations, not repeat polls of the same identity.
104
+
105
+ One queued notice represents an unchanged failure episode. Only a new group,
106
+ changed impact or exact successful recovery observation produces a new notice.
107
+ Recovery ends the corresponding episode without acknowledging inputs or proving
108
+ absence of previous effects. Recurrence after recovery gets a new episode.
109
+ Operator's own failures/recovery notices are retained without self-delivery.
110
+ Discovery and every evidence page retain the existing Role read boundary.
111
+
81
112
  ## Effects and exceptions
82
113
 
83
114
  Message send/queue/steer receipts preserve identity, digest, body byte count and
@@ -12,14 +12,14 @@ CLI 调用成功,不代表 Task、原生 Turn 或远端投递完成。
12
12
  | 问题 | 入口 | 默认信息与下一步 |
13
13
  | --- | --- | --- |
14
14
  | 找哪个 Task? | `task list` | 既有有界目录、过滤器、attention 与游标 |
15
- | 当前有什么? | `task context <task>` | 当前 Task/Brief/Role/Project/工作区事实、活跃工作与 Run、开放输入、有效决策、未解决 Job、近期 Message 引用;不倾倒事件或终态 Run |
15
+ | 当前有什么? | `task context <task>` | 当前事实、活跃工作、开放输入、有效决策、未解决 Job、未确认处理的 Message 引用;不倾倒事件或终态 Run |
16
16
  | 有哪些记录? | `task context list <task> --store <family>` | 一种获授权的记录、摘要与带 digest 的确切引用 |
17
17
  | 原文是什么? | `task context inspect <task> --store <family> --ref <id> --digest <digest>` | 确切当前记录,含原始结果展开;长文档分页 |
18
18
  | 发生了什么变化? | `task context delta <task> --after <cursor>` | 固定上界内的不可变事件,不是可变当前状态的快照 |
19
- | Global 收到了什么? | `session context <role>` | 身份、Profile、权限、当前原生 Turn/retry,以及分别有界的 pending/recent Message 页 |
19
+ | Global 收到了什么? | `session context <role>` | 身份、Profile 读取指针、权限、当前 Turn/retry 事实与小窗口 pending 页;历史按需读取 |
20
20
  | 读取 Global 输入 | `role message list <role> [--pending]`、`role message show <role> <id>` | 在自身范围内发现,再读完整原文;队列接受不删除历史 |
21
21
  | 本次唤醒带来什么? | `task wake show <task> <wake>` | 固定窗口的输入/结果、标明来源的可选摘要和确切原文入口;`--history` 展开诊断历史 |
22
- | 分配了什么? | `task run context <task>/<run>` | 冻结授权与一份带摘要的 `pointers` 目录;`deltaRefs` 表示变化身份;当前观察独立 |
22
+ | 分配了什么? | `task run context <task>/<run>` | 冻结授权与有限 `pointers` 窗口,变化身份和活跃观察附总数;`--view refs/full` 按需扩展 |
23
23
  | 实际配置是什么? | `task role session inspect <task> <role>` | Task/Role 身份、期望绑定、冻结 Session、当前 Provider 绑定、retry 与显式 Host 观察;不复制整个 Task/Role 或 Provider 会话历史 |
24
24
 
25
25
  Task Message、事件、WorkItem、Run、决策、里程碑、publication 和 InputRequest 列表
@@ -31,17 +31,26 @@ Context 列表还暴露候选、Review、Job、Project Knowledge、工作区等
31
31
  `--status`、`--after`、`--work-item` 缩小发现范围;续读必须保留过滤条件。
32
32
  Run 列表接受 Task 或 `task/work` 目标。
33
33
 
34
- 当前 Context 的 `attention.messages` 统计全部获授权 Message,不仅是未投递输入。
35
- `collections` 计数与 `omitted` 明确表达发现不完整。近期抽样不能证明没有更早的待处理
34
+ 当前 Context 的 `attention.messages` 排除明确 ack 或退役的 Message;投递成功不代表
35
+ 处理完成。精确 wake 回执必须覆盖最新原文版本。用 `--view current` 续读当前视图,
36
+ 默认分类列表仍保留完整历史。`collections` 计数与 `omitted` 明确表达发现不完整。抽样不能证明没有更早的待处理
36
37
  或相关输入。读取相关固定 wake 与原始 Message;更广的需求/历史审计使用分类发现。
37
38
 
38
39
  ## 预算与续读
39
40
 
40
- - 发现页默认 20 条,可选 1–100,紧凑 JSON 预算 32 KiB。条目包含摘要,不含完整报告正文。
41
+ - 发现页默认 20 条,可选 1–100,紧凑 JSON 预算 32 KiB,计入成功 envelope、
42
+ 转义身份、游标和嵌套结构。摘要至多 512 UTF-8 字节,不含完整报告正文。
41
43
  - 当前 Task Context 至多 64 条,记录与 attention 共 24 KiB,响应预算 32 KiB。
42
44
  单个内联值至多 2 KiB;大值及 Message/Run/WorkItem/Knowledge 正文用引用。
43
45
  入口每个集合最多抽样八条。
44
- - Global 入口分别抽样八条 pending 与八条 recent;独立续读,历史不能挤掉待处理输入。
46
+ - Global 入口最多八条未确认处理的输入,保留已领取或效果未知项;不重复 recent、
47
+ Profile 正文、历史 Skill 包和累计 retry 详情。Profile 由 Manifest 精确指向。
48
+ - Run 入口最多 16 个冻结引用和每类八条活跃观察,附总数。`--view refs` 配合
49
+ `pointerPage.nextCursor` 发现更多引用;`--view full` 显式读取完整冻结包。
50
+ 若 `input.directiveOmitted` 为 true,行动前用 `--view input` 全文读取分配指令;
51
+ 默认入口的指令摘要不是指令正文。
52
+ - `session skills [--cursor ...]` 只检查当前元信息和可读性,不读技能正文;
53
+ 配置元信息过大时使用相同文档分页。
45
54
  - 不超过 16 KiB 的详情保持普通 JSON。更大详情返回 `contentPage`:确切来源、
46
55
  SHA-256 digest、JSON 字符偏移、总字节数/字符数、文本、完整性与下一游标。
47
56
  每块最多 4096 个 UTF-16 单元,不拆代理对,转义后的输出低于 32 KiB。
@@ -61,6 +70,18 @@ Run 列表接受 Task 或 `task/work` 目标。
61
70
  追加事件遍历使用固定上界 Context delta。目前分类发现扫描选定的授权集合来计算指纹;
62
71
  有界的是输出,不是总存储读取成本。
63
72
 
73
+ ## 重复运行时诊断
74
+
75
+ `role message list <role> --diagnostics` 从原始 record-only Message 派生故障组,
76
+ 给出首次/最近时间、不同观察的数量及恢复证据;`--diagnostic <key>` 分页发现原文。
77
+ 按明确的 Host/Session、来源、故障类别/代码及效果边界区分;未分类错误不猜测合并。
78
+ 同一观察重复轮询不新增记录或计数,同组跨 Turn 不重复唤醒。新故障、影响变化、
79
+ 精确成功恢复或恢复后再发生可产生通知。Operator 自身诊断保留但不自动唤醒自身。
80
+ 恢复不等于消息 ack、Task 完成或撤销旧副作用。
81
+
82
+ 聚合不持久化,也不累计受影响 ID 数组;不增加表、消息 envelope 字段或第二状态机。
83
+ 旧证据仍由普通历史读取,不启发式重新分类。每页沿用现有 Role 权限边界。
84
+
64
85
  ## 效果与例外
65
86
 
66
87
  Message send/queue/steer 回执保留身份、digest、正文字节数及原有提交/投递/control
@@ -39,6 +39,40 @@ automatically create Runs. Explicit dispatch loads one exact Run Context Pack.
39
39
 
40
40
  ## Context
41
41
 
42
+ ### Current caller and durable handling
43
+
44
+ Desktop and TUI use the same current-Session authority. A Desktop command carrying
45
+ only `CODEX_THREAD_ID` resolves its owner from the selected Home's existing active
46
+ Session inventory, then verifies the current Role/Agent binding, revocation and
47
+ captured workspace. Codex's native ID takes precedence over an inherited transport
48
+ ID, so a native child cannot borrow its parent's identity. Unknown native IDs,
49
+ wrong Homes and conflicting hints fail closed; only a terminal with no managed or
50
+ native identity is a plain user. Environment variables and a Manifest locate
51
+ context, not continuing authority. A replaced Session retains only its bounded
52
+ self-diagnostic reads, not inbox or mutation permission.
53
+
54
+ `yui inbox list` exposes the current identity, delivery evidence, handling state
55
+ and blockers separately. Reads never consume input. Automatically accepted
56
+ Global messages, delivered Leader windows and the current Assignment's
57
+ continuation messages still need `claim` and explicit `ack --reason` after their
58
+ originals and effects have been handled. Claiming delivered input does not resend
59
+ it. Pending/unknown acceptance cannot be taken over; an accepted Global input or
60
+ Leader window can be explicitly settled by its rightful successor without
61
+ changing its original delivery target. Include useful result/effect receipt
62
+ references in the reason. Task completion still requires handling user inputs,
63
+ not merely a native terminal.
64
+
65
+ Receipts remain on the existing Message/TaskWake records. Both notification
66
+ paths pin mutable Draft revisions by existing `message.updated` event IDs,
67
+ not timestamps; a later revision cannot inherit an old acknowledgement.
68
+ Claimed Message content and fixed window references cannot be silently replaced.
69
+ Duplicate accepted notifications do not re-submit that revision. If a handler
70
+ crashes or ack fails after an external effect, inspect the original claim and
71
+ effect receipt, finish only unfinished work, and retry the same acknowledgement.
72
+ No lease expires and no installation upgrade or context compaction resets
73
+ handling. This reuses storage 1.7 payloads without adding a message system,
74
+ schema transition or an arbitrary external exactly-once guarantee.
75
+
42
76
  ```sh
43
77
  yui task context <task> --json
44
78
  yui task context list <task> --store <store> [--cursor <cursor>]
@@ -181,12 +215,17 @@ terminal for the exact Session, authority, attempt and native Turn. For a Deskto
181
215
  direct Turn, that Host must have retained both the exact start and terminal under
182
216
  the unchanged writer fence; `direct:<nativeTurnId>` and the native Turn are both
183
217
  required. This bounded latest observation does not make the input client-owned.
218
+ During an Inbox persistence failure, the Host additionally retains every
219
+ unpersisted original fact, including starts and full terminals, until the
220
+ existing Inbox accepts it. Later direct turns must not overwrite those bytes.
184
221
  This uses the existing Inbox and canonical observer, including the original result.
185
222
  It does not submit input, query another native client, restart a Host, or infer
186
223
  quiescence from elapsed time/idle state. Normal terminal processing signals again
187
224
  after releasing Host occupancy. Unknown acceptance remains isolated unless exact
188
225
  evidence settles that input. Explicit stop/replacement and external writers remain
189
- hard boundaries.
226
+ hard boundaries. Full Task and Global reconciliation also covers an unsettled
227
+ final input with no queued successor. A filesystem repair retries observations,
228
+ not native execution; process loss before persistence remains a disclosed gap.
190
229
 
191
230
  `yui session context <role> --json` includes bounded `backlog` diagnostics: pending
192
231
  count, oldest timestamp, target and attempt identities, blocking reason and
@@ -211,6 +250,13 @@ that CLI. An Endpoint checkout generation is not a complete Host build identity.
211
250
  The runtime-attention evidence distinguishes an unavailable control channel,
212
251
  rejected control (including implementations without reconciliation), and a missing
213
252
  exact retained terminal, with reported Endpoint/event-delivery observations.
253
+ The status `controlCapabilities` advertisement gates additive v1 commands.
254
+ Missing `reconcile-turn` support yields `unsupported` without sending the
255
+ invalid request. The original Inbox remains usable; no alternative native
256
+ input or guessed terminal is generated. `hostImplementation` identifies code
257
+ captured when the Host loaded, not the current install or Endpoint generation.
258
+ Compatible build changes do not block exact native Session resume after an
259
+ authorized safe release. They never change the user's launch configuration.
214
260
  Missing delivery diagnostics mean unreported, not healthy. Unsupported live code
215
261
  cannot be repaired by another Controller restart or guessed adoption; inspect the
216
262
  original evidence and explicitly authorize any necessary lifecycle recovery.
@@ -2,6 +2,30 @@
2
2
 
3
3
  # Session、AgentRun 与通知
4
4
 
5
+ ## 当前身份与持久处理回执
6
+
7
+ 桌面与 TUI 使用相同的当前 Session 授权。只有 `CODEX_THREAD_ID` 的桌面命令
8
+ 先在所选 Home 的现有活动 Session 索引中定位角色,再校验当前绑定、撤销状态、
9
+ 工作域和 Assignment。Codex 原生线程 ID 优先于继承的 transport ID,原生子
10
+ Agent 不能借用父身份。错误 Home、未知线程和冲突提示会明确拒绝,不降为公共
11
+ 用户;只有不带受管或原生身份的终端才是普通用户。环境变量和 Manifest 是
12
+ 定位提示,不是持续授权。旧 Session 仅保留限定的自身诊断读取。
13
+
14
+ `yui inbox list` 分别返回当前身份、投递事实、处理状态和阻断原因。自动接受的
15
+ Global 消息、已投递的 Leader 窗口及当前 Assignment 续接消息仍须显式 claim,
16
+ 核对原文和既有副作用,完成处理后再 `ack --reason`。这不会重新投递输入;
17
+ pending/unknown 不能借 claim 接管。合法继任者可以核对并结清已接受的 Global
18
+ 输入或 Leader 窗口,保留原投递目标。说明中可引用结果和外部操作回执。
19
+ native terminal 不能替代用户输入处理,也不能单独满足 Task 完成条件。
20
+
21
+ 回执继续保存在现有 Message/TaskWake 中。自动通知和主动领取都以既有
22
+ `message.updated` 事件 ID 绑定可变 Draft 修订,同时间戳的修改也不会沿用旧
23
+ ack。已领取消息的原文和固定窗口引用不能被悄悄替换,重复通知不会重新提交
24
+ 已投递修订。处理崩溃或副作用完成后 ack 失败时,先读回 claim 和外部回执,
25
+ 只完成未完成工作,再重试相同确认。上下文压缩、Session 续接和升级不清空回执。
26
+ 实现复用 storage 1.7 的现有字段,不新增消息系统或 schema 迁移,也不承诺
27
+ 任意外部系统的天然 exactly-once。
28
+
5
29
  Global Session 停止/替换与 Task Session 共用精确的原生执行静止确认边界。
6
30
  Host 消失或 Session 已入历史不代表已接受输入结束:须先检查并停止保留的
7
31
  Provider binding,再结算执行占用。Global 停止证据保存为仅记录的 system Message,
@@ -151,10 +175,18 @@ runtime-attention Message,可通过既有 message list/show 查看,不自动
151
175
 
152
176
  Controller 重启保留存活 Host,不替换它们已加载的代码。支持当前协议的原 Host 在 Controller
153
177
  停机期间仍把原始观察写入不可变 Inbox,重启后由 Controller 按当前 Session 围栏应用。
178
+ Inbox 写入故障时,Host 保留尚未持久化的原始 start 与完整终态,不能被后续直接 Turn
179
+ 覆盖;修复后按原始观察顺序补收。Task 与 Global 完整协调也覆盖没有后续输入的最后
180
+ 一个未结算 Turn。补收不重执行;落盘前进程丢失仍是明确的恢复缺口。
154
181
  冻结 Manifest 的旧 CLI/storage 不匹配是 Context 读取失败,不足以证明 Host 发布失败:
155
182
  发布器使用 Inbox/RPC,不执行该 CLI。Endpoint 的 checkout generation 也不是完整 Host
156
183
  构建身份。runtime-attention 区分控制通道不可达、控制被拒绝(包括实现不支持协调)和
157
184
  精确终态未保留,并附已报告的 Endpoint/eventDelivery 观察;缺少诊断表示未报告,而非健康。
185
+ status 的 `controlCapabilities` 决定可用的 v1 增量命令,未声明 `reconcile-turn` 时
186
+ 直接返回 unsupported,不发送已知无效请求,仍可消费原始 Inbox。
187
+ `hostImplementation` 在 Host 加载时捕获,不借磁盘当前安装或 Endpoint generation
188
+ 冒充运行代码。兼容构建差异不阻止安全释放后的同一原生 Session 恢复,
189
+ 不改变模型、账号、原生权限或工作域。
158
190
  再次重启 Controller 或猜测 adoption 不能修复不支持的存活代码;须检查原证据,并为必要的
159
191
  生命周期恢复另行取得明确授权。
160
192