Skip to content

[Feature] Give evolved code_extension a boundary Reef owns, for codex and terminus #210

Description

@simonucl

Primary area

Harness, recipes, or surfaces

Problem

Two adapters now render four of Reef's node kinds and reject code_extension, each because the evolved code would run with more privilege than the agent it configures.

codex (#201): Codex's mechanism is lifecycle hooks, whose Command handlers are subprocesses spawned outside the workspace-write sandbox that contains the model's own commands. Hooks also need a persisted trust record a fresh CODEX_HOME never has.

terminus (#209): Terminus 2 is a Harbor agent class, and a Reef module would be loaded in the runner's own process — outside the task container entirely. That adapter also declares self_isolating, so Reef's bubblewrap jail is off: there is no boundary left to contain it.

The shape is the same in both: the vendor isolates the commands the model writes, not code supplied alongside the agent. pi, opencode, dsh, hermes, and native accept code_extension because their extension point runs inside the agent's own process, under whatever containment the episode already has.

This is not urgent. Meta-Harness, the method these adapters exist for (#42), searches over {agent_command, rules, skill}recipes/meta_harness/.../composition.py sets ALLOWED_NODE_KINDS to exactly that — so nothing planned needs the kind on either adapter.

Concrete use cases

  • A method that evolves a PreToolUse guard and wants to measure it on Codex as it can on pi.
  • A Terminus context policy that rewrites the message list before each model call: its own compaction instead of enable_summarize, or notes carried between turns. This is the seam with the most headroom on the chronic clock-hit tasks in [Example] Add a Terminal-Bench harness self-evolution example #6, and the archived ReefTerminus prototype (archive/bo/reef-terminus) implemented exactly it.
  • A cross-adapter comparison where a tree must render identically everywhere, so a rejected kind does not silently change the instrument.

Proposed outcome

Reef owns the boundary for evolved code the vendor will not contain: the module or handler runs in a jail Reef controls, the way SandboxExecutor already jails the episode, and the adapter renders whatever entry point points at it. Until then, rejecting at render is the correct behaviour and both adapters should keep doing it.

Worth settling as part of the design: whether one mechanism serves both cases, given codex's is a subprocess Codex spawns and terminus's is an in-process module Reef loads. The terminus case may be the harder one, since assemble(state, request, files) has to return a message list into the calling process rather than just run to completion.

A smaller acceptable outcome is a decision to reject the kind permanently on both, recorded here, with each descriptor dropping its placeholder code_extension path so the adapters stop implying support they do not have.

Alternatives and workarounds

  • Express the behaviour as skill or rules. Works for guidance, not for mechanical enforcement or for context assembly, which is the point of the kind.
  • Enable it anyway. On codex that means --dangerously-bypass-hook-trust, whose own help says it is for automation that already vets its hook sources; on terminus it means exec in Reef's process with the jail off. Both run gate-promoted code above the model's own privilege.

Compatibility and maintenance

Additive: both rejections and their render tests stay until a boundary exists. Whoever builds it owns a second sandbox entry point distinct from the episode's, and it needs the same fail-fast treatment SandboxExecutor.preflight already gives, so a hosted deployment that cannot isolate refuses rather than degrades.

Submission checks

  • I searched open and closed issues, pull requests, and RFCs for related work.
  • I described the problem and use cases without assuming one implementation.
  • I have not started a large implementation that still needs project-direction approval.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: harnessHarness integration, recipes, and evolution surfacesenhancementNew capability or improvement to existing behaviorstatus: needs-triageNeeds an initial maintainer decision and routing

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions