Skip to content

feat(desktop): steward spawn sheet — template-driven, from the Navigator rail - #485

Merged
physercoe merged 1 commit into
mainfrom
steward-spawn-desktop
Jul 30, 2026
Merged

feat(desktop): steward spawn sheet — template-driven, from the Navigator rail#485
physercoe merged 1 commit into
mainfrom
steward-spawn-desktop

Conversation

@physercoe

Copy link
Copy Markdown
Owner

Why

Desktop could only mint workers (director-reported, verified): AgentSpawn sends an engine kind, 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 as role=worker). Mobile has a dedicated spawn_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, 7 node --test tests): the handle taxonomy from lib/services/steward_handle.dart (steward / *-steward; @-forms can never collide), name validation post-normalization, template picks (agents/steward*.yaml minus the steward.general* concierge singleton), suggested name from domain templates, and the block-aware backend.kind parser (mirrors mobile's mini-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 (role escalation rides the template), permission_mode: 'skip' (the bootstrap default everywhere), and auto_open_session: true 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), reusing vault/envSecrets + HostKeyTrustDialog.
  • Navigator: + on the Stewards KindSection (the existing onAdd affordance) and the empty state becomes a CTA instead of a dead end.
  • client.spawnAgent gains spawn_spec_yaml / permission_mode / auto_open_session — the hub JSON fields already existed; no hub change.
  • i18n en+zh (nav.spawnSteward, steward.*).

Out of scope (deliberate, matching mobile's sheet)

The @steward general 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 + full vite build — green
  • node --test src/state src/ssh — 405/405 (7 new stewardSpawn pins)
  • scripts/lint-desktop-tokens.sh — clean (no new CSS)

🤖 Generated with Claude Code

…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>
@physercoe
physercoe merged commit 16de5c1 into main Jul 30, 2026
8 checks passed
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