@sema-agent/server 7.99.0 → 7.101.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 (174) hide show
  1. package/MIGRATION.md +35 -1
  2. package/README.md +12 -1
  3. package/README.zh-CN.md +9 -1
  4. package/USAGE.md +150 -56
  5. package/dist/approval-ask-machine.d.ts +10 -0
  6. package/dist/approval-ask-machine.js +3 -0
  7. package/dist/approval-card.d.ts +86 -1
  8. package/dist/approval-card.js +42 -8
  9. package/dist/approval-policy-settlement.d.ts +31 -0
  10. package/dist/approval-policy-settlement.js +16 -0
  11. package/dist/approval-reconciler.d.ts +8 -1
  12. package/dist/approval-reconciler.js +5 -4
  13. package/dist/approval.d.ts +44 -20
  14. package/dist/approval.js +14 -6
  15. package/dist/boot/config-center.d.ts +16 -8
  16. package/dist/boot/config-center.js +114 -90
  17. package/dist/boot/execution-env.d.ts +1 -2
  18. package/dist/boot/execution-env.js +21 -3
  19. package/dist/boot/leader.js +12 -9
  20. package/dist/boot/memory-consolidation.d.ts +38 -0
  21. package/dist/boot/memory-consolidation.js +35 -0
  22. package/dist/boot/parked-revive-gate.js +1 -0
  23. package/dist/boot/reapers.js +1 -0
  24. package/dist/boot/resolve-spec.d.ts +0 -1
  25. package/dist/boot/resolve-spec.js +28 -10
  26. package/dist/boot/runner-deps.d.ts +2 -2
  27. package/dist/boot/runner-deps.js +9 -3
  28. package/dist/boot/stage-02-registry-pull.js +9 -0
  29. package/dist/boot/stage-05-execution-env.d.ts +1 -1
  30. package/dist/boot/stage-06-runners.d.ts +2 -2
  31. package/dist/boot/stage-06-runners.js +3 -3
  32. package/dist/boot/stage-07-capability-layer.d.ts +2 -3
  33. package/dist/boot/stage-07-capability-layer.js +6 -6
  34. package/dist/boot/stage-08-reapers.d.ts +3 -4
  35. package/dist/boot/stage-08-reapers.js +2 -2
  36. package/dist/boot/stage-09-leader.d.ts +2 -3
  37. package/dist/boot/stage-10-http-server.d.ts +2 -3
  38. package/dist/boot/stage-10-http-server.js +2 -2
  39. package/dist/boot/stores.js +4 -0
  40. package/dist/capabilities/center-plugins.d.ts +14 -2
  41. package/dist/capabilities/center-plugins.js +13 -5
  42. package/dist/capabilities/hands-lane.js +2 -1
  43. package/dist/capabilities/scenarios.js +18 -5
  44. package/dist/capabilities/tool-defer.d.ts +2 -2
  45. package/dist/config-catalog.d.ts +2 -2
  46. package/dist/config-catalog.js +16 -15
  47. package/dist/config-center/apply-effective.d.ts +59 -39
  48. package/dist/config-center/apply-effective.js +231 -120
  49. package/dist/config-center/apply-ledger.d.ts +45 -16
  50. package/dist/config-center/apply-ledger.js +28 -18
  51. package/dist/config-center/facade.d.ts +12 -6
  52. package/dist/config-center/facade.js +2 -2
  53. package/dist/config-center/hot-keys-registry.d.ts +11 -4
  54. package/dist/config-center/hot-keys-registry.js +11 -7
  55. package/dist/config-center/http-client.d.ts +4 -1
  56. package/dist/config-center/http-client.js +15 -10
  57. package/dist/config-center/read-warnings.d.ts +115 -6
  58. package/dist/config-center/read-warnings.js +115 -5
  59. package/dist/config-center/restart-signal.d.ts +21 -14
  60. package/dist/config-center/restart-signal.js +16 -22
  61. package/dist/config-center/types.d.ts +9 -3
  62. package/dist/config-invariants.d.ts +2 -2
  63. package/dist/config-invariants.js +15 -0
  64. package/dist/config-provider.d.ts +4 -0
  65. package/dist/config-provider.js +64 -9
  66. package/dist/config-types.d.ts +57 -13
  67. package/dist/config.js +87 -22
  68. package/dist/cross-session-settings.js +1 -1
  69. package/dist/deployment-governance.d.ts +45 -12
  70. package/dist/deployment-governance.js +37 -9
  71. package/dist/env-name-allowlist-knobs.d.ts +37 -0
  72. package/dist/env-name-allowlist-knobs.js +24 -0
  73. package/dist/fleet-client.d.ts +2 -1
  74. package/dist/hooks/hook-llm.js +13 -4
  75. package/dist/host-lsp-manager.d.ts +41 -0
  76. package/dist/host-lsp-manager.js +15 -0
  77. package/dist/http/active-run-conflict.d.ts +2 -12
  78. package/dist/http/active-run-conflict.js +1 -6
  79. package/dist/http/admission.js +30 -7
  80. package/dist/http/memory-store-refusal-reply.d.ts +24 -0
  81. package/dist/http/memory-store-refusal-reply.js +10 -0
  82. package/dist/http/resume-legs.d.ts +1 -1
  83. package/dist/http/resume-legs.js +14 -10
  84. package/dist/http/route-ctx.d.ts +2 -2
  85. package/dist/http/routes/approvals-assistant.d.ts +1 -1
  86. package/dist/http/routes/approvals-assistant.js +3 -2
  87. package/dist/http/routes/capabilities.js +3 -3
  88. package/dist/http/routes/memory-bundle.js +3 -0
  89. package/dist/http/routes/memory-compliance.js +3 -0
  90. package/dist/http/routes/memory-origin.js +3 -0
  91. package/dist/http/routes/sessions.js +7 -0
  92. package/dist/http/routes/side-query.js +10 -4
  93. package/dist/http/routes/tasks.js +7 -6
  94. package/dist/http/server.d.ts +6 -5
  95. package/dist/http/wire-types.d.ts +6 -3
  96. package/dist/instruction-source-notice.d.ts +97 -0
  97. package/dist/instruction-source-notice.js +78 -0
  98. package/dist/leader/wire.d.ts +20 -12
  99. package/dist/leader/wire.js +7 -6
  100. package/dist/memory-layer-legacy-lock.d.ts +14 -0
  101. package/dist/memory-layer-legacy-lock.js +74 -0
  102. package/dist/memory-store-refusal.d.ts +37 -0
  103. package/dist/memory-store-refusal.js +14 -0
  104. package/dist/model-entry-refusal.d.ts +130 -0
  105. package/dist/model-entry-refusal.js +157 -0
  106. package/dist/model-provider.d.ts +9 -3
  107. package/dist/model-route-endpoint.d.ts +1 -1
  108. package/dist/model-select.d.ts +49 -4
  109. package/dist/model-select.js +48 -17
  110. package/dist/observability/corrupt-read-seat.d.ts +21 -4
  111. package/dist/observability/corrupt-read-seat.js +31 -0
  112. package/dist/observability/fail-open.d.ts +16 -4
  113. package/dist/observability/fail-open.js +16 -4
  114. package/dist/observability/metrics.js +1 -0
  115. package/dist/observability/run-terminal.js +1 -0
  116. package/dist/observability/secret-env-scrub.d.ts +27 -3
  117. package/dist/observability/secret-env-scrub.js +22 -6
  118. package/dist/orchestration/workflow-completion-inbox.d.ts +31 -23
  119. package/dist/orchestration/workflow-completion-inbox.js +8 -3
  120. package/dist/plugins/approval-ask-store-file.d.ts +20 -2
  121. package/dist/plugins/approval-ask-store-file.js +21 -3
  122. package/dist/plugins/approval-ask-store-memory.d.ts +2 -0
  123. package/dist/plugins/approval-ask-store-memory.js +39 -13
  124. package/dist/plugins/approval-ask-store-sql.d.ts +24 -5
  125. package/dist/plugins/approval-ask-store-sql.js +27 -3
  126. package/dist/plugins/caching-session-store.d.ts +6 -0
  127. package/dist/plugins/caching-session-store.js +6 -0
  128. package/dist/plugins/checkpoint-store-sql.d.ts +9 -3
  129. package/dist/plugins/checkpoint-store-sql.js +19 -2
  130. package/dist/plugins/local-checkpoint-store.js +2 -0
  131. package/dist/plugins/local-session-store.d.ts +20 -25
  132. package/dist/plugins/local-session-store.js +111 -64
  133. package/dist/plugins/mailbox-store-sql.d.ts +7 -5
  134. package/dist/plugins/mailbox-store-sql.js +6 -4
  135. package/dist/plugins/permission-rule-store-file.js +3 -2
  136. package/dist/plugins/pg-session-storage.d.ts +7 -0
  137. package/dist/plugins/pg-session-storage.js +19 -0
  138. package/dist/plugins/remote-env-host.d.ts +3 -1
  139. package/dist/plugins/remote-env-host.js +3 -6
  140. package/dist/plugins/sql-json-column.d.ts +16 -3
  141. package/dist/plugins/sql-json-column.js +15 -4
  142. package/dist/plugins/tidb-pool.js +5 -0
  143. package/dist/plugins/tidb-session-store.d.ts +13 -0
  144. package/dist/plugins/tidb-session-store.js +14 -0
  145. package/dist/plugins/web-search.d.ts +44 -23
  146. package/dist/plugins/web-search.js +161 -50
  147. package/dist/project-memory.d.ts +10 -0
  148. package/dist/project-memory.js +28 -14
  149. package/dist/run-local.d.ts +17 -15
  150. package/dist/run-local.js +119 -18
  151. package/dist/runs.js +6 -5
  152. package/dist/runtime-governance.d.ts +50 -3
  153. package/dist/runtime-governance.js +5 -0
  154. package/dist/sealed-key.d.ts +5 -2
  155. package/dist/server-secret-env.d.ts +26 -2
  156. package/dist/server-secret-env.js +9 -0
  157. package/dist/task-settings.d.ts +1 -1
  158. package/dist/tool-approval.d.ts +150 -28
  159. package/dist/tool-approval.js +150 -54
  160. package/dist/trace/core-keyset-guard.d.ts +30 -8
  161. package/dist/trace/engine-notice-wire.d.ts +27 -1
  162. package/dist/trace/engine-notice-wire.js +8 -0
  163. package/dist/trace/ledger-sink.js +2 -2
  164. package/dist/trace/project.d.ts +13 -0
  165. package/dist/trace/project.js +22 -5
  166. package/dist/trace/projection-drop.d.ts +2 -0
  167. package/dist/trace/projection-drop.js +6 -0
  168. package/dist/trace/sema-provenance.d.ts +4 -1
  169. package/dist/trace/sema-provenance.js +1 -1
  170. package/dist/trace/task-notification-facets.d.ts +65 -0
  171. package/dist/trace/task-notification-facets.js +31 -0
  172. package/dist/trace/wire-projection-faces.d.ts +3 -3
  173. package/dist/trace/wire-projection-faces.js +3 -3
  174. package/package.json +3 -3
@@ -18,10 +18,18 @@ import { createConfigProvider, raceBootFetch, BOOT_FETCH_DEFERRED } from "../con
18
18
  import { executionLaneCaps, executionLaneOf } from "../execution-lane-caps.js";
19
19
  import { createKeyResolver } from "../key-resolver.js";
20
20
  import { ensureSealedKeyStore, reportExecutionPublicKey } from "../sealed-key.js";
21
- import { applyEffective, applyCenterReadFace, mutateInPlace, logEffectiveDiff, applyCenterSkills, resolveMcpServers, resolveA2aPeers, restartReasons, modelPlaneChanged, planeHasActiveTiers, fetchPromptArtifact } from "../config-center/facade.js";
21
+ import { applyEffective, applyCenterReadFace, mutateInPlace, logEffectiveDiff, applyCenterSkills, resolveMcpServers, resolveA2aPeers, restartReasons, modelPlaneChanged, withModelPlaneOf, buildEnvOnlyModelPlane, fetchPromptArtifact } from "../config-center/facade.js";
22
22
  import { createMcpRevocationLedger, enabledMcpEntries } from "../config-center/mcp-revocation.js";
23
23
  import { SHA256_HEX_RE } from "../digest-form.js";
24
- import { createConfigApplyLedger } from "../config-center/apply-ledger.js";
24
+ import { createConfigApplyLedger, modelPlaneCommitted, refusedGroups } from "../config-center/apply-ledger.js";
25
+ function lkgReadNote(scope) {
26
+ switch (scope) {
27
+ case "whole":
28
+ return "booting from the persisted last-known-good (all restart-to-apply faces included) — the live pull continues in the background and reconciles on arrival";
29
+ case "model-plane":
30
+ return "the live candidate's model plane was refused at boot — the persisted last-known-good supplies the model plane only (catalog and the collab templates that reference it); every other group and every restart-to-apply face stays the live candidate's";
31
+ }
32
+ }
25
33
  export async function createConfigCenterRuntime(ctx) {
26
34
  const { config, logger, metrics, localRoot } = ctx;
27
35
  let ccEtag;
@@ -114,6 +122,18 @@ export async function createConfigCenterRuntime(ctx) {
114
122
  : undefined;
115
123
  const rosterGateArmed = isRosterGateArmed(cc);
116
124
  const modelReadyState = { ready: !rosterGateArmed };
125
+ const warnDroppedEntries = (r, phase) => {
126
+ for (const d of r.droppedEntries ?? []) {
127
+ logger.warn("config_entry_dropped", {
128
+ domain: d.domain,
129
+ entry: d.entry,
130
+ error: d.error,
131
+ version: r.effective.version,
132
+ phase,
133
+ note: "this one entry failed its domain schema and was dropped on its own — the rest of the candidate applies (per-entry tolerance); fix the named entry to bring it back",
134
+ });
135
+ }
136
+ };
117
137
  const markRosterLanded = (eff) => {
118
138
  if (!modelReadyState.ready && (eff.models?.models ?? []).some((m) => m.enabled !== false)) {
119
139
  modelReadyState.ready = true;
@@ -312,7 +332,7 @@ export async function createConfigCenterRuntime(ctx) {
312
332
  };
313
333
  if (configProvider) {
314
334
  const dryRun = cc?.dryRun ?? false;
315
- const bootFromLkg = async (why) => {
335
+ const bootFromLkg = async (why, scope) => {
316
336
  if (!lkgEnabled || dryRun)
317
337
  return null;
318
338
  const identity = currentIdentity();
@@ -344,7 +364,7 @@ export async function createConfigCenterRuntime(ctx) {
344
364
  logger.warn("config_lkg_unusable", { path: lkgPath, reason: "center credential identity changed while the LKG was being read — not used", note: "env fallback serves; the current identity's next pull re-establishes its own LKG" });
345
365
  return null;
346
366
  }
347
- logger.info("config_loaded_lkg", { path: lkgPath, savedAt: read.lkg.savedAt, why, note: "booting from the persisted last-known-good (all restart-to-apply faces included) — the live pull continues in the background and reconciles on arrival" });
367
+ logger.info("config_loaded_lkg", { path: lkgPath, savedAt: read.lkg.savedAt, why, scope, note: lkgReadNote(scope) });
348
368
  const lkgEffective = read.lkg.effective;
349
369
  candidateIdentity.set(lkgEffective, identity);
350
370
  bindValidator(read.lkg.etag, identity);
@@ -353,18 +373,31 @@ export async function createConfigCenterRuntime(ctx) {
353
373
  const bootApplyLkgInline = async (lkgR) => {
354
374
  const lkgGen = generationOf(lkgR.effective.version);
355
375
  applyLedger.seenTarget(lkgGen, lkgR.effective.version);
356
- applyEffective(config, lkgR.effective, logger, { sealedKeys, generation: lkgGen, report: (rep) => applyLedger.recordApply(rep) });
376
+ let lkgReport;
377
+ applyEffective(config, lkgR.effective, logger, {
378
+ leg: "boot",
379
+ sealedKeys,
380
+ generation: lkgGen,
381
+ report: (rep) => {
382
+ lkgReport = rep;
383
+ applyLedger.recordApply(rep);
384
+ },
385
+ });
357
386
  applyLedger.applied(lkgGen, lkgR.effective.version);
358
387
  await adoptCenterPrompts(lkgR.effective, "boot-lkg");
359
- markRosterLanded(lkgR.effective);
388
+ const lkgPlane = modelPlaneCommitted(lkgReport);
389
+ if (lkgPlane)
390
+ markRosterLanded(lkgR.effective);
360
391
  effective = lkgR.effective;
361
- appliedPlaneEff = lkgR.effective;
392
+ if (lkgPlane)
393
+ appliedPlaneEff = lkgR.effective;
362
394
  latestEffective = lkgR.effective;
363
395
  if (lkgR.etag !== undefined)
364
396
  ccEtag = lkgR.etag;
365
397
  const cfgModels = (lkgR.effective.models?.models ?? []).filter((m) => m.enabled !== false).length;
366
398
  logger.info("config_loaded", { source: "lkg", version: lkgR.effective.version, worker: cc?.worker ?? "(global)", models: cfgModels });
367
399
  };
400
+ let bootApplyPhase = false;
368
401
  try {
369
402
  const bootFetch = pullEffective(configProvider, undefined);
370
403
  const raced = await raceBootFetch(bootFetch, config.configBootFetchBudgetMs);
@@ -372,7 +405,7 @@ export async function createConfigCenterRuntime(ctx) {
372
405
  if (raced === BOOT_FETCH_DEFERRED) {
373
406
  bootConfigPending = bootFetch;
374
407
  bootFetch.catch(() => { });
375
- lkgFallback = await bootFromLkg("boot fetch deferred (budget exceeded)");
408
+ lkgFallback = await bootFromLkg("boot fetch deferred (budget exceeded)", "whole");
376
409
  lkgBooted = lkgFallback !== null;
377
410
  logger.warn("config_boot_fetch_deferred", {
378
411
  source: configProvider.kind,
@@ -394,11 +427,13 @@ export async function createConfigCenterRuntime(ctx) {
394
427
  }
395
428
  const r = raced === BOOT_FETCH_DEFERRED ? null : raced;
396
429
  if (r) {
430
+ bootApplyPhase = true;
397
431
  const bootPromptsRaw = r.effective.prompts;
398
432
  const bootPromptsOk = bootPromptsRaw === undefined || validatePromptsDomain(bootPromptsRaw).ok;
399
433
  let bootClean = (r.domainErrors ?? []).length === 0 && bootPromptsOk;
400
434
  for (const de of r.domainErrors ?? [])
401
435
  logger.warn("config_domain_invalid", { domain: de.domain, error: de.error, note: "tolerated at BOOT (corrupt file → schema defaults; dangling ref → reported as-is); the refresh path rejects such a candidate whole and keeps the LKG (§9.5-5)" });
436
+ warnDroppedEntries(r, "boot");
402
437
  if (dryRun) {
403
438
  logEffectiveDiff(config, r.effective, logger);
404
439
  if (bootClean)
@@ -409,6 +444,7 @@ export async function createConfigCenterRuntime(ctx) {
409
444
  applyLedger.seenTarget(bootGen, r.effective.version);
410
445
  let bootReport;
411
446
  applyEffective(config, r.effective, logger, {
447
+ leg: "boot",
412
448
  sealedKeys,
413
449
  generation: bootGen,
414
450
  report: (rep) => {
@@ -422,9 +458,23 @@ export async function createConfigCenterRuntime(ctx) {
422
458
  if (bootClean)
423
459
  ccEtag = r.etag;
424
460
  await adoptCenterPrompts(r.effective, "boot");
425
- markRosterLanded(r.effective);
426
- effective = r.effective;
427
- appliedPlaneEff = r.effective;
461
+ let bootPlaneEff = modelPlaneCommitted(bootReport) ? r.effective : undefined;
462
+ if (bootPlaneEff === undefined) {
463
+ const lkgPlane = await bootFromLkg("boot candidate's model plane was refused", "model-plane");
464
+ if (lkgPlane) {
465
+ let planeReport;
466
+ applyEffective(config, withModelPlaneOf(r.effective, lkgPlane.effective), logger, { leg: "boot", sealedKeys, generation: bootGen, report: (rep) => (planeReport = rep) });
467
+ if (modelPlaneCommitted(planeReport)) {
468
+ bootPlaneEff = lkgPlane.effective;
469
+ logger.warn("config_model_plane_from_lkg", { version: r.effective.version, lkgVersion: lkgPlane.effective.version, note: "the live candidate's model plane was refused at boot — serving the LKG's model plane (catalog and the collab templates that reference it) with the live candidate's other groups; the refresh cadence re-judges the candidate" });
470
+ }
471
+ }
472
+ }
473
+ if (bootPlaneEff !== undefined)
474
+ markRosterLanded(bootPlaneEff);
475
+ effective = bootPlaneEff === r.effective ? r.effective : withModelPlaneOf(r.effective, bootPlaneEff ?? buildEnvOnlyModelPlane());
476
+ if (bootPlaneEff !== undefined)
477
+ appliedPlaneEff = bootPlaneEff;
428
478
  if (bootClean)
429
479
  latestEffective = r.effective;
430
480
  if (bootClean && !lkgBooted)
@@ -434,23 +484,30 @@ export async function createConfigCenterRuntime(ctx) {
434
484
  logger.info("config_loaded", { source: configProvider.kind, version: r.effective.version, worker: cc?.worker ?? "(global)", models: cfgModels, ...cfgDir });
435
485
  if (configProvider.kind === "local" && cfgModels === 0) {
436
486
  const modelsDomainErr = (r.domainErrors ?? []).find((de) => de.domain === "models");
487
+ const modelsDropped = (r.droppedEntries ?? []).filter((d) => d.domain === "models");
437
488
  const totalModels = (r.effective.models?.models ?? []).length;
438
489
  logger.warn("config_local_no_models", {
439
490
  ...cfgDir,
440
491
  ...(modelsDomainErr ? { domainError: modelsDomainErr.error } : {}),
492
+ ...(modelsDropped.length > 0 ? { droppedEntries: modelsDropped.map((d) => d.entry) } : {}),
441
493
  hint: modelsDomainErr
442
494
  ? "config.d/models.json 在场但 models 域判形失败落 default(真因见本行 domainError)— 模型继续走 env 兜底"
443
- : totalModels > 0
444
- ? `config.d/models.json 有 ${totalModels} 条模型但全部 enabled:false — 模型继续走 env 兜底`
445
- : "config.d/models.json 空或 CONFIG_LOCAL_DIR 指错目录(选目录旋钮是 CONFIG_LOCAL_DIR,不是 LOCAL_DATA_ROOT)— 模型继续走 env 兜底",
495
+ : modelsDropped.length > 0 && totalModels === 0
496
+ ? "config.d/models.json 的条目全部被逐条丢弃(逐条真因见 config_entry_dropped)— 模型继续走 env 兜底"
497
+ : totalModels > 0
498
+ ? `config.d/models.json 有 ${totalModels} 条模型但全部 enabled:false — 模型继续走 env 兜底`
499
+ : "config.d/models.json 空或 CONFIG_LOCAL_DIR 指错目录(选目录旋钮是 CONFIG_LOCAL_DIR,不是 LOCAL_DATA_ROOT)— 模型继续走 env 兜底",
446
500
  });
447
501
  }
448
502
  }
449
503
  }
450
504
  }
451
505
  catch (err) {
452
- logger.warn("config_source_unreachable_using_env", { source: configProvider.kind, err: String(err) });
453
- const lkgFallback = await bootFromLkg(`boot fetch failed: ${String(err).slice(0, 120)}`);
506
+ if (bootApplyPhase)
507
+ logger.warn("config_apply_refused", { source: configProvider.kind, err: String(err), note: "the pulled candidate failed to apply at boot — falling back to the LKG / env; this is not a reachability failure" });
508
+ else
509
+ logger.warn("config_source_unreachable_using_env", { source: configProvider.kind, err: String(err) });
510
+ const lkgFallback = await bootFromLkg(`${bootApplyPhase ? "boot apply refused" : "boot fetch failed"}: ${String(err).slice(0, 120)}`, "whole");
454
511
  if (lkgFallback) {
455
512
  lkgBooted = true;
456
513
  try {
@@ -474,8 +531,10 @@ export async function createConfigCenterRuntime(ctx) {
474
531
  let keyResolver;
475
532
  const mcpRevocations = createMcpRevocationLedger((ev) => logger.info("mcp_revocation_ledger", { ...(ev.revoked.length > 0 ? { revoked: ev.revoked } : {}), ...(ev.restored.length > 0 ? { restored: ev.restored } : {}) }));
476
533
  let mcpRevocationWired = false;
477
- const restartCtx = () => ({
534
+ const restartCtx = (consolidationSeat) => ({
478
535
  ...(config.degrade?.reactive ? { reactiveDegradeTo: config.degrade.to } : {}),
536
+ pluginsAllowHosts: config.pluginsAllowHosts,
537
+ ...(consolidationSeat !== undefined ? { consolidationSeat } : {}),
479
538
  ...(readFaceEnvHeld.length > 0 ? { readFaceEnvHeld } : {}),
480
539
  ...(mcpRevocationWired && mcpRevocations.hasBaseline() ? { mcpRevocationLive: true } : {}),
481
540
  });
@@ -485,10 +544,6 @@ export async function createConfigCenterRuntime(ctx) {
485
544
  const { faceChanged } = applyCenterReadFace(config, eff, logger, { phase: "live", baseline: readFaceBaseline });
486
545
  if (!faceChanged)
487
546
  return;
488
- if (swap === undefined) {
489
- logger.warn("read_face_swap_unwired", { face: config.readFace ?? null, phase, note: "the center's read FACE changed but no Runner swap door was wired — the value landed in config while the engine keeps the seat it booted with" });
490
- return;
491
- }
492
547
  try {
493
548
  swap({ readFace: config.readFace });
494
549
  logger.info("read_face_swapped", { from: before ?? null, to: config.readFace ?? null, phase, note: "hot seat (core swapDeps) — legs that already prepared keep the face they prepared under" });
@@ -644,7 +699,7 @@ export async function createConfigCenterRuntime(ctx) {
644
699
  }
645
700
  },
646
701
  startRefreshLoop(a) {
647
- const { runnerTierFrozen, pricing, limitSync, swapRunnerDeps, ceilingVerdict } = a;
702
+ const { pricing, limitSync, swapRunnerDeps, ceilingVerdict, consolidationSeat, checkpointStorePresent } = a;
648
703
  if (configProvider) {
649
704
  const ccRef = config.configCenter;
650
705
  let refreshInFlight = false;
@@ -662,14 +717,14 @@ export async function createConfigCenterRuntime(ctx) {
662
717
  if (r === null && planeDeferredNoHandoff) {
663
718
  const skillsDebt = (planeDeferredNoHandoff.blocked ?? []).includes("skills");
664
719
  const promoted = lkgSurvivesRestart || skillsDebt ? await persistLkgDurable(planeDeferredNoHandoff.candidate, planeDeferredNoHandoff.candidateEtag) : false;
665
- const skillsProofPromotion = !promoted && !lkgSurvivesRestart && skillsDebt && lastPrewarmBodiesVerified && planeDeferredNoHandoff.planeDeferred !== true;
720
+ const skillsProofPromotion = !promoted && !lkgSurvivesRestart && skillsDebt && lastPrewarmBodiesVerified;
666
721
  if (skillsProofPromotion) {
667
722
  pendingRestart = { restartRequired: true, reasons: ["skills"], version: planeDeferredNoHandoff.version, since: Date.now() };
668
723
  logger.info("config_boot_skill_debt_promoted", { version: planeDeferredNoHandoff.version, note: "skill bodies verified on a source-confirmed-current candidate — the withheld skills restart is now published (non-durable lane, repair proven)" });
669
724
  planeDeferredNoHandoff = undefined;
670
725
  }
671
726
  else if (promoted) {
672
- const promotedReasons = [...new Set([...(planeDeferredNoHandoff.blocked ?? []), ...(planeDeferredNoHandoff.planeDeferred ? ["models-tiers"] : [])])];
727
+ const promotedReasons = [...new Set(planeDeferredNoHandoff.blocked ?? [])];
673
728
  if (promotedReasons.length > 0) {
674
729
  pendingRestart = { restartRequired: true, reasons: promotedReasons, version: planeDeferredNoHandoff.version, since: Date.now() };
675
730
  }
@@ -697,6 +752,7 @@ export async function createConfigCenterRuntime(ctx) {
697
752
  ...(r.domainErrors ?? []).map((de) => ({ domain: de.domain, error: de.error })),
698
753
  ...(promptsGate.ok ? [] : [{ domain: "prompts", error: promptsGate.error }]),
699
754
  ],
755
+ ...(r.droppedEntries !== undefined ? { droppedEntries: r.droppedEntries } : {}),
700
756
  lkgVersion: latestEffective?.version ?? "(env)",
701
757
  note: "candidate rejected whole (§9.5-5) — live config keeps the last-known-good; fix the named files to unblock",
702
758
  });
@@ -704,24 +760,24 @@ export async function createConfigCenterRuntime(ctx) {
704
760
  return "ok";
705
761
  }
706
762
  lastRejectedCandidate = undefined;
763
+ warnDroppedEntries(r, "refresh");
707
764
  if (ccRef?.dryRun) {
708
765
  logEffectiveDiff(config, r.effective, logger);
709
766
  ccEtag = r.etag;
710
767
  }
711
768
  else {
712
769
  const planeChanged = modelPlaneChanged(appliedPlaneEff, r.effective);
713
- const planeDeferred = swapRunnerDeps === undefined && (runnerTierFrozen || planeHasActiveTiers(r.effective)) && planeChanged;
714
770
  let applyReport;
715
771
  const committed = applyEffective(config, r.effective, logger, {
716
- teamsOnly: true,
772
+ leg: "hot",
773
+ checkpointStorePresent,
717
774
  sealedKeys,
718
775
  generation: tickGen,
719
776
  report: (rep) => {
720
777
  applyReport = rep;
721
778
  applyLedger.recordApply(rep);
722
779
  },
723
- ...(planeDeferred ? { deferModelPlane: true } : {}),
724
- ...(swapRunnerDeps !== undefined && planeChanged ? { swapPlane: swapRunnerDeps } : {}),
780
+ ...(planeChanged ? { swapPlane: swapRunnerDeps } : {}),
725
781
  });
726
782
  if (!committed)
727
783
  return "ok";
@@ -732,57 +788,40 @@ export async function createConfigCenterRuntime(ctx) {
732
788
  mcpRevocations.applyEnabledEntries(enabledMcpEntries(r.effective.mcp));
733
789
  applyLiveReadFace(r.effective, swapRunnerDeps, "refresh");
734
790
  applyLedger.applied(tickGen, r.effective.version);
735
- if (planeDeferred) {
736
- logger.warn("models_tiers_plane_deferred", { version: r.effective.version, note: "tier-frozen Runner: the changed model plane (models/roles/tiers/default) is NOT hot-applied — admission stays on the Runner's generation; restart applies the new plane (models-tiers restart signal rides /health)" });
737
- }
738
- else {
791
+ const tickPlane = modelPlaneCommitted(applyReport);
792
+ if (tickPlane)
739
793
  appliedPlaneEff = r.effective;
740
- planeDeferredNoHandoff = undefined;
741
- }
794
+ planeDeferredNoHandoff = undefined;
742
795
  await adoptCenterPrompts(r.effective, "refresh");
743
- if (!planeDeferred)
796
+ if (tickPlane)
744
797
  markRosterLanded(r.effective);
745
798
  const fullyApplied = applyReport?.fullyApplied !== false;
746
799
  if (!fullyApplied) {
800
+ ccEtag = undefined;
801
+ const refused = applyReport ? refusedGroups(applyReport) : [];
747
802
  logger.warn("config_candidate_partially_applied", {
748
803
  version: r.effective.version,
749
- rejected: applyReport?.limits.rejected?.keys ?? [],
804
+ rejected: refused.flatMap((g) => g.keys),
805
+ groups: refused.map((g) => g.group),
750
806
  note: "a group of this candidate was refused — the live config keeps serving the prior values for it; the LKG and the ETag stay on the last FULLY applied generation (this tree is re-judged next tick)",
751
807
  });
752
808
  return "ok";
753
809
  }
754
810
  const lkgPersisted = await persistLkgDurable(r.effective, r.etag);
755
- const reasons = restartReasons(effective, r.effective, restartCtx());
756
- if (swapRunnerDeps !== undefined) {
757
- const mi = reasons.indexOf("models-tiers");
758
- if (mi >= 0)
759
- reasons.splice(mi, 1);
760
- }
811
+ const reasons = restartReasons(effective, r.effective, restartCtx(consolidationSeat?.read()));
761
812
  const skillsChangeDetected = reasons.includes("skills");
762
813
  if (bootSkillStale && !skillsChangeDetected)
763
814
  reasons.push("skills");
764
- if (planeDeferred) {
765
- if (lkgPersisted) {
766
- if (!reasons.includes("models-tiers"))
767
- reasons.push("models-tiers");
768
- planeDeferredNoHandoff = undefined;
769
- }
770
- else {
771
- const blocked = reasons.splice(0, reasons.length);
772
- planeDeferredNoHandoff = { version: r.effective.version, since: planeDeferredNoHandoff?.since ?? Date.now(), ...(blocked.length > 0 ? { blocked } : {}), planeDeferred: true, candidate: r.effective, ...(r.etag !== undefined ? { candidateEtag: r.etag } : {}) };
773
- logger.warn("models_tiers_deferred_no_handoff", { version: r.effective.version, blockedReasons: blocked, note: "plane deferred but no NEXT-BOOT handoff (LKG disabled/unwritable, or storage not declared restart-surviving — set CONFIG_LKG_DURABLE=true) — the WHOLE restart signal is withheld (it would loop); the old generation keeps serving" });
774
- }
775
- }
776
- else if (lkgSurvivesRestart && !lkgPersisted) {
815
+ if (lkgSurvivesRestart && !lkgPersisted) {
777
816
  const blocked = reasons.splice(0, reasons.length);
778
- planeDeferredNoHandoff = { version: r.effective.version, since: planeDeferredNoHandoff?.since ?? Date.now(), blocked, candidate: r.effective, ...(r.etag !== undefined ? { candidateEtag: r.etag } : {}) };
817
+ planeDeferredNoHandoff = { version: r.effective.version, since: Date.now(), blocked, candidate: r.effective, ...(r.etag !== undefined ? { candidateEtag: r.etag } : {}) };
779
818
  logger.warn("restart_candidate_publication_incomplete", { version: r.effective.version, blockedReasons: blocked, note: "durable LKG declared but the candidate's publication is incomplete (skill bodies unverified) — restart signal withheld; retried every tick until the cache completes" });
780
819
  }
781
- else if (!planeDeferred && !lkgSurvivesRestart && bootSkillStale && !skillsChangeDetected && !lastPrewarmBodiesVerified) {
820
+ else if (!lkgSurvivesRestart && bootSkillStale && !skillsChangeDetected && !lastPrewarmBodiesVerified) {
782
821
  const i = reasons.indexOf("skills");
783
822
  if (i >= 0) {
784
823
  reasons.splice(i, 1);
785
- planeDeferredNoHandoff = { version: r.effective.version, since: planeDeferredNoHandoff?.since ?? Date.now(), blocked: ["skills"], candidate: r.effective, ...(r.etag !== undefined ? { candidateEtag: r.etag } : {}) };
824
+ planeDeferredNoHandoff = { version: r.effective.version, since: Date.now(), blocked: ["skills"], candidate: r.effective, ...(r.etag !== undefined ? { candidateEtag: r.etag } : {}) };
786
825
  logger.warn("config_boot_skill_debt_withheld", { version: r.effective.version, note: "boot skill debt still unproven on a non-durable deployment (body cache does not verify) — skills restart withheld this tick; re-verified each tick and published once the bodies prove fetchable" });
787
826
  }
788
827
  }
@@ -797,7 +836,7 @@ export async function createConfigCenterRuntime(ctx) {
797
836
  }
798
837
  logger.info("sema_registry_refreshed", {
799
838
  version: r.effective.version,
800
- note: "collab + runtime governance + limits + models/roles/roster hot-applied; skills/mcp/runtime-gates(approvalRequire)/scenarios are restart-to-apply",
839
+ note: "collab + runtime governance (incl. approvalRequire) + limits + models/roles/roster hot-applied; skills/mcp/a2a/scenarios are restart-to-apply",
801
840
  ...(pendingRestart ? { restartRequired: true, restartReasons: pendingRestart.reasons } : {}),
802
841
  });
803
842
  latestEffective = r.effective;
@@ -848,28 +887,29 @@ export async function createConfigCenterRuntime(ctx) {
848
887
  logger.warn("config_boot_deferred_candidate_rejected", {
849
888
  version: r.effective.version,
850
889
  errors: [...(r.domainErrors ?? []).map((de) => ({ domain: de.domain, error: de.error })), ...(promptsGate.ok ? [] : [{ domain: "prompts", error: promptsGate.error }])],
890
+ ...(r.droppedEntries !== undefined ? { droppedEntries: r.droppedEntries } : {}),
851
891
  note: "late boot pull carried an invalid candidate — env fallback keeps serving; the refresh cadence re-judges the same tree (etag not advanced)",
852
892
  });
853
893
  return;
854
894
  }
895
+ warnDroppedEntries(r, "boot-deferred");
855
896
  if (ccRef?.dryRun) {
856
897
  logEffectiveDiff(config, r.effective, logger);
857
898
  ccEtag = r.etag;
858
899
  return;
859
900
  }
860
901
  const planeChangedLate = modelPlaneChanged(appliedPlaneEff, r.effective);
861
- const planeDeferredLate = swapRunnerDeps === undefined && (runnerTierFrozen || planeHasActiveTiers(r.effective)) && planeChangedLate;
862
902
  let applyReportLate;
863
903
  const committedLate = applyEffective(config, r.effective, logger, {
864
- teamsOnly: true,
904
+ leg: "hot",
905
+ checkpointStorePresent,
865
906
  sealedKeys,
866
907
  generation: lateGen,
867
908
  report: (rep) => {
868
909
  applyReportLate = rep;
869
910
  applyLedger.recordApply(rep);
870
911
  },
871
- ...(planeDeferredLate ? { deferModelPlane: true } : {}),
872
- ...(swapRunnerDeps !== undefined && planeChangedLate ? { swapPlane: swapRunnerDeps } : {}),
912
+ ...(planeChangedLate ? { swapPlane: swapRunnerDeps } : {}),
873
913
  });
874
914
  if (!committedLate)
875
915
  return;
@@ -879,20 +919,21 @@ export async function createConfigCenterRuntime(ctx) {
879
919
  ceilingVerdict?.judge();
880
920
  applyLiveReadFace(r.effective, swapRunnerDeps, "boot-deferred");
881
921
  applyLedger.applied(lateGen, r.effective.version);
882
- if (planeDeferredLate)
883
- logger.warn("models_tiers_plane_deferred", { version: r.effective.version, note: "tier-frozen Runner (env tiers): the late-boot center model plane is NOT hot-applied — restart applies it" });
884
- else {
922
+ const latePlane = modelPlaneCommitted(applyReportLate);
923
+ if (latePlane)
885
924
  appliedPlaneEff = r.effective;
886
- planeDeferredNoHandoff = undefined;
887
- }
925
+ planeDeferredNoHandoff = undefined;
888
926
  await adoptCenterPrompts(r.effective, "boot-deferred");
889
- if (!planeDeferredLate)
927
+ if (latePlane)
890
928
  markRosterLanded(r.effective);
891
929
  const fullyAppliedLate = applyReportLate?.fullyApplied !== false;
892
930
  if (!fullyAppliedLate) {
931
+ ccEtag = undefined;
932
+ const refusedLate = applyReportLate ? refusedGroups(applyReportLate) : [];
893
933
  logger.warn("config_candidate_partially_applied", {
894
934
  version: r.effective.version,
895
- rejected: applyReportLate?.limits.rejected?.keys ?? [],
935
+ rejected: refusedLate.flatMap((g) => g.keys),
936
+ groups: refusedLate.map((g) => g.group),
896
937
  note: "late-boot candidate had a refused group — the LKG/ETag stay on the last FULLY applied generation; the refresh cadence re-judges the same tree",
897
938
  });
898
939
  return;
@@ -901,27 +942,10 @@ export async function createConfigCenterRuntime(ctx) {
901
942
  latestEffective = r.effective;
902
943
  ccEtag = r.etag;
903
944
  const lkgPersistedLate = await persistLkgDurable(r.effective, r.etag);
904
- const reasons = restartReasons(undefined, r.effective, restartCtx());
905
- if (swapRunnerDeps !== undefined) {
906
- const miLate = reasons.indexOf("models-tiers");
907
- if (miLate >= 0)
908
- reasons.splice(miLate, 1);
909
- }
910
- if (planeDeferredLate) {
911
- if (lkgPersistedLate) {
912
- if (!reasons.includes("models-tiers"))
913
- reasons.push("models-tiers");
914
- planeDeferredNoHandoff = undefined;
915
- }
916
- else {
917
- const blocked = reasons.splice(0, reasons.length);
918
- planeDeferredNoHandoff = { version: r.effective.version, since: planeDeferredNoHandoff?.since ?? Date.now(), ...(blocked.length > 0 ? { blocked } : {}), planeDeferred: true, candidate: r.effective, ...(r.etag !== undefined ? { candidateEtag: r.etag } : {}) };
919
- logger.warn("models_tiers_deferred_no_handoff", { version: r.effective.version, blockedReasons: blocked, note: "late-boot plane deferred but no NEXT-BOOT handoff (see CONFIG_LKG_DURABLE) — the WHOLE restart signal is withheld (it would loop); old generation keeps serving" });
920
- }
921
- }
922
- else if (planeDeferredLate === false && lkgSurvivesRestart && !lkgPersistedLate) {
945
+ const reasons = restartReasons(undefined, r.effective, restartCtx(consolidationSeat?.read()));
946
+ if (lkgSurvivesRestart && !lkgPersistedLate) {
923
947
  const blocked = reasons.splice(0, reasons.length);
924
- planeDeferredNoHandoff = { version: r.effective.version, since: planeDeferredNoHandoff?.since ?? Date.now(), blocked, candidate: r.effective, ...(r.etag !== undefined ? { candidateEtag: r.etag } : {}) };
948
+ planeDeferredNoHandoff = { version: r.effective.version, since: Date.now(), blocked, candidate: r.effective, ...(r.etag !== undefined ? { candidateEtag: r.etag } : {}) };
925
949
  logger.warn("restart_candidate_publication_incomplete", { version: r.effective.version, blockedReasons: blocked, note: "late-boot candidate publication incomplete on a durable-declared deployment — restart signal withheld; retried every tick" });
926
950
  }
927
951
  if (reasons.length > 0)
@@ -1,4 +1,3 @@
1
- import { NodeLspManager } from "@sema-agent/core";
2
1
  import { TaskEnvRegistry } from "../capabilities/sandbox-file-send.js";
3
2
  import { SessionEnvironmentSelection } from "../capabilities/select-environment-tool.js";
4
3
  import type { ServiceConfig } from "../config.js";
@@ -67,6 +66,6 @@ export declare function createExecutionEnv(ctx: ExecutionEnvCtx): {
67
66
  executionEnvFactory: import("@sema-agent/core").ExecutionEnvFactory | undefined;
68
67
  worktreeReap: (() => Promise<void>) | undefined;
69
68
  sendUserFileTaskEnvs: TaskEnvRegistry | undefined;
70
- lspManager: import("../lsp/manager.js").E2bLspManager | NodeLspManager | undefined;
69
+ lspManager: import("@sema-agent/core").NodeLspManager | import("../lsp/manager.js").E2bLspManager | undefined;
71
70
  };
72
71
  //# sourceMappingURL=execution-env.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { NodeLspManager } from "@sema-agent/core";
3
+ import { createHostLspManager } from "../host-lsp-manager.js";
4
4
  import { sandboxSendLaneEnabled, TaskEnvRegistry } from "../capabilities/sandbox-file-send.js";
5
5
  import { SessionEnvironmentSelection } from "../capabilities/select-environment-tool.js";
6
6
  import { createE2bLspManager } from "../lsp/e2b-manager.js";
@@ -29,6 +29,24 @@ function boundedSessionSetter(map, maxEntries) {
29
29
  map.delete(map.keys().next().value);
30
30
  };
31
31
  }
32
+ function forwardedSandboxEnvKeys(remoteExec) {
33
+ switch (remoteExec.provider) {
34
+ case "e2b":
35
+ return Object.keys(remoteExec.sandboxEnv ?? {}).sort();
36
+ case "local-docker":
37
+ return Object.keys(remoteExec.env ?? {}).sort();
38
+ case "k8s":
39
+ case "ssh":
40
+ case "adb":
41
+ case "host":
42
+ case "device":
43
+ return [];
44
+ default: {
45
+ const unreachable = remoteExec;
46
+ throw new Error(`unhandled remote-exec provider: ${String(unreachable.provider)}`);
47
+ }
48
+ }
49
+ }
32
50
  const MAX_CWD_SESSIONS = 4096;
33
51
  export function createSessionScopedRegistries(maxEntries = MAX_CWD_SESSIONS) {
34
52
  const perSessionCwd = new Map();
@@ -275,7 +293,7 @@ export function createExecutionEnv(ctx) {
275
293
  config.remoteExec.provider === "local-docker";
276
294
  const suspendable = config.remoteExec.provider === "e2b" ||
277
295
  (config.remoteExec.provider === "k8s" && !!config.remoteExec.s3Snapshot);
278
- const sandboxEnvKeys = config.remoteExec.provider === "e2b" ? Object.keys(config.remoteExec.sandboxEnv ?? {}) : [];
296
+ const sandboxEnvKeys = forwardedSandboxEnvKeys(config.remoteExec);
279
297
  logger.info("remote_exec_enabled", { provider: config.remoteExec.provider, isolated, suspendable, ...(sandboxEnvKeys.length > 0 ? { sandboxEnvKeys } : {}) });
280
298
  if (!isolated)
281
299
  logger.warn("remote_exec_real_system", { provider: config.remoteExec.provider, note: "non-isolated target — actions are permanent; rely on the policy gate + HITL (design/61 §5)" });
@@ -290,7 +308,7 @@ export function createExecutionEnv(ctx) {
290
308
  })
291
309
  :
292
310
  lspProvider === "host" && config.lspHostEnabled && config.requirePrincipal !== true
293
- ? new NodeLspManager({ log: (event, fields) => logger.info(event, fields) })
311
+ ? createHostLspManager(config, (event, fields) => logger.info(event, fields))
294
312
  : undefined;
295
313
  if (lspManager)
296
314
  logger.info("lsp_enabled", { provider: lspProvider });
@@ -1,6 +1,7 @@
1
1
  import { createLeaderEndpoint } from "../leader/endpoint.js";
2
2
  import { createLeaderRunner } from "../leader/wire.js";
3
3
  import { buildDeploymentPostureSeats } from "./runner-deps.js";
4
+ import { hasApprovalListIntent } from "../approval.js";
4
5
  export function leaderK8sMinioGap(leaderEnabled, leaderProvider, hasS3) {
5
6
  if (!(leaderEnabled && leaderProvider === "k8s" && !hasS3))
6
7
  return null;
@@ -67,16 +68,18 @@ export function createLeaderFace(ctx) {
67
68
  ...(toolResultStore ? { toolResultStore } : {}),
68
69
  ...(leaderProvider === "k8s" ? { workspace: "/workspace" } : {}),
69
70
  sessionStore,
70
- ...(checkpointStore && config.approvalRequire.length > 0
71
+ ...(checkpointStore
71
72
  ? {
72
- durable: {
73
- checkpointStore,
74
- requireApproval: config.approvalRequire,
75
- deny: config.approvalDeny,
76
- autoBudget: config.approvalAutoBudget,
77
- neverAuto: config.approvalNeverAuto,
78
- ...(config.approvalTimeoutSec > 0 ? { ttlMs: config.approvalTimeoutSec * 1000 } : {}),
79
- },
73
+ durable: () => hasApprovalListIntent(config)
74
+ ? {
75
+ checkpointStore,
76
+ requireApproval: config.approvalRequire,
77
+ deny: config.approvalDeny,
78
+ autoBudget: config.approvalAutoBudget,
79
+ neverAuto: config.approvalNeverAuto,
80
+ ...(config.approvalTimeoutSec > 0 ? { ttlMs: config.approvalTimeoutSec * 1000 } : {}),
81
+ }
82
+ : undefined,
80
83
  }
81
84
  : {}),
82
85
  }), {
@@ -1,3 +1,4 @@
1
+ import type { RestartSliceCtx } from "../config-center/restart-signal.js";
1
2
  import { type ConsolidationDriverRunRow, type ConsolidationRunReceipt, type MemoryBackend, type MemoryConsolidationDriverDeps, type RunMemoryConsolidationOptions, type SessionCaptureRecordStore } from "@sema-agent/core";
2
3
  /** D3 投影的座标签闭集。`role:<name>` 里的 name 只可能是 core 的 role 链两跳之一。 */
3
4
  export type ConsolidationSeatLabel = "explicit" | "role:consolidate" | "role:summarize";
@@ -30,6 +31,43 @@ export interface ConsolidationDriverSeat {
30
31
  * (探针只构造闭包、不发任何请求、无副作用。)
31
32
  */
32
33
  export declare function resolveConsolidationDriverSeat(deps: MemoryConsolidationDriverDeps): ConsolidationDriverSeat;
34
+ /**
35
+ * S-668 波 0([ref] §3)—— 整理驱动席的 **restart 读数**。过渡件:**波 1 转热后删**(那时每轮 run 起手
36
+ * 现取当前代的席,不再有 boot 烤死的席,这只表也就没有要比的东西了)。
37
+ *
38
+ * ## 为什么要它
39
+ *
40
+ * 席位在 boot 期解析一次(本模块头注「座在启动期解析一次」),core 的解析器把它选中的那只 `Model` 对象焊进
41
+ * chat 闭包。refresh 拍对模型面的热换(`mutateInPlace` + `swapDeps`)换的是目录里的**值**,够不到那只对象
42
+ * ⇒ 中心改了 roles / 档位绑定 / 那条目录条目之后,整理跑仍打 boot 那一代。修前没有任何一片签它 —— 它唯一
43
+ * 沾边的 `models-tiers` 片在生产上恒被摘除(今已退役)—— 于是这块是「静默冷」:既不热应用、也不报重启。
44
+ *
45
+ * ## 读法:问 core 的**同一只**解析器,不抄它的 role 链
46
+ *
47
+ * 席位 = `consolidate → summarize(含 flash 档位缺省)` 那条链对「env 角色底 + 中心目录 + 档位表」解出来的
48
+ * 那只 Model;本层抄一份链就是第二真源({@link seatLabel} 注里同一条理由)。做法:拿活配置调
49
+ * `resolveMemoryConsolidationDriver`,brain 与 per-model 凭据席都换成探针,再调一次它交回的 `chat` ——
50
+ * core 的 chat 第一件事就是拿**它选中的那只 Model** 问凭据席(`deps.getApiKeyAndHeaders?.(resolved)`,在
51
+ * 第一个 await 之前同步求值),探针在那一刻记下它并抛停:零请求、零副作用。
52
+ * ⚠️ 这一步依赖 core chat 闭包的**行为次序**:哪天 core 改成先做别的再问凭据席,探针就截不到 —— 那一刻本函数
53
+ * **响亮抛**(boot 期抛 = 阀门开着的部署拒启,句子说清原因),不退化成「读不到就当没变」(那正是本件要消灭的
54
+ * 静默)。钉:test/memory-consolidation-driver.test.ts 的探针格对真 core 跑,提货批当场红。
55
+ *
56
+ * ## 指纹里有什么
57
+ *
58
+ * 整只 Model 减掉 `cost`:整理跑只读 usage 的 token 数、零处读价目(core 7.29.0 的 driver 实现零 `cost` /
59
+ * `pricing` 读点),纯改价不该造一次重启。解不出来(中心撤掉了 consolidate / summarize 两跳)⇒ 记成
60
+ * `{ unresolvable: <core 原句> }`,与 boot 那只不等 ⇒ 签重启;重启会在 D1 拒启、把同一句原句写进拒因 ——
61
+ * 那正是运维该看见的话,比「这台还在用一只中心已经撤掉的席」诚实。
62
+ */
63
+ export interface ConsolidationSeatWatch {
64
+ /** boot 烤进去的席 vs 活配置此刻会解出的席(`restartReasons` 的 `memory-consolidation` 片两侧读数)。 */
65
+ read(): NonNullable<RestartSliceCtx["consolidationSeat"]>;
66
+ }
67
+ /** 解席的输入面 = boot 期真席用的同三件(活引用:refresh 就地换代,`read()` 每次现取)。 */
68
+ export type ConsolidationSeatPlane = Pick<MemoryConsolidationDriverDeps, "models" | "tiers" | "roles">;
69
+ /** `create*`:返回带捕获状态(boot 那只指纹)的活对象。须在真席解析的**同一时刻**调(同一份输入)。 */
70
+ export declare function createConsolidationSeatWatch(plane: () => ConsolidationSeatPlane): ConsolidationSeatWatch;
33
71
  /**
34
72
  * **每 scope 单飞**(codex 交叉复审 [high],验真后修)—— 同一 scope 上在飞的那一轮被后来者**并入**,
35
73
  * 而不是各起一轮。`create*`:返回带状态的活对象。