feat(desktop): steward spawn sheet — template-driven, from the Navigator rail - #485
Merged
Conversation
…tor rail Desktop could only mint workers: AgentSpawn sends an engine `kind`, and the hub derives role from the template persona — so a desktop-first team had no way to create a steward (mobile has spawn_steward_sheet.dart; the Navigator's Stewards section was a dead-end 'No stewards.'). Parity wedge, mirroring the mobile sheet's contract: - state/stewardSpawn.ts (pure, node-tested): the handle taxonomy from lib/services/steward_handle.dart (steward / *-steward; @-forms never collide), name validation post-normalization, template picks (steward*.yaml minus the steward.general* concierge singleton), suggested name from domain templates, and the block-aware backend.kind parser. - ui/StewardSpawn.tsx: Name + template + host + env profile; submit fetches the MERGED template YAML, parses backend.kind for the request's engine kind, and spawns with spawn_spec_yaml (the template's default_role: team.* escalates the role hub-side), permission_mode 'skip' (the bootstrap default everywhere) and auto_open_session so the steward never exists agent-without-session. Env profiles with secret_refs run the same resolve → host-key trust → seal path as the worker sheet (ADR-056 E3b-3). - Navigator: '+' on the Stewards section + the empty state becomes a CTA. - client.spawnAgent gains spawn_spec_yaml / permission_mode / auto_open_session (hub fields already existed). The @steward general concierge (ensure-endpoint singleton) stays out of scope, as on mobile's sheet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Desktop could only mint workers (director-reported, verified):
AgentSpawnsends an enginekind, and the hub derives steward role from the template persona +default_role: team.*(handlers_agents.go— the same distinction whose absence once made every mobile steward land asrole=worker). Mobile has a dedicatedspawn_steward_sheet.dart; desktop's only steward path was ProjectBoard's "Bind steward…" (project steward on start), and the Navigator's Stewards section was a dead-end "No stewards." — a desktop-first team could not bootstrap a steward.What
Parity wedge mirroring the mobile sheet's contract:
state/stewardSpawn.ts(pure, import-free, 7node --testtests): the handle taxonomy fromlib/services/steward_handle.dart(steward/*-steward;@-forms can never collide), name validation post-normalization, template picks (agents/steward*.yamlminus thesteward.general*concierge singleton), suggested name from domain templates, and the block-awarebackend.kindparser (mirrors mobile's mini-parser).ui/StewardSpawn.tsx: Name + template + host + env profile. Submit fetches the merged template YAML, parsesbackend.kindfor the request's enginekind, and spawns withspawn_spec_yaml(role escalation rides the template),permission_mode: 'skip'(the bootstrap default everywhere), andauto_open_session: trueso the steward never exists agent-without-session. Env profiles withsecret_refsrun the same resolve → host-key trust → seal path as the worker sheet (ADR-056 E3b-3), reusingvault/envSecrets+HostKeyTrustDialog.+on the StewardsKindSection(the existingonAddaffordance) and the empty state becomes a CTA instead of a dead end.client.spawnAgentgainsspawn_spec_yaml/permission_mode/auto_open_session— the hub JSON fields already existed; no hub change.nav.spawnSteward,steward.*).Out of scope (deliberate, matching mobile's sheet)
The
@stewardgeneral concierge (hub ensure-endpoint singleton; mobile surfaces it on the home tab — a desktop card is a separate follow-up), persona seed, permission-mode picker, driving-mode override, and the session-swap recreate path.Verification
desktop:tsc --noEmit+ fullvite build— greennode --test src/state src/ssh— 405/405 (7 newstewardSpawnpins)scripts/lint-desktop-tokens.sh— clean (no new CSS)🤖 Generated with Claude Code