@sema-agent/server 7.140.0 → 7.142.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 +505 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +142 -25
- package/dist/approval-ask-audit-store.d.ts +54 -38
- package/dist/approval-ask-audit-store.js +58 -39
- package/dist/approval-batch-census.d.ts +27 -0
- package/dist/approval-batch-census.js +27 -0
- package/dist/approval-card.d.ts +39 -24
- package/dist/approval-card.js +6 -3
- package/dist/approval-crash-convergence.d.ts +17 -7
- package/dist/approval-crash-convergence.js +94 -22
- package/dist/approval-deny-reasons.d.ts +34 -30
- package/dist/approval-deny-reasons.js +21 -6
- package/dist/approval-policy-settlement.d.ts +1 -1
- package/dist/approval-reconciler.d.ts +33 -1
- package/dist/approval-reconciler.js +43 -40
- package/dist/approval.d.ts +15 -0
- package/dist/approval.js +10 -0
- package/dist/audit.d.ts +4 -2
- package/dist/audit.js +2 -2
- package/dist/auth-bridge.d.ts +9 -6
- package/dist/auth-bridge.js +9 -3
- package/dist/boot/adoption.js +2 -1
- package/dist/boot/budget-tracing.d.ts +16 -0
- package/dist/boot/budget-tracing.js +10 -6
- package/dist/boot/device-lane.d.ts +11 -0
- package/dist/boot/device-lane.js +16 -0
- package/dist/boot/engine-lease.d.ts +24 -3
- package/dist/boot/engine-lease.js +9 -2
- package/dist/boot/execution-env.d.ts +24 -4
- package/dist/boot/execution-env.js +34 -27
- package/dist/boot/execution-lane.js +2 -1
- package/dist/boot/exit-boundary.js +5 -4
- package/dist/boot/memory-boundary.d.ts +2 -2
- package/dist/boot/memory-consolidation.d.ts +1 -1
- package/dist/boot/memory-consolidation.js +3 -2
- package/dist/boot/parked-revive-gate.js +2 -1
- package/dist/boot/permission-rules-audit.d.ts +0 -28
- package/dist/boot/permission-rules-audit.js +2 -1
- package/dist/boot/read-deny-anchor-audit.js +2 -1
- package/dist/boot/reapers.d.ts +2 -2
- package/dist/boot/reapers.js +4 -3
- package/dist/boot/resolve-spec.js +18 -6
- package/dist/boot/retention-lane.js +5 -3
- package/dist/boot/runner-deps.js +16 -13
- package/dist/boot/runtime-caps.js +3 -2
- package/dist/boot/session-faces.d.ts +1 -1
- package/dist/boot/session-faces.js +8 -6
- package/dist/boot/shutdown.js +8 -2
- package/dist/boot/stage-04-stores.js +3 -2
- package/dist/boot/stage-05-execution-env.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.js +11 -7
- package/dist/boot/stage-06-runners.d.ts +1 -3
- package/dist/boot/stage-06-runners.js +3 -2
- package/dist/boot/stage-07-capability-layer.d.ts +1 -2
- package/dist/boot/stage-07-capability-layer.js +10 -11
- package/dist/boot/stage-08-reapers.d.ts +1 -2
- package/dist/boot/stage-08-reapers.js +3 -2
- package/dist/boot/stage-09-leader.d.ts +1 -2
- package/dist/boot/stage-10-http-server.d.ts +1 -2
- package/dist/boot/stage-10-http-server.js +6 -4
- package/dist/boot/stores.js +13 -6
- package/dist/boot/web-admin.js +18 -17
- package/dist/boot/webfetch-summarize-lane.js +2 -1
- package/dist/boot/workflow-orchestration.js +3 -2
- package/dist/capabilities/builtin-tools.d.ts +2 -1
- package/dist/capabilities/builtin-tools.js +2 -4
- package/dist/capabilities/composite-members.d.ts +2 -1
- package/dist/capabilities/composite-members.js +2 -1
- package/dist/capabilities/scenarios.d.ts +1 -1
- package/dist/capability-facts.d.ts +33 -0
- package/dist/capability-facts.js +32 -0
- package/dist/card-void.d.ts +38 -0
- package/dist/card-void.js +23 -0
- package/dist/config-catalog.js +12 -8
- package/dist/config-provider.d.ts +13 -13
- package/dist/config-provider.js +19 -33
- package/dist/config-types.d.ts +39 -10
- package/dist/config.d.ts +6 -0
- package/dist/config.js +72 -49
- package/dist/delegated-session-owner.d.ts +21 -19
- package/dist/delegated-session-owner.js +1 -1
- package/dist/device-store.d.ts +7 -0
- package/dist/device-store.js +3 -0
- package/dist/execution-config-root.d.ts +22 -0
- package/dist/execution-config-root.js +35 -0
- package/dist/execution-lane-caps.d.ts +50 -2
- package/dist/execution-lane-caps.js +90 -13
- package/dist/execution-placement.d.ts +3 -0
- package/dist/execution-placement.js +7 -0
- package/dist/fleet/drain-entry.d.ts +3 -0
- package/dist/fleet/fleet-bus.d.ts +6 -3
- package/dist/hooks/hook-runner.d.ts +6 -0
- package/dist/hooks/hook-runner.js +30 -1
- package/dist/hosted-posture.d.ts +8 -0
- package/dist/hosted-posture.js +4 -0
- package/dist/http/admission.js +3 -3
- package/dist/http/caller-trust.d.ts +3 -2
- package/dist/http/caller-trust.js +2 -1
- package/dist/http/dispatch.js +8 -2
- package/dist/http/execution-context.d.ts +2 -2
- package/dist/http/idempotency.d.ts +1 -1
- package/dist/http/live-frame.d.ts +24 -0
- package/dist/http/live-frame.js +16 -0
- package/dist/http/principal-gate.d.ts +3 -1
- package/dist/http/principal-gate.js +17 -8
- package/dist/http/resume-legs.js +42 -29
- package/dist/http/route-table.js +4 -0
- package/dist/http/routes/approvals-assistant.js +1 -0
- package/dist/http/routes/attachments.js +18 -0
- package/dist/http/routes/capabilities.js +10 -6
- package/dist/http/routes/diagnostics.d.ts +0 -19
- package/dist/http/routes/diagnostics.js +16 -2
- package/dist/http/routes/memory-bundle.d.ts +2 -2
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-policy.js +27 -7
- package/dist/http/routes/run-permission-mode.d.ts +75 -0
- package/dist/http/routes/run-permission-mode.js +170 -0
- package/dist/http/routes/runs.js +3 -3
- package/dist/http/routes/session-memory-sync.d.ts +63 -0
- package/dist/http/routes/session-memory-sync.js +157 -0
- package/dist/http/routes/session-sync.d.ts +3 -6
- package/dist/http/routes/session-sync.js +7 -2
- package/dist/http/routes/sessions-list.d.ts +2 -1
- package/dist/http/routes/sessions.js +5 -4
- package/dist/http/routes/tasks.js +70 -71
- package/dist/http/run-read-face.d.ts +7 -0
- package/dist/http/run-read-face.js +10 -4
- package/dist/http/send.d.ts +6 -1
- package/dist/http/send.js +10 -3
- package/dist/http/server.d.ts +20 -7
- package/dist/http/server.js +2 -4
- package/dist/http/sse-log.d.ts +3 -8
- package/dist/http/stored-body-replay.d.ts +3 -3
- package/dist/http/stored-body-replay.js +3 -1
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +2 -2
- package/dist/http/sync-submit-body.d.ts +21 -4
- package/dist/http/sync-submit-body.js +13 -0
- package/dist/identity-source.d.ts +21 -2
- package/dist/identity-source.js +6 -0
- package/dist/instruction-source-notice.d.ts +7 -0
- package/dist/instruction-source-notice.js +6 -6
- package/dist/mcp-assertion-header.d.ts +4 -0
- package/dist/mcp-assertion-header.js +5 -0
- package/dist/memory-incident-sink.d.ts +19 -6
- package/dist/memory-incident-sink.js +8 -4
- package/dist/memory-posture.d.ts +1 -1
- package/dist/memory-scope.d.ts +4 -4
- package/dist/memory-scope.js +1 -1
- package/dist/memory-sync-client.d.ts +35 -23
- package/dist/memory-sync-client.js +122 -52
- package/dist/memory-sync-identity.d.ts +24 -0
- package/dist/memory-sync-identity.js +57 -0
- package/dist/memory-sync.d.ts +7 -1
- package/dist/memory-sync.js +6 -3
- package/dist/observability/fail-open.d.ts +57 -12
- package/dist/observability/fail-open.js +50 -9
- package/dist/observability/metrics.js +0 -1
- package/dist/observability/run-terminal.d.ts +93 -31
- package/dist/observability/run-terminal.js +175 -171
- package/dist/observability/secret-env-scrub.d.ts +20 -1
- package/dist/observability/secret-env-scrub.js +14 -0
- package/dist/orchestration/workflow-completion-inbox.d.ts +5 -2
- package/dist/orchestration/workflow-completion-inbox.js +13 -5
- package/dist/orchestration/workflow-notify-journal.d.ts +5 -3
- package/dist/orchestration/workflow-notify-journal.js +2 -1
- package/dist/permission-mode-admission.d.ts +68 -0
- package/dist/permission-mode-admission.js +23 -0
- package/dist/permission-rule-list.d.ts +55 -6
- package/dist/permission-rule-list.js +52 -5
- package/dist/plugins/approval-ask-store-file.d.ts +14 -4
- package/dist/plugins/approval-ask-store-file.js +48 -7
- package/dist/plugins/approval-ask-store-memory.d.ts +2 -1
- package/dist/plugins/approval-ask-store-memory.js +9 -8
- package/dist/plugins/approval-ask-store-sql.d.ts +42 -10
- package/dist/plugins/approval-ask-store-sql.js +49 -19
- package/dist/plugins/caching-session-store.d.ts +6 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +65 -17
- package/dist/plugins/checkpoint-store-sql.js +74 -3
- package/dist/plugins/device-store-sql.d.ts +5 -2
- package/dist/plugins/device-store-sql.js +4 -1
- package/dist/plugins/execution-placement-sql.d.ts +11 -1
- package/dist/plugins/execution-placement-sql.js +12 -1
- package/dist/plugins/file-run-store.d.ts +7 -2
- package/dist/plugins/file-run-store.js +12 -2
- package/dist/plugins/fork-routing-session-store.d.ts +10 -32
- package/dist/plugins/fork-routing-session-store.js +2 -61
- package/dist/plugins/k8s-exec-protocol.d.ts +4 -1
- package/dist/plugins/k8s-exec-protocol.js +6 -1
- package/dist/plugins/local-checkpoint-store.d.ts +10 -1
- package/dist/plugins/local-checkpoint-store.js +22 -0
- package/dist/plugins/local-session-store.d.ts +260 -39
- package/dist/plugins/local-session-store.js +582 -57
- package/dist/plugins/local-session-window.d.ts +17 -3
- package/dist/plugins/local-session-window.js +7 -13
- package/dist/plugins/local-task-attachment-store.d.ts +12 -2
- package/dist/plugins/local-task-attachment-store.js +67 -43
- package/dist/plugins/memory-key-guards.d.ts +3 -3
- package/dist/plugins/memory-run-store.d.ts +7 -2
- package/dist/plugins/memory-run-store.js +12 -2
- package/dist/plugins/one-time-migrations.d.ts +68 -2
- package/dist/plugins/one-time-migrations.js +120 -4
- package/dist/plugins/pg-pool.js +3 -2
- package/dist/plugins/pg-session-storage.d.ts +2 -0
- package/dist/plugins/pg-session-storage.js +3 -2
- package/dist/plugins/remote-env-e2b.d.ts +47 -7
- package/dist/plugins/remote-env-e2b.js +242 -46
- package/dist/plugins/remote-env-k8s.d.ts +51 -6
- package/dist/plugins/remote-env-k8s.js +234 -44
- package/dist/plugins/remote-env-local-docker.d.ts +40 -14
- package/dist/plugins/remote-env-local-docker.js +127 -33
- package/dist/plugins/run-store-sql.d.ts +11 -3
- package/dist/plugins/run-store-sql.js +13 -4
- package/dist/plugins/sandbox-read-floor.d.ts +273 -0
- package/dist/plugins/sandbox-read-floor.js +608 -0
- package/dist/plugins/session-ownership.d.ts +2 -1
- package/dist/plugins/session-placement.d.ts +17 -4
- package/dist/plugins/session-placement.js +2 -1
- package/dist/plugins/session-store.d.ts +18 -20
- package/dist/plugins/session-store.js +4 -12
- package/dist/plugins/store-backend.d.ts +41 -7
- package/dist/plugins/store-backend.js +22 -4
- package/dist/plugins/store-contracts.d.ts +35 -3
- package/dist/plugins/store-contracts.js +3 -0
- package/dist/plugins/task-attachment-store.d.ts +112 -14
- package/dist/plugins/task-attachment-store.js +221 -28
- package/dist/plugins/tidb-pool.js +2 -1
- package/dist/plugins/tidb-session-store.d.ts +4 -1
- package/dist/plugins/tidb-session-store.js +3 -2
- package/dist/plugins/workspace-fill.d.ts +60 -0
- package/dist/plugins/workspace-fill.js +106 -0
- package/dist/project-bundle.d.ts +38 -0
- package/dist/project-bundle.js +609 -0
- package/dist/run-cancel-context.d.ts +34 -0
- package/dist/run-cancel-context.js +7 -0
- package/dist/run-local.js +2 -8
- package/dist/runs.d.ts +39 -12
- package/dist/runs.js +69 -55
- package/dist/sandbox-egress-policy.d.ts +4 -1
- package/dist/sandbox-egress-policy.js +3 -1
- package/dist/sandbox-git-plane.d.ts +31 -12
- package/dist/sandbox-git-plane.js +24 -4
- package/dist/security.d.ts +11 -2
- package/dist/security.js +8 -0
- package/dist/server-secret-env.d.ts +2 -1
- package/dist/server-secret-env.js +2 -4
- package/dist/session-error-wire.d.ts +46 -4
- package/dist/session-error-wire.js +23 -0
- package/dist/session-incarnation.d.ts +9 -3
- package/dist/session-sync-kernel.d.ts +42 -1
- package/dist/session-sync-kernel.js +17 -0
- package/dist/session-sync.js +16 -4
- package/dist/sql-engine-coordinates.d.ts +49 -0
- package/dist/sql-engine-coordinates.js +27 -0
- package/dist/standing-answer-grant.d.ts +31 -2
- package/dist/standing-answer-grant.js +14 -2
- package/dist/store-posture.d.ts +1 -1
- package/dist/task-a2a.d.ts +1 -1
- package/dist/task-mcp.d.ts +1 -1
- package/dist/task-settings.d.ts +62 -27
- package/dist/task-settings.js +105 -29
- package/dist/terminal.d.ts +97 -20
- package/dist/terminal.js +107 -18
- package/dist/tool-approval.d.ts +4 -3
- package/dist/tool-approval.js +12 -14
- package/dist/trace/core-keyset-guard.d.ts +196 -2
- package/dist/trace/engine-notice-wire.d.ts +8 -2
- package/dist/trace/engine-notice-wire.js +4 -2
- package/dist/trace/exit-seat.d.ts +9 -1
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/ledger-sink.d.ts +8 -4
- package/dist/trace/ledger-sink.js +2 -2
- package/dist/trace/model-segment.d.ts +2 -2
- package/dist/trace/project.d.ts +18 -1
- package/dist/trace/project.js +16 -0
- package/dist/trace/redact.js +323 -90
- package/dist/trace/self-minted-wire.d.ts +419 -4
- package/dist/trace/self-minted-wire.js +145 -0
- package/dist/trace/wire-projection-faces.d.ts +1 -1
- package/dist/trace/wire-projection-faces.js +1 -1
- package/dist/verifier-pause-card.d.ts +8 -0
- package/dist/verifier-pause-card.js +19 -0
- package/dist/web-admin-client/apply-effective.d.ts +5 -7
- package/dist/web-admin-client/apply-effective.js +22 -2
- package/dist/web-admin-client/candidate-gate.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.js +2 -0
- package/dist/web-admin-client/read-warnings.d.ts +2 -2
- package/dist/web-admin-client/types.d.ts +4 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
- package/package.json +2 -2
- package/wire-changes/server@7.141.0.json +367 -0
- package/wire-changes/server@7.142.0.json +639 -0
|
@@ -11,10 +11,11 @@ import { PerTaskImageRegistry } from "../per-task-image.js";
|
|
|
11
11
|
import { adbExecutionEnvFactory } from "../plugins/remote-env-adb.js";
|
|
12
12
|
import { deviceExecutionEnvFactory } from "../plugins/remote-env-device.js";
|
|
13
13
|
import { e2bExecutionEnvFactory } from "../plugins/remote-env-e2b.js";
|
|
14
|
+
import { createWorkspaceFill } from "../plugins/workspace-fill.js";
|
|
14
15
|
import { hostExecutionEnvFactory, RemoteHostExecutionEnv } from "../plugins/remote-env-host.js";
|
|
15
16
|
import { boundedStoreCall, checkSandboxEgressPolicy, createSandboxPodApi, createSpaceReclaimer, k8sExecutionEnvFactory, readSandboxSecretSeat, rpcTimeoutMsOf } from "../plugins/remote-env-k8s.js";
|
|
16
17
|
import { podSpecPatchBrokerRefusal, SANDBOX_SECRET_SEAT_VERBS } from "../plugins/k8s-exec-protocol.js";
|
|
17
|
-
import {
|
|
18
|
+
import { createSandboxBrokerSeatOf, createSandboxGitPlaneSeat, sandboxGitPlanePremisesOf } from "../sandbox-git-plane.js";
|
|
18
19
|
import { createSandboxPodReaper } from "../plugins/k8s-pod-reaper.js";
|
|
19
20
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
20
21
|
import { createRunWorkspaceSnapshotSeat } from "../fleet/workspace-snapshot-residual.js";
|
|
@@ -30,13 +31,15 @@ import { derivePkgSourceEnv } from "../sandbox-pkg-source.js";
|
|
|
30
31
|
import { effectiveHostWorkspace } from "../task-cwd.js";
|
|
31
32
|
import { taskInheritEnvRefusal } from "../hosted-posture.js";
|
|
32
33
|
import { sessionFaceOfHead } from "../session-incarnation.js";
|
|
34
|
+
import { isCodeToken } from "../terminal.js";
|
|
33
35
|
import { createCacheMissMemory } from "../workspace-cache.js";
|
|
34
36
|
import { workspaceSnapshotTimeoutOf } from "../workspace-space.js";
|
|
35
37
|
import { sayEgressPolicyReading } from "../sandbox-egress-policy.js";
|
|
36
38
|
import { sandboxPathEnvSlots, withSandboxPathEnvSlot } from "./deferred-sandbox-path-env.js";
|
|
37
39
|
import { createLaneHomeAbsenceReporter } from "../lane-home-probe.js";
|
|
38
|
-
import { REMOTE_EXEC_PROVIDER_WORDS, buildLaneHomeBootNote, buildLaneHomeClaim, capabilitiesFor, executionLaneOf, laneBindsReads, laneIsolated } from "../execution-lane-caps.js";
|
|
40
|
+
import { REMOTE_EXEC_PROVIDER_WORDS, buildLaneHomeBootNote, buildLaneHomeClaim, capabilitiesFor, executionLaneOf, laneBindsReads, laneIsolated, laneSandboxReadFloorState } from "../execution-lane-caps.js";
|
|
39
41
|
import { warnReadDenyFloorUnkept } from "./execution-lane.js";
|
|
42
|
+
import { seatText } from "../trace/exit-seat.js";
|
|
40
43
|
function boundedSessionSetter(map, maxEntries) {
|
|
41
44
|
return (sid, value) => {
|
|
42
45
|
map.delete(sid);
|
|
@@ -104,15 +107,19 @@ export function createSessionScopedRegistries(maxEntries = MAX_CWD_SESSIONS) {
|
|
|
104
107
|
dropSession,
|
|
105
108
|
};
|
|
106
109
|
}
|
|
110
|
+
export function ownsItsWorkspace(ctx) {
|
|
111
|
+
return ctx.placementRootSessionId === ctx.sessionId;
|
|
112
|
+
}
|
|
107
113
|
export function createK8sRunEnvFactory(k8sCfg, seats, deps) {
|
|
108
114
|
const cacheMisses = createCacheMissMemory();
|
|
109
115
|
return async (ctx) => {
|
|
110
116
|
const onWorkspaceSnapshot = createRunWorkspaceSnapshotSeat(ctx.sessionId);
|
|
111
|
-
const child = ctx
|
|
117
|
+
const child = !ownsItsWorkspace(ctx);
|
|
112
118
|
const s3Snapshot = child && k8sCfg.s3Snapshot !== undefined ? spaceOff(k8sCfg.s3Snapshot) : k8sCfg.s3Snapshot;
|
|
113
119
|
const spaceOccupant = child ? undefined : await occupantOf(seats, ctx.sessionId, ctx.taskId, rpcTimeoutMsOf(k8sCfg));
|
|
114
120
|
const runId = !child && ctx.taskId !== undefined ? ctx.taskId : undefined;
|
|
115
121
|
const sandboxBroker = await seats.brokerSeatOf?.(runId);
|
|
122
|
+
const workspaceFill = seats.workspaceFillOf?.(ctx);
|
|
116
123
|
const { cache, ...deploymentCfg } = k8sCfg;
|
|
117
124
|
return k8sExecutionEnvFactory({
|
|
118
125
|
...deploymentCfg,
|
|
@@ -122,11 +129,11 @@ export function createK8sRunEnvFactory(k8sCfg, seats, deps) {
|
|
|
122
129
|
...(spaceOccupant !== undefined ? { spaceOccupant } : {}),
|
|
123
130
|
...(runId !== undefined ? { runId } : {}),
|
|
124
131
|
...(sandboxBroker !== undefined ? { sandboxBroker } : {}),
|
|
132
|
+
...(workspaceFill !== undefined ? { workspaceFill } : {}),
|
|
125
133
|
onWorkspaceSnapshot,
|
|
126
134
|
}, deps)(ctx);
|
|
127
135
|
};
|
|
128
136
|
}
|
|
129
|
-
const STORE_ERROR_CODE = /^[A-Za-z0-9_.:-]{1,64}$/;
|
|
130
137
|
const INCARNATION_READ_TIMEOUT = "incarnation_read_timeout";
|
|
131
138
|
async function occupantOf(seats, sessionId, taskId, boundMs) {
|
|
132
139
|
let answer;
|
|
@@ -142,7 +149,7 @@ async function occupantOf(seats, sessionId, taskId, boundMs) {
|
|
|
142
149
|
}
|
|
143
150
|
catch (e) {
|
|
144
151
|
const code = e?.code;
|
|
145
|
-
return { fault:
|
|
152
|
+
return { fault: isCodeToken(code) ? code : "incarnation_read_failed" };
|
|
146
153
|
}
|
|
147
154
|
if (answer === undefined)
|
|
148
155
|
return { unread: "incarnation_unknown" };
|
|
@@ -171,7 +178,7 @@ export async function ensureSandboxSecretSeat(k8sCfg, logger, deps, read = () =>
|
|
|
171
178
|
recordFailOpen("server.sandbox-secret.seat-unverified", `namespace=${namespace} ${seat.detail}`);
|
|
172
179
|
logger.warn("sandbox_secret_seat_unverified", {
|
|
173
180
|
namespace,
|
|
174
|
-
detail: seat.detail,
|
|
181
|
+
detail: seatText("operator-log-text", seat.detail),
|
|
175
182
|
effect: `the boot could not confirm the sandbox Secret RBAC (secrets ${SANDBOX_SECRET_SEAT_VERBS.env.join(" / ")}) — the service starts; if the Role lacks them, the first run that forwards K8S_SANDBOX_ENV is refused at connect (auth_failed) and its pod deleted — the values never go into the pod spec`,
|
|
176
183
|
});
|
|
177
184
|
return;
|
|
@@ -239,9 +246,9 @@ export function createExecutionEnv(ctx) {
|
|
|
239
246
|
let spaceReclaimer;
|
|
240
247
|
let sandboxSecretSeatGate;
|
|
241
248
|
let sandboxPodReaper;
|
|
242
|
-
|
|
243
|
-
let readSandboxGitPlane = async () => (planeCell.current = judgeSandboxGitPlane(sandboxGitPlanePremisesOf(config, {})));
|
|
249
|
+
let sandboxGitPlane = createSandboxGitPlaneSeat((r) => sandboxGitPlanePremisesOf(config, r), {});
|
|
244
250
|
let worktreeReap;
|
|
251
|
+
const workspaceFillOf = taskAttachmentStore === undefined ? undefined : (fctx) => createWorkspaceFill({ store: taskAttachmentStore, sessionId: fctx.sessionId, seeds: ownsItsWorkspace(fctx), logger });
|
|
245
252
|
if (config.remoteExec?.provider === "e2b") {
|
|
246
253
|
executionEnvFactory = e2bExecutionEnvFactory({
|
|
247
254
|
apiKey: config.remoteExec.apiKey,
|
|
@@ -252,9 +259,11 @@ export function createExecutionEnv(ctx) {
|
|
|
252
259
|
...(config.remoteExec.allowInternetAccess != null ? { allowInternetAccess: config.remoteExec.allowInternetAccess } : {}),
|
|
253
260
|
...(config.remoteExec.mountPath ? { mountPath: config.remoteExec.mountPath } : {}),
|
|
254
261
|
...((env) => (env !== undefined ? { sandboxEnv: env } : {}))(sandboxLaneEnvMerged(buildSandboxLaneEnv(config, config.remoteExec.sandboxEnv))),
|
|
262
|
+
sandboxReadFloor: config.sandboxReadFloor,
|
|
263
|
+
...(workspaceFillOf !== undefined ? { workspaceFillOf } : {}),
|
|
255
264
|
logger,
|
|
256
265
|
metrics,
|
|
257
|
-
});
|
|
266
|
+
}, ctx.laneDeps?.e2b);
|
|
258
267
|
}
|
|
259
268
|
else if (config.remoteExec?.provider === "k8s") {
|
|
260
269
|
const k8sCfg = {
|
|
@@ -278,31 +287,26 @@ export function createExecutionEnv(ctx) {
|
|
|
278
287
|
...(config.remoteExec.workspaceSnapshotExclude ? { snapshotExclude: config.remoteExec.workspaceSnapshotExclude } : {}),
|
|
279
288
|
logger,
|
|
280
289
|
...((lane) => ({ ...(lane.env !== undefined ? { podEnv: lane.env } : {}), ...(lane.secretEnv !== undefined ? { podSecretEnv: lane.secretEnv } : {}) }))(buildSandboxLaneEnv(config, config.remoteExec.sandboxEnv)),
|
|
290
|
+
sandboxReadFloor: config.sandboxReadFloor,
|
|
281
291
|
};
|
|
282
|
-
|
|
292
|
+
sandboxGitPlane = createSandboxGitPlaneSeat((r) => sandboxGitPlanePremisesOf(config, r), {
|
|
293
|
+
patchRefusal: podSpecPatchBrokerRefusal(k8sCfg.podSpecPatch),
|
|
294
|
+
askSecretSeat: () => readSandboxSecretSeat(k8sCfg, "lease"),
|
|
295
|
+
});
|
|
283
296
|
executionEnvFactory = createK8sRunEnvFactory(k8sCfg, {
|
|
284
297
|
imageOf: (sid) => perTaskImage.get(sid),
|
|
285
298
|
headOf: ctx.headOf,
|
|
286
299
|
spaceCommits: ctx.spaceCommits ?? (() => undefined),
|
|
287
|
-
brokerSeatOf:
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
return undefined;
|
|
291
|
-
return sandboxBrokerSeatOf(plane, brokerImage, await runIdentitySourceOf(runId, ctx.runRows?.(), logger));
|
|
292
|
-
},
|
|
293
|
-
});
|
|
300
|
+
brokerSeatOf: createSandboxBrokerSeatOf(sandboxGitPlane.now, config.remoteExec.brokerImage, ctx.runRows, logger),
|
|
301
|
+
...(workspaceFillOf !== undefined ? { workspaceFillOf } : {}),
|
|
302
|
+
}, ctx.laneDeps?.k8s);
|
|
294
303
|
if (k8sCfg.cache !== undefined || k8sCfg.s3Snapshot !== undefined)
|
|
295
304
|
spaceReclaimer = createSpaceReclaimer(k8sCfg);
|
|
296
305
|
sandboxSecretSeatGate = () => ensureSandboxSecretSeat(k8sCfg, logger, undefined, () => readSandboxSecretSeat(k8sCfg, "env"));
|
|
297
|
-
readSandboxGitPlane = async () => {
|
|
298
|
-
const premises = sandboxGitPlanePremisesOf(config, { ...((r) => (r !== undefined ? { patchRefusal: r } : {}))(podSpecPatchBrokerRefusal(k8sCfg.podSpecPatch)) });
|
|
299
|
-
const secretSeat = sandboxGitPlaneAsksSecretSeat(premises) ? await readSandboxSecretSeat(k8sCfg, "lease") : undefined;
|
|
300
|
-
return (planeCell.current = judgeSandboxGitPlane({ ...premises, secretSeat }));
|
|
301
|
-
};
|
|
302
306
|
sandboxPodReaper = createSandboxPodReaper({ api: createSandboxPodApi(k8sCfg), logger, metrics });
|
|
303
307
|
void checkSandboxEgressPolicy(k8sCfg)
|
|
304
308
|
.then((gaps) => sayEgressPolicyReading(gaps, logger, k8sCfg.namespace))
|
|
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" }));
|
|
309
|
+
.catch((e) => logger.error("sandbox_egress_policy_check_crashed", { error: seatText("operator-log-text", 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" }));
|
|
306
310
|
}
|
|
307
311
|
else if (config.remoteExec?.provider === "ssh") {
|
|
308
312
|
executionEnvFactory = sshExecutionEnvFactory({
|
|
@@ -394,7 +398,9 @@ export function createExecutionEnv(ctx) {
|
|
|
394
398
|
...(config.remoteExec.network ? { network: config.remoteExec.network } : {}),
|
|
395
399
|
...(config.remoteExec.commandTimeoutMs != null ? { commandTimeoutMs: config.remoteExec.commandTimeoutMs } : {}),
|
|
396
400
|
...(config.remoteExec.env ? { env: config.remoteExec.env } : {}),
|
|
397
|
-
|
|
401
|
+
sandboxReadFloor: config.sandboxReadFloor,
|
|
402
|
+
...(workspaceFillOf !== undefined ? { workspaceFillOf } : {}),
|
|
403
|
+
}, ctx.laneDeps?.localDocker);
|
|
398
404
|
}
|
|
399
405
|
if (executionEnvFactory && DEPLOYMENT_SHAPE_PREDICATES.remoteScratchpad.holds(config)) {
|
|
400
406
|
executionEnvFactory = withRemoteScratchpad(executionEnvFactory, logger);
|
|
@@ -448,7 +454,7 @@ export function createExecutionEnv(ctx) {
|
|
|
448
454
|
executionEnvFactory = registry.wrapFactory(executionEnvFactory);
|
|
449
455
|
return registry;
|
|
450
456
|
})();
|
|
451
|
-
if (taskAttachmentStore && executionEnvFactory) {
|
|
457
|
+
if (taskAttachmentStore && executionEnvFactory && !laneIsolated(executionLaneOf(config.remoteExec.provider))) {
|
|
452
458
|
const inner = executionEnvFactory;
|
|
453
459
|
const attStore = taskAttachmentStore;
|
|
454
460
|
executionEnvFactory = async (ctx) => {
|
|
@@ -466,8 +472,9 @@ export function createExecutionEnv(ctx) {
|
|
|
466
472
|
const isolated = laneIsolated(executionLaneOf(config.remoteExec.provider));
|
|
467
473
|
const suspendable = DEPLOYMENT_SHAPE_PREDICATES.suspendableHands.holds(config);
|
|
468
474
|
const keepsReadFloor = capabilitiesFor(config).keepsReadFloor;
|
|
475
|
+
const sandboxReadFloor = laneSandboxReadFloorState(config);
|
|
469
476
|
const sandboxEnvKeys = [...sandboxEnvNamesInForce(config)].sort();
|
|
470
|
-
logger.info("remote_exec_enabled", { provider: config.remoteExec.provider, isolated, suspendable, keepsReadFloor, ...(sandboxEnvKeys.length > 0 ? { sandboxEnvKeys } : {}) });
|
|
477
|
+
logger.info("remote_exec_enabled", { provider: config.remoteExec.provider, isolated, suspendable, keepsReadFloor, ...(sandboxReadFloor !== undefined ? { sandboxReadFloor } : {}), ...(sandboxEnvKeys.length > 0 ? { sandboxEnvKeys } : {}) });
|
|
471
478
|
if (!isolated)
|
|
472
479
|
logger.warn("remote_exec_real_system", { provider: config.remoteExec.provider, note: buildRealSystemNote(config.remoteExec) });
|
|
473
480
|
const homeLine = buildLaneHomeBootNote(config);
|
|
@@ -503,7 +510,7 @@ export function createExecutionEnv(ctx) {
|
|
|
503
510
|
perTaskImage, sessionEnvSelection, perSessionCwd, setSessionCwd, setSessionShellEnv, setSessionInheritEnv,
|
|
504
511
|
fenceSessionOwner: sessionScoped.fenceSessionOwner,
|
|
505
512
|
dropSessionScoped: sessionScoped.dropSession,
|
|
506
|
-
executionEnvFactory, worktreeReap, sendUserFileTaskEnvs, lspManager, spaceReclaimer, sandboxSecretSeatGate, sandboxPodReaper,
|
|
513
|
+
executionEnvFactory, worktreeReap, sendUserFileTaskEnvs, lspManager, spaceReclaimer, sandboxSecretSeatGate, sandboxPodReaper, sandboxGitPlane,
|
|
507
514
|
};
|
|
508
515
|
}
|
|
509
516
|
//# sourceMappingURL=execution-env.js.map
|
|
@@ -4,6 +4,7 @@ import { crossInvariant } from "../config-invariants.js";
|
|
|
4
4
|
import { buildReadDenyFloorUnkeptNote, executionLaneOf, laneIsolated } from "../execution-lane-caps.js";
|
|
5
5
|
import { buildReadFacePostureNotice, settleDerivedReadFace } from "../read-face-posture.js";
|
|
6
6
|
import { settleHostShellAtBoot } from "../plugins/host-platform.js";
|
|
7
|
+
import { seatText } from "../trace/exit-seat.js";
|
|
7
8
|
export const FILE_SOURCED_LANES = ["host", "local-docker"];
|
|
8
9
|
export async function composeExecutionLane(config, ctx) {
|
|
9
10
|
if (ctx.configSource === "local")
|
|
@@ -55,7 +56,7 @@ async function applyRemoteExecFile(config, ctx) {
|
|
|
55
56
|
fileRx = await loadRemoteExec(localRoot);
|
|
56
57
|
}
|
|
57
58
|
catch (err) {
|
|
58
|
-
logger.error("remote_exec_file_invalid", { root: localRoot, err: String(err) });
|
|
59
|
+
logger.error("remote_exec_file_invalid", { root: localRoot, err: seatText("operator-log-text", String(err)) });
|
|
59
60
|
throw new Error(`config.d/remote-exec.json under ${localRoot} is invalid: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
60
61
|
}
|
|
61
62
|
if (!fileRx)
|
|
@@ -2,6 +2,7 @@ import { defaultTaskRegistry } from "@sema-agent/core";
|
|
|
2
2
|
import { reportHardKillReceipts } from "../background-session-reap.js";
|
|
3
3
|
import { liveHostForegroundChildCount, reapHostForegroundChildren } from "../plugins/host-platform.js";
|
|
4
4
|
import { liveEphemeralHostWorkspaceCount, reapEphemeralHostWorkspaces } from "../plugins/host-workspace-registry.js";
|
|
5
|
+
import { seatText } from "../trace/exit-seat.js";
|
|
5
6
|
const PROCESS_EXIT_INCLUDES_RETAINED = false;
|
|
6
7
|
export function installProcessExitBoundary({ logger }) {
|
|
7
8
|
const reapOwnChildProcesses = () => {
|
|
@@ -13,7 +14,7 @@ export function installProcessExitBoundary({ logger }) {
|
|
|
13
14
|
logger.info("shutdown_background_reaped", { reaped });
|
|
14
15
|
}
|
|
15
16
|
catch (err) {
|
|
16
|
-
logger.warn("shutdown_background_reap_failed", { err: String(err) });
|
|
17
|
+
logger.warn("shutdown_background_reap_failed", { err: seatText("operator-log-text", String(err)) });
|
|
17
18
|
}
|
|
18
19
|
try {
|
|
19
20
|
const fg = reapHostForegroundChildren();
|
|
@@ -23,7 +24,7 @@ export function installProcessExitBoundary({ logger }) {
|
|
|
23
24
|
logger.warn("shutdown_foreground_reap_incomplete", { groups: fg.failed });
|
|
24
25
|
}
|
|
25
26
|
catch (err) {
|
|
26
|
-
logger.warn("shutdown_foreground_reap_failed", { err: String(err) });
|
|
27
|
+
logger.warn("shutdown_foreground_reap_failed", { err: seatText("operator-log-text", String(err)) });
|
|
27
28
|
}
|
|
28
29
|
return backgroundSoftStopped;
|
|
29
30
|
};
|
|
@@ -33,7 +34,7 @@ export function installProcessExitBoundary({ logger }) {
|
|
|
33
34
|
reportHardKillReceipts(logger, receipts, "process_exit");
|
|
34
35
|
}
|
|
35
36
|
catch (err) {
|
|
36
|
-
logger.warn("shutdown_background_hard_kill_failed", { err: String(err) });
|
|
37
|
+
logger.warn("shutdown_background_hard_kill_failed", { err: seatText("operator-log-text", String(err)) });
|
|
37
38
|
}
|
|
38
39
|
};
|
|
39
40
|
const reapOwnHostWorkspaces = () => {
|
|
@@ -45,7 +46,7 @@ export function installProcessExitBoundary({ logger }) {
|
|
|
45
46
|
logger.warn("shutdown_host_workspace_reap_incomplete", { dirs: failed.map((f) => f.dir) });
|
|
46
47
|
}
|
|
47
48
|
catch (err) {
|
|
48
|
-
logger.warn("shutdown_host_workspace_reap_failed", { err: String(err) });
|
|
49
|
+
logger.warn("shutdown_host_workspace_reap_failed", { err: seatText("operator-log-text", String(err)) });
|
|
49
50
|
}
|
|
50
51
|
};
|
|
51
52
|
const onProcessExit = () => {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
* `memory_harvest_rejections_total{code}` + 一条 warn,见 `boot/runner-deps.ts` 的 harvest 报告站点),
|
|
41
41
|
* 等下一次非受限会话走正常门收编。
|
|
42
42
|
* ⚠️ **这一层只在 file 记忆引擎上**(受限视图 = `FileMemoryEngineBackend` 的实装,`materialize` 取它是
|
|
43
|
-
* `?? this.backend` 的可选 seam):`MEMORY_ENGINE_BACKEND=pg|
|
|
43
|
+
* `?? this.backend` 的可选 seam):`MEMORY_ENGINE_BACKEND=pg|mysql` 的两条腿读侧走库、盘上只是每任务投影,
|
|
44
44
|
* 没有「读磁盘即收编」的通道,`false` 在它们上仍买到披露/写门/零收编 harvest 三件。
|
|
45
45
|
* ⚠️ **口径别混**:受限 = **会话级 verdict 单键**(declared-false 那一个键);`writeScope:null` 的只读
|
|
46
46
|
* **平面**(请求键 `memoryWrite:false` 的 per-run 暂停 / org 层默认只读 / 双根非写面)**保持 adopt-on-read
|
|
@@ -75,7 +75,7 @@ export interface MemoryWriteBoundaryFacts {
|
|
|
75
75
|
declaredCapable: boolean | undefined;
|
|
76
76
|
/** 本部署的记忆引擎后端(`config.memoryEngineBackend`)。**只进文案**,不参与任何判决 —— 它在这里的
|
|
77
77
|
* 唯一作用是把「怎么把根挪进围栏」这句话指向**在该腿上真的有效**的那个旋钮:`MEMORY_ENGINE_DIR` 只被
|
|
78
|
-
* file 腿读(memory-scope 的 `resolveMemoryEngineRoot`),pg/
|
|
78
|
+
* file 腿读(memory-scope 的 `resolveMemoryEngineRoot`),pg/mysql 腿的根是
|
|
79
79
|
* `<LOCAL_DATA_ROOT|数据根>/memory-work`(boot/stores.ts 两支),那条腿上指 MEMORY_ENGINE_DIR 是让
|
|
80
80
|
* operator 去拧一个不接线的旋钮 —— 修不好还以为自己修了。 */
|
|
81
81
|
engineBackend: MemoryEngineBackend;
|
|
@@ -210,7 +210,7 @@ export declare function consolidationSeatBillingOf(plane: ConsolidationSeatPlane
|
|
|
210
210
|
* (结构上跑不起来由下游 D1 三条拒启臂照拒,本判决不吞);开而座落主模型 ⇒ 开 + 一行
|
|
211
211
|
* `memory_consolidation_on_main_model`(部署方显式承担,但必须知道账按主模型记)。
|
|
212
212
|
* · **未设 = 出厂缺省派生**([ref] 取代 [ref] ① 的「出厂 off」实况):
|
|
213
|
-
* 结构上跑不起来(判官 {@link consolidationDriverUnwirable} 有成因:多租户 / `MEMORY_ENGINE=off` / pg·
|
|
213
|
+
* 结构上跑不起来(判官 {@link consolidationDriverUnwirable} 有成因:多租户 / `MEMORY_ENGINE=off` / pg·mysql
|
|
214
214
|
* 记忆后端 / `MEMORY_PROVENANCE=off`)⇒ **恒关、零提示、零探针** —— 派生开撞上 D1 拒启臂 = 每台配了便宜模型的
|
|
215
215
|
* 多租户 worker 升级即起不来;而配不配便宜模型它都开不了,一句指向 `MODEL_CHEAP_ID` 的提示是误导;
|
|
216
216
|
* 座不落主模型({@link consolidationSeatBillingOf} = `own-model`)⇒ **开**;
|
|
@@ -7,6 +7,7 @@ import { DEFAULT_MODEL_REF, resolveMainModel } from "../model-select.js";
|
|
|
7
7
|
import { backendOwnsControlPlane, captureRecordStoreOf } from "../memory-operator-faces.js";
|
|
8
8
|
import { memoryStoreForRequest } from "../memory-scope-stores.js";
|
|
9
9
|
import { createConsolidationWriteJudge, deliverWriteRefusal, expandTiers, MemoryEngine, modelOriginOf, readConsolidationDriverRun, resolveMemoryConsolidationDriver, runMemoryConsolidationDriver, } from "@sema-agent/core";
|
|
10
|
+
import { seatText } from "../trace/exit-seat.js";
|
|
10
11
|
export function resolveConsolidationDriverSeat(deps) {
|
|
11
12
|
let options;
|
|
12
13
|
try {
|
|
@@ -114,7 +115,7 @@ function unwirableRefusal(code, facts) {
|
|
|
114
115
|
`(MEMORY_ENGINE_BACKEND=${facts.memoryEngineBackend}) does NOT own an engine control plane (controlPlaneRoot) — ` +
|
|
115
116
|
`core would derive one on THIS replica's local disk, and a consolidation run's resumable account would die with ` +
|
|
116
117
|
`the pod (a lost run re-mints the whole library at full model cost on the next attempt). The file memory backend ` +
|
|
117
|
-
`owns a control plane; the pg/
|
|
118
|
+
`owns a control plane; the pg/mysql memory backends do not. Set MEMORY_ENGINE_BACKEND=file, or set ` +
|
|
118
119
|
`MEMORY_CONSOLIDATION_DRIVER=off.`);
|
|
119
120
|
case "provenance-off":
|
|
120
121
|
return (`MEMORY_CONSOLIDATION_DRIVER=on is incompatible with MEMORY_PROVENANCE=off — core refuses to enable consolidation ` +
|
|
@@ -238,7 +239,7 @@ function decideConsolidationValve(input) {
|
|
|
238
239
|
return { valve: { enabled: true, source: "derived", catalogDependent: true } };
|
|
239
240
|
const seatFact = billing.kind === "main-model"
|
|
240
241
|
? `Here the seat resolves to the main model "${billing.mainModel}" (no MODEL_CHEAP_ID naming another model, and no catalog roles.consolidate / roles.summarize / "flash" tier binding to another model)`
|
|
241
|
-
: `Here no consolidation seat resolves at all (${billing.fault})`;
|
|
242
|
+
: `Here no consolidation seat resolves at all (${seatText("operator-log-text", billing.fault)})`;
|
|
242
243
|
return {
|
|
243
244
|
valve: {
|
|
244
245
|
enabled: false,
|
|
@@ -8,6 +8,7 @@ import { DeferredSandboxPathEnv, sandboxPathEnvSlots } from "./deferred-sandbox-
|
|
|
8
8
|
import { DEPLOYMENT_SHAPE_PREDICATES } from "../deployment-shape.js";
|
|
9
9
|
import { executionLaneHomeDir } from "../execution-lane-caps.js";
|
|
10
10
|
import { createDeploymentListExemption } from "../approval.js";
|
|
11
|
+
import { seatText } from "../trace/exit-seat.js";
|
|
11
12
|
function hostGateCwd(config, localRoot) {
|
|
12
13
|
return join(config.localDataRoot ?? localRoot, "parked-revive-unrooted");
|
|
13
14
|
}
|
|
@@ -63,7 +64,7 @@ async function resolveCapsFor(deps, identity) {
|
|
|
63
64
|
return await deps.resolveRuntimeCaps(identity.principal);
|
|
64
65
|
}
|
|
65
66
|
catch (err) {
|
|
66
|
-
deps.logger.warn("parked_revive_caps_unresolved", { principal: identity.principal ?? null, err: err instanceof Error ? err.message : String(err) });
|
|
67
|
+
deps.logger.warn("parked_revive_caps_unresolved", { principal: identity.principal ?? null, err: seatText("operator-log-text", err instanceof Error ? err.message : String(err)) });
|
|
67
68
|
return undefined;
|
|
68
69
|
}
|
|
69
70
|
}
|
|
@@ -1,31 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* [ref] §3([ref] v2 §6 F4 的**残余采纳**)—— 默认 ON 的**休眠行审计**。
|
|
3
|
-
*
|
|
4
|
-
* 🔴 这条审计存在的唯一理由:`PERMISSION_RULES_ENABLED` 的默认值在本车从 OFF 翻成 ON,而**旋钮翻转
|
|
5
|
-
* 与规则行的寿命是两条独立的时间线**。三张表自 [ref] 车二起就随中央 `ensureSchema` 建、并且从来没有被
|
|
6
|
-
* 清过,所以下面这两类部署在升级的那一刻会突然带着**既有**规则行开始放行:
|
|
7
|
-
* · 曾经把旋钮开过一段时间又关掉的部署(行留在库里,只是没人读);
|
|
8
|
-
* · 从旧库恢复/克隆出来的部署(行跟着数据一起来的)。
|
|
9
|
-
* 对运维来说,这是「我什么都没改,worker 却开始少问我了」——一次**放宽面**上的静默变化。审计做的事
|
|
10
|
-
* 很小但是承重:在启动日志里把它说出来,让「少问」是一条能被读到的因果,而不是一次玄学。
|
|
11
|
-
*
|
|
12
|
-
* ── 三条判据,逐条有理由 ────────────────────────────────────────────────────────────────────────
|
|
13
|
-
* ① **店缺席 ⇒ 整条不上场**(零 I/O、零行)。店缺席包括:显式关旋钮、`local` 车道没接 File 店的旧
|
|
14
|
-
* 部署、以及压根没有 backend 的 env-only worker。没有店就没有行,谈不上唤醒。
|
|
15
|
-
* ② **零桶 ⇒ 不打行**。一条「0 条既有规则随默认 ON 激活」的行是纯噪音:它对读日志的人不传递任何
|
|
16
|
-
* 可行动的信息,却让真正有东西被唤醒的那一行变得不显眼。
|
|
17
|
-
* ③ **运维**显式**表过态(`PERMISSION_RULES_ENABLED` 被设成 true 或 false)⇒ 不打行**。那些行本来
|
|
18
|
-
* 就是活的(或者旋钮被显式关着、店根本没装配),默认值翻不翻转对它们零影响 —— 说「随默认 ON
|
|
19
|
-
* 激活」是**假话**,而在启动日志里说假话比不说更坏。判据用 `permissionRulesEnabledExplicit`
|
|
20
|
-
* (config.ts 与 `dbBackendExplicit` 同姿势),不是猜。
|
|
21
|
-
*
|
|
22
|
-
* ── 失败方向 ────────────────────────────────────────────────────────────────────────────────────
|
|
23
|
-
* 数不出来(库抖动 / 文件读不了)⇒ **不拒启、也不编一个 0 出来**:返回 `undefined` + 一条 warn。
|
|
24
|
-
* 这是一条纯诊断面(它不参与任何放行/拒绝判决),所以它的降级方向是「安静地不知道」而不是「谎报
|
|
25
|
-
* 零」——`{ buckets: 0 }` 会被下游读成「确认没有休眠行」,那是把一次读失败伪装成一个结论。
|
|
26
|
-
* 因为它零判决,这条 fail-open 不属于 `docs/FAIL-OPEN-CENSUS.md` 的安全轴 P 类,故不占 `recordFailOpen`
|
|
27
|
-
* 的标签;它的可见性由那条 warn 承担。
|
|
28
|
-
*/
|
|
29
1
|
/** 审计只需要一只桶计数口——**刻意**不吃整个 `PermissionRuleStoreBundle`:诊断面对店的其余能力
|
|
30
2
|
* 一无所知也不该知道,窄口让测试能用四行 fixture 驱动真实现同一段代码。 */
|
|
31
3
|
export interface DormantRuleCounter {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { seatText } from "../trace/exit-seat.js";
|
|
1
2
|
export async function auditDormantPermissionRules(ctx) {
|
|
2
3
|
if (ctx.stores === undefined)
|
|
3
4
|
return undefined;
|
|
@@ -7,7 +8,7 @@ export async function auditDormantPermissionRules(ctx) {
|
|
|
7
8
|
}
|
|
8
9
|
catch (err) {
|
|
9
10
|
ctx.logger.warn?.("permission_rules_dormant_audit_failed", {
|
|
10
|
-
error: err instanceof Error ? err.message : String(err),
|
|
11
|
+
error: seatText("operator-log-text", err instanceof Error ? err.message : String(err)),
|
|
11
12
|
note: "the boot audit could not count pre-existing permission-rule buckets; the lane itself is unaffected",
|
|
12
13
|
});
|
|
13
14
|
return undefined;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { compileReadDeny, readDenyRowAnchor } from "@sema-agent/core";
|
|
2
2
|
import { echoCallerText } from "../caller-text-echo.js";
|
|
3
|
+
import { seatText } from "../trace/exit-seat.js";
|
|
3
4
|
export const READ_DENY_AUDIT_MAX_NAMED_ROWS = 20;
|
|
4
5
|
const NAMED_ROW_ECHO_CHARS = 200;
|
|
5
6
|
function isAnchoredCanonicalRow(canonical) {
|
|
@@ -14,7 +15,7 @@ export function auditReadDenyAnchoring(ctx) {
|
|
|
14
15
|
}
|
|
15
16
|
catch (err) {
|
|
16
17
|
ctx.logger.warn("read_deny_anchor_audit_failed", {
|
|
17
|
-
error:
|
|
18
|
+
error: seatText("operator-log-text", err instanceof Error ? err.message : String(err)),
|
|
18
19
|
note: "the boot audit could not read the deployment read-deny rows, so it names none and changes nothing; the engine itself refuses a row it cannot read when the Runner is built",
|
|
19
20
|
});
|
|
20
21
|
return [];
|
package/dist/boot/reapers.d.ts
CHANGED
|
@@ -167,8 +167,8 @@ interface ReapSessionsInputs {
|
|
|
167
167
|
* 的那条臂**结构上看不见**它(它从行出发枚举),只有从会话侧枚举才找得到。
|
|
168
168
|
*
|
|
169
169
|
* 两只面必须落在**host durable 店**上,而 release 这一格是承重的:
|
|
170
|
-
* · `listPlaced` = host 店的分区枚举(SQL
|
|
171
|
-
*
|
|
170
|
+
* · `listPlaced` = host 店的分区枚举(三只持久会话店都实装:SQL 两孪生读 `session_meta`,local 读会话存档行头;
|
|
171
|
+
* 店上没有这只面 ⇒ 键**不设**,core 那条腿如实不可用 —— 绝不给一个恒返回 `[]` 的假面,那会把「枚不了」读成「没有孤儿」);
|
|
172
172
|
* · `release` 对 **placed id** 必须走 host 店:路由店(`ForkRoutingSessionStore`)对一个重启后不认识
|
|
173
173
|
* 的 id 会回落 transient(进程内 no-op),那会让 core 数出一次**从未发生**的 release
|
|
174
174
|
* (`orphanPlacedReleased` 当场变成谎)而字节还在库里。故先按**持久化元组**判(一次 PK 探针),
|
package/dist/boot/reapers.js
CHANGED
|
@@ -6,6 +6,7 @@ import { createApprovalReconciler } from "../approval-reconciler.js";
|
|
|
6
6
|
import { createE2bOrphanSandboxProvider, reclaimOrphanE2bSandboxes, E2B_ORPHAN_GRACE_MS } from "../plugins/e2b-orphan-reclaim.js";
|
|
7
7
|
import { SANDBOX_POD_REAP_PERIOD_MS } from "../plugins/k8s-pod-reaper.js";
|
|
8
8
|
import { APPROVAL_ASK_RETENTION_PASS_MS, runApprovalAskRetentionPass } from "../approval-ask-retention.js";
|
|
9
|
+
import { seatText } from "../trace/exit-seat.js";
|
|
9
10
|
export const REAPER_FAILURE_WARN_THRESHOLD = 5;
|
|
10
11
|
export function createThrottledReaperCatch(name, logger, threshold = REAPER_FAILURE_WARN_THRESHOLD) {
|
|
11
12
|
let streak = 0;
|
|
@@ -21,7 +22,7 @@ export function createThrottledReaperCatch(name, logger, threshold = REAPER_FAIL
|
|
|
21
22
|
logger.warn("reaper_leg_repeated_failure", {
|
|
22
23
|
reaper: name,
|
|
23
24
|
consecutiveFailures: streak,
|
|
24
|
-
lastError: err instanceof Error ? err.message : String(err),
|
|
25
|
+
lastError: seatText("operator-log-text", err instanceof Error ? err.message : String(err)),
|
|
25
26
|
});
|
|
26
27
|
}
|
|
27
28
|
catch {
|
|
@@ -169,7 +170,7 @@ export function startReapers(ctx) {
|
|
|
169
170
|
catch (err) {
|
|
170
171
|
failedScopes++;
|
|
171
172
|
try {
|
|
172
|
-
logger.warn("bg_agent_reap_scope_failed", { scope, err: err instanceof Error ? err.message : String(err) });
|
|
173
|
+
logger.warn("bg_agent_reap_scope_failed", { scope, err: seatText("operator-log-text", err instanceof Error ? err.message : String(err)) });
|
|
173
174
|
}
|
|
174
175
|
catch {
|
|
175
176
|
}
|
|
@@ -266,7 +267,7 @@ export function startReapers(ctx) {
|
|
|
266
267
|
} })
|
|
267
268
|
.catch((err) => {
|
|
268
269
|
try {
|
|
269
|
-
logger.warn("attachment_orphan_sweep_failed", { err: err instanceof Error ? err.message : String(err) });
|
|
270
|
+
logger.warn("attachment_orphan_sweep_failed", { err: seatText("operator-log-text", err instanceof Error ? err.message : String(err)) });
|
|
270
271
|
}
|
|
271
272
|
catch {
|
|
272
273
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { realpathSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { NodeExecutionEnv, QUESTION_AWAITS_RESUME, deriveAskEffective, expandTiers,
|
|
3
|
+
import { NodeExecutionEnv, QUESTION_AWAITS_RESUME, deriveAskEffective, expandTiers, resolveAskSeamForm } from "@sema-agent/core";
|
|
4
4
|
import { cappedCeiling } from "../budget.js";
|
|
5
5
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
6
6
|
import { SessionEnvironmentSelection, selectEnvironmentTool } from "../capabilities/select-environment-tool.js";
|
|
@@ -14,14 +14,14 @@ import { createDeploymentListExemption, gateIntentUnserviceableReason, singleUse
|
|
|
14
14
|
import { acceptShellScratchpadDir, buildEnvFacts, egressForRemoteExec, ensureScratchpadDir, resumeFactsForLane, scratchpadCoveringTaskRoot } from "../env-facts.js";
|
|
15
15
|
import { FleetEventBus } from "../fleet/fleet-bus.js";
|
|
16
16
|
import { createSettingsHooksRegistration, settingsHooksBudgetMs } from "../hooks/hook-runner.js";
|
|
17
|
-
import { HOST_POSTURE_REFUSED_CODE,
|
|
17
|
+
import { HOST_POSTURE_REFUSED_CODE, permissionModeWriteFaceRefusal, taskInheritEnvRefusal } from "../hosted-posture.js";
|
|
18
18
|
import { headerStr } from "../http/principal-gate.js";
|
|
19
19
|
import { explicitOperatorOk } from "../http/server.js";
|
|
20
20
|
import { isAtMentionable, matchCatalogModel, refusedCatalogEntry, resolveTaskModel, selectableCatalog, terminalCatalogName } from "../model-select.js";
|
|
21
21
|
import { echoModelRef, modelUnavailableMessage } from "../model-entry-refusal.js";
|
|
22
22
|
import { PerTaskImageRegistry, resolveSandboxImageRef } from "../per-task-image.js";
|
|
23
23
|
import { remoteScratchpadDirFor } from "../plugins/remote-scratchpad.js";
|
|
24
|
-
import { bindAttachmentsForTask } from "../plugins/task-attachment-store.js";
|
|
24
|
+
import { attachmentBindRefusalAnswer, 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";
|
|
@@ -50,7 +50,8 @@ import { inertToolListEntryOf } from "../rule-entry-list.js";
|
|
|
50
50
|
import { TENANCY_WALL_CLOCK_BASE_SEC, enableForkFromBody, normalizeRetainSubagentSessions, selfOrchestrationFromBody } from "../task-workflow.js";
|
|
51
51
|
import { redactSecrets } from "../trace/redact.js";
|
|
52
52
|
import { DeferredSandboxPathEnv, sandboxPathEnvSlots } from "./deferred-sandbox-path-env.js";
|
|
53
|
-
import { executionLaneHomeDir, executionLaneOf, laneWiresExecutionEnv } from "../execution-lane-caps.js";
|
|
53
|
+
import { executionLaneHomeDir, executionLaneOf, laneIsolated, laneWiresExecutionEnv } from "../execution-lane-caps.js";
|
|
54
|
+
import { executionConfigRootOf } from "../execution-config-root.js";
|
|
54
55
|
import { withUnattendedLeg } from "../unattended-permission-mode.js";
|
|
55
56
|
import { fieldConflictFacts } from "../field-conflict.js";
|
|
56
57
|
function unrooted(spec) {
|
|
@@ -160,8 +161,8 @@ export function createResolveSpec(ctx) {
|
|
|
160
161
|
assertRequestImageUrls(body.images);
|
|
161
162
|
const gated = await gateScenarioAndAppend(body, auth, opts);
|
|
162
163
|
const effMode = effectivePermissionMode(body, gated.parsedSettings.settings);
|
|
163
|
-
|
|
164
|
-
const why =
|
|
164
|
+
{
|
|
165
|
+
const why = permissionModeWriteFaceRefusal(effMode, config);
|
|
165
166
|
if (why !== undefined)
|
|
166
167
|
throw new HttpError(422, why, { code: HOST_POSTURE_REFUSED_CODE });
|
|
167
168
|
}
|
|
@@ -216,11 +217,13 @@ export function createResolveSpec(ctx) {
|
|
|
216
217
|
if (!auth?.sessionId)
|
|
217
218
|
throw new HttpError(400, "`attachmentIds` requires a session-resolving deployment (no authorizer session)");
|
|
218
219
|
const sid = auth.sessionId;
|
|
220
|
+
const lane = opts.execution.lane;
|
|
219
221
|
const r = await bindAttachmentsForTask({
|
|
220
222
|
store: taskAttachmentStore,
|
|
221
223
|
owner: auth?.principal ?? "default",
|
|
222
224
|
ids: reqAtt,
|
|
223
225
|
sessionId: sid,
|
|
226
|
+
lane: { word: lane, isolated: laneIsolated(lane) },
|
|
224
227
|
leg: opts?.leg === "fresh" ? "fresh" : "resume",
|
|
225
228
|
nowMs: Date.now(),
|
|
226
229
|
onMissing: (id) => {
|
|
@@ -228,6 +231,12 @@ export function createResolveSpec(ctx) {
|
|
|
228
231
|
throw new HttpError(400, `attachment not found: ${id}`);
|
|
229
232
|
logger.warn("attachment_missing_on_resume", { sessionId: sid, id });
|
|
230
233
|
},
|
|
234
|
+
onRefused: (refusal) => {
|
|
235
|
+
const answer = attachmentBindRefusalAnswer(refusal);
|
|
236
|
+
if (opts?.leg === "fresh")
|
|
237
|
+
throw createCodedHttpError(answer.status, answer.errorCode, answer.message, answer.extra);
|
|
238
|
+
logger.warn("attachment_refused_on_resume", { sessionId: sid, errorCode: answer.errorCode, ...answer.extra });
|
|
239
|
+
},
|
|
231
240
|
});
|
|
232
241
|
attachmentNotice = r.notice;
|
|
233
242
|
}
|
|
@@ -276,6 +285,7 @@ export function createResolveSpec(ctx) {
|
|
|
276
285
|
sessionId: auth?.sessionId ?? "",
|
|
277
286
|
cwd: (auth?.sessionId ? perSessionCwd.get(auth.sessionId) : undefined) ?? process.cwd(),
|
|
278
287
|
...(parsedSettings.settings?.shellEnv ? { shellEnv: parsedSettings.settings.shellEnv } : {}),
|
|
288
|
+
httpHookAllowlistLayers: parsedSettings.settings?.httpHookAllowlist !== undefined ? [parsedSettings.settings.httpHookAllowlist] : [],
|
|
279
289
|
hookLlm,
|
|
280
290
|
hookAgent,
|
|
281
291
|
onHookNotice: (n) => fleetBus.publishHookNotice({
|
|
@@ -579,9 +589,11 @@ export function createResolveSpec(ctx) {
|
|
|
579
589
|
? await ensureScratchpadDir(config.localDataRoot ?? localRoot, auth.sessionId, (msg, meta) => logger.warn(msg, { ...(meta ?? {}), sessionId: auth.sessionId }))
|
|
580
590
|
: undefined);
|
|
581
591
|
if (effectiveSettings) {
|
|
592
|
+
const configRoot = executionConfigRootOf(config);
|
|
582
593
|
const ruleBases = {
|
|
583
594
|
...(pathAdjudication.taskRoot !== undefined ? { taskRoot: pathAdjudication.taskRoot } : {}),
|
|
584
595
|
...(pathAdjudication.taskHome !== undefined ? { taskHome: pathAdjudication.taskHome } : {}),
|
|
596
|
+
...(configRoot !== undefined ? { configRoot } : {}),
|
|
585
597
|
};
|
|
586
598
|
try {
|
|
587
599
|
governed = applyTaskSettings(governedBase, effectiveSettings, ruleBases);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
2
|
+
import { seatText } from "../trace/exit-seat.js";
|
|
2
3
|
export const RETENTION_SWEEP_STUCK_THRESHOLD = 5;
|
|
3
4
|
export const RETENTION_LEASE_TTL_FACTOR = 2;
|
|
4
5
|
const DAY_MS = 86_400_000;
|
|
@@ -137,15 +138,16 @@ async function recordDomainFailure(ctx, d) {
|
|
|
137
138
|
}
|
|
138
139
|
const streaks = ctx.streaks;
|
|
139
140
|
const streak = (streaks?.get(d.domain) ?? 0) + 1;
|
|
141
|
+
const shown = seatText("operator-log-text", message);
|
|
140
142
|
streaks?.set(d.domain, streak);
|
|
141
143
|
try {
|
|
142
|
-
ctx.logger.warn("retention_sweep_domain_failed", { domain: d.domain, fencingToken: d.fencingToken, consecutiveFailures: streak, auditRowWritten, err:
|
|
144
|
+
ctx.logger.warn("retention_sweep_domain_failed", { domain: d.domain, fencingToken: d.fencingToken, consecutiveFailures: streak, auditRowWritten, err: shown });
|
|
143
145
|
if (streak >= RETENTION_SWEEP_STUCK_THRESHOLD) {
|
|
144
146
|
ctx.metrics.inc("retention_sweep_stuck", {}, 1);
|
|
145
147
|
ctx.logger.warn("retention_sweep_stuck", {
|
|
146
148
|
domain: d.domain,
|
|
147
149
|
consecutiveFailures: streak,
|
|
148
|
-
lastError:
|
|
150
|
+
lastError: shown,
|
|
149
151
|
note: "this retention domain has failed its sweep for RETENTION_SWEEP_STUCK_THRESHOLD consecutive rounds — its data is NOT being retained per policy. Check retention_audit rows with action='failed' for this domain.",
|
|
150
152
|
});
|
|
151
153
|
streaks?.set(d.domain, 0);
|
|
@@ -168,7 +170,7 @@ export function startRetentionLane(ctx) {
|
|
|
168
170
|
.then(() => undefined)
|
|
169
171
|
.catch((err) => {
|
|
170
172
|
try {
|
|
171
|
-
ctx.logger.warn("retention_sweep_round_failed", { err: err instanceof Error ? err.message : String(err) });
|
|
173
|
+
ctx.logger.warn("retention_sweep_round_failed", { err: seatText("operator-log-text", err instanceof Error ? err.message : String(err)) });
|
|
172
174
|
}
|
|
173
175
|
catch {
|
|
174
176
|
recordFailOpen("server.retention.sweep-report-dropped", "round");
|