Skip to content

fix(tangent): make an agent's pipeline rename stick everywhere the name shows - #2796

Closed
camielvs wants to merge 4 commits into
09-23-fix_say_why_the_backend_refused_a_runfrom
09-23-fix_make_an_agent_s_pipeline_rename_stick
Closed

camielvs wants to merge 4 commits into
09-23-fix_say_why_the_backend_refused_a_runfrom
09-23-fix_make_an_agent_s_pipeline_rename_stick

Conversation

@camielvs

@camielvs camielvs commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator

Problem

An agent asked to name a pipeline calls set_pipeline_name. That renamed the
spec held in memory and nothing else, so it reported success while the file
stayed Draft and both resource lists kept showing the name recorded when the
pipeline was added.

Behind that sat a second problem: nothing asked for the rename in the first
place
on the path that matters. The naming brief only covered pipelines an
agent creates — but a project opened from a prompt already holds one, named
after the request, so the agent "found the open canvas" and no rule applied.
And the brief is seeded into the session's memory, which is Prime's, while the
only agent holding set_pipeline_name is the remote editor, whose prompt said
nothing about naming at all.

Then a third: even once a rename did fire, the lists kept the old name for a
minute. Browser storage fires no event a rename in this tab would reach, and the
query behind those lists is keyed on the pointer, which a rename does not change.
The new name appeared on reload, which read as the rename silently failing.

What changed

The spec name is canonical and everything follows it. The rename goes
through the file first, and the name the file actually took is what the spec is
called. An agent picks a name without knowing what else this browser holds, so a
collision adjusts rather than overwriting — the rule create_pipeline already
follows — and the tool says so instead of letting the agent believe it got the
name it asked for:

Renamed to "Churn model 2" — "Churn model" was already taken.

Agent renames go through a new renamePipelineFileFor rather than the hook the
menu bar uses: that one also navigates, which is meaningless for a pipeline open
in a workarea tab rather than at a url of its own. The rename invalidates the
local-pipeline queries and retitles the open tab, which otherwise keeps
announcing the name it resolved when it opened.

Naming happens on the first turn, not at the end of the build. A pipeline
created from the opening prompt is marked as carrying a name nobody chose;
get_pipeline_state reports that as nameIsProvisional. Prime gets a
name_pipeline tool it calls alongside name_session and rename_project
the opening message is enough to title a pipeline, so there is nothing to wait
for. It refuses a pipeline someone named deliberately, and drives the open tab's
bridge rather than the resource row, because only the bridge moves the spec, the
file and the row together. The editor keeps a fallback rule for a pipeline still
unnamed once its changes are in.

The mark lives on the spec rather than on the project resource because the agent
that acts on it reads the canvas and never sees the row.

Both resource lists ask what a pipeline is called now instead of trusting the
copy on the row, which also fixes the same staleness after a rename from the menu
bar. A name-only pointer is trusted only in the browser that wrote it — someone
else's "Churn model" is not the one this browser holds, and naming a row after it
would be naming the wrong pipeline. Unknown authorship is trusted, which is every
single-user backend.

useUnavailablePipelines becomes useLocalPipelineStatus in
services/projects: both pages need it now, and it answers two questions
(unreachable, and current name) rather than one.

Fixing the project page also meant separating two things that had shared one
prop: a row's display label and "this row opens a conversation elsewhere". A
renamed pipeline is still a row on this page, and overloading the label would
have made it open as a session and lose its Remove button.

Testing

  • New renamePipelineFileFor.test.ts (6), useLocalPipelineStatus.test.ts (6),
    provisionalPipelineName.test.ts (4); createNamingHandlers.test.ts and
    serializeSpecForAi.test.ts extended.
  • pnpm run validate clean; npx vitest run 321 files / 3256 tests green.
  • Observed against a live agent on the previous revision: the rename fired and
    the collision message surfaced correctly, but the new name only reached the
    lists on reload — which is what the query invalidation here fixes. The
    first-turn name_pipeline path has not been exercised against a live agent
    yet.

🤖 Generated with Claude Code

camielvs and others added 3 commits September 23, 2026 13:53
Everything a prompt brought into being was called something generic:
"Project 3", "Session 1", four random words. The agent knows what it is
building, so it gets tools to say so.

- rename_project and name_session, seeded with a standing brief telling the
  agent to use them, plus a nudge to name the pipelines it creates.
- rename_project replaces only a name nobody chose. Machine-made names carry
  a provisional mark; the first deliberate rename, by anyone, drops it.
- Underneath, a deterministic floor: project, session and pipeline are named
  from the opening prompt at creation, and a session started inside a project
  is named from its first message. An agent that never calls the tools still
  leaves something readable behind.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
"build a pipeline that scrapes wikipedia and converts articles into a
pokemon" became "Build a pipeline": the trailing-phrase trim cut at the
first joiner it found from the right, wherever that was. It now only drops
a phrase that starts in the tail of the name, leaving "Build a pipeline
that scrapes wikipedia".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A rejected submission explains itself — a 422 names the field it would not
accept and the value it was given — and all of it was dropped for the fixed
sentence "Failed to create pipeline run". An agent that reads only that
cannot tell a spec it could correct from a bug it should give up on, and
retries the identical request instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 23, 2026

Copy link
Copy Markdown

🎩 Preview

A preview build has been created at: 09-23-fix_make_an_agent_s_pipeline_rename_stick/97afd7e

camielvs commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

…me shows

`set_pipeline_name` renamed the spec in memory and nothing else, so the
agent reported success while the file stayed "Draft" and both resource
lists kept the name recorded when the pipeline was added. Nothing asked
for a rename in the first place on the path that matters, either: the
brief only covered pipelines an agent creates, and a project opened from
a prompt already holds one named after the request.

The spec name is canonical and everything follows it. The rename goes
through the file first, and the name the file actually took is what the
spec is called — a name already taken comes back adjusted, and the agent
is told so rather than left believing it got the name it asked for. The
two resource lists ask what a pipeline is called now instead of trusting
the copy on the row, which also fixes the same staleness after a rename
from the menu bar, and the open tab retitles rather than announcing the
name it had when it opened.

Browser storage fires no event a rename in this tab would reach, and the
query behind those lists is keyed on the pointer, which a rename does not
change — so the rename now invalidates it. Without that the new name only
appeared a minute later, or on reload, which read as the rename silently
failing.

A pipeline created from the opening prompt is marked as carrying a name
nobody chose, `get_pipeline_state` reports that as `nameIsProvisional`,
and Prime gets a `name_pipeline` tool it calls in its first turn beside
name_session and rename_project — the opening message is enough to title
a pipeline, so there is nothing to wait for. It refuses a pipeline
someone named deliberately, and drives the open tab's bridge rather than
the resource row, because only the bridge moves the spec, the file and
the row together. The editor keeps a fallback rule for a pipeline still
unnamed once its changes are in.

A name-only pointer is trusted only in the browser that wrote it:
someone else's "Churn model" is not the one this browser holds.
`useUnavailablePipelines` moves to `services/projects` as
`useLocalPipelineStatus`, since both pages need it and it answers two
questions rather than one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@camielvs
camielvs force-pushed the 09-23-fix_make_an_agent_s_pipeline_rename_stick branch from 656fc7f to 97afd7e Compare September 23, 2026 21:43
@camielvs
camielvs force-pushed the 09-23-fix_say_why_the_backend_refused_a_run branch from 65c7fbe to 5964134 Compare September 23, 2026 21:55
@camielvs

Copy link
Copy Markdown
Collaborator Author

Folded into #2792 — the pipeline-rename plumbing is the other half of that PR's pipeline naming, so keeping them apart meant #2792 claimed to name pipelines while the rename only reached the spec in memory.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant