@sema-agent/server 7.137.0 → 7.139.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/MIGRATION.md +600 -142
- package/README.md +7 -3
- package/README.zh-CN.md +6 -3
- package/USAGE.md +132 -41
- package/deploy/sema-up/README.md +1 -1
- package/deploy/sema-up/lib/lanes.json +3 -2
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +23 -16
- package/dist/approval-card.js +1 -0
- package/dist/audit.js +1 -0
- package/dist/background-agent-name.d.ts +5 -0
- package/dist/background-agent-name.js +5 -0
- package/dist/bench/s1/arms.d.ts +1 -1
- package/dist/bench/s1/arms.js +1 -3
- package/dist/bench/s1/run-firm.js +2 -2
- package/dist/boot/budget-tracing.d.ts +1 -12
- package/dist/boot/deployment-mods.d.ts +46 -16
- package/dist/boot/deployment-mods.js +82 -6
- package/dist/boot/device-lane.d.ts +8 -3
- package/dist/boot/device-lane.js +7 -2
- package/dist/boot/execution-env.d.ts +4 -2
- package/dist/boot/execution-env.js +16 -24
- package/dist/boot/execution-lane.d.ts +1 -1
- package/dist/boot/governance-seams.d.ts +12 -18
- package/dist/boot/governance-seams.js +10 -24
- package/dist/boot/leader.d.ts +3 -0
- package/dist/boot/leader.js +1 -0
- package/dist/boot/memory-consolidation.js +2 -2
- package/dist/boot/org-delivery.js +15 -2
- package/dist/boot/resolve-spec.d.ts +4 -1
- package/dist/boot/resolve-spec.js +29 -19
- package/dist/boot/retention-lane.d.ts +14 -8
- package/dist/boot/retention-lane.js +2 -8
- package/dist/boot/runner-deps.d.ts +10 -4
- package/dist/boot/runner-deps.js +2 -0
- package/dist/boot/session-faces.d.ts +0 -3
- package/dist/boot/session-faces.js +15 -8
- package/dist/boot/stage-02-web-admin-pull.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -12
- package/dist/boot/stage-05-execution-env.d.ts +3 -12
- package/dist/boot/stage-05-execution-env.js +8 -5
- package/dist/boot/stage-06-runners.d.ts +3 -12
- package/dist/boot/stage-06-runners.js +5 -3
- package/dist/boot/stage-07-capability-layer.d.ts +3 -12
- package/dist/boot/stage-07-capability-layer.js +2 -2
- package/dist/boot/stage-08-reapers.d.ts +3 -12
- package/dist/boot/stage-09-leader.d.ts +3 -12
- package/dist/boot/stage-09-leader.js +2 -3
- package/dist/boot/stage-10-http-server.d.ts +3 -12
- package/dist/boot/stage-10-http-server.js +5 -3
- package/dist/boot/stores.js +4 -4
- package/dist/boot/web-admin.d.ts +5 -2
- package/dist/boot/web-admin.js +5 -5
- package/dist/brain.js +5 -5
- package/dist/budget.d.ts +17 -15
- package/dist/budget.js +2 -2
- package/dist/capabilities/mcp-probe.d.ts +36 -11
- package/dist/capabilities/mcp-probe.js +44 -5
- package/dist/capabilities/scenarios.d.ts +1 -1
- package/dist/capability-facts.d.ts +21 -7
- package/dist/capability-facts.js +13 -3
- package/dist/checkpoint-identity.d.ts +13 -6
- package/dist/config-catalog.js +14 -8
- package/dist/config-invariants.d.ts +23 -3
- package/dist/config-invariants.js +42 -0
- package/dist/config-provider.d.ts +19 -24
- package/dist/config-provider.js +27 -12
- package/dist/config-types.d.ts +25 -12
- package/dist/config.d.ts +33 -0
- package/dist/config.js +52 -20
- package/dist/delegated-session-owner.d.ts +2 -2
- package/dist/deployment-shape.d.ts +7 -7
- package/dist/device-enrollment.d.ts +41 -2
- package/dist/device-enrollment.js +27 -12
- package/dist/device-store.d.ts +58 -85
- package/dist/device-store.js +19 -49
- package/dist/device-ws-hub.js +2 -1
- package/dist/env-name-allowlist-knobs.d.ts +5 -4
- package/dist/exec-cut.d.ts +60 -0
- package/dist/exec-cut.js +36 -0
- package/dist/execution-lane-caps.d.ts +19 -0
- package/dist/execution-lane-caps.js +10 -0
- package/dist/execution-placement.d.ts +259 -0
- package/dist/execution-placement.js +199 -0
- package/dist/field-conflict.d.ts +3 -2
- package/dist/field-conflict.js +1 -0
- package/dist/gate-settlement.d.ts +71 -0
- package/dist/gate-settlement.js +40 -0
- package/dist/hooks/classic-stations.d.ts +1 -0
- package/dist/hooks/classic-stations.js +1 -0
- package/dist/hooks/command-spawn.d.ts +2 -2
- package/dist/hooks/hook-runner.js +14 -14
- package/dist/hosted-posture.d.ts +2 -2
- package/dist/http/admission.js +10 -19
- package/dist/http/checkpoint-ctx.d.ts +21 -12
- package/dist/http/checkpoint-ctx.js +4 -2
- package/dist/http/claimed-run.d.ts +1 -1
- package/dist/http/dispatch.d.ts +4 -0
- package/dist/http/dispatch.js +3 -0
- package/dist/http/durable-run-leg.js +12 -6
- package/dist/http/execution-context.d.ts +218 -0
- package/dist/http/execution-context.js +330 -0
- package/dist/http/memory-compliance-failure-reply.js +3 -0
- package/dist/http/resume-legs.d.ts +5 -11
- package/dist/http/resume-legs.js +179 -104
- package/dist/http/route-ctx.d.ts +44 -59
- package/dist/http/route-ctx.js +2 -5
- package/dist/http/routes/a2a-serve.js +10 -4
- package/dist/http/routes/agents-roster.d.ts +1 -1
- package/dist/http/routes/agents-roster.js +5 -1
- package/dist/http/routes/approvals-assistant.js +6 -6
- package/dist/http/routes/background.d.ts +29 -1
- package/dist/http/routes/background.js +29 -2
- package/dist/http/routes/capabilities.js +12 -10
- package/dist/http/routes/devices.d.ts +13 -19
- package/dist/http/routes/devices.js +21 -26
- package/dist/http/routes/mcp-reconnect.d.ts +3 -2
- package/dist/http/routes/mcp-reconnect.js +7 -5
- package/dist/http/routes/memory-consolidation.d.ts +1 -1
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/rules.js +3 -3
- package/dist/http/routes/runs.js +11 -7
- package/dist/http/routes/session-sync.js +110 -15
- package/dist/http/routes/sessions.d.ts +6 -0
- package/dist/http/routes/sessions.js +119 -13
- package/dist/http/routes/side-query.d.ts +12 -4
- package/dist/http/routes/side-query.js +6 -8
- package/dist/http/routes/tasks.js +800 -782
- package/dist/http/server.d.ts +61 -39
- package/dist/http/server.js +11 -0
- package/dist/http/session-inherit-env.d.ts +3 -4
- package/dist/http/session-inherit-env.js +1 -1
- package/dist/http/wire-types.d.ts +22 -18
- package/dist/identity-source.d.ts +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/leader/wire.d.ts +7 -0
- package/dist/leader/wire.js +5 -4
- package/dist/mcp-assertion-header.d.ts +51 -40
- package/dist/mcp-assertion-header.js +10 -11
- package/dist/mcp-authorization-face.d.ts +27 -0
- package/dist/mcp-authorization-face.js +15 -0
- package/dist/memory-operator-faces.d.ts +13 -4
- package/dist/memory-operator-faces.js +1 -17
- package/dist/memory-sync-client.d.ts +53 -14
- package/dist/memory-sync-client.js +187 -92
- package/dist/memory-sync.d.ts +1 -1
- package/dist/memory-sync.js +3 -2
- package/dist/model-route-gap.d.ts +6 -22
- package/dist/model-route-gap.js +7 -5
- package/dist/mods-declaration.d.ts +110 -0
- package/dist/mods-declaration.js +109 -0
- package/dist/observability/cost-taxonomy.d.ts +2 -2
- package/dist/observability/err-text.d.ts +5 -0
- package/dist/observability/err-text.js +9 -0
- package/dist/observability/fail-open.d.ts +17 -1
- package/dist/observability/fail-open.js +17 -1
- package/dist/observability/run-terminal.js +0 -1
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/orchestration/workflow-notify-journal.js +4 -4
- package/dist/org-memory-admission.d.ts +4 -3
- package/dist/org-memory-admission.js +6 -6
- package/dist/parked-decide.d.ts +49 -11
- package/dist/parked-decide.js +25 -26
- package/dist/parked-revive-surface.d.ts +12 -15
- package/dist/parked-revive-surface.js +3 -6
- package/dist/peer-seat.d.ts +156 -0
- package/dist/peer-seat.js +273 -0
- package/dist/permission-rule-vocab.d.ts +7 -7
- package/dist/permission-rule-vocab.js +3 -3
- package/dist/plain-string-record.d.ts +38 -0
- package/dist/plain-string-record.js +38 -0
- package/dist/plugins/approval-ask-store-file.d.ts +7 -0
- package/dist/plugins/approval-ask-store-file.js +11 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +6 -0
- package/dist/plugins/approval-ask-store-memory.js +12 -0
- package/dist/plugins/approval-ask-store-sql.d.ts +22 -5
- package/dist/plugins/approval-ask-store-sql.js +30 -12
- package/dist/plugins/background-agent-store-sql.js +6 -3
- package/dist/plugins/caching-session-store.d.ts +11 -2
- package/dist/plugins/caching-session-store.js +15 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +21 -25
- package/dist/plugins/checkpoint-store-sql.js +13 -15
- package/dist/plugins/device-store-sql.d.ts +25 -51
- package/dist/plugins/device-store-sql.js +49 -103
- package/dist/plugins/execution-placement-sql.d.ts +151 -0
- package/dist/plugins/execution-placement-sql.js +223 -0
- package/dist/plugins/file-history-store-sql.d.ts +7 -6
- package/dist/plugins/file-history-store-sql.js +8 -7
- package/dist/plugins/file-run-store.d.ts +6 -1
- package/dist/plugins/file-run-store.js +4 -0
- package/dist/plugins/fork-routing-session-store.d.ts +6 -0
- package/dist/plugins/fork-routing-session-store.js +16 -0
- package/dist/plugins/k8s-pod-reaper.d.ts +2 -8
- package/dist/plugins/k8s-pod-reaper.js +3 -3
- package/dist/plugins/local-checkpoint-store.d.ts +1 -11
- package/dist/plugins/local-checkpoint-store.js +0 -1
- package/dist/plugins/local-session-store.d.ts +183 -45
- package/dist/plugins/local-session-store.js +412 -105
- package/dist/plugins/mailbox-store-sql.d.ts +11 -3
- package/dist/plugins/mailbox-store-sql.js +103 -15
- package/dist/plugins/memory-key-guards.d.ts +4 -0
- package/dist/plugins/memory-key-guards.js +1 -0
- package/dist/plugins/memory-run-store.d.ts +1 -1
- package/dist/plugins/memory-sync-store-pg.d.ts +16 -5
- package/dist/plugins/memory-sync-store-tidb.d.ts +3 -3
- package/dist/plugins/one-time-migrations.d.ts +117 -6
- package/dist/plugins/one-time-migrations.js +383 -14
- package/dist/plugins/outcome-ledger-sql.d.ts +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +13 -15
- package/dist/plugins/permission-rule-store-sql.js +34 -29
- package/dist/plugins/pg-pool.d.ts +7 -3
- package/dist/plugins/pg-session-storage.d.ts +41 -22
- package/dist/plugins/pg-session-storage.js +136 -55
- package/dist/plugins/remote-env-adb.d.ts +22 -4
- package/dist/plugins/remote-env-adb.js +70 -62
- package/dist/plugins/remote-env-device.d.ts +32 -12
- package/dist/plugins/remote-env-device.js +18 -17
- package/dist/plugins/remote-env-e2b.d.ts +19 -3
- package/dist/plugins/remote-env-e2b.js +41 -42
- package/dist/plugins/remote-env-file-error.d.ts +2 -0
- package/dist/plugins/remote-env-file-error.js +1 -1
- package/dist/plugins/remote-env-host.d.ts +23 -8
- package/dist/plugins/remote-env-host.js +66 -70
- package/dist/plugins/remote-env-k8s.d.ts +13 -16
- package/dist/plugins/remote-env-k8s.js +61 -54
- package/dist/plugins/remote-env-local-docker.d.ts +30 -5
- package/dist/plugins/remote-env-local-docker.js +46 -59
- package/dist/plugins/remote-env-ssh.d.ts +18 -4
- package/dist/plugins/remote-env-ssh.js +72 -56
- package/dist/plugins/remote-shell.d.ts +100 -3
- package/dist/plugins/remote-shell.js +166 -2
- package/dist/plugins/retention-store-sql.d.ts +23 -8
- package/dist/plugins/retention-store-sql.js +13 -1
- package/dist/plugins/run-store-sql.d.ts +13 -3
- package/dist/plugins/run-store-sql.js +5 -0
- package/dist/plugins/schema-consistency.d.ts +15 -5
- package/dist/plugins/schema-consistency.js +14 -8
- package/dist/plugins/schema-drift-sentence.d.ts +27 -0
- package/dist/plugins/schema-drift-sentence.js +38 -0
- package/dist/plugins/session-fork.d.ts +63 -12
- package/dist/plugins/session-fork.js +38 -21
- package/dist/plugins/session-ownership.d.ts +7 -0
- package/dist/plugins/session-ownership.js +5 -0
- package/dist/plugins/session-row-sql.d.ts +22 -0
- package/dist/plugins/session-row-sql.js +81 -0
- package/dist/plugins/session-store.d.ts +1 -1
- package/dist/plugins/session-workspace-cell.d.ts +17 -0
- package/dist/plugins/session-workspace-cell.js +38 -0
- package/dist/plugins/store-backend.d.ts +1 -1
- package/dist/plugins/store-backend.js +26 -14
- package/dist/plugins/store-contracts.d.ts +25 -5
- package/dist/plugins/tidb-pool.d.ts +12 -7
- package/dist/plugins/tidb-pool.js +15 -3
- package/dist/plugins/tidb-session-store.d.ts +74 -28
- package/dist/plugins/tidb-session-store.js +132 -53
- package/dist/plugins/tool-result-store-sql.d.ts +16 -8
- package/dist/plugins/tool-result-store-sql.js +26 -17
- package/dist/plugins/worktree-isolation.d.ts +3 -2
- package/dist/plugins/worktree-isolation.js +1 -7
- package/dist/project-identity.d.ts +1 -14
- package/dist/project-identity.js +0 -4
- package/dist/project-memory.d.ts +9 -15
- package/dist/project-memory.js +5 -4
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +6 -7
- package/dist/request-value-closure.js +1 -3
- package/dist/rules-consent.js +6 -4
- package/dist/run-local.d.ts +6 -0
- package/dist/run-local.js +36 -26
- package/dist/runs.d.ts +9 -2
- package/dist/runs.js +9 -2
- package/dist/sandbox-git-plane.d.ts +2 -2
- package/dist/security.d.ts +38 -12
- package/dist/security.js +8 -2
- package/dist/server-secret-env.d.ts +15 -8
- package/dist/server-secret-env.js +4 -2
- package/dist/session-children-retire.d.ts +27 -9
- package/dist/session-children-retire.js +9 -5
- package/dist/session-incarnation.d.ts +19 -10
- package/dist/session-incarnation.js +5 -3
- package/dist/session-row.d.ts +114 -5
- package/dist/session-row.js +55 -5
- package/dist/session-titler.d.ts +2 -2
- package/dist/session-workspace.d.ts +130 -0
- package/dist/session-workspace.js +83 -0
- package/dist/spec-fields.d.ts +1 -1
- package/dist/standing-answer-grant.d.ts +2 -13
- package/dist/standing-answer-grant.js +0 -7
- package/dist/task-a2a.d.ts +44 -14
- package/dist/task-a2a.js +46 -20
- package/dist/task-cwd.d.ts +6 -1
- package/dist/task-mcp.d.ts +33 -20
- package/dist/task-mcp.js +46 -22
- package/dist/tool-approval.d.ts +38 -8
- package/dist/tool-approval.js +57 -13
- package/dist/trace/core-keyset-guard.d.ts +33 -18
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.d.ts +20 -1
- package/dist/trace/exit-seat.js +3 -0
- package/dist/trace/extension-call-face.d.ts +33 -0
- package/dist/trace/extension-call-face.js +39 -0
- package/dist/trace/project.d.ts +26 -7
- package/dist/trace/project.js +30 -3
- package/dist/trace/redact.js +42 -13
- package/dist/trace/self-minted-wire.d.ts +240 -12
- package/dist/trace/self-minted-wire.js +100 -4
- package/dist/trace/wire-projection-faces.d.ts +6 -6
- package/dist/trace/wire-projection-faces.js +6 -5
- package/dist/url-refusal.d.ts +1 -1
- package/dist/user-authored-text.d.ts +2 -2
- package/dist/user-authored-text.js +16 -1
- package/dist/web-admin-client/apply-effective.d.ts +17 -3
- package/dist/web-admin-client/apply-effective.js +20 -10
- package/dist/web-admin-client/center-request.d.ts +3 -2
- package/dist/web-admin-client/center-request.js +2 -3
- package/dist/web-admin-client/skills-mcp.d.ts +8 -4
- package/dist/web-admin-client/skills-mcp.js +32 -18
- package/dist/web-admin-client/types.d.ts +11 -0
- package/package.json +3 -3
- package/wire-changes/server@7.138.0.json +446 -0
- package/wire-changes/server@7.139.0.json +348 -0
- package/dist/http/device-placement.d.ts +0 -175
- package/dist/http/device-placement.js +0 -145
- package/dist/http/mcp-remote-text.d.ts +0 -5
- package/dist/http/mcp-remote-text.js +0 -7
|
@@ -4,6 +4,7 @@ import { createHostLspManager } from "../host-lsp-manager.js";
|
|
|
4
4
|
import { TaskEnvRegistry } from "../capabilities/sandbox-file-send.js";
|
|
5
5
|
import { DEPLOYMENT_SHAPE_PREDICATES } from "../deployment-shape.js";
|
|
6
6
|
import { SessionEnvironmentSelection } from "../capabilities/select-environment-tool.js";
|
|
7
|
+
import { sandboxEnvNamesInForce } from "../config.js";
|
|
7
8
|
import { createE2bLspManager } from "../lsp/e2b-manager.js";
|
|
8
9
|
import { evictLspOnDestroy } from "../lsp-evict.js";
|
|
9
10
|
import { PerTaskImageRegistry } from "../per-task-image.js";
|
|
@@ -11,7 +12,7 @@ import { adbExecutionEnvFactory } from "../plugins/remote-env-adb.js";
|
|
|
11
12
|
import { deviceExecutionEnvFactory } from "../plugins/remote-env-device.js";
|
|
12
13
|
import { e2bExecutionEnvFactory } from "../plugins/remote-env-e2b.js";
|
|
13
14
|
import { hostExecutionEnvFactory, RemoteHostExecutionEnv } from "../plugins/remote-env-host.js";
|
|
14
|
-
import { boundedStoreCall, checkSandboxEgressPolicy, createSandboxPodApi, createSpaceReclaimer,
|
|
15
|
+
import { boundedStoreCall, checkSandboxEgressPolicy, createSandboxPodApi, createSpaceReclaimer, k8sExecutionEnvFactory, readSandboxSecretSeat, rpcTimeoutMsOf } from "../plugins/remote-env-k8s.js";
|
|
15
16
|
import { podSpecPatchBrokerRefusal, SANDBOX_SECRET_SEAT_VERBS } from "../plugins/k8s-exec-protocol.js";
|
|
16
17
|
import { judgeSandboxGitPlane, runIdentitySourceOf, sandboxBrokerSeatOf, sandboxGitPlaneAsksSecretSeat, sandboxGitPlanePremisesOf } from "../sandbox-git-plane.js";
|
|
17
18
|
import { createSandboxPodReaper } from "../plugins/k8s-pod-reaper.js";
|
|
@@ -43,24 +44,6 @@ function boundedSessionSetter(map, maxEntries) {
|
|
|
43
44
|
map.delete(map.keys().next().value);
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
|
-
function forwardedSandboxEnvKeys(remoteExec) {
|
|
47
|
-
switch (remoteExec.provider) {
|
|
48
|
-
case "e2b":
|
|
49
|
-
case "k8s":
|
|
50
|
-
return Object.keys(remoteExec.sandboxEnv ?? {}).sort();
|
|
51
|
-
case "local-docker":
|
|
52
|
-
return Object.keys(remoteExec.env ?? {}).sort();
|
|
53
|
-
case "ssh":
|
|
54
|
-
case "adb":
|
|
55
|
-
case "host":
|
|
56
|
-
case "device":
|
|
57
|
-
return [];
|
|
58
|
-
default: {
|
|
59
|
-
const unreachable = remoteExec;
|
|
60
|
-
throw new Error(`unhandled remote-exec provider: ${String(unreachable.provider)}`);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
47
|
function buildSandboxLaneEnv(config, explicit) {
|
|
65
48
|
const secretEnv = { ...(explicit ?? {}) };
|
|
66
49
|
const env = Object.fromEntries(Object.entries(derivePkgSourceEnv(config.sandboxPkgSource, config.sandboxPkgSourceCustom)).filter(([name]) => !Object.hasOwn(secretEnv, name)));
|
|
@@ -173,7 +156,7 @@ export async function ensureSandboxSecretSeat(k8sCfg, logger, deps, read = () =>
|
|
|
173
156
|
const names = Object.keys(k8sCfg.podSecretEnv ?? {});
|
|
174
157
|
if (names.length === 0)
|
|
175
158
|
return;
|
|
176
|
-
const namespace = k8sCfg.namespace
|
|
159
|
+
const namespace = k8sCfg.namespace;
|
|
177
160
|
const seat = await read();
|
|
178
161
|
switch (seat.state) {
|
|
179
162
|
case "granted":
|
|
@@ -235,6 +218,12 @@ function buildRealSystemNote(remoteExec) {
|
|
|
235
218
|
"and the Bash read boundary is a text-level friction floor, not a safety boundary; the safety boundary is a sandbox lane: " +
|
|
236
219
|
`set REMOTE_EXEC=${sandboxLanes} (see docs/DEPLOY-PREREQS.md, section "S-281")`);
|
|
237
220
|
}
|
|
221
|
+
function hostWorktreeUnwrappedRefusal() {
|
|
222
|
+
return Object.assign(new Error('isolation "worktree" was requested but cannot be honored: this host lane has no worktree wrapper active ' +
|
|
223
|
+
"(WORKTREE_ISOLATION_ENABLED=true together with WORKTREE_REPO_ROOT=<a git repository> turns it on; a repo root that does not exist or has no `.git` leaves it off — see the boot log), " +
|
|
224
|
+
"and the base host environment would place the sub-agent in an empty temporary directory instead of an isolated checkout. " +
|
|
225
|
+
"The sub-agent was not started (fail-closed — no silent fallback to the shared working tree)."), { code: "isolation.unavailable" });
|
|
226
|
+
}
|
|
238
227
|
export function createExecutionEnv(ctx) {
|
|
239
228
|
const { config, logger, metrics, taskAttachmentStore } = ctx;
|
|
240
229
|
const laneHomeDir = executionLaneHomeDir(config);
|
|
@@ -275,7 +264,7 @@ export function createExecutionEnv(ctx) {
|
|
|
275
264
|
...(config.remoteExec.token ? { token: config.remoteExec.token } : {}),
|
|
276
265
|
...(config.remoteExec.caCert ? { caCert: config.remoteExec.caCert } : {}),
|
|
277
266
|
...(config.remoteExec.insecureTls ? { insecureTls: true } : {}),
|
|
278
|
-
|
|
267
|
+
namespace: config.remoteExec.namespace,
|
|
279
268
|
...(config.remoteExec.runtimeClass != null ? { runtimeClass: config.remoteExec.runtimeClass } : {}),
|
|
280
269
|
...(config.remoteExec.mountPath ? { mountPath: config.remoteExec.mountPath } : {}),
|
|
281
270
|
...(config.remoteExec.timeoutMs != null ? { timeoutMs: config.remoteExec.timeoutMs } : {}),
|
|
@@ -312,7 +301,7 @@ export function createExecutionEnv(ctx) {
|
|
|
312
301
|
};
|
|
313
302
|
sandboxPodReaper = createSandboxPodReaper({ api: createSandboxPodApi(k8sCfg), logger, metrics });
|
|
314
303
|
void checkSandboxEgressPolicy(k8sCfg)
|
|
315
|
-
.then((gaps) => sayEgressPolicyReading(gaps, logger, k8sCfg.namespace
|
|
304
|
+
.then((gaps) => sayEgressPolicyReading(gaps, logger, k8sCfg.namespace))
|
|
316
305
|
.catch((e) => logger.error("sandbox_egress_policy_check_crashed", { error: e instanceof Error ? e.message : String(e), effect: "the sandbox egress self-check did not complete this boot — the lane runs; the egress policy was not read" }));
|
|
317
306
|
}
|
|
318
307
|
else if (config.remoteExec?.provider === "ssh") {
|
|
@@ -332,6 +321,7 @@ export function createExecutionEnv(ctx) {
|
|
|
332
321
|
hub: ctx.deviceLane.hub,
|
|
333
322
|
store: ctx.deviceLane.store,
|
|
334
323
|
enrollment: ctx.deviceLane.enrollment,
|
|
324
|
+
seat: ctx.deviceLane.seat,
|
|
335
325
|
...homeDirSeat,
|
|
336
326
|
...(config.remoteExec.execTimeoutMs != null ? { execTimeoutMs: config.remoteExec.execTimeoutMs } : {}),
|
|
337
327
|
perSessionCwd,
|
|
@@ -375,6 +365,8 @@ export function createExecutionEnv(ctx) {
|
|
|
375
365
|
backgroundShell: config.requirePrincipal !== true,
|
|
376
366
|
};
|
|
377
367
|
executionEnvFactory = (ctx) => {
|
|
368
|
+
if (ctx.isolation === "worktree")
|
|
369
|
+
throw hostWorktreeUnwrappedRefusal();
|
|
378
370
|
const cwd = effectiveHostWorkspace(perSessionCwd.get(ctx.sessionId), ctx);
|
|
379
371
|
const shellEnv = perSessionShellEnv.get(ctx.sessionId);
|
|
380
372
|
const inheritEnv = perSessionInheritEnv.get(ctx.sessionId);
|
|
@@ -414,7 +406,7 @@ export function createExecutionEnv(ctx) {
|
|
|
414
406
|
logger.error("worktree_isolation_disabled_bad_repo_root", {
|
|
415
407
|
repoRoot: wtRoot,
|
|
416
408
|
reason: existsSync(wtRoot) ? "not a git repository (no .git)" : "path does not exist",
|
|
417
|
-
note: "WORKTREE_ISOLATION_ENABLED is set but WORKTREE_REPO_ROOT is not a usable git repo — isolation left OFF; isolation:'worktree' agents
|
|
409
|
+
note: "WORKTREE_ISOLATION_ENABLED is set but WORKTREE_REPO_ROOT is not a usable git repo — isolation left OFF; isolation:'worktree' workflow agents are refused (isolation.unavailable) until it is fixed. Fix the path or unset the flag.",
|
|
418
410
|
});
|
|
419
411
|
}
|
|
420
412
|
else if (config.remoteExec?.provider === "host") {
|
|
@@ -473,7 +465,7 @@ export function createExecutionEnv(ctx) {
|
|
|
473
465
|
if (executionEnvFactory) {
|
|
474
466
|
const isolated = laneIsolated(executionLaneOf(config.remoteExec.provider));
|
|
475
467
|
const suspendable = DEPLOYMENT_SHAPE_PREDICATES.suspendableHands.holds(config);
|
|
476
|
-
const sandboxEnvKeys =
|
|
468
|
+
const sandboxEnvKeys = [...sandboxEnvNamesInForce(config)].sort();
|
|
477
469
|
logger.info("remote_exec_enabled", { provider: config.remoteExec.provider, isolated, suspendable, ...(sandboxEnvKeys.length > 0 ? { sandboxEnvKeys } : {}) });
|
|
478
470
|
if (!isolated)
|
|
479
471
|
logger.warn("remote_exec_real_system", { provider: config.remoteExec.provider, note: buildRealSystemNote(config.remoteExec) });
|
|
@@ -5,7 +5,7 @@ import type { Logger } from "../observability/logger.js";
|
|
|
5
5
|
export declare const FILE_SOURCED_LANES: readonly ["host", "local-docker"];
|
|
6
6
|
export type FileSourcedLane = (typeof FILE_SOURCED_LANES)[number];
|
|
7
7
|
export interface ExecutionLaneComposeCtx {
|
|
8
|
-
/** 本入口的配置源形态(`
|
|
8
|
+
/** 本入口的配置源形态(`configSourceKind` 的答案 —— 与它真建的 provider 同一只判据)。
|
|
9
9
|
* 只有 `local` 才读文件;`undefined` = 纯 env 部署。 */
|
|
10
10
|
readonly configSource: "local" | "remote" | undefined;
|
|
11
11
|
/** 配置根(与配置源同一个根,不分裂)。 */
|
|
@@ -41,13 +41,14 @@
|
|
|
41
41
|
*
|
|
42
42
|
* ## 件D 的边界(成文,别读成「数据会被删」)
|
|
43
43
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* (`assertRetentionCapability` ——
|
|
48
|
-
*
|
|
44
|
+
* 三只被托管的 SQL 店(session / checkpoint / tool-result)的 `retention` 声明读一个事实 —— 留存扫车道开不开(`plugins/retention-store-sql.ts` 的
|
|
45
|
+
* `retentionSweepRuns`):开 ⇒ `managed`,关(缺省)⇒ `none`;local 形的店恒声明 `none`。删除的执行面是扫车道(`boot/retention-lane.ts`)与 SQL 店上的
|
|
46
|
+
* 执行器,不在本装配点。所以本装配点对件D 只做两件事:①把策略与执行器递给 core 的启动期校验
|
|
47
|
+
* (`assertRetentionCapability` —— 配对由引擎一个判官判:店声明 `managed` 而部署不跑执行器、执行器不是执行器,锁不锁都拒;锁着 + 店不能删 ⇒ 拒启,
|
|
48
|
+
* 「策略锁着、数据永存」不许发生);②策略在场而扫车道关着(节律缺或为 0)时打一条响亮 warn,句说这个真因。**不**假装有执行面。
|
|
49
|
+
* 车道关着而策略在场只可能在 `audit-only` 档:`enforce` 而车道不齐在 `loadConfig` 就拒了(配置不变量 `retention-lane-complete`)。
|
|
49
50
|
*/
|
|
50
|
-
import { type LockedKey, type RunnerDeps } from "@sema-agent/core";
|
|
51
|
+
import { type LockedKey, type ManagedRetentionCapability, type RunnerDeps } from "@sema-agent/core";
|
|
51
52
|
import type { ServiceConfig } from "../config.js";
|
|
52
53
|
import type { Logger } from "../observability/logger.js";
|
|
53
54
|
/** 装配产物:三个 core 座席 + 已校验的锁集(同步拒面 `assertRequestMcpUnlocked` 读它)。 */
|
|
@@ -61,7 +62,7 @@ export interface GovernanceSeams {
|
|
|
61
62
|
}
|
|
62
63
|
/** 依赖收窄到真实消费面(接口隔离 —— 测试用真形字面量,零铸形)。 */
|
|
63
64
|
export interface GovernanceSeamsCtx {
|
|
64
|
-
config: Pick<ServiceConfig, "compliancePosture" | "lockedConfigKeys" | "retentionPolicy" | "mcpServers" | "requirePrincipal">;
|
|
65
|
+
config: Pick<ServiceConfig, "compliancePosture" | "lockedConfigKeys" | "retentionPolicy" | "retentionSweep" | "mcpServers" | "requirePrincipal">;
|
|
65
66
|
logger: Pick<Logger, "info" | "warn">;
|
|
66
67
|
/**
|
|
67
68
|
* core 留存能力校验的对象集(名字进拒启文案)。喂的是**装配现场的真店**,不是「我以为装了什么」——
|
|
@@ -72,18 +73,11 @@ export interface GovernanceSeamsCtx {
|
|
|
72
73
|
store: object | undefined;
|
|
73
74
|
}>;
|
|
74
75
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* 🔴 为什么这一位必须存在(codex 交叉复审 R2-[critical],验真后修):core 的
|
|
79
|
-
* `assertRetentionCapability` 只读**店的声明位**。[ref] 车1 让三只 SQL 店如实声明了 `"managed"`
|
|
80
|
-
* (它们的行确实由托管留存删),于是那道门从此**放行** locked policy —— 可执行器还在车2 手里。
|
|
81
|
-
* 两者之间的窗口如果什么都不做,后果正是本仓最忌的那种:部署自述「策略已受管」、审计与能力面
|
|
82
|
-
* 也这么说,而**没有任何东西在删数据**;车1 之前那条 `retention_policy_not_executed` 的响亮 warn
|
|
83
|
-
* 还会因为"有 managed 店在场"而**静音**。
|
|
84
|
-
* ⇒ 判据改成问「有没有东西真会删」,而不是「有没有店说自己被管」。车2 接上 lane 时把这一位传 true。
|
|
76
|
+
* 交给引擎启动检查的留存执行器 —— 本部署跑扫车道 ⇒ 那只执行器(`backend.retention`),不跑 ⇒ `null`(必填:漏递即编译红,
|
|
77
|
+
* 引擎对 `undefined` 也拒启)。「店说 managed」与「有执行器」的配对由引擎一个判官判(引擎 7.58.0:锁不锁都判);
|
|
78
|
+
* 店的词与这一格读同一个事实(`retention-store-sql.ts` 的 `retentionSweepRuns`),本仓不再另判一遍。
|
|
85
79
|
*/
|
|
86
|
-
|
|
80
|
+
retentionExecutor: ManagedRetentionCapability | null;
|
|
87
81
|
}
|
|
88
82
|
/**
|
|
89
83
|
* 件C 的装配相容性判据(纯,可单测)——见文件头「两条判据」。
|
|
@@ -49,30 +49,16 @@ export function createGovernanceSeams(ctx) {
|
|
|
49
49
|
}
|
|
50
50
|
const retentionPolicy = config.retentionPolicy;
|
|
51
51
|
const locked = lockedKeys.has("retentionPolicy");
|
|
52
|
-
assertRetentionCapability({ policy: retentionPolicy, locked, stores: retentionStores });
|
|
53
|
-
if (retentionPolicy !== undefined) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
else if (!executorWired) {
|
|
65
|
-
const detail = `retention policy is configured (maxAgeDays=${retentionPolicy.maxAgeDays}) and ${managed.length} wired store(s) declare ` +
|
|
66
|
-
`retention:"managed", but THIS BUILD WIRES NO RETENTION EXECUTOR (the sweep lane) — nothing enumerates domains or calls ` +
|
|
67
|
-
`the destructive store methods, so no data is deleted on the policy's account. A "managed" declaration is a statement ` +
|
|
68
|
-
`about who OWNS deleting those rows, not proof that a scheduler is running.`;
|
|
69
|
-
if (locked) {
|
|
70
|
-
throw new Error(`${detail} Refusing to start with the retentionPolicy key LOCKED: a locked policy over a deployment that does not ` +
|
|
71
|
-
`actually delete is exactly the "policy locked, data immortal" posture the engine's capability check exists to ` +
|
|
72
|
-
`prevent. Unlock the key, remove the policy, or run a build whose retention sweep lane is wired.`);
|
|
73
|
-
}
|
|
74
|
-
logger.warn("retention_policy_not_executed", { maxAgeDays: retentionPolicy.maxAgeDays, note: detail });
|
|
75
|
-
}
|
|
52
|
+
assertRetentionCapability({ policy: retentionPolicy, locked, stores: retentionStores, executor: ctx.retentionExecutor });
|
|
53
|
+
if (retentionPolicy !== undefined && config.retentionSweep.intervalSec === 0) {
|
|
54
|
+
logger.warn("retention_policy_not_executed", {
|
|
55
|
+
maxAgeDays: retentionPolicy.maxAgeDays,
|
|
56
|
+
mode: config.retentionSweep.mode,
|
|
57
|
+
retentionSweepIntervalSec: config.retentionSweep.intervalSec,
|
|
58
|
+
note: "RETENTION_MAX_AGE_DAYS is set but RETENTION_SWEEP_INTERVAL_SEC is unset or 0, so the retention sweep lane is off: nothing deletes data — " +
|
|
59
|
+
"or records what it would delete — on this policy's account; the policy is a declaration relayed to the engine's startup capability check. " +
|
|
60
|
+
"To run the lane set RETENTION_SWEEP_INTERVAL_SEC above 0 on a SQL backend (RETENTION_MODE=audit-only records what would be deleted; enforce deletes it).",
|
|
61
|
+
});
|
|
76
62
|
}
|
|
77
63
|
return { compliancePostureResolver, lockedConfig, retentionPolicy, lockedKeys };
|
|
78
64
|
}
|
package/dist/boot/leader.d.ts
CHANGED
|
@@ -49,6 +49,9 @@ export interface LeaderCtx {
|
|
|
49
49
|
* 唯一出口就是它(`runtask.js` 的 `catch (flushErr) => deps.onError`),所以它与 `usageWindowStore`
|
|
50
50
|
* 席同生共死:挂窗不挂汇 = 治理轴上的静默失败面([ref])。必填键,理由同 `tracer`。 */
|
|
51
51
|
onError: RunnerDeps["onError"];
|
|
52
|
+
/** 部署座 —— 起服第 5 段装配口 `assembleDeploymentMods` 交回的**同一份**(主车道各 Runner 经共享基座吃的就是它)。leader 车道的每一只 Runner 都要带:
|
|
53
|
+
* 缺席 = 运维声明的 mod 包管不到 leader 派出的腿。必填键,理由同 `tracer`。 */
|
|
54
|
+
deploymentMods: NonNullable<RunnerDeps["mods"]>;
|
|
52
55
|
/** [ref] 车4 件1:durable store 后端(leader-run 登记表从这里取)。缺席 = 无 DB 的 env-only worker。 */
|
|
53
56
|
backend?: StoreBackend | undefined;
|
|
54
57
|
}
|
package/dist/boot/leader.js
CHANGED
|
@@ -59,6 +59,7 @@ export function createLeaderFace(ctx) {
|
|
|
59
59
|
: {}),
|
|
60
60
|
...(ctx.promptSource ? { promptSource: ctx.promptSource } : {}),
|
|
61
61
|
...(ctx.onError ? { onError: ctx.onError } : {}),
|
|
62
|
+
mods: ctx.deploymentMods,
|
|
62
63
|
fanoutEnabled: config.leaderFanoutEnabled,
|
|
63
64
|
...((process.env.MODEL_ROUTER_ID || process.env.MODEL_CHEAP_ID)
|
|
64
65
|
? { routerModel: (process.env.MODEL_ROUTER_ID || process.env.MODEL_CHEAP_ID) }
|
|
@@ -5,7 +5,7 @@ import { memoryMountRootOf } from "../memory-scope.js";
|
|
|
5
5
|
import { executionLaneHomeDir } from "../execution-lane-caps.js";
|
|
6
6
|
import { DEFAULT_MODEL_REF, resolveMainModel } from "../model-select.js";
|
|
7
7
|
import { backendOwnsControlPlane } from "../memory-operator-faces.js";
|
|
8
|
-
import { createConsolidationWriteJudge, deliverWriteRefusal, expandTiers, MemoryEngine, readConsolidationDriverRun, resolveMemoryConsolidationDriver, runMemoryConsolidationDriver, } from "@sema-agent/core";
|
|
8
|
+
import { createConsolidationWriteJudge, deliverWriteRefusal, expandTiers, MemoryEngine, modelOriginOf, readConsolidationDriverRun, resolveMemoryConsolidationDriver, runMemoryConsolidationDriver, } from "@sema-agent/core";
|
|
9
9
|
export function resolveConsolidationDriverSeat(deps) {
|
|
10
10
|
let options;
|
|
11
11
|
try {
|
|
@@ -151,7 +151,7 @@ export function consolidationSeatBillingOf(plane) {
|
|
|
151
151
|
catch (err) {
|
|
152
152
|
return { kind: "unresolvable", fault: `the main model (${DEFAULT_MODEL_REF}) does not resolve: ${err instanceof Error ? err.message : String(err)}` };
|
|
153
153
|
}
|
|
154
|
-
return seat.entry === main ? { kind: "main-model", mainModel: main.id } : { kind: "own-model", seatModel: seat.entry.id, mainModel: main.id };
|
|
154
|
+
return modelOriginOf(seat.entry) === modelOriginOf(main) ? { kind: "main-model", mainModel: main.id } : { kind: "own-model", seatModel: seat.entry.id, mainModel: main.id };
|
|
155
155
|
}
|
|
156
156
|
export function resolveConsolidationValve(input) {
|
|
157
157
|
const decided = decideConsolidationValve(input);
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { principalInboxConsumerOf } from "@sema-agent/core";
|
|
2
2
|
import { createOrgDeliveryGate } from "../org-delivery-gate.js";
|
|
3
|
+
function declarationOf(consumer) {
|
|
4
|
+
switch (consumer.kind) {
|
|
5
|
+
case "assistant":
|
|
6
|
+
return { declared: "PRINCIPAL_INBOX_ASSISTANT declares a principal-inbox consumer", undeclare: "unset PRINCIPAL_INBOX_ASSISTANT" };
|
|
7
|
+
case "terminals":
|
|
8
|
+
return { declared: 'RunnerDeps.principalInboxConsumer declares "terminals" (the scope\'s terminal sessions drain the principal inbox)', undeclare: "drop the RunnerDeps.principalInboxConsumer declaration" };
|
|
9
|
+
default: {
|
|
10
|
+
const unknown = consumer;
|
|
11
|
+
throw new Error(`unknown principal-inbox consumer kind: ${JSON.stringify(unknown)}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
3
15
|
export function mountOrgDeliveryGate(input) {
|
|
4
16
|
const consumer = principalInboxConsumerOf(input.runnerDeps);
|
|
5
17
|
if (consumer.kind === "none")
|
|
@@ -11,8 +23,9 @@ export function mountOrgDeliveryGate(input) {
|
|
|
11
23
|
...(directory === undefined ? ["an organization membership directory (a web-admin center, or MEMORY_ORG_DIRECTORY_JSON)"] : []),
|
|
12
24
|
...(backend === undefined ? ["a store backend for the delivery quota (DB_BACKEND=mysql|pg|local)"] : []),
|
|
13
25
|
];
|
|
14
|
-
|
|
15
|
-
|
|
26
|
+
const { declared, undeclare } = declarationOf(consumer);
|
|
27
|
+
throw new Error(`${declared}, so this deployment must mount the organization delivery gate — but it lacks ${missing.join("; ")}. ` +
|
|
28
|
+
`Refusing to boot rather than run with a declared inbox that nothing may legitimately write to; provide the missing pieces or ${undeclare}.`);
|
|
16
29
|
}
|
|
17
30
|
input.logger.info("org_delivery_gate_mounted", { consumer: consumer.kind });
|
|
18
31
|
return createOrgDeliveryGate({ directory, mailbox: mailboxStore, quota: backend.orgDeliveryQuota(), consumer });
|
|
@@ -15,9 +15,10 @@ import type { Metrics } from "../observability/metrics.js";
|
|
|
15
15
|
import { PerTaskImageRegistry } from "../per-task-image.js";
|
|
16
16
|
import type { StoreBackend } from "../plugins/store-backend.js";
|
|
17
17
|
import { type TaskAttachmentStore } from "../plugins/task-attachment-store.js";
|
|
18
|
-
import {
|
|
18
|
+
import type { createPrincipalEntitlementsClient } from "../runtime-caps-resolver.js";
|
|
19
19
|
import { type OwnerAwareSessionStore } from "../security.js";
|
|
20
20
|
import type { MemorySyncRunner } from "../memory-sync-client.js";
|
|
21
|
+
import type { PeerDesk } from "../peer-seat.js";
|
|
21
22
|
import type { RunnerDepsOnAsk } from "./runner-deps.js";
|
|
22
23
|
type PrincipalCaps = ReturnType<typeof createPrincipalEntitlementsClient>;
|
|
23
24
|
/** `resolveSpec` 原先从 `main()` 闭包里拿到的全部 boot 局部量。 */
|
|
@@ -84,6 +85,8 @@ export interface ResolveSpecCtx {
|
|
|
84
85
|
/** [ref] 件C:本部署已校验的锁集(boot/governance-seams.ts 的产物,与 `RunnerDeps.lockedConfig`
|
|
85
86
|
* 同源一次解析)。空集 = 无锁 = 现行为。本域只用它做**同步拒面**(§4.3),不做第二次裁决。 */
|
|
86
87
|
lockedKeys: ReadonlySet<import("@sema-agent/core").LockedKey>;
|
|
88
|
+
/** 本进程的对端座 desk(stage-05 建、HTTP 服务的 `peerDesk` 同一只):请求面 MCP / A2A 的胜出草稿在 `opts.lease` 下经它登记,换回声明带的引用 —— 两只漏斗开的租约属于它。 */
|
|
89
|
+
peerDesk: PeerDesk;
|
|
87
90
|
/** 本部署**装载簿**(stage-07 的出厂技能 + 配置源覆盖之后的终表,场景工厂读的同一份)。本装配器只拿它答「场景交来的这只技能来自哪里」
|
|
88
91
|
* (run 名册 `wiring_manifest.skills[].source`,`buildRunSkills`);名字在装载簿里唯一(装载器同名即抛、配置源按名覆盖)。 */
|
|
89
92
|
loadedSkills: readonly LoadedSkill[];
|
|
@@ -25,10 +25,10 @@ import { bindAttachmentsForTask } from "../plugins/task-attachment-store.js";
|
|
|
25
25
|
import { resourceSuspendOptIn } from "../resource-suspend.js";
|
|
26
26
|
import { routeServiceTask, supPostureOverrides } from "../router/route-orchestration.js";
|
|
27
27
|
import { tightenGoverned } from "../governance-overrides.js";
|
|
28
|
-
import { gateExecutionLane } from "../runtime-caps-resolver.js";
|
|
29
28
|
import { applyRuntimeGovernance } from "../runtime-governance.js";
|
|
30
29
|
import { HttpError, createCodedHttpError, encodeCheckpointScope } from "../security.js";
|
|
31
30
|
import { headReadOf, sessionFaceOfHead } from "../session-incarnation.js";
|
|
31
|
+
import { legProjectIdOf, sessionWorkspaceStoreOf, stampLegSessionWitness } from "../session-workspace.js";
|
|
32
32
|
import { memorySpecForRequest } from "../memory-scope.js";
|
|
33
33
|
import { createMemoryProjectLayers } from "../memory-project-layer.js";
|
|
34
34
|
import { inheritEnvFacts, inheritEnvFieldIssue, singleMemberOffFieldIssue } from "../request-value-closure.js";
|
|
@@ -40,6 +40,7 @@ import { DEPLOYMENT_SHAPE_PREDICATES } from "../deployment-shape.js";
|
|
|
40
40
|
import { assertRequestA2aEntries, resolveRequestA2a, snapshotRequestA2a } from "../task-a2a.js";
|
|
41
41
|
import { assertRequestImageUrls } from "../request-image-urls.js";
|
|
42
42
|
import { assertRequestMcpEntries, assertRequestMcpUnlocked, resolveRequestMcp } from "../task-mcp.js";
|
|
43
|
+
import { GOVERNANCE_HTTP_STATUS } from "../governance-http-status.js";
|
|
43
44
|
import { storedToolAxesRereadM19 } from "../stored-request-tool-axes-m19.js";
|
|
44
45
|
import { storedHooksRereadM20 } from "../stored-request-hooks-m20.js";
|
|
45
46
|
import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, REQUEST_SETTINGS_REFUSAL_PREFIX, SETTINGS_RULE_REFUSAL_CODE, SettingsRuleRefusalError, acceptAppendSystemPrompt, applyTaskSettings, createWorkflowAskPolicy, effectivePermissionMode, effectiveThinking, parseTaskSettings, taskHooksHonored, settingsPermissionBucketIssue } from "../task-settings.js";
|
|
@@ -53,11 +54,16 @@ import { executionLaneHomeDir, executionLaneOf, laneWiresExecutionEnv } from "..
|
|
|
53
54
|
import { effectiveMemoryPersistenceCapable } from "./memory-boundary.js";
|
|
54
55
|
import { withUnattendedLeg } from "../unattended-permission-mode.js";
|
|
55
56
|
import { fieldConflictFacts } from "../field-conflict.js";
|
|
57
|
+
function unrooted(spec) {
|
|
58
|
+
const { sessionId: _neverWritten, ...resolved } = spec;
|
|
59
|
+
return resolved;
|
|
60
|
+
}
|
|
56
61
|
export function createResolveSpec(ctx) {
|
|
57
|
-
const { config, logger, metrics, localRoot, scenarios, principalCaps, centerRuntimeCapsResolver, getKeyResolver, taskAttachmentStore, perSessionCwd, setSessionCwd, setSessionShellEnv, fenceSessionOwner, hookLlm, hookAgent, fleetBus, hookWakeBus, resumeAnchorStore, ownerAware, taskLimitCaps, taskTimeoutSec, selectEnvTool, sendUserFileToolSpec, memoryEngine, memorySyncRunner, durableEnabled, approvalExemptionStore, checkpointStore, imageIndex, perTaskImage, sessionEnvSelection, liveQuestionFace, approverSeat, lockedKeys, loadedSkills, } = ctx;
|
|
62
|
+
const { config, logger, metrics, localRoot, scenarios, principalCaps, centerRuntimeCapsResolver, getKeyResolver, taskAttachmentStore, perSessionCwd, setSessionCwd, setSessionShellEnv, fenceSessionOwner, hookLlm, hookAgent, fleetBus, hookWakeBus, resumeAnchorStore, ownerAware, taskLimitCaps, taskTimeoutSec, selectEnvTool, sendUserFileToolSpec, memoryEngine, memorySyncRunner, durableEnabled, approvalExemptionStore, checkpointStore, imageIndex, perTaskImage, sessionEnvSelection, liveQuestionFace, approverSeat, lockedKeys, loadedSkills, peerDesk, } = ctx;
|
|
58
63
|
const deploymentSkillSources = new Map(loadedSkills.map((k) => [k.spec.name, k.source]));
|
|
59
64
|
const scenarioGate = createScenarioGate({ config, scenarios, principalCaps, logger }, "enforce");
|
|
60
65
|
const sessionHeadOf = headReadOf(ownerAware);
|
|
66
|
+
const sessionWorkspace = sessionWorkspaceStoreOf(ownerAware);
|
|
61
67
|
assertGuardPatternsUsable(config);
|
|
62
68
|
const onlySensitiveBaseline = buildOnlySensitiveBaselineWarning(config, {
|
|
63
69
|
approvalSeat: durableEnabled ? "durable" : "absent",
|
|
@@ -80,6 +86,13 @@ export function createResolveSpec(ctx) {
|
|
|
80
86
|
if (seatRefusal !== undefined)
|
|
81
87
|
throw createCodedHttpError(501, "capability.checkpoint_store_required", seatRefusal);
|
|
82
88
|
assertRequestMcpUnlocked(body.mcpServers, lockedKeys);
|
|
89
|
+
const storedToolAxes = opts?.leg === "fresh" ? undefined : storedToolAxesRereadM19(new Date().toISOString().slice(0, 10));
|
|
90
|
+
const a2aPeers = snapshotRequestA2a(body.a2aPeers, { reread: storedToolAxes !== undefined });
|
|
91
|
+
if (lockedKeys.has("a2a") && a2aPeers !== undefined && a2aPeers !== null) {
|
|
92
|
+
throw new HttpError(GOVERNANCE_HTTP_STATUS["config.locked_key"], "`a2aPeers` is administratively locked by this deployment (locked key \"a2a\") — task-supplied A2A peers are refused; locks are config-time and there is no request-time unlock", {
|
|
93
|
+
code: "config.locked_key",
|
|
94
|
+
});
|
|
95
|
+
}
|
|
83
96
|
if (opts?.leg === "fresh")
|
|
84
97
|
assertRequestMcpEntries(body.mcpServers);
|
|
85
98
|
if (opts?.leg === "fresh") {
|
|
@@ -142,8 +155,6 @@ export function createResolveSpec(ctx) {
|
|
|
142
155
|
}
|
|
143
156
|
}
|
|
144
157
|
}
|
|
145
|
-
const storedToolAxes = opts?.leg === "fresh" ? undefined : storedToolAxesRereadM19(new Date().toISOString().slice(0, 10));
|
|
146
|
-
const a2aPeers = snapshotRequestA2a(body.a2aPeers, { reread: storedToolAxes !== undefined });
|
|
147
158
|
if (opts?.leg === "fresh")
|
|
148
159
|
assertRequestA2aEntries(a2aPeers);
|
|
149
160
|
if (opts?.leg === "fresh")
|
|
@@ -167,12 +178,13 @@ export function createResolveSpec(ctx) {
|
|
|
167
178
|
hostSemanticsLane: folded.hostSemanticsLane,
|
|
168
179
|
});
|
|
169
180
|
const stamped = stampHandsLane(final, gated.hands);
|
|
170
|
-
return stampRunSkills(stamped, runSkills.roster);
|
|
181
|
+
return stampLegSessionWitness(stampRunSkills(stamped, runSkills.roster), gated.sessionWitness);
|
|
171
182
|
};
|
|
172
183
|
const gateScenarioAndAppend = async (body, auth, opts) => {
|
|
173
184
|
const scenarioName = await scenarioGate(auth?.principal, body.scenario);
|
|
174
|
-
|
|
175
|
-
const
|
|
185
|
+
const root = opts.execution.root;
|
|
186
|
+
const sessionWitness = { sessionId: root, incarnation: (sessionHeadOf === undefined ? undefined : sessionFaceOfHead(root, await sessionHeadOf(root)))?.incarnation ?? null };
|
|
187
|
+
const cap = selectScenario(scenarios, scenarioName)(body, auth?.principal, { sessionId: sessionWitness.sessionId, delegationRoot: sessionWitness });
|
|
176
188
|
const acceptedAppend = acceptAppendSystemPrompt(body.appendSystemPrompt, (detail) => logger.warn("append_system_prompt_dropped", { detail, sessionId: auth?.sessionId ?? null }));
|
|
177
189
|
const objective = typeof body.objective === "string" ? body.objective : "";
|
|
178
190
|
const parsedSettings = parseTaskSettings(body.settings, opts?.leg === "fresh" || !taskHooksHonored(config) ? {} : { storedHooksReread: storedHooksRereadM20(new Date().toISOString().slice(0, 10)) });
|
|
@@ -222,7 +234,7 @@ export function createResolveSpec(ctx) {
|
|
|
222
234
|
}
|
|
223
235
|
}
|
|
224
236
|
}
|
|
225
|
-
return { scenarioName, cap, hands: cap.hands, acceptedAppend, objective, parsedSettings, attachmentNotice };
|
|
237
|
+
return { scenarioName, cap, hands: cap.hands, acceptedAppend, objective, parsedSettings, attachmentNotice, sessionWitness };
|
|
226
238
|
};
|
|
227
239
|
const bindSettingsCwdEnvAndModel = (body, auth, gated, opts) => {
|
|
228
240
|
const { objective, parsedSettings } = gated;
|
|
@@ -339,9 +351,10 @@ export function createResolveSpec(ctx) {
|
|
|
339
351
|
if (rewindFilesToEntryId === undefined)
|
|
340
352
|
throw new HttpError(404, `rewindFilesTo: no such message in this session (rewind_files_to.unknown_event) — ${NO_ANCHOR_HINT}; name another prompt`, { code: "rewind_files_to.unknown_event" });
|
|
341
353
|
}
|
|
342
|
-
const
|
|
343
|
-
const s4DefaultScopes =
|
|
344
|
-
|
|
354
|
+
const submittedProjectId = auth?.resolvedProjectId ?? (typeof body.projectId === "string" && body.projectId ? body.projectId.toLowerCase() : undefined);
|
|
355
|
+
const s4DefaultScopes = submittedProjectId ? config.projects[submittedProjectId]?.defaultScopes : undefined;
|
|
356
|
+
const legProjectId = await legProjectIdOf(submittedProjectId, sessionWorkspace, auth?.sessionId);
|
|
357
|
+
return { resumeAtEntryId, rewindFilesToEntryId, s4DefaultScopes, legProjectId };
|
|
345
358
|
};
|
|
346
359
|
const declaresInteractivePosture = (body, req, opts) => {
|
|
347
360
|
if (opts?.liveStream !== true)
|
|
@@ -358,14 +371,14 @@ export function createResolveSpec(ctx) {
|
|
|
358
371
|
return deriveAskEffective(askForm.form, "unresolved") === "human_reachable";
|
|
359
372
|
};
|
|
360
373
|
const assembleSpecLiteral = (body, auth, req, opts, parts, effMode) => {
|
|
361
|
-
const { scenarioName, cap, hands, acceptedAppend, parsedSettings, attachmentNotice, taskHooks, additionalDirectories, additionalReadDirectories, wireCatalog, picked, resumeAtEntryId, rewindFilesToEntryId, s4DefaultScopes, projectKey, a2aPeers, storedToolAxes, runSkills, } = parts;
|
|
374
|
+
const { scenarioName, cap, hands, acceptedAppend, parsedSettings, attachmentNotice, taskHooks, additionalDirectories, additionalReadDirectories, wireCatalog, picked, resumeAtEntryId, rewindFilesToEntryId, s4DefaultScopes, legProjectId, projectKey, a2aPeers, storedToolAxes, runSkills, } = parts;
|
|
362
375
|
const spec = {
|
|
363
376
|
objective: attachmentNotice ? `${picked.cleanedObjective}\n\n${attachmentNotice}` : picked.cleanedObjective,
|
|
364
377
|
...buildPromptSeats(scenarioName, cap.prompt, typeof body.systemPrompt === "string" ? body.systemPrompt : undefined),
|
|
365
378
|
appendSystemPrompt: acceptedAppend,
|
|
366
379
|
...(body.outputStyle !== undefined ? { outputStyle: body.outputStyle } : {}),
|
|
367
380
|
...(body.projectMemory !== undefined ? { projectMemory: body.projectMemory } : {}),
|
|
368
|
-
|
|
381
|
+
...(legProjectId !== undefined ? { projectId: legProjectId } : {}),
|
|
369
382
|
principal: auth?.principal,
|
|
370
383
|
images: body.images,
|
|
371
384
|
...(body.userAttachments !== undefined ? { userAttachments: body.userAttachments } : {}),
|
|
@@ -385,7 +398,6 @@ export function createResolveSpec(ctx) {
|
|
|
385
398
|
suggestNextPrompts: normalizeSuggestNextPrompts(body.suggestNextPrompts),
|
|
386
399
|
restoreFiles: body.restoreFiles === true ? true : undefined,
|
|
387
400
|
acceptPartialRestore: body.acceptPartialRestore === true ? true : undefined,
|
|
388
|
-
...(body.rewindFiles === true ? { rewindFiles: true } : {}),
|
|
389
401
|
rewindFilesTo: rewindFilesToEntryId,
|
|
390
402
|
...(body.fileHistory === "disabled" ? { fileHistory: "disabled" } : {}),
|
|
391
403
|
additionalDirectories,
|
|
@@ -491,8 +503,8 @@ export function createResolveSpec(ctx) {
|
|
|
491
503
|
...(() => { const v = toolNameListFromBody(body.userInvokedSkills); return v ? { userInvokedSkills: v } : {}; })(),
|
|
492
504
|
...(parsedSettings.settings?.skillListingBudgetFraction !== undefined ? { skillListingBudgetFraction: parsedSettings.settings.skillListingBudgetFraction } : {}),
|
|
493
505
|
...(parsedSettings.settings?.skillListingMaxDescChars !== undefined ? { skillListingMaxDescChars: parsedSettings.settings.skillListingMaxDescChars } : {}),
|
|
494
|
-
mcp: resolveRequestMcp(mcpForScenario(config.mcpServers, scenarioName), body.mcpServers, config, logger, opts?.onNotice !== undefined ? { sessionId: auth?.sessionId, emit: opts.onNotice } : undefined, storedToolAxes),
|
|
495
|
-
a2a: resolveRequestA2a(a2aForScenario(config.a2aPeers, scenarioName), a2aPeers, config, logger, opts?.leg === "fresh" ? "fresh" : "resume", storedToolAxes),
|
|
506
|
+
mcp: resolveRequestMcp(mcpForScenario(config.mcpServers, scenarioName), body.mcpServers, config, peerDesk, opts.lease, logger, opts?.onNotice !== undefined ? { sessionId: auth?.sessionId, emit: opts.onNotice } : undefined, storedToolAxes),
|
|
507
|
+
a2a: resolveRequestA2a(a2aForScenario(config.a2aPeers, scenarioName), a2aPeers, config, peerDesk, opts.lease, logger, opts?.leg === "fresh" ? "fresh" : "resume", storedToolAxes),
|
|
496
508
|
toolPolicy: toolPolicyForHands(hands, durableEnabled
|
|
497
509
|
? createApprovalBaselinePolicy(config, {
|
|
498
510
|
kind: "durable",
|
|
@@ -659,9 +671,7 @@ export function createResolveSpec(ctx) {
|
|
|
659
671
|
};
|
|
660
672
|
const resolveSpecForLeg = async (body, req, auth, opts) => {
|
|
661
673
|
const spec = await resolveSpec(body, req, auth, opts);
|
|
662
|
-
|
|
663
|
-
return spec;
|
|
664
|
-
return withUnattendedLeg(spec);
|
|
674
|
+
return unrooted(opts.unattendedLeg !== true ? spec : withUnattendedLeg(spec));
|
|
665
675
|
};
|
|
666
676
|
return resolveSpecForLeg;
|
|
667
677
|
}
|
|
@@ -155,22 +155,28 @@ export interface RetentionSweepOutcome {
|
|
|
155
155
|
/**
|
|
156
156
|
* lane **自持的** boot 不变式(设计稿 §7,codex F3)—— 与 core 的 `assertRetentionCapability` 是两道门,
|
|
157
157
|
* 各答各的问题:
|
|
158
|
-
* · core
|
|
159
|
-
*
|
|
158
|
+
* · core 那道判**配对**,锁不锁都判(`executor` 必给):声明 `managed` 的店 × 没有执行器(`null`)⇒ 拒;执行器四个契约方法
|
|
159
|
+
* (`listRetentionDomains` / `expireCheckpoints` / `deleteExpiredSessions` / `deleteOrphanToolResults`)缺一 ⇒ 拒;
|
|
160
|
+
* **锁着**的策略盖在声明 `none` 的店上 ⇒ 拒。它不问 lane 开没开、策略在不在,也不拦没锁时「执行器在场 × 店声明 `none`」(部署可以持有执行器而不在某只店上跑);
|
|
161
|
+
* · **本道**问的是「lane 开着的时候,它接得上能删的东西吗」——**不看 locked 状态**:执行器在场、lane 调的**五**个方法都在
|
|
162
|
+
* (多出的 `previewRetention` 是 audit-only 档的读数口,不在 core 的四方法契约里,引擎的检查覆盖不到它)、每只被 lane 消费的店都声明 `managed`。
|
|
163
|
+
* 「执行器在场」与「契约方法齐」两格和引擎的判官说的是同一件事(各自一句拒句),其余几格是引擎不问的。
|
|
160
164
|
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
+
* 「lane 开着而没有视界(天数)」与「`RETENTION_MODE=enforce` 而车道不齐」不在本道:那是配置事实,判在 `loadConfig` 的配置不变量段
|
|
166
|
+
* (`config-invariants.ts` 的 `retentionLaneRefusal`,一条规则)—— 到得了本道的部署,lane 开着就一定有视界。本道只判**接线**(配置看不见的那几格)。
|
|
167
|
+
*
|
|
168
|
+
* 为什么本道必须存在:引擎的门不拦
|
|
169
|
+
* · 没锁时,执行器在场 × 一只 `"none"` 的店 —— 部署于是**广告了一个不执行的留存面**:能力位说
|
|
165
170
|
* `{mode,maxAgeDays}`、审计表也在长,而那只店的行谁都没在删。
|
|
166
|
-
*
|
|
171
|
+
* 本仓的 SQL 后端按同一个事实(扫车道开不开,`plugins/retention-store-sql.ts` 的 `retentionSweepRuns`)给它铸的三只店声明词,所以 lane 开着时
|
|
172
|
+
* 这三只店在这一格上恒是 `managed`;这一格防的是声明与 lane 脱钩的店(别的后端、替身)。
|
|
173
|
+
* 这些都在**启动期**拒(安全控件不得半开),不是让运维从一台"启动成功、什么也没删"的机器上猜。
|
|
167
174
|
*
|
|
168
175
|
* @param locked 只进文案(让拒启信息能说清"你锁没锁都一样拒");**判据本身不读它** —— 这一格的存在
|
|
169
176
|
* 就是为了让"不看 locked"这句话在签名上可见,而不是靠注释声明。
|
|
170
177
|
*/
|
|
171
178
|
export declare function assertRetentionLaneWirable(input: {
|
|
172
179
|
intervalSec: number;
|
|
173
|
-
policy: RetentionPolicy | undefined;
|
|
174
180
|
executor: RetentionExecutor | undefined;
|
|
175
181
|
stores: ReadonlyArray<{
|
|
176
182
|
name: string;
|
|
@@ -2,24 +2,18 @@ import { recordFailOpen } from "../observability/fail-open.js";
|
|
|
2
2
|
export const RETENTION_SWEEP_STUCK_THRESHOLD = 5;
|
|
3
3
|
export const RETENTION_LEASE_TTL_FACTOR = 2;
|
|
4
4
|
const DAY_MS = 86_400_000;
|
|
5
|
+
const LANE_EXECUTOR_METHODS = ["listRetentionDomains", "previewRetention", "expireCheckpoints", "deleteExpiredSessions", "deleteOrphanToolResults"];
|
|
5
6
|
export function assertRetentionLaneWirable(input) {
|
|
6
7
|
if (input.intervalSec <= 0)
|
|
7
8
|
return;
|
|
8
9
|
const lockNote = input.locked === true ? " (the retentionPolicy key is LOCKED, but this gate refuses either way)" : "";
|
|
9
|
-
if (input.policy === undefined) {
|
|
10
|
-
throw new Error(`RETENTION_SWEEP_INTERVAL_SEC=${input.intervalSec} arms the managed-retention sweep lane, but RETENTION_MAX_AGE_DAYS is not ` +
|
|
11
|
-
`configured — the lane would run with NO horizon to compute a cutoff from, enumerate domains every tick and delete nothing, ` +
|
|
12
|
-
`while the capability surface advertises a retention face that does not exist${lockNote}. Set RETENTION_MAX_AGE_DAYS, or set ` +
|
|
13
|
-
`RETENTION_SWEEP_INTERVAL_SEC=0 to leave the lane off.`);
|
|
14
|
-
}
|
|
15
10
|
if (input.executor === undefined) {
|
|
16
11
|
throw new Error(`RETENTION_SWEEP_INTERVAL_SEC=${input.intervalSec} arms the managed-retention sweep lane, but this deployment wires NO retention ` +
|
|
17
12
|
`executor — the destructive store methods live on the SQL backends only (DB_BACKEND=mysql|pg); the local/file backend honestly ` +
|
|
18
13
|
`declares retention:"none" and nothing would delete a row${lockNote}. Run a SQL backend, or set RETENTION_SWEEP_INTERVAL_SEC=0.`);
|
|
19
14
|
}
|
|
20
15
|
const executor = input.executor;
|
|
21
|
-
const
|
|
22
|
-
for (const m of CONTRACT_METHODS) {
|
|
16
|
+
for (const m of LANE_EXECUTOR_METHODS) {
|
|
23
17
|
if (typeof executor[m] !== "function") {
|
|
24
18
|
throw new Error(`the wired retention executor is missing \`${m}\` — a store that declares retention:"managed" PROMISES the whole ` +
|
|
25
19
|
`ManagedRetentionCapability contract, and the sweep lane calls every method of it${lockNote}. Refusing to start with a ` +
|
|
@@ -29,6 +29,7 @@ import type { ToolApprovalCoordinator } from "../tool-approval.js";
|
|
|
29
29
|
import type { MemoryBackend } from "@sema-agent/core";
|
|
30
30
|
import type { MemorySyncRunner } from "../memory-sync-client.js";
|
|
31
31
|
import type { MailboxRecipientLifecycle } from "../plugins/mailbox-recipient-lifecycle.js";
|
|
32
|
+
import type { PeerDesk } from "../peer-seat.js";
|
|
32
33
|
/**
|
|
33
34
|
* `RunnerDeps.onAsk` 的装配([ref] 件4:从内联闭包提为具名导出,**纯 testability 重构、零行为变化**)。
|
|
34
35
|
*
|
|
@@ -65,7 +66,9 @@ export declare function createRunnerDepsOnAsk(toolApproval: ToolApprovalCoordina
|
|
|
65
66
|
* [ref]:第五词 `shell-gate-off` 随 core 7.34.0 的 off 车道一起退役(引擎侧零发射点),同批删 —— 它唯一的本仓消费者
|
|
66
67
|
* (「本 session 显式 bypass ⇒ 降级 info」那条回查腿与 `boot/session-shell-gate-registry.ts` 登记簿)一并删干净。所以这是「按实现亲读」的开集快照,不是 core 类型闭集——词表外的值原样进日志并标
|
|
67
68
|
* `classificationKnown:false`(指标标签折 `unknown`),不吞不编;与安装包的锁步由 test/boot-runner-deps-shared-base.test.ts
|
|
68
|
-
* 的 dist 扫描格钉住(两种发射写法都读;读不出词的经变量发射点本身红;core 加词/收进 d.ts 那天先红)。
|
|
69
|
+
* 的 dist 扫描格钉住(两种发射写法都读;读不出词的经变量发射点本身红;core 加词/收进 d.ts 那天先红)。
|
|
70
|
+
* 第七词 `peer-seat-hold`(runtask 的 `holdDeclarations`,字面量):对端座的三员对象里 `hold` / `release` 抛了 ⇒ 引擎报一次、该引用
|
|
71
|
+
* 不被持有;座是本仓的 desk,所以这是部署自己的故障,与其余六词同走 warn + 计数。 */
|
|
69
72
|
export declare const CONFIG_ADVISORY_CLASSIFICATIONS: ReadonlySet<string>;
|
|
70
73
|
/** [ref]:core 的 [ref] 前缀缓存**断裂**探测器交给宿主的根因**闭集**,以及每个词的日志级别。
|
|
71
74
|
* 闭集**不抄词**:词源直接取 core 公开导出的 `CacheBreakFinding["cause"]`(`@sema-agent/core` 根导出,
|
|
@@ -163,6 +166,8 @@ export interface RunnerDepsCtx {
|
|
|
163
166
|
/** core 7.49.0 [ref]:引擎数据根(boot 事实,`boot/stores.ts` 恒铸 —— 记忆引擎开不开都在)。共享基座把它交成每只 Runner 的
|
|
164
167
|
* `memoryEngineDir`:引擎从它解出每条腿的唯一豁免根(守卫集不再收 `dataRoot`)。开引擎时与 `memoryEngine.root` 同一只。 */
|
|
165
168
|
engineDataRoot: string;
|
|
169
|
+
/** 对端座的 desk(进程一只,`peer-seat.ts`):共享基座把它的座交成每只 Runner 的 `peerSeat` —— MCP / A2A 声明里的引用只经它在发送时作答。 */
|
|
170
|
+
peerDesk: PeerDesk;
|
|
166
171
|
/**
|
|
167
172
|
* [ref](core 7.21.1)—— 记忆整理的**已解析座**(`boot/memory-consolidation.ts` 的
|
|
168
173
|
* `resolveConsolidationDriverSeat` 产物),在场 **iff** 整理阀门开着(`resolveConsolidationValve` 的判决:
|
|
@@ -228,7 +233,8 @@ export interface RunnerDepsCtx {
|
|
|
228
233
|
executionEnvFactory: RunnerDeps["executionEnvFactory"];
|
|
229
234
|
lspManager: RunnerDeps["lspManager"];
|
|
230
235
|
fleetBus: FleetEventBus;
|
|
231
|
-
/** 部署座的 mods 注册(
|
|
236
|
+
/** 部署座的 mods 注册(起服第 5 段装配口 `assembleDeploymentMods` 铸:自铸 + 运维声明的包,起服自证过)—— 主 / handless / hookAgent / sub 经本共享基座、
|
|
237
|
+
* leader 车道的路由 / worker / 修复腿经 `LeaderWireConfig.mods`(`boot/leader.ts` 递同一份),每一只 Runner 同一份。 */
|
|
232
238
|
deploymentMods: NonNullable<RunnerDeps["mods"]>;
|
|
233
239
|
workflowRunStore: WorkflowRunStore | undefined;
|
|
234
240
|
workflowJournalStore: ServiceWorkflowJournalStore | undefined;
|
|
@@ -241,7 +247,7 @@ export interface RunnerDepsCtx {
|
|
|
241
247
|
}
|
|
242
248
|
/** [ref] A10 留档发现②:main runner `RunnerDeps` 与 main.ts subRunner 字面量之间此前手工重复
|
|
243
249
|
* 的 ~15 个键,类型标注见 {@link createSharedRunnerDeps} 头注。 */
|
|
244
|
-
export type SharedRunnerDeps = Pick<RunnerDeps, "brain" | "readFace" | "readDenyPatterns" | "readDenyBuiltinTiers" | "readDenyBuiltinExclude" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "delegationEntryCaps" | "crossSessionInbound" | "crossSessionDialogExpiry" | "writeProtectedPaths" | "memoryEngineDir" | "allowedTools" | "crossBoundaryPosture" | "models" | "roles" | "tiers" | "pricing" | "tracer" | "promptSource" | "executionEnvFactory" | "lspManager" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "mods" | "toolResultStore" | "checkpointStore" | "hands" | "sessionPolicyStore" | "usageWindows" | "usageWindowStore" | "memoryScopeAdmission" | "deploymentMemoryScopes" | "sharedMemoryStores" | "compliancePostureResolver" | "lockedConfig" | "retentionPolicy" | "onNotice" | "mcpRevocations">;
|
|
250
|
+
export type SharedRunnerDeps = Pick<RunnerDeps, "brain" | "readFace" | "readDenyPatterns" | "readDenyBuiltinTiers" | "readDenyBuiltinExclude" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "delegationEntryCaps" | "crossSessionInbound" | "crossSessionDialogExpiry" | "writeProtectedPaths" | "memoryEngineDir" | "allowedTools" | "crossBoundaryPosture" | "models" | "roles" | "tiers" | "pricing" | "tracer" | "promptSource" | "executionEnvFactory" | "lspManager" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "mods" | "toolResultStore" | "checkpointStore" | "hands" | "sessionPolicyStore" | "usageWindows" | "usageWindowStore" | "memoryScopeAdmission" | "deploymentMemoryScopes" | "sharedMemoryStores" | "compliancePostureResolver" | "lockedConfig" | "retentionPolicy" | "onNotice" | "mcpRevocations" | "peerSeat">;
|
|
245
251
|
/**
|
|
246
252
|
* [ref] A10 留档发现②(review 2026-07-29,[ref]§三族A 同源修补的延续):main runner 的
|
|
247
253
|
* `RunnerDeps` 字面量(下方 `createRunnerDeps`)与 `main.ts` 里 subRunner 的 `new Runner({...})`
|
|
@@ -268,7 +274,7 @@ export type SharedRunnerDeps = Pick<RunnerDeps, "brain" | "readFace" | "readDeny
|
|
|
268
274
|
* 属性,比再抽一层共享基座更强的同源保证),不重复收纳进这里。
|
|
269
275
|
*/
|
|
270
276
|
/** 基座真实消费的窄面(Pick)——subRunner 调用点(main.ts)只需凑这 13 个字段,不必造全量 ctx。 */
|
|
271
|
-
export type SharedRunnerDepsCtx = Pick<RunnerDepsCtx, "config" | "brain" | "pricing" | "tracer" | "promptSource" | "executionEnvFactory" | "lspManager" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "deploymentMods" | "toolResultStore" | "checkpointStore" | "sessionPolicyStore" | "hands" | "usageWindowStore" | "orgMemoryAdmission" | "sharedMemoryStores" | "logger" | "governanceSeams" | "mcpRevocations" | "metrics" | "engineDataRoot">;
|
|
277
|
+
export type SharedRunnerDepsCtx = Pick<RunnerDepsCtx, "config" | "brain" | "pricing" | "tracer" | "promptSource" | "executionEnvFactory" | "lspManager" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "deploymentMods" | "toolResultStore" | "checkpointStore" | "sessionPolicyStore" | "hands" | "usageWindowStore" | "orgMemoryAdmission" | "sharedMemoryStores" | "logger" | "governanceSeams" | "mcpRevocations" | "metrics" | "engineDataRoot" | "peerDesk">;
|
|
272
278
|
/** 转发席只需要 `inc` —— 刻意窄到这一个动词,免得把整只 Metrics 拖进这条纯转发腿。 */
|
|
273
279
|
export interface EngineNoticeMetricsSeat {
|
|
274
280
|
inc: (name: string, labels?: Record<string, string>) => void;
|