Skip to content

feat(the-framework): bind a topic run to a project via a gate (#1121) - #1131

Merged
suleimansh merged 3 commits into
mainfrom
spike/1121-gates-bind
Jul 24, 2026
Merged

feat(the-framework): bind a topic run to a project via a gate (#1121)#1131
suleimansh merged 3 commits into
mainfrom
spike/1121-gates-bind

Conversation

@suleimansh

@suleimansh suleimansh commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

What

A project-less "topic" run (#1120) can now bind itself to a project mid-run, via an await gate, and the projects it can bind to are injected into its context.

Two halves, per the #1129 decision (an await-gate, not MCP tools; list = read, not a tool):

  • Bind (the "write" half). The agent ends a turn on one of two fenced blocks:

    • ```await-bind-project picks from the already-registered projects. The framework fills the option list from the registry at resolution time, so the agent never names an id and can never pick one that is gone.
    • ```await-create-project registers a new project by its absolute path and binds to it.
      The framework resolves the gate, records boundProjectId on the run's meta, and re-prompts the agent with the result.
  • List (the "read" half). For a topic run, the registered projects (name + path) are injected into the system channel as context, read through the same seam the gate resolves against so no node:fs reaches the browser-rendered prompt path. An empty registry says so, steering the agent to await-create-project.

Permission semantics

await-create-project recommends Approve and renders as a confirmation, so autopilot and a headless run auto-accept it, exactly like the plan confirmation gate (#358). Registering a path is what grants the app filesystem access to it, so the confirmation is the grant.

Hardening

  • An await-create-project path that is relative, empty, missing, or not a directory declines cleanly back to the agent (resolveProjectPath), never crashing the run. resolve collapses any ./.. and the absolute requirement is the traversal guard.
  • Registration is idempotent by resolved path and surfaces the existing record, with a distinct "already registered" reply.

Out of scope

The bind only registers + records here. The actual worktree allocation and continue-run (re-homing the topic run into the bound project) is a // #1122: follow-up, not implemented in this PR.

Notes

  • No prompts/system_prompt.md edit: the bind protocol and the project list live in the runtime append layer (system-prompt.ts), appended only for topic runs, so a normal run's channel stays byte-identical ([The Framework] Remove the persona / skill / memory framing #547).
  • Tests cover parsing, resolution, list-as-context (populated / empty / unwired), each path-validation edge case, idempotency, and the recommended-Approve grant.

Closes #1121

Await-gates variant of #1121: a project-less topic run (#1120) ends a turn on
an await-bind-project / await-create-project block; the framework resolves it by
registering + binding the project and recording the bind. Reuses the same bind
recording shapes as the MCP-tools spike (bind control entry, RunMeta.boundProjectId,
bind event, terminal line) so only the trigger differs.

The gate is taught via the runtime append layer (system-prompt.ts, topic-only), so
no base-prompt edit and the prompt-drift check stays green.

Spike for #1121, part of the #1129 decision.
Harden the topic-run bind gate to the real feature and add the list-as-context
"read" half (#1129).

- Inject the registered projects (name + path) into a topic run's system channel
  as context, not a tool: the node side reads listProjects through the same
  injected seam the gate resolves against, so no node:fs reaches the browser path.
  An empty registry steers the agent to await-create-project.
- Validate an await-create-project path via resolveProjectPath (absolute, exists,
  is a directory); a bad path declines cleanly back to the agent instead of
  crashing. Registration stays idempotent by resolved path and surfaces the
  existing record, with a distinct "already registered" reply.
- await-create-project recommends Approve, so autopilot and a headless run
  auto-accept the grant, exactly like the plan confirmation gate.
- The bind still only registers + records boundProjectId; the worktree re-home
  it implies is left as a #1122 TODO.
@suleimansh suleimansh added enhancement New feature or request priority: medium Worth doing, not urgent and removed question Further information is requested labels Jul 24, 2026
@suleimansh suleimansh changed the title spike(the-framework): gates bind for topics [#1121 spike] feat(the-framework): bind a topic run to a project via a gate (#1121) Jul 24, 2026
@suleimansh
suleimansh marked this pull request as ready for review July 24, 2026 22:06
@suleimansh
suleimansh merged commit 7509a4c into main Jul 24, 2026
1 check passed
@suleimansh
suleimansh deleted the spike/1121-gates-bind branch July 24, 2026 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request priority: medium Worth doing, not urgent the-framework ♻️

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Topics: bind-project and create-project await-gates

1 participant