@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
package/dist/boot/runner-deps.js
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* design/158 A10:composition root 分段 —— `RunnerDeps` 装配(含 self-orchestration 成组段)。
|
|
3
|
-
*
|
|
4
|
-
* 纯搬运:两个字面量逐字来自 `main.ts`(原 1579-1881 行),缩进不变(顶层键仍在 4 空格,
|
|
5
|
-
* `deps-literal-shape-gate` 的顶层条件展开门覆盖面不变);新增的只有 import 与包壳。
|
|
6
|
-
*
|
|
7
|
-
* ⚠️ **位置即契约**:必须晚于 stores/exec-env/coordinators/workflow 段(所有键都是它们的产物),
|
|
8
|
-
* 且早于 `new Runner(runnerDeps)` —— Runner 构造会冻结 tier 展开后的私有目录副本
|
|
9
|
-
* (`runnerTierFrozen` 判据就取自构造那一刻的 `config.tiers`)。
|
|
10
|
-
* `getRunStore()` 是唯一的晚绑取值(runStore 在本段之后才构造),原文靠同作用域前向引用。
|
|
11
|
-
*/
|
|
12
1
|
import { createFileWorkflowScriptStore } from "@sema-agent/core";
|
|
13
2
|
import { join } from "node:path";
|
|
14
3
|
import { listCollabWorkflows, resolveCollabWorkflow } from "../capabilities/collab-workflows.js";
|
|
@@ -17,7 +6,7 @@ import { createHardenedVmRunner } from "../orchestration/hardened-vm-runner.js";
|
|
|
17
6
|
import { createWorkerHardenedVmRunner } from "../orchestration/hardened-vm-worker-runner.js";
|
|
18
7
|
import { WorkflowAgentRegistry } from "../orchestration/workflow-agent-steer.js";
|
|
19
8
|
import { resolveServedSession } from "../orchestration/workflow-completion-inbox.js";
|
|
20
|
-
import { defaultEngineNoticeRouter } from "../trace/engine-notice-wire.js";
|
|
9
|
+
import { defaultEngineNoticeRouter } from "../trace/engine-notice-wire.js";
|
|
21
10
|
import { WorkflowNotifyGate } from "../orchestration/workflow-notify-journal.js";
|
|
22
11
|
import { makeLoadProjectMemory, makeProbeInstructionSources } from "../project-memory.js";
|
|
23
12
|
import { workflowModelAllowlistFor } from "../task-workflow.js";
|
|
@@ -26,216 +15,68 @@ export function createRunnerDepsOnAsk(toolApproval) {
|
|
|
26
15
|
return undefined;
|
|
27
16
|
return (req, signal) => toolApproval.ask(req, signal);
|
|
28
17
|
}
|
|
29
|
-
/**
|
|
30
|
-
* core `EngineNotice` → 结构化 `engine_notice` 行的**唯一**转发体(#240②)。
|
|
31
|
-
*
|
|
32
|
-
* 🔴 为什么是具名导出而不是就地闭包(合并码重扫):这一席此前只落在共享基座里,于是 leader 车道
|
|
33
|
-
* (`src/leader/wire.ts` 自拼 deps 的五处 `new Runner({...})`)一处都没有 —— core 的契约是「接线 ⇒ 走
|
|
34
|
-
* sink,缺席 ⇒ 逐字打 `console.warn`」,所以缺席不是静默而是**同一部署两条通告通道**:主车道进结构化
|
|
35
|
-
* JSON 行,leader 车道落裸 stderr,按 code 采集(`tool_result.offload_put_failed` 等)的运维面漏掉后者。
|
|
36
|
-
* 两处各写一份转发体必漂(键名/字段集),故收成一个函数;入参取**结构形** logger(leader 的 cfg 只带
|
|
37
|
-
* 可选 `warn`/`info` 两格,不是全形 `Logger`)。
|
|
38
|
-
*
|
|
39
|
-
* 🔴 `warn` 是**必填**(codex 复审第一轮,验真后修):可选链 `logger.warn?.(…)` 形在「只装了 `info` 的
|
|
40
|
-
* logger」上会把通告**吞掉** —— 比不接线还坏(不接线时 core 至少还打它自己的 `console.warn`)。所以
|
|
41
|
-
* 「有没有 warn」这个判断留在**装配点**:没有就别铸这一席,让 core 的响亮权留在原处。
|
|
42
|
-
*
|
|
43
|
-
* ## #310:双终点分流器(设计稿 = 黑板 [4630])
|
|
44
|
-
* 本体自 #310 起是**分流器**,两个终点:
|
|
45
|
-
* 1. **日志(全族,逐字保留)** —— 上面那段契约一个字节不变:任何 code、detail 原样、缺 detail 不铸键。
|
|
46
|
-
* 运维观察面零回退是本腿的硬前提(wire 半场是**增量**,不是搬家)。
|
|
47
|
-
* 2. **wire(白名单 + sessionId 路由)** —— `router.route(notice)`:码在
|
|
48
|
-
* {@link import("../trace/engine-notice-wire.js").ENGINE_NOTICE_WIRE_CODES} 内**且** `detail.sessionId`
|
|
49
|
-
* 在场时,投给那条会话的 run 腿(SSE + durable 账本);否则一帧不出。判据整条住在
|
|
50
|
-
* `src/trace/engine-notice-wire.ts`(白名单/归属/消毒/隔离四件同源),这里只负责**先日志后分流**的次序。
|
|
51
|
-
*
|
|
52
|
-
* 🔴 次序是承重的:日志在前 ⇒ 即便 wire 半场整条坏掉(路由抛、口抛),事实仍然完整落在运维面。
|
|
53
|
-
* 反过来写就是「wire 故障吃掉运维日志」,那正是本仓 #157 纪律要根除的形。route 自身按 sink 隔离 +
|
|
54
|
-
* F 类留痕(`server.engine-notice.wire-sink-threw`),不向 core 回抛。
|
|
55
|
-
*
|
|
56
|
-
* 🔴 `router` **有默认值**(进程单例)而不是必填:这一席有五个以上装配点(共享基座 / leader 车道四处 /
|
|
57
|
-
* 未来任何新车道),必填会让"新车道忘了传 router"变成**静默半聋**(日志有、wire 无)——与本函数当初
|
|
58
|
-
* 被抽成具名导出的理由逐字同一个。测试要隔离时显式传自己 new 的实例。
|
|
59
|
-
*/
|
|
60
18
|
export function createEngineNoticeForwarder(logger, router = defaultEngineNoticeRouter) {
|
|
61
19
|
return (notice) => {
|
|
62
20
|
logger.warn("engine_notice", { code: notice.code, message: notice.message, ...(notice.detail !== undefined ? { detail: notice.detail } : {}) });
|
|
63
21
|
router.route(notice);
|
|
64
22
|
};
|
|
65
23
|
}
|
|
66
|
-
/**
|
|
67
|
-
* `onNotice` **席**的装配判据本身 —— 「`warn` 真在场才铸席」这一条从此是**一个可直接调用的函数**,
|
|
68
|
-
* 不是散在装配点、只能靠扫源码文本去猜的一行三元(codex 对抗复审 R1-[medium],验真后修)。
|
|
69
|
-
*
|
|
70
|
-
* 病(实测):把 leader 的门写成 `cfg.logger ? ((m, x) => cfg.logger?.warn?.(m, x)) : undefined` 时,
|
|
71
|
-
* 「装配点切片里出现过 `warn` 这个词」这类**源码文本**判据一律照绿 —— 而只装了 `info` 的部署会拿到一个
|
|
72
|
-
* truthy 闭包、照样铸席,通告随后被可选链**静默吞掉**,比不铸席更坏(不铸时 core 至少还打它自己的
|
|
73
|
-
* `console.warn`,响亮权留在原处)。任何「在这段文本里找关键字」的门都挡不住这一族变异,因为病灶在
|
|
74
|
-
* **值**(闭包 truthy)而不在字面。⇒ 把判据搬进函数,让它可以被**行为**测:info-only ⇒ 空席;带 warn ⇒
|
|
75
|
-
* 具名转发体。
|
|
76
|
-
*
|
|
77
|
-
* 命名(CLAUDE.md 工厂律):返回的袋子里装的是**活闭包**(有行为)⇒ `create*`,不是 `build*`。
|
|
78
|
-
* 返回**展开形**(`{}` 或 `{ onNotice }`)而不是 `onNotice: undefined`。理由是**键卫生**,不是 core 行为
|
|
79
|
-
* (R3 复扫更正:core 5.28 的 `deliverEngineNotice` 只判 `typeof onNotice === "function"`,显式 `undefined`
|
|
80
|
-
* 与键缺席在 core 那侧行为逐字相同、响亮权都留在 core——旧句「显式 undefined 也算 host 接管」与真码相反):
|
|
81
|
-
* 展开形让 `new Runner({...seat})` 的键集只随真装配变化,EXPECTED_SHARED_KEYS 类的键集绊线才数得准。
|
|
82
|
-
*/
|
|
83
24
|
export function createEngineNoticeSeat(logger, router = defaultEngineNoticeRouter) {
|
|
84
25
|
const warn = logger?.warn?.bind(logger);
|
|
85
26
|
return warn ? { onNotice: createEngineNoticeForwarder({ warn }, router) } : {};
|
|
86
27
|
}
|
|
87
|
-
// #289(core 5.43.0 #316 观测席,[4448] 表态② 的评估结论,如实登记):`onSecretEnvScrub` 席在 server
|
|
88
|
-
// 侧**无真挂点**——host lane 的执行 env(真跑用户 Bash 的那只)由 core 引擎自建,server 构造的三只
|
|
89
|
-
// NodeExecutionEnv(resolve-spec 裁决 env / parked-revive-gate 裁决 env / run-local 治理探测 env)都不
|
|
90
|
-
// 执行用户 Bash,挂席=假遥测面。终态=core 的 once-per-process console 摘要腿(5.43 起自带,响亮权在
|
|
91
|
-
// core);若未来 core 给 RunnerDeps 开执行 env 构造参透传席,再按表态制接(上游件,不在此仓旁路)。
|
|
92
28
|
export function createSharedRunnerDeps(ctx) {
|
|
93
|
-
// 具名带类型的字面量(非裸 return)——deps-literal-shape-gate 的 POINTS 按 `const X: T = {` 咬装配
|
|
94
|
-
// 字面量,裸 return 形在它的覆盖外(复审 2026-07-30 F5):conditional-spread 病在这里就会失检。
|
|
95
29
|
const shared = {
|
|
96
30
|
brain: ctx.brain,
|
|
97
|
-
// core 5.28.0 EngineNotice 席(#240②,^5.28.0 floor 的编译锚之一):结构化运维通告——function 席
|
|
98
|
-
// **替换** console.warn 行(core 契约:host 接管即拥有响亮权,不双发),故必须真转发不吞。
|
|
99
|
-
// 🔴 转发体是**全族开放**的:按 `notice.code` 原样落 `logger.warn`,detail 逐字透传,不认词表、
|
|
100
|
-
// 不挑族 —— 族表的单一真源是 core 的 `EngineNotice.code` doc(`dist/core/types.d.ts` 的
|
|
101
|
-
// "Current families"),**不在本注里复述**。A-057.25:此处原写死「三族(config.env_timeout_discarded /
|
|
102
|
-
// config.materialize_env_discarded / tool_result.offload_put_failed)」,那是 5.28.0 当拍的快照,
|
|
103
|
-
// 5.29→5.45 六个提货代际零回填后已脱节 3/13(5.45.0 新增的三条 `memory.*` 就在漏的那半里)——
|
|
104
|
-
// 一张会漂的孪生词表比没有词表更坏:它会让下一个读它的人以为遥测面只需覆盖那三个码。
|
|
105
|
-
// 共享基座=两 Runner(main/sub)同源同席([1543] 纪律)。
|
|
106
31
|
onNotice: createEngineNoticeForwarder(ctx.logger),
|
|
107
|
-
// core 1.265: the active tier table (tier words + CC aliases → catalog keys, expandTiers at Runner
|
|
108
|
-
// construction; empty = INERT by core contract). Same mutateInPlace reference applyEffective fills — a
|
|
109
|
-
// refresh-time tier change is restart-to-apply, same tier as models.
|
|
110
32
|
tiers: ctx.config.tiers,
|
|
111
33
|
models: ctx.config.models,
|
|
112
34
|
roles: ctx.config.roles,
|
|
113
35
|
pricing: ctx.pricing,
|
|
114
36
|
tracer: ctx.tracer,
|
|
115
|
-
// e/b([985]):center catalog 轴的 core 消费面——candidate/pinned-digest 解析走这里(prepare-task
|
|
116
|
-
// dist:session_start 优先 candidate、resume 按 digest 解析、miss=fail-loud prompt_snapshot_unavailable)。
|
|
117
37
|
promptSource: ctx.promptSource,
|
|
118
|
-
// #246(core 5.30.0):readFace/readDenyPatterns 部署座席——READ 容纳姿态是部署级承重面,主/子
|
|
119
|
-
// Runner 必须同源同席([1543] 纪律,与 onNotice 同理);缺席=undefined=core 引擎默认(roots+内建表)。
|
|
120
38
|
readFace: ctx.config.readFace ? ctx.config.readFace : undefined,
|
|
121
39
|
readDenyPatterns: ctx.config.readDenyPatterns ? ctx.config.readDenyPatterns : undefined,
|
|
122
|
-
// #253 件 G5(core 5.33.0 #245,clay 裁定件):**内建** deny 表的档位/删行两座席——与上面两键同席
|
|
123
|
-
// 同源(主/子 Runner 必须同姿态)。缺席=undefined=core 自默认档位(除 shell-history 外全开)。
|
|
124
|
-
// 🔴 `?? undefined` 而不是真值判:`readDenyBuiltinTiers: []` 是**显式的空姿态**(env 写 `none`),
|
|
125
|
-
// 真值判会把它折回「缺席=默认全开」——正好把运维显式关掉的档位偷偷开回去。
|
|
126
40
|
readDenyBuiltinTiers: ctx.config.readDenyBuiltinTiers ?? undefined,
|
|
127
41
|
readDenyBuiltinExclude: ctx.config.readDenyBuiltinExclude ?? undefined,
|
|
128
|
-
// #299(core 5.45.0 design/324 #324①):委派臂的证据标准 —— 与上面四席同族的**部署座席**,同样必须
|
|
129
|
-
// **主 runner / subRunner / run-local 三族**同源(本基座的射程,`run-local.test.ts` 的 SHARED_KEYS
|
|
130
|
-
// 编译期闭包 + `boot-runner-deps-shared-base.test.ts` 的键集绊线各钉一半)。core 明写「每个 run 读
|
|
131
|
-
// **准备它的那只 Runner** 的 deps」⇒ 漏挂 subRunner 不是「子代少个旋钮」,而是委派子代按**另一套**
|
|
132
|
-
// 证据标准判自己的污染臂(运维选的 attested-only 对它不生效),正是 [1543]§三族A 那个事故族的形。
|
|
133
|
-
// ⚠️ **leader lane 不在本基座射程**(如实登记,既有族级缺口非本席引入):`src/leader/wire.ts` 的
|
|
134
|
-
// Runner 是独立字面量,上面四席同样到不了那里;今日影响结构性为零(leader 不挂记忆后端,core 的
|
|
135
|
-
// 铸点要求污染面在场)。边界钉 = `test/memory-delegation-evidence-lane.test.ts` 的 ⑤ 组。
|
|
136
|
-
// 缺席=undefined=core 自缺省(`static-face`)。
|
|
137
42
|
memoryDelegationEvidence: ctx.config.memoryDelegationEvidence ?? undefined,
|
|
138
|
-
// #307 件4(core 5.46.0 design/336 §13-3):provenance 总开关 —— 与上一席**同族同姿态**的部署座席。
|
|
139
|
-
// 同样必须三族(主 runner / subRunner / run-local)同源:core「每个 run 读准备它的那只 Runner 的
|
|
140
|
-
// deps」⇒ 漏挂 subRunner = 委派子代按另一套 provenance 写记忆(部署声称「暴露会话零收录」而子代
|
|
141
|
-
// 照收)。leader lane 的族级缺口同上一席,边界钉在 `memory-delegation-evidence-lane.test.ts` ⑤ 组
|
|
142
|
-
// 的 DEPLOYMENT_SEATS 名单里(本席已入册)。缺席=undefined=core 自缺省(`carry`)。
|
|
143
43
|
memoryProvenance: ctx.config.memoryProvenance ?? undefined,
|
|
144
|
-
// debt #322-B(core 5.48 C18):委派入口 caps ——上两席同族的部署座席,三族(主/sub/run-local)
|
|
145
|
-
// 同源经本基座;缺席=undefined=core 自缺省(CC parity 20/200)。坏值双门:env 解析 numEnvBounded
|
|
146
|
-
// 启动期拒,pair 合法性(concurrent ≤ cumulative)core prepare `config.delegation_entry_caps` 拒。
|
|
147
44
|
delegationEntryCaps: ctx.config.delegationEntryCaps ?? undefined,
|
|
148
45
|
executionEnvFactory: ctx.executionEnvFactory ? ctx.executionEnvFactory : undefined,
|
|
149
46
|
lspManager: ctx.lspManager ? ctx.lspManager : undefined,
|
|
150
|
-
// core 1.364 durable bg agents 读半场(写半场=scenarioDeps.backgroundAgentStore 同实例,组装区注释)。
|
|
151
47
|
backgroundAgentStore: ctx.backgroundAgentStore ? ctx.backgroundAgentStore : undefined,
|
|
152
|
-
// S3c tier-3 懒复活(core 1.374):SendMessage 链内消费,与 backgroundAgentStore 同实例配套挂载。
|
|
153
48
|
mailboxStore: ctx.mailboxStore ? ctx.mailboxStore : undefined,
|
|
154
|
-
// [1070]① agent-team S1:持久名册 seam(具名 spawn advisory 写入;SendMessage 活注册表 miss 后咨询)。
|
|
155
49
|
rosterStore: ctx.rosterStore ? ctx.rosterStore : undefined,
|
|
156
50
|
hooks: ctx.deploymentHooks,
|
|
157
|
-
// 交接件⑤:署名座进基座 ⇒ 主/sub 两只 Runner 自动同源(理由见 RunnerDepsCtx.hands 的注)。
|
|
158
51
|
hands: ctx.hands,
|
|
159
52
|
toolResultStore: ctx.toolResultStore,
|
|
160
|
-
// E6: operator-tightened session tool rules — core folds them into the ToolPolicy FIRST (subtract-only) for tasks
|
|
161
|
-
// carrying a sessionId (a delegated subagent has none → inherits no rules). Opt-in: undefined ⇒ no rules read.
|
|
162
53
|
sessionPolicyStore: ctx.sessionPolicyStore ? ctx.sessionPolicyStore : undefined,
|
|
163
|
-
// design/170 件A:org 记忆准入两 seam(core 5.13.0)。共享基座=主/sub 同源(委托子代 prepare 的
|
|
164
|
-
// 委托冻结重判腿同样过目录);resolver 缺席=core 对 request-origin org 铸 admission_required
|
|
165
|
-
// fail-closed,deployment 自证集空=键缺席(诚实缺席>空数组——core 按 Set 语义消费,空集与缺席
|
|
166
|
-
// 同义,但缺席让 deps 字面量不携带死键)。
|
|
167
54
|
memoryScopeAdmission: ctx.orgMemoryAdmission.memoryScopeAdmission ? ctx.orgMemoryAdmission.memoryScopeAdmission : undefined,
|
|
168
55
|
deploymentMemoryScopes: ctx.orgMemoryAdmission.deploymentMemoryScopes && ctx.orgMemoryAdmission.deploymentMemoryScopes.length > 0 ? ctx.orgMemoryAdmission.deploymentMemoryScopes : undefined,
|
|
169
|
-
// design/166-T1:治理窗两键**成对**且进共享基座——主/sub/hook 三 runner 全覆盖(漏挂 subRunner=
|
|
170
|
-
// 子代用量不进窗,治理可被 subagent 刷穿;双记不存在:core stats.nested 是旁路侧栏不折入
|
|
171
|
-
// stats.tokens,governance.commit 是 per-任务 delta 制)。store 只在 config.usageWindows 配置时
|
|
172
|
-
// 构造(boot/stores.ts),两键同真同假。
|
|
173
56
|
usageWindows: ctx.config.usageWindows ? ctx.config.usageWindows : undefined,
|
|
174
57
|
usageWindowStore: ctx.usageWindowStore ? ctx.usageWindowStore : undefined,
|
|
175
|
-
// design/177 —— 必须进**共享基座**(codex 复审轮3 真缺口):它原先只挂在主 runnerDeps 上,于是
|
|
176
|
-
// 委托子代静默没有 memory_list/memory_read,而能力面与 HTTP 面照样宣布共享库可用 —— 正是 [1543]§三族A
|
|
177
|
-
// 「主 runner 挂了、subRunner 漏挂」那个病族。授权按 per-request principal 折叠(子代同宿主身份),
|
|
178
|
-
// 所以共享同一个 provider 实例既正确又是唯一能让两只 Runner 看到同一份库集合的做法。
|
|
179
58
|
sharedMemoryStores: ctx.sharedMemoryStores ? ctx.sharedMemoryStores : undefined,
|
|
180
|
-
// design/170 件B/C/D(#252 件1)—— 三个部署治理座席,同样必须进**共享基座**:合规档位的判决沿委托
|
|
181
|
-
// 树继承(core 按 principal 冻结一次),而委托子代在本仓跑在**另一只 Runner** 上 —— 那只 Runner 不
|
|
182
|
-
// 挂 resolver 就等于子代平面没有档位;`lockedConfig` 同理(§4.2 明写「覆盖 resume / refresh / 子代
|
|
183
|
-
// 构造三条路径」)。三键的缺席形都是 undefined = core 契约的「无限制/无锁/无策略」,诚实缺席。
|
|
184
59
|
compliancePostureResolver: ctx.governanceSeams.compliancePostureResolver,
|
|
185
60
|
lockedConfig: ctx.governanceSeams.lockedConfig,
|
|
186
61
|
retentionPolicy: ctx.governanceSeams.retentionPolicy,
|
|
187
|
-
// #324(core 5.50 design/338):撤销台账席进**共享基座** —— core 每次 MCP dispatch 前探
|
|
188
|
-
// isRevoked,委托子代跑在另一只 Runner 上,漏挂 subRunner = 子代平面绕过撤销([1543]§三族A 形,
|
|
189
|
-
// 且这条轴的绕过方向是 fail-OPEN:被中心撤掉的服务器在子代腿继续可调)。leader lane 零 MCP mount
|
|
190
|
-
// (`src/leader/wire.ts` 无 MCP 面)⇒ 席不达 leader 结构性零影响(memoryDelegationEvidence 同款登记)。
|
|
191
|
-
// 缺席=undefined=pre-338 语义(纯 env 部署,restart-signal 的删除向豁免也不生效——同一动作绑定)。
|
|
192
62
|
mcpRevocations: ctx.mcpRevocations ? ctx.mcpRevocations : undefined,
|
|
193
63
|
};
|
|
194
64
|
return shared;
|
|
195
65
|
}
|
|
196
66
|
export function createRunnerDeps(ctx) {
|
|
197
67
|
const { config, logger, metrics, localRoot, outcomeSink, elicitation, question, toolApproval, sessionStore, memoryEngine, memorySyncRunner, runtimeCapsResolver, fileSnapshotStore, permissionRuleStore, fleetBus, workflowRunStore, workflowJournalStore, workflowAgentRegistry, workflowNotifyGate, workflowCompletionInbox, deliverWorkflowCompletion, getRunStore, } = ctx;
|
|
198
|
-
// design/158 A10 留档发现②:共享基座——见 createSharedRunnerDeps 头注(main.ts 的第二处展开是
|
|
199
|
-
// 并行车道待办,未在本次改动内接线)。
|
|
200
68
|
const sharedRunnerDeps = createSharedRunnerDeps(ctx);
|
|
201
|
-
// S8 (design/98) + SVC-1: mount core's `run_workflow` under the hardened-vm sandbox when
|
|
202
|
-
// enabled (default OFF → core fail-closed, tool not mounted, zero impact). The tool STARTS a workflow and
|
|
203
|
-
// returns its runId IMMEDIATELY (the background-run half — the caller never blocks); the workflow runs to
|
|
204
|
-
// terminal in the background and fires core's in-process completion notify. Workflow-spawned children inherit
|
|
205
|
-
// a CONSERVATIVE baseline (handsReadOnly — read-only by default; loosen deliberately); the script may pick
|
|
206
|
-
// ONLY allow-listed model names (empty ⇒ it cannot pick → the workflow's default role).
|
|
207
|
-
//
|
|
208
|
-
// design/158 S4:三处装配点里**唯一**一组多键条件段 —— 提成带类型标注的中间 const 再整体展开进
|
|
209
|
-
// runnerDeps。标注位 `Pick<RunnerDeps, …>` 本身触发 TS 多余属性检查(键名写错 / 键根本不属于
|
|
210
|
-
// RunnerDeps ⇒ 编译期红),所以这不是把旁路挪个地方;组内可选键一律写成显式
|
|
211
|
-
// `k: cond ? expr : undefined`,不再用 `...(cond ? { k } : {})`。
|
|
212
69
|
const workflowModelAllowlist = workflowModelAllowlistFor(config);
|
|
213
70
|
const selfOrchestrationDeps = config.selfOrchestrationEnabled
|
|
214
71
|
? {
|
|
215
|
-
// worker_thread isolation (heap cap + terminate) when opted in (multi-tenant DoS hardening), else
|
|
216
|
-
// the faster in-process runner. Both run the same conformance-validated + probe-hardened membrane.
|
|
217
72
|
workflowScriptRunner: config.selfOrchestrationWorkerIsolation
|
|
218
73
|
? createWorkerHardenedVmRunner()
|
|
219
74
|
: createHardenedVmRunner(),
|
|
220
75
|
workflowRunStore: workflowRunStore ? workflowRunStore : undefined,
|
|
221
|
-
// SVC-2 (CORE-9 Part A): durable resume journal — core auto-wires it into the tool's startWorkflow, the
|
|
222
|
-
// `resumeFromRunId` tool input then replays the unchanged prefix (cross-replica when tidb/pg-backed). The
|
|
223
|
-
// store enforces scope in its WHERE (CORE-9 audit BLOCKER: a cross-tenant resumeFromRunId → empty → live).
|
|
224
76
|
workflowJournalStore: workflowJournalStore ? workflowJournalStore : undefined,
|
|
225
|
-
// 切片 1.5 / design/140 §6: the named-workflow registry seam — a COMPOSITE store.
|
|
226
|
-
// persist/load = core's file store under `<localDataRoot>/workflow-scripts` (the CC scriptPath-iterate
|
|
227
|
-
// face: every invocation's script lands on disk, the model edits + re-invokes with {scriptPath};
|
|
228
|
-
// containment is the file store's contract). resolveName consults the collab projection FIRST (center
|
|
229
|
-
// collab templates as `{TEAM_DISCUSSION_SCRIPT, defaultArgs}` entries; a collab id equal to a built-in
|
|
230
|
-
// name SHADOWS it — §6 1c) and falls back to the file store's `<name>.js` face (an operator-saved
|
|
231
|
-
// script is a named workflow too). list() = collab entries only (the file store deliberately doesn't
|
|
232
|
-
// enumerate — its dir mixes per-run scripts with saved names, core contract note); sync, so the
|
|
233
|
-
// entries reach the statically-built Workflow tool card.
|
|
234
77
|
workflowScriptStore: (() => {
|
|
235
78
|
const fileStore = createFileWorkflowScriptStore(join(config.localDataRoot ?? localRoot, "workflow-scripts"));
|
|
236
79
|
return {
|
|
237
|
-
// core 1.366 (B-4) scope 分区一致性标:persist/load 直转 core file 实现(per-scope 子目录,
|
|
238
|
-
// 真分区)——标是诚实声明;缺标=core 工具读侧拒/写侧跳(编译期必填字面量即为此设计)。
|
|
239
80
|
scopePartitioned: true,
|
|
240
81
|
persist: fileStore.persist.bind(fileStore),
|
|
241
82
|
load: fileStore.load.bind(fileStore),
|
|
@@ -243,66 +84,29 @@ export function createRunnerDeps(ctx) {
|
|
|
243
84
|
list: () => listCollabWorkflows(),
|
|
244
85
|
};
|
|
245
86
|
})(),
|
|
246
|
-
// SVC-5 (CORE-9 Part B): the opt-in steer handle-sink. When set, the tool's `agent()` runs STEERABLE and
|
|
247
|
-
// emits the live handle HERE (never into the script/runner — the host-context membrane stays closed). We
|
|
248
|
-
// register it by runId+label so POST /v1/workflows/:id/agents/:label/steer can route a steer to it, and
|
|
249
|
-
// unregister when the agent settles (result() settles on stream completion; a stale handle would only
|
|
250
|
-
// 409 `steering.not_running` anyway — this just bounds the map). A steered agent is NOT journaled (CORE-9.1
|
|
251
|
-
// limitation: its resume re-runs live), which is correct + documented.
|
|
252
87
|
onWorkflowAgentSpawn: workflowAgentRegistry
|
|
253
88
|
? (handle) => {
|
|
254
89
|
const unregister = workflowAgentRegistry.register(handle);
|
|
255
90
|
void Promise.resolve(handle.result()).then(unregister, unregister);
|
|
256
91
|
}
|
|
257
92
|
: undefined,
|
|
258
|
-
// workflowSizeGuideline: advisory size guidance injected into the
|
|
259
|
-
// Workflow tool card (core Wvs, CC 206 verbatim). Absent/unrestricted = byte-compat card.
|
|
260
93
|
workflowLimits: config.workflowSizeGuideline ? { sizeGuideline: config.workflowSizeGuideline } : undefined,
|
|
261
94
|
workflowGovernanceBaseline: {
|
|
262
|
-
// [824]① clay 拍 A 案(workflow 权限全面 CC parity):默认基线撤 handsReadOnly 钳 —— 主 LLM 与
|
|
263
|
-
// 子 agent 同 root 同信任域,主 LLM 本就能写这棵树([816] ask 门照管),单独钳子 agent 的安全增益≈0
|
|
264
|
-
// (只防绕路不防直路的门不是边界);实测产品代价=[814]A 死锁(写型 workflow agent 永远只读)。并发
|
|
265
|
-
// 写互踩按 CC 同姿用建议解决(worktree 契约话术+design/111 advisory),不用强制钳。要保守的 TOB
|
|
266
|
-
// 部署自己开 WORKFLOW_AGENTS_READONLY=true(config.workflowAgentsReadOnly)加回旧钳。
|
|
267
95
|
base: config.workflowAgentsReadOnly ? { handsReadOnly: true } : {},
|
|
268
|
-
// [824]②/[826]-core 1.291 worktree seam(TOB 旋钮回归腿):旋钮开启时 worktreeBase 配成
|
|
269
|
-
// overlay 形状 —— core 对 `agent({isolation:"worktree"})` 做 base 浅合并(非整体替换,
|
|
270
|
-
// workflow-primitives effectiveBaseline:{...base,...worktreeBase}),{handsReadOnly:false} 语义=
|
|
271
|
-
// 「只放写,其余基线全保留」。效果:保守部署里非隔离子 agent 仍只读,进了自有 worktree 的
|
|
272
|
-
// agent 恢复可写([814]A 写型 workflow 在 TOB 形态下不死锁)。A 案默认(旋钮 off)不配 worktreeBase。
|
|
273
96
|
worktreeBase: config.workflowAgentsReadOnly ? { handsReadOnly: false } : undefined,
|
|
274
|
-
// Model allowlist for the script's `agent({model})` picks: explicit
|
|
275
|
-
// SELF_ORCHESTRATION_MODELS wins; single-user defaults to the deployment's own catalog; multi-tenant
|
|
276
|
-
// keeps core's fail-closed empty default. Decision + rationale in workflowModelAllowlistFor.
|
|
277
97
|
workflowModelAllowlist: workflowModelAllowlist ? workflowModelAllowlist : undefined,
|
|
278
98
|
},
|
|
279
|
-
// SVC-1 at-least-once notify: route core's terminal notify THROUGH the gate (deliver-then-ack +
|
|
280
|
-
// journal dedup) instead of straight to log/meter, so a crash mid-delivery re-delivers on the next boot
|
|
281
|
-
// recovery sweep. When the gate is absent (memory backend / no journal) fall back to the bare
|
|
282
|
-
// log+meter delivery (at-most-once, the prior behavior — honest about the lost-on-crash window).
|
|
283
99
|
workflowCompletionNotifier: {
|
|
284
|
-
// ⚠️ design/158 S4 有意保留的展开:两臂**都非空**(要么 gate 造的 notifier,要么裸 notify 兜底),
|
|
285
|
-
// 不是「条件键」形——它合并的是同一必填键 `notify` 的两个来源,两来源都有类型,不构成
|
|
286
|
-
// 多余属性检查旁路(缺 notify 反而当场编译红)。
|
|
287
100
|
...(workflowNotifyGate
|
|
288
101
|
? workflowNotifyGate.buildNotifier()
|
|
289
102
|
: { notify: (input) => deliverWorkflowCompletion(input) }),
|
|
290
|
-
// core 1.232 (the CORE half of the poll-then-also-notify dedup): pollWorkflow fires this
|
|
291
|
-
// ONCE when the ORIGINATING session polls the run to a real terminal (timeout/cross-session polls
|
|
292
|
-
// don't) — drop that (session, runId)'s pending inbox entry + arm the served fence, so the push
|
|
293
|
-
// that would duplicate what the model just read is dead even across a shell restart. Session
|
|
294
|
-
// attribution mirrors resolveCompletionRoute's session half (payload id, else the run row).
|
|
295
103
|
ackServed: async (input) => {
|
|
296
104
|
if (!workflowCompletionInbox)
|
|
297
105
|
return;
|
|
298
106
|
try {
|
|
299
|
-
const sid = await resolveServedSession(input, getRunStore() ? (id) => getRunStore().getRun(id) : undefined);
|
|
107
|
+
const sid = await resolveServedSession(input, getRunStore() ? (id) => getRunStore().getRun(id) : undefined);
|
|
300
108
|
if (sid) {
|
|
301
109
|
await workflowCompletionInbox.markTerminalServed(sid, input.runId);
|
|
302
|
-
// The THIRD way an inbox entry disappears (besides the three stream-open drains
|
|
303
|
-
// and the owner-mismatch drop) — the model itself polled the run to terminal, so the push is
|
|
304
|
-
// suppressed. An "enqueue → ack within ms, but the shell showed nothing" report with THIS line
|
|
305
|
-
// means the completion went to the MODEL in-process (core injected it), not onto any stream.
|
|
306
110
|
logger.info("workflow_complete_ack_served", { route: "poll-served", sessionId: sid, runId: input.runId });
|
|
307
111
|
}
|
|
308
112
|
}
|
|
@@ -314,44 +118,16 @@ export function createRunnerDeps(ctx) {
|
|
|
314
118
|
}
|
|
315
119
|
: {};
|
|
316
120
|
const runnerDeps = {
|
|
317
|
-
// design/158 A10 留档发现②:brain/models/roles/tiers/pricing/tracer/promptSource/
|
|
318
|
-
// executionEnvFactory/lspManager/backgroundAgentStore/mailboxStore/rosterStore/hooks/
|
|
319
|
-
// toolResultStore/sessionPolicyStore —— 共享基座展开,见 createSharedRunnerDeps 头注
|
|
320
|
-
// (含每键各自的历史 rationale 注释,搬到了那个函数里,不在此重复)。
|
|
321
121
|
...sharedRunnerDeps,
|
|
322
|
-
// 交接件⑤:`hands` 已随共享基座展开(`...sharedRunnerDeps`)—— 这里**不再**手写同名键,
|
|
323
|
-
// 否则它会 override 展开、把 subRunner 重新甩开(本文件头注写死的那条:「不要再在任一调用点
|
|
324
|
-
// 手写同名键」)。判据([931]① branded 才署名)搬到了唯一的取值点 main.ts 的 `commitHands`。
|
|
325
|
-
// design/73 §1 (core 1.226 seam, clay 拍 2026-07-04 接): consume mechanical TaskOutcome facts into the
|
|
326
|
-
// outcome ledger — tidb/pg = SQL rows (coreOutcomeToLedgerRow mapping + verbatim `core_outcome` JSON so
|
|
327
|
-
// red-line ② oracleHadRedRun survives lossless), local = owner-only JSONL. Read-only v1: records facts,
|
|
328
|
-
// drives NO policy (§7.4 backtest gate stands). Fire-and-forget — a sink failure logs and never touches
|
|
329
|
-
// the run (core's emitTaskOutcome swallow-guards too). Emitters today: core runGoal terminal + any
|
|
330
|
-
// harness with a REAL mechanical oracle calling runner.emitTaskOutcome; plain runTask never auto-emits.
|
|
331
122
|
onTaskOutcome: outcomeSink
|
|
332
123
|
? (o) => {
|
|
333
124
|
metrics.inc("task_outcomes_total", { status: o.status, green: String(o.oracle?.green ?? "unknown") });
|
|
334
125
|
void outcomeSink.recordCore(o).catch((err) => logger.warn("task_outcome_record_failed", { runId: o.runId, err: String(err) }));
|
|
335
126
|
}
|
|
336
127
|
: undefined,
|
|
337
|
-
// E23: the live-only inbound-elicitation seam. core invokes it only for servers that opted in via
|
|
338
|
-
// McpServerSpec.elicitation (default OFF) AND only when this is wired — both must hold (doubly fail-closed).
|
|
339
128
|
onElicit: elicitation ? elicitation.elicit : undefined,
|
|
340
|
-
// §4④: the live AskUserQuestion seam. core mounts the tool when onQuestion is present + routes each ask here.
|
|
341
|
-
// #152([2703] 案二): with the coordinator wired the durable leg NO LONGER stamps spec.onQuestion
|
|
342
|
-
// (QUESTION_AWAITS_RESUME) — park-vs-live is decided per-leg by resolve-spec's live-aware question policy
|
|
343
|
-
// (live-stream leg → this coordinator; no-live-context leg → durable park). The sentinel is stamped only
|
|
344
|
-
// when the coordinator is absent (ASK_QUESTION_ENABLED off).
|
|
345
129
|
onQuestion: question ? question.question : undefined,
|
|
346
|
-
// live tool-approval 接缝 —— 语义与历史全部搬进 `createRunnerDepsOnAsk` 的头注(#168 件4:同一份
|
|
347
|
-
// 说明只留一处,不在装配点复述)。
|
|
348
130
|
onAsk: createRunnerDepsOnAsk(toolApproval),
|
|
349
|
-
// [822]② auto permission mode, deployment half: RunnerDeps.autoMode is the operator TRUST face of core's
|
|
350
|
-
// auto-mode classifier (1.276/1.277) — wiring it alone arms NOTHING (core requires the per-principal entitlement
|
|
351
|
-
// runtimeCaps.autoMode === true from center, fail-closed dark by default; see runtime-caps-resolver.ts). With
|
|
352
|
-
// both present, core screens every policy `ask` through the classifier (allow safe / deny hostile / leave the
|
|
353
|
-
// rest on the ask path → this bridge or durable park). Defaults-only config (core's rules/window); breaker-open
|
|
354
|
-
// is surfaced for observability.
|
|
355
131
|
autoMode: {
|
|
356
132
|
onBreakerOpen: (info) => {
|
|
357
133
|
metrics.inc("auto_mode_breaker_open_total");
|
|
@@ -359,24 +135,8 @@ export function createRunnerDeps(ctx) {
|
|
|
359
135
|
},
|
|
360
136
|
},
|
|
361
137
|
sessionStore,
|
|
362
|
-
// design/138 S1: the memory-engine switch — when present (single-user + engine on), core replaces the
|
|
363
|
-
// legacy memory path WHOLESALE per task (materialize → session file ops → harvest; no remember/recall
|
|
364
|
-
// tools). `memoryEngineDir` = the resolved config root (core derives the B3 control plane beside the
|
|
365
|
-
// memory dir). Absent (multi-tenant / MEMORY_ENGINE=off) ⇒ no deps.memoryBackend ⇒ memory dark.
|
|
366
138
|
memoryBackend: memoryEngine ? memoryEngine.backend : undefined,
|
|
367
139
|
memoryEngineDir: memoryEngine ? memoryEngine.root : undefined,
|
|
368
|
-
// (sharedMemoryStores 由共享基座展开携带 —— 主/sub 两只 Runner 同源,见 createSharedRunnerDeps。
|
|
369
|
-
// 它与 `memoryBackend` **正交且完全不桥接**:那条是本地记忆链(注入索引 + 文件投影 + harvest,
|
|
370
|
-
// 有写路径),这条是纯文档只读面,共享内容永不进注入块/索引、永不落模型可写盘、永不被 harvest。)
|
|
371
|
-
// S3-TOB 复审 F-9(operator 可观测底座):harvest 报告 → metrics(拒收/incident/patch 计数从此可见;
|
|
372
|
-
// core swallow-guard 保证 throwing consumer 不伤边界)。
|
|
373
|
-
// #231(core 5.27.0 提货,codex 复审 [medium] 验真后修):**拒收码进遥测**。此前本站点只读
|
|
374
|
-
// `ok`/`incident`/`patches` 三件,而受限会话(`memoryPersistenceCapable:false`)对磁盘分歧的处置
|
|
375
|
-
// 走的是 `report.inboundFindings`(`ok` 仍是 true、`incident` 缺席)⇒ core 承诺的「响亮点名」在
|
|
376
|
-
// 我方这一侧**一条日志一个计数都没有**:运维看不到本机上有多少字节因为受限而没被收编。逐 code
|
|
377
|
-
// 计数(词表是 core 的 `HarvestRejectionCode` 闭集,基数天然有界)+ 一条 warn。
|
|
378
|
-
// ⚠️ **不打路径**:记忆根下的文件名是用户内容(core 已把逐条 reason 通告给模型那一侧),运维面
|
|
379
|
-
// 只需要「哪一类、多少条」。计数用 `??` 兜住旧引擎缺席的两个数组(additive 字段,不是 fail-open 分支)。
|
|
380
140
|
onMemoryHarvestReport: memoryEngine
|
|
381
141
|
? (report, info) => {
|
|
382
142
|
metrics.inc("memory_harvest_total", { ok: String(report.ok), phase: info.phase, incident: report.incident?.kind ?? "none" });
|
|
@@ -392,102 +152,51 @@ export function createRunnerDeps(ctx) {
|
|
|
392
152
|
if (byCode.size > 0) {
|
|
393
153
|
logger.warn("memory_harvest_rejections", {
|
|
394
154
|
phase: info.phase,
|
|
395
|
-
// 逐 code 计数(排序固定,便于日志 diff);内容/路径一律不进这条线。
|
|
396
155
|
codes: [...byCode].sort(([a], [b]) => (a < b ? -1 : 1)).map(([code, count]) => `${code}=${count}`).join(","),
|
|
397
156
|
});
|
|
398
157
|
}
|
|
399
|
-
// 142-S2.5-W1: 成功 harvest 真有 patch 落地 = 本地记忆变了 ⇒ fire-and-forget 一轮同步
|
|
400
|
-
// (trigger 自带 inflight 节流:上一轮在飞则跳过,漏掉的变更下一轮全量补上)。
|
|
401
158
|
if (memorySyncRunner && report.ok && (report.patches?.add ?? 0) + (report.patches?.update ?? 0) > 0)
|
|
402
159
|
memorySyncRunner.trigger("harvest");
|
|
403
160
|
}
|
|
404
161
|
: undefined,
|
|
405
|
-
// (toolResultStore/sessionPolicyStore already carried by the shared-base spread above.)
|
|
406
|
-
// design/99 §K: per-principal runtime entitlements (allowWorkflows / forceDurableGate) resolved from center.
|
|
407
|
-
// Opt-in: undefined ⇒ NO per-principal restriction (tighten-only; deployment default governs). See above.
|
|
408
162
|
runtimeCapsResolver: runtimeCapsResolver ? runtimeCapsResolver : undefined,
|
|
409
|
-
// E19: working-tree snapshot/restore for rewind (+ the 2c artifact store). core snapshots each completed turn +
|
|
410
|
-
// restores on resumeAt when spec.rewindFiles is set, for ANY env when this store is wired (gate-split 1.134.0).
|
|
411
163
|
fileSnapshotStore: fileSnapshotStore ? fileSnapshotStore : undefined,
|
|
412
|
-
// #154 车二(core 5.18.0 design/179):持久化权限规则店 —— 引擎据它铸 `AskRequest.ruleSuggestions`
|
|
413
|
-
// 并把 `permissionRules.storeWired` 报成真。缺席=诚实缺席(零候选、storeWired:false),绝不占位。
|
|
414
164
|
permissionRuleStore: permissionRuleStore ? permissionRuleStore : undefined,
|
|
415
|
-
// (executionEnvFactory/lspManager already carried by the shared-base spread above.)
|
|
416
|
-
// design/129-B (core 1.240.0): the PROCESS-LEVEL background-child observer — spawn/tick/terminal
|
|
417
|
-
// for every bg delegation child, never dying with a leg. Feeds the fleet rows (launch 即有行, session-scoped
|
|
418
|
-
// children stay visible past the turn — the 缺口① fix) + the bg_notification frame on the
|
|
419
|
-
// always-open fleet stream (缺口②: idle completion delivery is immediate). Wired once per process.
|
|
420
165
|
onBackgroundChildEvent: fleetBackgroundChildPublisher(fleetBus, (msg, fields) => logger.info(msg, fields)),
|
|
421
|
-
// design/113 C4: inject CLAUDE.md + git narrative so a chat opens project-aware (like CC). The helper reads cwd via
|
|
422
|
-
// local fs/execFile — only meaningful when cwd is LOCAL (host/file lane); it stats the dir and returns null on a
|
|
423
|
-
// remote-sandbox cwd, so this is safe to wire generally, but we gate it to single-user (cwdHonored posture — the
|
|
424
|
-
// same lane where reading the local project for the caller isn't a confused-deputy hole) + the opt-out kill-switch.
|
|
425
166
|
loadProjectMemory: config.requirePrincipal !== true && config.projectMemoryEnabled ? makeLoadProjectMemory({ logger }) : undefined,
|
|
426
|
-
// core 1.302 instructions-change lane (板 [952]②): re-fingerprint the declared instruction file each turn so a
|
|
427
|
-
// mid-run edit surfaces as a tail attachment. STRICTLY host lane — on a remote-sandbox lane the instruction file
|
|
428
|
-
// lives in the container; a local re-read would fingerprint the wrong tree, so the probe is not wired there.
|
|
429
167
|
probeInstructionSources: config.remoteExec?.provider === "host" && config.requirePrincipal !== true && config.projectMemoryEnabled
|
|
430
168
|
? makeProbeInstructionSources()
|
|
431
169
|
: undefined,
|
|
432
|
-
|
|
433
|
-
...selfOrchestrationDeps, // S8 self-orchestration 全家桶(成组条件段;类型标注在上方 const)
|
|
434
|
-
// F8: surface best-effort compaction failures + the 1.22 prompt-cache low-hit warning (an
|
|
435
|
-
// unstable/poisoned prefix tanking cost) instead of silently swallowing them.
|
|
170
|
+
...selfOrchestrationDeps,
|
|
436
171
|
onError: (err, ctx) => {
|
|
437
|
-
// "degraded" (1.40) is an operational event, NOT a failure — the task still completes (on a cheaper
|
|
438
|
-
// model). Log it as a warning so it doesn't pollute error rates/alerts. The degraded_total metric
|
|
439
|
-
// comes from the tracer's task.degraded event.
|
|
440
172
|
if (ctx.phase === "degraded") {
|
|
441
173
|
logger.warn("task_degraded", { sessionId: ctx.sessionId, info: String(err) });
|
|
442
174
|
return;
|
|
443
175
|
}
|
|
444
|
-
// "prompt-constitution" (core 1.243): a stableSystem provider returned an ALREADY-
|
|
445
|
-
// assembled prompt (constitution anchor found); core passed it through un-doubled. The task is safe
|
|
446
|
-
// (guard un-doubles), but the provider is pre-1.243-shaped and should be upgraded to return only the
|
|
447
|
-
// role base. Warn — paired with the tracer's prompt_constitution_total{mode="provider-assembled"}.
|
|
448
176
|
if (ctx.phase === "prompt-constitution") {
|
|
449
177
|
logger.warn("prompt_provider_needs_upgrade", { sessionId: ctx.sessionId, info: String(err) });
|
|
450
178
|
return;
|
|
451
179
|
}
|
|
452
|
-
// "rewind" (E19 per-turn file snapshot): best-effort — a failed snapshot only makes that one turn
|
|
453
|
-
// non-rewindable; the task itself is unaffected. `too_large` is the EXPECTED shape on a big working
|
|
454
|
-
// tree (TOC user opening a 20G folder: enumerate hits the 256MB bound EVERY turn → an error-level
|
|
455
|
-
// line per turn reads like the run is broken). Downgrade to warn + count by code so a real store
|
|
456
|
-
// fault (enumerate_failed on a readable tree, blob-write errors) still stands out in the metric.
|
|
457
180
|
if (ctx.phase === "rewind") {
|
|
458
181
|
const code = /\((\w+)\)/.exec(String(err))?.[1] ?? "unknown";
|
|
459
182
|
logger.warn("rewind_snapshot_failed", { sessionId: ctx.sessionId, code, info: String(err) });
|
|
460
183
|
metrics.inc("rewind_snapshot_failed_total", { code });
|
|
461
184
|
return;
|
|
462
185
|
}
|
|
463
|
-
// "memory" (1.62, design/41): a best-effort post-task consolidation pass failed. The task already
|
|
464
|
-
// completed and its notes are safely appended (just not reconciled this round) — warn, fail-open,
|
|
465
|
-
// don't pollute error rates. (Consolidation cost still lands in model_cost_micro_usd via the tracer.)
|
|
466
186
|
if (ctx.phase === "memory") {
|
|
467
187
|
logger.warn("memory_consolidation_failed", { sessionId: ctx.sessionId, info: String(err) });
|
|
468
188
|
return;
|
|
469
189
|
}
|
|
470
|
-
// "mcp" (1.68): a broken MCP server was SKIPPED (fail-open) — the task still ran without
|
|
471
|
-
// that server's tools. Surface it as a warning + metric so a misconfigured server is observable, not silent.
|
|
472
190
|
if (ctx.phase === "mcp") {
|
|
473
191
|
logger.warn("mcp_server_unavailable", { sessionId: ctx.sessionId, info: String(err) });
|
|
474
192
|
metrics.inc("mcp_server_unavailable_total");
|
|
475
193
|
return;
|
|
476
194
|
}
|
|
477
|
-
// "a2a" (DESIGN-269 车1 件4):an unreachable A2A peer was SKIPPED (core's materialize is fail-open per
|
|
478
|
-
// peer, `MaterializedA2a.warnings`) — the task still ran with the healthy peers' tools. Same posture as
|
|
479
|
-
// the MCP arm one line up, and for the same reason: a配置错/临时不可达的 peer 必须**可观测**,但它
|
|
480
|
-
// 不是任务失败,落 error 级会把它混进真故障的告警面。⚠️ 这不是「静默兜底」:fail-open 的裁决属 core
|
|
481
|
-
// (它已经决定跳过并把原因交出来),server 这一格只负责让它说出来 + 计数。
|
|
482
195
|
if (ctx.phase === "a2a") {
|
|
483
196
|
logger.warn("a2a_peer_unavailable", { sessionId: ctx.sessionId, info: String(err) });
|
|
484
197
|
metrics.inc("a2a_peer_unavailable_total");
|
|
485
198
|
return;
|
|
486
199
|
}
|
|
487
|
-
// "prompt-cache" (1.22 low-hit + design/31 break detector): since core 1.89 the detector passes its
|
|
488
|
-
// root cause as ctx.classification — "server-or-ttl" is usually benign in agentic tasks (slow tools ⇒
|
|
489
|
-
// 5min+ request gaps expire provider caches) → warn; the prefix-bug causes
|
|
490
|
-
// (model-switch/tool-schema/tool-set/system-prefix) stay errors that warrant attention.
|
|
491
200
|
if (ctx.phase === "prompt-cache") {
|
|
492
201
|
metrics.inc("prompt_cache_low_hit_total");
|
|
493
202
|
const fields = { sessionId: ctx.sessionId, ...(ctx.classification ? { classification: ctx.classification } : {}), err: String(err) };
|
|
@@ -497,9 +206,6 @@ export function createRunnerDeps(ctx) {
|
|
|
497
206
|
logger.error("prompt_cache_break", fields);
|
|
498
207
|
return;
|
|
499
208
|
}
|
|
500
|
-
// "config" (core 1.300 [931]②): assembly-time advisories — e.g. toolPolicy 名单池审计
|
|
501
|
-
// (config.toolpolicy.unmatched_names:名单里写了实挂宇宙不存在的工具名=typo 探测,enforcement
|
|
502
|
-
// 不变)。观测性提示,warn+metric,不进 error 告警面。
|
|
503
209
|
if (ctx.phase === "config") {
|
|
504
210
|
logger.warn("runner_config_advisory", { sessionId: ctx.sessionId, info: String(err) });
|
|
505
211
|
metrics.inc("runner_config_advisory_total");
|
|
@@ -1,46 +1,11 @@
|
|
|
1
1
|
import { applyObserverEnvOptIn, centerEntitlementSourceWired, createPrincipalEntitlementsClient, scopedTokenNeedsWorker } from "../runtime-caps-resolver.js";
|
|
2
2
|
export function createRuntimeCaps(ctx) {
|
|
3
3
|
const { config, logger } = ctx;
|
|
4
|
-
// design/99 §K (core 1.157 `RunnerDeps.runtimeCapsResolver`) — the ENFORCE last-link of the
|
|
5
|
-
// three-stage workflows gate. core calls it once per task at prepare time with `spec.principal`; we resolve the
|
|
6
|
-
// per-principal entitlement from center's `GET /api/config/effective?principal=` (cached + fail-closed). Wired
|
|
7
|
-
// ONLY when a center is configured AND not in dry-run: in dry-run the service pulls+logs but does NOT APPLY
|
|
8
|
-
// center config, so it must NOT ENFORCE center's per-principal caps either (enforcing would deny workflows = a
|
|
9
|
-
// real behavior change, contradicting observe-only). Absent ⇒ core sees `undefined` ⇒ no per-principal
|
|
10
|
-
// restriction (the deployment-level capability + toolPolicy gates still govern).
|
|
11
|
-
//
|
|
12
|
-
// 🔐 TRUST DEPENDENCY: the gate keys off `spec.principal` (= resolveSpec's `auth.principal`). F-fix (2026-07-01,
|
|
13
|
-
// core-steered; contract-compliance per core 1.187's hardened `TaskSpec.principal` doc — it MUST be the
|
|
14
|
-
// cryptographically VERIFIED identity, never a spoofable header): `auth.principal` now comes from
|
|
15
|
-
// `verifiedPrincipal` (security.ts). On a GATED door that's `principalFrom` (the BFF already verified the header;
|
|
16
|
-
// `gatedPrincipal === principalFrom` there); on a DIRECT door (`directDoorActive`) it's the verified
|
|
17
|
-
// `x-approval-principal-token` JWT `sub`, NEVER the spoofable header. So `spec.principal` is ALWAYS the verified
|
|
18
|
-
// identity — governance (this gate), cost, and isolation key off it safely on BOTH postures. The same verified
|
|
19
|
-
// identity also fans out to the non-authorizer owner/cost sites that don't run createAuthorizer
|
|
20
|
-
// (runOwnerOk / quotaExceeded / leader / idemKey — they call `gatedPrincipal` directly). The invariant:
|
|
21
|
-
// spec.principal AND every principal-keyed security decision are VERIFIED. (Was a real direct-door spoof hole
|
|
22
|
-
// before this fix; latent until a multi-tenant direct door ships, but it is the only wall against it.)
|
|
23
|
-
// wpt_ scoped-token: RESOLVED (center ruling, sema-registry `aeb4979`). The earlier 1.14.0 guard
|
|
24
|
-
// (skip the resolver on a `wpt_` token, because center 403'd it for `?principal=`) is GONE — center now lets a
|
|
25
|
-
// worker-scoped `wpt_<self>` resolve its OWN worker's principal caps when we pass `?worker=<self>` (caps-only,
|
|
26
|
-
// never others' config). So we ALWAYS wire the resolver (configCenter + !dryRun) and pass `worker` =
|
|
27
|
-
// `SEMA_REGISTRY_WORKER` — it authorizes the wpt_ path and is harmless on a full token (caps are worker-
|
|
28
|
-
// independent). Per-principal workflow gating now truly works on the scoped-token topology (no more silent
|
|
29
|
-
// fleet-wide deny). (A wpt_ with no worker still 403s → fail-closed deny, the correct degrade.)
|
|
30
|
-
// MISCONFIG diagnostic (review MEDIUM): a wpt_<self> token with NO SEMA_REGISTRY_WORKER will 403 every caps
|
|
31
|
-
// fetch → fail-closed DENY ALL workflows (correct degrade, but otherwise only per-task warns). One-shot BOOT
|
|
32
|
-
// warning so it's diagnosable. (The orchestrator normally injects the worker alongside a wpt_ — hand-misconfig.)
|
|
33
4
|
if (config.configCenter && !config.configCenter.dryRun && scopedTokenNeedsWorker(config.configCenter.token, config.configCenter.worker)) {
|
|
34
5
|
logger.warn("runtime_caps_scoped_token_no_worker", {
|
|
35
6
|
reason: "SEMA_REGISTRY_TOKEN is a worker-scoped wpt_ token but SEMA_REGISTRY_WORKER is unset → center 403s per-principal caps → ALL workflow self-orchestration will be fail-closed denied. Set SEMA_REGISTRY_WORKER (the orchestrator normally injects it) or use the full SERVICE_PULL_TOKEN.",
|
|
36
7
|
});
|
|
37
8
|
}
|
|
38
|
-
// ONE per-principal caps client serves two faces off the same fetch/cache — `resolveRuntimeCaps`
|
|
39
|
-
// (core's seam, fail-closed) and `scenarioRuling` (resolveSpec's scenario gate, fail-open; center attaches the
|
|
40
|
-
// resolved {scenario, allowlist} to the caps body, single semantic source in center resolve-scenario.ts).
|
|
41
|
-
// #A5([4147] 件2):判据搬进 `centerEntitlementSourceWired` —— **同一只**谓词也被 `/v1/capabilities` 的
|
|
42
|
-
// `permissionModeAuto.entitlementSource` 披露位消费,于是「装配点认为有 entitlement 源」与「能力面对外
|
|
43
|
-
// 声称有源」结构上不可能分家(两处各写一份条件正是本仓在册的「诊断说亮、位说暗」病族入口)。
|
|
44
9
|
const principalCaps = centerEntitlementSourceWired(config) && config.configCenter
|
|
45
10
|
? createPrincipalEntitlementsClient({
|
|
46
11
|
baseUrl: config.configCenter.baseUrl,
|
|
@@ -49,12 +14,7 @@ export function createRuntimeCaps(ctx) {
|
|
|
49
14
|
onError: (err, principal) => logger.warn("runtime_caps_resolve_failed", { principal, err: String(err) }),
|
|
50
15
|
})
|
|
51
16
|
: undefined;
|
|
52
|
-
// 「entitlement resolver wired」语义源(enableForkFromBody / selfOrchestrationFromBody 的多租户 fail-close
|
|
53
|
-
// 判别):只有 center 背书的 caps client 算数 —— 下面的 env observer 基线不是 entitlement 源,不得改变它。
|
|
54
17
|
const centerRuntimeCapsResolver = principalCaps?.resolveRuntimeCaps;
|
|
55
|
-
// observer 开闸线 env 半场:EXPERIMENTAL_OBSERVER_AGENTS=true → 单用户部署把
|
|
56
|
-
// allowObservers:true 作部署基线合成(center caps 带键则 center 赢);多租户不认 env(boot warn 一次,
|
|
57
|
-
// 行为零变)。center caps 的 allowObservers 键本身在 toCoreRuntimeCaps 宽读透传(缺键=core 默认 OFF)。
|
|
58
18
|
const runtimeCapsResolver = applyObserverEnvOptIn(centerRuntimeCapsResolver, {
|
|
59
19
|
experimentalObserverAgents: config.experimentalObserverAgents,
|
|
60
20
|
requirePrincipal: config.requirePrincipal,
|