From 38074806c11360ba31cb603a154c8758c4316e91 Mon Sep 17 00:00:00 2001 From: Paul Payne Date: Wed, 1 Jul 2026 11:52:56 -0700 Subject: [PATCH] Delete-program confirm enumerates each action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The confirm dialog (window.confirm in FormFooter) now spells out exactly what cascade will do — uninstall the tool from PATH / drop the static route / stop, disable and remove named service+job deployments, and remove the catalog entry — each as its own bullet, ending with the reassurance that source on disk is kept. --- app/src/components/detail/ProgramFields.tsx | 29 ++++++++++++--------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/app/src/components/detail/ProgramFields.tsx b/app/src/components/detail/ProgramFields.tsx index f787685..48285cd 100644 --- a/app/src/components/detail/ProgramFields.tsx +++ b/app/src/components/detail/ProgramFields.tsx @@ -169,17 +169,22 @@ export function ProgramFields({ program, onSave, onDelete }: Props) { } /** Deleting a program cascades to its deployments (tear down + remove), so the - * confirm names exactly what will go. Source on disk is always left untouched. */ + * confirm enumerates exactly what will happen. Source on disk is always kept. */ function deleteConfirm(program: ProgramDetail): string { - const deps = [...program.services, ...program.jobs] - const kind = program.kind - const own = - kind === "tool" - ? " This uninstalls it from PATH." - : kind === "static" - ? " This stops serving it." - : "" - const also = - deps.length > 0 ? ` Its deployments (${deps.join(", ")}) are torn down and removed too.` : "" - return `Delete "${program.id}"?${own}${also} (Source on disk is untouched.)` + const actions: string[] = [] + // The program's own 1:1 deployment (tool/static) isn't listed in services/jobs. + if (program.kind === "tool") actions.push(`uninstall ${program.id} from your PATH`) + else if (program.kind === "static") + actions.push(`stop serving ${program.id} (drop its gateway route)`) + // Named service/job deployments that reference this program. + const named = [...program.services, ...program.jobs] + if (named.length) actions.push(`stop, disable, and remove: ${named.join(", ")}`) + // Always: the catalog entry itself. + actions.push(`remove "${program.id}" from the catalog`) + + const lines = actions.map((a) => ` • ${a}`).join("\n") + return ( + `Delete "${program.id}"? This will:\n\n${lines}\n\n` + + `The source code on disk is left untouched.` + ) }