Skip to content

feat(agent): isolate Pi gate behavior resources#518

Closed
palinopr wants to merge 7 commits into
kunchenguid:mainfrom
palinopr:fm/no-mistakes-pi-gate-instruction-isolation
Closed

feat(agent): isolate Pi gate behavior resources#518
palinopr wants to merge 7 commits into
kunchenguid:mainfrom
palinopr:fm/no-mistakes-pi-gate-instruction-isolation

Conversation

@palinopr

Copy link
Copy Markdown

Intent

Add secure first-class Pi support to the trusted disable_project_settings boundary, preserving fail-closed gate isolation, configured model and thinking overrides, fallback safety, compatibility when disabled, focused regression coverage, and authoritative documentation.

What Changed

  • Add verified Pi support for disable_project_settings, suppressing automatic behavior resources and revalidating required version and flag capabilities before each invocation.
  • Fail closed when Pi overrides or fallback agents weaken isolation, while preserving model/thinking overrides and existing behavior when isolation is disabled.
  • Add focused Pi isolation, configuration, and daemon regression coverage, plus authoritative configuration documentation.

Risk Assessment

✅ Low: The Pi isolation change is well-bounded, fails closed, revalidates capabilities before each invocation, preserves safe overrides, and includes focused regression coverage and documentation.

Testing

The successful race baseline was supplemented by focused agent, daemon, configuration, and full e2e tests plus a real Pi 0.80.10 resource-isolation probe. The probe demonstrated that poisoned resources were excluded, project trust remained disabled, the generated base prompt survived, and no model turn started; all checks passed and the worktree remained clean.

Evidence: Real Pi gate-isolation startup-state report
{
  "pi_version": "0.80.10",
  "managed_isolation_args": [
    "--no-extensions",
    "--no-skills",
    "--no-prompt-templates",
    "--no-themes",
    "--no-context-files",
    "--no-approve",
    "--system-prompt",
    "",
    "--append-system-prompt",
    ""
  ],
  "automatic_extension_executed": false,
  "generated_base_prompt_retained": true,
  "custom_system_prompt": "",
  "appended_system_prompt": "",
  "context_files_loaded": [],
  "skills_loaded": [],
  "skill_or_prompt_commands_loaded": [],
  "project_trusted": false,
  "poison_markers_detected_in_prompt": [],
  "model_turn_started": false,
  "result": "isolated"
}
- Outcome: 🔧 1 issue found → auto-fixed ✅ across 2 runs (14m18s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 1 issue found → auto-fixed (3) ✅
  • 🚨 internal/agent/pi.go:38 - The required “fail-closed gate isolation” is not preserved across Pi versions: this returns true for every installed Pi version, although the isolation contract and regression probe are explicitly verified only for 0.80.10. A later Pi release can add or change automatic resource surfaces and still be launched as neutralized. Gate admission must verify a supported Pi version or otherwise validate the effective isolation contract before returning true.

🔧 Fix: Enforce Pi gate isolation capabilities
2 errors still open:

  • 🚨 internal/agent/pi.go:48 - Capability admission is cached for the agent's entire lifetime. If Pi is upgraded or replaced during a long-running pipeline, later gate starts execute the new binary without rechecking its version or flags, contradicting the required fail-closed isolation boundary. Revalidate before each invocation or invalidate the cache when executable identity changes.
  • 🚨 internal/agent/pi.go:239 - The conflict scan treats every token named install, list, config, etc. as a package command regardless of argument position. Valid overrides such as --model list are therefore refused, while equivalent --model=list forms pass, contradicting the requirement that configured model overrides remain supported. Parse option/value relationships before rejecting positional package commands.

🔧 Fix: Revalidate Pi isolation and parse overrides safely
2 errors still open:

  • 🚨 internal/agent/pi.go:189 - The capability probe runs pi --help without the isolation block. Pi 0.80.10 creates runtime services for help and loads automatic extensions before printing help, so global or cwd-local extension code can execute during the supposed fail-closed admission check. Probe help with an isolated cwd/environment and the established isolation flags so capability verification cannot itself load behavior resources.
  • 🚨 internal/agent/pi.go:309 - A value-taking override ending the argument list is accepted because expectsValue is never checked after the loop. For example, --name consumes the subsequently appended managed --mode, leaving Pi outside JSON mode; plain output can then be ignored by the JSONL parser and potentially produce an empty successful result. Reject dangling value-taking options before admitting or launching Pi.

🔧 Fix: Isolate Pi capability probes and reject dangling overrides
✅ Re-checked - no issues remain.

🔧 **Test** - 1 issue found → auto-fixed ✅
  • 🚨 tests failed with exit code 1
  • go test -race ./...

🔧 Fix: Fix Pi capability probe fixture argument scanning
✅ Re-checked - no issues remain.

  • go test -race ./...
  • Baseline supplied by test harness: go test -race ./...
  • NM_TEST_REAL_PI_GATE_ISOLATION=1 go test -race ./internal/agent ./internal/daemon -run 'TestPiAgent_(RealGateIsolationNoModelCall|GateIsolation|RunGateIsolation)|TestNeutralizesGateInstructions|TestEnsureGateNeutralized|TestNewPipelineAgent_(OptOut|NoOptOut)' -count=1 -v
  • go test -race ./internal/config -run 'Test.*AgentArgsOverride|Test.*DisableProjectSettings|Test.*Trusted' -count=1 -v
  • make e2e
  • Manual Pi 0.80.10 RPC probe with poisoned global/project extensions, skills, templates, context files, system prompts, settings, and project trust; invoked the production isolation flags and recorded effective startup state without a model call.
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@palinopr palinopr closed this Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant