fix(cli): confirm command echoes only the flags the user typed [ship]#1410
Conversation
Agent-mode write commands print a `confirmCommand` for the user to approve.
`buildConfirmCommand` serialized every entry of oclif's parsed flags, which
includes everything filled in from `default:`, so a bare `npx checkly deploy`
confirmed as:
checkly deploy --no-preview --no-verbose --schedule-on-deploy
--no-preserve-resources --no-cancel-in-progress-deployment
--verify-runtime-dependencies --no-debug-bundle
--debug-bundle-output-file="./debug-bundle.json" --force
That command does not run. `--no-x` is only a registered flag when the
definition sets `allowNo: true`, so oclif rejects the above with
"Nonexistent flags: --no-preview, ...". It also leaked two hidden debug
flags and buried whichever flag the user had actually typed.
Pass oclif's `metadata.flags` through the preview and skip flags marked
`setFromDefault`. A bare deploy now confirms as `checkly deploy --force`.
The helper was written for `incidents create`, where every flag is
user-typed and string-valued, and was later reused for `deploy`, whose
flags are mostly booleans with defaults. `deploy` and `destroy` were the
two commands producing unrunnable output; `incidents create/update/resolve`
were only noisy.
Docs: the confirmation protocol lived only in the incidents reference, so
an agent running a deploy never read it. Document deploy's two-stage
confirm, `--preserve-resources`, and the delete guard in the configure
reference. Also resolve the "never auto-append --force" contradiction —
the confirmCommand already ends in --force and is meant to run verbatim.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The previous commit told agents that deploy confirms twice and to present the itemised list of resources that would be deleted. That list is unreachable for an agent: the whole delete-guard block is gated on `!force` (deploy.ts:288), and `--force` is exactly what the confirmCommand carries. The guard is an interactive-only prompt. Point agents at `npx checkly deploy --preview` instead, which dry-runs and prints the would-be deletions without confirming or applying anything. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
This seems like a preexisting bug in the confirm path, but it seems like a too obvious thing to have been like that for a while. I'd appreciate your 2c here, guys. |
The confirmation docs promised that the `confirmCommand` is the command you ran plus `--force`, and that it "echoes back only the flags that were actually passed". That is true of every command on main today: the two callers that reshape their preview flags (`members delete`, `members update`) only drop empty ones, they never add. It stops being true the moment #1402 lands. `import commit` and `import cancel` resolve their plan and pin it into the preview, so a bare `checkly import commit` confirms as: checkly import commit --plan-id="abc123" --force The pin is the right call — it stops the approved run from re-resolving to a plan the user was never shown — but it makes an absolute claim in this reference false, and #1402 merges first. Widen the contract to allow a resolved target, and keep "treat every flag you see there as deliberate", which was always the operative rule and covers the pinned flag too. Worded to hold under either merge order: it describes the mechanism without pointing at the import section that arrives with #1402. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
timohuovinen
left a comment
There was a problem hiding this comment.
LGTM, the /review bits can be addressed now or as a follow-up
The confirmation protocol told agents that a command resolving a target pins it into the confirmCommand. No command on main does that: every call site passes raw user input, and members delete drops its email/id disambiguation before confirming. The pinning behavior arrives with import commit/cancel in #1402, which documents it there. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Awesome, thanks Timo! I addressed #1 from your findings as it was a genuine hole in the thing I intended to fix. Merging now. |
Conflict in the confirmation protocol docs: #1410 landed a paragraph on defaults being omitted from the confirmCommand, in the same spot as this branch's pinned-target section. Both are wanted — kept the general note first, then the pinning section. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Affected Components
What
In agent mode, write commands print a
confirmCommandfor the user to approve.buildConfirmCommandserialized every entry of oclif's parsed flags — including everything filled in fromdefault:— so a barenpx checkly deployconfirmed as:That command does not run.
--no-xis only a registered flag when the definition setsallowNo: true, and ondeployonlyschedule-on-deployandverify-runtime-dependenciesdo. oclif rejects the rest withNonexistent flags: --no-preview, .... So we printed a command, told agents to run it verbatim, and it errored out. It also leaked twohidden: truedebug flags and buried whichever flag the user had actually typed.Fix
Pass oclif's
metadata.flagsthrough the preview and skip flags markedsetFromDefault:buildConfirmCommandwas written forincidents create, where every flag is user-typed and string-valued, then reused verbatim fordeploy, whose flags are mostly booleans with defaults.deployanddestroywere the two commands producing unrunnable output;incidents create/update/resolvewere only noisy.members/delete|updatealready dodged this with a|| undefinedcoercion.flagMetadatais optional onCommandPreview, so call sites that don't pass it behave exactly as before.Docs
The confirmation protocol lived only in
references/communicate.md(the incidents/status-page doc), so an agent running a deploy never read it. TheDeployingsection ofreferences/configure.mdnow covers the two-stage confirm,--preserve-resources, and the delete guard.Also resolved a contradiction: the skill said "never auto-append
--force" whilebuildConfirmCommandalways appends it, making the rule read as unfollowable. It now says theconfirmCommandis meant to run verbatim.Tests
Added a round-trip test that feeds the generated
confirmCommandback through oclif's parser and asserts it parses. It fails with the exactNonexistent flagserror when the fix is disabled — verified, not assumed. Full suite green (1576 passing), lint clean.Notes for the Reviewer
CODEX_THREAD_IDwithout asking. That's preexisting and a product decision. Gating agent mode on!process.stdout.isTTYwould kill this exact false positive, but any agent that allocates a pty would fall back to interactive and hang on the prompt — worse than noise. Worth a separate discussion.🤖 Generated with Claude Code