Skip to content

Create a working Switch expert from the Templates view in two clicks (CHOO-2665) - #409

Draft
abeldantas wants to merge 54 commits into
mainfrom
work/switch-expert-template
Draft

abeldantas wants to merge 54 commits into
mainfrom
work/switch-expert-template

Conversation

@abeldantas

@abeldantas abeldantas commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

In this PR we make the Switch expert something you get from the Templates view in two clicks, working: pick it, click "Add agent and open its room", and the agent is created, put in a room with you, spoken to, and answering. It reconciles #434 and #409 (and #436, stacked on it) into one branch on top of the merged template registry (#421), with #405 (the Create-from-template view) merged in underneath.

What an agent template is now: a YAML document with an agent: block (name, description, instructions, the repository it works from, the pages it reads) beside an optional room: and kickoff: in the room-template shape. switch-expert/template.yaml is the first one and the field-by-field description of the format; the persona stays in AGENT.md and is filled in at bundle time, so it is written once. examples/agent-templates/jq-expert.template.yaml is the same shape on a different subject, with inline instructions, the way a template uploaded to a server's registry carries them. Templates uploaded with kind agent show in the same listing as the bundled one, with their owner as creator.

What the Console does on "Add agent": suggests a directory named after the agent under the Console's locations directory, creates it, shallow-clones the template's repository inside, registers the agent (auto-session on, owner-only addressing, as before), provisions the template's room through POST /rooms/from-yaml with {agent} filled in, and opens it. The kickoff is posted as the creating person, which is what starts the agent working. The room-template wizard's "+ Create" on a missing agent slot opens the form filled from the matching bundled template when there is one.

What we dropped from the earlier branches: the parallel stored_templates table and endpoints from #434 (the registry is the single store), and the repo_url / sources columns from #436 (the registry stores documents as they arrive; the repository and sources live in the document, where a second expert needs only a second document, and the API never served the columns anyway). Kept from #434: the persona and knowledge fixes under switch-expert/ from August that never reached main.

Server side this is small: agent is a known top-level key for the registry linter, and {agent} counts as declared inside an agent template. Also repairs three linter tests that still treated multiline as an unknown param field; it is a known one once #405's format is on the branch, so #405 will hit the same three.

The second pass, from a first-run user's seat

After the flow worked once, we went through it as someone who just installed the Console and fixed what stood between them and a working agent:

  • The dialog is a confirmation now: instructions fold to one line with Edit, a taken prefilled name moves to the first free variant with a note, and the repository fetch and the room are each a switch.
  • Before the click, the dialog checks the two things the first message depends on: that the server has a messaging app at all, and that the server can tell who the person is on the room's bridge. For the second it asks a new GET /collaborations/{id}/me, which resolves the caller the way a kickoff does (a claimed identity, else the account's name or email matched on the platform), so the warning fires only when the kickoff itself would fail. Missing either, it says so with the fix beside it (the claim dialog takes over and hands back; a button to the server page for connecting a messaging app).
  • After the click, the Console opens the agent's session as soon as it starts, instead of leaving the person on a room page that shows nothing.
  • A template can declare who may address the agent; the Switch expert says anyone in its rooms, since a team shares it.
  • The listing has search, a Details fold per card (repository, sources, the room it starts in, who it answers, the first lines of its brief), a notice when this computer has no usable provider, and Save to server for the bundled template.
  • Templates reach an existing room: the add-agents dialog and the room's Configuration tab offer them, the agent is created into that room, and the toast says to mention it there.
  • An agent keeps the template it came from in its config file, and its settings page offers "Update from ", filling the editor with the current instructions for the person to save.
  • Remote run locations get the same treatment: directory suggested under the host's home, created and the repository cloned over SSH on submit.
  • The suggested directory steps past a folder that already holds an agent, so a leftover from a reset server does not fail the click. The agents page offers "From a template" next to the blank form.
  • Testing

    Live on a local stack (this branch's core and Console, Test Slack bridge): Templates → Switch expert → Use → Add agent and open its room. Directory created at ~/switchdash/repositories/switch-expert with switch/ cloned inside, agent registered, room "Ask switch-expert" created on the bridge with me in it, kickoff posted as me, session auto-started, and the agent answered from its brief 32 seconds after the click (first check for a silent agent: is anything running it). A second template (the jq expert) uploaded to the registry with kind agent appeared in the listing and opened the same prefilled form. On an isolated stack for this branch (own Postgres, core on 8001, Test Slack bridge, identity linked): the two-click flow created switch-expert into a stepped directory, provisioned the room, posted the kickoff as me, the Console opened the session on its own, and the agent answered 26 seconds after the kickoff. From the room's Configuration tab, "From a template" created switch-expert-2 (auto-renamed) into that room with the toast. The settings page shows "Update from Switch expert" and reports already up to date. Save to server put the Switch expert on the registry, where it listed as "by Admin". Choosing the POC host as run location filled the directory with /home/ubuntu/switchdash/repositories/switch-expert-3, stepping past a taken folder on the host. Not exercised live: creating an agent on the remote host end to end, the wizard's "+ Create" from a matching template, and the name-or-email match behind /me (covered by unit tests; my test stack's admin account matches nothing on Slack).

    Checks: ruff, mypy, test_template_lint.py (54 passed), test_collaboration_me.py (3 passed); Console typecheck, oxlint, oxfmt, vitest (agent-template-format 13 passed; one pre-existing failure in session-spawner.test.ts that depends on this machine's Claude trust state, untouched here).

    https://claude.ai/code/session_01VNFGdRYHsohGjSdkJYgVtt

Three-step flow: paste YAML or pick a file → fill a form generated from
the template's params block → POST to /rooms/from-yaml and navigate to the
new room. Paramless templates skip straight to creation.

Agent-name params (named exactly "agent" or ending in "_agent") render as
a combobox over the live agent list with an inline warning when the name
doesn't match. Required fields block submission with inline errors before
any server call. Server 400s are mapped back to the offending field.

Registered as "Templates" in the workspace sidebar nav. One appended entry
each in view-ids.ts, view-registry.ts, and workspace-nav.tsx.
The package is "type": "module" so __dirname is undefined at runtime,
crashing electron-vite dev on launch. import.meta.dirname is the ESM
equivalent and works in both dev and packaged builds.
Two-column layout: form on left, "What this creates" summary panel on
right showing a live preview of the room name (interpolated from inputs),
which agents will be added, and template source info.

Field labels now use humanized param names with description as helper text
underneath. Agent-name fields show an inline "exists ✓" or "not found"
badge inside the input. Fields with unchanged defaults show "(default
kept)". Buttons are stacked full-width: "Back to template" + "Create
room". Step indicator "Step N of 2" in the header.

Parser now also extracts the agents list from the template's room block
for the summary panel preview.
Make the YAML paste area taller (min-h-64) and vertically resizable so
large templates are comfortable to work with.

Use describeFailure's detail field directly for server errors instead of
the HTTP-prefixed message, so the user sees "Unknown agents: foo" rather
than "Could not create the room from this template. (HTTP 400: ...)".
…rors

Pull the server's detail field from the RpcError before describeFailure
wraps it with an HTTP prefix, so the user sees "Unknown agents: foo"
rather than "HTTP 400: Unknown agents: foo".
Server side: new GET /gateway/rooms/template-schema endpoint returning
the JSON Schema for a valid room template document, generated from
Pydantic's TemplateDocument model (RoomSpec + ParamSpec).

Console side: fetches the schema when the Templates view loads and
validates the parsed YAML against it (via ajv) at the step 1→2
transition. Schema violations surface as parse errors before the form,
so the user learns their template is invalid before filling anything out.
Graceful degradation: if the server doesn't support the endpoint (404),
validation is skipped.

ajv added as an explicit dependency (was already present as a transitive
dep).
When the schema endpoint returns 404 (server lacks params support), the
parser now rejects unknown top-level keys like params: at step 1 with a
clear message instead of letting the user fill a form that will fail at
create time.

Adds drag-and-drop support to the source step textarea — drop a YAML
file onto it and it reads the same way the file picker does.
When the schema endpoint is unavailable, skip validation and let the
server decide on create. The previous fallback rejected params: on any
server without the schema endpoint, which blocked servers that support
params but predate this PR's schema endpoint.
The room view reads from a MobX store that caches the rooms list.
Navigating immediately after creation showed "still loading" because the
store had no entry for the new room. Call refreshSidebarRoomState(true)
before navigating — same pattern as CreateRoomModal.
The server reports users/refs/docs that couldn't be added in
failedAttachments, but the Console discarded them. Now shows a warning
toast naming each failed item so the user knows what didn't land — e.g.
"abel.dantas (no account with this name is known on the bridge)".
The existing override mapped <4.3.0 to >=4.3.0, which resolved to 4.3.1 —
still vulnerable to merge-key CPU exhaustion. Floor is now 4.3.2, the
fixed release. Transitive only; the app's direct js-yaml (5.x) is not in
the affected range.
The YAML provisioning path returned None when bridge was omitted,
creating an internal-only room. This broke templates with users: since
users live on a collaboration bridge. Now looks up the instance's
default bridge (same behavior as the regular create-room endpoint).
@abeldantas
abeldantas force-pushed the work/switch-expert-template branch from d74a784 to 64a427e Compare September 10, 2026 15:48
@abeldantas
abeldantas changed the base branch from work/import-ux to work/template-registry September 10, 2026 15:48
Hardcoded (non-interpolated) entries in a template's agents: and users:
lists now appear in the form as editable, removable fields with live
validation against the server's agent list.

Before creation, the Console rewrites the YAML's agents/users arrays to
reflect the user's edits — so removing an agent that doesn't exist on
this server avoids the "Unknown agents" server error.
Specifying the same agent twice in a template's agents list (e.g. both
coder and reviewer params resolved to the same agent) caused a 500
when trying to invite the same agent twice. Deduplicate early in
_resolve_names_to_ids so all callers are covered.
The from-yaml provisioning path didn't add the creating user to the
room, so they saw "unknown-channel" in Slack and the room didn't appear
in their sidebar. Now the creator's username is always prepended to the
users list (deduplicated), matching the regular create_room behavior.
Templates can now use {creator} anywhere in the room spec to reference
the signed-in user who creates the room. The server resolves it during
interpolation alongside param values. Template authors use it
explicitly (e.g. users: ["{creator}"]) rather than the server
auto-adding the creator unconditionally.

Reverts the unconditional auto-add from the previous commit — the
creator is only added when {creator} appears in the template.
It was added for the auto-add approach and is no longer used now that
{creator} handles it via parse-time builtins instead.
Built-in template variables now use a $ prefix to distinguish them from
user-defined params: {$creator}, {$date} (YYYY-MM-DD), {$timestamp}
(unix epoch). The placeholder regex is updated to match {$name}
patterns. $server deferred — needs a config dependency in the handler.
Two fixes for the template import flow:

1. Bridge user resolution now falls back to the platform's directory
   search when a user isn't found in the DB. This resolves users who
   exist on Slack but have never messaged through Switch — the adapter's
   search_directory_users matches by username and email. Also adds
   {$creator_email} builtin so templates can reference the creator's
   email for resolution.

2. Templates can now include a kickoff: field — a message posted to the
   room after creation to dispatch work to agents. The provisioning
   protocol gains send_message so the YAML service can post directly
   after room setup completes.
Fixes the 500 on kickoff by implementing send_message properly on
PostgresProvisioning — creates a Message row with all required fields
(transport_event_id, sender, event_type) instead of a partial object.

Makes user resolution more lenient: when the directory search returns
exactly one result (e.g. searching "Admin" finds one person), accept
it without requiring an exact username/email match. Catches RuntimeError
alongside NotImplementedError so a failed Slack API call doesn't crash.

Adds {$creator_email} builtin for email-based user resolution in
templates.
The kickoff crashed because Message.room_id is a FK to rooms.id (Switch
room ID), but send_message received the transport room ID. Now resolves
it via get_by_matrix_room_id first, matching the pattern used by
invite_to_room and kick_user.
When a template specifies users by their gateway display name (e.g.
"Admin" from {$creator}), resolve them to their claimed bridge identity
(e.g. "dantas.abel" on Slack) before passing to room creation. This
uses the external_user_claims table — the same data the Console shows
as the linked identity on the Home page.

Users without a linked identity pass through unchanged and are resolved
by the bridge's own directory search.
…ff as the creating user

The kickoff added in fc159b3 could never deliver: it wrote a raw messages
row with the transport room id in the rooms.id column and no event id or
event type, so every kickoff insert would fail — and even a well-formed
system message addresses no agent by design. Replaced with a real path:

- RoomService.post_kickoff sends the kickoff through the creating user's
  puppet, the same rail as a message they typed on the platform, so it
  addresses the agents it mentions and threads/attributes normally.
- BridgeCore.post_as_user stamps SWITCH_ORIGINATED_MARKER and the outbound
  relay forwards marked puppet events to the platform instead of treating
  them as echoes, so the kickoff shows up in the external channel too.
- Directory-search resolution now persists its hit (ExternalUser + puppet),
  so ensure_users_in_room — which used to skip anyone Switch had not seen
  speak — adds directory-resolved people to the room, not just the channel.
- $creator resolves claims-first: builtins_for reads the template's bridge
  and answers with the creating user's linked identity there, falling back
  to the gateway account name. resolve_switch_user gives kickoff the same
  claims-first answer.
- Kickoff failures land in failed_attachments (visible in the console
  toast) rather than failing a room that already exists.
- Removed the dead send_message from the Provisioning port.

Claude-Session: https://claude.ai/code/session_017PdBwqBjgajRdMjLiFSiuA
…zard

The wizard now answers the two questions that made template testing feel
bugged: will I be in this room, and what starts the work.

- "What this creates" lists the users being invited and, when the template
  carries a kickoff, that it is posted as you; the kickoff preview renders
  with your inputs filled in.
- Templates using {$creator} get a "You in this room" box: resolved via
  your linked identity on the template's bridge, with a warning when no
  identity is linked yet.
- The hardcoded-users list validates against the server's known bridge
  users instead of flagging every name "not found"; unseen names say so
  and note the directory is still tried at create time.
- Interpolated users ({$creator}) now survive the create rewrite — they
  were silently dropped when a template mixed them with hardcoded names.

Claude-Session: https://claude.ai/code/session_017PdBwqBjgajRdMjLiFSiuA
The coder/reviewer-loop template used to exercise the import flow end to
end, now carrying the full surface: typed params with the _agent picker
convention, {$creator} membership, and a kickoff that dispatches both
agents. Doubles as the reference for template authors.

Claude-Session: https://claude.ai/code/session_017PdBwqBjgajRdMjLiFSiuA
A template param like a task brief carries a full document, and the
wizard rendered every string param as a one-line input — pasting a brief
stripped its newlines, flattening the Acceptance section the whole
red-blue loop keys on. `multiline: true` on a string param is declared
in the template, validated by the server's ParamSpec (so the schema
advertises it), and rendered as a textarea by the Console.

Claude-Session: https://claude.ai/code/session_017PdBwqBjgajRdMjLiFSiuA
Admin client ("Agent Switch") by default. Falls back to the creator's
puppet when any agent in the room has a restricted addressing policy
that would reject the admin — so owner-only agents still receive the
kickoff as an addressed message from their owner.

The check reads each room agent's addressing_policy from the DB and
uses AddressingPolicy.is_open() to decide. Creator identity params
(user_id, user_name, user_email) are passed through from rooms_yaml
for the fallback path.

Tested: ran local server, created room with kickoff (no agents = open
policy). Verified sender_id=@switch-admin:localhost, sender_name=admin.
64 tests pass.

NOT tested: restricted-policy fallback path (requires agents with
owner-only policy on a bridged room — not available on local stack).
is_open() returns False for policies with wildcard rules (users: '*',
agents: '*') because it only checks len(rules)==0. A wildcard policy
is functionally open — any user sender is accepted, including the
admin bot.

New check: _accepts_any_user() returns True when any rule has users='*',
so wildcard policies correctly use the admin path. Only policies that
restrict users to a specific list trigger the creator puppet fallback.

Tested: local server, room with no agents. Kickoff posted by admin
(sender_id=@switch-admin:localhost). 64 tests pass.

NOT tested: wildcard-policy agents on a bridged room (not on local).
The admin client is not a "user" in the addressing system — agents with
any addressing policy reject admin-posted messages, even with users:'*'.
The creator puppet is the only sender that passes addressing checks.

Bridged rooms: kickoff posted as the creator's puppet via post_as_user.
Internal-only rooms (no bridge): best-effort via admin client since
there's no puppet to use.

Tested: local server, internal room kickoff via admin works. 64 tests
pass. Bridged kickoff via creator puppet is the same code path Abel's
merge (eef93ab) proved worked — this reverts the adaptive logic that
broke it.

NOT tested: bridged creator puppet path on local (no bridge).
Brings the branch up to date with main's multi-tenancy wave (CHOO-2623
RLS, tenant-scoped clients and sessions). The adaptations the merge
needs are included:

- post_kickoff loads the room through _load_room (tenant-scoped read)
  and passes room.tenant_id to get_by_type — the call CI flagged: the
  merge context made ClientLifecycleService.get_by_type require the
  tenant, since every tenant now has its own admin client.
- The bridge-core test harnesses stub the attributes the tenant work
  added (_bridge_tenant_id, _channel_to_room, _room_tenant), mirroring
  how main's own outbound-rendering harness adapted.

Claude-Session: https://claude.ai/code/session_017PdBwqBjgajRdMjLiFSiuA
Base automatically changed from work/template-registry to main September 11, 2026 16:38
The paste step now uses Monaco Editor with YAML syntax highlighting,
line numbers, code folding, and auto-expanding height (grows with
content, min 256px, max 600px). Drag-and-drop still works on the
surrounding div.

Monaco is already a dependency (@monaco-editor/react + monaco-editor).
The gateway has a similar YAML editor (CodeMirror-based) — this uses
the same concept but with the Console's existing Monaco integration.

NOT tested: visual rendering (no display on this VM). Typecheck, lint,
format all green.
@abeldantas
abeldantas force-pushed the work/switch-expert-template branch from 64a427e to 655ff0b Compare September 14, 2026 11:24
@abeldantas abeldantas changed the title feat: bundled Switch expert template in a DB-backed listing Create a working Switch expert from the Templates view in two clicks (CHOO-2665) Sep 14, 2026
@abeldantas

Copy link
Copy Markdown
Collaborator Author

E2E Screenshots — dev-abel @ 655ff0b8

1. Templates listing

Templates listing

2. Switch expert — Use modal (pre-filled)

Switch expert modal

3. After create — room opened, session starting

After create

4. Session transcript — agent answered the kickoff (41s)

Session answered

5. Two templates — extractable pattern works

Two templates

6. jq expert — different repo, different source, different creator

jq expert modal

7. Three questions answered (12-15s each)

Three questions

abeldantas and others added 10 commits September 14, 2026 14:24
# Conflicts:
#	core/switch_core/gateway/rooms.py
…ed locally

The Templates view now reads the server catalogue from the template
registry (CHOO-2677) instead of a parallel stored_templates table, which
this branch previously carried. The bundled Switch expert ships inside
the Console as a local template - it renders in the same listing and
works with no server round trip.

Registry rows map owner_name to the creator label; a template's content
becomes the agent's instructions on create.

(cherry picked from commit 64a427e)
(cherry picked from commit 132b93b)
Adds repo_url (Text) and sources (JSONB) columns to the registry's
templates table via a new migration. The template shape is now the full
extractable pattern: persona + provider (user input) + repo + sources.

- Replaces the 145-line bundled persona with the full switch-expert/
  AGENT.md (~340 lines of system prompt + knowledge file references)
- Bundled Switch-expert template declares repo sandbox-quantum/switch
  and 3 Switch docs source URLs
- Template cards in the listing show repo URL and source count
- Gateway client types carry repoUrl and sources
- Room-template wizard: "+ Create" button on not-found agent-slot chips
  opens add-agent modal with the name prefilled
- Add-agent modal gains prefillName prop for the wizard bridge

All checks green: ruff, mypy, oxfmt, oxlint, tsgo typecheck.

CHOO-2665.

(cherry picked from commit 5ead81f)
(cherry picked from commit 8c1ae0b)
…t is Switch"

The expert agent receives the connector skill when it joins a room, so
pointing it at connectors/*/skills/switch/SKILL.md in the clone sent it
after something it already had.

Route "what is Switch" and "why use it" to the repository README, whose
framing and examples land better than a composed pitch.

(cherry picked from commit ea4f7ee)
(cherry picked from commit 548f0a3)
…g choices

The expert told a user the working directory could be changed later in
the agent's settings. It cannot: Switch Console sets it once on the
new-agent dialog and has no update path. The editable "Repo dir" on the
web dashboard only feeds the generated session command, which is what
made this look changeable.

Write out the four addressing choices with the owner included in "only
me and my agents", and replace the blanket "never describe a UI" rule
with an instruction to read the Console source in the clone.

(cherry picked from commit e495a2d)
(cherry picked from commit 7011134)
(cherry picked from commit f1ef256)
(cherry picked from commit 5d24c23)
…ces columns (CHOO-2665)

An agent template is a YAML document with an `agent:` block beside the
optional `room:` and `kickoff:` it dispatches into, so `agent` joins the
top-level keys the linter knows. The `repo_url` and `sources` columns
added earlier go: the registry stores documents as they arrive and keeps
the table still while the format moves, so the agent's repository and
sources live in the document, where a second expert needs only a second
document. The columns were never served by the API anyway.

Also repairs three linter tests that treated `multiline` as an unknown
param field; it is a known one now that CHOO-2656's format is on this
branch.

(cherry picked from commit ffffeeb)
…shape (CHOO-2665)

switch-expert/template.yaml is the agent-template counterpart of the room
template: the agent's name, description, repository and sources as data,
plus the room it is put in and the message that starts it working. The
persona stays in AGENT.md and is filled in at bundle time, so it is
written once. examples/agent-templates/jq-expert.template.yaml is the
same shape on a different subject, with its instructions inline, the way
a template uploaded to a server carries them.

(cherry picked from commit adc6ecb)
…(CHOO-2665)

Picking a template used to prefill the description and instructions and
stop there: the person still had to choose a directory by hand, and the
agent then sat in no room with nobody talking to it, which is a
registered agent, not a working one. Now "Use" parses the agent-template
document (bundled or from the server's registry), the dialog suggests a
directory named after the agent, and on submit the Console creates it,
shallow-clones the template's repository inside, registers the agent,
provisions the template's room with the person in it, posts the kickoff
as them, and opens the room. The room-template wizard's "+ Create" on a
missing agent slot offers the matching bundled template when one exists.

The bundled Switch expert now reads switch-expert/template.yaml and
AGENT.md from the repository root instead of a copy, so the expert the
Console offers is the one the repository documents.

The parsing lives in agent-template-format.ts, free of Electron, with
tests; the controller wraps it with the directory and clone steps.

(cherry picked from commit 83be7f6)
…ers them (CHOO-2665)

switch-expert/AGENT.md opens with a Claude Code front matter block, and the
Console writes its own when it renders .claude/agents/<name>.md, so the
agent's definition file came out with two. The parser now drops a leading
block from a template's instructions, inline or filled in from AGENT.md.

(cherry picked from commit 655ff0b)
@abeldantas
abeldantas force-pushed the work/switch-expert-template branch from 655ff0b to 89eaebf Compare September 14, 2026 13:30
…h template does (CHOO-2665)

Opened from a template, the dialog showed the full agent form with three
hundred lines of instructions to scroll past, and a second person on a
server learned that "switch-expert" was taken only after the directory and
clone existed. Now the instructions fold to one line with Edit, a taken
prefilled name moves to the first free variant with a note saying so, and
the repository fetch and the room are each a switch the person can turn
off. A template can declare who may address the agent (`addressing:`
owner, owner-agents or anyone); the Switch expert says anyone, since a
team shares it.

The listing gains a search box, a Details fold per card (repository,
sources, the room it starts in, who it answers, the first lines of its
brief) and a notice when this computer has no usable agent provider, so
the dead end is named before the dialog rather than inside it.

Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…sion that answers (CHOO-2665)

The room's first message is posted as the person, through their linked
account on the room's bridge. Until now both halves were discovered after
the click: a server with no messaging app got a room nobody could talk in,
and an unlinked person got a red toast with a server error and a silent
agent. The dialog now looks both up first and says what to do, with a
button that swaps in the claim-identity dialog and hands back afterwards.
When it goes through, the Console opens the agent's session as soon as it
starts instead of leaving the person on a room page that shows nothing.

Also: a template's `addressing:` is applied to the form, a bundled
template can be saved to the server's registry from its card (persona
inlined), and the agents page offers "From a template" beside the blank
form.

Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…te so it can update (CHOO-2665)

Templates only reached a room by creating a new one, and the daily's ask
was to dispatch an expert into the room someone is already working in. The
add-agents-to-room dialog and the room's Configuration tab now offer the
agent templates too: the agent is created and put in that room, and the
toast says to mention it there, since only the room's own kickoff path can
speak as the person.

An agent's config file now records the template it came from (a new
top-level `template` key, ignored by older Consoles), and its settings
page offers "Update from <template>", which fills the editor with the
template's current instructions and leaves the save to the person. The
Switch expert's brief lives in the repository and moves; an agent created
in August would otherwise keep August's copy for good.

Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…2665)

A template on a remote run location kept the old shape: a directory typed
by hand, nothing made, nothing fetched. Now the same folder-per-agent
layout is suggested under the host's home, the directory is created and
the repository shallow-cloned over SSH on submit, and the fetch switch
applies there as well.

Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…nt (CHOO-2665)

The suggested directory is named after the agent, so a leftover from an
earlier install (a server since reset, an agent since removed) sits
exactly where the next one wants to go, carrying the old credentials the
add-agent pre-flight rightly refuses to overwrite. The person saw "name
already taken" after the click. Now a directory that already holds a
`.switch/` is skipped for `-2`, `-3`, on this machine and on a host.

Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…ree" exit zero (CHOO-2665)

Two reasons the remote directory suggestion never arrived. A bare `return`
of the probe promise ran the `finally` that disposes the SSH context
before the probes had run, so they were aborted; and `test -e` exits 1
for a free directory, which the runner reports as a failed command.
Both branches now echo and exit zero, and the probes are awaited first.

Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…2665)

The block that says what a template will do read as a paragraph, and
people do not read paragraphs in a dialog. One row per fact now:
Repository, Sources, Room, Answers, each with its switch on the right,
and the warning as one sentence with the fix beside it.

Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…h no messaging app (CHOO-2665)

The Room row carried "with you, kickoff sent as you" after the name; the
name is the fact, the rest is how rooms work. The no-messaging-app line
read as past tense and offered nothing to do; it now says the room would
have no chat and carries a button to the server page to connect one.

Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…s (CHOO-2665)

The dialog warned "this server does not know which Slack account is
yours" whenever the person had no explicit claim on the bridge. The
server is more forgiving than that: for a kickoff it matches the
account's name and email against the platform when nothing is claimed,
and remembers a hit, so the warning fired on people the kickoff would
have served fine. A new `GET /collaborations/{id}/me` answers with the
same resolution the kickoff uses, and the dialog asks that instead of
reading the claims list.

Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
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.

2 participants