@sema-agent/server 7.122.0 → 7.124.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 (256) hide show
  1. package/MIGRATION.md +209 -0
  2. package/README.md +7 -2
  3. package/README.zh-CN.md +5 -2
  4. package/USAGE.md +76 -56
  5. package/dist/approval-ask-audit-store.d.ts +27 -32
  6. package/dist/approval-ask-audit-store.js +10 -9
  7. package/dist/approval-crash-convergence.d.ts +2 -2
  8. package/dist/approval-crash-convergence.js +5 -5
  9. package/dist/approval-deny-reasons.d.ts +163 -51
  10. package/dist/approval-deny-reasons.js +79 -8
  11. package/dist/approval-policy-settlement.d.ts +4 -1
  12. package/dist/approval-policy-settlement.js +3 -2
  13. package/dist/approval-reconciler.d.ts +3 -3
  14. package/dist/approval-reconciler.js +10 -10
  15. package/dist/approval.d.ts +1 -1
  16. package/dist/approval.js +1 -1
  17. package/dist/audit.d.ts +1 -1
  18. package/dist/audit.js +53 -23
  19. package/dist/auth-bridge.d.ts +8 -8
  20. package/dist/auth-bridge.js +6 -6
  21. package/dist/auth-keys.d.ts +2 -2
  22. package/dist/auto-mode-face.d.ts +13 -9
  23. package/dist/auto-mode-face.js +8 -7
  24. package/dist/boot/budget-tracing.js +1 -1
  25. package/dist/boot/execution-env.js +1 -0
  26. package/dist/boot/leader.d.ts +1 -1
  27. package/dist/boot/memory-consolidation.d.ts +4 -4
  28. package/dist/boot/org-memory.d.ts +3 -3
  29. package/dist/boot/org-memory.js +5 -5
  30. package/dist/boot/resolve-spec.js +7 -7
  31. package/dist/boot/runner-deps.d.ts +1 -1
  32. package/dist/boot/runtime-caps.d.ts +1 -1
  33. package/dist/boot/runtime-caps.js +10 -10
  34. package/dist/boot/shutdown.d.ts +2 -2
  35. package/dist/boot/shutdown.js +2 -2
  36. package/dist/boot/side-query-lane.d.ts +3 -3
  37. package/dist/boot/{stage-02-registry-pull.d.ts → stage-02-web-admin-pull.d.ts} +2 -2
  38. package/dist/boot/{stage-02-registry-pull.js → stage-02-web-admin-pull.js} +4 -4
  39. package/dist/boot/stage-03-store-backend.d.ts +2 -2
  40. package/dist/boot/stage-04-stores.d.ts +1 -1
  41. package/dist/boot/stage-05-execution-env.d.ts +1 -1
  42. package/dist/boot/stage-06-runners.d.ts +2 -2
  43. package/dist/boot/stage-06-runners.js +6 -6
  44. package/dist/boot/stage-07-capability-layer.d.ts +2 -2
  45. package/dist/boot/stage-07-capability-layer.js +6 -5
  46. package/dist/boot/stage-08-reapers.d.ts +3 -3
  47. package/dist/boot/stage-08-reapers.js +3 -3
  48. package/dist/boot/stage-09-leader.d.ts +3 -3
  49. package/dist/boot/stage-09-leader.js +7 -7
  50. package/dist/boot/stage-10-http-server.d.ts +3 -3
  51. package/dist/boot/stage-10-http-server.js +19 -19
  52. package/dist/boot/unpriced-ceiling-verdict.d.ts +1 -1
  53. package/dist/boot/{config-center.d.ts → web-admin.d.ts} +11 -11
  54. package/dist/boot/{config-center.js → web-admin.js} +39 -20
  55. package/dist/boot/webfetch-summarize-lane.d.ts +2 -2
  56. package/dist/brain.d.ts +1 -1
  57. package/dist/brain.js +1 -1
  58. package/dist/budget.d.ts +3 -3
  59. package/dist/canonical-json.d.ts +2 -2
  60. package/dist/capabilities/center-plugins.d.ts +1 -1
  61. package/dist/capabilities/center-wiring.d.ts +12 -5
  62. package/dist/capabilities/center-wiring.js +11 -2
  63. package/dist/capabilities/composite-members.d.ts +1 -1
  64. package/dist/capabilities/composite-members.js +1 -1
  65. package/dist/capabilities/scenarios.js +2 -2
  66. package/dist/capabilities/team.d.ts +1 -1
  67. package/dist/capabilities/tool-defer.d.ts +1 -1
  68. package/dist/center-credential-renewer.d.ts +1 -1
  69. package/dist/center-credential-renewer.js +7 -7
  70. package/dist/center-credential.d.ts +9 -9
  71. package/dist/center-credential.js +6 -6
  72. package/dist/config-catalog.d.ts +7 -10
  73. package/dist/config-catalog.js +16 -16
  74. package/dist/config-d-migration.d.ts +32 -0
  75. package/dist/config-d-migration.js +59 -0
  76. package/dist/config-invariants.d.ts +14 -4
  77. package/dist/config-invariants.js +31 -2
  78. package/dist/config-lkg.d.ts +34 -11
  79. package/dist/config-lkg.js +76 -48
  80. package/dist/config-provider.d.ts +26 -21
  81. package/dist/config-provider.js +25 -27
  82. package/dist/config-types.d.ts +59 -50
  83. package/dist/config.d.ts +17 -54
  84. package/dist/config.js +99 -181
  85. package/dist/execution-lane-caps.d.ts +1 -1
  86. package/dist/fleet/drain-entry.d.ts +1 -1
  87. package/dist/fleet/engine-signal.d.ts +61 -30
  88. package/dist/fleet/engine-signal.js +29 -5
  89. package/dist/fleet/fleet-bus.d.ts +12 -3
  90. package/dist/fleet/fleet-bus.js +13 -9
  91. package/dist/fleet/serving-lease.d.ts +3 -3
  92. package/dist/fleet/serving-lease.js +1 -1
  93. package/dist/fleet-client.d.ts +15 -13
  94. package/dist/fleet-client.js +9 -7
  95. package/dist/fleet-lease.d.ts +3 -3
  96. package/dist/fleet-lease.js +2 -2
  97. package/dist/host-lsp-manager.d.ts +1 -1
  98. package/dist/hosted-posture.d.ts +4 -4
  99. package/dist/http/admission.js +4 -4
  100. package/dist/http/checkpoint-ctx.d.ts +20 -3
  101. package/dist/http/checkpoint-ctx.js +13 -5
  102. package/dist/http/dispatch.js +7 -16
  103. package/dist/http/durable-run-leg.js +2 -1
  104. package/dist/http/health-self-report.d.ts +7 -4
  105. package/dist/http/health-self-report.js +3 -3
  106. package/dist/http/idempotency.d.ts +1 -1
  107. package/dist/http/resume-legs.d.ts +4 -3
  108. package/dist/http/resume-legs.js +31 -18
  109. package/dist/http/route-ctx.d.ts +8 -0
  110. package/dist/http/routes/admin-config-refresh.d.ts +1 -1
  111. package/dist/http/routes/admin-config-refresh.js +1 -1
  112. package/dist/http/routes/admin-drain.d.ts +1 -1
  113. package/dist/http/routes/admin-drain.js +5 -4
  114. package/dist/http/routes/approvals-assistant.js +4 -4
  115. package/dist/http/routes/capabilities.js +6 -5
  116. package/dist/http/routes/config-catalog.js +2 -3
  117. package/dist/http/routes/diagnostics.js +1 -1
  118. package/dist/http/routes/runs.js +8 -4
  119. package/dist/http/routes/sessions-list.js +2 -1
  120. package/dist/http/routes/sessions.js +2 -5
  121. package/dist/http/routes/side-query.js +3 -3
  122. package/dist/http/routes/tasks.js +3 -2
  123. package/dist/http/run-meta.d.ts +1 -1
  124. package/dist/http/run-meta.js +2 -2
  125. package/dist/http/server.d.ts +7 -7
  126. package/dist/http/server.js +1 -1
  127. package/dist/http/stored-body-replay.d.ts +4 -3
  128. package/dist/http/stored-body-replay.js +5 -5
  129. package/dist/index.d.ts +2 -1
  130. package/dist/index.js +1 -1
  131. package/dist/key-resolver.d.ts +1 -1
  132. package/dist/leader/leader.d.ts +7 -6
  133. package/dist/leader/leader.js +3 -1
  134. package/dist/leader/run-entry.d.ts +2 -2
  135. package/dist/leader/run-entry.js +3 -3
  136. package/dist/leader/wire.d.ts +4 -4
  137. package/dist/leader/wire.js +2 -1
  138. package/dist/main.js +1 -1
  139. package/dist/mcp-tool-faces.d.ts +2 -2
  140. package/dist/model-entry-refusal.d.ts +20 -11
  141. package/dist/model-entry-refusal.js +22 -17
  142. package/dist/model-provider.d.ts +2 -2
  143. package/dist/model-route-endpoint.d.ts +22 -2
  144. package/dist/model-route-endpoint.js +9 -3
  145. package/dist/model-route-gap.d.ts +103 -0
  146. package/dist/model-route-gap.js +80 -0
  147. package/dist/model-route-url.d.ts +1 -1
  148. package/dist/model-route-url.js +2 -1
  149. package/dist/model-select.d.ts +24 -21
  150. package/dist/model-select.js +22 -17
  151. package/dist/namespaced-rule-name.d.ts +16 -30
  152. package/dist/namespaced-rule-name.js +2 -20
  153. package/dist/observability/fail-open.d.ts +0 -4
  154. package/dist/observability/fail-open.js +0 -4
  155. package/dist/observability/metrics.d.ts +1 -1
  156. package/dist/org-memory-admission.d.ts +1 -1
  157. package/dist/plugins/approval-ask-store-file.d.ts +4 -2
  158. package/dist/plugins/approval-ask-store-file.js +3 -3
  159. package/dist/plugins/approval-ask-store-memory.d.ts +4 -3
  160. package/dist/plugins/approval-ask-store-memory.js +10 -4
  161. package/dist/plugins/approval-ask-store-sql.d.ts +16 -2
  162. package/dist/plugins/approval-ask-store-sql.js +20 -13
  163. package/dist/plugins/caching-session-store.d.ts +0 -10
  164. package/dist/plugins/caching-session-store.js +0 -3
  165. package/dist/plugins/file-run-store.js +9 -3
  166. package/dist/plugins/leader-run-store-sql.d.ts +3 -2
  167. package/dist/plugins/leader-run-store-sql.js +3 -2
  168. package/dist/plugins/local-session-store.d.ts +20 -27
  169. package/dist/plugins/local-session-store.js +19 -17
  170. package/dist/plugins/memory-run-store.js +9 -3
  171. package/dist/plugins/one-time-migrations.js +51 -0
  172. package/dist/plugins/scheduler-support.d.ts +26 -7
  173. package/dist/plugins/scheduler-support.js +96 -53
  174. package/dist/plugins/session-policy-store-sql.js +1 -2
  175. package/dist/plugins/store-backend.js +1 -1
  176. package/dist/plugins/store-contracts.d.ts +20 -4
  177. package/dist/plugins/web-search.d.ts +1 -1
  178. package/dist/plugins/web-search.js +2 -1
  179. package/dist/plugins/workflow-run-store-sql.d.ts +4 -2
  180. package/dist/posture-source.d.ts +1 -1
  181. package/dist/read-face-posture.d.ts +3 -3
  182. package/dist/read-face-posture.js +1 -1
  183. package/dist/rule-entry-list.d.ts +3 -13
  184. package/dist/rule-entry-list.js +1 -12
  185. package/dist/run-local.js +10 -7
  186. package/dist/runtime-caps-resolver.d.ts +4 -4
  187. package/dist/runtime-caps-resolver.js +2 -2
  188. package/dist/runtime-governance.d.ts +36 -13
  189. package/dist/runtime-governance.js +7 -2
  190. package/dist/sealed-key.d.ts +4 -4
  191. package/dist/sealed-key.js +3 -2
  192. package/dist/security.d.ts +3 -3
  193. package/dist/service-version.d.ts +1 -1
  194. package/dist/service-version.js +5 -0
  195. package/dist/session-policy-wire.d.ts +47 -49
  196. package/dist/session-policy-wire.js +41 -36
  197. package/dist/session-sync.d.ts +5 -1
  198. package/dist/session-sync.js +2 -1
  199. package/dist/session-titler.d.ts +0 -11
  200. package/dist/session-titler.js +3 -5
  201. package/dist/shared-memory-scope-authorizer.d.ts +4 -4
  202. package/dist/spec-fields.d.ts +4 -4
  203. package/dist/spec-fields.js +1 -4
  204. package/dist/task-a2a.d.ts +1 -1
  205. package/dist/task-settings.d.ts +4 -5
  206. package/dist/task-settings.js +5 -8
  207. package/dist/tool-approval.d.ts +43 -4
  208. package/dist/tool-approval.js +147 -98
  209. package/dist/trace/core-keyset-guard.d.ts +1 -1
  210. package/dist/trace/project.d.ts +3 -3
  211. package/dist/trace/redact.d.ts +2 -23
  212. package/dist/trace/redact.js +1 -6
  213. package/dist/trace/self-minted-wire.d.ts +147 -3
  214. package/dist/trace/self-minted-wire.js +50 -9
  215. package/dist/unattended-permission-mode.d.ts +3 -3
  216. package/dist/unattended-permission-mode.js +2 -2
  217. package/dist/url-refusal.d.ts +35 -0
  218. package/dist/url-refusal.js +15 -0
  219. package/dist/user-authored-text.d.ts +31 -0
  220. package/dist/user-authored-text.js +18 -0
  221. package/dist/{config-center → web-admin-client}/apply-effective.d.ts +13 -70
  222. package/dist/{config-center → web-admin-client}/apply-effective.js +104 -121
  223. package/dist/{config-center → web-admin-client}/apply-ledger.d.ts +2 -2
  224. package/dist/{config-center → web-admin-client}/center-request.d.ts +7 -7
  225. package/dist/{config-center → web-admin-client}/center-request.js +5 -4
  226. package/dist/{config-center → web-admin-client}/effective-keys.d.ts +1 -3
  227. package/dist/{config-center → web-admin-client}/effective-keys.js +0 -9
  228. package/dist/{config-center → web-admin-client}/facade.d.ts +6 -6
  229. package/dist/{config-center → web-admin-client}/facade.js +2 -2
  230. package/dist/{config-center → web-admin-client}/http-client.d.ts +6 -10
  231. package/dist/{config-center → web-admin-client}/http-client.js +15 -15
  232. package/dist/{config-center → web-admin-client}/pull-state.d.ts +1 -1
  233. package/dist/{config-center → web-admin-client}/read-face.js +4 -4
  234. package/dist/web-admin-client/read-warnings.d.ts +137 -0
  235. package/dist/web-admin-client/read-warnings.js +168 -0
  236. package/dist/{config-center → web-admin-client}/restart-signal.d.ts +5 -3
  237. package/dist/{config-center → web-admin-client}/restart-signal.js +3 -4
  238. package/dist/{config-center → web-admin-client}/skills-mcp.d.ts +1 -1
  239. package/dist/{config-center → web-admin-client}/skills-mcp.js +13 -13
  240. package/dist/{config-center → web-admin-client}/stage-limits.d.ts +1 -7
  241. package/dist/{config-center → web-admin-client}/stage-limits.js +6 -7
  242. package/dist/{config-center → web-admin-client}/types.d.ts +19 -47
  243. package/package.json +3 -3
  244. package/skills/find-skills.md +2 -2
  245. package/dist/config-center/read-warnings.d.ts +0 -109
  246. package/dist/config-center/read-warnings.js +0 -110
  247. package/dist/url-shape.d.ts +0 -31
  248. package/dist/url-shape.js +0 -41
  249. /package/dist/{config-center → web-admin-client}/apply-ledger.js +0 -0
  250. /package/dist/{config-center → web-admin-client}/hot-keys-registry.d.ts +0 -0
  251. /package/dist/{config-center → web-admin-client}/hot-keys-registry.js +0 -0
  252. /package/dist/{config-center → web-admin-client}/mcp-revocation.d.ts +0 -0
  253. /package/dist/{config-center → web-admin-client}/mcp-revocation.js +0 -0
  254. /package/dist/{config-center → web-admin-client}/pull-state.js +0 -0
  255. /package/dist/{config-center → web-admin-client}/read-face.d.ts +0 -0
  256. /package/dist/{config-center → web-admin-client}/types.js +0 -0
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Config-center adapter — pull the effective config from the config-center control plane and
2
+ * Web-admin adapter — pull the effective config from the web-admin control plane and
3
3
  * apply it OVER the env-derived defaults (env = fallback, center = override). Follows the
4
4
  * "universal internal schema → translate at the boundary" pattern, with our security boundary kept:
5
5
  *
6
6
  * (name history: this module tracks the control plane's product name, which has changed over time
7
7
  * — registry → sema-web → sema-web-admin (2026-08-26 repo/product rename; an earlier revision of
8
8
  * this note listed "planned sema-admin" as the next step). The module itself keeps a neutral, product-name-free
9
- * identifier ("config-center") and does not chase the rename.)
9
+ * identifier ("web-admin") and does not chase the rename.)
10
10
  *
11
11
  * - the CENTER owns the LOGICAL config: the model roster (names/capabilities/tier), the role map,
12
12
  * and collab (multi-agent discussion) templates;
@@ -41,14 +41,14 @@
41
41
  * (`governance.approvalRequire` left this list in S-668 波 2 — its own staged group, hot on both legs.)
42
42
  *
43
43
  * ([ref] A13, internal-lossless) This module is now a FACADE: the implementation lives
44
- * alongside it in `src/config-center/` split by responsibility group (HTTP client / EffectiveConfig
44
+ * alongside it in `src/web-admin-client/` split by responsibility group (HTTP client / EffectiveConfig
45
45
  * application / restart-signal detection / skills+MCP consumption). Every symbol below is
46
- * re-exported UNCHANGED — existing `from ".../config-center/facade.js"` imports need zero changes
46
+ * re-exported UNCHANGED — existing `from ".../web-admin-client/facade.js"` imports need zero changes
47
47
  * across a rename of this file's *contents*; a path rename (this move, 2026-07-29) does require the
48
48
  * importers to update, which was done in the same commit.
49
49
  */
50
- export { fetchEffective, fetchPrincipalCaps, fetchPrincipalOrgMemory, ConfigCenterHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./http-client.js";
51
- export { mutateInPlace, applyEffective, type ApplyReport, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, MODEL_PLANE_DOMAINS, type ModelPlaneDomain, type ModelPlaneOf, withModelPlaneOf, fullyLandedForLkg, } from "./apply-effective.js";
50
+ export { fetchEffective, fetchPrincipalCaps, fetchPrincipalOrgMemory, WebAdminHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./http-client.js";
51
+ export { mutateInPlace, applyEffective, type ApplyReport, applyRuntimeGates, applyRuntimeHot, logEffectiveDiff, MODEL_PLANE_DOMAINS, type ModelPlaneDomain, type ModelPlaneOf, withModelPlaneOf, fullyLandedForLkg, } from "./apply-effective.js";
52
52
  export { restartReasons, modelPlaneChanged, type RestartSlice, type RestartSliceCtx, type EngineRestartSignal, } from "./restart-signal.js";
53
53
  export { applyCenterSkills, resolveMcpServers, mcpForScenario, resolveA2aPeers, a2aForScenario } from "./skills-mcp.js";
54
54
  export { applyCenterReadFace, CENTER_READ_FACE_LIVE_KEYS, type CenterReadFaceApply, type CenterReadFaceReport, type ReadFaceBaseline } from "./read-face.js";
@@ -1,5 +1,5 @@
1
- export { fetchEffective, fetchPrincipalCaps, fetchPrincipalOrgMemory, ConfigCenterHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./http-client.js";
2
- export { mutateInPlace, applyEffective, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, MODEL_PLANE_DOMAINS, withModelPlaneOf, fullyLandedForLkg, } from "./apply-effective.js";
1
+ export { fetchEffective, fetchPrincipalCaps, fetchPrincipalOrgMemory, WebAdminHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./http-client.js";
2
+ export { mutateInPlace, applyEffective, applyRuntimeGates, applyRuntimeHot, logEffectiveDiff, MODEL_PLANE_DOMAINS, withModelPlaneOf, fullyLandedForLkg, } from "./apply-effective.js";
3
3
  export { restartReasons, modelPlaneChanged, } from "./restart-signal.js";
4
4
  export { applyCenterSkills, resolveMcpServers, mcpForScenario, resolveA2aPeers, a2aForScenario } from "./skills-mcp.js";
5
5
  export { applyCenterReadFace, CENTER_READ_FACE_LIVE_KEYS } from "./read-face.js";
@@ -9,11 +9,7 @@ import { type CenterEndpoint } from "./center-request.js";
9
9
  * boot/refresh 的候选门直接消费。`droppedEntries`(S-704 ②):schema 逐条丢掉的条目(坐标 + 字段诊断)——
10
10
  * **不**进候选门,调用方响亮点名、其余照用(分面单点 `splitFoldedReadWarnings`,与本地腿同一只)。
11
11
  *
12
- * `readWarnings`:契约 `onWarning` 流的**原值**(未折叠),与本地腿同键同义。折叠是**有损**的——
13
- * `hosts-grandfathered` / `legacy-governance-lifted` 两员按律折成 `null`(值已被收编接受,见
14
- * `read-warnings.ts` 头注),于是只看 `domainErrors` 的人**永远**看不见兼容臂有没有开着;而契约把
15
- * `legacy-governance-lifted` 铸出来,理由逐字写在 `legacyGovernanceFromRuntime` 的 SUNSET 注里:
16
- * 「关窗的前提是有人知道它还开着」。两条读腿各返一份原流,那句话在本仓才成立。
12
+ * `readWarnings`:契约 `onWarning` 流的**原值**(未折叠),与本地腿同键同义(读者:一致性门的读腿适配器,见本地腿同名键注)。
17
13
  * 🔐 原流的 `error` 字段**未经** `redactConfigError`(那道脱敏挂在真正进日志流的 `domainErrors` 产出边界上)
18
14
  * —— 任何把本键路由进结构化日志/审计流的消费者必须自己先脱敏。
19
15
  *
@@ -36,12 +32,12 @@ export declare function fetchEffective(center: CenterEndpoint, etag: string | un
36
32
  * Center pre-resolves the tighten-only intersection (fleet defaults ∩ tier ⊕ roles + overrides) and returns a
37
33
  * `runtimeCaps` block — the service passes it through verbatim (no further tightening, per center's ruling).
38
34
  *
39
- * 🔐 TOKEN/WORKER (center ruling, sema-registry `aeb4979`): two valid postures —
35
+ * 🔐 TOKEN/WORKER (center ruling, web-admin `aeb4979`): two valid postures —
40
36
  * • FULL `SERVICE_PULL_TOKEN` + `?principal=` → full per-user body (caps + per-user config).
41
37
  * • worker-scoped `wpt_<self>` + `?principal=&worker=<self>` → **caps-only** body (`{principal, configured,
42
38
  * runtimeCaps, budget}`; never other tenants' config) — a worker MAY resolve its OWN worker's principals.
43
39
  * A `wpt_` with NO `?worker=` (or a mismatched worker) still 403s. So we ALWAYS pass `?worker=` when the
44
- * deployment has one (`SEMA_REGISTRY_WORKER`): it authorizes the wpt_ path AND is harmless on the full token
40
+ * deployment has one (`SEMA_WEB_ADMIN_WORKER`): it authorizes the wpt_ path AND is harmless on the full token
45
41
  * (the caps value is worker-independent — `resolveEntitlement` resolves from the principal alone; worker only
46
42
  * scopes the config view we ignore). This re-adds the `worker` arg dropped in 1.14.0 (L2-3) — center's ruling
47
43
  * makes it load-bearing for AUTHORIZATION, not for the caps value.
@@ -77,9 +73,9 @@ export declare function fetchPrincipalCaps(center: CenterEndpoint, principal: st
77
73
  * 因此 304 在传输层就是 fail-loud。
78
74
  */
79
75
  export declare function fetchPrincipalOrgMemory(center: CenterEndpoint, principal: string, fetchImpl?: typeof fetch, worker?: string): Promise<unknown>;
80
- /** An HTTP error from a config-center fetch that carries the response status so callers can branch on it
76
+ /** An HTTP error from a web-admin fetch that carries the response status so callers can branch on it
81
77
  * (e.g. translate a 404 to "unknown hash → undefined") WITHOUT parsing the message string. */
82
- export declare class ConfigCenterHttpError extends Error {
78
+ export declare class WebAdminHttpError extends Error {
83
79
  readonly status: number;
84
80
  constructor(message: string, status: number);
85
81
  }
@@ -87,7 +83,7 @@ export declare class ConfigCenterHttpError extends Error {
87
83
  * Fetch one skill's body by content hash (`GET <content root>/skills/content/<hash>`, Bearer; the root is
88
84
  * `/api/v1/me` for a user-JWT credential and `/api/config` otherwise — center-request.ts) and VERIFY its
89
85
  * sha256 matches the manifest hash (integrity + rewrite check). The content is immutable per hash, so the
90
- * caller caches by hash and never re-fetches an unchanged skill. Throws a {@link ConfigCenterHttpError}
86
+ * caller caches by hash and never re-fetches an unchanged skill. Throws a {@link WebAdminHttpError}
91
87
  * (carrying `.status`) on an HTTP error — INCLUDING 404 — or a plain Error on hash mismatch. Callers that
92
88
  * want "unknown hash → undefined" parity with the local backend inspect `.status === 404` and swallow it;
93
89
  * the legacy `applyCenterSkills` path keeps treating every throw as "skip this skill, keep baseline".
@@ -1,7 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { readEffectiveWire, PrincipalCapsWire } from "@sema-agent/settings-schema";
3
3
  import { centerPromptsFromEffective } from "../prompts-domain-validate.js";
4
- import { splitFoldedReadWarnings, withDroppedIdentities } from "./read-warnings.js";
4
+ import { splitFoldedReadWarnings, withDroppedCatalogEntries } from "./read-warnings.js";
5
5
  import { CENTER_PULL_TIMEOUT_MS, centerFetch } from "./center-request.js";
6
6
  import { answerStillCurrent } from "../center-credential.js";
7
7
  export async function fetchEffective(center, etag, fetchImpl = fetch, worker) {
@@ -9,7 +9,7 @@ export async function fetchEffective(center, etag, fetchImpl = fetch, worker) {
9
9
  if (res.status === 304)
10
10
  return null;
11
11
  if (!res.ok)
12
- throw new Error(`config-center HTTP ${res.status}`);
12
+ throw new Error(`web-admin HTTP ${res.status}`);
13
13
  const warnings = [];
14
14
  const body = await res.json();
15
15
  const wire = readEffectiveWire(body, (w) => warnings.push(w));
@@ -18,8 +18,8 @@ export async function fetchEffective(center, etag, fetchImpl = fetch, worker) {
18
18
  delete wire.prompts;
19
19
  else
20
20
  wire.prompts = centerPrompts;
21
- const { domainErrors, droppedEntries, droppedIdentities } = splitFoldedReadWarnings(warnings);
22
- const effective = withDroppedIdentities(wire, droppedIdentities);
21
+ const { domainErrors, droppedEntries, droppedCatalogEntries } = splitFoldedReadWarnings(warnings);
22
+ const effective = withDroppedCatalogEntries(wire, droppedCatalogEntries);
23
23
  return {
24
24
  effective,
25
25
  etag: res.headers.get("etag") ?? undefined,
@@ -35,7 +35,7 @@ export async function fetchPrincipalCaps(center, principal, etag, fetchImpl = fe
35
35
  return null;
36
36
  const parsedBody = PrincipalCapsWire.safeParse(raw.json);
37
37
  if (!parsedBody.success) {
38
- throw new Error(`config-center principal-caps body failed schema validation: ${parsedBody.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ").slice(0, 600)}`);
38
+ throw new Error(`web-admin principal-caps body failed schema validation: ${parsedBody.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ").slice(0, 600)}`);
39
39
  }
40
40
  const body = parsedBody.data;
41
41
  assertPrincipalEcho(body.principal, principal);
@@ -79,7 +79,7 @@ export async function fetchPrincipalCaps(center, principal, etag, fetchImpl = fe
79
79
  }
80
80
  function assertPrincipalEcho(echoed, principal) {
81
81
  if (echoed !== undefined && echoed !== principal) {
82
- throw new Error(`config-center principal-caps response echoes principal ${JSON.stringify(echoed)} but ${JSON.stringify(principal)} was requested — discarding the whole response`);
82
+ throw new Error(`web-admin principal-caps response echoes principal ${JSON.stringify(echoed)} but ${JSON.stringify(principal)} was requested — discarding the whole response`);
83
83
  }
84
84
  }
85
85
  async function requestPrincipalView(center, principal, etag, fetchImpl, worker) {
@@ -91,12 +91,12 @@ async function requestPrincipalView(center, principal, etag, fetchImpl, worker)
91
91
  };
92
92
  if (res.status === 304) {
93
93
  if (!etag)
94
- throw new Error("config-center returned 304 to a non-conditional principal-caps request");
94
+ throw new Error("web-admin returned 304 to a non-conditional principal-caps request");
95
95
  stillCurrent();
96
96
  return null;
97
97
  }
98
98
  if (!res.ok)
99
- throw new Error(`config-center principal-caps HTTP ${res.status}`);
99
+ throw new Error(`web-admin principal-caps HTTP ${res.status}`);
100
100
  const responseEtag = res.headers.get("etag");
101
101
  const json = await res.json();
102
102
  stillCurrent();
@@ -106,26 +106,26 @@ const PrincipalOrgMemoryEnvelope = PrincipalCapsWire.pick({ principal: true, org
106
106
  export async function fetchPrincipalOrgMemory(center, principal, fetchImpl = fetch, worker) {
107
107
  const raw = await requestPrincipalView(center, principal, undefined, fetchImpl, worker);
108
108
  if (raw === null)
109
- throw new Error("config-center returned 304 to a non-conditional org-directory fetch");
109
+ throw new Error("web-admin returned 304 to a non-conditional org-directory fetch");
110
110
  const parsed = PrincipalOrgMemoryEnvelope.safeParse(raw.json);
111
111
  if (!parsed.success) {
112
- throw new Error(`config-center org-memory section failed schema validation: ${parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ").slice(0, 600)}`);
112
+ throw new Error(`web-admin org-memory section failed schema validation: ${parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ").slice(0, 600)}`);
113
113
  }
114
114
  assertPrincipalEcho(parsed.data.principal, principal);
115
115
  return parsed.data.orgMemory;
116
116
  }
117
- export class ConfigCenterHttpError extends Error {
117
+ export class WebAdminHttpError extends Error {
118
118
  status;
119
119
  constructor(message, status) {
120
120
  super(message);
121
121
  this.status = status;
122
- this.name = "ConfigCenterHttpError";
122
+ this.name = "WebAdminHttpError";
123
123
  }
124
124
  }
125
125
  export async function fetchSkillContent(center, contentHash, fetchImpl = fetch) {
126
126
  const { res } = await centerFetch(center, { kind: "skill-content", contentHash }, { timeoutMs: CENTER_PULL_TIMEOUT_MS, fetchImpl });
127
127
  if (!res.ok)
128
- throw new ConfigCenterHttpError(`skill content HTTP ${res.status} for ${contentHash}`, res.status);
128
+ throw new WebAdminHttpError(`skill content HTTP ${res.status} for ${contentHash}`, res.status);
129
129
  const content = await res.text();
130
130
  const want = contentHash.replace(/^sha256:/, "").toLowerCase();
131
131
  const got = createHash("sha256").update(content, "utf8").digest("hex");
@@ -136,13 +136,13 @@ export async function fetchSkillContent(center, contentHash, fetchImpl = fetch)
136
136
  export async function fetchPromptArtifact(center, artifactDigest, fetchImpl = fetch) {
137
137
  const { res } = await centerFetch(center, { kind: "prompt-artifact", digest: artifactDigest }, { timeoutMs: CENTER_PULL_TIMEOUT_MS, fetchImpl });
138
138
  if (!res.ok)
139
- throw new ConfigCenterHttpError(`prompt artifact HTTP ${res.status} for ${artifactDigest}`, res.status);
139
+ throw new WebAdminHttpError(`prompt artifact HTTP ${res.status} for ${artifactDigest}`, res.status);
140
140
  return await res.json();
141
141
  }
142
142
  export async function fetchPromptBlob(center, contentDigest, fetchImpl = fetch) {
143
143
  const { res } = await centerFetch(center, { kind: "prompt-blob", digest: contentDigest }, { timeoutMs: CENTER_PULL_TIMEOUT_MS, fetchImpl });
144
144
  if (!res.ok)
145
- throw new ConfigCenterHttpError(`prompt blob HTTP ${res.status} for ${contentDigest}`, res.status);
145
+ throw new WebAdminHttpError(`prompt blob HTTP ${res.status} for ${contentDigest}`, res.status);
146
146
  const bytes = new Uint8Array(await res.arrayBuffer());
147
147
  const want = contentDigest.replace(/^sha256:/, "").toLowerCase();
148
148
  const got = createHash("sha256").update(bytes).digest("hex");
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * S-866 ②(设计稿 v1.1 §2②)—— 「这台引擎**此刻**是不是真的接着中心」的两件读数:最近一次实拉的结局(`lastPull`)与生效修订号
3
- * (`effectiveRevision`)。属主 = config-center 运行时(`boot/config-center.ts` 的 `centerPullState()`);读者 = caps `centerWiring`。
3
+ * (`effectiveRevision`)。属主 = web-admin 运行时(`boot/web-admin.ts` 的 `centerPullState()`);读者 = caps `centerWiring`。
4
4
  *
5
5
  * 纯叶(零值 import):词表与读面形住这里,运行时与读面两侧都从这里取型,不各写一份。
6
6
  */
@@ -59,7 +59,7 @@ export function applyCenterReadFace(config, eff, logger, apply = { phase: "boot"
59
59
  return report();
60
60
  }
61
61
  if (typeof domain !== "object" || Array.isArray(domain)) {
62
- logger?.warn("sema_registry_read_face_invalid", {
62
+ logger?.warn("web_admin_read_face_invalid", {
63
63
  detail: `published readFace domain must be an object with optional {face,denyPatterns,denyBuiltinTiers,denyBuiltinExclude} — got ${Array.isArray(domain) ? "array" : typeof domain}`,
64
64
  kept: "the deployment's env READ-face posture is unchanged (refusing a malformed domain WHOLE — a half-applied read-containment posture is worse than none)",
65
65
  });
@@ -90,7 +90,7 @@ export function applyCenterReadFace(config, eff, logger, apply = { phase: "boot"
90
90
  resolveReadDenyBuiltins(builtinsArg(finalTiers, finalExclude));
91
91
  }
92
92
  catch (e) {
93
- logger?.warn("sema_registry_read_face_invalid", {
93
+ logger?.warn("web_admin_read_face_invalid", {
94
94
  detail: e instanceof Error ? e.message : String(e),
95
95
  kept: "the deployment's env READ-face posture is unchanged (refusing the readFace domain WHOLE — applying half of a read-containment posture would read as 'policy landed' while part of it silently did not)",
96
96
  });
@@ -112,13 +112,13 @@ export function applyCenterReadFace(config, eff, logger, apply = { phase: "boot"
112
112
  config.readDenyBuiltinExclude = staged.readDenyBuiltinExclude;
113
113
  }
114
114
  if (envHeld.length > 0) {
115
- logger?.warn("sema_registry_read_face_env_wins", {
115
+ logger?.warn("web_admin_read_face_env_wins", {
116
116
  keys: envHeld,
117
117
  note: "this machine's explicit env READ-face keys WIN over the published readFace domain (deployment sovereignty) — the published values for these keys were NOT applied; unset the env key if the org publication should own it",
118
118
  });
119
119
  }
120
120
  if (Object.keys(staged).length > 0) {
121
- logger?.info("sema_registry_read_face", {
121
+ logger?.info("web_admin_read_face", {
122
122
  applied: Object.keys(staged).filter((k) => apply.phase === "boot" || KEY_MAP.some((r) => r.cfgKey === k && CENTER_READ_FACE_LIVE_KEYS.has(r.centerKey))),
123
123
  ...(staged.readFace !== undefined ? { face: staged.readFace } : {}),
124
124
  note: apply.phase === "boot"
@@ -0,0 +1,137 @@
1
+ /**
2
+ * `EffectiveReadWarning` → 候选门口径的**单点**折叠(本地腿 `config-provider.ts` 与远程腿 `http-client.ts` 共用;
3
+ * 两腿各抄一份映射正是漂移的成因——远程腿曾漏掉一次改动,版本超前的 center 多一个字段就整份远程 refresh 整拒)。
4
+ *
5
+ * **律只有一条:未知键 = 候选门错误,零特例。** 「别的写者按契约放的扩展键」(壳写在 models 条目上的 `sema*`)
6
+ * 不是本函数要分辨的事——那由 settings-schema 的 `EXTENSION_NAMESPACES` 在**声明处**说清(登记的键既不点名也不计数,
7
+ * 1.5.0 起);到了这里的每一个键都是「写了没生效」的拼错或越界,与 domain-defaulted 同级。此前本仓在下游按 kind/
8
+ * 按域/按键路径闭集/按 64 满额四层猜意图,每层都被下一轮复审打穿——意图只能在声明处说,消费方不猜。
9
+ *
10
+ * 截断:schema 的键列表有界(64),超界带 `truncatedFrom`(真实总数)——文案如实带上,消费方永远不把有界列表当穷举。
11
+ * 词表是闭集:`switch` 穷举 `kind`,schema 加新 kind 这里编译红,不会静默漏臂。
12
+ *
13
+ * **归族判据**(下游两个消费者:候选门 = 非空 ⇒ 这棵树整拒、保 LKG;逐条丢弃面 = 响亮点名、其余照用):每一种告警都是
14
+ * 「写了没生效」,按**失效的颗粒**分:丢的是**一条条目**(`entry-dropped`)⇒ `scope:"entry"` —— 这条条目单独不在,同域其余条目照用,
15
+ * 候选**不**因它整拒;丢的是一个域 / 一组键 / 一个文件 ⇒ `scope:"domain"` —— 候选门错误。(settings-schema 11 起读路径上零抬升臂:
16
+ * 此前「值已被收编接受」的两种告警 `hosts-grandfathered` / `legacy-governance-lifted` 随抬升臂一起退役,旧形由一次性迁移改写,
17
+ * 读侧遇旧形一律拒 —— 没有「不入诊断面」的那一族了。)
18
+ *
19
+ * 🔴 S-704 ②(2026-09-24,凭据轴):此前 `entry-dropped` 归「候选门错误」(settings-schema 2.0.0 提货时的归族),于是
20
+ * schema 的**逐条容错**在本仓的 refresh / 迟到 boot 两条腿上被**还原成整份拒** —— 目录里一条 `contextWindow:"abc"`
21
+ * 就让整份目录停在上一代;而上一代若还是 env(boot 拉取失败 / 超窗且无 LKG),env 模型就一直服务、env 钥匙一直被送到
22
+ * 网关缺省端点(红先实测:`config_candidate_rejected` + env 模型继续服务)。粒度对了规则反而更少:颗粒是条目的失效
23
+ * 留在条目上,只有颗粒更粗的失效才动候选。
24
+ */
25
+ import { z } from "zod";
26
+ import { type DroppedEntryIdentity, type DroppedEntryReasonCode, type EffectiveReadWarning } from "@sema-agent/settings-schema";
27
+ /** 折叠产物:`scope` 决定消费方做什么 —— `"domain"` 进候选门(`domainErrors`),`"entry"` 进逐条丢弃面(`droppedEntries`)。 */
28
+ export type FoldedReadWarning = {
29
+ readonly scope: "domain";
30
+ readonly domain: string;
31
+ readonly error: string;
32
+ } | {
33
+ readonly scope: "entry";
34
+ readonly domain: string;
35
+ readonly entry: string;
36
+ readonly error: string;
37
+ readonly reasonCode: DroppedEntryReasonCode;
38
+ };
39
+ /** 逐条丢弃面的一行(两条读腿的 `droppedEntries` 同形,`config_entry_dropped` 日志行读它):`entry` = 被丢那条的出门形坐标(`models.1`),
40
+ * `error` = 哪些字段、为什么(人读),`reasonCode` = 为什么丢的**闭集词**(S-1295:settings-schema 铸、原样过境 —— 目录行的
41
+ * `GET /v1/models.droppedEntries[].reasonCode` 就是这同一个词,取自同一次折叠的同一行)。 */
42
+ export type DroppedConfigEntry = {
43
+ readonly domain: string;
44
+ readonly entry: string;
45
+ readonly error: string;
46
+ readonly reasonCode: DroppedEntryReasonCode;
47
+ };
48
+ /**
49
+ * zod 形的错误 → 一行可读的字段诊断(`contextWindow: Invalid input: expected number, received string; apiKeyEnv: <契约句>`)。
50
+ * 每条 issue 的句子只有一只读法 {@link issueSentenceOf}、坐标只有一只写法 {@link issueCoordinateOf}(整域面 {@link describeDomainIssues} 读同两只);
51
+ * 坐标缺席(issue 指整条)写 `(entry)`。
52
+ * 读不出 issues 形 ⇒ `undefined`(调用方退回既有文案)。模型面 stage 的逐条判据、目录载体的 `issues` 与本折叠点共用这一只(一个刻度)。
53
+ */
54
+ export declare function describeSchemaIssues(error: unknown): string | undefined;
55
+ /**
56
+ * zod 形错误 → 坏字段的**键路径**(去重保序;`(entry)` = 整条)。与 {@link describeSchemaIssues} 同一只坐标写法({@link issueCoordinateOf}),
57
+ * 不含值。模型面 stage 的逐条判据(`judgeCatalogEntry`)与本折叠点的被丢条目身份共用这一只 —— 一个刻度。
58
+ */
59
+ export declare function describeSchemaIssueFields(error: unknown): string[];
60
+ /** 契约句子里**值**的位置在本仓诊断面上的写法(一个洞,不回显值;句子的固定词 —— 迁移指路、词表出路、字段名 —— 原样)。 */
61
+ export declare const SCHEMA_OPERAND_HOLE = "\u00ABvalue\u00BB";
62
+ /**
63
+ * 整域失效(`domain-defaulted`)的诊断文案:逐条 issue `坐标: 句子`,句子读 {@link issueSentenceOf}(与逐条丢弃面同一只):带结构化操作数的契约句重铸、
64
+ * 操作数换成 {@link SCHEMA_OPERAND_HOLE};不带的(zod 内建句、退役键墓碑句、迁移指路)原样。读不出 issues 形 ⇒ 退回 {@link errorText}。
65
+ * 为什么不直接用 `error.message`:zod 4 的 message 是整份 issues 的 JSON —— 本地腿出口的引号段指纹(`redactConfigError`)会把它从第一个
66
+ * 引号到最后一个引号整段吞掉,契约拒句里点名的迁移 id(「旧形读写两面响亮拒、拒句点名迁移 id」)就到不了运维眼前。
67
+ */
68
+ export declare function describeDomainIssues(error: unknown): string;
69
+ /** 一条读告警 → 它的诊断面(每一种都进:见文件头「归族判据」)。 */
70
+ export declare function foldEffectiveReadWarning(w: EffectiveReadWarning): FoldedReadWarning;
71
+ /**
72
+ * 🔴 S-712 / S-1295 —— **被丢目录条目的载体行**(载体 = `EffectiveConfig.models.droppedCatalogEntries`,读腿铸,随 effective 走 —— 盘上 LKG
73
+ * 从同一个对象落盘,重启从 LKG 起服时它还在)。形的**唯一定义**(型由它推出;判据按它判盘上来的行)。
74
+ *
75
+ * **规则一条:读腿把 schema 逐条丢掉的每一条目录条目(`models` 域的 `["models", <下标>]`)记一行,写入时不挑;每个读者读自己要的那一部分。**
76
+ * · 墓碑判据(`model-entry-refusal.ts` `judgeCatalogEntries`)—— 有名(`identity.name`)且未停用(`identity.enabled !== false`)的行;
77
+ * · `GET /v1/models` 的 `droppedEntries`({@link buildDroppedEntriesWire})—— 每一行的下标、闭集词与可披露身份;
78
+ * · `config_entry_dropped` 日志行读的是这一行由之而来的那条折叠行({@link DroppedConfigEntry},同一次折叠、同一个词)。
79
+ * (修前 S-712 的载体 `droppedIdentities` 在写入时只收「有名且启用」的行 —— 那是墓碑读者的筛子,装在了写入处;同一件事于是没有
80
+ * 第二个读者可用。筛子回到读者那里,载体就只剩「记下发生了什么」这一条律。)
81
+ *
82
+ * 🔐 不含值:`identity` 取告警自带的身份(settings-schema 只铸可披露的标识符 —— 秘密形 / 非标识符的串 ⇒ 该键缺席,三键都没有 ⇒ 整个缺席);
83
+ * `index` 是条目在**这次读到的那份目录文档** `models` 数组里的原下标(数,不是串);`fields` 是坏字段的键路径、`issues` 是
84
+ * {@link describeSchemaIssues} 的一行(键名 + 类型词)—— 后两者只供本机拒因句,不上 wire。
85
+ */
86
+ export declare const DroppedCatalogEntryRow: z.ZodObject<{
87
+ index: z.ZodNumber;
88
+ reasonCode: z.ZodEnum<{
89
+ "entry-schema-invalid": "entry-schema-invalid";
90
+ "entry-key-invalid": "entry-key-invalid";
91
+ "entry-unreadable": "entry-unreadable";
92
+ }>;
93
+ identity: z.ZodOptional<z.ZodObject<{
94
+ name: z.ZodOptional<z.ZodString>;
95
+ id: z.ZodOptional<z.ZodString>;
96
+ enabled: z.ZodOptional<z.ZodBoolean>;
97
+ }, z.core.$strict>>;
98
+ fields: z.ZodArray<z.ZodString>;
99
+ issues: z.ZodString;
100
+ }, z.core.$strict>;
101
+ export type DroppedCatalogEntry = z.infer<typeof DroppedCatalogEntryRow>;
102
+ /**
103
+ * 两条读腿(远端 `http-client.ts` / 本地 `config-provider.ts`)共用的**分面单点**:折叠产物按 `scope` 分进候选门
104
+ * (`domainErrors`)与逐条丢弃面(`droppedEntries`);逐条丢弃里的**目录条目**同一拍铸进目录载体(`droppedCatalogEntries`,
105
+ * 一次遍历、一行折叠、一个词 —— 日志行与载体行不各算一次)。`switch` 穷举 —— 加一种 scope 不补臂 = 编译红,两腿不会各分各的。
106
+ * 文案**未脱敏**:进日志流之前各腿在自己的产出边界上脱敏 —— `domainErrors` 过 `redactConfigError`(引号段读法);`droppedEntries` 的文案是结构化句子
107
+ * (键名坐标 + 类型词 + 契约整句,值位是洞)、不含配置里的值,只过 `redactSecrets`(契约句的固定词里有引号 / 撇号,引号段读法会把迁移指路整段吞掉)。
108
+ * 坏行本身照样走 `droppedEntries`(坐标 + 字段 + 词,不带值)。
109
+ */
110
+ export declare function splitFoldedReadWarnings(warnings: readonly EffectiveReadWarning[]): {
111
+ domainErrors: Array<{
112
+ domain: string;
113
+ error: string;
114
+ }>;
115
+ droppedEntries: DroppedConfigEntry[];
116
+ droppedCatalogEntries: DroppedCatalogEntry[];
117
+ };
118
+ /** 把本次读交出的目录载体挂上 effective 的模型域(两腿同一只;空 ⇒ 不挂键)。 */
119
+ export declare function withDroppedCatalogEntries<E extends {
120
+ models?: object;
121
+ }>(effective: E, rows: readonly DroppedCatalogEntry[]): E;
122
+ /** `GET /v1/models` 顶层 `droppedEntries` 的一行(wire 形;契约 §A.1d「`GET /v1/models` 的 `droppedEntries`」)。 */
123
+ export interface DroppedEntryWireRow {
124
+ readonly index: number;
125
+ readonly reasonCode: DroppedEntryReasonCode;
126
+ readonly identity?: DroppedEntryIdentity;
127
+ }
128
+ /**
129
+ * S-1295 —— 本代目录的被丢条目(`config.droppedCatalogEntries`)→ `GET /v1/models` 的 `droppedEntries`。纯投影,**唯一**出口。
130
+ * · 词:settings-schema 的闭集原样过境({@link reasonCodeForWire} 穷举:包加词 / 删词 ⇒ 本仓编译红,逼一次「这个词能不能上 wire」的显式决定);
131
+ * · 身份:`name` / `id` 在出口再问一次包的 `isDisclosableIdentity`(唯一判据,import 不复制)—— 载体可能来自被手改的盘上 LKG,读腿铸的身份
132
+ * 本来就过了同一只判据;不可披露 ⇒ 该键不出门(不打码:打过码的串不再是身份);`enabled` 是布尔照带;三键都不剩 ⇒ `identity` 缺席;
133
+ * · 不投 `fields` / `issues`(人读的诊断句,不是契约),不投坐标串(下标是数)。
134
+ * 恒返回数组(零条 = `[]`):键恒在场,缺席只意味着更早的 server。
135
+ */
136
+ export declare function buildDroppedEntriesWire(rows: readonly DroppedCatalogEntry[]): DroppedEntryWireRow[];
137
+ //# sourceMappingURL=read-warnings.d.ts.map
@@ -0,0 +1,168 @@
1
+ import { z } from "zod";
2
+ import { DROPPED_ENTRY_REASON_CODES, formatConfigPath, isDisclosableIdentity, renderQuotedSentence, } from "@sema-agent/settings-schema";
3
+ export function describeSchemaIssues(error) {
4
+ const issues = schemaIssuesOf(error);
5
+ if (issues === undefined)
6
+ return undefined;
7
+ return issues
8
+ .map((raw) => `${issueCoordinateOf(raw) ?? "(entry)"}: ${issueSentenceOf(raw)}`)
9
+ .join("; ");
10
+ }
11
+ function issueCoordinateOf(raw) {
12
+ const p = typeof raw === "object" && raw !== null ? raw.path : undefined;
13
+ return Array.isArray(p) && p.length > 0 ? formatConfigPath(p) : undefined;
14
+ }
15
+ function issueSentenceOf(raw) {
16
+ const message = typeof raw === "object" && raw !== null ? raw.message : undefined;
17
+ return contractSentenceOf(raw) ?? (typeof message === "string" ? message : "(unreadable issue)");
18
+ }
19
+ function contractSentenceOf(raw) {
20
+ const params = (typeof raw === "object" && raw !== null ? raw.params : undefined);
21
+ return params !== undefined && Array.isArray(params.template) && Array.isArray(params.operands)
22
+ ? renderQuotedSentence(params, () => SCHEMA_OPERAND_HOLE)
23
+ : undefined;
24
+ }
25
+ function schemaIssuesOf(error) {
26
+ const issues = typeof error === "object" && error !== null ? error.issues : undefined;
27
+ return Array.isArray(issues) && issues.length > 0 ? issues : undefined;
28
+ }
29
+ export function describeSchemaIssueFields(error) {
30
+ const issues = schemaIssuesOf(error) ?? [];
31
+ return [...new Set(issues.map((raw) => issueCoordinateOf(raw) ?? "(entry)"))];
32
+ }
33
+ const MAX_ERROR_CHARS = 600;
34
+ const TRUNCATED_MARK = "…(truncated)";
35
+ const cap = (s) => (s.length <= MAX_ERROR_CHARS ? s : `${s.slice(0, MAX_ERROR_CHARS - TRUNCATED_MARK.length)}${TRUNCATED_MARK}`);
36
+ const errorText = (e) => (e instanceof Error ? e.message : String(e));
37
+ export const SCHEMA_OPERAND_HOLE = "«value»";
38
+ export function describeDomainIssues(error) {
39
+ const issues = schemaIssuesOf(error);
40
+ if (issues === undefined)
41
+ return errorText(error);
42
+ return issues
43
+ .map((raw) => {
44
+ const at = issueCoordinateOf(raw);
45
+ const sentence = issueSentenceOf(raw);
46
+ return at !== undefined ? `${at}: ${sentence}` : sentence;
47
+ })
48
+ .join("; ");
49
+ }
50
+ const keyList = (prefix, keys, truncatedFrom) => {
51
+ const total = truncatedFrom ?? keys.length;
52
+ const budget = MAX_ERROR_CHARS - prefix.length;
53
+ const shown = [];
54
+ let used = 0;
55
+ const suffixFor = (n) => (n < total ? ` (+${total - n} more, list truncated)` : "");
56
+ for (const k of keys) {
57
+ const rendered = formatConfigPath(k);
58
+ const piece = (shown.length > 0 ? ", " : "") + rendered;
59
+ if (used + piece.length + suffixFor(shown.length + 1).length > budget)
60
+ break;
61
+ shown.push(rendered);
62
+ used += piece.length;
63
+ }
64
+ return `${prefix}${shown.join(", ")}${suffixFor(shown.length)}`;
65
+ };
66
+ export function foldEffectiveReadWarning(w) {
67
+ switch (w.kind) {
68
+ case "domain-defaulted":
69
+ return { scope: "domain", domain: w.domain, error: cap(describeDomainIssues(w.error)) };
70
+ case "entry-dropped":
71
+ return { scope: "entry", domain: w.domain, entry: formatConfigPath(w.path), error: cap(`entry dropped by domain schema: ${describeSchemaIssues(w.error) ?? errorText(w.error)}`), reasonCode: droppedReasonCodeOf(w) };
72
+ case "unknown-keys-dropped":
73
+ return { scope: "domain", domain: w.domain, error: keyList("unknown keys dropped by domain schema: ", w.keys, w.truncatedFrom) };
74
+ case "unknown-keys-carried":
75
+ return { scope: "domain", domain: w.domain, error: keyList("unknown keys carried to consumer (spelling?): ", w.keys, w.truncatedFrom) };
76
+ case "unread-config-file":
77
+ return { scope: "domain", domain: w.domain ?? "config.d", error: cap(`unread config file ${w.file} (${w.why})`) };
78
+ default: {
79
+ const never = w;
80
+ throw new Error(`unhandled EffectiveReadWarning kind: ${JSON.stringify(never)}`);
81
+ }
82
+ }
83
+ }
84
+ function droppedReasonCodeOf(w) {
85
+ if (w.reasonCode === undefined) {
86
+ throw new Error(`entry-dropped warning at ${formatConfigPath(w.path)} carries no reasonCode — settings-schema mints one on every dropped entry, so this warning did not come from the pinned package`);
87
+ }
88
+ return w.reasonCode;
89
+ }
90
+ export const DroppedCatalogEntryRow = z
91
+ .object({
92
+ index: z.number().int().nonnegative(),
93
+ reasonCode: z.enum(DROPPED_ENTRY_REASON_CODES),
94
+ identity: z.object({ name: z.string().optional(), id: z.string().optional(), enabled: z.boolean().optional() }).strict().optional(),
95
+ fields: z.array(z.string()),
96
+ issues: z.string(),
97
+ })
98
+ .strict();
99
+ function catalogIndexOf(w) {
100
+ return w.kind === "entry-dropped" && w.domain === "models" && w.path.length === 2 && w.path[0] === "models" && typeof w.path[1] === "number" ? w.path[1] : undefined;
101
+ }
102
+ function identityOf(i) {
103
+ if (i === undefined)
104
+ return undefined;
105
+ const out = { ...(i.name !== undefined ? { name: i.name } : {}), ...(i.id !== undefined ? { id: i.id } : {}), ...(i.enabled !== undefined ? { enabled: i.enabled } : {}) };
106
+ return Object.keys(out).length > 0 ? out : undefined;
107
+ }
108
+ export function splitFoldedReadWarnings(warnings) {
109
+ const domainErrors = [];
110
+ const droppedEntries = [];
111
+ const droppedCatalogEntries = [];
112
+ for (const w of warnings) {
113
+ const f = foldEffectiveReadWarning(w);
114
+ switch (f.scope) {
115
+ case "domain":
116
+ domainErrors.push({ domain: f.domain, error: f.error });
117
+ break;
118
+ case "entry": {
119
+ droppedEntries.push({ domain: f.domain, entry: f.entry, error: f.error, reasonCode: f.reasonCode });
120
+ const index = catalogIndexOf(w);
121
+ if (index !== undefined && w.kind === "entry-dropped") {
122
+ const identity = identityOf(w.identity);
123
+ droppedCatalogEntries.push({ index, reasonCode: f.reasonCode, ...(identity !== undefined ? { identity } : {}), fields: describeSchemaIssueFields(w.error), issues: describeSchemaIssues(w.error) ?? "(schema issues unreadable)" });
124
+ }
125
+ break;
126
+ }
127
+ default: {
128
+ const never = f;
129
+ throw new Error(`unhandled folded read-warning scope: ${JSON.stringify(never)}`);
130
+ }
131
+ }
132
+ }
133
+ return { domainErrors, droppedEntries, droppedCatalogEntries };
134
+ }
135
+ export function withDroppedCatalogEntries(effective, rows) {
136
+ if (rows.length === 0 || effective.models === undefined)
137
+ return effective;
138
+ return { ...effective, models: { ...effective.models, droppedCatalogEntries: [...rows] } };
139
+ }
140
+ export function buildDroppedEntriesWire(rows) {
141
+ return rows.map((r) => {
142
+ const identity = disclosableIdentityOf(r.identity);
143
+ return { index: r.index, reasonCode: reasonCodeForWire(r.reasonCode), ...(identity !== undefined ? { identity } : {}) };
144
+ });
145
+ }
146
+ function reasonCodeForWire(code) {
147
+ switch (code) {
148
+ case "entry-schema-invalid":
149
+ case "entry-key-invalid":
150
+ case "entry-unreadable":
151
+ return code;
152
+ default: {
153
+ const never = code;
154
+ throw new Error(`unhandled DroppedEntryReasonCode: ${JSON.stringify(never)}`);
155
+ }
156
+ }
157
+ }
158
+ function disclosableIdentityOf(i) {
159
+ if (i === undefined)
160
+ return undefined;
161
+ const out = {
162
+ ...(i.name !== undefined && isDisclosableIdentity(i.name) ? { name: i.name } : {}),
163
+ ...(i.id !== undefined && isDisclosableIdentity(i.id) ? { id: i.id } : {}),
164
+ ...(i.enabled !== undefined ? { enabled: i.enabled } : {}),
165
+ };
166
+ return Object.keys(out).length > 0 ? out : undefined;
167
+ }
168
+ //# sourceMappingURL=read-warnings.js.map
@@ -39,8 +39,8 @@ export interface RestartSliceCtx {
39
39
  }
40
40
  /** S-741(车OG):本引擎发布的重启信号。形的唯一定义是 settings-schema 6.1.0 `RestartSignal`(`{ reasons, version, since }`,在场即信号,
41
41
  * 不夹 `restartRequired` 布尔;本地手写的那份接口已删),这里只把 `reasons` 收窄到本文件的闭集 {@link RestartSlice} —— 写口
42
- * (`boot/config-center.ts` `publishRestart`)按它收,拼错 / 已退役的词编译红(opus 对抗腿 #2:直接用上游型时 `reasons` 是
43
- * `string[]`,闭集的编译期判据丢了)。`/health.restart` 与 fleet 心跳 `restart` 两个出口交 config-center 同一只 `restartState()`
42
+ * (`boot/web-admin.ts` `publishRestart`)按它收,拼错 / 已退役的词编译红(opus 对抗腿 #2:直接用上游型时 `reasons` 是
43
+ * `string[]`,闭集的编译期判据丢了)。`/health.restart` 与 fleet 心跳 `restart` 两个出口交 web-admin 同一只 `restartState()`
44
44
  * 的同一个对象,按契约形出门。 */
45
45
  export type EngineRestartSignal = RestartSignal & {
46
46
  reasons: RestartSlice[];
@@ -89,6 +89,8 @@ export declare function restartReasons(boot: EffectiveConfig | undefined, curren
89
89
  * undefined` (env-boot plane, no EffectiveConfig to compare) is conservatively "changed": the first center plane
90
90
  * always swaps. Not gated on tier activity: a Runner's expanded catalog goes stale on ANY plane change,
91
91
  * including a tiers-off flip, and the default entry rides the fingerprint because the Runner's copy carries its
92
- * own `default` (codex R8; SAME resolver as applyEffective — resolveDefaultModelName, single source). */
92
+ * own `default` (codex R8; SAME resolver as applyEffective — settings-schema `resolveCatalogDefaultModel`, single source: a
93
+ * `named` default fingerprints by its name, a `{select}` default by its criteria — the engine resolves the same criteria over
94
+ * the same fingerprinted catalog and tier table, so equal criteria on an unchanged plane give the same entry). */
93
95
  export declare function modelPlaneChanged(prev: EffectiveConfig | undefined, next: EffectiveConfig): boolean;
94
96
  //# sourceMappingURL=restart-signal.d.ts.map
@@ -1,7 +1,6 @@
1
- import { resolveActiveTiers } from "@sema-agent/settings-schema";
1
+ import { resolveActiveTiers, resolveCatalogDefaultModel } from "@sema-agent/settings-schema";
2
2
  import { stableStringify } from "@sema-agent/settings-schema/hash";
3
3
  import { DEFAULT_PLUGIN_ALLOW_HOSTS, materializablePlugins } from "../capabilities/center-plugins.js";
4
- import { resolveDefaultModelName } from "./apply-effective.js";
5
4
  import { CENTER_READ_FACE_LIVE_KEYS } from "./read-face.js";
6
5
  const RESTART_SLICES = ["skills", "mcp", "a2a", "scenarios", "degrade-route", "read-face", "memory-consolidation"];
7
6
  function enabledOnly(rows) {
@@ -83,8 +82,8 @@ export function modelPlaneChanged(prev, next) {
83
82
  const enabled = enabledOnly(e.models?.models);
84
83
  const active = e.models ? (resolveActiveTiers(e.models) ?? null) : null;
85
84
  const names = new Set((enabled ?? []).map((m) => m.name));
86
- const def = resolveDefaultModelName(e, (n) => names.has(n), enabled?.[0]?.name ?? "");
87
- return stableStringify({ models: planeEntriesFingerprint(e.models?.models), tiers: active, default: def.name });
85
+ const def = e.models ? resolveCatalogDefaultModel(e.models, (n) => names.has(n), enabled?.[0]?.name ?? "") : undefined;
86
+ return stableStringify({ models: planeEntriesFingerprint(e.models?.models), tiers: active, default: def === undefined ? null : def.kind === "named" ? def.name : { select: def.select } });
88
87
  };
89
88
  return fp(prev) !== fp(next);
90
89
  }
@@ -5,7 +5,7 @@ import type { LoadedSkill } from "../capabilities/skills.js";
5
5
  import type { CenterEndpoint } from "./center-request.js";
6
6
  import type { CenterA2aPeer, CenterMcpServer, CenterSkillManifest } from "./types.js";
7
7
  /**
8
- * Merge center skills OVER the image baseline ([ref]-sibling B1; `sema-registry docs/MCP-SKILLS.md`). Load order =
8
+ * Merge center skills OVER the image baseline ([ref]-sibling B1; `web-admin docs/MCP-SKILLS.md`). Load order =
9
9
  * `loadSkills(SKILLS_DIR)` baseline → center skills lazily fetched by hash and overlaid BY NAME (center
10
10
  * wins on a clash → can override a built-in; guarded center-side by publisher RBAC + the publish gate).
11
11
  * `enabled:false` is skipped. Content is verified + cached by hash (same hash fetched once). A skill whose