@sema-agent/server 7.43.0 → 7.44.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.
- package/USAGE.md +18 -0
- package/dist/adoption/plan.js +31 -192
- package/dist/adoption/quiesce.js +3 -86
- package/dist/adoption/runner.js +3 -140
- package/dist/adoption/sql.js +0 -74
- package/dist/adoption/wire.js +0 -80
- package/dist/approval-ask-machine.js +0 -75
- package/dist/approval-card.js +0 -323
- package/dist/approval-deny-reasons.js +0 -42
- package/dist/approval-hmac.js +0 -35
- package/dist/approval-reconciler.js +8 -166
- package/dist/approval.js +4 -67
- package/dist/audit.js +1 -44
- package/dist/auth-bridge.js +4 -47
- package/dist/auth-keys.js +0 -23
- package/dist/bake-runner/main.js +4 -65
- package/dist/bake-runner/protocol.js +3 -58
- package/dist/bake-runner/runner.js +5 -91
- package/dist/bench/l8/artifact.js +2 -61
- package/dist/bench/l8/escape.js +0 -25
- package/dist/bench/l8/index.js +0 -14
- package/dist/bench/l8/probes.js +0 -60
- package/dist/bench/l8/run-probes.js +2 -45
- package/dist/bench/s1/arms.js +14 -189
- package/dist/bench/s1/live-deps.js +11 -253
- package/dist/bench/s1/oracle.js +1 -36
- package/dist/bench/s1/repair-oracle-adapter.js +0 -30
- package/dist/bench/s1/reviewer.js +0 -34
- package/dist/bench/s1/row.js +0 -62
- package/dist/bench/s1/run-firm.js +4 -70
- package/dist/bench/s1/runner-ctx.js +0 -40
- package/dist/bench/s1/tasks.js +0 -115
- package/dist/boot/adoption.js +0 -20
- package/dist/boot/budget-tracing.js +3 -55
- package/dist/boot/config-center.js +43 -551
- package/dist/boot/coordinators.js +1 -69
- package/dist/boot/crash-last.js +0 -18
- package/dist/boot/deferred-sandbox-path-env.js +3 -119
- package/dist/boot/execution-env.js +5 -171
- package/dist/boot/governance-seams.js +0 -92
- package/dist/boot/leader.js +0 -69
- package/dist/boot/limit-sync.js +0 -2
- package/dist/boot/memory-boundary.js +3 -91
- package/dist/boot/org-memory.js +1 -25
- package/dist/boot/parked-revive-gate.js +0 -150
- package/dist/boot/permission-rules-audit.js +1 -56
- package/dist/boot/reapers.js +15 -273
- package/dist/boot/resolve-spec.js +9 -768
- package/dist/boot/retention-lane.js +4 -87
- package/dist/boot/runner-deps.js +3 -297
- package/dist/boot/runtime-caps.js +0 -40
- package/dist/boot/session-faces.js +2 -133
- package/dist/boot/shutdown.js +9 -83
- package/dist/boot/side-query-lane.js +2 -137
- package/dist/boot/stores.js +15 -215
- package/dist/boot/task-list-lane.js +0 -18
- package/dist/boot/webfetch-summarize-lane.js +0 -47
- package/dist/boot/workflow-orchestration.js +3 -99
- package/dist/boot-reclaim.js +0 -20
- package/dist/bounded-session-map.js +0 -19
- package/dist/brain.js +2 -139
- package/dist/budget.js +9 -244
- package/dist/capabilities/builtin-tools.js +0 -3
- package/dist/capabilities/center-plugins.js +6 -51
- package/dist/capabilities/center-prompts.js +6 -71
- package/dist/capabilities/code-review-council.js +7 -40
- package/dist/capabilities/collab-workflows.js +1 -44
- package/dist/capabilities/hands-lane.js +0 -65
- package/dist/capabilities/memory-notice.js +0 -70
- package/dist/capabilities/prompt.js +0 -14
- package/dist/capabilities/prompts/code-review.js +0 -14
- package/dist/capabilities/prompts/identity.js +0 -6
- package/dist/capabilities/prompts/team.js +0 -4
- package/dist/capabilities/repo-tools.js +0 -34
- package/dist/capabilities/sandbox-file-send.js +3 -92
- package/dist/capabilities/scenarios.d.ts +0 -1
- package/dist/capabilities/scenarios.js +18 -279
- package/dist/capabilities/select-environment-tool.js +0 -32
- package/dist/capabilities/send-user-file-tool.js +2 -66
- package/dist/capabilities/skills.d.ts +1 -2
- package/dist/capabilities/skills.js +3 -21
- package/dist/capabilities/team.d.ts +3 -11
- package/dist/capabilities/team.js +3 -51
- package/dist/capabilities/tool-defer.js +0 -3
- package/dist/config-center/apply-effective.js +15 -330
- package/dist/config-center/apply-ledger.js +5 -38
- package/dist/config-center/facade.js +0 -41
- package/dist/config-center/hot-keys-registry.js +0 -20
- package/dist/config-center/http-client.js +2 -125
- package/dist/config-center/mcp-revocation.js +2 -34
- package/dist/config-center/read-face.js +0 -59
- package/dist/config-center/restart-signal.js +1 -85
- package/dist/config-center/skills-mcp.d.ts +1 -1
- package/dist/config-center/skills-mcp.js +9 -76
- package/dist/config-center/stage-limits.js +8 -35
- package/dist/config-invariants.js +0 -16
- package/dist/config-lkg.js +0 -42
- package/dist/config-provider.js +3 -186
- package/dist/config-types.js +0 -5
- package/dist/config.js +107 -1145
- package/dist/degenerate-instrument.js +3 -67
- package/dist/deployment-governance.js +0 -124
- package/dist/digest-form.js +0 -12
- package/dist/elicitation.js +3 -86
- package/dist/env-facts.js +7 -75
- package/dist/fleet/fleet-bus.js +34 -507
- package/dist/fleet/fleet-reconciler.js +9 -149
- package/dist/fleet/fleet-terminal-window.js +10 -178
- package/dist/fleet/subagent-tail-bus.js +3 -72
- package/dist/fleet-client.js +10 -70
- package/dist/fleet-lease.js +5 -79
- package/dist/git-api-kind.js +0 -3
- package/dist/governance-ask-marks.js +2 -78
- package/dist/hooks/branch-transcript.js +0 -74
- package/dist/hooks/cc-agent-hook-prompt.js +0 -29
- package/dist/hooks/cc-stop-prompt.js +1 -46
- package/dist/hooks/hook-llm.js +1 -53
- package/dist/hooks/hook-runner.js +20 -414
- package/dist/http/active-run-conflict.js +4 -129
- package/dist/http/cursor-fingerprint.d.ts +5 -0
- package/dist/http/cursor-fingerprint.js +5 -0
- package/dist/http/idempotency.js +0 -37
- package/dist/http/principal-gate.js +3 -40
- package/dist/http/route-ctx.js +0 -9
- package/dist/http/routes/a2a-serve.js +7 -319
- package/dist/http/routes/admin-config-refresh.js +0 -4
- package/dist/http/routes/admin-drain.js +0 -10
- package/dist/http/routes/adoption.js +1 -29
- package/dist/http/routes/agents-roster.js +1 -47
- package/dist/http/routes/approvals-assistant.js +32 -395
- package/dist/http/routes/attachments.js +4 -22
- package/dist/http/routes/capabilities.js +3 -420
- package/dist/http/routes/diagnostics.js +1 -81
- package/dist/http/routes/fleet.js +9 -185
- package/dist/http/routes/images.js +14 -239
- package/dist/http/routes/leader.js +0 -13
- package/dist/http/routes/memory-bundle.js +1 -61
- package/dist/http/routes/memory-policy.js +9 -99
- package/dist/http/routes/notify-wake.js +3 -37
- package/dist/http/routes/observability.js +2 -19
- package/dist/http/routes/retention-ops.js +2 -34
- package/dist/http/routes/rules.js +1 -93
- package/dist/http/routes/runs.js +64 -873
- package/dist/http/routes/session-sync.js +19 -258
- package/dist/http/routes/sessions-list.js +17 -43
- package/dist/http/routes/sessions.js +34 -226
- package/dist/http/routes/shared-memory.js +5 -36
- package/dist/http/routes/side-query.js +1 -87
- package/dist/http/routes/tasks.js +52 -722
- package/dist/http/routes/trace-usage.js +32 -195
- package/dist/http/routes/workflows.js +19 -195
- package/dist/http/run-meta.js +0 -6
- package/dist/http/send.js +0 -32
- package/dist/http/server.js +92 -1597
- package/dist/http/sse-lifecycle.js +2 -13
- package/dist/http/sse-log.js +3 -48
- package/dist/http/tar.js +5 -21
- package/dist/http/verify-rounds.js +0 -5
- package/dist/http/wire-gate.js +0 -9
- package/dist/http/workspace-content.js +0 -10
- package/dist/images/bake-validate.js +1 -70
- package/dist/images/manifest.js +1 -6
- package/dist/index.js +0 -21
- package/dist/key-resolver.js +2 -17
- package/dist/leader/diffout.js +1 -20
- package/dist/leader/diffup.js +0 -47
- package/dist/leader/endpoint.js +2 -57
- package/dist/leader/fanout.js +3 -45
- package/dist/leader/grader-env-factory.js +3 -72
- package/dist/leader/leader.js +5 -156
- package/dist/leader/merge.js +8 -115
- package/dist/leader/planner.js +3 -54
- package/dist/leader/repair-oracle.js +1 -60
- package/dist/leader/repair-wire.js +2 -79
- package/dist/leader/wire.js +8 -307
- package/dist/lsp/e2b-bridge.js +4 -64
- package/dist/lsp/e2b-manager.js +6 -94
- package/dist/lsp/lsp-frames.js +0 -12
- package/dist/lsp/manager.js +4 -96
- package/dist/lsp/ws-transport.js +5 -55
- package/dist/lsp-evict.js +1 -15
- package/dist/main.js +57 -765
- package/dist/memory-bundle-engine.js +0 -55
- package/dist/memory-export.js +0 -4
- package/dist/memory-posture.js +1 -15
- package/dist/memory-scope.js +11 -148
- package/dist/memory-sync-client.js +2 -44
- package/dist/memory-sync.js +1 -80
- package/dist/model-select.js +3 -80
- package/dist/observability/cost-quota.js +1 -17
- package/dist/observability/cost-taxonomy.js +0 -34
- package/dist/observability/fail-open.js +7 -86
- package/dist/observability/logger.js +0 -6
- package/dist/observability/metrics.js +0 -94
- package/dist/observability/otel-exporter.js +3 -13
- package/dist/observability/principal-context.js +0 -9
- package/dist/observability/prompt-manifest.js +1 -37
- package/dist/observability/rate-limit.js +0 -4
- package/dist/observability/secret-env-scrub.js +2 -56
- package/dist/observability/tool-trace.js +1 -70
- package/dist/orchestration/hardened-vm-runner.js +4 -118
- package/dist/orchestration/hardened-vm-worker-runner.js +1 -26
- package/dist/orchestration/hardened-vm-worker.js +0 -27
- package/dist/orchestration/subagent-steer.js +1 -45
- package/dist/orchestration/workflow-agent-steer.js +1 -80
- package/dist/orchestration/workflow-completion-inbox.js +32 -285
- package/dist/orchestration/workflow-notify-journal.js +16 -259
- package/dist/org-memory-admission.js +3 -47
- package/dist/parent-watch.js +2 -48
- package/dist/parked-decide.js +1 -109
- package/dist/per-task-image.js +0 -57
- package/dist/plan-cache-probe.js +3 -27
- package/dist/plugins/adoption-log-sql.js +2 -119
- package/dist/plugins/approval-ask-store-memory.js +3 -38
- package/dist/plugins/approval-ask-store-sql.js +6 -188
- package/dist/plugins/approval-exemption-store.js +2 -28
- package/dist/plugins/background-agent-store-sql.js +4 -105
- package/dist/plugins/background-shell-support.js +14 -122
- package/dist/plugins/blob-backend.js +6 -169
- package/dist/plugins/breaker-state-sql.js +8 -46
- package/dist/plugins/caching-session-store.js +4 -106
- package/dist/plugins/checkpoint-store-sql.js +18 -505
- package/dist/plugins/e2b-orphan-reclaim.js +0 -45
- package/dist/plugins/file-outcome-sink.js +0 -9
- package/dist/plugins/file-resume-anchor-store.js +4 -43
- package/dist/plugins/file-run-store.js +26 -364
- package/dist/plugins/file-snapshot-store-sql.js +10 -181
- package/dist/plugins/fork-routing-session-store.js +8 -111
- package/dist/plugins/host-platform.js +2 -91
- package/dist/plugins/image-bake-store-sql.js +7 -250
- package/dist/plugins/image-index-sql.js +4 -123
- package/dist/plugins/k8s-bg-scripts.js +4 -88
- package/dist/plugins/k8s-exec-protocol.js +0 -41
- package/dist/plugins/leader-run-store-sql.js +0 -101
- package/dist/plugins/local-checkpoint-store.js +8 -128
- package/dist/plugins/local-session-store.js +34 -296
- package/dist/plugins/local-task-attachment-store.js +2 -16
- package/dist/plugins/mailbox-store-sql.js +8 -65
- package/dist/plugins/memory-embedder-fingerprint.js +5 -166
- package/dist/plugins/memory-embedder.js +4 -70
- package/dist/plugins/memory-engine-pg.js +6 -170
- package/dist/plugins/memory-engine-tidb.js +7 -155
- package/dist/plugins/memory-engine-vector-util.js +0 -10
- package/dist/plugins/memory-key-guards.js +0 -34
- package/dist/plugins/memory-origin-law.js +0 -187
- package/dist/plugins/memory-resume-anchor-store.js +0 -17
- package/dist/plugins/memory-run-store.js +12 -89
- package/dist/plugins/memory-session-policy-store.js +0 -17
- package/dist/plugins/memory-sync-store-pg.js +4 -49
- package/dist/plugins/memory-sync-store-tidb.js +3 -35
- package/dist/plugins/outcome-ledger-sql.js +3 -97
- package/dist/plugins/permission-rule-store-file.js +5 -133
- package/dist/plugins/permission-rule-store-sql.d.ts +3 -0
- package/dist/plugins/permission-rule-store-sql.js +50 -307
- package/dist/plugins/pg-cost-quota.js +0 -7
- package/dist/plugins/pg-pool.js +0 -92
- package/dist/plugins/pg-rate-limiter.js +2 -13
- package/dist/plugins/pg-safe-json.js +4 -40
- package/dist/plugins/pg-session-storage.js +25 -189
- package/dist/plugins/posix-shell-fs.js +1 -31
- package/dist/plugins/remote-env-adb.js +12 -101
- package/dist/plugins/remote-env-e2b.js +40 -371
- package/dist/plugins/remote-env-file-error.js +0 -37
- package/dist/plugins/remote-env-host.js +63 -483
- package/dist/plugins/remote-env-k8s.js +32 -326
- package/dist/plugins/remote-env-local-docker.js +24 -157
- package/dist/plugins/remote-env-ssh.js +20 -128
- package/dist/plugins/remote-scratchpad.js +2 -32
- package/dist/plugins/remote-shell.js +1 -32
- package/dist/plugins/resume-anchor-store-sql.js +0 -11
- package/dist/plugins/retention-lane-store-sql.js +0 -108
- package/dist/plugins/retention-store-sql.js +4 -383
- package/dist/plugins/roster-store-sql.js +0 -55
- package/dist/plugins/run-store-sql.js +14 -251
- package/dist/plugins/s3-presign.js +2 -49
- package/dist/plugins/scheduler-support.js +3 -80
- package/dist/plugins/send-file-ledger.js +4 -53
- package/dist/plugins/send-user-file.js +4 -94
- package/dist/plugins/session-placement.js +1 -89
- package/dist/plugins/session-policy-store-sql.js +3 -81
- package/dist/plugins/session-store.js +0 -57
- package/dist/plugins/shared-memory-store-sql.js +4 -167
- package/dist/plugins/sql-driver.js +0 -17
- package/dist/plugins/sql-errors.js +0 -7
- package/dist/plugins/sql-escape.js +0 -8
- package/dist/plugins/sql-row-helpers.js +0 -25
- package/dist/plugins/store-backend.js +42 -222
- package/dist/plugins/store-contracts.js +2 -46
- package/dist/plugins/task-attachment-store.js +3 -49
- package/dist/plugins/task-list-store-sql.js +0 -79
- package/dist/plugins/tidb-cost-quota.js +1 -4
- package/dist/plugins/tidb-pool.js +1 -207
- package/dist/plugins/tidb-rate-limiter.js +3 -9
- package/dist/plugins/tidb-session-storage.js +4 -70
- package/dist/plugins/tidb-session-store.js +19 -341
- package/dist/plugins/tool-result-store-sql.js +4 -179
- package/dist/plugins/usage-window-store-sql.js +0 -8
- package/dist/plugins/web-search.js +10 -132
- package/dist/plugins/workflow-journal-store-sql.js +2 -58
- package/dist/plugins/workflow-run-store-sql.js +6 -91
- package/dist/plugins/worktree-isolation.js +6 -126
- package/dist/plugins/write-behind-counter.js +16 -75
- package/dist/principal-jwt.js +5 -60
- package/dist/project-memory.js +15 -146
- package/dist/prompts-domain-validate.js +1 -51
- package/dist/question.js +2 -111
- package/dist/resource-suspend.js +0 -18
- package/dist/router/route-orchestration.js +0 -77
- package/dist/rules-consent.d.ts +44 -5
- package/dist/rules-consent.js +75 -215
- package/dist/run-local.js +14 -381
- package/dist/runs.js +29 -617
- package/dist/runtime-caps-resolver.js +6 -132
- package/dist/runtime-governance.js +1 -232
- package/dist/sandbox-pkg-source.js +0 -37
- package/dist/sealed-key.js +3 -68
- package/dist/security.js +6 -291
- package/dist/session-leaf-bus.js +0 -32
- package/dist/session-sync-content.js +1 -69
- package/dist/session-sync-kernel.js +3 -60
- package/dist/session-sync.js +3 -66
- package/dist/session-titler.js +7 -41
- package/dist/session-watch.js +9 -73
- package/dist/shared-memory-scope-authorizer.js +0 -18
- package/dist/sighup-idle.js +1 -12
- package/dist/spec-fields.js +4 -143
- package/dist/store-live-probe.js +3 -49
- package/dist/task-a2a.js +1 -126
- package/dist/task-cwd.js +1 -103
- package/dist/task-mcp.js +1 -89
- package/dist/task-settings.js +10 -300
- package/dist/task-workflow.js +8 -75
- package/dist/tool-approval.d.ts +28 -1
- package/dist/tool-approval.js +70 -1430
- package/dist/trace/artifacts.js +5 -20
- package/dist/trace/engine-notice-wire.js +6 -138
- package/dist/trace/ledger-sink.js +7 -96
- package/dist/trace/project.js +4 -448
- package/dist/trace/redact.js +9 -77
- package/dist/turn-activity.js +1 -27
- package/dist/usage-analytics.js +4 -34
- package/dist/wall-clock-jump-guard.js +1 -68
- package/package.json +3 -3
- package/dist/capabilities/scenario-alias.d.ts +0 -27
- package/dist/capabilities/scenario-alias.js +0 -61
|
@@ -1,85 +1,17 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* #261(docs/DESIGN-261-fleet-liveness-reconcile.md v1.2,四方零驳定稿)—— fleet 总线**存活对账腿**。
|
|
3
|
-
*
|
|
4
|
-
* ## 它修什么(§0 病灶机制链)
|
|
5
|
-
* fleet 总线是进程内纯内存聚合(`fleet-bus.ts` 头注自陈 NOT durable / NOT cross-replica),行的**唯一**
|
|
6
|
-
* 离场路径是发布方主动打 `onTerminal`/`onChildTerminal`。发布方没走到终态臂(run 事件环异常中断、引擎
|
|
7
|
-
* 被壳 reuse 而旧 run 对象已死、BCE 终态通知丢失),行就**永久僵在** `tasks` Map 里 —— 此后每个订阅方
|
|
8
|
-
* (含 snapshot 新连接)看到一条永远 "running" 的幽灵行。壳侧只能靠 overlay 防御(cli 1.0.74 过渡件)。
|
|
9
|
-
*
|
|
10
|
-
* ## 核心裁定:**不造第二个判死者**(§1)
|
|
11
|
-
* 本腿**不判死**。它只做两件事:
|
|
12
|
-
* (a) 副本本地活体登记面(`http/server.ts` 的 `inflightRuns` ∪ `steerableRuns`,经
|
|
13
|
-
* {@link FleetReconcilerDeps.isLiveOnThisReplica} 探针注入 —— **不搬 Map**)在场 ⇒ 行活,跳过;
|
|
14
|
-
* (b) 登记面无此 taskId ⇒ 读 durable run 行,把 durable **已有的判决**投影到总线上。
|
|
15
|
-
* 判死的属主始终是 durable 侧既有机制(心跳 → reaper finalize → 行翻终态);本腿是**投影腿**,
|
|
16
|
-
* 对 durable **恒只读**({@link FleetReconcileRunPort} 这只窄口连写方法都没有 —— 单写者不变量由类型执法)。
|
|
17
|
-
*
|
|
18
|
-
* `msSinceLastActivity` **显式排除**:它是「turn 卡死」诊断维,把它当退休输入会把真忙的后台 run 扫下
|
|
19
|
-
* 面板,方向错。卡死的 run 行**该**留着(它确实在占资源),诊断走 `GET /v1/runs/:id`。
|
|
20
|
-
*
|
|
21
|
-
* ## 对账矩阵(§1;每周期对 bus 的顶层 run 行逐行判)
|
|
22
|
-
* | 登记面 | durable 行 | 处置 |
|
|
23
|
-
* |---|---|---|
|
|
24
|
-
* | 在场 | 任意 | **跳过**(含 turn 卡死形) |
|
|
25
|
-
* | 无 | 终局 | **投影退休**:终态 `task` 帧(durable 真状态 + `retiredBy:"reconcile"` + 被退代际)→ `task_remove`,**结算级** |
|
|
26
|
-
* | 无 | `running`(本副本 claim / 他副本 claim) | **陈述级退场**:`task_remove` + `removeReason:"orphaned"`,**恒不造终态** |
|
|
27
|
-
* | 无 | 行不存在 | 陈述级退场(见下方"静默一周期"的收窄) |
|
|
28
|
-
*
|
|
29
|
-
* 🔴 **对"行不存在"这一格的收窄**(实施稿承重,设计稿 §3 的「拿不准的恒答最弱主张」同源):bus 上
|
|
30
|
-
* 一条 `parentId` 缺席的行**不一定**是顶层 run 行 —— BCE 车道的 `a*` 子代行在父链接尚未解析成功时
|
|
31
|
-
* 同样不发 `parentId`(`rowTags` 的 R6 臂),两者在总线上**结构同形**。而 `getRun(a*)` 必然 miss。
|
|
32
|
-
* 若照矩阵当周期就退场,一条**活着的**长寿 session-scoped bg 子代会被扫下面板。所以这一格额外要求
|
|
33
|
-
* 「**静默满一个对账周期**」(本腿订阅总线自记每行的最后帧时刻):还在出帧 = 活着的证据。
|
|
34
|
-
* durable 行**在场**的那三格没有这个歧义(`getRun` 命中 = 它就是一条 run 行),故照矩阵即时处置。
|
|
35
|
-
*
|
|
36
|
-
* ## 子代行(§1)
|
|
37
|
-
* 随父:父行退休/退场时**同扫**(与 `onTerminal` 的 removal 集同姿势)。子代**不读 durable** ——
|
|
38
|
-
* bg 子代的 durable 真源在 core 侧 registry,server 不越界重判。无父可循的孤儿子行(父行已不在 bus)
|
|
39
|
-
* 按「bus 内滞留超一个对账周期且无新帧」陈述级退场。
|
|
40
|
-
*
|
|
41
|
-
* ## workflow 行(§1)
|
|
42
|
-
* 只做同款「durable 终局投影」(#189 的 snapshot pull 腿 + reapers 的 workflow recover 腿已在场),
|
|
43
|
-
* **不加新判据**:活行恒不动,没有陈述级退场这一形。
|
|
44
|
-
*
|
|
45
|
-
* ## 五条界(任何一条失手都只是幽灵行多活一个周期 ⇒ 整体 F 类 fail-open,登记 tag,不静默)
|
|
46
|
-
* · 节律 {@link FLEET_RECONCILE_INTERVAL_MS} · 每周期读上限 {@link FLEET_RECONCILE_MAX_ROWS}
|
|
47
|
-
* · 读预算 {@link FLEET_RECONCILE_READ_BUDGET_MS} · 熔断冷却 {@link FLEET_RECONCILE_COOLDOWN_MS}
|
|
48
|
-
* · 待终局候补窗 {@link FLEET_RECONCILE_WATCH_MAX} × {@link FLEET_RECONCILE_WATCH_TTL_MS}
|
|
49
|
-
* 任何读错/超预算 ⇒ `recordFailOpen("server.fleet.reconcile-read-failed")` + 熔断 + 本周期跳过。
|
|
50
|
-
*
|
|
51
|
-
* ## 为什么整套常数都不做旋钮
|
|
52
|
-
* 与 `fleet-terminal-window.ts` 同一论证:两侧边界都由语义定死(比周期短 = 幽灵行仍在面板上,比周期长 =
|
|
53
|
-
* 拿对账腿当历史列表),旋钮只会让部署方去调一个没有正确取值的数;fleet 面现有零旋钮,从之。
|
|
54
|
-
*/
|
|
55
1
|
import { isTerminalWorkflowStatus } from "@sema-agent/core";
|
|
56
2
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
57
3
|
import { isParkedRunStatus, isTerminalRunStatus } from "../plugins/store-contracts.js";
|
|
58
4
|
import { buildFleetWorkflowRow, fleetRunResiduals, runStatusToFleet } from "./fleet-bus.js";
|
|
59
5
|
import { isTerminalWorkflowRowStatus } from "./fleet-terminal-window.js";
|
|
60
|
-
/** 对账节律 —— 60s 档。比它短 = 每分钟给 durable 加一批点读却换不来更快的面板真相(幽灵行的时间尺度
|
|
61
|
-
* 是"发布方已经死了",分钟级);比它长 = 壳的引擎温切门(cli engineSwapGate 读活行集)被幽灵行按住
|
|
62
|
-
* 太久。不做旋钮,理由见模块头。 */
|
|
63
6
|
export const FLEET_RECONCILE_INTERVAL_MS = 60_000;
|
|
64
|
-
/** 每周期的**点读上限**。超出的行留到下一周期(顺序稳定 = bus 的插入序),不把一次扫描变成全表点读风暴。 */
|
|
65
7
|
export const FLEET_RECONCILE_MAX_ROWS = 200;
|
|
66
|
-
/** 一个周期的 durable 读**时间预算**。超时 = 放弃这一轮(记 F 类 fail-open),行留在面板上。
|
|
67
|
-
* 与 `FLEET_SNAPSHOT_TERMINAL_READ_BUDGET_MS` 同值同理由:慢查询不该把整条腿钉死。 */
|
|
68
8
|
export const FLEET_RECONCILE_READ_BUDGET_MS = 2_000;
|
|
69
|
-
/** 熔断冷却:一次读失败/超预算之后,这段时间内**不再发起任何读**。`RunStore`/`WorkflowRunStore` 契约
|
|
70
|
-
* 都没有取消面(发出去的查询撤不回),挂死的后端不该被每周期继续加压。冷却一过自动重探(自愈)。 */
|
|
71
9
|
export const FLEET_RECONCILE_COOLDOWN_MS = 60_000;
|
|
72
|
-
/** 陈述级退场之后的**待终局候补窗**行数上限(§1 矩阵的「终局候 durable 翻转后由下一周期投影」半场:
|
|
73
|
-
* 行已不在 bus,故补发终态 `task` 帧 + remove 的**成对形**)。有界:超出即不再收新条目。 */
|
|
74
10
|
export const FLEET_RECONCILE_WATCH_MAX = 200;
|
|
75
|
-
/** 候补窗的存活时长。reaper 的孤儿宽限窗之外仍没翻终局的行 = 这条腿等不到了(它本来也只是投影),
|
|
76
|
-
* 丢弃并不损失真相:`GET /v1/runs/:id` 永远是那条 run 的真源。 */
|
|
77
11
|
export const FLEET_RECONCILE_WATCH_TTL_MS = 30 * 60_000;
|
|
78
12
|
const emptyTally = () => ({
|
|
79
13
|
scanned: 0, skippedLive: 0, skippedParked: 0, retired: 0, orphaned: 0, childrenSwept: 0, workflowsRetired: 0, reads: 0, cooling: false, failOpen: false,
|
|
80
14
|
});
|
|
81
|
-
/** 从 `cursor` 指的那一行开始的**环形**遍历(见 {@link createFleetReconciler} 里 `taskCursor` 的顶注)。
|
|
82
|
-
* `cursor` 缺席/已不在集合里 ⇒ 从头开始(诚实回落)。返回新数组,调用方照常按序 `for…of`。 */
|
|
83
15
|
function rotate(rows, cursor) {
|
|
84
16
|
if (cursor === undefined || rows.length === 0)
|
|
85
17
|
return rows;
|
|
@@ -88,26 +20,12 @@ function rotate(rows, cursor) {
|
|
|
88
20
|
return rows;
|
|
89
21
|
return [...rows.slice(at), ...rows.slice(0, at)];
|
|
90
22
|
}
|
|
91
|
-
/** 本周期该不该收这条行 —— 见模块头「对"行不存在"这一格的收窄」。 */
|
|
92
23
|
const SILENT_FOR_A_CYCLE = FLEET_RECONCILE_INTERVAL_MS;
|
|
93
24
|
export function createFleetReconciler(deps) {
|
|
94
25
|
const now = deps.now ?? (() => Date.now());
|
|
95
|
-
/**
|
|
96
|
-
* 每行的**最后帧时刻**。存在理由:「无新帧」是设计稿对孤儿子行(以及本实施稿对"durable 无行"格)
|
|
97
|
-
* 唯一诚实的活性证据 —— 长寿 session-scoped bg 子代在父 run 行离场之后照样出 tick,它必须留在面板上。
|
|
98
|
-
* 从总线订阅得到(而不是自己给行打时间戳):**行的单写者不变量**不许被观察者破坏。
|
|
99
|
-
*/
|
|
100
26
|
const lastFrameAt = new Map();
|
|
101
|
-
/** 陈述级退场后的待终局候补窗(见 {@link FLEET_RECONCILE_WATCH_MAX})。 */
|
|
102
27
|
const watch = new Map();
|
|
103
28
|
let coolingUntil;
|
|
104
|
-
/**
|
|
105
|
-
* 🔴 轮转游标(codex 对抗复审 R1-F4 [medium],红先复现):读上限是**每周期**的,而扫描顺序是 bus 的
|
|
106
|
-
* 稳定插入序 —— 于是「超出的行留到下一周期」这句承诺在**行不会自己走**的形下是假的:200 条长期
|
|
107
|
-
* parked/活的行会把预算逐周期吃光,第 201 行往后**永远**读不到,它们的终局投影永不发生(而那正是本腿
|
|
108
|
-
* 存在的理由)。游标记住"上一周期停在哪一行",下一周期从它接着扫,一圈之后必然轮到每一行。
|
|
109
|
-
* 记 id(不是下标):行集会增删,下标会指到别的行上;id 找不到就从头开始(诚实回落,不猜)。
|
|
110
|
-
*/
|
|
111
29
|
let taskCursor;
|
|
112
30
|
let wfCursor;
|
|
113
31
|
const unsubscribe = deps.bus.subscribe((frame) => {
|
|
@@ -125,14 +43,9 @@ export function createFleetReconciler(deps) {
|
|
|
125
43
|
}
|
|
126
44
|
coolingUntil = undefined;
|
|
127
45
|
const deadline = now() + FLEET_RECONCILE_READ_BUDGET_MS;
|
|
128
|
-
/** 读闸:上限/预算任一到顶就停(**不是**熔断——本周期已做的处置全部有效,余下的行下周期再来)。 */
|
|
129
46
|
const budgetLeft = () => tally.reads < FLEET_RECONCILE_MAX_ROWS && now() < deadline;
|
|
130
|
-
/** 一次点读。抛错/超预算 ⇒ 抛 {@link ReadAborted},由 runOnce 统一收成 F 类 fail-open + 熔断。 */
|
|
131
47
|
const readRun = async (id) => {
|
|
132
48
|
tally.reads++;
|
|
133
|
-
// A-067 C5(F7):竞速一结束就 clearTimeout(A-002.10 同款,approval-reconciler withDeadline 正形)
|
|
134
|
-
// ——unref 只保证不吊住进程退出,不回收定时器本身;每周期最多 FLEET_RECONCILE_MAX_ROWS 次点读,
|
|
135
|
-
// 不清就是同数量级带闭包定时器的逐周期累积。finally 对胜败两路都清。
|
|
136
49
|
let t;
|
|
137
50
|
const rec = await Promise.race([
|
|
138
51
|
deps.runs.getRun(id),
|
|
@@ -148,8 +61,6 @@ export function createFleetReconciler(deps) {
|
|
|
148
61
|
return rec;
|
|
149
62
|
};
|
|
150
63
|
const snap = deps.bus.snapshot();
|
|
151
|
-
// 静默钟的**首见播种**:本腿起动之前就已在 bus 上的行(重启/迟接线)没有帧记录,给它们记一个
|
|
152
|
-
// "从现在开始静默"的起点 —— 否则首轮就会把一屏历史行当成静默满一周期的幽灵。
|
|
153
64
|
for (const r of snap.tasks)
|
|
154
65
|
if (!lastFrameAt.has(r.id))
|
|
155
66
|
lastFrameAt.set(r.id, nowMs);
|
|
@@ -165,8 +76,6 @@ export function createFleetReconciler(deps) {
|
|
|
165
76
|
else
|
|
166
77
|
kids.set(r.parentId, [r]);
|
|
167
78
|
}
|
|
168
|
-
/** 随父同扫(与 `fleetRunPublisher.onTerminal` 的 removal 集同姿势)。子代恒**陈述级** ——
|
|
169
|
-
* 我们对它们没有任何终局证据(子代不读 durable),说"离场"是诚实的,说"完成/失败"是编。 */
|
|
170
79
|
const sweepChildren = (parentId) => {
|
|
171
80
|
for (const c of kids.get(parentId) ?? []) {
|
|
172
81
|
deps.bus.removeTask(c.id, { removeReason: "orphaned", ...(c.cycleSeq !== undefined ? { cycleSeq: c.cycleSeq } : {}) });
|
|
@@ -174,10 +83,7 @@ export function createFleetReconciler(deps) {
|
|
|
174
83
|
tally.childrenSwept++;
|
|
175
84
|
}
|
|
176
85
|
};
|
|
177
|
-
/** 投影退休(结算级):终态 `task` 帧 → `task_remove`,**成对且有序**。 */
|
|
178
86
|
const retire = (row, rec) => {
|
|
179
|
-
// 残局键走既有的**同一个** {@link fleetRunResiduals} 映射(键名映射写第二遍必漂;[1839]① 案:
|
|
180
|
-
// 只带 {id,status} 的终态帧让 idle 观察者从行卡上拿不到终局)。源恒是 durable 那份 result,不编。
|
|
181
87
|
deps.bus.publishTask({
|
|
182
88
|
id: row.id,
|
|
183
89
|
status: runStatusToFleet(rec.status),
|
|
@@ -190,7 +96,6 @@ export function createFleetReconciler(deps) {
|
|
|
190
96
|
tally.retired++;
|
|
191
97
|
deps.metrics?.inc("fleet_rows_reconciled_total", { disposition: "retired" });
|
|
192
98
|
};
|
|
193
|
-
/** 陈述级退场:只撤行,恒不造终态。行进候补窗,等 durable 翻终局后由后续周期补发成对终帧。 */
|
|
194
99
|
const orphanExit = (row, why) => {
|
|
195
100
|
sweepChildren(row.id);
|
|
196
101
|
deps.bus.removeTask(row.id, { removeReason: "orphaned", ...(row.cycleSeq !== undefined ? { cycleSeq: row.cycleSeq } : {}) });
|
|
@@ -202,18 +107,11 @@ export function createFleetReconciler(deps) {
|
|
|
202
107
|
deps.logger?.info("fleet_row_reconciled", { taskId: row.id, disposition: "orphaned", why, instanceId: deps.instanceId ?? null });
|
|
203
108
|
};
|
|
204
109
|
try {
|
|
205
|
-
// ── ① 候补窗:陈述级退场过的行,等 durable 翻终局 ─────────────────────────────────────
|
|
206
|
-
// 为什么要补这一拍:cli 的裁量是「渲**离场**不清行」([4044])—— 陈述级退场之后壳把行**保留**在
|
|
207
|
-
// 面板上(中性离场形、active 扣除、折叠排后),所以那条行后来真的翻了终局时,补发的成对终帧是壳
|
|
208
|
-
// 唯一能把"离场"升级成"真终局"的信号。行已不在 bus,故 publish 会**瞬时重铸**再撤(flip-through,
|
|
209
|
-
// 与 `onChildTerminal` 的合成终帧同姿势);带上退场时记住的整行,可见性字段(scope/sessionId)
|
|
210
|
-
// 才不会丢 —— 丢了就变成 scoped 订阅方一律看不见(fail-closed 到没人收得到)。
|
|
211
110
|
for (const [id, w] of [...watch]) {
|
|
212
111
|
if (nowMs - w.at > FLEET_RECONCILE_WATCH_TTL_MS) {
|
|
213
112
|
watch.delete(id);
|
|
214
113
|
continue;
|
|
215
114
|
}
|
|
216
|
-
// 行又出现在 bus 上 = **复活**(更大代际的首帧 = 正常出生):活发布方接管,候补窗让位。
|
|
217
115
|
if (present.has(id)) {
|
|
218
116
|
watch.delete(id);
|
|
219
117
|
continue;
|
|
@@ -224,9 +122,9 @@ export function createFleetReconciler(deps) {
|
|
|
224
122
|
if (!rec) {
|
|
225
123
|
watch.delete(id);
|
|
226
124
|
continue;
|
|
227
|
-
}
|
|
125
|
+
}
|
|
228
126
|
if (!isTerminalRunStatus(rec.status))
|
|
229
|
-
continue;
|
|
127
|
+
continue;
|
|
230
128
|
deps.bus.publishTask({ ...w.row, status: runStatusToFleet(rec.status), retiredBy: "reconcile", ...fleetRunResiduals(rec.result) });
|
|
231
129
|
deps.bus.removeTask(id, { ...(w.row.cycleSeq !== undefined ? { cycleSeq: w.row.cycleSeq } : {}) });
|
|
232
130
|
lastFrameAt.delete(id);
|
|
@@ -234,39 +132,31 @@ export function createFleetReconciler(deps) {
|
|
|
234
132
|
tally.retired++;
|
|
235
133
|
deps.metrics?.inc("fleet_rows_reconciled_total", { disposition: "retired_deferred" });
|
|
236
134
|
}
|
|
237
|
-
// ── ② 顶层 run 行 ────────────────────────────────────────────────────────────────────
|
|
238
135
|
for (const row of rotate(snap.tasks, taskCursor)) {
|
|
239
136
|
if (row.parentId !== undefined)
|
|
240
|
-
continue;
|
|
137
|
+
continue;
|
|
241
138
|
tally.scanned++;
|
|
242
139
|
if (deps.isLiveOnThisReplica(row.id)) {
|
|
243
|
-
// 登记面在场 ⇒ 活。**含 turn 卡死形** —— 诊断不驱逐(§1)。一次 durable 读都不发。
|
|
244
140
|
tally.skippedLive++;
|
|
245
141
|
continue;
|
|
246
142
|
}
|
|
247
143
|
if (!deps.runs)
|
|
248
|
-
continue;
|
|
144
|
+
continue;
|
|
249
145
|
if (!budgetLeft()) {
|
|
250
146
|
taskCursor = row.id;
|
|
251
147
|
break;
|
|
252
|
-
}
|
|
148
|
+
}
|
|
253
149
|
const rec = await readRun(row.id);
|
|
254
|
-
// 🔴 await 后**复核**(codex 对抗复审 R1-F3 [high],红先复现):`isLiveOnThisReplica` 在读之前只
|
|
255
|
-
// 问过一次,而 durable 读的那几十毫秒里 parked run 完全可能被 resume —— 它会重新登记进在飞面并
|
|
256
|
-
// 发出新行帧,而读回来的行还写着 `running`。不复核就等于把**刚复活**的顶层行删掉;顶层行按设计
|
|
257
|
-
// 恒无 `cycleSeq`(「无此概念」),总线那道代际条件删也救不了这一格,只能在这里问第二次。
|
|
258
150
|
if (deps.isLiveOnThisReplica(row.id)) {
|
|
259
151
|
tally.skippedLive++;
|
|
260
152
|
continue;
|
|
261
153
|
}
|
|
262
154
|
const nowRow = deps.bus.taskRow(row.id);
|
|
263
155
|
if (nowRow === undefined)
|
|
264
|
-
continue;
|
|
156
|
+
continue;
|
|
265
157
|
if (nowRow.cycleSeq !== row.cycleSeq)
|
|
266
|
-
continue;
|
|
158
|
+
continue;
|
|
267
159
|
if (rec === undefined) {
|
|
268
|
-
// durable 无行。**必须**静默满一个周期才退场:`a*` 子代行在父链接未解析时同样无 parentId,
|
|
269
|
-
// 与顶层行结构同形,而 `getRun(a*)` 必然 miss(见模块头收窄段)。还在出帧 = 活着的证据。
|
|
270
160
|
if (idle(row.id))
|
|
271
161
|
orphanExit(row, "durable_row_absent");
|
|
272
162
|
continue;
|
|
@@ -275,42 +165,31 @@ export function createFleetReconciler(deps) {
|
|
|
275
165
|
retire(row, rec);
|
|
276
166
|
continue;
|
|
277
167
|
}
|
|
278
|
-
// 🔴 **park 不是孤儿**(codex 对抗复审 R1-F1 [high],红先复现):`suspended` / `needs_review` 的行
|
|
279
|
-
// 还活着 —— `task_active` claim 还占着、checkpoint 还能被决议,而 fleet 契约(`fleetRunPublisher`
|
|
280
|
-
// 的 `onTerminal`)明写 park 态的行**留在面板上**(waiting / awaiting approval)。它们恰恰**不在**
|
|
281
|
-
// 任何在飞登记面里(park 的 run 没有活腿),所以上面那道活体谓词接不住它们 —— 不在这里显式跳过,
|
|
282
|
-
// 每一轮对账都会把一条合法的待审批任务从面板上摘掉,而用户看到的是"任务凭空消失"。
|
|
283
168
|
if (isParkedRunStatus(rec.status)) {
|
|
284
169
|
tally.skippedParked++;
|
|
285
170
|
continue;
|
|
286
171
|
}
|
|
287
|
-
// durable 还 `running` 而本副本没有它:发布方死了、durable 还没定局(reaper 宽限窗内),
|
|
288
|
-
// 或 run 活在别的副本上。两形处置相同 —— **不造终态**,只陈述离场。
|
|
289
172
|
orphanExit(row, rec.instanceId !== null && rec.instanceId !== (deps.instanceId ?? null) ? "durable_running_other_replica" : "durable_running_no_local_leg");
|
|
290
173
|
}
|
|
291
|
-
// ── ③ 无父可循的孤儿子行 ─────────────────────────────────────────────────────────────
|
|
292
|
-
// 判据里**没有** durable 读:bg 子代的真源在 core 侧 registry,server 不越界重判。
|
|
293
174
|
for (const row of snap.tasks) {
|
|
294
175
|
if (row.parentId === undefined || present.has(row.parentId))
|
|
295
176
|
continue;
|
|
296
177
|
if (!idle(row.id))
|
|
297
|
-
continue;
|
|
178
|
+
continue;
|
|
298
179
|
deps.bus.removeTask(row.id, { removeReason: "orphaned", ...(row.cycleSeq !== undefined ? { cycleSeq: row.cycleSeq } : {}) });
|
|
299
180
|
lastFrameAt.delete(row.id);
|
|
300
181
|
tally.orphaned++;
|
|
301
182
|
deps.metrics?.inc("fleet_rows_reconciled_total", { disposition: "orphaned_child" });
|
|
302
183
|
}
|
|
303
|
-
// ── ④ workflow 行:只做 durable 终局投影 ─────────────────────────────────────────────
|
|
304
184
|
if (wfGet) {
|
|
305
185
|
for (const wf of rotate(snap.workflows, wfCursor)) {
|
|
306
186
|
if (isTerminalWorkflowRowStatus(wf.status))
|
|
307
|
-
continue;
|
|
187
|
+
continue;
|
|
308
188
|
if (!budgetLeft()) {
|
|
309
189
|
wfCursor = wf.id;
|
|
310
190
|
break;
|
|
311
191
|
}
|
|
312
192
|
tally.reads++;
|
|
313
|
-
// A-067 C5(F7):同上 readRun——竞速一结束 finally 清(A-002.10 同款)。
|
|
314
193
|
let wfTimer;
|
|
315
194
|
const run = await Promise.race([
|
|
316
195
|
wfGet(wf.id),
|
|
@@ -325,8 +204,6 @@ export function createFleetReconciler(deps) {
|
|
|
325
204
|
});
|
|
326
205
|
if (!run || !isTerminalWorkflowStatus(run.status))
|
|
327
206
|
continue;
|
|
328
|
-
// 租户复核:`store.get` 是**无 scope 门**的裸读(带门的是 core 的 `getWorkflowRun`)——
|
|
329
|
-
// id 来自本进程的行,仍按真行的 scope 复核一次(同 fleet-terminal-window 的姿势)。
|
|
330
207
|
if (wf.scope !== undefined && run.scope !== wf.scope)
|
|
331
208
|
continue;
|
|
332
209
|
deps.bus.publishWorkflow(buildFleetWorkflowRow(wf.id, run));
|
|
@@ -337,12 +214,8 @@ export function createFleetReconciler(deps) {
|
|
|
337
214
|
}
|
|
338
215
|
}
|
|
339
216
|
catch (err) {
|
|
340
|
-
// F 类:读不出来 ≠ 该退休。**只向留行一侧** fail-open —— 库抖一下就把一屏在跑的任务从面板上
|
|
341
|
-
// 抹掉,比多留一条幽灵行伤得多。本周期已经做完的处置全部有效(它们各自都有 durable 证据)。
|
|
342
217
|
coolingUntil = now() + FLEET_RECONCILE_COOLDOWN_MS;
|
|
343
218
|
tally.failOpen = true;
|
|
344
|
-
// detail 用 `err.message` 而不是 `String(err)`:后者会调用抛出值自己的 toString,而那本身可能再抛
|
|
345
|
-
// (逃出本兜底,把降级变成故障)。非 Error 抛出值就如实说"不是 Error",不去问它任何问题。
|
|
346
219
|
recordFailOpen("server.fleet.reconcile-read-failed", err instanceof Error ? err.message : "fleet reconcile read threw a non-Error value");
|
|
347
220
|
}
|
|
348
221
|
return tally;
|
|
@@ -352,18 +225,8 @@ export function createFleetReconciler(deps) {
|
|
|
352
225
|
stop: unsubscribe,
|
|
353
226
|
};
|
|
354
227
|
}
|
|
355
|
-
/** 读预算到点的**具名**抛出值(与真实的店错误在日志里可分,且不会被误当成"店坏了"去查库)。 */
|
|
356
228
|
class ReadAborted extends Error {
|
|
357
229
|
}
|
|
358
|
-
/**
|
|
359
|
-
* 起对账定时器(60s 档,`unref`)+ 重入守卫。返回 handle 供收尾段 `clearInterval`。
|
|
360
|
-
*
|
|
361
|
-
* ⚠️ 装配点必须在 `createHttpServer` **之后** —— 活体谓词是 server 造出来的
|
|
362
|
-
* ({@link FleetReconcilerDeps.isLiveOnThisReplica});这也是本腿不并进 `boot/reapers.ts` 那只 tick 的
|
|
363
|
-
* 唯一原因(reaper 段按「位置即契约」必须在 server 之前建)。
|
|
364
|
-
*
|
|
365
|
-
* 重入守卫照 reapers 的四腿先例:本腿时长随 bus 行数与库延迟增长,短周期下无守卫会逐周期叠罗汉压同一批行。
|
|
366
|
-
*/
|
|
367
230
|
export function startFleetReconciler(deps) {
|
|
368
231
|
const reconciler = createFleetReconciler(deps);
|
|
369
232
|
let inFlight = false;
|
|
@@ -378,13 +241,10 @@ export function startFleetReconciler(deps) {
|
|
|
378
241
|
deps.logger?.info("fleet_reconcile_swept", { retired: t.retired, orphaned: t.orphaned, childrenSwept: t.childrenSwept, workflowsRetired: t.workflowsRetired, reads: t.reads });
|
|
379
242
|
}
|
|
380
243
|
}, (err) => {
|
|
381
|
-
// runOnce 自己已把读面的失败收成 fail-open;能到这里的只剩"对账腿自己有 bug"这一族。
|
|
382
|
-
// 观测绝不能变成故障(同 reapers 的 throttled catch 判据):整块 total/non-throwing。
|
|
383
244
|
try {
|
|
384
245
|
deps.logger?.warn("fleet_reconcile_failed", { err: err instanceof Error ? err.message : "non-Error throw" });
|
|
385
246
|
}
|
|
386
247
|
catch {
|
|
387
|
-
/* observability must never become the outage */
|
|
388
248
|
}
|
|
389
249
|
})
|
|
390
250
|
.finally(() => {
|