From 062857c1d3880e1494aba7f743dbf01ab18d02ce Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 3 Jul 2026 16:58:35 +0000 Subject: [PATCH] fix: keep controller closeout nonblocking --- .agents/skills/unidesk-cicd/references/branch-follower.md | 2 ++ scripts/src/cicd.ts | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.agents/skills/unidesk-cicd/references/branch-follower.md b/.agents/skills/unidesk-cicd/references/branch-follower.md index 98f8b876..646b281d 100644 --- a/.agents/skills/unidesk-cicd/references/branch-follower.md +++ b/.agents/skills/unidesk-cicd/references/branch-follower.md @@ -100,6 +100,8 @@ Validation, test and performance evidence for branch-follower changes must also Operator-facing commands must use intuitive target-side verbs instead of internal execution flags. From a local/master host, use `status --live`, `run-once ...`, `events`, or `logs`; these commands create a bounded target-side Job when live state is needed. The internal `--in-cluster` flag is reserved for the Kubernetes Job/Pod command line after the registry, serviceaccount, in-cluster API endpoint and EmptyDir source checkout are mounted. It must not appear in user-facing examples. +`--in-cluster` only selects the execution environment. It must not imply `--wait`, closeout blocking, longer budgets, or sequential waiting across followers. Only an explicit user-facing `--wait` may perform blocking closeout waits; the automatic controller loop must submit/observe one bounded step and let later loops advance state from native Kubernetes objects. + Legacy `--controller` is accepted only as a compatibility spelling: inside Kubernetes it maps to `--in-cluster`, while outside Kubernetes it behaves like the ordinary public target-side path rather than running in-cluster logic locally. If an internal flag, hidden mode, or operator shortcut is misused and can write partial state or misleading evidence, stop feature work and simplify the public command semantics plus this reference before continuing. `run-once --dry-run` is read-only for deployment: it may refresh the state ConfigMap with current native observations, but it must not trigger adapters. diff --git a/scripts/src/cicd.ts b/scripts/src/cicd.ts index f65fb5f7..33d5f873 100644 --- a/scripts/src/cicd.ts +++ b/scripts/src/cicd.ts @@ -805,7 +805,7 @@ async function decideAndMaybeTrigger( if (options.confirm && (phase === "PendingTrigger" || phase === "Superseded" || (phase === "Observed" && observedSha !== null))) { const trigger = await executeTrigger(registry, follower, observedSha, options); triggerCommand = trigger.command; - phase = trigger.ok ? (options.wait || options.inCluster ? "ClosingOut" : "Triggering") : "Failed"; + phase = trigger.ok ? (options.wait ? "ClosingOut" : "Triggering") : "Failed"; decision = trigger.ok ? `trigger submitted for ${shortSha(observedSha)}` : `trigger failed for ${shortSha(observedSha)}: ${redactText(trigger.message).slice(0, 220)}`; inFlightJob = trigger.jobId ?? live.inFlightJob; lastTriggeredSha = observedSha; @@ -818,7 +818,7 @@ async function decideAndMaybeTrigger( } if (!trigger.ok) warnings.push(trigger.message); } - if (options.confirm && (options.wait || options.inCluster) && phase === "ClosingOut" && observedSha !== null && triggerCommand === undefined) { + if (options.confirm && options.wait && phase === "ClosingOut" && observedSha !== null && triggerCommand === undefined) { const closeout = await waitNativeFollowerCloseout(registry, follower, observedSha, options, options.timeoutSeconds ?? follower.budgets.endToEndSeconds); triggerCommand = closeoutOnlyCommand(follower, live.pipelineRun, observedSha, closeout); if (closeout.completed) {