Skip to content

fix(workspace-update): prompt for option drift and immutable params#967

Open
EhabY wants to merge 2 commits into
mainfrom
fix/workspace-update-param-drift
Open

fix(workspace-update): prompt for option drift and immutable params#967
EhabY wants to merge 2 commits into
mainfrom
fix/workspace-update-param-drift

Conversation

@EhabY
Copy link
Copy Markdown
Collaborator

@EhabY EhabY commented May 20, 2026

Aligns workspace-update parameter collection with the dashboard's getMissingParameters (coder/site/src/api/api.ts:39). Two cases previously slipped through and produced server-side build rejections with no UI:

  • A stored option/multi-select value that is no longer one of the new template version's options (option-value drift) was carried forward verbatim.
  • An immutable parameter without a stored value was never prompted, even though it can never be set after the first build.

needsPrompt(param, storedValue) centralizes the decision; multi-select drift is also detected (parsing the JSON-encoded stored value) because the dashboard explicitly skips multi-select.

On a multi-select drift re-prompt the QuickPick now pre-selects the picks that are still valid, so the user does not have to re-select what was already correct. Non-required multi-selects can now also submit zero picks (previously the prompt stayed open with no way to express "none").

Behavior matrix

Case Behavior Vs. dashboard
No stored value, mutable + required, no default Prompt match
No stored value, mutable + required, has default Skip deviate (server applies default; avoid auto-update friction)
No stored value, immutable Prompt match
No stored value, not required (mutable) Skip match
Stored value still in new options Skip match
Single-select drift Prompt (no preselect) match
Multi-select drift Prompt with valid picks pre-selected beyond (dashboard skips multi-select)
Multi-select stored value not valid JSON Prompt beyond (defensive)
Non-required multi-select submitted empty Accept as "[]" n/a (pre-existing prompt code)

Files

  • src/api/updateParameters.ts: needsPrompt, parseMultiSelectValue; promptForParameter accepts storedValue and pre-selects still-valid multi-select picks.
  • test/unit/api/updateParameters.test.ts: 12 new cases covering single/multi drift, immutable + default, multi-select happy path, empty-array stored value, empty submission, and preselect verification.
  • CHANGELOG.md: user-facing entry under Unreleased > Fixed.

Aligns parameter collection with the dashboard's getMissingParameters
in coder/site/src/api/api.ts. Previously the filter only checked
`required && !default_value` against `name in storedValues`, so:

  - Required params whose stored option value was no longer in the new
    version's option list (option-value drift) were carried forward
    and the build was rejected server-side with no useful UI.
  - Immutable params without a stored value were never prompted, even
    though they can never be set after the first build.

Add `needsPrompt(param, storedValue)` covering both cases. Beyond the
dashboard, also handle multi-select drift by parsing the JSON-encoded
value (dashboard explicitly skips multi-select). The `default_value`
short-circuit is preserved for the unset case so the server can fall
back to the template default during auto-update without a prompt.
@EhabY EhabY self-assigned this May 20, 2026
@EhabY
Copy link
Copy Markdown
Collaborator Author

EhabY commented May 20, 2026

/coder-agents-review

Copy link
Copy Markdown

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, well-scoped fix. The needsPrompt extraction is solid, the behavior table in the PR description is exactly the kind of documentation that saves future debugging time, and 6 of 7 new tests fail on the base branch (Netero verified). The deviation comment at line 55 is a model for documenting intentional divergence.

One design concern (P2), two P3s, one P3 test gap, one P4, and three nits.

The P2 is about the default_value short-circuit applying to immutable parameters. When a new immutable param has a default, the user is never prompted, and because the param is immutable, they can never override it afterward. The dashboard prompts in this case. The PR documents this as intentional ("avoid auto-update friction"), but the friction argument holds for mutable params (temporary inconvenience), not immutable ones (permanent lock-in).

Melody walked all 11 ParameterFormType variants and confirmed the dispatch/filter pairing is clean. Chopper verified edge cases ("", "[]", invalid JSON). Mafu-san traced the alignment claim against the actual dashboard code and confirmed the logic matches where claimed.

"The user chose correctly; the tool failed to preserve what was still good." (Hisoka, on multi-select drift discarding valid picks)

🤖 This review was automatically generated with Coder Agents.

Comment thread src/api/updateParameters.ts Outdated
Comment thread src/api/updateParameters.ts Outdated
Comment thread src/api/updateParameters.ts
Comment thread test/unit/api/updateParameters.test.ts
Comment thread src/api/updateParameters.ts
Comment thread src/api/updateParameters.ts Outdated
Comment thread src/api/updateParameters.ts Outdated
Comment thread CHANGELOG.md Outdated
Comment thread test/unit/api/updateParameters.test.ts
@EhabY EhabY force-pushed the fix/workspace-update-param-drift branch 2 times, most recently from fa6a8a5 to 2e176c5 Compare May 20, 2026 12:35
@EhabY
Copy link
Copy Markdown
Collaborator Author

EhabY commented May 20, 2026

/coder-agents-review

Copy link
Copy Markdown

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All 9 round-1 findings addressed. The P2 (immutable default lock-in) is fixed at the root: if (!param.mutable) return true now runs before the default_value check. Kite, Pariston, Mafuuu, and Chopper independently confirmed the fix is complete. Melody walked 8 pairing modes across the updated code and found zero mismatches. Pariston's adversarial analysis couldn't build a case against the change.

One P3 test gap and two nits remain. The P3 is a missing test for the required-multi-select empty-submission guard; the behavior is correct but unprotected against regression.

"I tried to build a case against this change and couldn't." (Pariston)

🤖 This review was automatically generated with Coder Agents.

Comment thread test/unit/api/updateParameters.test.ts
Comment thread src/api/updateParameters.ts Outdated
Comment thread src/api/updateParameters.ts Outdated
- needsPrompt: prompt immutable + default (no user override possible later
  — permanent lock-in to server default otherwise). Per DEREM-3.
- promptForParameter: accept empty selection on non-required multi-select
  re-prompts; the previous logic kept the QuickPick open with no way to
  express "none." Per DEREM-5.
- promptForParameter: pre-select still-valid picks on multi-select drift
  re-prompts so the user doesn't lose what was already correct. Per DEREM-7.
- Inline notes on both deviations from the dashboard's getMissingParameters
  (default short-circuit + multi-select drift) so future syncs catch them.
- Drop manual `(v): v is string =>` predicate (TS 5.5+ inference).
- Tests: multi-select happy path, '[]' empty array, non-required empty
  submission, preselect verification, immutable + default prompt.
- CHANGELOG: user-facing wording ("closing a gap with the web dashboard").
@EhabY EhabY force-pushed the fix/workspace-update-param-drift branch from 2e176c5 to bd42d05 Compare May 20, 2026 13:31
@EhabY EhabY requested a review from code-asher May 20, 2026 15:37
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