@sema-agent/settings-schema 10.1.0 → 11.0.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 (235) hide show
  1. package/CHANGELOG.md +419 -0
  2. package/README.md +141 -65
  3. package/bin/settings-schema.mjs +13 -6
  4. package/conformance/VERSION +1 -1
  5. package/conformance/baseline.json +3 -1
  6. package/conformance/cases/c01-entry-salvage-then-typo/expected.json +3 -1
  7. package/conformance/cases/c02-hosts-clamp-stacked/expected.json +12 -5
  8. package/conformance/cases/c02-hosts-clamp-stacked/meta.json +1 -1
  9. package/conformance/cases/c03-literal-dotted-top-key/expected.json +22 -2
  10. package/conformance/cases/c04-all-bad-collection-not-salvaged/expected.json +3 -1
  11. package/conformance/cases/c06-legacy-governance-lift/expected.json +11 -101
  12. package/conformance/cases/c06-legacy-governance-lift/meta.json +1 -1
  13. package/conformance/cases/c07-hooks-is-not-a-config-domain/expected.json +3 -1
  14. package/conformance/cases/c08-limits-unknown-carried-64/expected.json +203 -2
  15. package/conformance/cases/c09-limits-unknown-carried-65/expected.json +204 -2
  16. package/conformance/cases/c10-record-key-secret-redacted-twice/expected.json +3 -1
  17. package/conformance/cases/c11-unicode-unknown-keys/expected.json +20 -2
  18. package/conformance/cases/c12-prototype-name-top-keys/expected.json +3 -1
  19. package/conformance/cases/c13-models-field-null/expected.json +3 -1
  20. package/conformance/cases/c14-models-field-empty-array/expected.json +6 -1
  21. package/conformance/cases/c15-models-field-number/expected.json +3 -1
  22. package/conformance/cases/c16-deep-nesting-205/expected.json +14 -2
  23. package/conformance/cases/c17-empty-domain-file/expected.json +3 -1
  24. package/conformance/cases/c18-wire-envelope-not-an-object/expected.json +3 -1
  25. package/conformance/cases/c19-wire-envelope-no-version/expected.json +3 -1
  26. package/conformance/cases/c20-governance-absent-lifts/expected.json +11 -86
  27. package/conformance/cases/c20-governance-absent-lifts/meta.json +1 -1
  28. package/conformance/cases/c21-governance-empty-object-wins/expected.json +6 -5
  29. package/conformance/cases/c21-governance-empty-object-wins/input.json +1 -4
  30. package/conformance/cases/c21-governance-empty-object-wins/meta.json +1 -1
  31. package/conformance/cases/c23-mixed-validity-models/expected.json +3 -1
  32. package/conformance/cases/c24-valid-entries-with-unknown-keys/expected.json +22 -2
  33. package/conformance/cases/c25-published-roundtrip-zero-warnings/expected.json +6 -1
  34. package/conformance/cases/c26-hosts-array-1024/expected.json +3 -1
  35. package/conformance/cases/c27-hosts-array-1025/expected.json +6 -7175
  36. package/conformance/cases/c27-hosts-array-1025/meta.json +1 -1
  37. package/conformance/cases/c28-large-document-over-1mb/expected.json +14 -2
  38. package/conformance/cases/c29-salvage-then-domain-refine-fails/expected.json +3 -1
  39. package/conformance/cases/c30-version-triple-a-first/expected.json +6 -1
  40. package/conformance/cases/c31-version-triple-b-changed/expected.json +6 -1
  41. package/conformance/cases/c32-version-triple-a-restored/expected.json +6 -1
  42. package/conformance/cases/c33-limits-nested-carried-key/expected.json +18 -2
  43. package/conformance/cases/c34-skills-content-vs-manifest/expected.json +19 -3
  44. package/conformance/cases/c35-portable-domain-file-is-null/expected.json +3 -1
  45. package/conformance/cases/c36-skills-entry-without-content/expected.json +6 -2
  46. package/conformance/cases/c37-skills-field-null/expected.json +6 -2
  47. package/conformance/cases/c38-remote-exec-is-a-non-domain-file/expected.json +3 -1
  48. package/conformance/cases/c39-hidden-file-in-config-d/expected.json +3 -1
  49. package/conformance/cases/c40-s712-identity-only-what-reads-out/expected.json +11 -4
  50. package/conformance/cases/c41-s792-encoded-pem-identity/expected.json +9 -3
  51. package/conformance/cases/c42-s792-unknown-key-secret-redacted/expected.json +39 -2
  52. package/conformance/cases/c43-s792-form-and-deep-encoded-pem/expected.json +4 -1
  53. package/conformance/cases/c44-s792-utf8-escape-glued-token/expected.json +3 -1
  54. package/conformance/cases/c45-s792-identity-bounds-and-decode-depth/expected.json +19 -10
  55. package/conformance/cases/c45-s792-identity-bounds-and-decode-depth/meta.json +1 -1
  56. package/conformance/cases/{c46-s811-host-name-url-userinfo-characterization → c46-s811-host-name-url-userinfo-withheld}/expected.json +12 -5
  57. package/conformance/cases/c46-s811-host-name-url-userinfo-withheld/meta.json +9 -0
  58. package/conformance/cases/{c47-s811-roles-key-url-userinfo-characterization → c47-s811-roles-key-url-userinfo-withheld}/expected.json +23 -3
  59. package/conformance/cases/{c47-s811-roles-key-url-userinfo-characterization → c47-s811-roles-key-url-userinfo-withheld}/input.json +6 -0
  60. package/conformance/cases/c47-s811-roles-key-url-userinfo-withheld/meta.json +10 -0
  61. package/conformance/cases/c48-s935-model-headers-transported/expected.json +6 -1
  62. package/conformance/cases/c49-s935-model-headers-secret-entry-dropped/expected.json +3 -1
  63. package/conformance/cases/c50-s784-lane-host-legal/expected.json +3 -1
  64. package/conformance/cases/c51-s784-lane-e2b-legal/expected.json +3 -1
  65. package/conformance/cases/c52-s784-lane-k8s-legal/expected.json +3 -1
  66. package/conformance/cases/c53-s784-lane-ssh-legal/expected.json +3 -1
  67. package/conformance/cases/c54-s784-lane-adb-legal/expected.json +3 -1
  68. package/conformance/cases/c55-s784-lane-local-docker-legal/expected.json +3 -1
  69. package/conformance/cases/c56-s784-lane-device-legal/expected.json +3 -1
  70. package/conformance/cases/c57-s784-g1-enabled-no-lane/expected.json +3 -1
  71. package/conformance/cases/c58-s784-g2-multitenant-host/expected.json +3 -1
  72. package/conformance/cases/c59-s784-g3-k8s-missing-image/expected.json +3 -1
  73. package/conformance/cases/c60-s784-g3-e2b-missing-key/expected.json +3 -1
  74. package/conformance/cases/c61-s784-g3-other-lane-key/expected.json +3 -1
  75. package/conformance/cases/c62-s784-g7a-session-tidb/expected.json +3 -1
  76. package/conformance/cases/c63-s784-host-two-replicas/expected.json +3 -1
  77. package/conformance/cases/c64-s784-multitenant-local-store/expected.json +3 -1
  78. package/conformance/cases/c65-s784-pg-without-db/expected.json +3 -1
  79. package/conformance/cases/c66-s784-memory-backend-mismatch/expected.json +3 -1
  80. package/conformance/cases/c67-s784-retired-field-loud/expected.json +3 -1
  81. package/conformance/cases/c67-s784-retired-field-loud/meta.json +1 -1
  82. package/conformance/cases/c68-s784-device-local-store/expected.json +3 -1
  83. package/conformance/cases/c69-deep-encoded-token-past-every-reading/expected.json +3 -1
  84. package/conformance/cases/c70-rewritten-token-in-front-of-encoded-pem-header/expected.json +3 -1
  85. package/conformance/cases/c71-one-scanner-write-reads-display-forms/expected.json +119 -0
  86. package/conformance/cases/c71-one-scanner-write-reads-display-forms/input.json +24 -0
  87. package/conformance/cases/c71-one-scanner-write-reads-display-forms/meta.json +10 -0
  88. package/conformance/cases/c72-dangling-reference-write-seat-refuses/expected.json +111 -0
  89. package/conformance/cases/c72-dangling-reference-write-seat-refuses/input.json +26 -0
  90. package/conformance/cases/c72-dangling-reference-write-seat-refuses/meta.json +6 -0
  91. package/conformance/cases/cc01-mcp-toolfaces-non-object/expected.json +3 -1
  92. package/conformance/cases/cc02-mcp-source-key-is-transported/expected.json +3 -1
  93. package/conformance/cases/cc03-model-compat-unknown-subkey/expected.json +6 -1
  94. package/conformance/cases/cli01-model-name-nfc-vs-nfd/expected.json +11 -1
  95. package/conformance/cases/cli02-control-and-zero-width-chars/expected.json +11 -1
  96. package/conformance/cases/cli03-credential-pasted-into-unknown-key/expected.json +16 -2
  97. package/conformance/cases/cli04-env-value-with-newline/expected.json +3 -1
  98. package/conformance/cases/cli05-long-and-prefix-colliding-names/expected.json +6 -1
  99. package/conformance/cases/t01-absent-domain-key-not-null/expected.json +3 -1
  100. package/conformance/cases/t03-prototype-name-key-not-swallowed/expected.json +29 -2
  101. package/conformance/cases/t04-secret-literal-never-in-warning-value/expected.json +3 -1
  102. package/conformance/cases/z01-every-domain-empty-object/expected.json +8 -4
  103. package/conformance/cases/z01-every-domain-empty-object/input.json +0 -1
  104. package/conformance/cases/z01-every-domain-empty-object/meta.json +1 -1
  105. package/conformance/cases/z02-every-domain-unknown-key/expected.json +163 -23
  106. package/conformance/cases/z02-every-domain-unknown-key/input.json +0 -3
  107. package/conformance/cases/z02-every-domain-unknown-key/meta.json +1 -1
  108. package/dist/api/auth-bridge.d.ts +51 -181
  109. package/dist/api/auth-bridge.js +58 -33
  110. package/dist/api/auth.d.ts +37 -146
  111. package/dist/api/auth.js +16 -26
  112. package/dist/api/feedback.d.ts +87 -0
  113. package/dist/api/feedback.js +66 -0
  114. package/dist/api/pull-token.d.ts +32 -0
  115. package/dist/api/pull-token.js +88 -0
  116. package/dist/api/scopes.d.ts +82 -174
  117. package/dist/api/scopes.js +23 -18
  118. package/dist/bundle.d.ts +15 -7
  119. package/dist/bundle.js +28 -27
  120. package/dist/cli.d.ts +3 -1
  121. package/dist/cli.js +132 -81
  122. package/dist/config-d-file.d.ts +14 -0
  123. package/dist/config-d-file.js +67 -0
  124. package/dist/config-fns.d.ts +87 -186
  125. package/dist/config-fns.js +207 -262
  126. package/dist/conformance/contract-adapter.d.ts +9 -2
  127. package/dist/conformance/contract-adapter.js +15 -7
  128. package/dist/conformance/corpus.d.ts +3 -0
  129. package/dist/conformance/corpus.js +5 -0
  130. package/dist/conformance/derive.d.ts +3 -0
  131. package/dist/conformance/index.d.ts +2 -2
  132. package/dist/conformance/index.js +2 -2
  133. package/dist/conformance/run.js +67 -22
  134. package/dist/conformance/types.d.ts +31 -15
  135. package/dist/conformance/types.js +5 -0
  136. package/dist/conformance/warnings.d.ts +1 -1
  137. package/dist/conformance/warnings.js +1 -4
  138. package/dist/cross-domain.d.ts +66 -22
  139. package/dist/cross-domain.js +164 -93
  140. package/dist/cross-session.d.ts +29 -11
  141. package/dist/default-model.d.ts +43 -0
  142. package/dist/default-model.js +34 -0
  143. package/dist/execution-lane-index.d.ts +4 -8
  144. package/dist/execution-lane-index.js +4 -8
  145. package/dist/execution-lanes.d.ts +31 -8
  146. package/dist/execution-lanes.js +23 -5
  147. package/dist/file-edit.js +5 -2
  148. package/dist/file-store.d.ts +7 -6
  149. package/dist/file-store.js +37 -50
  150. package/dist/fleet.d.ts +364 -762
  151. package/dist/fleet.js +277 -224
  152. package/dist/hooks.d.ts +1151 -4737
  153. package/dist/hooks.js +59 -15
  154. package/dist/index.d.ts +10 -4
  155. package/dist/index.js +13 -7
  156. package/dist/integer.d.ts +11 -0
  157. package/dist/integer.js +11 -0
  158. package/dist/issue-path.d.ts +10 -0
  159. package/dist/issue-path.js +10 -0
  160. package/dist/loopback.d.ts +26 -0
  161. package/dist/loopback.js +54 -0
  162. package/dist/migration-receipt.d.ts +42 -0
  163. package/dist/migration-receipt.js +12 -0
  164. package/dist/one-time-migrations.d.ts +56 -0
  165. package/dist/one-time-migrations.js +819 -0
  166. package/dist/prompts-digest.d.ts +1 -1
  167. package/dist/prompts-digest.js +3 -2
  168. package/dist/reader.d.ts +2 -2
  169. package/dist/remote-exec.d.ts +45 -187
  170. package/dist/remote-exec.js +13 -7
  171. package/dist/resolve-roster.d.ts +18 -3
  172. package/dist/resolve-roster.js +28 -25
  173. package/dist/retired-envs.d.ts +24 -0
  174. package/dist/retired-envs.js +114 -0
  175. package/dist/retired-form.d.ts +31 -0
  176. package/dist/retired-form.js +28 -0
  177. package/dist/safety-merge-spec.d.ts +131 -191
  178. package/dist/safety-merge-spec.js +18 -14
  179. package/dist/scheduler-lifetime.d.ts +5 -0
  180. package/dist/scheduler-lifetime.js +7 -0
  181. package/dist/scheduler-store-migration.d.ts +14 -0
  182. package/dist/scheduler-store-migration.js +14 -0
  183. package/dist/scheduler-store-node.d.ts +24 -9
  184. package/dist/scheduler-store-node.js +25 -15
  185. package/dist/scheduler-store.d.ts +47 -14
  186. package/dist/scheduler-store.js +32 -61
  187. package/dist/secret-refs.d.ts +3 -3
  188. package/dist/secret-refs.js +1 -1
  189. package/dist/secret-scan.d.ts +14 -24
  190. package/dist/secret-scan.js +45 -23
  191. package/dist/sha256-core.d.ts +16 -0
  192. package/dist/sha256-core.js +138 -0
  193. package/dist/sha256.d.ts +6 -1
  194. package/dist/sha256.js +8 -98
  195. package/dist/skills-manifest.js +1 -1
  196. package/dist/types.d.ts +1501 -13536
  197. package/dist/types.js +494 -438
  198. package/dist/url-shape.d.ts +34 -0
  199. package/dist/url-shape.js +61 -0
  200. package/dist/web-admin-credential.d.ts +96 -0
  201. package/dist/{center-credential.js → web-admin-credential.js} +46 -43
  202. package/dist/web-admin-env.d.ts +33 -0
  203. package/dist/web-admin-env.js +33 -0
  204. package/dist/worker-row-verdict.d.ts +16 -0
  205. package/dist/worker-row-verdict.js +31 -0
  206. package/dist/workers-rows.d.ts +34 -0
  207. package/dist/workers-rows.js +42 -0
  208. package/dist/zod-unwrap.d.ts +11 -0
  209. package/dist/zod-unwrap.js +25 -0
  210. package/package.json +17 -9
  211. package/conformance/cases/c46-s811-host-name-url-userinfo-characterization/meta.json +0 -6
  212. package/conformance/cases/c47-s811-roles-key-url-userinfo-characterization/meta.json +0 -6
  213. package/conformance/migrate-workers/m01-g5-k8s-env-lifted/expected.json +0 -49
  214. package/conformance/migrate-workers/m01-g5-k8s-env-lifted/input.json +0 -26
  215. package/conformance/migrate-workers/m01-g5-k8s-env-lifted/meta.json +0 -4
  216. package/conformance/migrate-workers/m02-g5-idempotent/expected.json +0 -38
  217. package/conformance/migrate-workers/m02-g5-idempotent/input.json +0 -33
  218. package/conformance/migrate-workers/m02-g5-idempotent/meta.json +0 -5
  219. package/conformance/migrate-workers/m03-g5-refused-no-lane/expected.json +0 -71
  220. package/conformance/migrate-workers/m03-g5-refused-no-lane/input.json +0 -42
  221. package/conformance/migrate-workers/m03-g5-refused-no-lane/meta.json +0 -4
  222. package/conformance/migrate-workers/m04-g7b-session-tidb-lifted/expected.json +0 -52
  223. package/conformance/migrate-workers/m04-g7b-session-tidb-lifted/input.json +0 -30
  224. package/conformance/migrate-workers/m04-g7b-session-tidb-lifted/meta.json +0 -4
  225. package/conformance/migrate-workers/m05-row-verdict-reserved-env/expected.json +0 -82
  226. package/conformance/migrate-workers/m05-row-verdict-reserved-env/input.json +0 -68
  227. package/conformance/migrate-workers/m05-row-verdict-reserved-env/meta.json +0 -4
  228. package/dist/center-credential.d.ts +0 -116
  229. package/dist/issue-text.d.ts +0 -10
  230. package/dist/issue-text.js +0 -8
  231. package/dist/migrate-workers.d.ts +0 -71
  232. package/dist/migrate-workers.js +0 -351
  233. package/dist/migrate.d.ts +0 -255
  234. package/dist/migrate.js +0 -542
  235. /package/conformance/cases/{c46-s811-host-name-url-userinfo-characterization → c46-s811-host-name-url-userinfo-withheld}/input.json +0 -0
package/dist/fleet.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @sema-agent/settings-schema/fleet — the PURE scheduling/fleet contract for the sema-center control plane
2
+ * @sema-agent/settings-schema/fleet — the PURE scheduling/fleet contract for the web-admin control plane
3
3
  * (design: the cc-parity control-plane scheduling design note, 产品拍板 2026-07-04 — "one contract, three orchestrators").
4
4
  *
5
5
  * Seven domains (rolling update / discovery / traffic / failover / LB / quota / token governance) are ONE
@@ -7,7 +7,7 @@
7
7
  * but all three read THESE shapes:
8
8
  * - TOC shell (engineLifecycleManager): health readiness + upgrade classification + local blue-green demo
9
9
  * - TOB (user k8s / fixed baseurl): preStop→drain semantics + readiness probe = !draining
10
- * - center (orchestrator reconciler): instance discovery table + /api/dispatch gateway + rolling primitive
10
+ * - web-admin (orchestrator reconciler): instance discovery table + /api/dispatch gateway + rolling primitive
11
11
  *
12
12
  * 🔴 Contract discipline (same rules as scheduler-store):
13
13
  * - ABSTRACT: types + zod wire shapes + PURE decision functions. ZERO IO, ZERO node:* — browser-safe barrel.
@@ -19,16 +19,16 @@
19
19
  */
20
20
  import { z } from "zod";
21
21
  /**
22
- * The center's `/api/fleet/*` endpoints that are addressed from outside the center, relative to its origin. ONE spelling: whoever
23
- * calls one (the engine, the executor) and whoever serves or routes it (the center, the deployment's Service / Ingress) imports it
22
+ * Web-admin's `/api/fleet/*` endpoints that are addressed from outside web-admin, relative to its origin. ONE spelling: whoever
23
+ * calls one (the engine, the executor) and whoever serves or routes it (web-admin, the deployment's Service / Ingress) imports it
24
24
  * here — nobody writes the string. Membership rule: an endpoint is here iff this package types its body, or it belongs to the
25
- * liveness group ({@link FLEET_LIVE_PATHS}); a center-internal route is not.
26
- * - `instances` — `POST` = the heartbeat ({@link InstanceAnnouncement}; its 2xx reply carries the center's
27
- * {@link CenterCapabilities} under {@link HEARTBEAT_REPLY_CAPABILITIES_KEY}), `DELETE` = the goodbye ({@link InstanceDeregistration}).
25
+ * liveness group ({@link FLEET_LIVE_PATHS}); a web-admin-internal route is not.
26
+ * - `instances` — `POST` = the heartbeat ({@link InstanceAnnouncement}; its 2xx reply carries web-admin's
27
+ * {@link WebAdminCapabilities} under {@link HEARTBEAT_REPLY_CAPABILITIES_KEY}), `DELETE` = the goodbye ({@link InstanceDeregistration}).
28
28
  * - `usage` — `POST` a {@link UsageReport}.
29
29
  * - `quotaLeases` — the quota lease ({@link QuotaLease}).
30
30
  * - `servingLease` — `POST` a {@link ServingLeaseRequest}, answered with a {@link ServingLeaseResponse}.
31
- * - `hostPlanner` — `GET` one host's planner record, for the executor (its body is the center's and the executor's contract, not
31
+ * - `hostPlanner` — `GET` one host's planner record, for the executor (its body is web-admin's and the executor's contract, not
32
32
  * this package's; it is here because the deployment routes it as a member of the liveness group).
33
33
  * Notation: a value is a path TEMPLATE — a parameter is a whole segment written `{name}` (`hostPlanner` ends in `/{host}`, filled
34
34
  * with the URL-encoded host id); the other values have none and are the path itself. A prefix router (an Ingress rule) takes the
@@ -42,8 +42,8 @@ export declare const FLEET_PATHS: {
42
42
  readonly hostPlanner: "/api/fleet/live/host-planner/{host}";
43
43
  };
44
44
  /**
45
- * The LIVENESS group — the fleet endpoints a center answers without its readiness gate and without its config-governance gates
46
- * (they read no config domain and take service credentials only), so that a center whose management face is refused never turns
45
+ * The LIVENESS group — the fleet endpoints a web-admin answers without its readiness gate and without its config-governance gates
46
+ * (they read no config domain and take service credentials only), so that a web-admin whose management face is refused never turns
47
47
  * into a fleet that gets no answers. A deployment routes exactly these past the readiness gate (on Kubernetes: a second Service
48
48
  * with `publishNotReadyAddresses`, and the Ingress rules for them point at it). Membership is THIS list, not a path prefix — the
49
49
  * heartbeat predates the `/api/fleet/live/` prefix; every {@link FLEET_PATHS} entry under that prefix is a member. The
@@ -60,7 +60,7 @@ export declare const DRAIN_PHASES: readonly ["running", "draining", "drained"];
60
60
  export type DrainPhase = (typeof DRAIN_PHASES)[number];
61
61
  /** Shipped default (server 1.96.0): generous by design — the only unrecoverable loss on restart is the
62
62
  * interactive turn currently streaming, so we wait long rather than cut short. Deployments override via
63
- * DRAIN_GRACE_MS; center overrides per-worker through the worker spec. */
63
+ * DRAIN_GRACE_MS; web-admin overrides per-worker through the worker spec. */
64
64
  export declare const DEFAULT_DRAIN_GRACE_MS = 600000;
65
65
  /** Hard floor — a grace below this is treated as this (protects against a fat-fingered 0). */
66
66
  export declare const DRAIN_GRACE_FLOOR_MS = 10000;
@@ -81,6 +81,10 @@ export type DrainVerdict = "wait" | "exit_clean" | "exit_forced";
81
81
  /** The drain state machine's single decision point: keep waiting, exit clean (drained), or force the exit
82
82
  * (grace exhausted with legs still in flight — durable legs resume cross-instance via resumeFromRunId). */
83
83
  export declare function drainVerdict(s: DrainSnapshot): DrainVerdict;
84
+ /** Drain action id grammar — one identifier shape for the drain request's `actionId` and the `EngineDraining.actionId` it echoes
85
+ * (the engine republishes it on the unauthenticated `/health` face, so it must never carry free text): 1–128 chars, first
86
+ * alphanumeric, then alphanumerics / `.` / `_` / `:` / `-`. Readers and writers share this one constant. */
87
+ export declare const DRAIN_ACTION_ID: RegExp;
84
88
  export declare function isCanonicalGeneration(value: unknown): value is string;
85
89
  /** Numeric order of two canonical generations: `-1` when `a` is older than `b`, `0` when equal, `1` when newer — `"9"` is
86
90
  * older than `"10"`; any number of digits. Throws a `TypeError` on an input that is not canonical (a comparison that quietly
@@ -90,27 +94,32 @@ export declare function compareGeneration(a: string, b: string): -1 | 0 | 1;
90
94
  /**
91
95
  * The serving lease as the ENGINE holds it — a CLOSED set of four words, owned here (the engine's vocabulary, word for word;
92
96
  * a reader that switches on it exhaustively is told by the compiler when a word is added):
93
- * - `none` — the lease is not in effect: the center has declared no {@link CenterCapabilities}`.servingLease` ({@link readCapabilityReading}
94
- * says `undeclared` — an older center — or `declared` without the bit). The engine behaves exactly as an engine without a lease —
97
+ * - `none` — the lease is not in effect: web-admin has declared no {@link WebAdminCapabilities}`.servingLease` ({@link readCapabilityReading}
98
+ * says `undeclared` — an older web-admin — or `declared` without the bit). The engine behaves exactly as an engine without a lease —
95
99
  * no renewals, no fence. A reply that cannot be read (`unreadable`) is not a reading: it does not move the engine into or out of
96
100
  * `none` — it keeps the state it had.
97
101
  * - `granted` — the engine holds a lease; `leaseUntil` says until when (epoch ms, the engine's own computation from the
98
102
  * granted `ttlMs`, see {@link ServingLeaseResponse}).
99
- * - `expired` — the lease is in effect but no grant is valid right now (the center is unreachable, answered `unknown`, or has
103
+ * - `expired` — the lease is in effect but no grant is valid right now (web-admin is unreachable, answered `unknown`, or has
100
104
  * not granted one yet): the engine keeps serving until its own outage allowance runs out. Not a denial.
101
- * - `denied` — the center denied this instance on positive evidence (the `denied` verdict): sticky; the engine is draining and
105
+ * - `denied` — web-admin denied this instance on positive evidence (the `denied` verdict): sticky; the engine is draining and
102
106
  * stops at its deadline.
103
107
  * Only a fleet member says it: an engine without a generation has no lease and carries no `leaseState` at all (there is no
104
108
  * fifth word for "not a member" — absence is that).
105
109
  */
106
110
  export declare const LEASE_STATES: readonly ["none", "granted", "expired", "denied"];
107
- export declare const LeaseState: z.ZodEnum<["none", "granted", "expired", "denied"]>;
111
+ export declare const LeaseState: z.ZodEnum<{
112
+ none: "none";
113
+ granted: "granted";
114
+ expired: "expired";
115
+ denied: "denied";
116
+ }>;
108
117
  export type LeaseState = z.infer<typeof LeaseState>;
109
118
  /**
110
- * "This instance must restart to apply config" — the engine's OWN observation (S-741), defined ONCE for both exits that
111
- * carry it: the fleet heartbeat ({@link InstanceAnnouncement}`.restart`, typed) and GET /health (`restart`, read through
112
- * {@link readRestartSignal} — {@link InstanceHealth} keeps carrying it untyped, see there). One mint point, two exits —
113
- * never a second judgement.
119
+ * "This instance must restart to apply config" — the engine's OWN observation (S-741), defined ONCE. It is part of the engine's
120
+ * state, so it rides inside {@link EngineSignal} (`restart`) on both exits — the fleet heartbeat and GET /health — and is read
121
+ * there and only there: `readEngineSignal(body)?.restart`, or `engineSignal?.restart` on a parsed heartbeat / health body. The
122
+ * flat `restart` key the two bodies still carry is the pre-11 dialect (see {@link EngineSignal}); nothing reads it.
114
123
  *
115
124
  * Shape = what the server already ships on /health (`restart: { reasons, version, since }`, plus the optional `withheld`
116
125
  * qualifier below). PRESENCE is the signal:
@@ -118,7 +127,7 @@ export type LeaseState = z.infer<typeof LeaseState>;
118
127
  * to presence is redundant, and two spellings of one fact drift).
119
128
  * - `reasons` — which restart-to-apply slices differ from the value baked at boot (the vocabulary is the engine's;
120
129
  * the contract only guarantees non-empty words, at least one).
121
- * - `version` — the config-center version that currently differs from boot (the LATEST seen — it moves forward with
130
+ * - `version` — the web-admin config version that currently differs from boot (the LATEST seen — it moves forward with
122
131
  * later publishes, so a "one restart per version" dedupe bounds restarts per config version, not per reason set).
123
132
  * Judged exactly as `readEffectiveWire` judges a config version (a finite number, `ConfigVersion`) — one quantity, one rule;
124
133
  * {@link EngineSignal}'s two version-ledger keys use the same one.
@@ -129,31 +138,15 @@ export type LeaseState = z.infer<typeof LeaseState>;
129
138
  * it. It is a qualifier INSIDE the restart signal, never a signal of its own: it exists only where `restart` does.
130
139
  */
131
140
  export declare const RestartSignal: z.ZodObject<{
132
- reasons: z.ZodArray<z.ZodString, "many">;
141
+ reasons: z.ZodArray<z.ZodString>;
133
142
  version: z.ZodNumber;
134
143
  since: z.ZodNumber;
135
144
  withheld: z.ZodOptional<z.ZodBoolean>;
136
- }, "strip", z.ZodTypeAny, {
137
- reasons: string[];
138
- version: number;
139
- since: number;
140
- withheld?: boolean | undefined;
141
- }, {
142
- reasons: string[];
143
- version: number;
144
- since: number;
145
- withheld?: boolean | undefined;
146
- }>;
145
+ }, z.core.$strip>;
147
146
  export type RestartSignal = z.infer<typeof RestartSignal>;
148
- /**
149
- * The /health exit of {@link RestartSignal}: `health.restart` judged against the one shape. Shape mismatch, a missing
150
- * key, a non-object body, even a throwing accessor ⇒ `undefined` — never throws (a probe must not die on one odd body).
151
- * Presence law: only `restart` counts; the top-level `restartRequired` boolean the server also ships is not read.
152
- */
153
- export declare function readRestartSignal(health: unknown): RestartSignal | undefined;
154
147
  /**
155
148
  * The model-refusal cause codes (S-768) — CLOSED sets, owned HERE, never a hand-copied second list. Adding a code is
156
- * one edit in this file; who goes red at compile time: a reader that switches on the code exhaustively (a center), and
149
+ * one edit in this file; who goes red at compile time: a reader that switches on the code exhaustively (a web-admin), and
157
150
  * a producer only where it holds a table KEYED BY the code (an exhaustive `switch` over the code, or a
158
151
  * `Record<ModelEntryRefusalCode, …>`) — a producer table that merely `satisfies` these codes as values proves a subset,
159
152
  * not equality, and stays green.
@@ -175,10 +168,18 @@ export declare function readRestartSignal(health: unknown): RestartSignal | unde
175
168
  * (invariant `model-route-endpoint`, judged by the model-plane stage in `src/config-center/apply-effective.ts:664-665`).
176
169
  */
177
170
  export declare const MODEL_ENTRY_REFUSAL_CODES: readonly ["config.model_no_brain", "config.model_entry_invalid"];
178
- export declare const ModelEntryRefusalCode: z.ZodEnum<["config.model_no_brain", "config.model_entry_invalid"]>;
171
+ export declare const ModelEntryRefusalCode: z.ZodEnum<{
172
+ "config.model_no_brain": "config.model_no_brain";
173
+ "config.model_entry_invalid": "config.model_entry_invalid";
174
+ }>;
179
175
  export type ModelEntryRefusalCode = z.infer<typeof ModelEntryRefusalCode>;
180
176
  export declare const MODEL_PLANE_REFUSAL_CODES: readonly ["config.default_model_missing", "config.model_refused_name_minted", "config.model_route_endpoint_missing", "config.gateway_fallback_without_primary"];
181
- export declare const ModelPlaneRefusalCode: z.ZodEnum<["config.default_model_missing", "config.model_refused_name_minted", "config.model_route_endpoint_missing", "config.gateway_fallback_without_primary"]>;
177
+ export declare const ModelPlaneRefusalCode: z.ZodEnum<{
178
+ "config.default_model_missing": "config.default_model_missing";
179
+ "config.model_refused_name_minted": "config.model_refused_name_minted";
180
+ "config.model_route_endpoint_missing": "config.model_route_endpoint_missing";
181
+ "config.gateway_fallback_without_primary": "config.gateway_fallback_without_primary";
182
+ }>;
182
183
  export type ModelPlaneRefusalCode = z.infer<typeof ModelPlaneRefusalCode>;
183
184
  /**
184
185
  * "This instance does not serve part (or all) of the model catalog it was handed" — the engine's OWN per-host verdict
@@ -221,22 +222,10 @@ export type ModelPlaneRefusalCode = z.infer<typeof ModelPlaneRefusalCode>;
221
222
  * law — "none" has exactly one spelling, the absent key. Inside, "no entry refusals" is spelled `entries: {}` (the key is
222
223
  * required) — one spelling at each level.
223
224
  */
224
- export declare const ModelRefusalsWire: z.ZodEffects<z.ZodObject<{
225
+ export declare const ModelRefusalsWire: z.ZodObject<{
225
226
  entries: z.ZodRecord<z.ZodString, z.ZodString>;
226
227
  plane: z.ZodOptional<z.ZodString>;
227
- }, "strip", z.ZodTypeAny, {
228
- entries: Record<string, string>;
229
- plane?: string | undefined;
230
- }, {
231
- entries: Record<string, string>;
232
- plane?: string | undefined;
233
- }>, {
234
- entries: Record<string, string>;
235
- plane?: string | undefined;
236
- }, {
237
- entries: Record<string, string>;
238
- plane?: string | undefined;
239
- }>;
228
+ }, z.core.$strip>;
240
229
  export type ModelRefusalsWire = z.infer<typeof ModelRefusalsWire>;
241
230
  /** {@link ModelRefusalsWire} narrowed to the closed code sets — the return type of {@link readModelRefusals}. */
242
231
  export type ModelRefusalsSignal = {
@@ -252,466 +241,297 @@ export type ModelRefusalsSignal = {
252
241
  * at all — it answers the key only and never judges the engine's version (see {@link InstanceAnnouncement}`.modelRefusals`).
253
242
  */
254
243
  export declare function readModelRefusals(body: unknown): ModelRefusalsSignal | undefined;
255
- /** The `/health` self-description every orchestrator reads (shipped shape, server 1.96.0). Liveness and
256
- * readiness are deliberately SPLIT: `status` stays ok while draining (the process is alive); routability is
257
- * `isReadyForTraffic`. Unknown fields pass through — health is a self-description, not a closed record. */
244
+ /**
245
+ * The engine's draining fact — ONE object wherever the engine says "I am draining": inside {@link EngineSignal}`.draining`
246
+ * and as the body of a {@link DrainReceipt}.
247
+ * - `actionId` — the action that put the engine into draining (idempotency key of the drain request).
248
+ * - `since` — epoch ms when draining began; it does not move when the same action repeats.
249
+ * - `deadlineAt` — epoch ms by which the engine stops on its own.
250
+ */
251
+ export declare const EngineDraining: z.ZodObject<{
252
+ actionId: z.ZodString;
253
+ since: z.ZodNumber;
254
+ deadlineAt: z.ZodNumber;
255
+ }, z.core.$strip>;
256
+ export type EngineDraining = z.infer<typeof EngineDraining>;
257
+ /**
258
+ * Everything the ENGINE itself mints about its own state, as one object. One mint point on the engine; it rides BOTH exits —
259
+ * the `/health` self-description ({@link InstanceHealth}) and the fleet heartbeat ({@link InstanceAnnouncement}) — WHOLE, under
260
+ * the one key {@link ENGINE_SIGNAL_KEY}. Readers read it there and only there: {@link readEngineSignal} for a body,
261
+ * `engineSignal` on a parsed heartbeat / health body; the readiness / routing judges ({@link judgeReadiness},
262
+ * {@link judgeRoutability}) read nothing else.
263
+ *
264
+ * One fact, one place on a body: the engine's STATE is this object; the row's IDENTITY (`instanceId`, `worker`, `address`,
265
+ * `version`, `heartbeatMs`) is the body's top level and is not repeated here. The flat keys of this object's names that the two
266
+ * bodies still carry (`ready`, `draining` as a boolean + `drainingSince`, `restart`, `generation`, `leaseState`, `leaseUntil`)
267
+ * are the pre-11 flat dialect: sent during its contraction window for readers that predate this key, unchanged in shape, read by
268
+ * nothing in this package; their removal is registered (`ONE_TIME_MIGRATIONS` row `SS-W1`).
269
+ *
270
+ * Nested under one key, not flat on the body: the boolean dialect (`draining: boolean` + `drainingSince`, {@link InstanceHealth} /
271
+ * {@link InstanceAnnouncement}) is still sent during its contraction window while `draining` here is an OBJECT — one key cannot hold
272
+ * both, and a flat object `draining` would make every reader still on the boolean refuse a draining engine's heartbeat. Nested, an
273
+ * older reader never sees it (the heartbeat shape strips unknown keys; `/health` is an open record) and a newer one reads only it.
274
+ *
275
+ * - `ready` — always said (never "absent while ready"): the engine can take new work right now.
276
+ * - `draining` — present ⇔ draining ({@link EngineDraining}).
277
+ * - `restart` — the one {@link RestartSignal}, same schema object, no copy.
278
+ * - `generation` — echo of the env the config renderer set on this instance ({@link FLEET_GENERATION_ENV}), a canonical
279
+ * decimal string ({@link isCanonicalGeneration}). Absent ⇔ not a fleet member (a single-machine engine): it takes no lease
280
+ * and is not fenced.
281
+ * - `leaseState` — the serving lease as the engine holds it ({@link LeaseState}: `none` / `granted` / `expired` / `denied`);
282
+ * present ⇔ fleet member (the engine says it on every beat once it has a generation).
283
+ * - `leaseUntil` — epoch ms until which the engine holds its serving lease, as the engine computed it from the last
284
+ * `ttlMs` it was granted ({@link ServingLeaseResponse}); present ⇔ `leaseState` is `granted`.
285
+ * - `configTargetVersion` / `configAppliedVersion` — the web-admin config version the engine was told to converge on, and the
286
+ * one it has applied: numbers, as the engine mints them (finite, the same rule as {@link RestartSignal}`.version`; equal ⇔ converged).
287
+ *
288
+ * Reading: the default strip — only these keys come out. A shape violation in ANY key makes the whole signal `undefined` (it is
289
+ * never "the rest of it"). `undefined` means "no signal this reader can say" — an engine that does not carry the key, or a
290
+ * malformed one — and is NEVER "ready": the judges answer `no-engine-signal`.
291
+ */
292
+ export declare const EngineSignal: z.ZodObject<{
293
+ ready: z.ZodBoolean;
294
+ draining: z.ZodOptional<z.ZodObject<{
295
+ actionId: z.ZodString;
296
+ since: z.ZodNumber;
297
+ deadlineAt: z.ZodNumber;
298
+ }, z.core.$strip>>;
299
+ restart: z.ZodOptional<z.ZodObject<{
300
+ reasons: z.ZodArray<z.ZodString>;
301
+ version: z.ZodNumber;
302
+ since: z.ZodNumber;
303
+ withheld: z.ZodOptional<z.ZodBoolean>;
304
+ }, z.core.$strip>>;
305
+ generation: z.ZodOptional<z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>;
306
+ leaseState: z.ZodOptional<z.ZodEnum<{
307
+ none: "none";
308
+ granted: "granted";
309
+ expired: "expired";
310
+ denied: "denied";
311
+ }>>;
312
+ leaseUntil: z.ZodOptional<z.ZodNumber>;
313
+ configTargetVersion: z.ZodOptional<z.ZodNumber>;
314
+ configAppliedVersion: z.ZodOptional<z.ZodNumber>;
315
+ }, z.core.$strip>;
316
+ export type EngineSignal = z.infer<typeof EngineSignal>;
317
+ /** The one key {@link EngineSignal} rides under, on the `/health` body and on the heartbeat body alike. Both sides import THIS
318
+ * constant; neither spells the key. */
319
+ export declare const ENGINE_SIGNAL_KEY = "engineSignal";
320
+ /**
321
+ * The reader of {@link EngineSignal} on a body — and so of every part of it (`readEngineSignal(body)?.restart` is THE restart
322
+ * reading): the value under {@link ENGINE_SIGNAL_KEY}, judged by the same guarded body reader as {@link readModelRefusals}, so the
323
+ * same odd input gets the same answer from both. A missing key, shape mismatch (a missing `ready` included), a non-object body,
324
+ * even a throwing accessor ⇒ `undefined` — never throws. Keys of the signal's names lying flat on the body are NOT read (the flat
325
+ * dialect; the carrier is the one key).
326
+ */
327
+ export declare function readEngineSignal(body: unknown): EngineSignal | undefined;
328
+ /** The `/health` self-description every orchestrator reads. Liveness and readiness are deliberately SPLIT: `status` stays ok while
329
+ * draining (the process is alive); readiness is {@link judgeReadiness} over the engine signal the body carries under
330
+ * {@link ENGINE_SIGNAL_KEY}. Unknown fields pass through — health is a self-description, not a closed record: `modelRefusals`
331
+ * rides it untyped and is read with {@link readModelRefusals}; the flat dialect keys other than the boolean pair (`ready`,
332
+ * `restart`, `generation`, `leaseState`, `leaseUntil`) ride it untyped too and are read by nothing. */
258
333
  export declare const InstanceHealth: z.ZodObject<{
259
334
  instanceId: z.ZodString;
260
- /** build self-description — "did the restart actually land new code" (upgrade classification) */
261
- version: z.ZodString;
262
- /** absent = not draining */
263
- draining: z.ZodOptional<z.ZodBoolean>;
264
- /** epoch ms, present iff draining */
265
- drainingSince: z.ZodOptional<z.ZodNumber>;
266
- }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
267
- instanceId: z.ZodString;
268
- /** build self-description — "did the restart actually land new code" (upgrade classification) */
269
- version: z.ZodString;
270
- /** absent = not draining */
271
- draining: z.ZodOptional<z.ZodBoolean>;
272
- /** epoch ms, present iff draining */
273
- drainingSince: z.ZodOptional<z.ZodNumber>;
274
- }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
275
- instanceId: z.ZodString;
276
- /** build self-description — "did the restart actually land new code" (upgrade classification) */
277
335
  version: z.ZodString;
278
- /** absent = not draining */
279
336
  draining: z.ZodOptional<z.ZodBoolean>;
280
- /** epoch ms, present iff draining */
281
337
  drainingSince: z.ZodOptional<z.ZodNumber>;
282
- }, z.ZodTypeAny, "passthrough">>;
338
+ engineSignal: z.ZodCatch<z.ZodOptional<z.ZodObject<{
339
+ ready: z.ZodBoolean;
340
+ draining: z.ZodOptional<z.ZodObject<{
341
+ actionId: z.ZodString;
342
+ since: z.ZodNumber;
343
+ deadlineAt: z.ZodNumber;
344
+ }, z.core.$strip>>;
345
+ restart: z.ZodOptional<z.ZodObject<{
346
+ reasons: z.ZodArray<z.ZodString>;
347
+ version: z.ZodNumber;
348
+ since: z.ZodNumber;
349
+ withheld: z.ZodOptional<z.ZodBoolean>;
350
+ }, z.core.$strip>>;
351
+ generation: z.ZodOptional<z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>;
352
+ leaseState: z.ZodOptional<z.ZodEnum<{
353
+ none: "none";
354
+ granted: "granted";
355
+ expired: "expired";
356
+ denied: "denied";
357
+ }>>;
358
+ leaseUntil: z.ZodOptional<z.ZodNumber>;
359
+ configTargetVersion: z.ZodOptional<z.ZodNumber>;
360
+ configAppliedVersion: z.ZodOptional<z.ZodNumber>;
361
+ }, z.core.$strip>>>;
362
+ }, z.core.$loose>;
283
363
  export type InstanceHealth = z.infer<typeof InstanceHealth>;
284
- /** Readiness = the routability predicate (k8s readiness probe, gateway health filter, shell seam switch).
285
- * Its input is the boolean-`draining` dialect of {@link InstanceHealth}. An {@link EngineSignal} types `draining` as an
286
- * object, so it does not typecheck here (on purpose: `!== true` would read an object-valued `draining` as "ready").
287
- * The next major retires the boolean pair (`draining` / `drainingSince`) and gives both this predicate and
288
- * {@link isRoutable} `EngineSignal` as their input. */
289
- export declare function isReadyForTraffic(h: Pick<InstanceHealth, "draining">): boolean;
290
- /** Heartbeat cadence the announcement declares (center judges staleness against the DECLARED cadence, so a
364
+ /** Why an instance is not routable — a CLOSED set, in the order the judges check:
365
+ * - `no-engine-signal` — no {@link EngineSignal} to read (an engine that does not carry it, or a malformed one). Never "ready".
366
+ * - `stale` — silent past its declared heartbeat cadence × {@link STALE_HEARTBEAT_MULTIPLIER} (stored rows only).
367
+ * - `observer-not-ready` — the reconciler's own observation vetoes it (stored rows only; the SECOND source, AND-merged).
368
+ * - `draining` — the engine says it is draining.
369
+ * - `not-ready` — the engine says it is not ready. */
370
+ export declare const NOT_ROUTABLE_CODES: readonly ["no-engine-signal", "stale", "observer-not-ready", "draining", "not-ready"];
371
+ export type NotRoutableCode = (typeof NOT_ROUTABLE_CODES)[number];
372
+ /** A judge's verdict: routable, or not with a closed-set code and one sentence for logs / operator surfaces. */
373
+ export type RoutingVerdict = {
374
+ routable: true;
375
+ } | {
376
+ routable: false;
377
+ code: NotRoutableCode;
378
+ why: string;
379
+ };
380
+ /** Readiness — the ONE judge of "may new work go to this engine", from the engine's own signal only (k8s readiness probe,
381
+ * gateway health filter, shell seam switch): ready ⇔ a signal is present, says `ready`, and is not draining. Pass
382
+ * {@link readEngineSignal}`(healthBody)`; `undefined` (no signal) is `no-engine-signal`, never ready. */
383
+ export declare function judgeReadiness(signal: EngineSignal | undefined): RoutingVerdict;
384
+ /** {@link judgeReadiness} as a boolean (the same judge, no second reading). */
385
+ export declare function isReadyForTraffic(signal: EngineSignal | undefined): boolean;
386
+ /** Heartbeat cadence the announcement declares (web-admin judges staleness against the DECLARED cadence, so a
291
387
  * slow-heartbeat worker is not falsely reaped). */
292
388
  export declare const DEFAULT_HEARTBEAT_MS = 30000;
293
389
  /** An instance is stale once silent for this many missed heartbeats (aligned with the reconciler's own
294
390
  * stale window: 2× cadence, not a fixed wall-clock). */
295
391
  export declare const STALE_HEARTBEAT_MULTIPLIER = 2;
296
- /** Register/heartbeat upsert (worker → center, D2: worker-active). ONE shape for both — registration is the
392
+ /** Register/heartbeat upsert (worker → web-admin, D2: worker-active). ONE shape for both — registration is the
297
393
  * first heartbeat; every heartbeat re-announces the full row (idempotent upsert, no drift between a
298
- * "register" and a "renew" schema). `draining:true` is the instance SELF-removing from the routable set the
299
- * moment the stop signal lands — faster than any observer.
394
+ * "register" and a "renew" schema). The engine's {@link EngineSignal} rides it whole under {@link ENGINE_SIGNAL_KEY}: a signal
395
+ * saying "draining" is the instance SELF-removing from the routable set the moment the stop signal lands — faster than any
396
+ * observer.
300
397
  * Scope: the body carries NO `scope` — this shape has no such key, and one sent anyway is stripped. The row lands in the scope
301
398
  * the CREDENTIAL names: under a per-worker token, the scope the token binds (a `?scope=` query parameter, when given, must equal
302
399
  * it); under the shared token, the `?scope=` query parameter, absent ⇒ `"global"`. */
303
400
  export declare const InstanceAnnouncement: z.ZodObject<{
304
401
  instanceId: z.ZodString;
305
- /** worker (deployment) this instance belongs to — the dispatch key */
306
402
  worker: z.ZodString;
307
- /** reachable base URL for the deployment form: k8s pod IP:port / docker net alias / 127.0.0.1:<engine.port> */
308
403
  address: z.ZodString;
309
404
  version: z.ZodString;
310
- /** self-declared readiness: model roster landed AND not draining (server ≥7.102.0; older engines: !draining only) */
311
405
  ready: z.ZodBoolean;
312
406
  draining: z.ZodDefault<z.ZodBoolean>;
313
407
  heartbeatMs: z.ZodDefault<z.ZodNumber>;
314
- /** S-741: present ⇔ this instance must restart to apply config — the SAME {@link RestartSignal} /health carries,
315
- * minted by the same getter (self-reported: a worker-scoped credential can only report for its own worker).
316
- * Every heartbeat re-announces the full row, so a later heartbeat WITHOUT it means "no longer required" — the
317
- * stored row ({@link InstanceRegistration}) is replaced, never merged. */
318
408
  restart: z.ZodOptional<z.ZodObject<{
319
- reasons: z.ZodArray<z.ZodString, "many">;
409
+ reasons: z.ZodArray<z.ZodString>;
320
410
  version: z.ZodNumber;
321
411
  since: z.ZodNumber;
322
412
  withheld: z.ZodOptional<z.ZodBoolean>;
323
- }, "strip", z.ZodTypeAny, {
324
- reasons: string[];
325
- version: number;
326
- since: number;
327
- withheld?: boolean | undefined;
328
- }, {
329
- reasons: string[];
330
- version: number;
331
- since: number;
332
- withheld?: boolean | undefined;
333
- }>>;
334
- /** S-768: present ⇔ this instance has at least one reportable model refusal — the SAME {@link ModelRefusalsWire} /health
335
- * carries, minted by the same getter; read it with {@link readModelRefusals}`(announcement)` (never off this field
336
- * directly: the field is the open wire form, the reader narrows to the closed sets). Every heartbeat re-announces the
337
- * full row, so a later heartbeat WITHOUT it means "no reportable refusals any more" (the stored row is replaced, never
338
- * merged). Reading absence: from an engine that reports this key, absent = none reportable; an engine that predates
339
- * the key never sends it, so there absence is UNKNOWN, not "none" — tell the two apart by the announced `version`.
340
- * Failure direction = meaning direction (this is a diagnostic key): a code this package version does not know passes
341
- * (it is "not said" to the reader), and a value that breaks the {@link ModelRefusalsWire} shape law is dropped to
342
- * ABSENT (`.catch`) — it never fails the announcement, so it can never make a healthy instance unroutable (unlike
343
- * `restart`, whose shape still gates the row). The key may then be present with the value `undefined`. */
344
- modelRefusals: z.ZodCatch<z.ZodOptional<z.ZodEffects<z.ZodObject<{
413
+ }, z.core.$strip>>;
414
+ modelRefusals: z.ZodCatch<z.ZodOptional<z.ZodObject<{
345
415
  entries: z.ZodRecord<z.ZodString, z.ZodString>;
346
416
  plane: z.ZodOptional<z.ZodString>;
347
- }, "strip", z.ZodTypeAny, {
348
- entries: Record<string, string>;
349
- plane?: string | undefined;
350
- }, {
351
- entries: Record<string, string>;
352
- plane?: string | undefined;
353
- }>, {
354
- entries: Record<string, string>;
355
- plane?: string | undefined;
356
- }, {
357
- entries: Record<string, string>;
358
- plane?: string | undefined;
417
+ }, z.core.$strip>>>;
418
+ generation: z.ZodCatch<z.ZodOptional<z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>>;
419
+ leaseState: z.ZodCatch<z.ZodOptional<z.ZodEnum<{
420
+ none: "none";
421
+ granted: "granted";
422
+ expired: "expired";
423
+ denied: "denied";
359
424
  }>>>;
360
- /** Fleet membership and the lease reading, flat on the heartbeat body under the names and values {@link EngineSignal} gives
361
- * them (one mint point on the engine; this shape reuses that shape's schemas, not copies):
362
- * - `generation` — the canonical decimal generation ({@link isCanonicalGeneration}); present ⇔ the instance is a fleet member.
363
- * - `leaseState` — {@link LeaseState}; present ⇔ fleet member.
364
- * - `leaseUntil` — epoch ms until which the held lease runs; present ⇔ `leaseState` is `granted`.
365
- * The presence law between the three is the engine's; this shape does not judge it across keys. Every heartbeat re-announces
366
- * the full row, so a later heartbeat without a key means the engine no longer says it (the stored row is replaced, never merged).
367
- * Failure direction = meaning direction: these are evidence a center keeps, never routing input — a value that breaks its schema
368
- * drops that ONE key to ABSENT (`.catch`) and the heartbeat is still accepted, so a lease word a newer engine adds can never make
369
- * an older center refuse every heartbeat of that engine. A dropped key reads exactly like an unsaid one; the key may then be
370
- * present with the value `undefined`. */
371
- generation: z.ZodCatch<z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>>;
372
- leaseState: z.ZodCatch<z.ZodOptional<z.ZodEnum<["none", "granted", "expired", "denied"]>>>;
373
425
  leaseUntil: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
374
- }, "strip", z.ZodTypeAny, {
375
- draining: boolean;
376
- version: string;
377
- instanceId: string;
378
- worker: string;
379
- address: string;
380
- ready: boolean;
381
- heartbeatMs: number;
382
- restart?: {
383
- reasons: string[];
384
- version: number;
385
- since: number;
386
- withheld?: boolean | undefined;
387
- } | undefined;
388
- modelRefusals?: {
389
- entries: Record<string, string>;
390
- plane?: string | undefined;
391
- } | undefined;
392
- generation?: string | undefined;
393
- leaseState?: "none" | "granted" | "expired" | "denied" | undefined;
394
- leaseUntil?: number | undefined;
395
- }, {
396
- version: string;
397
- instanceId: string;
398
- worker: string;
399
- address: string;
400
- ready: boolean;
401
- draining?: boolean | undefined;
402
- restart?: {
403
- reasons: string[];
404
- version: number;
405
- since: number;
406
- withheld?: boolean | undefined;
407
- } | undefined;
408
- modelRefusals?: unknown;
409
- heartbeatMs?: number | undefined;
410
- generation?: unknown;
411
- leaseState?: unknown;
412
- leaseUntil?: unknown;
413
- }>;
426
+ engineSignal: z.ZodCatch<z.ZodOptional<z.ZodObject<{
427
+ ready: z.ZodBoolean;
428
+ draining: z.ZodOptional<z.ZodObject<{
429
+ actionId: z.ZodString;
430
+ since: z.ZodNumber;
431
+ deadlineAt: z.ZodNumber;
432
+ }, z.core.$strip>>;
433
+ restart: z.ZodOptional<z.ZodObject<{
434
+ reasons: z.ZodArray<z.ZodString>;
435
+ version: z.ZodNumber;
436
+ since: z.ZodNumber;
437
+ withheld: z.ZodOptional<z.ZodBoolean>;
438
+ }, z.core.$strip>>;
439
+ generation: z.ZodOptional<z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>;
440
+ leaseState: z.ZodOptional<z.ZodEnum<{
441
+ none: "none";
442
+ granted: "granted";
443
+ expired: "expired";
444
+ denied: "denied";
445
+ }>>;
446
+ leaseUntil: z.ZodOptional<z.ZodNumber>;
447
+ configTargetVersion: z.ZodOptional<z.ZodNumber>;
448
+ configAppliedVersion: z.ZodOptional<z.ZodNumber>;
449
+ }, z.core.$strip>>>;
450
+ }, z.core.$strip>;
414
451
  export type InstanceAnnouncement = z.infer<typeof InstanceAnnouncement>;
415
452
  /** Explicit goodbye (stop signal handler) — removes the row immediately instead of waiting out staleness. */
416
453
  export declare const InstanceDeregistration: z.ZodObject<{
417
454
  instanceId: z.ZodString;
418
455
  worker: z.ZodString;
419
- reason: z.ZodOptional<z.ZodEnum<["draining", "shutdown", "superseded"]>>;
420
- }, "strip", z.ZodTypeAny, {
421
- instanceId: string;
422
- worker: string;
423
- reason?: "draining" | "shutdown" | "superseded" | undefined;
424
- }, {
425
- instanceId: string;
426
- worker: string;
427
- reason?: "draining" | "shutdown" | "superseded" | undefined;
428
- }>;
456
+ reason: z.ZodOptional<z.ZodEnum<{
457
+ draining: "draining";
458
+ shutdown: "shutdown";
459
+ superseded: "superseded";
460
+ }>>;
461
+ }, z.core.$strip>;
429
462
  export type InstanceDeregistration = z.infer<typeof InstanceDeregistration>;
430
- /** The stored discovery-table row = last announcement + center-side bookkeeping. `observedReady` is the
463
+ /** The stored discovery-table row = last announcement + web-admin-side bookkeeping. `observedReady` is the
431
464
  * reconciler's observation (phase Running) — the SECOND source; absent where no reconciler exists (TOC/TOB). */
432
465
  export declare const InstanceRegistration: z.ZodObject<{
433
466
  instanceId: z.ZodString;
434
- /** worker (deployment) this instance belongs to — the dispatch key */
435
467
  worker: z.ZodString;
436
- /** reachable base URL for the deployment form: k8s pod IP:port / docker net alias / 127.0.0.1:<engine.port> */
437
468
  address: z.ZodString;
438
469
  version: z.ZodString;
439
- /** self-declared readiness: model roster landed AND not draining (server ≥7.102.0; older engines: !draining only) */
440
470
  ready: z.ZodBoolean;
441
471
  draining: z.ZodDefault<z.ZodBoolean>;
442
472
  heartbeatMs: z.ZodDefault<z.ZodNumber>;
443
- /** S-741: present ⇔ this instance must restart to apply config — the SAME {@link RestartSignal} /health carries,
444
- * minted by the same getter (self-reported: a worker-scoped credential can only report for its own worker).
445
- * Every heartbeat re-announces the full row, so a later heartbeat WITHOUT it means "no longer required" — the
446
- * stored row ({@link InstanceRegistration}) is replaced, never merged. */
447
473
  restart: z.ZodOptional<z.ZodObject<{
448
- reasons: z.ZodArray<z.ZodString, "many">;
474
+ reasons: z.ZodArray<z.ZodString>;
449
475
  version: z.ZodNumber;
450
476
  since: z.ZodNumber;
451
477
  withheld: z.ZodOptional<z.ZodBoolean>;
452
- }, "strip", z.ZodTypeAny, {
453
- reasons: string[];
454
- version: number;
455
- since: number;
456
- withheld?: boolean | undefined;
457
- }, {
458
- reasons: string[];
459
- version: number;
460
- since: number;
461
- withheld?: boolean | undefined;
462
- }>>;
463
- /** S-768: present ⇔ this instance has at least one reportable model refusal — the SAME {@link ModelRefusalsWire} /health
464
- * carries, minted by the same getter; read it with {@link readModelRefusals}`(announcement)` (never off this field
465
- * directly: the field is the open wire form, the reader narrows to the closed sets). Every heartbeat re-announces the
466
- * full row, so a later heartbeat WITHOUT it means "no reportable refusals any more" (the stored row is replaced, never
467
- * merged). Reading absence: from an engine that reports this key, absent = none reportable; an engine that predates
468
- * the key never sends it, so there absence is UNKNOWN, not "none" — tell the two apart by the announced `version`.
469
- * Failure direction = meaning direction (this is a diagnostic key): a code this package version does not know passes
470
- * (it is "not said" to the reader), and a value that breaks the {@link ModelRefusalsWire} shape law is dropped to
471
- * ABSENT (`.catch`) — it never fails the announcement, so it can never make a healthy instance unroutable (unlike
472
- * `restart`, whose shape still gates the row). The key may then be present with the value `undefined`. */
473
- modelRefusals: z.ZodCatch<z.ZodOptional<z.ZodEffects<z.ZodObject<{
478
+ }, z.core.$strip>>;
479
+ modelRefusals: z.ZodCatch<z.ZodOptional<z.ZodObject<{
474
480
  entries: z.ZodRecord<z.ZodString, z.ZodString>;
475
481
  plane: z.ZodOptional<z.ZodString>;
476
- }, "strip", z.ZodTypeAny, {
477
- entries: Record<string, string>;
478
- plane?: string | undefined;
479
- }, {
480
- entries: Record<string, string>;
481
- plane?: string | undefined;
482
- }>, {
483
- entries: Record<string, string>;
484
- plane?: string | undefined;
485
- }, {
486
- entries: Record<string, string>;
487
- plane?: string | undefined;
482
+ }, z.core.$strip>>>;
483
+ generation: z.ZodCatch<z.ZodOptional<z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>>;
484
+ leaseState: z.ZodCatch<z.ZodOptional<z.ZodEnum<{
485
+ none: "none";
486
+ granted: "granted";
487
+ expired: "expired";
488
+ denied: "denied";
488
489
  }>>>;
489
- /** Fleet membership and the lease reading, flat on the heartbeat body under the names and values {@link EngineSignal} gives
490
- * them (one mint point on the engine; this shape reuses that shape's schemas, not copies):
491
- * - `generation` — the canonical decimal generation ({@link isCanonicalGeneration}); present ⇔ the instance is a fleet member.
492
- * - `leaseState` — {@link LeaseState}; present ⇔ fleet member.
493
- * - `leaseUntil` — epoch ms until which the held lease runs; present ⇔ `leaseState` is `granted`.
494
- * The presence law between the three is the engine's; this shape does not judge it across keys. Every heartbeat re-announces
495
- * the full row, so a later heartbeat without a key means the engine no longer says it (the stored row is replaced, never merged).
496
- * Failure direction = meaning direction: these are evidence a center keeps, never routing input — a value that breaks its schema
497
- * drops that ONE key to ABSENT (`.catch`) and the heartbeat is still accepted, so a lease word a newer engine adds can never make
498
- * an older center refuse every heartbeat of that engine. A dropped key reads exactly like an unsaid one; the key may then be
499
- * present with the value `undefined`. */
500
- generation: z.ZodCatch<z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>>;
501
- leaseState: z.ZodCatch<z.ZodOptional<z.ZodEnum<["none", "granted", "expired", "denied"]>>>;
502
490
  leaseUntil: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
503
- } & {
491
+ engineSignal: z.ZodCatch<z.ZodOptional<z.ZodObject<{
492
+ ready: z.ZodBoolean;
493
+ draining: z.ZodOptional<z.ZodObject<{
494
+ actionId: z.ZodString;
495
+ since: z.ZodNumber;
496
+ deadlineAt: z.ZodNumber;
497
+ }, z.core.$strip>>;
498
+ restart: z.ZodOptional<z.ZodObject<{
499
+ reasons: z.ZodArray<z.ZodString>;
500
+ version: z.ZodNumber;
501
+ since: z.ZodNumber;
502
+ withheld: z.ZodOptional<z.ZodBoolean>;
503
+ }, z.core.$strip>>;
504
+ generation: z.ZodOptional<z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>;
505
+ leaseState: z.ZodOptional<z.ZodEnum<{
506
+ none: "none";
507
+ granted: "granted";
508
+ expired: "expired";
509
+ denied: "denied";
510
+ }>>;
511
+ leaseUntil: z.ZodOptional<z.ZodNumber>;
512
+ configTargetVersion: z.ZodOptional<z.ZodNumber>;
513
+ configAppliedVersion: z.ZodOptional<z.ZodNumber>;
514
+ }, z.core.$strip>>>;
504
515
  registeredMs: z.ZodNumber;
505
516
  lastSeenMs: z.ZodNumber;
506
517
  observedReady: z.ZodOptional<z.ZodBoolean>;
507
- }, "strip", z.ZodTypeAny, {
508
- draining: boolean;
509
- version: string;
510
- instanceId: string;
511
- worker: string;
512
- address: string;
513
- ready: boolean;
514
- heartbeatMs: number;
515
- registeredMs: number;
516
- lastSeenMs: number;
517
- restart?: {
518
- reasons: string[];
519
- version: number;
520
- since: number;
521
- withheld?: boolean | undefined;
522
- } | undefined;
523
- modelRefusals?: {
524
- entries: Record<string, string>;
525
- plane?: string | undefined;
526
- } | undefined;
527
- generation?: string | undefined;
528
- leaseState?: "none" | "granted" | "expired" | "denied" | undefined;
529
- leaseUntil?: number | undefined;
530
- observedReady?: boolean | undefined;
531
- }, {
532
- version: string;
533
- instanceId: string;
534
- worker: string;
535
- address: string;
536
- ready: boolean;
537
- registeredMs: number;
538
- lastSeenMs: number;
539
- draining?: boolean | undefined;
540
- restart?: {
541
- reasons: string[];
542
- version: number;
543
- since: number;
544
- withheld?: boolean | undefined;
545
- } | undefined;
546
- modelRefusals?: unknown;
547
- heartbeatMs?: number | undefined;
548
- generation?: unknown;
549
- leaseState?: unknown;
550
- leaseUntil?: unknown;
551
- observedReady?: boolean | undefined;
552
- }>;
518
+ }, z.core.$strip>;
553
519
  export type InstanceRegistration = z.infer<typeof InstanceRegistration>;
554
520
  /** Silent past the declared cadence × multiplier ⇒ stale (auto-removed from the routable set). */
555
521
  export declare function isInstanceStale(r: Pick<InstanceRegistration, "lastSeenMs" | "heartbeatMs">, nowMs: number): boolean;
556
- /** Health fusion: routable ⇔ self-declared ready ∧ not draining ∧ not stale ∧ observer does not veto.
557
- * Two sources merge as an AND — EITHER source's "not ready" removes the instance (fail-closed).
558
- * Its input is the stored heartbeat row (boolean `draining`); it moves to {@link EngineSignal} in the same major as
559
- * {@link isReadyForTraffic}. */
522
+ /** Health fusion — the ONE judge of "may dispatch route to this stored instance": a signal is present ∧ the row is not stale ∧
523
+ * the observer does not veto ∧ the engine's own readiness ({@link judgeReadiness} over the row's {@link EngineSignal}). Two sources
524
+ * merge as an AND — EITHER source's "not ready" removes the instance (fail-closed). The row's boolean `draining` is not read. */
525
+ export declare function judgeRoutability(r: InstanceRegistration, nowMs: number): RoutingVerdict;
526
+ /** {@link judgeRoutability} as a boolean (the same judge, no second reading). */
560
527
  export declare function isRoutable(r: InstanceRegistration, nowMs: number): boolean;
561
528
  export declare function routableInstances(rs: InstanceRegistration[], nowMs: number): InstanceRegistration[];
562
- /**
563
- * The engine's draining fact — ONE object wherever the engine says "I am draining": inside {@link EngineSignal}`.draining`
564
- * and as the body of a {@link DrainReceipt}.
565
- * - `actionId` — the action that put the engine into draining (idempotency key of the drain request).
566
- * - `since` — epoch ms when draining began; it does not move when the same action repeats.
567
- * - `deadlineAt` — epoch ms by which the engine stops on its own.
568
- */
569
- export declare const EngineDraining: z.ZodObject<{
570
- actionId: z.ZodString;
571
- since: z.ZodNumber;
572
- deadlineAt: z.ZodNumber;
573
- }, "strip", z.ZodTypeAny, {
574
- since: number;
575
- actionId: string;
576
- deadlineAt: number;
577
- }, {
578
- since: number;
579
- actionId: string;
580
- deadlineAt: number;
581
- }>;
582
- export type EngineDraining = z.infer<typeof EngineDraining>;
583
- /**
584
- * Everything the ENGINE itself mints about its own state, as one object — the closed form of the engine-owned subset of the
585
- * /health self-description ({@link InstanceHealth} is that self-description: an open record, `.passthrough()`, which also
586
- * carries what the host adds — build, pid, port, store posture). One mint point on the engine; {@link readEngineSignal} reads
587
- * this shape off a body whose keys sit flat on it (no wrapper key).
588
- *
589
- * Where it rides today: on NEITHER exit whole. The heartbeat ({@link InstanceAnnouncement}) and `/health` ({@link InstanceHealth})
590
- * still speak the 8.0 dialect for the keys they share with this shape, in two ways:
591
- * 1. `draining` is a BOOLEAN there, not the {@link EngineDraining} object. The heartbeat always carries it (`false` included);
592
- * `/health` carries `draining: true` only while draining.
593
- * 2. `/health` carries `ready` only while NOT ready (`ready: false`); a ready engine's `/health` body has no `ready` key.
594
- * So `readEngineSignal` over a heartbeat body is always `undefined` (point 1), and over a `/health` body it is `undefined` whenever
595
- * either applies. What does ride both exits flat, under these names and with these values: `restart`, `instanceId`
596
- * and the fleet-membership keys `generation` / `leaseState` / `leaseUntil` — on the heartbeat, read them off the parsed
597
- * {@link InstanceAnnouncement} (which types all five). The next major retires the boolean pair (`draining` / `drainingSince`),
598
- * has both exits carry this shape whole and moves {@link isReadyForTraffic} / {@link isRoutable} onto it; until then this is
599
- * the target form, and `readEngineSignal` is the reader for a body that already speaks it.
600
- *
601
- * - `ready` — always said (never "absent while ready"): the engine can take new work right now.
602
- * - `draining` — present ⇔ draining ({@link EngineDraining}). NOTE the dialect: {@link InstanceHealth}`.draining` and
603
- * {@link InstanceAnnouncement}`.draining` are BOOLEANS (the 8.0 dialect, kept untouched); here it is an object. A body
604
- * whose `draining` is a boolean is therefore not an `EngineSignal` and reads as `undefined`.
605
- * - `restart` — the one {@link RestartSignal}, same schema object, no copy.
606
- * - `generation` — echo of the env the config renderer set on this instance ({@link FLEET_GENERATION_ENV}), a canonical
607
- * decimal string ({@link isCanonicalGeneration}). Absent ⇔ not a fleet member (a single-machine engine): it takes no lease
608
- * and is not fenced.
609
- * - `instanceId` — the engine's OWN process identity, minted by the engine every time the process starts (never read from
610
- * env: replicas of one Deployment share one env, and a restarted container reuses its env, so env cannot tell two
611
- * processes apart). It is present on a standalone engine too — only `generation` marks fleet membership.
612
- * - `leaseState` — the serving lease as the engine holds it ({@link LeaseState}: `none` / `granted` / `expired` / `denied`);
613
- * present ⇔ fleet member (the engine says it on every beat once it has a generation).
614
- * - `leaseUntil` — epoch ms until which the engine holds its serving lease, as the engine computed it from the last
615
- * `ttlMs` it was granted ({@link ServingLeaseResponse}); present ⇔ `leaseState` is `granted`.
616
- * - `configTargetVersion` / `configAppliedVersion` — the config-center version the engine was told to converge on, and the
617
- * one it has applied: numbers, as the engine mints them (finite, the same rule as {@link RestartSignal}`.version`; equal ⇔ converged).
618
- *
619
- * Reading: `EngineSignal` is parsed with the default strip — a whole /health body goes in, only these keys come out. A
620
- * shape violation in ANY key makes the whole signal `undefined` (it is never "the rest of it"). `undefined` means "no
621
- * signal this reader can say" — an engine that predates the keys, or a malformed body — and is NEVER "ready": a caller on
622
- * the routing axis treats it as not routable unless it deliberately falls back to the boolean dialect of
623
- * {@link InstanceHealth}.
624
- */
625
- export declare const EngineSignal: z.ZodObject<{
626
- ready: z.ZodBoolean;
627
- draining: z.ZodOptional<z.ZodObject<{
628
- actionId: z.ZodString;
629
- since: z.ZodNumber;
630
- deadlineAt: z.ZodNumber;
631
- }, "strip", z.ZodTypeAny, {
632
- since: number;
633
- actionId: string;
634
- deadlineAt: number;
635
- }, {
636
- since: number;
637
- actionId: string;
638
- deadlineAt: number;
639
- }>>;
640
- restart: z.ZodOptional<z.ZodObject<{
641
- reasons: z.ZodArray<z.ZodString, "many">;
642
- version: z.ZodNumber;
643
- since: z.ZodNumber;
644
- withheld: z.ZodOptional<z.ZodBoolean>;
645
- }, "strip", z.ZodTypeAny, {
646
- reasons: string[];
647
- version: number;
648
- since: number;
649
- withheld?: boolean | undefined;
650
- }, {
651
- reasons: string[];
652
- version: number;
653
- since: number;
654
- withheld?: boolean | undefined;
655
- }>>;
656
- generation: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
657
- instanceId: z.ZodOptional<z.ZodString>;
658
- leaseState: z.ZodOptional<z.ZodEnum<["none", "granted", "expired", "denied"]>>;
659
- leaseUntil: z.ZodOptional<z.ZodNumber>;
660
- configTargetVersion: z.ZodOptional<z.ZodNumber>;
661
- configAppliedVersion: z.ZodOptional<z.ZodNumber>;
662
- }, "strip", z.ZodTypeAny, {
663
- ready: boolean;
664
- draining?: {
665
- since: number;
666
- actionId: string;
667
- deadlineAt: number;
668
- } | undefined;
669
- restart?: {
670
- reasons: string[];
671
- version: number;
672
- since: number;
673
- withheld?: boolean | undefined;
674
- } | undefined;
675
- instanceId?: string | undefined;
676
- generation?: string | undefined;
677
- leaseState?: "none" | "granted" | "expired" | "denied" | undefined;
678
- leaseUntil?: number | undefined;
679
- configTargetVersion?: number | undefined;
680
- configAppliedVersion?: number | undefined;
681
- }, {
682
- ready: boolean;
683
- draining?: {
684
- since: number;
685
- actionId: string;
686
- deadlineAt: number;
687
- } | undefined;
688
- restart?: {
689
- reasons: string[];
690
- version: number;
691
- since: number;
692
- withheld?: boolean | undefined;
693
- } | undefined;
694
- instanceId?: string | undefined;
695
- generation?: string | undefined;
696
- leaseState?: "none" | "granted" | "expired" | "denied" | undefined;
697
- leaseUntil?: number | undefined;
698
- configTargetVersion?: number | undefined;
699
- configAppliedVersion?: number | undefined;
700
- }>;
701
- export type EngineSignal = z.infer<typeof EngineSignal>;
702
- /**
703
- * The reader of {@link EngineSignal}: the shape's keys, flat on the given body, judged by the same guarded body reader as
704
- * {@link readRestartSignal} and {@link readModelRefusals}, so the same odd input gets the same answer from all three. Shape
705
- * mismatch, a missing `ready`, a non-object body, even a throwing accessor ⇒ `undefined` — never throws. See {@link EngineSignal}
706
- * for what `undefined` means (not "ready") and for why today's heartbeat and `/health` bodies read as `undefined` here.
707
- */
708
- export declare function readEngineSignal(health: unknown): EngineSignal | undefined;
709
529
  /**
710
530
  * The env name a fleet member's generation travels under — the config renderer sets it, the engine reads it back and echoes
711
531
  * it as {@link EngineSignal}`.generation`. Both sides import THIS constant; neither spells the name. The value is the
712
532
  * generation this instance belongs to (opaque string); absent from the engine's env ⇔ not a fleet member (the standalone
713
533
  * form). There is deliberately NO env name for the instance id: an instance's identity is minted by the engine per process
714
- * ({@link EngineSignal}`.instanceId`), and env cannot carry it (see there).
534
+ * ({@link InstanceHealth}`.instanceId`), and env cannot carry it (see there).
715
535
  */
716
536
  export declare const FLEET_GENERATION_ENV = "FLEET_GENERATION";
717
537
  /**
@@ -723,19 +543,19 @@ export declare const FLEET_GENERATION_ENV = "FLEET_GENERATION";
723
543
  * {@link ServingLeaseRequest} and {@link InstanceAnnouncement}; nothing in the engine's env does); the engine's own identity
724
544
  * scope is the one the renderer gave in this env; that the two are the same value is the renderer's obligation.
725
545
  * The engine never derives it from the token's format (a token is opaque to it, and a format guess would be a second source
726
- * that can disagree with the scope the center binds). Absent from the engine's env ⇒ the default scope, {@link GLOBAL_SCOPE} (`api/scopes`) —
727
- * the same default the center reads where nothing names a scope; this note does not restate the value. Like
546
+ * that can disagree with the scope web-admin binds). Absent from the engine's env ⇒ the default scope, {@link GLOBAL_SCOPE} (`api/scopes`) —
547
+ * the same default web-admin reads where nothing names a scope; this note does not restate the value. Like
728
548
  * {@link FLEET_GENERATION_ENV} it is a reserved worker env name (`WorkerSpec.env` / `secretEnv` cannot set it).
729
549
  */
730
550
  export declare const FLEET_SCOPE_ENV = "FLEET_SCOPE";
731
551
  /**
732
552
  * The serving lease — the ONE fence between a superseded generation and the traffic it must stop taking. A fleet-member
733
- * engine renews it with the center; the center answers per the lifecycle object it holds for that instance. Three constants
553
+ * engine renews it with web-admin; web-admin answers per the lifecycle object it holds for that instance. Three constants
734
554
  * fix the clock, all in ms:
735
555
  * - {@link SERVING_LEASE_TTL_DEFAULT_MS} — the lease length when the operator sets none (10 min).
736
556
  * - {@link SERVING_LEASE_TTL_FLOOR_MS} — the shortest lease there is: a configured TTL below it is treated as it (1 min),
737
557
  * the same way {@link DRAIN_GRACE_FLOOR_MS} protects a fat-fingered grace.
738
- * - {@link SERVING_LEASE_DRIFT_MARGIN_MS} — the center's clock-skew allowance: it adds this to a lease's recorded expiry
558
+ * - {@link SERVING_LEASE_DRIFT_MARGIN_MS} — web-admin's clock-skew allowance: it adds this to a lease's recorded expiry
739
559
  * before it counts that lease as over. It is DERIVED from {@link DEFAULT_HEARTBEAT_MS} (one cadence, one number), never a
740
560
  * second constant that could drift from it.
741
561
  */
@@ -747,177 +567,137 @@ export declare const SERVING_LEASE_DRIFT_MARGIN_MS = 30000;
747
567
  * {@link SERVING_LEASE_TTL_DEFAULT_MS}; a number below {@link SERVING_LEASE_TTL_FLOOR_MS} (zero and negatives included) ⇒ the
748
568
  * floor; otherwise the number, truncated to whole ms, with no ceiling. It is for the ISSUING side's configuration. A reply's
749
569
  * `ttlMs` is used exactly as granted and is never clamped upward — an engine that stretched a short grant to the floor would
750
- * hold the lease past what the center recorded, which is the one thing the fence exists to prevent.
570
+ * hold the lease past what web-admin recorded, which is the one thing the fence exists to prevent.
751
571
  */
752
572
  export declare function clampServingLeaseTtlMs(configuredMs: number | undefined): number;
753
573
  /**
754
- * Engine → center: "may this instance keep serving?" The identity triple names the instance exactly — a lease is never
574
+ * Engine → web-admin: "may this instance keep serving?" The identity triple names the instance exactly — a lease is never
755
575
  * asked for by worker name alone. `generation` is the env echo ({@link FLEET_GENERATION_ENV}); `instanceId` is the engine's
756
- * own per-process identity ({@link EngineSignal}`.instanceId`), so a restarted process is a NEW instance to the center.
576
+ * own per-process identity ({@link InstanceHealth}`.instanceId`), so a restarted process is a NEW instance to web-admin.
757
577
  * `scope` — the tenant scope the lease is asked in. A renewal is taken on a PER-WORKER token only — the credential binds
758
578
  * (scope, worker) — so the credential decides the scope and this field can only agree: absent = the scope the token binds; present
759
579
  * ⇒ it must equal that scope (a mismatch is refused, never rewritten either way). The shared token may not renew a lease at all
760
- * (the center answers 403). Only fleet members ask: an engine without a generation (the standalone form) has no lease and sends
580
+ * (web-admin answers 403). Only fleet members ask: an engine without a generation (the standalone form) has no lease and sends
761
581
  * nothing.
762
582
  */
763
583
  export declare const ServingLeaseRequest: z.ZodObject<{
764
584
  worker: z.ZodString;
765
585
  scope: z.ZodOptional<z.ZodString>;
766
- generation: z.ZodEffects<z.ZodString, string, string>;
586
+ generation: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
767
587
  instanceId: z.ZodString;
768
- }, "strip", z.ZodTypeAny, {
769
- instanceId: string;
770
- worker: string;
771
- generation: string;
772
- scope?: string | undefined;
773
- }, {
774
- instanceId: string;
775
- worker: string;
776
- generation: string;
777
- scope?: string | undefined;
778
- }>;
588
+ }, z.core.$strip>;
779
589
  export type ServingLeaseRequest = z.infer<typeof ServingLeaseRequest>;
780
590
  /**
781
591
  * Why a lease is refused — a CLOSED set of exactly two words, owned here:
782
592
  * - `superseded` — a newer generation of this worker has taken over; this instance is the old one.
783
- * - `retired` — the center has retired this instance (or the worker it belongs to).
593
+ * - `retired` — web-admin has retired this instance (or the worker it belongs to).
784
594
  * Only {@link ServingLeaseResponse}'s `denied` arm carries a reason; `unknown` has none, by shape.
785
595
  */
786
596
  export declare const SERVING_LEASE_DENIED_REASONS: readonly ["superseded", "retired"];
787
- export declare const ServingLeaseDeniedReason: z.ZodEnum<["superseded", "retired"]>;
597
+ export declare const ServingLeaseDeniedReason: z.ZodEnum<{
598
+ superseded: "superseded";
599
+ retired: "retired";
600
+ }>;
788
601
  export type ServingLeaseDeniedReason = z.infer<typeof ServingLeaseDeniedReason>;
789
602
  /**
790
- * Center → engine: the verdict, a CLOSED set of three words ({@link SERVING_LEASE_VERDICTS}) — the arms of one
603
+ * Web-admin → engine: the verdict, a CLOSED set of three words ({@link SERVING_LEASE_VERDICTS}) — the arms of one
791
604
  * discriminated union, so a reader that switches on `verdict` is told by the compiler when a word is added.
792
605
  * - `granted` — keep serving; `ttlMs` is how long the lease lasts, a DURATION, never a wall-clock instant: the engine counts
793
- * it from the instant it SENT the request, on its own monotonic clock (`expiresAt = sendAt + ttlMs`), and the center keeps
606
+ * it from the instant it SENT the request, on its own monotonic clock (`expiresAt = sendAt + ttlMs`), and web-admin keeps
794
607
  * its own expiry from its store time — the two sides never compare clocks, so no clock agreement is needed.
795
608
  * - `denied` — this instance must stop: `reason` is {@link ServingLeaseDeniedReason}. The ONLY arm that obliges an engine to
796
- * stop serving, and it is issued on POSITIVE evidence only: the center keeps, per (scope, worker), a persisted generation
609
+ * stop serving, and it is issued on POSITIVE evidence only: web-admin keeps, per (scope, worker), a persisted generation
797
610
  * floor that is never garbage-collected, and a request whose generation lies below it is `superseded`; `retired` likewise
798
- * rests on a record the center holds. A center that merely holds no such record does not deny — it answers `unknown`.
799
- * - `unknown` — the center holds no lifecycle object for this instance right now (restoring its store, migrating scopes, not
611
+ * rests on a record web-admin holds. A web-admin that merely holds no such record does not deny — it answers `unknown`.
612
+ * - `unknown` — web-admin holds no lifecycle object for this instance right now (restoring its store, migrating scopes, not
800
613
  * yet claimed). It says NOTHING about whether the instance should serve, so it is not a kind of `denied` and absence of the
801
614
  * object NEVER turns into a denial: it carries no reason, and an engine never drains on it. To the engine it is the same
802
- * case as an unreachable center.
803
- * This is the law for what a center SENDS. A reader does not apply it to `reason`: {@link readServingLeaseResponse} judges by
615
+ * case as an unreachable web-admin.
616
+ * This is the law for what a web-admin SENDS. A reader does not apply it to `reason`: {@link readServingLeaseResponse} judges by
804
617
  * the `verdict` key and keeps a `denied` a `denied` even when its reason is outside the set ({@link ServingLeaseReading}). A
805
618
  * reply whose `verdict` itself is outside the three words (or a `granted` with no valid `ttlMs`) is not a verdict at all and
806
- * reads as `undefined` — an unreachable center, never `denied`, never `granted`.
619
+ * reads as `undefined` — an unreachable web-admin, never `denied`, never `granted`.
807
620
  */
808
- export declare const ServingLeaseResponse: z.ZodDiscriminatedUnion<"verdict", [z.ZodObject<{
621
+ export declare const ServingLeaseResponse: z.ZodDiscriminatedUnion<[z.ZodObject<{
809
622
  verdict: z.ZodLiteral<"granted">;
810
623
  ttlMs: z.ZodNumber;
811
- }, "strip", z.ZodTypeAny, {
812
- verdict: "granted";
813
- ttlMs: number;
814
- }, {
815
- verdict: "granted";
816
- ttlMs: number;
817
- }>, z.ZodObject<{
624
+ }, z.core.$strip>, z.ZodObject<{
818
625
  verdict: z.ZodLiteral<"denied">;
819
- reason: z.ZodEnum<["superseded", "retired"]>;
820
- }, "strip", z.ZodTypeAny, {
821
- reason: "superseded" | "retired";
822
- verdict: "denied";
823
- }, {
824
- reason: "superseded" | "retired";
825
- verdict: "denied";
826
- }>, z.ZodObject<{
626
+ reason: z.ZodEnum<{
627
+ superseded: "superseded";
628
+ retired: "retired";
629
+ }>;
630
+ }, z.core.$strip>, z.ZodObject<{
827
631
  verdict: z.ZodLiteral<"unknown">;
828
- }, "strip", z.ZodTypeAny, {
829
- verdict: "unknown";
830
- }, {
831
- verdict: "unknown";
832
- }>]>;
632
+ }, z.core.$strip>], "verdict">;
833
633
  export type ServingLeaseResponse = z.infer<typeof ServingLeaseResponse>;
834
634
  /** The reason word a READER puts in place of a `denied` reason it cannot place (outside {@link SERVING_LEASE_DENIED_REASONS},
835
635
  * missing, not a string). Read-face only: a producer never sends it, and the strict {@link ServingLeaseResponse} refuses it. */
836
636
  export declare const SERVING_LEASE_UNKNOWN_REASON = "unknown_reason";
837
637
  /** The read face of {@link ServingLeaseResponse} — same three arms, with the `denied` arm tolerant about `reason`. */
838
- declare const ServingLeaseReadFace: z.ZodDiscriminatedUnion<"verdict", [z.ZodObject<{
638
+ declare const ServingLeaseReadFace: z.ZodDiscriminatedUnion<[z.ZodObject<{
839
639
  verdict: z.ZodLiteral<"granted">;
840
640
  ttlMs: z.ZodNumber;
841
- }, "strip", z.ZodTypeAny, {
842
- verdict: "granted";
843
- ttlMs: number;
844
- }, {
845
- verdict: "granted";
846
- ttlMs: number;
847
- }>, z.ZodObject<{
641
+ }, z.core.$strip>, z.ZodObject<{
848
642
  verdict: z.ZodLiteral<"denied">;
849
- reason: z.ZodEffects<z.ZodUnknown, "superseded" | "retired" | "unknown_reason", unknown>;
850
- }, "strip", z.ZodTypeAny, {
851
- reason: "superseded" | "retired" | "unknown_reason";
852
- verdict: "denied";
853
- }, {
854
- verdict: "denied";
855
- reason?: unknown;
856
- }>, z.ZodObject<{
643
+ reason: z.ZodPipe<z.ZodOptional<z.ZodUnknown>, z.ZodTransform<"superseded" | "retired" | "unknown_reason", unknown>>;
644
+ }, z.core.$strip>, z.ZodObject<{
857
645
  verdict: z.ZodLiteral<"unknown">;
858
- }, "strip", z.ZodTypeAny, {
859
- verdict: "unknown";
860
- }, {
861
- verdict: "unknown";
862
- }>]>;
646
+ }, z.core.$strip>], "verdict">;
863
647
  /** The verdict words as a runtime list. `satisfies` bites a word the union does not have; the converse (a union arm missing
864
648
  * from this list) is pinned by a test that reads the union's discriminators. */
865
649
  export declare const SERVING_LEASE_VERDICTS: readonly ["granted", "denied", "unknown"];
866
- /** Center side: the request body of a serving-lease renewal. Shape mismatch / non-object / throwing accessor ⇒ `undefined`,
650
+ /** Web-admin side: the request body of a serving-lease renewal. Shape mismatch / non-object / throwing accessor ⇒ `undefined`,
867
651
  * never throws (same guarded reader as every other read in this file). */
868
652
  export declare function readServingLeaseRequest(body: unknown): ServingLeaseRequest | undefined;
869
653
  /**
870
654
  * What {@link readServingLeaseResponse} returns: {@link ServingLeaseResponse} plus the one thing a reader adds — a `denied`
871
655
  * whose reason it could not place carries {@link SERVING_LEASE_UNKNOWN_REASON}. Two faces on purpose (the failure direction
872
- * must match the meaning): the strict wire law says what a center may SEND (a closed two-word reason set); the reader judges
873
- * by the `verdict` key alone, so a center that learns a third reason word cannot make an older engine read `denied` as
656
+ * must match the meaning): the strict wire law says what a web-admin may SEND (a closed two-word reason set); the reader judges
657
+ * by the `verdict` key alone, so a web-admin that learns a third reason word cannot make an older engine read `denied` as
874
658
  * `undefined` and keep serving. Branch on `verdict`; `reason` is for the log line.
875
659
  */
876
660
  export type ServingLeaseReading = z.output<typeof ServingLeaseReadFace>;
877
661
  /** Engine side: the reply to a renewal, judged by its `verdict` key: `granted` needs a valid `ttlMs`, `denied` is `denied`
878
662
  * whatever its `reason` (see {@link ServingLeaseReading}), `unknown` is `unknown`. A non-object, a throwing accessor, a
879
663
  * `verdict` outside the three words or a `granted` without a valid `ttlMs` ⇒ `undefined`, never throws — and `undefined`
880
- * is read like an unreachable center, never like `denied` and never like `granted`. */
664
+ * is read like an unreachable web-admin, never like `denied` and never like `granted`. */
881
665
  export declare function readServingLeaseResponse(body: unknown): ServingLeaseReading | undefined;
882
666
  /**
883
- * What the CENTER says it can do: capability bits an engine reads before it starts using a center-side endpoint.
884
- * - `servingLease` — the center answers serving-lease renewals ({@link ServingLeaseRequest} / {@link ServingLeaseResponse}).
667
+ * What web-admin says it can do: capability bits an engine reads before it starts using a web-admin-side endpoint.
668
+ * - `servingLease` — web-admin answers serving-lease renewals ({@link ServingLeaseRequest} / {@link ServingLeaseResponse}).
885
669
  *
886
670
  * A bit is `true` or absent — one spelling for "not supported" (there is no `false`). An absent bit — in a declared object, or
887
- * because the center declares nothing at all (an older center) — means the center does not support the lease, and the engine then
888
- * neither renews a lease nor is fenced by one: this is the compatibility gate that lets an executor ship ahead of the center
889
- * without pushing running engines into lease expiry. It is a gate, not a verdict — nothing in this shape says "the center refuses
671
+ * because web-admin declares nothing at all (an older web-admin) — means web-admin does not support the lease, and the engine then
672
+ * neither renews a lease nor is fenced by one: this is the compatibility gate that lets an executor ship ahead of web-admin
673
+ * without pushing running engines into lease expiry. It is a gate, not a verdict — nothing in this shape says "web-admin refuses
890
674
  * leases". Read a heartbeat reply with {@link readCapabilityReading} and start the lease client only on a `declared` reading whose
891
675
  * `capabilities.servingLease === true`.
892
- * Unknown bits are stripped (a newer center's extra bits never break an older reader); a known bit whose value is not `true` breaks
676
+ * Unknown bits are stripped (a newer web-admin's extra bits never break an older reader); a known bit whose value is not `true` breaks
893
677
  * the declaration — and a broken declaration is NOT an absent one: the reply reads as `unreadable`, which is not a reading (the engine
894
678
  * keeps the state it had; see {@link readCapabilityReading}).
895
679
  * It rides in ONE place: the heartbeat's 2xx reply ({@link FLEET_PATHS}`.instances`), under {@link HEARTBEAT_REPLY_CAPABILITIES_KEY}.
896
- * The center answers the bits per CALLER CREDENTIAL: under a per-worker token, by what the center supports; under the shared token
680
+ * Web-admin answers the bits per CALLER CREDENTIAL: under a per-worker token, by what web-admin supports; under the shared token
897
681
  * `servingLease` is always absent (the serving-lease endpoint takes per-worker tokens only, so announcing it there would only push
898
682
  * that caller into the unreachable arm).
899
683
  */
900
- export declare const CenterCapabilities: z.ZodObject<{
684
+ export declare const WebAdminCapabilities: z.ZodObject<{
901
685
  servingLease: z.ZodOptional<z.ZodLiteral<true>>;
902
- }, "strip", z.ZodTypeAny, {
903
- servingLease?: true | undefined;
904
- }, {
905
- servingLease?: true | undefined;
906
- }>;
907
- export type CenterCapabilities = z.infer<typeof CenterCapabilities>;
686
+ }, z.core.$strip>;
687
+ export type WebAdminCapabilities = z.infer<typeof WebAdminCapabilities>;
908
688
  /**
909
- * The key of the heartbeat's 2xx reply body under which the center puts its {@link CenterCapabilities} — the object's only carrier.
910
- * The center writes `{ …, [HEARTBEAT_REPLY_CAPABILITIES_KEY]: caps }`; the engine reads the whole reply with
689
+ * The key of the heartbeat's 2xx reply body under which web-admin puts its {@link WebAdminCapabilities} — the object's only carrier.
690
+ * Web-admin writes `{ …, [HEARTBEAT_REPLY_CAPABILITIES_KEY]: caps }`; the engine reads the whole reply with
911
691
  * `readCapabilityReading(reply)` — the key lookup lives in the reader, one carrier one reader — and only on a 2xx (a failed heartbeat
912
692
  * says nothing about the bits). Nested, not flat: the reply's own keys and the capability bits never share a namespace.
913
- * A reply without the key is an older center — no capability said (`undeclared`). A reply with the key present with a value that
693
+ * A reply without the key is an older web-admin — no capability said (`undeclared`). A reply with the key present with a value that
914
694
  * breaks the shape is NOT "without the key" — it is `unreadable`, and an unreadable reply says nothing: neither declared nor undeclared.
915
695
  */
916
696
  export declare const HEARTBEAT_REPLY_CAPABILITIES_KEY = "capabilities";
917
- /** What one heartbeat reply says about the center's capabilities — three readings of the reply, see {@link readCapabilityReading}. */
697
+ /** What one heartbeat reply says about web-admin's capabilities — three readings of the reply, see {@link readCapabilityReading}. */
918
698
  export type CapabilityReading = {
919
699
  kind: "declared";
920
- capabilities: CenterCapabilities;
700
+ capabilities: WebAdminCapabilities;
921
701
  } | {
922
702
  kind: "undeclared";
923
703
  } | {
@@ -925,16 +705,16 @@ export type CapabilityReading = {
925
705
  why: "not-an-object" | "invalid-capabilities";
926
706
  };
927
707
  /**
928
- * Engine side: what one heartbeat reply says about the center's capabilities. The input is the heartbeat's whole 2xx reply body
708
+ * Engine side: what one heartbeat reply says about web-admin's capabilities. The input is the heartbeat's whole 2xx reply body
929
709
  * (the key lookup lives here — one carrier, one reader), the output one of three readings:
930
- * - `declared` — the key ({@link HEARTBEAT_REPLY_CAPABILITIES_KEY}) is present and its value passes {@link CenterCapabilities};
710
+ * - `declared` — the key ({@link HEARTBEAT_REPLY_CAPABILITIES_KEY}) is present and its value passes {@link WebAdminCapabilities};
931
711
  * `capabilities` is the parsed object (unknown bits stripped, an absent bit stays absent).
932
- * - `undeclared` — the reply is an object and the key is absent: an older center, which has said nothing about capabilities.
712
+ * - `undeclared` — the reply is an object and the key is absent: an older web-admin, which has said nothing about capabilities.
933
713
  * (`undefined` as the key's value is what JSON cannot carry; it reads as the key being absent.)
934
714
  * - `unreadable` — the reply is not an object (`why: "not-an-object"`), or the key is present but its value is not a
935
- * {@link CenterCapabilities} (`why: "invalid-capabilities"`; an accessor that throws reads the same way).
715
+ * {@link WebAdminCapabilities} (`why: "invalid-capabilities"`; an accessor that throws reads the same way).
936
716
  * Only `declared` and `undeclared` are readings. `unreadable` is not a reading: on the fence axis a malformed declaration must not
937
- * read as "the center declared nothing", so the engine acts on it as on no reply at all — it keeps the state it last had (before
717
+ * read as "web-admin declared nothing", so the engine acts on it as on no reply at all — it keeps the state it last had (before
938
718
  * any reading: no lease) and leaves its clocks, the lease expiry and the outage allowance, as they were. Start the lease client only
939
719
  * on `declared` with `capabilities.servingLease === true`. Never throws; judged by the same one guarded body judgement as every
940
720
  * other reader here.
@@ -942,8 +722,8 @@ export type CapabilityReading = {
942
722
  export declare function readCapabilityReading(reply: unknown): CapabilityReading;
943
723
  /**
944
724
  * The drain endpoint's request: "put this instance into draining, by this deadline". One persisted action, one validation,
945
- * whether the center calls directly or an executor retries it. Two lanes, one shape: on the Docker lane (and for a direct
946
- * call from the center) this HTTP request is how an instance is drained; on the Kubernetes lane no per-pod HTTP call is made
725
+ * whether web-admin calls directly or an executor retries it. Two lanes, one shape: on the Docker lane (and for a direct
726
+ * call from web-admin) this HTTP request is how an instance is drained; on the Kubernetes lane no per-pod HTTP call is made
947
727
  * (per-pod addressing and RBAC make it the wrong tool) — an instance is drained by its serving lease being denied
948
728
  * ({@link ServingLeaseResponse}), after which the engine puts itself into draining.
949
729
  * - `actionId` — idempotency key: the same id again echoes the first answer ({@link DrainReceipt}`.state` =
@@ -951,42 +731,29 @@ export declare function readCapabilityReading(reply: unknown): CapabilityReading
951
731
  * - the identity — `scope?` / `worker` / `expectedGeneration?` / `instanceId?` — names WHICH instance the action is for. The
952
732
  * engine compares it field by field against its own, absent against absent: an engine that is not a fleet member has no
953
733
  * generation, so a request with no `expectedGeneration` is the standalone form, not a wildcard; `instanceId`, when given,
954
- * is the engine's own per-process identity ({@link EngineSignal}`.instanceId`). A mismatch is the endpoint's refusal, not
734
+ * is the engine's own per-process identity ({@link InstanceHealth}`.instanceId`). A mismatch is the endpoint's refusal, not
955
735
  * this shape's: this schema only says what a well-formed request looks like.
956
736
  * - `deadlineAt` — epoch ms by which the engine stops on its own.
957
- * - `term` — the claim term the sending executor holds for this action (center-issued, opaque); absent where no executor
737
+ * - `term` — the claim term the sending executor holds for this action (web-admin-issued, opaque); absent where no executor
958
738
  * sits in between (a direct call, a hand-issued action).
959
739
  */
960
740
  export declare const DrainRequest: z.ZodObject<{
961
741
  actionId: z.ZodString;
962
742
  scope: z.ZodOptional<z.ZodString>;
963
743
  worker: z.ZodString;
964
- expectedGeneration: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
744
+ expectedGeneration: z.ZodOptional<z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>;
965
745
  instanceId: z.ZodOptional<z.ZodString>;
966
746
  deadlineAt: z.ZodNumber;
967
747
  term: z.ZodOptional<z.ZodString>;
968
- }, "strip", z.ZodTypeAny, {
969
- worker: string;
970
- actionId: string;
971
- deadlineAt: number;
972
- instanceId?: string | undefined;
973
- scope?: string | undefined;
974
- expectedGeneration?: string | undefined;
975
- term?: string | undefined;
976
- }, {
977
- worker: string;
978
- actionId: string;
979
- deadlineAt: number;
980
- instanceId?: string | undefined;
981
- scope?: string | undefined;
982
- expectedGeneration?: string | undefined;
983
- term?: string | undefined;
984
- }>;
748
+ }, z.core.$strip>;
985
749
  export type DrainRequest = z.infer<typeof DrainRequest>;
986
750
  /** What a drain request leaves the engine in: `draining` — this call put it into draining; `already_draining` — it already was
987
751
  * (the same action repeated), and the receipt reports the first call's facts. */
988
752
  export declare const DRAIN_RECEIPT_STATES: readonly ["draining", "already_draining"];
989
- export declare const DrainReceiptState: z.ZodEnum<["draining", "already_draining"]>;
753
+ export declare const DrainReceiptState: z.ZodEnum<{
754
+ draining: "draining";
755
+ already_draining: "already_draining";
756
+ }>;
990
757
  export type DrainReceiptState = z.infer<typeof DrainReceiptState>;
991
758
  /** The drain endpoint's answer: the engine's draining fact ({@link EngineDraining} — the same object {@link EngineSignal}
992
759
  * carries as `draining`, extended, not copied) plus how this call found the engine. */
@@ -994,19 +761,11 @@ export declare const DrainReceipt: z.ZodObject<{
994
761
  actionId: z.ZodString;
995
762
  since: z.ZodNumber;
996
763
  deadlineAt: z.ZodNumber;
997
- } & {
998
- state: z.ZodEnum<["draining", "already_draining"]>;
999
- }, "strip", z.ZodTypeAny, {
1000
- since: number;
1001
- actionId: string;
1002
- deadlineAt: number;
1003
- state: "draining" | "already_draining";
1004
- }, {
1005
- since: number;
1006
- actionId: string;
1007
- deadlineAt: number;
1008
- state: "draining" | "already_draining";
1009
- }>;
764
+ state: z.ZodEnum<{
765
+ draining: "draining";
766
+ already_draining: "already_draining";
767
+ }>;
768
+ }, z.core.$strip>;
1010
769
  export type DrainReceipt = z.infer<typeof DrainReceipt>;
1011
770
  /** Engine side: the request body of the drain endpoint. Shape mismatch / non-object / throwing accessor ⇒ `undefined`, never throws. */
1012
771
  export declare function readDrainRequest(body: unknown): DrainRequest | undefined;
@@ -1014,34 +773,20 @@ export declare function readDrainRequest(body: unknown): DrainRequest | undefine
1014
773
  export declare function readDrainReceipt(body: unknown): DrainReceipt | undefined;
1015
774
  export declare const DISPATCH_STRATEGIES: readonly ["round-robin", "least-inflight", "consistent-hash"];
1016
775
  export type DispatchStrategy = (typeof DISPATCH_STRATEGIES)[number];
1017
- /** Per-worker dispatch policy (center-configured; the gateway is OPTIONAL — D3: TOC/self-maintained TOB go
776
+ /** Per-worker dispatch policy (web-admin-configured; the gateway is OPTIONAL — D3: TOC/self-maintained TOB go
1018
777
  * direct, sema-managed fleets route through /api/dispatch). Strategy is an enum on purpose: a new LB
1019
778
  * algorithm is a new value, not a new skeleton. */
1020
779
  export declare const DispatchPolicy: z.ZodObject<{
1021
- strategy: z.ZodDefault<z.ZodEnum<["round-robin", "least-inflight", "consistent-hash"]>>;
1022
- /** live-steer legs must return to their instance (cross-replica live-steer is 409 by design) — when true,
1023
- * a request carrying an affinity key pins via consistent hash regardless of `strategy`. If the pinned
1024
- * instance dies, the run resumes elsewhere via resumeFromRunId (affinity avoids the gap; resume bounds it). */
780
+ strategy: z.ZodDefault<z.ZodEnum<{
781
+ "round-robin": "round-robin";
782
+ "least-inflight": "least-inflight";
783
+ "consistent-hash": "consistent-hash";
784
+ }>>;
1025
785
  sessionAffinity: z.ZodDefault<z.ZodBoolean>;
1026
- /** gateway-level concurrency gate (per worker) */
1027
786
  maxInflight: z.ZodOptional<z.ZodNumber>;
1028
- /** per-actor fairness gate */
1029
787
  perActorMaxInflight: z.ZodOptional<z.ZodNumber>;
1030
- /** cost clamp applied to submissions passing the gateway */
1031
788
  maxCostUsd: z.ZodOptional<z.ZodNumber>;
1032
- }, "strip", z.ZodTypeAny, {
1033
- strategy: "round-robin" | "least-inflight" | "consistent-hash";
1034
- sessionAffinity: boolean;
1035
- maxInflight?: number | undefined;
1036
- perActorMaxInflight?: number | undefined;
1037
- maxCostUsd?: number | undefined;
1038
- }, {
1039
- strategy?: "round-robin" | "least-inflight" | "consistent-hash" | undefined;
1040
- sessionAffinity?: boolean | undefined;
1041
- maxInflight?: number | undefined;
1042
- perActorMaxInflight?: number | undefined;
1043
- maxCostUsd?: number | undefined;
1044
- }>;
789
+ }, z.core.$strip>;
1045
790
  export type DispatchPolicy = z.infer<typeof DispatchPolicy>;
1046
791
  /** 🔴 Submit idempotency — the precondition that makes failover re-routing SAFE: a new-run submission MUST
1047
792
  * carry the client-minted durable taskId, and the server dedupes on it. Without this, "landed but the
@@ -1066,8 +811,8 @@ export declare function pickInstance(policy: DispatchPolicy, candidates: Dispatc
1066
811
  cursor?: number;
1067
812
  affinityKey?: string;
1068
813
  }): DispatchCandidate | null;
1069
- /** A pre-authorized slice of a principal's global budget, granted by center to ONE worker: the worker deducts
1070
- * locally (no per-call round-trip), renews when running low, and center reconciles reported consumption
814
+ /** A pre-authorized slice of a principal's global budget, granted by web-admin to ONE worker: the worker deducts
815
+ * locally (no per-call round-trip), renews when running low, and web-admin reconciles reported consumption
1071
816
  * against the grant after the fact — the roaming/CDN pattern.
1072
817
  *
1073
818
  * 0.6.1 双轴 slice(EXPERT-REDESIGN §4-2/§4-6, service 回执"发布即接单"):slice = **{weightedTokens,
@@ -1081,59 +826,17 @@ export declare const QuotaLease: z.ZodObject<{
1081
826
  leaseId: z.ZodString;
1082
827
  principal: z.ZodString;
1083
828
  worker: z.ZodString;
1084
- /** granted dimensions — either or both; a dimension absent = not governed by this lease.
1085
- * `weightedTokens` = 加权 tokens(配额轴)。 */
1086
829
  grant: z.ZodObject<{
1087
830
  weightedTokens: z.ZodOptional<z.ZodNumber>;
1088
831
  costMicroUsd: z.ZodOptional<z.ZodNumber>;
1089
- }, "strip", z.ZodTypeAny, {
1090
- weightedTokens?: number | undefined;
1091
- costMicroUsd?: number | undefined;
1092
- }, {
1093
- weightedTokens?: number | undefined;
1094
- costMicroUsd?: number | undefined;
1095
- }>;
1096
- consumed: z.ZodDefault<z.ZodObject<{
832
+ }, z.core.$strip>;
833
+ consumed: z.ZodPrefault<z.ZodObject<{
1097
834
  weightedTokens: z.ZodDefault<z.ZodNumber>;
1098
835
  costMicroUsd: z.ZodDefault<z.ZodNumber>;
1099
- }, "strip", z.ZodTypeAny, {
1100
- weightedTokens: number;
1101
- costMicroUsd: number;
1102
- }, {
1103
- weightedTokens?: number | undefined;
1104
- costMicroUsd?: number | undefined;
1105
- }>>;
836
+ }, z.core.$strip>>;
1106
837
  issuedMs: z.ZodNumber;
1107
838
  expiresMs: z.ZodNumber;
1108
- }, "strip", z.ZodTypeAny, {
1109
- worker: string;
1110
- leaseId: string;
1111
- principal: string;
1112
- grant: {
1113
- weightedTokens?: number | undefined;
1114
- costMicroUsd?: number | undefined;
1115
- };
1116
- consumed: {
1117
- weightedTokens: number;
1118
- costMicroUsd: number;
1119
- };
1120
- issuedMs: number;
1121
- expiresMs: number;
1122
- }, {
1123
- worker: string;
1124
- leaseId: string;
1125
- principal: string;
1126
- grant: {
1127
- weightedTokens?: number | undefined;
1128
- costMicroUsd?: number | undefined;
1129
- };
1130
- issuedMs: number;
1131
- expiresMs: number;
1132
- consumed?: {
1133
- weightedTokens?: number | undefined;
1134
- costMicroUsd?: number | undefined;
1135
- } | undefined;
1136
- }>;
839
+ }, z.core.$strip>;
1137
840
  export type QuotaLease = z.infer<typeof QuotaLease>;
1138
841
  /** Remaining per granted dimension; null = the dimension is not governed by this lease. Never negative. */
1139
842
  export declare function leaseRemaining(l: QuotaLease): {
@@ -1149,7 +852,7 @@ export declare function leaseExhausted(l: QuotaLease, nowMs: number): boolean;
1149
852
  export declare function shouldRenewLease(l: QuotaLease, nowMs: number, opts?: {
1150
853
  renewAtFraction?: number;
1151
854
  }): boolean;
1152
- /** Reconciliation (center side): consumption is MONOTONE — the reconciled row takes the max of what center
855
+ /** Reconciliation (web-admin side): consumption is MONOTONE — the reconciled row takes the max of what web-admin
1153
856
  * believed and what the worker reported (a lost report can only under-count, never roll back).
1154
857
  * 0.7.1:legacy `tokens` report alias removed with the QuotaLease shim(同一收账点,service 回执). */
1155
858
  export declare function reconcileLease(l: QuotaLease, reported: {
@@ -1163,43 +866,15 @@ export declare function reconcileLease(l: QuotaLease, reported: {
1163
866
  export declare const UsageEntry: z.ZodObject<{
1164
867
  principal: z.ZodString;
1165
868
  model: z.ZodString;
1166
- /** 归一化总输入 token(含 cache 读/写),非未命中分量——见类型头注。 */
1167
869
  inputTokens: z.ZodNumber;
1168
870
  outputTokens: z.ZodNumber;
1169
- /** 0.11.0 起 optional(RB-368 生态半场,跨仓记录在案):unpriced 部署(模型无价目)对 cost
1170
- * 只有「未知」这个业务态,required 逼 worker 编 0 = center 账面一个**精确的谎**。缺席=未知;
1171
- * 聚合面以 {@link AggregatedPrincipalUsage.costUnknown} 补偿(已知和=显式下界)。写了键 = producer
1172
- * 声称自己知道(0 就是真 0)。 */
1173
871
  costMicroUsd: z.ZodOptional<z.ZodNumber>;
1174
872
  runs: z.ZodOptional<z.ZodNumber>;
1175
- /** 加权 tokens(配额轴计账值,EXPERT-REDESIGN §4-1):=(input+output)×记账时的 quotaWeight,
1176
- * **weight-at-burn 持久化**——倍率 publish 只影响此后记账,不回算窗口内历史(余量/恢复时间不跳变)。
1177
- * 0.6.0 additive optional:旧 worker 不报 → 聚合按 quotaWeight=1 兜底折算。 */
1178
873
  weightedTokens: z.ZodOptional<z.ZodNumber>;
1179
- /** 记账时固化的该模型 quotaWeight(审计口径,与 weightedTokens 同时点)——lease 扣减与 registry 聚合两
1180
- * 路径按同一时点折算(同口径,§11-1)。 */
1181
874
  quotaWeightAtUse: z.ZodOptional<z.ZodNumber>;
1182
- }, "strip", z.ZodTypeAny, {
1183
- principal: string;
1184
- model: string;
1185
- inputTokens: number;
1186
- outputTokens: number;
1187
- weightedTokens?: number | undefined;
1188
- costMicroUsd?: number | undefined;
1189
- runs?: number | undefined;
1190
- quotaWeightAtUse?: number | undefined;
1191
- }, {
1192
- principal: string;
1193
- model: string;
1194
- inputTokens: number;
1195
- outputTokens: number;
1196
- weightedTokens?: number | undefined;
1197
- costMicroUsd?: number | undefined;
1198
- runs?: number | undefined;
1199
- quotaWeightAtUse?: number | undefined;
1200
- }>;
875
+ }, z.core.$strip>;
1201
876
  export type UsageEntry = z.infer<typeof UsageEntry>;
1202
- /** Periodic batch (worker → center POST). Windows are half-open [start, end) so adjacent batches never
877
+ /** Periodic batch (worker → web-admin POST). Windows are half-open [start, end) so adjacent batches never
1203
878
  * double-count a boundary instant. */
1204
879
  export declare const UsageReport: z.ZodObject<{
1205
880
  worker: z.ZodString;
@@ -1209,72 +884,14 @@ export declare const UsageReport: z.ZodObject<{
1209
884
  entries: z.ZodArray<z.ZodObject<{
1210
885
  principal: z.ZodString;
1211
886
  model: z.ZodString;
1212
- /** 归一化总输入 token(含 cache 读/写),非未命中分量——见类型头注。 */
1213
887
  inputTokens: z.ZodNumber;
1214
888
  outputTokens: z.ZodNumber;
1215
- /** 0.11.0 起 optional(RB-368 生态半场,跨仓记录在案):unpriced 部署(模型无价目)对 cost
1216
- * 只有「未知」这个业务态,required 逼 worker 编 0 = center 账面一个**精确的谎**。缺席=未知;
1217
- * 聚合面以 {@link AggregatedPrincipalUsage.costUnknown} 补偿(已知和=显式下界)。写了键 = producer
1218
- * 声称自己知道(0 就是真 0)。 */
1219
889
  costMicroUsd: z.ZodOptional<z.ZodNumber>;
1220
890
  runs: z.ZodOptional<z.ZodNumber>;
1221
- /** 加权 tokens(配额轴计账值,EXPERT-REDESIGN §4-1):=(input+output)×记账时的 quotaWeight,
1222
- * **weight-at-burn 持久化**——倍率 publish 只影响此后记账,不回算窗口内历史(余量/恢复时间不跳变)。
1223
- * 0.6.0 additive optional:旧 worker 不报 → 聚合按 quotaWeight=1 兜底折算。 */
1224
891
  weightedTokens: z.ZodOptional<z.ZodNumber>;
1225
- /** 记账时固化的该模型 quotaWeight(审计口径,与 weightedTokens 同时点)——lease 扣减与 registry 聚合两
1226
- * 路径按同一时点折算(同口径,§11-1)。 */
1227
892
  quotaWeightAtUse: z.ZodOptional<z.ZodNumber>;
1228
- }, "strip", z.ZodTypeAny, {
1229
- principal: string;
1230
- model: string;
1231
- inputTokens: number;
1232
- outputTokens: number;
1233
- weightedTokens?: number | undefined;
1234
- costMicroUsd?: number | undefined;
1235
- runs?: number | undefined;
1236
- quotaWeightAtUse?: number | undefined;
1237
- }, {
1238
- principal: string;
1239
- model: string;
1240
- inputTokens: number;
1241
- outputTokens: number;
1242
- weightedTokens?: number | undefined;
1243
- costMicroUsd?: number | undefined;
1244
- runs?: number | undefined;
1245
- quotaWeightAtUse?: number | undefined;
1246
- }>, "many">;
1247
- }, "strip", z.ZodTypeAny, {
1248
- entries: {
1249
- principal: string;
1250
- model: string;
1251
- inputTokens: number;
1252
- outputTokens: number;
1253
- weightedTokens?: number | undefined;
1254
- costMicroUsd?: number | undefined;
1255
- runs?: number | undefined;
1256
- quotaWeightAtUse?: number | undefined;
1257
- }[];
1258
- instanceId: string;
1259
- worker: string;
1260
- windowStartMs: number;
1261
- windowEndMs: number;
1262
- }, {
1263
- entries: {
1264
- principal: string;
1265
- model: string;
1266
- inputTokens: number;
1267
- outputTokens: number;
1268
- weightedTokens?: number | undefined;
1269
- costMicroUsd?: number | undefined;
1270
- runs?: number | undefined;
1271
- quotaWeightAtUse?: number | undefined;
1272
- }[];
1273
- instanceId: string;
1274
- worker: string;
1275
- windowStartMs: number;
1276
- windowEndMs: number;
1277
- }>;
893
+ }, z.core.$strip>>;
894
+ }, z.core.$strip>;
1278
895
  export type UsageReport = z.infer<typeof UsageReport>;
1279
896
  /** 额度清零事件(EXPERT-REDESIGN §4-4,契约随 E1 冻结、E4 消费):申请刷新获批即写一条;5h/周双窗聚合
1280
897
  * **只计最后一次 reset 之后**的 usage 报文(usage_report 是计费审计事实,全量留存,绝不删)。拒绝逻辑/
@@ -1282,25 +899,10 @@ export type UsageReport = z.infer<typeof UsageReport>;
1282
899
  export declare const QuotaResetEvent: z.ZodObject<{
1283
900
  id: z.ZodString;
1284
901
  principal: z.ZodString;
1285
- /** 清零生效时刻(ISO)——双窗聚合的下边界。 */
1286
902
  reset_at: z.ZodString;
1287
- /** 批准人(console username)。 */
1288
903
  decided_by: z.ZodString;
1289
- /** 关联的 quota_refresh_request id;admin 直接清零(无申请)时可缺。 */
1290
904
  request_id: z.ZodOptional<z.ZodString>;
1291
- }, "strip", z.ZodTypeAny, {
1292
- principal: string;
1293
- id: string;
1294
- reset_at: string;
1295
- decided_by: string;
1296
- request_id?: string | undefined;
1297
- }, {
1298
- principal: string;
1299
- id: string;
1300
- reset_at: string;
1301
- decided_by: string;
1302
- request_id?: string | undefined;
1303
- }>;
905
+ }, z.core.$strip>;
1304
906
  export type QuotaResetEvent = z.infer<typeof QuotaResetEvent>;
1305
907
  export interface AggregatedPrincipalUsage {
1306
908
  inputTokens: number;
@@ -1327,7 +929,7 @@ export interface AggregatedPrincipalUsage {
1327
929
  weightedTokens: number;
1328
930
  }>;
1329
931
  }
1330
- /** Center-side fold: per-principal totals ACROSS workers/instances (the "one user, many workers, one bill"
932
+ /** Web-admin-side fold: per-principal totals ACROSS workers/instances (the "one user, many workers, one bill"
1331
933
  * view). Pure — storage/dedup of replayed batches is the caller's concern (key batches by
1332
934
  * worker+instanceId+windowStartMs). */
1333
935
  export declare function aggregateUsage(reports: UsageReport[]): Record<string, AggregatedPrincipalUsage>;