The gap
A Repo Coder is configured to own exactly one repository:
"surfaces": ["coding"],
"surfaceOptions": { "coding": { "repos": "single", "drive": false, "copilot": false } }
repos: "single" is read only by the console (lib/surfaces.tsx, to hide add-repo and the
multi-repo list). It never reaches the system prompt. What the model gets instead is
## Attached Repositories (agent-think.ts:365) — an inventory of what happens to be attached,
phrased as context, not as responsibility.
So the agent's sense of owning a repo comes from a seeded memory string (goal = "Deliver the
objectives you are given in your repository…"), not from its declared capabilities. That is why it
can describe itself correctly one day and contradict its own configuration the next: memory is
narrative, capabilities are fact, and only the narrative is in the prompt.
Evidence it does not know its own configuration
FAS platform Coder (964594b6), 2026-08-04, asked what it can do:
To get started, attach a repository in the Repo tab and give me an objective.
This agent has no Repo tab. That surface is gated to surfaces: ["repo"] (lib/surfaces.tsx)
and it declares ["coding"]. It invented a UI location it cannot have, and told the user to go
there.
Same class as the toolBlurbFor docstring already warns about — "it tells the model a story about
itself that its actual tool set contradicts, and the model believes the story" — except here the
story is about surfaces and repo ownership rather than tools, and nothing derives it.
Why it matters beyond a wrong tab name
The product promise is "a workspace == an agent instance" — an agent responsible for a repo. The
implementation is a chat brain that can delegate to a separate executor via start_work, with no
declared statement of what it owns. Consequences already observed:
Suggested shape
Derive the self-description from the resolved capabilities, the way toolBlurbFor derives the tool
blurb:
surfaceOptions.coding.repos === "single" → state it plainly: "You are responsible for exactly
one repository: <owner/repo> at <workdir>. You do not manage other repositories and cannot add
one."
- Name only surfaces the agent actually declares, so it can never send a user to a tab that is not
rendered for it.
- Keep the seeded
goal memory for tone/purpose, but stop letting it be the only source of a fact
the capability registry already knows.
Verification
- A single-repo Coder names its repo when asked what it works on, without reading memory.
- No agent ever references a tab absent from its declared
surfaces.
- An agent with no repo attached says so and names the correct place to add one for its own
configuration.
The gap
A Repo Coder is configured to own exactly one repository:
repos: "single"is read only by the console (lib/surfaces.tsx, to hide add-repo and themulti-repo list). It never reaches the system prompt. What the model gets instead is
## Attached Repositories(agent-think.ts:365) — an inventory of what happens to be attached,phrased as context, not as responsibility.
So the agent's sense of owning a repo comes from a seeded memory string (
goal= "Deliver theobjectives you are given in your repository…"), not from its declared capabilities. That is why it
can describe itself correctly one day and contradict its own configuration the next: memory is
narrative, capabilities are fact, and only the narrative is in the prompt.
Evidence it does not know its own configuration
FAS platform Coder (
964594b6), 2026-08-04, asked what it can do:This agent has no Repo tab. That surface is gated to
surfaces: ["repo"](lib/surfaces.tsx)and it declares
["coding"]. It invented a UI location it cannot have, and told the user to gothere.
Same class as the
toolBlurbFordocstring already warns about — "it tells the model a story aboutitself that its actual tool set contradicts, and the model believes the story" — except here the
story is about surfaces and repo ownership rather than tools, and nothing derives it.
Why it matters beyond a wrong tab name
The product promise is "a workspace == an agent instance" — an agent responsible for a repo. The
implementation is a chat brain that can delegate to a separate executor via
start_work, with nodeclared statement of what it owns. Consequences already observed:
refuse or question an instruction aimed at a different repository.
Suggested shape
Derive the self-description from the resolved capabilities, the way
toolBlurbForderives the toolblurb:
surfaceOptions.coding.repos === "single"→ state it plainly: "You are responsible for exactlyone repository:
<owner/repo>at<workdir>. You do not manage other repositories and cannot addone."
rendered for it.
goalmemory for tone/purpose, but stop letting it be the only source of a factthe capability registry already knows.
Verification
surfaces.configuration.