subprocess: one explicit env channel on the spawn spec
Drop SubprocessSpawnSpec.dshEnv and splitEnvChannels(); childEnv() is now scrubbed-base + explicit entries with no namespace validation. The invariant dropped is the reserved-namespace check on explicit entries (DSH_* rejected from env, non-DSH_* rejected from dshEnv). Explicit-entry trust already covers it: an explicit credential-shaped entry has always merged after the scrub as a deliberate caller opt-in, and an explicit DSH_* entry is the same deliberate act — the staleness invariant lives entirely in scrubbedParentEnv dropping AMBIENT credential-shaped and DSH_* names, which stays. The validation's only observed effect was rejecting legitimate explicit entries: both recent CI breakages (DSH_GATE_CONCURRENCY exported into every job crashing lsp specs, DSH_PERMISSION_MODE in acp config.env crashing the child spawn) were this check firing on values a caller meant to pass, each fixed by routing around the bureaucracy the seam itself imposed. The bash seam keeps its own request/spec dshEnv field: that is bash-owned trusted-plugin vocabulary (the ctx.bashEnv collected overlay) whose merge-last position guarantees a caller env entry cannot displace a managed fact; bash-local now flattens ENV_OVERRIDES -> spec.env -> spec.dshEnv into the seam's one env map. subagent-acp and lsp-local pass their single config env map straight through. DshEnvironment/DshEnvironmentKey/DSH_ENV_PREFIX stay on the subprocess seam as the namespace vocabulary (bash re-exports them; scrubbedParentEnv filters on the prefix). Tests: the two channel-rejection specs and the splitEnvChannels partition spec are deleted; one spawn spec now proves an explicit DSH_* env entry reaches the child while an ambient one is scrubbed; the acp/lsp forwarding specs keep their MOCK_ECHO_ENV / LSP_FAKE_ECHO_ENV assertions with the split comments rewritten to merge-after-scrub. Docs (en+zh, re-recorded) and the owning Agent Notes updated; cordis api/services catalogs regenerated.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
|
||||
## 受管环境命名空间与捕获的输出
|
||||
|
||||
`DSH_*` 变量是归 Harness 所有的子进程事实;实现会在合并调用方快照之前丢弃环境中已有的 `DSH_*` 名称,每条被收集的流都通过 `CollectedOutput` 报告自身的截断与 spill 恢复状态。
|
||||
`DSH_*` 变量是归 Harness 所有的子进程事实;实现会在合并调用方显式 `env` 之前丢弃环境中已有的 `DSH_*` 名称,因此当前事实只会以有意提供的条目形式到达,每条被收集的流都通过 `CollectedOutput` 报告自身的截断与 spill 恢复状态。
|
||||
|
||||
```ts type-equiv
|
||||
/** One environment key inside the managed {@link DSH_ENV_PREFIX} namespace. */
|
||||
@@ -114,19 +114,14 @@ interface SubprocessSpawnSpec {
|
||||
*/
|
||||
signal?: AbortSignal | undefined
|
||||
/**
|
||||
* Ordinary environment entries merged onto the implementation's scrubbed
|
||||
* parent base (see `scrubbedParentEnv`). `DSH_*` names are rejected and
|
||||
* belong in {@link dshEnv}; a deliberately forwarded credential-shaped
|
||||
* entry survives because this layer merges after the scrub.
|
||||
* Explicit environment entries merged onto the implementation's scrubbed
|
||||
* parent base (see `scrubbedParentEnv`), with no namespace validation:
|
||||
* every entry is a deliberate caller opt-in, so a forwarded
|
||||
* credential-shaped entry or a current `DSH_*` fact survives precisely
|
||||
* because this layer merges after the scrub that drops its ambient
|
||||
* namesake.
|
||||
*/
|
||||
env?: Record<string, string> | undefined
|
||||
/**
|
||||
* Harness-owned `DSH_*` variables for this execution. The scrubbed base has
|
||||
* already discarded ambient `DSH_*` entries, so an unavailable current fact
|
||||
* cannot inherit a stale value from the harness process; non-`DSH_*` names
|
||||
* on this channel are rejected.
|
||||
*/
|
||||
dshEnv?: DshEnvironment | undefined
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user