Skip to content

[design] "Which repo does this agent work on" is stored twice — the field you can edit is read by nothing, and for a single-repo agent there is no supported way to fix a wrong path #411

Description

@serge-ivo

The control you can edit is not the value the agent reads

Reported as "I updated it, but it is still using the old one." Both halves are true, and the reason
is that "which repo does this agent work on" is stored in two places, only one of which is
editable, and the editable one is read by nothing.

Measured on Chess coder (26f71cd8, surfaceOptions.coding.repos: "single")

GET /v1/instances/26f71cd8…/settings
  settings.repo  =  ~/dev/stores/pas/platform/apps/chess-academy     ← the owner edited THIS
  field "repo"   =  { label: "Repository", type: "text",
                      description: "The repo this agent owns — a local path (~/dev/my-repo)…" }

GET /v1/instances/26f71cd8…/coding/repos
  workdir        =  ~/dev/pas/platform/apps/chess-academy             ← every tool reads THIS
  cloneStatus    =  ready
  updatedAt      =  2026-08-07 23:23:15                               ← untouched by the edit

grep across workers/api/src finds no reader of settings.repo at all. It is a
settingsSchema field seeded on the coder-repo agent (migrations/0063_seed_coder2_agents.sql),
stored faithfully, and consumed by nothing. The owner changed the one thing the console offers, the
platform saved it, and the agent kept reading a different column.

Both values happen to point at empty directories; the real checkout is
~/dev/stores/pas/apps/chess-academy (21,039 files). That is incidental — the bug is that no edit
to the visible field could ever have worked.

Why there is no way out from the UI

  • RepoSettingsModal.tsx:86 shows Folder through Detail — a read-only div, styled with the same
    border/radius/font-mono language as every input in the app (bg-paper vs bg-panel, i.e.
    #0a0a0a vs #141414 on a dark-only theme).
  • ReposList.tsx:192 hides the add-repo input entirely when singleRepo.
  • The empty state (:216) sends the user to "Settings → Agent settings" — the field that does
    nothing.

So for a single-repo agent the repo path is: not editable in repo settings, not re-addable in the
repo list, and editable only through a setting no code reads. There is no supported way to correct
it.
The only working route is POST /coding/repos by hand.

The design

1. One source of truth, and it is the setting

For repos: "single" the settings field is the right home: declarative, subscriber-owned, already
rendered, already documented in the empty state, and consistent with how every other per-instance
choice works (#41's typed settings). Make it authoritative:

  • PUT /v1/instances/:id/settings with a changed repo reconciles the coding_repos row
    updating workdir (local path) or the remote coordinates (owner/name), creating the row if
    absent, and never silently diverging again.
  • The row remains the internal representation. Nothing outside the reconciler needs to know.

For multi-repo agents the list stays the source of truth and the setting is absent — which is
already true, since only the coder-repo agent declares it.

2. Validate where the value is entered

Apply #405's check on the settings write, not only on POST /coding/repos: does the path exist, is
it non-empty, is it a git work tree — asked of the runner that will use it. A rejected value must
not be stored, and the reason must be shown next to the field. This is the moment the owner can
actually act on it.

3. Make the repo path editable in the repo settings modal too

PUT /coding/repos/:repoId currently accepts name | urls | mergePolicy only. Add workdir, with
the same validation. Two entry points are acceptable if they write the same place; that is the
whole lesson of this ticket.

4. Stop rendering read-only values as inputs

Detail is visually a text field. Give read-only rows their own treatment (no border, or an
explicit lock affordance) so a value that cannot be changed does not invite a change. This is
general — every Detail in the app has the problem — and belongs with the design-system primitives
that landed in #366.

5. Where this is going: a checkout is per MACHINE, not per repo

Recorded as direction, not proposed for this ticket. workdir is a property of (repo, machine),
not of a repo. This account has two connected machines; the same repository is at
~/dev/stores/pas/apps/chess-academy on one and may be anywhere or nowhere on the other. Today a
single workdir column means an agent bound to a second machine is silently wrong — the identical
failure this ticket describes, arriving invisibly. coding_sessions already carries runner_node;
coding_repos has no such dimension.

The end state: a repo row holds identity (name, provider, remote, merge policy, URLs,
instructions); a checkout row holds location per machine, validated on the machine it names, so
the platform can say "ready on Mac, missing on Mac-mini" — a sentence it cannot form today. Do this
when a second machine actually runs the same repo, not before.

Acceptance

  • Editing Repository in Agent settings changes what the agent reads, in one step.
  • A path that does not exist / is empty / is not a git repo is refused at the point of entry,
    with the reason beside the field.
  • The repo settings modal can also change the folder, writing the same place.
  • A single-repo agent whose repo is wrong can be corrected without deleting anything.
  • settings.repo and coding_repos.workdir can no longer disagree — with a test that asserts it.
  • Read-only detail rows are visually distinguishable from inputs.

Files: workers/api/src/routes/instances.ts (settings PUT), workers/api/src/lib/instance-settings.ts,
workers/api/src/routes/coding-repos.ts:146,500, workers/api/src/lib/coding-store.ts,
agents/coder/web/src/RepoSettingsModal.tsx:86,121, agents/coder/web/src/ReposList.tsx:192,216,
workers/api/migrations/0063_seed_coder2_agents.sql. Supersedes the framing of #410; extends
#405.

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

    backendBackend / Worker / API workbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions