Populate the program stack select from castle-api

The dashboard's stack dropdown hardcoded its options (python-cli/fastapi/
react-vite), so a supabase program showed "(none)" — the value had no matching
option. Make the backend the single source of truth instead:

- core: available_stacks() returns sorted(HANDLERS) — the stacks castle has
  handlers for.
- castle-api: GET /stacks exposes it.
- cli: --stack choices derive from available_stacks() (drops the duplicated list).
- app: ProgramFields fetches /stacks (useStacks) and renders options from it,
  always including the current value so it never silently blanks; StackBadge
  gets a Supabase label.

A new backend stack now appears everywhere without a frontend edit.
This commit is contained in:
2026-06-30 21:43:11 -07:00
parent bd9ea76d6a
commit 14145c9f15
6 changed files with 38 additions and 9 deletions

View File

@@ -49,6 +49,16 @@ export function useJobs() {
})
}
// The stacks castle has handlers for — authoritative source for the program
// stack select, so a new backend stack appears without a frontend change.
export function useStacks() {
return useQuery({
queryKey: ["stacks"],
queryFn: () => apiClient.get<string[]>("/stacks"),
staleTime: Infinity,
})
}
export function useJob(name: string) {
return useQuery({
queryKey: ["jobs", name],