Review #2 (MEDIUM). The M3 `[project.environments]` approval gate silently
failed open in three shapes:
- `EnvPolicy.confirm` was `#[serde(default)]`, so `production = {}` parsed as
un-gated. `confirm` is now a REQUIRED field — an env listed with an empty
policy is a load error (`missing field 'confirm'`), not a silent no-gate.
- `pic apply --file <leaf>` where the leaf carried no `[project]` skipped the
gate even when the repo root gated the env. `run` now discovers the governing
`[project]` by walking up from the manifest to the nearest ancestor
`picloud.toml` that declares one (`find_governing_project`, loaded without the
env overlay — only the block matters).
- A `[project].environments` in a non-root manifest under `--dir` was dropped
with a generic "ignored" note; `build_tree` now warns explicitly that its
approval gating is not enforced.
Pinned by `tests/env_approval.rs` (empty-policy load error; leaf `--file` apply
honoring the root gate).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>