Skip to content

fix(web): keep typed unpublished variable rows across settings re-deliveries - #30115

Open
justsrc wants to merge 2 commits into
pingdotgg:mainfrom
justsrc:fix/provider-env-add-variable-vanish
Open

justsrc wants to merge 2 commits into
pingdotgg:mainfrom
justsrc:fix/provider-env-add-variable-vanish

Conversation

@justsrc

@justsrc justsrc commented Nov 3, 2026 •

Copy link
Copy Markdown

Note

🤖 Pulse Alpha Free Max on behalf of Justin (@justsrc)

Problem

Settings > Providers > a provider instance card > Environment > Variables > Add variable: a row typed by the user but never published disappeared whenever an external settings write re-delivered a different environment. One client committing another variable on the same instance is enough to trigger it. reconcileRowsDraft reseeds rows when the incoming array differs from the last acknowledged state and fails to match the last published echo, and an unpublished row can never echo, so the row is discarded. Often while you're still typing it.

Change

In ProviderEnvironmentSection, after reconcileRowsDraft reseeds, keep rows the server never acknowledged (client-minted provider-env-* ids absent from the draft's reconciled baseline and from the re-delivered rows) and re-append them after the server rows. Acknowledged rows stay governed by the reseed, so a foreign delete removes them again.

Related

Scope and approval

There is no issue for this. It fixes silent data loss in an existing control, which falls under the very-small-fix-for-an-obvious-bug exception in CONTRIBUTING.md. It adds no setting or default, touches one component, and covers web and desktop (desktop shares the web UI). Mobile has no equivalent surface. The Add-provider dialog shares this section and inherits the fix.

Deliberately left out to keep this one problem: committed-row focus loss on reseed, rename-window draft text loss, uncommitted text loss on an acknowledged row, the silent all-or-nothing publish bail on an invalid committed name, and the Arguments editor (it publishes on add and has no unpublishable rows to preserve).

Verification

  • apps/web: vp test run src/components/settings/ProviderInstanceCard.environment.browser.test.tsx
    • with the new test file applied to cefb544af3, three pinned regressions fail (the typed row is discarded, the committed unpublishable row is discarded, the redacted-sibling regression fails the same way)
    • on this branch: 5/5 pass
  • vp run check:changed: format, lint, both knip passes, affected typechecks, tests beside changes, React Compiler coverage check — all pass
  • vp run typecheck: 40/40
  • Neighboring suites pass: ProviderSettingsForm.test.ts, AddProviderInstanceDialog.environment.browser.test.tsx, AddProviderInstanceDialog.test.ts, ProviderInstanceCard.test.ts
  • Live, on two empty-state dev servers (vp run dev --no-seed), two paired clients on each Replay (dev) instance. Before: unpatched main drops the typed row after the external write. After: this branch survives it. OTHER_SWAP persists and reads Stored secret in both.

Before: unpatched main, LIVE_SWAP_PROBE typed and focused in client A (unpublished), OTHER_SWAP committed in client B. The typed row is discarded.

pr-before.trim.mp4

After: this branch, same steps. The typed row survives the external write and stays focused.

pr-after.trim.mp4

Checked: vp run dev --no-seed, pair two clients, Settings > Providers > a provider instance > Environment > Variables > Add variable, type into the row and leave it focused, commit a different variable on the same instance from the second client, and watch the typed row survive.

Not verified: desktop and mobile shells, relay/tunnel connections, and the final rendered appearance with a real sensitive-value replacement flow.

Known limitations of this fix:

  • A typed row whose name matches a re-delivered row yields to the server's row.
  • Preserved rows re-append at the end; index-based labels shift with them.
  • A publish that never reaches the server leaves a ghost that re-publishes on the next edit.

Review

Five rounds with a three-model panel (gemini-3.8-flash high, glm-5.3-flash-free max, deepseek-v4.1-flash-free max).

Model and harness: opencode/pulse-alpha-free (OpenCode harness, via T3 Code)

…iveries

A row typed in an Add-variable card disappeared whenever an external settings
write re-delivered the environment. reconcileRowsDraft reseeds rows on any
non-echo change, and an unpublished row can never echo.

ProviderEnvironmentSection now keeps rows the server never acknowledged
(provider-env-* ids) across reseeds. Rows the server has acknowledged stay
governed by the reseed, so a foreign delete removes them again.

Model and harness: opencode/pulse-alpha-free (OpenCode harness, via T3 Code).
Panel review: gemini-3.8-flash (high), glm-5.3-flash-free (max),
deepseek-v4.1-flash-free (max).
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Nov 3, 2026
@macroscopeapp

macroscopeapp Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 4f3f7c9

Macroscope's review found this PR approvable — Keeps unpublished environment-variable drafts from disappearing when settings are re-delivered. The change is limited to local editor reconciliation and leaves publishing, secret handling, and product defaults unchanged.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

Run configuration
Commits

Reviewing files that changed from the base of the PR and between 4f3f7c9 and 187af64.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review

No actionable comments were generated in the recent review.

Walkthrough

The component now preserves eligible, unacknowledged draft rows when external environment updates reconcile stored rows. Browser tests cover unpublished rows, redacted server echoes, invalid names, and later removal.

Changes: Environment draft row reconciliation

Layer / File(s) Summary
Preserve draft rows during reconciliation
apps/web/src/components/settings/ProviderInstanceCard.tsx, apps/web/src/components/settings/ProviderInstanceCard.environment.browser.test.tsx
The component keeps eligible locally added rows during reconciliation. Browser tests check that external updates and server echoes preserve, acknowledge, and remove rows as expected.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: juliusmarminge, macroscopeapp, only21mil

Merge Risk: Minimal · previous review 4f3f7

Unpublished drafts are retained across settings updates. No actionable merge-blocking risk was established.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title clearly and concisely describes the primary fix: preserving typed, unpublished variable rows across settings re-deliveries.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description follows the repository template closely. It has Problem, Change, Scope and approval, and Verification sections. The Problem section states the bug, the trigger, and the root cause in `…
Full details: Description check

Explanation

The description follows the repository template closely. It has Problem, Change, Scope and approval, and Verification sections. The Problem section states the bug, the trigger, and the root cause in reconcileRowsDraft. The Change section names the component and the retained-row rule. Scope cites an exception for very small obvious-bug fixes and explains why it applies. Verification lists the focused test command, the observed before and after results, two screenshots or recordings, and items not verified. It also names the model and harness, as the template requests. Gaps: the Scope section does not link a triaged issue or maintainer approval, and it relies on the small-fix exception. The Related section is long and partly outside the template. The Verification section includes the before and after recordings. The Change section is brief and does not explain the echo-matching edge cases beyond the limitations list.

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Tip

🎯 Customize your risk assessments

Guide how CodeRabbit assesses merge risk and security architecture risk. Highlight sensitive changes and explain your security boundaries using Merge Risk Instructions and Security Risk Instructions in your review settings. Security architecture risk assessments require the Advanced plan or above.

✅ Automatic approvals, with your rules

Let CodeRabbit approve pull requests once required threads are resolved, pre-merge checks pass, and your risk limits are met. Enable Automatic approvals in review settings, with overrides for teams or file paths.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between cefb544 and 4f3f7c9.

Files selected for processing: 2
  • apps/web/src/components/settings/ProviderInstanceCard.environment.browser.test.tsx
  • apps/web/src/components/settings/ProviderInstanceCard.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

@justsrc
justsrc marked this pull request as draft November 3, 2026 11:49
@justsrc
justsrc marked this pull request as ready for review November 3, 2026 12:01
@maria-rcks

maria-rcks commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

verified unchanged head 4f3f7c9d0b18d624e7644fa8d479307a693a815b on linux with the repository Playwright dependency and /usr/bin/google-chrome. used one dev server at a time and two authenticated web clients on each server.

  • reproduced on github/main (cefb544af3): settings > providers > codex > environment > add variable. client a typed T3_VERIFY_DRAFT and kept the name focused. client b saved T3_VERIFY_OTHER. client a lost its draft.
  • repeated on this head: the focused draft survived the same external save. committed its name and sensitive value. reloading client b showed both saved rows exactly once, with values redacted. deleting T3_VERIFY_OTHER in client b removed the acknowledged row in client a.
  • created a local git project through the app, then started a real codex gpt-6.1-sol turn from the web composer. its shell read the retained, saved variable through the actual provider environment path:
printf '%s\n' "$T3_VERIFY_DRAFT" "$PWD"
draft-survived-main-and-pr
/home/user/t3code/.t3/projects/provider-env-verification

blacksmith checks passed: 22 tests across ProviderInstanceCard.environment.browser.test.tsx, AddProviderInstanceDialog.environment.browser.test.tsx, ProviderInstanceCard.test.ts, and ProviderSettingsForm.test.ts. vp run check:changed github/main also passed format, lint, both knip passes, affected typechecks, adjacent tests, and the react compiler check. no code changes were needed.

main: the external save removes the unpublished draft

pr: the same external save preserves the focused draft

animated recording of main and pr draft behavior during an external save

real codex turn reads the saved variable in the app-created git project

Not verified

electron and native ios/android shells, macos/windows behavior, relay/tunnel connections, non-codex provider runtimes, and external secret-reference services were not exercised on this linux vm. the add-provider dialog passed its existing browser suite but was not exercised end to end in the running app. existing acknowledged-row draft editing limitations described in the pr remain outside this verification.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants