Skip to content

Topics: recommend gate for bind + read for list (#1121 mechanism) #1129

Description

@suleimansh

Recommendation: gate for the bind/create, read for the list. Both approaches were spiked end to end and are green; evidence below. For #1121, part of #1115.

The call

  • create_project / bind a project -> await-gate. The agent ends a turn with an await-create-project / await-bind-project block; the framework shows Approve/pick, resolves it, resumes.
  • list_projects -> a read, not a gate: inject the registered projects into the topic run's context (add a read-only tool later only if the list gets large/dynamic).

The issue framed both as "tools", but a pure read and a permission-carrying respawn are different shapes. Splitting them is cleaner than forcing one mechanism on both.

Why a gate for the bind

  1. This is a permission feature ("the confirmation is the permission gate"). A gate IS that gate: Approve/Decline, asked once per new project, autopilot auto-accepts, all for free. Agents run in bypassPermissions, so an MCP tool call does not prompt the user; to get the required approval you would rebuild the gate round-trip anyway.
  2. Binding is a respawn. The run moves to the project's worktree (Topics: re-home a run's cwd/worktree on bind #1122), so it is a turn-ending transition. A gate models that. A tool returns a value mid-turn into a run that is about to be torn down.

Why a read (not a gate) for the list

A pure read is naturally tool/context-shaped; ending a turn to read a list is awkward.

Evidence from the two spikes (both draft, both CI green)

tools (#1130) gates (#1131)
footprint 6 files / +193 10 files / +249
tests 1260 1266
base-prompt edit none none (runtime append layer)
permission gate must bolt on native
respawn fit (#1122) fire-and-effect native

Findings that settled earlier unknowns:

  • Neither needs the drift-guarded system prompt. The gate protocol lives in the runtime append layer (system-prompt.ts), appended only for topic runs; system_prompt.md is untouched.
  • UI/UX is identical either way. Both feed the same bind event + RunMeta.boundProjectId; the approval routes through the existing choice panel. The mechanism choice is internal, not user-facing.
  • The bind-recording code is byte-identical across the two spike PRs, so the diff between them is purely the trigger.

Next once confirmed

Promote the #1131 gates spike to the real #1121 (add list-as-context, harden, fuller tests, changeset), then build #1122 re-home (allocate the worktree + continue-run into the chosen project). Retire the #1130 tools spike.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions